@helping-ai-workflow/md2doc 2.1.1 → 2.2.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/md2doc.js +40 -3
- package/package.json +2 -2
package/lib/md2doc.js
CHANGED
|
@@ -415,15 +415,52 @@ ${itemsHtml}
|
|
|
415
415
|
|
|
416
416
|
marked.setOptions({ gfm: true, breaks: false, renderer });
|
|
417
417
|
|
|
418
|
-
//
|
|
418
|
+
// Code-aware subscript / superscript as marked inline extensions.
|
|
419
|
+
// The old raw-text pre-pass (mdPre.replace(/~([^~]+)~/...)) ran BEFORE marked
|
|
420
|
+
// tokenised, so it rewrote ~NOT / ^XOR operators inside fenced, indented and
|
|
421
|
+
// inline code into <sub>/<sup> (96 such mangles in one RTL spec). As inline
|
|
422
|
+
// extensions marked tokenises code first, so these never fire inside code.
|
|
423
|
+
// The tokenizer also requires a single whitespace-free token (~x~ / ^x^), so
|
|
424
|
+
// spaced operator expressions (~a & ~b, a ^ b) and lone operators (2^24, ~rst)
|
|
425
|
+
// stay literal even in prose — only a genuine subscript/superscript converts.
|
|
426
|
+
marked.use({
|
|
427
|
+
extensions: [
|
|
428
|
+
{
|
|
429
|
+
name: 'subscript',
|
|
430
|
+
level: 'inline',
|
|
431
|
+
start(src) { const i = src.indexOf('~'); return i < 0 ? undefined : i; },
|
|
432
|
+
tokenizer(src) {
|
|
433
|
+
const m = /^~(?=\S)([^~\s\n]+)~/.exec(src);
|
|
434
|
+
if (m) {
|
|
435
|
+
return { type: 'subscript', raw: m[0], text: m[1],
|
|
436
|
+
tokens: this.lexer.inlineTokens(m[1]) };
|
|
437
|
+
}
|
|
438
|
+
},
|
|
439
|
+
renderer(token) { return `<sub>${this.parser.parseInline(token.tokens)}</sub>`; },
|
|
440
|
+
},
|
|
441
|
+
{
|
|
442
|
+
name: 'superscript',
|
|
443
|
+
level: 'inline',
|
|
444
|
+
start(src) { const i = src.indexOf('^'); return i < 0 ? undefined : i; },
|
|
445
|
+
tokenizer(src) {
|
|
446
|
+
const m = /^\^(?=\S)([^^\s\n]+)\^/.exec(src);
|
|
447
|
+
if (m) {
|
|
448
|
+
return { type: 'superscript', raw: m[0], text: m[1],
|
|
449
|
+
tokens: this.lexer.inlineTokens(m[1]) };
|
|
450
|
+
}
|
|
451
|
+
},
|
|
452
|
+
renderer(token) { return `<sup>${this.parser.parseInline(token.tokens)}</sup>`; },
|
|
453
|
+
},
|
|
454
|
+
],
|
|
455
|
+
});
|
|
456
|
+
|
|
457
|
+
// Pre-process the remaining non-standard inline syntax before marked parses
|
|
419
458
|
const escAttr = (s) => String(s)
|
|
420
459
|
.replace(/&/g, '&')
|
|
421
460
|
.replace(/</g, '<')
|
|
422
461
|
.replace(/>/g, '>')
|
|
423
462
|
.replace(/"/g, '"');
|
|
424
463
|
const mdPre = md
|
|
425
|
-
.replace(/\^([^^]+)\^/g, '<sup>$1</sup>') // ^a^ → <sup>a</sup>
|
|
426
|
-
.replace(/~([^~]+)~/g, '<sub>$1</sub>') // ~a~ → <sub>a</sub>
|
|
427
464
|
.replace(/\[\[([^\]\n]+)\]\]/g, (_, inner) => { // [[ref-id, §sub]] → clickable citation
|
|
428
465
|
const body = inner.trim();
|
|
429
466
|
const slug = body.split(',', 1)[0].trim();
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@helping-ai-workflow/md2doc",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.2.0",
|
|
4
4
|
"description": "Markdown → HTML / PDF renderer with WaveDrom, Mermaid, and Graphviz support",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"markdown",
|
|
@@ -31,7 +31,7 @@
|
|
|
31
31
|
},
|
|
32
32
|
"scripts": {
|
|
33
33
|
"preinstall": "node scripts/preinstall.js",
|
|
34
|
-
"test": "node test/md2doc.test.js && node test/cli.test.js"
|
|
34
|
+
"test": "node test/md2doc.test.js && node test/cli.test.js && node test/code-operator.test.js"
|
|
35
35
|
},
|
|
36
36
|
"repository": {
|
|
37
37
|
"type": "git",
|