@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.mjs
CHANGED
|
@@ -1,11 +1,7 @@
|
|
|
1
1
|
// src/Markdown.ts
|
|
2
2
|
import {
|
|
3
|
-
contentLineInHint,
|
|
4
3
|
BidiResolver,
|
|
5
|
-
|
|
6
|
-
GlyphRasterAtlas,
|
|
7
|
-
OBJECT_REPLACEMENT,
|
|
8
|
-
prepareContentGrid,
|
|
4
|
+
OBJECT_REPLACEMENT as OBJECT_REPLACEMENT2,
|
|
9
5
|
SVGEntity,
|
|
10
6
|
beginVectoUserTiming,
|
|
11
7
|
endVectoUserTiming,
|
|
@@ -422,754 +418,118 @@ function createStreamController(host, options = {}) {
|
|
|
422
418
|
return new StreamControllerImpl(host, options);
|
|
423
419
|
}
|
|
424
420
|
|
|
425
|
-
// src/
|
|
426
|
-
import {
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
} from "@vectojs/ui";
|
|
435
|
-
|
|
436
|
-
// src/blockAffordances.ts
|
|
437
|
-
import { Button, measureText, UIComponent } from "@vectojs/ui";
|
|
438
|
-
var LANGUAGE_EXTENSIONS = {
|
|
439
|
-
bash: "sh",
|
|
440
|
-
c: "c",
|
|
441
|
-
cpp: "cpp",
|
|
442
|
-
cs: "cs",
|
|
443
|
-
css: "css",
|
|
444
|
-
diff: "diff",
|
|
445
|
-
dockerfile: "dockerfile",
|
|
446
|
-
go: "go",
|
|
447
|
-
graphql: "graphql",
|
|
448
|
-
haskell: "hs",
|
|
449
|
-
html: "html",
|
|
450
|
-
java: "java",
|
|
451
|
-
javascript: "js",
|
|
452
|
-
js: "js",
|
|
453
|
-
json: "json",
|
|
454
|
-
jsonc: "jsonc",
|
|
455
|
-
jsx: "jsx",
|
|
456
|
-
kotlin: "kt",
|
|
457
|
-
latex: "tex",
|
|
458
|
-
lua: "lua",
|
|
459
|
-
make: "mk",
|
|
460
|
-
markdown: "md",
|
|
461
|
-
md: "md",
|
|
462
|
-
nix: "nix",
|
|
463
|
-
php: "php",
|
|
464
|
-
python: "py",
|
|
465
|
-
py: "py",
|
|
466
|
-
ruby: "rb",
|
|
467
|
-
rust: "rs",
|
|
468
|
-
rs: "rs",
|
|
469
|
-
scss: "scss",
|
|
470
|
-
sh: "sh",
|
|
471
|
-
shell: "sh",
|
|
472
|
-
sql: "sql",
|
|
473
|
-
svelte: "svelte",
|
|
474
|
-
swift: "swift",
|
|
475
|
-
tex: "tex",
|
|
476
|
-
toml: "toml",
|
|
477
|
-
ts: "ts",
|
|
478
|
-
tsx: "tsx",
|
|
479
|
-
typescript: "ts",
|
|
480
|
-
vue: "vue",
|
|
481
|
-
xml: "xml",
|
|
482
|
-
yaml: "yaml",
|
|
483
|
-
yml: "yaml",
|
|
484
|
-
zig: "zig",
|
|
485
|
-
zsh: "sh"
|
|
486
|
-
};
|
|
487
|
-
function extensionForLanguage(lang) {
|
|
488
|
-
const first = lang.trim().toLowerCase().split(/[\s:,{]/)[0] ?? "";
|
|
489
|
-
return LANGUAGE_EXTENSIONS[first] ?? "txt";
|
|
490
|
-
}
|
|
491
|
-
function mimeForLanguage(lang) {
|
|
492
|
-
const ext = extensionForLanguage(lang);
|
|
493
|
-
if (ext === "json" || ext === "jsonc") return "application/json";
|
|
494
|
-
if (ext === "html") return "text/html";
|
|
495
|
-
if (ext === "css") return "text/css";
|
|
496
|
-
if (ext === "xml" || ext === "svelte" || ext === "vue") return "text/plain";
|
|
497
|
-
return "text/plain";
|
|
498
|
-
}
|
|
499
|
-
function escapeCsvField(value) {
|
|
500
|
-
let needsQuoting = false;
|
|
501
|
-
let hasQuote = false;
|
|
502
|
-
for (const char of value) {
|
|
503
|
-
if (char === '"') {
|
|
504
|
-
hasQuote = true;
|
|
505
|
-
needsQuoting = true;
|
|
506
|
-
break;
|
|
507
|
-
}
|
|
508
|
-
if (char === "," || char === "\n" || char === "\r") needsQuoting = true;
|
|
509
|
-
}
|
|
510
|
-
if (!needsQuoting) return value;
|
|
511
|
-
return hasQuote ? `"${value.replace(/"/g, '""')}"` : `"${value}"`;
|
|
512
|
-
}
|
|
513
|
-
function escapeMarkdownTableCell(cell) {
|
|
514
|
-
let needsEscaping = false;
|
|
515
|
-
for (const char of cell) {
|
|
516
|
-
if (char === "\\" || char === "|") {
|
|
517
|
-
needsEscaping = true;
|
|
518
|
-
break;
|
|
519
|
-
}
|
|
520
|
-
}
|
|
521
|
-
if (!needsEscaping) return cell;
|
|
522
|
-
return cell.replace(/\\/g, "\\\\").replace(/\|/g, "\\|");
|
|
523
|
-
}
|
|
524
|
-
function tableToCsv(table) {
|
|
525
|
-
const lines = [table.headers.map(escapeCsvField).join(",")];
|
|
526
|
-
for (const row of table.rows) lines.push(row.map(escapeCsvField).join(","));
|
|
527
|
-
return `\uFEFF${lines.join("\r\n")}`;
|
|
528
|
-
}
|
|
529
|
-
function tableToMarkdown(table) {
|
|
530
|
-
const header = `| ${table.headers.map(escapeMarkdownTableCell).join(" | ")} |`;
|
|
531
|
-
const divider = `| ${table.headers.map((_cell, index) => {
|
|
532
|
-
switch (table.align[index]) {
|
|
533
|
-
case "left":
|
|
534
|
-
return ":---";
|
|
535
|
-
case "center":
|
|
536
|
-
return ":---:";
|
|
537
|
-
case "right":
|
|
538
|
-
return "---:";
|
|
539
|
-
default:
|
|
540
|
-
return "---";
|
|
541
|
-
}
|
|
542
|
-
}).join(" | ")} |`;
|
|
543
|
-
const body = table.rows.map(
|
|
544
|
-
(row) => `| ${table.headers.map((_cell, index) => escapeMarkdownTableCell(row[index] ?? "")).join(" | ")} |`
|
|
545
|
-
);
|
|
546
|
-
return [header, divider, ...body].join("\n");
|
|
547
|
-
}
|
|
548
|
-
function defaultWriteClipboard(text) {
|
|
549
|
-
const clipboard = globalThis.navigator?.clipboard;
|
|
550
|
-
clipboard?.writeText?.(text);
|
|
551
|
-
}
|
|
552
|
-
function defaultSaveFile(filename, content, mimeType) {
|
|
553
|
-
const doc = globalThis.document;
|
|
554
|
-
if (!doc?.body) return;
|
|
555
|
-
const blob = new Blob([content], { type: mimeType });
|
|
556
|
-
const url = URL.createObjectURL(blob);
|
|
557
|
-
const anchor = doc.createElement("a");
|
|
558
|
-
anchor.href = url;
|
|
559
|
-
anchor.download = filename;
|
|
560
|
-
doc.body.appendChild(anchor);
|
|
561
|
-
anchor.click();
|
|
562
|
-
doc.body.removeChild(anchor);
|
|
563
|
-
URL.revokeObjectURL(url);
|
|
564
|
-
}
|
|
565
|
-
var BlockAffordanceButton = class _BlockAffordanceButton extends Button {
|
|
566
|
-
constructor(label, successLabel, act, opts = {}) {
|
|
567
|
-
super(label, { ...opts, onClick: () => this.run() });
|
|
568
|
-
this.act = act;
|
|
569
|
-
this.restingLabel = label;
|
|
570
|
-
this.successLabel = successLabel;
|
|
571
|
-
this.width = Math.max(this.width, measureText(successLabel, this.font) + 24);
|
|
572
|
-
}
|
|
573
|
-
act;
|
|
574
|
-
/** How long the confirmation label stays up, in ms. */
|
|
575
|
-
static FEEDBACK_MS = 1600;
|
|
576
|
-
restingLabel;
|
|
577
|
-
successLabel;
|
|
578
|
-
feedbackTimer;
|
|
579
|
-
/**
|
|
580
|
-
* Runs the action, then shows the confirmation.
|
|
581
|
-
*
|
|
582
|
-
* The action runs first and a throw propagates: a clipboard write the browser
|
|
583
|
-
* rejected must not be reported as a success.
|
|
584
|
-
*/
|
|
585
|
-
run() {
|
|
586
|
-
this.act();
|
|
587
|
-
this.setTransientLabel(this.successLabel);
|
|
588
|
-
if (this.feedbackTimer !== void 0) clearTimeout(this.feedbackTimer);
|
|
589
|
-
this.feedbackTimer = setTimeout(() => {
|
|
590
|
-
this.setTransientLabel(this.restingLabel);
|
|
591
|
-
this.feedbackTimer = void 0;
|
|
592
|
-
}, _BlockAffordanceButton.FEEDBACK_MS);
|
|
593
|
-
}
|
|
594
|
-
setTransientLabel(label) {
|
|
595
|
-
this.label = label;
|
|
596
|
-
this.textWidth = measureText(label, this.font);
|
|
597
|
-
this.scene?.markDirty();
|
|
421
|
+
// src/markdown-entities.ts
|
|
422
|
+
import { Entity } from "@vectojs/core";
|
|
423
|
+
var HorizontalRule = class extends Entity {
|
|
424
|
+
color;
|
|
425
|
+
constructor(w, color) {
|
|
426
|
+
super();
|
|
427
|
+
this.width = w;
|
|
428
|
+
this.height = 1;
|
|
429
|
+
this.color = color;
|
|
598
430
|
}
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
* included, so an AT user gets the same feedback a sighted user does.
|
|
602
|
-
*/
|
|
603
|
-
getA11yAttributes() {
|
|
604
|
-
return { ...super.getA11yAttributes(), label: this.label };
|
|
431
|
+
isPointInside() {
|
|
432
|
+
return false;
|
|
605
433
|
}
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
|
|
611
|
-
}
|
|
612
|
-
super.destroy();
|
|
434
|
+
render(r) {
|
|
435
|
+
r.beginPath();
|
|
436
|
+
r.moveTo(0, 0);
|
|
437
|
+
r.lineTo(this.width, 0);
|
|
438
|
+
r.stroke(this.color, 1);
|
|
613
439
|
}
|
|
614
440
|
};
|
|
615
|
-
var
|
|
616
|
-
|
|
441
|
+
var QuoteBorder = class extends Entity {
|
|
442
|
+
color;
|
|
443
|
+
constructor(height, color, width = 4) {
|
|
617
444
|
super();
|
|
618
|
-
this.
|
|
619
|
-
this.
|
|
620
|
-
this.
|
|
621
|
-
for (const control of controls) this.add(control);
|
|
622
|
-
this.layoutAffordances();
|
|
623
|
-
}
|
|
624
|
-
block;
|
|
625
|
-
controls;
|
|
626
|
-
/** Gap between the block's edges and the controls, in px. */
|
|
627
|
-
static INSET = 8;
|
|
628
|
-
/** Gap between adjacent controls, in px. */
|
|
629
|
-
static GAP = 6;
|
|
630
|
-
/**
|
|
631
|
-
* Places the controls right-aligned along the block's top edge.
|
|
632
|
-
*
|
|
633
|
-
* Laid out right-to-left from the block's right edge so the first control in
|
|
634
|
-
* the list ends up leftmost, which keeps DOM order (and therefore tab order and
|
|
635
|
-
* the a11y reading order) matching the visual order.
|
|
636
|
-
*/
|
|
637
|
-
layoutAffordances() {
|
|
638
|
-
this.width = this.block.width;
|
|
639
|
-
this.height = this.block.height;
|
|
640
|
-
let right = this.block.width - _BlockWithAffordances.INSET;
|
|
641
|
-
for (let i = this.controls.length - 1; i >= 0; i--) {
|
|
642
|
-
const control = this.controls[i];
|
|
643
|
-
control.x = right - control.width;
|
|
644
|
-
control.y = _BlockWithAffordances.INSET;
|
|
645
|
-
right = control.x - _BlockWithAffordances.GAP;
|
|
646
|
-
}
|
|
445
|
+
this.width = width;
|
|
446
|
+
this.height = height;
|
|
447
|
+
this.color = color;
|
|
647
448
|
}
|
|
648
|
-
|
|
649
|
-
|
|
650
|
-
*
|
|
651
|
-
* Called by the owner when a block is resized or its content grew; the controls
|
|
652
|
-
* are anchored to the right edge, so a width change moves them.
|
|
653
|
-
*/
|
|
654
|
-
refreshAffordances() {
|
|
655
|
-
this.layoutAffordances();
|
|
656
|
-
this.scene?.markDirty();
|
|
449
|
+
isPointInside() {
|
|
450
|
+
return false;
|
|
657
451
|
}
|
|
658
|
-
|
|
659
|
-
|
|
660
|
-
|
|
452
|
+
render(r) {
|
|
453
|
+
r.beginPath();
|
|
454
|
+
r.roundRect(0, 0, this.width, this.height, this.width / 2);
|
|
455
|
+
r.fill(this.color);
|
|
661
456
|
}
|
|
662
|
-
|
|
663
|
-
|
|
664
|
-
|
|
665
|
-
|
|
666
|
-
getA11yAttributes() {
|
|
667
|
-
return { role: "group", pointerEvents: "none" };
|
|
457
|
+
};
|
|
458
|
+
var MarkdownContainer = class extends Entity {
|
|
459
|
+
isPointInside(_globalX, _globalY) {
|
|
460
|
+
return false;
|
|
668
461
|
}
|
|
669
|
-
render() {
|
|
462
|
+
render(_r) {
|
|
670
463
|
}
|
|
671
464
|
};
|
|
672
|
-
function tableContentOf(token) {
|
|
673
|
-
return {
|
|
674
|
-
headers: token.header.map((cell) => cell.text),
|
|
675
|
-
rows: token.rows.map((row) => row.map((cell) => cell.text)),
|
|
676
|
-
align: token.align
|
|
677
|
-
};
|
|
678
|
-
}
|
|
679
|
-
|
|
680
|
-
// src/frontMatter.ts
|
|
681
|
-
var OPEN_RE = /^---[ \t]*\r?\n/;
|
|
682
|
-
var OPENER_PREFIX_RE = /^(?:-|--|---[ \t]*\r?)$/;
|
|
683
|
-
var KEY_RE = /^[^\s:#][^:]*:(?:[ \t].*)?$/;
|
|
684
|
-
var CLOSE_RE = /^(?:---|\.\.\.)[ \t]*$/;
|
|
685
|
-
var MAX_PENDING_CHARS = 4096;
|
|
686
|
-
var NONE = { kind: "none" };
|
|
687
|
-
var PENDING = { kind: "pending" };
|
|
688
|
-
function scanFrontMatter(text, complete) {
|
|
689
|
-
if (text.length === 0) return PENDING;
|
|
690
|
-
const open = OPEN_RE.exec(text);
|
|
691
|
-
if (!open) {
|
|
692
|
-
return !complete && OPENER_PREFIX_RE.test(text) ? PENDING : NONE;
|
|
693
|
-
}
|
|
694
|
-
const decide = complete || text.length > MAX_PENDING_CHARS;
|
|
695
|
-
const contentStart = open[0].length;
|
|
696
|
-
let cursor = contentStart;
|
|
697
|
-
let keyChecked = false;
|
|
698
|
-
while (cursor < text.length) {
|
|
699
|
-
const nl = text.indexOf("\n", cursor);
|
|
700
|
-
if (nl === -1 && !decide) return PENDING;
|
|
701
|
-
const line = text.slice(cursor, nl === -1 ? text.length : nl).replace(/\r$/, "");
|
|
702
|
-
if (!keyChecked) {
|
|
703
|
-
if (!KEY_RE.test(line)) return NONE;
|
|
704
|
-
keyChecked = true;
|
|
705
|
-
} else if (CLOSE_RE.test(line)) {
|
|
706
|
-
return {
|
|
707
|
-
kind: "found",
|
|
708
|
-
raw: text.slice(contentStart, cursor),
|
|
709
|
-
// A closer with no trailing newline ends the document, so the body is
|
|
710
|
-
// empty rather than starting one character past the end.
|
|
711
|
-
bodyStart: nl === -1 ? text.length : nl + 1
|
|
712
|
-
};
|
|
713
|
-
}
|
|
714
|
-
if (nl === -1) break;
|
|
715
|
-
cursor = nl + 1;
|
|
716
|
-
}
|
|
717
|
-
return decide ? NONE : PENDING;
|
|
718
|
-
}
|
|
719
|
-
function parseFrontMatterFields(raw) {
|
|
720
|
-
const out = {};
|
|
721
|
-
for (const rawLine of raw.split("\n")) {
|
|
722
|
-
const line = rawLine.replace(/\r$/, "");
|
|
723
|
-
if (line.length === 0 || /^[\s#]/.test(line)) continue;
|
|
724
|
-
const sep = line.indexOf(":");
|
|
725
|
-
if (sep <= 0) continue;
|
|
726
|
-
const value = line.slice(sep + 1);
|
|
727
|
-
if (value.length > 0 && value[0] !== " " && value[0] !== " ") continue;
|
|
728
|
-
out[line.slice(0, sep).trim()] = unquote(value.trim());
|
|
729
|
-
}
|
|
730
|
-
return out;
|
|
731
|
-
}
|
|
732
|
-
function unquote(value) {
|
|
733
|
-
if (value.length < 2) return value;
|
|
734
|
-
const first = value[0];
|
|
735
|
-
if ((first === '"' || first === "'") && value.endsWith(first)) {
|
|
736
|
-
return value.slice(1, -1);
|
|
737
|
-
}
|
|
738
|
-
return value;
|
|
739
|
-
}
|
|
740
465
|
|
|
741
|
-
// src/
|
|
742
|
-
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';
|
|
466
|
+
// src/markdown-code.ts
|
|
467
|
+
import {
|
|
468
|
+
contentLineInHint,
|
|
469
|
+
GlyphRasterAtlas,
|
|
470
|
+
prepareContentGrid
|
|
471
|
+
} from "@vectojs/core";
|
|
472
|
+
import { measureText, UIComponent } from "@vectojs/ui";
|
|
743
473
|
|
|
744
|
-
// src/
|
|
745
|
-
var
|
|
746
|
-
|
|
747
|
-
|
|
748
|
-
|
|
749
|
-
|
|
750
|
-
|
|
751
|
-
|
|
752
|
-
|
|
753
|
-
|
|
754
|
-
|
|
755
|
-
|
|
756
|
-
|
|
757
|
-
|
|
758
|
-
|
|
759
|
-
|
|
760
|
-
|
|
761
|
-
|
|
762
|
-
|
|
763
|
-
|
|
764
|
-
|
|
765
|
-
|
|
766
|
-
|
|
767
|
-
|
|
768
|
-
|
|
769
|
-
|
|
770
|
-
|
|
771
|
-
|
|
772
|
-
|
|
773
|
-
|
|
774
|
-
|
|
775
|
-
|
|
776
|
-
|
|
777
|
-
|
|
778
|
-
|
|
779
|
-
|
|
780
|
-
|
|
781
|
-
|
|
782
|
-
|
|
783
|
-
|
|
784
|
-
|
|
785
|
-
|
|
786
|
-
if (match) {
|
|
787
|
-
return {
|
|
788
|
-
type: "inlineMath",
|
|
789
|
-
raw: match[0],
|
|
790
|
-
text: match[1].trim()
|
|
791
|
-
};
|
|
792
|
-
}
|
|
793
|
-
return void 0;
|
|
794
|
-
},
|
|
795
|
-
renderer(token) {
|
|
796
|
-
return token.raw;
|
|
797
|
-
}
|
|
798
|
-
}
|
|
799
|
-
]
|
|
800
|
-
});
|
|
801
|
-
var mathConverter = null;
|
|
802
|
-
var mathLoad = null;
|
|
803
|
-
function interop(mod, key) {
|
|
804
|
-
const ns = mod;
|
|
805
|
-
if (typeof ns?.[key] !== "undefined") return ns;
|
|
806
|
-
const fallback = ns?.default;
|
|
807
|
-
if (fallback && typeof fallback[key] !== "undefined") return fallback;
|
|
808
|
-
throw new Error(`mathjax-full module is missing export "${key}"`);
|
|
809
|
-
}
|
|
810
|
-
function preloadMathJax() {
|
|
811
|
-
if (mathLoad) return mathLoad;
|
|
812
|
-
mathLoad = (async () => {
|
|
813
|
-
const [mathjaxMod, texMod, svgMod, adaptorMod, handlerMod, packagesMod] = await Promise.all([
|
|
814
|
-
import("mathjax-full/js/mathjax.js"),
|
|
815
|
-
import("mathjax-full/js/input/tex.js"),
|
|
816
|
-
import("mathjax-full/js/output/svg.js"),
|
|
817
|
-
import("mathjax-full/js/adaptors/liteAdaptor.js"),
|
|
818
|
-
import("mathjax-full/js/handlers/html.js"),
|
|
819
|
-
import("mathjax-full/js/input/tex/AllPackages.js")
|
|
820
|
-
]);
|
|
821
|
-
const { mathjax } = interop(mathjaxMod, "mathjax");
|
|
822
|
-
const { TeX } = interop(texMod, "TeX");
|
|
823
|
-
const { SVG } = interop(svgMod, "SVG");
|
|
824
|
-
const { liteAdaptor } = interop(adaptorMod, "liteAdaptor");
|
|
825
|
-
const { RegisterHTMLHandler } = interop(handlerMod, "RegisterHTMLHandler");
|
|
826
|
-
const { AllPackages } = interop(packagesMod, "AllPackages");
|
|
827
|
-
const adaptor = liteAdaptor();
|
|
828
|
-
RegisterHTMLHandler(adaptor);
|
|
829
|
-
const tex = new TeX({ packages: AllPackages });
|
|
830
|
-
const svg = new SVG({ fontCache: "local" });
|
|
831
|
-
const htmlMathJax = mathjax.document("", { InputJax: tex, OutputJax: svg });
|
|
832
|
-
mathConverter = (formula, displayMode, color) => convertMathToSVGDataURI(
|
|
833
|
-
formula,
|
|
834
|
-
displayMode,
|
|
835
|
-
(f, d) => adaptor.innerHTML(htmlMathJax.convert(f, { display: d })),
|
|
836
|
-
color
|
|
837
|
-
);
|
|
838
|
-
})().catch((e) => {
|
|
839
|
-
console.error("MathJax failed to load; formulas will render as TeX source", e);
|
|
840
|
-
});
|
|
841
|
-
return mathLoad;
|
|
842
|
-
}
|
|
843
|
-
function isMathJaxReady() {
|
|
844
|
-
return mathConverter !== null;
|
|
845
|
-
}
|
|
846
|
-
var EX_PER_EM = 0.4421;
|
|
847
|
-
function exToPx(ex, fontSize) {
|
|
848
|
-
return ex * fontSize * EX_PER_EM;
|
|
849
|
-
}
|
|
850
|
-
function fontSizeFromFont(font) {
|
|
851
|
-
const pxIndex = font.indexOf("px");
|
|
852
|
-
if (pxIndex <= 0) return void 0;
|
|
853
|
-
let start = pxIndex;
|
|
854
|
-
while (start > 0) {
|
|
855
|
-
const ch = font[start - 1];
|
|
856
|
-
if (ch >= "0" && ch <= "9" || ch === ".") start--;
|
|
857
|
-
else break;
|
|
858
|
-
}
|
|
859
|
-
if (start === pxIndex) return void 0;
|
|
860
|
-
const size = parseFloat(font.slice(start, pxIndex));
|
|
861
|
-
return Number.isFinite(size) ? size : void 0;
|
|
862
|
-
}
|
|
863
|
-
var mathCache = /* @__PURE__ */ new Map();
|
|
864
|
-
var MATH_CACHE_LIMIT = 256;
|
|
865
|
-
var inlineMathRasters = /* @__PURE__ */ new Map();
|
|
866
|
-
var inlineMathRasterWaiters = /* @__PURE__ */ new Set();
|
|
867
|
-
function ensureInlineMathRaster(uri) {
|
|
868
|
-
const existing = inlineMathRasters.get(uri);
|
|
869
|
-
if (existing) return existing;
|
|
870
|
-
const entry = { decoded: false };
|
|
871
|
-
inlineMathRasters.set(uri, entry);
|
|
872
|
-
if (typeof globalThis.Image !== "undefined") {
|
|
873
|
-
const bitmap = new globalThis.Image();
|
|
874
|
-
bitmap.onload = () => {
|
|
875
|
-
entry.decoded = true;
|
|
876
|
-
for (const notify of inlineMathRasterWaiters) notify();
|
|
877
|
-
};
|
|
878
|
-
bitmap.src = uri;
|
|
879
|
-
entry.bitmap = bitmap;
|
|
880
|
-
}
|
|
881
|
-
return entry;
|
|
882
|
-
}
|
|
883
|
-
function paintInlineMath(uri, surface, box) {
|
|
884
|
-
const raster = ensureInlineMathRaster(uri);
|
|
885
|
-
if (!raster.decoded || !raster.bitmap) return;
|
|
886
|
-
surface.drawImage(raster.bitmap, box.x, box.y, box.width, box.height);
|
|
887
|
-
}
|
|
888
|
-
var MATH_LANGS = /* @__PURE__ */ new Set(["math", "latex", "tex"]);
|
|
889
|
-
function containsInlineMath(token) {
|
|
890
|
-
if (token.type === "inlineMath") return true;
|
|
891
|
-
const anyToken = token;
|
|
892
|
-
if (Array.isArray(anyToken.tokens) && anyToken.tokens.some(containsInlineMath)) {
|
|
893
|
-
return true;
|
|
894
|
-
}
|
|
895
|
-
if (Array.isArray(anyToken.items) && anyToken.items.some(containsInlineMath)) {
|
|
896
|
-
return true;
|
|
897
|
-
}
|
|
898
|
-
if (Array.isArray(anyToken.header) && anyToken.header.some(containsInlineMath)) {
|
|
899
|
-
return true;
|
|
900
|
-
}
|
|
901
|
-
if (Array.isArray(anyToken.rows)) {
|
|
902
|
-
for (const row of anyToken.rows) {
|
|
903
|
-
if (Array.isArray(row) && row.some(containsInlineMath)) return true;
|
|
904
|
-
}
|
|
474
|
+
// src/theme.ts
|
|
475
|
+
var DEFAULT_THEME = {
|
|
476
|
+
textColor: "#e2e8f0",
|
|
477
|
+
headingColor: "#f8fafc",
|
|
478
|
+
codeColor: "#a5f3fc",
|
|
479
|
+
codeBgColor: "rgba(30, 41, 59, 0.85)",
|
|
480
|
+
quoteBorderColor: "#6366f1",
|
|
481
|
+
quoteTextColor: "#e2e8f0",
|
|
482
|
+
hrColor: "rgba(148, 163, 184, 0.3)",
|
|
483
|
+
tableBgColor: "rgba(15, 15, 25, 0.4)",
|
|
484
|
+
tableHeaderBgColor: "rgba(255, 255, 255, 0.08)",
|
|
485
|
+
linkColor: "#38bdf8",
|
|
486
|
+
footnoteColor: "#38bdf8",
|
|
487
|
+
mathFallbackColor: "#fcd34d",
|
|
488
|
+
syntaxKeywordColor: "#c084fc",
|
|
489
|
+
syntaxStringColor: "#86efac",
|
|
490
|
+
syntaxCommentColor: "#64748b",
|
|
491
|
+
syntaxNumberColor: "#fbbf24",
|
|
492
|
+
bodyFont: "Inter, system-ui, sans-serif",
|
|
493
|
+
codeFont: 'ui-monospace, "JetBrains Mono", "Fira Code", monospace',
|
|
494
|
+
fontSize: 16,
|
|
495
|
+
headingSizes: [32, 28, 24, 20, 18, 16],
|
|
496
|
+
codeFontSize: 15,
|
|
497
|
+
tableFontSize: 14,
|
|
498
|
+
footnoteMarkerScale: 0.75,
|
|
499
|
+
codeLineHeight: 24,
|
|
500
|
+
bodyLineHeight: 24,
|
|
501
|
+
blockGap: 16,
|
|
502
|
+
codePadding: 18,
|
|
503
|
+
codeRadius: 8,
|
|
504
|
+
listGap: 6,
|
|
505
|
+
listItemGap: 4,
|
|
506
|
+
quoteIndent: 16,
|
|
507
|
+
quoteBorderWidth: 4,
|
|
508
|
+
quoteInnerGap: 8,
|
|
509
|
+
imageRadius: 8,
|
|
510
|
+
inlineImageScale: 1.15
|
|
511
|
+
};
|
|
512
|
+
function resolveTheme(theme) {
|
|
513
|
+
const merged = { ...DEFAULT_THEME, ...theme };
|
|
514
|
+
if (theme?.tableFontSize === void 0) {
|
|
515
|
+
merged.tableFontSize = Math.max(1, merged.fontSize - 2);
|
|
905
516
|
}
|
|
906
|
-
|
|
907
|
-
|
|
908
|
-
var FENCE_OPEN_RE = /^ {0,3}(`{3,}|~{3,})/;
|
|
909
|
-
var FENCE_CLOSE_RE = /^ {0,3}(`+|~+)[ \t]*$/;
|
|
910
|
-
function isFenceClosed(raw) {
|
|
911
|
-
const lines = raw.split("\n");
|
|
912
|
-
const open = FENCE_OPEN_RE.exec(lines[0]);
|
|
913
|
-
if (!open) return false;
|
|
914
|
-
const marker = open[1][0];
|
|
915
|
-
const minLen = open[1].length;
|
|
916
|
-
for (let i = 1; i < lines.length; i++) {
|
|
917
|
-
const close = FENCE_CLOSE_RE.exec(lines[i]);
|
|
918
|
-
if (close && close[1][0] === marker && close[1].length >= minLen) return true;
|
|
517
|
+
if (theme?.quoteTextColor === void 0) {
|
|
518
|
+
merged.quoteTextColor = merged.textColor;
|
|
919
519
|
}
|
|
920
|
-
|
|
921
|
-
|
|
922
|
-
function paragraphHasImage(token) {
|
|
923
|
-
return containsImage(token.tokens);
|
|
924
|
-
}
|
|
925
|
-
function containsImage(tokens) {
|
|
926
|
-
if (!tokens) return false;
|
|
927
|
-
for (const token of tokens) {
|
|
928
|
-
if (token.type === "image") return true;
|
|
929
|
-
if (containsImage(token.tokens)) return true;
|
|
520
|
+
if (theme?.footnoteColor === void 0) {
|
|
521
|
+
merged.footnoteColor = merged.linkColor;
|
|
930
522
|
}
|
|
931
|
-
return
|
|
523
|
+
return merged;
|
|
932
524
|
}
|
|
933
|
-
function
|
|
934
|
-
const
|
|
935
|
-
|
|
936
|
-
|
|
937
|
-
|
|
938
|
-
continue;
|
|
939
|
-
}
|
|
940
|
-
images.push(...imagesOf(token.tokens));
|
|
941
|
-
}
|
|
942
|
-
return images;
|
|
525
|
+
function headingSize(theme, depth) {
|
|
526
|
+
const sizes = theme.headingSizes;
|
|
527
|
+
if (sizes.length === 0) return theme.fontSize;
|
|
528
|
+
const idx = Math.min(Math.max(depth, 1) - 1, sizes.length - 1);
|
|
529
|
+
return sizes[idx] ?? theme.fontSize;
|
|
943
530
|
}
|
|
944
|
-
|
|
945
|
-
|
|
946
|
-
if (!children) return token;
|
|
947
|
-
const kept = [];
|
|
948
|
-
for (const child of children) {
|
|
949
|
-
if (child.type === "image") continue;
|
|
950
|
-
const grandchildren = child.tokens;
|
|
951
|
-
if (grandchildren && containsImage(grandchildren)) {
|
|
952
|
-
const stripped = stripImages(child);
|
|
953
|
-
const remaining = stripped.tokens;
|
|
954
|
-
if (remaining && remaining.length > 0) kept.push(stripped);
|
|
955
|
-
continue;
|
|
956
|
-
}
|
|
957
|
-
kept.push(child);
|
|
958
|
-
}
|
|
959
|
-
return { ...token, tokens: kept };
|
|
960
|
-
}
|
|
961
|
-
function liftNestedImages(tokens) {
|
|
962
|
-
const lifted = [];
|
|
963
|
-
for (const token of tokens) {
|
|
964
|
-
if (token.type === "image") {
|
|
965
|
-
lifted.push(token);
|
|
966
|
-
continue;
|
|
967
|
-
}
|
|
968
|
-
const children = token.tokens;
|
|
969
|
-
if (children && containsImage(children)) {
|
|
970
|
-
lifted.push(...liftNestedImages(children));
|
|
971
|
-
continue;
|
|
972
|
-
}
|
|
973
|
-
lifted.push(token);
|
|
974
|
-
}
|
|
975
|
-
return lifted;
|
|
976
|
-
}
|
|
977
|
-
function lastIndexOfImage(tokens) {
|
|
978
|
-
for (let i = tokens.length - 1; i >= 0; i--) {
|
|
979
|
-
if (tokens[i].type === "image") return i;
|
|
980
|
-
}
|
|
981
|
-
return -1;
|
|
982
|
-
}
|
|
983
|
-
function expectedImageParagraphChildren(tokens) {
|
|
984
|
-
let children = 0;
|
|
985
|
-
let inTextRun = false;
|
|
986
|
-
for (const token of liftNestedImages(tokens)) {
|
|
987
|
-
if (token.type === "image") {
|
|
988
|
-
children++;
|
|
989
|
-
inTextRun = false;
|
|
990
|
-
} else if (!inTextRun) {
|
|
991
|
-
children++;
|
|
992
|
-
inTextRun = true;
|
|
993
|
-
}
|
|
994
|
-
}
|
|
995
|
-
return children;
|
|
996
|
-
}
|
|
997
|
-
function rendersAsMath(token) {
|
|
998
|
-
return MATH_LANGS.has((token.lang ?? "").toLowerCase()) && token.text.trim() !== "" && isFenceClosed(token.raw);
|
|
999
|
-
}
|
|
1000
|
-
function renderMathToSVGDataURI(formula, displayMode, color) {
|
|
1001
|
-
const key = `${displayMode ? 1 : 0}\0${color}\0${formula}`;
|
|
1002
|
-
const hit = mathCache.get(key);
|
|
1003
|
-
if (hit) return hit;
|
|
1004
|
-
if (!mathConverter) return null;
|
|
1005
|
-
const converted = mathConverter(formula, displayMode, color);
|
|
1006
|
-
if (converted) {
|
|
1007
|
-
if (mathCache.size >= MATH_CACHE_LIMIT) {
|
|
1008
|
-
const oldest = mathCache.keys().next().value;
|
|
1009
|
-
if (oldest !== void 0) mathCache.delete(oldest);
|
|
1010
|
-
}
|
|
1011
|
-
mathCache.set(key, converted);
|
|
1012
|
-
}
|
|
1013
|
-
return converted;
|
|
1014
|
-
}
|
|
1015
|
-
function applyMathColor(svg, color) {
|
|
1016
|
-
const openTag = svg.match(/<svg\b[^>]*>/);
|
|
1017
|
-
if (!openTag) return svg;
|
|
1018
|
-
const tag = openTag[0];
|
|
1019
|
-
const colored = /\bstyle="/.test(tag) ? tag.replace(/\bstyle="/, `style="color:${color};`) : tag.replace(/^<svg\b/, `<svg style="color:${color}"`);
|
|
1020
|
-
return svg.replace(tag, colored);
|
|
1021
|
-
}
|
|
1022
|
-
function convertMathToSVGDataURI(formula, displayMode, typeset, color) {
|
|
1023
|
-
try {
|
|
1024
|
-
const svgString = applyMathColor(typeset(formula, displayMode), color);
|
|
1025
|
-
const wMatch = svgString.match(/width="([^"]+)ex"/);
|
|
1026
|
-
const hMatch = svgString.match(/height="([^"]+)ex"/);
|
|
1027
|
-
const wEx = wMatch ? parseFloat(wMatch[1]) : 10;
|
|
1028
|
-
const hEx = hMatch ? parseFloat(hMatch[1]) : 2;
|
|
1029
|
-
const vMatch = svgString.match(/vertical-align:\s*(-?[\d.]+)ex/);
|
|
1030
|
-
const depthEx = vMatch ? Math.max(0, -parseFloat(vMatch[1])) : 0;
|
|
1031
|
-
const base64 = btoa(unescape(encodeURIComponent(svgString)));
|
|
1032
|
-
return {
|
|
1033
|
-
uri: `data:image/svg+xml;base64,${base64}`,
|
|
1034
|
-
widthEx: wEx,
|
|
1035
|
-
heightEx: hEx,
|
|
1036
|
-
depthEx
|
|
1037
|
-
};
|
|
1038
|
-
} catch (e) {
|
|
1039
|
-
console.error("MathJax error", e);
|
|
1040
|
-
return null;
|
|
1041
|
-
}
|
|
1042
|
-
}
|
|
1043
|
-
var markdownWorker = null;
|
|
1044
|
-
var workerIdCounter = 0;
|
|
1045
|
-
var workerInstanceCounter = 0;
|
|
1046
|
-
var workerCallbacks = /* @__PURE__ */ new Map();
|
|
1047
|
-
function runSyncFallback(entry) {
|
|
1048
|
-
try {
|
|
1049
|
-
entry.cb(0, lexMarkdown(entry.text, entry.userTiming), true);
|
|
1050
|
-
} catch (err) {
|
|
1051
|
-
console.warn("Markdown sync fallback parse failed", err);
|
|
1052
|
-
entry.onDropped?.();
|
|
1053
|
-
}
|
|
1054
|
-
}
|
|
1055
|
-
if (typeof Worker !== "undefined") {
|
|
1056
|
-
try {
|
|
1057
|
-
const blob = new Blob([WORKER_SOURCE_STRING], {
|
|
1058
|
-
type: "application/javascript"
|
|
1059
|
-
});
|
|
1060
|
-
markdownWorker = new Worker(URL.createObjectURL(blob));
|
|
1061
|
-
markdownWorker.onmessage = (e) => {
|
|
1062
|
-
const { id, matchLen, tail, error, needResync, lexerMs, sourceCharsLexed } = e.data;
|
|
1063
|
-
const entry = workerCallbacks.get(id);
|
|
1064
|
-
if (entry) {
|
|
1065
|
-
workerCallbacks.delete(id);
|
|
1066
|
-
if (needResync && entry.onNeedResync) {
|
|
1067
|
-
entry.onNeedResync();
|
|
1068
|
-
} else if (needResync) {
|
|
1069
|
-
runSyncFallback(entry);
|
|
1070
|
-
} else if (!error) {
|
|
1071
|
-
entry.cb(matchLen, tail, false, {
|
|
1072
|
-
lexerMs: typeof lexerMs === "number" ? lexerMs : 0,
|
|
1073
|
-
sourceCharsLexed: typeof sourceCharsLexed === "number" ? sourceCharsLexed : 0
|
|
1074
|
-
});
|
|
1075
|
-
} else {
|
|
1076
|
-
runSyncFallback(entry);
|
|
1077
|
-
}
|
|
1078
|
-
}
|
|
1079
|
-
};
|
|
1080
|
-
markdownWorker.onerror = () => {
|
|
1081
|
-
const pending = [...workerCallbacks.values()];
|
|
1082
|
-
workerCallbacks.clear();
|
|
1083
|
-
markdownWorker = null;
|
|
1084
|
-
for (const entry of pending) runSyncFallback(entry);
|
|
1085
|
-
};
|
|
1086
|
-
} catch (err) {
|
|
1087
|
-
console.warn("Failed to initialize MarkdownWorker", err);
|
|
1088
|
-
}
|
|
1089
|
-
}
|
|
1090
|
-
var DEFAULT_THEME = {
|
|
1091
|
-
textColor: "#e2e8f0",
|
|
1092
|
-
headingColor: "#f8fafc",
|
|
1093
|
-
codeColor: "#a5f3fc",
|
|
1094
|
-
codeBgColor: "rgba(30, 41, 59, 0.85)",
|
|
1095
|
-
quoteBorderColor: "#6366f1",
|
|
1096
|
-
quoteTextColor: "#94a3b8",
|
|
1097
|
-
hrColor: "rgba(148, 163, 184, 0.3)",
|
|
1098
|
-
tableBgColor: "rgba(15, 15, 25, 0.4)",
|
|
1099
|
-
tableHeaderBgColor: "rgba(255, 255, 255, 0.08)",
|
|
1100
|
-
bodyFont: "Inter, system-ui, sans-serif",
|
|
1101
|
-
codeFont: 'ui-monospace, "JetBrains Mono", "Fira Code", monospace',
|
|
1102
|
-
fontSize: 16
|
|
1103
|
-
};
|
|
1104
|
-
var HorizontalRule = class extends Entity {
|
|
1105
|
-
color;
|
|
1106
|
-
constructor(w, color) {
|
|
1107
|
-
super();
|
|
1108
|
-
this.width = w;
|
|
1109
|
-
this.height = 1;
|
|
1110
|
-
this.color = color;
|
|
1111
|
-
}
|
|
1112
|
-
isPointInside() {
|
|
1113
|
-
return false;
|
|
1114
|
-
}
|
|
1115
|
-
render(r) {
|
|
1116
|
-
r.beginPath();
|
|
1117
|
-
r.moveTo(0, 0);
|
|
1118
|
-
r.lineTo(this.width, 0);
|
|
1119
|
-
r.stroke(this.color, 1);
|
|
1120
|
-
}
|
|
1121
|
-
};
|
|
1122
|
-
var QuoteBorder = class extends Entity {
|
|
1123
|
-
color;
|
|
1124
|
-
constructor(height, color) {
|
|
1125
|
-
super();
|
|
1126
|
-
this.width = 4;
|
|
1127
|
-
this.height = height;
|
|
1128
|
-
this.color = color;
|
|
1129
|
-
}
|
|
1130
|
-
isPointInside() {
|
|
1131
|
-
return false;
|
|
1132
|
-
}
|
|
1133
|
-
render(r) {
|
|
1134
|
-
r.beginPath();
|
|
1135
|
-
r.roundRect(0, 0, this.width, this.height, 2);
|
|
1136
|
-
r.fill(this.color);
|
|
1137
|
-
}
|
|
1138
|
-
};
|
|
1139
|
-
var MarkdownContainer = class extends Entity {
|
|
1140
|
-
isPointInside(_globalX, _globalY) {
|
|
1141
|
-
return false;
|
|
1142
|
-
}
|
|
1143
|
-
render(_r) {
|
|
1144
|
-
}
|
|
1145
|
-
};
|
|
1146
|
-
var MathBlock = class extends MarkdownContainer {
|
|
1147
|
-
/**
|
|
1148
|
-
* The TeX source, exactly as written between the delimiters.
|
|
1149
|
-
*
|
|
1150
|
-
* Also the projected text and the accessible name, so this is the one string a
|
|
1151
|
-
* reader can find, select, and copy.
|
|
1152
|
-
*/
|
|
1153
|
-
formula;
|
|
1154
|
-
/** The `data:image/svg+xml` URI of the typeset glyphs. */
|
|
1155
|
-
svgUri;
|
|
1156
|
-
constructor(formula, svgUri) {
|
|
1157
|
-
super();
|
|
1158
|
-
this.formula = formula;
|
|
1159
|
-
this.svgUri = svgUri;
|
|
1160
|
-
}
|
|
1161
|
-
getDevtoolsDescriptor() {
|
|
1162
|
-
return {
|
|
1163
|
-
kind: "MathBlock",
|
|
1164
|
-
groups: [
|
|
1165
|
-
{
|
|
1166
|
-
label: "Math",
|
|
1167
|
-
fields: [{ label: "formula", value: this.formula, readOnly: true }]
|
|
1168
|
-
}
|
|
1169
|
-
]
|
|
1170
|
-
};
|
|
1171
|
-
}
|
|
1172
|
-
};
|
|
531
|
+
|
|
532
|
+
// src/markdown-code.ts
|
|
1173
533
|
var KEYWORD_SETS = {
|
|
1174
534
|
js: /* @__PURE__ */ new Set([
|
|
1175
535
|
"const",
|
|
@@ -1344,10 +704,10 @@ function highlightLine(line, lang, theme) {
|
|
|
1344
704
|
return [{ text: line, color: theme.codeColor }];
|
|
1345
705
|
}
|
|
1346
706
|
const segments = [];
|
|
1347
|
-
const KEYWORD_COLOR =
|
|
1348
|
-
const STRING_COLOR =
|
|
1349
|
-
const COMMENT_COLOR =
|
|
1350
|
-
const NUMBER_COLOR =
|
|
707
|
+
const KEYWORD_COLOR = theme.syntaxKeywordColor;
|
|
708
|
+
const STRING_COLOR = theme.syntaxStringColor;
|
|
709
|
+
const COMMENT_COLOR = theme.syntaxCommentColor;
|
|
710
|
+
const NUMBER_COLOR = theme.syntaxNumberColor;
|
|
1351
711
|
let i = 0;
|
|
1352
712
|
let buf = "";
|
|
1353
713
|
const flush = (color) => {
|
|
@@ -1401,436 +761,1261 @@ function highlightLine(line, lang, theme) {
|
|
|
1401
761
|
i = j;
|
|
1402
762
|
continue;
|
|
1403
763
|
}
|
|
1404
|
-
if (/[a-zA-Z_]/.test(ch)) {
|
|
1405
|
-
flush(theme.codeColor);
|
|
1406
|
-
let j = i;
|
|
1407
|
-
while (j < line.length && /[a-zA-Z0-9_]/.test(line[j])) j++;
|
|
1408
|
-
const word = line.slice(i, j);
|
|
1409
|
-
segments.push({
|
|
1410
|
-
text: word,
|
|
1411
|
-
color: keywords.has(word) ? KEYWORD_COLOR : theme.codeColor
|
|
1412
|
-
});
|
|
1413
|
-
i = j;
|
|
1414
|
-
continue;
|
|
764
|
+
if (/[a-zA-Z_]/.test(ch)) {
|
|
765
|
+
flush(theme.codeColor);
|
|
766
|
+
let j = i;
|
|
767
|
+
while (j < line.length && /[a-zA-Z0-9_]/.test(line[j])) j++;
|
|
768
|
+
const word = line.slice(i, j);
|
|
769
|
+
segments.push({
|
|
770
|
+
text: word,
|
|
771
|
+
color: keywords.has(word) ? KEYWORD_COLOR : theme.codeColor
|
|
772
|
+
});
|
|
773
|
+
i = j;
|
|
774
|
+
continue;
|
|
775
|
+
}
|
|
776
|
+
buf += ch;
|
|
777
|
+
i++;
|
|
778
|
+
}
|
|
779
|
+
flush(theme.codeColor);
|
|
780
|
+
return segments;
|
|
781
|
+
}
|
|
782
|
+
var CodeBlock = class extends UIComponent {
|
|
783
|
+
lines;
|
|
784
|
+
grid = null;
|
|
785
|
+
/** Raw (unhighlighted) lines of the last build, for prefix reuse in buildLines. */
|
|
786
|
+
rawLines = null;
|
|
787
|
+
cellWidth = 0;
|
|
788
|
+
source;
|
|
789
|
+
/** Bumped by {@link buildLines} and {@link setSelectable}; read by `Scene`. */
|
|
790
|
+
contentEpoch = 0;
|
|
791
|
+
lang;
|
|
792
|
+
theme;
|
|
793
|
+
/**
|
|
794
|
+
* Assigned in the constructor rather than as a field initializer: both come
|
|
795
|
+
* from `theme`, and a field initializer runs before the constructor body has
|
|
796
|
+
* a `theme` to read.
|
|
797
|
+
*/
|
|
798
|
+
lineH;
|
|
799
|
+
pad;
|
|
800
|
+
codeFont;
|
|
801
|
+
selectable;
|
|
802
|
+
/**
|
|
803
|
+
* @param theme Any subset of {@link MarkdownTheme}; missing keys fall back to
|
|
804
|
+
* `DEFAULT_THEME` in `./theme`. Accepting a partial theme keeps callers that were
|
|
805
|
+
* written against an earlier, smaller `MarkdownTheme` working — this class
|
|
806
|
+
* is public API, and a hand-built theme literal would otherwise start
|
|
807
|
+
* throwing `lineHeight must be a positive finite number` the moment a new
|
|
808
|
+
* size key was added.
|
|
809
|
+
*/
|
|
810
|
+
constructor(code, lang, maxWidth, theme, selectable = true) {
|
|
811
|
+
super();
|
|
812
|
+
const resolved = resolveTheme(theme);
|
|
813
|
+
this.source = code;
|
|
814
|
+
this.lang = lang;
|
|
815
|
+
this.theme = resolved;
|
|
816
|
+
this.lineH = resolved.codeLineHeight;
|
|
817
|
+
this.pad = resolved.codePadding;
|
|
818
|
+
this.codeFont = `${resolved.codeFontSize}px ${resolved.codeFont}`;
|
|
819
|
+
this.selectable = selectable;
|
|
820
|
+
this.lines = [];
|
|
821
|
+
this.width = maxWidth;
|
|
822
|
+
this.buildLines(code);
|
|
823
|
+
}
|
|
824
|
+
/** Re-parse code content (e.g. for live editing). */
|
|
825
|
+
setCode(code, lang) {
|
|
826
|
+
if (lang !== void 0) this.lang = lang;
|
|
827
|
+
this.source = code;
|
|
828
|
+
this.buildLines(code);
|
|
829
|
+
this.scene?.markDirty();
|
|
830
|
+
return this;
|
|
831
|
+
}
|
|
832
|
+
/** Enable or disable browser-native selection for this code block. */
|
|
833
|
+
setSelectable(selectable) {
|
|
834
|
+
this.selectable = selectable;
|
|
835
|
+
this.contentEpoch++;
|
|
836
|
+
this.scene?.markDirty();
|
|
837
|
+
return this;
|
|
838
|
+
}
|
|
839
|
+
getContentEpoch() {
|
|
840
|
+
return this.contentEpoch;
|
|
841
|
+
}
|
|
842
|
+
/**
|
|
843
|
+
* Change the block's box width.
|
|
844
|
+
*
|
|
845
|
+
* Deliberately does **not** rebuild the grid or the highlight, because code does
|
|
846
|
+
* not reflow: lines are placed on a fixed monospace grid at `col × cellWidth` and
|
|
847
|
+
* a long line overflows rather than wrapping, so `height` is a function of line
|
|
848
|
+
* *count* alone. The width only sizes the rounded background. Anything that would
|
|
849
|
+
* change the glyph geometry — the source, the language, the font — goes through
|
|
850
|
+
* {@link setCode} and invalidates the grid there.
|
|
851
|
+
*
|
|
852
|
+
* @returns `this` for chaining.
|
|
853
|
+
*/
|
|
854
|
+
setWidth(width) {
|
|
855
|
+
const next = Math.max(0, width);
|
|
856
|
+
if (next === this.width) return this;
|
|
857
|
+
this.width = next;
|
|
858
|
+
this.scene?.markDirty();
|
|
859
|
+
return this;
|
|
860
|
+
}
|
|
861
|
+
getContentProjection(hint) {
|
|
862
|
+
if (!this.source) return null;
|
|
863
|
+
const grid = this.ensureGrid();
|
|
864
|
+
const rows = [];
|
|
865
|
+
rows.length = grid.lines.length;
|
|
866
|
+
for (let row = 0; row < grid.lines.length; row++) {
|
|
867
|
+
const line = grid.lines[row];
|
|
868
|
+
const y = this.pad + row * this.lineH;
|
|
869
|
+
if (!contentLineInHint(hint, y, this.lineH)) continue;
|
|
870
|
+
rows[row] = {
|
|
871
|
+
text: this.source.slice(line.sourceStart, line.sourceEnd),
|
|
872
|
+
separatorAfter: this.source.slice(line.sourceEnd, line.nextSourceStart) || void 0,
|
|
873
|
+
x: this.pad,
|
|
874
|
+
y,
|
|
875
|
+
baseline: this.lineH * 0.75,
|
|
876
|
+
font: this.codeFont,
|
|
877
|
+
lineHeight: this.lineH
|
|
878
|
+
};
|
|
879
|
+
}
|
|
880
|
+
return {
|
|
881
|
+
text: this.source,
|
|
882
|
+
font: this.codeFont,
|
|
883
|
+
lineHeight: this.lineH,
|
|
884
|
+
// Every row is absolutely positioned from the same local coordinates as
|
|
885
|
+
// render(). A single pre-wrap DOM text node would introduce browser
|
|
886
|
+
// wrapping for long source lines that canvas intentionally keeps intact.
|
|
887
|
+
//
|
|
888
|
+
lines: rows,
|
|
889
|
+
selectable: this.selectable,
|
|
890
|
+
// render() draws cell-by-cell (no ligatures can form); the DOM copy
|
|
891
|
+
// must not ligate either or Firefox selection geometry drifts.
|
|
892
|
+
ligatures: "none",
|
|
893
|
+
grid
|
|
894
|
+
};
|
|
895
|
+
}
|
|
896
|
+
/**
|
|
897
|
+
* Re-highlight the code, reusing the highlight of any unchanged line prefix.
|
|
898
|
+
*
|
|
899
|
+
* Streaming appends to the END of a block, so all but the last line or two are
|
|
900
|
+
* byte-identical to the previous call — yet this used to re-highlight every
|
|
901
|
+
* line on every chunk, making a streamed block O(N) per append and O(N^2)
|
|
902
|
+
* overall. Reusing the stable prefix makes an append proportional to what
|
|
903
|
+
* actually changed.
|
|
904
|
+
*
|
|
905
|
+
* The last previously-seen line is deliberately NOT reused: a chunk usually
|
|
906
|
+
* lands mid-line, so that line's text (and therefore its tokenization) changes.
|
|
907
|
+
*/
|
|
908
|
+
buildLines(code) {
|
|
909
|
+
this.contentEpoch++;
|
|
910
|
+
const rawLines = code.split(/\r\n|\r|\n/);
|
|
911
|
+
const previous = this.rawLines;
|
|
912
|
+
let reusable = 0;
|
|
913
|
+
if (previous && this.lines.length === previous.length) {
|
|
914
|
+
const limit = Math.min(previous.length - 1, rawLines.length);
|
|
915
|
+
while (reusable < limit && previous[reusable] === rawLines[reusable]) reusable++;
|
|
916
|
+
}
|
|
917
|
+
if (reusable > 0) {
|
|
918
|
+
const next = this.lines.slice(0, reusable);
|
|
919
|
+
for (let i = reusable; i < rawLines.length; i++) {
|
|
920
|
+
next.push(highlightLine(rawLines[i], this.lang, this.theme));
|
|
921
|
+
}
|
|
922
|
+
this.lines = next;
|
|
923
|
+
} else {
|
|
924
|
+
this.lines = rawLines.map((l) => highlightLine(l, this.lang, this.theme));
|
|
925
|
+
}
|
|
926
|
+
this.rawLines = rawLines;
|
|
927
|
+
this.grid = null;
|
|
928
|
+
this.height = this.pad * 2 + rawLines.length * this.lineH;
|
|
929
|
+
}
|
|
930
|
+
ensureGrid() {
|
|
931
|
+
const cellWidth = this.cellWidth || Math.max(1, measureText("M", this.codeFont));
|
|
932
|
+
if (!this.grid || this.grid.source !== this.source || this.grid.font !== this.codeFont || this.grid.cellWidth !== cellWidth) {
|
|
933
|
+
this.grid = prepareContentGrid(this.source, {
|
|
934
|
+
font: this.codeFont,
|
|
935
|
+
cellWidth,
|
|
936
|
+
lineHeight: this.lineH,
|
|
937
|
+
baseline: this.lineH * 0.75
|
|
938
|
+
});
|
|
939
|
+
}
|
|
940
|
+
return this.grid;
|
|
941
|
+
}
|
|
942
|
+
/** Code blocks are decorative — not interactive. */
|
|
943
|
+
isPointInside() {
|
|
944
|
+
return false;
|
|
945
|
+
}
|
|
946
|
+
render(r) {
|
|
947
|
+
r.beginPath();
|
|
948
|
+
r.roundRect(0, 0, this.width, this.height, this.theme.codeRadius);
|
|
949
|
+
r.fill(this.theme.codeBgColor);
|
|
950
|
+
const grid = this.ensureGrid();
|
|
951
|
+
const atlas = codeGlyphAtlas(r);
|
|
952
|
+
const atlasSource = atlas?.source ?? null;
|
|
953
|
+
const blit = atlas ? r.drawImageRect : void 0;
|
|
954
|
+
for (let row = 0; row < grid.lines.length; row++) {
|
|
955
|
+
const yBaseline = this.pad + row * this.lineH + this.lineH * 0.75;
|
|
956
|
+
const segments = this.lines[row];
|
|
957
|
+
let segmentIndex = 0;
|
|
958
|
+
let segmentEnd = segments[0]?.text.length ?? 0;
|
|
959
|
+
const lineStart = grid.lines[row].sourceStart;
|
|
960
|
+
for (const cell of grid.lines[row].cells) {
|
|
961
|
+
const localSourceStart = cell.sourceStart - lineStart;
|
|
962
|
+
while (segmentIndex < segments.length - 1 && localSourceStart >= segmentEnd) {
|
|
963
|
+
segmentIndex++;
|
|
964
|
+
segmentEnd += segments[segmentIndex].text.length;
|
|
965
|
+
}
|
|
966
|
+
const sourceText = this.source.slice(cell.sourceStart, cell.sourceEnd);
|
|
967
|
+
if (cell.advance <= 0 || sourceText === " " || sourceText === " ") continue;
|
|
968
|
+
const color = segments[segmentIndex]?.color ?? this.theme.codeColor;
|
|
969
|
+
const x = this.pad + cell.x;
|
|
970
|
+
if (blit && atlas) {
|
|
971
|
+
const slot = atlas.get(this.codeFont, color, cell.glyph);
|
|
972
|
+
const src = atlasSource ?? atlas.source;
|
|
973
|
+
if (slot && src) {
|
|
974
|
+
blit.call(
|
|
975
|
+
r,
|
|
976
|
+
src,
|
|
977
|
+
slot.sx,
|
|
978
|
+
slot.sy,
|
|
979
|
+
slot.sw,
|
|
980
|
+
slot.sh,
|
|
981
|
+
x - slot.offsetX,
|
|
982
|
+
yBaseline - slot.offsetY,
|
|
983
|
+
slot.w,
|
|
984
|
+
slot.h
|
|
985
|
+
);
|
|
986
|
+
continue;
|
|
987
|
+
}
|
|
988
|
+
}
|
|
989
|
+
r.fillText(cell.glyph, x, yBaseline, this.codeFont, color);
|
|
990
|
+
}
|
|
991
|
+
}
|
|
992
|
+
}
|
|
993
|
+
};
|
|
994
|
+
var codeAtlases = /* @__PURE__ */ new Map();
|
|
995
|
+
var MAX_CODE_ATLASES = 2;
|
|
996
|
+
var lastCodeAtlas = null;
|
|
997
|
+
function codeGlyphAtlas(r) {
|
|
998
|
+
if (typeof r.drawImageRect !== "function") return void 0;
|
|
999
|
+
if (typeof document === "undefined") return void 0;
|
|
1000
|
+
const dpr = Math.max(
|
|
1001
|
+
1,
|
|
1002
|
+
r.pixelRatio ?? (typeof window !== "undefined" ? window.devicePixelRatio || 1 : 1)
|
|
1003
|
+
);
|
|
1004
|
+
const existing = codeAtlases.get(dpr);
|
|
1005
|
+
if (existing) {
|
|
1006
|
+
codeAtlases.delete(dpr);
|
|
1007
|
+
codeAtlases.set(dpr, existing);
|
|
1008
|
+
lastCodeAtlas = existing;
|
|
1009
|
+
return existing;
|
|
1010
|
+
}
|
|
1011
|
+
const atlas = new GlyphRasterAtlas({ dpr, maxSize: 2048 });
|
|
1012
|
+
codeAtlases.set(dpr, atlas);
|
|
1013
|
+
if (codeAtlases.size > MAX_CODE_ATLASES) {
|
|
1014
|
+
const oldestKey = codeAtlases.keys().next().value;
|
|
1015
|
+
const oldest = codeAtlases.get(oldestKey);
|
|
1016
|
+
codeAtlases.delete(oldestKey);
|
|
1017
|
+
if (oldest && oldest !== atlas) oldest.destroy();
|
|
1018
|
+
}
|
|
1019
|
+
lastCodeAtlas = atlas;
|
|
1020
|
+
return atlas;
|
|
1021
|
+
}
|
|
1022
|
+
function codeAtlasStats() {
|
|
1023
|
+
return lastCodeAtlas ? lastCodeAtlas.stats : null;
|
|
1024
|
+
}
|
|
1025
|
+
function codeAtlas() {
|
|
1026
|
+
return lastCodeAtlas;
|
|
1027
|
+
}
|
|
1028
|
+
|
|
1029
|
+
// src/markdown-footnote.ts
|
|
1030
|
+
var LABEL = "([^\\]\\s]+)";
|
|
1031
|
+
var REF_RE = new RegExp(`^\\[\\^${LABEL}\\]`);
|
|
1032
|
+
var DEF_RE = new RegExp(`^ {0,3}\\[\\^${LABEL}\\]:[ \\t]*([^\\n]*)(?:\\n|$)`);
|
|
1033
|
+
var FOOTNOTE_EXTENSIONS = [
|
|
1034
|
+
{
|
|
1035
|
+
name: "footnoteRef",
|
|
1036
|
+
level: "inline",
|
|
1037
|
+
tokenizer(src) {
|
|
1038
|
+
const match = REF_RE.exec(src);
|
|
1039
|
+
if (match) {
|
|
1040
|
+
return {
|
|
1041
|
+
type: "footnoteRef",
|
|
1042
|
+
raw: match[0],
|
|
1043
|
+
label: match[1]
|
|
1044
|
+
};
|
|
1045
|
+
}
|
|
1046
|
+
return void 0;
|
|
1047
|
+
},
|
|
1048
|
+
renderer(token) {
|
|
1049
|
+
return token.raw;
|
|
1050
|
+
}
|
|
1051
|
+
},
|
|
1052
|
+
{
|
|
1053
|
+
name: "footnoteDef",
|
|
1054
|
+
level: "block",
|
|
1055
|
+
tokenizer(src) {
|
|
1056
|
+
const match = DEF_RE.exec(src);
|
|
1057
|
+
if (match) {
|
|
1058
|
+
return {
|
|
1059
|
+
type: "footnoteDef",
|
|
1060
|
+
raw: match[0],
|
|
1061
|
+
label: match[1],
|
|
1062
|
+
body: match[2]
|
|
1063
|
+
};
|
|
1064
|
+
}
|
|
1065
|
+
return void 0;
|
|
1066
|
+
},
|
|
1067
|
+
renderer(token) {
|
|
1068
|
+
return token.raw;
|
|
1069
|
+
}
|
|
1070
|
+
}
|
|
1071
|
+
];
|
|
1072
|
+
function footnoteMarker(label) {
|
|
1073
|
+
return `[${label}]`;
|
|
1074
|
+
}
|
|
1075
|
+
|
|
1076
|
+
// src/markdown-math.ts
|
|
1077
|
+
var mathConverter = null;
|
|
1078
|
+
var mathLoad = null;
|
|
1079
|
+
function preloadMathJax() {
|
|
1080
|
+
if (mathLoad) return mathLoad;
|
|
1081
|
+
mathLoad = (async () => {
|
|
1082
|
+
const { emitSVG, layout } = await import("@vectojs/tex");
|
|
1083
|
+
mathConverter = (formula, displayMode, color) => convertMathToSVGDataURI(formula, displayMode, color, layout, emitSVG);
|
|
1084
|
+
})().catch((e) => {
|
|
1085
|
+
console.error("Math engine failed to load; formulas will render as TeX source", e);
|
|
1086
|
+
});
|
|
1087
|
+
return mathLoad;
|
|
1088
|
+
}
|
|
1089
|
+
function isMathJaxReady() {
|
|
1090
|
+
return mathConverter !== null;
|
|
1091
|
+
}
|
|
1092
|
+
var EX_PER_EM = 0.4421;
|
|
1093
|
+
function exToPx(ex, fontSize) {
|
|
1094
|
+
return ex * fontSize * EX_PER_EM;
|
|
1095
|
+
}
|
|
1096
|
+
function fontSizeFromFont(font) {
|
|
1097
|
+
const pxIndex = font.indexOf("px");
|
|
1098
|
+
if (pxIndex <= 0) return void 0;
|
|
1099
|
+
let start = pxIndex;
|
|
1100
|
+
while (start > 0) {
|
|
1101
|
+
const ch = font[start - 1];
|
|
1102
|
+
if (ch >= "0" && ch <= "9" || ch === ".") start--;
|
|
1103
|
+
else break;
|
|
1104
|
+
}
|
|
1105
|
+
if (start === pxIndex) return void 0;
|
|
1106
|
+
const size = parseFloat(font.slice(start, pxIndex));
|
|
1107
|
+
return Number.isFinite(size) ? size : void 0;
|
|
1108
|
+
}
|
|
1109
|
+
var mathCache = /* @__PURE__ */ new Map();
|
|
1110
|
+
var MATH_CACHE_LIMIT = 256;
|
|
1111
|
+
var inlineMathRasters = /* @__PURE__ */ new Map();
|
|
1112
|
+
var inlineMathRasterWaiters = /* @__PURE__ */ new Set();
|
|
1113
|
+
function subscribeInlineMathRaster(notify) {
|
|
1114
|
+
inlineMathRasterWaiters.add(notify);
|
|
1115
|
+
}
|
|
1116
|
+
function unsubscribeInlineMathRaster(notify) {
|
|
1117
|
+
inlineMathRasterWaiters.delete(notify);
|
|
1118
|
+
}
|
|
1119
|
+
function ensureInlineMathRaster(uri) {
|
|
1120
|
+
const existing = inlineMathRasters.get(uri);
|
|
1121
|
+
if (existing) return existing;
|
|
1122
|
+
const entry = { decoded: false };
|
|
1123
|
+
inlineMathRasters.set(uri, entry);
|
|
1124
|
+
if (typeof globalThis.Image !== "undefined") {
|
|
1125
|
+
const bitmap = new globalThis.Image();
|
|
1126
|
+
bitmap.onload = () => {
|
|
1127
|
+
entry.decoded = true;
|
|
1128
|
+
for (const notify of inlineMathRasterWaiters) notify();
|
|
1129
|
+
};
|
|
1130
|
+
bitmap.src = uri;
|
|
1131
|
+
entry.bitmap = bitmap;
|
|
1132
|
+
}
|
|
1133
|
+
return entry;
|
|
1134
|
+
}
|
|
1135
|
+
function paintInlineMath(uri, surface, box) {
|
|
1136
|
+
const raster = ensureInlineMathRaster(uri);
|
|
1137
|
+
if (!raster.decoded || !raster.bitmap) return;
|
|
1138
|
+
surface.drawImage(raster.bitmap, box.x, box.y, box.width, box.height);
|
|
1139
|
+
}
|
|
1140
|
+
var MATH_LANGS = /* @__PURE__ */ new Set(["math", "latex", "tex"]);
|
|
1141
|
+
function containsInlineMath(token) {
|
|
1142
|
+
if (token.type === "inlineMath") return true;
|
|
1143
|
+
const anyToken = token;
|
|
1144
|
+
if (Array.isArray(anyToken.tokens) && anyToken.tokens.some(containsInlineMath)) {
|
|
1145
|
+
return true;
|
|
1146
|
+
}
|
|
1147
|
+
if (Array.isArray(anyToken.items) && anyToken.items.some(containsInlineMath)) {
|
|
1148
|
+
return true;
|
|
1149
|
+
}
|
|
1150
|
+
if (Array.isArray(anyToken.header) && anyToken.header.some(containsInlineMath)) {
|
|
1151
|
+
return true;
|
|
1152
|
+
}
|
|
1153
|
+
if (Array.isArray(anyToken.rows)) {
|
|
1154
|
+
for (const row of anyToken.rows) {
|
|
1155
|
+
if (Array.isArray(row) && row.some(containsInlineMath)) return true;
|
|
1156
|
+
}
|
|
1157
|
+
}
|
|
1158
|
+
return false;
|
|
1159
|
+
}
|
|
1160
|
+
var FENCE_OPEN_RE = /^ {0,3}(`{3,}|~{3,})/;
|
|
1161
|
+
var FENCE_CLOSE_RE = /^ {0,3}(`+|~+)[ \t]*$/;
|
|
1162
|
+
function isFenceClosed(raw) {
|
|
1163
|
+
const lines = raw.split("\n");
|
|
1164
|
+
const open = FENCE_OPEN_RE.exec(lines[0]);
|
|
1165
|
+
if (!open) return false;
|
|
1166
|
+
const marker = open[1][0];
|
|
1167
|
+
const minLen = open[1].length;
|
|
1168
|
+
for (let i = 1; i < lines.length; i++) {
|
|
1169
|
+
const close = FENCE_CLOSE_RE.exec(lines[i]);
|
|
1170
|
+
if (close && close[1][0] === marker && close[1].length >= minLen) return true;
|
|
1171
|
+
}
|
|
1172
|
+
return false;
|
|
1173
|
+
}
|
|
1174
|
+
function rendersAsMath(token) {
|
|
1175
|
+
return MATH_LANGS.has((token.lang ?? "").toLowerCase()) && token.text.trim() !== "" && isFenceClosed(token.raw);
|
|
1176
|
+
}
|
|
1177
|
+
function renderMathToSVGDataURI(formula, displayMode, color) {
|
|
1178
|
+
const key = `${displayMode ? 1 : 0}\0${color}\0${formula}`;
|
|
1179
|
+
const hit = mathCache.get(key);
|
|
1180
|
+
if (hit) return hit;
|
|
1181
|
+
if (!mathConverter) return null;
|
|
1182
|
+
const converted = mathConverter(formula, displayMode, color);
|
|
1183
|
+
if (converted) {
|
|
1184
|
+
if (mathCache.size >= MATH_CACHE_LIMIT) {
|
|
1185
|
+
const oldest = mathCache.keys().next().value;
|
|
1186
|
+
if (oldest !== void 0) mathCache.delete(oldest);
|
|
1187
|
+
}
|
|
1188
|
+
mathCache.set(key, converted);
|
|
1189
|
+
}
|
|
1190
|
+
return converted;
|
|
1191
|
+
}
|
|
1192
|
+
var MATH_PAD_EM = 0.05;
|
|
1193
|
+
var KATEX_FONT_SCALE = 1.21;
|
|
1194
|
+
var EX_PER_KATEX_EM = KATEX_FONT_SCALE / EX_PER_EM;
|
|
1195
|
+
function convertMathToSVGDataURI(formula, displayMode, color, layout, emitSVG) {
|
|
1196
|
+
try {
|
|
1197
|
+
const emitted = emitSVG(layout(formula, { displayMode }), {
|
|
1198
|
+
color,
|
|
1199
|
+
padEm: MATH_PAD_EM
|
|
1200
|
+
});
|
|
1201
|
+
if (emitted.missing.length > 0) return null;
|
|
1202
|
+
const pad2 = MATH_PAD_EM * 2;
|
|
1203
|
+
const base64 = btoa(unescape(encodeURIComponent(emitted.svg)));
|
|
1204
|
+
return {
|
|
1205
|
+
uri: `data:image/svg+xml;base64,${base64}`,
|
|
1206
|
+
widthEx: (emitted.width + pad2) * EX_PER_KATEX_EM,
|
|
1207
|
+
heightEx: (emitted.height + emitted.depth + pad2) * EX_PER_KATEX_EM,
|
|
1208
|
+
depthEx: (emitted.depth + MATH_PAD_EM) * EX_PER_KATEX_EM
|
|
1209
|
+
};
|
|
1210
|
+
} catch (e) {
|
|
1211
|
+
console.error("Math typesetting error", e);
|
|
1212
|
+
return null;
|
|
1213
|
+
}
|
|
1214
|
+
}
|
|
1215
|
+
var MathBlock = class extends MarkdownContainer {
|
|
1216
|
+
/**
|
|
1217
|
+
* The TeX source, exactly as written between the delimiters.
|
|
1218
|
+
*
|
|
1219
|
+
* Also the projected text and the accessible name, so this is the one string a
|
|
1220
|
+
* reader can find, select, and copy.
|
|
1221
|
+
*/
|
|
1222
|
+
formula;
|
|
1223
|
+
/** The `data:image/svg+xml` URI of the typeset glyphs. */
|
|
1224
|
+
svgUri;
|
|
1225
|
+
constructor(formula, svgUri) {
|
|
1226
|
+
super();
|
|
1227
|
+
this.formula = formula;
|
|
1228
|
+
this.svgUri = svgUri;
|
|
1229
|
+
}
|
|
1230
|
+
getDevtoolsDescriptor() {
|
|
1231
|
+
return {
|
|
1232
|
+
kind: "MathBlock",
|
|
1233
|
+
groups: [
|
|
1234
|
+
{
|
|
1235
|
+
label: "Math",
|
|
1236
|
+
fields: [{ label: "formula", value: this.formula, readOnly: true }]
|
|
1237
|
+
}
|
|
1238
|
+
]
|
|
1239
|
+
};
|
|
1240
|
+
}
|
|
1241
|
+
};
|
|
1242
|
+
|
|
1243
|
+
// src/markdown-inline.ts
|
|
1244
|
+
import { OBJECT_REPLACEMENT } from "@vectojs/core";
|
|
1245
|
+
import { RichText } from "@vectojs/ui";
|
|
1246
|
+
|
|
1247
|
+
// src/markdown-image.ts
|
|
1248
|
+
function paragraphHasImage(token) {
|
|
1249
|
+
return containsImage(token.tokens);
|
|
1250
|
+
}
|
|
1251
|
+
function containsImage(tokens) {
|
|
1252
|
+
if (!tokens) return false;
|
|
1253
|
+
for (const token of tokens) {
|
|
1254
|
+
if (token.type === "image") return true;
|
|
1255
|
+
const anyToken = token;
|
|
1256
|
+
if (containsImage(anyToken.tokens)) return true;
|
|
1257
|
+
if (Array.isArray(anyToken.items) && containsImage(anyToken.items)) {
|
|
1258
|
+
return true;
|
|
1259
|
+
}
|
|
1260
|
+
const table = token;
|
|
1261
|
+
if (Array.isArray(table.header) && table.header.some((cell) => containsImage(cell.tokens))) {
|
|
1262
|
+
return true;
|
|
1263
|
+
}
|
|
1264
|
+
if (Array.isArray(table.rows) && table.rows.some((row) => row.some((cell) => containsImage(cell.tokens)))) {
|
|
1265
|
+
return true;
|
|
1266
|
+
}
|
|
1267
|
+
}
|
|
1268
|
+
return false;
|
|
1269
|
+
}
|
|
1270
|
+
function imagesOf(tokens) {
|
|
1271
|
+
const images = [];
|
|
1272
|
+
for (const token of tokens ?? []) {
|
|
1273
|
+
if (token.type === "image") {
|
|
1274
|
+
images.push(token);
|
|
1275
|
+
continue;
|
|
1276
|
+
}
|
|
1277
|
+
images.push(...imagesOf(token.tokens));
|
|
1278
|
+
}
|
|
1279
|
+
return images;
|
|
1280
|
+
}
|
|
1281
|
+
function stripImages(token) {
|
|
1282
|
+
const children = token.tokens;
|
|
1283
|
+
if (!children) return token;
|
|
1284
|
+
const kept = [];
|
|
1285
|
+
for (const child of children) {
|
|
1286
|
+
if (child.type === "image") continue;
|
|
1287
|
+
const grandchildren = child.tokens;
|
|
1288
|
+
if (grandchildren && containsImage(grandchildren)) {
|
|
1289
|
+
const stripped = stripImages(child);
|
|
1290
|
+
const remaining = stripped.tokens;
|
|
1291
|
+
if (remaining && remaining.length > 0) kept.push(stripped);
|
|
1292
|
+
continue;
|
|
1293
|
+
}
|
|
1294
|
+
kept.push(child);
|
|
1295
|
+
}
|
|
1296
|
+
return { ...token, tokens: kept };
|
|
1297
|
+
}
|
|
1298
|
+
function liftNestedImages(tokens) {
|
|
1299
|
+
const lifted = [];
|
|
1300
|
+
for (const token of tokens) {
|
|
1301
|
+
if (token.type === "image") {
|
|
1302
|
+
lifted.push(token);
|
|
1303
|
+
continue;
|
|
1304
|
+
}
|
|
1305
|
+
const children = token.tokens;
|
|
1306
|
+
if (children && containsImage(children)) {
|
|
1307
|
+
lifted.push(...liftNestedImages(children));
|
|
1308
|
+
continue;
|
|
1309
|
+
}
|
|
1310
|
+
lifted.push(token);
|
|
1311
|
+
}
|
|
1312
|
+
return lifted;
|
|
1313
|
+
}
|
|
1314
|
+
function lastIndexOfImage(tokens) {
|
|
1315
|
+
for (let i = tokens.length - 1; i >= 0; i--) {
|
|
1316
|
+
if (tokens[i].type === "image") return i;
|
|
1317
|
+
}
|
|
1318
|
+
return -1;
|
|
1319
|
+
}
|
|
1320
|
+
var inlineImageRasters = /* @__PURE__ */ new Map();
|
|
1321
|
+
var inlineImageRasterWaiters = /* @__PURE__ */ new Set();
|
|
1322
|
+
function subscribeInlineImageRaster(notify) {
|
|
1323
|
+
inlineImageRasterWaiters.add(notify);
|
|
1324
|
+
}
|
|
1325
|
+
function unsubscribeInlineImageRaster(notify) {
|
|
1326
|
+
inlineImageRasterWaiters.delete(notify);
|
|
1327
|
+
}
|
|
1328
|
+
function ensureInlineImageRaster(src) {
|
|
1329
|
+
const existing = inlineImageRasters.get(src);
|
|
1330
|
+
if (existing) return existing;
|
|
1331
|
+
const entry = { decoded: false };
|
|
1332
|
+
inlineImageRasters.set(src, entry);
|
|
1333
|
+
if (typeof globalThis.Image !== "undefined") {
|
|
1334
|
+
const bitmap = new globalThis.Image();
|
|
1335
|
+
bitmap.onload = () => {
|
|
1336
|
+
entry.decoded = true;
|
|
1337
|
+
entry.naturalWidth = bitmap.naturalWidth || void 0;
|
|
1338
|
+
entry.naturalHeight = bitmap.naturalHeight || void 0;
|
|
1339
|
+
for (const notify of inlineImageRasterWaiters) notify();
|
|
1340
|
+
};
|
|
1341
|
+
bitmap.onerror = () => {
|
|
1342
|
+
entry.failed = true;
|
|
1343
|
+
for (const notify of inlineImageRasterWaiters) notify();
|
|
1344
|
+
};
|
|
1345
|
+
bitmap.src = src;
|
|
1346
|
+
entry.bitmap = bitmap;
|
|
1347
|
+
}
|
|
1348
|
+
return entry;
|
|
1349
|
+
}
|
|
1350
|
+
function paintInlineImage(src, surface, box) {
|
|
1351
|
+
const raster = ensureInlineImageRaster(src);
|
|
1352
|
+
if (!raster.decoded || !raster.bitmap) return;
|
|
1353
|
+
surface.drawImage(raster.bitmap, box.x, box.y, box.width, box.height);
|
|
1354
|
+
}
|
|
1355
|
+
function expectedImageParagraphChildren(tokens) {
|
|
1356
|
+
let children = 0;
|
|
1357
|
+
let inTextRun = false;
|
|
1358
|
+
for (const token of liftNestedImages(tokens)) {
|
|
1359
|
+
if (token.type === "image") {
|
|
1360
|
+
children++;
|
|
1361
|
+
inTextRun = false;
|
|
1362
|
+
} else if (!inTextRun) {
|
|
1363
|
+
children++;
|
|
1364
|
+
inTextRun = true;
|
|
1365
|
+
}
|
|
1366
|
+
}
|
|
1367
|
+
return children;
|
|
1368
|
+
}
|
|
1369
|
+
|
|
1370
|
+
// src/markdown-inline.ts
|
|
1371
|
+
function decodeEntities(text) {
|
|
1372
|
+
return text.replace(/</g, "<").replace(/>/g, ">").replace(/"/g, '"').replace(/'/g, "'").replace(/&/g, "&");
|
|
1373
|
+
}
|
|
1374
|
+
function collectSpans(tokens, inherited, theme, out, blockFontSize) {
|
|
1375
|
+
for (const token of tokens) {
|
|
1376
|
+
switch (token.type) {
|
|
1377
|
+
case "strong": {
|
|
1378
|
+
const t = token;
|
|
1379
|
+
if (t.tokens) {
|
|
1380
|
+
collectSpans(t.tokens, { ...inherited, bold: true }, theme, out, blockFontSize);
|
|
1381
|
+
} else {
|
|
1382
|
+
out.push({
|
|
1383
|
+
text: decodeEntities(t.text),
|
|
1384
|
+
style: { ...inherited, bold: true }
|
|
1385
|
+
});
|
|
1386
|
+
}
|
|
1387
|
+
break;
|
|
1388
|
+
}
|
|
1389
|
+
case "em": {
|
|
1390
|
+
const t = token;
|
|
1391
|
+
if (t.tokens) {
|
|
1392
|
+
collectSpans(t.tokens, { ...inherited, italic: true }, theme, out, blockFontSize);
|
|
1393
|
+
} else {
|
|
1394
|
+
out.push({
|
|
1395
|
+
text: decodeEntities(t.text),
|
|
1396
|
+
style: { ...inherited, italic: true }
|
|
1397
|
+
});
|
|
1398
|
+
}
|
|
1399
|
+
break;
|
|
1400
|
+
}
|
|
1401
|
+
case "del": {
|
|
1402
|
+
const t = token;
|
|
1403
|
+
if (t.tokens) {
|
|
1404
|
+
collectSpans(t.tokens, { ...inherited, lineThrough: true }, theme, out, blockFontSize);
|
|
1405
|
+
} else {
|
|
1406
|
+
out.push({
|
|
1407
|
+
text: decodeEntities(t.text),
|
|
1408
|
+
style: { ...inherited, lineThrough: true }
|
|
1409
|
+
});
|
|
1410
|
+
}
|
|
1411
|
+
break;
|
|
1412
|
+
}
|
|
1413
|
+
case "codespan": {
|
|
1414
|
+
const t = token;
|
|
1415
|
+
out.push({
|
|
1416
|
+
text: decodeEntities(t.text),
|
|
1417
|
+
// Inline code renders in the theme's monospace family (not just tinted
|
|
1418
|
+
// prose) — TextStyle.fontFamily drives both measurement and drawing.
|
|
1419
|
+
style: {
|
|
1420
|
+
...inherited,
|
|
1421
|
+
color: theme.codeColor,
|
|
1422
|
+
fontFamily: theme.codeFont
|
|
1423
|
+
}
|
|
1424
|
+
});
|
|
1425
|
+
break;
|
|
1426
|
+
}
|
|
1427
|
+
case "br": {
|
|
1428
|
+
out.push({ text: "\n" });
|
|
1429
|
+
break;
|
|
1430
|
+
}
|
|
1431
|
+
case "html": {
|
|
1432
|
+
const t = token;
|
|
1433
|
+
const raw = t.raw ?? t.text ?? "";
|
|
1434
|
+
const brCount = (raw.match(/<br\s*\/?>/gi) ?? []).length;
|
|
1435
|
+
for (let i = 0; i < brCount; i++) out.push({ text: "\n" });
|
|
1436
|
+
break;
|
|
1437
|
+
}
|
|
1438
|
+
case "inlineMath": {
|
|
1439
|
+
const t = token;
|
|
1440
|
+
const runSize = inherited.fontSize ?? blockFontSize ?? theme.fontSize;
|
|
1441
|
+
const runColor = inherited.color ?? theme.textColor;
|
|
1442
|
+
const rendered = renderMathToSVGDataURI(t.text, false, runColor);
|
|
1443
|
+
if (rendered) {
|
|
1444
|
+
const uri = rendered.uri;
|
|
1445
|
+
out.push({
|
|
1446
|
+
text: OBJECT_REPLACEMENT,
|
|
1447
|
+
style: inherited,
|
|
1448
|
+
object: {
|
|
1449
|
+
width: exToPx(rendered.widthEx, runSize),
|
|
1450
|
+
height: exToPx(rendered.heightEx, runSize),
|
|
1451
|
+
depth: exToPx(rendered.depthEx, runSize),
|
|
1452
|
+
// The TeX source is the accessible name: without it a screen reader
|
|
1453
|
+
// receives only the invisible U+FFFC sentinel.
|
|
1454
|
+
alt: t.text,
|
|
1455
|
+
// Without this the box is reserved and stays empty. The engine does
|
|
1456
|
+
// not draw objects, and nothing else in the tree holds the raster.
|
|
1457
|
+
paint: (surface, box) => paintInlineMath(uri, surface, box)
|
|
1458
|
+
}
|
|
1459
|
+
});
|
|
1460
|
+
} else {
|
|
1461
|
+
out.push({
|
|
1462
|
+
text: decodeEntities(t.raw),
|
|
1463
|
+
style: { ...inherited, color: theme.mathFallbackColor }
|
|
1464
|
+
});
|
|
1465
|
+
}
|
|
1466
|
+
break;
|
|
1467
|
+
}
|
|
1468
|
+
case "image": {
|
|
1469
|
+
const t = token;
|
|
1470
|
+
const runSize = inherited.fontSize ?? blockFontSize ?? theme.fontSize;
|
|
1471
|
+
const raster = ensureInlineImageRaster(t.href);
|
|
1472
|
+
if (raster.failed) {
|
|
1473
|
+
out.push({ text: decodeEntities(t.text), style: inherited });
|
|
1474
|
+
break;
|
|
1475
|
+
}
|
|
1476
|
+
const height = runSize * theme.inlineImageScale;
|
|
1477
|
+
const aspect = raster.naturalWidth && raster.naturalHeight ? raster.naturalWidth / raster.naturalHeight : 1;
|
|
1478
|
+
const src = t.href;
|
|
1479
|
+
out.push({
|
|
1480
|
+
text: OBJECT_REPLACEMENT,
|
|
1481
|
+
style: inherited,
|
|
1482
|
+
object: {
|
|
1483
|
+
width: height * aspect,
|
|
1484
|
+
height,
|
|
1485
|
+
// Sits on the baseline like a cap-height glyph rather than hanging
|
|
1486
|
+
// below it; an image has no descender to align.
|
|
1487
|
+
depth: 0,
|
|
1488
|
+
// The accessible name, and what a copy yields. Without it the
|
|
1489
|
+
// invisible U+FFFC sentinel is all a screen reader receives.
|
|
1490
|
+
alt: t.text,
|
|
1491
|
+
// What this object PAINTS, which `alt` does not determine: two badges
|
|
1492
|
+
// can share alt text and differ in URL. Without it the paragraph memo
|
|
1493
|
+
// serves the first one's painter to the second and every row of a badge
|
|
1494
|
+
// column draws the first row's badge.
|
|
1495
|
+
key: src,
|
|
1496
|
+
paint: (surface, box) => paintInlineImage(src, surface, box)
|
|
1497
|
+
}
|
|
1498
|
+
});
|
|
1499
|
+
break;
|
|
1500
|
+
}
|
|
1501
|
+
case "footnoteRef": {
|
|
1502
|
+
const t = token;
|
|
1503
|
+
const runSize = inherited.fontSize ?? blockFontSize ?? theme.fontSize;
|
|
1504
|
+
out.push({
|
|
1505
|
+
text: footnoteMarker(t.label),
|
|
1506
|
+
style: {
|
|
1507
|
+
...inherited,
|
|
1508
|
+
fontSize: runSize * theme.footnoteMarkerScale,
|
|
1509
|
+
color: theme.footnoteColor
|
|
1510
|
+
}
|
|
1511
|
+
});
|
|
1512
|
+
break;
|
|
1513
|
+
}
|
|
1514
|
+
case "link": {
|
|
1515
|
+
const t = token;
|
|
1516
|
+
const linkStyle = {
|
|
1517
|
+
...inherited,
|
|
1518
|
+
href: t.href,
|
|
1519
|
+
color: theme.linkColor
|
|
1520
|
+
};
|
|
1521
|
+
if (t.tokens && t.tokens.length > 0) {
|
|
1522
|
+
collectSpans(t.tokens, linkStyle, theme, out, blockFontSize);
|
|
1523
|
+
} else {
|
|
1524
|
+
out.push({ text: decodeEntities(t.text), style: linkStyle });
|
|
1525
|
+
}
|
|
1526
|
+
break;
|
|
1527
|
+
}
|
|
1528
|
+
case "text": {
|
|
1529
|
+
const t = token;
|
|
1530
|
+
if ("tokens" in t && t.tokens?.length) {
|
|
1531
|
+
collectSpans(t.tokens, inherited, theme, out, blockFontSize);
|
|
1532
|
+
} else {
|
|
1533
|
+
const decoded = decodeEntities(t.text);
|
|
1534
|
+
if (decoded) {
|
|
1535
|
+
const style = Object.keys(inherited).length > 0 ? inherited : void 0;
|
|
1536
|
+
out.push({ text: decoded, style });
|
|
1537
|
+
}
|
|
1538
|
+
}
|
|
1539
|
+
break;
|
|
1540
|
+
}
|
|
1541
|
+
default: {
|
|
1542
|
+
if ("text" in token) {
|
|
1543
|
+
const decoded = decodeEntities(token.text);
|
|
1544
|
+
if (decoded) {
|
|
1545
|
+
const style = Object.keys(inherited).length > 0 ? inherited : void 0;
|
|
1546
|
+
out.push({ text: decoded, style });
|
|
1547
|
+
}
|
|
1548
|
+
}
|
|
1549
|
+
break;
|
|
1550
|
+
}
|
|
1551
|
+
}
|
|
1552
|
+
}
|
|
1553
|
+
}
|
|
1554
|
+
function findUnclosedInline(text) {
|
|
1555
|
+
let best = null;
|
|
1556
|
+
const tick = text.lastIndexOf("`");
|
|
1557
|
+
if (tick !== -1 && tick < text.length - 1) {
|
|
1558
|
+
return { kind: "codespan", at: tick, contentAt: tick + 1 };
|
|
1559
|
+
}
|
|
1560
|
+
if (tick !== -1) return null;
|
|
1561
|
+
const emphasis = /(\*{1,2}(?!\*)|_{1,2}(?!_))(?=[^\s])/g;
|
|
1562
|
+
for (let match = emphasis.exec(text); match !== null; match = emphasis.exec(text)) {
|
|
1563
|
+
const marker = match[1];
|
|
1564
|
+
const at = match.index;
|
|
1565
|
+
if (marker[0] === "_" && at > 0 && /[\w]/.test(text[at - 1])) continue;
|
|
1566
|
+
best = {
|
|
1567
|
+
kind: marker.length === 2 ? "strong" : "em",
|
|
1568
|
+
at,
|
|
1569
|
+
contentAt: at + marker.length
|
|
1570
|
+
};
|
|
1571
|
+
}
|
|
1572
|
+
const bracket = text.lastIndexOf("[");
|
|
1573
|
+
if (bracket !== -1 && bracket < text.length - 1 && (best === null || bracket > best.at)) {
|
|
1574
|
+
const closed = /\]\([^)]*\)/.test(text.slice(bracket));
|
|
1575
|
+
if (!closed) {
|
|
1576
|
+
best = { kind: "link", at: bracket, contentAt: bracket + 1 };
|
|
1577
|
+
}
|
|
1578
|
+
}
|
|
1579
|
+
return best;
|
|
1580
|
+
}
|
|
1581
|
+
function renderInlineToRichText(tokens, fallbackText, font, color, maxWidth, theme, selectable, onLinkClick) {
|
|
1582
|
+
const spans = [];
|
|
1583
|
+
if (tokens && tokens.length > 0) {
|
|
1584
|
+
collectSpans(tokens, {}, theme, spans, fontSizeFromFont(font));
|
|
1585
|
+
}
|
|
1586
|
+
if (spans.length === 0) {
|
|
1587
|
+
spans.push({ text: decodeEntities(fallbackText) });
|
|
1588
|
+
}
|
|
1589
|
+
return new RichText(spans, {
|
|
1590
|
+
font,
|
|
1591
|
+
color,
|
|
1592
|
+
maxWidth,
|
|
1593
|
+
linkColor: theme.linkColor,
|
|
1594
|
+
selectable,
|
|
1595
|
+
onLinkClick
|
|
1596
|
+
});
|
|
1597
|
+
}
|
|
1598
|
+
|
|
1599
|
+
// src/Markdown.ts
|
|
1600
|
+
import { RichText as RichText2, Stack, Table, Text, Image, UIComponent as UIComponent3 } from "@vectojs/ui";
|
|
1601
|
+
|
|
1602
|
+
// src/blockAffordances.ts
|
|
1603
|
+
import { Button, measureText as measureText2, UIComponent as UIComponent2 } from "@vectojs/ui";
|
|
1604
|
+
var LANGUAGE_EXTENSIONS = {
|
|
1605
|
+
bash: "sh",
|
|
1606
|
+
c: "c",
|
|
1607
|
+
cpp: "cpp",
|
|
1608
|
+
cs: "cs",
|
|
1609
|
+
css: "css",
|
|
1610
|
+
diff: "diff",
|
|
1611
|
+
dockerfile: "dockerfile",
|
|
1612
|
+
go: "go",
|
|
1613
|
+
graphql: "graphql",
|
|
1614
|
+
haskell: "hs",
|
|
1615
|
+
html: "html",
|
|
1616
|
+
java: "java",
|
|
1617
|
+
javascript: "js",
|
|
1618
|
+
js: "js",
|
|
1619
|
+
json: "json",
|
|
1620
|
+
jsonc: "jsonc",
|
|
1621
|
+
jsx: "jsx",
|
|
1622
|
+
kotlin: "kt",
|
|
1623
|
+
latex: "tex",
|
|
1624
|
+
lua: "lua",
|
|
1625
|
+
make: "mk",
|
|
1626
|
+
markdown: "md",
|
|
1627
|
+
md: "md",
|
|
1628
|
+
nix: "nix",
|
|
1629
|
+
php: "php",
|
|
1630
|
+
python: "py",
|
|
1631
|
+
py: "py",
|
|
1632
|
+
ruby: "rb",
|
|
1633
|
+
rust: "rs",
|
|
1634
|
+
rs: "rs",
|
|
1635
|
+
scss: "scss",
|
|
1636
|
+
sh: "sh",
|
|
1637
|
+
shell: "sh",
|
|
1638
|
+
sql: "sql",
|
|
1639
|
+
svelte: "svelte",
|
|
1640
|
+
swift: "swift",
|
|
1641
|
+
tex: "tex",
|
|
1642
|
+
toml: "toml",
|
|
1643
|
+
ts: "ts",
|
|
1644
|
+
tsx: "tsx",
|
|
1645
|
+
typescript: "ts",
|
|
1646
|
+
vue: "vue",
|
|
1647
|
+
xml: "xml",
|
|
1648
|
+
yaml: "yaml",
|
|
1649
|
+
yml: "yaml",
|
|
1650
|
+
zig: "zig",
|
|
1651
|
+
zsh: "sh"
|
|
1652
|
+
};
|
|
1653
|
+
function extensionForLanguage(lang) {
|
|
1654
|
+
const first = lang.trim().toLowerCase().split(/[\s:,{]/)[0] ?? "";
|
|
1655
|
+
return LANGUAGE_EXTENSIONS[first] ?? "txt";
|
|
1656
|
+
}
|
|
1657
|
+
function mimeForLanguage(lang) {
|
|
1658
|
+
const ext = extensionForLanguage(lang);
|
|
1659
|
+
if (ext === "json" || ext === "jsonc") return "application/json";
|
|
1660
|
+
if (ext === "html") return "text/html";
|
|
1661
|
+
if (ext === "css") return "text/css";
|
|
1662
|
+
if (ext === "xml" || ext === "svelte" || ext === "vue") return "text/plain";
|
|
1663
|
+
return "text/plain";
|
|
1664
|
+
}
|
|
1665
|
+
function escapeCsvField(value) {
|
|
1666
|
+
let needsQuoting = false;
|
|
1667
|
+
let hasQuote = false;
|
|
1668
|
+
for (const char of value) {
|
|
1669
|
+
if (char === '"') {
|
|
1670
|
+
hasQuote = true;
|
|
1671
|
+
needsQuoting = true;
|
|
1672
|
+
break;
|
|
1673
|
+
}
|
|
1674
|
+
if (char === "," || char === "\n" || char === "\r") needsQuoting = true;
|
|
1675
|
+
}
|
|
1676
|
+
if (!needsQuoting) return value;
|
|
1677
|
+
return hasQuote ? `"${value.replace(/"/g, '""')}"` : `"${value}"`;
|
|
1678
|
+
}
|
|
1679
|
+
function escapeMarkdownTableCell(cell) {
|
|
1680
|
+
let needsEscaping = false;
|
|
1681
|
+
for (const char of cell) {
|
|
1682
|
+
if (char === "\\" || char === "|") {
|
|
1683
|
+
needsEscaping = true;
|
|
1684
|
+
break;
|
|
1415
1685
|
}
|
|
1416
|
-
buf += ch;
|
|
1417
|
-
i++;
|
|
1418
1686
|
}
|
|
1419
|
-
|
|
1420
|
-
return
|
|
1687
|
+
if (!needsEscaping) return cell;
|
|
1688
|
+
return cell.replace(/\\/g, "\\\\").replace(/\|/g, "\\|");
|
|
1421
1689
|
}
|
|
1422
|
-
|
|
1423
|
-
lines;
|
|
1424
|
-
|
|
1425
|
-
|
|
1426
|
-
|
|
1427
|
-
|
|
1428
|
-
|
|
1429
|
-
|
|
1430
|
-
|
|
1431
|
-
|
|
1432
|
-
|
|
1433
|
-
|
|
1434
|
-
|
|
1435
|
-
|
|
1436
|
-
|
|
1437
|
-
|
|
1438
|
-
|
|
1439
|
-
|
|
1440
|
-
|
|
1441
|
-
|
|
1442
|
-
|
|
1443
|
-
|
|
1444
|
-
|
|
1445
|
-
|
|
1446
|
-
|
|
1690
|
+
function tableToCsv(table) {
|
|
1691
|
+
const lines = [table.headers.map(escapeCsvField).join(",")];
|
|
1692
|
+
for (const row of table.rows) lines.push(row.map(escapeCsvField).join(","));
|
|
1693
|
+
return `\uFEFF${lines.join("\r\n")}`;
|
|
1694
|
+
}
|
|
1695
|
+
function tableToMarkdown(table) {
|
|
1696
|
+
const header = `| ${table.headers.map(escapeMarkdownTableCell).join(" | ")} |`;
|
|
1697
|
+
const divider = `| ${table.headers.map((_cell, index) => {
|
|
1698
|
+
switch (table.align[index]) {
|
|
1699
|
+
case "left":
|
|
1700
|
+
return ":---";
|
|
1701
|
+
case "center":
|
|
1702
|
+
return ":---:";
|
|
1703
|
+
case "right":
|
|
1704
|
+
return "---:";
|
|
1705
|
+
default:
|
|
1706
|
+
return "---";
|
|
1707
|
+
}
|
|
1708
|
+
}).join(" | ")} |`;
|
|
1709
|
+
const body = table.rows.map(
|
|
1710
|
+
(row) => `| ${table.headers.map((_cell, index) => escapeMarkdownTableCell(row[index] ?? "")).join(" | ")} |`
|
|
1711
|
+
);
|
|
1712
|
+
return [header, divider, ...body].join("\n");
|
|
1713
|
+
}
|
|
1714
|
+
function defaultWriteClipboard(text) {
|
|
1715
|
+
const clipboard = globalThis.navigator?.clipboard;
|
|
1716
|
+
clipboard?.writeText?.(text);
|
|
1717
|
+
}
|
|
1718
|
+
function defaultSaveFile(filename, content, mimeType) {
|
|
1719
|
+
const doc = globalThis.document;
|
|
1720
|
+
if (!doc?.body) return;
|
|
1721
|
+
const blob = new Blob([content], { type: mimeType });
|
|
1722
|
+
const url = URL.createObjectURL(blob);
|
|
1723
|
+
const anchor = doc.createElement("a");
|
|
1724
|
+
anchor.href = url;
|
|
1725
|
+
anchor.download = filename;
|
|
1726
|
+
doc.body.appendChild(anchor);
|
|
1727
|
+
anchor.click();
|
|
1728
|
+
doc.body.removeChild(anchor);
|
|
1729
|
+
URL.revokeObjectURL(url);
|
|
1730
|
+
}
|
|
1731
|
+
var BlockAffordanceButton = class _BlockAffordanceButton extends Button {
|
|
1732
|
+
constructor(label, successLabel, act, opts = {}) {
|
|
1733
|
+
super(label, { ...opts, onClick: () => this.run() });
|
|
1734
|
+
this.act = act;
|
|
1735
|
+
this.restingLabel = label;
|
|
1736
|
+
this.successLabel = successLabel;
|
|
1737
|
+
this.width = Math.max(this.width, measureText2(successLabel, this.font) + 24);
|
|
1447
1738
|
}
|
|
1448
|
-
|
|
1449
|
-
|
|
1450
|
-
|
|
1451
|
-
|
|
1452
|
-
|
|
1453
|
-
|
|
1454
|
-
|
|
1739
|
+
act;
|
|
1740
|
+
/** How long the confirmation label stays up, in ms. */
|
|
1741
|
+
static FEEDBACK_MS = 1600;
|
|
1742
|
+
restingLabel;
|
|
1743
|
+
successLabel;
|
|
1744
|
+
feedbackTimer;
|
|
1745
|
+
/**
|
|
1746
|
+
* Runs the action, then shows the confirmation.
|
|
1747
|
+
*
|
|
1748
|
+
* The action runs first and a throw propagates: a clipboard write the browser
|
|
1749
|
+
* rejected must not be reported as a success.
|
|
1750
|
+
*/
|
|
1751
|
+
run() {
|
|
1752
|
+
this.act();
|
|
1753
|
+
this.setTransientLabel(this.successLabel);
|
|
1754
|
+
if (this.feedbackTimer !== void 0) clearTimeout(this.feedbackTimer);
|
|
1755
|
+
this.feedbackTimer = setTimeout(() => {
|
|
1756
|
+
this.setTransientLabel(this.restingLabel);
|
|
1757
|
+
this.feedbackTimer = void 0;
|
|
1758
|
+
}, _BlockAffordanceButton.FEEDBACK_MS);
|
|
1455
1759
|
}
|
|
1456
|
-
|
|
1457
|
-
|
|
1458
|
-
this.
|
|
1459
|
-
this.contentEpoch++;
|
|
1760
|
+
setTransientLabel(label) {
|
|
1761
|
+
this.label = label;
|
|
1762
|
+
this.textWidth = measureText2(label, this.font);
|
|
1460
1763
|
this.scene?.markDirty();
|
|
1461
|
-
return this;
|
|
1462
|
-
}
|
|
1463
|
-
getContentEpoch() {
|
|
1464
|
-
return this.contentEpoch;
|
|
1465
1764
|
}
|
|
1466
1765
|
/**
|
|
1467
|
-
*
|
|
1468
|
-
*
|
|
1469
|
-
* Deliberately does **not** rebuild the grid or the highlight, because code does
|
|
1470
|
-
* not reflow: lines are placed on a fixed monospace grid at `col × cellWidth` and
|
|
1471
|
-
* a long line overflows rather than wrapping, so `height` is a function of line
|
|
1472
|
-
* *count* alone. The width only sizes the rounded background. Anything that would
|
|
1473
|
-
* change the glyph geometry — the source, the language, the font — goes through
|
|
1474
|
-
* {@link setCode} and invalidates the grid there.
|
|
1475
|
-
*
|
|
1476
|
-
* @returns `this` for chaining.
|
|
1766
|
+
* The label a reader hears is the one they see, transient confirmation
|
|
1767
|
+
* included, so an AT user gets the same feedback a sighted user does.
|
|
1477
1768
|
*/
|
|
1478
|
-
|
|
1479
|
-
|
|
1480
|
-
if (next === this.width) return this;
|
|
1481
|
-
this.width = next;
|
|
1482
|
-
this.scene?.markDirty();
|
|
1483
|
-
return this;
|
|
1769
|
+
getA11yAttributes() {
|
|
1770
|
+
return { ...super.getA11yAttributes(), label: this.label };
|
|
1484
1771
|
}
|
|
1485
|
-
|
|
1486
|
-
|
|
1487
|
-
|
|
1488
|
-
|
|
1489
|
-
|
|
1490
|
-
|
|
1491
|
-
|
|
1492
|
-
|
|
1493
|
-
|
|
1494
|
-
|
|
1495
|
-
|
|
1496
|
-
|
|
1497
|
-
|
|
1498
|
-
|
|
1499
|
-
|
|
1500
|
-
|
|
1501
|
-
|
|
1502
|
-
|
|
1772
|
+
/** Clears the pending revert so a destroyed block leaves no timer behind. */
|
|
1773
|
+
destroy() {
|
|
1774
|
+
if (this.feedbackTimer !== void 0) {
|
|
1775
|
+
clearTimeout(this.feedbackTimer);
|
|
1776
|
+
this.feedbackTimer = void 0;
|
|
1777
|
+
}
|
|
1778
|
+
super.destroy();
|
|
1779
|
+
}
|
|
1780
|
+
};
|
|
1781
|
+
var BlockWithAffordances = class _BlockWithAffordances extends UIComponent2 {
|
|
1782
|
+
constructor(block, controls) {
|
|
1783
|
+
super();
|
|
1784
|
+
this.block = block;
|
|
1785
|
+
this.controls = controls;
|
|
1786
|
+
this.add(block);
|
|
1787
|
+
for (const control of controls) this.add(control);
|
|
1788
|
+
this.layoutAffordances();
|
|
1789
|
+
}
|
|
1790
|
+
block;
|
|
1791
|
+
controls;
|
|
1792
|
+
/** Gap between the block's edges and the controls, in px. */
|
|
1793
|
+
static INSET = 8;
|
|
1794
|
+
/** Gap between adjacent controls, in px. */
|
|
1795
|
+
static GAP = 6;
|
|
1796
|
+
/**
|
|
1797
|
+
* Places the controls right-aligned along the block's top edge.
|
|
1798
|
+
*
|
|
1799
|
+
* Laid out right-to-left from the block's right edge so the first control in
|
|
1800
|
+
* the list ends up leftmost, which keeps DOM order (and therefore tab order and
|
|
1801
|
+
* the a11y reading order) matching the visual order.
|
|
1802
|
+
*/
|
|
1803
|
+
layoutAffordances() {
|
|
1804
|
+
this.width = this.block.width;
|
|
1805
|
+
this.height = this.block.height;
|
|
1806
|
+
let right = this.block.width - _BlockWithAffordances.INSET;
|
|
1807
|
+
for (let i = this.controls.length - 1; i >= 0; i--) {
|
|
1808
|
+
const control = this.controls[i];
|
|
1809
|
+
control.x = right - control.width;
|
|
1810
|
+
control.y = _BlockWithAffordances.INSET;
|
|
1811
|
+
right = control.x - _BlockWithAffordances.GAP;
|
|
1503
1812
|
}
|
|
1504
|
-
return {
|
|
1505
|
-
text: this.source,
|
|
1506
|
-
font: this.codeFont,
|
|
1507
|
-
lineHeight: this.lineH,
|
|
1508
|
-
// Every row is absolutely positioned from the same local coordinates as
|
|
1509
|
-
// render(). A single pre-wrap DOM text node would introduce browser
|
|
1510
|
-
// wrapping for long source lines that canvas intentionally keeps intact.
|
|
1511
|
-
//
|
|
1512
|
-
lines: rows,
|
|
1513
|
-
selectable: this.selectable,
|
|
1514
|
-
// render() draws cell-by-cell (no ligatures can form); the DOM copy
|
|
1515
|
-
// must not ligate either or Firefox selection geometry drifts.
|
|
1516
|
-
ligatures: "none",
|
|
1517
|
-
grid
|
|
1518
|
-
};
|
|
1519
1813
|
}
|
|
1520
1814
|
/**
|
|
1521
|
-
* Re-
|
|
1522
|
-
*
|
|
1523
|
-
* Streaming appends to the END of a block, so all but the last line or two are
|
|
1524
|
-
* byte-identical to the previous call — yet this used to re-highlight every
|
|
1525
|
-
* line on every chunk, making a streamed block O(N) per append and O(N^2)
|
|
1526
|
-
* overall. Reusing the stable prefix makes an append proportional to what
|
|
1527
|
-
* actually changed.
|
|
1815
|
+
* Re-places the controls after the block's own box changed.
|
|
1528
1816
|
*
|
|
1529
|
-
*
|
|
1530
|
-
*
|
|
1817
|
+
* Called by the owner when a block is resized or its content grew; the controls
|
|
1818
|
+
* are anchored to the right edge, so a width change moves them.
|
|
1531
1819
|
*/
|
|
1532
|
-
|
|
1533
|
-
this.
|
|
1534
|
-
|
|
1535
|
-
const previous = this.rawLines;
|
|
1536
|
-
let reusable = 0;
|
|
1537
|
-
if (previous && this.lines.length === previous.length) {
|
|
1538
|
-
const limit = Math.min(previous.length - 1, rawLines.length);
|
|
1539
|
-
while (reusable < limit && previous[reusable] === rawLines[reusable]) reusable++;
|
|
1540
|
-
}
|
|
1541
|
-
if (reusable > 0) {
|
|
1542
|
-
const next = this.lines.slice(0, reusable);
|
|
1543
|
-
for (let i = reusable; i < rawLines.length; i++) {
|
|
1544
|
-
next.push(highlightLine(rawLines[i], this.lang, this.theme));
|
|
1545
|
-
}
|
|
1546
|
-
this.lines = next;
|
|
1547
|
-
} else {
|
|
1548
|
-
this.lines = rawLines.map((l) => highlightLine(l, this.lang, this.theme));
|
|
1549
|
-
}
|
|
1550
|
-
this.rawLines = rawLines;
|
|
1551
|
-
this.grid = null;
|
|
1552
|
-
this.height = this.pad * 2 + rawLines.length * this.lineH;
|
|
1820
|
+
refreshAffordances() {
|
|
1821
|
+
this.layoutAffordances();
|
|
1822
|
+
this.scene?.markDirty();
|
|
1553
1823
|
}
|
|
1554
|
-
|
|
1555
|
-
|
|
1556
|
-
|
|
1557
|
-
this.grid = prepareContentGrid(this.source, {
|
|
1558
|
-
font: this.codeFont,
|
|
1559
|
-
cellWidth,
|
|
1560
|
-
lineHeight: this.lineH,
|
|
1561
|
-
baseline: this.lineH * 0.75
|
|
1562
|
-
});
|
|
1563
|
-
}
|
|
1564
|
-
return this.grid;
|
|
1824
|
+
/** The wrapper is a pass-through: its size is the block's size. */
|
|
1825
|
+
getLayoutControlledProperties() {
|
|
1826
|
+
return ["x", "y"];
|
|
1565
1827
|
}
|
|
1566
|
-
/**
|
|
1567
|
-
|
|
1568
|
-
|
|
1828
|
+
/**
|
|
1829
|
+
* Projected as a group so assistive technology reports one labelled region
|
|
1830
|
+
* containing the block and its controls, rather than two unrelated siblings.
|
|
1831
|
+
*/
|
|
1832
|
+
getA11yAttributes() {
|
|
1833
|
+
return { role: "group", pointerEvents: "none" };
|
|
1569
1834
|
}
|
|
1570
|
-
render(
|
|
1571
|
-
r.beginPath();
|
|
1572
|
-
r.roundRect(0, 0, this.width, this.height, 8);
|
|
1573
|
-
r.fill(this.theme.codeBgColor);
|
|
1574
|
-
const grid = this.ensureGrid();
|
|
1575
|
-
const atlas = codeGlyphAtlas(r);
|
|
1576
|
-
const atlasSource = atlas?.source ?? null;
|
|
1577
|
-
const blit = atlas ? r.drawImageRect : void 0;
|
|
1578
|
-
for (let row = 0; row < grid.lines.length; row++) {
|
|
1579
|
-
const yBaseline = this.pad + row * this.lineH + this.lineH * 0.75;
|
|
1580
|
-
const segments = this.lines[row];
|
|
1581
|
-
let segmentIndex = 0;
|
|
1582
|
-
let segmentEnd = segments[0]?.text.length ?? 0;
|
|
1583
|
-
const lineStart = grid.lines[row].sourceStart;
|
|
1584
|
-
for (const cell of grid.lines[row].cells) {
|
|
1585
|
-
const localSourceStart = cell.sourceStart - lineStart;
|
|
1586
|
-
while (segmentIndex < segments.length - 1 && localSourceStart >= segmentEnd) {
|
|
1587
|
-
segmentIndex++;
|
|
1588
|
-
segmentEnd += segments[segmentIndex].text.length;
|
|
1589
|
-
}
|
|
1590
|
-
const sourceText = this.source.slice(cell.sourceStart, cell.sourceEnd);
|
|
1591
|
-
if (cell.advance <= 0 || sourceText === " " || sourceText === " ") continue;
|
|
1592
|
-
const color = segments[segmentIndex]?.color ?? this.theme.codeColor;
|
|
1593
|
-
const x = this.pad + cell.x;
|
|
1594
|
-
if (blit && atlas) {
|
|
1595
|
-
const slot = atlas.get(this.codeFont, color, cell.glyph);
|
|
1596
|
-
const src = atlasSource ?? atlas.source;
|
|
1597
|
-
if (slot && src) {
|
|
1598
|
-
blit.call(
|
|
1599
|
-
r,
|
|
1600
|
-
src,
|
|
1601
|
-
slot.sx,
|
|
1602
|
-
slot.sy,
|
|
1603
|
-
slot.sw,
|
|
1604
|
-
slot.sh,
|
|
1605
|
-
x - slot.offsetX,
|
|
1606
|
-
yBaseline - slot.offsetY,
|
|
1607
|
-
slot.w,
|
|
1608
|
-
slot.h
|
|
1609
|
-
);
|
|
1610
|
-
continue;
|
|
1611
|
-
}
|
|
1612
|
-
}
|
|
1613
|
-
r.fillText(cell.glyph, x, yBaseline, this.codeFont, color);
|
|
1614
|
-
}
|
|
1615
|
-
}
|
|
1835
|
+
render() {
|
|
1616
1836
|
}
|
|
1617
1837
|
};
|
|
1618
|
-
|
|
1619
|
-
|
|
1620
|
-
|
|
1621
|
-
|
|
1622
|
-
|
|
1623
|
-
|
|
1624
|
-
|
|
1625
|
-
|
|
1626
|
-
|
|
1627
|
-
|
|
1628
|
-
|
|
1629
|
-
|
|
1630
|
-
|
|
1631
|
-
|
|
1632
|
-
|
|
1633
|
-
|
|
1838
|
+
function tableContentOf(token) {
|
|
1839
|
+
return {
|
|
1840
|
+
headers: token.header.map((cell) => cell.text),
|
|
1841
|
+
rows: token.rows.map((row) => row.map((cell) => cell.text)),
|
|
1842
|
+
align: token.align
|
|
1843
|
+
};
|
|
1844
|
+
}
|
|
1845
|
+
|
|
1846
|
+
// src/frontMatter.ts
|
|
1847
|
+
var OPEN_RE = /^---[ \t]*\r?\n/;
|
|
1848
|
+
var OPENER_PREFIX_RE = /^(?:-|--|---[ \t]*\r?)$/;
|
|
1849
|
+
var KEY_RE = /^[^\s:#][^:]*:(?:[ \t].*)?$/;
|
|
1850
|
+
var CLOSE_RE = /^(?:---|\.\.\.)[ \t]*$/;
|
|
1851
|
+
var MAX_PENDING_CHARS = 4096;
|
|
1852
|
+
var NONE = { kind: "none" };
|
|
1853
|
+
var PENDING = { kind: "pending" };
|
|
1854
|
+
function scanFrontMatter(text, complete) {
|
|
1855
|
+
if (text.length === 0) return PENDING;
|
|
1856
|
+
const open = OPEN_RE.exec(text);
|
|
1857
|
+
if (!open) {
|
|
1858
|
+
return !complete && OPENER_PREFIX_RE.test(text) ? PENDING : NONE;
|
|
1634
1859
|
}
|
|
1635
|
-
const
|
|
1636
|
-
|
|
1637
|
-
|
|
1638
|
-
|
|
1639
|
-
|
|
1640
|
-
|
|
1641
|
-
if (
|
|
1860
|
+
const decide = complete || text.length > MAX_PENDING_CHARS;
|
|
1861
|
+
const contentStart = open[0].length;
|
|
1862
|
+
let cursor = contentStart;
|
|
1863
|
+
let keyChecked = false;
|
|
1864
|
+
while (cursor < text.length) {
|
|
1865
|
+
const nl = text.indexOf("\n", cursor);
|
|
1866
|
+
if (nl === -1 && !decide) return PENDING;
|
|
1867
|
+
const line = text.slice(cursor, nl === -1 ? text.length : nl).replace(/\r$/, "");
|
|
1868
|
+
if (!keyChecked) {
|
|
1869
|
+
if (!KEY_RE.test(line)) return NONE;
|
|
1870
|
+
keyChecked = true;
|
|
1871
|
+
} else if (CLOSE_RE.test(line)) {
|
|
1872
|
+
return {
|
|
1873
|
+
kind: "found",
|
|
1874
|
+
raw: text.slice(contentStart, cursor),
|
|
1875
|
+
// A closer with no trailing newline ends the document, so the body is
|
|
1876
|
+
// empty rather than starting one character past the end.
|
|
1877
|
+
bodyStart: nl === -1 ? text.length : nl + 1
|
|
1878
|
+
};
|
|
1879
|
+
}
|
|
1880
|
+
if (nl === -1) break;
|
|
1881
|
+
cursor = nl + 1;
|
|
1642
1882
|
}
|
|
1643
|
-
|
|
1644
|
-
return atlas;
|
|
1883
|
+
return decide ? NONE : PENDING;
|
|
1645
1884
|
}
|
|
1646
|
-
function
|
|
1647
|
-
|
|
1885
|
+
function parseFrontMatterFields(raw) {
|
|
1886
|
+
const out = {};
|
|
1887
|
+
for (const rawLine of raw.split("\n")) {
|
|
1888
|
+
const line = rawLine.replace(/\r$/, "");
|
|
1889
|
+
if (line.length === 0 || /^[\s#]/.test(line)) continue;
|
|
1890
|
+
const sep = line.indexOf(":");
|
|
1891
|
+
if (sep <= 0) continue;
|
|
1892
|
+
const value = line.slice(sep + 1);
|
|
1893
|
+
if (value.length > 0 && value[0] !== " " && value[0] !== " ") continue;
|
|
1894
|
+
out[line.slice(0, sep).trim()] = unquote(value.trim());
|
|
1895
|
+
}
|
|
1896
|
+
return out;
|
|
1648
1897
|
}
|
|
1649
|
-
function
|
|
1650
|
-
return
|
|
1898
|
+
function unquote(value) {
|
|
1899
|
+
if (value.length < 2) return value;
|
|
1900
|
+
const first = value[0];
|
|
1901
|
+
if ((first === '"' || first === "'") && value.endsWith(first)) {
|
|
1902
|
+
return value.slice(1, -1);
|
|
1903
|
+
}
|
|
1904
|
+
return value;
|
|
1651
1905
|
}
|
|
1652
|
-
|
|
1653
|
-
|
|
1906
|
+
|
|
1907
|
+
// src/MarkdownWorkerSource.ts
|
|
1908
|
+
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';
|
|
1909
|
+
|
|
1910
|
+
// src/Markdown.ts
|
|
1911
|
+
var now = () => typeof performance !== "undefined" && typeof performance.now === "function" ? performance.now() : Date.now();
|
|
1912
|
+
function lexMarkdown(text, userTiming) {
|
|
1913
|
+
if (!userTiming) return marked.lexer(text);
|
|
1914
|
+
const timing = beginVectoUserTiming(VECTO_USER_TIMING.markdown.parse);
|
|
1915
|
+
try {
|
|
1916
|
+
return marked.lexer(text);
|
|
1917
|
+
} finally {
|
|
1918
|
+
if (timing) endVectoUserTiming(timing);
|
|
1919
|
+
}
|
|
1654
1920
|
}
|
|
1655
|
-
|
|
1656
|
-
|
|
1657
|
-
|
|
1658
|
-
|
|
1659
|
-
|
|
1660
|
-
|
|
1661
|
-
|
|
1662
|
-
|
|
1663
|
-
|
|
1664
|
-
|
|
1665
|
-
|
|
1666
|
-
|
|
1667
|
-
|
|
1668
|
-
|
|
1669
|
-
|
|
1670
|
-
|
|
1671
|
-
|
|
1672
|
-
|
|
1673
|
-
|
|
1674
|
-
|
|
1675
|
-
out.push({
|
|
1676
|
-
text: decodeEntities(t.text),
|
|
1677
|
-
style: { ...inherited, italic: true }
|
|
1678
|
-
});
|
|
1921
|
+
marked.use({
|
|
1922
|
+
// `FOOTNOTE_EXTENSIONS` is shared with `MarkdownWorker.ts` rather than spelled
|
|
1923
|
+
// out twice: the two registration sites must agree exactly, or the worker
|
|
1924
|
+
// returns tokens this renderer has no arm for.
|
|
1925
|
+
extensions: [
|
|
1926
|
+
...FOOTNOTE_EXTENSIONS,
|
|
1927
|
+
{
|
|
1928
|
+
name: "blockMath",
|
|
1929
|
+
level: "block",
|
|
1930
|
+
start(src) {
|
|
1931
|
+
return src.match(/^ {0,3}\$\$/m)?.index;
|
|
1932
|
+
},
|
|
1933
|
+
tokenizer(src) {
|
|
1934
|
+
const match = /^ {0,3}\$\$([\s\S]+?)\$\$[ \t]*(?:\n|$)/.exec(src);
|
|
1935
|
+
if (match) {
|
|
1936
|
+
return {
|
|
1937
|
+
type: "blockMath",
|
|
1938
|
+
raw: match[0],
|
|
1939
|
+
text: match[1].trim()
|
|
1940
|
+
};
|
|
1679
1941
|
}
|
|
1680
|
-
|
|
1942
|
+
return void 0;
|
|
1943
|
+
},
|
|
1944
|
+
renderer(token) {
|
|
1945
|
+
return token.raw;
|
|
1681
1946
|
}
|
|
1682
|
-
|
|
1683
|
-
|
|
1684
|
-
|
|
1685
|
-
|
|
1686
|
-
|
|
1687
|
-
|
|
1688
|
-
|
|
1689
|
-
|
|
1690
|
-
|
|
1947
|
+
},
|
|
1948
|
+
{
|
|
1949
|
+
name: "inlineMath",
|
|
1950
|
+
level: "inline",
|
|
1951
|
+
start(src) {
|
|
1952
|
+
return src.match(/(?<![\\$])\$(?![$\s])/)?.index;
|
|
1953
|
+
},
|
|
1954
|
+
tokenizer(src) {
|
|
1955
|
+
const match = /^\$(?![$\s\d])((?:\\\$|[^$\n])*?)(?<!\s)\$(?!\d)/.exec(src);
|
|
1956
|
+
if (match) {
|
|
1957
|
+
return {
|
|
1958
|
+
type: "inlineMath",
|
|
1959
|
+
raw: match[0],
|
|
1960
|
+
text: match[1].trim()
|
|
1961
|
+
};
|
|
1691
1962
|
}
|
|
1692
|
-
|
|
1693
|
-
}
|
|
1694
|
-
|
|
1695
|
-
|
|
1696
|
-
out.push({
|
|
1697
|
-
text: decodeEntities(t.text),
|
|
1698
|
-
// Inline code renders in the theme's monospace family (not just tinted
|
|
1699
|
-
// prose) — TextStyle.fontFamily drives both measurement and drawing.
|
|
1700
|
-
style: {
|
|
1701
|
-
...inherited,
|
|
1702
|
-
color: theme.codeColor,
|
|
1703
|
-
fontFamily: theme.codeFont
|
|
1704
|
-
}
|
|
1705
|
-
});
|
|
1706
|
-
break;
|
|
1707
|
-
}
|
|
1708
|
-
case "br": {
|
|
1709
|
-
out.push({ text: "\n" });
|
|
1710
|
-
break;
|
|
1711
|
-
}
|
|
1712
|
-
case "html": {
|
|
1713
|
-
const t = token;
|
|
1714
|
-
const raw = t.raw ?? t.text ?? "";
|
|
1715
|
-
const brCount = (raw.match(/<br\s*\/?>/gi) ?? []).length;
|
|
1716
|
-
for (let i = 0; i < brCount; i++) out.push({ text: "\n" });
|
|
1717
|
-
break;
|
|
1963
|
+
return void 0;
|
|
1964
|
+
},
|
|
1965
|
+
renderer(token) {
|
|
1966
|
+
return token.raw;
|
|
1718
1967
|
}
|
|
1719
|
-
|
|
1720
|
-
|
|
1721
|
-
|
|
1722
|
-
|
|
1723
|
-
|
|
1724
|
-
|
|
1725
|
-
|
|
1726
|
-
|
|
1727
|
-
|
|
1728
|
-
|
|
1729
|
-
|
|
1730
|
-
|
|
1731
|
-
|
|
1732
|
-
|
|
1733
|
-
|
|
1734
|
-
|
|
1735
|
-
|
|
1736
|
-
|
|
1737
|
-
|
|
1738
|
-
|
|
1739
|
-
|
|
1740
|
-
|
|
1741
|
-
|
|
1742
|
-
|
|
1743
|
-
|
|
1744
|
-
|
|
1968
|
+
}
|
|
1969
|
+
]
|
|
1970
|
+
});
|
|
1971
|
+
var markdownWorker = null;
|
|
1972
|
+
var workerIdCounter = 0;
|
|
1973
|
+
var workerInstanceCounter = 0;
|
|
1974
|
+
var workerCallbacks = /* @__PURE__ */ new Map();
|
|
1975
|
+
function runSyncFallback(entry) {
|
|
1976
|
+
try {
|
|
1977
|
+
entry.cb(0, lexMarkdown(entry.text, entry.userTiming), true);
|
|
1978
|
+
} catch (err) {
|
|
1979
|
+
console.warn("Markdown sync fallback parse failed", err);
|
|
1980
|
+
entry.onDropped?.();
|
|
1981
|
+
}
|
|
1982
|
+
}
|
|
1983
|
+
if (typeof Worker !== "undefined") {
|
|
1984
|
+
try {
|
|
1985
|
+
const blob = new Blob([WORKER_SOURCE_STRING], {
|
|
1986
|
+
type: "application/javascript"
|
|
1987
|
+
});
|
|
1988
|
+
markdownWorker = new Worker(URL.createObjectURL(blob));
|
|
1989
|
+
markdownWorker.onmessage = (e) => {
|
|
1990
|
+
const { id, matchLen, tail, error, needResync, lexerMs, sourceCharsLexed } = e.data;
|
|
1991
|
+
const entry = workerCallbacks.get(id);
|
|
1992
|
+
if (entry) {
|
|
1993
|
+
workerCallbacks.delete(id);
|
|
1994
|
+
if (needResync && entry.onNeedResync) {
|
|
1995
|
+
entry.onNeedResync();
|
|
1996
|
+
} else if (needResync) {
|
|
1997
|
+
runSyncFallback(entry);
|
|
1998
|
+
} else if (!error) {
|
|
1999
|
+
entry.cb(matchLen, tail, false, {
|
|
2000
|
+
lexerMs: typeof lexerMs === "number" ? lexerMs : 0,
|
|
2001
|
+
sourceCharsLexed: typeof sourceCharsLexed === "number" ? sourceCharsLexed : 0
|
|
1745
2002
|
});
|
|
1746
|
-
}
|
|
1747
|
-
break;
|
|
1748
|
-
}
|
|
1749
|
-
case "link": {
|
|
1750
|
-
const t = token;
|
|
1751
|
-
const linkStyle = {
|
|
1752
|
-
...inherited,
|
|
1753
|
-
href: t.href,
|
|
1754
|
-
color: "#38bdf8"
|
|
1755
|
-
};
|
|
1756
|
-
if (t.tokens && t.tokens.length > 0) {
|
|
1757
|
-
collectSpans(t.tokens, linkStyle, theme, out, blockFontSize);
|
|
1758
|
-
} else {
|
|
1759
|
-
out.push({ text: decodeEntities(t.text), style: linkStyle });
|
|
1760
|
-
}
|
|
1761
|
-
break;
|
|
1762
|
-
}
|
|
1763
|
-
case "text": {
|
|
1764
|
-
const t = token;
|
|
1765
|
-
if ("tokens" in t && t.tokens?.length) {
|
|
1766
|
-
collectSpans(t.tokens, inherited, theme, out, blockFontSize);
|
|
1767
2003
|
} else {
|
|
1768
|
-
|
|
1769
|
-
if (decoded) {
|
|
1770
|
-
const style = Object.keys(inherited).length > 0 ? inherited : void 0;
|
|
1771
|
-
out.push({ text: decoded, style });
|
|
1772
|
-
}
|
|
1773
|
-
}
|
|
1774
|
-
break;
|
|
1775
|
-
}
|
|
1776
|
-
default: {
|
|
1777
|
-
if ("text" in token) {
|
|
1778
|
-
const decoded = decodeEntities(token.text);
|
|
1779
|
-
if (decoded) {
|
|
1780
|
-
const style = Object.keys(inherited).length > 0 ? inherited : void 0;
|
|
1781
|
-
out.push({ text: decoded, style });
|
|
1782
|
-
}
|
|
2004
|
+
runSyncFallback(entry);
|
|
1783
2005
|
}
|
|
1784
|
-
break;
|
|
1785
2006
|
}
|
|
1786
|
-
}
|
|
1787
|
-
}
|
|
1788
|
-
}
|
|
1789
|
-
function findUnclosedInline(text) {
|
|
1790
|
-
let best = null;
|
|
1791
|
-
const tick = text.lastIndexOf("`");
|
|
1792
|
-
if (tick !== -1 && tick < text.length - 1) {
|
|
1793
|
-
return { kind: "codespan", at: tick, contentAt: tick + 1 };
|
|
1794
|
-
}
|
|
1795
|
-
if (tick !== -1) return null;
|
|
1796
|
-
const emphasis = /(\*{1,2}(?!\*)|_{1,2}(?!_))(?=[^\s])/g;
|
|
1797
|
-
for (let match = emphasis.exec(text); match !== null; match = emphasis.exec(text)) {
|
|
1798
|
-
const marker = match[1];
|
|
1799
|
-
const at = match.index;
|
|
1800
|
-
if (marker[0] === "_" && at > 0 && /[\w]/.test(text[at - 1])) continue;
|
|
1801
|
-
best = {
|
|
1802
|
-
kind: marker.length === 2 ? "strong" : "em",
|
|
1803
|
-
at,
|
|
1804
|
-
contentAt: at + marker.length
|
|
1805
2007
|
};
|
|
2008
|
+
markdownWorker.onerror = () => {
|
|
2009
|
+
const pending = [...workerCallbacks.values()];
|
|
2010
|
+
workerCallbacks.clear();
|
|
2011
|
+
markdownWorker = null;
|
|
2012
|
+
for (const entry of pending) runSyncFallback(entry);
|
|
2013
|
+
};
|
|
2014
|
+
} catch (err) {
|
|
2015
|
+
console.warn("Failed to initialize MarkdownWorker", err);
|
|
1806
2016
|
}
|
|
1807
|
-
const bracket = text.lastIndexOf("[");
|
|
1808
|
-
if (bracket !== -1 && bracket < text.length - 1 && (best === null || bracket > best.at)) {
|
|
1809
|
-
const closed = /\]\([^)]*\)/.test(text.slice(bracket));
|
|
1810
|
-
if (!closed) {
|
|
1811
|
-
best = { kind: "link", at: bracket, contentAt: bracket + 1 };
|
|
1812
|
-
}
|
|
1813
|
-
}
|
|
1814
|
-
return best;
|
|
1815
|
-
}
|
|
1816
|
-
function renderInlineToRichText(tokens, fallbackText, font, color, maxWidth, theme, selectable, onLinkClick) {
|
|
1817
|
-
const spans = [];
|
|
1818
|
-
if (tokens && tokens.length > 0) {
|
|
1819
|
-
collectSpans(tokens, {}, theme, spans, fontSizeFromFont(font));
|
|
1820
|
-
}
|
|
1821
|
-
if (spans.length === 0) {
|
|
1822
|
-
spans.push({ text: decodeEntities(fallbackText) });
|
|
1823
|
-
}
|
|
1824
|
-
return new RichText(spans, {
|
|
1825
|
-
font,
|
|
1826
|
-
color,
|
|
1827
|
-
maxWidth,
|
|
1828
|
-
linkColor: "#38bdf8",
|
|
1829
|
-
selectable,
|
|
1830
|
-
onLinkClick
|
|
1831
|
-
});
|
|
1832
2017
|
}
|
|
1833
|
-
var Markdown = class _Markdown extends
|
|
2018
|
+
var Markdown = class _Markdown extends UIComponent3 {
|
|
1834
2019
|
content;
|
|
1835
2020
|
maxWidth;
|
|
1836
2021
|
theme;
|
|
@@ -1923,6 +2108,20 @@ var Markdown = class _Markdown extends UIComponent2 {
|
|
|
1923
2108
|
* field only so {@link destroy} can remove the exact closure it added.
|
|
1924
2109
|
*/
|
|
1925
2110
|
inlineMathRepaint;
|
|
2111
|
+
/**
|
|
2112
|
+
* This instance's entry in the inline-image decode waiters, or `undefined` if it
|
|
2113
|
+
* has never rendered an image. Held as a field only so {@link destroy} can remove
|
|
2114
|
+
* the exact closure it added.
|
|
2115
|
+
*/
|
|
2116
|
+
inlineImageRemeasure;
|
|
2117
|
+
/**
|
|
2118
|
+
* URLs whose decoded aspect ratio this document has already reserved a box for.
|
|
2119
|
+
*
|
|
2120
|
+
* The guard that makes the re-measure fire once per image rather than once per
|
|
2121
|
+
* decode-notification-per-image: the waiter set is module-level, so a page of
|
|
2122
|
+
* many documents tells all of them about all decodes.
|
|
2123
|
+
*/
|
|
2124
|
+
inlineImagesMeasured = /* @__PURE__ */ new Set();
|
|
1926
2125
|
/**
|
|
1927
2126
|
* True while this document is waiting on the lazy MathJax load.
|
|
1928
2127
|
*
|
|
@@ -2068,14 +2267,17 @@ var Markdown = class _Markdown extends UIComponent2 {
|
|
|
2068
2267
|
constructor(markdownText, opts = {}) {
|
|
2069
2268
|
super();
|
|
2070
2269
|
this.maxWidth = opts.maxWidth ?? 800;
|
|
2071
|
-
this.theme =
|
|
2270
|
+
this.theme = resolveTheme(opts.theme);
|
|
2072
2271
|
this.onLinkClick = opts.onLinkClick;
|
|
2073
2272
|
this.selectable = opts.selectable ?? true;
|
|
2074
2273
|
this._userTiming = opts.userTiming ?? false;
|
|
2075
2274
|
this.blockAffordances = opts.blockAffordances ?? false;
|
|
2076
2275
|
this.writeClipboard = opts.writeClipboard ?? defaultWriteClipboard;
|
|
2077
2276
|
this.saveFile = opts.saveFile ?? defaultSaveFile;
|
|
2078
|
-
this.content = new Stack({
|
|
2277
|
+
this.content = new Stack({
|
|
2278
|
+
direction: "vertical",
|
|
2279
|
+
gap: this.theme.blockGap
|
|
2280
|
+
});
|
|
2079
2281
|
this.add(this.content);
|
|
2080
2282
|
this.rawMarkdown = "";
|
|
2081
2283
|
this.setTokens([]);
|
|
@@ -2294,14 +2496,14 @@ var Markdown = class _Markdown extends UIComponent2 {
|
|
|
2294
2496
|
switch (token.type) {
|
|
2295
2497
|
case "heading":
|
|
2296
2498
|
case "paragraph": {
|
|
2297
|
-
if (entity instanceof
|
|
2499
|
+
if (entity instanceof RichText2) {
|
|
2298
2500
|
entity.setMaxWidth(availableWidth);
|
|
2299
2501
|
return;
|
|
2300
2502
|
}
|
|
2301
2503
|
if (entity instanceof Stack) {
|
|
2302
2504
|
entity.maxWidth = availableWidth;
|
|
2303
2505
|
for (const run of entity.children) {
|
|
2304
|
-
if (run instanceof
|
|
2506
|
+
if (run instanceof RichText2) run.setMaxWidth(availableWidth);
|
|
2305
2507
|
else if (run instanceof Image) this.refitParagraphImage(run, availableWidth);
|
|
2306
2508
|
}
|
|
2307
2509
|
entity.layout();
|
|
@@ -2317,7 +2519,7 @@ var Markdown = class _Markdown extends UIComponent2 {
|
|
|
2317
2519
|
const bqToken = token;
|
|
2318
2520
|
const innerStack = entity.children.find((c) => c instanceof Stack);
|
|
2319
2521
|
const border = entity.children.find((c) => c instanceof QuoteBorder);
|
|
2320
|
-
const indentStart = Math.min(
|
|
2522
|
+
const indentStart = Math.min(this.theme.quoteIndent, availableWidth);
|
|
2321
2523
|
const childWidth = Math.max(0, availableWidth - indentStart);
|
|
2322
2524
|
if (innerStack instanceof Stack && bqToken.tokens) {
|
|
2323
2525
|
let index = 0;
|
|
@@ -2344,7 +2546,7 @@ var Markdown = class _Markdown extends UIComponent2 {
|
|
|
2344
2546
|
case "list": {
|
|
2345
2547
|
if (!(entity instanceof Stack)) return;
|
|
2346
2548
|
for (const item of entity.children) {
|
|
2347
|
-
if (item instanceof
|
|
2549
|
+
if (item instanceof RichText2) item.setMaxWidth(availableWidth);
|
|
2348
2550
|
}
|
|
2349
2551
|
entity.layout();
|
|
2350
2552
|
return;
|
|
@@ -2357,6 +2559,10 @@ var Markdown = class _Markdown extends UIComponent2 {
|
|
|
2357
2559
|
if (entity instanceof HorizontalRule) entity.width = availableWidth;
|
|
2358
2560
|
return;
|
|
2359
2561
|
}
|
|
2562
|
+
case "footnoteDef": {
|
|
2563
|
+
if (entity instanceof RichText2) entity.setMaxWidth(availableWidth);
|
|
2564
|
+
return;
|
|
2565
|
+
}
|
|
2360
2566
|
default: {
|
|
2361
2567
|
if (entity instanceof Text) entity.setMaxWidth(availableWidth);
|
|
2362
2568
|
return;
|
|
@@ -2420,7 +2626,98 @@ var Markdown = class _Markdown extends UIComponent2 {
|
|
|
2420
2626
|
this.scene?.markDirty();
|
|
2421
2627
|
};
|
|
2422
2628
|
this.inlineMathRepaint = repaint;
|
|
2423
|
-
|
|
2629
|
+
subscribeInlineMathRaster(repaint);
|
|
2630
|
+
}
|
|
2631
|
+
/**
|
|
2632
|
+
* Re-measure this document when an inline image's raster finishes decoding.
|
|
2633
|
+
*
|
|
2634
|
+
* Inline images differ from inline formulas in one way that matters: a formula's
|
|
2635
|
+
* box is known synchronously the moment it typesets, while an image's aspect
|
|
2636
|
+
* ratio arrives only with the decode. The span reserved a square until then, so a
|
|
2637
|
+
* decode that reports anything else has invalidated a WIDTH, and a repaint into
|
|
2638
|
+
* the old box would letterbox or stretch the picture.
|
|
2639
|
+
*
|
|
2640
|
+
* So this rebuilds through {@link retypesetFromTokens} — the same late-arrival
|
|
2641
|
+
* path MathJax uses — but only when a reserved width actually changed. Every live
|
|
2642
|
+
* document is notified for every decode, including images it does not contain, so
|
|
2643
|
+
* an unconditional rebuild here would be O(documents x images) full re-renders
|
|
2644
|
+
* for a page of many blocks.
|
|
2645
|
+
*
|
|
2646
|
+
* Subscribed lazily and held as a field for the same two reasons as its math
|
|
2647
|
+
* counterpart: a document with no images costs nothing, and `destroy` must remove
|
|
2648
|
+
* the exact closure it added.
|
|
2649
|
+
*/
|
|
2650
|
+
subscribeInlineImageRemeasure() {
|
|
2651
|
+
if (this.inlineImageRemeasure || this.isDestroyed) return;
|
|
2652
|
+
const remeasure = () => {
|
|
2653
|
+
if (this.isDestroyed) return;
|
|
2654
|
+
if (this.inlineImageBoxesStale()) this.retypesetFromTokens();
|
|
2655
|
+
else this.scene?.markDirty();
|
|
2656
|
+
};
|
|
2657
|
+
this.inlineImageRemeasure = remeasure;
|
|
2658
|
+
subscribeInlineImageRaster(remeasure);
|
|
2659
|
+
}
|
|
2660
|
+
/**
|
|
2661
|
+
* Whether any inline image in this document has just learned it is not square.
|
|
2662
|
+
*
|
|
2663
|
+
* An inline image's span reserves a square box before its raster decodes, because
|
|
2664
|
+
* that is the only shape available without a natural size. The decode supplies the
|
|
2665
|
+
* real aspect ratio, so a non-square image needs one rebuild to reserve the right
|
|
2666
|
+
* width — and exactly one. Every live document is notified of every decode on the
|
|
2667
|
+
* page, including images it does not contain, so this has to answer "did MY
|
|
2668
|
+
* geometry just change" and not merely "did something decode".
|
|
2669
|
+
*
|
|
2670
|
+
* Walks the tokens rather than the entity tree: the reserved box is a function of
|
|
2671
|
+
* the raster's aspect ratio, which is available here, and a token walk cannot be
|
|
2672
|
+
* confused by an entity a previous rebuild already corrected.
|
|
2673
|
+
*
|
|
2674
|
+
* Only headings and table cells are inspected. Every other context splits an image
|
|
2675
|
+
* into its own block whose `Image` entity resizes itself in `onLoad`, so a rebuild
|
|
2676
|
+
* for one of those would be pure cost.
|
|
2677
|
+
*/
|
|
2678
|
+
inlineImageBoxesStale() {
|
|
2679
|
+
const stale = (tokens) => {
|
|
2680
|
+
let changed2 = false;
|
|
2681
|
+
for (const token of tokens ?? []) {
|
|
2682
|
+
if (token.type === "image") {
|
|
2683
|
+
const href = token.href;
|
|
2684
|
+
if (this.inlineImagesMeasured.has(href)) continue;
|
|
2685
|
+
const raster = ensureInlineImageRaster(href);
|
|
2686
|
+
if (raster.failed) {
|
|
2687
|
+
this.inlineImagesMeasured.add(href);
|
|
2688
|
+
changed2 = true;
|
|
2689
|
+
continue;
|
|
2690
|
+
}
|
|
2691
|
+
if (!raster.decoded || !raster.naturalWidth || !raster.naturalHeight) {
|
|
2692
|
+
continue;
|
|
2693
|
+
}
|
|
2694
|
+
this.inlineImagesMeasured.add(href);
|
|
2695
|
+
if (raster.naturalWidth !== raster.naturalHeight) changed2 = true;
|
|
2696
|
+
continue;
|
|
2697
|
+
}
|
|
2698
|
+
if (stale(token.tokens)) {
|
|
2699
|
+
changed2 = true;
|
|
2700
|
+
}
|
|
2701
|
+
}
|
|
2702
|
+
return changed2;
|
|
2703
|
+
};
|
|
2704
|
+
let changed = false;
|
|
2705
|
+
for (const token of this.tokens) {
|
|
2706
|
+
if (token.type === "heading") {
|
|
2707
|
+
if (stale(token.tokens)) changed = true;
|
|
2708
|
+
} else if (token.type === "table") {
|
|
2709
|
+
const table = token;
|
|
2710
|
+
for (const cell of table.header) {
|
|
2711
|
+
if (stale(cell.tokens)) changed = true;
|
|
2712
|
+
}
|
|
2713
|
+
for (const row of table.rows) {
|
|
2714
|
+
for (const cell of row) {
|
|
2715
|
+
if (stale(cell.tokens)) changed = true;
|
|
2716
|
+
}
|
|
2717
|
+
}
|
|
2718
|
+
}
|
|
2719
|
+
}
|
|
2720
|
+
return changed;
|
|
2424
2721
|
}
|
|
2425
2722
|
destroy() {
|
|
2426
2723
|
this.isDestroyed = true;
|
|
@@ -2433,9 +2730,13 @@ var Markdown = class _Markdown extends UIComponent2 {
|
|
|
2433
2730
|
this.mathLoadPending = false;
|
|
2434
2731
|
this.flushAppendSettledWaiters();
|
|
2435
2732
|
if (this.inlineMathRepaint) {
|
|
2436
|
-
|
|
2733
|
+
unsubscribeInlineMathRaster(this.inlineMathRepaint);
|
|
2437
2734
|
this.inlineMathRepaint = void 0;
|
|
2438
2735
|
}
|
|
2736
|
+
if (this.inlineImageRemeasure) {
|
|
2737
|
+
unsubscribeInlineImageRaster(this.inlineImageRemeasure);
|
|
2738
|
+
this.inlineImageRemeasure = void 0;
|
|
2739
|
+
}
|
|
2439
2740
|
markdownWorker?.postMessage({
|
|
2440
2741
|
instance: this.workerInstanceId,
|
|
2441
2742
|
dispose: true
|
|
@@ -2829,11 +3130,11 @@ var Markdown = class _Markdown extends UIComponent2 {
|
|
|
2829
3130
|
}
|
|
2830
3131
|
/** One text run of an image-bearing paragraph, as both paths build it. */
|
|
2831
3132
|
inlineRunRichText(tokens, availableWidth, t) {
|
|
2832
|
-
return new
|
|
3133
|
+
return new RichText2(this.inlineRunSpans(tokens, t), {
|
|
2833
3134
|
font: `${t.fontSize}px ${t.bodyFont}`,
|
|
2834
3135
|
color: t.textColor,
|
|
2835
3136
|
maxWidth: availableWidth,
|
|
2836
|
-
linkColor:
|
|
3137
|
+
linkColor: t.linkColor,
|
|
2837
3138
|
selectable: this.selectable,
|
|
2838
3139
|
onLinkClick: this.onLinkClick
|
|
2839
3140
|
});
|
|
@@ -2937,7 +3238,7 @@ var Markdown = class _Markdown extends UIComponent2 {
|
|
|
2937
3238
|
width: initialWidth,
|
|
2938
3239
|
height: initialHeight,
|
|
2939
3240
|
alt: imgToken.text,
|
|
2940
|
-
radius:
|
|
3241
|
+
radius: this.theme.imageRadius,
|
|
2941
3242
|
onLoad: () => {
|
|
2942
3243
|
const bmp = img.bitmap;
|
|
2943
3244
|
if (bmp && bmp.naturalWidth && bmp.naturalHeight) {
|
|
@@ -2952,11 +3253,11 @@ var Markdown = class _Markdown extends UIComponent2 {
|
|
|
2952
3253
|
}
|
|
2953
3254
|
/** One table cell entity, shared by the render arm and the streamed-table path. */
|
|
2954
3255
|
tableCellRichText(cell, header, t) {
|
|
2955
|
-
return new
|
|
2956
|
-
font: `${t.
|
|
3256
|
+
return new RichText2(this.tableCellSpans(cell, t), {
|
|
3257
|
+
font: `${t.tableFontSize}px ${t.bodyFont}`,
|
|
2957
3258
|
color: header ? t.headingColor : t.textColor,
|
|
2958
3259
|
baseStyle: header ? { bold: true } : void 0,
|
|
2959
|
-
linkColor:
|
|
3260
|
+
linkColor: t.linkColor,
|
|
2960
3261
|
selectable: this.selectable,
|
|
2961
3262
|
onLinkClick: this.onLinkClick
|
|
2962
3263
|
});
|
|
@@ -3038,7 +3339,7 @@ var Markdown = class _Markdown extends UIComponent2 {
|
|
|
3038
3339
|
listItemBlockStack(token, index, availableWidth, t) {
|
|
3039
3340
|
const item = token.items[index];
|
|
3040
3341
|
const children = item.tokens ?? [];
|
|
3041
|
-
const stack = new Stack({ direction: "vertical", gap:
|
|
3342
|
+
const stack = new Stack({ direction: "vertical", gap: t.listItemGap });
|
|
3042
3343
|
const first = children[0];
|
|
3043
3344
|
const firstIsInline = Boolean(first) && (first.type === "text" || first.type === "paragraph");
|
|
3044
3345
|
const leadHasImage = firstIsInline && containsImage(first.tokens);
|
|
@@ -3110,11 +3411,11 @@ var Markdown = class _Markdown extends UIComponent2 {
|
|
|
3110
3411
|
}
|
|
3111
3412
|
/** Construct the `RichText` for one list item. */
|
|
3112
3413
|
listItemRichText(token, index, availableWidth, t) {
|
|
3113
|
-
return new
|
|
3414
|
+
return new RichText2(this.listItemSpans(token, index), {
|
|
3114
3415
|
font: `${t.fontSize}px ${t.bodyFont}`,
|
|
3115
3416
|
color: t.textColor,
|
|
3116
3417
|
maxWidth: availableWidth,
|
|
3117
|
-
linkColor:
|
|
3418
|
+
linkColor: t.linkColor,
|
|
3118
3419
|
selectable: this.selectable,
|
|
3119
3420
|
onLinkClick: this.onLinkClick
|
|
3120
3421
|
});
|
|
@@ -3238,7 +3539,7 @@ var Markdown = class _Markdown extends UIComponent2 {
|
|
|
3238
3539
|
entity.add(this.inlineRunRichText(newTail, availableWidth, t));
|
|
3239
3540
|
} else {
|
|
3240
3541
|
const tailEntity = entity.children[entity.children.length - 1];
|
|
3241
|
-
if (!(tailEntity instanceof
|
|
3542
|
+
if (!(tailEntity instanceof RichText2)) return false;
|
|
3242
3543
|
tailEntity.setSpans(this.inlineRunSpans(newTail, t));
|
|
3243
3544
|
}
|
|
3244
3545
|
const last = entity.children[entity.children.length - 1];
|
|
@@ -3291,7 +3592,7 @@ var Markdown = class _Markdown extends UIComponent2 {
|
|
|
3291
3592
|
if (lastRetained >= 0) {
|
|
3292
3593
|
for (let c = 0; c < oldToken.header.length; c++) {
|
|
3293
3594
|
const cell = entity.rows[lastRetained]?.[c];
|
|
3294
|
-
if (!(cell instanceof
|
|
3595
|
+
if (!(cell instanceof RichText2)) return false;
|
|
3295
3596
|
}
|
|
3296
3597
|
}
|
|
3297
3598
|
const t = this.theme;
|
|
@@ -3464,12 +3765,12 @@ var Markdown = class _Markdown extends UIComponent2 {
|
|
|
3464
3765
|
* queued while the first is outstanding.
|
|
3465
3766
|
*/
|
|
3466
3767
|
ensureMathJax() {
|
|
3467
|
-
if (
|
|
3768
|
+
if (isMathJaxReady() || this.mathLoadPending || this.isDestroyed) return;
|
|
3468
3769
|
this.mathLoadPending = true;
|
|
3469
3770
|
void preloadMathJax().then(() => {
|
|
3470
3771
|
this.mathLoadPending = false;
|
|
3471
3772
|
if (this.isDestroyed) return;
|
|
3472
|
-
if (
|
|
3773
|
+
if (isMathJaxReady()) this.retypesetFromTokens();
|
|
3473
3774
|
this.flushAppendSettledWaiters();
|
|
3474
3775
|
});
|
|
3475
3776
|
}
|
|
@@ -3762,6 +4063,12 @@ var Markdown = class _Markdown extends UIComponent2 {
|
|
|
3762
4063
|
case "list":
|
|
3763
4064
|
case "table":
|
|
3764
4065
|
case "hr":
|
|
4066
|
+
// A footnote definition is the only block-level token this package adds, so
|
|
4067
|
+
// it is the only one for which this three-way lockstep (here,
|
|
4068
|
+
// `renderToken`, `reflowToken`) has to be established rather than inherited.
|
|
4069
|
+
// It renders its own block, so it produces an entity — see `renderToken`'s
|
|
4070
|
+
// arm for why in place rather than collected into a document footer.
|
|
4071
|
+
case "footnoteDef":
|
|
3765
4072
|
return true;
|
|
3766
4073
|
default:
|
|
3767
4074
|
return "text" in token;
|
|
@@ -3789,10 +4096,10 @@ var Markdown = class _Markdown extends UIComponent2 {
|
|
|
3789
4096
|
const width = intrinsicW * scale;
|
|
3790
4097
|
const height = intrinsicH * scale;
|
|
3791
4098
|
const uri = mathData.uri;
|
|
3792
|
-
const math = new
|
|
4099
|
+
const math = new RichText2(
|
|
3793
4100
|
[
|
|
3794
4101
|
{
|
|
3795
|
-
text:
|
|
4102
|
+
text: OBJECT_REPLACEMENT2,
|
|
3796
4103
|
object: {
|
|
3797
4104
|
width,
|
|
3798
4105
|
height,
|
|
@@ -3832,15 +4139,15 @@ var Markdown = class _Markdown extends UIComponent2 {
|
|
|
3832
4139
|
};
|
|
3833
4140
|
const availableWidth = metrics.availableWidth;
|
|
3834
4141
|
if (containsInlineMath(token)) {
|
|
3835
|
-
if (!
|
|
4142
|
+
if (!isMathJaxReady()) this.ensureMathJax();
|
|
3836
4143
|
this.subscribeInlineMathRepaint();
|
|
3837
4144
|
}
|
|
4145
|
+
if (containsImage([token])) this.subscribeInlineImageRemeasure();
|
|
3838
4146
|
switch (token.type) {
|
|
3839
4147
|
// ── Headings ─────────────────────────────────────────────────────
|
|
3840
4148
|
case "heading": {
|
|
3841
4149
|
const hToken = token;
|
|
3842
|
-
const
|
|
3843
|
-
const size = sizes[Math.min(hToken.depth - 1, 5)];
|
|
4150
|
+
const size = headingSize(t, hToken.depth);
|
|
3844
4151
|
const headingFont = `bold ${size}px ${t.bodyFont}`;
|
|
3845
4152
|
return renderInlineToRichText(
|
|
3846
4153
|
hToken.tokens,
|
|
@@ -3870,7 +4177,7 @@ var Markdown = class _Markdown extends UIComponent2 {
|
|
|
3870
4177
|
}
|
|
3871
4178
|
const stack = new Stack({
|
|
3872
4179
|
direction: "vertical",
|
|
3873
|
-
gap:
|
|
4180
|
+
gap: this.theme.blockGap,
|
|
3874
4181
|
maxWidth: availableWidth
|
|
3875
4182
|
});
|
|
3876
4183
|
let currentTokens = [];
|
|
@@ -3916,28 +4223,43 @@ var Markdown = class _Markdown extends UIComponent2 {
|
|
|
3916
4223
|
// ── Blockquotes ──────────────────────────────────────────────────
|
|
3917
4224
|
case "blockquote": {
|
|
3918
4225
|
const bqToken = token;
|
|
3919
|
-
const innerStack = new Stack({
|
|
3920
|
-
|
|
4226
|
+
const innerStack = new Stack({
|
|
4227
|
+
direction: "vertical",
|
|
4228
|
+
gap: this.theme.quoteInnerGap
|
|
4229
|
+
});
|
|
4230
|
+
const indentStart = Math.min(this.theme.quoteIndent, availableWidth);
|
|
3921
4231
|
const childMetrics = {
|
|
3922
4232
|
marginBefore: 0,
|
|
3923
4233
|
marginAfter: 0,
|
|
3924
4234
|
indentStart,
|
|
3925
4235
|
availableWidth: Math.max(0, availableWidth - indentStart)
|
|
3926
4236
|
};
|
|
3927
|
-
|
|
3928
|
-
|
|
3929
|
-
|
|
3930
|
-
|
|
3931
|
-
|
|
3932
|
-
|
|
3933
|
-
|
|
3934
|
-
|
|
3935
|
-
|
|
3936
|
-
|
|
4237
|
+
const outerTheme = this.theme;
|
|
4238
|
+
if (t.quoteTextColor !== t.textColor) {
|
|
4239
|
+
this.theme = { ...outerTheme, textColor: t.quoteTextColor };
|
|
4240
|
+
}
|
|
4241
|
+
try {
|
|
4242
|
+
if (bqToken.tokens) {
|
|
4243
|
+
for (const inner of bqToken.tokens) {
|
|
4244
|
+
const el = this.renderTokenWithMetrics(inner, childMetrics);
|
|
4245
|
+
if (el) {
|
|
4246
|
+
const wrapper = new MarkdownContainer();
|
|
4247
|
+
el.x = childMetrics.indentStart;
|
|
4248
|
+
wrapper.add(el);
|
|
4249
|
+
wrapper.width = el.width + childMetrics.indentStart;
|
|
4250
|
+
wrapper.height = el.height;
|
|
4251
|
+
innerStack.add(wrapper);
|
|
4252
|
+
}
|
|
3937
4253
|
}
|
|
3938
4254
|
}
|
|
4255
|
+
} finally {
|
|
4256
|
+
this.theme = outerTheme;
|
|
3939
4257
|
}
|
|
3940
|
-
const border = new QuoteBorder(
|
|
4258
|
+
const border = new QuoteBorder(
|
|
4259
|
+
innerStack.height || 20,
|
|
4260
|
+
t.quoteBorderColor,
|
|
4261
|
+
t.quoteBorderWidth
|
|
4262
|
+
);
|
|
3941
4263
|
const container = new MarkdownContainer();
|
|
3942
4264
|
border.x = 0;
|
|
3943
4265
|
border.y = 0;
|
|
@@ -3952,7 +4274,10 @@ var Markdown = class _Markdown extends UIComponent2 {
|
|
|
3952
4274
|
// ── Lists ────────────────────────────────────────────────
|
|
3953
4275
|
case "list": {
|
|
3954
4276
|
const listToken = token;
|
|
3955
|
-
const listStack = new Stack({
|
|
4277
|
+
const listStack = new Stack({
|
|
4278
|
+
direction: "vertical",
|
|
4279
|
+
gap: this.theme.listGap
|
|
4280
|
+
});
|
|
3956
4281
|
for (let i = 0; i < listToken.items.length; i++) {
|
|
3957
4282
|
listStack.add(
|
|
3958
4283
|
this.itemIsInlineOnly(listToken.items[i]) ? this.listItemRichText(listToken, i, availableWidth, t) : this.listItemBlockStack(listToken, i, availableWidth, t)
|
|
@@ -3977,7 +4302,7 @@ var Markdown = class _Markdown extends UIComponent2 {
|
|
|
3977
4302
|
width: availableWidth,
|
|
3978
4303
|
textColor: t.textColor,
|
|
3979
4304
|
headerTextColor: t.headingColor,
|
|
3980
|
-
font: `${t.
|
|
4305
|
+
font: `${t.tableFontSize}px ${t.bodyFont}`,
|
|
3981
4306
|
borderColor: t.hrColor,
|
|
3982
4307
|
bg: t.tableBgColor,
|
|
3983
4308
|
headerBg: t.tableHeaderBgColor,
|
|
@@ -3986,6 +4311,24 @@ var Markdown = class _Markdown extends UIComponent2 {
|
|
|
3986
4311
|
() => this.tableAffordances(tblToken)
|
|
3987
4312
|
);
|
|
3988
4313
|
}
|
|
4314
|
+
// ── Footnote definition (`[^1]: note`) ───────────────────────────
|
|
4315
|
+
case "footnoteDef": {
|
|
4316
|
+
const fnToken = token;
|
|
4317
|
+
const spans = [
|
|
4318
|
+
{
|
|
4319
|
+
text: footnoteMarker(fnToken.label),
|
|
4320
|
+
style: { color: t.footnoteColor }
|
|
4321
|
+
},
|
|
4322
|
+
{ text: " " }
|
|
4323
|
+
];
|
|
4324
|
+
if (fnToken.body) spans.push({ text: decodeEntities(fnToken.body) });
|
|
4325
|
+
return new RichText2(spans, {
|
|
4326
|
+
font: bodyFont,
|
|
4327
|
+
color: t.textColor,
|
|
4328
|
+
maxWidth: availableWidth,
|
|
4329
|
+
selectable: this.selectable
|
|
4330
|
+
});
|
|
4331
|
+
}
|
|
3989
4332
|
// ── Horizontal rule ──────────────────────────────────────────────
|
|
3990
4333
|
case "hr":
|
|
3991
4334
|
return new HorizontalRule(availableWidth, t.hrColor);
|
|
@@ -4007,7 +4350,7 @@ var Markdown = class _Markdown extends UIComponent2 {
|
|
|
4007
4350
|
font: bodyFont,
|
|
4008
4351
|
color: t.textColor,
|
|
4009
4352
|
maxWidth: availableWidth,
|
|
4010
|
-
lineHeight:
|
|
4353
|
+
lineHeight: t.bodyLineHeight,
|
|
4011
4354
|
selectable: this.selectable
|
|
4012
4355
|
});
|
|
4013
4356
|
}
|
|
@@ -4029,6 +4372,7 @@ export {
|
|
|
4029
4372
|
escapeCsvField,
|
|
4030
4373
|
escapeMarkdownTableCell,
|
|
4031
4374
|
extensionForLanguage,
|
|
4375
|
+
footnoteMarker,
|
|
4032
4376
|
isMathJaxReady,
|
|
4033
4377
|
mimeForLanguage,
|
|
4034
4378
|
parseFrontMatterFields,
|