@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 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
 
@@ -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
+ });