@vectojs/markdown 0.14.0 → 0.16.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 +79 -17
- package/dist/Markdown.d.ts +61 -154
- package/dist/MarkdownWorkerSource.d.ts +1 -1
- package/dist/index.d.ts +2 -0
- package/dist/index.js +1706 -1353
- package/dist/index.mjs +1519 -1175
- package/dist/markdown-code.d.ts +102 -0
- package/dist/markdown-entities.d.ts +33 -0
- package/dist/markdown-footnote.d.ts +133 -0
- package/dist/markdown-image.d.ts +126 -0
- package/dist/markdown-inline.d.ts +58 -0
- package/dist/markdown-math.d.ts +169 -0
- package/dist/theme.d.ts +179 -0
- package/package.json +8 -7
package/dist/index.js
CHANGED
|
@@ -40,6 +40,7 @@ __export(index_exports, {
|
|
|
40
40
|
escapeCsvField: () => escapeCsvField,
|
|
41
41
|
escapeMarkdownTableCell: () => escapeMarkdownTableCell,
|
|
42
42
|
extensionForLanguage: () => extensionForLanguage,
|
|
43
|
+
footnoteMarker: () => footnoteMarker,
|
|
43
44
|
isMathJaxReady: () => isMathJaxReady,
|
|
44
45
|
mimeForLanguage: () => mimeForLanguage,
|
|
45
46
|
parseFrontMatterFields: () => parseFrontMatterFields,
|
|
@@ -52,7 +53,7 @@ __export(index_exports, {
|
|
|
52
53
|
module.exports = __toCommonJS(index_exports);
|
|
53
54
|
|
|
54
55
|
// src/Markdown.ts
|
|
55
|
-
var
|
|
56
|
+
var import_core4 = require("@vectojs/core");
|
|
56
57
|
var import_marked = require("marked");
|
|
57
58
|
|
|
58
59
|
// src/StreamController.ts
|
|
@@ -464,726 +465,803 @@ function createStreamController(host, options = {}) {
|
|
|
464
465
|
return new StreamControllerImpl(host, options);
|
|
465
466
|
}
|
|
466
467
|
|
|
467
|
-
// src/
|
|
468
|
-
var
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
cs: "cs",
|
|
477
|
-
css: "css",
|
|
478
|
-
diff: "diff",
|
|
479
|
-
dockerfile: "dockerfile",
|
|
480
|
-
go: "go",
|
|
481
|
-
graphql: "graphql",
|
|
482
|
-
haskell: "hs",
|
|
483
|
-
html: "html",
|
|
484
|
-
java: "java",
|
|
485
|
-
javascript: "js",
|
|
486
|
-
js: "js",
|
|
487
|
-
json: "json",
|
|
488
|
-
jsonc: "jsonc",
|
|
489
|
-
jsx: "jsx",
|
|
490
|
-
kotlin: "kt",
|
|
491
|
-
latex: "tex",
|
|
492
|
-
lua: "lua",
|
|
493
|
-
make: "mk",
|
|
494
|
-
markdown: "md",
|
|
495
|
-
md: "md",
|
|
496
|
-
nix: "nix",
|
|
497
|
-
php: "php",
|
|
498
|
-
python: "py",
|
|
499
|
-
py: "py",
|
|
500
|
-
ruby: "rb",
|
|
501
|
-
rust: "rs",
|
|
502
|
-
rs: "rs",
|
|
503
|
-
scss: "scss",
|
|
504
|
-
sh: "sh",
|
|
505
|
-
shell: "sh",
|
|
506
|
-
sql: "sql",
|
|
507
|
-
svelte: "svelte",
|
|
508
|
-
swift: "swift",
|
|
509
|
-
tex: "tex",
|
|
510
|
-
toml: "toml",
|
|
511
|
-
ts: "ts",
|
|
512
|
-
tsx: "tsx",
|
|
513
|
-
typescript: "ts",
|
|
514
|
-
vue: "vue",
|
|
515
|
-
xml: "xml",
|
|
516
|
-
yaml: "yaml",
|
|
517
|
-
yml: "yaml",
|
|
518
|
-
zig: "zig",
|
|
519
|
-
zsh: "sh"
|
|
520
|
-
};
|
|
521
|
-
function extensionForLanguage(lang) {
|
|
522
|
-
const first = lang.trim().toLowerCase().split(/[\s:,{]/)[0] ?? "";
|
|
523
|
-
return LANGUAGE_EXTENSIONS[first] ?? "txt";
|
|
524
|
-
}
|
|
525
|
-
function mimeForLanguage(lang) {
|
|
526
|
-
const ext = extensionForLanguage(lang);
|
|
527
|
-
if (ext === "json" || ext === "jsonc") return "application/json";
|
|
528
|
-
if (ext === "html") return "text/html";
|
|
529
|
-
if (ext === "css") return "text/css";
|
|
530
|
-
if (ext === "xml" || ext === "svelte" || ext === "vue") return "text/plain";
|
|
531
|
-
return "text/plain";
|
|
532
|
-
}
|
|
533
|
-
function escapeCsvField(value) {
|
|
534
|
-
let needsQuoting = false;
|
|
535
|
-
let hasQuote = false;
|
|
536
|
-
for (const char of value) {
|
|
537
|
-
if (char === '"') {
|
|
538
|
-
hasQuote = true;
|
|
539
|
-
needsQuoting = true;
|
|
540
|
-
break;
|
|
541
|
-
}
|
|
542
|
-
if (char === "," || char === "\n" || char === "\r") needsQuoting = true;
|
|
543
|
-
}
|
|
544
|
-
if (!needsQuoting) return value;
|
|
545
|
-
return hasQuote ? `"${value.replace(/"/g, '""')}"` : `"${value}"`;
|
|
546
|
-
}
|
|
547
|
-
function escapeMarkdownTableCell(cell) {
|
|
548
|
-
let needsEscaping = false;
|
|
549
|
-
for (const char of cell) {
|
|
550
|
-
if (char === "\\" || char === "|") {
|
|
551
|
-
needsEscaping = true;
|
|
552
|
-
break;
|
|
553
|
-
}
|
|
554
|
-
}
|
|
555
|
-
if (!needsEscaping) return cell;
|
|
556
|
-
return cell.replace(/\\/g, "\\\\").replace(/\|/g, "\\|");
|
|
557
|
-
}
|
|
558
|
-
function tableToCsv(table) {
|
|
559
|
-
const lines = [table.headers.map(escapeCsvField).join(",")];
|
|
560
|
-
for (const row of table.rows) lines.push(row.map(escapeCsvField).join(","));
|
|
561
|
-
return `\uFEFF${lines.join("\r\n")}`;
|
|
562
|
-
}
|
|
563
|
-
function tableToMarkdown(table) {
|
|
564
|
-
const header = `| ${table.headers.map(escapeMarkdownTableCell).join(" | ")} |`;
|
|
565
|
-
const divider = `| ${table.headers.map((_cell, index) => {
|
|
566
|
-
switch (table.align[index]) {
|
|
567
|
-
case "left":
|
|
568
|
-
return ":---";
|
|
569
|
-
case "center":
|
|
570
|
-
return ":---:";
|
|
571
|
-
case "right":
|
|
572
|
-
return "---:";
|
|
573
|
-
default:
|
|
574
|
-
return "---";
|
|
575
|
-
}
|
|
576
|
-
}).join(" | ")} |`;
|
|
577
|
-
const body = table.rows.map(
|
|
578
|
-
(row) => `| ${table.headers.map((_cell, index) => escapeMarkdownTableCell(row[index] ?? "")).join(" | ")} |`
|
|
579
|
-
);
|
|
580
|
-
return [header, divider, ...body].join("\n");
|
|
581
|
-
}
|
|
582
|
-
function defaultWriteClipboard(text) {
|
|
583
|
-
const clipboard = globalThis.navigator?.clipboard;
|
|
584
|
-
clipboard?.writeText?.(text);
|
|
585
|
-
}
|
|
586
|
-
function defaultSaveFile(filename, content, mimeType) {
|
|
587
|
-
const doc = globalThis.document;
|
|
588
|
-
if (!doc?.body) return;
|
|
589
|
-
const blob = new Blob([content], { type: mimeType });
|
|
590
|
-
const url = URL.createObjectURL(blob);
|
|
591
|
-
const anchor = doc.createElement("a");
|
|
592
|
-
anchor.href = url;
|
|
593
|
-
anchor.download = filename;
|
|
594
|
-
doc.body.appendChild(anchor);
|
|
595
|
-
anchor.click();
|
|
596
|
-
doc.body.removeChild(anchor);
|
|
597
|
-
URL.revokeObjectURL(url);
|
|
598
|
-
}
|
|
599
|
-
var BlockAffordanceButton = class _BlockAffordanceButton extends import_ui.Button {
|
|
600
|
-
constructor(label, successLabel, act, opts = {}) {
|
|
601
|
-
super(label, { ...opts, onClick: () => this.run() });
|
|
602
|
-
this.act = act;
|
|
603
|
-
this.restingLabel = label;
|
|
604
|
-
this.successLabel = successLabel;
|
|
605
|
-
this.width = Math.max(this.width, (0, import_ui.measureText)(successLabel, this.font) + 24);
|
|
606
|
-
}
|
|
607
|
-
act;
|
|
608
|
-
/** How long the confirmation label stays up, in ms. */
|
|
609
|
-
static FEEDBACK_MS = 1600;
|
|
610
|
-
restingLabel;
|
|
611
|
-
successLabel;
|
|
612
|
-
feedbackTimer;
|
|
613
|
-
/**
|
|
614
|
-
* Runs the action, then shows the confirmation.
|
|
615
|
-
*
|
|
616
|
-
* The action runs first and a throw propagates: a clipboard write the browser
|
|
617
|
-
* rejected must not be reported as a success.
|
|
618
|
-
*/
|
|
619
|
-
run() {
|
|
620
|
-
this.act();
|
|
621
|
-
this.setTransientLabel(this.successLabel);
|
|
622
|
-
if (this.feedbackTimer !== void 0) clearTimeout(this.feedbackTimer);
|
|
623
|
-
this.feedbackTimer = setTimeout(() => {
|
|
624
|
-
this.setTransientLabel(this.restingLabel);
|
|
625
|
-
this.feedbackTimer = void 0;
|
|
626
|
-
}, _BlockAffordanceButton.FEEDBACK_MS);
|
|
627
|
-
}
|
|
628
|
-
setTransientLabel(label) {
|
|
629
|
-
this.label = label;
|
|
630
|
-
this.textWidth = (0, import_ui.measureText)(label, this.font);
|
|
631
|
-
this.scene?.markDirty();
|
|
468
|
+
// src/markdown-entities.ts
|
|
469
|
+
var import_core = require("@vectojs/core");
|
|
470
|
+
var HorizontalRule = class extends import_core.Entity {
|
|
471
|
+
color;
|
|
472
|
+
constructor(w, color) {
|
|
473
|
+
super();
|
|
474
|
+
this.width = w;
|
|
475
|
+
this.height = 1;
|
|
476
|
+
this.color = color;
|
|
632
477
|
}
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
* included, so an AT user gets the same feedback a sighted user does.
|
|
636
|
-
*/
|
|
637
|
-
getA11yAttributes() {
|
|
638
|
-
return { ...super.getA11yAttributes(), label: this.label };
|
|
478
|
+
isPointInside() {
|
|
479
|
+
return false;
|
|
639
480
|
}
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
|
|
644
|
-
|
|
645
|
-
}
|
|
646
|
-
super.destroy();
|
|
481
|
+
render(r) {
|
|
482
|
+
r.beginPath();
|
|
483
|
+
r.moveTo(0, 0);
|
|
484
|
+
r.lineTo(this.width, 0);
|
|
485
|
+
r.stroke(this.color, 1);
|
|
647
486
|
}
|
|
648
487
|
};
|
|
649
|
-
var
|
|
650
|
-
|
|
488
|
+
var QuoteBorder = class extends import_core.Entity {
|
|
489
|
+
color;
|
|
490
|
+
constructor(height, color, width = 4) {
|
|
651
491
|
super();
|
|
652
|
-
this.
|
|
653
|
-
this.
|
|
654
|
-
this.
|
|
655
|
-
for (const control of controls) this.add(control);
|
|
656
|
-
this.layoutAffordances();
|
|
657
|
-
}
|
|
658
|
-
block;
|
|
659
|
-
controls;
|
|
660
|
-
/** Gap between the block's edges and the controls, in px. */
|
|
661
|
-
static INSET = 8;
|
|
662
|
-
/** Gap between adjacent controls, in px. */
|
|
663
|
-
static GAP = 6;
|
|
664
|
-
/**
|
|
665
|
-
* Places the controls right-aligned along the block's top edge.
|
|
666
|
-
*
|
|
667
|
-
* Laid out right-to-left from the block's right edge so the first control in
|
|
668
|
-
* the list ends up leftmost, which keeps DOM order (and therefore tab order and
|
|
669
|
-
* the a11y reading order) matching the visual order.
|
|
670
|
-
*/
|
|
671
|
-
layoutAffordances() {
|
|
672
|
-
this.width = this.block.width;
|
|
673
|
-
this.height = this.block.height;
|
|
674
|
-
let right = this.block.width - _BlockWithAffordances.INSET;
|
|
675
|
-
for (let i = this.controls.length - 1; i >= 0; i--) {
|
|
676
|
-
const control = this.controls[i];
|
|
677
|
-
control.x = right - control.width;
|
|
678
|
-
control.y = _BlockWithAffordances.INSET;
|
|
679
|
-
right = control.x - _BlockWithAffordances.GAP;
|
|
680
|
-
}
|
|
492
|
+
this.width = width;
|
|
493
|
+
this.height = height;
|
|
494
|
+
this.color = color;
|
|
681
495
|
}
|
|
682
|
-
|
|
683
|
-
|
|
684
|
-
*
|
|
685
|
-
* Called by the owner when a block is resized or its content grew; the controls
|
|
686
|
-
* are anchored to the right edge, so a width change moves them.
|
|
687
|
-
*/
|
|
688
|
-
refreshAffordances() {
|
|
689
|
-
this.layoutAffordances();
|
|
690
|
-
this.scene?.markDirty();
|
|
496
|
+
isPointInside() {
|
|
497
|
+
return false;
|
|
691
498
|
}
|
|
692
|
-
|
|
693
|
-
|
|
694
|
-
|
|
499
|
+
render(r) {
|
|
500
|
+
r.beginPath();
|
|
501
|
+
r.roundRect(0, 0, this.width, this.height, this.width / 2);
|
|
502
|
+
r.fill(this.color);
|
|
695
503
|
}
|
|
696
|
-
|
|
697
|
-
|
|
698
|
-
|
|
699
|
-
|
|
700
|
-
getA11yAttributes() {
|
|
701
|
-
return { role: "group", pointerEvents: "none" };
|
|
504
|
+
};
|
|
505
|
+
var MarkdownContainer = class extends import_core.Entity {
|
|
506
|
+
isPointInside(_globalX, _globalY) {
|
|
507
|
+
return false;
|
|
702
508
|
}
|
|
703
|
-
render() {
|
|
509
|
+
render(_r) {
|
|
704
510
|
}
|
|
705
511
|
};
|
|
706
|
-
function tableContentOf(token) {
|
|
707
|
-
return {
|
|
708
|
-
headers: token.header.map((cell) => cell.text),
|
|
709
|
-
rows: token.rows.map((row) => row.map((cell) => cell.text)),
|
|
710
|
-
align: token.align
|
|
711
|
-
};
|
|
712
|
-
}
|
|
713
512
|
|
|
714
|
-
// src/
|
|
715
|
-
var
|
|
716
|
-
var
|
|
717
|
-
|
|
718
|
-
|
|
719
|
-
var
|
|
720
|
-
|
|
721
|
-
|
|
722
|
-
|
|
723
|
-
|
|
724
|
-
|
|
725
|
-
|
|
726
|
-
|
|
513
|
+
// src/markdown-code.ts
|
|
514
|
+
var import_core2 = require("@vectojs/core");
|
|
515
|
+
var import_ui = require("@vectojs/ui");
|
|
516
|
+
|
|
517
|
+
// src/theme.ts
|
|
518
|
+
var DEFAULT_THEME = {
|
|
519
|
+
textColor: "#e2e8f0",
|
|
520
|
+
headingColor: "#f8fafc",
|
|
521
|
+
codeColor: "#a5f3fc",
|
|
522
|
+
codeBgColor: "rgba(30, 41, 59, 0.85)",
|
|
523
|
+
quoteBorderColor: "#6366f1",
|
|
524
|
+
quoteTextColor: "#e2e8f0",
|
|
525
|
+
hrColor: "rgba(148, 163, 184, 0.3)",
|
|
526
|
+
tableBgColor: "rgba(15, 15, 25, 0.4)",
|
|
527
|
+
tableHeaderBgColor: "rgba(255, 255, 255, 0.08)",
|
|
528
|
+
linkColor: "#38bdf8",
|
|
529
|
+
footnoteColor: "#38bdf8",
|
|
530
|
+
mathFallbackColor: "#fcd34d",
|
|
531
|
+
syntaxKeywordColor: "#c084fc",
|
|
532
|
+
syntaxStringColor: "#86efac",
|
|
533
|
+
syntaxCommentColor: "#64748b",
|
|
534
|
+
syntaxNumberColor: "#fbbf24",
|
|
535
|
+
bodyFont: "Inter, system-ui, sans-serif",
|
|
536
|
+
codeFont: 'ui-monospace, "JetBrains Mono", "Fira Code", monospace',
|
|
537
|
+
fontSize: 16,
|
|
538
|
+
headingSizes: [32, 28, 24, 20, 18, 16],
|
|
539
|
+
codeFontSize: 15,
|
|
540
|
+
tableFontSize: 14,
|
|
541
|
+
footnoteMarkerScale: 0.75,
|
|
542
|
+
codeLineHeight: 24,
|
|
543
|
+
bodyLineHeight: 24,
|
|
544
|
+
blockGap: 16,
|
|
545
|
+
codePadding: 18,
|
|
546
|
+
codeRadius: 8,
|
|
547
|
+
listGap: 6,
|
|
548
|
+
listItemGap: 4,
|
|
549
|
+
quoteIndent: 16,
|
|
550
|
+
quoteBorderWidth: 4,
|
|
551
|
+
quoteInnerGap: 8,
|
|
552
|
+
imageRadius: 8,
|
|
553
|
+
inlineImageScale: 1.15
|
|
554
|
+
};
|
|
555
|
+
function resolveTheme(theme) {
|
|
556
|
+
const merged = { ...DEFAULT_THEME, ...theme };
|
|
557
|
+
if (theme?.tableFontSize === void 0) {
|
|
558
|
+
merged.tableFontSize = Math.max(1, merged.fontSize - 2);
|
|
727
559
|
}
|
|
728
|
-
|
|
729
|
-
|
|
730
|
-
let cursor = contentStart;
|
|
731
|
-
let keyChecked = false;
|
|
732
|
-
while (cursor < text.length) {
|
|
733
|
-
const nl = text.indexOf("\n", cursor);
|
|
734
|
-
if (nl === -1 && !decide) return PENDING;
|
|
735
|
-
const line = text.slice(cursor, nl === -1 ? text.length : nl).replace(/\r$/, "");
|
|
736
|
-
if (!keyChecked) {
|
|
737
|
-
if (!KEY_RE.test(line)) return NONE;
|
|
738
|
-
keyChecked = true;
|
|
739
|
-
} else if (CLOSE_RE.test(line)) {
|
|
740
|
-
return {
|
|
741
|
-
kind: "found",
|
|
742
|
-
raw: text.slice(contentStart, cursor),
|
|
743
|
-
// A closer with no trailing newline ends the document, so the body is
|
|
744
|
-
// empty rather than starting one character past the end.
|
|
745
|
-
bodyStart: nl === -1 ? text.length : nl + 1
|
|
746
|
-
};
|
|
747
|
-
}
|
|
748
|
-
if (nl === -1) break;
|
|
749
|
-
cursor = nl + 1;
|
|
560
|
+
if (theme?.quoteTextColor === void 0) {
|
|
561
|
+
merged.quoteTextColor = merged.textColor;
|
|
750
562
|
}
|
|
751
|
-
|
|
752
|
-
|
|
753
|
-
function parseFrontMatterFields(raw) {
|
|
754
|
-
const out = {};
|
|
755
|
-
for (const rawLine of raw.split("\n")) {
|
|
756
|
-
const line = rawLine.replace(/\r$/, "");
|
|
757
|
-
if (line.length === 0 || /^[\s#]/.test(line)) continue;
|
|
758
|
-
const sep = line.indexOf(":");
|
|
759
|
-
if (sep <= 0) continue;
|
|
760
|
-
const value = line.slice(sep + 1);
|
|
761
|
-
if (value.length > 0 && value[0] !== " " && value[0] !== " ") continue;
|
|
762
|
-
out[line.slice(0, sep).trim()] = unquote(value.trim());
|
|
563
|
+
if (theme?.footnoteColor === void 0) {
|
|
564
|
+
merged.footnoteColor = merged.linkColor;
|
|
763
565
|
}
|
|
764
|
-
return
|
|
566
|
+
return merged;
|
|
765
567
|
}
|
|
766
|
-
function
|
|
767
|
-
|
|
768
|
-
|
|
769
|
-
|
|
770
|
-
|
|
771
|
-
}
|
|
772
|
-
return value;
|
|
568
|
+
function headingSize(theme, depth) {
|
|
569
|
+
const sizes = theme.headingSizes;
|
|
570
|
+
if (sizes.length === 0) return theme.fontSize;
|
|
571
|
+
const idx = Math.min(Math.max(depth, 1) - 1, sizes.length - 1);
|
|
572
|
+
return sizes[idx] ?? theme.fontSize;
|
|
773
573
|
}
|
|
774
574
|
|
|
775
|
-
// src/
|
|
776
|
-
var WORKER_SOURCE_STRING = '"use strict";(()=>{function V(){return{async:!1,breaks:!1,extensions:null,gfm:!0,hooks:null,pedantic:!1,renderer:null,silent:!1,tokenizer:null,walkTokens:null}}var _=V();function ke(t){_=t}var C={exec:()=>null};function P(t){let e=[];return n=>{let s=Math.max(0,Math.min(3,n-1)),r=e[s];return r||(r=t(s),e[s]=r),r}}function k(t,e=""){let n=typeof t=="string"?t:t.source,s={replace:(r,l)=>{let a=typeof l=="string"?l:l.source;return a=a.replace(x.caret,"$1"),n=n.replace(r,a),s},getRegex:()=>new RegExp(n,e)};return s}var _e=((t="")=>{try{return!!new RegExp("(?<=1)(?<!1)"+t)}catch{return!1}})(),x={codeRemoveIndent:/^(?: {1,4}| {0,3}\\t)/gm,outputLinkReplace:/\\\\([\\[\\]])/g,indentCodeCompensation:/^(\\s+)(?:```)/,beginningSpace:/^\\s+/,endingHash:/#$/,startingSpaceChar:/^ /,endingSpaceChar:/ $/,nonSpaceChar:/[^ ]/,newLineCharGlobal:/\\n/g,tabCharGlobal:/\\t/g,multipleSpaceGlobal:/\\s+/g,blankLine:/^[ \\t]*$/,doubleBlankLine:/\\n[ \\t]*\\n[ \\t]*$/,blockquoteStart:/^ {0,3}>/,blockquoteSetextReplace:/\\n {0,3}((?:=+|-+) *)(?=\\n|$)/g,blockquoteSetextReplace2:/^ {0,3}>[ \\t]?/gm,listReplaceNesting:/^ {1,4}(?=( {4})*[^ ])/g,listIsTask:/^\\[[ xX]\\] +\\S/,listReplaceTask:/^\\[[ xX]\\] +/,listTaskCheckbox:/\\[[ xX]\\]/,anyLine:/\\n.*\\n/,hrefBrackets:/^<(.*)>$/,tableDelimiter:/[:|]/,tableAlignChars:/^\\||\\| *$/g,tableRowBlankLine:/\\n[ \\t]*$/,tableAlignRight:/^ *-+: *$/,tableAlignCenter:/^ *:-+: *$/,tableAlignLeft:/^ *:-+ *$/,startATag:/^<a /i,endATag:/^<\\/a>/i,startPreScriptTag:/^<(pre|code|kbd|script)(\\s|>)/i,endPreScriptTag:/^<\\/(pre|code|kbd|script)(\\s|>)/i,startAngleBracket:/^</,endAngleBracket:/>$/,pedanticHrefTitle:/^([^\'"]*[^\\s])\\s+([\'"])(.*)\\2/,unicodeAlphaNumeric:/[\\p{L}\\p{N}]/u,escapeTest:/[&<>"\']/,escapeReplace:/[&<>"\']/g,escapeTestNoEncode:/[<>"\']|&(?!(#\\d{1,7}|#[Xx][a-fA-F0-9]{1,6}|\\w+);)/,escapeReplaceNoEncode:/[<>"\']|&(?!(#\\d{1,7}|#[Xx][a-fA-F0-9]{1,6}|\\w+);)/g,caret:/(^|[^\\[])\\^/g,percentDecode:/%25/g,findPipe:/\\|/g,splitPipe:/ \\|/,slashPipe:/\\\\\\|/g,carriageReturn:/\\r\\n|\\r/g,spaceLine:/^ +$/gm,notSpaceStart:/^\\S*/,endingNewline:/\\n$/,listItemRegex:t=>new RegExp(`^( {0,3}${t})((?:[ ][^\\\\n]*)?(?:\\\\n|$))`),nextBulletRegex:P(t=>new RegExp(`^ {0,${t}}(?:[*+-]|\\\\d{1,9}[.)])((?:[ ][^\\\\n]*)?(?:\\\\n|$))`)),hrRegex:P(t=>new RegExp(`^ {0,${t}}((?:- *){3,}|(?:_ *){3,}|(?:\\\\* *){3,})(?:\\\\n+|$)`)),fencesBeginRegex:P(t=>new RegExp(`^ {0,${t}}(?:\\`\\`\\`|~~~)`)),headingBeginRegex:P(t=>new RegExp(`^ {0,${t}}#`)),htmlBeginRegex:P(t=>new RegExp(`^ {0,${t}}<(?:[a-z].*>|!--)`,"i")),blockquoteBeginRegex:P(t=>new RegExp(`^ {0,${t}}>`))},Pe=/^(?:[ \\t]*(?:\\n|$))+/,Me=/^((?: {4}| {0,3}\\t)[^\\n]+(?:\\n(?:[ \\t]*(?:\\n|$))*)?)+/,Ee=/^ {0,3}(`{3,}(?=[^`\\n]*(?:\\n|$))|~{3,})([^\\n]*)(?:\\n|$)(?:|([\\s\\S]*?)(?:\\n|$))(?: {0,3}\\1[~`]* *(?=\\n|$)|$)/,v=/^ {0,3}((?:-[\\t ]*){3,}|(?:_[ \\t]*){3,}|(?:\\*[ \\t]*){3,})(?:\\n+|$)/,Be=/^ {0,3}(#{1,6})(?=\\s|$)(.*)(?:\\n+|$)/,K=/ {0,3}(?:[*+-]|\\d{1,9}[.)])/,fe=/^(?!bull |blockCode|fences|blockquote|heading|html|table)((?:.|\\n(?!\\s*?\\n|bull |blockCode|fences|blockquote|heading|html|table))+?)\\n {0,3}(=+|-+) *(?:\\n+|$)/,de=k(fe).replace(/bull/g,K).replace(/blockCode/g,/(?: {4}| {0,3}\\t)/).replace(/fences/g,/ {0,3}(?:`{3,}|~{3,})/).replace(/blockquote/g,/ {0,3}>/).replace(/heading/g,/ {0,3}#{1,6}(?:\\s|$)/).replace(/html/g,/ {0,3}<[^\\n>]+>\\n/).replace(/\\|table/g,"").getRegex(),qe=k(fe).replace(/bull/g,K).replace(/blockCode/g,/(?: {4}| {0,3}\\t)/).replace(/fences/g,/ {0,3}(?:`{3,}|~{3,})/).replace(/blockquote/g,/ {0,3}>/).replace(/heading/g,/ {0,3}#{1,6}(?:\\s|$)/).replace(/html/g,/ {0,3}<[^\\n>]+>\\n/).replace(/table/g,/ {0,3}\\|?(?:[:\\- ]*\\|)+[\\:\\- ]*\\n/).getRegex(),J=/^([^\\n]+(?:\\n(?!hr|heading|lheading|blockquote|fences|list|html|table|[ \\t]+\\n)[^\\n]+)*)/,ve=/^[^\\n]+/,Y=/(?!\\s*\\])(?:\\\\[\\s\\S]|[^\\[\\]\\\\])+/,De=k(/^ {0,3}\\[(label)\\]: *(?:\\n[ \\t]*)?([^<\\s][^\\s]*|<.*?>)(?:(?: +(?:\\n[ \\t]*)?| *\\n[ \\t]*)(title))? *(?:\\n+|$)/).replace("label",Y).replace("title",/(?:"(?:\\\\"?|[^"\\\\])*"|\'[^\'\\n]*(?:\\n[^\'\\n]+)*\\n?\'|\\([^()]*\\))/).getRegex(),Ze=k(/^(bull)([ \\t][^\\n]*?)?(?:\\n|$)/).replace(/bull/g,K).getRegex(),N="address|article|aside|base|basefont|blockquote|body|caption|center|col|colgroup|dd|details|dialog|dir|div|dl|dt|fieldset|figcaption|figure|footer|form|frame|frameset|h[1-6]|head|header|hr|html|iframe|legend|li|link|main|menu|menuitem|meta|nav|noframes|ol|optgroup|option|p|param|search|section|summary|table|tbody|td|tfoot|th|thead|title|tr|track|ul",ee=/<!--(?:-?>|[\\s\\S]*?(?:-->|$))/,Oe=k("^ {0,3}(?:<(script|pre|style|textarea)[\\\\s>][\\\\s\\\\S]*?(?:</\\\\1>[^\\\\n]*\\\\n*|$)|comment[^\\\\n]*(\\\\n+|$)|<\\\\?[\\\\s\\\\S]*?(?:\\\\?>[^\\\\n]*\\\\n*|$)|<![A-Z][\\\\s\\\\S]*?(?:>[^\\\\n]*\\\\n*|$)|<!\\\\[CDATA\\\\[[\\\\s\\\\S]*?(?:\\\\]\\\\]>[^\\\\n]*\\\\n*|$)|</?(tag)(?: +|\\\\n|/?>)[\\\\s\\\\S]*?(?:(?:\\\\n[ ]*)+\\\\n|$)|<(?!script|pre|style|textarea)([a-z][\\\\w-]*)(?:attribute)*? */?>(?=[ \\\\t]*(?:\\\\n|$))[\\\\s\\\\S]*?(?:(?:\\\\n[ ]*)+\\\\n|$)|</(?!script|pre|style|textarea)[a-z][\\\\w-]*\\\\s*>(?=[ \\\\t]*(?:\\\\n|$))[\\\\s\\\\S]*?(?:(?:\\\\n[ ]*)+\\\\n|$))","i").replace("comment",ee).replace("tag",N).replace("attribute",/ +[a-zA-Z:_][\\w.:-]*(?: *= *"[^"\\n]*"| *= *\'[^\'\\n]*\'| *= *[^\\s"\'=<>`]+)?/).getRegex(),xe=t=>k(J).replace("hr",v).replace("heading"," {0,3}#{1,6}(?:\\\\s|$)").replace("|lheading","").replace("|table","").replace("blockquote"," {0,3}>").replace("fences"," {0,3}(?:`{3,}(?=[^`\\\\n]*\\\\n)|~~~)[^\\\\n]*\\\\n").replace("list",t).replace("html","</?(?:tag)(?: +|\\\\n|/?>)|<(?:script|pre|style|textarea|!--)").replace("tag",N).getRegex(),Qe=xe(/ {0,3}(?:[*+-]|1[.)])[ \\t]+[^ \\t\\n]/),Ne=xe(/ {0,3}(?:[*+-]|\\d{1,9}[.)])(?:[ \\t]|\\n|$)/),He=k(/^( {0,3}> ?(paragraph|[^\\n]*)(?:\\n|$))+/).replace("paragraph",Ne).getRegex(),te={blockquote:He,code:Me,def:De,fences:Ee,heading:Be,hr:v,html:Oe,lheading:de,list:Ze,newline:Pe,paragraph:Qe,table:C,text:ve},ae=k("^ *([^\\\\n ].*)\\\\n {0,3}((?:\\\\| *)?:?-+:? *(?:\\\\| *:?-+:? *)*(?:\\\\| *)?)(?:\\\\n((?:(?! *\\\\n|hr|heading|blockquote|code|fences|list|html).*(?:\\\\n|$))*)\\\\n*|$)").replace("hr",v).replace("heading"," {0,3}#{1,6}(?:\\\\s|$)").replace("blockquote"," {0,3}>").replace("code","(?: {4}| {0,3} )[^\\\\n]").replace("fences"," {0,3}(?:`{3,}(?=[^`\\\\n]*\\\\n)|~~~)[^\\\\n]*\\\\n").replace("list"," {0,3}(?:[*+-]|1[.)])[ \\\\t]").replace("html","</?(?:tag)(?: +|\\\\n|/?>)|<(?:script|pre|style|textarea|!--)").replace("tag",N).getRegex(),je={...te,lheading:qe,table:ae,paragraph:k(J).replace("hr",v).replace("heading"," {0,3}#{1,6}(?:\\\\s|$)").replace("|lheading","").replace("table",ae).replace("blockquote"," {0,3}>").replace("fences"," {0,3}(?:`{3,}(?=[^`\\\\n]*\\\\n)|~~~)[^\\\\n]*\\\\n").replace("list"," {0,3}(?:[*+-]|1[.)])[ \\\\t]+[^ \\\\t\\\\n]").replace("html","</?(?:tag)(?: +|\\\\n|/?>)|<(?:script|pre|style|textarea|!--)").replace("tag",N).getRegex()},Ge={...te,html:k(`^ *(?:comment *(?:\\\\n|\\\\s*$)|<(tag)[\\\\s\\\\S]+?</\\\\1> *(?:\\\\n{2,}|\\\\s*$)|<tag(?:"[^"]*"|\'[^\']*\'|\\\\s[^\'"/>\\\\s]*)*?/?> *(?:\\\\n{2,}|\\\\s*$))`).replace("comment",ee).replace(/tag/g,"(?!(?:a|em|strong|small|s|cite|q|dfn|abbr|data|time|code|var|samp|kbd|sub|sup|i|b|u|mark|ruby|rt|rp|bdi|bdo|span|br|wbr|ins|del|img)\\\\b)\\\\w+(?!:|[^\\\\w\\\\s@]*@)\\\\b").getRegex(),def:/^ *\\[([^\\]]+)\\]: *<?([^\\s>]+)>?(?: +(["(][^\\n]+[")]))? *(?:\\n+|$)/,heading:/^(#{1,6})(.*)(?:\\n+|$)/,fences:C,lheading:/^(.+?)\\n {0,3}(=+|-+) *(?:\\n+|$)/,paragraph:k(J).replace("hr",v).replace("heading",` *#{1,6} *[^\n]`).replace("lheading",de).replace("|table","").replace("blockquote"," {0,3}>").replace("|fences","").replace("|list","").replace("|html","").replace("|tag","").getRegex()},We=/^\\\\([!"#$%&\'()*+,\\-./:;<=>?@\\[\\]\\\\^_`{|}~])/,Fe=/^(`+)([^`]|[^`][\\s\\S]*?[^`])\\1(?!`)/,be=/^( {2,}|\\\\)\\n(?!\\s*$)/,Xe=/^(`+|[^`])(?:(?= {2,}\\n)|[\\s\\S]*?(?:(?=[\\\\<!\\[`*_]|\\b_|$)|[^ ](?= {2,}\\n)))/,M=/[\\p{P}\\p{S}]/u,H=/[\\s\\p{P}\\p{S}]/u,ne=/[^\\s\\p{P}\\p{S}]/u,Ue=k(/^((?![*_])punctSpace)/,"u").replace(/punctSpace/g,H).getRegex(),me=/(?!~)[\\p{P}\\p{S}]/u,Ve=/(?!~)[\\s\\p{P}\\p{S}]/u,Ke=/(?:[^\\s\\p{P}\\p{S}]|~)/u,Je=k(/link|precode-code|html/,"g").replace("link",/\\[(?:[^\\[\\]`]|(?<a>`+)[^`]+\\k<a>(?!`))*?\\]\\((?:\\\\[\\s\\S]|[^\\\\\\(\\)]|\\((?:\\\\[\\s\\S]|[^\\\\\\(\\)])*\\))*\\)/).replace("precode-",_e?"(?<!`)()":"(^^|[^`])").replace("code",/(?<b>`+)[^`]+\\k<b>(?!`)/).replace("html",/<(?! )[^<>]*?>/).getRegex(),we=/^(?:\\*+(?:((?!\\*)punct)|([^\\s*]))?)|^_+(?:((?!_)punct)|([^\\s_]))?/,Ye=k(we,"u").replace(/punct/g,M).getRegex(),et=k(we,"u").replace(/punct/g,me).getRegex(),ye="^[^_*]*?__[^_*]*?\\\\*[^_*]*?(?=__)|[^*]+(?=[^*])|(?!\\\\*)punct(\\\\*+)(?=[\\\\s]|$)|notPunctSpace(\\\\*+)(?!\\\\*)(?=punctSpace|$)|(?!\\\\*)punctSpace(\\\\*+)(?=notPunctSpace)|[\\\\s](\\\\*+)(?!\\\\*)(?=punct)|(?!\\\\*)punct(\\\\*+)(?!\\\\*)(?=punct)|notPunctSpace(\\\\*+)(?=notPunctSpace)",tt=k(ye,"gu").replace(/notPunctSpace/g,ne).replace(/punctSpace/g,H).replace(/punct/g,M).getRegex(),nt=k(ye,"gu").replace(/notPunctSpace/g,Ke).replace(/punctSpace/g,Ve).replace(/punct/g,me).getRegex(),rt=k("^[^_*]*?\\\\*\\\\*[^_*]*?_[^_*]*?(?=\\\\*\\\\*)|[^_]+(?=[^_])|(?!_)punct(_+)(?=[\\\\s]|$)|notPunctSpace(_+)(?!_)(?=punctSpace|$)|(?!_)punctSpace(_+)(?=notPunctSpace)|[\\\\s](_+)(?!_)(?=punct)|(?!_)punct(_+)(?!_)(?=punct)","gu").replace(/notPunctSpace/g,ne).replace(/punctSpace/g,H).replace(/punct/g,M).getRegex(),st=k(/^~~?(?:((?!~)punct)|[^\\s~])/,"u").replace(/punct/g,M).getRegex(),lt="^[^~]+(?=[^~])|(?!~)punct(~~?)(?=[\\\\s]|$)|notPunctSpace(~~?)(?!~)(?=punctSpace|$)|(?!~)punctSpace(~~?)(?=notPunctSpace)|[\\\\s](~~?)(?!~)(?=punct)|(?!~)punct(~~?)(?!~)(?=punct)|notPunctSpace(~~?)(?=notPunctSpace)",it=k(lt,"gu").replace(/notPunctSpace/g,ne).replace(/punctSpace/g,H).replace(/punct/g,M).getRegex(),at=k(/\\\\(punct)/,"gu").replace(/punct/g,M).getRegex(),ot=k(/^<(scheme:[^\\s\\x00-\\x1f<>]*|email)>/).replace("scheme",/[a-zA-Z][a-zA-Z0-9+.-]{1,31}/).replace("email",/[a-zA-Z0-9.!#$%&\'*+/=?^_`{|}~-]+(@)[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)+(?![-_])/).getRegex(),ct=k(ee).replace("(?:-->|$)","-->").getRegex(),ht=k("^comment|^</[a-zA-Z][\\\\w:-]*\\\\s*>|^<[a-zA-Z][\\\\w-]*(?:attribute)*?\\\\s*/?>|^<\\\\?[\\\\s\\\\S]*?\\\\?>|^<![a-zA-Z]+\\\\s[\\\\s\\\\S]*?>|^<!\\\\[CDATA\\\\[[\\\\s\\\\S]*?\\\\]\\\\]>").replace("comment",ct).replace("attribute",/\\s+[a-zA-Z:_][\\w.:-]*(?:\\s*=\\s*"[^"]*"|\\s*=\\s*\'[^\']*\'|\\s*=\\s*[^\\s"\'=<>`]+)?/).getRegex(),Z=/(?:\\[(?:\\\\[\\s\\S]|[^\\[\\]\\\\])*\\]|\\\\[\\s\\S]|`+(?!`)[^`]*?`+(?!`)|``+(?=\\])|[^\\[\\]\\\\`])*?/,ut=k(/^!?\\[(label)\\]\\(\\s*(href)(?:(?:[ \\t]+(?:\\n[ \\t]*)?|\\n[ \\t]*)(title))?\\s*\\)/).replace("label",Z).replace("href",/<(?:\\\\.|[^\\n<>\\\\])+>|[^ \\t\\n\\x00-\\x1f]+|(?=\\))/).replace("title",/"(?:\\\\"?|[^"\\\\])*"|\'(?:\\\\\'?|[^\'\\\\])*\'|\\((?:\\\\\\)?|[^)\\\\])*\\)/).getRegex(),Re=k(/^!?\\[(label)\\]\\[(ref)\\]/).replace("label",Z).replace("ref",Y).getRegex(),$e=k(/^!?\\[(ref)\\](?:\\[\\])?/).replace("ref",Y).getRegex(),pt=k("reflink|nolink(?!\\\\()","g").replace("reflink",Re).replace("nolink",$e).getRegex(),oe=/[hH][tT][tT][pP][sS]?|[fF][tT][pP]/,re={_backpedal:C,anyPunctuation:at,autolink:ot,blockSkip:Je,br:be,code:Fe,del:C,delLDelim:C,delRDelim:C,emStrongLDelim:Ye,emStrongRDelimAst:tt,emStrongRDelimUnd:rt,escape:We,link:ut,nolink:$e,punctuation:Ue,reflink:Re,reflinkSearch:pt,tag:ht,text:Xe,url:C},gt={...re,link:k(/^!?\\[(label)\\]\\((.*?)\\)/).replace("label",Z).getRegex(),reflink:k(/^!?\\[(label)\\]\\s*\\[([^\\]]*)\\]/).replace("label",Z).getRegex()},F={...re,emStrongRDelimAst:nt,emStrongLDelim:et,delLDelim:st,delRDelim:it,url:k(/^((?:protocol):\\/\\/|www\\.)(?:[a-zA-Z0-9\\-]+\\.?)+[^\\s<]*|^email/).replace("protocol",oe).replace("email",/[A-Za-z0-9._+-]+(@)[a-zA-Z0-9-_]+(?:\\.[a-zA-Z0-9-_]*[a-zA-Z0-9])+(?![-_])/).getRegex(),_backpedal:/(?:[^?!.,:;*_\'"~()&]+|\\([^)]*\\)|&(?![a-zA-Z0-9]+;$)|[?!.,:;*_\'"~)]+(?!$))+/,del:/^(~~?)(?=[^\\s~])((?:\\\\[\\s\\S]|[^\\\\])*?(?:\\\\[\\s\\S]|[^\\s~\\\\]))\\1(?=[^~]|$)/,text:k(/^(`+|~+|[^`~])(?:(?=[`~])|(?= {2,}\\n)|(?=[a-zA-Z0-9.!#$%&\'*+\\/=?_`{\\|}~-]+@)|[\\s\\S]*?(?:(?=[\\\\<!\\[`*~_]|\\b_|protocol:\\/\\/|www\\.|$)|[^ ](?= {2,}\\n)|[^a-zA-Z0-9.!#$%&\'*+\\/=?_`{\\|}~-](?=[a-zA-Z0-9.!#$%&\'*+\\/=?_`{\\|}~-]+@)))/).replace("protocol",oe).getRegex()},kt={...F,br:k(be).replace("{2,}","*").getRegex(),text:k(F.text).replace("\\\\b_","\\\\b_| {2,}\\\\n").replace(/\\{2,\\}/g,"*").getRegex()},D={normal:te,gfm:je,pedantic:Ge},B={normal:re,gfm:F,breaks:kt,pedantic:gt},ft={"&":"&","<":"<",">":">",\'"\':""","\'":"'"},ce=t=>ft[t];function S(t,e){if(e){if(x.escapeTest.test(t))return t.replace(x.escapeReplace,ce)}else if(x.escapeTestNoEncode.test(t))return t.replace(x.escapeReplaceNoEncode,ce);return t}function he(t){try{t=encodeURI(t).replace(x.percentDecode,"%")}catch{return null}return t}function ue(t,e){let n=t.replace(x.findPipe,(l,a,i)=>{let o=!1,c=a;for(;--c>=0&&i[c]==="\\\\";)o=!o;return o?"|":" |"}),s=n.split(x.splitPipe),r=0;if(s[0].trim()||s.shift(),s.length>0&&!s.at(-1)?.trim()&&s.pop(),e)if(s.length>e)s.splice(e);else for(;s.length<e;)s.push("");for(;r<s.length;r++)s[r]=s[r].trim().replace(x.slashPipe,"|");return s}function z(t,e,n){let s=t.length;if(s===0)return"";let r=0;for(;r<s;){let l=t.charAt(s-r-1);if(l===e&&!n)r++;else if(l!==e&&n)r++;else break}return t.slice(0,s-r)}function pe(t){let e=t.split(`\n`),n=e.length-1;for(;n>=0&&x.blankLine.test(e[n]);)n--;return e.length-n<=2?t:e.slice(0,n+1).join(`\n`)}function dt(t,e){if(t.indexOf(e[1])===-1)return-1;let n=0;for(let s=0;s<t.length;s++)if(t[s]==="\\\\")s++;else if(t[s]===e[0])n++;else if(t[s]===e[1]&&(n--,n<0))return s;return n>0?-2:-1}function xt(t,e=0){let n=e,s="";for(let r of t)if(r===" "){let l=4-n%4;s+=" ".repeat(l),n+=l}else s+=r,n++;return s}function ge(t,e,n,s,r){let l=e.href,a=e.title||null,i=t[1].replace(r.other.outputLinkReplace,"$1");s.state.inLink=!0;let o={type:t[0].charAt(0)==="!"?"image":"link",raw:n,href:l,title:a,text:i,tokens:s.inlineTokens(i)};return s.state.inLink=!1,o}function bt(t,e,n){let s=t.match(n.other.indentCodeCompensation);if(s===null)return e;let r=s[1];return e.split(`\n`).map(l=>{let a=l.match(n.other.beginningSpace);if(a===null)return l;let[i]=a;return i.length>=r.length?l.slice(r.length):l}).join(`\n`)}var O=class{options;rules;lexer;constructor(t){this.options=t||_}space(t){let e=this.rules.block.newline.exec(t);if(e&&e[0].length>0)return{type:"space",raw:e[0]}}code(t){let e=this.rules.block.code.exec(t);if(e){let n=this.options.pedantic?e[0]:pe(e[0]),s=n.replace(this.rules.other.codeRemoveIndent,"");return{type:"code",raw:n,codeBlockStyle:"indented",text:s}}}fences(t){let e=this.rules.block.fences.exec(t);if(e){let n=e[0],s=bt(n,e[3]||"",this.rules);return{type:"code",raw:n,lang:e[2]?e[2].trim().replace(this.rules.inline.anyPunctuation,"$1"):e[2],text:s}}}heading(t){let e=this.rules.block.heading.exec(t);if(e){let n=e[2].trim();if(this.rules.other.endingHash.test(n)){let s=z(n,"#");(this.options.pedantic||!s||this.rules.other.endingSpaceChar.test(s))&&(n=s.trim())}return{type:"heading",raw:z(e[0],`\n`),depth:e[1].length,text:n,tokens:this.lexer.inline(n)}}}hr(t){let e=this.rules.block.hr.exec(t);if(e)return{type:"hr",raw:z(e[0],`\n`)}}blockquote(t){let e=this.rules.block.blockquote.exec(t);if(e){let n=z(e[0],`\n`).split(`\n`),s="",r="",l=[];for(;n.length>0;){let a=!1,i=[],o;for(o=0;o<n.length;o++)if(this.rules.other.blockquoteStart.test(n[o]))i.push(n[o]),a=!0;else if(!a)i.push(n[o]);else break;n=n.slice(o);let c=i.join(`\n`),u=c.replace(this.rules.other.blockquoteSetextReplace,`\n $1`).replace(this.rules.other.blockquoteSetextReplace2,"");s=s?`${s}\n${c}`:c,r=r?`${r}\n${u}`:u;let h=this.lexer.state.top;if(this.lexer.state.top=!0,this.lexer.blockTokens(u,l,!0),this.lexer.state.top=h,n.length===0)break;let p=l.at(-1);if(p?.type==="code")break;if(p?.type==="blockquote"){let d=p,f=d.raw+`\n`+n.join(`\n`),m=this.blockquote(f);l[l.length-1]=m,s=s.substring(0,s.length-d.raw.length)+m.raw,r=r.substring(0,r.length-d.text.length)+m.text;break}else if(p?.type==="list"){let d=p,f=d.raw+`\n`+n.join(`\n`),m=this.list(f);l[l.length-1]=m,s=s.substring(0,s.length-p.raw.length)+m.raw,r=r.substring(0,r.length-d.raw.length)+m.raw,n=f.substring(l.at(-1).raw.length).split(`\n`);continue}}return{type:"blockquote",raw:s,tokens:l,text:r}}}list(t){let e=this.rules.block.list.exec(t);if(e){let n=e[1].trim(),s=n.length>1,r={type:"list",raw:"",ordered:s,start:s?+n.slice(0,-1):"",loose:!1,items:[]};n=s?`\\\\d{1,9}\\\\${n.slice(-1)}`:`\\\\${n}`,this.options.pedantic&&(n=s?n:"[*+-]");let l=this.rules.other.listItemRegex(n),a=!1;for(;t;){let o=!1,c="",u="";if(!(e=l.exec(t))||this.rules.block.hr.test(t))break;c=e[0],t=t.substring(c.length);let h=xt(e[2].split(`\n`,1)[0],e[1].length),p=t.split(`\n`,1)[0],d=!h.trim(),f=0;if(this.options.pedantic?(f=2,u=h.trimStart()):d?f=e[1].length+1:(f=h.search(this.rules.other.nonSpaceChar),f=f>4?1:f,u=h.slice(f),f+=e[1].length),d&&this.rules.other.blankLine.test(p)&&(c+=p+`\n`,t=t.substring(p.length+1),o=!0),!o){let m=this.rules.other.nextBulletRegex(f),w=this.rules.other.hrRegex(f),y=this.rules.other.fencesBeginRegex(f),L=this.rules.other.headingBeginRegex(f),W=this.rules.other.htmlBeginRegex(f),A=this.rules.other.blockquoteBeginRegex(f);for(;t;){let b=t.split(`\n`,1)[0],T;if(p=b,this.options.pedantic?(p=p.replace(this.rules.other.listReplaceNesting," "),T=p):T=p.replace(this.rules.other.tabCharGlobal," "),y.test(p)||L.test(p)||W.test(p)||A.test(p)||m.test(p)||w.test(p))break;if(T.search(this.rules.other.nonSpaceChar)>=f||!p.trim())u+=`\n`+T.slice(f);else{if(d||h.replace(this.rules.other.tabCharGlobal," ").search(this.rules.other.nonSpaceChar)>=4||y.test(h)||L.test(h)||w.test(h))break;u+=`\n`+p}d=!p.trim(),c+=b+`\n`,t=t.substring(b.length+1),h=T.slice(f)}}r.loose||(a?r.loose=!0:this.rules.other.doubleBlankLine.test(c)&&(a=!0)),r.items.push({type:"list_item",raw:c,task:!!this.options.gfm&&this.rules.other.listIsTask.test(u),loose:!1,text:u,tokens:[]}),r.raw+=c}let i=r.items.at(-1);if(i)i.raw=i.raw.trimEnd(),i.text=i.text.trimEnd();else return;r.raw=r.raw.trimEnd();for(let o of r.items){this.lexer.state.top=!1,o.tokens=this.lexer.blockTokens(o.text,[]);let c=o.tokens[0];if(o.task&&(c?.type==="text"||c?.type==="paragraph")){o.text=o.text.replace(this.rules.other.listReplaceTask,""),c.raw=c.raw.replace(this.rules.other.listReplaceTask,""),c.text=c.text.replace(this.rules.other.listReplaceTask,"");for(let h=this.lexer.inlineQueue.length-1;h>=0;h--)if(this.rules.other.listIsTask.test(this.lexer.inlineQueue[h].src)){this.lexer.inlineQueue[h].src=this.lexer.inlineQueue[h].src.replace(this.rules.other.listReplaceTask,"");break}let u=this.rules.other.listTaskCheckbox.exec(o.raw);if(u){let h={type:"checkbox",raw:u[0]+" ",checked:u[0]!=="[ ]"};o.checked=h.checked,r.loose?o.tokens[0]&&["paragraph","text"].includes(o.tokens[0].type)&&"tokens"in o.tokens[0]&&o.tokens[0].tokens?(o.tokens[0].raw=h.raw+o.tokens[0].raw,o.tokens[0].text=h.raw+o.tokens[0].text,o.tokens[0].tokens.unshift(h)):o.tokens.unshift({type:"paragraph",raw:h.raw,text:h.raw,tokens:[h]}):o.tokens.unshift(h)}}else o.task&&(o.task=!1);if(!r.loose){let u=o.tokens.filter(p=>p.type==="space"),h=u.length>0&&u.some(p=>this.rules.other.anyLine.test(p.raw));r.loose=h}}if(r.loose)for(let o of r.items){o.loose=!0;for(let c of o.tokens)c.type==="text"&&(c.type="paragraph")}return r}}html(t){let e=this.rules.block.html.exec(t);if(e){let n=pe(e[0]);return{type:"html",block:!0,raw:n,pre:e[1]==="pre"||e[1]==="script"||e[1]==="style",text:n}}}def(t){let e=this.rules.block.def.exec(t);if(e){let n=e[1].toLowerCase().replace(this.rules.other.multipleSpaceGlobal," "),s=e[2]?e[2].replace(this.rules.other.hrefBrackets,"$1").replace(this.rules.inline.anyPunctuation,"$1"):"",r=e[3]?e[3].substring(1,e[3].length-1).replace(this.rules.inline.anyPunctuation,"$1"):e[3];return{type:"def",tag:n,raw:z(e[0],`\n`),href:s,title:r}}}table(t){let e=this.rules.block.table.exec(t);if(!e||!this.rules.other.tableDelimiter.test(e[2]))return;let n=ue(e[1]),s=e[2].replace(this.rules.other.tableAlignChars,"").split("|"),r=e[3]?.trim()?e[3].replace(this.rules.other.tableRowBlankLine,"").split(`\n`):[],l={type:"table",raw:z(e[0],`\n`),header:[],align:[],rows:[]};if(n.length===s.length){for(let a of s)this.rules.other.tableAlignRight.test(a)?l.align.push("right"):this.rules.other.tableAlignCenter.test(a)?l.align.push("center"):this.rules.other.tableAlignLeft.test(a)?l.align.push("left"):l.align.push(null);for(let a=0;a<n.length;a++)l.header.push({text:n[a],tokens:this.lexer.inline(n[a]),header:!0,align:l.align[a]});for(let a of r)l.rows.push(ue(a,l.header.length).map((i,o)=>({text:i,tokens:this.lexer.inline(i),header:!1,align:l.align[o]})));return l}}lheading(t){let e=this.rules.block.lheading.exec(t);if(e){let n=e[1].trim();return{type:"heading",raw:z(e[0],`\n`),depth:e[2].charAt(0)==="="?1:2,text:n,tokens:this.lexer.inline(n)}}}paragraph(t){let e=this.rules.block.paragraph.exec(t);if(e){let n=e[1].charAt(e[1].length-1)===`\n`?e[1].slice(0,-1):e[1];return{type:"paragraph",raw:e[0],text:n,tokens:this.lexer.inline(n)}}}text(t){let e=this.rules.block.text.exec(t);if(e)return{type:"text",raw:e[0],text:e[0],tokens:this.lexer.inline(e[0])}}escape(t){let e=this.rules.inline.escape.exec(t);if(e)return{type:"escape",raw:e[0],text:e[1]}}tag(t){let e=this.rules.inline.tag.exec(t);if(e)return!this.lexer.state.inLink&&this.rules.other.startATag.test(e[0])?this.lexer.state.inLink=!0:this.lexer.state.inLink&&this.rules.other.endATag.test(e[0])&&(this.lexer.state.inLink=!1),!this.lexer.state.inRawBlock&&this.rules.other.startPreScriptTag.test(e[0])?this.lexer.state.inRawBlock=!0:this.lexer.state.inRawBlock&&this.rules.other.endPreScriptTag.test(e[0])&&(this.lexer.state.inRawBlock=!1),{type:"html",raw:e[0],inLink:this.lexer.state.inLink,inRawBlock:this.lexer.state.inRawBlock,block:!1,text:e[0]}}link(t){let e=this.rules.inline.link.exec(t);if(e){let n=e[2].trim();if(!this.options.pedantic&&this.rules.other.startAngleBracket.test(n)){if(!this.rules.other.endAngleBracket.test(n))return;let l=z(n.slice(0,-1),"\\\\");if((n.length-l.length)%2===0)return}else{let l=dt(e[2],"()");if(l===-2)return;if(l>-1){let a=(e[0].indexOf("!")===0?5:4)+e[1].length+l;e[2]=e[2].substring(0,l),e[0]=e[0].substring(0,a).trim(),e[3]=""}}let s=e[2],r="";if(this.options.pedantic){let l=this.rules.other.pedanticHrefTitle.exec(s);l&&(s=l[1],r=l[3])}else r=e[3]?e[3].slice(1,-1):"";return s=s.trim(),this.rules.other.startAngleBracket.test(s)&&(this.options.pedantic&&!this.rules.other.endAngleBracket.test(n)?s=s.slice(1):s=s.slice(1,-1)),ge(e,{href:s&&s.replace(this.rules.inline.anyPunctuation,"$1"),title:r&&r.replace(this.rules.inline.anyPunctuation,"$1")},e[0],this.lexer,this.rules)}}reflink(t,e){let n;if((n=this.rules.inline.reflink.exec(t))||(n=this.rules.inline.nolink.exec(t))){let s=(n[2]||n[1]).replace(this.rules.other.multipleSpaceGlobal," "),r=e[s.toLowerCase()];if(!r){let l=n[0].charAt(0);return{type:"text",raw:l,text:l}}return ge(n,r,n[0],this.lexer,this.rules)}}emStrong(t,e,n=""){let s=this.rules.inline.emStrongLDelim.exec(t);if(!(!s||!s[1]&&!s[2]&&!s[3]&&!s[4]||s[4]&&n.match(this.rules.other.unicodeAlphaNumeric))&&(!(s[1]||s[3])||!n||this.rules.inline.punctuation.exec(n))){let r=[...s[0]].length-1,l,a,i=r,o=0,c=s[0][0]==="*"?this.rules.inline.emStrongRDelimAst:this.rules.inline.emStrongRDelimUnd;for(c.lastIndex=0,e=e.slice(-1*t.length+r);(s=c.exec(e))!==null;){if(l=s[1]||s[2]||s[3]||s[4]||s[5]||s[6],!l)continue;if(a=[...l].length,s[3]||s[4]){i+=a;continue}else if((s[5]||s[6])&&r%3&&!((r+a)%3)){o+=a;continue}if(i-=a,i>0)continue;a=Math.min(a,a+i+o);let u=[...s[0]][0].length,h=t.slice(0,r+s.index+u+a);if(Math.min(r,a)%2){let d=h.slice(1,-1);return{type:"em",raw:h,text:d,tokens:this.lexer.inlineTokens(d)}}let p=h.slice(2,-2);return{type:"strong",raw:h,text:p,tokens:this.lexer.inlineTokens(p)}}}}codespan(t){let e=this.rules.inline.code.exec(t);if(e){let n=e[2].replace(this.rules.other.newLineCharGlobal," "),s=this.rules.other.nonSpaceChar.test(n),r=this.rules.other.startingSpaceChar.test(n)&&this.rules.other.endingSpaceChar.test(n);return s&&r&&(n=n.substring(1,n.length-1)),{type:"codespan",raw:e[0],text:n}}}br(t){let e=this.rules.inline.br.exec(t);if(e)return{type:"br",raw:e[0]}}del(t,e,n=""){let s=this.rules.inline.delLDelim.exec(t);if(s&&(!s[1]||!n||this.rules.inline.punctuation.exec(n))){let r=[...s[0]].length-1,l,a,i=r,o=this.rules.inline.delRDelim;for(o.lastIndex=0,e=e.slice(-1*t.length+r);(s=o.exec(e))!==null;){if(l=s[1]||s[2]||s[3]||s[4]||s[5]||s[6],!l||(a=[...l].length,a!==r))continue;if(s[3]||s[4]){i+=a;continue}if(i-=a,i>0)continue;a=Math.min(a,a+i);let c=[...s[0]][0].length,u=t.slice(0,r+s.index+c+a),h=u.slice(r,-r);return{type:"del",raw:u,text:h,tokens:this.lexer.inlineTokens(h)}}}}autolink(t){let e=this.rules.inline.autolink.exec(t);if(e){let n,s;return e[2]==="@"?(n=e[1],s="mailto:"+n):(n=e[1],s=n),{type:"link",raw:e[0],text:n,href:s,tokens:[{type:"text",raw:n,text:n}]}}}url(t){let e;if(e=this.rules.inline.url.exec(t)){let n,s;if(e[2]==="@")n=e[0],s="mailto:"+n;else{let r;do r=e[0],e[0]=this.rules.inline._backpedal.exec(e[0])?.[0]??"";while(r!==e[0]);n=e[0],e[1]==="www."?s="http://"+e[0]:s=e[0]}return{type:"link",raw:e[0],text:n,href:s,tokens:[{type:"text",raw:n,text:n}]}}}inlineText(t){let e=this.rules.inline.text.exec(t);if(e){let n=this.lexer.state.inRawBlock;return{type:"text",raw:e[0],text:e[0],escaped:n}}}},R=class X{tokens;options;state;inlineQueue;tokenizer;constructor(e){this.tokens=[],this.tokens.links=Object.create(null),this.options=e||_,this.options.tokenizer=this.options.tokenizer||new O,this.tokenizer=this.options.tokenizer,this.tokenizer.options=this.options,this.tokenizer.lexer=this,this.inlineQueue=[],this.state={inLink:!1,inRawBlock:!1,top:!0};let n={other:x,block:D.normal,inline:B.normal};this.options.pedantic?(n.block=D.pedantic,n.inline=B.pedantic):this.options.gfm&&(n.block=D.gfm,this.options.breaks?n.inline=B.breaks:n.inline=B.gfm),this.tokenizer.rules=n}static get rules(){return{block:D,inline:B}}static lex(e,n){return new X(n).lex(e)}static lexInline(e,n){return new X(n).inlineTokens(e)}lex(e){e=e.replace(x.carriageReturn,`\n`),this.blockTokens(e,this.tokens);for(let n=0;n<this.inlineQueue.length;n++){let s=this.inlineQueue[n];this.inlineTokens(s.src,s.tokens)}return this.inlineQueue=[],this.tokens}blockTokens(e,n=[],s=!1){this.tokenizer.lexer=this,this.options.pedantic&&(e=e.replace(x.tabCharGlobal," ").replace(x.spaceLine,""));let r=1/0;for(;e;){if(e.length<r)r=e.length;else{this.infiniteLoopError(e.charCodeAt(0));break}let l;if(this.options.extensions?.block?.some(i=>(l=i.call({lexer:this},e,n))?(e=e.substring(l.raw.length),n.push(l),!0):!1))continue;if(l=this.tokenizer.space(e)){e=e.substring(l.raw.length);let i=n.at(-1);l.raw.length===1&&i!==void 0?i.raw+=`\n`:n.push(l);continue}if(l=this.tokenizer.code(e)){e=e.substring(l.raw.length);let i=n.at(-1);i?.type==="paragraph"||i?.type==="text"?(i.raw+=(i.raw.endsWith(`\n`)?"":`\n`)+l.raw,i.text+=`\n`+l.text,this.inlineQueue.at(-1).src=i.text):n.push(l);continue}if(l=this.tokenizer.fences(e)){e=e.substring(l.raw.length),n.push(l);continue}if(l=this.tokenizer.heading(e)){e=e.substring(l.raw.length),n.push(l);continue}if(l=this.tokenizer.hr(e)){e=e.substring(l.raw.length),n.push(l);continue}if(l=this.tokenizer.blockquote(e)){e=e.substring(l.raw.length),n.push(l);continue}if(l=this.tokenizer.list(e)){e=e.substring(l.raw.length),n.push(l);continue}if(l=this.tokenizer.html(e)){e=e.substring(l.raw.length),n.push(l);continue}if(l=this.tokenizer.def(e)){e=e.substring(l.raw.length);let i=n.at(-1);i?.type==="paragraph"||i?.type==="text"?(i.raw+=(i.raw.endsWith(`\n`)?"":`\n`)+l.raw,i.text+=`\n`+l.raw,this.inlineQueue.at(-1).src=i.text):this.tokens.links[l.tag]||(this.tokens.links[l.tag]={href:l.href,title:l.title},n.push(l));continue}if(l=this.tokenizer.table(e)){e=e.substring(l.raw.length),n.push(l);continue}if(l=this.tokenizer.lheading(e)){e=e.substring(l.raw.length),n.push(l);continue}let a=e;if(this.options.extensions?.startBlock){let i=1/0,o=e.slice(1),c;this.options.extensions.startBlock.forEach(u=>{c=u.call({lexer:this},o),typeof c=="number"&&c>=0&&(i=Math.min(i,c))}),i<1/0&&i>=0&&(a=e.substring(0,i+1))}if(this.state.top&&(l=this.tokenizer.paragraph(a))){let i=n.at(-1);s&&i?.type==="paragraph"?(i.raw+=(i.raw.endsWith(`\n`)?"":`\n`)+l.raw,i.text+=`\n`+l.text,this.inlineQueue.pop(),this.inlineQueue.at(-1).src=i.text):n.push(l),s=a.length!==e.length,e=e.substring(l.raw.length);continue}if(l=this.tokenizer.text(e)){e=e.substring(l.raw.length);let i=n.at(-1);i?.type==="text"?(i.raw+=(i.raw.endsWith(`\n`)?"":`\n`)+l.raw,i.text+=`\n`+l.text,this.inlineQueue.pop(),this.inlineQueue.at(-1).src=i.text):n.push(l);continue}if(e){this.infiniteLoopError(e.charCodeAt(0));break}}return this.state.top=!0,n}inline(e,n=[]){return this.inlineQueue.push({src:e,tokens:n}),n}inlineTokens(e,n=[]){this.tokenizer.lexer=this;let s=e;if(this.tokens.links){let i=Object.keys(this.tokens.links);i.length>0&&(s=s.replace(this.tokenizer.rules.inline.reflinkSearch,o=>i.includes(o.slice(o.lastIndexOf("[")+1,-1))?"["+"a".repeat(o.length-2)+"]":o))}s=s.replace(this.tokenizer.rules.inline.anyPunctuation,"++"),s=s.replace(this.tokenizer.rules.inline.blockSkip,(i,o,c)=>{let u=c?c.length:0;return i.slice(0,u)+"["+"a".repeat(i.length-u-2)+"]"}),s=this.options.hooks?.emStrongMask?.call({lexer:this},s)??s;let r=!1,l="",a=1/0;for(;e;){if(e.length<a)a=e.length;else{this.infiniteLoopError(e.charCodeAt(0));break}r||(l=""),r=!1;let i;if(this.options.extensions?.inline?.some(c=>(i=c.call({lexer:this},e,n))?(e=e.substring(i.raw.length),n.push(i),!0):!1))continue;if(i=this.tokenizer.escape(e)){e=e.substring(i.raw.length),n.push(i);continue}if(i=this.tokenizer.tag(e)){e=e.substring(i.raw.length),n.push(i);continue}if(i=this.tokenizer.link(e)){e=e.substring(i.raw.length),n.push(i);continue}if(i=this.tokenizer.reflink(e,this.tokens.links)){e=e.substring(i.raw.length);let c=n.at(-1);i.type==="text"&&c?.type==="text"?(c.raw+=i.raw,c.text+=i.text):n.push(i);continue}if(i=this.tokenizer.emStrong(e,s,l)){e=e.substring(i.raw.length),n.push(i);continue}if(i=this.tokenizer.codespan(e)){e=e.substring(i.raw.length),n.push(i);continue}if(i=this.tokenizer.br(e)){e=e.substring(i.raw.length),n.push(i);continue}if(i=this.tokenizer.del(e,s,l)){e=e.substring(i.raw.length),n.push(i);continue}if(i=this.tokenizer.autolink(e)){e=e.substring(i.raw.length),n.push(i);continue}if(!this.state.inLink&&(i=this.tokenizer.url(e))){e=e.substring(i.raw.length),n.push(i);continue}let o=e;if(this.options.extensions?.startInline){let c=1/0,u=e.slice(1),h;this.options.extensions.startInline.forEach(p=>{h=p.call({lexer:this},u),typeof h=="number"&&h>=0&&(c=Math.min(c,h))}),c<1/0&&c>=0&&(o=e.substring(0,c+1))}if(i=this.tokenizer.inlineText(o)){e=e.substring(i.raw.length),i.raw.slice(-1)!=="_"&&(l=i.raw.slice(-1)),r=!0;let c=n.at(-1);c?.type==="text"?(c.raw+=i.raw,c.text+=i.text):n.push(i);continue}if(e){this.infiniteLoopError(e.charCodeAt(0));break}}return n}infiniteLoopError(e){let n="Infinite loop on byte: "+e;if(this.options.silent)console.error(n);else throw new Error(n)}},Q=class{options;parser;constructor(t){this.options=t||_}space(t){return""}code({text:t,lang:e,escaped:n}){let s=(e||"").match(x.notSpaceStart)?.[0],r=t.replace(x.endingNewline,"")+`\n`;return s?\'<pre><code class="language-\'+S(s)+\'">\'+(n?r:S(r,!0))+`</code></pre>\n`:"<pre><code>"+(n?r:S(r,!0))+`</code></pre>\n`}blockquote({tokens:t}){return`<blockquote>\n${this.parser.parse(t)}</blockquote>\n`}html({text:t}){return t}def(t){return""}heading({tokens:t,depth:e}){return`<h${e}>${this.parser.parseInline(t)}</h${e}>\n`}hr(t){return`<hr>\n`}list(t){let e=t.ordered,n=t.start,s="";for(let a=0;a<t.items.length;a++){let i=t.items[a];s+=this.listitem(i)}let r=e?"ol":"ul",l=e&&n!==1?\' start="\'+n+\'"\':"";return"<"+r+l+`>\n`+s+"</"+r+`>\n`}listitem(t){return`<li>${this.parser.parse(t.tokens)}</li>\n`}checkbox({checked:t}){return"<input "+(t?\'checked="" \':"")+\'disabled="" type="checkbox"> \'}paragraph({tokens:t}){return`<p>${this.parser.parseInline(t)}</p>\n`}table(t){let e="",n="";for(let r=0;r<t.header.length;r++)n+=this.tablecell(t.header[r]);e+=this.tablerow({text:n});let s="";for(let r=0;r<t.rows.length;r++){let l=t.rows[r];n="";for(let a=0;a<l.length;a++)n+=this.tablecell(l[a]);s+=this.tablerow({text:n})}return s&&(s=`<tbody>${s}</tbody>`),`<table>\n<thead>\n`+e+`</thead>\n`+s+`</table>\n`}tablerow({text:t}){return`<tr>\n${t}</tr>\n`}tablecell(t){let e=this.parser.parseInline(t.tokens),n=t.header?"th":"td";return(t.align?`<${n} align="${t.align}">`:`<${n}>`)+e+`</${n}>\n`}strong({tokens:t}){return`<strong>${this.parser.parseInline(t)}</strong>`}em({tokens:t}){return`<em>${this.parser.parseInline(t)}</em>`}codespan({text:t}){return`<code>${S(t,!0)}</code>`}br(t){return"<br>"}del({tokens:t}){return`<del>${this.parser.parseInline(t)}</del>`}link({href:t,title:e,tokens:n}){let s=this.parser.parseInline(n),r=he(t);if(r===null)return s;t=r;let l=\'<a href="\'+t+\'"\';return e&&(l+=\' title="\'+S(e)+\'"\'),l+=">"+s+"</a>",l}image({href:t,title:e,text:n,tokens:s}){s&&(n=this.parser.parseInline(s,this.parser.textRenderer));let r=he(t);if(r===null)return S(n);t=r;let l=`<img src="${t}" alt="${S(n)}"`;return e&&(l+=` title="${S(e)}"`),l+=">",l}text(t){return"tokens"in t&&t.tokens?this.parser.parseInline(t.tokens):"escaped"in t&&t.escaped?t.text:S(t.text)}},se=class{strong({text:t}){return t}em({text:t}){return t}codespan({text:t}){return t}del({text:t}){return t}html({text:t}){return t}text({text:t}){return t}link({text:t}){return""+t}image({text:t}){return""+t}br(){return""}checkbox({raw:t}){return t}},$=class U{options;renderer;textRenderer;constructor(e){this.options=e||_,this.options.renderer=this.options.renderer||new Q,this.renderer=this.options.renderer,this.renderer.options=this.options,this.renderer.parser=this,this.textRenderer=new se}static parse(e,n){return new U(n).parse(e)}static parseInline(e,n){return new U(n).parseInline(e)}parse(e){this.renderer.parser=this;let n="";for(let s=0;s<e.length;s++){let r=e[s];if(this.options.extensions?.renderers?.[r.type]){let a=r,i=this.options.extensions.renderers[a.type].call({parser:this},a);if(i!==!1||!["space","hr","heading","code","table","blockquote","list","html","def","paragraph","text"].includes(a.type)){n+=i||"";continue}}let l=r;switch(l.type){case"space":{n+=this.renderer.space(l);break}case"hr":{n+=this.renderer.hr(l);break}case"heading":{n+=this.renderer.heading(l);break}case"code":{n+=this.renderer.code(l);break}case"table":{n+=this.renderer.table(l);break}case"blockquote":{n+=this.renderer.blockquote(l);break}case"list":{n+=this.renderer.list(l);break}case"checkbox":{n+=this.renderer.checkbox(l);break}case"html":{n+=this.renderer.html(l);break}case"def":{n+=this.renderer.def(l);break}case"paragraph":{n+=this.renderer.paragraph(l);break}case"text":{n+=this.renderer.text(l);break}default:{let a=\'Token with "\'+l.type+\'" type was not found.\';if(this.options.silent)return console.error(a),"";throw new Error(a)}}}return n}parseInline(e,n=this.renderer){this.renderer.parser=this;let s="";for(let r=0;r<e.length;r++){let l=e[r];if(this.options.extensions?.renderers?.[l.type]){let i=this.options.extensions.renderers[l.type].call({parser:this},l);if(i!==!1||!["escape","html","link","image","strong","em","codespan","br","del","text"].includes(l.type)){s+=i||"";continue}}let a=l;switch(a.type){case"escape":{s+=n.text(a);break}case"html":{s+=n.html(a);break}case"link":{s+=n.link(a);break}case"image":{s+=n.image(a);break}case"checkbox":{s+=n.checkbox(a);break}case"strong":{s+=n.strong(a);break}case"em":{s+=n.em(a);break}case"codespan":{s+=n.codespan(a);break}case"br":{s+=n.br(a);break}case"del":{s+=n.del(a);break}case"text":{s+=n.text(a);break}default:{let i=\'Token with "\'+a.type+\'" type was not found.\';if(this.options.silent)return console.error(i),"";throw new Error(i)}}}return s}},q=class{options;block;constructor(t){this.options=t||_}static passThroughHooks=new Set(["preprocess","postprocess","processAllTokens","emStrongMask"]);static passThroughHooksRespectAsync=new Set(["preprocess","postprocess","processAllTokens"]);preprocess(t){return t}postprocess(t){return t}processAllTokens(t){return t}emStrongMask(t){return t}provideLexer(t=this.block){return t?R.lex:R.lexInline}provideParser(t=this.block){return t?$.parse:$.parseInline}},mt=class{defaults=V();options=this.setOptions;parse=this.parseMarkdown(!0);parseInline=this.parseMarkdown(!1);Parser=$;Renderer=Q;TextRenderer=se;Lexer=R;Tokenizer=O;Hooks=q;constructor(...t){this.use(...t)}walkTokens(t,e){let n=[];for(let s of t)switch(n=n.concat(e.call(this,s)),s.type){case"table":{let r=s;for(let l of r.header)n=n.concat(this.walkTokens(l.tokens,e));for(let l of r.rows)for(let a of l)n=n.concat(this.walkTokens(a.tokens,e));break}case"list":{let r=s;n=n.concat(this.walkTokens(r.items,e));break}default:{let r=s;this.defaults.extensions?.childTokens?.[r.type]?this.defaults.extensions.childTokens[r.type].forEach(l=>{let a=r[l].flat(1/0);n=n.concat(this.walkTokens(a,e))}):r.tokens&&(n=n.concat(this.walkTokens(r.tokens,e)))}}return n}use(...t){let e=this.defaults.extensions||{renderers:{},childTokens:{}};return t.forEach(n=>{let s={...n};if(s.async=this.defaults.async||s.async||!1,n.extensions&&(n.extensions.forEach(r=>{if(!r.name)throw new Error("extension name required");if("renderer"in r){let l=e.renderers[r.name];l?e.renderers[r.name]=function(...a){let i=r.renderer.apply(this,a);return i===!1&&(i=l.apply(this,a)),i}:e.renderers[r.name]=r.renderer}if("tokenizer"in r){if(!r.level||r.level!=="block"&&r.level!=="inline")throw new Error("extension level must be \'block\' or \'inline\'");let l=e[r.level];l?l.unshift(r.tokenizer):e[r.level]=[r.tokenizer],r.start&&(r.level==="block"?e.startBlock?e.startBlock.push(r.start):e.startBlock=[r.start]:r.level==="inline"&&(e.startInline?e.startInline.push(r.start):e.startInline=[r.start]))}"childTokens"in r&&r.childTokens&&(e.childTokens[r.name]=r.childTokens)}),s.extensions=e),n.renderer){let r=this.defaults.renderer||new Q(this.defaults);for(let l in n.renderer){if(!(l in r))throw new Error(`renderer \'${l}\' does not exist`);if(["options","parser"].includes(l))continue;let a=l,i=n.renderer[a],o=r[a];r[a]=(...c)=>{let u=i.apply(r,c);return u===!1&&(u=o.apply(r,c)),u||""}}s.renderer=r}if(n.tokenizer){let r=this.defaults.tokenizer||new O(this.defaults);for(let l in n.tokenizer){if(!(l in r))throw new Error(`tokenizer \'${l}\' does not exist`);if(["options","rules","lexer"].includes(l))continue;let a=l,i=n.tokenizer[a],o=r[a];r[a]=(...c)=>{let u=i.apply(r,c);return u===!1&&(u=o.apply(r,c)),u}}s.tokenizer=r}if(n.hooks){let r=this.defaults.hooks||new q;for(let l in n.hooks){if(!(l in r))throw new Error(`hook \'${l}\' does not exist`);if(["options","block"].includes(l))continue;let a=l,i=n.hooks[a],o=r[a];q.passThroughHooks.has(l)?r[a]=c=>{if(this.defaults.async&&q.passThroughHooksRespectAsync.has(l))return(async()=>{let h=await i.call(r,c);return o.call(r,h)})();let u=i.call(r,c);return o.call(r,u)}:r[a]=(...c)=>{if(this.defaults.async)return(async()=>{let h=await i.apply(r,c);return h===!1&&(h=await o.apply(r,c)),h})();let u=i.apply(r,c);return u===!1&&(u=o.apply(r,c)),u}}s.hooks=r}if(n.walkTokens){let r=this.defaults.walkTokens,l=n.walkTokens;s.walkTokens=function(a){let i=[];return i.push(l.call(this,a)),r&&(i=i.concat(r.call(this,a))),i}}this.defaults={...this.defaults,...s}}),this}setOptions(t){return this.defaults={...this.defaults,...t},this}lexer(t,e){return R.lex(t,e??this.defaults)}parser(t,e){return $.parse(t,e??this.defaults)}parseMarkdown(t){return(e,n)=>{let s={...n},r={...this.defaults,...s},l=this.onError(!!r.silent,!!r.async);if(this.defaults.async===!0&&s.async===!1)return l(new Error("marked(): The async option was set to true by an extension. Remove async: false from the parse options object to return a Promise."));if(typeof e>"u"||e===null)return l(new Error("marked(): input parameter is undefined or null"));if(typeof e!="string")return l(new Error("marked(): input parameter is of type "+Object.prototype.toString.call(e)+", string expected"));if(r.hooks&&(r.hooks.options=r,r.hooks.block=t),r.async)return(async()=>{let a=r.hooks?await r.hooks.preprocess(e):e,i=await(r.hooks?await r.hooks.provideLexer(t):t?R.lex:R.lexInline)(a,r),o=r.hooks?await r.hooks.processAllTokens(i):i;r.walkTokens&&await Promise.all(this.walkTokens(o,r.walkTokens));let c=await(r.hooks?await r.hooks.provideParser(t):t?$.parse:$.parseInline)(o,r);return r.hooks?await r.hooks.postprocess(c):c})().catch(l);try{r.hooks&&(e=r.hooks.preprocess(e));let a=(r.hooks?r.hooks.provideLexer(t):t?R.lex:R.lexInline)(e,r);r.hooks&&(a=r.hooks.processAllTokens(a)),r.walkTokens&&this.walkTokens(a,r.walkTokens);let i=(r.hooks?r.hooks.provideParser(t):t?$.parse:$.parseInline)(a,r);return r.hooks&&(i=r.hooks.postprocess(i)),i}catch(a){return l(a)}}}onError(t,e){return n=>{if(n.message+=`\nPlease report this to https://github.com/markedjs/marked.`,t){let s="<p>An error occurred:</p><pre>"+S(n.message+"",!0)+"</pre>";return e?Promise.resolve(s):s}if(e)return Promise.reject(n);throw n}}},I=new mt;function g(t,e){return I.parse(t,e)}g.options=g.setOptions=function(t){return I.setOptions(t),g.defaults=I.defaults,ke(g.defaults),g};g.getDefaults=V;g.defaults=_;g.use=function(...t){return I.use(...t),g.defaults=I.defaults,ke(g.defaults),g};g.walkTokens=function(t,e){return I.walkTokens(t,e)};g.parseInline=I.parseInline;g.Parser=$;g.parser=$.parse;g.Renderer=Q;g.TextRenderer=se;g.Lexer=R;g.lexer=R.lex;g.Tokenizer=O;g.Hooks=q;g.parse=g;var zt=g.options,At=g.setOptions,Ct=g.use,It=g.walkTokens,_t=g.parseInline;var Pt=$.parse,Mt=R.lex;function Se(t,e,n){let s=0;for(let r=e;r<n;r++)s+=t[r].raw.length;return s}function wt(t,e){let n=t;return n.links=e,n}var yt=/^ {0,3}\\$\\$/m;function Le(t){return t.includes("$$")===!1?!1:yt.test(t)}function Rt(t,e){return t[e-2]?.type!=="list"?!0:e+1<t.length}function ze(t,e){for(let n=t.length-2;n>=e;n--)if(t[n].type==="space"&&Rt(t,n+1)!==!1)return n+1;return-1}function Ae(t){let e=t.links;if(!e)return!1;for(let n in e)return!0;return!1}function Ce(t,e,n,s,r){let l=r;for(let a=e;a<n;a++){let i=t[a].raw;if(s.startsWith(i,l)===!1)return!1;l+=i.length}return!0}function G(t,e,n){return{source:t,tail:t,tokens:e,stableCount:0,stableOffset:0,degraded:!0,degradedReason:n}}function Te(t,e){return{source:t,tail:t,tokens:e,stableCount:0,stableOffset:0,degraded:!1,degradedReason:null}}function $t(t,e){if(Ae(e))return G(t,e,"link-definition");if(t.includes("\\r"))return G(t,e,"carriage-return");if(Le(t))return G(t,e,"block-math");let n=ze(e,1);if(n<0||Ce(e,0,n,t,0)===!1)return Te(t,e);let s=Se(e,0,n);return{source:t,tail:t.slice(s),tokens:e,stableCount:n,stableOffset:s,degraded:!1,degradedReason:null}}function le(t){let e=g.lexer(t);return{tokens:e,cache:$t(t,e),charsLexed:t.length,reusedTokens:0}}function j(t,e){let n=g.lexer(t);return{tokens:n,cache:G(t,n,e),charsLexed:t.length,reusedTokens:0}}function Ie(t,e){let n=t.source+e;if(t.degraded)return j(n,t.degradedReason??"link-definition");if(e.includes("\\r"))return j(n,"carriage-return");if(t.stableCount===0)return le(n);let s=t.tail+e;if(Le(s))return j(n,"block-math");let r=g.lexer(s);if(Ae(r))return j(n,"link-definition");let l=t.tokens.slice(0,t.stableCount),a=wt([...l,...r],r.links),i=t.stableCount,o=t.stableOffset,c=s,u=ze(a,t.stableCount+1);if(u>t.stableCount&&Ce(a,t.stableCount,u,s,0)){let h=Se(a,t.stableCount,u);i=u,o=t.stableOffset+h,c=s.slice(h)}return{tokens:a,cache:{source:n,tail:c,tokens:a,stableCount:i,stableOffset:o,degraded:!1,degradedReason:null},charsLexed:s.length,reusedTokens:t.stableCount}}var Tt=0;function St(t){if(typeof t!="string"||typeof performance.mark!="function"||typeof performance.measure!="function")return null;let e=Tt++,n={name:t,startMark:`${t}:start:${e}`,endMark:`${t}:end:${e}`};try{return performance.mark(n.startMark),n}catch{return null}}function Lt(t){if(t)try{performance.mark(t.endMark),performance.measure(t.name,t.startMark,t.endMark)}catch{}finally{try{performance.clearMarks?.(t.startMark),performance.clearMarks?.(t.endMark)}catch{}}}g.use({extensions:[{name:"blockMath",level:"block",start(t){return t.match(/^ {0,3}\\$\\$/m)?.index},tokenizer(t){let e=/^ {0,3}\\$\\$([\\s\\S]+?)\\$\\$[ \\t]*(?:\\n|$)/.exec(t);if(e)return{type:"blockMath",raw:e[0],text:e[1].trim()}},renderer(t){return t.raw}},{name:"inlineMath",level:"inline",start(t){return t.match(/(?<![\\\\$])\\$(?![$\\s])/)?.index},tokenizer(t){let e=/^\\$(?![$\\s\\d])((?:\\\\\\$|[^$\\n])*?)(?<!\\s)\\$(?!\\d)/.exec(t);if(e)return{type:"inlineMath",raw:e[0],text:e[1].trim()}},renderer(t){return t.raw}}]});var E=new Map;self.onmessage=t=>{let e=t.data;if(typeof e!="object"||e===null)return;let{id:n,text:s,append:r,expectedLength:l,oldRaws:a,instance:i,baseVersion:o,dispose:c,userTimingName:u}=e;if(c===!0){typeof i=="string"&&E.delete(i);return}let h=typeof i=="string"?i:null,p=typeof o=="number"?o:null,d,f=null,m=null;if(typeof r=="string"){if(h===null||p===null){self.postMessage({id:n,needResync:!0});return}let w=E.get(h);if(!w||w.version!==p){self.postMessage({id:n,needResync:!0});return}if(typeof l=="number"&&w.lex.source.length+r.length!==l){E.delete(h),self.postMessage({id:n,needResync:!0});return}let y=w.lex;d=()=>Ie(y,r),m=y.tokens}else if(typeof s=="string"){let w=s;if(d=()=>le(w),Array.isArray(a))f=a;else if(h!==null&&p!==null){let y=E.get(h);if(y&&y.version===p)m=y.lex.tokens;else{self.postMessage({id:n,needResync:!0});return}}}else return;try{let w=typeof u=="string"?St(u):null,y=performance.now(),L;try{L=d()}finally{w&&Lt(w)}let W=performance.now()-y,A=L.tokens,b=0;if(f!==null){let T=Math.min(f.length,A.length);for(;b<T&&f[b]===A[b].raw;b++);}else if(m!==null){let T=m,ie=Math.min(T.length,A.length);for(b=Math.min(L.reusedTokens,ie);b<ie&&T[b].raw===A[b].raw;b++);}h!==null&&p!==null&&E.set(h,{version:p+1,lex:L.cache}),self.postMessage({id:n,matchLen:b,tail:A.slice(b),lexerMs:W,sourceCharsLexed:L.charsLexed})}catch(w){h!==null&&E.delete(h),self.postMessage({id:n,error:String(w)})}};})();\n';
|
|
777
|
-
|
|
778
|
-
|
|
779
|
-
|
|
780
|
-
|
|
781
|
-
|
|
782
|
-
|
|
783
|
-
|
|
784
|
-
|
|
785
|
-
|
|
786
|
-
|
|
575
|
+
// src/markdown-code.ts
|
|
576
|
+
var KEYWORD_SETS = {
|
|
577
|
+
js: /* @__PURE__ */ new Set([
|
|
578
|
+
"const",
|
|
579
|
+
"let",
|
|
580
|
+
"var",
|
|
581
|
+
"function",
|
|
582
|
+
"return",
|
|
583
|
+
"if",
|
|
584
|
+
"else",
|
|
585
|
+
"for",
|
|
586
|
+
"while",
|
|
587
|
+
"class",
|
|
588
|
+
"extends",
|
|
589
|
+
"new",
|
|
590
|
+
"this",
|
|
591
|
+
"import",
|
|
592
|
+
"export",
|
|
593
|
+
"from",
|
|
594
|
+
"default",
|
|
595
|
+
"async",
|
|
596
|
+
"await",
|
|
597
|
+
"try",
|
|
598
|
+
"catch",
|
|
599
|
+
"throw",
|
|
600
|
+
"of",
|
|
601
|
+
"in",
|
|
602
|
+
"typeof",
|
|
603
|
+
"instanceof",
|
|
604
|
+
"switch",
|
|
605
|
+
"case",
|
|
606
|
+
"break",
|
|
607
|
+
"continue",
|
|
608
|
+
"null",
|
|
609
|
+
"undefined",
|
|
610
|
+
"true",
|
|
611
|
+
"false"
|
|
612
|
+
]),
|
|
613
|
+
ts: /* @__PURE__ */ new Set([
|
|
614
|
+
"const",
|
|
615
|
+
"let",
|
|
616
|
+
"var",
|
|
617
|
+
"function",
|
|
618
|
+
"return",
|
|
619
|
+
"if",
|
|
620
|
+
"else",
|
|
621
|
+
"for",
|
|
622
|
+
"while",
|
|
623
|
+
"class",
|
|
624
|
+
"extends",
|
|
625
|
+
"new",
|
|
626
|
+
"this",
|
|
627
|
+
"import",
|
|
628
|
+
"export",
|
|
629
|
+
"from",
|
|
630
|
+
"default",
|
|
631
|
+
"async",
|
|
632
|
+
"await",
|
|
633
|
+
"try",
|
|
634
|
+
"catch",
|
|
635
|
+
"throw",
|
|
636
|
+
"of",
|
|
637
|
+
"in",
|
|
638
|
+
"typeof",
|
|
639
|
+
"instanceof",
|
|
640
|
+
"switch",
|
|
641
|
+
"case",
|
|
642
|
+
"break",
|
|
643
|
+
"continue",
|
|
644
|
+
"null",
|
|
645
|
+
"undefined",
|
|
646
|
+
"true",
|
|
647
|
+
"false",
|
|
648
|
+
"type",
|
|
649
|
+
"interface",
|
|
650
|
+
"enum",
|
|
651
|
+
"as",
|
|
652
|
+
"is",
|
|
653
|
+
"readonly",
|
|
654
|
+
"implements",
|
|
655
|
+
"abstract",
|
|
656
|
+
"public",
|
|
657
|
+
"private",
|
|
658
|
+
"protected",
|
|
659
|
+
"static",
|
|
660
|
+
"void",
|
|
661
|
+
"never",
|
|
662
|
+
"any",
|
|
663
|
+
"unknown"
|
|
664
|
+
]),
|
|
665
|
+
py: /* @__PURE__ */ new Set([
|
|
666
|
+
"def",
|
|
667
|
+
"class",
|
|
668
|
+
"return",
|
|
669
|
+
"if",
|
|
670
|
+
"elif",
|
|
671
|
+
"else",
|
|
672
|
+
"for",
|
|
673
|
+
"while",
|
|
674
|
+
"import",
|
|
675
|
+
"from",
|
|
676
|
+
"as",
|
|
677
|
+
"with",
|
|
678
|
+
"try",
|
|
679
|
+
"except",
|
|
680
|
+
"raise",
|
|
681
|
+
"finally",
|
|
682
|
+
"pass",
|
|
683
|
+
"break",
|
|
684
|
+
"continue",
|
|
685
|
+
"and",
|
|
686
|
+
"or",
|
|
687
|
+
"not",
|
|
688
|
+
"in",
|
|
689
|
+
"is",
|
|
690
|
+
"None",
|
|
691
|
+
"True",
|
|
692
|
+
"False",
|
|
693
|
+
"yield",
|
|
694
|
+
"lambda",
|
|
695
|
+
"global",
|
|
696
|
+
"nonlocal",
|
|
697
|
+
"del",
|
|
698
|
+
"assert",
|
|
699
|
+
"async",
|
|
700
|
+
"await"
|
|
701
|
+
]),
|
|
702
|
+
rust: /* @__PURE__ */ new Set([
|
|
703
|
+
"fn",
|
|
704
|
+
"let",
|
|
705
|
+
"mut",
|
|
706
|
+
"const",
|
|
707
|
+
"if",
|
|
708
|
+
"else",
|
|
709
|
+
"for",
|
|
710
|
+
"while",
|
|
711
|
+
"loop",
|
|
712
|
+
"match",
|
|
713
|
+
"return",
|
|
714
|
+
"struct",
|
|
715
|
+
"enum",
|
|
716
|
+
"impl",
|
|
717
|
+
"trait",
|
|
718
|
+
"pub",
|
|
719
|
+
"use",
|
|
720
|
+
"mod",
|
|
721
|
+
"crate",
|
|
722
|
+
"self",
|
|
723
|
+
"super",
|
|
724
|
+
"where",
|
|
725
|
+
"as",
|
|
726
|
+
"in",
|
|
727
|
+
"ref",
|
|
728
|
+
"move",
|
|
729
|
+
"async",
|
|
730
|
+
"await",
|
|
731
|
+
"true",
|
|
732
|
+
"false",
|
|
733
|
+
"type",
|
|
734
|
+
"unsafe",
|
|
735
|
+
"extern",
|
|
736
|
+
"dyn",
|
|
737
|
+
"static"
|
|
738
|
+
])
|
|
739
|
+
};
|
|
740
|
+
KEYWORD_SETS["javascript"] = KEYWORD_SETS["js"];
|
|
741
|
+
KEYWORD_SETS["typescript"] = KEYWORD_SETS["ts"];
|
|
742
|
+
KEYWORD_SETS["python"] = KEYWORD_SETS["py"];
|
|
743
|
+
KEYWORD_SETS["rs"] = KEYWORD_SETS["rust"];
|
|
744
|
+
function highlightLine(line, lang, theme) {
|
|
745
|
+
const keywords = KEYWORD_SETS[lang];
|
|
746
|
+
if (!keywords) {
|
|
747
|
+
return [{ text: line, color: theme.codeColor }];
|
|
787
748
|
}
|
|
788
|
-
|
|
789
|
-
|
|
790
|
-
|
|
791
|
-
|
|
792
|
-
|
|
793
|
-
|
|
794
|
-
|
|
795
|
-
|
|
796
|
-
|
|
797
|
-
|
|
798
|
-
|
|
799
|
-
if (match) {
|
|
800
|
-
return {
|
|
801
|
-
type: "blockMath",
|
|
802
|
-
raw: match[0],
|
|
803
|
-
text: match[1].trim()
|
|
804
|
-
};
|
|
805
|
-
}
|
|
806
|
-
return void 0;
|
|
807
|
-
},
|
|
808
|
-
renderer(token) {
|
|
809
|
-
return token.raw;
|
|
810
|
-
}
|
|
811
|
-
},
|
|
812
|
-
{
|
|
813
|
-
name: "inlineMath",
|
|
814
|
-
level: "inline",
|
|
815
|
-
start(src) {
|
|
816
|
-
return src.match(/(?<![\\$])\$(?![$\s])/)?.index;
|
|
817
|
-
},
|
|
818
|
-
tokenizer(src) {
|
|
819
|
-
const match = /^\$(?![$\s\d])((?:\\\$|[^$\n])*?)(?<!\s)\$(?!\d)/.exec(src);
|
|
820
|
-
if (match) {
|
|
821
|
-
return {
|
|
822
|
-
type: "inlineMath",
|
|
823
|
-
raw: match[0],
|
|
824
|
-
text: match[1].trim()
|
|
825
|
-
};
|
|
826
|
-
}
|
|
827
|
-
return void 0;
|
|
828
|
-
},
|
|
829
|
-
renderer(token) {
|
|
830
|
-
return token.raw;
|
|
831
|
-
}
|
|
749
|
+
const segments = [];
|
|
750
|
+
const KEYWORD_COLOR = theme.syntaxKeywordColor;
|
|
751
|
+
const STRING_COLOR = theme.syntaxStringColor;
|
|
752
|
+
const COMMENT_COLOR = theme.syntaxCommentColor;
|
|
753
|
+
const NUMBER_COLOR = theme.syntaxNumberColor;
|
|
754
|
+
let i = 0;
|
|
755
|
+
let buf = "";
|
|
756
|
+
const flush = (color) => {
|
|
757
|
+
if (buf) {
|
|
758
|
+
segments.push({ text: buf, color });
|
|
759
|
+
buf = "";
|
|
832
760
|
}
|
|
833
|
-
|
|
834
|
-
|
|
835
|
-
|
|
836
|
-
|
|
837
|
-
|
|
838
|
-
|
|
839
|
-
|
|
840
|
-
const fallback = ns?.default;
|
|
841
|
-
if (fallback && typeof fallback[key] !== "undefined") return fallback;
|
|
842
|
-
throw new Error(`mathjax-full module is missing export "${key}"`);
|
|
843
|
-
}
|
|
844
|
-
function preloadMathJax() {
|
|
845
|
-
if (mathLoad) return mathLoad;
|
|
846
|
-
mathLoad = (async () => {
|
|
847
|
-
const [mathjaxMod, texMod, svgMod, adaptorMod, handlerMod, packagesMod] = await Promise.all([
|
|
848
|
-
import("mathjax-full/js/mathjax.js"),
|
|
849
|
-
import("mathjax-full/js/input/tex.js"),
|
|
850
|
-
import("mathjax-full/js/output/svg.js"),
|
|
851
|
-
import("mathjax-full/js/adaptors/liteAdaptor.js"),
|
|
852
|
-
import("mathjax-full/js/handlers/html.js"),
|
|
853
|
-
import("mathjax-full/js/input/tex/AllPackages.js")
|
|
854
|
-
]);
|
|
855
|
-
const { mathjax } = interop(mathjaxMod, "mathjax");
|
|
856
|
-
const { TeX } = interop(texMod, "TeX");
|
|
857
|
-
const { SVG } = interop(svgMod, "SVG");
|
|
858
|
-
const { liteAdaptor } = interop(adaptorMod, "liteAdaptor");
|
|
859
|
-
const { RegisterHTMLHandler } = interop(handlerMod, "RegisterHTMLHandler");
|
|
860
|
-
const { AllPackages } = interop(packagesMod, "AllPackages");
|
|
861
|
-
const adaptor = liteAdaptor();
|
|
862
|
-
RegisterHTMLHandler(adaptor);
|
|
863
|
-
const tex = new TeX({ packages: AllPackages });
|
|
864
|
-
const svg = new SVG({ fontCache: "local" });
|
|
865
|
-
const htmlMathJax = mathjax.document("", { InputJax: tex, OutputJax: svg });
|
|
866
|
-
mathConverter = (formula, displayMode, color) => convertMathToSVGDataURI(
|
|
867
|
-
formula,
|
|
868
|
-
displayMode,
|
|
869
|
-
(f, d) => adaptor.innerHTML(htmlMathJax.convert(f, { display: d })),
|
|
870
|
-
color
|
|
871
|
-
);
|
|
872
|
-
})().catch((e) => {
|
|
873
|
-
console.error("MathJax failed to load; formulas will render as TeX source", e);
|
|
874
|
-
});
|
|
875
|
-
return mathLoad;
|
|
876
|
-
}
|
|
877
|
-
function isMathJaxReady() {
|
|
878
|
-
return mathConverter !== null;
|
|
879
|
-
}
|
|
880
|
-
var EX_PER_EM = 0.4421;
|
|
881
|
-
function exToPx(ex, fontSize) {
|
|
882
|
-
return ex * fontSize * EX_PER_EM;
|
|
883
|
-
}
|
|
884
|
-
function fontSizeFromFont(font) {
|
|
885
|
-
const pxIndex = font.indexOf("px");
|
|
886
|
-
if (pxIndex <= 0) return void 0;
|
|
887
|
-
let start = pxIndex;
|
|
888
|
-
while (start > 0) {
|
|
889
|
-
const ch = font[start - 1];
|
|
890
|
-
if (ch >= "0" && ch <= "9" || ch === ".") start--;
|
|
891
|
-
else break;
|
|
892
|
-
}
|
|
893
|
-
if (start === pxIndex) return void 0;
|
|
894
|
-
const size = parseFloat(font.slice(start, pxIndex));
|
|
895
|
-
return Number.isFinite(size) ? size : void 0;
|
|
896
|
-
}
|
|
897
|
-
var mathCache = /* @__PURE__ */ new Map();
|
|
898
|
-
var MATH_CACHE_LIMIT = 256;
|
|
899
|
-
var inlineMathRasters = /* @__PURE__ */ new Map();
|
|
900
|
-
var inlineMathRasterWaiters = /* @__PURE__ */ new Set();
|
|
901
|
-
function ensureInlineMathRaster(uri) {
|
|
902
|
-
const existing = inlineMathRasters.get(uri);
|
|
903
|
-
if (existing) return existing;
|
|
904
|
-
const entry = { decoded: false };
|
|
905
|
-
inlineMathRasters.set(uri, entry);
|
|
906
|
-
if (typeof globalThis.Image !== "undefined") {
|
|
907
|
-
const bitmap = new globalThis.Image();
|
|
908
|
-
bitmap.onload = () => {
|
|
909
|
-
entry.decoded = true;
|
|
910
|
-
for (const notify of inlineMathRasterWaiters) notify();
|
|
911
|
-
};
|
|
912
|
-
bitmap.src = uri;
|
|
913
|
-
entry.bitmap = bitmap;
|
|
914
|
-
}
|
|
915
|
-
return entry;
|
|
916
|
-
}
|
|
917
|
-
function paintInlineMath(uri, surface, box) {
|
|
918
|
-
const raster = ensureInlineMathRaster(uri);
|
|
919
|
-
if (!raster.decoded || !raster.bitmap) return;
|
|
920
|
-
surface.drawImage(raster.bitmap, box.x, box.y, box.width, box.height);
|
|
921
|
-
}
|
|
922
|
-
var MATH_LANGS = /* @__PURE__ */ new Set(["math", "latex", "tex"]);
|
|
923
|
-
function containsInlineMath(token) {
|
|
924
|
-
if (token.type === "inlineMath") return true;
|
|
925
|
-
const anyToken = token;
|
|
926
|
-
if (Array.isArray(anyToken.tokens) && anyToken.tokens.some(containsInlineMath)) {
|
|
927
|
-
return true;
|
|
928
|
-
}
|
|
929
|
-
if (Array.isArray(anyToken.items) && anyToken.items.some(containsInlineMath)) {
|
|
930
|
-
return true;
|
|
931
|
-
}
|
|
932
|
-
if (Array.isArray(anyToken.header) && anyToken.header.some(containsInlineMath)) {
|
|
933
|
-
return true;
|
|
934
|
-
}
|
|
935
|
-
if (Array.isArray(anyToken.rows)) {
|
|
936
|
-
for (const row of anyToken.rows) {
|
|
937
|
-
if (Array.isArray(row) && row.some(containsInlineMath)) return true;
|
|
761
|
+
};
|
|
762
|
+
while (i < line.length) {
|
|
763
|
+
const ch = line[i];
|
|
764
|
+
if (ch === "/" && line[i + 1] === "/") {
|
|
765
|
+
flush(theme.codeColor);
|
|
766
|
+
segments.push({ text: line.slice(i), color: COMMENT_COLOR });
|
|
767
|
+
return segments;
|
|
938
768
|
}
|
|
939
|
-
|
|
940
|
-
|
|
941
|
-
}
|
|
942
|
-
|
|
943
|
-
var FENCE_CLOSE_RE = /^ {0,3}(`+|~+)[ \t]*$/;
|
|
944
|
-
function isFenceClosed(raw) {
|
|
945
|
-
const lines = raw.split("\n");
|
|
946
|
-
const open = FENCE_OPEN_RE.exec(lines[0]);
|
|
947
|
-
if (!open) return false;
|
|
948
|
-
const marker = open[1][0];
|
|
949
|
-
const minLen = open[1].length;
|
|
950
|
-
for (let i = 1; i < lines.length; i++) {
|
|
951
|
-
const close = FENCE_CLOSE_RE.exec(lines[i]);
|
|
952
|
-
if (close && close[1][0] === marker && close[1].length >= minLen) return true;
|
|
953
|
-
}
|
|
954
|
-
return false;
|
|
955
|
-
}
|
|
956
|
-
function paragraphHasImage(token) {
|
|
957
|
-
return containsImage(token.tokens);
|
|
958
|
-
}
|
|
959
|
-
function containsImage(tokens) {
|
|
960
|
-
if (!tokens) return false;
|
|
961
|
-
for (const token of tokens) {
|
|
962
|
-
if (token.type === "image") return true;
|
|
963
|
-
if (containsImage(token.tokens)) return true;
|
|
964
|
-
}
|
|
965
|
-
return false;
|
|
966
|
-
}
|
|
967
|
-
function imagesOf(tokens) {
|
|
968
|
-
const images = [];
|
|
969
|
-
for (const token of tokens ?? []) {
|
|
970
|
-
if (token.type === "image") {
|
|
971
|
-
images.push(token);
|
|
972
|
-
continue;
|
|
769
|
+
if (ch === "#" && (lang === "py" || lang === "python" || lang === "rust" || lang === "rs")) {
|
|
770
|
+
flush(theme.codeColor);
|
|
771
|
+
segments.push({ text: line.slice(i), color: COMMENT_COLOR });
|
|
772
|
+
return segments;
|
|
973
773
|
}
|
|
974
|
-
|
|
975
|
-
|
|
976
|
-
|
|
977
|
-
|
|
978
|
-
|
|
979
|
-
|
|
980
|
-
|
|
981
|
-
|
|
982
|
-
|
|
983
|
-
|
|
984
|
-
|
|
985
|
-
|
|
986
|
-
|
|
987
|
-
|
|
988
|
-
|
|
774
|
+
if (ch === '"' || ch === "'" || ch === "`") {
|
|
775
|
+
const quote = ch;
|
|
776
|
+
let j = i + 1;
|
|
777
|
+
let closed = false;
|
|
778
|
+
while (j < line.length) {
|
|
779
|
+
if (line[j] === "\\") {
|
|
780
|
+
j += 2;
|
|
781
|
+
continue;
|
|
782
|
+
}
|
|
783
|
+
if (line[j] === quote) {
|
|
784
|
+
closed = true;
|
|
785
|
+
break;
|
|
786
|
+
}
|
|
787
|
+
j++;
|
|
788
|
+
}
|
|
789
|
+
if (closed) {
|
|
790
|
+
flush(theme.codeColor);
|
|
791
|
+
segments.push({ text: line.slice(i, j + 1), color: STRING_COLOR });
|
|
792
|
+
i = j + 1;
|
|
793
|
+
continue;
|
|
794
|
+
}
|
|
795
|
+
buf += ch;
|
|
796
|
+
i++;
|
|
989
797
|
continue;
|
|
990
798
|
}
|
|
991
|
-
|
|
992
|
-
|
|
993
|
-
|
|
994
|
-
|
|
995
|
-
|
|
996
|
-
|
|
997
|
-
for (const token of tokens) {
|
|
998
|
-
if (token.type === "image") {
|
|
999
|
-
lifted.push(token);
|
|
799
|
+
if (/\d/.test(ch) && (i === 0 || /[\s(,=+\-*/<>[\]{}:;]/.test(line[i - 1]))) {
|
|
800
|
+
flush(theme.codeColor);
|
|
801
|
+
let j = i;
|
|
802
|
+
while (j < line.length && /[\d._xXa-fA-F]/.test(line[j])) j++;
|
|
803
|
+
segments.push({ text: line.slice(i, j), color: NUMBER_COLOR });
|
|
804
|
+
i = j;
|
|
1000
805
|
continue;
|
|
1001
806
|
}
|
|
1002
|
-
|
|
1003
|
-
|
|
1004
|
-
|
|
807
|
+
if (/[a-zA-Z_]/.test(ch)) {
|
|
808
|
+
flush(theme.codeColor);
|
|
809
|
+
let j = i;
|
|
810
|
+
while (j < line.length && /[a-zA-Z0-9_]/.test(line[j])) j++;
|
|
811
|
+
const word = line.slice(i, j);
|
|
812
|
+
segments.push({
|
|
813
|
+
text: word,
|
|
814
|
+
color: keywords.has(word) ? KEYWORD_COLOR : theme.codeColor
|
|
815
|
+
});
|
|
816
|
+
i = j;
|
|
1005
817
|
continue;
|
|
1006
818
|
}
|
|
1007
|
-
|
|
1008
|
-
|
|
1009
|
-
return lifted;
|
|
1010
|
-
}
|
|
1011
|
-
function lastIndexOfImage(tokens) {
|
|
1012
|
-
for (let i = tokens.length - 1; i >= 0; i--) {
|
|
1013
|
-
if (tokens[i].type === "image") return i;
|
|
819
|
+
buf += ch;
|
|
820
|
+
i++;
|
|
1014
821
|
}
|
|
1015
|
-
|
|
822
|
+
flush(theme.codeColor);
|
|
823
|
+
return segments;
|
|
1016
824
|
}
|
|
1017
|
-
|
|
1018
|
-
|
|
1019
|
-
|
|
1020
|
-
|
|
1021
|
-
|
|
1022
|
-
|
|
1023
|
-
|
|
1024
|
-
|
|
1025
|
-
|
|
1026
|
-
|
|
1027
|
-
|
|
1028
|
-
|
|
1029
|
-
|
|
1030
|
-
|
|
1031
|
-
|
|
1032
|
-
|
|
1033
|
-
|
|
1034
|
-
|
|
1035
|
-
|
|
1036
|
-
|
|
1037
|
-
|
|
1038
|
-
|
|
1039
|
-
|
|
1040
|
-
|
|
1041
|
-
|
|
1042
|
-
|
|
1043
|
-
|
|
1044
|
-
|
|
1045
|
-
|
|
825
|
+
var CodeBlock = class extends import_ui.UIComponent {
|
|
826
|
+
lines;
|
|
827
|
+
grid = null;
|
|
828
|
+
/** Raw (unhighlighted) lines of the last build, for prefix reuse in buildLines. */
|
|
829
|
+
rawLines = null;
|
|
830
|
+
cellWidth = 0;
|
|
831
|
+
source;
|
|
832
|
+
/** Bumped by {@link buildLines} and {@link setSelectable}; read by `Scene`. */
|
|
833
|
+
contentEpoch = 0;
|
|
834
|
+
lang;
|
|
835
|
+
theme;
|
|
836
|
+
/**
|
|
837
|
+
* Assigned in the constructor rather than as a field initializer: both come
|
|
838
|
+
* from `theme`, and a field initializer runs before the constructor body has
|
|
839
|
+
* a `theme` to read.
|
|
840
|
+
*/
|
|
841
|
+
lineH;
|
|
842
|
+
pad;
|
|
843
|
+
codeFont;
|
|
844
|
+
selectable;
|
|
845
|
+
/**
|
|
846
|
+
* @param theme Any subset of {@link MarkdownTheme}; missing keys fall back to
|
|
847
|
+
* `DEFAULT_THEME` in `./theme`. Accepting a partial theme keeps callers that were
|
|
848
|
+
* written against an earlier, smaller `MarkdownTheme` working — this class
|
|
849
|
+
* is public API, and a hand-built theme literal would otherwise start
|
|
850
|
+
* throwing `lineHeight must be a positive finite number` the moment a new
|
|
851
|
+
* size key was added.
|
|
852
|
+
*/
|
|
853
|
+
constructor(code, lang, maxWidth, theme, selectable = true) {
|
|
854
|
+
super();
|
|
855
|
+
const resolved = resolveTheme(theme);
|
|
856
|
+
this.source = code;
|
|
857
|
+
this.lang = lang;
|
|
858
|
+
this.theme = resolved;
|
|
859
|
+
this.lineH = resolved.codeLineHeight;
|
|
860
|
+
this.pad = resolved.codePadding;
|
|
861
|
+
this.codeFont = `${resolved.codeFontSize}px ${resolved.codeFont}`;
|
|
862
|
+
this.selectable = selectable;
|
|
863
|
+
this.lines = [];
|
|
864
|
+
this.width = maxWidth;
|
|
865
|
+
this.buildLines(code);
|
|
1046
866
|
}
|
|
1047
|
-
|
|
1048
|
-
|
|
1049
|
-
|
|
1050
|
-
|
|
1051
|
-
|
|
1052
|
-
|
|
1053
|
-
|
|
1054
|
-
return svg.replace(tag, colored);
|
|
1055
|
-
}
|
|
1056
|
-
function convertMathToSVGDataURI(formula, displayMode, typeset, color) {
|
|
1057
|
-
try {
|
|
1058
|
-
const svgString = applyMathColor(typeset(formula, displayMode), color);
|
|
1059
|
-
const wMatch = svgString.match(/width="([^"]+)ex"/);
|
|
1060
|
-
const hMatch = svgString.match(/height="([^"]+)ex"/);
|
|
1061
|
-
const wEx = wMatch ? parseFloat(wMatch[1]) : 10;
|
|
1062
|
-
const hEx = hMatch ? parseFloat(hMatch[1]) : 2;
|
|
1063
|
-
const vMatch = svgString.match(/vertical-align:\s*(-?[\d.]+)ex/);
|
|
1064
|
-
const depthEx = vMatch ? Math.max(0, -parseFloat(vMatch[1])) : 0;
|
|
1065
|
-
const base64 = btoa(unescape(encodeURIComponent(svgString)));
|
|
1066
|
-
return {
|
|
1067
|
-
uri: `data:image/svg+xml;base64,${base64}`,
|
|
1068
|
-
widthEx: wEx,
|
|
1069
|
-
heightEx: hEx,
|
|
1070
|
-
depthEx
|
|
1071
|
-
};
|
|
1072
|
-
} catch (e) {
|
|
1073
|
-
console.error("MathJax error", e);
|
|
1074
|
-
return null;
|
|
867
|
+
/** Re-parse code content (e.g. for live editing). */
|
|
868
|
+
setCode(code, lang) {
|
|
869
|
+
if (lang !== void 0) this.lang = lang;
|
|
870
|
+
this.source = code;
|
|
871
|
+
this.buildLines(code);
|
|
872
|
+
this.scene?.markDirty();
|
|
873
|
+
return this;
|
|
1075
874
|
}
|
|
1076
|
-
|
|
1077
|
-
|
|
1078
|
-
|
|
1079
|
-
|
|
1080
|
-
|
|
1081
|
-
|
|
1082
|
-
try {
|
|
1083
|
-
entry.cb(0, lexMarkdown(entry.text, entry.userTiming), true);
|
|
1084
|
-
} catch (err) {
|
|
1085
|
-
console.warn("Markdown sync fallback parse failed", err);
|
|
1086
|
-
entry.onDropped?.();
|
|
875
|
+
/** Enable or disable browser-native selection for this code block. */
|
|
876
|
+
setSelectable(selectable) {
|
|
877
|
+
this.selectable = selectable;
|
|
878
|
+
this.contentEpoch++;
|
|
879
|
+
this.scene?.markDirty();
|
|
880
|
+
return this;
|
|
1087
881
|
}
|
|
1088
|
-
|
|
1089
|
-
|
|
1090
|
-
try {
|
|
1091
|
-
const blob = new Blob([WORKER_SOURCE_STRING], {
|
|
1092
|
-
type: "application/javascript"
|
|
1093
|
-
});
|
|
1094
|
-
markdownWorker = new Worker(URL.createObjectURL(blob));
|
|
1095
|
-
markdownWorker.onmessage = (e) => {
|
|
1096
|
-
const { id, matchLen, tail, error, needResync, lexerMs, sourceCharsLexed } = e.data;
|
|
1097
|
-
const entry = workerCallbacks.get(id);
|
|
1098
|
-
if (entry) {
|
|
1099
|
-
workerCallbacks.delete(id);
|
|
1100
|
-
if (needResync && entry.onNeedResync) {
|
|
1101
|
-
entry.onNeedResync();
|
|
1102
|
-
} else if (needResync) {
|
|
1103
|
-
runSyncFallback(entry);
|
|
1104
|
-
} else if (!error) {
|
|
1105
|
-
entry.cb(matchLen, tail, false, {
|
|
1106
|
-
lexerMs: typeof lexerMs === "number" ? lexerMs : 0,
|
|
1107
|
-
sourceCharsLexed: typeof sourceCharsLexed === "number" ? sourceCharsLexed : 0
|
|
1108
|
-
});
|
|
1109
|
-
} else {
|
|
1110
|
-
runSyncFallback(entry);
|
|
1111
|
-
}
|
|
1112
|
-
}
|
|
1113
|
-
};
|
|
1114
|
-
markdownWorker.onerror = () => {
|
|
1115
|
-
const pending = [...workerCallbacks.values()];
|
|
1116
|
-
workerCallbacks.clear();
|
|
1117
|
-
markdownWorker = null;
|
|
1118
|
-
for (const entry of pending) runSyncFallback(entry);
|
|
1119
|
-
};
|
|
1120
|
-
} catch (err) {
|
|
1121
|
-
console.warn("Failed to initialize MarkdownWorker", err);
|
|
882
|
+
getContentEpoch() {
|
|
883
|
+
return this.contentEpoch;
|
|
1122
884
|
}
|
|
1123
|
-
|
|
1124
|
-
|
|
1125
|
-
|
|
1126
|
-
|
|
1127
|
-
|
|
1128
|
-
|
|
1129
|
-
|
|
1130
|
-
|
|
1131
|
-
|
|
1132
|
-
|
|
1133
|
-
|
|
1134
|
-
|
|
1135
|
-
|
|
1136
|
-
|
|
1137
|
-
|
|
1138
|
-
|
|
1139
|
-
|
|
1140
|
-
|
|
1141
|
-
super();
|
|
1142
|
-
this.width = w;
|
|
1143
|
-
this.height = 1;
|
|
1144
|
-
this.color = color;
|
|
885
|
+
/**
|
|
886
|
+
* Change the block's box width.
|
|
887
|
+
*
|
|
888
|
+
* Deliberately does **not** rebuild the grid or the highlight, because code does
|
|
889
|
+
* not reflow: lines are placed on a fixed monospace grid at `col × cellWidth` and
|
|
890
|
+
* a long line overflows rather than wrapping, so `height` is a function of line
|
|
891
|
+
* *count* alone. The width only sizes the rounded background. Anything that would
|
|
892
|
+
* change the glyph geometry — the source, the language, the font — goes through
|
|
893
|
+
* {@link setCode} and invalidates the grid there.
|
|
894
|
+
*
|
|
895
|
+
* @returns `this` for chaining.
|
|
896
|
+
*/
|
|
897
|
+
setWidth(width) {
|
|
898
|
+
const next = Math.max(0, width);
|
|
899
|
+
if (next === this.width) return this;
|
|
900
|
+
this.width = next;
|
|
901
|
+
this.scene?.markDirty();
|
|
902
|
+
return this;
|
|
1145
903
|
}
|
|
1146
|
-
|
|
1147
|
-
return
|
|
904
|
+
getContentProjection(hint) {
|
|
905
|
+
if (!this.source) return null;
|
|
906
|
+
const grid = this.ensureGrid();
|
|
907
|
+
const rows = [];
|
|
908
|
+
rows.length = grid.lines.length;
|
|
909
|
+
for (let row = 0; row < grid.lines.length; row++) {
|
|
910
|
+
const line = grid.lines[row];
|
|
911
|
+
const y = this.pad + row * this.lineH;
|
|
912
|
+
if (!(0, import_core2.contentLineInHint)(hint, y, this.lineH)) continue;
|
|
913
|
+
rows[row] = {
|
|
914
|
+
text: this.source.slice(line.sourceStart, line.sourceEnd),
|
|
915
|
+
separatorAfter: this.source.slice(line.sourceEnd, line.nextSourceStart) || void 0,
|
|
916
|
+
x: this.pad,
|
|
917
|
+
y,
|
|
918
|
+
baseline: this.lineH * 0.75,
|
|
919
|
+
font: this.codeFont,
|
|
920
|
+
lineHeight: this.lineH
|
|
921
|
+
};
|
|
922
|
+
}
|
|
923
|
+
return {
|
|
924
|
+
text: this.source,
|
|
925
|
+
font: this.codeFont,
|
|
926
|
+
lineHeight: this.lineH,
|
|
927
|
+
// Every row is absolutely positioned from the same local coordinates as
|
|
928
|
+
// render(). A single pre-wrap DOM text node would introduce browser
|
|
929
|
+
// wrapping for long source lines that canvas intentionally keeps intact.
|
|
930
|
+
//
|
|
931
|
+
lines: rows,
|
|
932
|
+
selectable: this.selectable,
|
|
933
|
+
// render() draws cell-by-cell (no ligatures can form); the DOM copy
|
|
934
|
+
// must not ligate either or Firefox selection geometry drifts.
|
|
935
|
+
ligatures: "none",
|
|
936
|
+
grid
|
|
937
|
+
};
|
|
1148
938
|
}
|
|
1149
|
-
|
|
1150
|
-
|
|
1151
|
-
|
|
1152
|
-
|
|
1153
|
-
|
|
939
|
+
/**
|
|
940
|
+
* Re-highlight the code, reusing the highlight of any unchanged line prefix.
|
|
941
|
+
*
|
|
942
|
+
* Streaming appends to the END of a block, so all but the last line or two are
|
|
943
|
+
* byte-identical to the previous call — yet this used to re-highlight every
|
|
944
|
+
* line on every chunk, making a streamed block O(N) per append and O(N^2)
|
|
945
|
+
* overall. Reusing the stable prefix makes an append proportional to what
|
|
946
|
+
* actually changed.
|
|
947
|
+
*
|
|
948
|
+
* The last previously-seen line is deliberately NOT reused: a chunk usually
|
|
949
|
+
* lands mid-line, so that line's text (and therefore its tokenization) changes.
|
|
950
|
+
*/
|
|
951
|
+
buildLines(code) {
|
|
952
|
+
this.contentEpoch++;
|
|
953
|
+
const rawLines = code.split(/\r\n|\r|\n/);
|
|
954
|
+
const previous = this.rawLines;
|
|
955
|
+
let reusable = 0;
|
|
956
|
+
if (previous && this.lines.length === previous.length) {
|
|
957
|
+
const limit = Math.min(previous.length - 1, rawLines.length);
|
|
958
|
+
while (reusable < limit && previous[reusable] === rawLines[reusable]) reusable++;
|
|
959
|
+
}
|
|
960
|
+
if (reusable > 0) {
|
|
961
|
+
const next = this.lines.slice(0, reusable);
|
|
962
|
+
for (let i = reusable; i < rawLines.length; i++) {
|
|
963
|
+
next.push(highlightLine(rawLines[i], this.lang, this.theme));
|
|
964
|
+
}
|
|
965
|
+
this.lines = next;
|
|
966
|
+
} else {
|
|
967
|
+
this.lines = rawLines.map((l) => highlightLine(l, this.lang, this.theme));
|
|
968
|
+
}
|
|
969
|
+
this.rawLines = rawLines;
|
|
970
|
+
this.grid = null;
|
|
971
|
+
this.height = this.pad * 2 + rawLines.length * this.lineH;
|
|
1154
972
|
}
|
|
1155
|
-
|
|
1156
|
-
|
|
1157
|
-
|
|
1158
|
-
|
|
1159
|
-
|
|
1160
|
-
|
|
1161
|
-
|
|
1162
|
-
|
|
973
|
+
ensureGrid() {
|
|
974
|
+
const cellWidth = this.cellWidth || Math.max(1, (0, import_ui.measureText)("M", this.codeFont));
|
|
975
|
+
if (!this.grid || this.grid.source !== this.source || this.grid.font !== this.codeFont || this.grid.cellWidth !== cellWidth) {
|
|
976
|
+
this.grid = (0, import_core2.prepareContentGrid)(this.source, {
|
|
977
|
+
font: this.codeFont,
|
|
978
|
+
cellWidth,
|
|
979
|
+
lineHeight: this.lineH,
|
|
980
|
+
baseline: this.lineH * 0.75
|
|
981
|
+
});
|
|
982
|
+
}
|
|
983
|
+
return this.grid;
|
|
1163
984
|
}
|
|
985
|
+
/** Code blocks are decorative — not interactive. */
|
|
1164
986
|
isPointInside() {
|
|
1165
987
|
return false;
|
|
1166
988
|
}
|
|
1167
989
|
render(r) {
|
|
1168
990
|
r.beginPath();
|
|
1169
|
-
r.roundRect(0, 0, this.width, this.height,
|
|
1170
|
-
r.fill(this.
|
|
1171
|
-
|
|
1172
|
-
|
|
1173
|
-
|
|
1174
|
-
|
|
1175
|
-
|
|
1176
|
-
|
|
1177
|
-
|
|
1178
|
-
|
|
1179
|
-
|
|
1180
|
-
|
|
1181
|
-
|
|
1182
|
-
|
|
1183
|
-
|
|
1184
|
-
|
|
1185
|
-
|
|
1186
|
-
|
|
991
|
+
r.roundRect(0, 0, this.width, this.height, this.theme.codeRadius);
|
|
992
|
+
r.fill(this.theme.codeBgColor);
|
|
993
|
+
const grid = this.ensureGrid();
|
|
994
|
+
const atlas = codeGlyphAtlas(r);
|
|
995
|
+
const atlasSource = atlas?.source ?? null;
|
|
996
|
+
const blit = atlas ? r.drawImageRect : void 0;
|
|
997
|
+
for (let row = 0; row < grid.lines.length; row++) {
|
|
998
|
+
const yBaseline = this.pad + row * this.lineH + this.lineH * 0.75;
|
|
999
|
+
const segments = this.lines[row];
|
|
1000
|
+
let segmentIndex = 0;
|
|
1001
|
+
let segmentEnd = segments[0]?.text.length ?? 0;
|
|
1002
|
+
const lineStart = grid.lines[row].sourceStart;
|
|
1003
|
+
for (const cell of grid.lines[row].cells) {
|
|
1004
|
+
const localSourceStart = cell.sourceStart - lineStart;
|
|
1005
|
+
while (segmentIndex < segments.length - 1 && localSourceStart >= segmentEnd) {
|
|
1006
|
+
segmentIndex++;
|
|
1007
|
+
segmentEnd += segments[segmentIndex].text.length;
|
|
1008
|
+
}
|
|
1009
|
+
const sourceText = this.source.slice(cell.sourceStart, cell.sourceEnd);
|
|
1010
|
+
if (cell.advance <= 0 || sourceText === " " || sourceText === " ") continue;
|
|
1011
|
+
const color = segments[segmentIndex]?.color ?? this.theme.codeColor;
|
|
1012
|
+
const x = this.pad + cell.x;
|
|
1013
|
+
if (blit && atlas) {
|
|
1014
|
+
const slot = atlas.get(this.codeFont, color, cell.glyph);
|
|
1015
|
+
const src = atlasSource ?? atlas.source;
|
|
1016
|
+
if (slot && src) {
|
|
1017
|
+
blit.call(
|
|
1018
|
+
r,
|
|
1019
|
+
src,
|
|
1020
|
+
slot.sx,
|
|
1021
|
+
slot.sy,
|
|
1022
|
+
slot.sw,
|
|
1023
|
+
slot.sh,
|
|
1024
|
+
x - slot.offsetX,
|
|
1025
|
+
yBaseline - slot.offsetY,
|
|
1026
|
+
slot.w,
|
|
1027
|
+
slot.h
|
|
1028
|
+
);
|
|
1029
|
+
continue;
|
|
1030
|
+
}
|
|
1031
|
+
}
|
|
1032
|
+
r.fillText(cell.glyph, x, yBaseline, this.codeFont, color);
|
|
1033
|
+
}
|
|
1034
|
+
}
|
|
1035
|
+
}
|
|
1036
|
+
};
|
|
1037
|
+
var codeAtlases = /* @__PURE__ */ new Map();
|
|
1038
|
+
var MAX_CODE_ATLASES = 2;
|
|
1039
|
+
var lastCodeAtlas = null;
|
|
1040
|
+
function codeGlyphAtlas(r) {
|
|
1041
|
+
if (typeof r.drawImageRect !== "function") return void 0;
|
|
1042
|
+
if (typeof document === "undefined") return void 0;
|
|
1043
|
+
const dpr = Math.max(
|
|
1044
|
+
1,
|
|
1045
|
+
r.pixelRatio ?? (typeof window !== "undefined" ? window.devicePixelRatio || 1 : 1)
|
|
1046
|
+
);
|
|
1047
|
+
const existing = codeAtlases.get(dpr);
|
|
1048
|
+
if (existing) {
|
|
1049
|
+
codeAtlases.delete(dpr);
|
|
1050
|
+
codeAtlases.set(dpr, existing);
|
|
1051
|
+
lastCodeAtlas = existing;
|
|
1052
|
+
return existing;
|
|
1053
|
+
}
|
|
1054
|
+
const atlas = new import_core2.GlyphRasterAtlas({ dpr, maxSize: 2048 });
|
|
1055
|
+
codeAtlases.set(dpr, atlas);
|
|
1056
|
+
if (codeAtlases.size > MAX_CODE_ATLASES) {
|
|
1057
|
+
const oldestKey = codeAtlases.keys().next().value;
|
|
1058
|
+
const oldest = codeAtlases.get(oldestKey);
|
|
1059
|
+
codeAtlases.delete(oldestKey);
|
|
1060
|
+
if (oldest && oldest !== atlas) oldest.destroy();
|
|
1061
|
+
}
|
|
1062
|
+
lastCodeAtlas = atlas;
|
|
1063
|
+
return atlas;
|
|
1064
|
+
}
|
|
1065
|
+
function codeAtlasStats() {
|
|
1066
|
+
return lastCodeAtlas ? lastCodeAtlas.stats : null;
|
|
1067
|
+
}
|
|
1068
|
+
function codeAtlas() {
|
|
1069
|
+
return lastCodeAtlas;
|
|
1070
|
+
}
|
|
1071
|
+
|
|
1072
|
+
// src/markdown-footnote.ts
|
|
1073
|
+
var LABEL = "([^\\]\\s]+)";
|
|
1074
|
+
var REF_RE = new RegExp(`^\\[\\^${LABEL}\\]`);
|
|
1075
|
+
var DEF_RE = new RegExp(`^ {0,3}\\[\\^${LABEL}\\]:[ \\t]*([^\\n]*)(?:\\n|$)`);
|
|
1076
|
+
var FOOTNOTE_EXTENSIONS = [
|
|
1077
|
+
{
|
|
1078
|
+
name: "footnoteRef",
|
|
1079
|
+
level: "inline",
|
|
1080
|
+
tokenizer(src) {
|
|
1081
|
+
const match = REF_RE.exec(src);
|
|
1082
|
+
if (match) {
|
|
1083
|
+
return {
|
|
1084
|
+
type: "footnoteRef",
|
|
1085
|
+
raw: match[0],
|
|
1086
|
+
label: match[1]
|
|
1087
|
+
};
|
|
1088
|
+
}
|
|
1089
|
+
return void 0;
|
|
1090
|
+
},
|
|
1091
|
+
renderer(token) {
|
|
1092
|
+
return token.raw;
|
|
1093
|
+
}
|
|
1094
|
+
},
|
|
1095
|
+
{
|
|
1096
|
+
name: "footnoteDef",
|
|
1097
|
+
level: "block",
|
|
1098
|
+
tokenizer(src) {
|
|
1099
|
+
const match = DEF_RE.exec(src);
|
|
1100
|
+
if (match) {
|
|
1101
|
+
return {
|
|
1102
|
+
type: "footnoteDef",
|
|
1103
|
+
raw: match[0],
|
|
1104
|
+
label: match[1],
|
|
1105
|
+
body: match[2]
|
|
1106
|
+
};
|
|
1107
|
+
}
|
|
1108
|
+
return void 0;
|
|
1109
|
+
},
|
|
1110
|
+
renderer(token) {
|
|
1111
|
+
return token.raw;
|
|
1112
|
+
}
|
|
1113
|
+
}
|
|
1114
|
+
];
|
|
1115
|
+
function footnoteMarker(label) {
|
|
1116
|
+
return `[${label}]`;
|
|
1117
|
+
}
|
|
1118
|
+
|
|
1119
|
+
// src/markdown-math.ts
|
|
1120
|
+
var mathConverter = null;
|
|
1121
|
+
var mathLoad = null;
|
|
1122
|
+
function preloadMathJax() {
|
|
1123
|
+
if (mathLoad) return mathLoad;
|
|
1124
|
+
mathLoad = (async () => {
|
|
1125
|
+
const { emitSVG, layout } = await import("@vectojs/tex");
|
|
1126
|
+
mathConverter = (formula, displayMode, color) => convertMathToSVGDataURI(formula, displayMode, color, layout, emitSVG);
|
|
1127
|
+
})().catch((e) => {
|
|
1128
|
+
console.error("Math engine failed to load; formulas will render as TeX source", e);
|
|
1129
|
+
});
|
|
1130
|
+
return mathLoad;
|
|
1131
|
+
}
|
|
1132
|
+
function isMathJaxReady() {
|
|
1133
|
+
return mathConverter !== null;
|
|
1134
|
+
}
|
|
1135
|
+
var EX_PER_EM = 0.4421;
|
|
1136
|
+
function exToPx(ex, fontSize) {
|
|
1137
|
+
return ex * fontSize * EX_PER_EM;
|
|
1138
|
+
}
|
|
1139
|
+
function fontSizeFromFont(font) {
|
|
1140
|
+
const pxIndex = font.indexOf("px");
|
|
1141
|
+
if (pxIndex <= 0) return void 0;
|
|
1142
|
+
let start = pxIndex;
|
|
1143
|
+
while (start > 0) {
|
|
1144
|
+
const ch = font[start - 1];
|
|
1145
|
+
if (ch >= "0" && ch <= "9" || ch === ".") start--;
|
|
1146
|
+
else break;
|
|
1147
|
+
}
|
|
1148
|
+
if (start === pxIndex) return void 0;
|
|
1149
|
+
const size = parseFloat(font.slice(start, pxIndex));
|
|
1150
|
+
return Number.isFinite(size) ? size : void 0;
|
|
1151
|
+
}
|
|
1152
|
+
var mathCache = /* @__PURE__ */ new Map();
|
|
1153
|
+
var MATH_CACHE_LIMIT = 256;
|
|
1154
|
+
var inlineMathRasters = /* @__PURE__ */ new Map();
|
|
1155
|
+
var inlineMathRasterWaiters = /* @__PURE__ */ new Set();
|
|
1156
|
+
function subscribeInlineMathRaster(notify) {
|
|
1157
|
+
inlineMathRasterWaiters.add(notify);
|
|
1158
|
+
}
|
|
1159
|
+
function unsubscribeInlineMathRaster(notify) {
|
|
1160
|
+
inlineMathRasterWaiters.delete(notify);
|
|
1161
|
+
}
|
|
1162
|
+
function ensureInlineMathRaster(uri) {
|
|
1163
|
+
const existing = inlineMathRasters.get(uri);
|
|
1164
|
+
if (existing) return existing;
|
|
1165
|
+
const entry = { decoded: false };
|
|
1166
|
+
inlineMathRasters.set(uri, entry);
|
|
1167
|
+
if (typeof globalThis.Image !== "undefined") {
|
|
1168
|
+
const bitmap = new globalThis.Image();
|
|
1169
|
+
bitmap.onload = () => {
|
|
1170
|
+
entry.decoded = true;
|
|
1171
|
+
for (const notify of inlineMathRasterWaiters) notify();
|
|
1172
|
+
};
|
|
1173
|
+
bitmap.src = uri;
|
|
1174
|
+
entry.bitmap = bitmap;
|
|
1175
|
+
}
|
|
1176
|
+
return entry;
|
|
1177
|
+
}
|
|
1178
|
+
function paintInlineMath(uri, surface, box) {
|
|
1179
|
+
const raster = ensureInlineMathRaster(uri);
|
|
1180
|
+
if (!raster.decoded || !raster.bitmap) return;
|
|
1181
|
+
surface.drawImage(raster.bitmap, box.x, box.y, box.width, box.height);
|
|
1182
|
+
}
|
|
1183
|
+
var MATH_LANGS = /* @__PURE__ */ new Set(["math", "latex", "tex"]);
|
|
1184
|
+
function containsInlineMath(token) {
|
|
1185
|
+
if (token.type === "inlineMath") return true;
|
|
1186
|
+
const anyToken = token;
|
|
1187
|
+
if (Array.isArray(anyToken.tokens) && anyToken.tokens.some(containsInlineMath)) {
|
|
1188
|
+
return true;
|
|
1189
|
+
}
|
|
1190
|
+
if (Array.isArray(anyToken.items) && anyToken.items.some(containsInlineMath)) {
|
|
1191
|
+
return true;
|
|
1192
|
+
}
|
|
1193
|
+
if (Array.isArray(anyToken.header) && anyToken.header.some(containsInlineMath)) {
|
|
1194
|
+
return true;
|
|
1195
|
+
}
|
|
1196
|
+
if (Array.isArray(anyToken.rows)) {
|
|
1197
|
+
for (const row of anyToken.rows) {
|
|
1198
|
+
if (Array.isArray(row) && row.some(containsInlineMath)) return true;
|
|
1199
|
+
}
|
|
1200
|
+
}
|
|
1201
|
+
return false;
|
|
1202
|
+
}
|
|
1203
|
+
var FENCE_OPEN_RE = /^ {0,3}(`{3,}|~{3,})/;
|
|
1204
|
+
var FENCE_CLOSE_RE = /^ {0,3}(`+|~+)[ \t]*$/;
|
|
1205
|
+
function isFenceClosed(raw) {
|
|
1206
|
+
const lines = raw.split("\n");
|
|
1207
|
+
const open = FENCE_OPEN_RE.exec(lines[0]);
|
|
1208
|
+
if (!open) return false;
|
|
1209
|
+
const marker = open[1][0];
|
|
1210
|
+
const minLen = open[1].length;
|
|
1211
|
+
for (let i = 1; i < lines.length; i++) {
|
|
1212
|
+
const close = FENCE_CLOSE_RE.exec(lines[i]);
|
|
1213
|
+
if (close && close[1][0] === marker && close[1].length >= minLen) return true;
|
|
1214
|
+
}
|
|
1215
|
+
return false;
|
|
1216
|
+
}
|
|
1217
|
+
function rendersAsMath(token) {
|
|
1218
|
+
return MATH_LANGS.has((token.lang ?? "").toLowerCase()) && token.text.trim() !== "" && isFenceClosed(token.raw);
|
|
1219
|
+
}
|
|
1220
|
+
function renderMathToSVGDataURI(formula, displayMode, color) {
|
|
1221
|
+
const key = `${displayMode ? 1 : 0}\0${color}\0${formula}`;
|
|
1222
|
+
const hit = mathCache.get(key);
|
|
1223
|
+
if (hit) return hit;
|
|
1224
|
+
if (!mathConverter) return null;
|
|
1225
|
+
const converted = mathConverter(formula, displayMode, color);
|
|
1226
|
+
if (converted) {
|
|
1227
|
+
if (mathCache.size >= MATH_CACHE_LIMIT) {
|
|
1228
|
+
const oldest = mathCache.keys().next().value;
|
|
1229
|
+
if (oldest !== void 0) mathCache.delete(oldest);
|
|
1230
|
+
}
|
|
1231
|
+
mathCache.set(key, converted);
|
|
1232
|
+
}
|
|
1233
|
+
return converted;
|
|
1234
|
+
}
|
|
1235
|
+
var MATH_PAD_EM = 0.05;
|
|
1236
|
+
var KATEX_FONT_SCALE = 1.21;
|
|
1237
|
+
var EX_PER_KATEX_EM = KATEX_FONT_SCALE / EX_PER_EM;
|
|
1238
|
+
function convertMathToSVGDataURI(formula, displayMode, color, layout, emitSVG) {
|
|
1239
|
+
try {
|
|
1240
|
+
const emitted = emitSVG(layout(formula, { displayMode }), {
|
|
1241
|
+
color,
|
|
1242
|
+
padEm: MATH_PAD_EM
|
|
1243
|
+
});
|
|
1244
|
+
if (emitted.missing.length > 0) return null;
|
|
1245
|
+
const pad2 = MATH_PAD_EM * 2;
|
|
1246
|
+
const base64 = btoa(unescape(encodeURIComponent(emitted.svg)));
|
|
1247
|
+
return {
|
|
1248
|
+
uri: `data:image/svg+xml;base64,${base64}`,
|
|
1249
|
+
widthEx: (emitted.width + pad2) * EX_PER_KATEX_EM,
|
|
1250
|
+
heightEx: (emitted.height + emitted.depth + pad2) * EX_PER_KATEX_EM,
|
|
1251
|
+
depthEx: (emitted.depth + MATH_PAD_EM) * EX_PER_KATEX_EM
|
|
1252
|
+
};
|
|
1253
|
+
} catch (e) {
|
|
1254
|
+
console.error("Math typesetting error", e);
|
|
1255
|
+
return null;
|
|
1256
|
+
}
|
|
1257
|
+
}
|
|
1258
|
+
var MathBlock = class extends MarkdownContainer {
|
|
1259
|
+
/**
|
|
1260
|
+
* The TeX source, exactly as written between the delimiters.
|
|
1261
|
+
*
|
|
1262
|
+
* Also the projected text and the accessible name, so this is the one string a
|
|
1263
|
+
* reader can find, select, and copy.
|
|
1264
|
+
*/
|
|
1187
1265
|
formula;
|
|
1188
1266
|
/** The `data:image/svg+xml` URI of the typeset glyphs. */
|
|
1189
1267
|
svgUri;
|
|
@@ -1204,667 +1282,783 @@ var MathBlock = class extends MarkdownContainer {
|
|
|
1204
1282
|
};
|
|
1205
1283
|
}
|
|
1206
1284
|
};
|
|
1207
|
-
|
|
1208
|
-
|
|
1209
|
-
|
|
1210
|
-
|
|
1211
|
-
|
|
1212
|
-
|
|
1213
|
-
|
|
1214
|
-
|
|
1215
|
-
|
|
1216
|
-
|
|
1217
|
-
|
|
1218
|
-
|
|
1219
|
-
"
|
|
1220
|
-
|
|
1221
|
-
|
|
1222
|
-
|
|
1223
|
-
|
|
1224
|
-
|
|
1225
|
-
|
|
1226
|
-
|
|
1227
|
-
|
|
1228
|
-
|
|
1229
|
-
|
|
1230
|
-
|
|
1231
|
-
|
|
1232
|
-
"in",
|
|
1233
|
-
"typeof",
|
|
1234
|
-
"instanceof",
|
|
1235
|
-
"switch",
|
|
1236
|
-
"case",
|
|
1237
|
-
"break",
|
|
1238
|
-
"continue",
|
|
1239
|
-
"null",
|
|
1240
|
-
"undefined",
|
|
1241
|
-
"true",
|
|
1242
|
-
"false"
|
|
1243
|
-
]),
|
|
1244
|
-
ts: /* @__PURE__ */ new Set([
|
|
1245
|
-
"const",
|
|
1246
|
-
"let",
|
|
1247
|
-
"var",
|
|
1248
|
-
"function",
|
|
1249
|
-
"return",
|
|
1250
|
-
"if",
|
|
1251
|
-
"else",
|
|
1252
|
-
"for",
|
|
1253
|
-
"while",
|
|
1254
|
-
"class",
|
|
1255
|
-
"extends",
|
|
1256
|
-
"new",
|
|
1257
|
-
"this",
|
|
1258
|
-
"import",
|
|
1259
|
-
"export",
|
|
1260
|
-
"from",
|
|
1261
|
-
"default",
|
|
1262
|
-
"async",
|
|
1263
|
-
"await",
|
|
1264
|
-
"try",
|
|
1265
|
-
"catch",
|
|
1266
|
-
"throw",
|
|
1267
|
-
"of",
|
|
1268
|
-
"in",
|
|
1269
|
-
"typeof",
|
|
1270
|
-
"instanceof",
|
|
1271
|
-
"switch",
|
|
1272
|
-
"case",
|
|
1273
|
-
"break",
|
|
1274
|
-
"continue",
|
|
1275
|
-
"null",
|
|
1276
|
-
"undefined",
|
|
1277
|
-
"true",
|
|
1278
|
-
"false",
|
|
1279
|
-
"type",
|
|
1280
|
-
"interface",
|
|
1281
|
-
"enum",
|
|
1282
|
-
"as",
|
|
1283
|
-
"is",
|
|
1284
|
-
"readonly",
|
|
1285
|
-
"implements",
|
|
1286
|
-
"abstract",
|
|
1287
|
-
"public",
|
|
1288
|
-
"private",
|
|
1289
|
-
"protected",
|
|
1290
|
-
"static",
|
|
1291
|
-
"void",
|
|
1292
|
-
"never",
|
|
1293
|
-
"any",
|
|
1294
|
-
"unknown"
|
|
1295
|
-
]),
|
|
1296
|
-
py: /* @__PURE__ */ new Set([
|
|
1297
|
-
"def",
|
|
1298
|
-
"class",
|
|
1299
|
-
"return",
|
|
1300
|
-
"if",
|
|
1301
|
-
"elif",
|
|
1302
|
-
"else",
|
|
1303
|
-
"for",
|
|
1304
|
-
"while",
|
|
1305
|
-
"import",
|
|
1306
|
-
"from",
|
|
1307
|
-
"as",
|
|
1308
|
-
"with",
|
|
1309
|
-
"try",
|
|
1310
|
-
"except",
|
|
1311
|
-
"raise",
|
|
1312
|
-
"finally",
|
|
1313
|
-
"pass",
|
|
1314
|
-
"break",
|
|
1315
|
-
"continue",
|
|
1316
|
-
"and",
|
|
1317
|
-
"or",
|
|
1318
|
-
"not",
|
|
1319
|
-
"in",
|
|
1320
|
-
"is",
|
|
1321
|
-
"None",
|
|
1322
|
-
"True",
|
|
1323
|
-
"False",
|
|
1324
|
-
"yield",
|
|
1325
|
-
"lambda",
|
|
1326
|
-
"global",
|
|
1327
|
-
"nonlocal",
|
|
1328
|
-
"del",
|
|
1329
|
-
"assert",
|
|
1330
|
-
"async",
|
|
1331
|
-
"await"
|
|
1332
|
-
]),
|
|
1333
|
-
rust: /* @__PURE__ */ new Set([
|
|
1334
|
-
"fn",
|
|
1335
|
-
"let",
|
|
1336
|
-
"mut",
|
|
1337
|
-
"const",
|
|
1338
|
-
"if",
|
|
1339
|
-
"else",
|
|
1340
|
-
"for",
|
|
1341
|
-
"while",
|
|
1342
|
-
"loop",
|
|
1343
|
-
"match",
|
|
1344
|
-
"return",
|
|
1345
|
-
"struct",
|
|
1346
|
-
"enum",
|
|
1347
|
-
"impl",
|
|
1348
|
-
"trait",
|
|
1349
|
-
"pub",
|
|
1350
|
-
"use",
|
|
1351
|
-
"mod",
|
|
1352
|
-
"crate",
|
|
1353
|
-
"self",
|
|
1354
|
-
"super",
|
|
1355
|
-
"where",
|
|
1356
|
-
"as",
|
|
1357
|
-
"in",
|
|
1358
|
-
"ref",
|
|
1359
|
-
"move",
|
|
1360
|
-
"async",
|
|
1361
|
-
"await",
|
|
1362
|
-
"true",
|
|
1363
|
-
"false",
|
|
1364
|
-
"type",
|
|
1365
|
-
"unsafe",
|
|
1366
|
-
"extern",
|
|
1367
|
-
"dyn",
|
|
1368
|
-
"static"
|
|
1369
|
-
])
|
|
1370
|
-
};
|
|
1371
|
-
KEYWORD_SETS["javascript"] = KEYWORD_SETS["js"];
|
|
1372
|
-
KEYWORD_SETS["typescript"] = KEYWORD_SETS["ts"];
|
|
1373
|
-
KEYWORD_SETS["python"] = KEYWORD_SETS["py"];
|
|
1374
|
-
KEYWORD_SETS["rs"] = KEYWORD_SETS["rust"];
|
|
1375
|
-
function highlightLine(line, lang, theme) {
|
|
1376
|
-
const keywords = KEYWORD_SETS[lang];
|
|
1377
|
-
if (!keywords) {
|
|
1378
|
-
return [{ text: line, color: theme.codeColor }];
|
|
1285
|
+
|
|
1286
|
+
// src/markdown-inline.ts
|
|
1287
|
+
var import_core3 = require("@vectojs/core");
|
|
1288
|
+
var import_ui2 = require("@vectojs/ui");
|
|
1289
|
+
|
|
1290
|
+
// src/markdown-image.ts
|
|
1291
|
+
function paragraphHasImage(token) {
|
|
1292
|
+
return containsImage(token.tokens);
|
|
1293
|
+
}
|
|
1294
|
+
function containsImage(tokens) {
|
|
1295
|
+
if (!tokens) return false;
|
|
1296
|
+
for (const token of tokens) {
|
|
1297
|
+
if (token.type === "image") return true;
|
|
1298
|
+
const anyToken = token;
|
|
1299
|
+
if (containsImage(anyToken.tokens)) return true;
|
|
1300
|
+
if (Array.isArray(anyToken.items) && containsImage(anyToken.items)) {
|
|
1301
|
+
return true;
|
|
1302
|
+
}
|
|
1303
|
+
const table = token;
|
|
1304
|
+
if (Array.isArray(table.header) && table.header.some((cell) => containsImage(cell.tokens))) {
|
|
1305
|
+
return true;
|
|
1306
|
+
}
|
|
1307
|
+
if (Array.isArray(table.rows) && table.rows.some((row) => row.some((cell) => containsImage(cell.tokens)))) {
|
|
1308
|
+
return true;
|
|
1309
|
+
}
|
|
1379
1310
|
}
|
|
1380
|
-
|
|
1381
|
-
|
|
1382
|
-
|
|
1383
|
-
const
|
|
1384
|
-
const
|
|
1385
|
-
|
|
1386
|
-
|
|
1387
|
-
|
|
1388
|
-
if (buf) {
|
|
1389
|
-
segments.push({ text: buf, color });
|
|
1390
|
-
buf = "";
|
|
1311
|
+
return false;
|
|
1312
|
+
}
|
|
1313
|
+
function imagesOf(tokens) {
|
|
1314
|
+
const images = [];
|
|
1315
|
+
for (const token of tokens ?? []) {
|
|
1316
|
+
if (token.type === "image") {
|
|
1317
|
+
images.push(token);
|
|
1318
|
+
continue;
|
|
1391
1319
|
}
|
|
1392
|
-
|
|
1393
|
-
|
|
1394
|
-
|
|
1395
|
-
|
|
1396
|
-
|
|
1397
|
-
|
|
1398
|
-
|
|
1320
|
+
images.push(...imagesOf(token.tokens));
|
|
1321
|
+
}
|
|
1322
|
+
return images;
|
|
1323
|
+
}
|
|
1324
|
+
function stripImages(token) {
|
|
1325
|
+
const children = token.tokens;
|
|
1326
|
+
if (!children) return token;
|
|
1327
|
+
const kept = [];
|
|
1328
|
+
for (const child of children) {
|
|
1329
|
+
if (child.type === "image") continue;
|
|
1330
|
+
const grandchildren = child.tokens;
|
|
1331
|
+
if (grandchildren && containsImage(grandchildren)) {
|
|
1332
|
+
const stripped = stripImages(child);
|
|
1333
|
+
const remaining = stripped.tokens;
|
|
1334
|
+
if (remaining && remaining.length > 0) kept.push(stripped);
|
|
1335
|
+
continue;
|
|
1399
1336
|
}
|
|
1400
|
-
|
|
1401
|
-
|
|
1402
|
-
|
|
1403
|
-
|
|
1337
|
+
kept.push(child);
|
|
1338
|
+
}
|
|
1339
|
+
return { ...token, tokens: kept };
|
|
1340
|
+
}
|
|
1341
|
+
function liftNestedImages(tokens) {
|
|
1342
|
+
const lifted = [];
|
|
1343
|
+
for (const token of tokens) {
|
|
1344
|
+
if (token.type === "image") {
|
|
1345
|
+
lifted.push(token);
|
|
1346
|
+
continue;
|
|
1404
1347
|
}
|
|
1405
|
-
|
|
1406
|
-
|
|
1407
|
-
|
|
1408
|
-
|
|
1409
|
-
|
|
1410
|
-
|
|
1411
|
-
|
|
1412
|
-
|
|
1348
|
+
const children = token.tokens;
|
|
1349
|
+
if (children && containsImage(children)) {
|
|
1350
|
+
lifted.push(...liftNestedImages(children));
|
|
1351
|
+
continue;
|
|
1352
|
+
}
|
|
1353
|
+
lifted.push(token);
|
|
1354
|
+
}
|
|
1355
|
+
return lifted;
|
|
1356
|
+
}
|
|
1357
|
+
function lastIndexOfImage(tokens) {
|
|
1358
|
+
for (let i = tokens.length - 1; i >= 0; i--) {
|
|
1359
|
+
if (tokens[i].type === "image") return i;
|
|
1360
|
+
}
|
|
1361
|
+
return -1;
|
|
1362
|
+
}
|
|
1363
|
+
var inlineImageRasters = /* @__PURE__ */ new Map();
|
|
1364
|
+
var inlineImageRasterWaiters = /* @__PURE__ */ new Set();
|
|
1365
|
+
function subscribeInlineImageRaster(notify) {
|
|
1366
|
+
inlineImageRasterWaiters.add(notify);
|
|
1367
|
+
}
|
|
1368
|
+
function unsubscribeInlineImageRaster(notify) {
|
|
1369
|
+
inlineImageRasterWaiters.delete(notify);
|
|
1370
|
+
}
|
|
1371
|
+
function ensureInlineImageRaster(src) {
|
|
1372
|
+
const existing = inlineImageRasters.get(src);
|
|
1373
|
+
if (existing) return existing;
|
|
1374
|
+
const entry = { decoded: false };
|
|
1375
|
+
inlineImageRasters.set(src, entry);
|
|
1376
|
+
if (typeof globalThis.Image !== "undefined") {
|
|
1377
|
+
const bitmap = new globalThis.Image();
|
|
1378
|
+
bitmap.onload = () => {
|
|
1379
|
+
entry.decoded = true;
|
|
1380
|
+
entry.naturalWidth = bitmap.naturalWidth || void 0;
|
|
1381
|
+
entry.naturalHeight = bitmap.naturalHeight || void 0;
|
|
1382
|
+
for (const notify of inlineImageRasterWaiters) notify();
|
|
1383
|
+
};
|
|
1384
|
+
bitmap.onerror = () => {
|
|
1385
|
+
entry.failed = true;
|
|
1386
|
+
for (const notify of inlineImageRasterWaiters) notify();
|
|
1387
|
+
};
|
|
1388
|
+
bitmap.src = src;
|
|
1389
|
+
entry.bitmap = bitmap;
|
|
1390
|
+
}
|
|
1391
|
+
return entry;
|
|
1392
|
+
}
|
|
1393
|
+
function paintInlineImage(src, surface, box) {
|
|
1394
|
+
const raster = ensureInlineImageRaster(src);
|
|
1395
|
+
if (!raster.decoded || !raster.bitmap) return;
|
|
1396
|
+
surface.drawImage(raster.bitmap, box.x, box.y, box.width, box.height);
|
|
1397
|
+
}
|
|
1398
|
+
function expectedImageParagraphChildren(tokens) {
|
|
1399
|
+
let children = 0;
|
|
1400
|
+
let inTextRun = false;
|
|
1401
|
+
for (const token of liftNestedImages(tokens)) {
|
|
1402
|
+
if (token.type === "image") {
|
|
1403
|
+
children++;
|
|
1404
|
+
inTextRun = false;
|
|
1405
|
+
} else if (!inTextRun) {
|
|
1406
|
+
children++;
|
|
1407
|
+
inTextRun = true;
|
|
1408
|
+
}
|
|
1409
|
+
}
|
|
1410
|
+
return children;
|
|
1411
|
+
}
|
|
1412
|
+
|
|
1413
|
+
// src/markdown-inline.ts
|
|
1414
|
+
function decodeEntities(text) {
|
|
1415
|
+
return text.replace(/</g, "<").replace(/>/g, ">").replace(/"/g, '"').replace(/'/g, "'").replace(/&/g, "&");
|
|
1416
|
+
}
|
|
1417
|
+
function collectSpans(tokens, inherited, theme, out, blockFontSize) {
|
|
1418
|
+
for (const token of tokens) {
|
|
1419
|
+
switch (token.type) {
|
|
1420
|
+
case "strong": {
|
|
1421
|
+
const t = token;
|
|
1422
|
+
if (t.tokens) {
|
|
1423
|
+
collectSpans(t.tokens, { ...inherited, bold: true }, theme, out, blockFontSize);
|
|
1424
|
+
} else {
|
|
1425
|
+
out.push({
|
|
1426
|
+
text: decodeEntities(t.text),
|
|
1427
|
+
style: { ...inherited, bold: true }
|
|
1428
|
+
});
|
|
1413
1429
|
}
|
|
1414
|
-
|
|
1415
|
-
|
|
1430
|
+
break;
|
|
1431
|
+
}
|
|
1432
|
+
case "em": {
|
|
1433
|
+
const t = token;
|
|
1434
|
+
if (t.tokens) {
|
|
1435
|
+
collectSpans(t.tokens, { ...inherited, italic: true }, theme, out, blockFontSize);
|
|
1436
|
+
} else {
|
|
1437
|
+
out.push({
|
|
1438
|
+
text: decodeEntities(t.text),
|
|
1439
|
+
style: { ...inherited, italic: true }
|
|
1440
|
+
});
|
|
1441
|
+
}
|
|
1442
|
+
break;
|
|
1443
|
+
}
|
|
1444
|
+
case "del": {
|
|
1445
|
+
const t = token;
|
|
1446
|
+
if (t.tokens) {
|
|
1447
|
+
collectSpans(t.tokens, { ...inherited, lineThrough: true }, theme, out, blockFontSize);
|
|
1448
|
+
} else {
|
|
1449
|
+
out.push({
|
|
1450
|
+
text: decodeEntities(t.text),
|
|
1451
|
+
style: { ...inherited, lineThrough: true }
|
|
1452
|
+
});
|
|
1453
|
+
}
|
|
1454
|
+
break;
|
|
1455
|
+
}
|
|
1456
|
+
case "codespan": {
|
|
1457
|
+
const t = token;
|
|
1458
|
+
out.push({
|
|
1459
|
+
text: decodeEntities(t.text),
|
|
1460
|
+
// Inline code renders in the theme's monospace family (not just tinted
|
|
1461
|
+
// prose) — TextStyle.fontFamily drives both measurement and drawing.
|
|
1462
|
+
style: {
|
|
1463
|
+
...inherited,
|
|
1464
|
+
color: theme.codeColor,
|
|
1465
|
+
fontFamily: theme.codeFont
|
|
1466
|
+
}
|
|
1467
|
+
});
|
|
1468
|
+
break;
|
|
1469
|
+
}
|
|
1470
|
+
case "br": {
|
|
1471
|
+
out.push({ text: "\n" });
|
|
1472
|
+
break;
|
|
1473
|
+
}
|
|
1474
|
+
case "html": {
|
|
1475
|
+
const t = token;
|
|
1476
|
+
const raw = t.raw ?? t.text ?? "";
|
|
1477
|
+
const brCount = (raw.match(/<br\s*\/?>/gi) ?? []).length;
|
|
1478
|
+
for (let i = 0; i < brCount; i++) out.push({ text: "\n" });
|
|
1479
|
+
break;
|
|
1480
|
+
}
|
|
1481
|
+
case "inlineMath": {
|
|
1482
|
+
const t = token;
|
|
1483
|
+
const runSize = inherited.fontSize ?? blockFontSize ?? theme.fontSize;
|
|
1484
|
+
const runColor = inherited.color ?? theme.textColor;
|
|
1485
|
+
const rendered = renderMathToSVGDataURI(t.text, false, runColor);
|
|
1486
|
+
if (rendered) {
|
|
1487
|
+
const uri = rendered.uri;
|
|
1488
|
+
out.push({
|
|
1489
|
+
text: import_core3.OBJECT_REPLACEMENT,
|
|
1490
|
+
style: inherited,
|
|
1491
|
+
object: {
|
|
1492
|
+
width: exToPx(rendered.widthEx, runSize),
|
|
1493
|
+
height: exToPx(rendered.heightEx, runSize),
|
|
1494
|
+
depth: exToPx(rendered.depthEx, runSize),
|
|
1495
|
+
// The TeX source is the accessible name: without it a screen reader
|
|
1496
|
+
// receives only the invisible U+FFFC sentinel.
|
|
1497
|
+
alt: t.text,
|
|
1498
|
+
// Without this the box is reserved and stays empty. The engine does
|
|
1499
|
+
// not draw objects, and nothing else in the tree holds the raster.
|
|
1500
|
+
paint: (surface, box) => paintInlineMath(uri, surface, box)
|
|
1501
|
+
}
|
|
1502
|
+
});
|
|
1503
|
+
} else {
|
|
1504
|
+
out.push({
|
|
1505
|
+
text: decodeEntities(t.raw),
|
|
1506
|
+
style: { ...inherited, color: theme.mathFallbackColor }
|
|
1507
|
+
});
|
|
1508
|
+
}
|
|
1509
|
+
break;
|
|
1510
|
+
}
|
|
1511
|
+
case "image": {
|
|
1512
|
+
const t = token;
|
|
1513
|
+
const runSize = inherited.fontSize ?? blockFontSize ?? theme.fontSize;
|
|
1514
|
+
const raster = ensureInlineImageRaster(t.href);
|
|
1515
|
+
if (raster.failed) {
|
|
1516
|
+
out.push({ text: decodeEntities(t.text), style: inherited });
|
|
1416
1517
|
break;
|
|
1417
1518
|
}
|
|
1418
|
-
|
|
1519
|
+
const height = runSize * theme.inlineImageScale;
|
|
1520
|
+
const aspect = raster.naturalWidth && raster.naturalHeight ? raster.naturalWidth / raster.naturalHeight : 1;
|
|
1521
|
+
const src = t.href;
|
|
1522
|
+
out.push({
|
|
1523
|
+
text: import_core3.OBJECT_REPLACEMENT,
|
|
1524
|
+
style: inherited,
|
|
1525
|
+
object: {
|
|
1526
|
+
width: height * aspect,
|
|
1527
|
+
height,
|
|
1528
|
+
// Sits on the baseline like a cap-height glyph rather than hanging
|
|
1529
|
+
// below it; an image has no descender to align.
|
|
1530
|
+
depth: 0,
|
|
1531
|
+
// The accessible name, and what a copy yields. Without it the
|
|
1532
|
+
// invisible U+FFFC sentinel is all a screen reader receives.
|
|
1533
|
+
alt: t.text,
|
|
1534
|
+
// What this object PAINTS, which `alt` does not determine: two badges
|
|
1535
|
+
// can share alt text and differ in URL. Without it the paragraph memo
|
|
1536
|
+
// serves the first one's painter to the second and every row of a badge
|
|
1537
|
+
// column draws the first row's badge.
|
|
1538
|
+
key: src,
|
|
1539
|
+
paint: (surface, box) => paintInlineImage(src, surface, box)
|
|
1540
|
+
}
|
|
1541
|
+
});
|
|
1542
|
+
break;
|
|
1419
1543
|
}
|
|
1420
|
-
|
|
1421
|
-
|
|
1422
|
-
|
|
1423
|
-
|
|
1424
|
-
|
|
1544
|
+
case "footnoteRef": {
|
|
1545
|
+
const t = token;
|
|
1546
|
+
const runSize = inherited.fontSize ?? blockFontSize ?? theme.fontSize;
|
|
1547
|
+
out.push({
|
|
1548
|
+
text: footnoteMarker(t.label),
|
|
1549
|
+
style: {
|
|
1550
|
+
...inherited,
|
|
1551
|
+
fontSize: runSize * theme.footnoteMarkerScale,
|
|
1552
|
+
color: theme.footnoteColor
|
|
1553
|
+
}
|
|
1554
|
+
});
|
|
1555
|
+
break;
|
|
1556
|
+
}
|
|
1557
|
+
case "link": {
|
|
1558
|
+
const t = token;
|
|
1559
|
+
const linkStyle = {
|
|
1560
|
+
...inherited,
|
|
1561
|
+
href: t.href,
|
|
1562
|
+
color: theme.linkColor
|
|
1563
|
+
};
|
|
1564
|
+
if (t.tokens && t.tokens.length > 0) {
|
|
1565
|
+
collectSpans(t.tokens, linkStyle, theme, out, blockFontSize);
|
|
1566
|
+
} else {
|
|
1567
|
+
out.push({ text: decodeEntities(t.text), style: linkStyle });
|
|
1568
|
+
}
|
|
1569
|
+
break;
|
|
1570
|
+
}
|
|
1571
|
+
case "text": {
|
|
1572
|
+
const t = token;
|
|
1573
|
+
if ("tokens" in t && t.tokens?.length) {
|
|
1574
|
+
collectSpans(t.tokens, inherited, theme, out, blockFontSize);
|
|
1575
|
+
} else {
|
|
1576
|
+
const decoded = decodeEntities(t.text);
|
|
1577
|
+
if (decoded) {
|
|
1578
|
+
const style = Object.keys(inherited).length > 0 ? inherited : void 0;
|
|
1579
|
+
out.push({ text: decoded, style });
|
|
1580
|
+
}
|
|
1581
|
+
}
|
|
1582
|
+
break;
|
|
1583
|
+
}
|
|
1584
|
+
default: {
|
|
1585
|
+
if ("text" in token) {
|
|
1586
|
+
const decoded = decodeEntities(token.text);
|
|
1587
|
+
if (decoded) {
|
|
1588
|
+
const style = Object.keys(inherited).length > 0 ? inherited : void 0;
|
|
1589
|
+
out.push({ text: decoded, style });
|
|
1590
|
+
}
|
|
1591
|
+
}
|
|
1592
|
+
break;
|
|
1425
1593
|
}
|
|
1426
|
-
buf += ch;
|
|
1427
|
-
i++;
|
|
1428
|
-
continue;
|
|
1429
1594
|
}
|
|
1430
|
-
|
|
1431
|
-
|
|
1432
|
-
|
|
1433
|
-
|
|
1434
|
-
|
|
1435
|
-
|
|
1436
|
-
|
|
1595
|
+
}
|
|
1596
|
+
}
|
|
1597
|
+
function findUnclosedInline(text) {
|
|
1598
|
+
let best = null;
|
|
1599
|
+
const tick = text.lastIndexOf("`");
|
|
1600
|
+
if (tick !== -1 && tick < text.length - 1) {
|
|
1601
|
+
return { kind: "codespan", at: tick, contentAt: tick + 1 };
|
|
1602
|
+
}
|
|
1603
|
+
if (tick !== -1) return null;
|
|
1604
|
+
const emphasis = /(\*{1,2}(?!\*)|_{1,2}(?!_))(?=[^\s])/g;
|
|
1605
|
+
for (let match = emphasis.exec(text); match !== null; match = emphasis.exec(text)) {
|
|
1606
|
+
const marker = match[1];
|
|
1607
|
+
const at = match.index;
|
|
1608
|
+
if (marker[0] === "_" && at > 0 && /[\w]/.test(text[at - 1])) continue;
|
|
1609
|
+
best = {
|
|
1610
|
+
kind: marker.length === 2 ? "strong" : "em",
|
|
1611
|
+
at,
|
|
1612
|
+
contentAt: at + marker.length
|
|
1613
|
+
};
|
|
1614
|
+
}
|
|
1615
|
+
const bracket = text.lastIndexOf("[");
|
|
1616
|
+
if (bracket !== -1 && bracket < text.length - 1 && (best === null || bracket > best.at)) {
|
|
1617
|
+
const closed = /\]\([^)]*\)/.test(text.slice(bracket));
|
|
1618
|
+
if (!closed) {
|
|
1619
|
+
best = { kind: "link", at: bracket, contentAt: bracket + 1 };
|
|
1620
|
+
}
|
|
1621
|
+
}
|
|
1622
|
+
return best;
|
|
1623
|
+
}
|
|
1624
|
+
function renderInlineToRichText(tokens, fallbackText, font, color, maxWidth, theme, selectable, onLinkClick) {
|
|
1625
|
+
const spans = [];
|
|
1626
|
+
if (tokens && tokens.length > 0) {
|
|
1627
|
+
collectSpans(tokens, {}, theme, spans, fontSizeFromFont(font));
|
|
1628
|
+
}
|
|
1629
|
+
if (spans.length === 0) {
|
|
1630
|
+
spans.push({ text: decodeEntities(fallbackText) });
|
|
1631
|
+
}
|
|
1632
|
+
return new import_ui2.RichText(spans, {
|
|
1633
|
+
font,
|
|
1634
|
+
color,
|
|
1635
|
+
maxWidth,
|
|
1636
|
+
linkColor: theme.linkColor,
|
|
1637
|
+
selectable,
|
|
1638
|
+
onLinkClick
|
|
1639
|
+
});
|
|
1640
|
+
}
|
|
1641
|
+
|
|
1642
|
+
// src/Markdown.ts
|
|
1643
|
+
var import_ui4 = require("@vectojs/ui");
|
|
1644
|
+
|
|
1645
|
+
// src/blockAffordances.ts
|
|
1646
|
+
var import_ui3 = require("@vectojs/ui");
|
|
1647
|
+
var LANGUAGE_EXTENSIONS = {
|
|
1648
|
+
bash: "sh",
|
|
1649
|
+
c: "c",
|
|
1650
|
+
cpp: "cpp",
|
|
1651
|
+
cs: "cs",
|
|
1652
|
+
css: "css",
|
|
1653
|
+
diff: "diff",
|
|
1654
|
+
dockerfile: "dockerfile",
|
|
1655
|
+
go: "go",
|
|
1656
|
+
graphql: "graphql",
|
|
1657
|
+
haskell: "hs",
|
|
1658
|
+
html: "html",
|
|
1659
|
+
java: "java",
|
|
1660
|
+
javascript: "js",
|
|
1661
|
+
js: "js",
|
|
1662
|
+
json: "json",
|
|
1663
|
+
jsonc: "jsonc",
|
|
1664
|
+
jsx: "jsx",
|
|
1665
|
+
kotlin: "kt",
|
|
1666
|
+
latex: "tex",
|
|
1667
|
+
lua: "lua",
|
|
1668
|
+
make: "mk",
|
|
1669
|
+
markdown: "md",
|
|
1670
|
+
md: "md",
|
|
1671
|
+
nix: "nix",
|
|
1672
|
+
php: "php",
|
|
1673
|
+
python: "py",
|
|
1674
|
+
py: "py",
|
|
1675
|
+
ruby: "rb",
|
|
1676
|
+
rust: "rs",
|
|
1677
|
+
rs: "rs",
|
|
1678
|
+
scss: "scss",
|
|
1679
|
+
sh: "sh",
|
|
1680
|
+
shell: "sh",
|
|
1681
|
+
sql: "sql",
|
|
1682
|
+
svelte: "svelte",
|
|
1683
|
+
swift: "swift",
|
|
1684
|
+
tex: "tex",
|
|
1685
|
+
toml: "toml",
|
|
1686
|
+
ts: "ts",
|
|
1687
|
+
tsx: "tsx",
|
|
1688
|
+
typescript: "ts",
|
|
1689
|
+
vue: "vue",
|
|
1690
|
+
xml: "xml",
|
|
1691
|
+
yaml: "yaml",
|
|
1692
|
+
yml: "yaml",
|
|
1693
|
+
zig: "zig",
|
|
1694
|
+
zsh: "sh"
|
|
1695
|
+
};
|
|
1696
|
+
function extensionForLanguage(lang) {
|
|
1697
|
+
const first = lang.trim().toLowerCase().split(/[\s:,{]/)[0] ?? "";
|
|
1698
|
+
return LANGUAGE_EXTENSIONS[first] ?? "txt";
|
|
1699
|
+
}
|
|
1700
|
+
function mimeForLanguage(lang) {
|
|
1701
|
+
const ext = extensionForLanguage(lang);
|
|
1702
|
+
if (ext === "json" || ext === "jsonc") return "application/json";
|
|
1703
|
+
if (ext === "html") return "text/html";
|
|
1704
|
+
if (ext === "css") return "text/css";
|
|
1705
|
+
if (ext === "xml" || ext === "svelte" || ext === "vue") return "text/plain";
|
|
1706
|
+
return "text/plain";
|
|
1707
|
+
}
|
|
1708
|
+
function escapeCsvField(value) {
|
|
1709
|
+
let needsQuoting = false;
|
|
1710
|
+
let hasQuote = false;
|
|
1711
|
+
for (const char of value) {
|
|
1712
|
+
if (char === '"') {
|
|
1713
|
+
hasQuote = true;
|
|
1714
|
+
needsQuoting = true;
|
|
1715
|
+
break;
|
|
1437
1716
|
}
|
|
1438
|
-
if (
|
|
1439
|
-
|
|
1440
|
-
|
|
1441
|
-
|
|
1442
|
-
|
|
1443
|
-
|
|
1444
|
-
|
|
1445
|
-
|
|
1446
|
-
|
|
1447
|
-
|
|
1448
|
-
|
|
1717
|
+
if (char === "," || char === "\n" || char === "\r") needsQuoting = true;
|
|
1718
|
+
}
|
|
1719
|
+
if (!needsQuoting) return value;
|
|
1720
|
+
return hasQuote ? `"${value.replace(/"/g, '""')}"` : `"${value}"`;
|
|
1721
|
+
}
|
|
1722
|
+
function escapeMarkdownTableCell(cell) {
|
|
1723
|
+
let needsEscaping = false;
|
|
1724
|
+
for (const char of cell) {
|
|
1725
|
+
if (char === "\\" || char === "|") {
|
|
1726
|
+
needsEscaping = true;
|
|
1727
|
+
break;
|
|
1449
1728
|
}
|
|
1450
|
-
buf += ch;
|
|
1451
|
-
i++;
|
|
1452
1729
|
}
|
|
1453
|
-
|
|
1454
|
-
return
|
|
1730
|
+
if (!needsEscaping) return cell;
|
|
1731
|
+
return cell.replace(/\\/g, "\\\\").replace(/\|/g, "\\|");
|
|
1455
1732
|
}
|
|
1456
|
-
|
|
1457
|
-
lines;
|
|
1458
|
-
|
|
1459
|
-
|
|
1460
|
-
|
|
1461
|
-
|
|
1462
|
-
|
|
1463
|
-
|
|
1464
|
-
|
|
1465
|
-
|
|
1466
|
-
|
|
1467
|
-
|
|
1468
|
-
|
|
1469
|
-
|
|
1470
|
-
|
|
1471
|
-
|
|
1472
|
-
|
|
1473
|
-
|
|
1474
|
-
|
|
1475
|
-
|
|
1476
|
-
|
|
1477
|
-
|
|
1478
|
-
|
|
1479
|
-
|
|
1480
|
-
|
|
1733
|
+
function tableToCsv(table) {
|
|
1734
|
+
const lines = [table.headers.map(escapeCsvField).join(",")];
|
|
1735
|
+
for (const row of table.rows) lines.push(row.map(escapeCsvField).join(","));
|
|
1736
|
+
return `\uFEFF${lines.join("\r\n")}`;
|
|
1737
|
+
}
|
|
1738
|
+
function tableToMarkdown(table) {
|
|
1739
|
+
const header = `| ${table.headers.map(escapeMarkdownTableCell).join(" | ")} |`;
|
|
1740
|
+
const divider = `| ${table.headers.map((_cell, index) => {
|
|
1741
|
+
switch (table.align[index]) {
|
|
1742
|
+
case "left":
|
|
1743
|
+
return ":---";
|
|
1744
|
+
case "center":
|
|
1745
|
+
return ":---:";
|
|
1746
|
+
case "right":
|
|
1747
|
+
return "---:";
|
|
1748
|
+
default:
|
|
1749
|
+
return "---";
|
|
1750
|
+
}
|
|
1751
|
+
}).join(" | ")} |`;
|
|
1752
|
+
const body = table.rows.map(
|
|
1753
|
+
(row) => `| ${table.headers.map((_cell, index) => escapeMarkdownTableCell(row[index] ?? "")).join(" | ")} |`
|
|
1754
|
+
);
|
|
1755
|
+
return [header, divider, ...body].join("\n");
|
|
1756
|
+
}
|
|
1757
|
+
function defaultWriteClipboard(text) {
|
|
1758
|
+
const clipboard = globalThis.navigator?.clipboard;
|
|
1759
|
+
clipboard?.writeText?.(text);
|
|
1760
|
+
}
|
|
1761
|
+
function defaultSaveFile(filename, content, mimeType) {
|
|
1762
|
+
const doc = globalThis.document;
|
|
1763
|
+
if (!doc?.body) return;
|
|
1764
|
+
const blob = new Blob([content], { type: mimeType });
|
|
1765
|
+
const url = URL.createObjectURL(blob);
|
|
1766
|
+
const anchor = doc.createElement("a");
|
|
1767
|
+
anchor.href = url;
|
|
1768
|
+
anchor.download = filename;
|
|
1769
|
+
doc.body.appendChild(anchor);
|
|
1770
|
+
anchor.click();
|
|
1771
|
+
doc.body.removeChild(anchor);
|
|
1772
|
+
URL.revokeObjectURL(url);
|
|
1773
|
+
}
|
|
1774
|
+
var BlockAffordanceButton = class _BlockAffordanceButton extends import_ui3.Button {
|
|
1775
|
+
constructor(label, successLabel, act, opts = {}) {
|
|
1776
|
+
super(label, { ...opts, onClick: () => this.run() });
|
|
1777
|
+
this.act = act;
|
|
1778
|
+
this.restingLabel = label;
|
|
1779
|
+
this.successLabel = successLabel;
|
|
1780
|
+
this.width = Math.max(this.width, (0, import_ui3.measureText)(successLabel, this.font) + 24);
|
|
1481
1781
|
}
|
|
1482
|
-
|
|
1483
|
-
|
|
1484
|
-
|
|
1485
|
-
|
|
1486
|
-
|
|
1487
|
-
|
|
1488
|
-
|
|
1782
|
+
act;
|
|
1783
|
+
/** How long the confirmation label stays up, in ms. */
|
|
1784
|
+
static FEEDBACK_MS = 1600;
|
|
1785
|
+
restingLabel;
|
|
1786
|
+
successLabel;
|
|
1787
|
+
feedbackTimer;
|
|
1788
|
+
/**
|
|
1789
|
+
* Runs the action, then shows the confirmation.
|
|
1790
|
+
*
|
|
1791
|
+
* The action runs first and a throw propagates: a clipboard write the browser
|
|
1792
|
+
* rejected must not be reported as a success.
|
|
1793
|
+
*/
|
|
1794
|
+
run() {
|
|
1795
|
+
this.act();
|
|
1796
|
+
this.setTransientLabel(this.successLabel);
|
|
1797
|
+
if (this.feedbackTimer !== void 0) clearTimeout(this.feedbackTimer);
|
|
1798
|
+
this.feedbackTimer = setTimeout(() => {
|
|
1799
|
+
this.setTransientLabel(this.restingLabel);
|
|
1800
|
+
this.feedbackTimer = void 0;
|
|
1801
|
+
}, _BlockAffordanceButton.FEEDBACK_MS);
|
|
1489
1802
|
}
|
|
1490
|
-
|
|
1491
|
-
|
|
1492
|
-
this.
|
|
1493
|
-
this.contentEpoch++;
|
|
1803
|
+
setTransientLabel(label) {
|
|
1804
|
+
this.label = label;
|
|
1805
|
+
this.textWidth = (0, import_ui3.measureText)(label, this.font);
|
|
1494
1806
|
this.scene?.markDirty();
|
|
1495
|
-
return this;
|
|
1496
|
-
}
|
|
1497
|
-
getContentEpoch() {
|
|
1498
|
-
return this.contentEpoch;
|
|
1499
1807
|
}
|
|
1500
1808
|
/**
|
|
1501
|
-
*
|
|
1502
|
-
*
|
|
1503
|
-
* Deliberately does **not** rebuild the grid or the highlight, because code does
|
|
1504
|
-
* not reflow: lines are placed on a fixed monospace grid at `col × cellWidth` and
|
|
1505
|
-
* a long line overflows rather than wrapping, so `height` is a function of line
|
|
1506
|
-
* *count* alone. The width only sizes the rounded background. Anything that would
|
|
1507
|
-
* change the glyph geometry — the source, the language, the font — goes through
|
|
1508
|
-
* {@link setCode} and invalidates the grid there.
|
|
1509
|
-
*
|
|
1510
|
-
* @returns `this` for chaining.
|
|
1809
|
+
* The label a reader hears is the one they see, transient confirmation
|
|
1810
|
+
* included, so an AT user gets the same feedback a sighted user does.
|
|
1511
1811
|
*/
|
|
1512
|
-
|
|
1513
|
-
|
|
1514
|
-
if (next === this.width) return this;
|
|
1515
|
-
this.width = next;
|
|
1516
|
-
this.scene?.markDirty();
|
|
1517
|
-
return this;
|
|
1812
|
+
getA11yAttributes() {
|
|
1813
|
+
return { ...super.getA11yAttributes(), label: this.label };
|
|
1518
1814
|
}
|
|
1519
|
-
|
|
1520
|
-
|
|
1521
|
-
|
|
1522
|
-
|
|
1523
|
-
|
|
1524
|
-
|
|
1525
|
-
|
|
1526
|
-
|
|
1527
|
-
|
|
1528
|
-
|
|
1529
|
-
|
|
1530
|
-
|
|
1531
|
-
|
|
1532
|
-
|
|
1533
|
-
|
|
1534
|
-
|
|
1535
|
-
|
|
1536
|
-
|
|
1815
|
+
/** Clears the pending revert so a destroyed block leaves no timer behind. */
|
|
1816
|
+
destroy() {
|
|
1817
|
+
if (this.feedbackTimer !== void 0) {
|
|
1818
|
+
clearTimeout(this.feedbackTimer);
|
|
1819
|
+
this.feedbackTimer = void 0;
|
|
1820
|
+
}
|
|
1821
|
+
super.destroy();
|
|
1822
|
+
}
|
|
1823
|
+
};
|
|
1824
|
+
var BlockWithAffordances = class _BlockWithAffordances extends import_ui3.UIComponent {
|
|
1825
|
+
constructor(block, controls) {
|
|
1826
|
+
super();
|
|
1827
|
+
this.block = block;
|
|
1828
|
+
this.controls = controls;
|
|
1829
|
+
this.add(block);
|
|
1830
|
+
for (const control of controls) this.add(control);
|
|
1831
|
+
this.layoutAffordances();
|
|
1832
|
+
}
|
|
1833
|
+
block;
|
|
1834
|
+
controls;
|
|
1835
|
+
/** Gap between the block's edges and the controls, in px. */
|
|
1836
|
+
static INSET = 8;
|
|
1837
|
+
/** Gap between adjacent controls, in px. */
|
|
1838
|
+
static GAP = 6;
|
|
1839
|
+
/**
|
|
1840
|
+
* Places the controls right-aligned along the block's top edge.
|
|
1841
|
+
*
|
|
1842
|
+
* Laid out right-to-left from the block's right edge so the first control in
|
|
1843
|
+
* the list ends up leftmost, which keeps DOM order (and therefore tab order and
|
|
1844
|
+
* the a11y reading order) matching the visual order.
|
|
1845
|
+
*/
|
|
1846
|
+
layoutAffordances() {
|
|
1847
|
+
this.width = this.block.width;
|
|
1848
|
+
this.height = this.block.height;
|
|
1849
|
+
let right = this.block.width - _BlockWithAffordances.INSET;
|
|
1850
|
+
for (let i = this.controls.length - 1; i >= 0; i--) {
|
|
1851
|
+
const control = this.controls[i];
|
|
1852
|
+
control.x = right - control.width;
|
|
1853
|
+
control.y = _BlockWithAffordances.INSET;
|
|
1854
|
+
right = control.x - _BlockWithAffordances.GAP;
|
|
1537
1855
|
}
|
|
1538
|
-
return {
|
|
1539
|
-
text: this.source,
|
|
1540
|
-
font: this.codeFont,
|
|
1541
|
-
lineHeight: this.lineH,
|
|
1542
|
-
// Every row is absolutely positioned from the same local coordinates as
|
|
1543
|
-
// render(). A single pre-wrap DOM text node would introduce browser
|
|
1544
|
-
// wrapping for long source lines that canvas intentionally keeps intact.
|
|
1545
|
-
//
|
|
1546
|
-
lines: rows,
|
|
1547
|
-
selectable: this.selectable,
|
|
1548
|
-
// render() draws cell-by-cell (no ligatures can form); the DOM copy
|
|
1549
|
-
// must not ligate either or Firefox selection geometry drifts.
|
|
1550
|
-
ligatures: "none",
|
|
1551
|
-
grid
|
|
1552
|
-
};
|
|
1553
1856
|
}
|
|
1554
1857
|
/**
|
|
1555
|
-
* Re-
|
|
1556
|
-
*
|
|
1557
|
-
* Streaming appends to the END of a block, so all but the last line or two are
|
|
1558
|
-
* byte-identical to the previous call — yet this used to re-highlight every
|
|
1559
|
-
* line on every chunk, making a streamed block O(N) per append and O(N^2)
|
|
1560
|
-
* overall. Reusing the stable prefix makes an append proportional to what
|
|
1561
|
-
* actually changed.
|
|
1858
|
+
* Re-places the controls after the block's own box changed.
|
|
1562
1859
|
*
|
|
1563
|
-
*
|
|
1564
|
-
*
|
|
1860
|
+
* Called by the owner when a block is resized or its content grew; the controls
|
|
1861
|
+
* are anchored to the right edge, so a width change moves them.
|
|
1565
1862
|
*/
|
|
1566
|
-
|
|
1567
|
-
this.
|
|
1568
|
-
|
|
1569
|
-
const previous = this.rawLines;
|
|
1570
|
-
let reusable = 0;
|
|
1571
|
-
if (previous && this.lines.length === previous.length) {
|
|
1572
|
-
const limit = Math.min(previous.length - 1, rawLines.length);
|
|
1573
|
-
while (reusable < limit && previous[reusable] === rawLines[reusable]) reusable++;
|
|
1574
|
-
}
|
|
1575
|
-
if (reusable > 0) {
|
|
1576
|
-
const next = this.lines.slice(0, reusable);
|
|
1577
|
-
for (let i = reusable; i < rawLines.length; i++) {
|
|
1578
|
-
next.push(highlightLine(rawLines[i], this.lang, this.theme));
|
|
1579
|
-
}
|
|
1580
|
-
this.lines = next;
|
|
1581
|
-
} else {
|
|
1582
|
-
this.lines = rawLines.map((l) => highlightLine(l, this.lang, this.theme));
|
|
1583
|
-
}
|
|
1584
|
-
this.rawLines = rawLines;
|
|
1585
|
-
this.grid = null;
|
|
1586
|
-
this.height = this.pad * 2 + rawLines.length * this.lineH;
|
|
1863
|
+
refreshAffordances() {
|
|
1864
|
+
this.layoutAffordances();
|
|
1865
|
+
this.scene?.markDirty();
|
|
1587
1866
|
}
|
|
1588
|
-
|
|
1589
|
-
|
|
1590
|
-
|
|
1591
|
-
this.grid = (0, import_core.prepareContentGrid)(this.source, {
|
|
1592
|
-
font: this.codeFont,
|
|
1593
|
-
cellWidth,
|
|
1594
|
-
lineHeight: this.lineH,
|
|
1595
|
-
baseline: this.lineH * 0.75
|
|
1596
|
-
});
|
|
1597
|
-
}
|
|
1598
|
-
return this.grid;
|
|
1867
|
+
/** The wrapper is a pass-through: its size is the block's size. */
|
|
1868
|
+
getLayoutControlledProperties() {
|
|
1869
|
+
return ["x", "y"];
|
|
1599
1870
|
}
|
|
1600
|
-
/**
|
|
1601
|
-
|
|
1602
|
-
|
|
1871
|
+
/**
|
|
1872
|
+
* Projected as a group so assistive technology reports one labelled region
|
|
1873
|
+
* containing the block and its controls, rather than two unrelated siblings.
|
|
1874
|
+
*/
|
|
1875
|
+
getA11yAttributes() {
|
|
1876
|
+
return { role: "group", pointerEvents: "none" };
|
|
1603
1877
|
}
|
|
1604
|
-
render(
|
|
1605
|
-
r.beginPath();
|
|
1606
|
-
r.roundRect(0, 0, this.width, this.height, 8);
|
|
1607
|
-
r.fill(this.theme.codeBgColor);
|
|
1608
|
-
const grid = this.ensureGrid();
|
|
1609
|
-
const atlas = codeGlyphAtlas(r);
|
|
1610
|
-
const atlasSource = atlas?.source ?? null;
|
|
1611
|
-
const blit = atlas ? r.drawImageRect : void 0;
|
|
1612
|
-
for (let row = 0; row < grid.lines.length; row++) {
|
|
1613
|
-
const yBaseline = this.pad + row * this.lineH + this.lineH * 0.75;
|
|
1614
|
-
const segments = this.lines[row];
|
|
1615
|
-
let segmentIndex = 0;
|
|
1616
|
-
let segmentEnd = segments[0]?.text.length ?? 0;
|
|
1617
|
-
const lineStart = grid.lines[row].sourceStart;
|
|
1618
|
-
for (const cell of grid.lines[row].cells) {
|
|
1619
|
-
const localSourceStart = cell.sourceStart - lineStart;
|
|
1620
|
-
while (segmentIndex < segments.length - 1 && localSourceStart >= segmentEnd) {
|
|
1621
|
-
segmentIndex++;
|
|
1622
|
-
segmentEnd += segments[segmentIndex].text.length;
|
|
1623
|
-
}
|
|
1624
|
-
const sourceText = this.source.slice(cell.sourceStart, cell.sourceEnd);
|
|
1625
|
-
if (cell.advance <= 0 || sourceText === " " || sourceText === " ") continue;
|
|
1626
|
-
const color = segments[segmentIndex]?.color ?? this.theme.codeColor;
|
|
1627
|
-
const x = this.pad + cell.x;
|
|
1628
|
-
if (blit && atlas) {
|
|
1629
|
-
const slot = atlas.get(this.codeFont, color, cell.glyph);
|
|
1630
|
-
const src = atlasSource ?? atlas.source;
|
|
1631
|
-
if (slot && src) {
|
|
1632
|
-
blit.call(
|
|
1633
|
-
r,
|
|
1634
|
-
src,
|
|
1635
|
-
slot.sx,
|
|
1636
|
-
slot.sy,
|
|
1637
|
-
slot.sw,
|
|
1638
|
-
slot.sh,
|
|
1639
|
-
x - slot.offsetX,
|
|
1640
|
-
yBaseline - slot.offsetY,
|
|
1641
|
-
slot.w,
|
|
1642
|
-
slot.h
|
|
1643
|
-
);
|
|
1644
|
-
continue;
|
|
1645
|
-
}
|
|
1646
|
-
}
|
|
1647
|
-
r.fillText(cell.glyph, x, yBaseline, this.codeFont, color);
|
|
1648
|
-
}
|
|
1649
|
-
}
|
|
1878
|
+
render() {
|
|
1650
1879
|
}
|
|
1651
1880
|
};
|
|
1652
|
-
|
|
1653
|
-
|
|
1654
|
-
|
|
1655
|
-
|
|
1656
|
-
|
|
1657
|
-
|
|
1658
|
-
|
|
1659
|
-
|
|
1660
|
-
|
|
1661
|
-
|
|
1662
|
-
|
|
1663
|
-
|
|
1664
|
-
|
|
1665
|
-
|
|
1666
|
-
|
|
1667
|
-
|
|
1881
|
+
function tableContentOf(token) {
|
|
1882
|
+
return {
|
|
1883
|
+
headers: token.header.map((cell) => cell.text),
|
|
1884
|
+
rows: token.rows.map((row) => row.map((cell) => cell.text)),
|
|
1885
|
+
align: token.align
|
|
1886
|
+
};
|
|
1887
|
+
}
|
|
1888
|
+
|
|
1889
|
+
// src/frontMatter.ts
|
|
1890
|
+
var OPEN_RE = /^---[ \t]*\r?\n/;
|
|
1891
|
+
var OPENER_PREFIX_RE = /^(?:-|--|---[ \t]*\r?)$/;
|
|
1892
|
+
var KEY_RE = /^[^\s:#][^:]*:(?:[ \t].*)?$/;
|
|
1893
|
+
var CLOSE_RE = /^(?:---|\.\.\.)[ \t]*$/;
|
|
1894
|
+
var MAX_PENDING_CHARS = 4096;
|
|
1895
|
+
var NONE = { kind: "none" };
|
|
1896
|
+
var PENDING = { kind: "pending" };
|
|
1897
|
+
function scanFrontMatter(text, complete) {
|
|
1898
|
+
if (text.length === 0) return PENDING;
|
|
1899
|
+
const open = OPEN_RE.exec(text);
|
|
1900
|
+
if (!open) {
|
|
1901
|
+
return !complete && OPENER_PREFIX_RE.test(text) ? PENDING : NONE;
|
|
1668
1902
|
}
|
|
1669
|
-
const
|
|
1670
|
-
|
|
1671
|
-
|
|
1672
|
-
|
|
1673
|
-
|
|
1674
|
-
|
|
1675
|
-
if (
|
|
1903
|
+
const decide = complete || text.length > MAX_PENDING_CHARS;
|
|
1904
|
+
const contentStart = open[0].length;
|
|
1905
|
+
let cursor = contentStart;
|
|
1906
|
+
let keyChecked = false;
|
|
1907
|
+
while (cursor < text.length) {
|
|
1908
|
+
const nl = text.indexOf("\n", cursor);
|
|
1909
|
+
if (nl === -1 && !decide) return PENDING;
|
|
1910
|
+
const line = text.slice(cursor, nl === -1 ? text.length : nl).replace(/\r$/, "");
|
|
1911
|
+
if (!keyChecked) {
|
|
1912
|
+
if (!KEY_RE.test(line)) return NONE;
|
|
1913
|
+
keyChecked = true;
|
|
1914
|
+
} else if (CLOSE_RE.test(line)) {
|
|
1915
|
+
return {
|
|
1916
|
+
kind: "found",
|
|
1917
|
+
raw: text.slice(contentStart, cursor),
|
|
1918
|
+
// A closer with no trailing newline ends the document, so the body is
|
|
1919
|
+
// empty rather than starting one character past the end.
|
|
1920
|
+
bodyStart: nl === -1 ? text.length : nl + 1
|
|
1921
|
+
};
|
|
1922
|
+
}
|
|
1923
|
+
if (nl === -1) break;
|
|
1924
|
+
cursor = nl + 1;
|
|
1676
1925
|
}
|
|
1677
|
-
|
|
1678
|
-
return atlas;
|
|
1926
|
+
return decide ? NONE : PENDING;
|
|
1679
1927
|
}
|
|
1680
|
-
function
|
|
1681
|
-
|
|
1928
|
+
function parseFrontMatterFields(raw) {
|
|
1929
|
+
const out = {};
|
|
1930
|
+
for (const rawLine of raw.split("\n")) {
|
|
1931
|
+
const line = rawLine.replace(/\r$/, "");
|
|
1932
|
+
if (line.length === 0 || /^[\s#]/.test(line)) continue;
|
|
1933
|
+
const sep = line.indexOf(":");
|
|
1934
|
+
if (sep <= 0) continue;
|
|
1935
|
+
const value = line.slice(sep + 1);
|
|
1936
|
+
if (value.length > 0 && value[0] !== " " && value[0] !== " ") continue;
|
|
1937
|
+
out[line.slice(0, sep).trim()] = unquote(value.trim());
|
|
1938
|
+
}
|
|
1939
|
+
return out;
|
|
1682
1940
|
}
|
|
1683
|
-
function
|
|
1684
|
-
return
|
|
1941
|
+
function unquote(value) {
|
|
1942
|
+
if (value.length < 2) return value;
|
|
1943
|
+
const first = value[0];
|
|
1944
|
+
if ((first === '"' || first === "'") && value.endsWith(first)) {
|
|
1945
|
+
return value.slice(1, -1);
|
|
1946
|
+
}
|
|
1947
|
+
return value;
|
|
1685
1948
|
}
|
|
1686
|
-
|
|
1687
|
-
|
|
1949
|
+
|
|
1950
|
+
// src/MarkdownWorkerSource.ts
|
|
1951
|
+
var WORKER_SOURCE_STRING = '"use strict";(()=>{function V(){return{async:!1,breaks:!1,extensions:null,gfm:!0,hooks:null,pedantic:!1,renderer:null,silent:!1,tokenizer:null,walkTokens:null}}var _=V();function ke(t){_=t}var C={exec:()=>null};function E(t){let e=[];return n=>{let s=Math.max(0,Math.min(3,n-1)),r=e[s];return r||(r=t(s),e[s]=r),r}}function k(t,e=""){let n=typeof t=="string"?t:t.source,s={replace:(r,i)=>{let a=typeof i=="string"?i:i.source;return a=a.replace(x.caret,"$1"),n=n.replace(r,a),s},getRegex:()=>new RegExp(n,e)};return s}var Pe=((t="")=>{try{return!!new RegExp("(?<=1)(?<!1)"+t)}catch{return!1}})(),x={codeRemoveIndent:/^(?: {1,4}| {0,3}\\t)/gm,outputLinkReplace:/\\\\([\\[\\]])/g,indentCodeCompensation:/^(\\s+)(?:```)/,beginningSpace:/^\\s+/,endingHash:/#$/,startingSpaceChar:/^ /,endingSpaceChar:/ $/,nonSpaceChar:/[^ ]/,newLineCharGlobal:/\\n/g,tabCharGlobal:/\\t/g,multipleSpaceGlobal:/\\s+/g,blankLine:/^[ \\t]*$/,doubleBlankLine:/\\n[ \\t]*\\n[ \\t]*$/,blockquoteStart:/^ {0,3}>/,blockquoteSetextReplace:/\\n {0,3}((?:=+|-+) *)(?=\\n|$)/g,blockquoteSetextReplace2:/^ {0,3}>[ \\t]?/gm,listReplaceNesting:/^ {1,4}(?=( {4})*[^ ])/g,listIsTask:/^\\[[ xX]\\] +\\S/,listReplaceTask:/^\\[[ xX]\\] +/,listTaskCheckbox:/\\[[ xX]\\]/,anyLine:/\\n.*\\n/,hrefBrackets:/^<(.*)>$/,tableDelimiter:/[:|]/,tableAlignChars:/^\\||\\| *$/g,tableRowBlankLine:/\\n[ \\t]*$/,tableAlignRight:/^ *-+: *$/,tableAlignCenter:/^ *:-+: *$/,tableAlignLeft:/^ *:-+ *$/,startATag:/^<a /i,endATag:/^<\\/a>/i,startPreScriptTag:/^<(pre|code|kbd|script)(\\s|>)/i,endPreScriptTag:/^<\\/(pre|code|kbd|script)(\\s|>)/i,startAngleBracket:/^</,endAngleBracket:/>$/,pedanticHrefTitle:/^([^\'"]*[^\\s])\\s+([\'"])(.*)\\2/,unicodeAlphaNumeric:/[\\p{L}\\p{N}]/u,escapeTest:/[&<>"\']/,escapeReplace:/[&<>"\']/g,escapeTestNoEncode:/[<>"\']|&(?!(#\\d{1,7}|#[Xx][a-fA-F0-9]{1,6}|\\w+);)/,escapeReplaceNoEncode:/[<>"\']|&(?!(#\\d{1,7}|#[Xx][a-fA-F0-9]{1,6}|\\w+);)/g,caret:/(^|[^\\[])\\^/g,percentDecode:/%25/g,findPipe:/\\|/g,splitPipe:/ \\|/,slashPipe:/\\\\\\|/g,carriageReturn:/\\r\\n|\\r/g,spaceLine:/^ +$/gm,notSpaceStart:/^\\S*/,endingNewline:/\\n$/,listItemRegex:t=>new RegExp(`^( {0,3}${t})((?:[ ][^\\\\n]*)?(?:\\\\n|$))`),nextBulletRegex:E(t=>new RegExp(`^ {0,${t}}(?:[*+-]|\\\\d{1,9}[.)])((?:[ ][^\\\\n]*)?(?:\\\\n|$))`)),hrRegex:E(t=>new RegExp(`^ {0,${t}}((?:- *){3,}|(?:_ *){3,}|(?:\\\\* *){3,})(?:\\\\n+|$)`)),fencesBeginRegex:E(t=>new RegExp(`^ {0,${t}}(?:\\`\\`\\`|~~~)`)),headingBeginRegex:E(t=>new RegExp(`^ {0,${t}}#`)),htmlBeginRegex:E(t=>new RegExp(`^ {0,${t}}<(?:[a-z].*>|!--)`,"i")),blockquoteBeginRegex:E(t=>new RegExp(`^ {0,${t}}>`))},Me=/^(?:[ \\t]*(?:\\n|$))+/,Be=/^((?: {4}| {0,3}\\t)[^\\n]+(?:\\n(?:[ \\t]*(?:\\n|$))*)?)+/,qe=/^ {0,3}(`{3,}(?=[^`\\n]*(?:\\n|$))|~{3,})([^\\n]*)(?:\\n|$)(?:|([\\s\\S]*?)(?:\\n|$))(?: {0,3}\\1[~`]* *(?=\\n|$)|$)/,v=/^ {0,3}((?:-[\\t ]*){3,}|(?:_[ \\t]*){3,}|(?:\\*[ \\t]*){3,})(?:\\n+|$)/,ve=/^ {0,3}(#{1,6})(?=\\s|$)(.*)(?:\\n+|$)/,K=/ {0,3}(?:[*+-]|\\d{1,9}[.)])/,fe=/^(?!bull |blockCode|fences|blockquote|heading|html|table)((?:.|\\n(?!\\s*?\\n|bull |blockCode|fences|blockquote|heading|html|table))+?)\\n {0,3}(=+|-+) *(?:\\n+|$)/,de=k(fe).replace(/bull/g,K).replace(/blockCode/g,/(?: {4}| {0,3}\\t)/).replace(/fences/g,/ {0,3}(?:`{3,}|~{3,})/).replace(/blockquote/g,/ {0,3}>/).replace(/heading/g,/ {0,3}#{1,6}(?:\\s|$)/).replace(/html/g,/ {0,3}<[^\\n>]+>\\n/).replace(/\\|table/g,"").getRegex(),De=k(fe).replace(/bull/g,K).replace(/blockCode/g,/(?: {4}| {0,3}\\t)/).replace(/fences/g,/ {0,3}(?:`{3,}|~{3,})/).replace(/blockquote/g,/ {0,3}>/).replace(/heading/g,/ {0,3}#{1,6}(?:\\s|$)/).replace(/html/g,/ {0,3}<[^\\n>]+>\\n/).replace(/table/g,/ {0,3}\\|?(?:[:\\- ]*\\|)+[\\:\\- ]*\\n/).getRegex(),J=/^([^\\n]+(?:\\n(?!hr|heading|lheading|blockquote|fences|list|html|table|[ \\t]+\\n)[^\\n]+)*)/,Oe=/^[^\\n]+/,Y=/(?!\\s*\\])(?:\\\\[\\s\\S]|[^\\[\\]\\\\])+/,Ze=k(/^ {0,3}\\[(label)\\]: *(?:\\n[ \\t]*)?([^<\\s][^\\s]*|<.*?>)(?:(?: +(?:\\n[ \\t]*)?| *\\n[ \\t]*)(title))? *(?:\\n+|$)/).replace("label",Y).replace("title",/(?:"(?:\\\\"?|[^"\\\\])*"|\'[^\'\\n]*(?:\\n[^\'\\n]+)*\\n?\'|\\([^()]*\\))/).getRegex(),Ne=k(/^(bull)([ \\t][^\\n]*?)?(?:\\n|$)/).replace(/bull/g,K).getRegex(),Q="address|article|aside|base|basefont|blockquote|body|caption|center|col|colgroup|dd|details|dialog|dir|div|dl|dt|fieldset|figcaption|figure|footer|form|frame|frameset|h[1-6]|head|header|hr|html|iframe|legend|li|link|main|menu|menuitem|meta|nav|noframes|ol|optgroup|option|p|param|search|section|summary|table|tbody|td|tfoot|th|thead|title|tr|track|ul",ee=/<!--(?:-?>|[\\s\\S]*?(?:-->|$))/,Qe=k("^ {0,3}(?:<(script|pre|style|textarea)[\\\\s>][\\\\s\\\\S]*?(?:</\\\\1>[^\\\\n]*\\\\n*|$)|comment[^\\\\n]*(\\\\n+|$)|<\\\\?[\\\\s\\\\S]*?(?:\\\\?>[^\\\\n]*\\\\n*|$)|<![A-Z][\\\\s\\\\S]*?(?:>[^\\\\n]*\\\\n*|$)|<!\\\\[CDATA\\\\[[\\\\s\\\\S]*?(?:\\\\]\\\\]>[^\\\\n]*\\\\n*|$)|</?(tag)(?: +|\\\\n|/?>)[\\\\s\\\\S]*?(?:(?:\\\\n[ ]*)+\\\\n|$)|<(?!script|pre|style|textarea)([a-z][\\\\w-]*)(?:attribute)*? */?>(?=[ \\\\t]*(?:\\\\n|$))[\\\\s\\\\S]*?(?:(?:\\\\n[ ]*)+\\\\n|$)|</(?!script|pre|style|textarea)[a-z][\\\\w-]*\\\\s*>(?=[ \\\\t]*(?:\\\\n|$))[\\\\s\\\\S]*?(?:(?:\\\\n[ ]*)+\\\\n|$))","i").replace("comment",ee).replace("tag",Q).replace("attribute",/ +[a-zA-Z:_][\\w.:-]*(?: *= *"[^"\\n]*"| *= *\'[^\'\\n]*\'| *= *[^\\s"\'=<>`]+)?/).getRegex(),xe=t=>k(J).replace("hr",v).replace("heading"," {0,3}#{1,6}(?:\\\\s|$)").replace("|lheading","").replace("|table","").replace("blockquote"," {0,3}>").replace("fences"," {0,3}(?:`{3,}(?=[^`\\\\n]*\\\\n)|~~~)[^\\\\n]*\\\\n").replace("list",t).replace("html","</?(?:tag)(?: +|\\\\n|/?>)|<(?:script|pre|style|textarea|!--)").replace("tag",Q).getRegex(),Fe=xe(/ {0,3}(?:[*+-]|1[.)])[ \\t]+[^ \\t\\n]/),He=xe(/ {0,3}(?:[*+-]|\\d{1,9}[.)])(?:[ \\t]|\\n|$)/),je=k(/^( {0,3}> ?(paragraph|[^\\n]*)(?:\\n|$))+/).replace("paragraph",He).getRegex(),te={blockquote:je,code:Be,def:Ze,fences:qe,heading:ve,hr:v,html:Qe,lheading:de,list:Ne,newline:Me,paragraph:Fe,table:C,text:Oe},ae=k("^ *([^\\\\n ].*)\\\\n {0,3}((?:\\\\| *)?:?-+:? *(?:\\\\| *:?-+:? *)*(?:\\\\| *)?)(?:\\\\n((?:(?! *\\\\n|hr|heading|blockquote|code|fences|list|html).*(?:\\\\n|$))*)\\\\n*|$)").replace("hr",v).replace("heading"," {0,3}#{1,6}(?:\\\\s|$)").replace("blockquote"," {0,3}>").replace("code","(?: {4}| {0,3} )[^\\\\n]").replace("fences"," {0,3}(?:`{3,}(?=[^`\\\\n]*\\\\n)|~~~)[^\\\\n]*\\\\n").replace("list"," {0,3}(?:[*+-]|1[.)])[ \\\\t]").replace("html","</?(?:tag)(?: +|\\\\n|/?>)|<(?:script|pre|style|textarea|!--)").replace("tag",Q).getRegex(),Ge={...te,lheading:De,table:ae,paragraph:k(J).replace("hr",v).replace("heading"," {0,3}#{1,6}(?:\\\\s|$)").replace("|lheading","").replace("table",ae).replace("blockquote"," {0,3}>").replace("fences"," {0,3}(?:`{3,}(?=[^`\\\\n]*\\\\n)|~~~)[^\\\\n]*\\\\n").replace("list"," {0,3}(?:[*+-]|1[.)])[ \\\\t]+[^ \\\\t\\\\n]").replace("html","</?(?:tag)(?: +|\\\\n|/?>)|<(?:script|pre|style|textarea|!--)").replace("tag",Q).getRegex()},We={...te,html:k(`^ *(?:comment *(?:\\\\n|\\\\s*$)|<(tag)[\\\\s\\\\S]+?</\\\\1> *(?:\\\\n{2,}|\\\\s*$)|<tag(?:"[^"]*"|\'[^\']*\'|\\\\s[^\'"/>\\\\s]*)*?/?> *(?:\\\\n{2,}|\\\\s*$))`).replace("comment",ee).replace(/tag/g,"(?!(?:a|em|strong|small|s|cite|q|dfn|abbr|data|time|code|var|samp|kbd|sub|sup|i|b|u|mark|ruby|rt|rp|bdi|bdo|span|br|wbr|ins|del|img)\\\\b)\\\\w+(?!:|[^\\\\w\\\\s@]*@)\\\\b").getRegex(),def:/^ *\\[([^\\]]+)\\]: *<?([^\\s>]+)>?(?: +(["(][^\\n]+[")]))? *(?:\\n+|$)/,heading:/^(#{1,6})(.*)(?:\\n+|$)/,fences:C,lheading:/^(.+?)\\n {0,3}(=+|-+) *(?:\\n+|$)/,paragraph:k(J).replace("hr",v).replace("heading",` *#{1,6} *[^\n]`).replace("lheading",de).replace("|table","").replace("blockquote"," {0,3}>").replace("|fences","").replace("|list","").replace("|html","").replace("|tag","").getRegex()},Xe=/^\\\\([!"#$%&\'()*+,\\-./:;<=>?@\\[\\]\\\\^_`{|}~])/,Ue=/^(`+)([^`]|[^`][\\s\\S]*?[^`])\\1(?!`)/,be=/^( {2,}|\\\\)\\n(?!\\s*$)/,Ve=/^(`+|[^`])(?:(?= {2,}\\n)|[\\s\\S]*?(?:(?=[\\\\<!\\[`*_]|\\b_|$)|[^ ](?= {2,}\\n)))/,P=/[\\p{P}\\p{S}]/u,F=/[\\s\\p{P}\\p{S}]/u,ne=/[^\\s\\p{P}\\p{S}]/u,Ke=k(/^((?![*_])punctSpace)/,"u").replace(/punctSpace/g,F).getRegex(),me=/(?!~)[\\p{P}\\p{S}]/u,Je=/(?!~)[\\s\\p{P}\\p{S}]/u,Ye=/(?:[^\\s\\p{P}\\p{S}]|~)/u,et=k(/link|precode-code|html/,"g").replace("link",/\\[(?:[^\\[\\]`]|(?<a>`+)[^`]+\\k<a>(?!`))*?\\]\\((?:\\\\[\\s\\S]|[^\\\\\\(\\)]|\\((?:\\\\[\\s\\S]|[^\\\\\\(\\)])*\\))*\\)/).replace("precode-",Pe?"(?<!`)()":"(^^|[^`])").replace("code",/(?<b>`+)[^`]+\\k<b>(?!`)/).replace("html",/<(?! )[^<>]*?>/).getRegex(),we=/^(?:\\*+(?:((?!\\*)punct)|([^\\s*]))?)|^_+(?:((?!_)punct)|([^\\s_]))?/,tt=k(we,"u").replace(/punct/g,P).getRegex(),nt=k(we,"u").replace(/punct/g,me).getRegex(),ye="^[^_*]*?__[^_*]*?\\\\*[^_*]*?(?=__)|[^*]+(?=[^*])|(?!\\\\*)punct(\\\\*+)(?=[\\\\s]|$)|notPunctSpace(\\\\*+)(?!\\\\*)(?=punctSpace|$)|(?!\\\\*)punctSpace(\\\\*+)(?=notPunctSpace)|[\\\\s](\\\\*+)(?!\\\\*)(?=punct)|(?!\\\\*)punct(\\\\*+)(?!\\\\*)(?=punct)|notPunctSpace(\\\\*+)(?=notPunctSpace)",rt=k(ye,"gu").replace(/notPunctSpace/g,ne).replace(/punctSpace/g,F).replace(/punct/g,P).getRegex(),st=k(ye,"gu").replace(/notPunctSpace/g,Ye).replace(/punctSpace/g,Je).replace(/punct/g,me).getRegex(),it=k("^[^_*]*?\\\\*\\\\*[^_*]*?_[^_*]*?(?=\\\\*\\\\*)|[^_]+(?=[^_])|(?!_)punct(_+)(?=[\\\\s]|$)|notPunctSpace(_+)(?!_)(?=punctSpace|$)|(?!_)punctSpace(_+)(?=notPunctSpace)|[\\\\s](_+)(?!_)(?=punct)|(?!_)punct(_+)(?!_)(?=punct)","gu").replace(/notPunctSpace/g,ne).replace(/punctSpace/g,F).replace(/punct/g,P).getRegex(),lt=k(/^~~?(?:((?!~)punct)|[^\\s~])/,"u").replace(/punct/g,P).getRegex(),at="^[^~]+(?=[^~])|(?!~)punct(~~?)(?=[\\\\s]|$)|notPunctSpace(~~?)(?!~)(?=punctSpace|$)|(?!~)punctSpace(~~?)(?=notPunctSpace)|[\\\\s](~~?)(?!~)(?=punct)|(?!~)punct(~~?)(?!~)(?=punct)|notPunctSpace(~~?)(?=notPunctSpace)",ot=k(at,"gu").replace(/notPunctSpace/g,ne).replace(/punctSpace/g,F).replace(/punct/g,P).getRegex(),ct=k(/\\\\(punct)/,"gu").replace(/punct/g,P).getRegex(),ht=k(/^<(scheme:[^\\s\\x00-\\x1f<>]*|email)>/).replace("scheme",/[a-zA-Z][a-zA-Z0-9+.-]{1,31}/).replace("email",/[a-zA-Z0-9.!#$%&\'*+/=?^_`{|}~-]+(@)[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)+(?![-_])/).getRegex(),ut=k(ee).replace("(?:-->|$)","-->").getRegex(),pt=k("^comment|^</[a-zA-Z][\\\\w:-]*\\\\s*>|^<[a-zA-Z][\\\\w-]*(?:attribute)*?\\\\s*/?>|^<\\\\?[\\\\s\\\\S]*?\\\\?>|^<![a-zA-Z]+\\\\s[\\\\s\\\\S]*?>|^<!\\\\[CDATA\\\\[[\\\\s\\\\S]*?\\\\]\\\\]>").replace("comment",ut).replace("attribute",/\\s+[a-zA-Z:_][\\w.:-]*(?:\\s*=\\s*"[^"]*"|\\s*=\\s*\'[^\']*\'|\\s*=\\s*[^\\s"\'=<>`]+)?/).getRegex(),O=/(?:\\[(?:\\\\[\\s\\S]|[^\\[\\]\\\\])*\\]|\\\\[\\s\\S]|`+(?!`)[^`]*?`+(?!`)|``+(?=\\])|[^\\[\\]\\\\`])*?/,gt=k(/^!?\\[(label)\\]\\(\\s*(href)(?:(?:[ \\t]+(?:\\n[ \\t]*)?|\\n[ \\t]*)(title))?\\s*\\)/).replace("label",O).replace("href",/<(?:\\\\.|[^\\n<>\\\\])+>|[^ \\t\\n\\x00-\\x1f]+|(?=\\))/).replace("title",/"(?:\\\\"?|[^"\\\\])*"|\'(?:\\\\\'?|[^\'\\\\])*\'|\\((?:\\\\\\)?|[^)\\\\])*\\)/).getRegex(),Re=k(/^!?\\[(label)\\]\\[(ref)\\]/).replace("label",O).replace("ref",Y).getRegex(),$e=k(/^!?\\[(ref)\\](?:\\[\\])?/).replace("ref",Y).getRegex(),kt=k("reflink|nolink(?!\\\\()","g").replace("reflink",Re).replace("nolink",$e).getRegex(),oe=/[hH][tT][tT][pP][sS]?|[fF][tT][pP]/,re={_backpedal:C,anyPunctuation:ct,autolink:ht,blockSkip:et,br:be,code:Ue,del:C,delLDelim:C,delRDelim:C,emStrongLDelim:tt,emStrongRDelimAst:rt,emStrongRDelimUnd:it,escape:Xe,link:gt,nolink:$e,punctuation:Ke,reflink:Re,reflinkSearch:kt,tag:pt,text:Ve,url:C},ft={...re,link:k(/^!?\\[(label)\\]\\((.*?)\\)/).replace("label",O).getRegex(),reflink:k(/^!?\\[(label)\\]\\s*\\[([^\\]]*)\\]/).replace("label",O).getRegex()},W={...re,emStrongRDelimAst:st,emStrongLDelim:nt,delLDelim:lt,delRDelim:ot,url:k(/^((?:protocol):\\/\\/|www\\.)(?:[a-zA-Z0-9\\-]+\\.?)+[^\\s<]*|^email/).replace("protocol",oe).replace("email",/[A-Za-z0-9._+-]+(@)[a-zA-Z0-9-_]+(?:\\.[a-zA-Z0-9-_]*[a-zA-Z0-9])+(?![-_])/).getRegex(),_backpedal:/(?:[^?!.,:;*_\'"~()&]+|\\([^)]*\\)|&(?![a-zA-Z0-9]+;$)|[?!.,:;*_\'"~)]+(?!$))+/,del:/^(~~?)(?=[^\\s~])((?:\\\\[\\s\\S]|[^\\\\])*?(?:\\\\[\\s\\S]|[^\\s~\\\\]))\\1(?=[^~]|$)/,text:k(/^(`+|~+|[^`~])(?:(?=[`~])|(?= {2,}\\n)|(?=[a-zA-Z0-9.!#$%&\'*+\\/=?_`{\\|}~-]+@)|[\\s\\S]*?(?:(?=[\\\\<!\\[`*~_]|\\b_|protocol:\\/\\/|www\\.|$)|[^ ](?= {2,}\\n)|[^a-zA-Z0-9.!#$%&\'*+\\/=?_`{\\|}~-](?=[a-zA-Z0-9.!#$%&\'*+\\/=?_`{\\|}~-]+@)))/).replace("protocol",oe).getRegex()},dt={...W,br:k(be).replace("{2,}","*").getRegex(),text:k(W.text).replace("\\\\b_","\\\\b_| {2,}\\\\n").replace(/\\{2,\\}/g,"*").getRegex()},D={normal:te,gfm:Ge,pedantic:We},B={normal:re,gfm:W,breaks:dt,pedantic:ft},xt={"&":"&","<":"<",">":">",\'"\':""","\'":"'"},ce=t=>xt[t];function S(t,e){if(e){if(x.escapeTest.test(t))return t.replace(x.escapeReplace,ce)}else if(x.escapeTestNoEncode.test(t))return t.replace(x.escapeReplaceNoEncode,ce);return t}function he(t){try{t=encodeURI(t).replace(x.percentDecode,"%")}catch{return null}return t}function ue(t,e){let n=t.replace(x.findPipe,(i,a,l)=>{let o=!1,c=a;for(;--c>=0&&l[c]==="\\\\";)o=!o;return o?"|":" |"}),s=n.split(x.splitPipe),r=0;if(s[0].trim()||s.shift(),s.length>0&&!s.at(-1)?.trim()&&s.pop(),e)if(s.length>e)s.splice(e);else for(;s.length<e;)s.push("");for(;r<s.length;r++)s[r]=s[r].trim().replace(x.slashPipe,"|");return s}function z(t,e,n){let s=t.length;if(s===0)return"";let r=0;for(;r<s;){let i=t.charAt(s-r-1);if(i===e&&!n)r++;else if(i!==e&&n)r++;else break}return t.slice(0,s-r)}function pe(t){let e=t.split(`\n`),n=e.length-1;for(;n>=0&&x.blankLine.test(e[n]);)n--;return e.length-n<=2?t:e.slice(0,n+1).join(`\n`)}function bt(t,e){if(t.indexOf(e[1])===-1)return-1;let n=0;for(let s=0;s<t.length;s++)if(t[s]==="\\\\")s++;else if(t[s]===e[0])n++;else if(t[s]===e[1]&&(n--,n<0))return s;return n>0?-2:-1}function mt(t,e=0){let n=e,s="";for(let r of t)if(r===" "){let i=4-n%4;s+=" ".repeat(i),n+=i}else s+=r,n++;return s}function ge(t,e,n,s,r){let i=e.href,a=e.title||null,l=t[1].replace(r.other.outputLinkReplace,"$1");s.state.inLink=!0;let o={type:t[0].charAt(0)==="!"?"image":"link",raw:n,href:i,title:a,text:l,tokens:s.inlineTokens(l)};return s.state.inLink=!1,o}function wt(t,e,n){let s=t.match(n.other.indentCodeCompensation);if(s===null)return e;let r=s[1];return e.split(`\n`).map(i=>{let a=i.match(n.other.beginningSpace);if(a===null)return i;let[l]=a;return l.length>=r.length?i.slice(r.length):i}).join(`\n`)}var Z=class{options;rules;lexer;constructor(t){this.options=t||_}space(t){let e=this.rules.block.newline.exec(t);if(e&&e[0].length>0)return{type:"space",raw:e[0]}}code(t){let e=this.rules.block.code.exec(t);if(e){let n=this.options.pedantic?e[0]:pe(e[0]),s=n.replace(this.rules.other.codeRemoveIndent,"");return{type:"code",raw:n,codeBlockStyle:"indented",text:s}}}fences(t){let e=this.rules.block.fences.exec(t);if(e){let n=e[0],s=wt(n,e[3]||"",this.rules);return{type:"code",raw:n,lang:e[2]?e[2].trim().replace(this.rules.inline.anyPunctuation,"$1"):e[2],text:s}}}heading(t){let e=this.rules.block.heading.exec(t);if(e){let n=e[2].trim();if(this.rules.other.endingHash.test(n)){let s=z(n,"#");(this.options.pedantic||!s||this.rules.other.endingSpaceChar.test(s))&&(n=s.trim())}return{type:"heading",raw:z(e[0],`\n`),depth:e[1].length,text:n,tokens:this.lexer.inline(n)}}}hr(t){let e=this.rules.block.hr.exec(t);if(e)return{type:"hr",raw:z(e[0],`\n`)}}blockquote(t){let e=this.rules.block.blockquote.exec(t);if(e){let n=z(e[0],`\n`).split(`\n`),s="",r="",i=[];for(;n.length>0;){let a=!1,l=[],o;for(o=0;o<n.length;o++)if(this.rules.other.blockquoteStart.test(n[o]))l.push(n[o]),a=!0;else if(!a)l.push(n[o]);else break;n=n.slice(o);let c=l.join(`\n`),u=c.replace(this.rules.other.blockquoteSetextReplace,`\n $1`).replace(this.rules.other.blockquoteSetextReplace2,"");s=s?`${s}\n${c}`:c,r=r?`${r}\n${u}`:u;let h=this.lexer.state.top;if(this.lexer.state.top=!0,this.lexer.blockTokens(u,i,!0),this.lexer.state.top=h,n.length===0)break;let p=i.at(-1);if(p?.type==="code")break;if(p?.type==="blockquote"){let d=p,f=d.raw+`\n`+n.join(`\n`),m=this.blockquote(f);i[i.length-1]=m,s=s.substring(0,s.length-d.raw.length)+m.raw,r=r.substring(0,r.length-d.text.length)+m.text;break}else if(p?.type==="list"){let d=p,f=d.raw+`\n`+n.join(`\n`),m=this.list(f);i[i.length-1]=m,s=s.substring(0,s.length-p.raw.length)+m.raw,r=r.substring(0,r.length-d.raw.length)+m.raw,n=f.substring(i.at(-1).raw.length).split(`\n`);continue}}return{type:"blockquote",raw:s,tokens:i,text:r}}}list(t){let e=this.rules.block.list.exec(t);if(e){let n=e[1].trim(),s=n.length>1,r={type:"list",raw:"",ordered:s,start:s?+n.slice(0,-1):"",loose:!1,items:[]};n=s?`\\\\d{1,9}\\\\${n.slice(-1)}`:`\\\\${n}`,this.options.pedantic&&(n=s?n:"[*+-]");let i=this.rules.other.listItemRegex(n),a=!1;for(;t;){let o=!1,c="",u="";if(!(e=i.exec(t))||this.rules.block.hr.test(t))break;c=e[0],t=t.substring(c.length);let h=mt(e[2].split(`\n`,1)[0],e[1].length),p=t.split(`\n`,1)[0],d=!h.trim(),f=0;if(this.options.pedantic?(f=2,u=h.trimStart()):d?f=e[1].length+1:(f=h.search(this.rules.other.nonSpaceChar),f=f>4?1:f,u=h.slice(f),f+=e[1].length),d&&this.rules.other.blankLine.test(p)&&(c+=p+`\n`,t=t.substring(p.length+1),o=!0),!o){let m=this.rules.other.nextBulletRegex(f),w=this.rules.other.hrRegex(f),y=this.rules.other.fencesBeginRegex(f),L=this.rules.other.headingBeginRegex(f),G=this.rules.other.htmlBeginRegex(f),A=this.rules.other.blockquoteBeginRegex(f);for(;t;){let b=t.split(`\n`,1)[0],T;if(p=b,this.options.pedantic?(p=p.replace(this.rules.other.listReplaceNesting," "),T=p):T=p.replace(this.rules.other.tabCharGlobal," "),y.test(p)||L.test(p)||G.test(p)||A.test(p)||m.test(p)||w.test(p))break;if(T.search(this.rules.other.nonSpaceChar)>=f||!p.trim())u+=`\n`+T.slice(f);else{if(d||h.replace(this.rules.other.tabCharGlobal," ").search(this.rules.other.nonSpaceChar)>=4||y.test(h)||L.test(h)||w.test(h))break;u+=`\n`+p}d=!p.trim(),c+=b+`\n`,t=t.substring(b.length+1),h=T.slice(f)}}r.loose||(a?r.loose=!0:this.rules.other.doubleBlankLine.test(c)&&(a=!0)),r.items.push({type:"list_item",raw:c,task:!!this.options.gfm&&this.rules.other.listIsTask.test(u),loose:!1,text:u,tokens:[]}),r.raw+=c}let l=r.items.at(-1);if(l)l.raw=l.raw.trimEnd(),l.text=l.text.trimEnd();else return;r.raw=r.raw.trimEnd();for(let o of r.items){this.lexer.state.top=!1,o.tokens=this.lexer.blockTokens(o.text,[]);let c=o.tokens[0];if(o.task&&(c?.type==="text"||c?.type==="paragraph")){o.text=o.text.replace(this.rules.other.listReplaceTask,""),c.raw=c.raw.replace(this.rules.other.listReplaceTask,""),c.text=c.text.replace(this.rules.other.listReplaceTask,"");for(let h=this.lexer.inlineQueue.length-1;h>=0;h--)if(this.rules.other.listIsTask.test(this.lexer.inlineQueue[h].src)){this.lexer.inlineQueue[h].src=this.lexer.inlineQueue[h].src.replace(this.rules.other.listReplaceTask,"");break}let u=this.rules.other.listTaskCheckbox.exec(o.raw);if(u){let h={type:"checkbox",raw:u[0]+" ",checked:u[0]!=="[ ]"};o.checked=h.checked,r.loose?o.tokens[0]&&["paragraph","text"].includes(o.tokens[0].type)&&"tokens"in o.tokens[0]&&o.tokens[0].tokens?(o.tokens[0].raw=h.raw+o.tokens[0].raw,o.tokens[0].text=h.raw+o.tokens[0].text,o.tokens[0].tokens.unshift(h)):o.tokens.unshift({type:"paragraph",raw:h.raw,text:h.raw,tokens:[h]}):o.tokens.unshift(h)}}else o.task&&(o.task=!1);if(!r.loose){let u=o.tokens.filter(p=>p.type==="space"),h=u.length>0&&u.some(p=>this.rules.other.anyLine.test(p.raw));r.loose=h}}if(r.loose)for(let o of r.items){o.loose=!0;for(let c of o.tokens)c.type==="text"&&(c.type="paragraph")}return r}}html(t){let e=this.rules.block.html.exec(t);if(e){let n=pe(e[0]);return{type:"html",block:!0,raw:n,pre:e[1]==="pre"||e[1]==="script"||e[1]==="style",text:n}}}def(t){let e=this.rules.block.def.exec(t);if(e){let n=e[1].toLowerCase().replace(this.rules.other.multipleSpaceGlobal," "),s=e[2]?e[2].replace(this.rules.other.hrefBrackets,"$1").replace(this.rules.inline.anyPunctuation,"$1"):"",r=e[3]?e[3].substring(1,e[3].length-1).replace(this.rules.inline.anyPunctuation,"$1"):e[3];return{type:"def",tag:n,raw:z(e[0],`\n`),href:s,title:r}}}table(t){let e=this.rules.block.table.exec(t);if(!e||!this.rules.other.tableDelimiter.test(e[2]))return;let n=ue(e[1]),s=e[2].replace(this.rules.other.tableAlignChars,"").split("|"),r=e[3]?.trim()?e[3].replace(this.rules.other.tableRowBlankLine,"").split(`\n`):[],i={type:"table",raw:z(e[0],`\n`),header:[],align:[],rows:[]};if(n.length===s.length){for(let a of s)this.rules.other.tableAlignRight.test(a)?i.align.push("right"):this.rules.other.tableAlignCenter.test(a)?i.align.push("center"):this.rules.other.tableAlignLeft.test(a)?i.align.push("left"):i.align.push(null);for(let a=0;a<n.length;a++)i.header.push({text:n[a],tokens:this.lexer.inline(n[a]),header:!0,align:i.align[a]});for(let a of r)i.rows.push(ue(a,i.header.length).map((l,o)=>({text:l,tokens:this.lexer.inline(l),header:!1,align:i.align[o]})));return i}}lheading(t){let e=this.rules.block.lheading.exec(t);if(e){let n=e[1].trim();return{type:"heading",raw:z(e[0],`\n`),depth:e[2].charAt(0)==="="?1:2,text:n,tokens:this.lexer.inline(n)}}}paragraph(t){let e=this.rules.block.paragraph.exec(t);if(e){let n=e[1].charAt(e[1].length-1)===`\n`?e[1].slice(0,-1):e[1];return{type:"paragraph",raw:e[0],text:n,tokens:this.lexer.inline(n)}}}text(t){let e=this.rules.block.text.exec(t);if(e)return{type:"text",raw:e[0],text:e[0],tokens:this.lexer.inline(e[0])}}escape(t){let e=this.rules.inline.escape.exec(t);if(e)return{type:"escape",raw:e[0],text:e[1]}}tag(t){let e=this.rules.inline.tag.exec(t);if(e)return!this.lexer.state.inLink&&this.rules.other.startATag.test(e[0])?this.lexer.state.inLink=!0:this.lexer.state.inLink&&this.rules.other.endATag.test(e[0])&&(this.lexer.state.inLink=!1),!this.lexer.state.inRawBlock&&this.rules.other.startPreScriptTag.test(e[0])?this.lexer.state.inRawBlock=!0:this.lexer.state.inRawBlock&&this.rules.other.endPreScriptTag.test(e[0])&&(this.lexer.state.inRawBlock=!1),{type:"html",raw:e[0],inLink:this.lexer.state.inLink,inRawBlock:this.lexer.state.inRawBlock,block:!1,text:e[0]}}link(t){let e=this.rules.inline.link.exec(t);if(e){let n=e[2].trim();if(!this.options.pedantic&&this.rules.other.startAngleBracket.test(n)){if(!this.rules.other.endAngleBracket.test(n))return;let i=z(n.slice(0,-1),"\\\\");if((n.length-i.length)%2===0)return}else{let i=bt(e[2],"()");if(i===-2)return;if(i>-1){let a=(e[0].indexOf("!")===0?5:4)+e[1].length+i;e[2]=e[2].substring(0,i),e[0]=e[0].substring(0,a).trim(),e[3]=""}}let s=e[2],r="";if(this.options.pedantic){let i=this.rules.other.pedanticHrefTitle.exec(s);i&&(s=i[1],r=i[3])}else r=e[3]?e[3].slice(1,-1):"";return s=s.trim(),this.rules.other.startAngleBracket.test(s)&&(this.options.pedantic&&!this.rules.other.endAngleBracket.test(n)?s=s.slice(1):s=s.slice(1,-1)),ge(e,{href:s&&s.replace(this.rules.inline.anyPunctuation,"$1"),title:r&&r.replace(this.rules.inline.anyPunctuation,"$1")},e[0],this.lexer,this.rules)}}reflink(t,e){let n;if((n=this.rules.inline.reflink.exec(t))||(n=this.rules.inline.nolink.exec(t))){let s=(n[2]||n[1]).replace(this.rules.other.multipleSpaceGlobal," "),r=e[s.toLowerCase()];if(!r){let i=n[0].charAt(0);return{type:"text",raw:i,text:i}}return ge(n,r,n[0],this.lexer,this.rules)}}emStrong(t,e,n=""){let s=this.rules.inline.emStrongLDelim.exec(t);if(!(!s||!s[1]&&!s[2]&&!s[3]&&!s[4]||s[4]&&n.match(this.rules.other.unicodeAlphaNumeric))&&(!(s[1]||s[3])||!n||this.rules.inline.punctuation.exec(n))){let r=[...s[0]].length-1,i,a,l=r,o=0,c=s[0][0]==="*"?this.rules.inline.emStrongRDelimAst:this.rules.inline.emStrongRDelimUnd;for(c.lastIndex=0,e=e.slice(-1*t.length+r);(s=c.exec(e))!==null;){if(i=s[1]||s[2]||s[3]||s[4]||s[5]||s[6],!i)continue;if(a=[...i].length,s[3]||s[4]){l+=a;continue}else if((s[5]||s[6])&&r%3&&!((r+a)%3)){o+=a;continue}if(l-=a,l>0)continue;a=Math.min(a,a+l+o);let u=[...s[0]][0].length,h=t.slice(0,r+s.index+u+a);if(Math.min(r,a)%2){let d=h.slice(1,-1);return{type:"em",raw:h,text:d,tokens:this.lexer.inlineTokens(d)}}let p=h.slice(2,-2);return{type:"strong",raw:h,text:p,tokens:this.lexer.inlineTokens(p)}}}}codespan(t){let e=this.rules.inline.code.exec(t);if(e){let n=e[2].replace(this.rules.other.newLineCharGlobal," "),s=this.rules.other.nonSpaceChar.test(n),r=this.rules.other.startingSpaceChar.test(n)&&this.rules.other.endingSpaceChar.test(n);return s&&r&&(n=n.substring(1,n.length-1)),{type:"codespan",raw:e[0],text:n}}}br(t){let e=this.rules.inline.br.exec(t);if(e)return{type:"br",raw:e[0]}}del(t,e,n=""){let s=this.rules.inline.delLDelim.exec(t);if(s&&(!s[1]||!n||this.rules.inline.punctuation.exec(n))){let r=[...s[0]].length-1,i,a,l=r,o=this.rules.inline.delRDelim;for(o.lastIndex=0,e=e.slice(-1*t.length+r);(s=o.exec(e))!==null;){if(i=s[1]||s[2]||s[3]||s[4]||s[5]||s[6],!i||(a=[...i].length,a!==r))continue;if(s[3]||s[4]){l+=a;continue}if(l-=a,l>0)continue;a=Math.min(a,a+l);let c=[...s[0]][0].length,u=t.slice(0,r+s.index+c+a),h=u.slice(r,-r);return{type:"del",raw:u,text:h,tokens:this.lexer.inlineTokens(h)}}}}autolink(t){let e=this.rules.inline.autolink.exec(t);if(e){let n,s;return e[2]==="@"?(n=e[1],s="mailto:"+n):(n=e[1],s=n),{type:"link",raw:e[0],text:n,href:s,tokens:[{type:"text",raw:n,text:n}]}}}url(t){let e;if(e=this.rules.inline.url.exec(t)){let n,s;if(e[2]==="@")n=e[0],s="mailto:"+n;else{let r;do r=e[0],e[0]=this.rules.inline._backpedal.exec(e[0])?.[0]??"";while(r!==e[0]);n=e[0],e[1]==="www."?s="http://"+e[0]:s=e[0]}return{type:"link",raw:e[0],text:n,href:s,tokens:[{type:"text",raw:n,text:n}]}}}inlineText(t){let e=this.rules.inline.text.exec(t);if(e){let n=this.lexer.state.inRawBlock;return{type:"text",raw:e[0],text:e[0],escaped:n}}}},R=class X{tokens;options;state;inlineQueue;tokenizer;constructor(e){this.tokens=[],this.tokens.links=Object.create(null),this.options=e||_,this.options.tokenizer=this.options.tokenizer||new Z,this.tokenizer=this.options.tokenizer,this.tokenizer.options=this.options,this.tokenizer.lexer=this,this.inlineQueue=[],this.state={inLink:!1,inRawBlock:!1,top:!0};let n={other:x,block:D.normal,inline:B.normal};this.options.pedantic?(n.block=D.pedantic,n.inline=B.pedantic):this.options.gfm&&(n.block=D.gfm,this.options.breaks?n.inline=B.breaks:n.inline=B.gfm),this.tokenizer.rules=n}static get rules(){return{block:D,inline:B}}static lex(e,n){return new X(n).lex(e)}static lexInline(e,n){return new X(n).inlineTokens(e)}lex(e){e=e.replace(x.carriageReturn,`\n`),this.blockTokens(e,this.tokens);for(let n=0;n<this.inlineQueue.length;n++){let s=this.inlineQueue[n];this.inlineTokens(s.src,s.tokens)}return this.inlineQueue=[],this.tokens}blockTokens(e,n=[],s=!1){this.tokenizer.lexer=this,this.options.pedantic&&(e=e.replace(x.tabCharGlobal," ").replace(x.spaceLine,""));let r=1/0;for(;e;){if(e.length<r)r=e.length;else{this.infiniteLoopError(e.charCodeAt(0));break}let i;if(this.options.extensions?.block?.some(l=>(i=l.call({lexer:this},e,n))?(e=e.substring(i.raw.length),n.push(i),!0):!1))continue;if(i=this.tokenizer.space(e)){e=e.substring(i.raw.length);let l=n.at(-1);i.raw.length===1&&l!==void 0?l.raw+=`\n`:n.push(i);continue}if(i=this.tokenizer.code(e)){e=e.substring(i.raw.length);let l=n.at(-1);l?.type==="paragraph"||l?.type==="text"?(l.raw+=(l.raw.endsWith(`\n`)?"":`\n`)+i.raw,l.text+=`\n`+i.text,this.inlineQueue.at(-1).src=l.text):n.push(i);continue}if(i=this.tokenizer.fences(e)){e=e.substring(i.raw.length),n.push(i);continue}if(i=this.tokenizer.heading(e)){e=e.substring(i.raw.length),n.push(i);continue}if(i=this.tokenizer.hr(e)){e=e.substring(i.raw.length),n.push(i);continue}if(i=this.tokenizer.blockquote(e)){e=e.substring(i.raw.length),n.push(i);continue}if(i=this.tokenizer.list(e)){e=e.substring(i.raw.length),n.push(i);continue}if(i=this.tokenizer.html(e)){e=e.substring(i.raw.length),n.push(i);continue}if(i=this.tokenizer.def(e)){e=e.substring(i.raw.length);let l=n.at(-1);l?.type==="paragraph"||l?.type==="text"?(l.raw+=(l.raw.endsWith(`\n`)?"":`\n`)+i.raw,l.text+=`\n`+i.raw,this.inlineQueue.at(-1).src=l.text):this.tokens.links[i.tag]||(this.tokens.links[i.tag]={href:i.href,title:i.title},n.push(i));continue}if(i=this.tokenizer.table(e)){e=e.substring(i.raw.length),n.push(i);continue}if(i=this.tokenizer.lheading(e)){e=e.substring(i.raw.length),n.push(i);continue}let a=e;if(this.options.extensions?.startBlock){let l=1/0,o=e.slice(1),c;this.options.extensions.startBlock.forEach(u=>{c=u.call({lexer:this},o),typeof c=="number"&&c>=0&&(l=Math.min(l,c))}),l<1/0&&l>=0&&(a=e.substring(0,l+1))}if(this.state.top&&(i=this.tokenizer.paragraph(a))){let l=n.at(-1);s&&l?.type==="paragraph"?(l.raw+=(l.raw.endsWith(`\n`)?"":`\n`)+i.raw,l.text+=`\n`+i.text,this.inlineQueue.pop(),this.inlineQueue.at(-1).src=l.text):n.push(i),s=a.length!==e.length,e=e.substring(i.raw.length);continue}if(i=this.tokenizer.text(e)){e=e.substring(i.raw.length);let l=n.at(-1);l?.type==="text"?(l.raw+=(l.raw.endsWith(`\n`)?"":`\n`)+i.raw,l.text+=`\n`+i.text,this.inlineQueue.pop(),this.inlineQueue.at(-1).src=l.text):n.push(i);continue}if(e){this.infiniteLoopError(e.charCodeAt(0));break}}return this.state.top=!0,n}inline(e,n=[]){return this.inlineQueue.push({src:e,tokens:n}),n}inlineTokens(e,n=[]){this.tokenizer.lexer=this;let s=e;if(this.tokens.links){let l=Object.keys(this.tokens.links);l.length>0&&(s=s.replace(this.tokenizer.rules.inline.reflinkSearch,o=>l.includes(o.slice(o.lastIndexOf("[")+1,-1))?"["+"a".repeat(o.length-2)+"]":o))}s=s.replace(this.tokenizer.rules.inline.anyPunctuation,"++"),s=s.replace(this.tokenizer.rules.inline.blockSkip,(l,o,c)=>{let u=c?c.length:0;return l.slice(0,u)+"["+"a".repeat(l.length-u-2)+"]"}),s=this.options.hooks?.emStrongMask?.call({lexer:this},s)??s;let r=!1,i="",a=1/0;for(;e;){if(e.length<a)a=e.length;else{this.infiniteLoopError(e.charCodeAt(0));break}r||(i=""),r=!1;let l;if(this.options.extensions?.inline?.some(c=>(l=c.call({lexer:this},e,n))?(e=e.substring(l.raw.length),n.push(l),!0):!1))continue;if(l=this.tokenizer.escape(e)){e=e.substring(l.raw.length),n.push(l);continue}if(l=this.tokenizer.tag(e)){e=e.substring(l.raw.length),n.push(l);continue}if(l=this.tokenizer.link(e)){e=e.substring(l.raw.length),n.push(l);continue}if(l=this.tokenizer.reflink(e,this.tokens.links)){e=e.substring(l.raw.length);let c=n.at(-1);l.type==="text"&&c?.type==="text"?(c.raw+=l.raw,c.text+=l.text):n.push(l);continue}if(l=this.tokenizer.emStrong(e,s,i)){e=e.substring(l.raw.length),n.push(l);continue}if(l=this.tokenizer.codespan(e)){e=e.substring(l.raw.length),n.push(l);continue}if(l=this.tokenizer.br(e)){e=e.substring(l.raw.length),n.push(l);continue}if(l=this.tokenizer.del(e,s,i)){e=e.substring(l.raw.length),n.push(l);continue}if(l=this.tokenizer.autolink(e)){e=e.substring(l.raw.length),n.push(l);continue}if(!this.state.inLink&&(l=this.tokenizer.url(e))){e=e.substring(l.raw.length),n.push(l);continue}let o=e;if(this.options.extensions?.startInline){let c=1/0,u=e.slice(1),h;this.options.extensions.startInline.forEach(p=>{h=p.call({lexer:this},u),typeof h=="number"&&h>=0&&(c=Math.min(c,h))}),c<1/0&&c>=0&&(o=e.substring(0,c+1))}if(l=this.tokenizer.inlineText(o)){e=e.substring(l.raw.length),l.raw.slice(-1)!=="_"&&(i=l.raw.slice(-1)),r=!0;let c=n.at(-1);c?.type==="text"?(c.raw+=l.raw,c.text+=l.text):n.push(l);continue}if(e){this.infiniteLoopError(e.charCodeAt(0));break}}return n}infiniteLoopError(e){let n="Infinite loop on byte: "+e;if(this.options.silent)console.error(n);else throw new Error(n)}},N=class{options;parser;constructor(t){this.options=t||_}space(t){return""}code({text:t,lang:e,escaped:n}){let s=(e||"").match(x.notSpaceStart)?.[0],r=t.replace(x.endingNewline,"")+`\n`;return s?\'<pre><code class="language-\'+S(s)+\'">\'+(n?r:S(r,!0))+`</code></pre>\n`:"<pre><code>"+(n?r:S(r,!0))+`</code></pre>\n`}blockquote({tokens:t}){return`<blockquote>\n${this.parser.parse(t)}</blockquote>\n`}html({text:t}){return t}def(t){return""}heading({tokens:t,depth:e}){return`<h${e}>${this.parser.parseInline(t)}</h${e}>\n`}hr(t){return`<hr>\n`}list(t){let e=t.ordered,n=t.start,s="";for(let a=0;a<t.items.length;a++){let l=t.items[a];s+=this.listitem(l)}let r=e?"ol":"ul",i=e&&n!==1?\' start="\'+n+\'"\':"";return"<"+r+i+`>\n`+s+"</"+r+`>\n`}listitem(t){return`<li>${this.parser.parse(t.tokens)}</li>\n`}checkbox({checked:t}){return"<input "+(t?\'checked="" \':"")+\'disabled="" type="checkbox"> \'}paragraph({tokens:t}){return`<p>${this.parser.parseInline(t)}</p>\n`}table(t){let e="",n="";for(let r=0;r<t.header.length;r++)n+=this.tablecell(t.header[r]);e+=this.tablerow({text:n});let s="";for(let r=0;r<t.rows.length;r++){let i=t.rows[r];n="";for(let a=0;a<i.length;a++)n+=this.tablecell(i[a]);s+=this.tablerow({text:n})}return s&&(s=`<tbody>${s}</tbody>`),`<table>\n<thead>\n`+e+`</thead>\n`+s+`</table>\n`}tablerow({text:t}){return`<tr>\n${t}</tr>\n`}tablecell(t){let e=this.parser.parseInline(t.tokens),n=t.header?"th":"td";return(t.align?`<${n} align="${t.align}">`:`<${n}>`)+e+`</${n}>\n`}strong({tokens:t}){return`<strong>${this.parser.parseInline(t)}</strong>`}em({tokens:t}){return`<em>${this.parser.parseInline(t)}</em>`}codespan({text:t}){return`<code>${S(t,!0)}</code>`}br(t){return"<br>"}del({tokens:t}){return`<del>${this.parser.parseInline(t)}</del>`}link({href:t,title:e,tokens:n}){let s=this.parser.parseInline(n),r=he(t);if(r===null)return s;t=r;let i=\'<a href="\'+t+\'"\';return e&&(i+=\' title="\'+S(e)+\'"\'),i+=">"+s+"</a>",i}image({href:t,title:e,text:n,tokens:s}){s&&(n=this.parser.parseInline(s,this.parser.textRenderer));let r=he(t);if(r===null)return S(n);t=r;let i=`<img src="${t}" alt="${S(n)}"`;return e&&(i+=` title="${S(e)}"`),i+=">",i}text(t){return"tokens"in t&&t.tokens?this.parser.parseInline(t.tokens):"escaped"in t&&t.escaped?t.text:S(t.text)}},se=class{strong({text:t}){return t}em({text:t}){return t}codespan({text:t}){return t}del({text:t}){return t}html({text:t}){return t}text({text:t}){return t}link({text:t}){return""+t}image({text:t}){return""+t}br(){return""}checkbox({raw:t}){return t}},$=class U{options;renderer;textRenderer;constructor(e){this.options=e||_,this.options.renderer=this.options.renderer||new N,this.renderer=this.options.renderer,this.renderer.options=this.options,this.renderer.parser=this,this.textRenderer=new se}static parse(e,n){return new U(n).parse(e)}static parseInline(e,n){return new U(n).parseInline(e)}parse(e){this.renderer.parser=this;let n="";for(let s=0;s<e.length;s++){let r=e[s];if(this.options.extensions?.renderers?.[r.type]){let a=r,l=this.options.extensions.renderers[a.type].call({parser:this},a);if(l!==!1||!["space","hr","heading","code","table","blockquote","list","html","def","paragraph","text"].includes(a.type)){n+=l||"";continue}}let i=r;switch(i.type){case"space":{n+=this.renderer.space(i);break}case"hr":{n+=this.renderer.hr(i);break}case"heading":{n+=this.renderer.heading(i);break}case"code":{n+=this.renderer.code(i);break}case"table":{n+=this.renderer.table(i);break}case"blockquote":{n+=this.renderer.blockquote(i);break}case"list":{n+=this.renderer.list(i);break}case"checkbox":{n+=this.renderer.checkbox(i);break}case"html":{n+=this.renderer.html(i);break}case"def":{n+=this.renderer.def(i);break}case"paragraph":{n+=this.renderer.paragraph(i);break}case"text":{n+=this.renderer.text(i);break}default:{let a=\'Token with "\'+i.type+\'" type was not found.\';if(this.options.silent)return console.error(a),"";throw new Error(a)}}}return n}parseInline(e,n=this.renderer){this.renderer.parser=this;let s="";for(let r=0;r<e.length;r++){let i=e[r];if(this.options.extensions?.renderers?.[i.type]){let l=this.options.extensions.renderers[i.type].call({parser:this},i);if(l!==!1||!["escape","html","link","image","strong","em","codespan","br","del","text"].includes(i.type)){s+=l||"";continue}}let a=i;switch(a.type){case"escape":{s+=n.text(a);break}case"html":{s+=n.html(a);break}case"link":{s+=n.link(a);break}case"image":{s+=n.image(a);break}case"checkbox":{s+=n.checkbox(a);break}case"strong":{s+=n.strong(a);break}case"em":{s+=n.em(a);break}case"codespan":{s+=n.codespan(a);break}case"br":{s+=n.br(a);break}case"del":{s+=n.del(a);break}case"text":{s+=n.text(a);break}default:{let l=\'Token with "\'+a.type+\'" type was not found.\';if(this.options.silent)return console.error(l),"";throw new Error(l)}}}return s}},q=class{options;block;constructor(t){this.options=t||_}static passThroughHooks=new Set(["preprocess","postprocess","processAllTokens","emStrongMask"]);static passThroughHooksRespectAsync=new Set(["preprocess","postprocess","processAllTokens"]);preprocess(t){return t}postprocess(t){return t}processAllTokens(t){return t}emStrongMask(t){return t}provideLexer(t=this.block){return t?R.lex:R.lexInline}provideParser(t=this.block){return t?$.parse:$.parseInline}},yt=class{defaults=V();options=this.setOptions;parse=this.parseMarkdown(!0);parseInline=this.parseMarkdown(!1);Parser=$;Renderer=N;TextRenderer=se;Lexer=R;Tokenizer=Z;Hooks=q;constructor(...t){this.use(...t)}walkTokens(t,e){let n=[];for(let s of t)switch(n=n.concat(e.call(this,s)),s.type){case"table":{let r=s;for(let i of r.header)n=n.concat(this.walkTokens(i.tokens,e));for(let i of r.rows)for(let a of i)n=n.concat(this.walkTokens(a.tokens,e));break}case"list":{let r=s;n=n.concat(this.walkTokens(r.items,e));break}default:{let r=s;this.defaults.extensions?.childTokens?.[r.type]?this.defaults.extensions.childTokens[r.type].forEach(i=>{let a=r[i].flat(1/0);n=n.concat(this.walkTokens(a,e))}):r.tokens&&(n=n.concat(this.walkTokens(r.tokens,e)))}}return n}use(...t){let e=this.defaults.extensions||{renderers:{},childTokens:{}};return t.forEach(n=>{let s={...n};if(s.async=this.defaults.async||s.async||!1,n.extensions&&(n.extensions.forEach(r=>{if(!r.name)throw new Error("extension name required");if("renderer"in r){let i=e.renderers[r.name];i?e.renderers[r.name]=function(...a){let l=r.renderer.apply(this,a);return l===!1&&(l=i.apply(this,a)),l}:e.renderers[r.name]=r.renderer}if("tokenizer"in r){if(!r.level||r.level!=="block"&&r.level!=="inline")throw new Error("extension level must be \'block\' or \'inline\'");let i=e[r.level];i?i.unshift(r.tokenizer):e[r.level]=[r.tokenizer],r.start&&(r.level==="block"?e.startBlock?e.startBlock.push(r.start):e.startBlock=[r.start]:r.level==="inline"&&(e.startInline?e.startInline.push(r.start):e.startInline=[r.start]))}"childTokens"in r&&r.childTokens&&(e.childTokens[r.name]=r.childTokens)}),s.extensions=e),n.renderer){let r=this.defaults.renderer||new N(this.defaults);for(let i in n.renderer){if(!(i in r))throw new Error(`renderer \'${i}\' does not exist`);if(["options","parser"].includes(i))continue;let a=i,l=n.renderer[a],o=r[a];r[a]=(...c)=>{let u=l.apply(r,c);return u===!1&&(u=o.apply(r,c)),u||""}}s.renderer=r}if(n.tokenizer){let r=this.defaults.tokenizer||new Z(this.defaults);for(let i in n.tokenizer){if(!(i in r))throw new Error(`tokenizer \'${i}\' does not exist`);if(["options","rules","lexer"].includes(i))continue;let a=i,l=n.tokenizer[a],o=r[a];r[a]=(...c)=>{let u=l.apply(r,c);return u===!1&&(u=o.apply(r,c)),u}}s.tokenizer=r}if(n.hooks){let r=this.defaults.hooks||new q;for(let i in n.hooks){if(!(i in r))throw new Error(`hook \'${i}\' does not exist`);if(["options","block"].includes(i))continue;let a=i,l=n.hooks[a],o=r[a];q.passThroughHooks.has(i)?r[a]=c=>{if(this.defaults.async&&q.passThroughHooksRespectAsync.has(i))return(async()=>{let h=await l.call(r,c);return o.call(r,h)})();let u=l.call(r,c);return o.call(r,u)}:r[a]=(...c)=>{if(this.defaults.async)return(async()=>{let h=await l.apply(r,c);return h===!1&&(h=await o.apply(r,c)),h})();let u=l.apply(r,c);return u===!1&&(u=o.apply(r,c)),u}}s.hooks=r}if(n.walkTokens){let r=this.defaults.walkTokens,i=n.walkTokens;s.walkTokens=function(a){let l=[];return l.push(i.call(this,a)),r&&(l=l.concat(r.call(this,a))),l}}this.defaults={...this.defaults,...s}}),this}setOptions(t){return this.defaults={...this.defaults,...t},this}lexer(t,e){return R.lex(t,e??this.defaults)}parser(t,e){return $.parse(t,e??this.defaults)}parseMarkdown(t){return(e,n)=>{let s={...n},r={...this.defaults,...s},i=this.onError(!!r.silent,!!r.async);if(this.defaults.async===!0&&s.async===!1)return i(new Error("marked(): The async option was set to true by an extension. Remove async: false from the parse options object to return a Promise."));if(typeof e>"u"||e===null)return i(new Error("marked(): input parameter is undefined or null"));if(typeof e!="string")return i(new Error("marked(): input parameter is of type "+Object.prototype.toString.call(e)+", string expected"));if(r.hooks&&(r.hooks.options=r,r.hooks.block=t),r.async)return(async()=>{let a=r.hooks?await r.hooks.preprocess(e):e,l=await(r.hooks?await r.hooks.provideLexer(t):t?R.lex:R.lexInline)(a,r),o=r.hooks?await r.hooks.processAllTokens(l):l;r.walkTokens&&await Promise.all(this.walkTokens(o,r.walkTokens));let c=await(r.hooks?await r.hooks.provideParser(t):t?$.parse:$.parseInline)(o,r);return r.hooks?await r.hooks.postprocess(c):c})().catch(i);try{r.hooks&&(e=r.hooks.preprocess(e));let a=(r.hooks?r.hooks.provideLexer(t):t?R.lex:R.lexInline)(e,r);r.hooks&&(a=r.hooks.processAllTokens(a)),r.walkTokens&&this.walkTokens(a,r.walkTokens);let l=(r.hooks?r.hooks.provideParser(t):t?$.parse:$.parseInline)(a,r);return r.hooks&&(l=r.hooks.postprocess(l)),l}catch(a){return i(a)}}}onError(t,e){return n=>{if(n.message+=`\nPlease report this to https://github.com/markedjs/marked.`,t){let s="<p>An error occurred:</p><pre>"+S(n.message+"",!0)+"</pre>";return e?Promise.resolve(s):s}if(e)return Promise.reject(n);throw n}}},I=new yt;function g(t,e){return I.parse(t,e)}g.options=g.setOptions=function(t){return I.setOptions(t),g.defaults=I.defaults,ke(g.defaults),g};g.getDefaults=V;g.defaults=_;g.use=function(...t){return I.use(...t),g.defaults=I.defaults,ke(g.defaults),g};g.walkTokens=function(t,e){return I.walkTokens(t,e)};g.parseInline=I.parseInline;g.Parser=$;g.parser=$.parse;g.Renderer=N;g.TextRenderer=se;g.Lexer=R;g.lexer=R.lex;g.Tokenizer=Z;g.Hooks=q;g.parse=g;var _t=g.options,Et=g.setOptions,Pt=g.use,Mt=g.walkTokens,Bt=g.parseInline;var qt=$.parse,vt=R.lex;function Se(t,e,n){let s=0;for(let r=e;r<n;r++)s+=t[r].raw.length;return s}function Rt(t,e){let n=t;return n.links=e,n}var $t=/^ {0,3}\\$\\$/m;function Le(t){return t.includes("$$")===!1?!1:$t.test(t)}function Tt(t,e){return t[e-2]?.type!=="list"?!0:e+1<t.length}function ze(t,e){for(let n=t.length-2;n>=e;n--)if(t[n].type==="space"&&Tt(t,n+1)!==!1)return n+1;return-1}function Ae(t){let e=t.links;if(!e)return!1;for(let n in e)return!0;return!1}function Ce(t,e,n,s,r){let i=r;for(let a=e;a<n;a++){let l=t[a].raw;if(s.startsWith(l,i)===!1)return!1;i+=l.length}return!0}function j(t,e,n){return{source:t,tail:t,tokens:e,stableCount:0,stableOffset:0,degraded:!0,degradedReason:n}}function Te(t,e){return{source:t,tail:t,tokens:e,stableCount:0,stableOffset:0,degraded:!1,degradedReason:null}}function St(t,e){if(Ae(e))return j(t,e,"link-definition");if(t.includes("\\r"))return j(t,e,"carriage-return");if(Le(t))return j(t,e,"block-math");let n=ze(e,1);if(n<0||Ce(e,0,n,t,0)===!1)return Te(t,e);let s=Se(e,0,n);return{source:t,tail:t.slice(s),tokens:e,stableCount:n,stableOffset:s,degraded:!1,degradedReason:null}}function ie(t){let e=g.lexer(t);return{tokens:e,cache:St(t,e),charsLexed:t.length,reusedTokens:0}}function H(t,e){let n=g.lexer(t);return{tokens:n,cache:j(t,n,e),charsLexed:t.length,reusedTokens:0}}function Ie(t,e){let n=t.source+e;if(t.degraded)return H(n,t.degradedReason??"link-definition");if(e.includes("\\r"))return H(n,"carriage-return");if(t.stableCount===0)return ie(n);let s=t.tail+e;if(Le(s))return H(n,"block-math");let r=g.lexer(s);if(Ae(r))return H(n,"link-definition");let i=t.tokens.slice(0,t.stableCount),a=Rt([...i,...r],r.links),l=t.stableCount,o=t.stableOffset,c=s,u=ze(a,t.stableCount+1);if(u>t.stableCount&&Ce(a,t.stableCount,u,s,0)){let h=Se(a,t.stableCount,u);l=u,o=t.stableOffset+h,c=s.slice(h)}return{tokens:a,cache:{source:n,tail:c,tokens:a,stableCount:l,stableOffset:o,degraded:!1,degradedReason:null},charsLexed:s.length,reusedTokens:t.stableCount}}var _e="([^\\\\]\\\\s]+)",Lt=new RegExp(`^\\\\[\\\\^${_e}\\\\]`),zt=new RegExp(`^ {0,3}\\\\[\\\\^${_e}\\\\]:[ \\\\t]*([^\\\\n]*)(?:\\\\n|$)`),Ee=[{name:"footnoteRef",level:"inline",tokenizer(t){let e=Lt.exec(t);if(e)return{type:"footnoteRef",raw:e[0],label:e[1]}},renderer(t){return t.raw}},{name:"footnoteDef",level:"block",tokenizer(t){let e=zt.exec(t);if(e)return{type:"footnoteDef",raw:e[0],label:e[1],body:e[2]}},renderer(t){return t.raw}}];var At=0;function Ct(t){if(typeof t!="string"||typeof performance.mark!="function"||typeof performance.measure!="function")return null;let e=At++,n={name:t,startMark:`${t}:start:${e}`,endMark:`${t}:end:${e}`};try{return performance.mark(n.startMark),n}catch{return null}}function It(t){if(t)try{performance.mark(t.endMark),performance.measure(t.name,t.startMark,t.endMark)}catch{}finally{try{performance.clearMarks?.(t.startMark),performance.clearMarks?.(t.endMark)}catch{}}}g.use({extensions:[...Ee,{name:"blockMath",level:"block",start(t){return t.match(/^ {0,3}\\$\\$/m)?.index},tokenizer(t){let e=/^ {0,3}\\$\\$([\\s\\S]+?)\\$\\$[ \\t]*(?:\\n|$)/.exec(t);if(e)return{type:"blockMath",raw:e[0],text:e[1].trim()}},renderer(t){return t.raw}},{name:"inlineMath",level:"inline",start(t){return t.match(/(?<![\\\\$])\\$(?![$\\s])/)?.index},tokenizer(t){let e=/^\\$(?![$\\s\\d])((?:\\\\\\$|[^$\\n])*?)(?<!\\s)\\$(?!\\d)/.exec(t);if(e)return{type:"inlineMath",raw:e[0],text:e[1].trim()}},renderer(t){return t.raw}}]});var M=new Map;self.onmessage=t=>{let e=t.data;if(typeof e!="object"||e===null)return;let{id:n,text:s,append:r,expectedLength:i,oldRaws:a,instance:l,baseVersion:o,dispose:c,userTimingName:u}=e;if(c===!0){typeof l=="string"&&M.delete(l);return}let h=typeof l=="string"?l:null,p=typeof o=="number"?o:null,d,f=null,m=null;if(typeof r=="string"){if(h===null||p===null){self.postMessage({id:n,needResync:!0});return}let w=M.get(h);if(!w||w.version!==p){self.postMessage({id:n,needResync:!0});return}if(typeof i=="number"&&w.lex.source.length+r.length!==i){M.delete(h),self.postMessage({id:n,needResync:!0});return}let y=w.lex;d=()=>Ie(y,r),m=y.tokens}else if(typeof s=="string"){let w=s;if(d=()=>ie(w),Array.isArray(a))f=a;else if(h!==null&&p!==null){let y=M.get(h);if(y&&y.version===p)m=y.lex.tokens;else{self.postMessage({id:n,needResync:!0});return}}}else return;try{let w=typeof u=="string"?Ct(u):null,y=performance.now(),L;try{L=d()}finally{w&&It(w)}let G=performance.now()-y,A=L.tokens,b=0;if(f!==null){let T=Math.min(f.length,A.length);for(;b<T&&f[b]===A[b].raw;b++);}else if(m!==null){let T=m,le=Math.min(T.length,A.length);for(b=Math.min(L.reusedTokens,le);b<le&&T[b].raw===A[b].raw;b++);}h!==null&&p!==null&&M.set(h,{version:p+1,lex:L.cache}),self.postMessage({id:n,matchLen:b,tail:A.slice(b),lexerMs:G,sourceCharsLexed:L.charsLexed})}catch(w){h!==null&&M.delete(h),self.postMessage({id:n,error:String(w)})}};})();\n';
|
|
1952
|
+
|
|
1953
|
+
// src/Markdown.ts
|
|
1954
|
+
var now = () => typeof performance !== "undefined" && typeof performance.now === "function" ? performance.now() : Date.now();
|
|
1955
|
+
function lexMarkdown(text, userTiming) {
|
|
1956
|
+
if (!userTiming) return import_marked.marked.lexer(text);
|
|
1957
|
+
const timing = (0, import_core4.beginVectoUserTiming)(import_core4.VECTO_USER_TIMING.markdown.parse);
|
|
1958
|
+
try {
|
|
1959
|
+
return import_marked.marked.lexer(text);
|
|
1960
|
+
} finally {
|
|
1961
|
+
if (timing) (0, import_core4.endVectoUserTiming)(timing);
|
|
1962
|
+
}
|
|
1688
1963
|
}
|
|
1689
|
-
|
|
1690
|
-
|
|
1691
|
-
|
|
1692
|
-
|
|
1693
|
-
|
|
1694
|
-
|
|
1695
|
-
|
|
1696
|
-
|
|
1697
|
-
|
|
1698
|
-
|
|
1699
|
-
|
|
1700
|
-
|
|
1701
|
-
|
|
1702
|
-
|
|
1703
|
-
|
|
1704
|
-
|
|
1705
|
-
|
|
1706
|
-
|
|
1707
|
-
|
|
1708
|
-
|
|
1709
|
-
out.push({
|
|
1710
|
-
text: decodeEntities(t.text),
|
|
1711
|
-
style: { ...inherited, italic: true }
|
|
1712
|
-
});
|
|
1964
|
+
import_marked.marked.use({
|
|
1965
|
+
// `FOOTNOTE_EXTENSIONS` is shared with `MarkdownWorker.ts` rather than spelled
|
|
1966
|
+
// out twice: the two registration sites must agree exactly, or the worker
|
|
1967
|
+
// returns tokens this renderer has no arm for.
|
|
1968
|
+
extensions: [
|
|
1969
|
+
...FOOTNOTE_EXTENSIONS,
|
|
1970
|
+
{
|
|
1971
|
+
name: "blockMath",
|
|
1972
|
+
level: "block",
|
|
1973
|
+
start(src) {
|
|
1974
|
+
return src.match(/^ {0,3}\$\$/m)?.index;
|
|
1975
|
+
},
|
|
1976
|
+
tokenizer(src) {
|
|
1977
|
+
const match = /^ {0,3}\$\$([\s\S]+?)\$\$[ \t]*(?:\n|$)/.exec(src);
|
|
1978
|
+
if (match) {
|
|
1979
|
+
return {
|
|
1980
|
+
type: "blockMath",
|
|
1981
|
+
raw: match[0],
|
|
1982
|
+
text: match[1].trim()
|
|
1983
|
+
};
|
|
1713
1984
|
}
|
|
1714
|
-
|
|
1985
|
+
return void 0;
|
|
1986
|
+
},
|
|
1987
|
+
renderer(token) {
|
|
1988
|
+
return token.raw;
|
|
1715
1989
|
}
|
|
1716
|
-
|
|
1717
|
-
|
|
1718
|
-
|
|
1719
|
-
|
|
1720
|
-
|
|
1721
|
-
|
|
1722
|
-
|
|
1723
|
-
|
|
1724
|
-
|
|
1990
|
+
},
|
|
1991
|
+
{
|
|
1992
|
+
name: "inlineMath",
|
|
1993
|
+
level: "inline",
|
|
1994
|
+
start(src) {
|
|
1995
|
+
return src.match(/(?<![\\$])\$(?![$\s])/)?.index;
|
|
1996
|
+
},
|
|
1997
|
+
tokenizer(src) {
|
|
1998
|
+
const match = /^\$(?![$\s\d])((?:\\\$|[^$\n])*?)(?<!\s)\$(?!\d)/.exec(src);
|
|
1999
|
+
if (match) {
|
|
2000
|
+
return {
|
|
2001
|
+
type: "inlineMath",
|
|
2002
|
+
raw: match[0],
|
|
2003
|
+
text: match[1].trim()
|
|
2004
|
+
};
|
|
1725
2005
|
}
|
|
1726
|
-
|
|
1727
|
-
}
|
|
1728
|
-
|
|
1729
|
-
|
|
1730
|
-
out.push({
|
|
1731
|
-
text: decodeEntities(t.text),
|
|
1732
|
-
// Inline code renders in the theme's monospace family (not just tinted
|
|
1733
|
-
// prose) — TextStyle.fontFamily drives both measurement and drawing.
|
|
1734
|
-
style: {
|
|
1735
|
-
...inherited,
|
|
1736
|
-
color: theme.codeColor,
|
|
1737
|
-
fontFamily: theme.codeFont
|
|
1738
|
-
}
|
|
1739
|
-
});
|
|
1740
|
-
break;
|
|
1741
|
-
}
|
|
1742
|
-
case "br": {
|
|
1743
|
-
out.push({ text: "\n" });
|
|
1744
|
-
break;
|
|
1745
|
-
}
|
|
1746
|
-
case "html": {
|
|
1747
|
-
const t = token;
|
|
1748
|
-
const raw = t.raw ?? t.text ?? "";
|
|
1749
|
-
const brCount = (raw.match(/<br\s*\/?>/gi) ?? []).length;
|
|
1750
|
-
for (let i = 0; i < brCount; i++) out.push({ text: "\n" });
|
|
1751
|
-
break;
|
|
2006
|
+
return void 0;
|
|
2007
|
+
},
|
|
2008
|
+
renderer(token) {
|
|
2009
|
+
return token.raw;
|
|
1752
2010
|
}
|
|
1753
|
-
|
|
1754
|
-
|
|
1755
|
-
|
|
1756
|
-
|
|
1757
|
-
|
|
1758
|
-
|
|
1759
|
-
|
|
1760
|
-
|
|
1761
|
-
|
|
1762
|
-
|
|
1763
|
-
|
|
1764
|
-
|
|
1765
|
-
|
|
1766
|
-
|
|
1767
|
-
|
|
1768
|
-
|
|
1769
|
-
|
|
1770
|
-
|
|
1771
|
-
|
|
1772
|
-
|
|
1773
|
-
|
|
1774
|
-
|
|
1775
|
-
|
|
1776
|
-
|
|
1777
|
-
|
|
1778
|
-
|
|
2011
|
+
}
|
|
2012
|
+
]
|
|
2013
|
+
});
|
|
2014
|
+
var markdownWorker = null;
|
|
2015
|
+
var workerIdCounter = 0;
|
|
2016
|
+
var workerInstanceCounter = 0;
|
|
2017
|
+
var workerCallbacks = /* @__PURE__ */ new Map();
|
|
2018
|
+
function runSyncFallback(entry) {
|
|
2019
|
+
try {
|
|
2020
|
+
entry.cb(0, lexMarkdown(entry.text, entry.userTiming), true);
|
|
2021
|
+
} catch (err) {
|
|
2022
|
+
console.warn("Markdown sync fallback parse failed", err);
|
|
2023
|
+
entry.onDropped?.();
|
|
2024
|
+
}
|
|
2025
|
+
}
|
|
2026
|
+
if (typeof Worker !== "undefined") {
|
|
2027
|
+
try {
|
|
2028
|
+
const blob = new Blob([WORKER_SOURCE_STRING], {
|
|
2029
|
+
type: "application/javascript"
|
|
2030
|
+
});
|
|
2031
|
+
markdownWorker = new Worker(URL.createObjectURL(blob));
|
|
2032
|
+
markdownWorker.onmessage = (e) => {
|
|
2033
|
+
const { id, matchLen, tail, error, needResync, lexerMs, sourceCharsLexed } = e.data;
|
|
2034
|
+
const entry = workerCallbacks.get(id);
|
|
2035
|
+
if (entry) {
|
|
2036
|
+
workerCallbacks.delete(id);
|
|
2037
|
+
if (needResync && entry.onNeedResync) {
|
|
2038
|
+
entry.onNeedResync();
|
|
2039
|
+
} else if (needResync) {
|
|
2040
|
+
runSyncFallback(entry);
|
|
2041
|
+
} else if (!error) {
|
|
2042
|
+
entry.cb(matchLen, tail, false, {
|
|
2043
|
+
lexerMs: typeof lexerMs === "number" ? lexerMs : 0,
|
|
2044
|
+
sourceCharsLexed: typeof sourceCharsLexed === "number" ? sourceCharsLexed : 0
|
|
1779
2045
|
});
|
|
1780
|
-
}
|
|
1781
|
-
break;
|
|
1782
|
-
}
|
|
1783
|
-
case "link": {
|
|
1784
|
-
const t = token;
|
|
1785
|
-
const linkStyle = {
|
|
1786
|
-
...inherited,
|
|
1787
|
-
href: t.href,
|
|
1788
|
-
color: "#38bdf8"
|
|
1789
|
-
};
|
|
1790
|
-
if (t.tokens && t.tokens.length > 0) {
|
|
1791
|
-
collectSpans(t.tokens, linkStyle, theme, out, blockFontSize);
|
|
1792
|
-
} else {
|
|
1793
|
-
out.push({ text: decodeEntities(t.text), style: linkStyle });
|
|
1794
|
-
}
|
|
1795
|
-
break;
|
|
1796
|
-
}
|
|
1797
|
-
case "text": {
|
|
1798
|
-
const t = token;
|
|
1799
|
-
if ("tokens" in t && t.tokens?.length) {
|
|
1800
|
-
collectSpans(t.tokens, inherited, theme, out, blockFontSize);
|
|
1801
2046
|
} else {
|
|
1802
|
-
|
|
1803
|
-
if (decoded) {
|
|
1804
|
-
const style = Object.keys(inherited).length > 0 ? inherited : void 0;
|
|
1805
|
-
out.push({ text: decoded, style });
|
|
1806
|
-
}
|
|
1807
|
-
}
|
|
1808
|
-
break;
|
|
1809
|
-
}
|
|
1810
|
-
default: {
|
|
1811
|
-
if ("text" in token) {
|
|
1812
|
-
const decoded = decodeEntities(token.text);
|
|
1813
|
-
if (decoded) {
|
|
1814
|
-
const style = Object.keys(inherited).length > 0 ? inherited : void 0;
|
|
1815
|
-
out.push({ text: decoded, style });
|
|
1816
|
-
}
|
|
2047
|
+
runSyncFallback(entry);
|
|
1817
2048
|
}
|
|
1818
|
-
break;
|
|
1819
2049
|
}
|
|
1820
|
-
}
|
|
1821
|
-
}
|
|
1822
|
-
}
|
|
1823
|
-
function findUnclosedInline(text) {
|
|
1824
|
-
let best = null;
|
|
1825
|
-
const tick = text.lastIndexOf("`");
|
|
1826
|
-
if (tick !== -1 && tick < text.length - 1) {
|
|
1827
|
-
return { kind: "codespan", at: tick, contentAt: tick + 1 };
|
|
1828
|
-
}
|
|
1829
|
-
if (tick !== -1) return null;
|
|
1830
|
-
const emphasis = /(\*{1,2}(?!\*)|_{1,2}(?!_))(?=[^\s])/g;
|
|
1831
|
-
for (let match = emphasis.exec(text); match !== null; match = emphasis.exec(text)) {
|
|
1832
|
-
const marker = match[1];
|
|
1833
|
-
const at = match.index;
|
|
1834
|
-
if (marker[0] === "_" && at > 0 && /[\w]/.test(text[at - 1])) continue;
|
|
1835
|
-
best = {
|
|
1836
|
-
kind: marker.length === 2 ? "strong" : "em",
|
|
1837
|
-
at,
|
|
1838
|
-
contentAt: at + marker.length
|
|
1839
2050
|
};
|
|
2051
|
+
markdownWorker.onerror = () => {
|
|
2052
|
+
const pending = [...workerCallbacks.values()];
|
|
2053
|
+
workerCallbacks.clear();
|
|
2054
|
+
markdownWorker = null;
|
|
2055
|
+
for (const entry of pending) runSyncFallback(entry);
|
|
2056
|
+
};
|
|
2057
|
+
} catch (err) {
|
|
2058
|
+
console.warn("Failed to initialize MarkdownWorker", err);
|
|
1840
2059
|
}
|
|
1841
|
-
const bracket = text.lastIndexOf("[");
|
|
1842
|
-
if (bracket !== -1 && bracket < text.length - 1 && (best === null || bracket > best.at)) {
|
|
1843
|
-
const closed = /\]\([^)]*\)/.test(text.slice(bracket));
|
|
1844
|
-
if (!closed) {
|
|
1845
|
-
best = { kind: "link", at: bracket, contentAt: bracket + 1 };
|
|
1846
|
-
}
|
|
1847
|
-
}
|
|
1848
|
-
return best;
|
|
1849
|
-
}
|
|
1850
|
-
function renderInlineToRichText(tokens, fallbackText, font, color, maxWidth, theme, selectable, onLinkClick) {
|
|
1851
|
-
const spans = [];
|
|
1852
|
-
if (tokens && tokens.length > 0) {
|
|
1853
|
-
collectSpans(tokens, {}, theme, spans, fontSizeFromFont(font));
|
|
1854
|
-
}
|
|
1855
|
-
if (spans.length === 0) {
|
|
1856
|
-
spans.push({ text: decodeEntities(fallbackText) });
|
|
1857
|
-
}
|
|
1858
|
-
return new import_ui2.RichText(spans, {
|
|
1859
|
-
font,
|
|
1860
|
-
color,
|
|
1861
|
-
maxWidth,
|
|
1862
|
-
linkColor: "#38bdf8",
|
|
1863
|
-
selectable,
|
|
1864
|
-
onLinkClick
|
|
1865
|
-
});
|
|
1866
2060
|
}
|
|
1867
|
-
var Markdown = class _Markdown extends
|
|
2061
|
+
var Markdown = class _Markdown extends import_ui4.UIComponent {
|
|
1868
2062
|
content;
|
|
1869
2063
|
maxWidth;
|
|
1870
2064
|
theme;
|
|
@@ -1957,6 +2151,20 @@ var Markdown = class _Markdown extends import_ui2.UIComponent {
|
|
|
1957
2151
|
* field only so {@link destroy} can remove the exact closure it added.
|
|
1958
2152
|
*/
|
|
1959
2153
|
inlineMathRepaint;
|
|
2154
|
+
/**
|
|
2155
|
+
* This instance's entry in the inline-image decode waiters, or `undefined` if it
|
|
2156
|
+
* has never rendered an image. Held as a field only so {@link destroy} can remove
|
|
2157
|
+
* the exact closure it added.
|
|
2158
|
+
*/
|
|
2159
|
+
inlineImageRemeasure;
|
|
2160
|
+
/**
|
|
2161
|
+
* URLs whose decoded aspect ratio this document has already reserved a box for.
|
|
2162
|
+
*
|
|
2163
|
+
* The guard that makes the re-measure fire once per image rather than once per
|
|
2164
|
+
* decode-notification-per-image: the waiter set is module-level, so a page of
|
|
2165
|
+
* many documents tells all of them about all decodes.
|
|
2166
|
+
*/
|
|
2167
|
+
inlineImagesMeasured = /* @__PURE__ */ new Set();
|
|
1960
2168
|
/**
|
|
1961
2169
|
* True while this document is waiting on the lazy MathJax load.
|
|
1962
2170
|
*
|
|
@@ -2102,14 +2310,17 @@ var Markdown = class _Markdown extends import_ui2.UIComponent {
|
|
|
2102
2310
|
constructor(markdownText, opts = {}) {
|
|
2103
2311
|
super();
|
|
2104
2312
|
this.maxWidth = opts.maxWidth ?? 800;
|
|
2105
|
-
this.theme =
|
|
2313
|
+
this.theme = resolveTheme(opts.theme);
|
|
2106
2314
|
this.onLinkClick = opts.onLinkClick;
|
|
2107
2315
|
this.selectable = opts.selectable ?? true;
|
|
2108
2316
|
this._userTiming = opts.userTiming ?? false;
|
|
2109
2317
|
this.blockAffordances = opts.blockAffordances ?? false;
|
|
2110
2318
|
this.writeClipboard = opts.writeClipboard ?? defaultWriteClipboard;
|
|
2111
2319
|
this.saveFile = opts.saveFile ?? defaultSaveFile;
|
|
2112
|
-
this.content = new
|
|
2320
|
+
this.content = new import_ui4.Stack({
|
|
2321
|
+
direction: "vertical",
|
|
2322
|
+
gap: this.theme.blockGap
|
|
2323
|
+
});
|
|
2113
2324
|
this.add(this.content);
|
|
2114
2325
|
this.rawMarkdown = "";
|
|
2115
2326
|
this.setTokens([]);
|
|
@@ -2328,15 +2539,15 @@ var Markdown = class _Markdown extends import_ui2.UIComponent {
|
|
|
2328
2539
|
switch (token.type) {
|
|
2329
2540
|
case "heading":
|
|
2330
2541
|
case "paragraph": {
|
|
2331
|
-
if (entity instanceof
|
|
2542
|
+
if (entity instanceof import_ui4.RichText) {
|
|
2332
2543
|
entity.setMaxWidth(availableWidth);
|
|
2333
2544
|
return;
|
|
2334
2545
|
}
|
|
2335
|
-
if (entity instanceof
|
|
2546
|
+
if (entity instanceof import_ui4.Stack) {
|
|
2336
2547
|
entity.maxWidth = availableWidth;
|
|
2337
2548
|
for (const run of entity.children) {
|
|
2338
|
-
if (run instanceof
|
|
2339
|
-
else if (run instanceof
|
|
2549
|
+
if (run instanceof import_ui4.RichText) run.setMaxWidth(availableWidth);
|
|
2550
|
+
else if (run instanceof import_ui4.Image) this.refitParagraphImage(run, availableWidth);
|
|
2340
2551
|
}
|
|
2341
2552
|
entity.layout();
|
|
2342
2553
|
}
|
|
@@ -2349,11 +2560,11 @@ var Markdown = class _Markdown extends import_ui2.UIComponent {
|
|
|
2349
2560
|
}
|
|
2350
2561
|
case "blockquote": {
|
|
2351
2562
|
const bqToken = token;
|
|
2352
|
-
const innerStack = entity.children.find((c) => c instanceof
|
|
2563
|
+
const innerStack = entity.children.find((c) => c instanceof import_ui4.Stack);
|
|
2353
2564
|
const border = entity.children.find((c) => c instanceof QuoteBorder);
|
|
2354
|
-
const indentStart = Math.min(
|
|
2565
|
+
const indentStart = Math.min(this.theme.quoteIndent, availableWidth);
|
|
2355
2566
|
const childWidth = Math.max(0, availableWidth - indentStart);
|
|
2356
|
-
if (innerStack instanceof
|
|
2567
|
+
if (innerStack instanceof import_ui4.Stack && bqToken.tokens) {
|
|
2357
2568
|
let index = 0;
|
|
2358
2569
|
for (const inner of bqToken.tokens) {
|
|
2359
2570
|
if (!this.producesEntity(inner)) continue;
|
|
@@ -2376,23 +2587,27 @@ var Markdown = class _Markdown extends import_ui2.UIComponent {
|
|
|
2376
2587
|
return;
|
|
2377
2588
|
}
|
|
2378
2589
|
case "list": {
|
|
2379
|
-
if (!(entity instanceof
|
|
2590
|
+
if (!(entity instanceof import_ui4.Stack)) return;
|
|
2380
2591
|
for (const item of entity.children) {
|
|
2381
|
-
if (item instanceof
|
|
2592
|
+
if (item instanceof import_ui4.RichText) item.setMaxWidth(availableWidth);
|
|
2382
2593
|
}
|
|
2383
2594
|
entity.layout();
|
|
2384
2595
|
return;
|
|
2385
2596
|
}
|
|
2386
2597
|
case "table": {
|
|
2387
|
-
if (entity instanceof
|
|
2598
|
+
if (entity instanceof import_ui4.Table) entity.setWidth(availableWidth);
|
|
2388
2599
|
return;
|
|
2389
2600
|
}
|
|
2390
2601
|
case "hr": {
|
|
2391
2602
|
if (entity instanceof HorizontalRule) entity.width = availableWidth;
|
|
2392
2603
|
return;
|
|
2393
2604
|
}
|
|
2605
|
+
case "footnoteDef": {
|
|
2606
|
+
if (entity instanceof import_ui4.RichText) entity.setMaxWidth(availableWidth);
|
|
2607
|
+
return;
|
|
2608
|
+
}
|
|
2394
2609
|
default: {
|
|
2395
|
-
if (entity instanceof
|
|
2610
|
+
if (entity instanceof import_ui4.Text) entity.setMaxWidth(availableWidth);
|
|
2396
2611
|
return;
|
|
2397
2612
|
}
|
|
2398
2613
|
}
|
|
@@ -2454,7 +2669,98 @@ var Markdown = class _Markdown extends import_ui2.UIComponent {
|
|
|
2454
2669
|
this.scene?.markDirty();
|
|
2455
2670
|
};
|
|
2456
2671
|
this.inlineMathRepaint = repaint;
|
|
2457
|
-
|
|
2672
|
+
subscribeInlineMathRaster(repaint);
|
|
2673
|
+
}
|
|
2674
|
+
/**
|
|
2675
|
+
* Re-measure this document when an inline image's raster finishes decoding.
|
|
2676
|
+
*
|
|
2677
|
+
* Inline images differ from inline formulas in one way that matters: a formula's
|
|
2678
|
+
* box is known synchronously the moment it typesets, while an image's aspect
|
|
2679
|
+
* ratio arrives only with the decode. The span reserved a square until then, so a
|
|
2680
|
+
* decode that reports anything else has invalidated a WIDTH, and a repaint into
|
|
2681
|
+
* the old box would letterbox or stretch the picture.
|
|
2682
|
+
*
|
|
2683
|
+
* So this rebuilds through {@link retypesetFromTokens} — the same late-arrival
|
|
2684
|
+
* path MathJax uses — but only when a reserved width actually changed. Every live
|
|
2685
|
+
* document is notified for every decode, including images it does not contain, so
|
|
2686
|
+
* an unconditional rebuild here would be O(documents x images) full re-renders
|
|
2687
|
+
* for a page of many blocks.
|
|
2688
|
+
*
|
|
2689
|
+
* Subscribed lazily and held as a field for the same two reasons as its math
|
|
2690
|
+
* counterpart: a document with no images costs nothing, and `destroy` must remove
|
|
2691
|
+
* the exact closure it added.
|
|
2692
|
+
*/
|
|
2693
|
+
subscribeInlineImageRemeasure() {
|
|
2694
|
+
if (this.inlineImageRemeasure || this.isDestroyed) return;
|
|
2695
|
+
const remeasure = () => {
|
|
2696
|
+
if (this.isDestroyed) return;
|
|
2697
|
+
if (this.inlineImageBoxesStale()) this.retypesetFromTokens();
|
|
2698
|
+
else this.scene?.markDirty();
|
|
2699
|
+
};
|
|
2700
|
+
this.inlineImageRemeasure = remeasure;
|
|
2701
|
+
subscribeInlineImageRaster(remeasure);
|
|
2702
|
+
}
|
|
2703
|
+
/**
|
|
2704
|
+
* Whether any inline image in this document has just learned it is not square.
|
|
2705
|
+
*
|
|
2706
|
+
* An inline image's span reserves a square box before its raster decodes, because
|
|
2707
|
+
* that is the only shape available without a natural size. The decode supplies the
|
|
2708
|
+
* real aspect ratio, so a non-square image needs one rebuild to reserve the right
|
|
2709
|
+
* width — and exactly one. Every live document is notified of every decode on the
|
|
2710
|
+
* page, including images it does not contain, so this has to answer "did MY
|
|
2711
|
+
* geometry just change" and not merely "did something decode".
|
|
2712
|
+
*
|
|
2713
|
+
* Walks the tokens rather than the entity tree: the reserved box is a function of
|
|
2714
|
+
* the raster's aspect ratio, which is available here, and a token walk cannot be
|
|
2715
|
+
* confused by an entity a previous rebuild already corrected.
|
|
2716
|
+
*
|
|
2717
|
+
* Only headings and table cells are inspected. Every other context splits an image
|
|
2718
|
+
* into its own block whose `Image` entity resizes itself in `onLoad`, so a rebuild
|
|
2719
|
+
* for one of those would be pure cost.
|
|
2720
|
+
*/
|
|
2721
|
+
inlineImageBoxesStale() {
|
|
2722
|
+
const stale = (tokens) => {
|
|
2723
|
+
let changed2 = false;
|
|
2724
|
+
for (const token of tokens ?? []) {
|
|
2725
|
+
if (token.type === "image") {
|
|
2726
|
+
const href = token.href;
|
|
2727
|
+
if (this.inlineImagesMeasured.has(href)) continue;
|
|
2728
|
+
const raster = ensureInlineImageRaster(href);
|
|
2729
|
+
if (raster.failed) {
|
|
2730
|
+
this.inlineImagesMeasured.add(href);
|
|
2731
|
+
changed2 = true;
|
|
2732
|
+
continue;
|
|
2733
|
+
}
|
|
2734
|
+
if (!raster.decoded || !raster.naturalWidth || !raster.naturalHeight) {
|
|
2735
|
+
continue;
|
|
2736
|
+
}
|
|
2737
|
+
this.inlineImagesMeasured.add(href);
|
|
2738
|
+
if (raster.naturalWidth !== raster.naturalHeight) changed2 = true;
|
|
2739
|
+
continue;
|
|
2740
|
+
}
|
|
2741
|
+
if (stale(token.tokens)) {
|
|
2742
|
+
changed2 = true;
|
|
2743
|
+
}
|
|
2744
|
+
}
|
|
2745
|
+
return changed2;
|
|
2746
|
+
};
|
|
2747
|
+
let changed = false;
|
|
2748
|
+
for (const token of this.tokens) {
|
|
2749
|
+
if (token.type === "heading") {
|
|
2750
|
+
if (stale(token.tokens)) changed = true;
|
|
2751
|
+
} else if (token.type === "table") {
|
|
2752
|
+
const table = token;
|
|
2753
|
+
for (const cell of table.header) {
|
|
2754
|
+
if (stale(cell.tokens)) changed = true;
|
|
2755
|
+
}
|
|
2756
|
+
for (const row of table.rows) {
|
|
2757
|
+
for (const cell of row) {
|
|
2758
|
+
if (stale(cell.tokens)) changed = true;
|
|
2759
|
+
}
|
|
2760
|
+
}
|
|
2761
|
+
}
|
|
2762
|
+
}
|
|
2763
|
+
return changed;
|
|
2458
2764
|
}
|
|
2459
2765
|
destroy() {
|
|
2460
2766
|
this.isDestroyed = true;
|
|
@@ -2467,9 +2773,13 @@ var Markdown = class _Markdown extends import_ui2.UIComponent {
|
|
|
2467
2773
|
this.mathLoadPending = false;
|
|
2468
2774
|
this.flushAppendSettledWaiters();
|
|
2469
2775
|
if (this.inlineMathRepaint) {
|
|
2470
|
-
|
|
2776
|
+
unsubscribeInlineMathRaster(this.inlineMathRepaint);
|
|
2471
2777
|
this.inlineMathRepaint = void 0;
|
|
2472
2778
|
}
|
|
2779
|
+
if (this.inlineImageRemeasure) {
|
|
2780
|
+
unsubscribeInlineImageRaster(this.inlineImageRemeasure);
|
|
2781
|
+
this.inlineImageRemeasure = void 0;
|
|
2782
|
+
}
|
|
2473
2783
|
markdownWorker?.postMessage({
|
|
2474
2784
|
instance: this.workerInstanceId,
|
|
2475
2785
|
dispose: true
|
|
@@ -2771,7 +3081,7 @@ var Markdown = class _Markdown extends import_ui2.UIComponent {
|
|
|
2771
3081
|
id,
|
|
2772
3082
|
instance: this.workerInstanceId,
|
|
2773
3083
|
baseVersion,
|
|
2774
|
-
userTimingName: this._userTiming ?
|
|
3084
|
+
userTimingName: this._userTiming ? import_core4.VECTO_USER_TIMING.markdown.parse : void 0,
|
|
2775
3085
|
...canSendDelta ? {
|
|
2776
3086
|
append: this.rawMarkdown.slice(this.workerSourceLen),
|
|
2777
3087
|
// What the worker's source must total once it applies this append. It
|
|
@@ -2863,11 +3173,11 @@ var Markdown = class _Markdown extends import_ui2.UIComponent {
|
|
|
2863
3173
|
}
|
|
2864
3174
|
/** One text run of an image-bearing paragraph, as both paths build it. */
|
|
2865
3175
|
inlineRunRichText(tokens, availableWidth, t) {
|
|
2866
|
-
return new
|
|
3176
|
+
return new import_ui4.RichText(this.inlineRunSpans(tokens, t), {
|
|
2867
3177
|
font: `${t.fontSize}px ${t.bodyFont}`,
|
|
2868
3178
|
color: t.textColor,
|
|
2869
3179
|
maxWidth: availableWidth,
|
|
2870
|
-
linkColor:
|
|
3180
|
+
linkColor: t.linkColor,
|
|
2871
3181
|
selectable: this.selectable,
|
|
2872
3182
|
onLinkClick: this.onLinkClick
|
|
2873
3183
|
});
|
|
@@ -2967,11 +3277,11 @@ var Markdown = class _Markdown extends import_ui2.UIComponent {
|
|
|
2967
3277
|
paragraphImage(imgToken, availableWidth) {
|
|
2968
3278
|
const initialWidth = Math.min(800, availableWidth);
|
|
2969
3279
|
const initialHeight = Math.round(initialWidth * 0.6);
|
|
2970
|
-
const img = new
|
|
3280
|
+
const img = new import_ui4.Image(imgToken.href, {
|
|
2971
3281
|
width: initialWidth,
|
|
2972
3282
|
height: initialHeight,
|
|
2973
3283
|
alt: imgToken.text,
|
|
2974
|
-
radius:
|
|
3284
|
+
radius: this.theme.imageRadius,
|
|
2975
3285
|
onLoad: () => {
|
|
2976
3286
|
const bmp = img.bitmap;
|
|
2977
3287
|
if (bmp && bmp.naturalWidth && bmp.naturalHeight) {
|
|
@@ -2986,11 +3296,11 @@ var Markdown = class _Markdown extends import_ui2.UIComponent {
|
|
|
2986
3296
|
}
|
|
2987
3297
|
/** One table cell entity, shared by the render arm and the streamed-table path. */
|
|
2988
3298
|
tableCellRichText(cell, header, t) {
|
|
2989
|
-
return new
|
|
2990
|
-
font: `${t.
|
|
3299
|
+
return new import_ui4.RichText(this.tableCellSpans(cell, t), {
|
|
3300
|
+
font: `${t.tableFontSize}px ${t.bodyFont}`,
|
|
2991
3301
|
color: header ? t.headingColor : t.textColor,
|
|
2992
3302
|
baseStyle: header ? { bold: true } : void 0,
|
|
2993
|
-
linkColor:
|
|
3303
|
+
linkColor: t.linkColor,
|
|
2994
3304
|
selectable: this.selectable,
|
|
2995
3305
|
onLinkClick: this.onLinkClick
|
|
2996
3306
|
});
|
|
@@ -3072,7 +3382,7 @@ var Markdown = class _Markdown extends import_ui2.UIComponent {
|
|
|
3072
3382
|
listItemBlockStack(token, index, availableWidth, t) {
|
|
3073
3383
|
const item = token.items[index];
|
|
3074
3384
|
const children = item.tokens ?? [];
|
|
3075
|
-
const stack = new
|
|
3385
|
+
const stack = new import_ui4.Stack({ direction: "vertical", gap: t.listItemGap });
|
|
3076
3386
|
const first = children[0];
|
|
3077
3387
|
const firstIsInline = Boolean(first) && (first.type === "text" || first.type === "paragraph");
|
|
3078
3388
|
const leadHasImage = firstIsInline && containsImage(first.tokens);
|
|
@@ -3139,16 +3449,16 @@ var Markdown = class _Markdown extends import_ui2.UIComponent {
|
|
|
3139
3449
|
const box = item.task ? item.checked ? "\u2611 " : "\u2610 " : "";
|
|
3140
3450
|
const leadingMarker = token.ordered ? `${num}. ${box}` : box || "\u2022 ";
|
|
3141
3451
|
const trailingMarker = token.ordered ? ` ${box}.${num}` : box ? ` ${box.trimEnd()}` : " \u2022";
|
|
3142
|
-
const itemIsRtl =
|
|
3452
|
+
const itemIsRtl = import_core4.BidiResolver.getBaseLevel(contentSpans.map((s) => s.text).join("")) % 2 === 1;
|
|
3143
3453
|
return itemIsRtl ? [...contentSpans, { text: trailingMarker }] : [{ text: leadingMarker }, ...contentSpans];
|
|
3144
3454
|
}
|
|
3145
3455
|
/** Construct the `RichText` for one list item. */
|
|
3146
3456
|
listItemRichText(token, index, availableWidth, t) {
|
|
3147
|
-
return new
|
|
3457
|
+
return new import_ui4.RichText(this.listItemSpans(token, index), {
|
|
3148
3458
|
font: `${t.fontSize}px ${t.bodyFont}`,
|
|
3149
3459
|
color: t.textColor,
|
|
3150
3460
|
maxWidth: availableWidth,
|
|
3151
|
-
linkColor:
|
|
3461
|
+
linkColor: t.linkColor,
|
|
3152
3462
|
selectable: this.selectable,
|
|
3153
3463
|
onLinkClick: this.onLinkClick
|
|
3154
3464
|
});
|
|
@@ -3179,7 +3489,7 @@ var Markdown = class _Markdown extends import_ui2.UIComponent {
|
|
|
3179
3489
|
* and keep stale spans. Bail when `loose` flips.
|
|
3180
3490
|
*/
|
|
3181
3491
|
updateStreamedList(stack, oldToken, newToken) {
|
|
3182
|
-
if (!(stack instanceof
|
|
3492
|
+
if (!(stack instanceof import_ui4.Stack)) return false;
|
|
3183
3493
|
if (newToken.items.length < oldToken.items.length || oldToken.items.length === 0) return false;
|
|
3184
3494
|
if (oldToken.ordered !== newToken.ordered) return false;
|
|
3185
3495
|
if ((oldToken.start ?? 1) !== (newToken.start ?? 1)) return false;
|
|
@@ -3188,7 +3498,7 @@ var Markdown = class _Markdown extends import_ui2.UIComponent {
|
|
|
3188
3498
|
const lastRetained = oldToken.items.length - 1;
|
|
3189
3499
|
for (let i = 0; i < lastRetained; i++) {
|
|
3190
3500
|
if (oldToken.items[i].text !== newToken.items[i].text) return false;
|
|
3191
|
-
const isStack = stack.children[i] instanceof
|
|
3501
|
+
const isStack = stack.children[i] instanceof import_ui4.Stack;
|
|
3192
3502
|
if (isStack !== !this.itemIsInlineOnly(newToken.items[i])) return false;
|
|
3193
3503
|
}
|
|
3194
3504
|
const availableWidth = this.activeBlockMetrics?.availableWidth ?? this.maxWidth;
|
|
@@ -3247,7 +3557,7 @@ var Markdown = class _Markdown extends import_ui2.UIComponent {
|
|
|
3247
3557
|
* *token runs* split at the last image, never token index against child index.
|
|
3248
3558
|
*/
|
|
3249
3559
|
updateImageParagraph(entity, oldToken, newToken) {
|
|
3250
|
-
if (!(entity instanceof
|
|
3560
|
+
if (!(entity instanceof import_ui4.Stack)) return false;
|
|
3251
3561
|
const oldTokens = oldToken.tokens;
|
|
3252
3562
|
const newTokens = newToken.tokens;
|
|
3253
3563
|
if (!oldTokens || !newTokens) return false;
|
|
@@ -3272,7 +3582,7 @@ var Markdown = class _Markdown extends import_ui2.UIComponent {
|
|
|
3272
3582
|
entity.add(this.inlineRunRichText(newTail, availableWidth, t));
|
|
3273
3583
|
} else {
|
|
3274
3584
|
const tailEntity = entity.children[entity.children.length - 1];
|
|
3275
|
-
if (!(tailEntity instanceof
|
|
3585
|
+
if (!(tailEntity instanceof import_ui4.RichText)) return false;
|
|
3276
3586
|
tailEntity.setSpans(this.inlineRunSpans(newTail, t));
|
|
3277
3587
|
}
|
|
3278
3588
|
const last = entity.children[entity.children.length - 1];
|
|
@@ -3304,7 +3614,7 @@ var Markdown = class _Markdown extends import_ui2.UIComponent {
|
|
|
3304
3614
|
* (its keys are `text`/`tokens`/`header`/`align`).
|
|
3305
3615
|
*/
|
|
3306
3616
|
updateStreamedTable(entity, oldToken, newToken) {
|
|
3307
|
-
if (!(entity instanceof
|
|
3617
|
+
if (!(entity instanceof import_ui4.Table)) return false;
|
|
3308
3618
|
if (oldToken.header.length !== newToken.header.length) return false;
|
|
3309
3619
|
for (let c = 0; c < oldToken.header.length; c++) {
|
|
3310
3620
|
if (oldToken.header[c].text !== newToken.header[c].text) return false;
|
|
@@ -3325,7 +3635,7 @@ var Markdown = class _Markdown extends import_ui2.UIComponent {
|
|
|
3325
3635
|
if (lastRetained >= 0) {
|
|
3326
3636
|
for (let c = 0; c < oldToken.header.length; c++) {
|
|
3327
3637
|
const cell = entity.rows[lastRetained]?.[c];
|
|
3328
|
-
if (!(cell instanceof
|
|
3638
|
+
if (!(cell instanceof import_ui4.RichText)) return false;
|
|
3329
3639
|
}
|
|
3330
3640
|
}
|
|
3331
3641
|
const t = this.theme;
|
|
@@ -3358,7 +3668,7 @@ var Markdown = class _Markdown extends import_ui2.UIComponent {
|
|
|
3358
3668
|
const newTail = newInner[tail];
|
|
3359
3669
|
if (oldTail.type !== newTail.type) return false;
|
|
3360
3670
|
const innerStack = container.children[1];
|
|
3361
|
-
if (!(innerStack instanceof
|
|
3671
|
+
if (!(innerStack instanceof import_ui4.Stack)) return false;
|
|
3362
3672
|
const wrapper = innerStack.children.at(-1);
|
|
3363
3673
|
if (!wrapper || wrapper.children.length !== 1) return false;
|
|
3364
3674
|
const entity = wrapper.children[0];
|
|
@@ -3498,12 +3808,12 @@ var Markdown = class _Markdown extends import_ui2.UIComponent {
|
|
|
3498
3808
|
* queued while the first is outstanding.
|
|
3499
3809
|
*/
|
|
3500
3810
|
ensureMathJax() {
|
|
3501
|
-
if (
|
|
3811
|
+
if (isMathJaxReady() || this.mathLoadPending || this.isDestroyed) return;
|
|
3502
3812
|
this.mathLoadPending = true;
|
|
3503
3813
|
void preloadMathJax().then(() => {
|
|
3504
3814
|
this.mathLoadPending = false;
|
|
3505
3815
|
if (this.isDestroyed) return;
|
|
3506
|
-
if (
|
|
3816
|
+
if (isMathJaxReady()) this.retypesetFromTokens();
|
|
3507
3817
|
this.flushAppendSettledWaiters();
|
|
3508
3818
|
});
|
|
3509
3819
|
}
|
|
@@ -3796,6 +4106,12 @@ var Markdown = class _Markdown extends import_ui2.UIComponent {
|
|
|
3796
4106
|
case "list":
|
|
3797
4107
|
case "table":
|
|
3798
4108
|
case "hr":
|
|
4109
|
+
// A footnote definition is the only block-level token this package adds, so
|
|
4110
|
+
// it is the only one for which this three-way lockstep (here,
|
|
4111
|
+
// `renderToken`, `reflowToken`) has to be established rather than inherited.
|
|
4112
|
+
// It renders its own block, so it produces an entity — see `renderToken`'s
|
|
4113
|
+
// arm for why in place rather than collected into a document footer.
|
|
4114
|
+
case "footnoteDef":
|
|
3799
4115
|
return true;
|
|
3800
4116
|
default:
|
|
3801
4117
|
return "text" in token;
|
|
@@ -3823,10 +4139,10 @@ var Markdown = class _Markdown extends import_ui2.UIComponent {
|
|
|
3823
4139
|
const width = intrinsicW * scale;
|
|
3824
4140
|
const height = intrinsicH * scale;
|
|
3825
4141
|
const uri = mathData.uri;
|
|
3826
|
-
const math = new
|
|
4142
|
+
const math = new import_ui4.RichText(
|
|
3827
4143
|
[
|
|
3828
4144
|
{
|
|
3829
|
-
text:
|
|
4145
|
+
text: import_core4.OBJECT_REPLACEMENT,
|
|
3830
4146
|
object: {
|
|
3831
4147
|
width,
|
|
3832
4148
|
height,
|
|
@@ -3866,15 +4182,15 @@ var Markdown = class _Markdown extends import_ui2.UIComponent {
|
|
|
3866
4182
|
};
|
|
3867
4183
|
const availableWidth = metrics.availableWidth;
|
|
3868
4184
|
if (containsInlineMath(token)) {
|
|
3869
|
-
if (!
|
|
4185
|
+
if (!isMathJaxReady()) this.ensureMathJax();
|
|
3870
4186
|
this.subscribeInlineMathRepaint();
|
|
3871
4187
|
}
|
|
4188
|
+
if (containsImage([token])) this.subscribeInlineImageRemeasure();
|
|
3872
4189
|
switch (token.type) {
|
|
3873
4190
|
// ── Headings ─────────────────────────────────────────────────────
|
|
3874
4191
|
case "heading": {
|
|
3875
4192
|
const hToken = token;
|
|
3876
|
-
const
|
|
3877
|
-
const size = sizes[Math.min(hToken.depth - 1, 5)];
|
|
4193
|
+
const size = headingSize(t, hToken.depth);
|
|
3878
4194
|
const headingFont = `bold ${size}px ${t.bodyFont}`;
|
|
3879
4195
|
return renderInlineToRichText(
|
|
3880
4196
|
hToken.tokens,
|
|
@@ -3902,9 +4218,9 @@ var Markdown = class _Markdown extends import_ui2.UIComponent {
|
|
|
3902
4218
|
this.onLinkClick
|
|
3903
4219
|
);
|
|
3904
4220
|
}
|
|
3905
|
-
const stack = new
|
|
4221
|
+
const stack = new import_ui4.Stack({
|
|
3906
4222
|
direction: "vertical",
|
|
3907
|
-
gap:
|
|
4223
|
+
gap: this.theme.blockGap,
|
|
3908
4224
|
maxWidth: availableWidth
|
|
3909
4225
|
});
|
|
3910
4226
|
let currentTokens = [];
|
|
@@ -3950,28 +4266,43 @@ var Markdown = class _Markdown extends import_ui2.UIComponent {
|
|
|
3950
4266
|
// ── Blockquotes ──────────────────────────────────────────────────
|
|
3951
4267
|
case "blockquote": {
|
|
3952
4268
|
const bqToken = token;
|
|
3953
|
-
const innerStack = new
|
|
3954
|
-
|
|
4269
|
+
const innerStack = new import_ui4.Stack({
|
|
4270
|
+
direction: "vertical",
|
|
4271
|
+
gap: this.theme.quoteInnerGap
|
|
4272
|
+
});
|
|
4273
|
+
const indentStart = Math.min(this.theme.quoteIndent, availableWidth);
|
|
3955
4274
|
const childMetrics = {
|
|
3956
4275
|
marginBefore: 0,
|
|
3957
4276
|
marginAfter: 0,
|
|
3958
4277
|
indentStart,
|
|
3959
4278
|
availableWidth: Math.max(0, availableWidth - indentStart)
|
|
3960
4279
|
};
|
|
3961
|
-
|
|
3962
|
-
|
|
3963
|
-
|
|
3964
|
-
|
|
3965
|
-
|
|
3966
|
-
|
|
3967
|
-
|
|
3968
|
-
|
|
3969
|
-
|
|
3970
|
-
|
|
4280
|
+
const outerTheme = this.theme;
|
|
4281
|
+
if (t.quoteTextColor !== t.textColor) {
|
|
4282
|
+
this.theme = { ...outerTheme, textColor: t.quoteTextColor };
|
|
4283
|
+
}
|
|
4284
|
+
try {
|
|
4285
|
+
if (bqToken.tokens) {
|
|
4286
|
+
for (const inner of bqToken.tokens) {
|
|
4287
|
+
const el = this.renderTokenWithMetrics(inner, childMetrics);
|
|
4288
|
+
if (el) {
|
|
4289
|
+
const wrapper = new MarkdownContainer();
|
|
4290
|
+
el.x = childMetrics.indentStart;
|
|
4291
|
+
wrapper.add(el);
|
|
4292
|
+
wrapper.width = el.width + childMetrics.indentStart;
|
|
4293
|
+
wrapper.height = el.height;
|
|
4294
|
+
innerStack.add(wrapper);
|
|
4295
|
+
}
|
|
3971
4296
|
}
|
|
3972
4297
|
}
|
|
4298
|
+
} finally {
|
|
4299
|
+
this.theme = outerTheme;
|
|
3973
4300
|
}
|
|
3974
|
-
const border = new QuoteBorder(
|
|
4301
|
+
const border = new QuoteBorder(
|
|
4302
|
+
innerStack.height || 20,
|
|
4303
|
+
t.quoteBorderColor,
|
|
4304
|
+
t.quoteBorderWidth
|
|
4305
|
+
);
|
|
3975
4306
|
const container = new MarkdownContainer();
|
|
3976
4307
|
border.x = 0;
|
|
3977
4308
|
border.y = 0;
|
|
@@ -3986,7 +4317,10 @@ var Markdown = class _Markdown extends import_ui2.UIComponent {
|
|
|
3986
4317
|
// ── Lists ────────────────────────────────────────────────
|
|
3987
4318
|
case "list": {
|
|
3988
4319
|
const listToken = token;
|
|
3989
|
-
const listStack = new
|
|
4320
|
+
const listStack = new import_ui4.Stack({
|
|
4321
|
+
direction: "vertical",
|
|
4322
|
+
gap: this.theme.listGap
|
|
4323
|
+
});
|
|
3990
4324
|
for (let i = 0; i < listToken.items.length; i++) {
|
|
3991
4325
|
listStack.add(
|
|
3992
4326
|
this.itemIsInlineOnly(listToken.items[i]) ? this.listItemRichText(listToken, i, availableWidth, t) : this.listItemBlockStack(listToken, i, availableWidth, t)
|
|
@@ -4002,7 +4336,7 @@ var Markdown = class _Markdown extends import_ui2.UIComponent {
|
|
|
4002
4336
|
(row) => row.map((cell) => this.tableCellRichText(cell, false, t))
|
|
4003
4337
|
);
|
|
4004
4338
|
return this.withBlockAffordances(
|
|
4005
|
-
new
|
|
4339
|
+
new import_ui4.Table({
|
|
4006
4340
|
headers,
|
|
4007
4341
|
rows,
|
|
4008
4342
|
// `| :--- | :---: | ---: |` already resolves to this on the token; it
|
|
@@ -4011,7 +4345,7 @@ var Markdown = class _Markdown extends import_ui2.UIComponent {
|
|
|
4011
4345
|
width: availableWidth,
|
|
4012
4346
|
textColor: t.textColor,
|
|
4013
4347
|
headerTextColor: t.headingColor,
|
|
4014
|
-
font: `${t.
|
|
4348
|
+
font: `${t.tableFontSize}px ${t.bodyFont}`,
|
|
4015
4349
|
borderColor: t.hrColor,
|
|
4016
4350
|
bg: t.tableBgColor,
|
|
4017
4351
|
headerBg: t.tableHeaderBgColor,
|
|
@@ -4020,6 +4354,24 @@ var Markdown = class _Markdown extends import_ui2.UIComponent {
|
|
|
4020
4354
|
() => this.tableAffordances(tblToken)
|
|
4021
4355
|
);
|
|
4022
4356
|
}
|
|
4357
|
+
// ── Footnote definition (`[^1]: note`) ───────────────────────────
|
|
4358
|
+
case "footnoteDef": {
|
|
4359
|
+
const fnToken = token;
|
|
4360
|
+
const spans = [
|
|
4361
|
+
{
|
|
4362
|
+
text: footnoteMarker(fnToken.label),
|
|
4363
|
+
style: { color: t.footnoteColor }
|
|
4364
|
+
},
|
|
4365
|
+
{ text: " " }
|
|
4366
|
+
];
|
|
4367
|
+
if (fnToken.body) spans.push({ text: decodeEntities(fnToken.body) });
|
|
4368
|
+
return new import_ui4.RichText(spans, {
|
|
4369
|
+
font: bodyFont,
|
|
4370
|
+
color: t.textColor,
|
|
4371
|
+
maxWidth: availableWidth,
|
|
4372
|
+
selectable: this.selectable
|
|
4373
|
+
});
|
|
4374
|
+
}
|
|
4023
4375
|
// ── Horizontal rule ──────────────────────────────────────────────
|
|
4024
4376
|
case "hr":
|
|
4025
4377
|
return new HorizontalRule(availableWidth, t.hrColor);
|
|
@@ -4030,18 +4382,18 @@ var Markdown = class _Markdown extends import_ui2.UIComponent {
|
|
|
4030
4382
|
case "html": {
|
|
4031
4383
|
const htmlToken = token;
|
|
4032
4384
|
if (htmlToken.text.toLowerCase().includes("<svg") && htmlToken.text.toLowerCase().includes("</svg>")) {
|
|
4033
|
-
return new
|
|
4385
|
+
return new import_core4.SVGEntity(htmlToken.text);
|
|
4034
4386
|
}
|
|
4035
4387
|
return null;
|
|
4036
4388
|
}
|
|
4037
4389
|
// ── Fallback ─────────────────────────────────────────────────────
|
|
4038
4390
|
default:
|
|
4039
4391
|
if ("text" in token) {
|
|
4040
|
-
return new
|
|
4392
|
+
return new import_ui4.Text(token.text, {
|
|
4041
4393
|
font: bodyFont,
|
|
4042
4394
|
color: t.textColor,
|
|
4043
4395
|
maxWidth: availableWidth,
|
|
4044
|
-
lineHeight:
|
|
4396
|
+
lineHeight: t.bodyLineHeight,
|
|
4045
4397
|
selectable: this.selectable
|
|
4046
4398
|
});
|
|
4047
4399
|
}
|
|
@@ -4064,6 +4416,7 @@ var Markdown = class _Markdown extends import_ui2.UIComponent {
|
|
|
4064
4416
|
escapeCsvField,
|
|
4065
4417
|
escapeMarkdownTableCell,
|
|
4066
4418
|
extensionForLanguage,
|
|
4419
|
+
footnoteMarker,
|
|
4067
4420
|
isMathJaxReady,
|
|
4068
4421
|
mimeForLanguage,
|
|
4069
4422
|
parseFrontMatterFields,
|