mirror of
https://github.com/JimLiu/baoyu-skills.git
synced 2026-07-30 05:39:47 +08:00
feat(baoyu-markdown-to-html): add HTML meta tags and quote stripping for frontmatter
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
@@ -126,7 +126,18 @@ export async function convertMarkdown(markdownPath: string, options?: { title?:
|
|||||||
|
|
||||||
const { frontmatter, body } = parseFrontmatter(content);
|
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) {
|
if (!title) {
|
||||||
const lines = body.split('\n');
|
const lines = body.split('\n');
|
||||||
for (const line of lines) {
|
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));
|
if (!title) title = path.basename(markdownPath, path.extname(markdownPath));
|
||||||
const author = frontmatter.author || '';
|
const author = stripQuotes(frontmatter.author);
|
||||||
let summary = frontmatter.description || frontmatter.summary || '';
|
let summary = stripQuotes(frontmatter.description) || stripQuotes(frontmatter.summary);
|
||||||
|
|
||||||
if (!summary) {
|
if (!summary) {
|
||||||
const lines = body.split('\n');
|
const lines = body.split('\n');
|
||||||
|
|||||||
@@ -708,14 +708,28 @@ function normalizeThemeCss(css: string): string {
|
|||||||
return stripOutputScope(css);
|
return stripOutputScope(css);
|
||||||
}
|
}
|
||||||
|
|
||||||
function buildHtmlDocument(title: string, css: string, html: string): string {
|
interface HtmlDocumentMeta {
|
||||||
return [
|
title: string;
|
||||||
|
author?: string;
|
||||||
|
description?: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
function buildHtmlDocument(meta: HtmlDocumentMeta, css: string, html: string): string {
|
||||||
|
const lines = [
|
||||||
"<!doctype html>",
|
"<!doctype html>",
|
||||||
"<html>",
|
"<html>",
|
||||||
"<head>",
|
"<head>",
|
||||||
' <meta charset="utf-8" />',
|
' <meta charset="utf-8" />',
|
||||||
' <meta name="viewport" content="width=device-width, initial-scale=1" />',
|
' <meta name="viewport" content="width=device-width, initial-scale=1" />',
|
||||||
` <title>${title}</title>`,
|
` <title>${meta.title}</title>`,
|
||||||
|
];
|
||||||
|
if (meta.author) {
|
||||||
|
lines.push(` <meta name="author" content="${meta.author}" />`);
|
||||||
|
}
|
||||||
|
if (meta.description) {
|
||||||
|
lines.push(` <meta name="description" content="${meta.description}" />`);
|
||||||
|
}
|
||||||
|
lines.push(
|
||||||
` <style>${css}</style>`,
|
` <style>${css}</style>`,
|
||||||
"</head>",
|
"</head>",
|
||||||
"<body>",
|
"<body>",
|
||||||
@@ -723,8 +737,9 @@ function buildHtmlDocument(title: string, css: string, html: string): string {
|
|||||||
html,
|
html,
|
||||||
" </div>",
|
" </div>",
|
||||||
"</body>",
|
"</body>",
|
||||||
"</html>",
|
"</html>"
|
||||||
].join("\n");
|
);
|
||||||
|
return lines.join("\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
async function inlineCss(html: string): Promise<string> {
|
async function inlineCss(html: string): Promise<string> {
|
||||||
@@ -814,6 +829,7 @@ async function main(): Promise<void> {
|
|||||||
const markdown = fs.readFileSync(inputPath, "utf-8");
|
const markdown = fs.readFileSync(inputPath, "utf-8");
|
||||||
|
|
||||||
const renderer = initRenderer({});
|
const renderer = initRenderer({});
|
||||||
|
const { yamlData } = renderer.parseFrontMatterAndContent(markdown);
|
||||||
const { html: baseHtml, readingTime: readingTimeResult } = renderMarkdown(
|
const { html: baseHtml, readingTime: readingTimeResult } = renderMarkdown(
|
||||||
markdown,
|
markdown,
|
||||||
renderer
|
renderer
|
||||||
@@ -823,8 +839,23 @@ async function main(): Promise<void> {
|
|||||||
content = removeFirstHeading(content);
|
content = removeFirstHeading(content);
|
||||||
}
|
}
|
||||||
|
|
||||||
const title = path.basename(outputPath, ".html");
|
const stripQuotes = (s?: string): string | undefined => {
|
||||||
const html = buildHtmlDocument(title, css, content);
|
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 inlinedHtml = normalizeInlineCss(await inlineCss(html));
|
||||||
const finalHtml = modifyHtmlStructure(inlinedHtml);
|
const finalHtml = modifyHtmlStructure(inlinedHtml);
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user