Merge 39ff322777e29515360cc135b6175a5efd9a7fcb into 32ec711767401c93605b7631f03eee47dea1cada

This commit is contained in:
Anton Bulakh 2025-02-07 01:29:57 +08:00 committed by GitHub
commit 4d86830d92
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
5 changed files with 55 additions and 37 deletions

View File

@ -1,4 +1,4 @@
import { FullSlug, resolveRelative } from "../util/path" import { FullSlug, resolveRelative, slugTag } from "../util/path"
import { QuartzPluginData } from "../plugins/vfile" import { QuartzPluginData } from "../plugins/vfile"
import { Date, getDate } from "./Date" import { Date, getDate } from "./Date"
import { QuartzComponent, QuartzComponentProps } from "./types" import { QuartzComponent, QuartzComponentProps } from "./types"
@ -61,7 +61,7 @@ export const PageList: QuartzComponent = ({ cfg, fileData, allFiles, limit, sort
<li> <li>
<a <a
class="internal tag-link" class="internal tag-link"
href={resolveRelative(fileData.slug!, `tags/${tag}` as FullSlug)} href={resolveRelative(fileData.slug!, `tags/${slugTag(tag)}` as FullSlug)}
> >
{tag} {tag}
</a> </a>

View File

@ -1,5 +1,5 @@
import { QuartzComponent, QuartzComponentConstructor, QuartzComponentProps } from "./types" 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 { QuartzPluginData } from "../plugins/vfile"
import { byDateAndAlphabetical } from "./PageList" import { byDateAndAlphabetical } from "./PageList"
import style from "./styles/recentNotes.scss" import style from "./styles/recentNotes.scss"
@ -64,7 +64,10 @@ export default ((userOpts?: Partial<Options>) => {
<li> <li>
<a <a
class="internal tag-link" class="internal tag-link"
href={resolveRelative(fileData.slug!, `tags/${tag}` as FullSlug)} href={resolveRelative(
fileData.slug!,
`tags/${slugTag(tag)}` as FullSlug,
)}
> >
{tag} {tag}
</a> </a>

View File

@ -1,7 +1,7 @@
import { QuartzComponent, QuartzComponentConstructor, QuartzComponentProps } from "../types" import { QuartzComponent, QuartzComponentConstructor, QuartzComponentProps } from "../types"
import style from "../styles/listPage.scss" import style from "../styles/listPage.scss"
import { PageList, SortFn } from "../PageList" 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 { QuartzPluginData } from "../../plugins/vfile"
import { Root } from "hast" import { Root } from "hast"
import { htmlToJsx } from "../../util/jsx" import { htmlToJsx } from "../../util/jsx"
@ -63,7 +63,8 @@ export default ((opts?: Partial<TagContentOptions>) => {
allFiles: pages, 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 root = contentPage?.htmlAst
const content = const content =
@ -74,7 +75,7 @@ export default ((opts?: Partial<TagContentOptions>) => {
return ( return (
<div> <div>
<h2> <h2>
<a class="internal tag-link" href={`../tags/${tag}`}> <a class="internal tag-link" href={`../tags/${tagSlug}`}>
{tag} {tag}
</a> </a>
</h2> </h2>

View File

@ -11,6 +11,7 @@ import {
getAllSegmentPrefixes, getAllSegmentPrefixes,
joinSegments, joinSegments,
pathToRoot, pathToRoot,
slugTag,
} from "../../util/path" } from "../../util/path"
import { defaultListPageLayout, sharedPageComponents } from "../../../quartz.layout" import { defaultListPageLayout, sharedPageComponents } from "../../../quartz.layout"
import { TagContent } from "../../components" import { TagContent } from "../../components"
@ -64,7 +65,7 @@ export const TagPage: QuartzEmitterPlugin<Partial<TagPageOptions>> = (userOpts)
for (const tag of tags) { for (const tag of tags) {
graph.addEdge( graph.addEdge(
sourcePath, 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<Partial<TagPageOptions>> = (userOpts)
allFiles.flatMap((data) => data.frontmatter?.tags ?? []).flatMap(getAllSegmentPrefixes), allFiles.flatMap((data) => data.frontmatter?.tags ?? []).flatMap(getAllSegmentPrefixes),
) )
// add base tag const tagDescriptions: Map<FullSlug, { tag: string; content: ProcessedContent }> = new Map(
tags.add("index")
const tagDescriptions: Record<string, ProcessedContent> = Object.fromEntries(
[...tags].map((tag) => { [...tags].map((tag) => {
const title = const title = `${i18n(cfg.locale).pages.tagContent.tag}: ${tag}`
tag === "index" const slug = joinSegments("tags", slugTag(tag)) as FullSlug
? i18n(cfg.locale).pages.tagContent.tagIndex const content = defaultProcessedContent({ slug, frontmatter: { title } })
: `${i18n(cfg.locale).pages.tagContent.tag}: ${tag}` return [slug, { tag, content }]
return [
tag,
defaultProcessedContent({
slug: joinSegments("tags", tag) as FullSlug,
frontmatter: { title, tags: [] },
}),
]
}), }),
) )
// 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) { for (const [tree, file] of content) {
const slug = file.data.slug! const slug = file.data.slug!
if (slug.startsWith("tags/")) { if (!slug.startsWith("tags/")) {
const tag = slug.slice("tags/".length) continue
if (tags.has(tag)) { }
tagDescriptions[tag] = [tree, file] const desc = tagDescriptions.get(slug)
if (file.data.frontmatter?.title === tag) { if (!desc) {
file.data.frontmatter.title = `${i18n(cfg.locale).pages.tagContent.tag}: ${tag}` 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) { // this is a hack to make sure our virtual `tags/index` page has the same folder as the other tag pages
const slug = joinSegments("tags", tag) as FullSlug // so that the breadcrumbs render consistent capitalization etc
const [tree, file] = tagDescriptions[tag] if (tagFolder) {
const externalResources = pageResources(pathToRoot(slug), file.data, resources) 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 = { const componentData: QuartzComponentProps = {
ctx, ctx,
fileData: file.data, fileData: file.data,

View File

@ -337,7 +337,6 @@ export const ObsidianFlavoredMarkdown: QuartzTransformerPlugin<Partial<Options>>
return false return false
} }
tag = slugTag(tag)
if (file.data.frontmatter) { if (file.data.frontmatter) {
const noteTags = file.data.frontmatter.tags ?? [] const noteTags = file.data.frontmatter.tags ?? []
file.data.frontmatter.tags = [...new Set([...noteTags, tag])] file.data.frontmatter.tags = [...new Set([...noteTags, tag])]
@ -345,7 +344,7 @@ export const ObsidianFlavoredMarkdown: QuartzTransformerPlugin<Partial<Options>>
return { return {
type: "link", type: "link",
url: base + `/tags/${tag}`, url: `${base}/tags/${slugTag(tag)}`,
data: { data: {
hProperties: { hProperties: {
className: ["tag-link"], className: ["tag-link"],