diff --git a/quartz/plugins/transformers/description.ts b/quartz/plugins/transformers/description.ts index c6c1576..763a8f8 100644 --- a/quartz/plugins/transformers/description.ts +++ b/quartz/plugins/transformers/description.ts @@ -28,23 +28,12 @@ function isElementNode(node: RootContent): node is Element { return node.type === "element" } -function isMeaningfulNode(node: RootContent): boolean { - return normalizeWhitespace(toString(node)).length > 0 +function isHeadingElement(node: RootContent): node is Element { + return isElementNode(node) && /^h[1-6]$/.test(node.tagName) } -function isDuplicateTitleHeading(node: RootContent, pageTitle?: string): boolean { - if (!isElementNode(node) || node.tagName !== "h1") { - return false - } - - const headingText = normalizeWhitespace(toString(node)) - const normalizedTitle = normalizeWhitespace(pageTitle ?? "") - - if (headingText.length === 0) { - return false - } - - return normalizedTitle.length > 0 ? headingText === normalizedTitle : true +function isMeaningfulNode(node: RootContent): boolean { + return normalizeWhitespace(toString(node)).length > 0 } function isStandalonePreviewTagline(node: RootContent): boolean { @@ -67,14 +56,12 @@ function isStandalonePreviewTagline(node: RootContent): boolean { export function extractDescriptionText(tree: HTMLRoot, pageTitle?: string): string { const children = [...tree.children] let startIdx = 0 - let strippedTitle = false while (startIdx < children.length && !isMeaningfulNode(children[startIdx])) { startIdx++ } - if (startIdx < children.length && isDuplicateTitleHeading(children[startIdx], pageTitle)) { - strippedTitle = true + while (startIdx < children.length && isHeadingElement(children[startIdx])) { startIdx++ } @@ -82,11 +69,7 @@ export function extractDescriptionText(tree: HTMLRoot, pageTitle?: string): stri startIdx++ } - if ( - startIdx < children.length && - (strippedTitle || pageTitle) && - isStandalonePreviewTagline(children[startIdx]) - ) { + if (startIdx < children.length && pageTitle && isStandalonePreviewTagline(children[startIdx])) { startIdx++ } diff --git a/quartz/plugins/transformers/frontmatter.ts b/quartz/plugins/transformers/frontmatter.ts index db1cf42..7deb619 100644 --- a/quartz/plugins/transformers/frontmatter.ts +++ b/quartz/plugins/transformers/frontmatter.ts @@ -3,6 +3,8 @@ import remarkFrontmatter from "remark-frontmatter" import { QuartzTransformerPlugin } from "../types" import yaml from "js-yaml" import toml from "toml" +import { Root as MdRoot } from "mdast" +import { toString } from "mdast-util-to-string" import { FilePath, FullSlug, getFileExtension, slugifyFilePath, slugTag } from "../../util/path" import { QuartzPluginData } from "../vfile" import { i18n } from "../../i18n" @@ -52,6 +54,23 @@ function getAliasSlugs(aliases: string[]): FullSlug[] { return res } +function getFirstMarkdownHeading(root: MdRoot): string | undefined { + const firstMeaningfulNode = root.children.find((node) => { + if (node.type === "yaml") { + return false + } + + return toString(node).trim().length > 0 + }) + + if (!firstMeaningfulNode || firstMeaningfulNode.type !== "heading") { + return undefined + } + + const text = toString(firstMeaningfulNode).trim() + return text.length > 0 ? text : undefined +} + export const FrontMatter: QuartzTransformerPlugin> = (userOpts) => { const opts = { ...defaultOptions, ...userOpts } return { @@ -61,7 +80,7 @@ export const FrontMatter: QuartzTransformerPlugin> = (userOpts) return [ [remarkFrontmatter, ["yaml", "toml"]], () => { - return (_, file) => { + return (tree: MdRoot, file) => { const fileData = Buffer.from(file.value as Uint8Array) const { data } = matter(fileData, { ...opts, @@ -74,7 +93,10 @@ export const FrontMatter: QuartzTransformerPlugin> = (userOpts) if (data.title != null && data.title.toString() !== "") { data.title = data.title.toString() } else { - data.title = file.stem ?? i18n(cfg.configuration.locale).propertyDefaults.title + data.title = + getFirstMarkdownHeading(tree) ?? + file.stem ?? + i18n(cfg.configuration.locale).propertyDefaults.title } const tags = coerceToArray(coalesceAliases(data, ["tags", "tag"]))