@vectojs/markdown 0.5.0 → 0.7.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 +119 -4
- package/dist/Markdown.d.ts +363 -0
- package/dist/MarkdownWorkerSource.d.ts +1 -1
- package/dist/StreamController.d.ts +53 -0
- package/dist/index.d.ts +1 -1
- package/dist/index.js +1199 -143
- package/dist/index.mjs +1187 -142
- package/package.json +5 -5
package/dist/index.mjs
CHANGED
|
@@ -3,6 +3,7 @@ import {
|
|
|
3
3
|
BidiResolver,
|
|
4
4
|
Entity,
|
|
5
5
|
GlyphRasterAtlas,
|
|
6
|
+
OBJECT_REPLACEMENT,
|
|
6
7
|
prepareContentGrid,
|
|
7
8
|
SVGEntity,
|
|
8
9
|
beginVectoUserTiming,
|
|
@@ -38,7 +39,10 @@ var StreamControllerImpl = class {
|
|
|
38
39
|
this.signal = options.signal;
|
|
39
40
|
this.onSignalAbort = () => this.abort(this.signal?.reason);
|
|
40
41
|
if (this.signal?.aborted) this.abort(this.signal.reason);
|
|
41
|
-
else
|
|
42
|
+
else
|
|
43
|
+
this.signal?.addEventListener("abort", this.onSignalAbort, {
|
|
44
|
+
once: true
|
|
45
|
+
});
|
|
42
46
|
}
|
|
43
47
|
host;
|
|
44
48
|
maxBufferedChars;
|
|
@@ -126,10 +130,33 @@ var StreamControllerImpl = class {
|
|
|
126
130
|
return closePromise;
|
|
127
131
|
}
|
|
128
132
|
this.currentState = "closed";
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
+
let settled;
|
|
134
|
+
try {
|
|
135
|
+
settled = this.host.onClose?.();
|
|
136
|
+
} catch (error) {
|
|
137
|
+
this.cleanup();
|
|
138
|
+
this.rejectPendingClose(error);
|
|
139
|
+
return closePromise;
|
|
140
|
+
}
|
|
141
|
+
if (settled === void 0) {
|
|
142
|
+
this.cleanup();
|
|
143
|
+
this.resolveClose?.();
|
|
144
|
+
this.resolveClose = null;
|
|
145
|
+
this.rejectClose = null;
|
|
146
|
+
return closePromise;
|
|
147
|
+
}
|
|
148
|
+
void Promise.resolve(settled).then(
|
|
149
|
+
() => {
|
|
150
|
+
this.cleanup();
|
|
151
|
+
this.resolveClose?.();
|
|
152
|
+
this.resolveClose = null;
|
|
153
|
+
this.rejectClose = null;
|
|
154
|
+
},
|
|
155
|
+
(error) => {
|
|
156
|
+
this.cleanup();
|
|
157
|
+
this.rejectPendingClose(error);
|
|
158
|
+
}
|
|
159
|
+
);
|
|
133
160
|
return closePromise;
|
|
134
161
|
}
|
|
135
162
|
abort(reason) {
|
|
@@ -395,16 +422,10 @@ function createStreamController(host, options = {}) {
|
|
|
395
422
|
}
|
|
396
423
|
|
|
397
424
|
// src/Markdown.ts
|
|
398
|
-
import { mathjax } from "mathjax-full/js/mathjax.js";
|
|
399
|
-
import { TeX } from "mathjax-full/js/input/tex.js";
|
|
400
|
-
import { SVG } from "mathjax-full/js/output/svg.js";
|
|
401
|
-
import { liteAdaptor } from "mathjax-full/js/adaptors/liteAdaptor.js";
|
|
402
|
-
import { RegisterHTMLHandler } from "mathjax-full/js/handlers/html.js";
|
|
403
|
-
import { AllPackages } from "mathjax-full/js/input/tex/AllPackages.js";
|
|
404
425
|
import { measureText, RichText, Stack, Table, Text, Image, UIComponent } from "@vectojs/ui";
|
|
405
426
|
|
|
406
427
|
// src/MarkdownWorkerSource.ts
|
|
407
|
-
var WORKER_SOURCE_STRING = '"use strict";(()=>{function U(){return{async:!1,breaks:!1,extensions:null,gfm:!0,hooks:null,pedantic:!1,renderer:null,silent:!1,tokenizer:null,walkTokens:null}}var A=U();function he(r){A=r}var T={exec:()=>null};function L(r){let e=[];return t=>{let s=Math.max(0,Math.min(3,t-1)),n=e[s];return n||(n=r(s),e[s]=n),n}}function g(r,e=""){let t=typeof r=="string"?r:r.source,s={replace:(n,i)=>{let a=typeof i=="string"?i:i.source;return a=a.replace(b.caret,"$1"),t=t.replace(n,a),s},getRegex:()=>new RegExp(t,e)};return s}var me=((r="")=>{try{return!!new RegExp("(?<=1)(?<!1)"+r)}catch{return!1}})(),b={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:r=>new RegExp(`^( {0,3}${r})((?:[ ][^\\\\n]*)?(?:\\\\n|$))`),nextBulletRegex:L(r=>new RegExp(`^ {0,${r}}(?:[*+-]|\\\\d{1,9}[.)])((?:[ ][^\\\\n]*)?(?:\\\\n|$))`)),hrRegex:L(r=>new RegExp(`^ {0,${r}}((?:- *){3,}|(?:_ *){3,}|(?:\\\\* *){3,})(?:\\\\n+|$)`)),fencesBeginRegex:L(r=>new RegExp(`^ {0,${r}}(?:\\`\\`\\`|~~~)`)),headingBeginRegex:L(r=>new RegExp(`^ {0,${r}}#`)),htmlBeginRegex:L(r=>new RegExp(`^ {0,${r}}<(?:[a-z].*>|!--)`,"i")),blockquoteBeginRegex:L(r=>new RegExp(`^ {0,${r}}>`))},ye=/^(?:[ \\t]*(?:\\n|$))+/,$e=/^((?: {4}| {0,3}\\t)[^\\n]+(?:\\n(?:[ \\t]*(?:\\n|$))*)?)+/,Re=/^ {0,3}(`{3,}(?=[^`\\n]*(?:\\n|$))|~{3,})([^\\n]*)(?:\\n|$)(?:|([\\s\\S]*?)(?:\\n|$))(?: {0,3}\\1[~`]* *(?=\\n|$)|$)/,M=/^ {0,3}((?:-[\\t ]*){3,}|(?:_[ \\t]*){3,}|(?:\\*[ \\t]*){3,})(?:\\n+|$)/,Se=/^ {0,3}(#{1,6})(?=\\s|$)(.*)(?:\\n+|$)/,F=/ {0,3}(?:[*+-]|\\d{1,9}[.)])/,pe=/^(?!bull |blockCode|fences|blockquote|heading|html|table)((?:.|\\n(?!\\s*?\\n|bull |blockCode|fences|blockquote|heading|html|table))+?)\\n {0,3}(=+|-+) *(?:\\n+|$)/,ue=g(pe).replace(/bull/g,F).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(),Te=g(pe).replace(/bull/g,F).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(),V=/^([^\\n]+(?:\\n(?!hr|heading|lheading|blockquote|fences|list|html|table|[ \\t]+\\n)[^\\n]+)*)/,ze=/^[^\\n]+/,J=/(?!\\s*\\])(?:\\\\[\\s\\S]|[^\\[\\]\\\\])+/,Ae=g(/^ {0,3}\\[(label)\\]: *(?:\\n[ \\t]*)?([^<\\s][^\\s]*|<.*?>)(?:(?: +(?:\\n[ \\t]*)?| *\\n[ \\t]*)(title))? *(?:\\n+|$)/).replace("label",J).replace("title",/(?:"(?:\\\\"?|[^"\\\\])*"|\'[^\'\\n]*(?:\\n[^\'\\n]+)*\\n?\'|\\([^()]*\\))/).getRegex(),Le=g(/^(bull)([ \\t][^\\n]*?)?(?:\\n|$)/).replace(/bull/g,F).getRegex(),j="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",K=/<!--(?:-?>|[\\s\\S]*?(?:-->|$))/,_e=g("^ {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",K).replace("tag",j).replace("attribute",/ +[a-zA-Z:_][\\w.:-]*(?: *= *"[^"\\n]*"| *= *\'[^\'\\n]*\'| *= *[^\\s"\'=<>`]+)?/).getRegex(),ge=r=>g(V).replace("hr",M).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",r).replace("html","</?(?:tag)(?: +|\\\\n|/?>)|<(?:script|pre|style|textarea|!--)").replace("tag",j).getRegex(),Pe=ge(/ {0,3}(?:[*+-]|1[.)])[ \\t]+[^ \\t\\n]/),ve=ge(/ {0,3}(?:[*+-]|\\d{1,9}[.)])(?:[ \\t]|\\n|$)/),Ie=g(/^( {0,3}> ?(paragraph|[^\\n]*)(?:\\n|$))+/).replace("paragraph",ve).getRegex(),Y={blockquote:Ie,code:$e,def:Ae,fences:Re,heading:Se,hr:M,html:_e,lheading:ue,list:Le,newline:ye,paragraph:Pe,table:T,text:ze},ne=g("^ *([^\\\\n ].*)\\\\n {0,3}((?:\\\\| *)?:?-+:? *(?:\\\\| *:?-+:? *)*(?:\\\\| *)?)(?:\\\\n((?:(?! *\\\\n|hr|heading|blockquote|code|fences|list|html).*(?:\\\\n|$))*)\\\\n*|$)").replace("hr",M).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",j).getRegex(),Ce={...Y,lheading:Te,table:ne,paragraph:g(V).replace("hr",M).replace("heading"," {0,3}#{1,6}(?:\\\\s|$)").replace("|lheading","").replace("table",ne).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",j).getRegex()},Ee={...Y,html:g(`^ *(?:comment *(?:\\\\n|\\\\s*$)|<(tag)[\\\\s\\\\S]+?</\\\\1> *(?:\\\\n{2,}|\\\\s*$)|<tag(?:"[^"]*"|\'[^\']*\'|\\\\s[^\'"/>\\\\s]*)*?/?> *(?:\\\\n{2,}|\\\\s*$))`).replace("comment",K).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:T,lheading:/^(.+?)\\n {0,3}(=+|-+) *(?:\\n+|$)/,paragraph:g(V).replace("hr",M).replace("heading",` *#{1,6} *[^\n]`).replace("lheading",ue).replace("|table","").replace("blockquote"," {0,3}>").replace("|fences","").replace("|list","").replace("|html","").replace("|tag","").getRegex()},Me=/^\\\\([!"#$%&\'()*+,\\-./:;<=>?@\\[\\]\\\\^_`{|}~])/,Be=/^(`+)([^`]|[^`][\\s\\S]*?[^`])\\1(?!`)/,ke=/^( {2,}|\\\\)\\n(?!\\s*$)/,qe=/^(`+|[^`])(?:(?= {2,}\\n)|[\\s\\S]*?(?:(?=[\\\\<!\\[`*_]|\\b_|$)|[^ ](?= {2,}\\n)))/,_=/[\\p{P}\\p{S}]/u,H=/[\\s\\p{P}\\p{S}]/u,ee=/[^\\s\\p{P}\\p{S}]/u,Ze=g(/^((?![*_])punctSpace)/,"u").replace(/punctSpace/g,H).getRegex(),fe=/(?!~)[\\p{P}\\p{S}]/u,De=/(?!~)[\\s\\p{P}\\p{S}]/u,Qe=/(?:[^\\s\\p{P}\\p{S}]|~)/u,Ne=g(/link|precode-code|html/,"g").replace("link",/\\[(?:[^\\[\\]`]|(?<a>`+)[^`]+\\k<a>(?!`))*?\\]\\((?:\\\\[\\s\\S]|[^\\\\\\(\\)]|\\((?:\\\\[\\s\\S]|[^\\\\\\(\\)])*\\))*\\)/).replace("precode-",me?"(?<!`)()":"(^^|[^`])").replace("code",/(?<b>`+)[^`]+\\k<b>(?!`)/).replace("html",/<(?! )[^<>]*?>/).getRegex(),de=/^(?:\\*+(?:((?!\\*)punct)|([^\\s*]))?)|^_+(?:((?!_)punct)|([^\\s_]))?/,je=g(de,"u").replace(/punct/g,_).getRegex(),He=g(de,"u").replace(/punct/g,fe).getRegex(),xe="^[^_*]*?__[^_*]*?\\\\*[^_*]*?(?=__)|[^*]+(?=[^*])|(?!\\\\*)punct(\\\\*+)(?=[\\\\s]|$)|notPunctSpace(\\\\*+)(?!\\\\*)(?=punctSpace|$)|(?!\\\\*)punctSpace(\\\\*+)(?=notPunctSpace)|[\\\\s](\\\\*+)(?!\\\\*)(?=punct)|(?!\\\\*)punct(\\\\*+)(?!\\\\*)(?=punct)|notPunctSpace(\\\\*+)(?=notPunctSpace)",Oe=g(xe,"gu").replace(/notPunctSpace/g,ee).replace(/punctSpace/g,H).replace(/punct/g,_).getRegex(),Ge=g(xe,"gu").replace(/notPunctSpace/g,Qe).replace(/punctSpace/g,De).replace(/punct/g,fe).getRegex(),We=g("^[^_*]*?\\\\*\\\\*[^_*]*?_[^_*]*?(?=\\\\*\\\\*)|[^_]+(?=[^_])|(?!_)punct(_+)(?=[\\\\s]|$)|notPunctSpace(_+)(?!_)(?=punctSpace|$)|(?!_)punctSpace(_+)(?=notPunctSpace)|[\\\\s](_+)(?!_)(?=punct)|(?!_)punct(_+)(?!_)(?=punct)","gu").replace(/notPunctSpace/g,ee).replace(/punctSpace/g,H).replace(/punct/g,_).getRegex(),Xe=g(/^~~?(?:((?!~)punct)|[^\\s~])/,"u").replace(/punct/g,_).getRegex(),Ue="^[^~]+(?=[^~])|(?!~)punct(~~?)(?=[\\\\s]|$)|notPunctSpace(~~?)(?!~)(?=punctSpace|$)|(?!~)punctSpace(~~?)(?=notPunctSpace)|[\\\\s](~~?)(?!~)(?=punct)|(?!~)punct(~~?)(?!~)(?=punct)|notPunctSpace(~~?)(?=notPunctSpace)",Fe=g(Ue,"gu").replace(/notPunctSpace/g,ee).replace(/punctSpace/g,H).replace(/punct/g,_).getRegex(),Ve=g(/\\\\(punct)/,"gu").replace(/punct/g,_).getRegex(),Je=g(/^<(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(),Ke=g(K).replace("(?:-->|$)","-->").getRegex(),Ye=g("^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",Ke).replace("attribute",/\\s+[a-zA-Z:_][\\w.:-]*(?:\\s*=\\s*"[^"]*"|\\s*=\\s*\'[^\']*\'|\\s*=\\s*[^\\s"\'=<>`]+)?/).getRegex(),D=/(?:\\[(?:\\\\[\\s\\S]|[^\\[\\]\\\\])*\\]|\\\\[\\s\\S]|`+(?!`)[^`]*?`+(?!`)|``+(?=\\])|[^\\[\\]\\\\`])*?/,et=g(/^!?\\[(label)\\]\\(\\s*(href)(?:(?:[ \\t]+(?:\\n[ \\t]*)?|\\n[ \\t]*)(title))?\\s*\\)/).replace("label",D).replace("href",/<(?:\\\\.|[^\\n<>\\\\])+>|[^ \\t\\n\\x00-\\x1f]+|(?=\\))/).replace("title",/"(?:\\\\"?|[^"\\\\])*"|\'(?:\\\\\'?|[^\'\\\\])*\'|\\((?:\\\\\\)?|[^)\\\\])*\\)/).getRegex(),be=g(/^!?\\[(label)\\]\\[(ref)\\]/).replace("label",D).replace("ref",J).getRegex(),we=g(/^!?\\[(ref)\\](?:\\[\\])?/).replace("ref",J).getRegex(),tt=g("reflink|nolink(?!\\\\()","g").replace("reflink",be).replace("nolink",we).getRegex(),se=/[hH][tT][tT][pP][sS]?|[fF][tT][pP]/,te={_backpedal:T,anyPunctuation:Ve,autolink:Je,blockSkip:Ne,br:ke,code:Be,del:T,delLDelim:T,delRDelim:T,emStrongLDelim:je,emStrongRDelimAst:Oe,emStrongRDelimUnd:We,escape:Me,link:et,nolink:we,punctuation:Ze,reflink:be,reflinkSearch:tt,tag:Ye,text:qe,url:T},rt={...te,link:g(/^!?\\[(label)\\]\\((.*?)\\)/).replace("label",D).getRegex(),reflink:g(/^!?\\[(label)\\]\\s*\\[([^\\]]*)\\]/).replace("label",D).getRegex()},G={...te,emStrongRDelimAst:Ge,emStrongLDelim:He,delLDelim:Xe,delRDelim:Fe,url:g(/^((?:protocol):\\/\\/|www\\.)(?:[a-zA-Z0-9\\-]+\\.?)+[^\\s<]*|^email/).replace("protocol",se).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:g(/^(`+|~+|[^`~])(?:(?=[`~])|(?= {2,}\\n)|(?=[a-zA-Z0-9.!#$%&\'*+\\/=?_`{\\|}~-]+@)|[\\s\\S]*?(?:(?=[\\\\<!\\[`*~_]|\\b_|protocol:\\/\\/|www\\.|$)|[^ ](?= {2,}\\n)|[^a-zA-Z0-9.!#$%&\'*+\\/=?_`{\\|}~-](?=[a-zA-Z0-9.!#$%&\'*+\\/=?_`{\\|}~-]+@)))/).replace("protocol",se).getRegex()},nt={...G,br:g(ke).replace("{2,}","*").getRegex(),text:g(G.text).replace("\\\\b_","\\\\b_| {2,}\\\\n").replace(/\\{2,\\}/g,"*").getRegex()},Z={normal:Y,gfm:Ce,pedantic:Ee},C={normal:te,gfm:G,breaks:nt,pedantic:rt},st={"&":"&","<":"<",">":">",\'"\':""","\'":"'"},ie=r=>st[r];function y(r,e){if(e){if(b.escapeTest.test(r))return r.replace(b.escapeReplace,ie)}else if(b.escapeTestNoEncode.test(r))return r.replace(b.escapeReplaceNoEncode,ie);return r}function le(r){try{r=encodeURI(r).replace(b.percentDecode,"%")}catch{return null}return r}function ae(r,e){let t=r.replace(b.findPipe,(i,a,l)=>{let o=!1,c=a;for(;--c>=0&&l[c]==="\\\\";)o=!o;return o?"|":" |"}),s=t.split(b.splitPipe),n=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(;n<s.length;n++)s[n]=s[n].trim().replace(b.slashPipe,"|");return s}function S(r,e,t){let s=r.length;if(s===0)return"";let n=0;for(;n<s;){let i=r.charAt(s-n-1);if(i===e&&!t)n++;else if(i!==e&&t)n++;else break}return r.slice(0,s-n)}function oe(r){let e=r.split(`\n`),t=e.length-1;for(;t>=0&&b.blankLine.test(e[t]);)t--;return e.length-t<=2?r:e.slice(0,t+1).join(`\n`)}function it(r,e){if(r.indexOf(e[1])===-1)return-1;let t=0;for(let s=0;s<r.length;s++)if(r[s]==="\\\\")s++;else if(r[s]===e[0])t++;else if(r[s]===e[1]&&(t--,t<0))return s;return t>0?-2:-1}function lt(r,e=0){let t=e,s="";for(let n of r)if(n===" "){let i=4-t%4;s+=" ".repeat(i),t+=i}else s+=n,t++;return s}function ce(r,e,t,s,n){let i=e.href,a=e.title||null,l=r[1].replace(n.other.outputLinkReplace,"$1");s.state.inLink=!0;let o={type:r[0].charAt(0)==="!"?"image":"link",raw:t,href:i,title:a,text:l,tokens:s.inlineTokens(l)};return s.state.inLink=!1,o}function at(r,e,t){let s=r.match(t.other.indentCodeCompensation);if(s===null)return e;let n=s[1];return e.split(`\n`).map(i=>{let a=i.match(t.other.beginningSpace);if(a===null)return i;let[l]=a;return l.length>=n.length?i.slice(n.length):i}).join(`\n`)}var Q=class{options;rules;lexer;constructor(r){this.options=r||A}space(r){let e=this.rules.block.newline.exec(r);if(e&&e[0].length>0)return{type:"space",raw:e[0]}}code(r){let e=this.rules.block.code.exec(r);if(e){let t=this.options.pedantic?e[0]:oe(e[0]),s=t.replace(this.rules.other.codeRemoveIndent,"");return{type:"code",raw:t,codeBlockStyle:"indented",text:s}}}fences(r){let e=this.rules.block.fences.exec(r);if(e){let t=e[0],s=at(t,e[3]||"",this.rules);return{type:"code",raw:t,lang:e[2]?e[2].trim().replace(this.rules.inline.anyPunctuation,"$1"):e[2],text:s}}}heading(r){let e=this.rules.block.heading.exec(r);if(e){let t=e[2].trim();if(this.rules.other.endingHash.test(t)){let s=S(t,"#");(this.options.pedantic||!s||this.rules.other.endingSpaceChar.test(s))&&(t=s.trim())}return{type:"heading",raw:S(e[0],`\n`),depth:e[1].length,text:t,tokens:this.lexer.inline(t)}}}hr(r){let e=this.rules.block.hr.exec(r);if(e)return{type:"hr",raw:S(e[0],`\n`)}}blockquote(r){let e=this.rules.block.blockquote.exec(r);if(e){let t=S(e[0],`\n`).split(`\n`),s="",n="",i=[];for(;t.length>0;){let a=!1,l=[],o;for(o=0;o<t.length;o++)if(this.rules.other.blockquoteStart.test(t[o]))l.push(t[o]),a=!0;else if(!a)l.push(t[o]);else break;t=t.slice(o);let c=l.join(`\n`),p=c.replace(this.rules.other.blockquoteSetextReplace,`\n $1`).replace(this.rules.other.blockquoteSetextReplace2,"");s=s?`${s}\n${c}`:c,n=n?`${n}\n${p}`:p;let h=this.lexer.state.top;if(this.lexer.state.top=!0,this.lexer.blockTokens(p,i,!0),this.lexer.state.top=h,t.length===0)break;let u=i.at(-1);if(u?.type==="code")break;if(u?.type==="blockquote"){let x=u,f=x.raw+`\n`+t.join(`\n`),d=this.blockquote(f);i[i.length-1]=d,s=s.substring(0,s.length-x.raw.length)+d.raw,n=n.substring(0,n.length-x.text.length)+d.text;break}else if(u?.type==="list"){let x=u,f=x.raw+`\n`+t.join(`\n`),d=this.list(f);i[i.length-1]=d,s=s.substring(0,s.length-u.raw.length)+d.raw,n=n.substring(0,n.length-x.raw.length)+d.raw,t=f.substring(i.at(-1).raw.length).split(`\n`);continue}}return{type:"blockquote",raw:s,tokens:i,text:n}}}list(r){let e=this.rules.block.list.exec(r);if(e){let t=e[1].trim(),s=t.length>1,n={type:"list",raw:"",ordered:s,start:s?+t.slice(0,-1):"",loose:!1,items:[]};t=s?`\\\\d{1,9}\\\\${t.slice(-1)}`:`\\\\${t}`,this.options.pedantic&&(t=s?t:"[*+-]");let i=this.rules.other.listItemRegex(t),a=!1;for(;r;){let o=!1,c="",p="";if(!(e=i.exec(r))||this.rules.block.hr.test(r))break;c=e[0],r=r.substring(c.length);let h=lt(e[2].split(`\n`,1)[0],e[1].length),u=r.split(`\n`,1)[0],x=!h.trim(),f=0;if(this.options.pedantic?(f=2,p=h.trimStart()):x?f=e[1].length+1:(f=h.search(this.rules.other.nonSpaceChar),f=f>4?1:f,p=h.slice(f),f+=e[1].length),x&&this.rules.other.blankLine.test(u)&&(c+=u+`\n`,r=r.substring(u.length+1),o=!0),!o){let d=this.rules.other.nextBulletRegex(f),B=this.rules.other.hrRegex(f),$=this.rules.other.fencesBeginRegex(f),q=this.rules.other.headingBeginRegex(f),R=this.rules.other.htmlBeginRegex(f),v=this.rules.other.blockquoteBeginRegex(f);for(;r;){let O=r.split(`\n`,1)[0],I;if(u=O,this.options.pedantic?(u=u.replace(this.rules.other.listReplaceNesting," "),I=u):I=u.replace(this.rules.other.tabCharGlobal," "),$.test(u)||q.test(u)||R.test(u)||v.test(u)||d.test(u)||B.test(u))break;if(I.search(this.rules.other.nonSpaceChar)>=f||!u.trim())p+=`\n`+I.slice(f);else{if(x||h.replace(this.rules.other.tabCharGlobal," ").search(this.rules.other.nonSpaceChar)>=4||$.test(h)||q.test(h)||B.test(h))break;p+=`\n`+u}x=!u.trim(),c+=O+`\n`,r=r.substring(O.length+1),h=I.slice(f)}}n.loose||(a?n.loose=!0:this.rules.other.doubleBlankLine.test(c)&&(a=!0)),n.items.push({type:"list_item",raw:c,task:!!this.options.gfm&&this.rules.other.listIsTask.test(p),loose:!1,text:p,tokens:[]}),n.raw+=c}let l=n.items.at(-1);if(l)l.raw=l.raw.trimEnd(),l.text=l.text.trimEnd();else return;n.raw=n.raw.trimEnd();for(let o of n.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 p=this.rules.other.listTaskCheckbox.exec(o.raw);if(p){let h={type:"checkbox",raw:p[0]+" ",checked:p[0]!=="[ ]"};o.checked=h.checked,n.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(!n.loose){let p=o.tokens.filter(u=>u.type==="space"),h=p.length>0&&p.some(u=>this.rules.other.anyLine.test(u.raw));n.loose=h}}if(n.loose)for(let o of n.items){o.loose=!0;for(let c of o.tokens)c.type==="text"&&(c.type="paragraph")}return n}}html(r){let e=this.rules.block.html.exec(r);if(e){let t=oe(e[0]);return{type:"html",block:!0,raw:t,pre:e[1]==="pre"||e[1]==="script"||e[1]==="style",text:t}}}def(r){let e=this.rules.block.def.exec(r);if(e){let t=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"):"",n=e[3]?e[3].substring(1,e[3].length-1).replace(this.rules.inline.anyPunctuation,"$1"):e[3];return{type:"def",tag:t,raw:S(e[0],`\n`),href:s,title:n}}}table(r){let e=this.rules.block.table.exec(r);if(!e||!this.rules.other.tableDelimiter.test(e[2]))return;let t=ae(e[1]),s=e[2].replace(this.rules.other.tableAlignChars,"").split("|"),n=e[3]?.trim()?e[3].replace(this.rules.other.tableRowBlankLine,"").split(`\n`):[],i={type:"table",raw:S(e[0],`\n`),header:[],align:[],rows:[]};if(t.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<t.length;a++)i.header.push({text:t[a],tokens:this.lexer.inline(t[a]),header:!0,align:i.align[a]});for(let a of n)i.rows.push(ae(a,i.header.length).map((l,o)=>({text:l,tokens:this.lexer.inline(l),header:!1,align:i.align[o]})));return i}}lheading(r){let e=this.rules.block.lheading.exec(r);if(e){let t=e[1].trim();return{type:"heading",raw:S(e[0],`\n`),depth:e[2].charAt(0)==="="?1:2,text:t,tokens:this.lexer.inline(t)}}}paragraph(r){let e=this.rules.block.paragraph.exec(r);if(e){let t=e[1].charAt(e[1].length-1)===`\n`?e[1].slice(0,-1):e[1];return{type:"paragraph",raw:e[0],text:t,tokens:this.lexer.inline(t)}}}text(r){let e=this.rules.block.text.exec(r);if(e)return{type:"text",raw:e[0],text:e[0],tokens:this.lexer.inline(e[0])}}escape(r){let e=this.rules.inline.escape.exec(r);if(e)return{type:"escape",raw:e[0],text:e[1]}}tag(r){let e=this.rules.inline.tag.exec(r);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(r){let e=this.rules.inline.link.exec(r);if(e){let t=e[2].trim();if(!this.options.pedantic&&this.rules.other.startAngleBracket.test(t)){if(!this.rules.other.endAngleBracket.test(t))return;let i=S(t.slice(0,-1),"\\\\");if((t.length-i.length)%2===0)return}else{let i=it(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],n="";if(this.options.pedantic){let i=this.rules.other.pedanticHrefTitle.exec(s);i&&(s=i[1],n=i[3])}else n=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(t)?s=s.slice(1):s=s.slice(1,-1)),ce(e,{href:s&&s.replace(this.rules.inline.anyPunctuation,"$1"),title:n&&n.replace(this.rules.inline.anyPunctuation,"$1")},e[0],this.lexer,this.rules)}}reflink(r,e){let t;if((t=this.rules.inline.reflink.exec(r))||(t=this.rules.inline.nolink.exec(r))){let s=(t[2]||t[1]).replace(this.rules.other.multipleSpaceGlobal," "),n=e[s.toLowerCase()];if(!n){let i=t[0].charAt(0);return{type:"text",raw:i,text:i}}return ce(t,n,t[0],this.lexer,this.rules)}}emStrong(r,e,t=""){let s=this.rules.inline.emStrongLDelim.exec(r);if(!(!s||!s[1]&&!s[2]&&!s[3]&&!s[4]||s[4]&&t.match(this.rules.other.unicodeAlphaNumeric))&&(!(s[1]||s[3])||!t||this.rules.inline.punctuation.exec(t))){let n=[...s[0]].length-1,i,a,l=n,o=0,c=s[0][0]==="*"?this.rules.inline.emStrongRDelimAst:this.rules.inline.emStrongRDelimUnd;for(c.lastIndex=0,e=e.slice(-1*r.length+n);(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])&&n%3&&!((n+a)%3)){o+=a;continue}if(l-=a,l>0)continue;a=Math.min(a,a+l+o);let p=[...s[0]][0].length,h=r.slice(0,n+s.index+p+a);if(Math.min(n,a)%2){let x=h.slice(1,-1);return{type:"em",raw:h,text:x,tokens:this.lexer.inlineTokens(x)}}let u=h.slice(2,-2);return{type:"strong",raw:h,text:u,tokens:this.lexer.inlineTokens(u)}}}}codespan(r){let e=this.rules.inline.code.exec(r);if(e){let t=e[2].replace(this.rules.other.newLineCharGlobal," "),s=this.rules.other.nonSpaceChar.test(t),n=this.rules.other.startingSpaceChar.test(t)&&this.rules.other.endingSpaceChar.test(t);return s&&n&&(t=t.substring(1,t.length-1)),{type:"codespan",raw:e[0],text:t}}}br(r){let e=this.rules.inline.br.exec(r);if(e)return{type:"br",raw:e[0]}}del(r,e,t=""){let s=this.rules.inline.delLDelim.exec(r);if(s&&(!s[1]||!t||this.rules.inline.punctuation.exec(t))){let n=[...s[0]].length-1,i,a,l=n,o=this.rules.inline.delRDelim;for(o.lastIndex=0,e=e.slice(-1*r.length+n);(s=o.exec(e))!==null;){if(i=s[1]||s[2]||s[3]||s[4]||s[5]||s[6],!i||(a=[...i].length,a!==n))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,p=r.slice(0,n+s.index+c+a),h=p.slice(n,-n);return{type:"del",raw:p,text:h,tokens:this.lexer.inlineTokens(h)}}}}autolink(r){let e=this.rules.inline.autolink.exec(r);if(e){let t,s;return e[2]==="@"?(t=e[1],s="mailto:"+t):(t=e[1],s=t),{type:"link",raw:e[0],text:t,href:s,tokens:[{type:"text",raw:t,text:t}]}}}url(r){let e;if(e=this.rules.inline.url.exec(r)){let t,s;if(e[2]==="@")t=e[0],s="mailto:"+t;else{let n;do n=e[0],e[0]=this.rules.inline._backpedal.exec(e[0])?.[0]??"";while(n!==e[0]);t=e[0],e[1]==="www."?s="http://"+e[0]:s=e[0]}return{type:"link",raw:e[0],text:t,href:s,tokens:[{type:"text",raw:t,text:t}]}}}inlineText(r){let e=this.rules.inline.text.exec(r);if(e){let t=this.lexer.state.inRawBlock;return{type:"text",raw:e[0],text:e[0],escaped:t}}}},w=class W{tokens;options;state;inlineQueue;tokenizer;constructor(e){this.tokens=[],this.tokens.links=Object.create(null),this.options=e||A,this.options.tokenizer=this.options.tokenizer||new Q,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 t={other:b,block:Z.normal,inline:C.normal};this.options.pedantic?(t.block=Z.pedantic,t.inline=C.pedantic):this.options.gfm&&(t.block=Z.gfm,this.options.breaks?t.inline=C.breaks:t.inline=C.gfm),this.tokenizer.rules=t}static get rules(){return{block:Z,inline:C}}static lex(e,t){return new W(t).lex(e)}static lexInline(e,t){return new W(t).inlineTokens(e)}lex(e){e=e.replace(b.carriageReturn,`\n`),this.blockTokens(e,this.tokens);for(let t=0;t<this.inlineQueue.length;t++){let s=this.inlineQueue[t];this.inlineTokens(s.src,s.tokens)}return this.inlineQueue=[],this.tokens}blockTokens(e,t=[],s=!1){this.tokenizer.lexer=this,this.options.pedantic&&(e=e.replace(b.tabCharGlobal," ").replace(b.spaceLine,""));let n=1/0;for(;e;){if(e.length<n)n=e.length;else{this.infiniteLoopError(e.charCodeAt(0));break}let i;if(this.options.extensions?.block?.some(l=>(i=l.call({lexer:this},e,t))?(e=e.substring(i.raw.length),t.push(i),!0):!1))continue;if(i=this.tokenizer.space(e)){e=e.substring(i.raw.length);let l=t.at(-1);i.raw.length===1&&l!==void 0?l.raw+=`\n`:t.push(i);continue}if(i=this.tokenizer.code(e)){e=e.substring(i.raw.length);let l=t.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):t.push(i);continue}if(i=this.tokenizer.fences(e)){e=e.substring(i.raw.length),t.push(i);continue}if(i=this.tokenizer.heading(e)){e=e.substring(i.raw.length),t.push(i);continue}if(i=this.tokenizer.hr(e)){e=e.substring(i.raw.length),t.push(i);continue}if(i=this.tokenizer.blockquote(e)){e=e.substring(i.raw.length),t.push(i);continue}if(i=this.tokenizer.list(e)){e=e.substring(i.raw.length),t.push(i);continue}if(i=this.tokenizer.html(e)){e=e.substring(i.raw.length),t.push(i);continue}if(i=this.tokenizer.def(e)){e=e.substring(i.raw.length);let l=t.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},t.push(i));continue}if(i=this.tokenizer.table(e)){e=e.substring(i.raw.length),t.push(i);continue}if(i=this.tokenizer.lheading(e)){e=e.substring(i.raw.length),t.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(p=>{c=p.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=t.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):t.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=t.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):t.push(i);continue}if(e){this.infiniteLoopError(e.charCodeAt(0));break}}return this.state.top=!0,t}inline(e,t=[]){return this.inlineQueue.push({src:e,tokens:t}),t}inlineTokens(e,t=[]){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 p=c?c.length:0;return l.slice(0,p)+"["+"a".repeat(l.length-p-2)+"]"}),s=this.options.hooks?.emStrongMask?.call({lexer:this},s)??s;let n=!1,i="",a=1/0;for(;e;){if(e.length<a)a=e.length;else{this.infiniteLoopError(e.charCodeAt(0));break}n||(i=""),n=!1;let l;if(this.options.extensions?.inline?.some(c=>(l=c.call({lexer:this},e,t))?(e=e.substring(l.raw.length),t.push(l),!0):!1))continue;if(l=this.tokenizer.escape(e)){e=e.substring(l.raw.length),t.push(l);continue}if(l=this.tokenizer.tag(e)){e=e.substring(l.raw.length),t.push(l);continue}if(l=this.tokenizer.link(e)){e=e.substring(l.raw.length),t.push(l);continue}if(l=this.tokenizer.reflink(e,this.tokens.links)){e=e.substring(l.raw.length);let c=t.at(-1);l.type==="text"&&c?.type==="text"?(c.raw+=l.raw,c.text+=l.text):t.push(l);continue}if(l=this.tokenizer.emStrong(e,s,i)){e=e.substring(l.raw.length),t.push(l);continue}if(l=this.tokenizer.codespan(e)){e=e.substring(l.raw.length),t.push(l);continue}if(l=this.tokenizer.br(e)){e=e.substring(l.raw.length),t.push(l);continue}if(l=this.tokenizer.del(e,s,i)){e=e.substring(l.raw.length),t.push(l);continue}if(l=this.tokenizer.autolink(e)){e=e.substring(l.raw.length),t.push(l);continue}if(!this.state.inLink&&(l=this.tokenizer.url(e))){e=e.substring(l.raw.length),t.push(l);continue}let o=e;if(this.options.extensions?.startInline){let c=1/0,p=e.slice(1),h;this.options.extensions.startInline.forEach(u=>{h=u.call({lexer:this},p),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)),n=!0;let c=t.at(-1);c?.type==="text"?(c.raw+=l.raw,c.text+=l.text):t.push(l);continue}if(e){this.infiniteLoopError(e.charCodeAt(0));break}}return t}infiniteLoopError(e){let t="Infinite loop on byte: "+e;if(this.options.silent)console.error(t);else throw new Error(t)}},N=class{options;parser;constructor(r){this.options=r||A}space(r){return""}code({text:r,lang:e,escaped:t}){let s=(e||"").match(b.notSpaceStart)?.[0],n=r.replace(b.endingNewline,"")+`\n`;return s?\'<pre><code class="language-\'+y(s)+\'">\'+(t?n:y(n,!0))+`</code></pre>\n`:"<pre><code>"+(t?n:y(n,!0))+`</code></pre>\n`}blockquote({tokens:r}){return`<blockquote>\n${this.parser.parse(r)}</blockquote>\n`}html({text:r}){return r}def(r){return""}heading({tokens:r,depth:e}){return`<h${e}>${this.parser.parseInline(r)}</h${e}>\n`}hr(r){return`<hr>\n`}list(r){let e=r.ordered,t=r.start,s="";for(let a=0;a<r.items.length;a++){let l=r.items[a];s+=this.listitem(l)}let n=e?"ol":"ul",i=e&&t!==1?\' start="\'+t+\'"\':"";return"<"+n+i+`>\n`+s+"</"+n+`>\n`}listitem(r){return`<li>${this.parser.parse(r.tokens)}</li>\n`}checkbox({checked:r}){return"<input "+(r?\'checked="" \':"")+\'disabled="" type="checkbox"> \'}paragraph({tokens:r}){return`<p>${this.parser.parseInline(r)}</p>\n`}table(r){let e="",t="";for(let n=0;n<r.header.length;n++)t+=this.tablecell(r.header[n]);e+=this.tablerow({text:t});let s="";for(let n=0;n<r.rows.length;n++){let i=r.rows[n];t="";for(let a=0;a<i.length;a++)t+=this.tablecell(i[a]);s+=this.tablerow({text:t})}return s&&(s=`<tbody>${s}</tbody>`),`<table>\n<thead>\n`+e+`</thead>\n`+s+`</table>\n`}tablerow({text:r}){return`<tr>\n${r}</tr>\n`}tablecell(r){let e=this.parser.parseInline(r.tokens),t=r.header?"th":"td";return(r.align?`<${t} align="${r.align}">`:`<${t}>`)+e+`</${t}>\n`}strong({tokens:r}){return`<strong>${this.parser.parseInline(r)}</strong>`}em({tokens:r}){return`<em>${this.parser.parseInline(r)}</em>`}codespan({text:r}){return`<code>${y(r,!0)}</code>`}br(r){return"<br>"}del({tokens:r}){return`<del>${this.parser.parseInline(r)}</del>`}link({href:r,title:e,tokens:t}){let s=this.parser.parseInline(t),n=le(r);if(n===null)return s;r=n;let i=\'<a href="\'+r+\'"\';return e&&(i+=\' title="\'+y(e)+\'"\'),i+=">"+s+"</a>",i}image({href:r,title:e,text:t,tokens:s}){s&&(t=this.parser.parseInline(s,this.parser.textRenderer));let n=le(r);if(n===null)return y(t);r=n;let i=`<img src="${r}" alt="${y(t)}"`;return e&&(i+=` title="${y(e)}"`),i+=">",i}text(r){return"tokens"in r&&r.tokens?this.parser.parseInline(r.tokens):"escaped"in r&&r.escaped?r.text:y(r.text)}},re=class{strong({text:r}){return r}em({text:r}){return r}codespan({text:r}){return r}del({text:r}){return r}html({text:r}){return r}text({text:r}){return r}link({text:r}){return""+r}image({text:r}){return""+r}br(){return""}checkbox({raw:r}){return r}},m=class X{options;renderer;textRenderer;constructor(e){this.options=e||A,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 re}static parse(e,t){return new X(t).parse(e)}static parseInline(e,t){return new X(t).parseInline(e)}parse(e){this.renderer.parser=this;let t="";for(let s=0;s<e.length;s++){let n=e[s];if(this.options.extensions?.renderers?.[n.type]){let a=n,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)){t+=l||"";continue}}let i=n;switch(i.type){case"space":{t+=this.renderer.space(i);break}case"hr":{t+=this.renderer.hr(i);break}case"heading":{t+=this.renderer.heading(i);break}case"code":{t+=this.renderer.code(i);break}case"table":{t+=this.renderer.table(i);break}case"blockquote":{t+=this.renderer.blockquote(i);break}case"list":{t+=this.renderer.list(i);break}case"checkbox":{t+=this.renderer.checkbox(i);break}case"html":{t+=this.renderer.html(i);break}case"def":{t+=this.renderer.def(i);break}case"paragraph":{t+=this.renderer.paragraph(i);break}case"text":{t+=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 t}parseInline(e,t=this.renderer){this.renderer.parser=this;let s="";for(let n=0;n<e.length;n++){let i=e[n];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+=t.text(a);break}case"html":{s+=t.html(a);break}case"link":{s+=t.link(a);break}case"image":{s+=t.image(a);break}case"checkbox":{s+=t.checkbox(a);break}case"strong":{s+=t.strong(a);break}case"em":{s+=t.em(a);break}case"codespan":{s+=t.codespan(a);break}case"br":{s+=t.br(a);break}case"del":{s+=t.del(a);break}case"text":{s+=t.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}},E=class{options;block;constructor(r){this.options=r||A}static passThroughHooks=new Set(["preprocess","postprocess","processAllTokens","emStrongMask"]);static passThroughHooksRespectAsync=new Set(["preprocess","postprocess","processAllTokens"]);preprocess(r){return r}postprocess(r){return r}processAllTokens(r){return r}emStrongMask(r){return r}provideLexer(r=this.block){return r?w.lex:w.lexInline}provideParser(r=this.block){return r?m.parse:m.parseInline}},ot=class{defaults=U();options=this.setOptions;parse=this.parseMarkdown(!0);parseInline=this.parseMarkdown(!1);Parser=m;Renderer=N;TextRenderer=re;Lexer=w;Tokenizer=Q;Hooks=E;constructor(...r){this.use(...r)}walkTokens(r,e){let t=[];for(let s of r)switch(t=t.concat(e.call(this,s)),s.type){case"table":{let n=s;for(let i of n.header)t=t.concat(this.walkTokens(i.tokens,e));for(let i of n.rows)for(let a of i)t=t.concat(this.walkTokens(a.tokens,e));break}case"list":{let n=s;t=t.concat(this.walkTokens(n.items,e));break}default:{let n=s;this.defaults.extensions?.childTokens?.[n.type]?this.defaults.extensions.childTokens[n.type].forEach(i=>{let a=n[i].flat(1/0);t=t.concat(this.walkTokens(a,e))}):n.tokens&&(t=t.concat(this.walkTokens(n.tokens,e)))}}return t}use(...r){let e=this.defaults.extensions||{renderers:{},childTokens:{}};return r.forEach(t=>{let s={...t};if(s.async=this.defaults.async||s.async||!1,t.extensions&&(t.extensions.forEach(n=>{if(!n.name)throw new Error("extension name required");if("renderer"in n){let i=e.renderers[n.name];i?e.renderers[n.name]=function(...a){let l=n.renderer.apply(this,a);return l===!1&&(l=i.apply(this,a)),l}:e.renderers[n.name]=n.renderer}if("tokenizer"in n){if(!n.level||n.level!=="block"&&n.level!=="inline")throw new Error("extension level must be \'block\' or \'inline\'");let i=e[n.level];i?i.unshift(n.tokenizer):e[n.level]=[n.tokenizer],n.start&&(n.level==="block"?e.startBlock?e.startBlock.push(n.start):e.startBlock=[n.start]:n.level==="inline"&&(e.startInline?e.startInline.push(n.start):e.startInline=[n.start]))}"childTokens"in n&&n.childTokens&&(e.childTokens[n.name]=n.childTokens)}),s.extensions=e),t.renderer){let n=this.defaults.renderer||new N(this.defaults);for(let i in t.renderer){if(!(i in n))throw new Error(`renderer \'${i}\' does not exist`);if(["options","parser"].includes(i))continue;let a=i,l=t.renderer[a],o=n[a];n[a]=(...c)=>{let p=l.apply(n,c);return p===!1&&(p=o.apply(n,c)),p||""}}s.renderer=n}if(t.tokenizer){let n=this.defaults.tokenizer||new Q(this.defaults);for(let i in t.tokenizer){if(!(i in n))throw new Error(`tokenizer \'${i}\' does not exist`);if(["options","rules","lexer"].includes(i))continue;let a=i,l=t.tokenizer[a],o=n[a];n[a]=(...c)=>{let p=l.apply(n,c);return p===!1&&(p=o.apply(n,c)),p}}s.tokenizer=n}if(t.hooks){let n=this.defaults.hooks||new E;for(let i in t.hooks){if(!(i in n))throw new Error(`hook \'${i}\' does not exist`);if(["options","block"].includes(i))continue;let a=i,l=t.hooks[a],o=n[a];E.passThroughHooks.has(i)?n[a]=c=>{if(this.defaults.async&&E.passThroughHooksRespectAsync.has(i))return(async()=>{let h=await l.call(n,c);return o.call(n,h)})();let p=l.call(n,c);return o.call(n,p)}:n[a]=(...c)=>{if(this.defaults.async)return(async()=>{let h=await l.apply(n,c);return h===!1&&(h=await o.apply(n,c)),h})();let p=l.apply(n,c);return p===!1&&(p=o.apply(n,c)),p}}s.hooks=n}if(t.walkTokens){let n=this.defaults.walkTokens,i=t.walkTokens;s.walkTokens=function(a){let l=[];return l.push(i.call(this,a)),n&&(l=l.concat(n.call(this,a))),l}}this.defaults={...this.defaults,...s}}),this}setOptions(r){return this.defaults={...this.defaults,...r},this}lexer(r,e){return w.lex(r,e??this.defaults)}parser(r,e){return m.parse(r,e??this.defaults)}parseMarkdown(r){return(e,t)=>{let s={...t},n={...this.defaults,...s},i=this.onError(!!n.silent,!!n.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(n.hooks&&(n.hooks.options=n,n.hooks.block=r),n.async)return(async()=>{let a=n.hooks?await n.hooks.preprocess(e):e,l=await(n.hooks?await n.hooks.provideLexer(r):r?w.lex:w.lexInline)(a,n),o=n.hooks?await n.hooks.processAllTokens(l):l;n.walkTokens&&await Promise.all(this.walkTokens(o,n.walkTokens));let c=await(n.hooks?await n.hooks.provideParser(r):r?m.parse:m.parseInline)(o,n);return n.hooks?await n.hooks.postprocess(c):c})().catch(i);try{n.hooks&&(e=n.hooks.preprocess(e));let a=(n.hooks?n.hooks.provideLexer(r):r?w.lex:w.lexInline)(e,n);n.hooks&&(a=n.hooks.processAllTokens(a)),n.walkTokens&&this.walkTokens(a,n.walkTokens);let l=(n.hooks?n.hooks.provideParser(r):r?m.parse:m.parseInline)(a,n);return n.hooks&&(l=n.hooks.postprocess(l)),l}catch(a){return i(a)}}}onError(r,e){return t=>{if(t.message+=`\nPlease report this to https://github.com/markedjs/marked.`,r){let s="<p>An error occurred:</p><pre>"+y(t.message+"",!0)+"</pre>";return e?Promise.resolve(s):s}if(e)return Promise.reject(t);throw t}}},z=new ot;function k(r,e){return z.parse(r,e)}k.options=k.setOptions=function(r){return z.setOptions(r),k.defaults=z.defaults,he(k.defaults),k};k.getDefaults=U;k.defaults=A;k.use=function(...r){return z.use(...r),k.defaults=z.defaults,he(k.defaults),k};k.walkTokens=function(r,e){return z.walkTokens(r,e)};k.parseInline=z.parseInline;k.Parser=m;k.parser=m.parse;k.Renderer=N;k.TextRenderer=re;k.Lexer=w;k.lexer=w.lex;k.Tokenizer=Q;k.Hooks=E;k.parse=k;var ut=k.options,gt=k.setOptions,kt=k.use,ft=k.walkTokens,dt=k.parseInline;var xt=m.parse,bt=w.lex;var ct=0;function ht(r){if(typeof r!="string"||typeof performance.mark!="function"||typeof performance.measure!="function")return null;let e=ct++,t={name:r,startMark:`${r}:start:${e}`,endMark:`${r}:end:${e}`};try{return performance.mark(t.startMark),t}catch{return null}}function pt(r){if(r)try{performance.mark(r.endMark),performance.measure(r.name,r.startMark,r.endMark)}catch{}finally{try{performance.clearMarks?.(r.startMark),performance.clearMarks?.(r.endMark)}catch{}}}k.use({extensions:[{name:"inlineMath",level:"inline",start(r){return r.match(/(?<![\\\\$])\\$(?![$\\s])/)?.index},tokenizer(r){let e=/^\\$(?![$\\s\\d])((?:\\\\\\$|[^$\\n])*?)(?<!\\s)\\$(?!\\d)/.exec(r);if(e)return{type:"inlineMath",raw:e[0],text:e[1].trim()}},renderer(r){return r.raw}}]});var P=new Map;self.onmessage=r=>{let e=r.data;if(typeof e!="object"||e===null)return;let{id:t,text:s,append:n,expectedLength:i,oldRaws:a,instance:l,baseVersion:o,dispose:c,userTimingName:p}=e;if(c===!0){typeof l=="string"&&P.delete(l);return}let h=typeof l=="string"?l:null,u=typeof o=="number"?o:null,x,f=null;if(typeof n=="string"){if(h===null||u===null){self.postMessage({id:t,needResync:!0});return}let d=P.get(h);if(!d||d.version!==u){self.postMessage({id:t,needResync:!0});return}if(x=d.source+n,typeof i=="number"&&x.length!==i){P.delete(h),self.postMessage({id:t,needResync:!0});return}f=d.raws}else if(typeof s=="string"){if(x=s,Array.isArray(a))f=a;else if(h!==null&&u!==null){let d=P.get(h);if(d&&d.version===u)f=d.raws;else{self.postMessage({id:t,needResync:!0});return}}}else return;try{let d=typeof p=="string"?ht(p):null,B=performance.now(),$;try{$=k.lexer(x)}finally{d&&pt(d)}let q=performance.now()-B,R=0;if(f){let v=Math.min(f.length,$.length);for(;R<v&&f[R]===$[R].raw;R++);}h!==null&&u!==null&&P.set(h,{version:u+1,raws:$.map(v=>v.raw),source:x}),self.postMessage({id:t,matchLen:R,tail:$.slice(R),lexerMs:q,sourceCharsLexed:x.length})}catch(d){h!==null&&P.delete(h),self.postMessage({id:t,error:String(d)})}};})();\n';
|
|
428
|
+
var WORKER_SOURCE_STRING = '"use strict";(()=>{function U(){return{async:!1,breaks:!1,extensions:null,gfm:!0,hooks:null,pedantic:!1,renderer:null,silent:!1,tokenizer:null,walkTokens:null}}var A=U();function he(r){A=r}var T={exec:()=>null};function L(r){let e=[];return t=>{let s=Math.max(0,Math.min(3,t-1)),n=e[s];return n||(n=r(s),e[s]=n),n}}function g(r,e=""){let t=typeof r=="string"?r:r.source,s={replace:(n,i)=>{let a=typeof i=="string"?i:i.source;return a=a.replace(b.caret,"$1"),t=t.replace(n,a),s},getRegex:()=>new RegExp(t,e)};return s}var me=((r="")=>{try{return!!new RegExp("(?<=1)(?<!1)"+r)}catch{return!1}})(),b={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:r=>new RegExp(`^( {0,3}${r})((?:[ ][^\\\\n]*)?(?:\\\\n|$))`),nextBulletRegex:L(r=>new RegExp(`^ {0,${r}}(?:[*+-]|\\\\d{1,9}[.)])((?:[ ][^\\\\n]*)?(?:\\\\n|$))`)),hrRegex:L(r=>new RegExp(`^ {0,${r}}((?:- *){3,}|(?:_ *){3,}|(?:\\\\* *){3,})(?:\\\\n+|$)`)),fencesBeginRegex:L(r=>new RegExp(`^ {0,${r}}(?:\\`\\`\\`|~~~)`)),headingBeginRegex:L(r=>new RegExp(`^ {0,${r}}#`)),htmlBeginRegex:L(r=>new RegExp(`^ {0,${r}}<(?:[a-z].*>|!--)`,"i")),blockquoteBeginRegex:L(r=>new RegExp(`^ {0,${r}}>`))},ye=/^(?:[ \\t]*(?:\\n|$))+/,$e=/^((?: {4}| {0,3}\\t)[^\\n]+(?:\\n(?:[ \\t]*(?:\\n|$))*)?)+/,Re=/^ {0,3}(`{3,}(?=[^`\\n]*(?:\\n|$))|~{3,})([^\\n]*)(?:\\n|$)(?:|([\\s\\S]*?)(?:\\n|$))(?: {0,3}\\1[~`]* *(?=\\n|$)|$)/,M=/^ {0,3}((?:-[\\t ]*){3,}|(?:_[ \\t]*){3,}|(?:\\*[ \\t]*){3,})(?:\\n+|$)/,Se=/^ {0,3}(#{1,6})(?=\\s|$)(.*)(?:\\n+|$)/,F=/ {0,3}(?:[*+-]|\\d{1,9}[.)])/,pe=/^(?!bull |blockCode|fences|blockquote|heading|html|table)((?:.|\\n(?!\\s*?\\n|bull |blockCode|fences|blockquote|heading|html|table))+?)\\n {0,3}(=+|-+) *(?:\\n+|$)/,ue=g(pe).replace(/bull/g,F).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(),Te=g(pe).replace(/bull/g,F).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(),V=/^([^\\n]+(?:\\n(?!hr|heading|lheading|blockquote|fences|list|html|table|[ \\t]+\\n)[^\\n]+)*)/,ze=/^[^\\n]+/,J=/(?!\\s*\\])(?:\\\\[\\s\\S]|[^\\[\\]\\\\])+/,Ae=g(/^ {0,3}\\[(label)\\]: *(?:\\n[ \\t]*)?([^<\\s][^\\s]*|<.*?>)(?:(?: +(?:\\n[ \\t]*)?| *\\n[ \\t]*)(title))? *(?:\\n+|$)/).replace("label",J).replace("title",/(?:"(?:\\\\"?|[^"\\\\])*"|\'[^\'\\n]*(?:\\n[^\'\\n]+)*\\n?\'|\\([^()]*\\))/).getRegex(),Le=g(/^(bull)([ \\t][^\\n]*?)?(?:\\n|$)/).replace(/bull/g,F).getRegex(),j="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",K=/<!--(?:-?>|[\\s\\S]*?(?:-->|$))/,_e=g("^ {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",K).replace("tag",j).replace("attribute",/ +[a-zA-Z:_][\\w.:-]*(?: *= *"[^"\\n]*"| *= *\'[^\'\\n]*\'| *= *[^\\s"\'=<>`]+)?/).getRegex(),ge=r=>g(V).replace("hr",M).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",r).replace("html","</?(?:tag)(?: +|\\\\n|/?>)|<(?:script|pre|style|textarea|!--)").replace("tag",j).getRegex(),Pe=ge(/ {0,3}(?:[*+-]|1[.)])[ \\t]+[^ \\t\\n]/),ve=ge(/ {0,3}(?:[*+-]|\\d{1,9}[.)])(?:[ \\t]|\\n|$)/),Ie=g(/^( {0,3}> ?(paragraph|[^\\n]*)(?:\\n|$))+/).replace("paragraph",ve).getRegex(),Y={blockquote:Ie,code:$e,def:Ae,fences:Re,heading:Se,hr:M,html:_e,lheading:ue,list:Le,newline:ye,paragraph:Pe,table:T,text:ze},ne=g("^ *([^\\\\n ].*)\\\\n {0,3}((?:\\\\| *)?:?-+:? *(?:\\\\| *:?-+:? *)*(?:\\\\| *)?)(?:\\\\n((?:(?! *\\\\n|hr|heading|blockquote|code|fences|list|html).*(?:\\\\n|$))*)\\\\n*|$)").replace("hr",M).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",j).getRegex(),Ce={...Y,lheading:Te,table:ne,paragraph:g(V).replace("hr",M).replace("heading"," {0,3}#{1,6}(?:\\\\s|$)").replace("|lheading","").replace("table",ne).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",j).getRegex()},Ee={...Y,html:g(`^ *(?:comment *(?:\\\\n|\\\\s*$)|<(tag)[\\\\s\\\\S]+?</\\\\1> *(?:\\\\n{2,}|\\\\s*$)|<tag(?:"[^"]*"|\'[^\']*\'|\\\\s[^\'"/>\\\\s]*)*?/?> *(?:\\\\n{2,}|\\\\s*$))`).replace("comment",K).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:T,lheading:/^(.+?)\\n {0,3}(=+|-+) *(?:\\n+|$)/,paragraph:g(V).replace("hr",M).replace("heading",` *#{1,6} *[^\n]`).replace("lheading",ue).replace("|table","").replace("blockquote"," {0,3}>").replace("|fences","").replace("|list","").replace("|html","").replace("|tag","").getRegex()},Me=/^\\\\([!"#$%&\'()*+,\\-./:;<=>?@\\[\\]\\\\^_`{|}~])/,Be=/^(`+)([^`]|[^`][\\s\\S]*?[^`])\\1(?!`)/,ke=/^( {2,}|\\\\)\\n(?!\\s*$)/,qe=/^(`+|[^`])(?:(?= {2,}\\n)|[\\s\\S]*?(?:(?=[\\\\<!\\[`*_]|\\b_|$)|[^ ](?= {2,}\\n)))/,_=/[\\p{P}\\p{S}]/u,H=/[\\s\\p{P}\\p{S}]/u,ee=/[^\\s\\p{P}\\p{S}]/u,Ze=g(/^((?![*_])punctSpace)/,"u").replace(/punctSpace/g,H).getRegex(),fe=/(?!~)[\\p{P}\\p{S}]/u,De=/(?!~)[\\s\\p{P}\\p{S}]/u,Qe=/(?:[^\\s\\p{P}\\p{S}]|~)/u,Ne=g(/link|precode-code|html/,"g").replace("link",/\\[(?:[^\\[\\]`]|(?<a>`+)[^`]+\\k<a>(?!`))*?\\]\\((?:\\\\[\\s\\S]|[^\\\\\\(\\)]|\\((?:\\\\[\\s\\S]|[^\\\\\\(\\)])*\\))*\\)/).replace("precode-",me?"(?<!`)()":"(^^|[^`])").replace("code",/(?<b>`+)[^`]+\\k<b>(?!`)/).replace("html",/<(?! )[^<>]*?>/).getRegex(),de=/^(?:\\*+(?:((?!\\*)punct)|([^\\s*]))?)|^_+(?:((?!_)punct)|([^\\s_]))?/,je=g(de,"u").replace(/punct/g,_).getRegex(),He=g(de,"u").replace(/punct/g,fe).getRegex(),xe="^[^_*]*?__[^_*]*?\\\\*[^_*]*?(?=__)|[^*]+(?=[^*])|(?!\\\\*)punct(\\\\*+)(?=[\\\\s]|$)|notPunctSpace(\\\\*+)(?!\\\\*)(?=punctSpace|$)|(?!\\\\*)punctSpace(\\\\*+)(?=notPunctSpace)|[\\\\s](\\\\*+)(?!\\\\*)(?=punct)|(?!\\\\*)punct(\\\\*+)(?!\\\\*)(?=punct)|notPunctSpace(\\\\*+)(?=notPunctSpace)",Oe=g(xe,"gu").replace(/notPunctSpace/g,ee).replace(/punctSpace/g,H).replace(/punct/g,_).getRegex(),Ge=g(xe,"gu").replace(/notPunctSpace/g,Qe).replace(/punctSpace/g,De).replace(/punct/g,fe).getRegex(),We=g("^[^_*]*?\\\\*\\\\*[^_*]*?_[^_*]*?(?=\\\\*\\\\*)|[^_]+(?=[^_])|(?!_)punct(_+)(?=[\\\\s]|$)|notPunctSpace(_+)(?!_)(?=punctSpace|$)|(?!_)punctSpace(_+)(?=notPunctSpace)|[\\\\s](_+)(?!_)(?=punct)|(?!_)punct(_+)(?!_)(?=punct)","gu").replace(/notPunctSpace/g,ee).replace(/punctSpace/g,H).replace(/punct/g,_).getRegex(),Xe=g(/^~~?(?:((?!~)punct)|[^\\s~])/,"u").replace(/punct/g,_).getRegex(),Ue="^[^~]+(?=[^~])|(?!~)punct(~~?)(?=[\\\\s]|$)|notPunctSpace(~~?)(?!~)(?=punctSpace|$)|(?!~)punctSpace(~~?)(?=notPunctSpace)|[\\\\s](~~?)(?!~)(?=punct)|(?!~)punct(~~?)(?!~)(?=punct)|notPunctSpace(~~?)(?=notPunctSpace)",Fe=g(Ue,"gu").replace(/notPunctSpace/g,ee).replace(/punctSpace/g,H).replace(/punct/g,_).getRegex(),Ve=g(/\\\\(punct)/,"gu").replace(/punct/g,_).getRegex(),Je=g(/^<(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(),Ke=g(K).replace("(?:-->|$)","-->").getRegex(),Ye=g("^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",Ke).replace("attribute",/\\s+[a-zA-Z:_][\\w.:-]*(?:\\s*=\\s*"[^"]*"|\\s*=\\s*\'[^\']*\'|\\s*=\\s*[^\\s"\'=<>`]+)?/).getRegex(),D=/(?:\\[(?:\\\\[\\s\\S]|[^\\[\\]\\\\])*\\]|\\\\[\\s\\S]|`+(?!`)[^`]*?`+(?!`)|``+(?=\\])|[^\\[\\]\\\\`])*?/,et=g(/^!?\\[(label)\\]\\(\\s*(href)(?:(?:[ \\t]+(?:\\n[ \\t]*)?|\\n[ \\t]*)(title))?\\s*\\)/).replace("label",D).replace("href",/<(?:\\\\.|[^\\n<>\\\\])+>|[^ \\t\\n\\x00-\\x1f]+|(?=\\))/).replace("title",/"(?:\\\\"?|[^"\\\\])*"|\'(?:\\\\\'?|[^\'\\\\])*\'|\\((?:\\\\\\)?|[^)\\\\])*\\)/).getRegex(),be=g(/^!?\\[(label)\\]\\[(ref)\\]/).replace("label",D).replace("ref",J).getRegex(),we=g(/^!?\\[(ref)\\](?:\\[\\])?/).replace("ref",J).getRegex(),tt=g("reflink|nolink(?!\\\\()","g").replace("reflink",be).replace("nolink",we).getRegex(),se=/[hH][tT][tT][pP][sS]?|[fF][tT][pP]/,te={_backpedal:T,anyPunctuation:Ve,autolink:Je,blockSkip:Ne,br:ke,code:Be,del:T,delLDelim:T,delRDelim:T,emStrongLDelim:je,emStrongRDelimAst:Oe,emStrongRDelimUnd:We,escape:Me,link:et,nolink:we,punctuation:Ze,reflink:be,reflinkSearch:tt,tag:Ye,text:qe,url:T},rt={...te,link:g(/^!?\\[(label)\\]\\((.*?)\\)/).replace("label",D).getRegex(),reflink:g(/^!?\\[(label)\\]\\s*\\[([^\\]]*)\\]/).replace("label",D).getRegex()},G={...te,emStrongRDelimAst:Ge,emStrongLDelim:He,delLDelim:Xe,delRDelim:Fe,url:g(/^((?:protocol):\\/\\/|www\\.)(?:[a-zA-Z0-9\\-]+\\.?)+[^\\s<]*|^email/).replace("protocol",se).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:g(/^(`+|~+|[^`~])(?:(?=[`~])|(?= {2,}\\n)|(?=[a-zA-Z0-9.!#$%&\'*+\\/=?_`{\\|}~-]+@)|[\\s\\S]*?(?:(?=[\\\\<!\\[`*~_]|\\b_|protocol:\\/\\/|www\\.|$)|[^ ](?= {2,}\\n)|[^a-zA-Z0-9.!#$%&\'*+\\/=?_`{\\|}~-](?=[a-zA-Z0-9.!#$%&\'*+\\/=?_`{\\|}~-]+@)))/).replace("protocol",se).getRegex()},nt={...G,br:g(ke).replace("{2,}","*").getRegex(),text:g(G.text).replace("\\\\b_","\\\\b_| {2,}\\\\n").replace(/\\{2,\\}/g,"*").getRegex()},Z={normal:Y,gfm:Ce,pedantic:Ee},C={normal:te,gfm:G,breaks:nt,pedantic:rt},st={"&":"&","<":"<",">":">",\'"\':""","\'":"'"},ie=r=>st[r];function y(r,e){if(e){if(b.escapeTest.test(r))return r.replace(b.escapeReplace,ie)}else if(b.escapeTestNoEncode.test(r))return r.replace(b.escapeReplaceNoEncode,ie);return r}function le(r){try{r=encodeURI(r).replace(b.percentDecode,"%")}catch{return null}return r}function ae(r,e){let t=r.replace(b.findPipe,(i,a,l)=>{let o=!1,c=a;for(;--c>=0&&l[c]==="\\\\";)o=!o;return o?"|":" |"}),s=t.split(b.splitPipe),n=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(;n<s.length;n++)s[n]=s[n].trim().replace(b.slashPipe,"|");return s}function S(r,e,t){let s=r.length;if(s===0)return"";let n=0;for(;n<s;){let i=r.charAt(s-n-1);if(i===e&&!t)n++;else if(i!==e&&t)n++;else break}return r.slice(0,s-n)}function oe(r){let e=r.split(`\n`),t=e.length-1;for(;t>=0&&b.blankLine.test(e[t]);)t--;return e.length-t<=2?r:e.slice(0,t+1).join(`\n`)}function it(r,e){if(r.indexOf(e[1])===-1)return-1;let t=0;for(let s=0;s<r.length;s++)if(r[s]==="\\\\")s++;else if(r[s]===e[0])t++;else if(r[s]===e[1]&&(t--,t<0))return s;return t>0?-2:-1}function lt(r,e=0){let t=e,s="";for(let n of r)if(n===" "){let i=4-t%4;s+=" ".repeat(i),t+=i}else s+=n,t++;return s}function ce(r,e,t,s,n){let i=e.href,a=e.title||null,l=r[1].replace(n.other.outputLinkReplace,"$1");s.state.inLink=!0;let o={type:r[0].charAt(0)==="!"?"image":"link",raw:t,href:i,title:a,text:l,tokens:s.inlineTokens(l)};return s.state.inLink=!1,o}function at(r,e,t){let s=r.match(t.other.indentCodeCompensation);if(s===null)return e;let n=s[1];return e.split(`\n`).map(i=>{let a=i.match(t.other.beginningSpace);if(a===null)return i;let[l]=a;return l.length>=n.length?i.slice(n.length):i}).join(`\n`)}var Q=class{options;rules;lexer;constructor(r){this.options=r||A}space(r){let e=this.rules.block.newline.exec(r);if(e&&e[0].length>0)return{type:"space",raw:e[0]}}code(r){let e=this.rules.block.code.exec(r);if(e){let t=this.options.pedantic?e[0]:oe(e[0]),s=t.replace(this.rules.other.codeRemoveIndent,"");return{type:"code",raw:t,codeBlockStyle:"indented",text:s}}}fences(r){let e=this.rules.block.fences.exec(r);if(e){let t=e[0],s=at(t,e[3]||"",this.rules);return{type:"code",raw:t,lang:e[2]?e[2].trim().replace(this.rules.inline.anyPunctuation,"$1"):e[2],text:s}}}heading(r){let e=this.rules.block.heading.exec(r);if(e){let t=e[2].trim();if(this.rules.other.endingHash.test(t)){let s=S(t,"#");(this.options.pedantic||!s||this.rules.other.endingSpaceChar.test(s))&&(t=s.trim())}return{type:"heading",raw:S(e[0],`\n`),depth:e[1].length,text:t,tokens:this.lexer.inline(t)}}}hr(r){let e=this.rules.block.hr.exec(r);if(e)return{type:"hr",raw:S(e[0],`\n`)}}blockquote(r){let e=this.rules.block.blockquote.exec(r);if(e){let t=S(e[0],`\n`).split(`\n`),s="",n="",i=[];for(;t.length>0;){let a=!1,l=[],o;for(o=0;o<t.length;o++)if(this.rules.other.blockquoteStart.test(t[o]))l.push(t[o]),a=!0;else if(!a)l.push(t[o]);else break;t=t.slice(o);let c=l.join(`\n`),p=c.replace(this.rules.other.blockquoteSetextReplace,`\n $1`).replace(this.rules.other.blockquoteSetextReplace2,"");s=s?`${s}\n${c}`:c,n=n?`${n}\n${p}`:p;let h=this.lexer.state.top;if(this.lexer.state.top=!0,this.lexer.blockTokens(p,i,!0),this.lexer.state.top=h,t.length===0)break;let u=i.at(-1);if(u?.type==="code")break;if(u?.type==="blockquote"){let x=u,f=x.raw+`\n`+t.join(`\n`),d=this.blockquote(f);i[i.length-1]=d,s=s.substring(0,s.length-x.raw.length)+d.raw,n=n.substring(0,n.length-x.text.length)+d.text;break}else if(u?.type==="list"){let x=u,f=x.raw+`\n`+t.join(`\n`),d=this.list(f);i[i.length-1]=d,s=s.substring(0,s.length-u.raw.length)+d.raw,n=n.substring(0,n.length-x.raw.length)+d.raw,t=f.substring(i.at(-1).raw.length).split(`\n`);continue}}return{type:"blockquote",raw:s,tokens:i,text:n}}}list(r){let e=this.rules.block.list.exec(r);if(e){let t=e[1].trim(),s=t.length>1,n={type:"list",raw:"",ordered:s,start:s?+t.slice(0,-1):"",loose:!1,items:[]};t=s?`\\\\d{1,9}\\\\${t.slice(-1)}`:`\\\\${t}`,this.options.pedantic&&(t=s?t:"[*+-]");let i=this.rules.other.listItemRegex(t),a=!1;for(;r;){let o=!1,c="",p="";if(!(e=i.exec(r))||this.rules.block.hr.test(r))break;c=e[0],r=r.substring(c.length);let h=lt(e[2].split(`\n`,1)[0],e[1].length),u=r.split(`\n`,1)[0],x=!h.trim(),f=0;if(this.options.pedantic?(f=2,p=h.trimStart()):x?f=e[1].length+1:(f=h.search(this.rules.other.nonSpaceChar),f=f>4?1:f,p=h.slice(f),f+=e[1].length),x&&this.rules.other.blankLine.test(u)&&(c+=u+`\n`,r=r.substring(u.length+1),o=!0),!o){let d=this.rules.other.nextBulletRegex(f),B=this.rules.other.hrRegex(f),$=this.rules.other.fencesBeginRegex(f),q=this.rules.other.headingBeginRegex(f),R=this.rules.other.htmlBeginRegex(f),v=this.rules.other.blockquoteBeginRegex(f);for(;r;){let O=r.split(`\n`,1)[0],I;if(u=O,this.options.pedantic?(u=u.replace(this.rules.other.listReplaceNesting," "),I=u):I=u.replace(this.rules.other.tabCharGlobal," "),$.test(u)||q.test(u)||R.test(u)||v.test(u)||d.test(u)||B.test(u))break;if(I.search(this.rules.other.nonSpaceChar)>=f||!u.trim())p+=`\n`+I.slice(f);else{if(x||h.replace(this.rules.other.tabCharGlobal," ").search(this.rules.other.nonSpaceChar)>=4||$.test(h)||q.test(h)||B.test(h))break;p+=`\n`+u}x=!u.trim(),c+=O+`\n`,r=r.substring(O.length+1),h=I.slice(f)}}n.loose||(a?n.loose=!0:this.rules.other.doubleBlankLine.test(c)&&(a=!0)),n.items.push({type:"list_item",raw:c,task:!!this.options.gfm&&this.rules.other.listIsTask.test(p),loose:!1,text:p,tokens:[]}),n.raw+=c}let l=n.items.at(-1);if(l)l.raw=l.raw.trimEnd(),l.text=l.text.trimEnd();else return;n.raw=n.raw.trimEnd();for(let o of n.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 p=this.rules.other.listTaskCheckbox.exec(o.raw);if(p){let h={type:"checkbox",raw:p[0]+" ",checked:p[0]!=="[ ]"};o.checked=h.checked,n.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(!n.loose){let p=o.tokens.filter(u=>u.type==="space"),h=p.length>0&&p.some(u=>this.rules.other.anyLine.test(u.raw));n.loose=h}}if(n.loose)for(let o of n.items){o.loose=!0;for(let c of o.tokens)c.type==="text"&&(c.type="paragraph")}return n}}html(r){let e=this.rules.block.html.exec(r);if(e){let t=oe(e[0]);return{type:"html",block:!0,raw:t,pre:e[1]==="pre"||e[1]==="script"||e[1]==="style",text:t}}}def(r){let e=this.rules.block.def.exec(r);if(e){let t=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"):"",n=e[3]?e[3].substring(1,e[3].length-1).replace(this.rules.inline.anyPunctuation,"$1"):e[3];return{type:"def",tag:t,raw:S(e[0],`\n`),href:s,title:n}}}table(r){let e=this.rules.block.table.exec(r);if(!e||!this.rules.other.tableDelimiter.test(e[2]))return;let t=ae(e[1]),s=e[2].replace(this.rules.other.tableAlignChars,"").split("|"),n=e[3]?.trim()?e[3].replace(this.rules.other.tableRowBlankLine,"").split(`\n`):[],i={type:"table",raw:S(e[0],`\n`),header:[],align:[],rows:[]};if(t.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<t.length;a++)i.header.push({text:t[a],tokens:this.lexer.inline(t[a]),header:!0,align:i.align[a]});for(let a of n)i.rows.push(ae(a,i.header.length).map((l,o)=>({text:l,tokens:this.lexer.inline(l),header:!1,align:i.align[o]})));return i}}lheading(r){let e=this.rules.block.lheading.exec(r);if(e){let t=e[1].trim();return{type:"heading",raw:S(e[0],`\n`),depth:e[2].charAt(0)==="="?1:2,text:t,tokens:this.lexer.inline(t)}}}paragraph(r){let e=this.rules.block.paragraph.exec(r);if(e){let t=e[1].charAt(e[1].length-1)===`\n`?e[1].slice(0,-1):e[1];return{type:"paragraph",raw:e[0],text:t,tokens:this.lexer.inline(t)}}}text(r){let e=this.rules.block.text.exec(r);if(e)return{type:"text",raw:e[0],text:e[0],tokens:this.lexer.inline(e[0])}}escape(r){let e=this.rules.inline.escape.exec(r);if(e)return{type:"escape",raw:e[0],text:e[1]}}tag(r){let e=this.rules.inline.tag.exec(r);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(r){let e=this.rules.inline.link.exec(r);if(e){let t=e[2].trim();if(!this.options.pedantic&&this.rules.other.startAngleBracket.test(t)){if(!this.rules.other.endAngleBracket.test(t))return;let i=S(t.slice(0,-1),"\\\\");if((t.length-i.length)%2===0)return}else{let i=it(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],n="";if(this.options.pedantic){let i=this.rules.other.pedanticHrefTitle.exec(s);i&&(s=i[1],n=i[3])}else n=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(t)?s=s.slice(1):s=s.slice(1,-1)),ce(e,{href:s&&s.replace(this.rules.inline.anyPunctuation,"$1"),title:n&&n.replace(this.rules.inline.anyPunctuation,"$1")},e[0],this.lexer,this.rules)}}reflink(r,e){let t;if((t=this.rules.inline.reflink.exec(r))||(t=this.rules.inline.nolink.exec(r))){let s=(t[2]||t[1]).replace(this.rules.other.multipleSpaceGlobal," "),n=e[s.toLowerCase()];if(!n){let i=t[0].charAt(0);return{type:"text",raw:i,text:i}}return ce(t,n,t[0],this.lexer,this.rules)}}emStrong(r,e,t=""){let s=this.rules.inline.emStrongLDelim.exec(r);if(!(!s||!s[1]&&!s[2]&&!s[3]&&!s[4]||s[4]&&t.match(this.rules.other.unicodeAlphaNumeric))&&(!(s[1]||s[3])||!t||this.rules.inline.punctuation.exec(t))){let n=[...s[0]].length-1,i,a,l=n,o=0,c=s[0][0]==="*"?this.rules.inline.emStrongRDelimAst:this.rules.inline.emStrongRDelimUnd;for(c.lastIndex=0,e=e.slice(-1*r.length+n);(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])&&n%3&&!((n+a)%3)){o+=a;continue}if(l-=a,l>0)continue;a=Math.min(a,a+l+o);let p=[...s[0]][0].length,h=r.slice(0,n+s.index+p+a);if(Math.min(n,a)%2){let x=h.slice(1,-1);return{type:"em",raw:h,text:x,tokens:this.lexer.inlineTokens(x)}}let u=h.slice(2,-2);return{type:"strong",raw:h,text:u,tokens:this.lexer.inlineTokens(u)}}}}codespan(r){let e=this.rules.inline.code.exec(r);if(e){let t=e[2].replace(this.rules.other.newLineCharGlobal," "),s=this.rules.other.nonSpaceChar.test(t),n=this.rules.other.startingSpaceChar.test(t)&&this.rules.other.endingSpaceChar.test(t);return s&&n&&(t=t.substring(1,t.length-1)),{type:"codespan",raw:e[0],text:t}}}br(r){let e=this.rules.inline.br.exec(r);if(e)return{type:"br",raw:e[0]}}del(r,e,t=""){let s=this.rules.inline.delLDelim.exec(r);if(s&&(!s[1]||!t||this.rules.inline.punctuation.exec(t))){let n=[...s[0]].length-1,i,a,l=n,o=this.rules.inline.delRDelim;for(o.lastIndex=0,e=e.slice(-1*r.length+n);(s=o.exec(e))!==null;){if(i=s[1]||s[2]||s[3]||s[4]||s[5]||s[6],!i||(a=[...i].length,a!==n))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,p=r.slice(0,n+s.index+c+a),h=p.slice(n,-n);return{type:"del",raw:p,text:h,tokens:this.lexer.inlineTokens(h)}}}}autolink(r){let e=this.rules.inline.autolink.exec(r);if(e){let t,s;return e[2]==="@"?(t=e[1],s="mailto:"+t):(t=e[1],s=t),{type:"link",raw:e[0],text:t,href:s,tokens:[{type:"text",raw:t,text:t}]}}}url(r){let e;if(e=this.rules.inline.url.exec(r)){let t,s;if(e[2]==="@")t=e[0],s="mailto:"+t;else{let n;do n=e[0],e[0]=this.rules.inline._backpedal.exec(e[0])?.[0]??"";while(n!==e[0]);t=e[0],e[1]==="www."?s="http://"+e[0]:s=e[0]}return{type:"link",raw:e[0],text:t,href:s,tokens:[{type:"text",raw:t,text:t}]}}}inlineText(r){let e=this.rules.inline.text.exec(r);if(e){let t=this.lexer.state.inRawBlock;return{type:"text",raw:e[0],text:e[0],escaped:t}}}},w=class W{tokens;options;state;inlineQueue;tokenizer;constructor(e){this.tokens=[],this.tokens.links=Object.create(null),this.options=e||A,this.options.tokenizer=this.options.tokenizer||new Q,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 t={other:b,block:Z.normal,inline:C.normal};this.options.pedantic?(t.block=Z.pedantic,t.inline=C.pedantic):this.options.gfm&&(t.block=Z.gfm,this.options.breaks?t.inline=C.breaks:t.inline=C.gfm),this.tokenizer.rules=t}static get rules(){return{block:Z,inline:C}}static lex(e,t){return new W(t).lex(e)}static lexInline(e,t){return new W(t).inlineTokens(e)}lex(e){e=e.replace(b.carriageReturn,`\n`),this.blockTokens(e,this.tokens);for(let t=0;t<this.inlineQueue.length;t++){let s=this.inlineQueue[t];this.inlineTokens(s.src,s.tokens)}return this.inlineQueue=[],this.tokens}blockTokens(e,t=[],s=!1){this.tokenizer.lexer=this,this.options.pedantic&&(e=e.replace(b.tabCharGlobal," ").replace(b.spaceLine,""));let n=1/0;for(;e;){if(e.length<n)n=e.length;else{this.infiniteLoopError(e.charCodeAt(0));break}let i;if(this.options.extensions?.block?.some(l=>(i=l.call({lexer:this},e,t))?(e=e.substring(i.raw.length),t.push(i),!0):!1))continue;if(i=this.tokenizer.space(e)){e=e.substring(i.raw.length);let l=t.at(-1);i.raw.length===1&&l!==void 0?l.raw+=`\n`:t.push(i);continue}if(i=this.tokenizer.code(e)){e=e.substring(i.raw.length);let l=t.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):t.push(i);continue}if(i=this.tokenizer.fences(e)){e=e.substring(i.raw.length),t.push(i);continue}if(i=this.tokenizer.heading(e)){e=e.substring(i.raw.length),t.push(i);continue}if(i=this.tokenizer.hr(e)){e=e.substring(i.raw.length),t.push(i);continue}if(i=this.tokenizer.blockquote(e)){e=e.substring(i.raw.length),t.push(i);continue}if(i=this.tokenizer.list(e)){e=e.substring(i.raw.length),t.push(i);continue}if(i=this.tokenizer.html(e)){e=e.substring(i.raw.length),t.push(i);continue}if(i=this.tokenizer.def(e)){e=e.substring(i.raw.length);let l=t.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},t.push(i));continue}if(i=this.tokenizer.table(e)){e=e.substring(i.raw.length),t.push(i);continue}if(i=this.tokenizer.lheading(e)){e=e.substring(i.raw.length),t.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(p=>{c=p.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=t.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):t.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=t.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):t.push(i);continue}if(e){this.infiniteLoopError(e.charCodeAt(0));break}}return this.state.top=!0,t}inline(e,t=[]){return this.inlineQueue.push({src:e,tokens:t}),t}inlineTokens(e,t=[]){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 p=c?c.length:0;return l.slice(0,p)+"["+"a".repeat(l.length-p-2)+"]"}),s=this.options.hooks?.emStrongMask?.call({lexer:this},s)??s;let n=!1,i="",a=1/0;for(;e;){if(e.length<a)a=e.length;else{this.infiniteLoopError(e.charCodeAt(0));break}n||(i=""),n=!1;let l;if(this.options.extensions?.inline?.some(c=>(l=c.call({lexer:this},e,t))?(e=e.substring(l.raw.length),t.push(l),!0):!1))continue;if(l=this.tokenizer.escape(e)){e=e.substring(l.raw.length),t.push(l);continue}if(l=this.tokenizer.tag(e)){e=e.substring(l.raw.length),t.push(l);continue}if(l=this.tokenizer.link(e)){e=e.substring(l.raw.length),t.push(l);continue}if(l=this.tokenizer.reflink(e,this.tokens.links)){e=e.substring(l.raw.length);let c=t.at(-1);l.type==="text"&&c?.type==="text"?(c.raw+=l.raw,c.text+=l.text):t.push(l);continue}if(l=this.tokenizer.emStrong(e,s,i)){e=e.substring(l.raw.length),t.push(l);continue}if(l=this.tokenizer.codespan(e)){e=e.substring(l.raw.length),t.push(l);continue}if(l=this.tokenizer.br(e)){e=e.substring(l.raw.length),t.push(l);continue}if(l=this.tokenizer.del(e,s,i)){e=e.substring(l.raw.length),t.push(l);continue}if(l=this.tokenizer.autolink(e)){e=e.substring(l.raw.length),t.push(l);continue}if(!this.state.inLink&&(l=this.tokenizer.url(e))){e=e.substring(l.raw.length),t.push(l);continue}let o=e;if(this.options.extensions?.startInline){let c=1/0,p=e.slice(1),h;this.options.extensions.startInline.forEach(u=>{h=u.call({lexer:this},p),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)),n=!0;let c=t.at(-1);c?.type==="text"?(c.raw+=l.raw,c.text+=l.text):t.push(l);continue}if(e){this.infiniteLoopError(e.charCodeAt(0));break}}return t}infiniteLoopError(e){let t="Infinite loop on byte: "+e;if(this.options.silent)console.error(t);else throw new Error(t)}},N=class{options;parser;constructor(r){this.options=r||A}space(r){return""}code({text:r,lang:e,escaped:t}){let s=(e||"").match(b.notSpaceStart)?.[0],n=r.replace(b.endingNewline,"")+`\n`;return s?\'<pre><code class="language-\'+y(s)+\'">\'+(t?n:y(n,!0))+`</code></pre>\n`:"<pre><code>"+(t?n:y(n,!0))+`</code></pre>\n`}blockquote({tokens:r}){return`<blockquote>\n${this.parser.parse(r)}</blockquote>\n`}html({text:r}){return r}def(r){return""}heading({tokens:r,depth:e}){return`<h${e}>${this.parser.parseInline(r)}</h${e}>\n`}hr(r){return`<hr>\n`}list(r){let e=r.ordered,t=r.start,s="";for(let a=0;a<r.items.length;a++){let l=r.items[a];s+=this.listitem(l)}let n=e?"ol":"ul",i=e&&t!==1?\' start="\'+t+\'"\':"";return"<"+n+i+`>\n`+s+"</"+n+`>\n`}listitem(r){return`<li>${this.parser.parse(r.tokens)}</li>\n`}checkbox({checked:r}){return"<input "+(r?\'checked="" \':"")+\'disabled="" type="checkbox"> \'}paragraph({tokens:r}){return`<p>${this.parser.parseInline(r)}</p>\n`}table(r){let e="",t="";for(let n=0;n<r.header.length;n++)t+=this.tablecell(r.header[n]);e+=this.tablerow({text:t});let s="";for(let n=0;n<r.rows.length;n++){let i=r.rows[n];t="";for(let a=0;a<i.length;a++)t+=this.tablecell(i[a]);s+=this.tablerow({text:t})}return s&&(s=`<tbody>${s}</tbody>`),`<table>\n<thead>\n`+e+`</thead>\n`+s+`</table>\n`}tablerow({text:r}){return`<tr>\n${r}</tr>\n`}tablecell(r){let e=this.parser.parseInline(r.tokens),t=r.header?"th":"td";return(r.align?`<${t} align="${r.align}">`:`<${t}>`)+e+`</${t}>\n`}strong({tokens:r}){return`<strong>${this.parser.parseInline(r)}</strong>`}em({tokens:r}){return`<em>${this.parser.parseInline(r)}</em>`}codespan({text:r}){return`<code>${y(r,!0)}</code>`}br(r){return"<br>"}del({tokens:r}){return`<del>${this.parser.parseInline(r)}</del>`}link({href:r,title:e,tokens:t}){let s=this.parser.parseInline(t),n=le(r);if(n===null)return s;r=n;let i=\'<a href="\'+r+\'"\';return e&&(i+=\' title="\'+y(e)+\'"\'),i+=">"+s+"</a>",i}image({href:r,title:e,text:t,tokens:s}){s&&(t=this.parser.parseInline(s,this.parser.textRenderer));let n=le(r);if(n===null)return y(t);r=n;let i=`<img src="${r}" alt="${y(t)}"`;return e&&(i+=` title="${y(e)}"`),i+=">",i}text(r){return"tokens"in r&&r.tokens?this.parser.parseInline(r.tokens):"escaped"in r&&r.escaped?r.text:y(r.text)}},re=class{strong({text:r}){return r}em({text:r}){return r}codespan({text:r}){return r}del({text:r}){return r}html({text:r}){return r}text({text:r}){return r}link({text:r}){return""+r}image({text:r}){return""+r}br(){return""}checkbox({raw:r}){return r}},m=class X{options;renderer;textRenderer;constructor(e){this.options=e||A,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 re}static parse(e,t){return new X(t).parse(e)}static parseInline(e,t){return new X(t).parseInline(e)}parse(e){this.renderer.parser=this;let t="";for(let s=0;s<e.length;s++){let n=e[s];if(this.options.extensions?.renderers?.[n.type]){let a=n,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)){t+=l||"";continue}}let i=n;switch(i.type){case"space":{t+=this.renderer.space(i);break}case"hr":{t+=this.renderer.hr(i);break}case"heading":{t+=this.renderer.heading(i);break}case"code":{t+=this.renderer.code(i);break}case"table":{t+=this.renderer.table(i);break}case"blockquote":{t+=this.renderer.blockquote(i);break}case"list":{t+=this.renderer.list(i);break}case"checkbox":{t+=this.renderer.checkbox(i);break}case"html":{t+=this.renderer.html(i);break}case"def":{t+=this.renderer.def(i);break}case"paragraph":{t+=this.renderer.paragraph(i);break}case"text":{t+=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 t}parseInline(e,t=this.renderer){this.renderer.parser=this;let s="";for(let n=0;n<e.length;n++){let i=e[n];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+=t.text(a);break}case"html":{s+=t.html(a);break}case"link":{s+=t.link(a);break}case"image":{s+=t.image(a);break}case"checkbox":{s+=t.checkbox(a);break}case"strong":{s+=t.strong(a);break}case"em":{s+=t.em(a);break}case"codespan":{s+=t.codespan(a);break}case"br":{s+=t.br(a);break}case"del":{s+=t.del(a);break}case"text":{s+=t.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}},E=class{options;block;constructor(r){this.options=r||A}static passThroughHooks=new Set(["preprocess","postprocess","processAllTokens","emStrongMask"]);static passThroughHooksRespectAsync=new Set(["preprocess","postprocess","processAllTokens"]);preprocess(r){return r}postprocess(r){return r}processAllTokens(r){return r}emStrongMask(r){return r}provideLexer(r=this.block){return r?w.lex:w.lexInline}provideParser(r=this.block){return r?m.parse:m.parseInline}},ot=class{defaults=U();options=this.setOptions;parse=this.parseMarkdown(!0);parseInline=this.parseMarkdown(!1);Parser=m;Renderer=N;TextRenderer=re;Lexer=w;Tokenizer=Q;Hooks=E;constructor(...r){this.use(...r)}walkTokens(r,e){let t=[];for(let s of r)switch(t=t.concat(e.call(this,s)),s.type){case"table":{let n=s;for(let i of n.header)t=t.concat(this.walkTokens(i.tokens,e));for(let i of n.rows)for(let a of i)t=t.concat(this.walkTokens(a.tokens,e));break}case"list":{let n=s;t=t.concat(this.walkTokens(n.items,e));break}default:{let n=s;this.defaults.extensions?.childTokens?.[n.type]?this.defaults.extensions.childTokens[n.type].forEach(i=>{let a=n[i].flat(1/0);t=t.concat(this.walkTokens(a,e))}):n.tokens&&(t=t.concat(this.walkTokens(n.tokens,e)))}}return t}use(...r){let e=this.defaults.extensions||{renderers:{},childTokens:{}};return r.forEach(t=>{let s={...t};if(s.async=this.defaults.async||s.async||!1,t.extensions&&(t.extensions.forEach(n=>{if(!n.name)throw new Error("extension name required");if("renderer"in n){let i=e.renderers[n.name];i?e.renderers[n.name]=function(...a){let l=n.renderer.apply(this,a);return l===!1&&(l=i.apply(this,a)),l}:e.renderers[n.name]=n.renderer}if("tokenizer"in n){if(!n.level||n.level!=="block"&&n.level!=="inline")throw new Error("extension level must be \'block\' or \'inline\'");let i=e[n.level];i?i.unshift(n.tokenizer):e[n.level]=[n.tokenizer],n.start&&(n.level==="block"?e.startBlock?e.startBlock.push(n.start):e.startBlock=[n.start]:n.level==="inline"&&(e.startInline?e.startInline.push(n.start):e.startInline=[n.start]))}"childTokens"in n&&n.childTokens&&(e.childTokens[n.name]=n.childTokens)}),s.extensions=e),t.renderer){let n=this.defaults.renderer||new N(this.defaults);for(let i in t.renderer){if(!(i in n))throw new Error(`renderer \'${i}\' does not exist`);if(["options","parser"].includes(i))continue;let a=i,l=t.renderer[a],o=n[a];n[a]=(...c)=>{let p=l.apply(n,c);return p===!1&&(p=o.apply(n,c)),p||""}}s.renderer=n}if(t.tokenizer){let n=this.defaults.tokenizer||new Q(this.defaults);for(let i in t.tokenizer){if(!(i in n))throw new Error(`tokenizer \'${i}\' does not exist`);if(["options","rules","lexer"].includes(i))continue;let a=i,l=t.tokenizer[a],o=n[a];n[a]=(...c)=>{let p=l.apply(n,c);return p===!1&&(p=o.apply(n,c)),p}}s.tokenizer=n}if(t.hooks){let n=this.defaults.hooks||new E;for(let i in t.hooks){if(!(i in n))throw new Error(`hook \'${i}\' does not exist`);if(["options","block"].includes(i))continue;let a=i,l=t.hooks[a],o=n[a];E.passThroughHooks.has(i)?n[a]=c=>{if(this.defaults.async&&E.passThroughHooksRespectAsync.has(i))return(async()=>{let h=await l.call(n,c);return o.call(n,h)})();let p=l.call(n,c);return o.call(n,p)}:n[a]=(...c)=>{if(this.defaults.async)return(async()=>{let h=await l.apply(n,c);return h===!1&&(h=await o.apply(n,c)),h})();let p=l.apply(n,c);return p===!1&&(p=o.apply(n,c)),p}}s.hooks=n}if(t.walkTokens){let n=this.defaults.walkTokens,i=t.walkTokens;s.walkTokens=function(a){let l=[];return l.push(i.call(this,a)),n&&(l=l.concat(n.call(this,a))),l}}this.defaults={...this.defaults,...s}}),this}setOptions(r){return this.defaults={...this.defaults,...r},this}lexer(r,e){return w.lex(r,e??this.defaults)}parser(r,e){return m.parse(r,e??this.defaults)}parseMarkdown(r){return(e,t)=>{let s={...t},n={...this.defaults,...s},i=this.onError(!!n.silent,!!n.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(n.hooks&&(n.hooks.options=n,n.hooks.block=r),n.async)return(async()=>{let a=n.hooks?await n.hooks.preprocess(e):e,l=await(n.hooks?await n.hooks.provideLexer(r):r?w.lex:w.lexInline)(a,n),o=n.hooks?await n.hooks.processAllTokens(l):l;n.walkTokens&&await Promise.all(this.walkTokens(o,n.walkTokens));let c=await(n.hooks?await n.hooks.provideParser(r):r?m.parse:m.parseInline)(o,n);return n.hooks?await n.hooks.postprocess(c):c})().catch(i);try{n.hooks&&(e=n.hooks.preprocess(e));let a=(n.hooks?n.hooks.provideLexer(r):r?w.lex:w.lexInline)(e,n);n.hooks&&(a=n.hooks.processAllTokens(a)),n.walkTokens&&this.walkTokens(a,n.walkTokens);let l=(n.hooks?n.hooks.provideParser(r):r?m.parse:m.parseInline)(a,n);return n.hooks&&(l=n.hooks.postprocess(l)),l}catch(a){return i(a)}}}onError(r,e){return t=>{if(t.message+=`\nPlease report this to https://github.com/markedjs/marked.`,r){let s="<p>An error occurred:</p><pre>"+y(t.message+"",!0)+"</pre>";return e?Promise.resolve(s):s}if(e)return Promise.reject(t);throw t}}},z=new ot;function k(r,e){return z.parse(r,e)}k.options=k.setOptions=function(r){return z.setOptions(r),k.defaults=z.defaults,he(k.defaults),k};k.getDefaults=U;k.defaults=A;k.use=function(...r){return z.use(...r),k.defaults=z.defaults,he(k.defaults),k};k.walkTokens=function(r,e){return z.walkTokens(r,e)};k.parseInline=z.parseInline;k.Parser=m;k.parser=m.parse;k.Renderer=N;k.TextRenderer=re;k.Lexer=w;k.lexer=w.lex;k.Tokenizer=Q;k.Hooks=E;k.parse=k;var ut=k.options,gt=k.setOptions,kt=k.use,ft=k.walkTokens,dt=k.parseInline;var xt=m.parse,bt=w.lex;var ct=0;function ht(r){if(typeof r!="string"||typeof performance.mark!="function"||typeof performance.measure!="function")return null;let e=ct++,t={name:r,startMark:`${r}:start:${e}`,endMark:`${r}:end:${e}`};try{return performance.mark(t.startMark),t}catch{return null}}function pt(r){if(r)try{performance.mark(r.endMark),performance.measure(r.name,r.startMark,r.endMark)}catch{}finally{try{performance.clearMarks?.(r.startMark),performance.clearMarks?.(r.endMark)}catch{}}}k.use({extensions:[{name:"blockMath",level:"block",start(r){return r.match(/^ {0,3}\\$\\$/m)?.index},tokenizer(r){let e=/^ {0,3}\\$\\$([\\s\\S]+?)\\$\\$[ \\t]*(?:\\n|$)/.exec(r);if(e)return{type:"blockMath",raw:e[0],text:e[1].trim()}},renderer(r){return r.raw}},{name:"inlineMath",level:"inline",start(r){return r.match(/(?<![\\\\$])\\$(?![$\\s])/)?.index},tokenizer(r){let e=/^\\$(?![$\\s\\d])((?:\\\\\\$|[^$\\n])*?)(?<!\\s)\\$(?!\\d)/.exec(r);if(e)return{type:"inlineMath",raw:e[0],text:e[1].trim()}},renderer(r){return r.raw}}]});var P=new Map;self.onmessage=r=>{let e=r.data;if(typeof e!="object"||e===null)return;let{id:t,text:s,append:n,expectedLength:i,oldRaws:a,instance:l,baseVersion:o,dispose:c,userTimingName:p}=e;if(c===!0){typeof l=="string"&&P.delete(l);return}let h=typeof l=="string"?l:null,u=typeof o=="number"?o:null,x,f=null;if(typeof n=="string"){if(h===null||u===null){self.postMessage({id:t,needResync:!0});return}let d=P.get(h);if(!d||d.version!==u){self.postMessage({id:t,needResync:!0});return}if(x=d.source+n,typeof i=="number"&&x.length!==i){P.delete(h),self.postMessage({id:t,needResync:!0});return}f=d.raws}else if(typeof s=="string"){if(x=s,Array.isArray(a))f=a;else if(h!==null&&u!==null){let d=P.get(h);if(d&&d.version===u)f=d.raws;else{self.postMessage({id:t,needResync:!0});return}}}else return;try{let d=typeof p=="string"?ht(p):null,B=performance.now(),$;try{$=k.lexer(x)}finally{d&&pt(d)}let q=performance.now()-B,R=0;if(f){let v=Math.min(f.length,$.length);for(;R<v&&f[R]===$[R].raw;R++);}h!==null&&u!==null&&P.set(h,{version:u+1,raws:$.map(v=>v.raw),source:x}),self.postMessage({id:t,matchLen:R,tail:$.slice(R),lexerMs:q,sourceCharsLexed:x.length})}catch(d){h!==null&&P.delete(h),self.postMessage({id:t,error:String(d)})}};})();\n';
|
|
408
429
|
|
|
409
430
|
// src/Markdown.ts
|
|
410
431
|
var now = () => typeof performance !== "undefined" && typeof performance.now === "function" ? performance.now() : Date.now();
|
|
@@ -419,6 +440,27 @@ function lexMarkdown(text, userTiming) {
|
|
|
419
440
|
}
|
|
420
441
|
marked.use({
|
|
421
442
|
extensions: [
|
|
443
|
+
{
|
|
444
|
+
name: "blockMath",
|
|
445
|
+
level: "block",
|
|
446
|
+
start(src) {
|
|
447
|
+
return src.match(/^ {0,3}\$\$/m)?.index;
|
|
448
|
+
},
|
|
449
|
+
tokenizer(src) {
|
|
450
|
+
const match = /^ {0,3}\$\$([\s\S]+?)\$\$[ \t]*(?:\n|$)/.exec(src);
|
|
451
|
+
if (match) {
|
|
452
|
+
return {
|
|
453
|
+
type: "blockMath",
|
|
454
|
+
raw: match[0],
|
|
455
|
+
text: match[1].trim()
|
|
456
|
+
};
|
|
457
|
+
}
|
|
458
|
+
return void 0;
|
|
459
|
+
},
|
|
460
|
+
renderer(token) {
|
|
461
|
+
return token.raw;
|
|
462
|
+
}
|
|
463
|
+
},
|
|
422
464
|
{
|
|
423
465
|
name: "inlineMath",
|
|
424
466
|
level: "inline",
|
|
@@ -442,23 +484,191 @@ marked.use({
|
|
|
442
484
|
}
|
|
443
485
|
]
|
|
444
486
|
});
|
|
445
|
-
var
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
487
|
+
var mathConverter = null;
|
|
488
|
+
var mathLoad = null;
|
|
489
|
+
function interop(mod, key) {
|
|
490
|
+
const ns = mod;
|
|
491
|
+
if (typeof ns?.[key] !== "undefined") return ns;
|
|
492
|
+
const fallback = ns?.default;
|
|
493
|
+
if (fallback && typeof fallback[key] !== "undefined") return fallback;
|
|
494
|
+
throw new Error(`mathjax-full module is missing export "${key}"`);
|
|
495
|
+
}
|
|
496
|
+
function preloadMathJax() {
|
|
497
|
+
if (mathLoad) return mathLoad;
|
|
498
|
+
mathLoad = (async () => {
|
|
499
|
+
const [mathjaxMod, texMod, svgMod, adaptorMod, handlerMod, packagesMod] = await Promise.all([
|
|
500
|
+
import("mathjax-full/js/mathjax.js"),
|
|
501
|
+
import("mathjax-full/js/input/tex.js"),
|
|
502
|
+
import("mathjax-full/js/output/svg.js"),
|
|
503
|
+
import("mathjax-full/js/adaptors/liteAdaptor.js"),
|
|
504
|
+
import("mathjax-full/js/handlers/html.js"),
|
|
505
|
+
import("mathjax-full/js/input/tex/AllPackages.js")
|
|
506
|
+
]);
|
|
507
|
+
const { mathjax } = interop(mathjaxMod, "mathjax");
|
|
508
|
+
const { TeX } = interop(texMod, "TeX");
|
|
509
|
+
const { SVG } = interop(svgMod, "SVG");
|
|
510
|
+
const { liteAdaptor } = interop(adaptorMod, "liteAdaptor");
|
|
511
|
+
const { RegisterHTMLHandler } = interop(handlerMod, "RegisterHTMLHandler");
|
|
512
|
+
const { AllPackages } = interop(packagesMod, "AllPackages");
|
|
513
|
+
const adaptor = liteAdaptor();
|
|
514
|
+
RegisterHTMLHandler(adaptor);
|
|
515
|
+
const tex = new TeX({ packages: AllPackages });
|
|
516
|
+
const svg = new SVG({ fontCache: "local" });
|
|
517
|
+
const htmlMathJax = mathjax.document("", { InputJax: tex, OutputJax: svg });
|
|
518
|
+
mathConverter = (formula, displayMode, color) => convertMathToSVGDataURI(
|
|
519
|
+
formula,
|
|
520
|
+
displayMode,
|
|
521
|
+
(f, d) => adaptor.innerHTML(htmlMathJax.convert(f, { display: d })),
|
|
522
|
+
color
|
|
523
|
+
);
|
|
524
|
+
})().catch((e) => {
|
|
525
|
+
console.error("MathJax failed to load; formulas will render as TeX source", e);
|
|
526
|
+
});
|
|
527
|
+
return mathLoad;
|
|
528
|
+
}
|
|
529
|
+
function isMathJaxReady() {
|
|
530
|
+
return mathConverter !== null;
|
|
531
|
+
}
|
|
532
|
+
var EX_PER_EM = 0.4421;
|
|
533
|
+
function exToPx(ex, fontSize) {
|
|
534
|
+
return ex * fontSize * EX_PER_EM;
|
|
535
|
+
}
|
|
536
|
+
function fontSizeFromFont(font) {
|
|
537
|
+
const pxIndex = font.indexOf("px");
|
|
538
|
+
if (pxIndex <= 0) return void 0;
|
|
539
|
+
let start = pxIndex;
|
|
540
|
+
while (start > 0) {
|
|
541
|
+
const ch = font[start - 1];
|
|
542
|
+
if (ch >= "0" && ch <= "9" || ch === ".") start--;
|
|
543
|
+
else break;
|
|
544
|
+
}
|
|
545
|
+
if (start === pxIndex) return void 0;
|
|
546
|
+
const size = parseFloat(font.slice(start, pxIndex));
|
|
547
|
+
return Number.isFinite(size) ? size : void 0;
|
|
548
|
+
}
|
|
549
|
+
var mathCache = /* @__PURE__ */ new Map();
|
|
550
|
+
var MATH_CACHE_LIMIT = 256;
|
|
551
|
+
var inlineMathRasters = /* @__PURE__ */ new Map();
|
|
552
|
+
var inlineMathRasterWaiters = /* @__PURE__ */ new Set();
|
|
553
|
+
function ensureInlineMathRaster(uri) {
|
|
554
|
+
const existing = inlineMathRasters.get(uri);
|
|
555
|
+
if (existing) return existing;
|
|
556
|
+
const entry = { decoded: false };
|
|
557
|
+
inlineMathRasters.set(uri, entry);
|
|
558
|
+
if (typeof globalThis.Image !== "undefined") {
|
|
559
|
+
const bitmap = new globalThis.Image();
|
|
560
|
+
bitmap.onload = () => {
|
|
561
|
+
entry.decoded = true;
|
|
562
|
+
for (const notify of inlineMathRasterWaiters) notify();
|
|
563
|
+
};
|
|
564
|
+
bitmap.src = uri;
|
|
565
|
+
entry.bitmap = bitmap;
|
|
566
|
+
}
|
|
567
|
+
return entry;
|
|
568
|
+
}
|
|
569
|
+
function paintInlineMath(uri, surface, box) {
|
|
570
|
+
const raster = ensureInlineMathRaster(uri);
|
|
571
|
+
if (!raster.decoded || !raster.bitmap) return;
|
|
572
|
+
surface.drawImage(raster.bitmap, box.x, box.y, box.width, box.height);
|
|
573
|
+
}
|
|
574
|
+
var MATH_LANGS = /* @__PURE__ */ new Set(["math", "latex", "tex"]);
|
|
575
|
+
function containsInlineMath(token) {
|
|
576
|
+
if (token.type === "inlineMath") return true;
|
|
577
|
+
const anyToken = token;
|
|
578
|
+
if (Array.isArray(anyToken.tokens) && anyToken.tokens.some(containsInlineMath)) {
|
|
579
|
+
return true;
|
|
580
|
+
}
|
|
581
|
+
if (Array.isArray(anyToken.items) && anyToken.items.some(containsInlineMath)) {
|
|
582
|
+
return true;
|
|
583
|
+
}
|
|
584
|
+
if (Array.isArray(anyToken.header) && anyToken.header.some(containsInlineMath)) {
|
|
585
|
+
return true;
|
|
586
|
+
}
|
|
587
|
+
if (Array.isArray(anyToken.rows)) {
|
|
588
|
+
for (const row of anyToken.rows) {
|
|
589
|
+
if (Array.isArray(row) && row.some(containsInlineMath)) return true;
|
|
590
|
+
}
|
|
591
|
+
}
|
|
592
|
+
return false;
|
|
593
|
+
}
|
|
594
|
+
var FENCE_OPEN_RE = /^ {0,3}(`{3,}|~{3,})/;
|
|
595
|
+
var FENCE_CLOSE_RE = /^ {0,3}(`+|~+)[ \t]*$/;
|
|
596
|
+
function isFenceClosed(raw) {
|
|
597
|
+
const lines = raw.split("\n");
|
|
598
|
+
const open = FENCE_OPEN_RE.exec(lines[0]);
|
|
599
|
+
if (!open) return false;
|
|
600
|
+
const marker = open[1][0];
|
|
601
|
+
const minLen = open[1].length;
|
|
602
|
+
for (let i = 1; i < lines.length; i++) {
|
|
603
|
+
const close = FENCE_CLOSE_RE.exec(lines[i]);
|
|
604
|
+
if (close && close[1][0] === marker && close[1].length >= minLen) return true;
|
|
605
|
+
}
|
|
606
|
+
return false;
|
|
607
|
+
}
|
|
608
|
+
function paragraphHasImage(token) {
|
|
609
|
+
return token.tokens?.some((child) => child.type === "image") === true;
|
|
610
|
+
}
|
|
611
|
+
function lastIndexOfImage(tokens) {
|
|
612
|
+
for (let i = tokens.length - 1; i >= 0; i--) {
|
|
613
|
+
if (tokens[i].type === "image") return i;
|
|
614
|
+
}
|
|
615
|
+
return -1;
|
|
616
|
+
}
|
|
617
|
+
function expectedImageParagraphChildren(tokens) {
|
|
618
|
+
let children = 0;
|
|
619
|
+
let inTextRun = false;
|
|
620
|
+
for (const token of tokens) {
|
|
621
|
+
if (token.type === "image") {
|
|
622
|
+
children++;
|
|
623
|
+
inTextRun = false;
|
|
624
|
+
} else if (!inTextRun) {
|
|
625
|
+
children++;
|
|
626
|
+
inTextRun = true;
|
|
627
|
+
}
|
|
628
|
+
}
|
|
629
|
+
return children;
|
|
630
|
+
}
|
|
631
|
+
function rendersAsMath(token) {
|
|
632
|
+
return MATH_LANGS.has((token.lang ?? "").toLowerCase()) && token.text.trim() !== "" && isFenceClosed(token.raw);
|
|
633
|
+
}
|
|
634
|
+
function renderMathToSVGDataURI(formula, displayMode, color) {
|
|
635
|
+
const key = `${displayMode ? 1 : 0}\0${color}\0${formula}`;
|
|
636
|
+
const hit = mathCache.get(key);
|
|
637
|
+
if (hit) return hit;
|
|
638
|
+
if (!mathConverter) return null;
|
|
639
|
+
const converted = mathConverter(formula, displayMode, color);
|
|
640
|
+
if (converted) {
|
|
641
|
+
if (mathCache.size >= MATH_CACHE_LIMIT) {
|
|
642
|
+
const oldest = mathCache.keys().next().value;
|
|
643
|
+
if (oldest !== void 0) mathCache.delete(oldest);
|
|
644
|
+
}
|
|
645
|
+
mathCache.set(key, converted);
|
|
646
|
+
}
|
|
647
|
+
return converted;
|
|
648
|
+
}
|
|
649
|
+
function applyMathColor(svg, color) {
|
|
650
|
+
const openTag = svg.match(/<svg\b[^>]*>/);
|
|
651
|
+
if (!openTag) return svg;
|
|
652
|
+
const tag = openTag[0];
|
|
653
|
+
const colored = /\bstyle="/.test(tag) ? tag.replace(/\bstyle="/, `style="color:${color};`) : tag.replace(/^<svg\b/, `<svg style="color:${color}"`);
|
|
654
|
+
return svg.replace(tag, colored);
|
|
655
|
+
}
|
|
656
|
+
function convertMathToSVGDataURI(formula, displayMode, typeset, color) {
|
|
451
657
|
try {
|
|
452
|
-
const
|
|
453
|
-
const svgString = adaptor.innerHTML(node);
|
|
658
|
+
const svgString = applyMathColor(typeset(formula, displayMode), color);
|
|
454
659
|
const wMatch = svgString.match(/width="([^"]+)ex"/);
|
|
455
660
|
const hMatch = svgString.match(/height="([^"]+)ex"/);
|
|
456
661
|
const wEx = wMatch ? parseFloat(wMatch[1]) : 10;
|
|
457
662
|
const hEx = hMatch ? parseFloat(hMatch[1]) : 2;
|
|
458
|
-
const
|
|
459
|
-
const
|
|
663
|
+
const vMatch = svgString.match(/vertical-align:\s*(-?[\d.]+)ex/);
|
|
664
|
+
const depthEx = vMatch ? Math.max(0, -parseFloat(vMatch[1])) : 0;
|
|
460
665
|
const base64 = btoa(unescape(encodeURIComponent(svgString)));
|
|
461
|
-
return {
|
|
666
|
+
return {
|
|
667
|
+
uri: `data:image/svg+xml;base64,${base64}`,
|
|
668
|
+
widthEx: wEx,
|
|
669
|
+
heightEx: hEx,
|
|
670
|
+
depthEx
|
|
671
|
+
};
|
|
462
672
|
} catch (e) {
|
|
463
673
|
console.error("MathJax error", e);
|
|
464
674
|
return null;
|
|
@@ -473,6 +683,7 @@ function runSyncFallback(entry) {
|
|
|
473
683
|
entry.cb(0, lexMarkdown(entry.text, entry.userTiming), true);
|
|
474
684
|
} catch (err) {
|
|
475
685
|
console.warn("Markdown sync fallback parse failed", err);
|
|
686
|
+
entry.onDropped?.();
|
|
476
687
|
}
|
|
477
688
|
}
|
|
478
689
|
if (typeof Worker !== "undefined") {
|
|
@@ -998,13 +1209,13 @@ function codeAtlas() {
|
|
|
998
1209
|
function decodeEntities(text) {
|
|
999
1210
|
return text.replace(/</g, "<").replace(/>/g, ">").replace(/"/g, '"').replace(/'/g, "'").replace(/&/g, "&");
|
|
1000
1211
|
}
|
|
1001
|
-
function collectSpans(tokens, inherited, theme, out) {
|
|
1212
|
+
function collectSpans(tokens, inherited, theme, out, blockFontSize) {
|
|
1002
1213
|
for (const token of tokens) {
|
|
1003
1214
|
switch (token.type) {
|
|
1004
1215
|
case "strong": {
|
|
1005
1216
|
const t = token;
|
|
1006
1217
|
if (t.tokens) {
|
|
1007
|
-
collectSpans(t.tokens, { ...inherited, bold: true }, theme, out);
|
|
1218
|
+
collectSpans(t.tokens, { ...inherited, bold: true }, theme, out, blockFontSize);
|
|
1008
1219
|
} else {
|
|
1009
1220
|
out.push({
|
|
1010
1221
|
text: decodeEntities(t.text),
|
|
@@ -1016,7 +1227,7 @@ function collectSpans(tokens, inherited, theme, out) {
|
|
|
1016
1227
|
case "em": {
|
|
1017
1228
|
const t = token;
|
|
1018
1229
|
if (t.tokens) {
|
|
1019
|
-
collectSpans(t.tokens, { ...inherited, italic: true }, theme, out);
|
|
1230
|
+
collectSpans(t.tokens, { ...inherited, italic: true }, theme, out, blockFontSize);
|
|
1020
1231
|
} else {
|
|
1021
1232
|
out.push({
|
|
1022
1233
|
text: decodeEntities(t.text),
|
|
@@ -1052,10 +1263,32 @@ function collectSpans(tokens, inherited, theme, out) {
|
|
|
1052
1263
|
}
|
|
1053
1264
|
case "inlineMath": {
|
|
1054
1265
|
const t = token;
|
|
1055
|
-
|
|
1056
|
-
|
|
1057
|
-
|
|
1058
|
-
|
|
1266
|
+
const runSize = inherited.fontSize ?? blockFontSize ?? theme.fontSize;
|
|
1267
|
+
const runColor = inherited.color ?? theme.textColor;
|
|
1268
|
+
const rendered = renderMathToSVGDataURI(t.text, false, runColor);
|
|
1269
|
+
if (rendered) {
|
|
1270
|
+
const uri = rendered.uri;
|
|
1271
|
+
out.push({
|
|
1272
|
+
text: OBJECT_REPLACEMENT,
|
|
1273
|
+
style: inherited,
|
|
1274
|
+
object: {
|
|
1275
|
+
width: exToPx(rendered.widthEx, runSize),
|
|
1276
|
+
height: exToPx(rendered.heightEx, runSize),
|
|
1277
|
+
depth: exToPx(rendered.depthEx, runSize),
|
|
1278
|
+
// The TeX source is the accessible name: without it a screen reader
|
|
1279
|
+
// receives only the invisible U+FFFC sentinel.
|
|
1280
|
+
alt: t.text,
|
|
1281
|
+
// Without this the box is reserved and stays empty. The engine does
|
|
1282
|
+
// not draw objects, and nothing else in the tree holds the raster.
|
|
1283
|
+
paint: (surface, box) => paintInlineMath(uri, surface, box)
|
|
1284
|
+
}
|
|
1285
|
+
});
|
|
1286
|
+
} else {
|
|
1287
|
+
out.push({
|
|
1288
|
+
text: decodeEntities(t.raw),
|
|
1289
|
+
style: { ...inherited, color: "#fcd34d" }
|
|
1290
|
+
});
|
|
1291
|
+
}
|
|
1059
1292
|
break;
|
|
1060
1293
|
}
|
|
1061
1294
|
case "link": {
|
|
@@ -1066,7 +1299,7 @@ function collectSpans(tokens, inherited, theme, out) {
|
|
|
1066
1299
|
color: "#38bdf8"
|
|
1067
1300
|
};
|
|
1068
1301
|
if (t.tokens && t.tokens.length > 0) {
|
|
1069
|
-
collectSpans(t.tokens, linkStyle, theme, out);
|
|
1302
|
+
collectSpans(t.tokens, linkStyle, theme, out, blockFontSize);
|
|
1070
1303
|
} else {
|
|
1071
1304
|
out.push({ text: decodeEntities(t.text), style: linkStyle });
|
|
1072
1305
|
}
|
|
@@ -1075,7 +1308,7 @@ function collectSpans(tokens, inherited, theme, out) {
|
|
|
1075
1308
|
case "text": {
|
|
1076
1309
|
const t = token;
|
|
1077
1310
|
if ("tokens" in t && t.tokens?.length) {
|
|
1078
|
-
collectSpans(t.tokens, inherited, theme, out);
|
|
1311
|
+
collectSpans(t.tokens, inherited, theme, out, blockFontSize);
|
|
1079
1312
|
} else {
|
|
1080
1313
|
const decoded = decodeEntities(t.text);
|
|
1081
1314
|
if (decoded) {
|
|
@@ -1098,10 +1331,37 @@ function collectSpans(tokens, inherited, theme, out) {
|
|
|
1098
1331
|
}
|
|
1099
1332
|
}
|
|
1100
1333
|
}
|
|
1334
|
+
function findUnclosedInline(text) {
|
|
1335
|
+
let best = null;
|
|
1336
|
+
const tick = text.lastIndexOf("`");
|
|
1337
|
+
if (tick !== -1 && tick < text.length - 1) {
|
|
1338
|
+
return { kind: "codespan", at: tick, contentAt: tick + 1 };
|
|
1339
|
+
}
|
|
1340
|
+
if (tick !== -1) return null;
|
|
1341
|
+
const emphasis = /(\*{1,2}(?!\*)|_{1,2}(?!_))(?=[^\s])/g;
|
|
1342
|
+
for (let match = emphasis.exec(text); match !== null; match = emphasis.exec(text)) {
|
|
1343
|
+
const marker = match[1];
|
|
1344
|
+
const at = match.index;
|
|
1345
|
+
if (marker[0] === "_" && at > 0 && /[\w]/.test(text[at - 1])) continue;
|
|
1346
|
+
best = {
|
|
1347
|
+
kind: marker.length === 2 ? "strong" : "em",
|
|
1348
|
+
at,
|
|
1349
|
+
contentAt: at + marker.length
|
|
1350
|
+
};
|
|
1351
|
+
}
|
|
1352
|
+
const bracket = text.lastIndexOf("[");
|
|
1353
|
+
if (bracket !== -1 && bracket < text.length - 1 && (best === null || bracket > best.at)) {
|
|
1354
|
+
const closed = /\]\([^)]*\)/.test(text.slice(bracket));
|
|
1355
|
+
if (!closed) {
|
|
1356
|
+
best = { kind: "link", at: bracket, contentAt: bracket + 1 };
|
|
1357
|
+
}
|
|
1358
|
+
}
|
|
1359
|
+
return best;
|
|
1360
|
+
}
|
|
1101
1361
|
function renderInlineToRichText(tokens, fallbackText, font, color, maxWidth, theme, selectable, onLinkClick) {
|
|
1102
1362
|
const spans = [];
|
|
1103
1363
|
if (tokens && tokens.length > 0) {
|
|
1104
|
-
collectSpans(tokens, {}, theme, spans);
|
|
1364
|
+
collectSpans(tokens, {}, theme, spans, fontSizeFromFont(font));
|
|
1105
1365
|
}
|
|
1106
1366
|
if (spans.length === 0) {
|
|
1107
1367
|
spans.push({ text: decodeEntities(fallbackText) });
|
|
@@ -1133,6 +1393,51 @@ var Markdown = class extends UIComponent {
|
|
|
1133
1393
|
onLayoutUpdated;
|
|
1134
1394
|
rawMarkdown;
|
|
1135
1395
|
streamController = null;
|
|
1396
|
+
/**
|
|
1397
|
+
* Trailing-unclosed-syntax policy of the active stream, or `'literal'` when no
|
|
1398
|
+
* stream is open.
|
|
1399
|
+
*
|
|
1400
|
+
* Held here rather than read back off the controller because it is a rendering
|
|
1401
|
+
* concern: `StreamController` owns buffering and pacing and has no view of the
|
|
1402
|
+
* entity tree, while the guess is a transform applied where spans are built.
|
|
1403
|
+
*/
|
|
1404
|
+
streamIncompleteMode = "literal";
|
|
1405
|
+
/** End-of-stream callback of the active stream, if it supplied one. */
|
|
1406
|
+
streamOnStable = null;
|
|
1407
|
+
/**
|
|
1408
|
+
* The trailing paragraph entity currently showing an optimistic guess, plus the
|
|
1409
|
+
* token it was rendered from.
|
|
1410
|
+
*
|
|
1411
|
+
* Both halves are needed. The entity is what must be re-rendered to drop the
|
|
1412
|
+
* guess; the token is what it must be re-rendered FROM, and it is the only
|
|
1413
|
+
* copy — `this.tokens` has already moved on by the time an unwind is decided.
|
|
1414
|
+
* `null` means no guess is live, which is the state every `'literal'` stream
|
|
1415
|
+
* and every closed stream stays in.
|
|
1416
|
+
*/
|
|
1417
|
+
optimisticTail = null;
|
|
1418
|
+
/** Resolvers waiting for every in-flight worker append to have been applied. */
|
|
1419
|
+
appendSettledWaiters = [];
|
|
1420
|
+
/** True only inside an `onStable` callback, to reject reentrant mutation. */
|
|
1421
|
+
inStableCallback = false;
|
|
1422
|
+
/** Set by {@link destroy} so late settlement work skips a torn-down tree. */
|
|
1423
|
+
isDestroyed = false;
|
|
1424
|
+
/**
|
|
1425
|
+
* This instance's entry in {@link inlineMathRasterWaiters}, or `undefined` if it
|
|
1426
|
+
* has never rendered inline math.
|
|
1427
|
+
*
|
|
1428
|
+
* Subscribed lazily so a document without formulas costs nothing, and held as a
|
|
1429
|
+
* field only so {@link destroy} can remove the exact closure it added.
|
|
1430
|
+
*/
|
|
1431
|
+
inlineMathRepaint;
|
|
1432
|
+
/**
|
|
1433
|
+
* True while this document is waiting on the lazy MathJax load.
|
|
1434
|
+
*
|
|
1435
|
+
* Tracked per instance rather than read off the module state because it also
|
|
1436
|
+
* gates settlement: `await close()` and `onStable` must not resolve while a
|
|
1437
|
+
* formula is still showing TeX source, or a caller doing expensive one-time
|
|
1438
|
+
* work on a "final" document would measure and export placeholder boxes.
|
|
1439
|
+
*/
|
|
1440
|
+
mathLoadPending = false;
|
|
1136
1441
|
_userTiming;
|
|
1137
1442
|
tokens = [];
|
|
1138
1443
|
// At most one worker lex request in flight at a time. Required for the
|
|
@@ -1290,21 +1595,44 @@ var Markdown = class extends UIComponent {
|
|
|
1290
1595
|
{
|
|
1291
1596
|
append: (chunk) => this.appendMarkdownCore(chunk),
|
|
1292
1597
|
release: (released) => {
|
|
1293
|
-
if (this.streamController
|
|
1598
|
+
if (this.streamController !== released) return;
|
|
1599
|
+
this.streamController = null;
|
|
1600
|
+
this.streamIncompleteMode = "literal";
|
|
1601
|
+
this.streamOnStable = null;
|
|
1602
|
+
this.unwindOptimisticTail();
|
|
1603
|
+
},
|
|
1604
|
+
onClose: async () => {
|
|
1605
|
+
await this.waitForAppendSettled();
|
|
1606
|
+
if (this.isDestroyed) return;
|
|
1607
|
+
this.unwindOptimisticTail();
|
|
1608
|
+
const onStable = this.streamOnStable;
|
|
1609
|
+
if (!onStable) return;
|
|
1610
|
+
this.inStableCallback = true;
|
|
1611
|
+
try {
|
|
1612
|
+
onStable(Array.from(this.content.children));
|
|
1613
|
+
} finally {
|
|
1614
|
+
this.inStableCallback = false;
|
|
1615
|
+
}
|
|
1294
1616
|
}
|
|
1295
1617
|
},
|
|
1296
1618
|
options
|
|
1297
1619
|
);
|
|
1298
|
-
if (controller.state === "open")
|
|
1620
|
+
if (controller.state === "open") {
|
|
1621
|
+
this.streamController = controller;
|
|
1622
|
+
this.streamIncompleteMode = options.incompleteMode ?? "literal";
|
|
1623
|
+
this.streamOnStable = options.onStable ?? null;
|
|
1624
|
+
}
|
|
1299
1625
|
return controller;
|
|
1300
1626
|
}
|
|
1301
1627
|
/** Replace all markdown content (full rebuild). */
|
|
1302
1628
|
setContent(markdown) {
|
|
1629
|
+
this.assertNotInStableCallback("setContent");
|
|
1303
1630
|
this.streamController?.abort(new Error("Markdown content was replaced"));
|
|
1304
1631
|
for (const id of this.pendingWorkerIds) workerCallbacks.delete(id);
|
|
1305
1632
|
this.pendingWorkerIds.clear();
|
|
1306
1633
|
this.appendInFlight = false;
|
|
1307
1634
|
this.appendPending = false;
|
|
1635
|
+
this.flushAppendSettledWaiters();
|
|
1308
1636
|
this.rawMarkdown = markdown;
|
|
1309
1637
|
this.workerSourceLen = 0;
|
|
1310
1638
|
while (this.content.children.length > 0) {
|
|
@@ -1320,12 +1648,35 @@ var Markdown = class extends UIComponent {
|
|
|
1320
1648
|
* the whole subtree alive until the worker replied), then recurse into the
|
|
1321
1649
|
* content subtree via `super.destroy()` so every block's resources are freed.
|
|
1322
1650
|
*/
|
|
1651
|
+
/**
|
|
1652
|
+
* Repaint this document when an inline formula's raster finishes decoding.
|
|
1653
|
+
*
|
|
1654
|
+
* Idempotent — called on every render of a math-bearing token, and the set holds
|
|
1655
|
+
* one closure per instance.
|
|
1656
|
+
*/
|
|
1657
|
+
subscribeInlineMathRepaint() {
|
|
1658
|
+
if (this.inlineMathRepaint || this.isDestroyed) return;
|
|
1659
|
+
const repaint = () => {
|
|
1660
|
+
if (this.isDestroyed) return;
|
|
1661
|
+
this.scene?.markDirty();
|
|
1662
|
+
};
|
|
1663
|
+
this.inlineMathRepaint = repaint;
|
|
1664
|
+
inlineMathRasterWaiters.add(repaint);
|
|
1665
|
+
}
|
|
1323
1666
|
destroy() {
|
|
1667
|
+
this.isDestroyed = true;
|
|
1668
|
+
this.optimisticTail = null;
|
|
1324
1669
|
this.streamController?.destroy();
|
|
1325
1670
|
for (const id of this.pendingWorkerIds) workerCallbacks.delete(id);
|
|
1326
1671
|
this.pendingWorkerIds.clear();
|
|
1327
1672
|
this.appendInFlight = false;
|
|
1328
1673
|
this.appendPending = false;
|
|
1674
|
+
this.mathLoadPending = false;
|
|
1675
|
+
this.flushAppendSettledWaiters();
|
|
1676
|
+
if (this.inlineMathRepaint) {
|
|
1677
|
+
inlineMathRasterWaiters.delete(this.inlineMathRepaint);
|
|
1678
|
+
this.inlineMathRepaint = void 0;
|
|
1679
|
+
}
|
|
1329
1680
|
markdownWorker?.postMessage({
|
|
1330
1681
|
instance: this.workerInstanceId,
|
|
1331
1682
|
dispose: true
|
|
@@ -1514,6 +1865,7 @@ var Markdown = class extends UIComponent {
|
|
|
1514
1865
|
}
|
|
1515
1866
|
/** Append a markdown chunk incrementally. Reuses unchanged prefix entities. */
|
|
1516
1867
|
appendMarkdown(chunk) {
|
|
1868
|
+
this.assertNotInStableCallback("appendMarkdown");
|
|
1517
1869
|
this.streamController?.flush();
|
|
1518
1870
|
return this.appendMarkdownCore(chunk);
|
|
1519
1871
|
}
|
|
@@ -1582,6 +1934,7 @@ var Markdown = class extends UIComponent {
|
|
|
1582
1934
|
this.appendPending = false;
|
|
1583
1935
|
this.dispatchAppend();
|
|
1584
1936
|
}
|
|
1937
|
+
this.flushAppendSettledWaiters();
|
|
1585
1938
|
},
|
|
1586
1939
|
// The worker can't trust what it holds for this request; retry it once with
|
|
1587
1940
|
// the full text and raws attached. `this.tokens` is untouched (no
|
|
@@ -1592,6 +1945,20 @@ var Markdown = class extends UIComponent {
|
|
|
1592
1945
|
this.workerSourceLen = 0;
|
|
1593
1946
|
this.dispatchAppend(true);
|
|
1594
1947
|
},
|
|
1948
|
+
// Neither the worker nor the fallback lexer could produce tokens for this
|
|
1949
|
+
// request, so `this.tokens` stays as it was. Only the in-flight bookkeeping
|
|
1950
|
+
// needs unwinding — including any coalesced chunk waiting behind it, which
|
|
1951
|
+
// still has to be attempted.
|
|
1952
|
+
onDropped: () => {
|
|
1953
|
+
this.pendingWorkerIds.delete(id);
|
|
1954
|
+
this.appendInFlight = false;
|
|
1955
|
+
this.workerSourceLen = 0;
|
|
1956
|
+
if (this.appendPending) {
|
|
1957
|
+
this.appendPending = false;
|
|
1958
|
+
this.dispatchAppend(true);
|
|
1959
|
+
}
|
|
1960
|
+
this.flushAppendSettledWaiters();
|
|
1961
|
+
},
|
|
1595
1962
|
text: this.rawMarkdown,
|
|
1596
1963
|
userTiming: this._userTiming
|
|
1597
1964
|
});
|
|
@@ -1613,6 +1980,647 @@ var Markdown = class extends UIComponent {
|
|
|
1613
1980
|
}
|
|
1614
1981
|
});
|
|
1615
1982
|
}
|
|
1983
|
+
/**
|
|
1984
|
+
* Spans for one paragraph token exactly as `marked` produced it.
|
|
1985
|
+
*
|
|
1986
|
+
* The literal baseline: what every release renders, and what an optimistic
|
|
1987
|
+
* guess is unwound back to.
|
|
1988
|
+
*/
|
|
1989
|
+
literalParagraphSpans(token) {
|
|
1990
|
+
const spans = [];
|
|
1991
|
+
if (token.tokens && token.tokens.length > 0) {
|
|
1992
|
+
collectSpans(token.tokens, {}, this.theme, spans);
|
|
1993
|
+
}
|
|
1994
|
+
if (spans.length === 0) spans.push({ text: token.text });
|
|
1995
|
+
return spans;
|
|
1996
|
+
}
|
|
1997
|
+
/**
|
|
1998
|
+
* Update a reused blockquote's tail child in place, or report that it cannot be.
|
|
1999
|
+
*
|
|
2000
|
+
* The render arm builds `container[border, innerStack]` where every inner block
|
|
2001
|
+
* sits in its own single-child `wrapper`, so the tail entity is
|
|
2002
|
+
* `innerStack.children.at(-1).children[0]`. Only the LAST inner block may be
|
|
2003
|
+
* updated: the inner token list is prefix-stable exactly like the top level (a
|
|
2004
|
+
* growing quote keeps its earlier blocks byte-identical), so anything before the
|
|
2005
|
+
* tail is untouched and anything more complicated than a changed tail falls back
|
|
2006
|
+
* to the caller's rebuild.
|
|
2007
|
+
*
|
|
2008
|
+
* Returns `false` without mutating anything when the shape is not the simple
|
|
2009
|
+
* grow-the-tail case, which is the signal for the caller to rebuild. Every early
|
|
2010
|
+
* return has to leave the entity untouched, or a rejected reuse would leave a
|
|
2011
|
+
* half-updated quote on screen.
|
|
2012
|
+
*/
|
|
2013
|
+
/**
|
|
2014
|
+
* Build one list item's spans: inline content plus its marker.
|
|
2015
|
+
*
|
|
2016
|
+
* Shared by the `list` render arm and the streamed-reuse path below, because
|
|
2017
|
+
* the two must produce byte-identical spans — a reused list that disagreed with
|
|
2018
|
+
* a rebuilt one about its marker or its entity decoding would make a streamed
|
|
2019
|
+
* document differ from the same source pasted at once.
|
|
2020
|
+
*/
|
|
2021
|
+
/**
|
|
2022
|
+
* Inline spans for one table cell.
|
|
2023
|
+
*
|
|
2024
|
+
* Always returns at least one span. A cell whose markup collapses to nothing —
|
|
2025
|
+
* an empty cell, but also a bare `<span>`, an image, or an HTML comment, none
|
|
2026
|
+
* of which `collectSpans` emits for — falls back to its decoded source text,
|
|
2027
|
+
* which is what the previous string-returning path rendered. That guarantee is
|
|
2028
|
+
* what lets every cell be a `RichText`: an empty cell would otherwise become a
|
|
2029
|
+
* `Text`, and since `Text` has `setText` while `RichText` has `setSpans` and
|
|
2030
|
+
* nothing converts between them, a cell that starts empty and later gains
|
|
2031
|
+
* content could not be updated in place. A streamed table needs exactly that,
|
|
2032
|
+
* because `marked` materializes a partial row as a full row of empty cells and
|
|
2033
|
+
* then fills them one at a time.
|
|
2034
|
+
*/
|
|
2035
|
+
tableCellSpans(cell, t) {
|
|
2036
|
+
const spans = [];
|
|
2037
|
+
collectSpans(cell.tokens, {}, t, spans);
|
|
2038
|
+
if (spans.length === 0) spans.push({ text: decodeEntities(cell.text) });
|
|
2039
|
+
return spans;
|
|
2040
|
+
}
|
|
2041
|
+
/**
|
|
2042
|
+
* Spans for one run of consecutive non-image inline tokens.
|
|
2043
|
+
*
|
|
2044
|
+
* A paragraph holding an image renders as a `Stack` of alternating text runs
|
|
2045
|
+
* and images, and this is one text run. Shared by the render arm and
|
|
2046
|
+
* {@link updateImageParagraph} so a reused run cannot drift from a rebuilt one.
|
|
2047
|
+
*
|
|
2048
|
+
* The empty fallback mirrors `renderInlineToRichText('', …)`, which the render
|
|
2049
|
+
* arm passed for these runs: a run is only created when it has at least one
|
|
2050
|
+
* token, so the fallback is for tokens that emit no spans at all rather than
|
|
2051
|
+
* for an empty run.
|
|
2052
|
+
*/
|
|
2053
|
+
inlineRunSpans(tokens, t) {
|
|
2054
|
+
const spans = [];
|
|
2055
|
+
if (tokens.length > 0) collectSpans(tokens, {}, t, spans);
|
|
2056
|
+
if (spans.length === 0) spans.push({ text: "" });
|
|
2057
|
+
return spans;
|
|
2058
|
+
}
|
|
2059
|
+
/** One text run of an image-bearing paragraph, as both paths build it. */
|
|
2060
|
+
inlineRunRichText(tokens, availableWidth, t) {
|
|
2061
|
+
return new RichText(this.inlineRunSpans(tokens, t), {
|
|
2062
|
+
font: `${t.fontSize}px ${t.bodyFont}`,
|
|
2063
|
+
color: t.textColor,
|
|
2064
|
+
maxWidth: availableWidth,
|
|
2065
|
+
linkColor: "#38bdf8",
|
|
2066
|
+
selectable: this.selectable,
|
|
2067
|
+
onLinkClick: this.onLinkClick
|
|
2068
|
+
});
|
|
2069
|
+
}
|
|
2070
|
+
/**
|
|
2071
|
+
* One image inside a paragraph, sized by a guess until its bitmap decodes.
|
|
2072
|
+
*
|
|
2073
|
+
* Width and height start at a 16:10 guess because the intrinsic size is not
|
|
2074
|
+
* known until the browser has the bitmap; `onLoad` corrects both from
|
|
2075
|
+
* `naturalWidth`/`naturalHeight`. Extracted from the render arm so the streamed
|
|
2076
|
+
* path reuses this exact entity rather than constructing a second variant.
|
|
2077
|
+
*
|
|
2078
|
+
* `markDirty()` is unconditional, matching the display-math sibling. It used
|
|
2079
|
+
* to sit inside the `naturalWidth && naturalHeight` check, which meant a
|
|
2080
|
+
* source that loads successfully while reporting a zero dimension left the
|
|
2081
|
+
* scene un-notified. `Image` sets `loaded` before invoking this callback, so
|
|
2082
|
+
* its `render()` starts drawing the bitmap either way — the cost was not a
|
|
2083
|
+
* stale placeholder but a box frozen at the guess: measured on Chromium and
|
|
2084
|
+
* Firefox, an `<svg width="0" height="0">` paragraph image kept 800x480 of
|
|
2085
|
+
* reserved layout forever while a normal raster corrected to 80x60. An
|
|
2086
|
+
* `onDemand` scene repaints only when marked, so nothing reclaimed it.
|
|
2087
|
+
*
|
|
2088
|
+
* The box is deliberately left at the guess when the bitmap reports zero.
|
|
2089
|
+
* Collapsing it to 0x0 would make the paragraph reflow correctly but would
|
|
2090
|
+
* also silently delete a reserved region on the strength of one browser
|
|
2091
|
+
* quirk, and `Image.render()` still blits whatever the bitmap holds. Sizing
|
|
2092
|
+
* policy for a zero-dimension source is a separate decision from notifying
|
|
2093
|
+
* the scene, which is the actual defect here.
|
|
2094
|
+
*/
|
|
2095
|
+
paragraphImage(imgToken, availableWidth) {
|
|
2096
|
+
const initialWidth = Math.min(800, availableWidth);
|
|
2097
|
+
const initialHeight = Math.round(initialWidth * 0.6);
|
|
2098
|
+
const img = new Image(imgToken.href, {
|
|
2099
|
+
width: initialWidth,
|
|
2100
|
+
height: initialHeight,
|
|
2101
|
+
alt: imgToken.text,
|
|
2102
|
+
radius: 8,
|
|
2103
|
+
onLoad: () => {
|
|
2104
|
+
const bmp = img.bitmap;
|
|
2105
|
+
if (bmp && bmp.naturalWidth && bmp.naturalHeight) {
|
|
2106
|
+
const aspect = bmp.naturalHeight / bmp.naturalWidth;
|
|
2107
|
+
img.width = Math.min(bmp.naturalWidth, availableWidth);
|
|
2108
|
+
img.height = Math.round(img.width * aspect);
|
|
2109
|
+
}
|
|
2110
|
+
this.scene?.markDirty();
|
|
2111
|
+
}
|
|
2112
|
+
});
|
|
2113
|
+
return img;
|
|
2114
|
+
}
|
|
2115
|
+
/** One table cell entity, shared by the render arm and the streamed-table path. */
|
|
2116
|
+
tableCellRichText(cell, header, t) {
|
|
2117
|
+
return new RichText(this.tableCellSpans(cell, t), {
|
|
2118
|
+
font: `${t.fontSize - 2}px ${t.bodyFont}`,
|
|
2119
|
+
color: header ? t.headingColor : t.textColor,
|
|
2120
|
+
baseStyle: header ? { bold: true } : void 0,
|
|
2121
|
+
linkColor: "#38bdf8",
|
|
2122
|
+
selectable: this.selectable,
|
|
2123
|
+
onLinkClick: this.onLinkClick
|
|
2124
|
+
});
|
|
2125
|
+
}
|
|
2126
|
+
listItemSpans(token, index) {
|
|
2127
|
+
const item = token.items[index];
|
|
2128
|
+
const num = Number(token.start ?? 1) + index;
|
|
2129
|
+
const contentSpans = [];
|
|
2130
|
+
if (item.tokens && item.tokens.length > 0) {
|
|
2131
|
+
for (const inner of item.tokens) {
|
|
2132
|
+
if (inner.type === "text" && "tokens" in inner && inner.tokens?.length) {
|
|
2133
|
+
collectSpans(
|
|
2134
|
+
inner.tokens,
|
|
2135
|
+
{},
|
|
2136
|
+
this.theme,
|
|
2137
|
+
contentSpans
|
|
2138
|
+
);
|
|
2139
|
+
} else if ("tokens" in inner && inner.tokens?.length) {
|
|
2140
|
+
collectSpans(
|
|
2141
|
+
inner.tokens,
|
|
2142
|
+
{},
|
|
2143
|
+
this.theme,
|
|
2144
|
+
contentSpans
|
|
2145
|
+
);
|
|
2146
|
+
} else if ("text" in inner) {
|
|
2147
|
+
contentSpans.push({ text: decodeEntities(inner.text) });
|
|
2148
|
+
}
|
|
2149
|
+
}
|
|
2150
|
+
} else {
|
|
2151
|
+
contentSpans.push({ text: decodeEntities(item.text) });
|
|
2152
|
+
}
|
|
2153
|
+
const itemIsRtl = BidiResolver.getBaseLevel(contentSpans.map((s) => s.text).join("")) % 2 === 1;
|
|
2154
|
+
return itemIsRtl ? [...contentSpans, { text: token.ordered ? ` .${num}` : " \u2022" }] : [{ text: token.ordered ? `${num}. ` : "\u2022 " }, ...contentSpans];
|
|
2155
|
+
}
|
|
2156
|
+
/** Construct the `RichText` for one list item. */
|
|
2157
|
+
listItemRichText(token, index, availableWidth, t) {
|
|
2158
|
+
return new RichText(this.listItemSpans(token, index), {
|
|
2159
|
+
font: `${t.fontSize}px ${t.bodyFont}`,
|
|
2160
|
+
color: t.textColor,
|
|
2161
|
+
maxWidth: availableWidth,
|
|
2162
|
+
linkColor: "#38bdf8",
|
|
2163
|
+
selectable: this.selectable,
|
|
2164
|
+
onLinkClick: this.onLinkClick
|
|
2165
|
+
});
|
|
2166
|
+
}
|
|
2167
|
+
/**
|
|
2168
|
+
* Reuse a streamed list's `Stack` instead of rebuilding every item.
|
|
2169
|
+
*
|
|
2170
|
+
* Returns `false` to mean "rebuild instead", exactly like
|
|
2171
|
+
* {@link updateBlockquoteTail}, and every rejection path leaves the entity
|
|
2172
|
+
* untouched so a refused reuse cannot leave a half-updated list on screen.
|
|
2173
|
+
*
|
|
2174
|
+
* This is the shape a stream actually produces: items are APPENDED, and only
|
|
2175
|
+
* the last one grows. That matters for the ordinal marker, which is
|
|
2176
|
+
* position-derived (`start + index`) — under append an already-rendered item's
|
|
2177
|
+
* index never changes, so its marker stays correct. A mid-list insertion would
|
|
2178
|
+
* shift every later ordinal, but no stream produces one.
|
|
2179
|
+
*
|
|
2180
|
+
* Two traps this guards, both found by probing marked 18.0.7 rather than by
|
|
2181
|
+
* reading:
|
|
2182
|
+
*
|
|
2183
|
+
* - **A retained item's `raw` is NOT stable.** `items[1].raw` goes `"- two"` ->
|
|
2184
|
+
* `"- two\\n"` when item 3 arrives, so a byte-equality guard on `raw` fails on
|
|
2185
|
+
* every chunk and the fast path would never fire. `text` is stable; compare
|
|
2186
|
+
* that.
|
|
2187
|
+
* - **A tight list can become loose.** Adding a blank line flips
|
|
2188
|
+
* `token.loose`, which re-lexes every item's children from `text` to
|
|
2189
|
+
* `paragraph`. Item 0's own `text` is unchanged, so a naive guard would reuse
|
|
2190
|
+
* and keep stale spans. Bail when `loose` flips.
|
|
2191
|
+
*/
|
|
2192
|
+
updateStreamedList(stack, oldToken, newToken) {
|
|
2193
|
+
if (!(stack instanceof Stack)) return false;
|
|
2194
|
+
if (newToken.items.length < oldToken.items.length || oldToken.items.length === 0) return false;
|
|
2195
|
+
if (oldToken.ordered !== newToken.ordered) return false;
|
|
2196
|
+
if ((oldToken.start ?? 1) !== (newToken.start ?? 1)) return false;
|
|
2197
|
+
if (oldToken.loose !== newToken.loose) return false;
|
|
2198
|
+
if (stack.children.length !== oldToken.items.length) return false;
|
|
2199
|
+
const lastRetained = oldToken.items.length - 1;
|
|
2200
|
+
for (let i = 0; i < lastRetained; i++) {
|
|
2201
|
+
if (oldToken.items[i].text !== newToken.items[i].text) return false;
|
|
2202
|
+
}
|
|
2203
|
+
const availableWidth = this.activeBlockMetrics?.availableWidth ?? this.maxWidth;
|
|
2204
|
+
const t = this.theme;
|
|
2205
|
+
const tailEntity = stack.children[lastRetained];
|
|
2206
|
+
if (oldToken.items[lastRetained].text !== newToken.items[lastRetained].text) {
|
|
2207
|
+
if (!("setSpans" in tailEntity)) return false;
|
|
2208
|
+
tailEntity.setSpans(
|
|
2209
|
+
this.listItemSpans(newToken, lastRetained)
|
|
2210
|
+
);
|
|
2211
|
+
}
|
|
2212
|
+
for (let i = oldToken.items.length; i < newToken.items.length; i++) {
|
|
2213
|
+
stack.add(this.listItemRichText(newToken, i, availableWidth, t));
|
|
2214
|
+
}
|
|
2215
|
+
const last = stack.children.at(-1);
|
|
2216
|
+
if (last) stack.resizeLastChild(last);
|
|
2217
|
+
return true;
|
|
2218
|
+
}
|
|
2219
|
+
/**
|
|
2220
|
+
* Reuse a streamed image-bearing paragraph's `Stack` instead of rebuilding it.
|
|
2221
|
+
*
|
|
2222
|
+
* Returns `false` to mean "rebuild instead", and every rejection happens before
|
|
2223
|
+
* any mutation, so a refused reuse leaves the entity exactly as it was.
|
|
2224
|
+
*
|
|
2225
|
+
* This was the last silent fallthrough in the in-place reuse path. A paragraph
|
|
2226
|
+
* holding an image renders as a `Stack` of alternating text runs and images
|
|
2227
|
+
* rather than one `RichText`, so it has no `setSpans` and failed the ordinary
|
|
2228
|
+
* paragraph gate — with no `else`, which is what made the miss invisible:
|
|
2229
|
+
* `inPlaceUpdates` stayed flat while `entitiesRebuilt` climbed. Measured on a
|
|
2230
|
+
* six-chunk stream, `inPlaceUpdates` 0 / `entitiesRebuilt` 4 with an image
|
|
2231
|
+
* against 4 / 0 for the identical shape without one. Every rebuild also
|
|
2232
|
+
* re-created the `Image`, discarding its decoded bitmap and its corrected
|
|
2233
|
+
* intrinsic size.
|
|
2234
|
+
*
|
|
2235
|
+
* It is *only* a performance path. The obvious worry — that a fresh `Image`
|
|
2236
|
+
* starts at `loaded = false` and so repaints its placeholder slab — was
|
|
2237
|
+
* measured and does not happen: sampling the real canvas pixel at the image
|
|
2238
|
+
* centre in both Chromium and Firefox gives zero placeholder frames after the
|
|
2239
|
+
* first paint, at 60ms and at 0ms between chunks, because a cached bitmap
|
|
2240
|
+
* decodes before the next frame.
|
|
2241
|
+
*
|
|
2242
|
+
* The reuse is deliberately narrow: **only a growing trailing text run**. Probed
|
|
2243
|
+
* against `marked@18.0.7`, that is the shape a stream actually produces once an
|
|
2244
|
+
* image has closed — the image token's `raw` and its index are then stable while
|
|
2245
|
+
* trailing prose grows, and the token list settles at
|
|
2246
|
+
* `[…, image, text]` and stops changing length. Anything else (a new image
|
|
2247
|
+
* arriving, an image token changing, a run appearing before the last image)
|
|
2248
|
+
* falls through to the rebuild, which is correct and rare.
|
|
2249
|
+
*
|
|
2250
|
+
* Note the child list is not one entity per token: consecutive non-image tokens
|
|
2251
|
+
* are merged into one `RichText` by the render arm's `flushText`, so
|
|
2252
|
+
* `[text, text, image]` is two children, not three. The guards therefore compare
|
|
2253
|
+
* *token runs* split at the last image, never token index against child index.
|
|
2254
|
+
*/
|
|
2255
|
+
updateImageParagraph(entity, oldToken, newToken) {
|
|
2256
|
+
if (!(entity instanceof Stack)) return false;
|
|
2257
|
+
const oldTokens = oldToken.tokens;
|
|
2258
|
+
const newTokens = newToken.tokens;
|
|
2259
|
+
if (!oldTokens || !newTokens) return false;
|
|
2260
|
+
const oldLastImage = lastIndexOfImage(oldTokens);
|
|
2261
|
+
const newLastImage = lastIndexOfImage(newTokens);
|
|
2262
|
+
if (oldLastImage < 0 || newLastImage < 0) return false;
|
|
2263
|
+
if (oldLastImage !== newLastImage) return false;
|
|
2264
|
+
for (let i = 0; i <= newLastImage; i++) {
|
|
2265
|
+
if (oldTokens[i].raw !== newTokens[i].raw) return false;
|
|
2266
|
+
}
|
|
2267
|
+
const oldTail = oldTokens.slice(oldLastImage + 1);
|
|
2268
|
+
const newTail = newTokens.slice(newLastImage + 1);
|
|
2269
|
+
if (newTail.length === 0) return false;
|
|
2270
|
+
const oldTailRaw = oldTail.map((t2) => t2.raw).join("");
|
|
2271
|
+
const newTailRaw = newTail.map((t2) => t2.raw).join("");
|
|
2272
|
+
if (!newTailRaw.startsWith(oldTailRaw)) return false;
|
|
2273
|
+
const expectedOldChildren = expectedImageParagraphChildren(oldTokens);
|
|
2274
|
+
if (entity.children.length !== expectedOldChildren) return false;
|
|
2275
|
+
const t = this.theme;
|
|
2276
|
+
const availableWidth = this.activeBlockMetrics?.availableWidth ?? this.maxWidth;
|
|
2277
|
+
if (oldTail.length === 0) {
|
|
2278
|
+
entity.add(this.inlineRunRichText(newTail, availableWidth, t));
|
|
2279
|
+
} else {
|
|
2280
|
+
const tailEntity = entity.children[entity.children.length - 1];
|
|
2281
|
+
if (!(tailEntity instanceof RichText)) return false;
|
|
2282
|
+
tailEntity.setSpans(this.inlineRunSpans(newTail, t));
|
|
2283
|
+
}
|
|
2284
|
+
const last = entity.children[entity.children.length - 1];
|
|
2285
|
+
if (last) entity.resizeLastChild(last);
|
|
2286
|
+
return true;
|
|
2287
|
+
}
|
|
2288
|
+
/**
|
|
2289
|
+
* Reuse a streamed table's `Table` entity instead of rebuilding every cell.
|
|
2290
|
+
*
|
|
2291
|
+
* Returns `false` to mean "rebuild instead", and every rejection happens before
|
|
2292
|
+
* any mutation, so a refused reuse leaves the entity exactly as it was.
|
|
2293
|
+
*
|
|
2294
|
+
* A `table` token carries every row, so the rebuild path costs Θ(C·N²)
|
|
2295
|
+
* `RichText` constructions across a stream — and a further 2×, because
|
|
2296
|
+
* `Table.layout()` re-runs `fitCell` on every cell. This was the last block
|
|
2297
|
+
* type without an in-place path.
|
|
2298
|
+
*
|
|
2299
|
+
* Two shapes have to be handled, because of how `marked` lexes a growing table
|
|
2300
|
+
* (probed against 18.0.7): a partial row is materialized immediately as a FULL
|
|
2301
|
+
* row padded with empty cells, and its cells are then filled one at a time. A
|
|
2302
|
+
* 2×2 table passes through eleven distinct row states, of which only two are
|
|
2303
|
+
* clean row appends. So handling appends alone would reject most chunks and
|
|
2304
|
+
* leave the quadratic cost essentially in place:
|
|
2305
|
+
*
|
|
2306
|
+
* 1. the last row's cells are rewritten in place via `setSpans`, and
|
|
2307
|
+
* 2. genuinely new rows go through `Table.appendRows`.
|
|
2308
|
+
*
|
|
2309
|
+
* Cells are compared by `text`, never `raw` — a table cell has no `raw` at all
|
|
2310
|
+
* (its keys are `text`/`tokens`/`header`/`align`).
|
|
2311
|
+
*/
|
|
2312
|
+
updateStreamedTable(entity, oldToken, newToken) {
|
|
2313
|
+
if (!(entity instanceof Table)) return false;
|
|
2314
|
+
if (oldToken.header.length !== newToken.header.length) return false;
|
|
2315
|
+
for (let c = 0; c < oldToken.header.length; c++) {
|
|
2316
|
+
if (oldToken.header[c].text !== newToken.header[c].text) return false;
|
|
2317
|
+
}
|
|
2318
|
+
if (newToken.rows.length < oldToken.rows.length) return false;
|
|
2319
|
+
if (entity.rows.length !== oldToken.rows.length) return false;
|
|
2320
|
+
const lastRetained = oldToken.rows.length - 1;
|
|
2321
|
+
for (let r = 0; r < lastRetained; r++) {
|
|
2322
|
+
const oldRow = oldToken.rows[r];
|
|
2323
|
+
const newRow = newToken.rows[r];
|
|
2324
|
+
for (let c = 0; c < oldToken.header.length; c++) {
|
|
2325
|
+
if (oldRow[c]?.text !== newRow[c]?.text) return false;
|
|
2326
|
+
}
|
|
2327
|
+
}
|
|
2328
|
+
if (lastRetained >= 0) {
|
|
2329
|
+
for (let c = 0; c < oldToken.header.length; c++) {
|
|
2330
|
+
const cell = entity.rows[lastRetained]?.[c];
|
|
2331
|
+
if (!(cell instanceof RichText)) return false;
|
|
2332
|
+
}
|
|
2333
|
+
}
|
|
2334
|
+
const t = this.theme;
|
|
2335
|
+
let changed = false;
|
|
2336
|
+
if (lastRetained >= 0) {
|
|
2337
|
+
const oldRow = oldToken.rows[lastRetained];
|
|
2338
|
+
const newRow = newToken.rows[lastRetained];
|
|
2339
|
+
for (let c = 0; c < oldToken.header.length; c++) {
|
|
2340
|
+
if (oldRow[c]?.text === newRow[c]?.text) continue;
|
|
2341
|
+
const cell = entity.rows[lastRetained][c];
|
|
2342
|
+
cell.setSpans(this.tableCellSpans(newRow[c], t));
|
|
2343
|
+
changed = true;
|
|
2344
|
+
}
|
|
2345
|
+
}
|
|
2346
|
+
if (newToken.rows.length > oldToken.rows.length) {
|
|
2347
|
+
const added = newToken.rows.slice(oldToken.rows.length).map((row) => row.map((cell) => this.tableCellRichText(cell, false, t)));
|
|
2348
|
+
entity.appendRows(added);
|
|
2349
|
+
} else if (changed) {
|
|
2350
|
+
entity.layout();
|
|
2351
|
+
}
|
|
2352
|
+
return true;
|
|
2353
|
+
}
|
|
2354
|
+
updateBlockquoteTail(container, oldInner, newInner) {
|
|
2355
|
+
if (oldInner.length !== newInner.length || newInner.length === 0) return false;
|
|
2356
|
+
const tail = newInner.length - 1;
|
|
2357
|
+
for (let i = 0; i < tail; i++) {
|
|
2358
|
+
if (oldInner[i].raw !== newInner[i].raw) return false;
|
|
2359
|
+
}
|
|
2360
|
+
const oldTail = oldInner[tail];
|
|
2361
|
+
const newTail = newInner[tail];
|
|
2362
|
+
if (oldTail.type !== newTail.type) return false;
|
|
2363
|
+
const innerStack = container.children[1];
|
|
2364
|
+
if (!(innerStack instanceof Stack)) return false;
|
|
2365
|
+
const wrapper = innerStack.children.at(-1);
|
|
2366
|
+
if (!wrapper || wrapper.children.length !== 1) return false;
|
|
2367
|
+
const entity = wrapper.children[0];
|
|
2368
|
+
if (!this.producesEntity(newTail)) return false;
|
|
2369
|
+
if (newTail.type === "paragraph" && "setSpans" in entity) {
|
|
2370
|
+
entity.setSpans(
|
|
2371
|
+
this.literalParagraphSpans(newTail)
|
|
2372
|
+
);
|
|
2373
|
+
} else if (newTail.type === "heading" && "setSpans" in entity) {
|
|
2374
|
+
if (oldTail.depth !== newTail.depth) {
|
|
2375
|
+
return false;
|
|
2376
|
+
}
|
|
2377
|
+
entity.setSpans(
|
|
2378
|
+
this.headingSpans(newTail)
|
|
2379
|
+
);
|
|
2380
|
+
} else if (newTail.type === "code" && entity instanceof CodeBlock && !rendersAsMath(newTail)) {
|
|
2381
|
+
const codeToken = newTail;
|
|
2382
|
+
entity.setCode(codeToken.text, codeToken.lang ?? void 0);
|
|
2383
|
+
} else {
|
|
2384
|
+
return false;
|
|
2385
|
+
}
|
|
2386
|
+
wrapper.width = entity.x + entity.width;
|
|
2387
|
+
wrapper.height = entity.height;
|
|
2388
|
+
innerStack.resizeLastChild(wrapper);
|
|
2389
|
+
const border = container.children[0];
|
|
2390
|
+
if (border instanceof QuoteBorder) border.height = innerStack.height || 20;
|
|
2391
|
+
container.height = Math.max(border?.height ?? 0, innerStack.height);
|
|
2392
|
+
return true;
|
|
2393
|
+
}
|
|
2394
|
+
/**
|
|
2395
|
+
* Spans for a heading being updated in place.
|
|
2396
|
+
*
|
|
2397
|
+
* Kept in lockstep with the `heading` arm of {@link renderToken}, which builds
|
|
2398
|
+
* its `RichText` through `renderInlineToRichText`: same `collectSpans` call and
|
|
2399
|
+
* the same `decodeEntities` fallback when a heading has no inline tokens (`##`
|
|
2400
|
+
* with no text yet, which a stream produces before its first word arrives). A
|
|
2401
|
+
* plain `token.text` fallback here would leave an entity-bearing heading
|
|
2402
|
+
* undecoded on the in-place path but decoded on a fresh render.
|
|
2403
|
+
*/
|
|
2404
|
+
headingSpans(token) {
|
|
2405
|
+
const spans = [];
|
|
2406
|
+
if (token.tokens && token.tokens.length > 0) {
|
|
2407
|
+
collectSpans(token.tokens, {}, this.theme, spans);
|
|
2408
|
+
}
|
|
2409
|
+
if (spans.length === 0) spans.push({ text: decodeEntities(token.text) });
|
|
2410
|
+
return spans;
|
|
2411
|
+
}
|
|
2412
|
+
/**
|
|
2413
|
+
* Spans for the trailing paragraph with its last unclosed inline construct
|
|
2414
|
+
* rendered as though it had closed, or `null` when there is nothing to guess.
|
|
2415
|
+
*
|
|
2416
|
+
* `null` is the answer for every `'literal'` stream, every closed or absent
|
|
2417
|
+
* stream, and any trailing paragraph whose syntax is all balanced — so the
|
|
2418
|
+
* caller falls back to {@link literalParagraphSpans} and pays nothing.
|
|
2419
|
+
*
|
|
2420
|
+
* Only the paragraph's LAST inline token is scanned. An unclosed construct can
|
|
2421
|
+
* only be there: anything that closed is already its own `strong`/`em`/
|
|
2422
|
+
* `codespan`/`link` token, so a syntax character surviving into a trailing
|
|
2423
|
+
* plain-text run is one `marked` could not pair. Scanning the whole raw string
|
|
2424
|
+
* instead would re-find the markers of already-closed constructs.
|
|
2425
|
+
*/
|
|
2426
|
+
optimisticParagraphSpans(token) {
|
|
2427
|
+
if (this.streamIncompleteMode !== "optimistic") return null;
|
|
2428
|
+
if (this.streamController?.state !== "open") return null;
|
|
2429
|
+
const inline = token.tokens;
|
|
2430
|
+
if (!inline || inline.length === 0) return null;
|
|
2431
|
+
let runLength = 1;
|
|
2432
|
+
let runText;
|
|
2433
|
+
const last = inline[inline.length - 1];
|
|
2434
|
+
const prev = inline.length > 1 ? inline[inline.length - 2] : null;
|
|
2435
|
+
const isFlatText = (token2) => token2.type === "text" && !token2.tokens?.length;
|
|
2436
|
+
if (last.type === "link" && last.raw === last.text && prev !== null && isFlatText(prev) && prev.text.endsWith("](")) {
|
|
2437
|
+
runLength = 2;
|
|
2438
|
+
runText = prev.text + last.raw;
|
|
2439
|
+
} else if (isFlatText(last)) {
|
|
2440
|
+
runText = last.text;
|
|
2441
|
+
} else {
|
|
2442
|
+
return null;
|
|
2443
|
+
}
|
|
2444
|
+
const found = findUnclosedInline(runText);
|
|
2445
|
+
if (!found) return null;
|
|
2446
|
+
const spans = [];
|
|
2447
|
+
if (inline.length > runLength) {
|
|
2448
|
+
collectSpans(inline.slice(0, -runLength), {}, this.theme, spans);
|
|
2449
|
+
}
|
|
2450
|
+
const head = runText.slice(0, found.at);
|
|
2451
|
+
if (head) spans.push({ text: decodeEntities(head) });
|
|
2452
|
+
let content = runText.slice(found.contentAt);
|
|
2453
|
+
if (found.kind === "link") {
|
|
2454
|
+
const close = content.indexOf("](");
|
|
2455
|
+
if (close !== -1) content = content.slice(0, close);
|
|
2456
|
+
}
|
|
2457
|
+
if (!content) return null;
|
|
2458
|
+
const style = this.optimisticStyle(found.kind);
|
|
2459
|
+
spans.push({ text: decodeEntities(content), style });
|
|
2460
|
+
return spans;
|
|
2461
|
+
}
|
|
2462
|
+
/** Display style for a guessed-closed construct. */
|
|
2463
|
+
optimisticStyle(kind) {
|
|
2464
|
+
switch (kind) {
|
|
2465
|
+
case "strong":
|
|
2466
|
+
return { bold: true };
|
|
2467
|
+
case "em":
|
|
2468
|
+
return { italic: true };
|
|
2469
|
+
case "codespan":
|
|
2470
|
+
return { color: this.theme.codeColor, fontFamily: this.theme.codeFont };
|
|
2471
|
+
// A link with no closing paren has no href, so it renders as plain text —
|
|
2472
|
+
// no link color and no click affordance for a destination nobody has yet.
|
|
2473
|
+
case "link":
|
|
2474
|
+
return void 0;
|
|
2475
|
+
}
|
|
2476
|
+
}
|
|
2477
|
+
/**
|
|
2478
|
+
* Re-render the paragraph currently showing a guess from its own tokens, with
|
|
2479
|
+
* no overlay, and forget it.
|
|
2480
|
+
*
|
|
2481
|
+
* Idempotent and free when no guess is live, which is what lets `close()`,
|
|
2482
|
+
* `abort()`, and a mid-stream staleness check all call it unconditionally.
|
|
2483
|
+
*/
|
|
2484
|
+
/**
|
|
2485
|
+
* Start the MathJax load, and re-typeset this document once it resolves.
|
|
2486
|
+
*
|
|
2487
|
+
* Called from two places, for two different reasons:
|
|
2488
|
+
*
|
|
2489
|
+
* - When an OPEN math fence is rendered. This is a prefetch, and it is what
|
|
2490
|
+
* makes the lazy load invisible while streaming: the module starts loading
|
|
2491
|
+
* the moment a formula begins arriving, several chunks before its closing
|
|
2492
|
+
* fence, so by the time the fence closes the converter is usually already
|
|
2493
|
+
* installed and the formula typesets synchronously on the normal path.
|
|
2494
|
+
* - When a CLOSED fence could not be typeset because the module is not ready.
|
|
2495
|
+
* That is the case a rebuild actually exists for: a document constructed with
|
|
2496
|
+
* math already complete, or a stream that closed a fence faster than the
|
|
2497
|
+
* module loaded.
|
|
2498
|
+
*
|
|
2499
|
+
* Idempotent per instance. Concurrent callers coalesce onto the one cached
|
|
2500
|
+
* module promise, and `mathLoadPending` keeps a second rebuild from being
|
|
2501
|
+
* queued while the first is outstanding.
|
|
2502
|
+
*/
|
|
2503
|
+
ensureMathJax() {
|
|
2504
|
+
if (mathConverter || this.mathLoadPending || this.isDestroyed) return;
|
|
2505
|
+
this.mathLoadPending = true;
|
|
2506
|
+
void preloadMathJax().then(() => {
|
|
2507
|
+
this.mathLoadPending = false;
|
|
2508
|
+
if (this.isDestroyed) return;
|
|
2509
|
+
if (mathConverter) this.retypesetFromTokens();
|
|
2510
|
+
this.flushAppendSettledWaiters();
|
|
2511
|
+
});
|
|
2512
|
+
}
|
|
2513
|
+
/**
|
|
2514
|
+
* Rebuild every block from the tokens already lexed, without re-lexing.
|
|
2515
|
+
*
|
|
2516
|
+
* Used only when MathJax arrives after a formula has already been rendered as
|
|
2517
|
+
* source. Rebuilding wholesale rather than surgically replacing the math blocks
|
|
2518
|
+
* is the deliberate choice: `tokenChildPrefix` maps token indices to child
|
|
2519
|
+
* slots positionally, so swapping one child in place would have to keep that
|
|
2520
|
+
* mapping, the `Stack`'s cached box, and every following sibling's position in
|
|
2521
|
+
* agreement by hand. Re-rendering the same token list in the same order leaves
|
|
2522
|
+
* the mapping trivially correct, and this runs at most once per document — the
|
|
2523
|
+
* same cost as the `setContent` rebuild that already exists.
|
|
2524
|
+
*
|
|
2525
|
+
* The optimistic tail is dropped first. Its `entity` is about to be destroyed,
|
|
2526
|
+
* so the pointer would dangle; unwinding restores literal spans, and if the
|
|
2527
|
+
* stream is still open the next chunk re-applies a guess.
|
|
2528
|
+
*/
|
|
2529
|
+
retypesetFromTokens() {
|
|
2530
|
+
this.unwindOptimisticTail();
|
|
2531
|
+
const tokens = this.tokens;
|
|
2532
|
+
while (this.content.children.length > 0) {
|
|
2533
|
+
this.content.children[this.content.children.length - 1].destroy();
|
|
2534
|
+
}
|
|
2535
|
+
for (const token of tokens) {
|
|
2536
|
+
const el = this.renderToken(token);
|
|
2537
|
+
if (el) this.content.add(el);
|
|
2538
|
+
}
|
|
2539
|
+
this.width = this.content.width;
|
|
2540
|
+
this.height = this.content.height;
|
|
2541
|
+
this.scene?.markDirty();
|
|
2542
|
+
}
|
|
2543
|
+
unwindOptimisticTail() {
|
|
2544
|
+
const tail = this.optimisticTail;
|
|
2545
|
+
this.optimisticTail = null;
|
|
2546
|
+
if (!tail || this.isDestroyed) return;
|
|
2547
|
+
const entity = tail.entity;
|
|
2548
|
+
if (!entity.setSpans || entity.parent !== this.content) return;
|
|
2549
|
+
entity.setSpans(this.literalParagraphSpans(tail.token));
|
|
2550
|
+
if (this.content.children.at(-1) === entity) {
|
|
2551
|
+
this.content.resizeLastChild(entity);
|
|
2552
|
+
} else {
|
|
2553
|
+
this.content.layout();
|
|
2554
|
+
}
|
|
2555
|
+
this.width = this.content.width;
|
|
2556
|
+
this.height = this.content.height;
|
|
2557
|
+
this.scene?.markDirty();
|
|
2558
|
+
}
|
|
2559
|
+
/**
|
|
2560
|
+
* Drop a guess that is no longer on the document's trailing paragraph.
|
|
2561
|
+
*
|
|
2562
|
+
* A coalesced append can add a block after the paragraph that owns the guess,
|
|
2563
|
+
* at which point the guess is frozen — the construct can never close, because
|
|
2564
|
+
* no further text lands in that paragraph. Without this the stale styling would
|
|
2565
|
+
* survive until `close()`.
|
|
2566
|
+
*
|
|
2567
|
+
* `writtenThisPass` is the entity whose spans this reconcile already rewrote,
|
|
2568
|
+
* if any: for that one, literal spans are on screen already and re-rendering it
|
|
2569
|
+
* would be wasted layout, so only the bookkeeping is cleared.
|
|
2570
|
+
*/
|
|
2571
|
+
dropStaleOptimisticTail(trailing, writtenThisPass) {
|
|
2572
|
+
const tail = this.optimisticTail;
|
|
2573
|
+
if (!tail || tail.entity === trailing) return;
|
|
2574
|
+
if (tail.entity === writtenThisPass) {
|
|
2575
|
+
this.optimisticTail = null;
|
|
2576
|
+
return;
|
|
2577
|
+
}
|
|
2578
|
+
this.unwindOptimisticTail();
|
|
2579
|
+
}
|
|
2580
|
+
/**
|
|
2581
|
+
* Resolve once every in-flight worker append has actually been applied.
|
|
2582
|
+
*
|
|
2583
|
+
* Committing text is not the same as the document reflecting it: `append()`
|
|
2584
|
+
* reaches `dispatchAppend()`, which `postMessage()`s and returns, and the reply
|
|
2585
|
+
* that runs `updateTokens()` lands later. Without waiting here, `close()` could
|
|
2586
|
+
* resolve — and `onStable` fire — against a document missing its last chunk.
|
|
2587
|
+
*
|
|
2588
|
+
* An outstanding lazy MathJax load counts as unsettled for the same reason. A
|
|
2589
|
+
* document whose formulas are still TeX source is not final in any sense a
|
|
2590
|
+
* caller of `onStable` cares about: the boxes are the wrong size, so measuring
|
|
2591
|
+
* or exporting there would capture placeholders.
|
|
2592
|
+
*/
|
|
2593
|
+
waitForAppendSettled() {
|
|
2594
|
+
if (!this.appendInFlight && !this.mathLoadPending) return Promise.resolve();
|
|
2595
|
+
return new Promise((resolve) => {
|
|
2596
|
+
this.appendSettledWaiters.push(resolve);
|
|
2597
|
+
});
|
|
2598
|
+
}
|
|
2599
|
+
/**
|
|
2600
|
+
* Release settlement waiters, but only once nothing is outstanding.
|
|
2601
|
+
*
|
|
2602
|
+
* Called at the very END of the worker callback, after its coalesced-re-dispatch
|
|
2603
|
+
* check, rather than wherever `appendInFlight` goes false. Within that callback
|
|
2604
|
+
* `appendInFlight` is cleared and then, if another chunk arrived while the
|
|
2605
|
+
* request was in flight, set straight back to `true` by the re-dispatch — both
|
|
2606
|
+
* synchronously, before anything watching the flag could observe the gap. Only
|
|
2607
|
+
* checking here, after that, waits through the re-dispatch instead of resolving
|
|
2608
|
+
* one chunk early.
|
|
2609
|
+
*/
|
|
2610
|
+
flushAppendSettledWaiters() {
|
|
2611
|
+
if (this.appendInFlight || this.mathLoadPending || this.appendSettledWaiters.length === 0) {
|
|
2612
|
+
return;
|
|
2613
|
+
}
|
|
2614
|
+
const waiters = this.appendSettledWaiters;
|
|
2615
|
+
this.appendSettledWaiters = [];
|
|
2616
|
+
for (const resolve of waiters) resolve();
|
|
2617
|
+
}
|
|
2618
|
+
/** Throw if a public mutation is attempted from inside an `onStable` callback. */
|
|
2619
|
+
assertNotInStableCallback(method) {
|
|
2620
|
+
if (this.inStableCallback) {
|
|
2621
|
+
throw new Error(`Markdown.${method}() cannot be called from an onStable callback`);
|
|
2622
|
+
}
|
|
2623
|
+
}
|
|
1616
2624
|
updateTokens(newTokens, knownMatchLen) {
|
|
1617
2625
|
const oldTokens = this.tokens;
|
|
1618
2626
|
const oldChildren = [...this.content.children];
|
|
@@ -1632,11 +2640,18 @@ var Markdown = class extends UIComponent {
|
|
|
1632
2640
|
}
|
|
1633
2641
|
const oldTokenToChild = this.tokenChildPrefix;
|
|
1634
2642
|
const rawMatchLen = matchLen;
|
|
2643
|
+
let pendingTail = null;
|
|
2644
|
+
let spansWrittenTo = null;
|
|
1635
2645
|
const lastTokenSameType = matchLen === oldTokens.length - 1 && matchLen < newTokens.length && oldTokens[matchLen]?.type === newTokens[matchLen]?.type;
|
|
1636
2646
|
if (lastTokenSameType && newTokens[matchLen]?.type === "code") {
|
|
1637
2647
|
const existingEntity = oldChildren[oldTokenToChild[matchLen]];
|
|
1638
2648
|
const codeToken = newTokens[matchLen];
|
|
1639
|
-
|
|
2649
|
+
const oldCodeToken = oldTokens[matchLen];
|
|
2650
|
+
const isMath = rendersAsMath(codeToken);
|
|
2651
|
+
if (isMath && rendersAsMath(oldCodeToken) && oldCodeToken.text === codeToken.text) {
|
|
2652
|
+
this.streamStats.inPlaceUpdates++;
|
|
2653
|
+
matchLen++;
|
|
2654
|
+
} else if (existingEntity instanceof CodeBlock && !isMath) {
|
|
1640
2655
|
existingEntity.setCode(codeToken.text, codeToken.lang ?? void 0);
|
|
1641
2656
|
this.streamStats.inPlaceUpdates++;
|
|
1642
2657
|
matchLen++;
|
|
@@ -1645,17 +2660,63 @@ var Markdown = class extends UIComponent {
|
|
|
1645
2660
|
} else if (lastTokenSameType && newTokens[matchLen]?.type === "paragraph") {
|
|
1646
2661
|
const entityIdx = oldTokenToChild[matchLen];
|
|
1647
2662
|
const existingEntity = oldChildren[entityIdx];
|
|
1648
|
-
if (existingEntity && "setSpans" in existingEntity) {
|
|
2663
|
+
if (existingEntity && "setSpans" in existingEntity && !paragraphHasImage(newTokens[matchLen])) {
|
|
1649
2664
|
const pToken = newTokens[matchLen];
|
|
1650
|
-
const
|
|
1651
|
-
const
|
|
1652
|
-
|
|
1653
|
-
|
|
1654
|
-
}
|
|
1655
|
-
|
|
1656
|
-
|
|
1657
|
-
|
|
1658
|
-
|
|
2665
|
+
const isTrailing = matchLen === newTokens.length - 1;
|
|
2666
|
+
const optimistic = isTrailing ? this.optimisticParagraphSpans(pToken) : null;
|
|
2667
|
+
existingEntity.setSpans(optimistic ?? this.literalParagraphSpans(pToken));
|
|
2668
|
+
spansWrittenTo = existingEntity;
|
|
2669
|
+
if (optimistic) pendingTail = { entity: existingEntity, token: pToken };
|
|
2670
|
+
this.streamStats.inPlaceUpdates++;
|
|
2671
|
+
matchLen++;
|
|
2672
|
+
this.content.resizeLastChild(existingEntity);
|
|
2673
|
+
} else if (existingEntity && this.updateImageParagraph(
|
|
2674
|
+
existingEntity,
|
|
2675
|
+
oldTokens[matchLen],
|
|
2676
|
+
newTokens[matchLen]
|
|
2677
|
+
)) {
|
|
2678
|
+
this.streamStats.inPlaceUpdates++;
|
|
2679
|
+
matchLen++;
|
|
2680
|
+
this.content.resizeLastChild(existingEntity);
|
|
2681
|
+
}
|
|
2682
|
+
} else if (lastTokenSameType && newTokens[matchLen]?.type === "heading") {
|
|
2683
|
+
const existingEntity = oldChildren[oldTokenToChild[matchLen]];
|
|
2684
|
+
const hToken = newTokens[matchLen];
|
|
2685
|
+
const oldToken = oldTokens[matchLen];
|
|
2686
|
+
if (existingEntity && "setSpans" in existingEntity && oldToken?.depth === hToken.depth) {
|
|
2687
|
+
existingEntity.setSpans(this.headingSpans(hToken));
|
|
2688
|
+
spansWrittenTo = existingEntity;
|
|
2689
|
+
this.streamStats.inPlaceUpdates++;
|
|
2690
|
+
matchLen++;
|
|
2691
|
+
this.content.resizeLastChild(existingEntity);
|
|
2692
|
+
}
|
|
2693
|
+
} else if (lastTokenSameType && newTokens[matchLen]?.type === "blockquote") {
|
|
2694
|
+
const existingEntity = oldChildren[oldTokenToChild[matchLen]];
|
|
2695
|
+
const newInner = newTokens[matchLen].tokens;
|
|
2696
|
+
const oldInner = oldTokens[matchLen].tokens;
|
|
2697
|
+
if (existingEntity instanceof MarkdownContainer && newInner && oldInner && this.updateBlockquoteTail(existingEntity, oldInner, newInner)) {
|
|
2698
|
+
this.streamStats.inPlaceUpdates++;
|
|
2699
|
+
matchLen++;
|
|
2700
|
+
this.content.resizeLastChild(existingEntity);
|
|
2701
|
+
}
|
|
2702
|
+
} else if (lastTokenSameType && newTokens[matchLen]?.type === "list") {
|
|
2703
|
+
const existingEntity = oldChildren[oldTokenToChild[matchLen]];
|
|
2704
|
+
if (existingEntity && this.updateStreamedList(
|
|
2705
|
+
existingEntity,
|
|
2706
|
+
oldTokens[matchLen],
|
|
2707
|
+
newTokens[matchLen]
|
|
2708
|
+
)) {
|
|
2709
|
+
this.streamStats.inPlaceUpdates++;
|
|
2710
|
+
matchLen++;
|
|
2711
|
+
this.content.resizeLastChild(existingEntity);
|
|
2712
|
+
}
|
|
2713
|
+
} else if (lastTokenSameType && newTokens[matchLen]?.type === "table") {
|
|
2714
|
+
const existingEntity = oldChildren[oldTokenToChild[matchLen]];
|
|
2715
|
+
if (existingEntity && this.updateStreamedTable(
|
|
2716
|
+
existingEntity,
|
|
2717
|
+
oldTokens[matchLen],
|
|
2718
|
+
newTokens[matchLen]
|
|
2719
|
+
)) {
|
|
1659
2720
|
this.streamStats.inPlaceUpdates++;
|
|
1660
2721
|
matchLen++;
|
|
1661
2722
|
this.content.resizeLastChild(existingEntity);
|
|
@@ -1673,10 +2734,24 @@ var Markdown = class extends UIComponent {
|
|
|
1673
2734
|
}
|
|
1674
2735
|
}
|
|
1675
2736
|
}
|
|
2737
|
+
const lastIndex = newTokens.length - 1;
|
|
1676
2738
|
for (let i = matchLen; i < newTokens.length; i++) {
|
|
1677
2739
|
const el = this.renderToken(newTokens[i]);
|
|
1678
|
-
if (el)
|
|
2740
|
+
if (!el) continue;
|
|
2741
|
+
this.content.add(el);
|
|
2742
|
+
if (i === lastIndex && newTokens[i].type === "paragraph" && "setSpans" in el) {
|
|
2743
|
+
const pToken = newTokens[i];
|
|
2744
|
+
const optimistic = this.optimisticParagraphSpans(pToken);
|
|
2745
|
+
if (optimistic) {
|
|
2746
|
+
el.setSpans(optimistic);
|
|
2747
|
+
this.content.resizeLastChild(el);
|
|
2748
|
+
pendingTail = { entity: el, token: pToken };
|
|
2749
|
+
spansWrittenTo = el;
|
|
2750
|
+
}
|
|
2751
|
+
}
|
|
1679
2752
|
}
|
|
2753
|
+
this.dropStaleOptimisticTail(pendingTail?.entity ?? null, spansWrittenTo);
|
|
2754
|
+
if (pendingTail) this.optimisticTail = pendingTail;
|
|
1680
2755
|
this.setTokens(newTokens, rawMatchLen);
|
|
1681
2756
|
this.width = this.content.width;
|
|
1682
2757
|
this.height = this.content.height;
|
|
@@ -1729,6 +2804,43 @@ var Markdown = class extends UIComponent {
|
|
|
1729
2804
|
return "text" in token;
|
|
1730
2805
|
}
|
|
1731
2806
|
}
|
|
2807
|
+
/**
|
|
2808
|
+
* Build a centered display-math block, or `null` if MathJax cannot typeset yet.
|
|
2809
|
+
*
|
|
2810
|
+
* Shared by the `$$..$$` block token and a closed ```` ```math ```` fence:
|
|
2811
|
+
* both are display math and must render identically, differing only in how
|
|
2812
|
+
* they were spelled in the source.
|
|
2813
|
+
*
|
|
2814
|
+
* `ex` is font-relative, so the intrinsic box is resolved against the theme's
|
|
2815
|
+
* body size. This is what a previously hardcoded `* 8` got wrong -- exact only
|
|
2816
|
+
* near fontSize 18.1px, so a formula was ~13% oversized at the 16px default
|
|
2817
|
+
* and far worse at other sizes.
|
|
2818
|
+
*/
|
|
2819
|
+
renderDisplayMath(formula, availableWidth) {
|
|
2820
|
+
const t = this.theme;
|
|
2821
|
+
const mathData = renderMathToSVGDataURI(formula, true, t.textColor);
|
|
2822
|
+
if (!mathData) return null;
|
|
2823
|
+
const intrinsicW = exToPx(mathData.widthEx, t.fontSize);
|
|
2824
|
+
const intrinsicH = exToPx(mathData.heightEx, t.fontSize);
|
|
2825
|
+
const mathImg = new Image(mathData.uri, {
|
|
2826
|
+
width: Math.min(availableWidth, intrinsicW),
|
|
2827
|
+
height: intrinsicH * Math.min(1, availableWidth / intrinsicW),
|
|
2828
|
+
alt: formula,
|
|
2829
|
+
// The SVG decodes asynchronously and Image paints a placeholder until it
|
|
2830
|
+
// lands. Without this an `onDemand` scene, which repaints only when marked
|
|
2831
|
+
// dirty, leaves the formula a blank slab forever.
|
|
2832
|
+
onLoad: () => {
|
|
2833
|
+
this.scene?.markDirty();
|
|
2834
|
+
}
|
|
2835
|
+
});
|
|
2836
|
+
const wrapper = new MarkdownContainer();
|
|
2837
|
+
mathImg.x = 16;
|
|
2838
|
+
mathImg.y = 8;
|
|
2839
|
+
wrapper.add(mathImg);
|
|
2840
|
+
wrapper.width = mathImg.width + 16;
|
|
2841
|
+
wrapper.height = mathImg.height + 16;
|
|
2842
|
+
return wrapper;
|
|
2843
|
+
}
|
|
1732
2844
|
renderToken(token) {
|
|
1733
2845
|
const t = this.theme;
|
|
1734
2846
|
const bodyFont = `${t.fontSize}px ${t.bodyFont}`;
|
|
@@ -1739,6 +2851,10 @@ var Markdown = class extends UIComponent {
|
|
|
1739
2851
|
availableWidth: this.maxWidth
|
|
1740
2852
|
};
|
|
1741
2853
|
const availableWidth = metrics.availableWidth;
|
|
2854
|
+
if (containsInlineMath(token)) {
|
|
2855
|
+
if (!mathConverter) this.ensureMathJax();
|
|
2856
|
+
this.subscribeInlineMathRepaint();
|
|
2857
|
+
}
|
|
1742
2858
|
switch (token.type) {
|
|
1743
2859
|
// ── Headings ─────────────────────────────────────────────────────
|
|
1744
2860
|
case "heading": {
|
|
@@ -1760,7 +2876,7 @@ var Markdown = class extends UIComponent {
|
|
|
1760
2876
|
// ── Paragraphs ───────────────────────────────────────────────────
|
|
1761
2877
|
case "paragraph": {
|
|
1762
2878
|
const pToken = token;
|
|
1763
|
-
if (!pToken
|
|
2879
|
+
if (!paragraphHasImage(pToken)) {
|
|
1764
2880
|
return renderInlineToRichText(
|
|
1765
2881
|
pToken.tokens,
|
|
1766
2882
|
pToken.text,
|
|
@@ -1780,43 +2896,14 @@ var Markdown = class extends UIComponent {
|
|
|
1780
2896
|
let currentTokens = [];
|
|
1781
2897
|
const flushText = () => {
|
|
1782
2898
|
if (currentTokens.length > 0) {
|
|
1783
|
-
stack.add(
|
|
1784
|
-
renderInlineToRichText(
|
|
1785
|
-
currentTokens,
|
|
1786
|
-
"",
|
|
1787
|
-
bodyFont,
|
|
1788
|
-
t.textColor,
|
|
1789
|
-
availableWidth,
|
|
1790
|
-
t,
|
|
1791
|
-
this.selectable,
|
|
1792
|
-
this.onLinkClick
|
|
1793
|
-
)
|
|
1794
|
-
);
|
|
2899
|
+
stack.add(this.inlineRunRichText(currentTokens, availableWidth, t));
|
|
1795
2900
|
currentTokens = [];
|
|
1796
2901
|
}
|
|
1797
2902
|
};
|
|
1798
2903
|
for (const child of pToken.tokens) {
|
|
1799
2904
|
if (child.type === "image") {
|
|
1800
2905
|
flushText();
|
|
1801
|
-
|
|
1802
|
-
const initialWidth = Math.min(800, availableWidth);
|
|
1803
|
-
const initialHeight = Math.round(initialWidth * 0.6);
|
|
1804
|
-
const img = new Image(imgToken.href, {
|
|
1805
|
-
width: initialWidth,
|
|
1806
|
-
height: initialHeight,
|
|
1807
|
-
alt: imgToken.text,
|
|
1808
|
-
radius: 8,
|
|
1809
|
-
onLoad: () => {
|
|
1810
|
-
const bmp = img.bitmap;
|
|
1811
|
-
if (bmp && bmp.naturalWidth && bmp.naturalHeight) {
|
|
1812
|
-
const aspect = bmp.naturalHeight / bmp.naturalWidth;
|
|
1813
|
-
img.width = Math.min(bmp.naturalWidth, availableWidth);
|
|
1814
|
-
img.height = Math.round(img.width * aspect);
|
|
1815
|
-
if (this.scene) this.scene.markDirty();
|
|
1816
|
-
}
|
|
1817
|
-
}
|
|
1818
|
-
});
|
|
1819
|
-
stack.add(img);
|
|
2906
|
+
stack.add(this.paragraphImage(child, availableWidth));
|
|
1820
2907
|
} else {
|
|
1821
2908
|
currentTokens.push(child);
|
|
1822
2909
|
}
|
|
@@ -1824,26 +2911,22 @@ var Markdown = class extends UIComponent {
|
|
|
1824
2911
|
flushText();
|
|
1825
2912
|
return stack;
|
|
1826
2913
|
}
|
|
2914
|
+
// ── Display math (`$$..$$`) ──────────────────────────────────────
|
|
2915
|
+
case "blockMath": {
|
|
2916
|
+
const mathToken = token;
|
|
2917
|
+
const mathBlock = this.renderDisplayMath(mathToken.text, availableWidth);
|
|
2918
|
+
if (mathBlock) return mathBlock;
|
|
2919
|
+
this.ensureMathJax();
|
|
2920
|
+
return new CodeBlock(mathToken.text, "latex", availableWidth, t, this.selectable);
|
|
2921
|
+
}
|
|
1827
2922
|
// ── Code blocks ──────────────────────────────────────────────────
|
|
1828
2923
|
case "code": {
|
|
1829
2924
|
const codeToken = token;
|
|
1830
2925
|
const lang = (codeToken.lang ?? "").toLowerCase();
|
|
1831
|
-
if (lang
|
|
1832
|
-
|
|
1833
|
-
|
|
1834
|
-
|
|
1835
|
-
width: Math.min(availableWidth, mathData.width),
|
|
1836
|
-
height: mathData.height * Math.min(1, availableWidth / mathData.width),
|
|
1837
|
-
alt: codeToken.text
|
|
1838
|
-
});
|
|
1839
|
-
const wrapper = new MarkdownContainer();
|
|
1840
|
-
mathImg.x = 16;
|
|
1841
|
-
mathImg.y = 8;
|
|
1842
|
-
wrapper.add(mathImg);
|
|
1843
|
-
wrapper.width = mathImg.width + 16;
|
|
1844
|
-
wrapper.height = mathImg.height + 16;
|
|
1845
|
-
return wrapper;
|
|
1846
|
-
}
|
|
2926
|
+
if (MATH_LANGS.has(lang)) this.ensureMathJax();
|
|
2927
|
+
if (rendersAsMath(codeToken)) {
|
|
2928
|
+
const mathBlock = this.renderDisplayMath(codeToken.text, availableWidth);
|
|
2929
|
+
if (mathBlock) return mathBlock;
|
|
1847
2930
|
}
|
|
1848
2931
|
return new CodeBlock(codeToken.text, lang, availableWidth, t, this.selectable);
|
|
1849
2932
|
}
|
|
@@ -1883,62 +2966,22 @@ var Markdown = class extends UIComponent {
|
|
|
1883
2966
|
container.height = Math.max(border.height, innerStack.height);
|
|
1884
2967
|
return container;
|
|
1885
2968
|
}
|
|
1886
|
-
// ── Lists
|
|
2969
|
+
// ── Lists ────────────────────────────────────────────────
|
|
1887
2970
|
case "list": {
|
|
1888
2971
|
const listToken = token;
|
|
1889
2972
|
const listStack = new Stack({ direction: "vertical", gap: 6 });
|
|
1890
2973
|
for (let i = 0; i < listToken.items.length; i++) {
|
|
1891
|
-
|
|
1892
|
-
const num = Number(listToken.start ?? 1) + i;
|
|
1893
|
-
const contentSpans = [];
|
|
1894
|
-
if (item.tokens && item.tokens.length > 0) {
|
|
1895
|
-
for (const inner of item.tokens) {
|
|
1896
|
-
if (inner.type === "text" && "tokens" in inner && inner.tokens?.length) {
|
|
1897
|
-
collectSpans(inner.tokens, {}, t, contentSpans);
|
|
1898
|
-
} else if ("tokens" in inner && inner.tokens?.length) {
|
|
1899
|
-
collectSpans(inner.tokens, {}, t, contentSpans);
|
|
1900
|
-
} else if ("text" in inner) {
|
|
1901
|
-
contentSpans.push({
|
|
1902
|
-
text: decodeEntities(inner.text)
|
|
1903
|
-
});
|
|
1904
|
-
}
|
|
1905
|
-
}
|
|
1906
|
-
} else {
|
|
1907
|
-
contentSpans.push({ text: decodeEntities(item.text) });
|
|
1908
|
-
}
|
|
1909
|
-
const itemIsRtl = BidiResolver.getBaseLevel(contentSpans.map((s) => s.text).join("")) % 2 === 1;
|
|
1910
|
-
const itemSpans = itemIsRtl ? [...contentSpans, { text: listToken.ordered ? ` .${num}` : " \u2022" }] : [{ text: listToken.ordered ? `${num}. ` : "\u2022 " }, ...contentSpans];
|
|
1911
|
-
const itemRt = new RichText(itemSpans, {
|
|
1912
|
-
font: bodyFont,
|
|
1913
|
-
color: t.textColor,
|
|
1914
|
-
maxWidth: Math.max(0, availableWidth - 24),
|
|
1915
|
-
linkColor: "#38bdf8",
|
|
1916
|
-
selectable: this.selectable,
|
|
1917
|
-
onLinkClick: this.onLinkClick
|
|
1918
|
-
});
|
|
1919
|
-
itemRt.x = 12;
|
|
1920
|
-
listStack.add(itemRt);
|
|
2974
|
+
listStack.add(this.listItemRichText(listToken, i, availableWidth, t));
|
|
1921
2975
|
}
|
|
1922
2976
|
return listStack;
|
|
1923
2977
|
}
|
|
1924
2978
|
// ── Table ────────────────────────────────────────────────────────
|
|
1925
2979
|
case "table": {
|
|
1926
2980
|
const tblToken = token;
|
|
1927
|
-
const
|
|
1928
|
-
|
|
1929
|
-
|
|
1930
|
-
|
|
1931
|
-
return new RichText(spans, {
|
|
1932
|
-
font: `${t.fontSize - 2}px ${t.bodyFont}`,
|
|
1933
|
-
color: header ? t.headingColor : t.textColor,
|
|
1934
|
-
baseStyle: header ? { bold: true } : void 0,
|
|
1935
|
-
linkColor: "#38bdf8",
|
|
1936
|
-
selectable: this.selectable,
|
|
1937
|
-
onLinkClick: this.onLinkClick
|
|
1938
|
-
});
|
|
1939
|
-
};
|
|
1940
|
-
const headers = tblToken.header.map((cell) => buildCell(cell, true));
|
|
1941
|
-
const rows = tblToken.rows.map((row) => row.map((cell) => buildCell(cell, false)));
|
|
2981
|
+
const headers = tblToken.header.map((cell) => this.tableCellRichText(cell, true, t));
|
|
2982
|
+
const rows = tblToken.rows.map(
|
|
2983
|
+
(row) => row.map((cell) => this.tableCellRichText(cell, false, t))
|
|
2984
|
+
);
|
|
1942
2985
|
return new Table({
|
|
1943
2986
|
headers,
|
|
1944
2987
|
rows,
|
|
@@ -1988,5 +3031,7 @@ export {
|
|
|
1988
3031
|
CodeBlock,
|
|
1989
3032
|
Markdown,
|
|
1990
3033
|
codeAtlas,
|
|
1991
|
-
codeAtlasStats
|
|
3034
|
+
codeAtlasStats,
|
|
3035
|
+
isMathJaxReady,
|
|
3036
|
+
preloadMathJax
|
|
1992
3037
|
};
|