printdown 1.1.1 → 1.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +177 -0
- package/dist/{chunk-ZB6NLLOD.js → chunk-BLKOSAAA.js} +861 -59
- package/dist/chunk-BLKOSAAA.js.map +1 -0
- package/dist/{chunk-GEQQR3U7.js → chunk-QYKBYAYW.js} +221 -4
- package/dist/chunk-QYKBYAYW.js.map +1 -0
- package/dist/cli.js +24 -6
- package/dist/cli.js.map +1 -1
- package/dist/index.d.ts +89 -2
- package/dist/index.js +19 -5
- package/dist/themes/default/index.d.ts +8 -2
- package/dist/themes/default/index.js +5 -1
- package/dist/themes/default/style.css +211 -3
- package/package.json +3 -1
- package/dist/chunk-GEQQR3U7.js.map +0 -1
- package/dist/chunk-ZB6NLLOD.js.map +0 -1
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/index.ts","../src/markdown/index.ts","../src/markdown/plugins/highlight.ts","../src/markdown/plugins/task-list.ts","../src/markdown/plugins/badge.ts","../src/markdown/plugins/kbd.ts","../src/markdown/plugins/center.ts","../src/markdown/plugins/heading.ts","../src/markdown/plugins/page-break.ts","../src/markdown/plugins/cover.ts","../src/markdown/plugins/math.ts","../src/renderer/index.ts","../src/renderer/header-footer.ts","../src/renderer/html.ts","../src/renderer/images.ts"],"sourcesContent":["import fs from \"node:fs\";\nimport path from \"node:path\";\nimport { createMarkdownRenderer } from \"./markdown/index.js\";\nimport { mathPlugin, type MathPluginOptions } from \"./markdown/plugins/math.js\";\nimport { BrowserRenderer, renderHtmlToBuffer, renderHtmlToPageBuffers } from \"./renderer/index.js\";\nimport {\n buildHeaderFooterHtml,\n resolveHeaderFooterPdfOptions,\n formatHeaderFooterCanvasText,\n type HeaderFooterTemplateOptions,\n} from \"./renderer/header-footer.js\";\nimport { buildHtmlDocument } from \"./renderer/html.js\";\nimport { resolveLocalImageToDataUri, inlineLocalImagesInHtml } from \"./renderer/images.js\";\nimport {\n defaultTheme,\n defaultThemeCss,\n defaultThemeCssParts,\n mathCss,\n} from \"./themes/default/index.js\";\nimport type { OutputFormat, RenderFileOptions, RenderOptions } from \"./types.js\";\n\nexport * from \"./types.js\";\nexport {\n BrowserRenderer,\n createMarkdownRenderer,\n mathPlugin,\n type MathPluginOptions,\n defaultTheme,\n defaultThemeCss,\n defaultThemeCssParts,\n mathCss,\n renderHtmlToPageBuffers,\n buildHeaderFooterHtml,\n resolveHeaderFooterPdfOptions,\n formatHeaderFooterCanvasText,\n type HeaderFooterTemplateOptions,\n resolveLocalImageToDataUri,\n inlineLocalImagesInHtml,\n};\n\nfunction inferFormat(output?: string, explicitFormat?: OutputFormat): OutputFormat {\n if (explicitFormat) {\n return explicitFormat;\n }\n if (output) {\n const ext = path.extname(output).toLowerCase();\n if (ext === \".png\") return \"png\";\n if (ext === \".jpg\" || ext === \".jpeg\") return \"jpeg\";\n if (ext === \".webp\") return \"webp\";\n if (ext === \".pdf\") return \"pdf\";\n }\n return \"pdf\";\n}\n\nfunction resolvePageOutputFilePath(\n outputPath: string,\n pageIndex: number,\n totalPages: number,\n): string {\n const pageNumber = pageIndex + 1;\n if (outputPath.includes(\"%d\")) {\n return outputPath.replace(/%d/g, String(pageNumber));\n }\n if (totalPages === 1 && !outputPath.includes(\"-1\")) {\n // If only 1 page, we can still use -1 or keep name, but let's append -1 for consistency with multi-page requests\n const parsed = path.parse(outputPath);\n return path.join(parsed.dir, `${parsed.name}-${pageNumber}${parsed.ext}`);\n }\n const parsed = path.parse(outputPath);\n return path.join(parsed.dir, `${parsed.name}-${pageNumber}${parsed.ext}`);\n}\n\n/**\n * Compiles Markdown into an HTML document with theme and custom styles.\n */\nexport async function renderToHtml(markdown: string, options: RenderOptions = {}): Promise<string> {\n const markdownOptions = {\n ...options.markdown,\n ...(options.katex ? { katex: options.katex } : {}),\n };\n const md = await createMarkdownRenderer(markdownOptions);\n const bodyHtml = md.render(markdown);\n return buildHtmlDocument(bodyHtml, options);\n}\n\n/**\n * Renders Markdown to multiple page image buffers (matching A4 / PDF page dimensions).\n * If `options.output` is provided, each page image will be saved to disk.\n */\nexport async function renderPages(\n markdown: string,\n options: RenderOptions = {},\n): Promise<Buffer[]> {\n const format = inferFormat(options.output, options.format);\n const html = await renderToHtml(markdown, options);\n const buffers = await renderHtmlToPageBuffers(html, format, options);\n\n if (options.output) {\n const resolvedPath = path.resolve(options.output);\n const outputDir = path.dirname(resolvedPath);\n if (!fs.existsSync(outputDir)) {\n fs.mkdirSync(outputDir, { recursive: true });\n }\n\n if (format === \"pdf\" && buffers.length === 1) {\n fs.writeFileSync(resolvedPath, buffers[0]);\n } else {\n buffers.forEach((buf, idx) => {\n const filePath = resolvePageOutputFilePath(resolvedPath, idx, buffers.length);\n fs.writeFileSync(filePath, buf);\n });\n }\n }\n\n return buffers;\n}\n\n/**\n * Renders a Markdown file to multiple page image buffers.\n * If `options.output` is provided, each page image will be saved to disk.\n */\nexport async function renderFilePages(\n filePath: string,\n options: RenderFileOptions = {},\n): Promise<Buffer[]> {\n const absolutePath = path.resolve(filePath);\n const encoding = options.encoding ?? \"utf-8\";\n const markdown = fs.readFileSync(absolutePath, encoding);\n\n const fileDir = path.dirname(absolutePath);\n const baseUrl = options.baseUrl ?? fileDir;\n\n return renderPages(markdown, {\n baseUrl,\n ...options,\n });\n}\n\n/**\n * Renders Markdown to PDF, PNG, JPEG, or WebP buffer (or multiple buffers if `options.pages` is true).\n * If `options.output` is provided, the result is saved to disk.\n */\nexport async function render(\n markdown: string,\n options?: RenderOptions & { pages?: false },\n): Promise<Buffer>;\nexport async function render(\n markdown: string,\n options: RenderOptions & { pages: true },\n): Promise<Buffer[]>;\nexport async function render(markdown: string, options?: RenderOptions): Promise<Buffer | Buffer[]>;\nexport async function render(\n markdown: string,\n options: RenderOptions = {},\n): Promise<Buffer | Buffer[]> {\n if (options.pages) {\n return renderPages(markdown, options);\n }\n\n const format = inferFormat(options.output, options.format);\n const html = await renderToHtml(markdown, options);\n const buffer = await renderHtmlToBuffer(html, format, options);\n\n if (options.output) {\n const outputPath = path.resolve(options.output);\n const outputDir = path.dirname(outputPath);\n if (!fs.existsSync(outputDir)) {\n fs.mkdirSync(outputDir, { recursive: true });\n }\n fs.writeFileSync(outputPath, buffer);\n }\n\n return buffer;\n}\n\n/**\n * Renders a Markdown file to PDF, PNG, JPEG, or WebP buffer (or multiple buffers if `options.pages` is true).\n * If `options.output` is provided, the result is saved to disk.\n */\nexport async function renderFile(\n filePath: string,\n options?: RenderFileOptions & { pages?: false },\n): Promise<Buffer>;\nexport async function renderFile(\n filePath: string,\n options: RenderFileOptions & { pages: true },\n): Promise<Buffer[]>;\nexport async function renderFile(\n filePath: string,\n options?: RenderFileOptions,\n): Promise<Buffer | Buffer[]>;\nexport async function renderFile(\n filePath: string,\n options: RenderFileOptions = {},\n): Promise<Buffer | Buffer[]> {\n const absolutePath = path.resolve(filePath);\n const encoding = options.encoding ?? \"utf-8\";\n const markdown = fs.readFileSync(absolutePath, encoding);\n\n const fileDir = path.dirname(absolutePath);\n const baseUrl = options.baseUrl ?? fileDir;\n\n if (options.pages) {\n return renderPages(markdown, {\n baseUrl,\n ...options,\n });\n }\n\n return render(markdown, {\n baseUrl,\n ...options,\n });\n}\n","import MarkdownIt from \"markdown-it\";\nimport {\n createHighlighter,\n type BundledLanguage,\n type BundledTheme,\n type Highlighter,\n} from \"shiki\";\nimport { highlightPlugin } from \"./plugins/highlight.js\";\nimport { taskListPlugin } from \"./plugins/task-list.js\";\nimport { badgePlugin } from \"./plugins/badge.js\";\nimport { kbdPlugin } from \"./plugins/kbd.js\";\nimport { centerPlugin } from \"./plugins/center.js\";\nimport { headingPlugin } from \"./plugins/heading.js\";\nimport { pageBreakPlugin } from \"./plugins/page-break.js\";\nimport { coverPlugin } from \"./plugins/cover.js\";\nimport { mathPlugin } from \"./plugins/math.js\";\nimport type { KatexOptions } from \"katex\";\n\nexport interface MarkdownOptions {\n html?: boolean;\n linkify?: boolean;\n typographer?: boolean;\n shiki?: {\n theme?: BundledTheme | string;\n langs?: (BundledLanguage | string)[];\n };\n katex?: KatexOptions;\n}\n\nconst DEFAULT_LANGS: BundledLanguage[] = [\n \"javascript\",\n \"typescript\",\n \"jsx\",\n \"tsx\",\n \"html\",\n \"css\",\n \"json\",\n \"markdown\",\n \"mdx\",\n \"bash\",\n \"shell\",\n \"yaml\",\n \"toml\",\n \"sql\",\n \"python\",\n \"rust\",\n \"go\",\n \"c\",\n \"cpp\",\n \"diff\",\n \"dockerfile\",\n \"graphql\",\n \"ini\",\n \"java\",\n \"kotlin\",\n \"ruby\",\n \"php\",\n \"swift\",\n \"xml\",\n];\n\nconst DEFAULT_THEME: BundledTheme = \"github-dark\";\n\nlet cachedHighlighter: Highlighter | null = null;\nconst cachedLangs = new Set<string>();\nconst cachedThemes = new Set<string>();\n\nexport async function getHighlighter(options?: MarkdownOptions[\"shiki\"]): Promise<Highlighter> {\n const theme = (options?.theme as BundledTheme) || DEFAULT_THEME;\n const userLangs = (options?.langs as BundledLanguage[]) || [];\n const requiredLangs = Array.from(new Set([...DEFAULT_LANGS, ...userLangs]));\n\n if (!cachedHighlighter) {\n cachedHighlighter = await createHighlighter({\n themes: [theme],\n langs: requiredLangs,\n });\n for (const lang of requiredLangs) {\n cachedLangs.add(lang);\n }\n cachedThemes.add(theme);\n return cachedHighlighter;\n }\n\n // Load missing theme if necessary\n if (!cachedThemes.has(theme)) {\n await cachedHighlighter.loadTheme(theme);\n cachedThemes.add(theme);\n }\n\n // Load missing languages if necessary\n const missingLangs = requiredLangs.filter((l) => !cachedLangs.has(l));\n if (missingLangs.length > 0) {\n await cachedHighlighter.loadLanguage(...missingLangs);\n for (const lang of missingLangs) {\n cachedLangs.add(lang);\n }\n }\n\n return cachedHighlighter;\n}\n\nexport async function createMarkdownRenderer(\n options: MarkdownOptions = {},\n): Promise<InstanceType<typeof MarkdownIt>> {\n const md = new MarkdownIt({\n html: options.html ?? true,\n linkify: options.linkify ?? true,\n typographer: options.typographer ?? true,\n });\n\n // Apply plugins\n md.use(highlightPlugin);\n md.use(taskListPlugin);\n md.use(badgePlugin);\n md.use(kbdPlugin);\n md.use(centerPlugin);\n md.use(headingPlugin);\n md.use(pageBreakPlugin);\n md.use(coverPlugin);\n md.use(mathPlugin, { katexOptions: options.katex });\n\n // Initialize Shiki\n const highlighter = await getHighlighter(options.shiki);\n const theme = options.shiki?.theme || DEFAULT_THEME;\n\n // Custom fence renderer\n const defaultFence = md.renderer.rules.fence;\n md.renderer.rules.fence = (tokens, idx, fenceOptions, env, self) => {\n const token = tokens[idx];\n const info = token.info ? token.info.trim() : \"\";\n const lang = info ? info.split(/\\s+/)[0].toLowerCase() : \"text\";\n const code = token.content;\n\n // Delegate math/latex fences to math plugin\n if (lang === \"math\" || lang === \"latex\" || lang === \"tex\" || lang === \"katex\") {\n if (defaultFence) {\n return defaultFence(tokens, idx, fenceOptions, env, self);\n }\n }\n\n try {\n const loadedLangs = highlighter.getLoadedLanguages();\n const targetLang = loadedLangs.includes(lang) ? lang : \"text\";\n\n return highlighter.codeToHtml(code, {\n lang: targetLang,\n theme,\n transformers: [\n {\n pre(node) {\n const existingClass = (node.properties.class as string) || \"\";\n node.properties.class = `printdown-code ${existingClass}`.trim();\n },\n },\n ],\n });\n } catch {\n // Fallback to default fence rule or simple pre/code\n if (defaultFence) {\n return defaultFence(tokens, idx, fenceOptions, env, self);\n }\n return `<pre class=\"printdown-code\"><code>${md.utils.escapeHtml(code)}</code></pre>\\n`;\n }\n };\n\n return md;\n}\n","import type MarkdownIt from \"markdown-it\";\nimport type { StateInline } from \"markdown-it\";\n\nexport function highlightPlugin(md: InstanceType<typeof MarkdownIt>): void {\n function tokenize(state: StateInline, silent: boolean): boolean {\n const start = state.pos;\n const marker = state.src.charCodeAt(start);\n\n // 0x3d is '='\n if (marker !== 0x3d) {\n return false;\n }\n\n const scanned = state.scanDelims(state.pos, true);\n const len = scanned.length;\n const ch = String.fromCharCode(marker);\n\n if (len < 2) {\n return false;\n }\n\n let isColor = false;\n let color = \"blue\";\n\n // Check if opener has {color}\n if (scanned.can_open) {\n const match = state.src.slice(start + len).match(/^\\{([a-zA-Z0-9_-]+)\\}/);\n if (match) {\n isColor = true;\n color = match[1];\n state.pos += match[0].length;\n }\n }\n\n if (silent) {\n state.pos += len;\n return true;\n }\n\n for (let i = 0; i < Math.floor(len / 2); i++) {\n const token = state.push(\"text\", \"\", 0);\n token.content = ch + ch;\n\n state.delimiters.push({\n marker: 0x3d,\n length: 0,\n jump: i,\n token: state.tokens.length - 1,\n level: state.level,\n end: -1,\n open: scanned.can_open,\n close: scanned.can_close,\n color: isColor ? color : \"blue\",\n } as unknown as (typeof state.delimiters)[number]);\n }\n\n state.pos += len;\n return true;\n }\n\n function postProcess(state: StateInline): void {\n const delimiters = state.delimiters;\n if (!delimiters) return;\n\n for (let i = 0; i < delimiters.length; i++) {\n const startDelim = delimiters[i] as unknown as {\n marker: number;\n end: number;\n token: number;\n color?: string;\n };\n if (startDelim.marker !== 0x3d || startDelim.end === -1) continue;\n\n const endDelim = delimiters[startDelim.end] as unknown as {\n token: number;\n };\n\n const tokenStart = state.tokens[startDelim.token];\n tokenStart.type = \"mark_open\";\n tokenStart.tag = \"mark\";\n tokenStart.nesting = 1;\n tokenStart.markup = \"==\";\n tokenStart.content = \"\";\n tokenStart.attrs = [\n [\"class\", `printdown-highlight printdown-highlight--${startDelim.color || \"blue\"}`],\n ];\n\n const tokenEnd = state.tokens[endDelim.token];\n tokenEnd.type = \"mark_close\";\n tokenEnd.tag = \"mark\";\n tokenEnd.nesting = -1;\n tokenEnd.markup = \"==\";\n tokenEnd.content = \"\";\n }\n }\n\n md.inline.ruler.before(\"emphasis\", \"highlight\", tokenize);\n md.inline.ruler2.before(\"emphasis\", \"highlight\", (state: StateInline) => {\n const delimiters = state.delimiters;\n if (!delimiters) return;\n\n for (let i = 0; i < delimiters.length; i++) {\n const startDelim = delimiters[i];\n if (startDelim.marker !== 0x3d) continue;\n\n for (let j = i + 1; j < delimiters.length; j++) {\n const endDelim = delimiters[j];\n if (endDelim.marker !== 0x3d) continue;\n\n if (startDelim.open && endDelim.close && endDelim.end === -1 && startDelim.end === -1) {\n startDelim.end = j;\n endDelim.end = i;\n break;\n }\n }\n }\n\n postProcess(state);\n });\n}\n","import type MarkdownIt from \"markdown-it\";\nimport type { StateCore, Token } from \"markdown-it\";\n\nconst TASK_LIST_REGEX = /^\\[([ xX])\\][ \\t]+/;\n\nexport function taskListPlugin(md: InstanceType<typeof MarkdownIt>): void {\n md.core.ruler.after(\"inline\", \"task_list\", (state: StateCore) => {\n const tokens = state.tokens;\n\n for (let i = 0; i < tokens.length; i++) {\n if (tokens[i].type !== \"bullet_list_open\") {\n continue;\n }\n\n // Check if this list contains any task list items\n let listEnd = i + 1;\n let depth = 1;\n let hasTaskItems = false;\n\n while (listEnd < tokens.length && depth > 0) {\n if (tokens[listEnd].type === \"bullet_list_open\") {\n depth++;\n } else if (tokens[listEnd].type === \"bullet_list_close\") {\n depth--;\n }\n listEnd++;\n }\n\n // Scan items within this list level\n for (let j = i + 1; j < listEnd; j++) {\n if (tokens[j].type === \"list_item_open\") {\n // Look for paragraph -> inline\n const inlineTokenIndex = findFirstInlineToken(tokens, j);\n if (inlineTokenIndex !== -1) {\n const inlineToken = tokens[inlineTokenIndex];\n if (isTaskListItem(inlineToken)) {\n hasTaskItems = true;\n break;\n }\n }\n }\n }\n\n if (!hasTaskItems) {\n continue;\n }\n\n // Add class to bullet_list_open\n addClass(tokens[i], \"printdown-task-list\");\n\n // Now transform each task list item\n for (let j = i + 1; j < listEnd; j++) {\n if (tokens[j].type === \"list_item_open\") {\n const inlineTokenIndex = findFirstInlineToken(tokens, j);\n if (inlineTokenIndex !== -1) {\n const inlineToken = tokens[inlineTokenIndex];\n const match = getTaskListMatch(inlineToken);\n if (match) {\n addClass(tokens[j], \"printdown-task-list-item\");\n const isChecked = match[1].toLowerCase() === \"x\";\n removeTaskListPrefix(inlineToken);\n insertCheckboxToken(inlineToken, isChecked, state.Token);\n }\n }\n }\n }\n }\n });\n}\n\nfunction findFirstInlineToken(tokens: Token[], listItemIndex: number): number {\n for (let i = listItemIndex + 1; i < tokens.length; i++) {\n if (tokens[i].type === \"list_item_close\" || tokens[i].type === \"list_item_open\") {\n return -1;\n }\n if (tokens[i].type === \"inline\") {\n return i;\n }\n }\n return -1;\n}\n\nfunction isTaskListItem(inlineToken: Token): boolean {\n if (!inlineToken.children || inlineToken.children.length === 0) {\n return false;\n }\n const firstChild = inlineToken.children[0];\n return firstChild.type === \"text\" && TASK_LIST_REGEX.test(firstChild.content);\n}\n\nfunction getTaskListMatch(inlineToken: Token): RegExpMatchArray | null {\n if (!inlineToken.children || inlineToken.children.length === 0) {\n return null;\n }\n const firstChild = inlineToken.children[0];\n if (firstChild.type === \"text\") {\n return firstChild.content.match(TASK_LIST_REGEX);\n }\n return null;\n}\n\nfunction removeTaskListPrefix(inlineToken: Token): void {\n if (!inlineToken.children || inlineToken.children.length === 0) {\n return;\n }\n const firstChild = inlineToken.children[0];\n if (firstChild.type === \"text\") {\n firstChild.content = firstChild.content.replace(TASK_LIST_REGEX, \"\");\n }\n}\n\nfunction insertCheckboxToken(\n inlineToken: Token,\n checked: boolean,\n TokenConstructor: typeof Token,\n): void {\n const checkboxToken = new TokenConstructor(\"html_inline\", \"\", 0);\n checkboxToken.content = `<input class=\"printdown-task-list-checkbox\" type=\"checkbox\" disabled${\n checked ? ' checked=\"\"' : \"\"\n } /> `;\n if (!inlineToken.children) {\n inlineToken.children = [];\n }\n inlineToken.children.unshift(checkboxToken);\n}\n\nfunction addClass(token: Token, className: string): void {\n const classIndex = token.attrIndex(\"class\");\n if (classIndex < 0) {\n token.attrPush([\"class\", className]);\n } else if (token.attrs) {\n const existing = token.attrs[classIndex][1];\n if (typeof existing === \"string\" && !existing.split(\" \").includes(className)) {\n token.attrs[classIndex][1] = `${existing} ${className}`.trim();\n }\n }\n}\n","import type MarkdownIt from \"markdown-it\";\nimport type { StateCore, StateInline, Token } from \"markdown-it\";\n\nexport type BadgeVariant = \"solid\" | \"soft\" | \"outline\";\n\nconst BADGE_MARKDOWN_REGEX = /^\\[badge(?:\\(([^)]+)\\)|\\{([^}]+)\\})?:([\\s\\S]*?)\\]/i;\nconst BADGE_OPEN_TAG_REGEX = /^<badge(\\s+[^>]*)?>$/i;\nconst BADGE_CLOSE_TAG_REGEX = /^<\\/badge>$/i;\nconst BADGE_SELF_CLOSING_REGEX = /^<badge(\\s+[^>]*)?\\/>$/i;\n\nfunction parseBadgeOptions(optionsStr?: string): { variant: BadgeVariant; color: string } {\n let variant: BadgeVariant = \"solid\";\n let color = \"blue\";\n\n if (!optionsStr) {\n return { variant, color };\n }\n\n const parts = optionsStr\n .split(/[\\s,]+/)\n .map((p) => p.trim().toLowerCase())\n .filter(Boolean);\n\n for (const part of parts) {\n if (part === \"solid\" || part === \"soft\" || part === \"outline\") {\n variant = part;\n } else if (/^[a-z0-9_-]+$/.test(part)) {\n color = part;\n }\n }\n\n return { variant, color };\n}\n\nfunction parseBadgeAttrs(attrsStr?: string): { variant: BadgeVariant; color: string } {\n let variant: BadgeVariant = \"solid\";\n let color = \"blue\";\n\n if (!attrsStr) {\n return { variant, color };\n }\n\n const variantMatch = attrsStr.match(/variant=[\"']?([a-zA-Z0-9_-]+)[\"']?/i);\n if (variantMatch) {\n const v = variantMatch[1].toLowerCase();\n if (v === \"solid\" || v === \"soft\" || v === \"outline\") {\n variant = v;\n }\n }\n\n const colorMatch = attrsStr.match(/color=[\"']?([a-zA-Z0-9_-]+)[\"']?/i);\n if (colorMatch) {\n color = colorMatch[1].toLowerCase();\n }\n\n return { variant, color };\n}\n\nexport function badgePlugin(md: InstanceType<typeof MarkdownIt>): void {\n // 1. Inline ruler for markdown syntax: [badge:Text], [badge(soft):Text], [badge(outline,amber):Text], [badge{amber}:Text]\n function inlineBadgeRule(state: StateInline, silent: boolean): boolean {\n const max = state.posMax;\n const start = state.pos;\n\n if (state.src.charCodeAt(start) !== 0x5b /* '[' */) {\n return false;\n }\n\n const match = state.src.slice(start).match(BADGE_MARKDOWN_REGEX);\n if (!match) {\n return false;\n }\n\n const matchedLength = match[0].length;\n if (start + matchedLength > max) {\n return false;\n }\n\n if (silent) {\n state.pos += matchedLength;\n return true;\n }\n\n const rawOptions = match[1] || match[2] || \"\";\n const badgeText = match[3];\n const { variant, color } = parseBadgeOptions(rawOptions);\n\n const tokenOpen = state.push(\"badge_open\", \"span\", 1);\n tokenOpen.attrs = [\n [\"class\", `printdown-badge printdown-badge--${variant} printdown-badge--${color}`],\n ];\n\n // Parse nested inline markdown if any\n const nestedTokens: Token[] = [];\n state.md.inline.parse(badgeText, state.md, state.env, nestedTokens);\n for (const nested of nestedTokens) {\n state.tokens.push(nested);\n }\n\n state.push(\"badge_close\", \"span\", -1);\n\n state.pos += matchedLength;\n return true;\n }\n\n md.inline.ruler.before(\"link\", \"badge\", inlineBadgeRule);\n\n // 2. Core ruler to process <Badge ...> and <badge ...> HTML tags\n md.core.ruler.after(\"inline\", \"badge_tags\", (state: StateCore) => {\n const tokens = state.tokens;\n\n function processToken(token: Token) {\n if (token.type === \"html_inline\") {\n const trimmed = token.content.trim();\n\n if (BADGE_SELF_CLOSING_REGEX.test(trimmed)) {\n const match = trimmed.match(BADGE_SELF_CLOSING_REGEX);\n const { variant, color } = parseBadgeAttrs(match?.[1]);\n token.content = `<span class=\"printdown-badge printdown-badge--${variant} printdown-badge--${color}\"></span>`;\n } else if (BADGE_OPEN_TAG_REGEX.test(trimmed)) {\n const match = trimmed.match(BADGE_OPEN_TAG_REGEX);\n const { variant, color } = parseBadgeAttrs(match?.[1]);\n token.content = `<span class=\"printdown-badge printdown-badge--${variant} printdown-badge--${color}\">`;\n } else if (BADGE_CLOSE_TAG_REGEX.test(trimmed)) {\n token.content = `</span>`;\n }\n } else if (token.type === \"html_block\") {\n token.content = token.content.replace(\n /<badge(\\s+[^>]*)?>([\\s\\S]*?)<\\/badge>/gi,\n (_, attrs, body) => {\n const { variant, color } = parseBadgeAttrs(attrs);\n return `<span class=\"printdown-badge printdown-badge--${variant} printdown-badge--${color}\">${body}</span>`;\n },\n );\n }\n }\n\n for (let i = 0; i < tokens.length; i++) {\n processToken(tokens[i]);\n if (tokens[i].children) {\n for (let j = 0; j < tokens[i].children!.length; j++) {\n processToken(tokens[i].children![j]);\n }\n }\n }\n });\n}\n","import type MarkdownIt from \"markdown-it\";\nimport type { StateCore, StateInline, Token } from \"markdown-it\";\n\nconst KBD_MARKDOWN_REGEX = /^\\[kbd(?:\\(([^)]+)\\))?:([\\s\\S]*?)\\]/i;\nconst KBD_ICON_ONLY_REGEX = /^\\[kbd\\(([^)]+)\\)\\]/i;\nconst KBD_OPEN_TAG_REGEX = /^<kbd(\\s+[^>]*)?>$/i;\nconst KBD_CLOSE_TAG_REGEX = /^<\\/kbd>$/i;\nconst KBD_SELF_CLOSING_REGEX = /^<kbd(\\s+[^>]*)?\\/>$/i;\n\nfunction parseKbdAttrs(attrsStr?: string): { icon?: string } {\n if (!attrsStr) return {};\n\n const iconMatch = attrsStr.match(/icon=[\"']?([a-zA-Z0-9_-]+)[\"']?/i);\n if (iconMatch) {\n return { icon: iconMatch[1].toLowerCase() };\n }\n return {};\n}\n\nexport function kbdPlugin(md: InstanceType<typeof MarkdownIt>): void {\n // 1. Inline ruler for markdown syntax: [kbd:K], [kbd(command)], [kbd(command):K], [kbd:Ctrl]\n function inlineKbdRule(state: StateInline, silent: boolean): boolean {\n const max = state.posMax;\n const start = state.pos;\n\n if (state.src.charCodeAt(start) !== 0x5b /* '[' */) {\n return false;\n }\n\n const rest = state.src.slice(start);\n\n // Try [kbd(icon):Text] or [kbd:Text]\n const matchWithText = rest.match(KBD_MARKDOWN_REGEX);\n // Try [kbd(icon)]\n const matchIconOnly = !matchWithText ? rest.match(KBD_ICON_ONLY_REGEX) : null;\n\n const match = matchWithText || matchIconOnly;\n if (!match) {\n return false;\n }\n\n const matchedLength = match[0].length;\n if (start + matchedLength > max) {\n return false;\n }\n\n if (silent) {\n state.pos += matchedLength;\n return true;\n }\n\n const icon = matchWithText ? matchWithText[1] : matchIconOnly ? matchIconOnly[1] : undefined;\n const kbdText = matchWithText ? matchWithText[2] : \"\";\n\n const tokenOpen = state.push(\"kbd_open\", \"kbd\", 1);\n tokenOpen.attrs = [[\"class\", \"printdown-kbd\"]];\n\n if (icon) {\n const iconToken = state.push(\"html_inline\", \"\", 0);\n iconToken.content = `<span class=\"printdown-kbd-icon printdown-kbd-icon--${icon.toLowerCase()}\"></span>`;\n }\n\n if (kbdText) {\n const nestedTokens: Token[] = [];\n state.md.inline.parse(kbdText, state.md, state.env, nestedTokens);\n for (const nested of nestedTokens) {\n state.tokens.push(nested);\n }\n }\n\n state.push(\"kbd_close\", \"kbd\", -1);\n\n state.pos += matchedLength;\n return true;\n }\n\n md.inline.ruler.before(\"link\", \"kbd\", inlineKbdRule);\n\n // 2. Core ruler to process <Kbd ...> and <kbd ...> HTML tags\n md.core.ruler.after(\"inline\", \"kbd_tags\", (state: StateCore) => {\n const tokens = state.tokens;\n\n function processToken(token: Token) {\n if (token.type === \"html_inline\") {\n const trimmed = token.content.trim();\n\n if (KBD_SELF_CLOSING_REGEX.test(trimmed)) {\n const match = trimmed.match(KBD_SELF_CLOSING_REGEX);\n const { icon } = parseKbdAttrs(match?.[1]);\n const iconHtml = icon\n ? `<span class=\"printdown-kbd-icon printdown-kbd-icon--${icon}\"></span>`\n : \"\";\n token.content = `<kbd class=\"printdown-kbd\">${iconHtml}</kbd>`;\n } else if (KBD_OPEN_TAG_REGEX.test(trimmed)) {\n const match = trimmed.match(KBD_OPEN_TAG_REGEX);\n const { icon } = parseKbdAttrs(match?.[1]);\n const iconHtml = icon\n ? `<span class=\"printdown-kbd-icon printdown-kbd-icon--${icon}\"></span>`\n : \"\";\n token.content = `<kbd class=\"printdown-kbd\">${iconHtml}`;\n } else if (KBD_CLOSE_TAG_REGEX.test(trimmed)) {\n token.content = `</kbd>`;\n }\n } else if (token.type === \"html_block\") {\n token.content = token.content.replace(\n /<kbd(\\s+[^>]*)?>([\\s\\S]*?)<\\/kbd>/gi,\n (_, attrs, body) => {\n const { icon } = parseKbdAttrs(attrs);\n const iconHtml = icon\n ? `<span class=\"printdown-kbd-icon printdown-kbd-icon--${icon}\"></span>`\n : \"\";\n return `<kbd class=\"printdown-kbd\">${iconHtml}${body}</kbd>`;\n },\n );\n }\n }\n\n for (let i = 0; i < tokens.length; i++) {\n processToken(tokens[i]);\n if (tokens[i].children) {\n for (let j = 0; j < tokens[i].children!.length; j++) {\n processToken(tokens[i].children![j]);\n }\n }\n }\n });\n}\n","import type MarkdownIt from \"markdown-it\";\nimport type { StateBlock, StateCore, StateInline, Token } from \"markdown-it\";\n\nconst CENTER_INLINE_BRACKET_REGEX = /^\\[center:([\\s\\S]*?)\\]/i;\nconst CENTER_INLINE_ARROW_REGEX = /^->\\s*([\\s\\S]*?)\\s*<-/;\n\nconst CENTER_OPEN_TAG_REGEX = /^<center(\\s+[^>]*)?>$/i;\nconst CENTER_CLOSE_TAG_REGEX = /^<\\/center>$/i;\n\n/**\n * Center alignment plugin for MarkdownIt.\n *\n * Supports:\n * 1. Inline bracket syntax: `[center:Centered Text]`\n * 2. Inline arrow syntax: `->Centered Text<-`\n * 3. Container block syntax: `::: center` ... `:::`\n * 4. Arrow block syntax: `->` ... `<-` or `-> Centered Line <-`\n * 5. HTML tags: `<center>...</center>` and `<Center>...</Center>`\n */\nexport function centerPlugin(md: InstanceType<typeof MarkdownIt>): void {\n // 1. Inline ruler for [center:...] and ->...<-\n function inlineCenterRule(state: StateInline, silent: boolean): boolean {\n const start = state.pos;\n const max = state.posMax;\n const src = state.src;\n\n // Check [center:...]\n if (src.charCodeAt(start) === 0x5b /* '[' */) {\n const match = src.slice(start).match(CENTER_INLINE_BRACKET_REGEX);\n if (match) {\n const matchedLength = match[0].length;\n if (start + matchedLength > max) return false;\n\n if (silent) {\n state.pos += matchedLength;\n return true;\n }\n\n const centerText = match[1];\n const tokenOpen = state.push(\"center_open\", \"span\", 1);\n tokenOpen.attrs = [[\"class\", \"printdown-center\"]];\n\n const nestedTokens: Token[] = [];\n state.md.inline.parse(centerText, state.md, state.env, nestedTokens);\n for (const nested of nestedTokens) {\n state.tokens.push(nested);\n }\n\n state.push(\"center_close\", \"span\", -1);\n state.pos += matchedLength;\n return true;\n }\n }\n\n // Check ->...<- inline\n if (src.charCodeAt(start) === 0x2d /* '-' */ && src.charCodeAt(start + 1) === 0x3e /* '>' */) {\n // Must not be preceded by another '-' (e.g. '-->')\n if (start > 0 && src.charCodeAt(start - 1) === 0x2d) {\n return false;\n }\n\n const rest = src.slice(start);\n const match = rest.match(CENTER_INLINE_ARROW_REGEX);\n if (match && match[1].length > 0) {\n const matchedLength = match[0].length;\n if (start + matchedLength > max) return false;\n\n if (silent) {\n state.pos += matchedLength;\n return true;\n }\n\n const centerText = match[1];\n const tokenOpen = state.push(\"center_open\", \"span\", 1);\n tokenOpen.attrs = [[\"class\", \"printdown-center\"]];\n\n const nestedTokens: Token[] = [];\n state.md.inline.parse(centerText, state.md, state.env, nestedTokens);\n for (const nested of nestedTokens) {\n state.tokens.push(nested);\n }\n\n state.push(\"center_close\", \"span\", -1);\n state.pos += matchedLength;\n return true;\n }\n }\n\n return false;\n }\n\n md.inline.ruler.before(\"link\", \"center_inline\", inlineCenterRule);\n\n // 2. Block ruler for ::: center and -> ... <-\n function blockCenterRule(\n state: StateBlock,\n startLine: number,\n endLine: number,\n silent: boolean,\n ): boolean {\n const startPos = state.bMarks[startLine] + state.tShift[startLine];\n const maxPos = state.eMarks[startLine];\n const lineText = state.src.slice(startPos, maxPos).trim();\n\n // Check for ::: center\n if (/^:::\\s*center\\s*$/i.test(lineText)) {\n if (silent) return true;\n\n let nextLine = startLine + 1;\n let foundEnd = false;\n\n while (nextLine < endLine) {\n const pos = state.bMarks[nextLine] + state.tShift[nextLine];\n const max = state.eMarks[nextLine];\n const curLine = state.src.slice(pos, max).trim();\n\n if (/^:::\\s*$/.test(curLine) || /^:::\\s*center\\s*$/i.test(curLine)) {\n foundEnd = true;\n break;\n }\n nextLine++;\n }\n\n const tokenOpen = state.push(\"center_container_open\", \"div\", 1);\n tokenOpen.attrs = [[\"class\", \"printdown-center\"]];\n tokenOpen.block = true;\n\n const oldParentType = state.parentType;\n state.parentType = \"root\";\n\n // Parse nested markdown blocks within container\n state.md.block.tokenize(state, startLine + 1, nextLine);\n\n state.parentType = oldParentType;\n\n const tokenClose = state.push(\"center_container_close\", \"div\", -1);\n tokenClose.block = true;\n\n state.line = foundEnd ? nextLine + 1 : nextLine;\n return true;\n }\n\n // Check for -> ... <- single line or multi-line block\n if (lineText.startsWith(\"->\")) {\n // Single line: -> Centered Text <-\n if (lineText.endsWith(\"<-\") && lineText.length >= 4) {\n if (silent) return true;\n\n const content = lineText.slice(2, -2).trim();\n const tokenOpen = state.push(\"center_container_open\", \"div\", 1);\n tokenOpen.attrs = [[\"class\", \"printdown-center\"]];\n tokenOpen.block = true;\n\n const pOpen = state.push(\"paragraph_open\", \"p\", 1);\n pOpen.attrs = [[\"class\", \"printdown-center\"]];\n const inlineToken = state.push(\"inline\", \"\", 0);\n inlineToken.content = content;\n inlineToken.children = [];\n state.push(\"paragraph_close\", \"p\", -1);\n\n const tokenClose = state.push(\"center_container_close\", \"div\", -1);\n tokenClose.block = true;\n\n state.line = startLine + 1;\n return true;\n }\n\n // Multi-line block starting with standalone '->'\n if (lineText === \"->\") {\n if (silent) return true;\n\n let nextLine = startLine + 1;\n let foundEnd = false;\n\n while (nextLine < endLine) {\n const pos = state.bMarks[nextLine] + state.tShift[nextLine];\n const max = state.eMarks[nextLine];\n const curLine = state.src.slice(pos, max).trim();\n\n if (curLine === \"<-\") {\n foundEnd = true;\n break;\n }\n nextLine++;\n }\n\n const tokenOpen = state.push(\"center_container_open\", \"div\", 1);\n tokenOpen.attrs = [[\"class\", \"printdown-center\"]];\n tokenOpen.block = true;\n\n const oldParentType = state.parentType;\n state.parentType = \"root\";\n\n state.md.block.tokenize(state, startLine + 1, nextLine);\n\n state.parentType = oldParentType;\n\n const tokenClose = state.push(\"center_container_close\", \"div\", -1);\n tokenClose.block = true;\n\n state.line = foundEnd ? nextLine + 1 : nextLine;\n return true;\n }\n }\n\n return false;\n }\n\n md.block.ruler.before(\"fence\", \"center_block\", blockCenterRule);\n\n // 3. Core ruler to process <center> and <Center> tags and parse inner markdown\n md.core.ruler.after(\"inline\", \"center_tags\", (state: StateCore) => {\n const tokens = state.tokens;\n\n function processToken(token: Token) {\n if (token.type === \"html_inline\") {\n const trimmed = token.content.trim();\n\n if (CENTER_OPEN_TAG_REGEX.test(trimmed)) {\n token.content = '<span class=\"printdown-center\">';\n } else if (CENTER_CLOSE_TAG_REGEX.test(trimmed)) {\n token.content = \"</span>\";\n }\n } else if (token.type === \"html_block\") {\n // Match <center>...</center> across multiple lines\n token.content = token.content.replace(\n /<center(\\s+[^>]*)?>([\\s\\S]*?)<\\/center>/gi,\n (_, _attrs, body) => {\n const rendered = md.render(body.trim()).trim();\n return `<div class=\"printdown-center\">${rendered}</div>`;\n },\n );\n }\n }\n\n for (let i = 0; i < tokens.length; i++) {\n processToken(tokens[i]);\n if (tokens[i].children) {\n for (let j = 0; j < tokens[i].children!.length; j++) {\n processToken(tokens[i].children![j]);\n }\n }\n }\n });\n}\n","import type MarkdownIt from \"markdown-it\";\nimport type { StateCore, Token } from \"markdown-it\";\n\nconst HEADING_ATTR_REGEX =\n /\\s*(?:\\{(?:\\.|\\s)*(?:no-border|no-underline|no-bottom-border|plain|-|page-break|pagebreak|break-before)(?:\\s+(?:\\.|\\s)*(?:no-border|no-underline|no-bottom-border|plain|-|page-break|pagebreak|break-before))*\\s*\\}|\\[(?:no-border|no-underline|page-break|pagebreak|break-before)\\]|<!--\\s*(?:no-border|no-underline|page-break|pagebreak|break-before)\\s*-->)\\s*$/i;\n\nfunction addClass(token: Token, className: string): void {\n const classIndex = token.attrIndex(\"class\");\n if (classIndex < 0) {\n token.attrPush([\"class\", className]);\n } else if (token.attrs) {\n const existing = token.attrs[classIndex][1];\n if (typeof existing === \"string\") {\n const classes = existing.split(\" \");\n const newClasses = className.split(\" \");\n for (const cls of newClasses) {\n if (!classes.includes(cls)) {\n classes.push(cls);\n }\n }\n token.attrs[classIndex][1] = classes.join(\" \").trim();\n }\n }\n}\n\n/**\n * Heading plugin to support custom attributes on headings (H1, H2, H3, etc.):\n * - Removing bottom border/underline: `{.no-border}`, `{.no-underline}`, `{-}`, `{.plain}`\n * - Forcing a page break before heading: `{.page-break}`, `{.break-before}`\n */\nexport function headingPlugin(md: InstanceType<typeof MarkdownIt>): void {\n md.core.ruler.after(\"inline\", \"heading_attributes\", (state: StateCore) => {\n const tokens = state.tokens;\n\n for (let i = 0; i < tokens.length; i++) {\n if (tokens[i].type === \"heading_open\") {\n const inlineToken = tokens[i + 1];\n if (inlineToken && inlineToken.type === \"inline\") {\n const match = inlineToken.content.match(HEADING_ATTR_REGEX);\n if (match) {\n const attrStr = match[0].toLowerCase();\n\n if (\n attrStr.includes(\"no-border\") ||\n attrStr.includes(\"no-underline\") ||\n attrStr.includes(\"plain\") ||\n attrStr.includes(\"{-}\")\n ) {\n addClass(tokens[i], \"printdown-no-border printdown-no-underline\");\n }\n\n if (\n attrStr.includes(\"page-break\") ||\n attrStr.includes(\"pagebreak\") ||\n attrStr.includes(\"break-before\")\n ) {\n addClass(tokens[i], \"printdown-page-break\");\n }\n\n // Strip from raw content\n inlineToken.content = inlineToken.content.replace(HEADING_ATTR_REGEX, \"\");\n\n // Strip from children tokens\n if (inlineToken.children && inlineToken.children.length > 0) {\n for (let j = inlineToken.children.length - 1; j >= 0; j--) {\n const child = inlineToken.children[j];\n if (child.type === \"text\") {\n if (HEADING_ATTR_REGEX.test(child.content)) {\n child.content = child.content.replace(HEADING_ATTR_REGEX, \"\");\n if (child.content === \"\") {\n inlineToken.children.splice(j, 1);\n }\n break;\n }\n } else if (child.type === \"html_inline\") {\n if (\n child.content.includes(\"no-border\") ||\n child.content.includes(\"no-underline\") ||\n child.content.includes(\"page-break\") ||\n child.content.includes(\"pagebreak\") ||\n child.content.includes(\"break-before\")\n ) {\n inlineToken.children.splice(j, 1);\n break;\n }\n }\n }\n }\n }\n }\n } else if (tokens[i].type === \"html_block\") {\n // Handle HTML headings like <h1 no-border page-break>\n tokens[i].content = tokens[i].content.replace(\n /<(h[1-6])(\\s+[^>]*)?(?:\\s+(?:no-border|no-underline|page-break|pagebreak|break-before))\\s*([^>]*)>/gi,\n (match, tag, before, after) => {\n const combinedAttrs = `${before || \"\"} ${after || \"\"}`.trim();\n const classesToAdd: string[] = [];\n if (match.includes(\"no-border\") || match.includes(\"no-underline\")) {\n classesToAdd.push(\"printdown-no-border printdown-no-underline\");\n }\n if (\n match.includes(\"page-break\") ||\n match.includes(\"pagebreak\") ||\n match.includes(\"break-before\")\n ) {\n classesToAdd.push(\"printdown-page-break\");\n }\n\n const classString = classesToAdd.join(\" \");\n\n if (combinedAttrs.includes('class=\"') || combinedAttrs.includes(\"class='\")) {\n return `<${tag} ${combinedAttrs.replace(\n /class=([\"'])(.*?)\\1/,\n `class=$1$2 ${classString}$1`,\n )}>`;\n }\n return `<${tag} class=\"${classString}\" ${combinedAttrs}>`.replace(/\\s+>/, \">\");\n },\n );\n }\n }\n });\n}\n","import type MarkdownIt from \"markdown-it\";\nimport type { StateBlock, StateCore } from \"markdown-it\";\n\nconst PAGE_BREAK_LINE_REGEX =\n /^(?:<!--\\s*(?:pagebreak|page-break|newpage|break)\\s*-->|\\\\(?:pagebreak|newpage)|\\[(?:pagebreak|page-break|newpage)\\]|<(?:pagebreak|page-break|newpage)(?:\\s*\\/?)>)$/i;\n\nconst PAGE_BREAK_MATCH_REGEX =\n /(?:<!--\\s*(?:pagebreak|page-break|newpage|break)\\s*-->|\\\\(?:pagebreak|newpage)|\\[(?:pagebreak|page-break|newpage)\\]|<(?:pagebreak|page-break|newpage)(?:\\s*\\/?)>)/gi;\n\n/**\n * Page break plugin for MarkdownIt.\n *\n * Supports:\n * - HTML comment syntax: `<!-- pagebreak -->`, `<!-- page-break -->`, `<!-- newpage -->`\n * - LaTeX / Pandoc syntax: `\\pagebreak`, `\\newpage`\n * - Bracket syntax: `[pagebreak]`, `[page-break]`, `[newpage]`\n * - Custom tag syntax: `<pagebreak />`, `<pagebreak>`, `<newpage />`, `<newpage>`\n * - Container directive: `::: pagebreak` ... `:::`\n */\nexport function pageBreakPlugin(md: InstanceType<typeof MarkdownIt>): void {\n // 1. Block ruler for standalone page break lines and ::: pagebreak containers\n function blockPageBreakRule(\n state: StateBlock,\n startLine: number,\n endLine: number,\n silent: boolean,\n ): boolean {\n const startPos = state.bMarks[startLine] + state.tShift[startLine];\n const maxPos = state.eMarks[startLine];\n const lineText = state.src.slice(startPos, maxPos).trim();\n\n // Check standalone line like <!-- pagebreak -->, \\pagebreak, [pagebreak], <pagebreak />\n if (PAGE_BREAK_LINE_REGEX.test(lineText)) {\n if (silent) return true;\n\n const token = state.push(\"html_block\", \"\", 0);\n token.content = '<div class=\"printdown-page-break\"></div>\\n';\n token.map = [startLine, startLine + 1];\n\n state.line = startLine + 1;\n return true;\n }\n\n // Check ::: pagebreak or ::: page-break or ::: newpage\n if (/^:::\\s*(?:pagebreak|page-break|newpage)\\s*$/i.test(lineText)) {\n if (silent) return true;\n\n let nextLine = startLine + 1;\n while (nextLine < endLine) {\n const pos = state.bMarks[nextLine] + state.tShift[nextLine];\n const max = state.eMarks[nextLine];\n const curLine = state.src.slice(pos, max).trim();\n\n if (/^:::\\s*$/.test(curLine)) {\n break;\n }\n nextLine++;\n }\n\n const token = state.push(\"html_block\", \"\", 0);\n token.content = '<div class=\"printdown-page-break\"></div>\\n';\n token.map = [startLine, nextLine + 1];\n\n state.line = nextLine < endLine ? nextLine + 1 : nextLine;\n return true;\n }\n\n return false;\n }\n\n md.block.ruler.before(\"hr\", \"page_break\", blockPageBreakRule);\n\n // 2. Core ruler to process HTML blocks and inline tokens\n md.core.ruler.after(\"inline\", \"page_break_tags\", (state: StateCore) => {\n const tokens = state.tokens;\n\n for (let i = 0; i < tokens.length; i++) {\n const token = tokens[i];\n\n if (token.type === \"html_block\") {\n if (PAGE_BREAK_MATCH_REGEX.test(token.content)) {\n token.content = token.content.replace(\n PAGE_BREAK_MATCH_REGEX,\n '<div class=\"printdown-page-break\"></div>',\n );\n }\n } else if (token.type === \"paragraph_open\") {\n // If paragraph only contains a page break token or text, convert to html_block\n const inlineToken = tokens[i + 1];\n if (inlineToken && inlineToken.type === \"inline\") {\n const content = inlineToken.content.trim();\n if (PAGE_BREAK_LINE_REGEX.test(content)) {\n // Replace paragraph_open, inline, paragraph_close with a single html_block\n tokens[i].type = \"html_block\";\n tokens[i].tag = \"\";\n tokens[i].content = '<div class=\"printdown-page-break\"></div>\\n';\n tokens[i].children = null;\n // Remove inline and paragraph_close tokens\n tokens.splice(i + 1, 2);\n }\n }\n } else if (token.type === \"inline\" && token.children) {\n for (let j = 0; j < token.children.length; j++) {\n const child = token.children[j];\n if (child.type === \"html_inline\" || child.type === \"text\") {\n if (PAGE_BREAK_MATCH_REGEX.test(child.content)) {\n child.type = \"html_inline\";\n child.content = child.content.replace(\n PAGE_BREAK_MATCH_REGEX,\n '<div class=\"printdown-page-break\"></div>',\n );\n }\n }\n }\n }\n }\n });\n}\n","import type MarkdownIt from \"markdown-it\";\nimport type { StateBlock, StateCore, Token } from \"markdown-it\";\n\nconst COVER_CONTAINER_START_REGEX = /^:::\\s*cover(?:\\s+([a-zA-Z0-9_-]+))?\\s*$/i;\nconst COVER_TAG_OPEN_REGEX =\n /^<cover(?:\\s+variant=[\"']?([a-zA-Z0-9_-]+)[\"']?)?(?:\\s+class=[\"']?([^\"'>]*)[\"']?)?[^>]*>$/i;\nconst COVER_TAG_CLOSE_REGEX = /^<\\/cover>$/i;\n\n/**\n * Cover page plugin for MarkdownIt.\n *\n * Supports:\n * 1. Container block syntax:\n * ::: cover [variant]\n * # Document Title\n * Subtitle\n * :::\n *\n * 2. Meta/Footer section inside cover:\n * ::: cover-meta or ::: cover-footer\n * Author: Name\n * Date: 2026-08-30\n * :::\n *\n * 3. HTML tags:\n * <cover variant=\"modern\">...</cover>\n */\nexport function coverPlugin(md: InstanceType<typeof MarkdownIt>): void {\n // 1. Block ruler for ::: cover [variant] and ::: cover-footer / cover-meta\n function blockCoverRule(\n state: StateBlock,\n startLine: number,\n endLine: number,\n silent: boolean,\n ): boolean {\n const startPos = state.bMarks[startLine] + state.tShift[startLine];\n const maxPos = state.eMarks[startLine];\n const lineText = state.src.slice(startPos, maxPos).trim();\n\n // Check ::: cover-meta or ::: cover-footer\n if (/^:::\\s*(?:cover-meta|cover-footer)\\s*$/i.test(lineText)) {\n if (silent) return true;\n\n let nextLine = startLine + 1;\n let foundEnd = false;\n\n while (nextLine < endLine) {\n const pos = state.bMarks[nextLine] + state.tShift[nextLine];\n const max = state.eMarks[nextLine];\n const curLine = state.src.slice(pos, max).trim();\n\n if (/^:::\\s*$/.test(curLine) || /^:::\\s*(?:cover-meta|cover-footer)\\s*$/i.test(curLine)) {\n foundEnd = true;\n break;\n }\n nextLine++;\n }\n\n const tokenOpen = state.push(\"cover_meta_open\", \"div\", 1);\n tokenOpen.attrs = [[\"class\", \"printdown-cover-meta\"]];\n tokenOpen.block = true;\n\n const oldParentType = state.parentType;\n state.parentType = \"root\";\n\n state.md.block.tokenize(state, startLine + 1, nextLine);\n\n state.parentType = oldParentType;\n\n const tokenClose = state.push(\"cover_meta_close\", \"div\", -1);\n tokenClose.block = true;\n\n state.line = foundEnd ? nextLine + 1 : nextLine;\n return true;\n }\n\n // Check ::: cover [variant]\n const coverMatch = lineText.match(COVER_CONTAINER_START_REGEX);\n if (coverMatch) {\n if (silent) return true;\n\n const variant = coverMatch[1] ? coverMatch[1].toLowerCase() : \"default\";\n\n let nextLine = startLine + 1;\n let foundEnd = false;\n let depth = 1;\n\n while (nextLine < endLine) {\n const pos = state.bMarks[nextLine] + state.tShift[nextLine];\n const max = state.eMarks[nextLine];\n const curLine = state.src.slice(pos, max).trim();\n\n if (/^:::\\s*[a-zA-Z0-9_-]+\\s*$/i.test(curLine)) {\n depth++;\n } else if (/^:::\\s*$/i.test(curLine)) {\n depth--;\n if (depth === 0) {\n foundEnd = true;\n break;\n }\n } else if (/^:::\\s*cover\\s*$/i.test(curLine)) {\n depth--;\n if (depth <= 0) {\n foundEnd = true;\n break;\n }\n }\n nextLine++;\n }\n\n const tokenOpen = state.push(\"cover_open\", \"div\", 1);\n const classNames = [\"printdown-cover\", `printdown-cover-${variant}`];\n tokenOpen.attrs = [[\"class\", classNames.join(\" \")]];\n tokenOpen.block = true;\n\n const oldParentType = state.parentType;\n state.parentType = \"root\";\n\n state.md.block.tokenize(state, startLine + 1, nextLine);\n\n state.parentType = oldParentType;\n\n const tokenClose = state.push(\"cover_close\", \"div\", -1);\n tokenClose.block = true;\n\n state.line = foundEnd ? nextLine + 1 : nextLine;\n return true;\n }\n\n return false;\n }\n\n md.block.ruler.before(\"fence\", \"cover_block\", blockCoverRule);\n\n // 2. Core ruler to process <cover> and <Cover> HTML tags\n md.core.ruler.after(\"inline\", \"cover_tags\", (state: StateCore) => {\n const tokens = state.tokens;\n\n function processToken(token: Token) {\n if (token.type === \"html_inline\") {\n const trimmed = token.content.trim();\n\n const openMatch = trimmed.match(COVER_TAG_OPEN_REGEX);\n if (openMatch) {\n const variant = openMatch[1] ? openMatch[1].toLowerCase() : \"default\";\n const extraClass = openMatch[2] ? ` ${openMatch[2]}` : \"\";\n token.content = `<div class=\"printdown-cover printdown-cover-${variant}${extraClass}\">`;\n } else if (COVER_TAG_CLOSE_REGEX.test(trimmed)) {\n token.content = \"</div>\";\n }\n } else if (token.type === \"html_block\") {\n token.content = token.content.replace(\n /<cover(?:\\s+variant=[\"']?([a-zA-Z0-9_-]+)[\"']?)?(?:\\s+class=[\"']?([^\"'>]*)[\"']?)?[^>]*>([\\s\\S]*?)<\\/cover>/gi,\n (_, variant, customClass, body) => {\n const v = variant ? variant.toLowerCase() : \"default\";\n const extra = customClass ? ` ${customClass}` : \"\";\n const rendered = md.render(body.trim()).trim();\n return `<div class=\"printdown-cover printdown-cover-${v}${extra}\">\\n${rendered}\\n</div>`;\n },\n );\n }\n }\n\n for (let i = 0; i < tokens.length; i++) {\n processToken(tokens[i]);\n if (tokens[i].children) {\n for (const child of tokens[i].children!) {\n processToken(child);\n }\n }\n }\n });\n}\n","import type MarkdownIt from \"markdown-it\";\nimport type { StateBlock, StateInline, Token } from \"markdown-it\";\nimport katex from \"katex\";\n\nexport interface MathPluginOptions {\n katexOptions?: katex.KatexOptions;\n}\n\n/**\n * Math typesetting plugin for MarkdownIt powered by KaTeX.\n *\n * Supports:\n * 1. Inline math: `$E = mc^2$` or `\\(E = mc^2\\)`\n * 2. Inline display math: `$$\\sum_{i=1}^n i$$`\n * 3. Block math: `$$\\n\\int_0^\\infty e^{-x^2} dx = \\frac{\\sqrt{\\pi}}{2}\\n$$`\n * 4. Fenced code block: ````math` or ````latex` / ````tex` / ````katex`\n * 5. Container syntax: `::: math` ... `:::`\n * 6. HTML tags: `<math>...</math>` / `<latex>...</latex>`\n */\nexport function mathPlugin(\n md: InstanceType<typeof MarkdownIt>,\n options: MathPluginOptions = {},\n): void {\n const defaultKatexOptions: katex.KatexOptions = {\n throwOnError: false,\n output: \"htmlAndMathml\",\n ...options.katexOptions,\n };\n\n // 1. Inline math ruler ($...$, $$...$$, \\(...\\))\n function inlineMathRule(state: StateInline, silent: boolean): boolean {\n const start = state.pos;\n const max = state.posMax;\n const src = state.src;\n\n // Must not start with escaped character (e.g. \\$)\n if (start > 0 && src.charCodeAt(start - 1) === 0x5c /* '\\' */) {\n return false;\n }\n\n const firstChar = src.charCodeAt(start);\n\n // Case 1: LaTeX style \\( ... \\)\n if (firstChar === 0x5c /* '\\' */ && src.charCodeAt(start + 1) === 0x28 /* '(' */) {\n let matchEnd = -1;\n let pos = start + 2;\n\n while (pos < max - 1) {\n if (src.charCodeAt(pos) === 0x5c /* '\\' */ && src.charCodeAt(pos + 1) === 0x29 /* ')' */) {\n matchEnd = pos;\n break;\n }\n pos++;\n }\n\n if (matchEnd === -1) return false;\n\n if (!silent) {\n const content = src.slice(start + 2, matchEnd).trim();\n const token = state.push(\"math_inline\", \"math\", 0);\n token.content = content;\n token.meta = { displayMode: false };\n }\n\n state.pos = matchEnd + 2;\n return true;\n }\n\n // Case 2: Dollar-delimited ($...$ or $$...$$)\n if (firstChar === 0x24 /* '$' */) {\n const isDouble = src.charCodeAt(start + 1) === 0x24; /* '$' */\n const delimiterLength = isDouble ? 2 : 1;\n\n // Opening delimiter checks for single $: next char must not be whitespace\n if (!isDouble) {\n const nextChar = src.charCodeAt(start + 1);\n if (\n nextChar === 0x20 ||\n nextChar === 0x09 ||\n nextChar === 0x0a ||\n nextChar === 0x0d ||\n isNaN(nextChar)\n ) {\n return false;\n }\n }\n\n let matchEnd = -1;\n let pos = start + delimiterLength;\n\n while (pos < max) {\n if (src.charCodeAt(pos) === 0x5c /* '\\' */) {\n pos += 2; // Skip escaped character\n continue;\n }\n\n if (isDouble) {\n if (src.charCodeAt(pos) === 0x24 && src.charCodeAt(pos + 1) === 0x24) {\n matchEnd = pos;\n break;\n }\n } else {\n if (src.charCodeAt(pos) === 0x24) {\n // Check closing $ for single $: prev char not whitespace, next char not a digit\n const prevChar = src.charCodeAt(pos - 1);\n if (prevChar !== 0x20 && prevChar !== 0x09 && prevChar !== 0x0a && prevChar !== 0x0d) {\n const nextChar = src.charCodeAt(pos + 1);\n // Avoid matching currencies like $20,000 and $30,000\n if (isNaN(nextChar) || nextChar < 0x30 || nextChar > 0x39) {\n matchEnd = pos;\n break;\n }\n }\n }\n }\n pos++;\n }\n\n if (matchEnd === -1) return false;\n\n const content = src.slice(start + delimiterLength, matchEnd).trim();\n if (content.length === 0) return false;\n\n if (!silent) {\n const token = state.push(isDouble ? \"math_block\" : \"math_inline\", \"math\", 0);\n token.content = content;\n token.meta = { displayMode: isDouble };\n }\n\n state.pos = matchEnd + delimiterLength;\n return true;\n }\n\n return false;\n }\n\n // 2. Block math ruler ($$ ... $$ and ::: math ... :::)\n function blockMathRule(\n state: StateBlock,\n startLine: number,\n endLine: number,\n silent: boolean,\n ): boolean {\n const startPos = state.bMarks[startLine] + state.tShift[startLine];\n const maxPos = state.eMarks[startLine];\n const lineText = state.src.slice(startPos, maxPos).trim();\n\n // Check ::: math or ::: latex / ::: tex / ::: katex\n const containerMatch = lineText.match(/^:::\\s*(math|latex|tex|katex)\\s*$/i);\n if (containerMatch) {\n if (silent) return true;\n\n let nextLine = startLine + 1;\n let foundEnd = false;\n\n while (nextLine < endLine) {\n const pos = state.bMarks[nextLine] + state.tShift[nextLine];\n const max = state.eMarks[nextLine];\n const curLine = state.src.slice(pos, max).trim();\n\n if (/^:::\\s*$/.test(curLine) || /^:::\\s*(math|latex|tex|katex)\\s*$/i.test(curLine)) {\n foundEnd = true;\n break;\n }\n nextLine++;\n }\n\n const contentLines: string[] = [];\n for (let l = startLine + 1; l < nextLine; l++) {\n const pos = state.bMarks[l] + state.tShift[l];\n const max = state.eMarks[l];\n contentLines.push(state.src.slice(pos, max));\n }\n\n const token = state.push(\"math_block\", \"math\", 0);\n token.block = true;\n token.content = contentLines.join(\"\\n\").trim();\n token.meta = { displayMode: true };\n\n state.line = foundEnd ? nextLine + 1 : nextLine;\n return true;\n }\n\n // Check $$ [optional math]\n if (lineText.startsWith(\"$$\")) {\n // Single line $$ math $$ on its own line\n if (lineText.length > 2 && lineText.endsWith(\"$$\")) {\n if (silent) return true;\n const mathContent = lineText.slice(2, -2).trim();\n const token = state.push(\"math_block\", \"math\", 0);\n token.block = true;\n token.content = mathContent;\n token.meta = { displayMode: true };\n state.line = startLine + 1;\n return true;\n }\n\n if (silent) return true;\n\n const firstLineContent = lineText.slice(2).trim();\n const contentLines: string[] = [];\n if (firstLineContent) {\n contentLines.push(firstLineContent);\n }\n\n let nextLine = startLine + 1;\n let foundEnd = false;\n\n while (nextLine < endLine) {\n const pos = state.bMarks[nextLine] + state.tShift[nextLine];\n const max = state.eMarks[nextLine];\n const curLine = state.src.slice(pos, max).trim();\n\n if (curLine.endsWith(\"$$\")) {\n foundEnd = true;\n const lastLineContent = curLine.slice(0, -2).trim();\n if (lastLineContent) {\n contentLines.push(lastLineContent);\n }\n break;\n }\n\n contentLines.push(state.src.slice(pos, max));\n nextLine++;\n }\n\n const token = state.push(\"math_block\", \"math\", 0);\n token.block = true;\n token.content = contentLines.join(\"\\n\").trim();\n token.meta = { displayMode: true };\n\n state.line = foundEnd ? nextLine + 1 : nextLine;\n return true;\n }\n\n return false;\n }\n\n md.inline.ruler.before(\"escape\", \"math_inline\", inlineMathRule);\n md.block.ruler.before(\"fence\", \"math_block\", blockMathRule);\n\n // 3. Intercept code fence for ```math, ```latex, ```tex, ```katex\n const originalFence = md.renderer.rules.fence;\n md.renderer.rules.fence = (tokens, idx, opt, env, self) => {\n const token = tokens[idx];\n const info = token.info ? token.info.trim().toLowerCase() : \"\";\n\n if (info === \"math\" || info === \"latex\" || info === \"tex\" || info === \"katex\") {\n try {\n const rendered = katex.renderToString(token.content.trim(), {\n ...defaultKatexOptions,\n displayMode: true,\n });\n return `<div class=\"printdown-math-block katex-display\">${rendered}</div>\\n`;\n } catch (err) {\n const errMessage = err instanceof Error ? err.message : String(err);\n return `<div class=\"printdown-math-block katex-display\"><span class=\"katex-error\">${errMessage}</span></div>\\n`;\n }\n }\n\n if (originalFence) {\n return originalFence(tokens, idx, opt, env, self);\n }\n return self.renderToken(tokens, idx, opt);\n };\n\n // 4. Renderer rules for math_inline and math_block\n md.renderer.rules.math_inline = (tokens: Token[], idx: number) => {\n const token = tokens[idx];\n try {\n const rendered = katex.renderToString(token.content, {\n ...defaultKatexOptions,\n displayMode: false,\n });\n return `<span class=\"printdown-math-inline\">${rendered}</span>`;\n } catch (err) {\n const errMessage = err instanceof Error ? err.message : String(err);\n return `<span class=\"printdown-math-inline katex-error\">${errMessage}</span>`;\n }\n };\n\n md.renderer.rules.math_block = (tokens: Token[], idx: number) => {\n const token = tokens[idx];\n const displayMode = token.meta?.displayMode !== false;\n try {\n const rendered = katex.renderToString(token.content, {\n ...defaultKatexOptions,\n displayMode,\n });\n return `<div class=\"printdown-math-block katex-display\">${rendered}</div>\\n`;\n } catch (err) {\n const errMessage = err instanceof Error ? err.message : String(err);\n return `<div class=\"printdown-math-block katex-display\"><span class=\"katex-error\">${errMessage}</span></div>\\n`;\n }\n };\n}\n","import fs from \"node:fs\";\nimport path from \"node:path\";\nimport { chromium, type Browser, type BrowserContext, type Page } from \"playwright\";\nimport { getFontDir } from \"../themes/default/fonts.js\";\nimport { resolveHeaderFooterPdfOptions, formatHeaderFooterCanvasText } from \"./header-footer.js\";\nimport type { RenderOptions, OutputFormat } from \"../types.js\";\n\nasync function setupFontRouting(context: BrowserContext): Promise<void> {\n const interDir = getFontDir(\"@fontsource-variable/inter/index.css\");\n const notoDir = getFontDir(\"@fontsource-variable/noto-sans-jp/index.css\");\n const jbDir = getFontDir(\"@fontsource-variable/jetbrains-mono/index.css\");\n const genDir = getFontDir(\"gen-interface-jp/500.css\");\n const katexDir = getFontDir(\"katex/dist/katex.min.css\");\n\n await context.route(\"https://printdown.local/fonts/**\", async (route) => {\n const reqUrl = route.request().url();\n let filePath = \"\";\n\n if (interDir && reqUrl.startsWith(\"https://printdown.local/fonts/inter/\")) {\n filePath = path.join(\n interDir,\n \"files\",\n reqUrl.replace(\"https://printdown.local/fonts/inter/\", \"\"),\n );\n } else if (notoDir && reqUrl.startsWith(\"https://printdown.local/fonts/noto-sans-jp/\")) {\n filePath = path.join(\n notoDir,\n \"files\",\n reqUrl.replace(\"https://printdown.local/fonts/noto-sans-jp/\", \"\"),\n );\n } else if (jbDir && reqUrl.startsWith(\"https://printdown.local/fonts/jetbrains-mono/\")) {\n filePath = path.join(\n jbDir,\n \"files\",\n reqUrl.replace(\"https://printdown.local/fonts/jetbrains-mono/\", \"\"),\n );\n } else if (genDir && reqUrl.startsWith(\"https://printdown.local/fonts/gen-interface-jp/w/\")) {\n filePath = path.join(\n genDir,\n \"w\",\n reqUrl.replace(\"https://printdown.local/fonts/gen-interface-jp/w/\", \"\"),\n );\n } else if (katexDir && reqUrl.startsWith(\"https://printdown.local/fonts/katex/\")) {\n filePath = path.join(\n katexDir,\n \"fonts\",\n reqUrl.replace(\"https://printdown.local/fonts/katex/\", \"\"),\n );\n }\n\n if (filePath && fs.existsSync(filePath)) {\n try {\n const body = fs.readFileSync(filePath);\n const contentType = filePath.endsWith(\".woff2\")\n ? \"font/woff2\"\n : filePath.endsWith(\".woff\")\n ? \"font/woff\"\n : filePath.endsWith(\".ttf\")\n ? \"font/ttf\"\n : \"font/woff2\";\n await route.fulfill({\n status: 200,\n contentType,\n body,\n });\n return;\n } catch {\n // Fallback to abort\n }\n }\n await route.abort();\n });\n}\n\nexport class BrowserRenderer {\n private browser: Browser | null = null;\n\n async init(): Promise<void> {\n if (!this.browser) {\n this.browser = await chromium.launch({\n headless: true,\n args: [\n \"--disable-gpu\",\n \"--no-sandbox\",\n \"--disable-setuid-sandbox\",\n \"--font-render-hinting=medium\",\n ],\n });\n }\n }\n\n async close(): Promise<void> {\n if (this.browser) {\n await this.browser.close();\n this.browser = null;\n }\n }\n\n private async preparePage(\n html: string,\n width: number,\n height: number,\n deviceScaleFactor: number,\n ): Promise<{ browser: Browser; context: BrowserContext; page: Page; isLocalBrowser: boolean }> {\n let isLocalBrowser = false;\n let browser = this.browser;\n\n if (!browser) {\n browser = await chromium.launch({\n headless: true,\n args: [\n \"--disable-gpu\",\n \"--no-sandbox\",\n \"--disable-setuid-sandbox\",\n \"--font-render-hinting=medium\",\n ],\n });\n isLocalBrowser = true;\n }\n\n const context = await browser.newContext({\n viewport: { width, height },\n deviceScaleFactor,\n });\n\n // Intercept and serve font files directly from npm packages (Fontsource, Gen Interface JP)\n await setupFontRouting(context);\n\n const page = await context.newPage();\n\n // Load HTML content\n await page.setContent(html, {\n waitUntil: \"networkidle\",\n });\n\n // Wait for fonts to be loaded\n await page.evaluate(async () => {\n if (document.fonts) {\n await document.fonts.ready;\n }\n });\n\n // Wait for all images to complete loading\n await page.evaluate(async () => {\n const images = Array.from(document.images);\n const pendingImages = images.filter((img) => !img.complete);\n if (pendingImages.length > 0) {\n await Promise.all(\n pendingImages.map(\n (img) =>\n new Promise((resolve) => {\n img.onload = img.onerror = resolve;\n }),\n ),\n );\n }\n });\n\n return { browser, context, page, isLocalBrowser };\n }\n\n async renderToBuffer(\n html: string,\n format: OutputFormat,\n options: RenderOptions = {},\n ): Promise<Buffer> {\n const width = options.width ?? (format === \"pdf\" ? 820 : 1200);\n const height = options.height ?? 800;\n const deviceScaleFactor = options.scale ?? options.deviceScaleFactor ?? 2;\n\n const { browser, context, page, isLocalBrowser } = await this.preparePage(\n html,\n width,\n height,\n deviceScaleFactor,\n );\n\n try {\n if (format === \"pdf\") {\n const headerFooterOptions = resolveHeaderFooterPdfOptions(options);\n const pdfBuffer = await page.pdf({\n printBackground: true,\n preferCSSPageSize: true,\n ...headerFooterOptions,\n ...options.pdf,\n });\n return Buffer.from(pdfBuffer);\n } else if (format === \"png\") {\n const screenshotBuffer = await page.screenshot({\n type: \"png\",\n fullPage: options.image?.fullPage ?? true,\n ...options.image,\n });\n return Buffer.from(screenshotBuffer);\n } else if (format === \"jpeg\") {\n const screenshotBuffer = await page.screenshot({\n type: \"jpeg\",\n quality: options.quality ?? 90,\n fullPage: options.image?.fullPage ?? true,\n ...options.image,\n });\n return Buffer.from(screenshotBuffer);\n } else if (format === \"webp\") {\n const screenshotBuffer = await page.screenshot({\n type: \"webp\",\n quality: options.quality ?? 90,\n fullPage: options.image?.fullPage ?? true,\n ...options.image,\n });\n return Buffer.from(screenshotBuffer);\n } else {\n throw new Error(`Unsupported output format: ${format}`);\n }\n } finally {\n await page.close().catch(() => {});\n await context.close().catch(() => {});\n if (isLocalBrowser && browser) {\n await browser.close().catch(() => {});\n }\n }\n }\n\n async renderToPageBuffers(\n html: string,\n format: OutputFormat,\n options: RenderOptions = {},\n ): Promise<Buffer[]> {\n if (format === \"pdf\") {\n const singleBuffer = await this.renderToBuffer(html, format, options);\n return [singleBuffer];\n }\n\n const width = options.width ?? 820;\n const pageHeight = options.pageHeight ?? Math.round((width * 297) / 210);\n const marginTop = options.pageMarginTop ?? Math.round((20 / 297) * pageHeight);\n const marginBottom = options.pageMarginBottom ?? Math.round((20 / 297) * pageHeight);\n const contentHeightPerPage = Math.max(100, pageHeight - marginTop - marginBottom);\n const deviceScaleFactor = options.scale ?? options.deviceScaleFactor ?? 2;\n\n // In pages mode, remove vertical padding from .printdown container so the page margin provides clean top/bottom whitespace\n // Also style cover elements so their height matches the printable content height\n const pagesHtml = html.includes(\"</head>\")\n ? html.replace(\n \"</head>\",\n `<style>\n .printdown { padding-top: 0 !important; padding-bottom: 0 !important; }\n .printdown .printdown-cover, .printdown cover { min-height: ${contentHeightPerPage}px !important; height: ${contentHeightPerPage}px !important; margin: 0 !important; }\n </style></head>`,\n )\n : html +\n `<style>\n .printdown { padding-top: 0 !important; padding-bottom: 0 !important; }\n .printdown .printdown-cover, .printdown cover { min-height: ${contentHeightPerPage}px !important; height: ${contentHeightPerPage}px !important; margin: 0 !important; }\n </style>`;\n\n const { browser, context, page, isLocalBrowser } = await this.preparePage(\n pagesHtml,\n width,\n pageHeight,\n deviceScaleFactor,\n );\n\n let composePage: Page | null = null;\n\n try {\n const pageSlices = await page.evaluate((maxPageH: number) => {\n const totalH = Math.max(document.documentElement.scrollHeight, document.body.scrollHeight);\n\n // Collect all block elements and forced page breaks\n const selectors = [\n \"h1\",\n \"h2\",\n \"h3\",\n \"h4\",\n \"h5\",\n \"h6\",\n \"p\",\n \"ul > li\",\n \"ol > li\",\n \".printdown-task-list-item\",\n \"blockquote\",\n \"table\",\n \"tr\",\n \"pre\",\n \".printdown-cover\",\n \"cover\",\n \".printdown-page-break\",\n \".page-break\",\n \".break-before\",\n \".break-after\",\n ];\n\n const elements = Array.from(document.querySelectorAll<HTMLElement>(selectors.join(\",\")));\n\n interface ElementInfo {\n top: number;\n bottom: number;\n isForcedBreak: boolean;\n isForcedAfterBreak: boolean;\n }\n\n const items: ElementInfo[] = [];\n for (const el of elements) {\n const rect = el.getBoundingClientRect();\n const top = rect.top + window.scrollY;\n const bottom = rect.bottom + window.scrollY;\n const isForcedBreak =\n el.classList.contains(\"printdown-page-break\") ||\n el.classList.contains(\"page-break\") ||\n el.classList.contains(\"break-before\") ||\n window.getComputedStyle(el).breakBefore === \"page\" ||\n window.getComputedStyle(el).pageBreakBefore === \"always\";\n\n const isForcedAfterBreak =\n el.classList.contains(\"printdown-cover\") ||\n el.tagName.toLowerCase() === \"cover\" ||\n el.classList.contains(\"break-after\") ||\n el.classList.contains(\"printdown-break-after\") ||\n window.getComputedStyle(el).breakAfter === \"page\" ||\n window.getComputedStyle(el).pageBreakAfter === \"always\";\n\n if (rect.height > 0 || isForcedBreak || isForcedAfterBreak) {\n items.push({ top, bottom, isForcedBreak, isForcedAfterBreak });\n }\n }\n\n // Sort items by vertical position\n items.sort((a, b) => a.top - b.top);\n\n // Headings that should not be alone at the bottom (orphan headings)\n const headings = Array.from(\n document.querySelectorAll<HTMLElement>(\"h1, h2, h3, h4, h5, h6\"),\n ).map((h) => {\n const rect = h.getBoundingClientRect();\n return {\n top: rect.top + window.scrollY,\n bottom: rect.bottom + window.scrollY,\n };\n });\n\n const slices: { y: number; h: number }[] = [];\n let currentY = 0;\n\n while (currentY < totalH - 5) {\n const idealBottom = currentY + maxPageH;\n\n if (idealBottom >= totalH) {\n slices.push({ y: currentY, h: totalH - currentY });\n break;\n }\n\n // Check for forced break after an element (e.g. cover page)\n const forcedAfterBreak = items.find(\n (item) => item.isForcedAfterBreak && item.bottom > currentY && item.top >= currentY - 5,\n );\n\n if (forcedAfterBreak && forcedAfterBreak.bottom > currentY) {\n slices.push({ y: currentY, h: Math.max(20, forcedAfterBreak.bottom - currentY) });\n currentY = forcedAfterBreak.bottom;\n continue;\n }\n\n // Check for forced page breaks within current slice\n const forcedBreak = items.find(\n (item) => item.isForcedBreak && item.top > currentY + 10 && item.top <= idealBottom,\n );\n\n if (forcedBreak) {\n slices.push({ y: currentY, h: Math.max(20, forcedBreak.top - currentY) });\n currentY = forcedBreak.top;\n continue;\n }\n\n // Find an optimal break point before idealBottom\n let bestBreakY = idealBottom;\n let foundGoodBreak = false;\n\n // Check if a heading is placed too close to the bottom of the page (orphan heading prevention)\n const orphanHeading = headings.find(\n (h) => h.top > currentY + 50 && h.top <= idealBottom && idealBottom - h.top < 80,\n );\n\n if (orphanHeading) {\n bestBreakY = orphanHeading.top;\n foundGoodBreak = true;\n } else {\n // Search backwards from items near the boundary\n for (let i = items.length - 1; i >= 0; i--) {\n const item = items[i];\n\n // If an element crosses the boundary or starts near the boundary\n if (item.top > currentY + 40 && item.top <= idealBottom) {\n if (item.bottom > idealBottom) {\n // Element is cut across by idealBottom; break right before it\n bestBreakY = item.top;\n foundGoodBreak = true;\n break;\n } else if (idealBottom - item.bottom <= 50) {\n // Element cleanly ends just before idealBottom\n bestBreakY = item.bottom;\n foundGoodBreak = true;\n break;\n }\n }\n }\n }\n\n // If no clean element boundary was found within a reasonable window, fall back to idealBottom\n if (!foundGoodBreak || bestBreakY <= currentY + 50) {\n bestBreakY = idealBottom;\n }\n\n slices.push({ y: currentY, h: bestBreakY - currentY });\n currentY = bestBreakY;\n }\n\n return slices.length > 0 ? slices : [{ y: 0, h: totalH }];\n }, contentHeightPerPage);\n\n const totalContentHeight = await page.evaluate(() =>\n Math.max(document.documentElement.scrollHeight, document.body.scrollHeight),\n );\n\n const pageCount = pageSlices.length;\n\n // Expand viewport height for the full document capture\n await page.setViewportSize({\n width,\n height: Math.max(totalContentHeight + 100, pageHeight),\n });\n\n const fullContentScreenshot = await page.screenshot({\n type: \"png\",\n fullPage: true,\n });\n\n // Create a page for compositing each page slice on an A4 canvas with top/bottom margins\n composePage = await context.newPage();\n await composePage.setContent(`\n <!DOCTYPE html>\n <html>\n <head>\n <style>\n html, body { margin: 0; padding: 0; background: #ffffff; overflow: hidden; }\n canvas { display: block; }\n </style>\n </head>\n <body>\n <canvas id=\"canvas\" width=\"${width * deviceScaleFactor}\" height=\"${pageHeight * deviceScaleFactor}\" style=\"width:${width}px; height:${pageHeight}px;\"></canvas>\n </body>\n </html>\n `);\n\n const base64Img = fullContentScreenshot.toString(\"base64\");\n const pageBuffers: Buffer[] = [];\n const imageType = format === \"jpeg\" ? \"jpeg\" : format === \"webp\" ? \"webp\" : \"png\";\n\n for (let i = 0; i < pageCount; i++) {\n const slice = pageSlices[i];\n const srcY = slice.y;\n const srcH = slice.h;\n\n const headerText = options.header\n ? formatHeaderFooterCanvasText(\n options.header === true ? options.title || \"\" : options.header,\n i + 1,\n pageCount,\n options.title,\n )\n : \"\";\n\n const footerContent = options.footer || options.pageNumber;\n const footerText = footerContent\n ? formatHeaderFooterCanvasText(\n typeof footerContent === \"boolean\" ? \"{page} / {total}\" : footerContent,\n i + 1,\n pageCount,\n options.title,\n )\n : \"\";\n\n await composePage.evaluate(\n async ({\n base64,\n width,\n pageHeight,\n marginTop,\n marginBottom,\n srcY,\n srcH,\n scale,\n headerText,\n footerText,\n }) => {\n const canvas = document.getElementById(\"canvas\") as HTMLCanvasElement;\n const ctx = canvas.getContext(\"2d\");\n if (!ctx) return;\n\n ctx.fillStyle = \"#ffffff\";\n ctx.fillRect(0, 0, canvas.width, canvas.height);\n\n const img = new Image();\n await new Promise((resolve) => {\n img.onload = resolve;\n img.src = \"data:image/png;base64,\" + base64;\n });\n\n ctx.drawImage(\n img,\n 0,\n srcY * scale,\n width * scale,\n srcH * scale,\n 0,\n marginTop * scale,\n width * scale,\n srcH * scale,\n );\n\n // Draw header if specified\n if (headerText) {\n ctx.font = `${9 * scale}px -apple-system, BlinkMacSystemFont, \"Segoe UI\", Roboto, sans-serif`;\n ctx.fillStyle = \"#64748b\";\n ctx.textBaseline = \"middle\";\n const parts = headerText.split(\"|\").map((s) => s.trim());\n const paddingX = (18 / 210) * width * scale;\n const y = (marginTop * scale) / 2;\n\n if (parts.length === 1) {\n ctx.textAlign = \"center\";\n ctx.fillText(parts[0], (width * scale) / 2, y);\n } else if (parts.length === 2) {\n ctx.textAlign = \"left\";\n ctx.fillText(parts[0], paddingX, y);\n ctx.textAlign = \"right\";\n ctx.fillText(parts[1], width * scale - paddingX, y);\n } else {\n ctx.textAlign = \"left\";\n ctx.fillText(parts[0], paddingX, y);\n ctx.textAlign = \"center\";\n ctx.fillText(parts[1], (width * scale) / 2, y);\n ctx.textAlign = \"right\";\n ctx.fillText(parts[2], width * scale - paddingX, y);\n }\n }\n\n // Draw footer if specified\n if (footerText) {\n ctx.font = `${9 * scale}px -apple-system, BlinkMacSystemFont, \"Segoe UI\", Roboto, sans-serif`;\n ctx.fillStyle = \"#64748b\";\n ctx.textBaseline = \"middle\";\n const parts = footerText.split(\"|\").map((s) => s.trim());\n const paddingX = (18 / 210) * width * scale;\n const y = (pageHeight - marginBottom / 2) * scale;\n\n if (parts.length === 1) {\n ctx.textAlign = \"center\";\n ctx.fillText(parts[0], (width * scale) / 2, y);\n } else if (parts.length === 2) {\n ctx.textAlign = \"left\";\n ctx.fillText(parts[0], paddingX, y);\n ctx.textAlign = \"right\";\n ctx.fillText(parts[1], width * scale - paddingX, y);\n } else {\n ctx.textAlign = \"left\";\n ctx.fillText(parts[0], paddingX, y);\n ctx.textAlign = \"center\";\n ctx.fillText(parts[1], (width * scale) / 2, y);\n ctx.textAlign = \"right\";\n ctx.fillText(parts[2], width * scale - paddingX, y);\n }\n }\n },\n {\n base64: base64Img,\n width,\n pageHeight,\n marginTop,\n marginBottom,\n srcY,\n srcH,\n scale: deviceScaleFactor,\n headerText,\n footerText,\n },\n );\n\n const screenshotBuffer = await composePage.screenshot({\n type: imageType,\n quality: imageType !== \"png\" ? (options.quality ?? 90) : undefined,\n ...options.image,\n });\n\n pageBuffers.push(Buffer.from(screenshotBuffer));\n }\n\n return pageBuffers;\n } finally {\n if (composePage) {\n await composePage.close().catch(() => {});\n }\n await page.close().catch(() => {});\n await context.close().catch(() => {});\n if (isLocalBrowser && browser) {\n await browser.close().catch(() => {});\n }\n }\n }\n}\n\nexport async function renderHtmlToBuffer(\n html: string,\n format: OutputFormat,\n options: RenderOptions = {},\n): Promise<Buffer> {\n const renderer = new BrowserRenderer();\n return renderer.renderToBuffer(html, format, options);\n}\n\nexport async function renderHtmlToPageBuffers(\n html: string,\n format: OutputFormat,\n options: RenderOptions = {},\n): Promise<Buffer[]> {\n const renderer = new BrowserRenderer();\n return renderer.renderToPageBuffers(html, format, options);\n}\n","export interface HeaderFooterTemplateOptions {\n header?: string | boolean;\n footer?: string | boolean;\n pageNumber?: boolean | string;\n headerTemplate?: string;\n footerTemplate?: string;\n displayHeaderFooter?: boolean;\n}\n\nconst DEFAULT_FONT_STYLE =\n 'font-family: -apple-system, BlinkMacSystemFont, \"Segoe UI\", Roboto, \"Helvetica Neue\", Arial, sans-serif; font-size: 8pt; color: #64748b; width: 100%; padding: 0 18mm; box-sizing: border-box; -webkit-print-color-adjust: exact;';\n\nfunction replacePlaceholdersWithHtml(str: string): string {\n return str\n .replace(/\\{page\\}/gi, '<span class=\"pageNumber\"></span>')\n .replace(/\\{(?:total|totalPages)\\}/gi, '<span class=\"totalPages\"></span>')\n .replace(/\\{date\\}/gi, '<span class=\"date\"></span>')\n .replace(/\\{title\\}/gi, '<span class=\"title\"></span>');\n}\n\nexport function buildHeaderFooterHtml(\n content: string | boolean,\n type: \"header\" | \"footer\",\n): string {\n const text =\n typeof content === \"boolean\"\n ? type === \"header\"\n ? \"{title}\"\n : \"{page} / {total}\"\n : content.trim();\n\n const parts = text.split(\"|\").map((p) => replacePlaceholdersWithHtml(p.trim()));\n\n let innerHtml: string;\n if (parts.length === 1) {\n const isCentered =\n type === \"footer\" ||\n text.includes(\"{page}\") ||\n text.includes(\"{total}\") ||\n text.includes('<span class=\"pageNumber\">');\n innerHtml = `<div style=\"display: flex; justify-content: ${\n isCentered ? \"center\" : \"space-between\"\n }; width: 100%; align-items: center;\"><span>${parts[0]}</span></div>`;\n } else if (parts.length === 2) {\n innerHtml = `<div style=\"display: flex; justify-content: space-between; width: 100%; align-items: center;\"><span>${parts[0]}</span><span>${parts[1]}</span></div>`;\n } else {\n innerHtml = `<div style=\"display: flex; justify-content: space-between; width: 100%; align-items: center;\"><span style=\"flex: 1; text-align: left;\">${parts[0]}</span><span style=\"flex: 1; text-align: center;\">${parts[1]}</span><span style=\"flex: 1; text-align: right;\">${parts[2]}</span></div>`;\n }\n\n return `<div style=\"${DEFAULT_FONT_STYLE}\">${innerHtml}</div>`;\n}\n\nexport function resolveHeaderFooterPdfOptions(options: HeaderFooterTemplateOptions): {\n displayHeaderFooter?: boolean;\n headerTemplate?: string;\n footerTemplate?: string;\n margin?: {\n top?: string;\n bottom?: string;\n left?: string;\n right?: string;\n };\n} {\n const hasHeader = Boolean(options.header || options.headerTemplate);\n const hasPageNumber = Boolean(options.pageNumber);\n const hasFooter = Boolean(options.footer || options.footerTemplate || hasPageNumber);\n const shouldDisplay = options.displayHeaderFooter ?? (hasHeader || hasFooter);\n\n if (!shouldDisplay) {\n return {};\n }\n\n let headerTemplate = options.headerTemplate;\n if (!headerTemplate && options.header) {\n headerTemplate = buildHeaderFooterHtml(options.header, \"header\");\n }\n if (!headerTemplate) {\n headerTemplate = '<span style=\"font-size: 0px;\"></span>';\n }\n\n let footerTemplate = options.footerTemplate;\n if (!footerTemplate) {\n if (options.footer) {\n footerTemplate = buildHeaderFooterHtml(options.footer, \"footer\");\n } else if (options.pageNumber) {\n const pageFormat =\n typeof options.pageNumber === \"string\" ? options.pageNumber : \"{page} / {total}\";\n footerTemplate = buildHeaderFooterHtml(pageFormat, \"footer\");\n }\n }\n if (!footerTemplate) {\n footerTemplate = '<span style=\"font-size: 0px;\"></span>';\n }\n\n return {\n displayHeaderFooter: true,\n headerTemplate,\n footerTemplate,\n margin: {\n top: \"20mm\",\n bottom: \"20mm\",\n left: \"18mm\",\n right: \"18mm\",\n },\n };\n}\n\nexport function formatHeaderFooterCanvasText(\n content: string | boolean,\n pageIndex: number,\n totalPages: number,\n docTitle?: string,\n): string {\n const text = typeof content === \"boolean\" ? \"{page} / {total}\" : content;\n const today = new Date().toLocaleDateString();\n const title = docTitle || \"\";\n\n return text\n .replace(/\\{page\\}/gi, String(pageIndex))\n .replace(/\\{(?:total|totalPages)\\}/gi, String(totalPages))\n .replace(/\\{date\\}/gi, today)\n .replace(/\\{title\\}/gi, title);\n}\n","import fs from \"node:fs\";\nimport path from \"node:path\";\nimport { defaultThemeCss, type Theme } from \"../themes/default/index.js\";\nimport { inlineLocalImagesInHtml } from \"./images.js\";\nimport type { RenderOptions } from \"../types.js\";\n\nfunction resolveCss(cssInput: string | string[], baseUrl?: string): string {\n const inputs = Array.isArray(cssInput) ? cssInput : [cssInput];\n const resolvedCssParts: string[] = [];\n\n for (const input of inputs) {\n if (!input || typeof input !== \"string\") continue;\n\n // Check if input is a file path\n let isFile = false;\n let filePath = input;\n\n if (baseUrl && !path.isAbsolute(input)) {\n const candidate = path.resolve(baseUrl, input);\n if (fs.existsSync(candidate) && fs.statSync(candidate).isFile()) {\n isFile = true;\n filePath = candidate;\n }\n }\n\n if (!isFile && (fs.existsSync(input) || input.endsWith(\".css\"))) {\n if (fs.existsSync(input) && fs.statSync(input).isFile()) {\n isFile = true;\n filePath = path.resolve(input);\n }\n }\n\n if (isFile) {\n try {\n const fileContent = fs.readFileSync(filePath, \"utf-8\");\n resolvedCssParts.push(fileContent);\n } catch (err) {\n console.warn(`[printdown] Failed to read CSS file \"${filePath}\":`, err);\n }\n } else {\n // Inline CSS string\n resolvedCssParts.push(input);\n }\n }\n\n return resolvedCssParts.join(\"\\n\\n\");\n}\n\nfunction escapeHtml(str: string): string {\n return str\n .replace(/&/g, \"&\")\n .replace(/</g, \"<\")\n .replace(/>/g, \">\")\n .replace(/\"/g, \""\")\n .replace(/'/g, \"'\");\n}\n\nexport function buildHtmlDocument(bodyHtml: string, options: RenderOptions = {}): string {\n const title = options.title || \"Printdown Document\";\n let themeCss = \"\";\n\n if (options.theme !== false) {\n if (typeof options.theme === \"object\" && options.theme !== null && \"css\" in options.theme) {\n themeCss = (options.theme as Theme).css;\n } else {\n // Default theme\n themeCss = defaultThemeCss;\n }\n }\n\n const userCssRaw = options.css ? resolveCss(options.css, options.baseUrl) : \"\";\n const userCss = userCssRaw ? inlineLocalImagesInHtml(userCssRaw, options.baseUrl) : \"\";\n const processedBodyHtml = inlineLocalImagesInHtml(bodyHtml, options.baseUrl);\n\n const baseTag = options.baseUrl\n ? `<base href=\"${options.baseUrl.endsWith(\"/\") ? options.baseUrl : options.baseUrl + \"/\"}\">`\n : \"\";\n\n return `<!DOCTYPE html>\n<html lang=\"ja\">\n<head>\n <meta charset=\"utf-8\">\n <meta name=\"viewport\" content=\"width=device-width, initial-scale=1\">\n <title>${escapeHtml(title)}</title>\n ${baseTag}\n ${themeCss ? `<style id=\"printdown-theme\">${themeCss}</style>` : \"\"}\n ${userCss ? `<style id=\"printdown-user-css\">${userCss}</style>` : \"\"}\n</head>\n<body>\n <article class=\"printdown\">\n${processedBodyHtml}\n </article>\n</body>\n</html>`;\n}\n","import fs from \"node:fs\";\nimport path from \"node:path\";\nimport url from \"node:url\";\n\nconst MIME_TYPES: Record<string, string> = {\n \".png\": \"image/png\",\n \".jpg\": \"image/jpeg\",\n \".jpeg\": \"image/jpeg\",\n \".webp\": \"image/webp\",\n \".gif\": \"image/gif\",\n \".svg\": \"image/svg+xml\",\n \".ico\": \"image/x-icon\",\n \".avif\": \"image/avif\",\n \".bmp\": \"image/bmp\",\n \".tiff\": \"image/tiff\",\n \".tif\": \"image/tiff\",\n};\n\n/**\n * Resolves a local image path or file URL to a base64 Data URI.\n * Returns null if the image is remote, already a data URI, or cannot be found on disk.\n */\nexport function resolveLocalImageToDataUri(src: string, baseUrl?: string): string | null {\n if (!src || typeof src !== \"string\") return null;\n\n const trimmed = src.trim();\n\n // Skip remote or already inlined URLs\n if (\n trimmed.startsWith(\"data:\") ||\n trimmed.startsWith(\"http://\") ||\n trimmed.startsWith(\"https://\") ||\n trimmed.startsWith(\"//\") ||\n trimmed.startsWith(\"blob:\")\n ) {\n return null;\n }\n\n let rawPath = trimmed;\n\n // Handle file:// URLs\n if (rawPath.startsWith(\"file://\")) {\n try {\n rawPath = url.fileURLToPath(rawPath);\n } catch {\n rawPath = rawPath.replace(/^file:\\/\\//, \"\");\n }\n }\n\n // Strip query parameters (?v=...) and hash fragments (#...)\n const [cleanPath] = rawPath.split(/[?#]/);\n\n // Decode URI encoding (e.g. %20 -> space)\n let decodedPath: string;\n try {\n decodedPath = decodeURIComponent(cleanPath);\n } catch {\n decodedPath = cleanPath;\n }\n\n // Find candidate paths on filesystem\n const candidates: string[] = [];\n\n if (path.isAbsolute(decodedPath)) {\n candidates.push(decodedPath);\n } else {\n if (baseUrl) {\n const baseDir =\n fs.existsSync(baseUrl) && fs.statSync(baseUrl).isFile() ? path.dirname(baseUrl) : baseUrl;\n candidates.push(path.resolve(baseDir, decodedPath));\n }\n candidates.push(path.resolve(process.cwd(), decodedPath));\n }\n\n for (const candidate of candidates) {\n try {\n if (fs.existsSync(candidate) && fs.statSync(candidate).isFile()) {\n const fileBuffer = fs.readFileSync(candidate);\n const ext = path.extname(candidate).toLowerCase();\n const mimeType = MIME_TYPES[ext] || \"image/png\";\n return `data:${mimeType};base64,${fileBuffer.toString(\"base64\")}`;\n }\n } catch {\n // Continue to next candidate\n }\n }\n\n return null;\n}\n\n/**\n * Inlines all local images referenced in HTML (via <img> tags, <image> tags, and CSS url()) as base64 Data URIs.\n */\nexport function inlineLocalImagesInHtml(html: string, baseUrl?: string): string {\n if (!html) return html;\n\n // 1. Replace <img> tag src attributes\n let result = html.replace(\n /(<img\\b[^>]*?\\bsrc\\s*=\\s*)([\"']?)([^\"'\\s>]+)\\2([^>]*>)/gi,\n (match, prefix, _quote, src, suffix) => {\n const dataUri = resolveLocalImageToDataUri(src, baseUrl);\n if (dataUri) {\n return `${prefix}\"${dataUri}\"${suffix}`;\n }\n return match;\n },\n );\n\n // 2. Replace <image> (SVG) tag href and xlink:href attributes\n result = result.replace(\n /(<image\\b[^>]*?\\b(?:href|xlink:href)\\s*=\\s*)([\"']?)([^\"'\\s>]+)\\2([^>]*>)/gi,\n (match, prefix, _quote, src, suffix) => {\n const dataUri = resolveLocalImageToDataUri(src, baseUrl);\n if (dataUri) {\n return `${prefix}\"${dataUri}\"${suffix}`;\n }\n return match;\n },\n );\n\n // 3. Replace CSS url(...) containing local image references (excluding fonts and data URIs)\n result = result.replace(/url\\(\\s*([\"']?)([^\"')]+)\\1\\s*\\)/gi, (match, _quote, urlStr) => {\n if (\n urlStr.startsWith(\"https://printdown.local/fonts/\") ||\n urlStr.startsWith(\"data:\") ||\n urlStr.startsWith(\"http://\") ||\n urlStr.startsWith(\"https://\")\n ) {\n return match;\n }\n const dataUri = resolveLocalImageToDataUri(urlStr, baseUrl);\n if (dataUri) {\n return `url(\"${dataUri}\")`;\n }\n return match;\n });\n\n return result;\n}\n"],"mappings":"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","names":["fs","path","addClass","token","width","pageHeight","marginTop","marginBottom","srcY","srcH","headerText","footerText","fs","path","fs","path","path","fs","path","parsed","fs"]}
|
|
@@ -47,11 +47,16 @@ function buildNpmFontsCss() {
|
|
|
47
47
|
const genCss = [gen500, gen600, gen700].join("\n").replace(/url\(["']?\.\/w\//g, 'url("https://printdown.local/fonts/gen-interface-jp/w/');
|
|
48
48
|
parts.push(genCss);
|
|
49
49
|
}
|
|
50
|
+
const katexRaw = tryResolveFontCss("katex/dist/katex.min.css");
|
|
51
|
+
if (katexRaw) {
|
|
52
|
+
parts.push(katexRaw.replace(/url\(fonts\//g, "url(https://printdown.local/fonts/katex/"));
|
|
53
|
+
}
|
|
50
54
|
parts.push(`/* CDN Fallback for Standalone HTML */
|
|
51
55
|
@import url('https://cdn.jsdelivr.net/npm/gen-interface-jp@0.8.0/500.css');
|
|
52
56
|
@import url('https://cdn.jsdelivr.net/npm/gen-interface-jp@0.8.0/600.css');
|
|
53
57
|
@import url('https://cdn.jsdelivr.net/npm/gen-interface-jp@0.8.0/700.css');
|
|
54
58
|
@import url('https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&family=Noto+Sans+JP:wght@400;500;600;700&family=JetBrains+Mono:wght@400;500;600&display=swap');
|
|
59
|
+
@import url('https://cdn.jsdelivr.net/npm/katex@0.18.4/dist/katex.min.css');
|
|
55
60
|
`);
|
|
56
61
|
parts.push(`:root {
|
|
57
62
|
--printdown-font-fallback:
|
|
@@ -862,6 +867,166 @@ var centerCss = `/* Center Alignment */
|
|
|
862
867
|
}
|
|
863
868
|
`;
|
|
864
869
|
|
|
870
|
+
// src/themes/default/cover.ts
|
|
871
|
+
var coverCss = `/* Cover Page Styling */
|
|
872
|
+
.printdown .printdown-cover,
|
|
873
|
+
.printdown cover {
|
|
874
|
+
box-sizing: border-box;
|
|
875
|
+
width: 100%;
|
|
876
|
+
min-height: calc(100vh - 4rem);
|
|
877
|
+
display: flex;
|
|
878
|
+
flex-direction: column;
|
|
879
|
+
justify-content: center;
|
|
880
|
+
align-items: center;
|
|
881
|
+
text-align: center;
|
|
882
|
+
padding: 4rem 2rem;
|
|
883
|
+
margin: 0 0 2rem 0;
|
|
884
|
+
background-color: transparent;
|
|
885
|
+
border: none !important;
|
|
886
|
+
border-radius: 0;
|
|
887
|
+
position: relative;
|
|
888
|
+
page-break-after: always !important;
|
|
889
|
+
break-after: page !important;
|
|
890
|
+
}
|
|
891
|
+
|
|
892
|
+
@media print {
|
|
893
|
+
.printdown .printdown-cover,
|
|
894
|
+
.printdown cover {
|
|
895
|
+
min-height: calc(297mm - 40mm);
|
|
896
|
+
margin: 0;
|
|
897
|
+
padding: 0;
|
|
898
|
+
page-break-after: always !important;
|
|
899
|
+
break-after: page !important;
|
|
900
|
+
}
|
|
901
|
+
}
|
|
902
|
+
|
|
903
|
+
/* Headings inside cover */
|
|
904
|
+
.printdown .printdown-cover h1 {
|
|
905
|
+
font-size: 2.75rem;
|
|
906
|
+
line-height: 1.25;
|
|
907
|
+
font-weight: var(--printdown-font-weight-bold);
|
|
908
|
+
letter-spacing: -0.03em;
|
|
909
|
+
color: var(--printdown-text-strong);
|
|
910
|
+
margin-top: 0;
|
|
911
|
+
margin-bottom: 1.25rem;
|
|
912
|
+
padding-bottom: 0;
|
|
913
|
+
border: none !important;
|
|
914
|
+
border-bottom: none !important;
|
|
915
|
+
text-align: center;
|
|
916
|
+
}
|
|
917
|
+
|
|
918
|
+
.printdown .printdown-cover h2 {
|
|
919
|
+
font-size: 1.4rem;
|
|
920
|
+
line-height: 1.45;
|
|
921
|
+
font-weight: var(--printdown-font-weight-normal);
|
|
922
|
+
color: var(--printdown-text-muted);
|
|
923
|
+
letter-spacing: -0.01em;
|
|
924
|
+
margin-top: 0;
|
|
925
|
+
margin-bottom: 1.5rem;
|
|
926
|
+
border: none !important;
|
|
927
|
+
border-bottom: none !important;
|
|
928
|
+
text-align: center;
|
|
929
|
+
}
|
|
930
|
+
|
|
931
|
+
.printdown .printdown-cover h3 {
|
|
932
|
+
font-size: 1.2rem;
|
|
933
|
+
font-weight: var(--printdown-font-weight-semibold);
|
|
934
|
+
color: var(--printdown-text);
|
|
935
|
+
margin-top: 1rem;
|
|
936
|
+
margin-bottom: 0.5rem;
|
|
937
|
+
border: none !important;
|
|
938
|
+
border-bottom: none !important;
|
|
939
|
+
text-align: center;
|
|
940
|
+
}
|
|
941
|
+
|
|
942
|
+
.printdown .printdown-cover p {
|
|
943
|
+
font-size: 1.1rem;
|
|
944
|
+
line-height: 1.6;
|
|
945
|
+
color: var(--printdown-text);
|
|
946
|
+
margin-top: 0;
|
|
947
|
+
margin-bottom: 1.25rem;
|
|
948
|
+
text-align: center;
|
|
949
|
+
max-width: 650px;
|
|
950
|
+
}
|
|
951
|
+
|
|
952
|
+
/* Cover Metadata / Footer */
|
|
953
|
+
.printdown .printdown-cover .printdown-cover-meta,
|
|
954
|
+
.printdown .printdown-cover-meta {
|
|
955
|
+
margin-top: 2rem;
|
|
956
|
+
padding-top: 0;
|
|
957
|
+
border: none !important;
|
|
958
|
+
border-top: none !important;
|
|
959
|
+
font-size: 0.95rem;
|
|
960
|
+
color: var(--printdown-text-muted);
|
|
961
|
+
display: flex;
|
|
962
|
+
flex-direction: column;
|
|
963
|
+
align-items: center;
|
|
964
|
+
text-align: center;
|
|
965
|
+
gap: 0.35rem;
|
|
966
|
+
}
|
|
967
|
+
|
|
968
|
+
.printdown .printdown-cover .printdown-cover-meta p,
|
|
969
|
+
.printdown .printdown-cover-meta p {
|
|
970
|
+
margin: 0;
|
|
971
|
+
font-size: 0.95rem;
|
|
972
|
+
line-height: 1.5;
|
|
973
|
+
color: inherit;
|
|
974
|
+
text-align: center;
|
|
975
|
+
}
|
|
976
|
+
|
|
977
|
+
.printdown .printdown-cover .printdown-cover-meta strong,
|
|
978
|
+
.printdown .printdown-cover-meta strong {
|
|
979
|
+
color: var(--printdown-text-strong);
|
|
980
|
+
}
|
|
981
|
+
`;
|
|
982
|
+
|
|
983
|
+
// src/themes/default/math.ts
|
|
984
|
+
var mathCss = `/* Math & KaTeX Formula Styling */
|
|
985
|
+
.printdown .printdown-math-block,
|
|
986
|
+
.printdown .katex-display {
|
|
987
|
+
display: block;
|
|
988
|
+
margin: 1.25rem 0;
|
|
989
|
+
text-align: center;
|
|
990
|
+
overflow-x: auto;
|
|
991
|
+
overflow-y: hidden;
|
|
992
|
+
padding: 0.5rem 0;
|
|
993
|
+
page-break-inside: avoid;
|
|
994
|
+
break-inside: avoid;
|
|
995
|
+
}
|
|
996
|
+
|
|
997
|
+
.printdown .printdown-math-inline {
|
|
998
|
+
display: inline-block;
|
|
999
|
+
font-size: 1em;
|
|
1000
|
+
line-height: 1;
|
|
1001
|
+
text-indent: 0;
|
|
1002
|
+
white-space: nowrap;
|
|
1003
|
+
}
|
|
1004
|
+
|
|
1005
|
+
.printdown .katex {
|
|
1006
|
+
font: normal 1.15em KaTeX_Main, "Times New Roman", serif;
|
|
1007
|
+
line-height: 1.2;
|
|
1008
|
+
text-rendering: auto;
|
|
1009
|
+
color: var(--printdown-text-strong);
|
|
1010
|
+
}
|
|
1011
|
+
|
|
1012
|
+
.printdown .katex-error {
|
|
1013
|
+
color: var(--printdown-amber-text, #b45309);
|
|
1014
|
+
background-color: var(--printdown-amber-bg, #fef3c7);
|
|
1015
|
+
padding: 0.15em 0.35em;
|
|
1016
|
+
border-radius: 4px;
|
|
1017
|
+
font-family: var(--printdown-font-mono);
|
|
1018
|
+
font-size: 0.875em;
|
|
1019
|
+
}
|
|
1020
|
+
|
|
1021
|
+
@media print {
|
|
1022
|
+
.printdown .printdown-math-block,
|
|
1023
|
+
.printdown .katex-display {
|
|
1024
|
+
page-break-inside: avoid !important;
|
|
1025
|
+
break-inside: avoid !important;
|
|
1026
|
+
}
|
|
1027
|
+
}
|
|
1028
|
+
`;
|
|
1029
|
+
|
|
865
1030
|
// src/themes/default/print.ts
|
|
866
1031
|
var printCss = `/* Print and PDF Layout */
|
|
867
1032
|
@page {
|
|
@@ -909,11 +1074,57 @@ var printCss = `/* Print and PDF Layout */
|
|
|
909
1074
|
widows: 3;
|
|
910
1075
|
}
|
|
911
1076
|
|
|
912
|
-
|
|
913
|
-
|
|
914
|
-
|
|
1077
|
+
/* Forced Page Breaks */
|
|
1078
|
+
.printdown .printdown-page-break,
|
|
1079
|
+
.printdown .page-break,
|
|
1080
|
+
.printdown pagebreak,
|
|
1081
|
+
.printdown newpage,
|
|
1082
|
+
.printdown .break-before,
|
|
1083
|
+
.printdown .printdown-break-before,
|
|
1084
|
+
.printdown h1.printdown-page-break,
|
|
1085
|
+
.printdown h1.page-break,
|
|
1086
|
+
.printdown h1.break-before,
|
|
1087
|
+
.printdown h2.printdown-page-break,
|
|
1088
|
+
.printdown h2.page-break,
|
|
1089
|
+
.printdown h2.break-before,
|
|
1090
|
+
.printdown h3.printdown-page-break,
|
|
1091
|
+
.printdown h3.page-break,
|
|
1092
|
+
.printdown h3.break-before,
|
|
1093
|
+
.printdown h4.printdown-page-break,
|
|
1094
|
+
.printdown h4.page-break,
|
|
1095
|
+
.printdown h4.break-before,
|
|
1096
|
+
.printdown h5.printdown-page-break,
|
|
1097
|
+
.printdown h5.page-break,
|
|
1098
|
+
.printdown h5.break-before,
|
|
1099
|
+
.printdown h6.printdown-page-break,
|
|
1100
|
+
.printdown h6.page-break,
|
|
1101
|
+
.printdown h6.break-before {
|
|
1102
|
+
break-before: page !important;
|
|
1103
|
+
page-break-before: always !important;
|
|
1104
|
+
height: 0 !important;
|
|
1105
|
+
margin: 0 !important;
|
|
1106
|
+
padding: 0 !important;
|
|
1107
|
+
border: none !important;
|
|
1108
|
+
}
|
|
1109
|
+
|
|
1110
|
+
.printdown .break-after,
|
|
1111
|
+
.printdown .printdown-break-after {
|
|
1112
|
+
break-after: page !important;
|
|
1113
|
+
page-break-after: always !important;
|
|
915
1114
|
}
|
|
916
1115
|
}
|
|
1116
|
+
|
|
1117
|
+
/* Screen and default layout page-break styling */
|
|
1118
|
+
.printdown .printdown-page-break,
|
|
1119
|
+
.printdown .page-break,
|
|
1120
|
+
.printdown pagebreak,
|
|
1121
|
+
.printdown newpage {
|
|
1122
|
+
display: block;
|
|
1123
|
+
height: 0;
|
|
1124
|
+
margin: 0;
|
|
1125
|
+
padding: 0;
|
|
1126
|
+
border: none;
|
|
1127
|
+
}
|
|
917
1128
|
`;
|
|
918
1129
|
|
|
919
1130
|
// src/themes/default/index.ts
|
|
@@ -928,6 +1139,8 @@ var defaultThemeCssParts = {
|
|
|
928
1139
|
badge: badgeCss,
|
|
929
1140
|
kbd: kbdCss,
|
|
930
1141
|
center: centerCss,
|
|
1142
|
+
cover: coverCss,
|
|
1143
|
+
math: mathCss,
|
|
931
1144
|
print: printCss
|
|
932
1145
|
};
|
|
933
1146
|
var defaultThemeCss = [
|
|
@@ -941,6 +1154,8 @@ var defaultThemeCss = [
|
|
|
941
1154
|
badgeCss,
|
|
942
1155
|
kbdCss,
|
|
943
1156
|
centerCss,
|
|
1157
|
+
coverCss,
|
|
1158
|
+
mathCss,
|
|
944
1159
|
printCss
|
|
945
1160
|
].join("\n\n");
|
|
946
1161
|
var defaultTheme = {
|
|
@@ -960,9 +1175,11 @@ export {
|
|
|
960
1175
|
badgeCss,
|
|
961
1176
|
kbdCss,
|
|
962
1177
|
centerCss,
|
|
1178
|
+
coverCss,
|
|
1179
|
+
mathCss,
|
|
963
1180
|
printCss,
|
|
964
1181
|
defaultThemeCssParts,
|
|
965
1182
|
defaultThemeCss,
|
|
966
1183
|
defaultTheme
|
|
967
1184
|
};
|
|
968
|
-
//# sourceMappingURL=chunk-
|
|
1185
|
+
//# sourceMappingURL=chunk-QYKBYAYW.js.map
|