md2x 0.2.2 → 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +25 -1
- package/dist/index.mjs +555 -90
- package/dist/md2x.mjs +578 -104
- package/dist/renderer/puppeteer-render-worker.js +99 -94
- package/dist/types/node/src/host/node-exporter.d.ts +47 -10
- package/dist/types/node/src/index.d.ts +6 -3
- package/package.json +1 -1
package/dist/index.mjs
CHANGED
|
@@ -53070,10 +53070,10 @@ var init_lib4 = __esm({
|
|
|
53070
53070
|
* @returns {undefined}
|
|
53071
53071
|
* Nothing.
|
|
53072
53072
|
*/
|
|
53073
|
-
set basename(
|
|
53074
|
-
assertNonEmpty(
|
|
53075
|
-
assertPart(
|
|
53076
|
-
this.path = default2.join(this.dirname || "",
|
|
53073
|
+
set basename(basename2) {
|
|
53074
|
+
assertNonEmpty(basename2, "basename");
|
|
53075
|
+
assertPart(basename2, "basename");
|
|
53076
|
+
this.path = default2.join(this.dirname || "", basename2);
|
|
53077
53077
|
}
|
|
53078
53078
|
/**
|
|
53079
53079
|
* Get the parent path (example: `'~'`).
|
|
@@ -53119,18 +53119,18 @@ var init_lib4 = __esm({
|
|
|
53119
53119
|
* @returns {undefined}
|
|
53120
53120
|
* Nothing.
|
|
53121
53121
|
*/
|
|
53122
|
-
set extname(
|
|
53123
|
-
assertPart(
|
|
53122
|
+
set extname(extname2) {
|
|
53123
|
+
assertPart(extname2, "extname");
|
|
53124
53124
|
assertPath(this.dirname, "extname");
|
|
53125
|
-
if (
|
|
53126
|
-
if (
|
|
53125
|
+
if (extname2) {
|
|
53126
|
+
if (extname2.codePointAt(0) !== 46) {
|
|
53127
53127
|
throw new Error("`extname` must start with `.`");
|
|
53128
53128
|
}
|
|
53129
|
-
if (
|
|
53129
|
+
if (extname2.includes(".", 1)) {
|
|
53130
53130
|
throw new Error("`extname` cannot contain multiple dots");
|
|
53131
53131
|
}
|
|
53132
53132
|
}
|
|
53133
|
-
this.path = default2.join(this.dirname, this.stem + (
|
|
53133
|
+
this.path = default2.join(this.dirname, this.stem + (extname2 || ""));
|
|
53134
53134
|
}
|
|
53135
53135
|
/**
|
|
53136
53136
|
* Get the full path (example: `'~/index.min.js'`).
|
|
@@ -127486,6 +127486,7 @@ var init_theme_to_css = __esm({
|
|
|
127486
127486
|
var node_exporter_exports = {};
|
|
127487
127487
|
__export(node_exporter_exports, {
|
|
127488
127488
|
NodeDocxExporter: () => NodeDocxExporter,
|
|
127489
|
+
NodeHtmlExporter: () => NodeHtmlExporter,
|
|
127489
127490
|
NodePdfExporter: () => NodePdfExporter,
|
|
127490
127491
|
default: () => node_exporter_default
|
|
127491
127492
|
});
|
|
@@ -127524,6 +127525,94 @@ function createPluginRenderer(browserRenderer, basePath, themeConfig) {
|
|
|
127524
127525
|
}
|
|
127525
127526
|
};
|
|
127526
127527
|
}
|
|
127528
|
+
function escapeHtmlText(text9) {
|
|
127529
|
+
return String(text9).replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">").replace(/"/g, """).replace(/'/g, "'");
|
|
127530
|
+
}
|
|
127531
|
+
function decodeHtmlEntities3(text9) {
|
|
127532
|
+
return text9.replace(/</g, "<").replace(/>/g, ">").replace(/&/g, "&").replace(/"/g, '"').replace(/'/g, "'").replace(/'/g, "'").replace(///g, "/").replace(/</gi, "<").replace(/>/gi, ">").replace(/&/gi, "&").replace(/</g, "<").replace(/>/g, ">").replace(/&/g, "&");
|
|
127533
|
+
}
|
|
127534
|
+
async function processDiagrams(html7, browserRenderer, basePath, themeConfig, mode) {
|
|
127535
|
+
if (mode !== "img") return html7;
|
|
127536
|
+
if (!browserRenderer) return html7;
|
|
127537
|
+
const pluginLangs = plugins.filter((p3) => p3.nodeSelector.includes("code")).map((p3) => p3.language).filter((lang) => lang !== null);
|
|
127538
|
+
const aliases = ["graphviz", "gv", "vegalite"];
|
|
127539
|
+
const supportedLangs = [...pluginLangs, ...aliases].join("|");
|
|
127540
|
+
if (!supportedLangs) return html7;
|
|
127541
|
+
const codeBlockRegex = new RegExp(
|
|
127542
|
+
`<pre><code class="(?:hljs )?language-(${supportedLangs})">([\\s\\S]*?)<\\/code><\\/pre>`,
|
|
127543
|
+
"gi"
|
|
127544
|
+
);
|
|
127545
|
+
const matches = [...html7.matchAll(codeBlockRegex)];
|
|
127546
|
+
for (const match of matches) {
|
|
127547
|
+
const [fullMatch, lang, code4] = match;
|
|
127548
|
+
const decodedCode = decodeHtmlEntities3(code4);
|
|
127549
|
+
let renderType = lang.toLowerCase();
|
|
127550
|
+
if (renderType === "graphviz" || renderType === "gv") renderType = "dot";
|
|
127551
|
+
if (renderType === "vegalite") renderType = "vega-lite";
|
|
127552
|
+
try {
|
|
127553
|
+
const result = await browserRenderer.render(renderType, decodedCode, basePath, themeConfig);
|
|
127554
|
+
if (result && result.base64) {
|
|
127555
|
+
const imgTag = `<div class="md2x-diagram"><img class="md2x-diagram" src="data:image/${result.format};base64,${result.base64}" alt="${escapeHtmlText(
|
|
127556
|
+
`${lang} diagram`
|
|
127557
|
+
)}" style="max-width: 100%;" /></div>`;
|
|
127558
|
+
html7 = html7.replace(fullMatch, imgTag);
|
|
127559
|
+
}
|
|
127560
|
+
} catch (e) {
|
|
127561
|
+
console.warn(`Failed to render ${lang} diagram:`, e);
|
|
127562
|
+
}
|
|
127563
|
+
}
|
|
127564
|
+
return html7;
|
|
127565
|
+
}
|
|
127566
|
+
async function markdownToHtmlFragment(markdown2, browserRenderer, basePath, themeConfig, diagramMode) {
|
|
127567
|
+
const { unified: unified2 } = await Promise.resolve().then(() => (init_unified(), unified_exports));
|
|
127568
|
+
const remarkParse2 = (await Promise.resolve().then(() => (init_remark_parse(), remark_parse_exports))).default;
|
|
127569
|
+
const remarkGfm2 = (await Promise.resolve().then(() => (init_remark_gfm(), remark_gfm_exports))).default;
|
|
127570
|
+
const remarkMath2 = (await Promise.resolve().then(() => (init_remark_math(), remark_math_exports))).default;
|
|
127571
|
+
const remarkSuperSub2 = (await Promise.resolve().then(() => (init_remark_super_sub(), remark_super_sub_exports))).default;
|
|
127572
|
+
const remarkRehype2 = (await Promise.resolve().then(() => (init_remark_rehype(), remark_rehype_exports))).default;
|
|
127573
|
+
const rehypeKatex2 = (await Promise.resolve().then(() => (init_rehype_katex(), rehype_katex_exports))).default;
|
|
127574
|
+
const rehypeHighlight2 = (await Promise.resolve().then(() => (init_rehype_highlight(), rehype_highlight_exports))).default;
|
|
127575
|
+
const rehypeStringify2 = (await Promise.resolve().then(() => (init_rehype_stringify(), rehype_stringify_exports))).default;
|
|
127576
|
+
const { visit: visit2 } = await Promise.resolve().then(() => (init_unist_util_visit(), unist_util_visit_exports));
|
|
127577
|
+
function rehypeBlockImages() {
|
|
127578
|
+
return (tree) => {
|
|
127579
|
+
visit2(tree, "element", (node2) => {
|
|
127580
|
+
if (node2.tagName !== "p") return;
|
|
127581
|
+
const children = node2.children || [];
|
|
127582
|
+
if (children.length === 0) return;
|
|
127583
|
+
let imageCount = 0;
|
|
127584
|
+
let imageIndex = -1;
|
|
127585
|
+
let hasSubstantialTextAfterImage = false;
|
|
127586
|
+
let foundImage = false;
|
|
127587
|
+
for (let i = 0; i < children.length; i++) {
|
|
127588
|
+
const child = children[i];
|
|
127589
|
+
if (child.type === "element" && child.tagName === "img") {
|
|
127590
|
+
imageCount++;
|
|
127591
|
+
imageIndex = i;
|
|
127592
|
+
foundImage = true;
|
|
127593
|
+
} else if (foundImage) {
|
|
127594
|
+
if (child.type === "text" && child.value.trim() !== "") {
|
|
127595
|
+
hasSubstantialTextAfterImage = true;
|
|
127596
|
+
} else if (child.type === "element" && child.tagName !== "br") {
|
|
127597
|
+
hasSubstantialTextAfterImage = true;
|
|
127598
|
+
}
|
|
127599
|
+
}
|
|
127600
|
+
}
|
|
127601
|
+
if (imageCount === 1 && !hasSubstantialTextAfterImage && imageIndex >= 0) {
|
|
127602
|
+
const img = children[imageIndex];
|
|
127603
|
+
img.properties = img.properties || {};
|
|
127604
|
+
const existingClass = img.properties.className || [];
|
|
127605
|
+
img.properties.className = Array.isArray(existingClass) ? [...existingClass, "block-image"] : [existingClass, "block-image"];
|
|
127606
|
+
}
|
|
127607
|
+
});
|
|
127608
|
+
};
|
|
127609
|
+
}
|
|
127610
|
+
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 });
|
|
127611
|
+
const file = await processor.process(markdown2);
|
|
127612
|
+
let html7 = String(file);
|
|
127613
|
+
html7 = await processDiagrams(html7, browserRenderer, basePath, themeConfig, diagramMode);
|
|
127614
|
+
return html7;
|
|
127615
|
+
}
|
|
127527
127616
|
async function loadThemeCss(themeId) {
|
|
127528
127617
|
const platform = globalThis.platform;
|
|
127529
127618
|
const themeManager2 = (await Promise.resolve().then(() => (init_theme_manager(), theme_manager_exports))).default;
|
|
@@ -127725,6 +127814,31 @@ img {
|
|
|
127725
127814
|
page-break-inside: avoid;
|
|
127726
127815
|
}
|
|
127727
127816
|
|
|
127817
|
+
.md2x-diagram .md2x-diagram-inner {
|
|
127818
|
+
display: inline-block;
|
|
127819
|
+
max-width: 100%;
|
|
127820
|
+
text-align: left;
|
|
127821
|
+
}
|
|
127822
|
+
|
|
127823
|
+
.md2x-diagram .md2x-diagram-mount {
|
|
127824
|
+
display: inline-block;
|
|
127825
|
+
max-width: 100%;
|
|
127826
|
+
}
|
|
127827
|
+
|
|
127828
|
+
.md2x-diagram .vega-embed {
|
|
127829
|
+
display: inline-block;
|
|
127830
|
+
max-width: 100%;
|
|
127831
|
+
width: auto !important;
|
|
127832
|
+
}
|
|
127833
|
+
|
|
127834
|
+
.md2x-diagram .md2x-diagram-inner svg,
|
|
127835
|
+
.md2x-diagram .md2x-diagram-inner > svg {
|
|
127836
|
+
display: block;
|
|
127837
|
+
margin-left: auto;
|
|
127838
|
+
margin-right: auto;
|
|
127839
|
+
max-width: 100%;
|
|
127840
|
+
}
|
|
127841
|
+
|
|
127728
127842
|
.md2x-diagram img,
|
|
127729
127843
|
img.md2x-diagram {
|
|
127730
127844
|
display: block;
|
|
@@ -127877,7 +127991,7 @@ function loadKatexCss() {
|
|
|
127877
127991
|
css2 = css2.replace(/url\((['"]?)(?:\.\/)?fonts\//g, `url($1${katexFontsHref}`);
|
|
127878
127992
|
return css2;
|
|
127879
127993
|
}
|
|
127880
|
-
var NodeDocxExporter, NodePdfExporter, node_exporter_default;
|
|
127994
|
+
var NodeDocxExporter, NodePdfExporter, NodeHtmlExporter, node_exporter_default;
|
|
127881
127995
|
var init_node_exporter = __esm({
|
|
127882
127996
|
"src/host/node-exporter.ts"() {
|
|
127883
127997
|
"use strict";
|
|
@@ -128002,7 +128116,7 @@ var init_node_exporter = __esm({
|
|
|
128002
128116
|
}
|
|
128003
128117
|
await browserRenderer.initialize();
|
|
128004
128118
|
const themeConfig = await loadRendererThemeConfig(themeId);
|
|
128005
|
-
const html7 = await
|
|
128119
|
+
const html7 = await markdownToHtmlFragment(markdown2, browserRenderer, basePath, themeConfig, "img");
|
|
128006
128120
|
let katexCss = "";
|
|
128007
128121
|
try {
|
|
128008
128122
|
katexCss = loadKatexCss();
|
|
@@ -128045,94 +128159,426 @@ var init_node_exporter = __esm({
|
|
|
128045
128159
|
}
|
|
128046
128160
|
fs3.writeFileSync(outputPath, buffer2);
|
|
128047
128161
|
}
|
|
128162
|
+
};
|
|
128163
|
+
NodeHtmlExporter = class {
|
|
128048
128164
|
/**
|
|
128049
|
-
*
|
|
128165
|
+
* Export markdown to standalone HTML string (default) or HTML fragment.
|
|
128050
128166
|
*/
|
|
128051
|
-
async
|
|
128052
|
-
|
|
128053
|
-
const
|
|
128054
|
-
const
|
|
128055
|
-
const
|
|
128056
|
-
const
|
|
128057
|
-
const
|
|
128058
|
-
|
|
128059
|
-
|
|
128060
|
-
|
|
128061
|
-
|
|
128062
|
-
|
|
128063
|
-
|
|
128064
|
-
|
|
128065
|
-
|
|
128066
|
-
|
|
128067
|
-
|
|
128068
|
-
|
|
128069
|
-
|
|
128070
|
-
|
|
128071
|
-
|
|
128072
|
-
|
|
128073
|
-
|
|
128074
|
-
|
|
128075
|
-
|
|
128076
|
-
|
|
128077
|
-
|
|
128078
|
-
|
|
128079
|
-
|
|
128080
|
-
|
|
128081
|
-
|
|
128082
|
-
|
|
128083
|
-
|
|
128084
|
-
|
|
128085
|
-
|
|
128086
|
-
|
|
128087
|
-
|
|
128088
|
-
|
|
128089
|
-
|
|
128090
|
-
|
|
128091
|
-
|
|
128092
|
-
|
|
128167
|
+
async exportToString(markdown2, options = {}) {
|
|
128168
|
+
ensureBase64Globals();
|
|
128169
|
+
const themeId = options.theme || "default";
|
|
128170
|
+
const basePath = options.basePath || process.cwd();
|
|
128171
|
+
const moduleDir = path5.dirname(fileURLToPath3(import.meta.url));
|
|
128172
|
+
const diagramMode = options.diagramMode || "live";
|
|
128173
|
+
const { platform } = createNodePlatform({
|
|
128174
|
+
moduleDir,
|
|
128175
|
+
selectedThemeId: themeId,
|
|
128176
|
+
output: { kind: "buffer" }
|
|
128177
|
+
});
|
|
128178
|
+
const previousPlatform = globalThis.platform;
|
|
128179
|
+
globalThis.platform = platform;
|
|
128180
|
+
let browserRenderer = null;
|
|
128181
|
+
try {
|
|
128182
|
+
const themeConfig = await loadRendererThemeConfig(themeId);
|
|
128183
|
+
if (diagramMode === "img") {
|
|
128184
|
+
browserRenderer = await createBrowserRenderer();
|
|
128185
|
+
if (browserRenderer) {
|
|
128186
|
+
await browserRenderer.initialize();
|
|
128187
|
+
}
|
|
128188
|
+
}
|
|
128189
|
+
const fragment = await markdownToHtmlFragment(markdown2, browserRenderer, basePath, themeConfig, diagramMode);
|
|
128190
|
+
const standalone = options.standalone !== false;
|
|
128191
|
+
if (!standalone) return fragment;
|
|
128192
|
+
let katexCss = "";
|
|
128193
|
+
try {
|
|
128194
|
+
katexCss = loadKatexCss();
|
|
128195
|
+
} catch (e) {
|
|
128196
|
+
console.warn("Failed to load KaTeX CSS for HTML export:", e);
|
|
128197
|
+
}
|
|
128198
|
+
const baseCss = await loadBaseCss(options.htmlHrAsPageBreak ?? false);
|
|
128199
|
+
let themeCss = "";
|
|
128200
|
+
try {
|
|
128201
|
+
themeCss = await loadThemeCss(themeId);
|
|
128202
|
+
} catch (e) {
|
|
128203
|
+
console.warn("Failed to load theme CSS for HTML export, using base styles only:", e);
|
|
128204
|
+
}
|
|
128205
|
+
const css2 = katexCss + "\n" + baseCss + "\n" + themeCss;
|
|
128206
|
+
const title = options.title || "Document";
|
|
128207
|
+
const shouldEmitBase = options.baseTag !== false && !!basePath;
|
|
128208
|
+
const baseHref = shouldEmitBase ? pathToFileURL3(basePath + path5.sep).href : "";
|
|
128209
|
+
const baseTag = baseHref ? ` <base href="${escapeHtmlText(baseHref)}" />
|
|
128210
|
+
` : "";
|
|
128211
|
+
const cdnBaseDefaults = {
|
|
128212
|
+
mermaid: "https://cdn.jsdelivr.net/npm/mermaid@11.12.2/dist/mermaid.min.js",
|
|
128213
|
+
// Preferred: modern Graphviz WASM build (provides window.Viz.instance()).
|
|
128214
|
+
vizGlobal: "https://cdn.jsdelivr.net/npm/@viz-js/viz@3.24.0/dist/viz-global.js",
|
|
128215
|
+
// Legacy fallback (provides window.Viz constructor).
|
|
128216
|
+
viz: "https://cdn.jsdelivr.net/npm/viz.js@2.1.2/viz.js",
|
|
128217
|
+
vizRender: "https://cdn.jsdelivr.net/npm/viz.js@2.1.2/full.render.js",
|
|
128218
|
+
infographic: "https://cdn.jsdelivr.net/npm/@antv/infographic@0.2.7/dist/infographic.min.js"
|
|
128219
|
+
};
|
|
128220
|
+
const cdnVegaDefaultsByMajor = {
|
|
128221
|
+
// Vega-Lite v5 is typically used with Vega v5 + Vega-Embed v6.
|
|
128222
|
+
5: {
|
|
128223
|
+
vega: "https://cdn.jsdelivr.net/npm/vega@5/build/vega.min.js",
|
|
128224
|
+
vegaLite: "https://cdn.jsdelivr.net/npm/vega-lite@5/build/vega-lite.min.js",
|
|
128225
|
+
vegaEmbed: "https://cdn.jsdelivr.net/npm/vega-embed@6/build/vega-embed.min.js"
|
|
128226
|
+
},
|
|
128227
|
+
// Vega-Lite v6 is typically used with Vega v6 + Vega-Embed v7.
|
|
128228
|
+
6: {
|
|
128229
|
+
vega: "https://cdn.jsdelivr.net/npm/vega@6/build/vega.min.js",
|
|
128230
|
+
vegaLite: "https://cdn.jsdelivr.net/npm/vega-lite@6/build/vega-lite.min.js",
|
|
128231
|
+
vegaEmbed: "https://cdn.jsdelivr.net/npm/vega-embed@7/build/vega-embed.min.js"
|
|
128232
|
+
}
|
|
128093
128233
|
};
|
|
128234
|
+
const cdnOverrides = options.cdn ?? {};
|
|
128235
|
+
const liveBootstrap = diagramMode !== "live" ? "" : `
|
|
128236
|
+
<!-- md2x live diagram renderer (CDN) -->
|
|
128237
|
+
<script>
|
|
128238
|
+
(function () {
|
|
128239
|
+
const themeConfig = ${JSON.stringify(themeConfig ?? null)};
|
|
128240
|
+
const baseHref = ${JSON.stringify(baseHref)};
|
|
128241
|
+
const cdnOverrides = ${JSON.stringify(cdnOverrides)};
|
|
128242
|
+
const cdnBaseDefaults = ${JSON.stringify(cdnBaseDefaults)};
|
|
128243
|
+
const cdnVegaDefaultsByMajor = ${JSON.stringify(cdnVegaDefaultsByMajor)};
|
|
128244
|
+
|
|
128245
|
+
function loadScript(src) {
|
|
128246
|
+
return new Promise((resolve, reject) => {
|
|
128247
|
+
const s = document.createElement('script');
|
|
128248
|
+
s.src = src;
|
|
128249
|
+
s.async = false;
|
|
128250
|
+
s.onload = () => resolve();
|
|
128251
|
+
s.onerror = () => reject(new Error('Failed to load script: ' + src));
|
|
128252
|
+
document.head.appendChild(s);
|
|
128253
|
+
});
|
|
128254
|
+
}
|
|
128255
|
+
|
|
128256
|
+
function getLangFromCodeClass(codeEl) {
|
|
128257
|
+
const cls = (codeEl && codeEl.className) ? String(codeEl.className) : '';
|
|
128258
|
+
const m = cls.match(/\\blanguage-([a-z0-9-]+)\\b/i);
|
|
128259
|
+
return m ? m[1] : '';
|
|
128260
|
+
}
|
|
128261
|
+
|
|
128262
|
+
function normalizeLang(lang) {
|
|
128263
|
+
const l = String(lang || '').toLowerCase();
|
|
128264
|
+
if (l === 'graphviz' || l === 'gv') return 'dot';
|
|
128265
|
+
if (l === 'vegalite') return 'vega-lite';
|
|
128266
|
+
return l;
|
|
128267
|
+
}
|
|
128268
|
+
|
|
128269
|
+
function guessVegaLiteSchemaMajorFromSpec(spec) {
|
|
128270
|
+
if (!spec || typeof spec !== 'object') return null;
|
|
128271
|
+
const schema = spec.$schema;
|
|
128272
|
+
if (typeof schema !== 'string') return null;
|
|
128273
|
+
const m = schema.match(/\\/vega-lite\\/v(\\d+)(?:\\.|\\.json|$)/i) || schema.match(/\\/v(\\d+)\\.json$/i);
|
|
128274
|
+
if (!m) return null;
|
|
128275
|
+
const major = parseInt(m[1], 10);
|
|
128276
|
+
return Number.isFinite(major) ? major : null;
|
|
128277
|
+
}
|
|
128278
|
+
|
|
128279
|
+
function guessVegaLiteSchemaMajorFromText(text) {
|
|
128280
|
+
const t = String(text || '');
|
|
128281
|
+
const m = t.match(/\\/vega-lite\\/v(\\d+)(?:\\.|\\.json|$)/i) || t.match(/\\/v(\\d+)\\.json$/i);
|
|
128282
|
+
if (!m) return null;
|
|
128283
|
+
const major = parseInt(m[1], 10);
|
|
128284
|
+
return Number.isFinite(major) ? major : null;
|
|
128285
|
+
}
|
|
128286
|
+
|
|
128287
|
+
function detectVegaLiteMajorFromDocument() {
|
|
128288
|
+
// Scan vega-lite blocks and pick a major version based on $schema.
|
|
128289
|
+
const blocks = Array.from(document.querySelectorAll('pre > code'));
|
|
128290
|
+
let detected = null;
|
|
128291
|
+
for (const codeEl of blocks) {
|
|
128292
|
+
const langRaw = getLangFromCodeClass(codeEl);
|
|
128293
|
+
const lang = normalizeLang(langRaw);
|
|
128294
|
+
if (lang !== 'vega-lite') continue;
|
|
128295
|
+
|
|
128296
|
+
const text = (codeEl && codeEl.textContent) ? codeEl.textContent : '';
|
|
128297
|
+
if (!text.trim()) continue;
|
|
128298
|
+
|
|
128299
|
+
// Prefer a regex scan first so we can still detect schema versions for
|
|
128300
|
+
// code blocks that aren't strictly valid JSON (e.g. trailing commas).
|
|
128301
|
+
const majorFromText = guessVegaLiteSchemaMajorFromText(text);
|
|
128302
|
+
if (majorFromText && (majorFromText === 5 || majorFromText === 6)) {
|
|
128303
|
+
detected = majorFromText;
|
|
128304
|
+
if (majorFromText === 6) return 6;
|
|
128305
|
+
continue;
|
|
128306
|
+
}
|
|
128307
|
+
|
|
128308
|
+
try {
|
|
128309
|
+
const spec = JSON.parse(text);
|
|
128310
|
+
const major = guessVegaLiteSchemaMajorFromSpec(spec);
|
|
128311
|
+
if (major && (major === 5 || major === 6)) {
|
|
128312
|
+
detected = major;
|
|
128313
|
+
// If any block is v6, prefer v6. Otherwise keep v5.
|
|
128314
|
+
if (major === 6) return 6;
|
|
128315
|
+
}
|
|
128316
|
+
} catch {
|
|
128317
|
+
// ignore parse errors
|
|
128094
128318
|
}
|
|
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 });
|
|
128096
|
-
const file = await processor.process(markdown2);
|
|
128097
|
-
let html7 = String(file);
|
|
128098
|
-
html7 = await this.processDiagrams(html7, browserRenderer, basePath, themeConfig);
|
|
128099
|
-
return html7;
|
|
128100
128319
|
}
|
|
128101
|
-
|
|
128102
|
-
|
|
128103
|
-
|
|
128104
|
-
|
|
128105
|
-
|
|
128106
|
-
|
|
128107
|
-
|
|
128108
|
-
|
|
128109
|
-
|
|
128110
|
-
|
|
128111
|
-
|
|
128112
|
-
|
|
128113
|
-
|
|
128114
|
-
|
|
128115
|
-
|
|
128116
|
-
|
|
128117
|
-
|
|
128118
|
-
|
|
128320
|
+
return detected || 6;
|
|
128321
|
+
}
|
|
128322
|
+
|
|
128323
|
+
async function ensureCdnLibsLoaded() {
|
|
128324
|
+
const major = detectVegaLiteMajorFromDocument();
|
|
128325
|
+
const vegaDefaults = cdnVegaDefaultsByMajor[String(major)] || cdnVegaDefaultsByMajor['6'];
|
|
128326
|
+
const cdn = Object.assign({}, cdnBaseDefaults, vegaDefaults, cdnOverrides || {});
|
|
128327
|
+
|
|
128328
|
+
// Load order matters.
|
|
128329
|
+
await loadScript(cdn.mermaid);
|
|
128330
|
+
if (cdn.vizGlobal) {
|
|
128331
|
+
await loadScript(cdn.vizGlobal);
|
|
128332
|
+
} else {
|
|
128333
|
+
await loadScript(cdn.viz);
|
|
128334
|
+
await loadScript(cdn.vizRender);
|
|
128335
|
+
}
|
|
128336
|
+
await loadScript(cdn.vega);
|
|
128337
|
+
await loadScript(cdn.vegaLite);
|
|
128338
|
+
await loadScript(cdn.vegaEmbed);
|
|
128339
|
+
await loadScript(cdn.infographic);
|
|
128340
|
+
}
|
|
128341
|
+
|
|
128342
|
+
function replacePreWithContainer(preEl, kind) {
|
|
128343
|
+
const wrapper = document.createElement('div');
|
|
128344
|
+
wrapper.className = 'md2x-diagram';
|
|
128345
|
+
wrapper.setAttribute('data-md2x-diagram-kind', kind);
|
|
128346
|
+
wrapper.style.maxWidth = '100%';
|
|
128347
|
+
const inner = document.createElement('div');
|
|
128348
|
+
inner.className = 'md2x-diagram-inner';
|
|
128349
|
+
inner.style.display = 'inline-block';
|
|
128350
|
+
inner.style.maxWidth = '100%';
|
|
128351
|
+
const mount = document.createElement('div');
|
|
128352
|
+
mount.className = 'md2x-diagram-mount';
|
|
128353
|
+
mount.style.maxWidth = '100%';
|
|
128354
|
+
inner.appendChild(mount);
|
|
128355
|
+
wrapper.appendChild(inner);
|
|
128356
|
+
preEl.replaceWith(wrapper);
|
|
128357
|
+
return mount;
|
|
128358
|
+
}
|
|
128359
|
+
|
|
128360
|
+
function getText(codeEl) {
|
|
128361
|
+
return (codeEl && codeEl.textContent) ? codeEl.textContent : '';
|
|
128362
|
+
}
|
|
128363
|
+
|
|
128364
|
+
async function renderMermaid(code, mount, id) {
|
|
128365
|
+
const mermaid = window.mermaid;
|
|
128366
|
+
if (!mermaid) return;
|
|
128367
|
+
mermaid.initialize({
|
|
128368
|
+
startOnLoad: false,
|
|
128369
|
+
theme: 'default',
|
|
128370
|
+
securityLevel: 'loose',
|
|
128371
|
+
fontFamily: themeConfig && themeConfig.fontFamily ? themeConfig.fontFamily : undefined,
|
|
128372
|
+
});
|
|
128373
|
+
const out = await mermaid.render('md2x-mermaid-' + id, code);
|
|
128374
|
+
mount.innerHTML = out && out.svg ? out.svg : '';
|
|
128375
|
+
}
|
|
128376
|
+
|
|
128377
|
+
async function renderDot(code, mount) {
|
|
128378
|
+
const VizGlobal = window.Viz;
|
|
128379
|
+
// Preferred: @viz-js/viz global build
|
|
128380
|
+
if (VizGlobal && typeof VizGlobal.instance === 'function') {
|
|
128381
|
+
const viz = await VizGlobal.instance();
|
|
128382
|
+
const svgEl = viz.renderSVGElement(code, { graphAttributes: { bgcolor: 'transparent' } });
|
|
128383
|
+
mount.appendChild(svgEl);
|
|
128384
|
+
return;
|
|
128385
|
+
}
|
|
128386
|
+
|
|
128387
|
+
// Legacy: viz.js
|
|
128388
|
+
if (typeof window.Viz === 'function') {
|
|
128389
|
+
const viz = new window.Viz();
|
|
128390
|
+
const svgEl = await viz.renderSVGElement(code);
|
|
128391
|
+
mount.appendChild(svgEl);
|
|
128392
|
+
}
|
|
128393
|
+
}
|
|
128394
|
+
|
|
128395
|
+
function applyDefaultVegaLiteSort(spec) {
|
|
128396
|
+
// If users mark a field as ordinal, a common expectation is "use the data order"
|
|
128397
|
+
// (e.g. '1\u6708'...'12\u6708'). Vega-Lite defaults to sorting discrete domains, which can
|
|
128398
|
+
// produce surprising orders for stringified numbers. We only change behavior
|
|
128399
|
+
// when the author hasn't specified an explicit sort.
|
|
128400
|
+
const applyOne = (s) => {
|
|
128401
|
+
if (!s || typeof s !== 'object') return;
|
|
128402
|
+
const enc = s.encoding;
|
|
128403
|
+
const x = enc && enc.x;
|
|
128404
|
+
if (x && typeof x === 'object' && x.type === 'ordinal' && !('sort' in x)) {
|
|
128405
|
+
x.sort = null;
|
|
128406
|
+
}
|
|
128407
|
+
};
|
|
128408
|
+
|
|
128409
|
+
const walk = (s) => {
|
|
128410
|
+
if (!s || typeof s !== 'object') return;
|
|
128411
|
+
applyOne(s);
|
|
128412
|
+
|
|
128413
|
+
const arrays = ['layer', 'hconcat', 'vconcat', 'concat'];
|
|
128414
|
+
for (const key of arrays) {
|
|
128415
|
+
const childArr = s[key];
|
|
128416
|
+
if (Array.isArray(childArr)) {
|
|
128417
|
+
for (const child of childArr) walk(child);
|
|
128418
|
+
}
|
|
128419
|
+
}
|
|
128420
|
+
if (s.spec) walk(s.spec);
|
|
128421
|
+
};
|
|
128422
|
+
|
|
128423
|
+
walk(spec);
|
|
128424
|
+
}
|
|
128425
|
+
|
|
128426
|
+
async function renderVegaLite(code, mount) {
|
|
128427
|
+
const vegaEmbed = window.vegaEmbed;
|
|
128428
|
+
if (typeof vegaEmbed !== 'function') return;
|
|
128429
|
+
let spec;
|
|
128430
|
+
try {
|
|
128431
|
+
spec = JSON.parse(code);
|
|
128432
|
+
} catch {
|
|
128433
|
+
mount.textContent = 'Invalid Vega-Lite JSON.';
|
|
128434
|
+
return;
|
|
128435
|
+
}
|
|
128436
|
+
applyDefaultVegaLiteSort(spec);
|
|
128437
|
+
await vegaEmbed(mount, spec, {
|
|
128438
|
+
actions: false,
|
|
128439
|
+
renderer: 'svg',
|
|
128440
|
+
defaultStyle: true,
|
|
128441
|
+
logLevel: (window.vega && window.vega.Warn) ? window.vega.Warn : undefined,
|
|
128442
|
+
});
|
|
128443
|
+
}
|
|
128444
|
+
|
|
128445
|
+
async function renderInfographic(code, mount) {
|
|
128446
|
+
const lib = window.AntVInfographic;
|
|
128447
|
+
if (!lib || !lib.Infographic) return;
|
|
128448
|
+
|
|
128449
|
+
try {
|
|
128450
|
+
if (typeof lib.setDefaultFont === 'function') {
|
|
128451
|
+
const ff = themeConfig && themeConfig.fontFamily ? themeConfig.fontFamily : undefined;
|
|
128452
|
+
if (ff) lib.setDefaultFont(ff);
|
|
128453
|
+
}
|
|
128454
|
+
} catch {}
|
|
128455
|
+
|
|
128456
|
+
const opts = {
|
|
128457
|
+
container: mount,
|
|
128458
|
+
width: 900,
|
|
128459
|
+
height: 600,
|
|
128460
|
+
padding: 24,
|
|
128461
|
+
};
|
|
128462
|
+
|
|
128463
|
+
if (themeConfig && themeConfig.diagramStyle === 'handDrawn') {
|
|
128464
|
+
opts.themeConfig = { stylize: { type: 'rough', roughness: 0.5, bowing: 0.5 } };
|
|
128465
|
+
}
|
|
128466
|
+
|
|
128467
|
+
const ig = new lib.Infographic(opts);
|
|
128468
|
+
await new Promise((resolve, reject) => {
|
|
128469
|
+
const timeout = setTimeout(() => reject(new Error('Infographic render timeout after 10s')), 10000);
|
|
128470
|
+
ig.on && ig.on('rendered', () => { clearTimeout(timeout); resolve(); });
|
|
128471
|
+
ig.on && ig.on('error', (err) => { clearTimeout(timeout); reject(err); });
|
|
128472
|
+
try {
|
|
128473
|
+
ig.render(code);
|
|
128474
|
+
} catch (e) {
|
|
128475
|
+
clearTimeout(timeout);
|
|
128476
|
+
reject(e);
|
|
128477
|
+
}
|
|
128478
|
+
}).catch(() => {
|
|
128479
|
+
// keep container content on errors
|
|
128480
|
+
});
|
|
128481
|
+
}
|
|
128482
|
+
|
|
128483
|
+
async function main() {
|
|
128484
|
+
// Best-effort base href: some renderers may load assets relative to document.
|
|
128485
|
+
try {
|
|
128486
|
+
if (baseHref) {
|
|
128487
|
+
let base = document.querySelector('base');
|
|
128488
|
+
if (!base) {
|
|
128489
|
+
base = document.createElement('base');
|
|
128490
|
+
document.head.appendChild(base);
|
|
128491
|
+
}
|
|
128492
|
+
base.href = baseHref;
|
|
128493
|
+
}
|
|
128494
|
+
} catch {}
|
|
128495
|
+
|
|
128496
|
+
try {
|
|
128497
|
+
await ensureCdnLibsLoaded();
|
|
128498
|
+
} catch (e) {
|
|
128499
|
+
// If CDN scripts fail to load, keep code blocks as-is.
|
|
128500
|
+
return;
|
|
128501
|
+
}
|
|
128502
|
+
|
|
128503
|
+
const blocks = Array.from(document.querySelectorAll('pre > code'));
|
|
128504
|
+
let idx = 0;
|
|
128505
|
+
for (const codeEl of blocks) {
|
|
128506
|
+
const pre = codeEl && codeEl.parentElement;
|
|
128507
|
+
if (!pre) continue;
|
|
128508
|
+
const langRaw = getLangFromCodeClass(codeEl);
|
|
128509
|
+
if (!langRaw) continue;
|
|
128510
|
+
const lang = normalizeLang(langRaw);
|
|
128511
|
+
const code = getText(codeEl);
|
|
128512
|
+
if (!code.trim()) continue;
|
|
128513
|
+
|
|
128514
|
+
try {
|
|
128515
|
+
if (lang === 'mermaid') {
|
|
128516
|
+
const mount = replacePreWithContainer(pre, 'mermaid');
|
|
128517
|
+
await renderMermaid(code, mount, idx++);
|
|
128518
|
+
} else if (lang === 'dot') {
|
|
128519
|
+
const mount = replacePreWithContainer(pre, 'dot');
|
|
128520
|
+
await renderDot(code, mount);
|
|
128521
|
+
} else if (lang === 'vega-lite') {
|
|
128522
|
+
const mount = replacePreWithContainer(pre, 'vega-lite');
|
|
128523
|
+
await renderVegaLite(code, mount);
|
|
128524
|
+
} else if (lang === 'infographic') {
|
|
128525
|
+
const mount = replacePreWithContainer(pre, 'infographic');
|
|
128526
|
+
await renderInfographic(code, mount);
|
|
128527
|
+
}
|
|
128528
|
+
} catch {
|
|
128529
|
+
// Keep original code block on error
|
|
128530
|
+
}
|
|
128531
|
+
}
|
|
128532
|
+
}
|
|
128533
|
+
|
|
128534
|
+
if (document.readyState === 'loading') {
|
|
128535
|
+
document.addEventListener('DOMContentLoaded', () => { main(); }, { once: true });
|
|
128536
|
+
} else {
|
|
128537
|
+
main();
|
|
128538
|
+
}
|
|
128539
|
+
})();
|
|
128540
|
+
</script>`;
|
|
128541
|
+
return `<!DOCTYPE html>
|
|
128542
|
+
<html lang="en">
|
|
128543
|
+
<head>
|
|
128544
|
+
<meta charset="UTF-8" />
|
|
128545
|
+
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
|
128546
|
+
${baseTag} <title>${escapeHtmlText(title)}</title>
|
|
128547
|
+
<style>${css2}</style>
|
|
128548
|
+
</head>
|
|
128549
|
+
<body>
|
|
128550
|
+
<div id="markdown-content" class="markdown-body">${fragment}</div>
|
|
128551
|
+
${liveBootstrap}
|
|
128552
|
+
</body>
|
|
128553
|
+
</html>`;
|
|
128554
|
+
} finally {
|
|
128119
128555
|
try {
|
|
128120
|
-
|
|
128121
|
-
|
|
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>`;
|
|
128123
|
-
html7 = html7.replace(fullMatch, imgTag);
|
|
128556
|
+
if (browserRenderer) {
|
|
128557
|
+
await browserRenderer.close();
|
|
128124
128558
|
}
|
|
128125
|
-
}
|
|
128126
|
-
|
|
128559
|
+
} finally {
|
|
128560
|
+
globalThis.platform = previousPlatform;
|
|
128127
128561
|
}
|
|
128128
128562
|
}
|
|
128129
|
-
return html7;
|
|
128130
128563
|
}
|
|
128131
|
-
|
|
128132
|
-
|
|
128133
|
-
|
|
128134
|
-
|
|
128135
|
-
|
|
128564
|
+
async exportToBuffer(markdown2, options = {}) {
|
|
128565
|
+
const html7 = await this.exportToString(markdown2, options);
|
|
128566
|
+
return Buffer.from(html7, "utf8");
|
|
128567
|
+
}
|
|
128568
|
+
async exportToFile(inputPath, outputPath, options = {}) {
|
|
128569
|
+
const markdown2 = fs3.readFileSync(inputPath, "utf-8");
|
|
128570
|
+
const basePath = options.basePath || path5.dirname(path5.resolve(inputPath));
|
|
128571
|
+
const title = options.title || path5.basename(inputPath, path5.extname(inputPath));
|
|
128572
|
+
const outputDir = path5.dirname(outputPath);
|
|
128573
|
+
if (!fs3.existsSync(outputDir)) {
|
|
128574
|
+
fs3.mkdirSync(outputDir, { recursive: true });
|
|
128575
|
+
}
|
|
128576
|
+
const html7 = await this.exportToString(markdown2, {
|
|
128577
|
+
...options,
|
|
128578
|
+
basePath,
|
|
128579
|
+
title
|
|
128580
|
+
});
|
|
128581
|
+
fs3.writeFileSync(outputPath, html7, "utf8");
|
|
128136
128582
|
}
|
|
128137
128583
|
};
|
|
128138
128584
|
node_exporter_default = NodeDocxExporter;
|
|
@@ -128156,17 +128602,36 @@ async function markdownToPdfBuffer(markdown2, options = {}) {
|
|
|
128156
128602
|
const exporter = new NodePdfExporter2();
|
|
128157
128603
|
return exporter.exportToBuffer(markdown2, options);
|
|
128158
128604
|
}
|
|
128605
|
+
async function markdownToHtmlString(markdown2, options = {}) {
|
|
128606
|
+
const { NodeHtmlExporter: NodeHtmlExporter2 } = await Promise.resolve().then(() => (init_node_exporter(), node_exporter_exports));
|
|
128607
|
+
const exporter = new NodeHtmlExporter2();
|
|
128608
|
+
return exporter.exportToString(markdown2, options);
|
|
128609
|
+
}
|
|
128610
|
+
async function markdownToHtmlBuffer(markdown2, options = {}) {
|
|
128611
|
+
const { NodeHtmlExporter: NodeHtmlExporter2 } = await Promise.resolve().then(() => (init_node_exporter(), node_exporter_exports));
|
|
128612
|
+
const exporter = new NodeHtmlExporter2();
|
|
128613
|
+
return exporter.exportToBuffer(markdown2, options);
|
|
128614
|
+
}
|
|
128159
128615
|
async function markdownFileToPdfFile(inputPath, outputPath, options = {}) {
|
|
128160
128616
|
const { NodePdfExporter: NodePdfExporter2 } = await Promise.resolve().then(() => (init_node_exporter(), node_exporter_exports));
|
|
128161
128617
|
const exporter = new NodePdfExporter2();
|
|
128162
128618
|
return exporter.exportToFile(inputPath, outputPath, options);
|
|
128163
128619
|
}
|
|
128620
|
+
async function markdownFileToHtmlFile(inputPath, outputPath, options = {}) {
|
|
128621
|
+
const { NodeHtmlExporter: NodeHtmlExporter2 } = await Promise.resolve().then(() => (init_node_exporter(), node_exporter_exports));
|
|
128622
|
+
const exporter = new NodeHtmlExporter2();
|
|
128623
|
+
return exporter.exportToFile(inputPath, outputPath, options);
|
|
128624
|
+
}
|
|
128164
128625
|
export {
|
|
128165
128626
|
NodeDocxExporter,
|
|
128627
|
+
NodeHtmlExporter,
|
|
128166
128628
|
NodePdfExporter,
|
|
128167
128629
|
markdownFileToDocxFile,
|
|
128630
|
+
markdownFileToHtmlFile,
|
|
128168
128631
|
markdownFileToPdfFile,
|
|
128169
128632
|
markdownToDocxBuffer,
|
|
128633
|
+
markdownToHtmlBuffer,
|
|
128634
|
+
markdownToHtmlString,
|
|
128170
128635
|
markdownToPdfBuffer
|
|
128171
128636
|
};
|
|
128172
128637
|
/*! Bundled license information:
|