printdown 1.0.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.
@@ -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/renderer/index.ts","../src/renderer/html.ts"],"sourcesContent":["import fs from \"node:fs\";\nimport path from \"node:path\";\nimport { createMarkdownRenderer } from \"./markdown/index.js\";\nimport { BrowserRenderer, renderHtmlToBuffer, renderHtmlToPageBuffers } from \"./renderer/index.js\";\nimport { buildHtmlDocument } from \"./renderer/html.js\";\nimport { defaultTheme, defaultThemeCss, defaultThemeCssParts } from \"./themes/default/index.js\";\nimport type { OutputFormat, RenderFileOptions, RenderOptions } from \"./types.js\";\n\nexport * from \"./types.js\";\nexport {\n BrowserRenderer,\n createMarkdownRenderer,\n defaultTheme,\n defaultThemeCss,\n defaultThemeCssParts,\n renderHtmlToPageBuffers,\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 md = await createMarkdownRenderer(options.markdown);\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\";\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}\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\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] : \"text\";\n const code = token.content;\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 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 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\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 }\n\n if (filePath && fs.existsSync(filePath)) {\n try {\n const body = fs.readFileSync(filePath);\n await route.fulfill({\n status: 200,\n contentType: \"font/woff2\",\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 pdfBuffer = await page.pdf({\n printBackground: true,\n preferCSSPageSize: true,\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 const pagesHtml = html.includes(\"</head>\")\n ? html.replace(\n \"</head>\",\n \"<style>.printdown { padding-top: 0 !important; padding-bottom: 0 !important; }</style></head>\",\n )\n : html +\n \"<style>.printdown { padding-top: 0 !important; padding-bottom: 0 !important; }</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 totalContentHeight = await page.evaluate(() =>\n Math.max(document.documentElement.scrollHeight, document.body.scrollHeight),\n );\n\n const pageCount = Math.max(1, Math.ceil(totalContentHeight / contentHeightPerPage));\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 srcY = i * contentHeightPerPage;\n const srcH = Math.min(contentHeightPerPage, totalContentHeight - srcY);\n\n await composePage.evaluate(\n async ({ base64, width, marginTop, srcY, srcH, scale }) => {\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 {\n base64: base64Img,\n width,\n marginTop,\n srcY,\n srcH,\n scale: deviceScaleFactor,\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","import fs from \"node:fs\";\nimport path from \"node:path\";\nimport { defaultThemeCss, type Theme } from \"../themes/default/index.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, \"&amp;\")\n .replace(/</g, \"&lt;\")\n .replace(/>/g, \"&gt;\")\n .replace(/\"/g, \"&quot;\")\n .replace(/'/g, \"&#039;\");\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 userCss = options.css ? resolveCss(options.css, 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${bodyHtml}\n </article>\n</body>\n</html>`;\n}\n"],"mappings":"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","names":["fs","path","width","marginTop","srcY","srcH","fs","path","path","fs","path","parsed","fs"]}