@helping-ai-workflow/md2doc 3.16.1 → 3.17.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/lib/editor/client.js +2459 -106
- package/lib/editor/code-edit.js +184 -0
- package/lib/editor/icons.js +3 -0
- package/lib/editor/inline-md.js +105 -1
- package/lib/editor/server.js +30 -2
- package/lib/highlight.js +46 -5
- package/lib/md2doc.js +189 -39
- package/lib/theme/runtime.js +33 -2
- package/package.json +2 -2
package/lib/md2doc.js
CHANGED
|
@@ -1993,6 +1993,48 @@ ${edUlMarkerCss}${edOlCounterCss}
|
|
|
1993
1993
|
color: var(--md-strong); cursor: pointer; box-shadow: 0 1px 3px var(--md-ed-shadow);
|
|
1994
1994
|
}
|
|
1995
1995
|
.ed-wave-edit-btn:hover { background: var(--md-ed-surface); border-color: var(--md-border); }
|
|
1996
|
+
.ed-diagram-edit-btn {
|
|
1997
|
+
position: fixed; z-index: 12; padding: 3px 10px; font-size: 12px;
|
|
1998
|
+
display: inline-flex; align-items: center; gap: 4px;
|
|
1999
|
+
border: 1px solid var(--md-border); border-radius: 4px; background: var(--md-ed-surface);
|
|
2000
|
+
color: var(--md-strong); cursor: pointer; box-shadow: 0 1px 3px var(--md-ed-shadow);
|
|
2001
|
+
}
|
|
2002
|
+
.ed-diagram-edit-btn[hidden] { display: none; }
|
|
2003
|
+
.ed-diagram-edit-btn:hover { background: var(--md-ed-surface); border-color: var(--md-border); }
|
|
2004
|
+
.ed-diagram-edit-btn svg { flex: 0 0 auto; width: 14px; height: 14px; margin: 0; }
|
|
2005
|
+
/* v3.17.0 T5: the diagram panel (openDiagramPanel() in the client runtime).
|
|
2006
|
+
It replaces the block's content in place, inside the block, like the raw
|
|
2007
|
+
box: a 2px accent frame, the header (language, the muted hint, the done
|
|
2008
|
+
button), the source (monospace on the field colour, 50vh at most, then it
|
|
2009
|
+
scrolls), the preview (60vh at most, scrolls both ways) and one message
|
|
2010
|
+
line. A preview kept after an error, or after an answer with nothing to
|
|
2011
|
+
draw, is dimmed (.is-stale). No backticks in this comment: it lives
|
|
2012
|
+
inside a JS template literal. */
|
|
2013
|
+
.ed-diagram-panel {
|
|
2014
|
+
border: 2px solid var(--md-accent); border-radius: 6px; padding: 8px;
|
|
2015
|
+
background: var(--md-ed-surface); color: var(--md-strong);
|
|
2016
|
+
}
|
|
2017
|
+
.ed-diagram-head { display: flex; align-items: center; gap: 8px; margin: 0 0 6px; font-size: 13px; }
|
|
2018
|
+
.ed-diagram-lang { font-weight: 600; }
|
|
2019
|
+
.ed-diagram-hint { flex: 1 1 auto; min-width: 0; color: var(--md-muted); font-size: 12px; }
|
|
2020
|
+
.ed-diagram-done {
|
|
2021
|
+
flex: 0 0 auto; font: inherit; font-size: 13px; padding: 2px 12px; cursor: pointer;
|
|
2022
|
+
border: 1px solid var(--md-border); border-radius: 6px;
|
|
2023
|
+
background: var(--md-ed-surface); color: var(--md-strong);
|
|
2024
|
+
}
|
|
2025
|
+
.ed-diagram-done:hover { background: var(--md-ed-hover); }
|
|
2026
|
+
.ed-diagram-src {
|
|
2027
|
+
display: block; width: 100%; box-sizing: border-box; min-height: 3em; max-height: 50vh; overflow-y: auto;
|
|
2028
|
+
padding: 6px; resize: vertical; tab-size: 2;
|
|
2029
|
+
font-family: "Cascadia Mono", Consolas, ui-monospace, monospace; font-size: 13px;
|
|
2030
|
+
border: 1px solid var(--md-border); border-radius: 6px;
|
|
2031
|
+
background: var(--md-ed-field); color: var(--md-strong);
|
|
2032
|
+
}
|
|
2033
|
+
.ed-diagram-preview { margin-top: 8px; max-height: 60vh; overflow: auto; outline: none; }
|
|
2034
|
+
.ed-diagram-preview svg { display: block; max-width: none; }
|
|
2035
|
+
.ed-diagram-preview.is-stale { opacity: 0.35; }
|
|
2036
|
+
.ed-diagram-error { margin-top: 6px; font-size: 12px; color: var(--md-ed-err); }
|
|
2037
|
+
.ed-diagram-error[data-kind="empty"] { color: var(--md-muted); }
|
|
1996
2038
|
.ed-wave-overlay {
|
|
1997
2039
|
position: fixed; inset: 0; z-index: 998; background: rgba(0,0,0,.45);
|
|
1998
2040
|
display: flex; align-items: center; justify-content: center;
|
|
@@ -3520,6 +3562,17 @@ ${usesDrawio ? ` /* v3.4.0 §4: a document with no drawio reference must not pa
|
|
|
3520
3562
|
outline: 2px solid var(--md-accent); outline-offset: 2px;
|
|
3521
3563
|
caret-color: var(--md-accent);
|
|
3522
3564
|
}
|
|
3565
|
+
/* v3.17.0 T2: a fenced code block edited in place. The pre itself is the
|
|
3566
|
+
editing host (editCodeInPlace() in the client runtime) and takes the
|
|
3567
|
+
same ring as an armed surface, drawn outside its own padding. Code never
|
|
3568
|
+
wraps, also where an engine's contenteditable default would wrap it, and
|
|
3569
|
+
an empty body keeps one line of height to click and type into. */
|
|
3570
|
+
pre[data-ed-code-edit] {
|
|
3571
|
+
white-space: pre; overflow-wrap: normal; word-wrap: normal; line-break: auto;
|
|
3572
|
+
cursor: text; caret-color: var(--md-accent);
|
|
3573
|
+
}
|
|
3574
|
+
pre[data-ed-code-edit]:focus { outline: 2px solid var(--md-accent); outline-offset: 2px; }
|
|
3575
|
+
pre[data-ed-code-edit] > code { display: block; min-height: 1lh; }
|
|
3523
3576
|
/* v3.14.0 T4: the empty-paragraph hint. syncEmptyMark() in the client sets
|
|
3524
3577
|
data-ed-empty on a paragraph surface with no text; a real paragraph shows
|
|
3525
3578
|
the hint while focused, the transient (an empty document's, or one Enter
|
|
@@ -3687,6 +3740,53 @@ ${usesDrawio ? ` /* v3.4.0 §4: a document with no drawio reference must not pa
|
|
|
3687
3740
|
flex: 0 0 auto; padding: 6px 10px; font-size: 11px; color: var(--md-muted);
|
|
3688
3741
|
border-top: 1px solid var(--md-ed-ring);
|
|
3689
3742
|
}
|
|
3743
|
+
/* v3.17.0 T3: the language chip and the copy chip of a fenced code block.
|
|
3744
|
+
Both live in one singleton on document.body (not inside .content: the
|
|
3745
|
+
client reads .content back as its own render), fixed at the top-right of
|
|
3746
|
+
the block the pointer is over or that is being edited. 24px tall, the
|
|
3747
|
+
editor surface with a 1px ring and a 6px radius; the copy chip shows the
|
|
3748
|
+
same check and Copied feedback as the reader button. The language menu
|
|
3749
|
+
is the slash menu look: 220px wide, 320px tall at most, its list scrolls
|
|
3750
|
+
on its own. No backticks in this comment: it lives inside a JS template
|
|
3751
|
+
literal. */
|
|
3752
|
+
.ed-code-chips {
|
|
3753
|
+
position: fixed; z-index: 12; display: flex; align-items: center; gap: 4px;
|
|
3754
|
+
}
|
|
3755
|
+
.ed-code-chips[hidden] { display: none; }
|
|
3756
|
+
.ed-code-chip {
|
|
3757
|
+
display: inline-flex; align-items: center; justify-content: center; gap: 4px;
|
|
3758
|
+
height: 24px; min-width: 24px; padding: 0 6px; margin: 0; box-sizing: border-box;
|
|
3759
|
+
border: 0; border-radius: 6px; background: var(--md-ed-surface); color: var(--md-muted);
|
|
3760
|
+
box-shadow: 0 0 0 1px var(--md-ed-ring);
|
|
3761
|
+
font: inherit; font-size: 12px; line-height: 1; cursor: pointer;
|
|
3762
|
+
}
|
|
3763
|
+
.ed-code-chip:hover, .ed-code-chip[aria-expanded="true"] { background: var(--md-ed-hover); color: var(--md-strong); }
|
|
3764
|
+
.ed-code-chip svg { flex: 0 0 auto; width: 14px; height: 14px; margin: 0; }
|
|
3765
|
+
.ed-code-copy.is-copied { color: var(--md-accent); }
|
|
3766
|
+
.ed-code-langmenu {
|
|
3767
|
+
position: fixed; z-index: 100; width: 220px; max-height: 320px;
|
|
3768
|
+
display: flex; flex-direction: column; box-sizing: border-box; overflow: hidden;
|
|
3769
|
+
border-radius: 8px; background: var(--md-ed-surface); color: var(--md-strong);
|
|
3770
|
+
box-shadow: 0 0 0 1px var(--md-ed-ring), 0 8px 24px var(--md-ed-shadow);
|
|
3771
|
+
font-size: 13px; line-height: 1.3;
|
|
3772
|
+
}
|
|
3773
|
+
.ed-code-langfilter {
|
|
3774
|
+
flex: 0 0 auto; margin: 4px 4px 0; padding: 0 8px; height: 28px; box-sizing: border-box;
|
|
3775
|
+
border: 0; border-radius: 6px; background: var(--md-ed-hover); color: inherit;
|
|
3776
|
+
font: inherit; outline: none;
|
|
3777
|
+
}
|
|
3778
|
+
.ed-code-langfilter::placeholder { color: var(--md-muted); }
|
|
3779
|
+
.ed-code-langlist { flex: 1 1 auto; min-height: 0; overflow-y: auto; padding: 4px; }
|
|
3780
|
+
.ed-code-langitem {
|
|
3781
|
+
display: flex; align-items: center; gap: 8px; width: 100%; height: 32px;
|
|
3782
|
+
padding: 0 8px; box-sizing: border-box; margin: 0;
|
|
3783
|
+
border: 0; border-radius: 6px; background: transparent; color: inherit;
|
|
3784
|
+
font: inherit; text-align: left; cursor: pointer;
|
|
3785
|
+
}
|
|
3786
|
+
.ed-code-langitem:hover, .ed-code-langitem[data-ed-lang-cursor] { background: var(--md-ed-hover); }
|
|
3787
|
+
.ed-code-langitem span { flex: 1 1 auto; min-width: 0; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
|
|
3788
|
+
.ed-code-langitem svg { flex: 0 0 auto; width: 14px; height: 14px; margin: 0; }
|
|
3789
|
+
.ed-code-langempty { padding: 8px; color: var(--md-muted); }
|
|
3690
3790
|
/* §10-gap fix: block-level INSERT — the + button sits NEXT TO the ⠿
|
|
3691
3791
|
handle in the left gutter, same node/visibility-toggle shape as
|
|
3692
3792
|
.ed-handle above (real per-block node, opacity-only reveal on hover).
|
|
@@ -3991,6 +4091,32 @@ ${usesDrawio ? ` /* v3.4.0 §4: a document with no drawio reference must not pa
|
|
|
3991
4091
|
background: transparent; color: inherit; font: inherit; font-size: 13px; cursor: pointer;
|
|
3992
4092
|
}
|
|
3993
4093
|
.ed-linkcard-btn:hover { background: var(--md-ed-hover); }
|
|
4094
|
+
/* v3.17.0 T7: the image toolbar, 8px inside the top-left of the image the
|
|
4095
|
+
pointer is over (a fixed singleton on body, like the link card; the same
|
|
4096
|
+
surface, ring and shadow roles). 刪除 is the error colour. In its alt-text
|
|
4097
|
+
mode the buttons give way to one input. */
|
|
4098
|
+
.ed-imgtb {
|
|
4099
|
+
position: fixed; z-index: 15;
|
|
4100
|
+
display: flex; align-items: center; gap: 2px; box-sizing: border-box;
|
|
4101
|
+
max-width: calc(100vw - 8px); padding: 3px; border-radius: 8px;
|
|
4102
|
+
background: var(--md-ed-surface); color: var(--md-strong); font-size: 13px;
|
|
4103
|
+
box-shadow: 0 0 0 1px var(--md-ed-ring), 0 8px 24px var(--md-ed-shadow);
|
|
4104
|
+
}
|
|
4105
|
+
.ed-imgtb[hidden] { display: none; }
|
|
4106
|
+
.ed-imgtb-btns { display: flex; align-items: center; gap: 2px; }
|
|
4107
|
+
.ed-imgtb-btns[hidden], .ed-imgtb-input[hidden] { display: none; }
|
|
4108
|
+
.ed-imgtb-btn {
|
|
4109
|
+
flex: none; height: 26px; padding: 0 8px; border: 0; border-radius: 6px;
|
|
4110
|
+
background: transparent; color: inherit; font: inherit; font-size: 13px; cursor: pointer;
|
|
4111
|
+
}
|
|
4112
|
+
.ed-imgtb-btn:hover { background: var(--md-ed-hover); }
|
|
4113
|
+
.ed-imgtb-delete { color: var(--md-ed-err); }
|
|
4114
|
+
.ed-imgtb-input {
|
|
4115
|
+
flex: 1 1 auto; width: 260px; max-width: calc(100vw - 24px); min-width: 0; height: 28px;
|
|
4116
|
+
box-sizing: border-box; padding: 0 8px; border: 1px solid var(--md-ed-ring); border-radius: 6px;
|
|
4117
|
+
background: var(--md-ed-field); color: inherit; font: inherit; font-size: 13px;
|
|
4118
|
+
}
|
|
4119
|
+
.ed-imgtb-input:focus { outline: none; border-color: var(--md-muted); }
|
|
3994
4120
|
/* v3.1.0 §4: the always-visible editing toolbar. Its numeric language is
|
|
3995
4121
|
.lightbox-bar's (8px/12px padding, 6px gap, 13px type) over .ed-seltb's
|
|
3996
4122
|
dark pill, so the two floating surfaces read as one family.
|
|
@@ -6652,7 +6778,7 @@ ${usesDrawioMultiPage ? ` // v3.4.0 batch2 Task 6: wired through a NAMED, reusa
|
|
|
6652
6778
|
// server's on-demand GET /api/lib/<name> serves exactly what this file inlines
|
|
6653
6779
|
// instead of resolving them a second time.
|
|
6654
6780
|
const diagramEnginePaths = { mermaid: localMermaidJs, wavedrom: localWaveDromJs, wavedromSkin: localWaveDromSkin };
|
|
6655
|
-
module.exports = { renderMarkdown, buildKatexStyleTag, diagramEnginePaths };
|
|
6781
|
+
module.exports = { renderMarkdown, buildKatexStyleTag, diagramEnginePaths, renderDotSvg };
|
|
6656
6782
|
|
|
6657
6783
|
// Index of the first "{" in dot source that opens the graph body: not inside a
|
|
6658
6784
|
// double-quoted string, a // or /* */ comment, a line starting with # (dot
|
|
@@ -6690,59 +6816,83 @@ function firstDotBrace(src) {
|
|
|
6690
6816
|
return -1;
|
|
6691
6817
|
}
|
|
6692
6818
|
|
|
6819
|
+
// One dot path for the bake and the editor preview. The loaded Graphviz
|
|
6820
|
+
// instance is cached at module scope (the library does not memoise load()).
|
|
6821
|
+
let graphvizLoading = null;
|
|
6822
|
+
function loadGraphviz() {
|
|
6823
|
+
if (!graphvizLoading) {
|
|
6824
|
+
const { Graphviz } = require('@hpcc-js/wasm-graphviz');
|
|
6825
|
+
graphvizLoading = Graphviz.load();
|
|
6826
|
+
// A failed load must not poison the cache: the next call tries again.
|
|
6827
|
+
graphvizLoading.catch(() => { graphvizLoading = null; });
|
|
6828
|
+
}
|
|
6829
|
+
return graphvizLoading;
|
|
6830
|
+
}
|
|
6831
|
+
async function renderDotSvg(dotSrc) {
|
|
6832
|
+
const gv = await loadGraphviz();
|
|
6833
|
+
// Graphviz measures label widths with the font it lays out in, and with
|
|
6834
|
+
// no fontname that is Times, whose metrics are narrower than the sans
|
|
6835
|
+
// the SVG is drawn in -- so labels overflowed their boxes. Declare
|
|
6836
|
+
// Helvetica BEFORE layout, right after the first brace; a fontname the
|
|
6837
|
+
// author writes later in the source still wins. Exactly "Helvetica":
|
|
6838
|
+
// a "Helvetica,sans-Serif" family list falls back to Times widths.
|
|
6839
|
+
const at = firstDotBrace(dotSrc);
|
|
6840
|
+
const laidOut = at < 0 ? dotSrc : dotSrc.slice(0, at + 1) +
|
|
6841
|
+
' graph [fontname="Helvetica"]; node [fontname="Helvetica"]; edge [fontname="Helvetica"]; ' + dotSrc.slice(at + 1);
|
|
6842
|
+
let laid;
|
|
6843
|
+
try {
|
|
6844
|
+
laid = gv.dot(laidOut);
|
|
6845
|
+
} catch (injectErr) {
|
|
6846
|
+
// Injection must never turn a valid graph into an error: lay the
|
|
6847
|
+
// original source out as the author wrote it.
|
|
6848
|
+
if (laidOut === dotSrc) throw injectErr;
|
|
6849
|
+
laid = gv.dot(dotSrc);
|
|
6850
|
+
}
|
|
6851
|
+
return laid
|
|
6852
|
+
.replace(/<\?xml[^>]*\?>/g, '')
|
|
6853
|
+
.replace(/<!DOCTYPE[\s\S]*?>/g, '')
|
|
6854
|
+
// drop graphviz's "Generated by graphviz" banner comment so the div and <svg> are adjacent
|
|
6855
|
+
.replace(/<!--[\s\S]*?-->/g, '')
|
|
6856
|
+
// v3.8.0: graphviz falls back to Times when no fontname is set. The
|
|
6857
|
+
// injection above makes Helvetica the layout font, so this rewrite
|
|
6858
|
+
// now only touches an author's explicit Times-Roman, or a figure
|
|
6859
|
+
// whose injection fell back to the original source; other explicit
|
|
6860
|
+
// fontnames are untouched.
|
|
6861
|
+
.replace(/font-family="Times,serif"/g, 'font-family="Helvetica,sans-Serif"')
|
|
6862
|
+
.trim();
|
|
6863
|
+
}
|
|
6864
|
+
|
|
6693
6865
|
// Render every deferred dot/graphviz placeholder to inline SVG using the
|
|
6694
6866
|
// in-process WASM engine. Loads the WASM module only when at least one dot
|
|
6695
6867
|
// block exists, so text-only docs pay nothing.
|
|
6696
6868
|
async function bakeGraphviz(htmlStr) {
|
|
6697
6869
|
if (!GRAPHVIZ_PLACEHOLDER.probe.test(htmlStr)) return htmlStr;
|
|
6698
|
-
let Graphviz;
|
|
6699
6870
|
try {
|
|
6700
|
-
|
|
6871
|
+
require('@hpcc-js/wasm-graphviz');
|
|
6701
6872
|
} catch (e) {
|
|
6702
6873
|
console.error('[ERROR] @hpcc-js/wasm-graphviz not installed — run `npm install`:', e.message);
|
|
6703
6874
|
return htmlStr;
|
|
6704
6875
|
}
|
|
6705
|
-
|
|
6706
|
-
|
|
6707
|
-
|
|
6876
|
+
// A WASM load failure throws, as it always did; only a per-block render
|
|
6877
|
+
// failure degrades that block to pre/code.
|
|
6878
|
+
await loadGraphviz();
|
|
6879
|
+
const jobs = [];
|
|
6880
|
+
htmlStr.replace(GRAPHVIZ_PLACEHOLDER.re, (m, b64) => {
|
|
6881
|
+
jobs.push(Buffer.from(b64, 'base64').toString('utf8'));
|
|
6882
|
+
return m;
|
|
6883
|
+
});
|
|
6884
|
+
const out = [];
|
|
6885
|
+
for (const dotSrc of jobs) {
|
|
6708
6886
|
try {
|
|
6709
|
-
|
|
6710
|
-
// no fontname that is Times, whose metrics are narrower than the sans
|
|
6711
|
-
// the SVG is drawn in -- so labels overflowed their boxes. Declare
|
|
6712
|
-
// Helvetica BEFORE layout, right after the first brace; a fontname the
|
|
6713
|
-
// author writes later in the source still wins. Exactly "Helvetica":
|
|
6714
|
-
// a "Helvetica,sans-Serif" family list falls back to Times widths.
|
|
6715
|
-
const at = firstDotBrace(dotSrc);
|
|
6716
|
-
const laidOut = at < 0 ? dotSrc : dotSrc.slice(0, at + 1) +
|
|
6717
|
-
' graph [fontname="Helvetica"]; node [fontname="Helvetica"]; edge [fontname="Helvetica"]; ' + dotSrc.slice(at + 1);
|
|
6718
|
-
let laid;
|
|
6719
|
-
try {
|
|
6720
|
-
laid = gv.dot(laidOut);
|
|
6721
|
-
} catch (injectErr) {
|
|
6722
|
-
// Injection must never turn a valid graph into an error: lay the
|
|
6723
|
-
// original source out as the author wrote it.
|
|
6724
|
-
if (laidOut === dotSrc) throw injectErr;
|
|
6725
|
-
laid = gv.dot(dotSrc);
|
|
6726
|
-
}
|
|
6727
|
-
const svg = laid
|
|
6728
|
-
.replace(/<\?xml[^>]*\?>/g, '')
|
|
6729
|
-
.replace(/<!DOCTYPE[\s\S]*?>/g, '')
|
|
6730
|
-
// drop graphviz's "Generated by graphviz" banner comment so the div and <svg> are adjacent
|
|
6731
|
-
.replace(/<!--[\s\S]*?-->/g, '')
|
|
6732
|
-
// v3.8.0: graphviz falls back to Times when no fontname is set. The
|
|
6733
|
-
// injection above makes Helvetica the layout font, so this rewrite
|
|
6734
|
-
// now only touches an author's explicit Times-Roman, or a figure
|
|
6735
|
-
// whose injection fell back to the original source; other explicit
|
|
6736
|
-
// fontnames are untouched.
|
|
6737
|
-
.replace(/font-family="Times,serif"/g, 'font-family="Helvetica,sans-Serif"')
|
|
6738
|
-
.trim();
|
|
6739
|
-
return `<div class="graphviz">${svg}</div>`;
|
|
6887
|
+
out.push(`<div class="graphviz">${await renderDotSvg(dotSrc)}</div>`);
|
|
6740
6888
|
} catch (e) {
|
|
6741
6889
|
console.error('[WARN] graphviz render failed:', e.message);
|
|
6742
6890
|
const escaped = dotSrc.replace(/&/g, '&').replace(/</g, '<').replace(/>/g, '>');
|
|
6743
|
-
|
|
6891
|
+
out.push(`<pre><code class="language-dot">${escaped}</code></pre>\n`);
|
|
6744
6892
|
}
|
|
6745
|
-
}
|
|
6893
|
+
}
|
|
6894
|
+
let i = 0;
|
|
6895
|
+
return htmlStr.replace(GRAPHVIZ_PLACEHOLDER.re, () => out[i++]);
|
|
6746
6896
|
}
|
|
6747
6897
|
|
|
6748
6898
|
function launchBrowser(puppeteer) {
|
package/lib/theme/runtime.js
CHANGED
|
@@ -22,7 +22,9 @@
|
|
|
22
22
|
if (at !== -1) listeners.splice(at, 1);
|
|
23
23
|
};
|
|
24
24
|
}
|
|
25
|
-
|
|
25
|
+
// Over a copy: a listener may unsubscribe itself (or another) while it
|
|
26
|
+
// runs, and a splice under the loop would skip the next one.
|
|
27
|
+
function notify(dark) { var ls = listeners.slice(); for (var i = 0; i < ls.length; i++) ls[i](dark); }
|
|
26
28
|
function isDark() { return root.getAttribute('data-md2doc-theme') === 'dark'; }
|
|
27
29
|
function save(dark) {
|
|
28
30
|
try {
|
|
@@ -228,6 +230,35 @@
|
|
|
228
230
|
return true;
|
|
229
231
|
};
|
|
230
232
|
|
|
233
|
+
// v3.17.0 (D13): one off-page render for the editor's diagram panel preview.
|
|
234
|
+
// It waits its turn on the same chain, because mermaid has ONE global config
|
|
235
|
+
// and a render beside a light / dark draw could be drawn with the other's
|
|
236
|
+
// theme. Its turn initialises the theme on screen at that moment, renders
|
|
237
|
+
// under a fresh id, and puts the light config back after (the invariant
|
|
238
|
+
// every draw here keeps). Resolves the svg text; rejects with mermaid's
|
|
239
|
+
// error, its stray #d<id> element removed. Counted in inFlight like the
|
|
240
|
+
// draws, so a toggle to a cached theme waits behind it too.
|
|
241
|
+
var previewSeq = 0;
|
|
242
|
+
function renderMermaid(src) {
|
|
243
|
+
if (typeof window.mermaid === 'undefined') return Promise.reject(new Error('mermaid is not loaded'));
|
|
244
|
+
inFlight++;
|
|
245
|
+
var run = chain.then(function () {
|
|
246
|
+
var id = 'md2doc-mermaid-preview-' + (++previewSeq);
|
|
247
|
+
window.mermaid.initialize(mermaidConfig(isDark() ? 'dark' : 'light'));
|
|
248
|
+
return Promise.resolve().then(function () { return window.mermaid.render(id, String(src)); }).then(function (res) {
|
|
249
|
+
window.mermaid.initialize(mermaidConfig('light'));
|
|
250
|
+
return res.svg;
|
|
251
|
+
}, function (e) {
|
|
252
|
+
var stray = document.getElementById('d' + id);
|
|
253
|
+
if (stray && stray.parentNode) stray.parentNode.removeChild(stray);
|
|
254
|
+
window.mermaid.initialize(mermaidConfig('light'));
|
|
255
|
+
throw e;
|
|
256
|
+
});
|
|
257
|
+
});
|
|
258
|
+
chain = run.catch(function () { /* the caller shows the error */ }).then(function () { inFlight--; });
|
|
259
|
+
return run;
|
|
260
|
+
}
|
|
261
|
+
|
|
231
262
|
// ── graphviz / WaveDrom / baked SVG: recolour by computed colour ──
|
|
232
263
|
// Rules: spec "Diagram recolour rules (D10)". Reading COMPUTED fill/stroke
|
|
233
264
|
// covers both graphviz presentation attributes and WaveDrom's own <style>.
|
|
@@ -617,6 +648,6 @@
|
|
|
617
648
|
// Public surface for pages that draw their own SVG outside .content (the wave editor canvas).
|
|
618
649
|
// `__listenerCount` is a test hook (test/editor-click.test.js): the wave
|
|
619
650
|
// editor subscribes once per open and must unsubscribe on close.
|
|
620
|
-
window.md2docTheme = { isDark: isDark, onTheme: onTheme, recolourSvg: recolourSvg,
|
|
651
|
+
window.md2docTheme = { isDark: isDark, onTheme: onTheme, recolourSvg: recolourSvg, renderMermaid: renderMermaid,
|
|
621
652
|
__listenerCount: function () { return listeners.length; } };
|
|
622
653
|
})();
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@helping-ai-workflow/md2doc",
|
|
3
|
-
"version": "3.
|
|
3
|
+
"version": "3.17.0",
|
|
4
4
|
"description": "Markdown → HTML / PDF renderer with WaveDrom, Mermaid, Graphviz, and draw.io support",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"markdown",
|
|
@@ -46,7 +46,7 @@
|
|
|
46
46
|
},
|
|
47
47
|
"scripts": {
|
|
48
48
|
"preinstall": "node scripts/preinstall.js",
|
|
49
|
-
"test": "node test/md2doc.test.js && node test/highlight.test.js && node test/blockmap.test.js && node test/drawio.test.js && node test/images.test.js && node test/scroll-anchor.test.js && node test/lightbox.test.js && node test/lightbox-anno.test.js && node test/lightbox-anno-style.test.js && node test/reader-panels.test.js && node test/cli.test.js && node test/code-operator.test.js && node test/convert-md.test.js && node test/block-catalog.test.js && node test/render-api.test.js && node test/lineops.test.js && node test/indent-clamp.test.js && node test/selection.test.js && node test/cell-range.test.js && node test/editmode-render.test.js && node test/editmode-wavedrom-reinit.test.js && node test/editor-server.test.js && node test/cli-edit.test.js && node test/open-viewer.test.js && node test/editor-client.test.js && node test/editor-client-runtime.test.js && node test/roundtrip.test.js && node test/byte-stability.test.js && node test/editor-server-throw.test.js && node test/editor-reader-rebind.test.js && node test/inline-md.test.js && node test/table-md.test.js && node test/table-anchor-recovery.test.js && node test/gate-compat.test.js && node test/history.test.js && node test/list-md.test.js && node test/table-width.test.js && node test/toolbar-model.test.js && node test/asset.test.js && node test/paste-md.test.js && node test/patchmap.test.js && node test/wave-codec.test.js && node test/wave-draw.test.js && node test/wave-geometry.test.js && node test/wave-store.test.js && node test/editor-journey.test.js && node test/detach-census.test.js && node test/editor-arrow-nav.test.js && node test/editor-cell-range.test.js && node test/reader-design.test.js && node test/theme.test.js && node test/release-check.test.js && node test/wave-overflow.test.js",
|
|
49
|
+
"test": "node test/md2doc.test.js && node test/highlight.test.js && node test/blockmap.test.js && node test/drawio.test.js && node test/images.test.js && node test/scroll-anchor.test.js && node test/lightbox.test.js && node test/lightbox-anno.test.js && node test/lightbox-anno-style.test.js && node test/reader-panels.test.js && node test/cli.test.js && node test/code-operator.test.js && node test/convert-md.test.js && node test/block-catalog.test.js && node test/code-edit.test.js && node test/render-api.test.js && node test/lineops.test.js && node test/indent-clamp.test.js && node test/selection.test.js && node test/cell-range.test.js && node test/editmode-render.test.js && node test/editmode-wavedrom-reinit.test.js && node test/editor-server.test.js && node test/cli-edit.test.js && node test/open-viewer.test.js && node test/editor-client.test.js && node test/editor-client-runtime.test.js && node test/roundtrip.test.js && node test/byte-stability.test.js && node test/editor-server-throw.test.js && node test/editor-reader-rebind.test.js && node test/inline-md.test.js && node test/table-md.test.js && node test/table-anchor-recovery.test.js && node test/gate-compat.test.js && node test/history.test.js && node test/list-md.test.js && node test/table-width.test.js && node test/toolbar-model.test.js && node test/asset.test.js && node test/paste-md.test.js && node test/patchmap.test.js && node test/wave-codec.test.js && node test/wave-draw.test.js && node test/wave-geometry.test.js && node test/wave-store.test.js && node test/editor-journey.test.js && node test/detach-census.test.js && node test/editor-arrow-nav.test.js && node test/editor-cell-range.test.js && node test/reader-design.test.js && node test/theme.test.js && node test/theme-runtime.test.js && node test/release-check.test.js && node test/wave-overflow.test.js",
|
|
50
50
|
"test:browser": "node test/reader-click.test.js && node test/editor-click.test.js && node test/wave-canvas.test.js"
|
|
51
51
|
},
|
|
52
52
|
"repository": {
|