quartz-research-note/quartz/plugins/emitters/tagPage.tsx

97 lines
2.9 KiB
TypeScript
Raw Normal View History

2023-07-01 07:03:01 +00:00
import { QuartzEmitterPlugin } from "../types"
import { QuartzComponentProps } from "../../components/types"
import HeaderConstructor from "../../components/Header"
import BodyConstructor from "../../components/Body"
import { pageResources, renderPage } from "../../components/renderPage"
import { ProcessedContent, defaultProcessedContent } from "../vfile"
import { FullPageLayout } from "../../cfg"
2023-07-26 04:10:37 +00:00
import {
CanonicalSlug,
FilePath,
ServerSlug,
getAllSegmentPrefixes,
joinSegments,
} from "../../path"
2023-07-26 06:37:24 +00:00
import { defaultListPageLayout, sharedPageComponents } from "../../../quartz.layout"
import { TagContent } from "../../components"
2023-07-01 07:03:01 +00:00
2023-07-26 06:37:24 +00:00
export const TagPage: QuartzEmitterPlugin<FullPageLayout> = (userOpts) => {
const opts: FullPageLayout = {
...sharedPageComponents,
...defaultListPageLayout,
pageBody: TagContent(),
...userOpts,
2023-07-01 07:03:01 +00:00
}
2023-07-26 06:37:24 +00:00
const { head: Head, header, beforeBody, pageBody, left, right, footer: Footer } = opts
2023-07-01 07:03:01 +00:00
const Header = HeaderConstructor()
const Body = BodyConstructor()
return {
name: "TagPage",
getQuartzComponents() {
2023-07-26 06:37:24 +00:00
return [Head, Header, Body, ...header, ...beforeBody, pageBody, ...left, ...right, Footer]
2023-07-01 07:03:01 +00:00
},
async emit(ctx, content, resources, emit): Promise<FilePath[]> {
2023-07-13 07:19:35 +00:00
const fps: FilePath[] = []
2023-07-23 00:27:41 +00:00
const allFiles = content.map((c) => c[1].data)
const cfg = ctx.cfg.configuration
2023-07-01 07:03:01 +00:00
2023-07-26 04:10:37 +00:00
const tags: Set<string> = new Set(
allFiles.flatMap((data) => data.frontmatter?.tags ?? []).flatMap(getAllSegmentPrefixes),
)
// add base tag
tags.add("")
2023-07-23 00:27:41 +00:00
const tagDescriptions: Record<string, ProcessedContent> = Object.fromEntries(
2023-07-26 04:10:37 +00:00
[...tags].map((tag) => {
const title = tag === "" ? "Tag Index" : `Tag: #${tag}`
return [
tag,
defaultProcessedContent({
slug: joinSegments("tags", tag, "index") as ServerSlug,
frontmatter: { title, tags: [] },
}),
]
}),
2023-07-23 00:27:41 +00:00
)
2023-07-01 07:03:01 +00:00
for (const [tree, file] of content) {
const slug = file.data.slug!
2023-07-01 07:03:01 +00:00
if (slug.startsWith("tags/")) {
const tag = joinSegments(slug.slice("tags/".length), "index")
2023-07-01 07:03:01 +00:00
if (tags.has(tag)) {
tagDescriptions[tag] = [tree, file]
}
}
}
for (const tag of tags) {
2023-07-26 04:10:37 +00:00
const slug = joinSegments("tags", tag) as CanonicalSlug
2023-07-01 07:03:01 +00:00
const externalResources = pageResources(slug, resources)
const [tree, file] = tagDescriptions[tag]
const componentData: QuartzComponentProps = {
fileData: file.data,
externalResources,
cfg,
children: [],
tree,
2023-07-23 00:27:41 +00:00
allFiles,
2023-07-01 07:03:01 +00:00
}
2023-07-23 00:27:41 +00:00
const content = renderPage(slug, componentData, opts, externalResources)
2023-07-01 07:03:01 +00:00
2023-07-23 00:27:41 +00:00
const fp = (file.data.slug + ".html") as FilePath
2023-07-01 07:03:01 +00:00
await emit({
content,
slug: file.data.slug!,
ext: ".html",
})
fps.push(fp)
}
return fps
2023-07-23 00:27:41 +00:00
},
2023-07-01 07:03:01 +00:00
}
}