md2x 0.1.0 → 0.2.1

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.
Files changed (65) hide show
  1. package/README.md +13 -7
  2. package/dist/index.mjs +158 -7
  3. package/dist/md2x.mjs +158 -7
  4. package/dist/vendor/katex/fonts/KaTeX_AMS-Regular.ttf +0 -0
  5. package/dist/vendor/katex/fonts/KaTeX_AMS-Regular.woff +0 -0
  6. package/dist/vendor/katex/fonts/KaTeX_AMS-Regular.woff2 +0 -0
  7. package/dist/vendor/katex/fonts/KaTeX_Caligraphic-Bold.ttf +0 -0
  8. package/dist/vendor/katex/fonts/KaTeX_Caligraphic-Bold.woff +0 -0
  9. package/dist/vendor/katex/fonts/KaTeX_Caligraphic-Bold.woff2 +0 -0
  10. package/dist/vendor/katex/fonts/KaTeX_Caligraphic-Regular.ttf +0 -0
  11. package/dist/vendor/katex/fonts/KaTeX_Caligraphic-Regular.woff +0 -0
  12. package/dist/vendor/katex/fonts/KaTeX_Caligraphic-Regular.woff2 +0 -0
  13. package/dist/vendor/katex/fonts/KaTeX_Fraktur-Bold.ttf +0 -0
  14. package/dist/vendor/katex/fonts/KaTeX_Fraktur-Bold.woff +0 -0
  15. package/dist/vendor/katex/fonts/KaTeX_Fraktur-Bold.woff2 +0 -0
  16. package/dist/vendor/katex/fonts/KaTeX_Fraktur-Regular.ttf +0 -0
  17. package/dist/vendor/katex/fonts/KaTeX_Fraktur-Regular.woff +0 -0
  18. package/dist/vendor/katex/fonts/KaTeX_Fraktur-Regular.woff2 +0 -0
  19. package/dist/vendor/katex/fonts/KaTeX_Main-Bold.ttf +0 -0
  20. package/dist/vendor/katex/fonts/KaTeX_Main-Bold.woff +0 -0
  21. package/dist/vendor/katex/fonts/KaTeX_Main-Bold.woff2 +0 -0
  22. package/dist/vendor/katex/fonts/KaTeX_Main-BoldItalic.ttf +0 -0
  23. package/dist/vendor/katex/fonts/KaTeX_Main-BoldItalic.woff +0 -0
  24. package/dist/vendor/katex/fonts/KaTeX_Main-BoldItalic.woff2 +0 -0
  25. package/dist/vendor/katex/fonts/KaTeX_Main-Italic.ttf +0 -0
  26. package/dist/vendor/katex/fonts/KaTeX_Main-Italic.woff +0 -0
  27. package/dist/vendor/katex/fonts/KaTeX_Main-Italic.woff2 +0 -0
  28. package/dist/vendor/katex/fonts/KaTeX_Main-Regular.ttf +0 -0
  29. package/dist/vendor/katex/fonts/KaTeX_Main-Regular.woff +0 -0
  30. package/dist/vendor/katex/fonts/KaTeX_Main-Regular.woff2 +0 -0
  31. package/dist/vendor/katex/fonts/KaTeX_Math-BoldItalic.ttf +0 -0
  32. package/dist/vendor/katex/fonts/KaTeX_Math-BoldItalic.woff +0 -0
  33. package/dist/vendor/katex/fonts/KaTeX_Math-BoldItalic.woff2 +0 -0
  34. package/dist/vendor/katex/fonts/KaTeX_Math-Italic.ttf +0 -0
  35. package/dist/vendor/katex/fonts/KaTeX_Math-Italic.woff +0 -0
  36. package/dist/vendor/katex/fonts/KaTeX_Math-Italic.woff2 +0 -0
  37. package/dist/vendor/katex/fonts/KaTeX_SansSerif-Bold.ttf +0 -0
  38. package/dist/vendor/katex/fonts/KaTeX_SansSerif-Bold.woff +0 -0
  39. package/dist/vendor/katex/fonts/KaTeX_SansSerif-Bold.woff2 +0 -0
  40. package/dist/vendor/katex/fonts/KaTeX_SansSerif-Italic.ttf +0 -0
  41. package/dist/vendor/katex/fonts/KaTeX_SansSerif-Italic.woff +0 -0
  42. package/dist/vendor/katex/fonts/KaTeX_SansSerif-Italic.woff2 +0 -0
  43. package/dist/vendor/katex/fonts/KaTeX_SansSerif-Regular.ttf +0 -0
  44. package/dist/vendor/katex/fonts/KaTeX_SansSerif-Regular.woff +0 -0
  45. package/dist/vendor/katex/fonts/KaTeX_SansSerif-Regular.woff2 +0 -0
  46. package/dist/vendor/katex/fonts/KaTeX_Script-Regular.ttf +0 -0
  47. package/dist/vendor/katex/fonts/KaTeX_Script-Regular.woff +0 -0
  48. package/dist/vendor/katex/fonts/KaTeX_Script-Regular.woff2 +0 -0
  49. package/dist/vendor/katex/fonts/KaTeX_Size1-Regular.ttf +0 -0
  50. package/dist/vendor/katex/fonts/KaTeX_Size1-Regular.woff +0 -0
  51. package/dist/vendor/katex/fonts/KaTeX_Size1-Regular.woff2 +0 -0
  52. package/dist/vendor/katex/fonts/KaTeX_Size2-Regular.ttf +0 -0
  53. package/dist/vendor/katex/fonts/KaTeX_Size2-Regular.woff +0 -0
  54. package/dist/vendor/katex/fonts/KaTeX_Size2-Regular.woff2 +0 -0
  55. package/dist/vendor/katex/fonts/KaTeX_Size3-Regular.ttf +0 -0
  56. package/dist/vendor/katex/fonts/KaTeX_Size3-Regular.woff +0 -0
  57. package/dist/vendor/katex/fonts/KaTeX_Size3-Regular.woff2 +0 -0
  58. package/dist/vendor/katex/fonts/KaTeX_Size4-Regular.ttf +0 -0
  59. package/dist/vendor/katex/fonts/KaTeX_Size4-Regular.woff +0 -0
  60. package/dist/vendor/katex/fonts/KaTeX_Size4-Regular.woff2 +0 -0
  61. package/dist/vendor/katex/fonts/KaTeX_Typewriter-Regular.ttf +0 -0
  62. package/dist/vendor/katex/fonts/KaTeX_Typewriter-Regular.woff +0 -0
  63. package/dist/vendor/katex/fonts/KaTeX_Typewriter-Regular.woff2 +0 -0
  64. package/dist/vendor/katex/katex.min.css +1 -0
  65. package/package.json +1 -1
package/README.md CHANGED
@@ -1,6 +1,8 @@
1
1
  # md2x
2
2
 
3
- Markdown → PDF/DOCX converter (local, no server). Supports Mermaid/Graphviz/Vega/HTML/SVG rendering, math, and code highlighting.
3
+ Markdown → PDF/DOCX converter (local, no server). Supports Mermaid/Graphviz/Infographic/Vega/HTML/SVG rendering, math, and code highlighting.
4
+
5
+ [![npm version](https://img.shields.io/npm/v/md2x.svg?style=flat-square)](https://www.npmjs.com/package/md2x)
4
6
 
5
7
  ## Usage
6
8
 
@@ -26,18 +28,22 @@ Use a theme:
26
28
  npx md2x input.md -o output.pdf --theme academic
27
29
  ```
28
30
 
29
- ## Dev (this repo)
31
+ Help:
30
32
 
31
33
  ```bash
32
- npm run node:dev -- ./demo/test.md
34
+ npx md2x -h
33
35
  ```
34
36
 
35
37
  ## Puppeteer / Chrome install
36
38
 
37
39
  This package depends on `puppeteer`. On first install, Puppeteer downloads a compatible "Chrome for Testing" build (cached under your user directory). Set `PUPPETEER_SKIP_DOWNLOAD=1` to skip download and use a system Chrome via `PUPPETEER_EXECUTABLE_PATH`.
38
40
 
39
- ## Publish (maintainers)
41
+ ## Open Source License
40
42
 
41
- ```bash
42
- npm publish
43
- ```
43
+ This project is open source under ISC license. Welcome to Star, report issues, suggest features, and contribute code.
44
+
45
+ **Project URL:** https://github.com/LarchLiu/md2x
46
+
47
+ ## Acknowledgements
48
+
49
+ - [markdown-viewer-extension](https://github.com/xicilion/markdown-viewer-extension) - Developed based on this project
package/dist/index.mjs CHANGED
@@ -82282,6 +82282,10 @@ var init_remark_gemoji = __esm({
82282
82282
  });
82283
82283
 
82284
82284
  // ../src/plugins/remark-super-sub.ts
82285
+ var remark_super_sub_exports = {};
82286
+ __export(remark_super_sub_exports, {
82287
+ default: () => remark_super_sub_default
82288
+ });
82285
82289
  function parseScriptSyntax(text9) {
82286
82290
  const result = [];
82287
82291
  let remaining = text9;
@@ -126670,6 +126674,35 @@ function resolveRendererHtmlPath() {
126670
126674
  const moduleDir = path3.dirname(fileURLToPath2(import.meta.url));
126671
126675
  return path3.join(moduleDir, "renderer", "puppeteer-render.html");
126672
126676
  }
126677
+ function getPaperSizeInches(format) {
126678
+ switch (format) {
126679
+ case "Letter":
126680
+ return { widthIn: 8.5, heightIn: 11 };
126681
+ case "Legal":
126682
+ return { widthIn: 8.5, heightIn: 14 };
126683
+ case "A3":
126684
+ return { widthIn: 11.69, heightIn: 16.54 };
126685
+ case "A5":
126686
+ return { widthIn: 5.83, heightIn: 8.27 };
126687
+ case "A4":
126688
+ default:
126689
+ return { widthIn: 8.27, heightIn: 11.69 };
126690
+ }
126691
+ }
126692
+ function parseCssLengthToInches(value) {
126693
+ const v = String(value ?? "").trim();
126694
+ if (!v) return null;
126695
+ const m = v.match(/^(-?\d+(?:\.\d+)?)(px|in|mm|cm)$/i);
126696
+ if (!m) return null;
126697
+ const n = parseFloat(m[1]);
126698
+ if (!Number.isFinite(n)) return null;
126699
+ const unit = m[2].toLowerCase();
126700
+ if (unit === "in") return n;
126701
+ if (unit === "cm") return n / 2.54;
126702
+ if (unit === "mm") return n / 25.4;
126703
+ if (unit === "px") return n / 96;
126704
+ return null;
126705
+ }
126673
126706
  async function createBrowserRenderer() {
126674
126707
  try {
126675
126708
  puppeteer = await import("puppeteer");
@@ -126835,6 +126868,53 @@ Original error: ${message}${tail}`);
126835
126868
  } else {
126836
126869
  await pdfPage.setContent(fullHtml, { waitUntil: "networkidle0" });
126837
126870
  }
126871
+ const format = options.format || "A4";
126872
+ const landscape = options.landscape || false;
126873
+ const pdfScale = options.scale || 1;
126874
+ const { widthIn, heightIn } = getPaperSizeInches(format);
126875
+ const pageHeightIn = landscape ? widthIn : heightIn;
126876
+ const marginTopIn = parseCssLengthToInches(options.margin?.top || "20mm") ?? parseCssLengthToInches("20mm");
126877
+ const marginBottomIn = parseCssLengthToInches(options.margin?.bottom || "20mm") ?? parseCssLengthToInches("20mm");
126878
+ const printableHeightCssPx = (pageHeightIn - marginTopIn - marginBottomIn) * 96 / pdfScale;
126879
+ await pdfPage.evaluate((printableHeightPx) => {
126880
+ const container = document.getElementById("markdown-content");
126881
+ if (!container) return;
126882
+ const cs = window.getComputedStyle(container);
126883
+ const padTop = parseFloat(cs.paddingTop || "0") || 0;
126884
+ const padBottom = parseFloat(cs.paddingBottom || "0") || 0;
126885
+ const available = Math.max(0, printableHeightPx - padTop - padBottom);
126886
+ const imgs = container.querySelectorAll(".md2x-diagram img.md2x-diagram, img.md2x-diagram");
126887
+ imgs.forEach((img) => {
126888
+ const el = img;
126889
+ const rect = el.getBoundingClientRect();
126890
+ const currentHeight = rect.height || el.naturalHeight || 0;
126891
+ if (!currentHeight) return;
126892
+ if (currentHeight <= available + 0.5) return;
126893
+ el.style.maxHeight = `${available}px`;
126894
+ el.style.height = "auto";
126895
+ el.style.width = "auto";
126896
+ el.style.maxWidth = "100%";
126897
+ el.style.objectFit = "contain";
126898
+ });
126899
+ }, printableHeightCssPx);
126900
+ await pdfPage.evaluate(() => {
126901
+ const container = document.getElementById("markdown-content");
126902
+ if (!container) return;
126903
+ const availableWidth = container.clientWidth;
126904
+ if (!availableWidth) return;
126905
+ const wideDivs = container.querySelectorAll(':scope > div[style*="width"]');
126906
+ wideDivs.forEach((div) => {
126907
+ const el = div;
126908
+ const widthMatch = el.style.width?.match(/^(\d+(?:\.\d+)?)px$/);
126909
+ if (!widthMatch) return;
126910
+ const fixedWidth = parseFloat(widthMatch[1]);
126911
+ if (!Number.isFinite(fixedWidth) || fixedWidth <= 0) return;
126912
+ const scale = Math.min(1, availableWidth / fixedWidth);
126913
+ if (scale >= 0.999) return;
126914
+ el.style.transformOrigin = "top left";
126915
+ el.style.transform = `scale(${scale})`;
126916
+ });
126917
+ });
126838
126918
  const pdfBuffer = await pdfPage.pdf({
126839
126919
  format: options.format || "A4",
126840
126920
  landscape: options.landscape || false,
@@ -127411,6 +127491,7 @@ __export(node_exporter_exports, {
127411
127491
  });
127412
127492
  import * as fs3 from "fs";
127413
127493
  import * as path5 from "path";
127494
+ import { createRequire } from "module";
127414
127495
  import { fileURLToPath as fileURLToPath3, pathToFileURL as pathToFileURL3 } from "url";
127415
127496
  function ensureBase64Globals() {
127416
127497
  if (typeof globalThis.atob !== "function") {
@@ -127500,6 +127581,15 @@ body {
127500
127581
  padding: 20px;
127501
127582
  }
127502
127583
 
127584
+ /* Wide content auto-scaling for PDF */
127585
+ /* Use transform scale to fit wide content within page width */
127586
+ /* The actual scale value will be set dynamically via JavaScript */
127587
+ #markdown-content > div[style*="width"] {
127588
+ transform-origin: top left;
127589
+ break-inside: avoid;
127590
+ page-break-inside: avoid;
127591
+ }
127592
+
127503
127593
  /* Headings */
127504
127594
  h1, h2, h3, h4, h5, h6 {
127505
127595
  margin-top: 24px;
@@ -127558,7 +127648,10 @@ code {
127558
127648
 
127559
127649
  pre {
127560
127650
  padding: 16px;
127561
- overflow: auto;
127651
+ /* PDFs can't scroll horizontally; wrap long lines instead of clipping. */
127652
+ white-space: pre-wrap;
127653
+ overflow-wrap: anywhere;
127654
+ word-break: break-word;
127562
127655
  font-size: 85%;
127563
127656
  line-height: 1.45;
127564
127657
  background-color: #f6f8fa;
@@ -127573,6 +127666,10 @@ pre code {
127573
127666
  font-size: 100%;
127574
127667
  background-color: transparent;
127575
127668
  border: 0;
127669
+ /* Inherit wrapping behavior from <pre> for PDFs */
127670
+ white-space: inherit;
127671
+ overflow-wrap: inherit;
127672
+ word-break: inherit;
127576
127673
  }
127577
127674
 
127578
127675
  /* Blockquotes */
@@ -127621,6 +127718,32 @@ img {
127621
127718
  box-sizing: content-box;
127622
127719
  }
127623
127720
 
127721
+ /* Diagrams (rendered images) */
127722
+ .md2x-diagram {
127723
+ text-align: center;
127724
+ break-inside: avoid;
127725
+ page-break-inside: avoid;
127726
+ }
127727
+
127728
+ .md2x-diagram img,
127729
+ img.md2x-diagram {
127730
+ display: block;
127731
+ max-width: 100%;
127732
+ height: auto;
127733
+ margin-left: auto;
127734
+ margin-right: auto;
127735
+ break-inside: avoid;
127736
+ page-break-inside: avoid;
127737
+ }
127738
+
127739
+ #markdown-content svg {
127740
+ display: block;
127741
+ margin-left: auto;
127742
+ margin-right: auto;
127743
+ break-inside: avoid;
127744
+ page-break-inside: avoid;
127745
+ }
127746
+
127624
127747
  /* Block-level images: marked by rehypeBlockImages plugin */
127625
127748
  img.block-image {
127626
127749
  display: block;
@@ -127740,6 +127863,20 @@ img.block-image {
127740
127863
  ${hrStyles}
127741
127864
  `;
127742
127865
  }
127866
+ function loadKatexCss() {
127867
+ const moduleDir = path5.dirname(fileURLToPath3(import.meta.url));
127868
+ const bundledKatexCssPath = path5.join(moduleDir, "vendor", "katex", "katex.min.css");
127869
+ let katexCssPath = bundledKatexCssPath;
127870
+ if (!fs3.existsSync(bundledKatexCssPath)) {
127871
+ const require2 = createRequire(import.meta.url);
127872
+ katexCssPath = require2.resolve("katex/dist/katex.min.css");
127873
+ }
127874
+ const katexDistDir = path5.dirname(katexCssPath);
127875
+ const katexFontsHref = pathToFileURL3(path5.join(katexDistDir, "fonts") + path5.sep).href;
127876
+ let css2 = fs3.readFileSync(katexCssPath, "utf-8");
127877
+ css2 = css2.replace(/url\((['"]?)(?:\.\/)?fonts\//g, `url($1${katexFontsHref}`);
127878
+ return css2;
127879
+ }
127743
127880
  var NodeDocxExporter, NodePdfExporter, node_exporter_default;
127744
127881
  var init_node_exporter = __esm({
127745
127882
  "src/host/node-exporter.ts"() {
@@ -127747,6 +127884,7 @@ var init_node_exporter = __esm({
127747
127884
  init_docx_exporter();
127748
127885
  init_browser_renderer();
127749
127886
  init_node_platform();
127887
+ init_plugins();
127750
127888
  NodeDocxExporter = class {
127751
127889
  /**
127752
127890
  * Export markdown to DOCX buffer
@@ -127865,6 +128003,12 @@ var init_node_exporter = __esm({
127865
128003
  await browserRenderer.initialize();
127866
128004
  const themeConfig = await loadRendererThemeConfig(themeId);
127867
128005
  const html7 = await this.processMarkdownToHtml(markdown2, browserRenderer, basePath, themeConfig);
128006
+ let katexCss = "";
128007
+ try {
128008
+ katexCss = loadKatexCss();
128009
+ } catch (e) {
128010
+ console.warn("Failed to load KaTeX CSS for PDF export:", e);
128011
+ }
127868
128012
  const baseCss = await loadBaseCss(options.pdfHrAsPageBreak ?? true);
127869
128013
  let themeCss = "";
127870
128014
  try {
@@ -127872,7 +128016,7 @@ var init_node_exporter = __esm({
127872
128016
  } catch (e) {
127873
128017
  console.warn("Failed to load theme CSS, using base styles only:", e);
127874
128018
  }
127875
- const css2 = baseCss + "\n" + themeCss;
128019
+ const css2 = katexCss + "\n" + baseCss + "\n" + themeCss;
127876
128020
  return await browserRenderer.exportToPdf(html7, css2, options.pdf, basePath);
127877
128021
  } finally {
127878
128022
  try {
@@ -127909,6 +128053,7 @@ var init_node_exporter = __esm({
127909
128053
  const remarkParse2 = (await Promise.resolve().then(() => (init_remark_parse(), remark_parse_exports))).default;
127910
128054
  const remarkGfm2 = (await Promise.resolve().then(() => (init_remark_gfm(), remark_gfm_exports))).default;
127911
128055
  const remarkMath2 = (await Promise.resolve().then(() => (init_remark_math(), remark_math_exports))).default;
128056
+ const remarkSuperSub2 = (await Promise.resolve().then(() => (init_remark_super_sub(), remark_super_sub_exports))).default;
127912
128057
  const remarkRehype2 = (await Promise.resolve().then(() => (init_remark_rehype(), remark_rehype_exports))).default;
127913
128058
  const rehypeKatex2 = (await Promise.resolve().then(() => (init_rehype_katex(), rehype_katex_exports))).default;
127914
128059
  const rehypeHighlight2 = (await Promise.resolve().then(() => (init_rehype_highlight(), rehype_highlight_exports))).default;
@@ -127947,7 +128092,7 @@ var init_node_exporter = __esm({
127947
128092
  });
127948
128093
  };
127949
128094
  }
127950
- const processor = unified2().use(remarkParse2).use(remarkGfm2).use(remarkMath2).use(remarkRehype2, { allowDangerousHtml: true }).use(rehypeKatex2).use(rehypeHighlight2).use(rehypeBlockImages).use(rehypeStringify2, { allowDangerousHtml: true });
128095
+ const processor = unified2().use(remarkParse2).use(remarkGfm2, { singleTilde: false }).use(remarkMath2).use(remarkSuperSub2).use(remarkRehype2, { allowDangerousHtml: true }).use(rehypeKatex2).use(rehypeHighlight2).use(rehypeBlockImages).use(rehypeStringify2, { allowDangerousHtml: true });
127951
128096
  const file = await processor.process(markdown2);
127952
128097
  let html7 = String(file);
127953
128098
  html7 = await this.processDiagrams(html7, browserRenderer, basePath, themeConfig);
@@ -127957,18 +128102,24 @@ var init_node_exporter = __esm({
127957
128102
  * Process diagram code blocks and replace with rendered images
127958
128103
  */
127959
128104
  async processDiagrams(html7, browserRenderer, basePath, themeConfig) {
127960
- const codeBlockRegex = /<pre><code class="(?:hljs )?language-(mermaid|graphviz|dot|vega|vega-lite|infographic)">([\s\S]*?)<\/code><\/pre>/gi;
128105
+ const pluginLangs = plugins.filter((p3) => p3.nodeSelector.includes("code")).map((p3) => p3.language).filter((lang) => lang !== null);
128106
+ const aliases = ["graphviz", "gv", "vegalite"];
128107
+ const supportedLangs = [...pluginLangs, ...aliases].join("|");
128108
+ const codeBlockRegex = new RegExp(
128109
+ `<pre><code class="(?:hljs )?language-(${supportedLangs})">([\\s\\S]*?)<\\/code><\\/pre>`,
128110
+ "gi"
128111
+ );
127961
128112
  const matches = [...html7.matchAll(codeBlockRegex)];
127962
128113
  for (const match of matches) {
127963
128114
  const [fullMatch, lang, code4] = match;
127964
128115
  const decodedCode = this.decodeHtmlEntities(code4);
127965
128116
  let renderType = lang.toLowerCase();
127966
- if (renderType === "graphviz") renderType = "dot";
127967
- if (renderType === "vega") renderType = "vega-lite";
128117
+ if (renderType === "graphviz" || renderType === "gv") renderType = "dot";
128118
+ if (renderType === "vegalite") renderType = "vega-lite";
127968
128119
  try {
127969
128120
  const result = await browserRenderer.render(renderType, decodedCode, basePath, themeConfig);
127970
128121
  if (result && result.base64) {
127971
- const imgTag = `<img src="data:image/${result.format};base64,${result.base64}" alt="${lang} diagram" style="max-width: 100%;" />`;
128122
+ const imgTag = `<div class="md2x-diagram"><img class="md2x-diagram" src="data:image/${result.format};base64,${result.base64}" alt="${lang} diagram" style="max-width: 100%;" /></div>`;
127972
128123
  html7 = html7.replace(fullMatch, imgTag);
127973
128124
  }
127974
128125
  } catch (e) {
package/dist/md2x.mjs CHANGED
@@ -82283,6 +82283,10 @@ var init_remark_gemoji = __esm({
82283
82283
  });
82284
82284
 
82285
82285
  // ../src/plugins/remark-super-sub.ts
82286
+ var remark_super_sub_exports = {};
82287
+ __export(remark_super_sub_exports, {
82288
+ default: () => remark_super_sub_default
82289
+ });
82286
82290
  function parseScriptSyntax(text9) {
82287
82291
  const result = [];
82288
82292
  let remaining = text9;
@@ -126671,6 +126675,35 @@ function resolveRendererHtmlPath() {
126671
126675
  const moduleDir = path3.dirname(fileURLToPath2(import.meta.url));
126672
126676
  return path3.join(moduleDir, "renderer", "puppeteer-render.html");
126673
126677
  }
126678
+ function getPaperSizeInches(format) {
126679
+ switch (format) {
126680
+ case "Letter":
126681
+ return { widthIn: 8.5, heightIn: 11 };
126682
+ case "Legal":
126683
+ return { widthIn: 8.5, heightIn: 14 };
126684
+ case "A3":
126685
+ return { widthIn: 11.69, heightIn: 16.54 };
126686
+ case "A5":
126687
+ return { widthIn: 5.83, heightIn: 8.27 };
126688
+ case "A4":
126689
+ default:
126690
+ return { widthIn: 8.27, heightIn: 11.69 };
126691
+ }
126692
+ }
126693
+ function parseCssLengthToInches(value) {
126694
+ const v = String(value ?? "").trim();
126695
+ if (!v) return null;
126696
+ const m = v.match(/^(-?\d+(?:\.\d+)?)(px|in|mm|cm)$/i);
126697
+ if (!m) return null;
126698
+ const n = parseFloat(m[1]);
126699
+ if (!Number.isFinite(n)) return null;
126700
+ const unit = m[2].toLowerCase();
126701
+ if (unit === "in") return n;
126702
+ if (unit === "cm") return n / 2.54;
126703
+ if (unit === "mm") return n / 25.4;
126704
+ if (unit === "px") return n / 96;
126705
+ return null;
126706
+ }
126674
126707
  async function createBrowserRenderer() {
126675
126708
  try {
126676
126709
  puppeteer = await import("puppeteer");
@@ -126836,6 +126869,53 @@ Original error: ${message}${tail}`);
126836
126869
  } else {
126837
126870
  await pdfPage.setContent(fullHtml, { waitUntil: "networkidle0" });
126838
126871
  }
126872
+ const format = options.format || "A4";
126873
+ const landscape = options.landscape || false;
126874
+ const pdfScale = options.scale || 1;
126875
+ const { widthIn, heightIn } = getPaperSizeInches(format);
126876
+ const pageHeightIn = landscape ? widthIn : heightIn;
126877
+ const marginTopIn = parseCssLengthToInches(options.margin?.top || "20mm") ?? parseCssLengthToInches("20mm");
126878
+ const marginBottomIn = parseCssLengthToInches(options.margin?.bottom || "20mm") ?? parseCssLengthToInches("20mm");
126879
+ const printableHeightCssPx = (pageHeightIn - marginTopIn - marginBottomIn) * 96 / pdfScale;
126880
+ await pdfPage.evaluate((printableHeightPx) => {
126881
+ const container = document.getElementById("markdown-content");
126882
+ if (!container) return;
126883
+ const cs = window.getComputedStyle(container);
126884
+ const padTop = parseFloat(cs.paddingTop || "0") || 0;
126885
+ const padBottom = parseFloat(cs.paddingBottom || "0") || 0;
126886
+ const available = Math.max(0, printableHeightPx - padTop - padBottom);
126887
+ const imgs = container.querySelectorAll(".md2x-diagram img.md2x-diagram, img.md2x-diagram");
126888
+ imgs.forEach((img) => {
126889
+ const el = img;
126890
+ const rect = el.getBoundingClientRect();
126891
+ const currentHeight = rect.height || el.naturalHeight || 0;
126892
+ if (!currentHeight) return;
126893
+ if (currentHeight <= available + 0.5) return;
126894
+ el.style.maxHeight = `${available}px`;
126895
+ el.style.height = "auto";
126896
+ el.style.width = "auto";
126897
+ el.style.maxWidth = "100%";
126898
+ el.style.objectFit = "contain";
126899
+ });
126900
+ }, printableHeightCssPx);
126901
+ await pdfPage.evaluate(() => {
126902
+ const container = document.getElementById("markdown-content");
126903
+ if (!container) return;
126904
+ const availableWidth = container.clientWidth;
126905
+ if (!availableWidth) return;
126906
+ const wideDivs = container.querySelectorAll(':scope > div[style*="width"]');
126907
+ wideDivs.forEach((div) => {
126908
+ const el = div;
126909
+ const widthMatch = el.style.width?.match(/^(\d+(?:\.\d+)?)px$/);
126910
+ if (!widthMatch) return;
126911
+ const fixedWidth = parseFloat(widthMatch[1]);
126912
+ if (!Number.isFinite(fixedWidth) || fixedWidth <= 0) return;
126913
+ const scale = Math.min(1, availableWidth / fixedWidth);
126914
+ if (scale >= 0.999) return;
126915
+ el.style.transformOrigin = "top left";
126916
+ el.style.transform = `scale(${scale})`;
126917
+ });
126918
+ });
126839
126919
  const pdfBuffer = await pdfPage.pdf({
126840
126920
  format: options.format || "A4",
126841
126921
  landscape: options.landscape || false,
@@ -127412,6 +127492,7 @@ __export(node_exporter_exports, {
127412
127492
  });
127413
127493
  import * as fs3 from "fs";
127414
127494
  import * as path5 from "path";
127495
+ import { createRequire } from "module";
127415
127496
  import { fileURLToPath as fileURLToPath3, pathToFileURL as pathToFileURL3 } from "url";
127416
127497
  function ensureBase64Globals() {
127417
127498
  if (typeof globalThis.atob !== "function") {
@@ -127501,6 +127582,15 @@ body {
127501
127582
  padding: 20px;
127502
127583
  }
127503
127584
 
127585
+ /* Wide content auto-scaling for PDF */
127586
+ /* Use transform scale to fit wide content within page width */
127587
+ /* The actual scale value will be set dynamically via JavaScript */
127588
+ #markdown-content > div[style*="width"] {
127589
+ transform-origin: top left;
127590
+ break-inside: avoid;
127591
+ page-break-inside: avoid;
127592
+ }
127593
+
127504
127594
  /* Headings */
127505
127595
  h1, h2, h3, h4, h5, h6 {
127506
127596
  margin-top: 24px;
@@ -127559,7 +127649,10 @@ code {
127559
127649
 
127560
127650
  pre {
127561
127651
  padding: 16px;
127562
- overflow: auto;
127652
+ /* PDFs can't scroll horizontally; wrap long lines instead of clipping. */
127653
+ white-space: pre-wrap;
127654
+ overflow-wrap: anywhere;
127655
+ word-break: break-word;
127563
127656
  font-size: 85%;
127564
127657
  line-height: 1.45;
127565
127658
  background-color: #f6f8fa;
@@ -127574,6 +127667,10 @@ pre code {
127574
127667
  font-size: 100%;
127575
127668
  background-color: transparent;
127576
127669
  border: 0;
127670
+ /* Inherit wrapping behavior from <pre> for PDFs */
127671
+ white-space: inherit;
127672
+ overflow-wrap: inherit;
127673
+ word-break: inherit;
127577
127674
  }
127578
127675
 
127579
127676
  /* Blockquotes */
@@ -127622,6 +127719,32 @@ img {
127622
127719
  box-sizing: content-box;
127623
127720
  }
127624
127721
 
127722
+ /* Diagrams (rendered images) */
127723
+ .md2x-diagram {
127724
+ text-align: center;
127725
+ break-inside: avoid;
127726
+ page-break-inside: avoid;
127727
+ }
127728
+
127729
+ .md2x-diagram img,
127730
+ img.md2x-diagram {
127731
+ display: block;
127732
+ max-width: 100%;
127733
+ height: auto;
127734
+ margin-left: auto;
127735
+ margin-right: auto;
127736
+ break-inside: avoid;
127737
+ page-break-inside: avoid;
127738
+ }
127739
+
127740
+ #markdown-content svg {
127741
+ display: block;
127742
+ margin-left: auto;
127743
+ margin-right: auto;
127744
+ break-inside: avoid;
127745
+ page-break-inside: avoid;
127746
+ }
127747
+
127625
127748
  /* Block-level images: marked by rehypeBlockImages plugin */
127626
127749
  img.block-image {
127627
127750
  display: block;
@@ -127741,6 +127864,20 @@ img.block-image {
127741
127864
  ${hrStyles}
127742
127865
  `;
127743
127866
  }
127867
+ function loadKatexCss() {
127868
+ const moduleDir = path5.dirname(fileURLToPath3(import.meta.url));
127869
+ const bundledKatexCssPath = path5.join(moduleDir, "vendor", "katex", "katex.min.css");
127870
+ let katexCssPath = bundledKatexCssPath;
127871
+ if (!fs3.existsSync(bundledKatexCssPath)) {
127872
+ const require2 = createRequire(import.meta.url);
127873
+ katexCssPath = require2.resolve("katex/dist/katex.min.css");
127874
+ }
127875
+ const katexDistDir = path5.dirname(katexCssPath);
127876
+ const katexFontsHref = pathToFileURL3(path5.join(katexDistDir, "fonts") + path5.sep).href;
127877
+ let css2 = fs3.readFileSync(katexCssPath, "utf-8");
127878
+ css2 = css2.replace(/url\((['"]?)(?:\.\/)?fonts\//g, `url($1${katexFontsHref}`);
127879
+ return css2;
127880
+ }
127744
127881
  var NodeDocxExporter, NodePdfExporter, node_exporter_default;
127745
127882
  var init_node_exporter = __esm({
127746
127883
  "src/host/node-exporter.ts"() {
@@ -127748,6 +127885,7 @@ var init_node_exporter = __esm({
127748
127885
  init_docx_exporter();
127749
127886
  init_browser_renderer();
127750
127887
  init_node_platform();
127888
+ init_plugins();
127751
127889
  NodeDocxExporter = class {
127752
127890
  /**
127753
127891
  * Export markdown to DOCX buffer
@@ -127866,6 +128004,12 @@ var init_node_exporter = __esm({
127866
128004
  await browserRenderer.initialize();
127867
128005
  const themeConfig = await loadRendererThemeConfig(themeId);
127868
128006
  const html7 = await this.processMarkdownToHtml(markdown2, browserRenderer, basePath, themeConfig);
128007
+ let katexCss = "";
128008
+ try {
128009
+ katexCss = loadKatexCss();
128010
+ } catch (e) {
128011
+ console.warn("Failed to load KaTeX CSS for PDF export:", e);
128012
+ }
127869
128013
  const baseCss = await loadBaseCss(options.pdfHrAsPageBreak ?? true);
127870
128014
  let themeCss = "";
127871
128015
  try {
@@ -127873,7 +128017,7 @@ var init_node_exporter = __esm({
127873
128017
  } catch (e) {
127874
128018
  console.warn("Failed to load theme CSS, using base styles only:", e);
127875
128019
  }
127876
- const css2 = baseCss + "\n" + themeCss;
128020
+ const css2 = katexCss + "\n" + baseCss + "\n" + themeCss;
127877
128021
  return await browserRenderer.exportToPdf(html7, css2, options.pdf, basePath);
127878
128022
  } finally {
127879
128023
  try {
@@ -127910,6 +128054,7 @@ var init_node_exporter = __esm({
127910
128054
  const remarkParse2 = (await Promise.resolve().then(() => (init_remark_parse(), remark_parse_exports))).default;
127911
128055
  const remarkGfm2 = (await Promise.resolve().then(() => (init_remark_gfm(), remark_gfm_exports))).default;
127912
128056
  const remarkMath2 = (await Promise.resolve().then(() => (init_remark_math(), remark_math_exports))).default;
128057
+ const remarkSuperSub2 = (await Promise.resolve().then(() => (init_remark_super_sub(), remark_super_sub_exports))).default;
127913
128058
  const remarkRehype2 = (await Promise.resolve().then(() => (init_remark_rehype(), remark_rehype_exports))).default;
127914
128059
  const rehypeKatex2 = (await Promise.resolve().then(() => (init_rehype_katex(), rehype_katex_exports))).default;
127915
128060
  const rehypeHighlight2 = (await Promise.resolve().then(() => (init_rehype_highlight(), rehype_highlight_exports))).default;
@@ -127948,7 +128093,7 @@ var init_node_exporter = __esm({
127948
128093
  });
127949
128094
  };
127950
128095
  }
127951
- const processor = unified2().use(remarkParse2).use(remarkGfm2).use(remarkMath2).use(remarkRehype2, { allowDangerousHtml: true }).use(rehypeKatex2).use(rehypeHighlight2).use(rehypeBlockImages).use(rehypeStringify2, { allowDangerousHtml: true });
128096
+ const processor = unified2().use(remarkParse2).use(remarkGfm2, { singleTilde: false }).use(remarkMath2).use(remarkSuperSub2).use(remarkRehype2, { allowDangerousHtml: true }).use(rehypeKatex2).use(rehypeHighlight2).use(rehypeBlockImages).use(rehypeStringify2, { allowDangerousHtml: true });
127952
128097
  const file = await processor.process(markdown2);
127953
128098
  let html7 = String(file);
127954
128099
  html7 = await this.processDiagrams(html7, browserRenderer, basePath, themeConfig);
@@ -127958,18 +128103,24 @@ var init_node_exporter = __esm({
127958
128103
  * Process diagram code blocks and replace with rendered images
127959
128104
  */
127960
128105
  async processDiagrams(html7, browserRenderer, basePath, themeConfig) {
127961
- const codeBlockRegex = /<pre><code class="(?:hljs )?language-(mermaid|graphviz|dot|vega|vega-lite|infographic)">([\s\S]*?)<\/code><\/pre>/gi;
128106
+ const pluginLangs = plugins.filter((p3) => p3.nodeSelector.includes("code")).map((p3) => p3.language).filter((lang) => lang !== null);
128107
+ const aliases = ["graphviz", "gv", "vegalite"];
128108
+ const supportedLangs = [...pluginLangs, ...aliases].join("|");
128109
+ const codeBlockRegex = new RegExp(
128110
+ `<pre><code class="(?:hljs )?language-(${supportedLangs})">([\\s\\S]*?)<\\/code><\\/pre>`,
128111
+ "gi"
128112
+ );
127962
128113
  const matches = [...html7.matchAll(codeBlockRegex)];
127963
128114
  for (const match of matches) {
127964
128115
  const [fullMatch, lang, code4] = match;
127965
128116
  const decodedCode = this.decodeHtmlEntities(code4);
127966
128117
  let renderType = lang.toLowerCase();
127967
- if (renderType === "graphviz") renderType = "dot";
127968
- if (renderType === "vega") renderType = "vega-lite";
128118
+ if (renderType === "graphviz" || renderType === "gv") renderType = "dot";
128119
+ if (renderType === "vegalite") renderType = "vega-lite";
127969
128120
  try {
127970
128121
  const result = await browserRenderer.render(renderType, decodedCode, basePath, themeConfig);
127971
128122
  if (result && result.base64) {
127972
- const imgTag = `<img src="data:image/${result.format};base64,${result.base64}" alt="${lang} diagram" style="max-width: 100%;" />`;
128123
+ const imgTag = `<div class="md2x-diagram"><img class="md2x-diagram" src="data:image/${result.format};base64,${result.base64}" alt="${lang} diagram" style="max-width: 100%;" /></div>`;
127973
128124
  html7 = html7.replace(fullMatch, imgTag);
127974
128125
  }
127975
128126
  } catch (e) {
@@ -0,0 +1 @@
1
+ @font-face{font-display:block;font-family:KaTeX_AMS;font-style:normal;font-weight:400;src:url(fonts/KaTeX_AMS-Regular.woff2) format("woff2"),url(fonts/KaTeX_AMS-Regular.woff) format("woff"),url(fonts/KaTeX_AMS-Regular.ttf) format("truetype")}@font-face{font-display:block;font-family:KaTeX_Caligraphic;font-style:normal;font-weight:700;src:url(fonts/KaTeX_Caligraphic-Bold.woff2) format("woff2"),url(fonts/KaTeX_Caligraphic-Bold.woff) format("woff"),url(fonts/KaTeX_Caligraphic-Bold.ttf) format("truetype")}@font-face{font-display:block;font-family:KaTeX_Caligraphic;font-style:normal;font-weight:400;src:url(fonts/KaTeX_Caligraphic-Regular.woff2) format("woff2"),url(fonts/KaTeX_Caligraphic-Regular.woff) format("woff"),url(fonts/KaTeX_Caligraphic-Regular.ttf) format("truetype")}@font-face{font-display:block;font-family:KaTeX_Fraktur;font-style:normal;font-weight:700;src:url(fonts/KaTeX_Fraktur-Bold.woff2) format("woff2"),url(fonts/KaTeX_Fraktur-Bold.woff) format("woff"),url(fonts/KaTeX_Fraktur-Bold.ttf) format("truetype")}@font-face{font-display:block;font-family:KaTeX_Fraktur;font-style:normal;font-weight:400;src:url(fonts/KaTeX_Fraktur-Regular.woff2) format("woff2"),url(fonts/KaTeX_Fraktur-Regular.woff) format("woff"),url(fonts/KaTeX_Fraktur-Regular.ttf) format("truetype")}@font-face{font-display:block;font-family:KaTeX_Main;font-style:normal;font-weight:700;src:url(fonts/KaTeX_Main-Bold.woff2) format("woff2"),url(fonts/KaTeX_Main-Bold.woff) format("woff"),url(fonts/KaTeX_Main-Bold.ttf) format("truetype")}@font-face{font-display:block;font-family:KaTeX_Main;font-style:italic;font-weight:700;src:url(fonts/KaTeX_Main-BoldItalic.woff2) format("woff2"),url(fonts/KaTeX_Main-BoldItalic.woff) format("woff"),url(fonts/KaTeX_Main-BoldItalic.ttf) format("truetype")}@font-face{font-display:block;font-family:KaTeX_Main;font-style:italic;font-weight:400;src:url(fonts/KaTeX_Main-Italic.woff2) format("woff2"),url(fonts/KaTeX_Main-Italic.woff) format("woff"),url(fonts/KaTeX_Main-Italic.ttf) format("truetype")}@font-face{font-display:block;font-family:KaTeX_Main;font-style:normal;font-weight:400;src:url(fonts/KaTeX_Main-Regular.woff2) format("woff2"),url(fonts/KaTeX_Main-Regular.woff) format("woff"),url(fonts/KaTeX_Main-Regular.ttf) format("truetype")}@font-face{font-display:block;font-family:KaTeX_Math;font-style:italic;font-weight:700;src:url(fonts/KaTeX_Math-BoldItalic.woff2) format("woff2"),url(fonts/KaTeX_Math-BoldItalic.woff) format("woff"),url(fonts/KaTeX_Math-BoldItalic.ttf) format("truetype")}@font-face{font-display:block;font-family:KaTeX_Math;font-style:italic;font-weight:400;src:url(fonts/KaTeX_Math-Italic.woff2) format("woff2"),url(fonts/KaTeX_Math-Italic.woff) format("woff"),url(fonts/KaTeX_Math-Italic.ttf) format("truetype")}@font-face{font-display:block;font-family:"KaTeX_SansSerif";font-style:normal;font-weight:700;src:url(fonts/KaTeX_SansSerif-Bold.woff2) format("woff2"),url(fonts/KaTeX_SansSerif-Bold.woff) format("woff"),url(fonts/KaTeX_SansSerif-Bold.ttf) format("truetype")}@font-face{font-display:block;font-family:"KaTeX_SansSerif";font-style:italic;font-weight:400;src:url(fonts/KaTeX_SansSerif-Italic.woff2) format("woff2"),url(fonts/KaTeX_SansSerif-Italic.woff) format("woff"),url(fonts/KaTeX_SansSerif-Italic.ttf) format("truetype")}@font-face{font-display:block;font-family:"KaTeX_SansSerif";font-style:normal;font-weight:400;src:url(fonts/KaTeX_SansSerif-Regular.woff2) format("woff2"),url(fonts/KaTeX_SansSerif-Regular.woff) format("woff"),url(fonts/KaTeX_SansSerif-Regular.ttf) format("truetype")}@font-face{font-display:block;font-family:KaTeX_Script;font-style:normal;font-weight:400;src:url(fonts/KaTeX_Script-Regular.woff2) format("woff2"),url(fonts/KaTeX_Script-Regular.woff) format("woff"),url(fonts/KaTeX_Script-Regular.ttf) format("truetype")}@font-face{font-display:block;font-family:KaTeX_Size1;font-style:normal;font-weight:400;src:url(fonts/KaTeX_Size1-Regular.woff2) format("woff2"),url(fonts/KaTeX_Size1-Regular.woff) format("woff"),url(fonts/KaTeX_Size1-Regular.ttf) format("truetype")}@font-face{font-display:block;font-family:KaTeX_Size2;font-style:normal;font-weight:400;src:url(fonts/KaTeX_Size2-Regular.woff2) format("woff2"),url(fonts/KaTeX_Size2-Regular.woff) format("woff"),url(fonts/KaTeX_Size2-Regular.ttf) format("truetype")}@font-face{font-display:block;font-family:KaTeX_Size3;font-style:normal;font-weight:400;src:url(fonts/KaTeX_Size3-Regular.woff2) format("woff2"),url(fonts/KaTeX_Size3-Regular.woff) format("woff"),url(fonts/KaTeX_Size3-Regular.ttf) format("truetype")}@font-face{font-display:block;font-family:KaTeX_Size4;font-style:normal;font-weight:400;src:url(fonts/KaTeX_Size4-Regular.woff2) format("woff2"),url(fonts/KaTeX_Size4-Regular.woff) format("woff"),url(fonts/KaTeX_Size4-Regular.ttf) format("truetype")}@font-face{font-display:block;font-family:KaTeX_Typewriter;font-style:normal;font-weight:400;src:url(fonts/KaTeX_Typewriter-Regular.woff2) format("woff2"),url(fonts/KaTeX_Typewriter-Regular.woff) format("woff"),url(fonts/KaTeX_Typewriter-Regular.ttf) format("truetype")}.katex{font:normal 1.21em KaTeX_Main,Times New Roman,serif;line-height:1.2;text-indent:0;text-rendering:auto}.katex *{-ms-high-contrast-adjust:none!important;border-color:currentColor}.katex .katex-version:after{content:"0.16.27"}.katex .katex-mathml{clip:rect(1px,1px,1px,1px);border:0;height:1px;overflow:hidden;padding:0;position:absolute;width:1px}.katex .katex-html>.newline{display:block}.katex .base{position:relative;white-space:nowrap;width:-webkit-min-content;width:-moz-min-content;width:min-content}.katex .base,.katex .strut{display:inline-block}.katex .textbf{font-weight:700}.katex .textit{font-style:italic}.katex .textrm{font-family:KaTeX_Main}.katex .textsf{font-family:KaTeX_SansSerif}.katex .texttt{font-family:KaTeX_Typewriter}.katex .mathnormal{font-family:KaTeX_Math;font-style:italic}.katex .mathit{font-family:KaTeX_Main;font-style:italic}.katex .mathrm{font-style:normal}.katex .mathbf{font-family:KaTeX_Main;font-weight:700}.katex .boldsymbol{font-family:KaTeX_Math;font-style:italic;font-weight:700}.katex .amsrm,.katex .mathbb,.katex .textbb{font-family:KaTeX_AMS}.katex .mathcal{font-family:KaTeX_Caligraphic}.katex .mathfrak,.katex .textfrak{font-family:KaTeX_Fraktur}.katex .mathboldfrak,.katex .textboldfrak{font-family:KaTeX_Fraktur;font-weight:700}.katex .mathtt{font-family:KaTeX_Typewriter}.katex .mathscr,.katex .textscr{font-family:KaTeX_Script}.katex .mathsf,.katex .textsf{font-family:KaTeX_SansSerif}.katex .mathboldsf,.katex .textboldsf{font-family:KaTeX_SansSerif;font-weight:700}.katex .mathitsf,.katex .mathsfit,.katex .textitsf{font-family:KaTeX_SansSerif;font-style:italic}.katex .mainrm{font-family:KaTeX_Main;font-style:normal}.katex .vlist-t{border-collapse:collapse;display:inline-table;table-layout:fixed}.katex .vlist-r{display:table-row}.katex .vlist{display:table-cell;position:relative;vertical-align:bottom}.katex .vlist>span{display:block;height:0;position:relative}.katex .vlist>span>span{display:inline-block}.katex .vlist>span>.pstrut{overflow:hidden;width:0}.katex .vlist-t2{margin-right:-2px}.katex .vlist-s{display:table-cell;font-size:1px;min-width:2px;vertical-align:bottom;width:2px}.katex .vbox{align-items:baseline;display:inline-flex;flex-direction:column}.katex .hbox{width:100%}.katex .hbox,.katex .thinbox{display:inline-flex;flex-direction:row}.katex .thinbox{max-width:0;width:0}.katex .msupsub{text-align:left}.katex .mfrac>span>span{text-align:center}.katex .mfrac .frac-line{border-bottom-style:solid;display:inline-block;width:100%}.katex .hdashline,.katex .hline,.katex .mfrac .frac-line,.katex .overline .overline-line,.katex .rule,.katex .underline .underline-line{min-height:1px}.katex .mspace{display:inline-block}.katex .clap,.katex .llap,.katex .rlap{position:relative;width:0}.katex .clap>.inner,.katex .llap>.inner,.katex .rlap>.inner{position:absolute}.katex .clap>.fix,.katex .llap>.fix,.katex .rlap>.fix{display:inline-block}.katex .llap>.inner{right:0}.katex .clap>.inner,.katex .rlap>.inner{left:0}.katex .clap>.inner>span{margin-left:-50%;margin-right:50%}.katex .rule{border:0 solid;display:inline-block;position:relative}.katex .hline,.katex .overline .overline-line,.katex .underline .underline-line{border-bottom-style:solid;display:inline-block;width:100%}.katex .hdashline{border-bottom-style:dashed;display:inline-block;width:100%}.katex .sqrt>.root{margin-left:.2777777778em;margin-right:-.5555555556em}.katex .fontsize-ensurer.reset-size1.size1,.katex .sizing.reset-size1.size1{font-size:1em}.katex .fontsize-ensurer.reset-size1.size2,.katex .sizing.reset-size1.size2{font-size:1.2em}.katex .fontsize-ensurer.reset-size1.size3,.katex .sizing.reset-size1.size3{font-size:1.4em}.katex .fontsize-ensurer.reset-size1.size4,.katex .sizing.reset-size1.size4{font-size:1.6em}.katex .fontsize-ensurer.reset-size1.size5,.katex .sizing.reset-size1.size5{font-size:1.8em}.katex .fontsize-ensurer.reset-size1.size6,.katex .sizing.reset-size1.size6{font-size:2em}.katex .fontsize-ensurer.reset-size1.size7,.katex .sizing.reset-size1.size7{font-size:2.4em}.katex .fontsize-ensurer.reset-size1.size8,.katex .sizing.reset-size1.size8{font-size:2.88em}.katex .fontsize-ensurer.reset-size1.size9,.katex .sizing.reset-size1.size9{font-size:3.456em}.katex .fontsize-ensurer.reset-size1.size10,.katex .sizing.reset-size1.size10{font-size:4.148em}.katex .fontsize-ensurer.reset-size1.size11,.katex .sizing.reset-size1.size11{font-size:4.976em}.katex .fontsize-ensurer.reset-size2.size1,.katex .sizing.reset-size2.size1{font-size:.8333333333em}.katex .fontsize-ensurer.reset-size2.size2,.katex .sizing.reset-size2.size2{font-size:1em}.katex .fontsize-ensurer.reset-size2.size3,.katex .sizing.reset-size2.size3{font-size:1.1666666667em}.katex .fontsize-ensurer.reset-size2.size4,.katex .sizing.reset-size2.size4{font-size:1.3333333333em}.katex .fontsize-ensurer.reset-size2.size5,.katex .sizing.reset-size2.size5{font-size:1.5em}.katex .fontsize-ensurer.reset-size2.size6,.katex .sizing.reset-size2.size6{font-size:1.6666666667em}.katex .fontsize-ensurer.reset-size2.size7,.katex .sizing.reset-size2.size7{font-size:2em}.katex .fontsize-ensurer.reset-size2.size8,.katex .sizing.reset-size2.size8{font-size:2.4em}.katex .fontsize-ensurer.reset-size2.size9,.katex .sizing.reset-size2.size9{font-size:2.88em}.katex .fontsize-ensurer.reset-size2.size10,.katex .sizing.reset-size2.size10{font-size:3.4566666667em}.katex .fontsize-ensurer.reset-size2.size11,.katex .sizing.reset-size2.size11{font-size:4.1466666667em}.katex .fontsize-ensurer.reset-size3.size1,.katex .sizing.reset-size3.size1{font-size:.7142857143em}.katex .fontsize-ensurer.reset-size3.size2,.katex .sizing.reset-size3.size2{font-size:.8571428571em}.katex .fontsize-ensurer.reset-size3.size3,.katex .sizing.reset-size3.size3{font-size:1em}.katex .fontsize-ensurer.reset-size3.size4,.katex .sizing.reset-size3.size4{font-size:1.1428571429em}.katex .fontsize-ensurer.reset-size3.size5,.katex .sizing.reset-size3.size5{font-size:1.2857142857em}.katex .fontsize-ensurer.reset-size3.size6,.katex .sizing.reset-size3.size6{font-size:1.4285714286em}.katex .fontsize-ensurer.reset-size3.size7,.katex .sizing.reset-size3.size7{font-size:1.7142857143em}.katex .fontsize-ensurer.reset-size3.size8,.katex .sizing.reset-size3.size8{font-size:2.0571428571em}.katex .fontsize-ensurer.reset-size3.size9,.katex .sizing.reset-size3.size9{font-size:2.4685714286em}.katex .fontsize-ensurer.reset-size3.size10,.katex .sizing.reset-size3.size10{font-size:2.9628571429em}.katex .fontsize-ensurer.reset-size3.size11,.katex .sizing.reset-size3.size11{font-size:3.5542857143em}.katex .fontsize-ensurer.reset-size4.size1,.katex .sizing.reset-size4.size1{font-size:.625em}.katex .fontsize-ensurer.reset-size4.size2,.katex .sizing.reset-size4.size2{font-size:.75em}.katex .fontsize-ensurer.reset-size4.size3,.katex .sizing.reset-size4.size3{font-size:.875em}.katex .fontsize-ensurer.reset-size4.size4,.katex .sizing.reset-size4.size4{font-size:1em}.katex .fontsize-ensurer.reset-size4.size5,.katex .sizing.reset-size4.size5{font-size:1.125em}.katex .fontsize-ensurer.reset-size4.size6,.katex .sizing.reset-size4.size6{font-size:1.25em}.katex .fontsize-ensurer.reset-size4.size7,.katex .sizing.reset-size4.size7{font-size:1.5em}.katex .fontsize-ensurer.reset-size4.size8,.katex .sizing.reset-size4.size8{font-size:1.8em}.katex .fontsize-ensurer.reset-size4.size9,.katex .sizing.reset-size4.size9{font-size:2.16em}.katex .fontsize-ensurer.reset-size4.size10,.katex .sizing.reset-size4.size10{font-size:2.5925em}.katex .fontsize-ensurer.reset-size4.size11,.katex .sizing.reset-size4.size11{font-size:3.11em}.katex .fontsize-ensurer.reset-size5.size1,.katex .sizing.reset-size5.size1{font-size:.5555555556em}.katex .fontsize-ensurer.reset-size5.size2,.katex .sizing.reset-size5.size2{font-size:.6666666667em}.katex .fontsize-ensurer.reset-size5.size3,.katex .sizing.reset-size5.size3{font-size:.7777777778em}.katex .fontsize-ensurer.reset-size5.size4,.katex .sizing.reset-size5.size4{font-size:.8888888889em}.katex .fontsize-ensurer.reset-size5.size5,.katex .sizing.reset-size5.size5{font-size:1em}.katex .fontsize-ensurer.reset-size5.size6,.katex .sizing.reset-size5.size6{font-size:1.1111111111em}.katex .fontsize-ensurer.reset-size5.size7,.katex .sizing.reset-size5.size7{font-size:1.3333333333em}.katex .fontsize-ensurer.reset-size5.size8,.katex .sizing.reset-size5.size8{font-size:1.6em}.katex .fontsize-ensurer.reset-size5.size9,.katex .sizing.reset-size5.size9{font-size:1.92em}.katex .fontsize-ensurer.reset-size5.size10,.katex .sizing.reset-size5.size10{font-size:2.3044444444em}.katex .fontsize-ensurer.reset-size5.size11,.katex .sizing.reset-size5.size11{font-size:2.7644444444em}.katex .fontsize-ensurer.reset-size6.size1,.katex .sizing.reset-size6.size1{font-size:.5em}.katex .fontsize-ensurer.reset-size6.size2,.katex .sizing.reset-size6.size2{font-size:.6em}.katex .fontsize-ensurer.reset-size6.size3,.katex .sizing.reset-size6.size3{font-size:.7em}.katex .fontsize-ensurer.reset-size6.size4,.katex .sizing.reset-size6.size4{font-size:.8em}.katex .fontsize-ensurer.reset-size6.size5,.katex .sizing.reset-size6.size5{font-size:.9em}.katex .fontsize-ensurer.reset-size6.size6,.katex .sizing.reset-size6.size6{font-size:1em}.katex .fontsize-ensurer.reset-size6.size7,.katex .sizing.reset-size6.size7{font-size:1.2em}.katex .fontsize-ensurer.reset-size6.size8,.katex .sizing.reset-size6.size8{font-size:1.44em}.katex .fontsize-ensurer.reset-size6.size9,.katex .sizing.reset-size6.size9{font-size:1.728em}.katex .fontsize-ensurer.reset-size6.size10,.katex .sizing.reset-size6.size10{font-size:2.074em}.katex .fontsize-ensurer.reset-size6.size11,.katex .sizing.reset-size6.size11{font-size:2.488em}.katex .fontsize-ensurer.reset-size7.size1,.katex .sizing.reset-size7.size1{font-size:.4166666667em}.katex .fontsize-ensurer.reset-size7.size2,.katex .sizing.reset-size7.size2{font-size:.5em}.katex .fontsize-ensurer.reset-size7.size3,.katex .sizing.reset-size7.size3{font-size:.5833333333em}.katex .fontsize-ensurer.reset-size7.size4,.katex .sizing.reset-size7.size4{font-size:.6666666667em}.katex .fontsize-ensurer.reset-size7.size5,.katex .sizing.reset-size7.size5{font-size:.75em}.katex .fontsize-ensurer.reset-size7.size6,.katex .sizing.reset-size7.size6{font-size:.8333333333em}.katex .fontsize-ensurer.reset-size7.size7,.katex .sizing.reset-size7.size7{font-size:1em}.katex .fontsize-ensurer.reset-size7.size8,.katex .sizing.reset-size7.size8{font-size:1.2em}.katex .fontsize-ensurer.reset-size7.size9,.katex .sizing.reset-size7.size9{font-size:1.44em}.katex .fontsize-ensurer.reset-size7.size10,.katex .sizing.reset-size7.size10{font-size:1.7283333333em}.katex .fontsize-ensurer.reset-size7.size11,.katex .sizing.reset-size7.size11{font-size:2.0733333333em}.katex .fontsize-ensurer.reset-size8.size1,.katex .sizing.reset-size8.size1{font-size:.3472222222em}.katex .fontsize-ensurer.reset-size8.size2,.katex .sizing.reset-size8.size2{font-size:.4166666667em}.katex .fontsize-ensurer.reset-size8.size3,.katex .sizing.reset-size8.size3{font-size:.4861111111em}.katex .fontsize-ensurer.reset-size8.size4,.katex .sizing.reset-size8.size4{font-size:.5555555556em}.katex .fontsize-ensurer.reset-size8.size5,.katex .sizing.reset-size8.size5{font-size:.625em}.katex .fontsize-ensurer.reset-size8.size6,.katex .sizing.reset-size8.size6{font-size:.6944444444em}.katex .fontsize-ensurer.reset-size8.size7,.katex .sizing.reset-size8.size7{font-size:.8333333333em}.katex .fontsize-ensurer.reset-size8.size8,.katex .sizing.reset-size8.size8{font-size:1em}.katex .fontsize-ensurer.reset-size8.size9,.katex .sizing.reset-size8.size9{font-size:1.2em}.katex .fontsize-ensurer.reset-size8.size10,.katex .sizing.reset-size8.size10{font-size:1.4402777778em}.katex .fontsize-ensurer.reset-size8.size11,.katex .sizing.reset-size8.size11{font-size:1.7277777778em}.katex .fontsize-ensurer.reset-size9.size1,.katex .sizing.reset-size9.size1{font-size:.2893518519em}.katex .fontsize-ensurer.reset-size9.size2,.katex .sizing.reset-size9.size2{font-size:.3472222222em}.katex .fontsize-ensurer.reset-size9.size3,.katex .sizing.reset-size9.size3{font-size:.4050925926em}.katex .fontsize-ensurer.reset-size9.size4,.katex .sizing.reset-size9.size4{font-size:.462962963em}.katex .fontsize-ensurer.reset-size9.size5,.katex .sizing.reset-size9.size5{font-size:.5208333333em}.katex .fontsize-ensurer.reset-size9.size6,.katex .sizing.reset-size9.size6{font-size:.5787037037em}.katex .fontsize-ensurer.reset-size9.size7,.katex .sizing.reset-size9.size7{font-size:.6944444444em}.katex .fontsize-ensurer.reset-size9.size8,.katex .sizing.reset-size9.size8{font-size:.8333333333em}.katex .fontsize-ensurer.reset-size9.size9,.katex .sizing.reset-size9.size9{font-size:1em}.katex .fontsize-ensurer.reset-size9.size10,.katex .sizing.reset-size9.size10{font-size:1.2002314815em}.katex .fontsize-ensurer.reset-size9.size11,.katex .sizing.reset-size9.size11{font-size:1.4398148148em}.katex .fontsize-ensurer.reset-size10.size1,.katex .sizing.reset-size10.size1{font-size:.2410800386em}.katex .fontsize-ensurer.reset-size10.size2,.katex .sizing.reset-size10.size2{font-size:.2892960463em}.katex .fontsize-ensurer.reset-size10.size3,.katex .sizing.reset-size10.size3{font-size:.337512054em}.katex .fontsize-ensurer.reset-size10.size4,.katex .sizing.reset-size10.size4{font-size:.3857280617em}.katex .fontsize-ensurer.reset-size10.size5,.katex .sizing.reset-size10.size5{font-size:.4339440694em}.katex .fontsize-ensurer.reset-size10.size6,.katex .sizing.reset-size10.size6{font-size:.4821600771em}.katex .fontsize-ensurer.reset-size10.size7,.katex .sizing.reset-size10.size7{font-size:.5785920926em}.katex .fontsize-ensurer.reset-size10.size8,.katex .sizing.reset-size10.size8{font-size:.6943105111em}.katex .fontsize-ensurer.reset-size10.size9,.katex .sizing.reset-size10.size9{font-size:.8331726133em}.katex .fontsize-ensurer.reset-size10.size10,.katex .sizing.reset-size10.size10{font-size:1em}.katex .fontsize-ensurer.reset-size10.size11,.katex .sizing.reset-size10.size11{font-size:1.1996142719em}.katex .fontsize-ensurer.reset-size11.size1,.katex .sizing.reset-size11.size1{font-size:.2009646302em}.katex .fontsize-ensurer.reset-size11.size2,.katex .sizing.reset-size11.size2{font-size:.2411575563em}.katex .fontsize-ensurer.reset-size11.size3,.katex .sizing.reset-size11.size3{font-size:.2813504823em}.katex .fontsize-ensurer.reset-size11.size4,.katex .sizing.reset-size11.size4{font-size:.3215434084em}.katex .fontsize-ensurer.reset-size11.size5,.katex .sizing.reset-size11.size5{font-size:.3617363344em}.katex .fontsize-ensurer.reset-size11.size6,.katex .sizing.reset-size11.size6{font-size:.4019292605em}.katex .fontsize-ensurer.reset-size11.size7,.katex .sizing.reset-size11.size7{font-size:.4823151125em}.katex .fontsize-ensurer.reset-size11.size8,.katex .sizing.reset-size11.size8{font-size:.578778135em}.katex .fontsize-ensurer.reset-size11.size9,.katex .sizing.reset-size11.size9{font-size:.6945337621em}.katex .fontsize-ensurer.reset-size11.size10,.katex .sizing.reset-size11.size10{font-size:.8336012862em}.katex .fontsize-ensurer.reset-size11.size11,.katex .sizing.reset-size11.size11{font-size:1em}.katex .delimsizing.size1{font-family:KaTeX_Size1}.katex .delimsizing.size2{font-family:KaTeX_Size2}.katex .delimsizing.size3{font-family:KaTeX_Size3}.katex .delimsizing.size4{font-family:KaTeX_Size4}.katex .delimsizing.mult .delim-size1>span{font-family:KaTeX_Size1}.katex .delimsizing.mult .delim-size4>span{font-family:KaTeX_Size4}.katex .nulldelimiter{display:inline-block;width:.12em}.katex .delimcenter,.katex .op-symbol{position:relative}.katex .op-symbol.small-op{font-family:KaTeX_Size1}.katex .op-symbol.large-op{font-family:KaTeX_Size2}.katex .accent>.vlist-t,.katex .op-limits>.vlist-t{text-align:center}.katex .accent .accent-body{position:relative}.katex .accent .accent-body:not(.accent-full){width:0}.katex .overlay{display:block}.katex .mtable .vertical-separator{display:inline-block;min-width:1px}.katex .mtable .arraycolsep{display:inline-block}.katex .mtable .col-align-c>.vlist-t{text-align:center}.katex .mtable .col-align-l>.vlist-t{text-align:left}.katex .mtable .col-align-r>.vlist-t{text-align:right}.katex .svg-align{text-align:left}.katex svg{fill:currentColor;stroke:currentColor;fill-rule:nonzero;fill-opacity:1;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;display:block;height:inherit;position:absolute;width:100%}.katex svg path{stroke:none}.katex img{border-style:none;max-height:none;max-width:none;min-height:0;min-width:0}.katex .stretchy{display:block;overflow:hidden;position:relative;width:100%}.katex .stretchy:after,.katex .stretchy:before{content:""}.katex .hide-tail{overflow:hidden;position:relative;width:100%}.katex .halfarrow-left{left:0;overflow:hidden;position:absolute;width:50.2%}.katex .halfarrow-right{overflow:hidden;position:absolute;right:0;width:50.2%}.katex .brace-left{left:0;overflow:hidden;position:absolute;width:25.1%}.katex .brace-center{left:25%;overflow:hidden;position:absolute;width:50%}.katex .brace-right{overflow:hidden;position:absolute;right:0;width:25.1%}.katex .x-arrow-pad{padding:0 .5em}.katex .cd-arrow-pad{padding:0 .55556em 0 .27778em}.katex .mover,.katex .munder,.katex .x-arrow{text-align:center}.katex .boxpad{padding:0 .3em}.katex .fbox,.katex .fcolorbox{border:.04em solid;box-sizing:border-box}.katex .cancel-pad{padding:0 .2em}.katex .cancel-lap{margin-left:-.2em;margin-right:-.2em}.katex .sout{border-bottom-style:solid;border-bottom-width:.08em}.katex .angl{border-right:.049em solid;border-top:.049em solid;box-sizing:border-box;margin-right:.03889em}.katex .anglpad{padding:0 .03889em}.katex .eqn-num:before{content:"(" counter(katexEqnNo) ")";counter-increment:katexEqnNo}.katex .mml-eqn-num:before{content:"(" counter(mmlEqnNo) ")";counter-increment:mmlEqnNo}.katex .mtr-glue{width:50%}.katex .cd-vert-arrow{display:inline-block;position:relative}.katex .cd-label-left{display:inline-block;position:absolute;right:calc(50% + .3em);text-align:left}.katex .cd-label-right{display:inline-block;left:calc(50% + .3em);position:absolute;text-align:right}.katex-display{display:block;margin:1em 0;text-align:center}.katex-display>.katex{display:block;text-align:center;white-space:nowrap}.katex-display>.katex>.katex-html{display:block;position:relative}.katex-display>.katex>.katex-html>.tag{position:absolute;right:0}.katex-display.leqno>.katex>.katex-html>.tag{left:0;right:auto}.katex-display.fleqn>.katex{padding-left:2em;text-align:left}body{counter-reset:katexEqnNo mmlEqnNo}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "md2x",
3
- "version": "0.1.0",
3
+ "version": "0.2.1",
4
4
  "description": "Markdown → PDF/DOCX converter (local, no server). Supports Mermaid/Graphviz/Vega/HTML/SVG rendering, math, and code highlighting.",
5
5
  "type": "module",
6
6
  "private": false,