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 (
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"],