Merge branch 'SplitRSS' of github-bfahrenfort:bfahrenfort/quartz into v4

This commit is contained in:
bfahrenfort 2024-02-14 13:53:29 -06:00
commit 1b14e33bf1

View File

@ -8,6 +8,7 @@ import { toHtml } from "hast-util-to-html"
import { write } from "./helpers" import { write } from "./helpers"
import { i18n } from "../../i18n" import { i18n } from "../../i18n"
import DepGraph from "../../depgraph" import DepGraph from "../../depgraph"
import chalk from "chalk"
export type ContentIndex = Map<FullSlug, ContentDetails> export type ContentIndex = Map<FullSlug, ContentDetails>
export type ContentDetails = { export type ContentDetails = {
@ -23,6 +24,7 @@ export type ContentDetails = {
interface Options { interface Options {
enableSiteMap: boolean enableSiteMap: boolean
enableRSS: boolean enableRSS: boolean
bypassIndexCheck: boolean
rssLimit?: number rssLimit?: number
rssFullHtml: boolean rssFullHtml: boolean
includeEmptyFiles: boolean includeEmptyFiles: boolean
@ -30,6 +32,7 @@ interface Options {
} }
const defaultOptions: Options = { const defaultOptions: Options = {
bypassIndexCheck: false,
enableSiteMap: true, enableSiteMap: true,
enableRSS: true, enableRSS: true,
rssLimit: 10, rssLimit: 10,
@ -51,9 +54,6 @@ function generateSiteMap(cfg: GlobalConfiguration, idx: ContentIndex): string {
} }
function generateRSSFeed(cfg: GlobalConfiguration, idx: ContentIndex, limit?: number): string { function generateRSSFeed(cfg: GlobalConfiguration, idx: ContentIndex, limit?: number): string {
if (idx == undefined) {
return ""
}
const base = cfg.baseUrl ?? "" const base = cfg.baseUrl ?? ""
const createURLEntry = (slug: SimpleSlug, content: ContentDetails): string => `<item> const createURLEntry = (slug: SimpleSlug, content: ContentDetails): string => `<item>
@ -119,15 +119,24 @@ export const ContentIndex: QuartzEmitterPlugin<Partial<Options>> = (opts) => {
return graph return graph
}, },
async emit(ctx, content, _resources) { async emit(ctx, content, _resources) {
// If we're missing an index file, don't bother with sitemap/RSS gen
if (!(opts?.bypassIndexCheck || "index" in content.map((c) => c[1].data.slug!))) {
console.warn(
chalk.yellow(`Warning: contentIndex:
content/ folder is missing an index.md. RSS feeds and sitemap will not be generated.
If you still wish to generate these files, add:
bypassIndexCheck: true,
to your configuration for Plugin.ContentIndex({...}) in quartz.config.ts.
Don't do this unless you know what you're doing!`),
)
return []
}
const cfg = ctx.cfg.configuration const cfg = ctx.cfg.configuration
const emitted: FilePath[] = [] const emitted: Promise<FilePath>[] = []
const feedIndices: Map<String, ContentIndex> = new Map() const feedIndices: Map<string, ContentIndex> = new Map()
// bfahrenfort: ts can't see the expansion of opts above that guarantees a non-null feedDirectories for (const feed of opts?.feedDirectories!) {
const directories =
opts?.feedDirectories == null ? defaultOptions.feedDirectories : opts.feedDirectories
for (const feed of directories) {
const linkIndex: ContentIndex = new Map() const linkIndex: ContentIndex = new Map()
for (const [tree, file] of content) { for (const [tree, file] of content) {
const slug = file.data.slug! const slug = file.data.slug!
@ -153,13 +162,14 @@ export const ContentIndex: QuartzEmitterPlugin<Partial<Options>> = (opts) => {
feedIndices.set(feed, linkIndex) feedIndices.set(feed, linkIndex)
} }
const siteFeed = feedIndices.get("index")!
if (opts?.enableSiteMap) { if (opts?.enableSiteMap) {
emitted.push( emitted.push(
await write({ write({
ctx, ctx,
// bfahrenfort: "index" is guaranteed non-null // bfahrenfort: "index" is guaranteed non-null
// see directories instantiation and feedIndices.set iterating over directories // see directories instantiation and feedIndices.set iterating over directories
content: generateSiteMap(cfg, feedIndices.get("index")!), content: generateSiteMap(cfg, siteFeed),
slug: "sitemap" as FullSlug, slug: "sitemap" as FullSlug,
ext: ".xml", ext: ".xml",
}), }),
@ -167,21 +177,22 @@ export const ContentIndex: QuartzEmitterPlugin<Partial<Options>> = (opts) => {
} }
if (opts?.enableRSS) { if (opts?.enableRSS) {
directories.map(async (feed) => { opts.feedDirectories!.map((feed) => {
const emittedFeed = await write({ emitted.push(
ctx, write({
// bfahrenfort: we just generated a feedIndices entry for every directories entry, guaranteed non-null ctx,
content: generateRSSFeed(cfg, feedIndices.get(feed)!, opts?.rssLimit), // bfahrenfort: we just generated a feedIndices entry for every directories entry, guaranteed non-null
slug: feed as FullSlug, content: generateRSSFeed(cfg, feedIndices.get(feed)!, opts?.rssLimit),
ext: ".xml", slug: feed as FullSlug,
}) ext: ".xml",
emitted.push(emittedFeed) }),
)
}) })
} }
const fp = joinSegments("static", "contentIndex") as FullSlug const fp = joinSegments("static", "contentIndex") as FullSlug
const simplifiedIndex = Object.fromEntries( const simplifiedIndex = Object.fromEntries(
Array.from(feedIndices.get("index") ?? []).map(([slug, content]) => { Array.from(feedIndices.get("index")!).map(([slug, content]) => {
// remove description and from content index as nothing downstream // remove description and from content index as nothing downstream
// actually uses it. we only keep it in the index as we need it // actually uses it. we only keep it in the index as we need it
// for the RSS feed // for the RSS feed
@ -192,7 +203,7 @@ export const ContentIndex: QuartzEmitterPlugin<Partial<Options>> = (opts) => {
) )
emitted.push( emitted.push(
await write({ write({
ctx, ctx,
content: JSON.stringify(simplifiedIndex), content: JSON.stringify(simplifiedIndex),
slug: fp, slug: fp,
@ -200,7 +211,7 @@ export const ContentIndex: QuartzEmitterPlugin<Partial<Options>> = (opts) => {
}), }),
) )
return emitted return await Promise.all(emitted)
}, },
getQuartzComponents: () => [], getQuartzComponents: () => [],
} }