diff --git a/quartz/components/PageList.tsx b/quartz/components/PageList.tsx index c0538f5fa..380d06104 100644 --- a/quartz/components/PageList.tsx +++ b/quartz/components/PageList.tsx @@ -1,4 +1,4 @@ -import { FullSlug, resolveRelative } from "../util/path" +import { FullSlug, resolveRelative, slugTag } from "../util/path" import { QuartzPluginData } from "../plugins/vfile" import { Date, getDate } from "./Date" import { QuartzComponent, QuartzComponentProps } from "./types" @@ -61,7 +61,7 @@ export const PageList: QuartzComponent = ({ cfg, fileData, allFiles, limit, sort
  • {tag} diff --git a/quartz/components/RecentNotes.tsx b/quartz/components/RecentNotes.tsx index 2c32feadf..5c566520e 100644 --- a/quartz/components/RecentNotes.tsx +++ b/quartz/components/RecentNotes.tsx @@ -1,5 +1,5 @@ import { QuartzComponent, QuartzComponentConstructor, QuartzComponentProps } from "./types" -import { FullSlug, SimpleSlug, resolveRelative } from "../util/path" +import { FullSlug, SimpleSlug, resolveRelative, slugTag } from "../util/path" import { QuartzPluginData } from "../plugins/vfile" import { byDateAndAlphabetical } from "./PageList" import style from "./styles/recentNotes.scss" @@ -64,7 +64,10 @@ export default ((userOpts?: Partial) => {
  • {tag} diff --git a/quartz/components/pages/TagContent.tsx b/quartz/components/pages/TagContent.tsx index e56c6d609..f11cb921b 100644 --- a/quartz/components/pages/TagContent.tsx +++ b/quartz/components/pages/TagContent.tsx @@ -1,7 +1,7 @@ import { QuartzComponent, QuartzComponentConstructor, QuartzComponentProps } from "../types" import style from "../styles/listPage.scss" import { PageList, SortFn } from "../PageList" -import { FullSlug, getAllSegmentPrefixes, simplifySlug } from "../../util/path" +import { FullSlug, getAllSegmentPrefixes, simplifySlug, slugTag } from "../../util/path" import { QuartzPluginData } from "../../plugins/vfile" import { Root } from "hast" import { htmlToJsx } from "../../util/jsx" @@ -63,7 +63,8 @@ export default ((opts?: Partial) => { allFiles: pages, } - const contentPage = allFiles.filter((file) => file.slug === `tags/${tag}`).at(0) + const tagSlug = slugTag(tag) + const contentPage = allFiles.filter((file) => file.slug === `tags/${tagSlug}`).at(0) const root = contentPage?.htmlAst const content = @@ -74,7 +75,7 @@ export default ((opts?: Partial) => { return (

    - + {tag}

    diff --git a/quartz/plugins/emitters/tagPage.tsx b/quartz/plugins/emitters/tagPage.tsx index 9913e7d82..bedbf5c39 100644 --- a/quartz/plugins/emitters/tagPage.tsx +++ b/quartz/plugins/emitters/tagPage.tsx @@ -11,6 +11,7 @@ import { getAllSegmentPrefixes, joinSegments, pathToRoot, + slugTag, } from "../../util/path" import { defaultListPageLayout, sharedPageComponents } from "../../../quartz.layout" import { TagContent } from "../../components" @@ -64,7 +65,7 @@ export const TagPage: QuartzEmitterPlugin> = (userOpts) for (const tag of tags) { graph.addEdge( sourcePath, - joinSegments(ctx.argv.output, "tags", tag + ".html") as FilePath, + joinSegments(ctx.argv.output, "tags", slugTag(tag) + ".html") as FilePath, ) } } @@ -80,42 +81,56 @@ export const TagPage: QuartzEmitterPlugin> = (userOpts) allFiles.flatMap((data) => data.frontmatter?.tags ?? []).flatMap(getAllSegmentPrefixes), ) - // add base tag - tags.add("index") - - const tagDescriptions: Record = Object.fromEntries( + const tagDescriptions: Map = new Map( [...tags].map((tag) => { - const title = - tag === "index" - ? i18n(cfg.locale).pages.tagContent.tagIndex - : `${i18n(cfg.locale).pages.tagContent.tag}: ${tag}` - return [ - tag, - defaultProcessedContent({ - slug: joinSegments("tags", tag) as FullSlug, - frontmatter: { title, tags: [] }, - }), - ] + const title = `${i18n(cfg.locale).pages.tagContent.tag}: ${tag}` + const slug = joinSegments("tags", slugTag(tag)) as FullSlug + const content = defaultProcessedContent({ slug, frontmatter: { title } }) + return [slug, { tag, content }] }), ) + // add base tag + tagDescriptions.set("tags/index" as FullSlug, { + tag: "index", + content: defaultProcessedContent({ + slug: "tags/index" as FullSlug, + frontmatter: { + title: i18n(cfg.locale).pages.tagContent.tagIndex, + }, + }), + }) + + let tagFolder: string | undefined + for (const [tree, file] of content) { const slug = file.data.slug! - if (slug.startsWith("tags/")) { - const tag = slug.slice("tags/".length) - if (tags.has(tag)) { - tagDescriptions[tag] = [tree, file] - if (file.data.frontmatter?.title === tag) { - file.data.frontmatter.title = `${i18n(cfg.locale).pages.tagContent.tag}: ${tag}` - } - } + if (!slug.startsWith("tags/")) { + continue + } + const desc = tagDescriptions.get(slug) + if (!desc) { + continue + } + desc.content = [tree, file] + if (file.data.frontmatter?.title === desc.tag) { + file.data.frontmatter.title = `${i18n(cfg.locale).pages.tagContent.tag}: ${desc.tag}` + } + if (!tagFolder && file.data.relativePath) { + tagFolder = file.data.relativePath.split("/").at(0) } } - for (const tag of tags) { - const slug = joinSegments("tags", tag) as FullSlug - const [tree, file] = tagDescriptions[tag] - const externalResources = pageResources(pathToRoot(slug), file.data, resources) + // this is a hack to make sure our virtual `tags/index` page has the same folder as the other tag pages + // so that the breadcrumbs render consistent capitalization etc + if (tagFolder) { + const path = `${tagFolder}/index.html` as FilePath + tagDescriptions.get("tags/index" as FullSlug)!.content[1].data.relativePath = path + } + + for (const [slug, desc] of tagDescriptions.entries()) { + const [tree, file] = desc.content + const externalResources = pageResources(pathToRoot(slug as FullSlug), file.data, resources) const componentData: QuartzComponentProps = { ctx, fileData: file.data, diff --git a/quartz/plugins/transformers/ofm.ts b/quartz/plugins/transformers/ofm.ts index b0b0a42ef..dc0019d4f 100644 --- a/quartz/plugins/transformers/ofm.ts +++ b/quartz/plugins/transformers/ofm.ts @@ -337,7 +337,6 @@ export const ObsidianFlavoredMarkdown: QuartzTransformerPlugin> return false } - tag = slugTag(tag) if (file.data.frontmatter) { const noteTags = file.data.frontmatter.tags ?? [] file.data.frontmatter.tags = [...new Set([...noteTags, tag])] @@ -345,7 +344,7 @@ export const ObsidianFlavoredMarkdown: QuartzTransformerPlugin> return { type: "link", - url: base + `/tags/${tag}`, + url: `${base}/tags/${slugTag(tag)}`, data: { hProperties: { className: ["tag-link"],