quartz-research-note/quartz/components/pages/TagContent.tsx

97 lines
2.9 KiB
TypeScript
Raw Normal View History

2023-07-01 07:03:01 +00:00
import { QuartzComponentConstructor, QuartzComponentProps } from "../types"
2023-07-23 00:27:41 +00:00
import style from "../styles/listPage.scss"
2023-07-01 07:03:01 +00:00
import { PageList } from "../PageList"
import { FullSlug, getAllSegmentPrefixes, simplifySlug } from "../../util/path"
2023-07-26 04:10:37 +00:00
import { QuartzPluginData } from "../../plugins/vfile"
import { Root } from "hast"
2023-09-03 01:07:26 +00:00
import { pluralize } from "../../util/lang"
import { htmlToJsx } from "../../util/jsx"
2023-07-01 07:03:01 +00:00
2023-07-26 04:10:37 +00:00
const numPages = 10
2023-07-01 07:03:01 +00:00
function TagContent(props: QuartzComponentProps) {
const { tree, fileData, allFiles } = props
const slug = fileData.slug
if (!(slug?.startsWith("tags/") || slug === "tags")) {
2023-07-26 04:10:37 +00:00
throw new Error(`Component "TagContent" tried to render a non-tag page: ${slug}`)
}
const tag = simplifySlug(slug.slice("tags/".length) as FullSlug)
2023-07-26 04:10:37 +00:00
const allPagesWithTag = (tag: string) =>
allFiles.filter((file) =>
(file.frontmatter?.tags ?? []).flatMap(getAllSegmentPrefixes).includes(tag),
)
const content =
(tree as Root).children.length === 0
? fileData.description
: htmlToJsx(fileData.filePath!, tree)
2024-01-05 08:29:34 +00:00
if (tag === "/") {
const tags = [
...new Set(
allFiles.flatMap((data) => data.frontmatter?.tags ?? []).flatMap(getAllSegmentPrefixes),
),
].sort((a, b) => a.localeCompare(b))
2023-07-26 04:10:37 +00:00
const tagItemMap: Map<string, QuartzPluginData[]> = new Map()
for (const tag of tags) {
tagItemMap.set(tag, allPagesWithTag(tag))
}
return (
<div class="popover-hint">
2023-08-23 20:10:23 +00:00
<article>
<p>{content}</p>
</article>
2023-07-26 04:10:37 +00:00
<p>Found {tags.length} total tags.</p>
<div>
{tags.map((tag) => {
const pages = tagItemMap.get(tag)!
const listProps = {
...props,
allFiles: pages,
}
const contentPage = allFiles.filter((file) => file.slug === `tags/${tag}`)[0]
const content = contentPage?.description
2023-07-26 04:10:37 +00:00
return (
<div>
<h2>
<a class="internal tag-link" href={`../tags/${tag}`}>
2023-07-26 04:10:37 +00:00
#{tag}
</a>
</h2>
{content && <p>{content}</p>}
2023-07-26 04:11:06 +00:00
<p>
2023-09-03 01:07:26 +00:00
{pluralize(pages.length, "item")} with this tag.{" "}
2023-07-26 04:11:06 +00:00
{pages.length > numPages && `Showing first ${numPages}.`}
</p>
2023-07-26 04:10:37 +00:00
<PageList limit={numPages} {...listProps} />
</div>
)
})}
</div>
</div>
)
} else {
const pages = allPagesWithTag(tag)
2023-07-01 07:03:01 +00:00
const listProps = {
...props,
2023-07-26 04:10:37 +00:00
allFiles: pages,
2023-07-01 07:03:01 +00:00
}
2023-07-23 00:27:41 +00:00
return (
<div class="popover-hint">
<article>{content}</article>
2023-09-03 01:07:26 +00:00
<p>{pluralize(pages.length, "item")} with this tag.</p>
2023-07-23 00:27:41 +00:00
<div>
<PageList {...listProps} />
</div>
2023-07-01 07:03:01 +00:00
</div>
2023-07-23 00:27:41 +00:00
)
2023-07-01 07:03:01 +00:00
}
}
TagContent.css = style + PageList.css
export default (() => TagContent) satisfies QuartzComponentConstructor