orz-mdhtml 0.1.0 → 0.1.2
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 +12 -9
- package/assets/app.js +35 -3
- package/dist/cli.js +1 -0
- package/dist/orzmd.browser.js +50 -50
- package/orz-mdhtml-skills/SKILL.md +14 -9
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -36,17 +36,16 @@ as the single source of truth; Save/Export re-serialize the whole document.
|
|
|
36
36
|
|
|
37
37
|
## Install / generate
|
|
38
38
|
|
|
39
|
-
Requires Node 18+.
|
|
39
|
+
Requires Node 18+. No install needed — run it with `npx`:
|
|
40
40
|
|
|
41
41
|
```bash
|
|
42
|
-
|
|
43
|
-
cd orz-mdhtml
|
|
44
|
-
npm install
|
|
45
|
-
npm run bundle # build dist/orzmd.browser.js (the in-browser renderer)
|
|
46
|
-
npm run gen -- path/to/doc.md # → path/to/doc.md.html
|
|
42
|
+
npx orz-mdhtml path/to/doc.md # → path/to/doc.md.html
|
|
47
43
|
open path/to/doc.md.html
|
|
48
44
|
```
|
|
49
45
|
|
|
46
|
+
Or install the CLI globally (`npm i -g orz-mdhtml`), then `orz-mdhtml doc.md`.
|
|
47
|
+
To hack on it, clone the repo and use `npm run gen -- doc.md`.
|
|
48
|
+
|
|
50
49
|
### CLI options
|
|
51
50
|
|
|
52
51
|
```
|
|
@@ -54,11 +53,15 @@ orz-mdhtml <input.md> [options]
|
|
|
54
53
|
|
|
55
54
|
-o, --out <file> output path (default: <input>.md.html)
|
|
56
55
|
--theme <name> default theme id (default: light-academic-1)
|
|
57
|
-
--
|
|
58
|
-
--
|
|
56
|
+
--cdn reference the renderer from jsDelivr (default; small files)
|
|
57
|
+
--inline embed the renderer bundle (larger file, no renderer fetch)
|
|
59
58
|
--title <text> document <title> (default: input filename)
|
|
60
59
|
```
|
|
61
60
|
|
|
61
|
+
By default (`--cdn`), the renderer is fetched from jsDelivr on first open and
|
|
62
|
+
cached, so generated files are small (~tens of KB). Use `--inline` to embed the
|
|
63
|
+
renderer (~750 KB) when you want the file to carry its own renderer.
|
|
64
|
+
|
|
62
65
|
Themes: `light-academic-1/2`, `light-neat-1/2`, `light-playful-1/2`,
|
|
63
66
|
`beige-decent-1/2`, `dark-elegant-1/2`. (Readers can switch live in the editor.)
|
|
64
67
|
|
|
@@ -104,7 +107,7 @@ whole-table/blockquote copy fix.
|
|
|
104
107
|
- [x] Document-first UI: read / edit, iframe preview, incremental live updates
|
|
105
108
|
- [x] Theme picker, reader font size, export, scroll-sync toggle
|
|
106
109
|
- [x] copy-as-markdown via orz-markdown core
|
|
107
|
-
- [
|
|
110
|
+
- [x] Publish `orz-mdhtml` (the CLI) and `orz-mdhtml-browser` (CDN bundle) to npm
|
|
108
111
|
- [ ] Optional fully-offline build (inline themes + editor libs)
|
|
109
112
|
- [ ] Mermaid/KaTeX live re-render parity in the editor
|
|
110
113
|
|
package/assets/app.js
CHANGED
|
@@ -63,11 +63,18 @@
|
|
|
63
63
|
+ '<article class="markdown-body" id="orz-doc"></article>'
|
|
64
64
|
+ '<script src="' + f.hljsJs + '"><\/script>'
|
|
65
65
|
+ '<script src="' + f.mermaidJs + '"><\/script>'
|
|
66
|
+
+ '<script src="' + f.smilesJs + '"><\/script>'
|
|
66
67
|
+ '<script>try{mermaid.initialize({startOnLoad:false})}catch(e){}<\/script>'
|
|
67
68
|
+ '<script>' + guard(CFG.runtime) + '<\/script>'
|
|
68
69
|
+ '<script>window.__orzEnhance=function(){'
|
|
69
70
|
+ 'try{if(window.hljs){document.querySelectorAll("#orz-doc pre code:not(.hljs)").forEach(function(b){window.hljs.highlightElement(b)})}}catch(e){}'
|
|
70
71
|
+ 'try{if(window.mermaid){window.mermaid.run({querySelector:"#orz-doc .mermaid:not([data-processed])"})}}catch(e){}'
|
|
72
|
+
// SMILES: draw each canvas once (tracked via a JS prop so morphdom keeps
|
|
73
|
+
// the drawn canvas across edits — DOM attributes stay identical).
|
|
74
|
+
+ 'try{if(window.SmilesDrawer){document.querySelectorAll("#orz-doc canvas[data-smiles]").forEach(function(c){if(c.__orzSmilesDone)return;var s=c.getAttribute("data-smiles");if(!s)return;c.__orzSmilesDone=true;var dr=new window.SmilesDrawer.Drawer({width:c.width,height:c.height});window.SmilesDrawer.parse(s,function(t){try{dr.draw(t,c,window.__orzSmilesTheme||"light",false)}catch(e){}},function(){})})}}catch(e){}'
|
|
75
|
+
// Tabs init runs in the runtime on load (empty #orz-doc); re-run now that
|
|
76
|
+
// content is injected, and after each incremental update. Idempotent.
|
|
77
|
+
+ 'try{if(window.OrzMarkdownRuntime&&window.OrzMarkdownRuntime.initTabs){window.OrzMarkdownRuntime.initTabs(document)}}catch(e){}'
|
|
71
78
|
+ '};<\/script></body></html>';
|
|
72
79
|
}
|
|
73
80
|
|
|
@@ -91,7 +98,20 @@
|
|
|
91
98
|
|
|
92
99
|
function enhance() {
|
|
93
100
|
var w = frame.contentWindow;
|
|
94
|
-
if (w
|
|
101
|
+
if (!w) return;
|
|
102
|
+
try { w.__orzSmilesTheme = themeById(currentTheme).scheme === 'dark' ? 'dark' : 'light'; } catch (e) {}
|
|
103
|
+
if (typeof w.__orzEnhance === 'function') { try { w.__orzEnhance(); } catch (e) {} }
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
// Re-draw SMILES canvases (fresh, cleared) so they pick up the current
|
|
107
|
+
// light/dark theme; used after a theme switch.
|
|
108
|
+
function redrawSmiles() {
|
|
109
|
+
var doc = frameDoc(); if (!doc) return;
|
|
110
|
+
Array.prototype.forEach.call(doc.querySelectorAll('#orz-doc canvas[data-smiles]'), function (c) {
|
|
111
|
+
var fresh = c.cloneNode(false); // drops the drawing + the __orzSmilesDone JS prop
|
|
112
|
+
if (c.parentNode) c.parentNode.replaceChild(fresh, c);
|
|
113
|
+
});
|
|
114
|
+
enhance();
|
|
95
115
|
}
|
|
96
116
|
// CDN libs inside the iframe load async — retry enhance a few times.
|
|
97
117
|
function enhanceSoon() { enhance(); setTimeout(enhance, 150); setTimeout(enhance, 600); setTimeout(enhance, 1500); }
|
|
@@ -327,6 +347,7 @@
|
|
|
327
347
|
root.setAttribute('data-chrome', t.scheme);
|
|
328
348
|
if (themeSelect) themeSelect.value = id;
|
|
329
349
|
applyThemeToFrame(t);
|
|
350
|
+
redrawSmiles(); // pick up the new light/dark SMILES palette
|
|
330
351
|
if (cm) cm.setOption('theme', cmTheme(t.scheme));
|
|
331
352
|
markDirty();
|
|
332
353
|
}
|
|
@@ -463,19 +484,30 @@
|
|
|
463
484
|
}
|
|
464
485
|
|
|
465
486
|
// ---- version check -------------------------------------------------------
|
|
487
|
+
// True only when `a` is a strictly newer semver than `b` (so an older
|
|
488
|
+
// resolved version never shows a bogus "update available").
|
|
489
|
+
function isNewer(a, b) {
|
|
490
|
+
var pa = String(a).split('.'), pb = String(b).split('.');
|
|
491
|
+
for (var i = 0; i < 3; i++) {
|
|
492
|
+
var x = parseInt(pa[i], 10) || 0, y = parseInt(pb[i], 10) || 0;
|
|
493
|
+
if (x > y) return true;
|
|
494
|
+
if (x < y) return false;
|
|
495
|
+
}
|
|
496
|
+
return false;
|
|
497
|
+
}
|
|
466
498
|
function checkVersion() {
|
|
467
499
|
if (!CFG.versionManifest || !CFG.rendererVersion) return;
|
|
468
500
|
try {
|
|
469
501
|
var cached = JSON.parse(localStorage.getItem('orz-mdhtml:vercheck') || 'null');
|
|
470
502
|
if (cached && (Date.now() - cached.t) < 86400000) {
|
|
471
|
-
if (cached.v && cached.v
|
|
503
|
+
if (cached.v && isNewer(cached.v, CFG.rendererVersion)) showUpdate(cached.v);
|
|
472
504
|
return;
|
|
473
505
|
}
|
|
474
506
|
} catch (e) {}
|
|
475
507
|
fetch(CFG.versionManifest).then(function (r) { return r.json(); }).then(function (j) {
|
|
476
508
|
var latest = j && j.version;
|
|
477
509
|
try { localStorage.setItem('orz-mdhtml:vercheck', JSON.stringify({ t: Date.now(), v: latest })); } catch (e) {}
|
|
478
|
-
if (latest && latest
|
|
510
|
+
if (latest && isNewer(latest, CFG.rendererVersion)) showUpdate(latest);
|
|
479
511
|
}).catch(function () {});
|
|
480
512
|
}
|
|
481
513
|
function showUpdate(latest) {
|
package/dist/cli.js
CHANGED
|
@@ -140,6 +140,7 @@ function main() {
|
|
|
140
140
|
hljsDarkCss: `${CDN.hl}/styles/atom-one-dark.min.css`,
|
|
141
141
|
hljsJs: `${CDN.hl}/highlight.min.js`,
|
|
142
142
|
mermaidJs: 'https://cdn.jsdelivr.net/npm/mermaid@11/dist/mermaid.min.js',
|
|
143
|
+
smilesJs: 'https://cdn.jsdelivr.net/npm/smiles-drawer@1.0.10/dist/smiles-drawer.min.js',
|
|
143
144
|
},
|
|
144
145
|
editorLibs: {
|
|
145
146
|
codemirrorCss: `${CDN.cm}/codemirror.min.css`,
|