You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 

71 lines
2.1 KiB

import type MarkdownIt from "markdown-it"
/** 匹配以 --- 开头/结尾的 YAML front matter(全文开头) */
const FRONT_MATTER_RE = /^---[\t ]*\r?\n([\s\S]*?)\r?\n---[\t ]*(?:\r?\n|$)([\s\S]*)$/
export function splitFrontMatter(markdown: string): { front: string | null; body: string } {
const s = markdown.replace(/^\uFEFF/, "")
const m = FRONT_MATTER_RE.exec(s)
if (!m) {
return { front: null, body: markdown }
}
const frontBlock = m[1] ?? ""
const body = m[2] ?? ""
return { front: frontBlock.trim(), body }
}
/** 正文渲染用:去掉 front matter,避免把元数据块排进 HTML */
export function stripFrontMatter(markdown: string): string {
return splitFrontMatter(markdown).body
}
function pickYamlScalar(block: string, key: string): string {
const lines = block.split(/\r?\n/)
const prefix = `${key}:`
for (const line of lines) {
const t = line.trim()
if (!t.startsWith(prefix)) {
continue
}
let v = t.slice(prefix.length).trim()
if (!v) {
return ""
}
if (
(v.startsWith('"') && v.endsWith('"')) ||
(v.startsWith("'") && v.endsWith("'"))
) {
return v.slice(1, -1)
}
return v
}
return ""
}
/** 列表摘要:优先 `desc`,其次 `description`(简单标量行) */
export function extractFrontMatterDesc(markdown: string): string {
const { front } = splitFrontMatter(markdown)
if (!front) {
return ""
}
const d = pickYamlScalar(front, "desc") || pickYamlScalar(front, "description")
return d.trim()
}
export function listCardSummaryFromPostBody(bodyMarkdown: string, dbExcerpt: string): string {
const fromFm = extractFrontMatterDesc(bodyMarkdown)
if (fromFm) {
return fromFm
}
return (dbExcerpt ?? "").trim()
}
/**
* md-editor-v3 的 `markdownItConfig`:在 core 管线中去掉 front matter,预览与站点渲染一致。
* `ruleName` 须唯一(多编辑器实例时用 useId 等生成)。
*/
export function attachMarkdownItStripFrontMatter(md: MarkdownIt, ruleName: string): void {
md.core.ruler.after("normalize", ruleName, (state) => {
state.src = stripFrontMatter(state.src)
})
}