@leadertechie/md2html 0.1.0-alpha.18 → 0.1.0-alpha.19
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 +152 -2
- package/dist/index.d.ts +266 -28
- package/dist/index.js +452 -435
- package/dist/index.js.map +1 -1
- package/dist/index2.js +4 -325
- package/dist/index2.js.map +1 -1
- package/dist/lit-renderer-Bp1Q6wYL.js +790 -0
- package/dist/lit-renderer-Bp1Q6wYL.js.map +1 -0
- package/dist/lit-renderer.d.ts +46 -2
- package/package.json +2 -1
package/dist/index.js
CHANGED
|
@@ -1,41 +1,6 @@
|
|
|
1
|
+
import { d as defaultAllowedHTMLTags, H as HTMLRenderer } from "./lit-renderer-Bp1Q6wYL.js";
|
|
2
|
+
import { L, a, b, c, e, f, g, h, i, j, k, l, m, n, R, o } from "./lit-renderer-Bp1Q6wYL.js";
|
|
1
3
|
import { marked } from "marked";
|
|
2
|
-
const defaultAllowedHTMLTags = [
|
|
3
|
-
"img",
|
|
4
|
-
"style",
|
|
5
|
-
"div",
|
|
6
|
-
"span",
|
|
7
|
-
"section",
|
|
8
|
-
"article",
|
|
9
|
-
"aside",
|
|
10
|
-
"header",
|
|
11
|
-
"footer",
|
|
12
|
-
"nav",
|
|
13
|
-
"main",
|
|
14
|
-
"figure",
|
|
15
|
-
"figcaption",
|
|
16
|
-
"details",
|
|
17
|
-
"summary",
|
|
18
|
-
"mark",
|
|
19
|
-
"time",
|
|
20
|
-
"video",
|
|
21
|
-
"audio",
|
|
22
|
-
"source",
|
|
23
|
-
"iframe",
|
|
24
|
-
"embed"
|
|
25
|
-
];
|
|
26
|
-
const nodeTypeToScope = {
|
|
27
|
-
"text": "root",
|
|
28
|
-
"heading": "heading",
|
|
29
|
-
"paragraph": "paragraph",
|
|
30
|
-
"list": "list",
|
|
31
|
-
"list-item": "list-item",
|
|
32
|
-
"image": "image",
|
|
33
|
-
"code": "code",
|
|
34
|
-
"container": "container",
|
|
35
|
-
"strong": "strong",
|
|
36
|
-
"emphasis": "emphasis",
|
|
37
|
-
"link": "link"
|
|
38
|
-
};
|
|
39
4
|
class HeadingHandler {
|
|
40
5
|
constructor() {
|
|
41
6
|
this.type = "heading";
|
|
@@ -268,7 +233,7 @@ class ContainerBlockHandler {
|
|
|
268
233
|
const classMatches = [...specifier.matchAll(/\.([\w-]+)/g)];
|
|
269
234
|
const tag = tagMatch?.[1] || "div";
|
|
270
235
|
const id = idMatch?.[1] || "";
|
|
271
|
-
const classes = classMatches.map((
|
|
236
|
+
const classes = classMatches.map((m2) => m2[1]);
|
|
272
237
|
const children = ctx.parseTokens(childTokens, 0);
|
|
273
238
|
return {
|
|
274
239
|
type: "container",
|
|
@@ -329,6 +294,392 @@ class TokenHandlerRegistry {
|
|
|
329
294
|
return this.catchAll;
|
|
330
295
|
}
|
|
331
296
|
}
|
|
297
|
+
var h2 = /* @__PURE__ */ ((t) => (t[t.DEBUG = 1] = "DEBUG", t[t.INFO = 9] = "INFO", t[t.WARN = 13] = "WARN", t[t.ERROR = 17] = "ERROR", t))(h2 || {});
|
|
298
|
+
const S = {
|
|
299
|
+
1: "DEBUG",
|
|
300
|
+
9: "INFO",
|
|
301
|
+
13: "WARN",
|
|
302
|
+
17: "ERROR"
|
|
303
|
+
}, E = [
|
|
304
|
+
"/telemetry/src/logger.ts",
|
|
305
|
+
"/telemetry/src/caller.ts",
|
|
306
|
+
"/telemetry/src/index.ts"
|
|
307
|
+
];
|
|
308
|
+
function N() {
|
|
309
|
+
const e2 = new Error().stack;
|
|
310
|
+
if (!e2) return;
|
|
311
|
+
const s = e2.split(`
|
|
312
|
+
`);
|
|
313
|
+
for (let r = 1; r < s.length; r++) {
|
|
314
|
+
const o2 = s[r].trim(), n2 = $(o2);
|
|
315
|
+
if (!n2) continue;
|
|
316
|
+
const { file: l2 } = n2;
|
|
317
|
+
if (!(l2 && E.some((m2) => l2.includes(m2))) && !(l2 && l2.includes("/node_modules/")) && l2)
|
|
318
|
+
return n2;
|
|
319
|
+
}
|
|
320
|
+
}
|
|
321
|
+
function $(t) {
|
|
322
|
+
const e2 = t.match(
|
|
323
|
+
/at\s+(?:(?:async\s+)?(?:(.+?)\s+\()?)?(?:(.+?):(\d+):(\d+)\)?)$/
|
|
324
|
+
);
|
|
325
|
+
if (!e2) return null;
|
|
326
|
+
const s = e2[1] || "<anonymous>", r = e2[2], o2 = parseInt(e2[3], 10), n2 = parseInt(e2[4], 10);
|
|
327
|
+
return r ? { file: r, line: o2, column: n2, functionName: s } : null;
|
|
328
|
+
}
|
|
329
|
+
class g2 {
|
|
330
|
+
constructor(e2 = [], s, r = {}) {
|
|
331
|
+
this.processors = [...e2], this.resource = s ?? { serviceName: "unknown" }, this.baseAttributes = { ...r };
|
|
332
|
+
}
|
|
333
|
+
// ── Public API ───────────────────────────────────────────────────────────
|
|
334
|
+
debug(e2, s) {
|
|
335
|
+
this.emit(h2.DEBUG, e2, void 0, s);
|
|
336
|
+
}
|
|
337
|
+
info(e2, s) {
|
|
338
|
+
this.emit(h2.INFO, e2, void 0, s);
|
|
339
|
+
}
|
|
340
|
+
warn(e2, s) {
|
|
341
|
+
this.emit(h2.WARN, e2, void 0, s);
|
|
342
|
+
}
|
|
343
|
+
error(e2, s, r) {
|
|
344
|
+
this.emit(h2.ERROR, e2, s, r);
|
|
345
|
+
}
|
|
346
|
+
/**
|
|
347
|
+
* Create a child logger with merged base attributes.
|
|
348
|
+
* Returns a NEW Logger — original is immutable.
|
|
349
|
+
*/
|
|
350
|
+
withContext(e2) {
|
|
351
|
+
return new g2(this.processors, this.resource, {
|
|
352
|
+
...this.baseAttributes,
|
|
353
|
+
...e2
|
|
354
|
+
});
|
|
355
|
+
}
|
|
356
|
+
/**
|
|
357
|
+
* Append a processor to the pipeline.
|
|
358
|
+
* Returns a NEW Logger — original is immutable.
|
|
359
|
+
*/
|
|
360
|
+
withProcessor(e2) {
|
|
361
|
+
return new g2(
|
|
362
|
+
[...this.processors, e2],
|
|
363
|
+
this.resource,
|
|
364
|
+
this.baseAttributes
|
|
365
|
+
);
|
|
366
|
+
}
|
|
367
|
+
/**
|
|
368
|
+
* Force-flush all pending records in all processors.
|
|
369
|
+
* Await before the end of a CF Worker request (inside ctx.waitUntil).
|
|
370
|
+
*/
|
|
371
|
+
async flush() {
|
|
372
|
+
await Promise.all(this.processors.map((e2) => e2.forceFlush()));
|
|
373
|
+
}
|
|
374
|
+
/**
|
|
375
|
+
* Shutdown: flush + release resources. No logging after shutdown.
|
|
376
|
+
*/
|
|
377
|
+
async shutdown() {
|
|
378
|
+
await this.flush(), await Promise.all(this.processors.map((e2) => e2.shutdown()));
|
|
379
|
+
}
|
|
380
|
+
// ── Internal ────────────────────────────────────────────────────────────
|
|
381
|
+
emit(e2, s, r, o2) {
|
|
382
|
+
if (this.processors.length === 0) return;
|
|
383
|
+
const n2 = (/* @__PURE__ */ new Date()).toISOString(), l2 = {
|
|
384
|
+
severityNumber: e2,
|
|
385
|
+
severityText: S[e2],
|
|
386
|
+
body: s,
|
|
387
|
+
timestamp: n2,
|
|
388
|
+
observedTimestamp: n2,
|
|
389
|
+
attributes: { ...this.baseAttributes, ...o2 },
|
|
390
|
+
caller: N(),
|
|
391
|
+
...r ? { error: r } : {},
|
|
392
|
+
resource: { ...this.resource }
|
|
393
|
+
};
|
|
394
|
+
for (const m2 of this.processors)
|
|
395
|
+
try {
|
|
396
|
+
m2.onEmit(l2);
|
|
397
|
+
} catch (f2) {
|
|
398
|
+
console.error(
|
|
399
|
+
"[telemetry] Processor threw in onEmit:",
|
|
400
|
+
f2
|
|
401
|
+
);
|
|
402
|
+
}
|
|
403
|
+
}
|
|
404
|
+
}
|
|
405
|
+
class T {
|
|
406
|
+
constructor(e2) {
|
|
407
|
+
this.shutdownFlag = false, this.pendingExport = Promise.resolve(), this.adapter = e2;
|
|
408
|
+
}
|
|
409
|
+
onEmit(e2) {
|
|
410
|
+
this.shutdownFlag || (this.pendingExport = this.pendingExport.then(() => this.adapter.export([e2])).catch((s) => {
|
|
411
|
+
console.error(
|
|
412
|
+
`[telemetry] SimpleLogProcessor: adapter "${this.adapter.name}" export failed:`,
|
|
413
|
+
s
|
|
414
|
+
);
|
|
415
|
+
}));
|
|
416
|
+
}
|
|
417
|
+
async forceFlush() {
|
|
418
|
+
await this.pendingExport;
|
|
419
|
+
}
|
|
420
|
+
async shutdown() {
|
|
421
|
+
this.shutdownFlag = true, await this.forceFlush(), await this.adapter.shutdown?.();
|
|
422
|
+
}
|
|
423
|
+
}
|
|
424
|
+
class M {
|
|
425
|
+
constructor(e2) {
|
|
426
|
+
this.processors = [], this.resource = {
|
|
427
|
+
serviceName: e2?.serviceName ?? "unknown",
|
|
428
|
+
environment: e2?.environment,
|
|
429
|
+
version: e2?.version,
|
|
430
|
+
processName: e2?.processName
|
|
431
|
+
};
|
|
432
|
+
}
|
|
433
|
+
/**
|
|
434
|
+
* Register an adapter via a SimpleLogProcessor (immediate export).
|
|
435
|
+
* For batching, use addProcessor(new BatchLogProcessor(adapter, opts)).
|
|
436
|
+
*/
|
|
437
|
+
addAdapter(e2) {
|
|
438
|
+
return this.addProcessor(new T(e2));
|
|
439
|
+
}
|
|
440
|
+
/**
|
|
441
|
+
* Register a custom processor (SimpleLogProcessor, BatchLogProcessor,
|
|
442
|
+
* or your own implementation).
|
|
443
|
+
*/
|
|
444
|
+
addProcessor(e2) {
|
|
445
|
+
return this.processors.push(e2), this;
|
|
446
|
+
}
|
|
447
|
+
/**
|
|
448
|
+
* Get a named Logger instance.
|
|
449
|
+
* The logger inherits the provider's resource and processors.
|
|
450
|
+
* Optionally provide initial context attributes.
|
|
451
|
+
*/
|
|
452
|
+
getLogger(e2, s) {
|
|
453
|
+
const r = {
|
|
454
|
+
...this.resource,
|
|
455
|
+
...e2 ? { processName: e2 } : {}
|
|
456
|
+
};
|
|
457
|
+
return new g2(this.processors, r, s);
|
|
458
|
+
}
|
|
459
|
+
/**
|
|
460
|
+
* Force-flush all registered processors.
|
|
461
|
+
*/
|
|
462
|
+
async flush() {
|
|
463
|
+
await Promise.all(this.processors.map((e2) => e2.forceFlush()));
|
|
464
|
+
}
|
|
465
|
+
/**
|
|
466
|
+
* Shutdown: flush + release all processor resources.
|
|
467
|
+
*/
|
|
468
|
+
async shutdown() {
|
|
469
|
+
await this.flush(), await Promise.all(this.processors.map((e2) => e2.shutdown()));
|
|
470
|
+
}
|
|
471
|
+
}
|
|
472
|
+
function U(t) {
|
|
473
|
+
const e2 = t?.level ?? h2.DEBUG, s = t?.json ?? false;
|
|
474
|
+
return {
|
|
475
|
+
name: "console",
|
|
476
|
+
async export(r) {
|
|
477
|
+
for (const o2 of r)
|
|
478
|
+
o2.severityNumber < e2 || (s ? I(o2) : R2(o2));
|
|
479
|
+
}
|
|
480
|
+
};
|
|
481
|
+
}
|
|
482
|
+
function R2(t) {
|
|
483
|
+
const e2 = F(t.severityNumber), s = t.timestamp, r = t.severityText, o2 = t.caller ? ` (${t.caller.file}:${t.caller.line})` : "", n2 = Object.keys(t.attributes).length > 0;
|
|
484
|
+
!!t.error ? e2(
|
|
485
|
+
`[${s}] [${r}]${o2} ${t.body}`,
|
|
486
|
+
t.attributes,
|
|
487
|
+
t.error
|
|
488
|
+
) : n2 ? e2(`[${s}] [${r}]${o2} ${t.body}`, t.attributes) : e2(`[${s}] [${r}]${o2} ${t.body}`);
|
|
489
|
+
}
|
|
490
|
+
function I(t) {
|
|
491
|
+
const e2 = {
|
|
492
|
+
timestamp: t.timestamp,
|
|
493
|
+
level: t.severityText,
|
|
494
|
+
message: t.body,
|
|
495
|
+
service: t.resource.serviceName,
|
|
496
|
+
environment: t.resource.environment,
|
|
497
|
+
attributes: t.attributes,
|
|
498
|
+
caller: t.caller
|
|
499
|
+
};
|
|
500
|
+
t.error && (e2.error = {
|
|
501
|
+
name: t.error.name,
|
|
502
|
+
message: t.error.message,
|
|
503
|
+
stack: t.error.stack
|
|
504
|
+
}), console.log(JSON.stringify(e2));
|
|
505
|
+
}
|
|
506
|
+
function F(t) {
|
|
507
|
+
switch (t) {
|
|
508
|
+
case h2.ERROR:
|
|
509
|
+
return console.error.bind(console);
|
|
510
|
+
case h2.WARN:
|
|
511
|
+
return console.warn.bind(console);
|
|
512
|
+
case h2.INFO:
|
|
513
|
+
return console.log.bind(console);
|
|
514
|
+
case h2.DEBUG:
|
|
515
|
+
default:
|
|
516
|
+
return console.debug.bind(console);
|
|
517
|
+
}
|
|
518
|
+
}
|
|
519
|
+
const defaultLoggers = /* @__PURE__ */ new Map();
|
|
520
|
+
function getDefaultLogger(serviceName) {
|
|
521
|
+
let log = defaultLoggers.get(serviceName);
|
|
522
|
+
if (!log) {
|
|
523
|
+
const provider = new M({ serviceName });
|
|
524
|
+
provider.addAdapter(U({ level: h2.WARN }));
|
|
525
|
+
log = provider.getLogger();
|
|
526
|
+
defaultLoggers.set(serviceName, log);
|
|
527
|
+
}
|
|
528
|
+
return log;
|
|
529
|
+
}
|
|
530
|
+
function createParseContext(services) {
|
|
531
|
+
const metadata = {};
|
|
532
|
+
return {
|
|
533
|
+
get preserveRawHTML() {
|
|
534
|
+
return services.preserveRawHTML;
|
|
535
|
+
},
|
|
536
|
+
get errorRecovery() {
|
|
537
|
+
return services.errorRecovery;
|
|
538
|
+
},
|
|
539
|
+
get maxRecursionDepth() {
|
|
540
|
+
return services.maxRecursionDepth;
|
|
541
|
+
},
|
|
542
|
+
processImagePath: (src) => services.processImagePath(src),
|
|
543
|
+
processInlineFormatting: (text) => services.processInlineFormatting(text),
|
|
544
|
+
processSlots: (text) => services.processSlots(text),
|
|
545
|
+
processRawHTML: (html) => services.processRawHTML(html),
|
|
546
|
+
parseTokens: (tokens, depth) => services.parseTokens(tokens, depth),
|
|
547
|
+
reportUnhandled: (type, token) => {
|
|
548
|
+
services.onUnhandledToken?.(type, token);
|
|
549
|
+
},
|
|
550
|
+
metadata
|
|
551
|
+
};
|
|
552
|
+
}
|
|
553
|
+
class ContainerBlockPreprocessor {
|
|
554
|
+
constructor() {
|
|
555
|
+
this.name = "container-blocks";
|
|
556
|
+
}
|
|
557
|
+
process(markdown) {
|
|
558
|
+
return markdown.replace(/^:::(?:(\w+(?:[.#][\w-]+)*)\s*)?$/gm, (_match, specifier) => {
|
|
559
|
+
if (!specifier) {
|
|
560
|
+
return "<!-- /md-container -->";
|
|
561
|
+
}
|
|
562
|
+
const normalized = specifier.match(/^\w/) ? specifier : `div${specifier}`;
|
|
563
|
+
return `<!-- md-container:${normalized} -->`;
|
|
564
|
+
});
|
|
565
|
+
}
|
|
566
|
+
}
|
|
567
|
+
class CompositePreprocessor {
|
|
568
|
+
constructor(processors) {
|
|
569
|
+
this.name = "composite";
|
|
570
|
+
this.processors = [];
|
|
571
|
+
if (processors) {
|
|
572
|
+
this.processors = [...processors];
|
|
573
|
+
}
|
|
574
|
+
}
|
|
575
|
+
/** Add a preprocessor to the chain. Returns `this` for fluent API. */
|
|
576
|
+
add(processor) {
|
|
577
|
+
this.processors.push(processor);
|
|
578
|
+
return this;
|
|
579
|
+
}
|
|
580
|
+
/** Remove a preprocessor by name. */
|
|
581
|
+
remove(name) {
|
|
582
|
+
this.processors = this.processors.filter((p) => p.name !== name);
|
|
583
|
+
}
|
|
584
|
+
/** Get the list of registered preprocessors. */
|
|
585
|
+
getProcessors() {
|
|
586
|
+
return [...this.processors];
|
|
587
|
+
}
|
|
588
|
+
process(markdown) {
|
|
589
|
+
let result = markdown;
|
|
590
|
+
for (const processor of this.processors) {
|
|
591
|
+
result = processor.process(result);
|
|
592
|
+
}
|
|
593
|
+
return result;
|
|
594
|
+
}
|
|
595
|
+
}
|
|
596
|
+
function createDefaultPreprocessor() {
|
|
597
|
+
return new CompositePreprocessor([
|
|
598
|
+
new ContainerBlockPreprocessor()
|
|
599
|
+
]);
|
|
600
|
+
}
|
|
601
|
+
class ContainerBlockPostprocessor {
|
|
602
|
+
constructor() {
|
|
603
|
+
this.name = "container-blocks";
|
|
604
|
+
}
|
|
605
|
+
process(tokens) {
|
|
606
|
+
const result = [];
|
|
607
|
+
const stack = [];
|
|
608
|
+
for (const token of tokens) {
|
|
609
|
+
const t = token;
|
|
610
|
+
if (t.type === "html") {
|
|
611
|
+
const raw = t.raw.trim();
|
|
612
|
+
const openMatch = raw.match(/^<!--\s*md-container:\s*(\S+)\s*-->$/);
|
|
613
|
+
const closeMatch = raw.match(/^<!--\s*\/md-container\s*-->$/);
|
|
614
|
+
if (openMatch) {
|
|
615
|
+
stack.push({
|
|
616
|
+
specifier: openMatch[1],
|
|
617
|
+
tokens: []
|
|
618
|
+
});
|
|
619
|
+
continue;
|
|
620
|
+
}
|
|
621
|
+
if (closeMatch) {
|
|
622
|
+
if (stack.length === 0) {
|
|
623
|
+
continue;
|
|
624
|
+
}
|
|
625
|
+
const container = stack.pop();
|
|
626
|
+
const processedInner = this.process(container.tokens);
|
|
627
|
+
const containerToken = {
|
|
628
|
+
type: "containerBlock",
|
|
629
|
+
specifier: container.specifier,
|
|
630
|
+
tokens: processedInner
|
|
631
|
+
};
|
|
632
|
+
if (stack.length > 0) {
|
|
633
|
+
stack[stack.length - 1].tokens.push(containerToken);
|
|
634
|
+
} else {
|
|
635
|
+
result.push(containerToken);
|
|
636
|
+
}
|
|
637
|
+
continue;
|
|
638
|
+
}
|
|
639
|
+
}
|
|
640
|
+
if (stack.length > 0) {
|
|
641
|
+
stack[stack.length - 1].tokens.push(token);
|
|
642
|
+
} else {
|
|
643
|
+
result.push(token);
|
|
644
|
+
}
|
|
645
|
+
}
|
|
646
|
+
return result;
|
|
647
|
+
}
|
|
648
|
+
}
|
|
649
|
+
class CompositeTokenPostprocessor {
|
|
650
|
+
constructor(processors) {
|
|
651
|
+
this.name = "composite";
|
|
652
|
+
this.processors = [];
|
|
653
|
+
if (processors) {
|
|
654
|
+
this.processors = [...processors];
|
|
655
|
+
}
|
|
656
|
+
}
|
|
657
|
+
/** Add a postprocessor to the chain. Returns `this` for fluent API. */
|
|
658
|
+
add(processor) {
|
|
659
|
+
this.processors.push(processor);
|
|
660
|
+
return this;
|
|
661
|
+
}
|
|
662
|
+
/** Remove a postprocessor by name. */
|
|
663
|
+
remove(name) {
|
|
664
|
+
this.processors = this.processors.filter((p) => p.name !== name);
|
|
665
|
+
}
|
|
666
|
+
/** Get the list of registered postprocessors. */
|
|
667
|
+
getProcessors() {
|
|
668
|
+
return [...this.processors];
|
|
669
|
+
}
|
|
670
|
+
process(tokens) {
|
|
671
|
+
let result = tokens;
|
|
672
|
+
for (const processor of this.processors) {
|
|
673
|
+
result = processor.process(result);
|
|
674
|
+
}
|
|
675
|
+
return result;
|
|
676
|
+
}
|
|
677
|
+
}
|
|
678
|
+
function createDefaultPostprocessor() {
|
|
679
|
+
return new CompositeTokenPostprocessor([
|
|
680
|
+
new ContainerBlockPostprocessor()
|
|
681
|
+
]);
|
|
682
|
+
}
|
|
332
683
|
const DEFAULT_SLOT_PATTERN = /\[\[(.*?)\]\]/g;
|
|
333
684
|
class MarkdownParser {
|
|
334
685
|
constructor(options) {
|
|
@@ -337,6 +688,7 @@ class MarkdownParser {
|
|
|
337
688
|
this.preserveRawHTML = options?.preserveRawHTML ?? false;
|
|
338
689
|
this.slotPattern = options?.slotPattern ?? DEFAULT_SLOT_PATTERN;
|
|
339
690
|
this.onSlot = options?.onSlot;
|
|
691
|
+
this.log = options?.logger ?? getDefaultLogger("md2html");
|
|
340
692
|
this.errorRecovery = options?.errorRecovery ?? "throw";
|
|
341
693
|
this.maxRecursionDepth = options?.maxRecursionDepth ?? 100;
|
|
342
694
|
this.allowedHTMLTags = /* @__PURE__ */ new Set([
|
|
@@ -346,11 +698,21 @@ class MarkdownParser {
|
|
|
346
698
|
this.allowedAttributes = options?.allowedAttributes ?? {};
|
|
347
699
|
this.handlerRegistry = new TokenHandlerRegistry();
|
|
348
700
|
this.onUnhandledToken = options?.onUnhandledToken;
|
|
701
|
+
this.preprocessor = createDefaultPreprocessor();
|
|
702
|
+
this.postprocessor = createDefaultPostprocessor();
|
|
349
703
|
}
|
|
350
704
|
/** Access the handler registry for customization. */
|
|
351
705
|
get handlers() {
|
|
352
706
|
return this.handlerRegistry;
|
|
353
707
|
}
|
|
708
|
+
/** Access the preprocessor chain for customization. */
|
|
709
|
+
get preprocessors() {
|
|
710
|
+
return this.preprocessor;
|
|
711
|
+
}
|
|
712
|
+
/** Access the token postprocessor chain for customization. */
|
|
713
|
+
get postprocessors() {
|
|
714
|
+
return this.postprocessor;
|
|
715
|
+
}
|
|
354
716
|
processImagePath(src) {
|
|
355
717
|
if (src.startsWith("http") || src.startsWith("/")) {
|
|
356
718
|
return src;
|
|
@@ -445,31 +807,20 @@ class MarkdownParser {
|
|
|
445
807
|
return html;
|
|
446
808
|
}
|
|
447
809
|
/**
|
|
448
|
-
* Build
|
|
449
|
-
*
|
|
810
|
+
* Build a ParserServices object that bridges the parser's private methods
|
|
811
|
+
* to the ParseContext factory. This keeps context creation decoupled.
|
|
450
812
|
*/
|
|
451
|
-
|
|
452
|
-
const self = this;
|
|
453
|
-
const metadata = {};
|
|
813
|
+
buildServices() {
|
|
454
814
|
return {
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
processImagePath: (src) => self.processImagePath(src),
|
|
465
|
-
processInlineFormatting: (text) => self.processInlineFormatting(text),
|
|
466
|
-
processSlots: (text) => self.processSlots(text),
|
|
467
|
-
processRawHTML: (html) => self.processRawHTML(html),
|
|
468
|
-
parseTokens: (tokens, depth) => self.parseTokens(tokens, depth),
|
|
469
|
-
reportUnhandled: (type, token) => {
|
|
470
|
-
self.onUnhandledToken?.(type, token);
|
|
471
|
-
},
|
|
472
|
-
metadata
|
|
815
|
+
preserveRawHTML: this.preserveRawHTML,
|
|
816
|
+
errorRecovery: this.errorRecovery,
|
|
817
|
+
maxRecursionDepth: this.maxRecursionDepth,
|
|
818
|
+
processImagePath: (src) => this.processImagePath(src),
|
|
819
|
+
processInlineFormatting: (text) => this.processInlineFormatting(text),
|
|
820
|
+
processSlots: (text) => this.processSlots(text),
|
|
821
|
+
processRawHTML: (html) => this.processRawHTML(html),
|
|
822
|
+
parseTokens: (tokens, depth) => this.parseTokens(tokens, depth),
|
|
823
|
+
onUnhandledToken: this.onUnhandledToken
|
|
473
824
|
};
|
|
474
825
|
}
|
|
475
826
|
/**
|
|
@@ -481,12 +832,12 @@ class MarkdownParser {
|
|
|
481
832
|
if (depth > this.maxRecursionDepth) {
|
|
482
833
|
const msg = `[md2html] Max recursion depth (${this.maxRecursionDepth}) exceeded, truncating`;
|
|
483
834
|
if (this.errorRecovery === "warn") {
|
|
484
|
-
|
|
835
|
+
this.log.warn(msg);
|
|
485
836
|
}
|
|
486
837
|
return [];
|
|
487
838
|
}
|
|
488
839
|
const nodes = [];
|
|
489
|
-
const ctx = sharedCtx || this.
|
|
840
|
+
const ctx = sharedCtx || createParseContext(this.buildServices());
|
|
490
841
|
for (const token of tokens) {
|
|
491
842
|
const typedToken = token;
|
|
492
843
|
const handler = this.handlerRegistry.get(typedToken.type);
|
|
@@ -497,82 +848,6 @@ class MarkdownParser {
|
|
|
497
848
|
}
|
|
498
849
|
return nodes;
|
|
499
850
|
}
|
|
500
|
-
/**
|
|
501
|
-
* Pre-process markdown: convert `:::tag#id.class` container syntax
|
|
502
|
-
* into HTML comment markers that marked will preserve as html tokens,
|
|
503
|
-
* but won't affect markdown parsing of the inner content.
|
|
504
|
-
*
|
|
505
|
-
* Example:
|
|
506
|
-
* :::section#header
|
|
507
|
-
* # Heading inside container
|
|
508
|
-
* Some text
|
|
509
|
-
* :::
|
|
510
|
-
*
|
|
511
|
-
* Becomes:
|
|
512
|
-
* <!-- md-container:section#header -->
|
|
513
|
-
* # Heading inside container
|
|
514
|
-
* Some text
|
|
515
|
-
* <!-- /md-container -->
|
|
516
|
-
*/
|
|
517
|
-
preprocessContainerBlocks(markdown) {
|
|
518
|
-
return markdown.replace(/^:::(?:(\w+(?:[.#][\w-]+)*)\s*)?$/gm, (match, specifier) => {
|
|
519
|
-
if (!specifier) {
|
|
520
|
-
return "<!-- /md-container -->";
|
|
521
|
-
}
|
|
522
|
-
const normalized = specifier.match(/^\w/) ? specifier : `div${specifier}`;
|
|
523
|
-
return `<!-- md-container:${normalized} -->`;
|
|
524
|
-
});
|
|
525
|
-
}
|
|
526
|
-
/**
|
|
527
|
-
* Post-process marked tokens to collapse container block markers
|
|
528
|
-
* into structured containerBlock tokens with proper nesting.
|
|
529
|
-
*
|
|
530
|
-
* This handles nesting depth up to maxRecursionDepth.
|
|
531
|
-
*/
|
|
532
|
-
postprocessTokens(tokens) {
|
|
533
|
-
const result = [];
|
|
534
|
-
const stack = [];
|
|
535
|
-
for (const token of tokens) {
|
|
536
|
-
const t = token;
|
|
537
|
-
if (t.type === "html") {
|
|
538
|
-
const raw = t.raw.trim();
|
|
539
|
-
const openMatch = raw.match(/^<!--\s*md-container:\s*(\S+)\s*-->$/);
|
|
540
|
-
const closeMatch = raw.match(/^<!--\s*\/md-container\s*-->$/);
|
|
541
|
-
if (openMatch) {
|
|
542
|
-
const newContainer = {
|
|
543
|
-
specifier: openMatch[1],
|
|
544
|
-
tokens: []
|
|
545
|
-
};
|
|
546
|
-
stack.push(newContainer);
|
|
547
|
-
continue;
|
|
548
|
-
}
|
|
549
|
-
if (closeMatch) {
|
|
550
|
-
if (stack.length === 0) {
|
|
551
|
-
continue;
|
|
552
|
-
}
|
|
553
|
-
const container = stack.pop();
|
|
554
|
-
const processedInner = this.postprocessTokens(container.tokens);
|
|
555
|
-
const containerToken = {
|
|
556
|
-
type: "containerBlock",
|
|
557
|
-
specifier: container.specifier,
|
|
558
|
-
tokens: processedInner
|
|
559
|
-
};
|
|
560
|
-
if (stack.length > 0) {
|
|
561
|
-
stack[stack.length - 1].tokens.push(containerToken);
|
|
562
|
-
} else {
|
|
563
|
-
result.push(containerToken);
|
|
564
|
-
}
|
|
565
|
-
continue;
|
|
566
|
-
}
|
|
567
|
-
}
|
|
568
|
-
if (stack.length > 0) {
|
|
569
|
-
stack[stack.length - 1].tokens.push(token);
|
|
570
|
-
} else {
|
|
571
|
-
result.push(token);
|
|
572
|
-
}
|
|
573
|
-
}
|
|
574
|
-
return result;
|
|
575
|
-
}
|
|
576
851
|
parse(markdown, options) {
|
|
577
852
|
const parseOptions = {
|
|
578
853
|
gfm: options?.gfm ?? true,
|
|
@@ -580,10 +855,10 @@ class MarkdownParser {
|
|
|
580
855
|
pedantic: options?.pedantic ?? false
|
|
581
856
|
};
|
|
582
857
|
try {
|
|
583
|
-
const processed = this.
|
|
858
|
+
const processed = this.preprocessor.process(markdown);
|
|
584
859
|
const rawTokens = marked.lexer(processed, parseOptions);
|
|
585
|
-
const tokens = this.
|
|
586
|
-
const ctx = this.
|
|
860
|
+
const tokens = this.postprocessor.process(rawTokens);
|
|
861
|
+
const ctx = createParseContext(this.buildServices());
|
|
587
862
|
const content = this.parseTokens(tokens, 0, ctx);
|
|
588
863
|
return {
|
|
589
864
|
title: "",
|
|
@@ -594,7 +869,7 @@ class MarkdownParser {
|
|
|
594
869
|
if (this.errorRecovery === "throw") throw err;
|
|
595
870
|
const msg = `[md2html] Parse error: ${err instanceof Error ? err.message : String(err)}`;
|
|
596
871
|
if (this.errorRecovery === "warn") {
|
|
597
|
-
|
|
872
|
+
this.log.warn(msg);
|
|
598
873
|
}
|
|
599
874
|
return {
|
|
600
875
|
title: "",
|
|
@@ -606,296 +881,9 @@ class MarkdownParser {
|
|
|
606
881
|
return this.parse(markdown, options).content;
|
|
607
882
|
}
|
|
608
883
|
}
|
|
609
|
-
class HeadingRendererStrategy {
|
|
610
|
-
constructor() {
|
|
611
|
-
this.type = "heading";
|
|
612
|
-
}
|
|
613
|
-
render(node, _renderChild, ctx) {
|
|
614
|
-
const level = node.attributes?.level || "2";
|
|
615
|
-
const headingId = ctx.addHeadingIds ? ` id="${ctx.generateHeadingId(node.content)}"` : "";
|
|
616
|
-
const scopeAttr = ctx.getScopeAttr(node);
|
|
617
|
-
if (!ctx.hasClassConfig()) {
|
|
618
|
-
return `<h${level}${headingId}${scopeAttr}>${node.content || ""}</h${level}>`;
|
|
619
|
-
}
|
|
620
|
-
const prefix = ctx.classPrefix;
|
|
621
|
-
const levelClass = level === "1" ? "h1" : level === "2" ? "h2" : level === "3" ? "h3" : level === "4" ? "h4" : level === "5" ? "h5" : "h6";
|
|
622
|
-
const headingClass = prefix ? `${prefix}${levelClass}` : levelClass;
|
|
623
|
-
return `<h${level}${headingId}${scopeAttr} class="${headingClass}">${node.content || ""}</h${level}>`;
|
|
624
|
-
}
|
|
625
|
-
}
|
|
626
|
-
class ParagraphRendererStrategy {
|
|
627
|
-
constructor() {
|
|
628
|
-
this.type = "paragraph";
|
|
629
|
-
}
|
|
630
|
-
render(node, renderChild, ctx) {
|
|
631
|
-
const scopeAttr = ctx.getScopeAttr(node);
|
|
632
|
-
if (node.children) {
|
|
633
|
-
const childrenHtml = node.children.map(renderChild).join("");
|
|
634
|
-
return ctx.hasClassConfig() && ctx.classPrefix ? `<p class="${ctx.classPrefix}paragraph"${scopeAttr}>${childrenHtml}</p>` : `<p${scopeAttr}>${childrenHtml}</p>`;
|
|
635
|
-
}
|
|
636
|
-
return ctx.hasClassConfig() && ctx.classPrefix ? `<p class="${ctx.classPrefix}paragraph"${scopeAttr}>${node.content || ""}</p>` : `<p${scopeAttr}>${node.content || ""}</p>`;
|
|
637
|
-
}
|
|
638
|
-
}
|
|
639
|
-
class ListRendererStrategy {
|
|
640
|
-
constructor() {
|
|
641
|
-
this.type = "list";
|
|
642
|
-
}
|
|
643
|
-
render(node, renderChild, ctx) {
|
|
644
|
-
const tag = node.ordered ? "ol" : "ul";
|
|
645
|
-
const items = node.children?.map(renderChild).join("") || "";
|
|
646
|
-
const scopeAttr = ctx.getScopeAttr(node);
|
|
647
|
-
return ctx.hasClassConfig() && ctx.classPrefix ? `<${tag} class="${ctx.classPrefix}list"${scopeAttr}>${items}</${tag}>` : `<${tag}${scopeAttr}>${items}</${tag}>`;
|
|
648
|
-
}
|
|
649
|
-
}
|
|
650
|
-
class ListItemRendererStrategy {
|
|
651
|
-
constructor() {
|
|
652
|
-
this.type = "list-item";
|
|
653
|
-
}
|
|
654
|
-
render(node, _renderChild, ctx) {
|
|
655
|
-
const scopeAttr = ctx.getScopeAttr(node);
|
|
656
|
-
return ctx.hasClassConfig() && ctx.classPrefix ? `<li class="${ctx.classPrefix}list-item"${scopeAttr}>${node.content || ""}</li>` : `<li${scopeAttr}>${node.content || ""}</li>`;
|
|
657
|
-
}
|
|
658
|
-
}
|
|
659
|
-
class ImageRendererStrategy {
|
|
660
|
-
constructor() {
|
|
661
|
-
this.type = "image";
|
|
662
|
-
}
|
|
663
|
-
render(node, _renderChild, ctx) {
|
|
664
|
-
const src = node.src || node.attributes?.src || "";
|
|
665
|
-
const alt = node.alt || node.attributes?.alt || "";
|
|
666
|
-
const scopeAttr = ctx.getScopeAttr(node);
|
|
667
|
-
let classStr = "";
|
|
668
|
-
if (ctx.hasClassConfig()) {
|
|
669
|
-
const prefix = ctx.classPrefix;
|
|
670
|
-
classStr = prefix ? `${prefix}image` : "image";
|
|
671
|
-
if (node.className) classStr += ` ${node.className}`;
|
|
672
|
-
return `<img src="${src}" alt="${alt}" class="${classStr}"${scopeAttr}>`;
|
|
673
|
-
}
|
|
674
|
-
if (node.className) {
|
|
675
|
-
return `<img src="${src}" alt="${alt}" class="${node.className}"${scopeAttr}>`;
|
|
676
|
-
}
|
|
677
|
-
return `<img src="${src}" alt="${alt}"${scopeAttr}>`;
|
|
678
|
-
}
|
|
679
|
-
}
|
|
680
|
-
class CodeRendererStrategy {
|
|
681
|
-
constructor() {
|
|
682
|
-
this.type = "code";
|
|
683
|
-
}
|
|
684
|
-
render(node, _renderChild, ctx) {
|
|
685
|
-
const scopeAttr = ctx.getScopeAttr(node);
|
|
686
|
-
const lang = node.attributes?.lang || "";
|
|
687
|
-
if (ctx.hasClassConfig()) {
|
|
688
|
-
const prefix = ctx.classPrefix;
|
|
689
|
-
const codeClass = prefix ? `${prefix}code` : "code";
|
|
690
|
-
return `<pre${scopeAttr}><code class="${codeClass} language-${lang}">${node.content || ""}</code></pre>`;
|
|
691
|
-
}
|
|
692
|
-
return `<pre${scopeAttr}><code class="language-${lang}">${node.content || ""}</code></pre>`;
|
|
693
|
-
}
|
|
694
|
-
}
|
|
695
|
-
class ContainerRendererStrategy {
|
|
696
|
-
constructor() {
|
|
697
|
-
this.type = "container";
|
|
698
|
-
}
|
|
699
|
-
render(node, renderChild, ctx) {
|
|
700
|
-
if (node.rawHTML) {
|
|
701
|
-
return node.rawHTML;
|
|
702
|
-
}
|
|
703
|
-
const tag = node.attributes?.tag || "div";
|
|
704
|
-
const children = node.children?.map(renderChild).join("") || "";
|
|
705
|
-
const id = node.attributes?.id;
|
|
706
|
-
const idAttr = id ? ` id="${id}"` : "";
|
|
707
|
-
const scopeAttr = ctx.getScopeAttr(node);
|
|
708
|
-
if (tag === "hr") return "<hr>";
|
|
709
|
-
if (ctx.hasClassConfig()) {
|
|
710
|
-
const containerClass = ctx.getContainerClass(tag);
|
|
711
|
-
const prefix = ctx.classPrefix;
|
|
712
|
-
if (prefix) {
|
|
713
|
-
const classes2 = [prefix + (containerClass || "container")];
|
|
714
|
-
if (node.className) classes2.push(node.className);
|
|
715
|
-
return `<${tag} class="${classes2.join(" ")}"${idAttr}${scopeAttr}>${children}</${tag}>`;
|
|
716
|
-
}
|
|
717
|
-
const classes = [containerClass || "container"];
|
|
718
|
-
if (node.className) classes.push(node.className);
|
|
719
|
-
return `<${tag} class="${classes.join(" ")}"${idAttr}${scopeAttr}>${children}</${tag}>`;
|
|
720
|
-
}
|
|
721
|
-
if (node.className) {
|
|
722
|
-
return `<${tag} class="${node.className}"${idAttr}${scopeAttr}>${children}</${tag}>`;
|
|
723
|
-
}
|
|
724
|
-
return `<${tag}${idAttr}${scopeAttr}>${children}</${tag}>`;
|
|
725
|
-
}
|
|
726
|
-
}
|
|
727
|
-
class StrongRendererStrategy {
|
|
728
|
-
constructor() {
|
|
729
|
-
this.type = "strong";
|
|
730
|
-
}
|
|
731
|
-
render(node, _renderChild, ctx) {
|
|
732
|
-
return `<strong${ctx.getScopeAttr(node)}>${node.content || ""}</strong>`;
|
|
733
|
-
}
|
|
734
|
-
}
|
|
735
|
-
class EmphasisRendererStrategy {
|
|
736
|
-
constructor() {
|
|
737
|
-
this.type = "emphasis";
|
|
738
|
-
}
|
|
739
|
-
render(node, _renderChild, ctx) {
|
|
740
|
-
return `<em${ctx.getScopeAttr(node)}>${node.content || ""}</em>`;
|
|
741
|
-
}
|
|
742
|
-
}
|
|
743
|
-
class LinkRendererStrategy {
|
|
744
|
-
constructor() {
|
|
745
|
-
this.type = "link";
|
|
746
|
-
}
|
|
747
|
-
render(node, _renderChild, ctx) {
|
|
748
|
-
const href = node.attributes?.href || "";
|
|
749
|
-
return `<a href="${href}"${ctx.getScopeAttr(node)}>${node.content || ""}</a>`;
|
|
750
|
-
}
|
|
751
|
-
}
|
|
752
|
-
class TextRendererStrategy {
|
|
753
|
-
constructor() {
|
|
754
|
-
this.type = "text";
|
|
755
|
-
}
|
|
756
|
-
render(node, _renderChild, _ctx) {
|
|
757
|
-
return node.content || "";
|
|
758
|
-
}
|
|
759
|
-
}
|
|
760
|
-
class RendererStrategyRegistry {
|
|
761
|
-
constructor() {
|
|
762
|
-
this.strategies = /* @__PURE__ */ new Map();
|
|
763
|
-
this.register(new HeadingRendererStrategy());
|
|
764
|
-
this.register(new ParagraphRendererStrategy());
|
|
765
|
-
this.register(new ListRendererStrategy());
|
|
766
|
-
this.register(new ListItemRendererStrategy());
|
|
767
|
-
this.register(new ImageRendererStrategy());
|
|
768
|
-
this.register(new CodeRendererStrategy());
|
|
769
|
-
this.register(new ContainerRendererStrategy());
|
|
770
|
-
this.register(new StrongRendererStrategy());
|
|
771
|
-
this.register(new EmphasisRendererStrategy());
|
|
772
|
-
this.register(new LinkRendererStrategy());
|
|
773
|
-
this.register(new TextRendererStrategy());
|
|
774
|
-
this.fallback = new TextRendererStrategy();
|
|
775
|
-
}
|
|
776
|
-
/** Register a strategy for a node type. Overrides any existing strategy. */
|
|
777
|
-
register(strategy) {
|
|
778
|
-
this.strategies.set(strategy.type, strategy);
|
|
779
|
-
}
|
|
780
|
-
/** Unregister a strategy by node type. */
|
|
781
|
-
unregister(type) {
|
|
782
|
-
this.strategies.delete(type);
|
|
783
|
-
}
|
|
784
|
-
/** Get a strategy for the given node type, falling back to catch-all. */
|
|
785
|
-
get(type) {
|
|
786
|
-
return this.strategies.get(type) ?? this.fallback;
|
|
787
|
-
}
|
|
788
|
-
/** Check if a dedicated strategy exists for the given node type. */
|
|
789
|
-
has(type) {
|
|
790
|
-
return this.strategies.has(type);
|
|
791
|
-
}
|
|
792
|
-
/** Get all registered dedicated strategy types. */
|
|
793
|
-
get types() {
|
|
794
|
-
return Array.from(this.strategies.keys());
|
|
795
|
-
}
|
|
796
|
-
/** Replace the fallback strategy. */
|
|
797
|
-
setFallback(strategy) {
|
|
798
|
-
this.fallback = strategy;
|
|
799
|
-
}
|
|
800
|
-
}
|
|
801
|
-
class HTMLRenderer {
|
|
802
|
-
constructor(config = {}) {
|
|
803
|
-
this.config = {
|
|
804
|
-
classPrefix: config.classPrefix || "",
|
|
805
|
-
customCSS: config.customCSS || "",
|
|
806
|
-
addHeadingIds: config.addHeadingIds ?? false,
|
|
807
|
-
emitScopeAnchors: config.emitScopeAnchors ?? false
|
|
808
|
-
};
|
|
809
|
-
this.strategyRegistry = new RendererStrategyRegistry();
|
|
810
|
-
}
|
|
811
|
-
/** Access the strategy registry for customization. */
|
|
812
|
-
get strategies() {
|
|
813
|
-
return this.strategyRegistry;
|
|
814
|
-
}
|
|
815
|
-
hasClassConfig() {
|
|
816
|
-
return this.config.classPrefix !== "" || this.config.addHeadingIds;
|
|
817
|
-
}
|
|
818
|
-
getClass(baseClass, nodeClass) {
|
|
819
|
-
if (!this.hasClassConfig()) {
|
|
820
|
-
return nodeClass || "";
|
|
821
|
-
}
|
|
822
|
-
const prefix = this.config.classPrefix;
|
|
823
|
-
const classes = [prefix ? `${prefix}${baseClass}` : baseClass];
|
|
824
|
-
if (nodeClass) classes.push(nodeClass);
|
|
825
|
-
return classes.join(" ");
|
|
826
|
-
}
|
|
827
|
-
generateHeadingId(content) {
|
|
828
|
-
if (!content) return "";
|
|
829
|
-
return content.toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/(^-|-$)/g, "");
|
|
830
|
-
}
|
|
831
|
-
/**
|
|
832
|
-
* Get the scope attribute string for a node type.
|
|
833
|
-
* Returns empty string if emitScopeAnchors is disabled.
|
|
834
|
-
*/
|
|
835
|
-
getScopeAttr(node) {
|
|
836
|
-
if (!this.config.emitScopeAnchors) return "";
|
|
837
|
-
const scopeValue = node.scope || nodeTypeToScope[node.type] || "container";
|
|
838
|
-
return ` data-md-scope="${scopeValue}"`;
|
|
839
|
-
}
|
|
840
|
-
/**
|
|
841
|
-
* Get the CSS class for a container's tag-based rendering.
|
|
842
|
-
* Returns just the tag name since renderWithClass applies the prefix.
|
|
843
|
-
*/
|
|
844
|
-
getContainerClass(tag) {
|
|
845
|
-
if (!this.hasClassConfig()) return "";
|
|
846
|
-
return tag;
|
|
847
|
-
}
|
|
848
|
-
buildRenderContext() {
|
|
849
|
-
const self = this;
|
|
850
|
-
return {
|
|
851
|
-
get classPrefix() {
|
|
852
|
-
return self.config.classPrefix;
|
|
853
|
-
},
|
|
854
|
-
get addHeadingIds() {
|
|
855
|
-
return self.config.addHeadingIds;
|
|
856
|
-
},
|
|
857
|
-
get emitScopeAnchors() {
|
|
858
|
-
return self.config.emitScopeAnchors;
|
|
859
|
-
},
|
|
860
|
-
get customCSS() {
|
|
861
|
-
return self.config.customCSS;
|
|
862
|
-
},
|
|
863
|
-
hasClassConfig: () => self.hasClassConfig(),
|
|
864
|
-
getClass: (baseClass, nodeClass) => self.getClass(baseClass, nodeClass),
|
|
865
|
-
getScopeAttr: (node) => self.getScopeAttr(node),
|
|
866
|
-
generateHeadingId: (content) => self.generateHeadingId(content),
|
|
867
|
-
getContainerClass: (tag) => self.getContainerClass(tag)
|
|
868
|
-
};
|
|
869
|
-
}
|
|
870
|
-
renderNode(node) {
|
|
871
|
-
const ctx = this.buildRenderContext();
|
|
872
|
-
const strategy = this.strategyRegistry.get(node.type);
|
|
873
|
-
return strategy.render(node, (child) => this.renderNode(child), ctx);
|
|
874
|
-
}
|
|
875
|
-
renderNodes(nodes) {
|
|
876
|
-
if (!nodes || nodes.length === 0) {
|
|
877
|
-
return "";
|
|
878
|
-
}
|
|
879
|
-
if (this.config.emitScopeAnchors) {
|
|
880
|
-
const inner = nodes.map((node) => this.renderNode(node)).join("\n");
|
|
881
|
-
return `<div data-md-scope="root">
|
|
882
|
-
${inner}
|
|
883
|
-
</div>`;
|
|
884
|
-
}
|
|
885
|
-
return nodes.map((node) => this.renderNode(node)).join("\n");
|
|
886
|
-
}
|
|
887
|
-
renderToHTMLString(nodes) {
|
|
888
|
-
return this.renderNodes(nodes);
|
|
889
|
-
}
|
|
890
|
-
render(markdown) {
|
|
891
|
-
return markdown;
|
|
892
|
-
}
|
|
893
|
-
getCustomCSS() {
|
|
894
|
-
return this.config.customCSS;
|
|
895
|
-
}
|
|
896
|
-
}
|
|
897
884
|
class MarkdownPipeline {
|
|
898
885
|
constructor(config = {}) {
|
|
886
|
+
this.log = config.logger ?? getDefaultLogger("md2html");
|
|
899
887
|
this.config = {
|
|
900
888
|
imagePathPrefix: config.imagePathPrefix || "",
|
|
901
889
|
imageBaseUrl: config.imageBaseUrl || "",
|
|
@@ -941,8 +929,16 @@ class MarkdownPipeline {
|
|
|
941
929
|
return this.renderer.renderNodes(nodes);
|
|
942
930
|
}
|
|
943
931
|
renderMarkdown(markdown) {
|
|
944
|
-
|
|
945
|
-
|
|
932
|
+
try {
|
|
933
|
+
const nodes = this.parse(markdown);
|
|
934
|
+
return this.render(nodes);
|
|
935
|
+
} catch (err) {
|
|
936
|
+
this.log.error("Markdown render failed", err, {
|
|
937
|
+
length: markdown.length,
|
|
938
|
+
recovery: this.config.errorRecovery
|
|
939
|
+
});
|
|
940
|
+
throw err;
|
|
941
|
+
}
|
|
946
942
|
}
|
|
947
943
|
renderPage(title, nodes, options) {
|
|
948
944
|
const html = this.render(nodes);
|
|
@@ -1087,7 +1083,11 @@ export {
|
|
|
1087
1083
|
BlockquoteHandler,
|
|
1088
1084
|
CatchAllHandler,
|
|
1089
1085
|
CodeHandler,
|
|
1086
|
+
CompositePreprocessor,
|
|
1087
|
+
CompositeTokenPostprocessor,
|
|
1090
1088
|
ContainerBlockHandler,
|
|
1089
|
+
ContainerBlockPostprocessor,
|
|
1090
|
+
ContainerBlockPreprocessor,
|
|
1091
1091
|
FrontmatterHandler,
|
|
1092
1092
|
HTMLRenderer,
|
|
1093
1093
|
HeadingHandler,
|
|
@@ -1096,18 +1096,35 @@ export {
|
|
|
1096
1096
|
ImageHandler,
|
|
1097
1097
|
LinkHandler,
|
|
1098
1098
|
ListHandler,
|
|
1099
|
+
L as LitCodeStrategy,
|
|
1100
|
+
a as LitContainerStrategy,
|
|
1101
|
+
b as LitEmphasisStrategy,
|
|
1102
|
+
c as LitFallbackStrategy,
|
|
1103
|
+
e as LitHeadingStrategy,
|
|
1104
|
+
f as LitImageStrategy,
|
|
1105
|
+
g as LitLinkStrategy,
|
|
1106
|
+
h as LitListItemStrategy,
|
|
1107
|
+
i as LitListStrategy,
|
|
1108
|
+
j as LitParagraphStrategy,
|
|
1109
|
+
k as LitRenderer,
|
|
1110
|
+
l as LitStrategyRegistry,
|
|
1111
|
+
m as LitStrongStrategy,
|
|
1112
|
+
n as LitTextStrategy,
|
|
1099
1113
|
MarkdownParser,
|
|
1100
1114
|
MarkdownPipeline,
|
|
1101
1115
|
NodeFactory,
|
|
1102
1116
|
ParagraphHandler,
|
|
1103
|
-
RendererStrategyRegistry,
|
|
1117
|
+
R as RendererStrategyRegistry,
|
|
1104
1118
|
TokenHandlerRegistry,
|
|
1105
1119
|
collectByType,
|
|
1106
1120
|
collectFromTree,
|
|
1107
1121
|
collectHeadings,
|
|
1108
1122
|
collectImages,
|
|
1123
|
+
createDefaultPostprocessor,
|
|
1124
|
+
createDefaultPreprocessor,
|
|
1125
|
+
createParseContext,
|
|
1109
1126
|
defaultAllowedHTMLTags,
|
|
1110
|
-
nodeTypeToScope,
|
|
1127
|
+
o as nodeTypeToScope,
|
|
1111
1128
|
walkTree
|
|
1112
1129
|
};
|
|
1113
1130
|
//# sourceMappingURL=index.js.map
|