From 876c6332f68ca22e87e1ab518ec511346169c13a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jim=20Liu=20=E5=AE=9D=E7=8E=89?= Date: Tue, 3 Feb 2026 11:49:07 -0600 Subject: [PATCH] feat(baoyu-markdown-to-html): add HTML meta tags and quote stripping for frontmatter Co-Authored-By: Claude Opus 4.5 --- skills/baoyu-markdown-to-html/scripts/main.ts | 17 +++++-- .../scripts/md/render.ts | 45 ++++++++++++++++--- 2 files changed, 52 insertions(+), 10 deletions(-) diff --git a/skills/baoyu-markdown-to-html/scripts/main.ts b/skills/baoyu-markdown-to-html/scripts/main.ts index 9c34c30..3779caa 100644 --- a/skills/baoyu-markdown-to-html/scripts/main.ts +++ b/skills/baoyu-markdown-to-html/scripts/main.ts @@ -126,7 +126,18 @@ export async function convertMarkdown(markdownPath: string, options?: { title?: const { frontmatter, body } = parseFrontmatter(content); - let title = options?.title ?? frontmatter.title ?? ''; + const stripQuotes = (s?: string): string => { + if (!s) return ''; + if ((s.startsWith('"') && s.endsWith('"')) || (s.startsWith("'") && s.endsWith("'"))) { + return s.slice(1, -1); + } + if ((s.startsWith('\u201c') && s.endsWith('\u201d')) || (s.startsWith('\u2018') && s.endsWith('\u2019'))) { + return s.slice(1, -1); + } + return s; + }; + + let title = options?.title ?? stripQuotes(frontmatter.title) ?? ''; if (!title) { const lines = body.split('\n'); for (const line of lines) { @@ -138,8 +149,8 @@ export async function convertMarkdown(markdownPath: string, options?: { title?: } } if (!title) title = path.basename(markdownPath, path.extname(markdownPath)); - const author = frontmatter.author || ''; - let summary = frontmatter.description || frontmatter.summary || ''; + const author = stripQuotes(frontmatter.author); + let summary = stripQuotes(frontmatter.description) || stripQuotes(frontmatter.summary); if (!summary) { const lines = body.split('\n'); diff --git a/skills/baoyu-markdown-to-html/scripts/md/render.ts b/skills/baoyu-markdown-to-html/scripts/md/render.ts index 7cd4620..b703ca7 100644 --- a/skills/baoyu-markdown-to-html/scripts/md/render.ts +++ b/skills/baoyu-markdown-to-html/scripts/md/render.ts @@ -708,14 +708,28 @@ function normalizeThemeCss(css: string): string { return stripOutputScope(css); } -function buildHtmlDocument(title: string, css: string, html: string): string { - return [ +interface HtmlDocumentMeta { + title: string; + author?: string; + description?: string; +} + +function buildHtmlDocument(meta: HtmlDocumentMeta, css: string, html: string): string { + const lines = [ "", "", "", ' ', ' ', - ` ${title}`, + ` ${meta.title}`, + ]; + if (meta.author) { + lines.push(` `); + } + if (meta.description) { + lines.push(` `); + } + lines.push( ` `, "", "", @@ -723,8 +737,9 @@ function buildHtmlDocument(title: string, css: string, html: string): string { html, " ", "", - "", - ].join("\n"); + "" + ); + return lines.join("\n"); } async function inlineCss(html: string): Promise { @@ -814,6 +829,7 @@ async function main(): Promise { const markdown = fs.readFileSync(inputPath, "utf-8"); const renderer = initRenderer({}); + const { yamlData } = renderer.parseFrontMatterAndContent(markdown); const { html: baseHtml, readingTime: readingTimeResult } = renderMarkdown( markdown, renderer @@ -823,8 +839,23 @@ async function main(): Promise { content = removeFirstHeading(content); } - const title = path.basename(outputPath, ".html"); - const html = buildHtmlDocument(title, css, content); + const stripQuotes = (s?: string): string | undefined => { + if (!s) return s; + if ((s.startsWith('"') && s.endsWith('"')) || (s.startsWith("'") && s.endsWith("'"))) { + return s.slice(1, -1); + } + if ((s.startsWith('\u201c') && s.endsWith('\u201d')) || (s.startsWith('\u2018') && s.endsWith('\u2019'))) { + return s.slice(1, -1); + } + return s; + }; + + const meta: HtmlDocumentMeta = { + title: stripQuotes(yamlData.title) || path.basename(outputPath, ".html"), + author: stripQuotes(yamlData.author), + description: stripQuotes(yamlData.description) || stripQuotes(yamlData.summary), + }; + const html = buildHtmlDocument(meta, css, content); const inlinedHtml = normalizeInlineCss(await inlineCss(html)); const finalHtml = modifyHtmlStructure(inlinedHtml);