@helping-ai-workflow/md2doc 3.6.1 → 3.8.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 +1 -0
- package/THIRD-PARTY-NOTICES.md +21 -0
- package/bin/md2doc.js +19 -3
- package/lib/editor/cell-range.js +85 -0
- package/lib/editor/client.js +809 -14
- package/lib/editor/server.js +5 -0
- package/lib/md2doc.js +433 -131
- package/package.json +6 -2
package/README.md
CHANGED
|
@@ -74,6 +74,7 @@ also pass `--open`.
|
|
|
74
74
|
| `--no-open` | Skip the viewer launch. |
|
|
75
75
|
| `--quiet` | Suppress per-file progress messages. |
|
|
76
76
|
| `--bake-svg` | Pre-render Mermaid / WaveDrom to inert SVG at generation time (HTML output only; needs Chromium). The output then contains no diagram JavaScript. |
|
|
77
|
+
| `--lang <tag>` | Set `<html lang>` (for example `en`, `zh-Hant`). Default: detected — `zh-Hant` when Chinese characters are at least 10% of the prose (code excluded), `ja` / `ko` when kana / Hangul make up at least 20% of the CJK characters, otherwise `en`. |
|
|
77
78
|
| `--version`, `-v` | Print version. |
|
|
78
79
|
| `--help`, `-h` | Print help. |
|
|
79
80
|
|
package/THIRD-PARTY-NOTICES.md
CHANGED
|
@@ -42,3 +42,24 @@ turndown, `@hpcc-js/wasm-graphviz`) are ordinary npm packages: they are
|
|
|
42
42
|
resolved into your `node_modules` by your own installer, carry their own
|
|
43
43
|
licence files there, and are not redistributed inside md2doc's tarball.
|
|
44
44
|
They are out of scope for this file.
|
|
45
|
+
|
|
46
|
+
## Lucide (icon path data)
|
|
47
|
+
|
|
48
|
+
The sidebar icons in `lib/md2doc.js` (`READER_ICONS`) use path data from
|
|
49
|
+
Lucide, https://lucide.dev — ISC License.
|
|
50
|
+
|
|
51
|
+
Copyright (c) for portions of Lucide are held by Cole Bemis 2013-2022 as part
|
|
52
|
+
of Feather (MIT). All other copyright (c) for Lucide are held by Lucide
|
|
53
|
+
Contributors 2022.
|
|
54
|
+
|
|
55
|
+
Permission to use, copy, modify, and/or distribute this software for any
|
|
56
|
+
purpose with or without fee is hereby granted, provided that the above
|
|
57
|
+
copyright notice and this permission notice appear in all copies.
|
|
58
|
+
|
|
59
|
+
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
|
60
|
+
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
|
61
|
+
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
|
|
62
|
+
SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
|
63
|
+
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
|
|
64
|
+
OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
|
|
65
|
+
CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
package/bin/md2doc.js
CHANGED
|
@@ -32,6 +32,7 @@ function printHelp() {
|
|
|
32
32
|
' --open Launch the platform viewer after render (default when --out is absent).',
|
|
33
33
|
' --no-open Skip the viewer launch.',
|
|
34
34
|
' --quiet Suppress per-file progress messages.',
|
|
35
|
+
' --lang <tag> Set <html lang> (default: detected — zh-Hant for Chinese-heavy text, ja / ko for Japanese / Korean, else en).',
|
|
35
36
|
' --bake-svg Pre-render mermaid/wavedrom to inert SVG (HTML output only; needs Chromium).',
|
|
36
37
|
' --edit Serve listed .md files in the browser editor (localhost).',
|
|
37
38
|
' --port <n> Pin the editor server port (only with --edit).',
|
|
@@ -51,6 +52,7 @@ function parseArgs(argv) {
|
|
|
51
52
|
let bakeSvg = false;
|
|
52
53
|
let edit = false;
|
|
53
54
|
let port = null;
|
|
55
|
+
let lang = null;
|
|
54
56
|
|
|
55
57
|
for (let i = 0; i < argv.length; i++) {
|
|
56
58
|
const a = argv[i];
|
|
@@ -96,6 +98,19 @@ function parseArgs(argv) {
|
|
|
96
98
|
out = argv[i];
|
|
97
99
|
continue;
|
|
98
100
|
}
|
|
101
|
+
if (a === '--lang') {
|
|
102
|
+
i++;
|
|
103
|
+
if (i >= argv.length) {
|
|
104
|
+
process.stderr.write('error: --lang requires a value\n');
|
|
105
|
+
process.exit(2);
|
|
106
|
+
}
|
|
107
|
+
if (!/^[A-Za-z]{2,3}(?:-[A-Za-z0-9]{2,8})*$/.test(argv[i])) {
|
|
108
|
+
process.stderr.write('error: --lang must be a language tag such as en or zh-Hant\n');
|
|
109
|
+
process.exit(2);
|
|
110
|
+
}
|
|
111
|
+
lang = argv[i];
|
|
112
|
+
continue;
|
|
113
|
+
}
|
|
99
114
|
if (a.startsWith('-')) {
|
|
100
115
|
process.stderr.write('error: unknown flag ' + a + '\n');
|
|
101
116
|
process.exit(2);
|
|
@@ -124,7 +139,7 @@ function parseArgs(argv) {
|
|
|
124
139
|
open = (out === null);
|
|
125
140
|
}
|
|
126
141
|
|
|
127
|
-
return { inputs, formats, formatsExplicit, out, open, quiet, bakeSvg, edit, port };
|
|
142
|
+
return { inputs, formats, formatsExplicit, out, open, quiet, bakeSvg, edit, port, lang };
|
|
128
143
|
}
|
|
129
144
|
|
|
130
145
|
function shortHash(absPath) {
|
|
@@ -232,8 +247,8 @@ function main() {
|
|
|
232
247
|
}
|
|
233
248
|
|
|
234
249
|
if (args.edit) {
|
|
235
|
-
if (args.formatsExplicit || args.out !== null || args.bakeSvg) {
|
|
236
|
-
process.stderr.write('error: --edit cannot be combined with --html/--pdf/--out/--bake-svg\n');
|
|
250
|
+
if (args.formatsExplicit || args.out !== null || args.bakeSvg || args.lang !== null) {
|
|
251
|
+
process.stderr.write('error: --edit cannot be combined with --html/--pdf/--out/--bake-svg/--lang\n');
|
|
237
252
|
process.exit(2);
|
|
238
253
|
}
|
|
239
254
|
for (const input of args.inputs) {
|
|
@@ -262,6 +277,7 @@ function main() {
|
|
|
262
277
|
const stdio = args.quiet ? ['inherit', 'ignore', 'inherit'] : 'inherit';
|
|
263
278
|
const childArgs = [LIB, input, output];
|
|
264
279
|
if (args.bakeSvg) childArgs.push('--bake-svg');
|
|
280
|
+
if (args.lang) childArgs.push('--lang=' + args.lang);
|
|
265
281
|
const r = spawnSync(process.execPath, childArgs, { stdio });
|
|
266
282
|
if (r.status !== 0) {
|
|
267
283
|
process.stderr.write('error: render failed for ' + input + ' (exit ' + r.status + ')\n');
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
/* Table cell-range selection — the pure model.
|
|
3
|
+
Spec: docs/superpowers/specs/2026-09-24-editor-cell-range-design.md.
|
|
4
|
+
UMD, same shape as selection.js: require-able in node for the unit tests,
|
|
5
|
+
injected into the editor page as window.md2docCellRange. Points are
|
|
6
|
+
{r, c}: r indexes the table's rows with the header row as 0, c the cell
|
|
7
|
+
index within that row. */
|
|
8
|
+
(function (root, factory) {
|
|
9
|
+
if (typeof module === 'object' && module.exports) module.exports = factory();
|
|
10
|
+
else root.md2docCellRange = factory();
|
|
11
|
+
})(typeof self !== 'undefined' ? self : this, function () {
|
|
12
|
+
function clamp(n, lo, hi) { return Math.max(lo, Math.min(hi, n)); }
|
|
13
|
+
|
|
14
|
+
function normalize(a, f) {
|
|
15
|
+
return { top: Math.min(a.r, f.r), left: Math.min(a.c, f.c),
|
|
16
|
+
bottom: Math.max(a.r, f.r), right: Math.max(a.c, f.c) };
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
function cellsIn(rect) {
|
|
20
|
+
const out = [];
|
|
21
|
+
for (let r = rect.top; r <= rect.bottom; r++) {
|
|
22
|
+
for (let c = rect.left; c <= rect.right; c++) out.push({ r: r, c: c });
|
|
23
|
+
}
|
|
24
|
+
return out;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
function isSingle(a, f) { return a.r === f.r && a.c === f.c; }
|
|
28
|
+
|
|
29
|
+
const DELTA = { up: [-1, 0], down: [1, 0], left: [0, -1], right: [0, 1] };
|
|
30
|
+
function step(p, dir, rowCount, colCount) {
|
|
31
|
+
const d = DELTA[dir];
|
|
32
|
+
return { r: clamp(p.r + d[0], 0, rowCount - 1), c: clamp(p.c + d[1], 0, colCount - 1) };
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
// Excel's TSV: TAB between fields, newline between records, a field that
|
|
36
|
+
// STARTS with a quote is quoted ("" inside is one quote, and it may hold
|
|
37
|
+
// TABs and newlines). A trailing newline does not make an empty record.
|
|
38
|
+
function parseTsv(text) {
|
|
39
|
+
const s = String(text).replace(/\r\n?/g, '\n');
|
|
40
|
+
const rows = [];
|
|
41
|
+
let row = [];
|
|
42
|
+
let field = '';
|
|
43
|
+
let atStart = true;
|
|
44
|
+
let i = 0;
|
|
45
|
+
while (i < s.length) {
|
|
46
|
+
const ch = s[i];
|
|
47
|
+
if (atStart && ch === '"') {
|
|
48
|
+
i++;
|
|
49
|
+
while (i < s.length) {
|
|
50
|
+
if (s[i] === '"') {
|
|
51
|
+
if (s[i + 1] === '"') { field += '"'; i += 2; continue; }
|
|
52
|
+
i++;
|
|
53
|
+
break;
|
|
54
|
+
}
|
|
55
|
+
field += s[i];
|
|
56
|
+
i++;
|
|
57
|
+
}
|
|
58
|
+
atStart = false;
|
|
59
|
+
continue;
|
|
60
|
+
}
|
|
61
|
+
if (ch === '\t') { row.push(field); field = ''; atStart = true; i++; continue; }
|
|
62
|
+
if (ch === '\n') { row.push(field); rows.push(row); row = []; field = ''; atStart = true; i++; continue; }
|
|
63
|
+
field += ch;
|
|
64
|
+
atStart = false;
|
|
65
|
+
i++;
|
|
66
|
+
}
|
|
67
|
+
if (field !== '' || row.length) { row.push(field); rows.push(row); }
|
|
68
|
+
return rows;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
function quoteField(f) {
|
|
72
|
+
return /[\t\n"]/.test(f) ? '"' + f.replace(/"/g, '""') + '"' : f;
|
|
73
|
+
}
|
|
74
|
+
function toTsv(grid) {
|
|
75
|
+
return grid.map((row) => row.map(quoteField).join('\t')).join('\n');
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
function growthNeeded(origin, grid, rowCount, colCount) {
|
|
79
|
+
const width = grid.reduce((w, row) => Math.max(w, row.length), 0);
|
|
80
|
+
return { addRows: Math.max(0, origin.r + grid.length - rowCount),
|
|
81
|
+
addCols: Math.max(0, origin.c + width - colCount) };
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
return { normalize, cellsIn, isSingle, step, parseTsv, toTsv, growthNeeded };
|
|
85
|
+
});
|