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

105 lines
3.4 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"
import { htmlToJsx } from "../../util/jsx"
2024-02-05 10:45:36 +00:00
import { i18n } from "../../i18n"
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) {
2024-02-05 10:45:36 +00:00
const { tree, fileData, allFiles, cfg } = props
2023-07-01 07:03:01 +00:00
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-02-05 10:45:36 +00:00
const cssClasses: string[] = fileData.frontmatter?.cssclasses ?? []
const classes = ["popover-hint", ...cssClasses].join(" ")
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 (
2024-02-05 10:45:36 +00:00
<div class={classes}>
2023-08-23 20:10:23 +00:00
<article>
<p>{content}</p>
</article>
2024-02-05 10:45:36 +00:00
<p>{i18n(cfg.locale).pages.tagContent.totalTags({ count: tags.length })}</p>
2023-07-26 04:10:37 +00:00
<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>}
2024-02-05 10:45:36 +00:00
<div class="page-listing">
<p>
{i18n(cfg.locale).pages.tagContent.itemsUnderTag({ count: pages.length })}
{pages.length > numPages && (
<span>
{i18n(cfg.locale).pages.tagContent.showingFirst({ count: numPages })}
</span>
)}
</p>
<PageList limit={numPages} {...listProps} />
</div>
2023-07-26 04:10:37 +00:00
</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 (
2024-02-05 10:45:36 +00:00
<div class={classes}>
2023-07-23 00:27:41 +00:00
<article>{content}</article>
2024-02-05 10:45:36 +00:00
<div class="page-listing">
<p>{i18n(cfg.locale).pages.tagContent.itemsUnderTag({ count: pages.length })}</p>
<div>
<PageList {...listProps} />
</div>
2023-07-23 00:27:41 +00:00
</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