mirror of
https://github.com/jackyzha0/quartz.git
synced 2026-02-03 22:15:42 -06:00
feat(contentIndex): add optional tag-based RSS feed generation
- Add 'includeTags' and 'rssTagsLimit' options to ContentIndex plugin - Implement logic to generate RSS feeds for unique tags - Output feeds to 'tags/<tag>/index.xml' - Support limiting the number of generated tag feeds by frequency
This commit is contained in:
parent
f346a01296
commit
47433a9068
@ -2,7 +2,7 @@ import { Root } from "hast"
|
|||||||
import { GlobalConfiguration } from "../../cfg"
|
import { GlobalConfiguration } from "../../cfg"
|
||||||
import { getDate } from "../../components/Date"
|
import { getDate } from "../../components/Date"
|
||||||
import { escapeHTML } from "../../util/escape"
|
import { escapeHTML } from "../../util/escape"
|
||||||
import { FilePath, FullSlug, SimpleSlug, joinSegments, simplifySlug } from "../../util/path"
|
import { FilePath, FullSlug, SimpleSlug, getAllSegmentPrefixes, joinSegments, simplifySlug } from "../../util/path"
|
||||||
import { QuartzEmitterPlugin } from "../types"
|
import { QuartzEmitterPlugin } from "../types"
|
||||||
import { toHtml } from "hast-util-to-html"
|
import { toHtml } from "hast-util-to-html"
|
||||||
import { write } from "./helpers"
|
import { write } from "./helpers"
|
||||||
@ -28,6 +28,8 @@ interface Options {
|
|||||||
rssFullHtml: boolean
|
rssFullHtml: boolean
|
||||||
rssSlug: string
|
rssSlug: string
|
||||||
includeEmptyFiles: boolean
|
includeEmptyFiles: boolean
|
||||||
|
includeTags: boolean
|
||||||
|
rssTagsLimit: number
|
||||||
}
|
}
|
||||||
|
|
||||||
const defaultOptions: Options = {
|
const defaultOptions: Options = {
|
||||||
@ -37,6 +39,8 @@ const defaultOptions: Options = {
|
|||||||
rssFullHtml: false,
|
rssFullHtml: false,
|
||||||
rssSlug: "index",
|
rssSlug: "index",
|
||||||
includeEmptyFiles: true,
|
includeEmptyFiles: true,
|
||||||
|
includeTags: false,
|
||||||
|
rssTagsLimit: 15,
|
||||||
}
|
}
|
||||||
|
|
||||||
function generateSiteMap(cfg: GlobalConfiguration, idx: ContentIndexMap): string {
|
function generateSiteMap(cfg: GlobalConfiguration, idx: ContentIndexMap): string {
|
||||||
@ -135,6 +139,39 @@ export const ContentIndex: QuartzEmitterPlugin<Partial<Options>> = (opts) => {
|
|||||||
slug: (opts?.rssSlug ?? "index") as FullSlug,
|
slug: (opts?.rssSlug ?? "index") as FullSlug,
|
||||||
ext: ".xml",
|
ext: ".xml",
|
||||||
})
|
})
|
||||||
|
|
||||||
|
if (opts?.includeTags && (opts.rssTagsLimit ?? 0) > 0) {
|
||||||
|
const tagCounts: Map<string, number> = new Map()
|
||||||
|
|
||||||
|
// Count tags from all non-empty files (unless includeEmptyFiles is true)
|
||||||
|
for (const [_, content] of linkIndex) {
|
||||||
|
const tags = content.tags.flatMap(getAllSegmentPrefixes)
|
||||||
|
for (const tag of new Set(tags)) { // Use Set to avoid double counting per file
|
||||||
|
tagCounts.set(tag, (tagCounts.get(tag) ?? 0) + 1)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const sortedTags = Array.from(tagCounts.entries())
|
||||||
|
.sort((a, b) => b[1] - a[1]) // Sort by frequency descending
|
||||||
|
.slice(0, opts.rssTagsLimit)
|
||||||
|
.map(([tag]) => tag)
|
||||||
|
|
||||||
|
for (const tag of sortedTags) {
|
||||||
|
const tagFilteredIndex = new Map(
|
||||||
|
Array.from(linkIndex).filter(([_, content]) => {
|
||||||
|
const fileTags = new Set(content.tags.flatMap(getAllSegmentPrefixes))
|
||||||
|
return fileTags.has(tag)
|
||||||
|
})
|
||||||
|
)
|
||||||
|
|
||||||
|
yield write({
|
||||||
|
ctx,
|
||||||
|
content: generateRSSFeed(cfg, tagFilteredIndex, opts.rssLimit),
|
||||||
|
slug: joinSegments("tags", tag, "index") as FullSlug,
|
||||||
|
ext: ".xml",
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const fp = joinSegments("static", "contentIndex") as FullSlug
|
const fp = joinSegments("static", "contentIndex") as FullSlug
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user