@vectojs/markdown 0.4.0 → 0.6.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/dist/index.mjs CHANGED
@@ -3,23 +3,441 @@ import {
3
3
  BidiResolver,
4
4
  Entity,
5
5
  GlyphRasterAtlas,
6
+ OBJECT_REPLACEMENT,
6
7
  prepareContentGrid,
7
- SVGEntity
8
+ SVGEntity,
9
+ beginVectoUserTiming,
10
+ endVectoUserTiming,
11
+ VECTO_USER_TIMING
8
12
  } from "@vectojs/core";
9
13
  import { marked } from "marked";
10
- import { mathjax } from "mathjax-full/js/mathjax.js";
11
- import { TeX } from "mathjax-full/js/input/tex.js";
12
- import { SVG } from "mathjax-full/js/output/svg.js";
13
- import { liteAdaptor } from "mathjax-full/js/adaptors/liteAdaptor.js";
14
- import { RegisterHTMLHandler } from "mathjax-full/js/handlers/html.js";
15
- import { AllPackages } from "mathjax-full/js/input/tex/AllPackages.js";
14
+
15
+ // src/StreamController.ts
16
+ var DEFAULT_MAX_BUFFERED_CHARS = 64 * 1024;
17
+ var MAX_FRAME_DELTA_MS = 100;
18
+ var MIN_SCAN_CODE_UNITS = 64;
19
+ function positiveFinite(value, label) {
20
+ if (!Number.isFinite(value) || value <= 0) {
21
+ throw new RangeError(`${label} must be a positive finite number`);
22
+ }
23
+ return value;
24
+ }
25
+ function abortError() {
26
+ const error = new Error("Stream aborted");
27
+ error.name = "AbortError";
28
+ return error;
29
+ }
30
+ var StreamControllerImpl = class {
31
+ constructor(host, options) {
32
+ this.host = host;
33
+ this.maxBufferedChars = positiveFinite(
34
+ options.maxBufferedChars ?? DEFAULT_MAX_BUFFERED_CHARS,
35
+ "maxBufferedChars"
36
+ );
37
+ this.graphemesPerSecond = options.pacing ? positiveFinite(options.pacing.graphemesPerSecond, "pacing.graphemesPerSecond") : null;
38
+ this.segmenter = this.graphemesPerSecond === null ? null : new Intl.Segmenter(void 0, { granularity: "grapheme" });
39
+ this.signal = options.signal;
40
+ this.onSignalAbort = () => this.abort(this.signal?.reason);
41
+ if (this.signal?.aborted) this.abort(this.signal.reason);
42
+ else
43
+ this.signal?.addEventListener("abort", this.onSignalAbort, {
44
+ once: true
45
+ });
46
+ }
47
+ host;
48
+ maxBufferedChars;
49
+ graphemesPerSecond;
50
+ segmenter;
51
+ signal;
52
+ onSignalAbort;
53
+ chunks = [];
54
+ headIndex = 0;
55
+ headOffset = 0;
56
+ acceptedChars = 0;
57
+ blocked = null;
58
+ currentState = "open";
59
+ terminalReason = null;
60
+ rafId = null;
61
+ lastFrameAt = null;
62
+ graphemeCredit = 0;
63
+ released = false;
64
+ closePromise = null;
65
+ resolveClose = null;
66
+ rejectClose = null;
67
+ get state() {
68
+ return this.currentState;
69
+ }
70
+ get bufferedChars() {
71
+ return this.acceptedChars + (this.blocked?.chunk.length ?? 0);
72
+ }
73
+ write(chunk) {
74
+ if (this.currentState !== "open" || this.closePromise) {
75
+ return Promise.reject(this.reasonForWrite());
76
+ }
77
+ if (chunk.length === 0) return Promise.resolve();
78
+ if (this.blocked) {
79
+ return Promise.reject(new Error("StreamController already has a blocked write"));
80
+ }
81
+ if (this.canAdmit(chunk)) {
82
+ this.admit(chunk);
83
+ try {
84
+ this.schedule();
85
+ return Promise.resolve();
86
+ } catch (error) {
87
+ return Promise.reject(error);
88
+ }
89
+ }
90
+ return new Promise((resolve, reject) => {
91
+ const blocked = { chunk, resolve, reject };
92
+ this.blocked = blocked;
93
+ try {
94
+ this.schedule();
95
+ } catch (error) {
96
+ if (this.blocked === blocked) this.blocked = null;
97
+ reject(error);
98
+ }
99
+ });
100
+ }
101
+ flush() {
102
+ if (this.currentState === "closed") return;
103
+ if (this.currentState === "aborted") throw this.terminalReason;
104
+ this.cancelFrame();
105
+ this.commitAllSubmitted();
106
+ this.resetPacingIfIdle();
107
+ }
108
+ close() {
109
+ if (this.currentState === "closed") return Promise.resolve();
110
+ if (this.currentState === "aborted") return Promise.reject(this.terminalReason);
111
+ if (this.closePromise) return this.closePromise;
112
+ let resolveClose;
113
+ let rejectClose;
114
+ const closePromise = new Promise((resolve, reject) => {
115
+ resolveClose = resolve;
116
+ rejectClose = reject;
117
+ });
118
+ this.closePromise = closePromise;
119
+ this.resolveClose = resolveClose;
120
+ this.rejectClose = rejectClose;
121
+ this.cancelFrame();
122
+ try {
123
+ this.commitAllSubmitted();
124
+ } catch (error) {
125
+ this.rejectPendingClose(error);
126
+ return closePromise;
127
+ }
128
+ if (this.currentState !== "open") {
129
+ this.rejectPendingClose(this.terminalReason);
130
+ return closePromise;
131
+ }
132
+ this.currentState = "closed";
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
+ );
160
+ return closePromise;
161
+ }
162
+ abort(reason) {
163
+ if (this.currentState !== "open") return;
164
+ this.fail(reason === void 0 ? abortError() : reason);
165
+ }
166
+ destroy() {
167
+ this.abort();
168
+ }
169
+ onFrame = (timestamp) => {
170
+ this.rafId = null;
171
+ if (this.currentState !== "open") return;
172
+ let keepScheduling = true;
173
+ try {
174
+ if (this.graphemesPerSecond === null) this.commitAccepted();
175
+ else keepScheduling = this.commitPaced(timestamp);
176
+ } catch {
177
+ return;
178
+ }
179
+ if (this.currentState !== "open") return;
180
+ this.admitBlockedIfPossible();
181
+ this.resetPacingIfIdle();
182
+ if (!keepScheduling) return;
183
+ try {
184
+ this.schedule();
185
+ } catch {
186
+ }
187
+ };
188
+ reasonForWrite() {
189
+ if (this.currentState === "aborted") return this.terminalReason;
190
+ if (this.currentState === "closed") return new Error("StreamController is closed");
191
+ return new Error("StreamController is closing");
192
+ }
193
+ canAdmit(chunk) {
194
+ return this.acceptedChars + chunk.length <= this.maxBufferedChars || this.acceptedChars === 0 && chunk.length > this.maxBufferedChars;
195
+ }
196
+ admit(chunk) {
197
+ this.chunks.push(chunk);
198
+ this.acceptedChars += chunk.length;
199
+ }
200
+ admitBlockedIfPossible() {
201
+ const blocked = this.blocked;
202
+ if (!blocked || !this.canAdmit(blocked.chunk)) return;
203
+ this.blocked = null;
204
+ this.admit(blocked.chunk);
205
+ blocked.resolve();
206
+ }
207
+ schedule() {
208
+ if (this.currentState !== "open" || this.acceptedChars === 0 || this.rafId !== null) return;
209
+ if (typeof requestAnimationFrame !== "function") {
210
+ this.flush();
211
+ return;
212
+ }
213
+ this.rafId = requestAnimationFrame(this.onFrame);
214
+ }
215
+ cancelFrame() {
216
+ if (this.rafId === null) return;
217
+ if (typeof cancelAnimationFrame === "function") cancelAnimationFrame(this.rafId);
218
+ this.rafId = null;
219
+ }
220
+ commitAccepted() {
221
+ if (this.acceptedChars === 0) return;
222
+ const text = this.takeAcceptedText();
223
+ try {
224
+ this.host.append(text);
225
+ } catch (error) {
226
+ this.fail(error);
227
+ throw error;
228
+ }
229
+ }
230
+ /** Return true while another frame can make progress without more producer input. */
231
+ commitPaced(timestamp) {
232
+ if (this.lastFrameAt === null) {
233
+ this.lastFrameAt = timestamp;
234
+ return true;
235
+ }
236
+ const delta = Math.min(MAX_FRAME_DELTA_MS, Math.max(0, timestamp - this.lastFrameAt));
237
+ this.lastFrameAt = timestamp;
238
+ this.graphemeCredit += delta * this.graphemesPerSecond / 1e3;
239
+ const available = Math.floor(this.graphemeCredit);
240
+ if (available < 1) return true;
241
+ const selected = this.selectGraphemePrefix(available);
242
+ if (selected.count === 0) {
243
+ this.lastFrameAt = null;
244
+ this.graphemeCredit = 0;
245
+ return false;
246
+ }
247
+ const completedBlocked = this.consumeSubmittedChars(selected.codeUnits);
248
+ try {
249
+ this.host.append(selected.text);
250
+ completedBlocked?.resolve();
251
+ } catch (error) {
252
+ completedBlocked?.reject(error);
253
+ this.fail(error);
254
+ throw error;
255
+ }
256
+ this.graphemeCredit -= selected.count;
257
+ return true;
258
+ }
259
+ selectGraphemePrefix(maxCount) {
260
+ const submittedChars = this.acceptedChars + (this.blocked?.chunk.length ?? 0);
261
+ let scanLength = Math.min(submittedChars, Math.max(MIN_SCAN_CODE_UNITS, maxCount * 2));
262
+ while (scanLength > 0) {
263
+ let sample = this.peekSubmittedChars(scanLength);
264
+ if (scanLength < submittedChars && /[\uD800-\uDBFF]$/.test(sample)) {
265
+ scanLength++;
266
+ sample = this.peekSubmittedChars(scanLength);
267
+ }
268
+ const segments = [...this.segmenter.segment(sample)];
269
+ const hasUnscannedText = scanLength < submittedChars;
270
+ if (hasUnscannedText && segments.length <= maxCount) {
271
+ scanLength = Math.min(submittedChars, scanLength * 2);
272
+ continue;
273
+ }
274
+ const count = hasUnscannedText ? maxCount : Math.min(maxCount, Math.max(0, segments.length - 1));
275
+ if (count > 0) {
276
+ const last = segments[count - 1];
277
+ const codeUnits = last.index + last.segment.length;
278
+ return { text: sample.slice(0, codeUnits), count, codeUnits };
279
+ }
280
+ if (this.blocked || this.acceptedChars > this.maxBufferedChars) {
281
+ return this.forceCodePointPrefix(sample);
282
+ }
283
+ return { text: "", count: 0, codeUnits: 0 };
284
+ }
285
+ return { text: "", count: 0, codeUnits: 0 };
286
+ }
287
+ forceCodePointPrefix(sample) {
288
+ const first = sample.charCodeAt(0);
289
+ const second = sample.charCodeAt(1);
290
+ const codeUnits = first >= 55296 && first <= 56319 && second >= 56320 && second <= 57343 ? 2 : 1;
291
+ return { text: sample.slice(0, codeUnits), count: 1, codeUnits };
292
+ }
293
+ peekSubmittedChars(limit) {
294
+ const parts = this.peekAcceptedParts(Math.min(limit, this.acceptedChars));
295
+ const acceptedLength = Math.min(limit, this.acceptedChars);
296
+ const blockedLength = limit - acceptedLength;
297
+ if (blockedLength > 0 && this.blocked) {
298
+ parts.push(this.blocked.chunk.slice(0, blockedLength));
299
+ }
300
+ return parts.length === 1 ? parts[0] : parts.join("");
301
+ }
302
+ peekAcceptedParts(limit) {
303
+ if (limit <= 0) return [];
304
+ const parts = [];
305
+ let remaining = limit;
306
+ for (let index = this.headIndex; index < this.chunks.length && remaining > 0; index++) {
307
+ const chunk = this.chunks[index];
308
+ const start = index === this.headIndex ? this.headOffset : 0;
309
+ const available = chunk.length - start;
310
+ if (available <= remaining) {
311
+ parts.push(start === 0 ? chunk : chunk.slice(start));
312
+ remaining -= available;
313
+ } else {
314
+ parts.push(chunk.slice(start, start + remaining));
315
+ remaining = 0;
316
+ }
317
+ }
318
+ return parts;
319
+ }
320
+ consumeSubmittedChars(count) {
321
+ const acceptedCount = Math.min(count, this.acceptedChars);
322
+ this.consumeAcceptedChars(acceptedCount);
323
+ const blockedCount = count - acceptedCount;
324
+ if (blockedCount === 0) return null;
325
+ const blocked = this.blocked;
326
+ if (!blocked) throw new Error("StreamController queue accounting diverged");
327
+ if (blockedCount >= blocked.chunk.length) {
328
+ this.blocked = null;
329
+ return blocked;
330
+ }
331
+ blocked.chunk = blocked.chunk.slice(blockedCount);
332
+ return null;
333
+ }
334
+ consumeAcceptedChars(count) {
335
+ if (count < 0 || count > this.acceptedChars) {
336
+ throw new Error("StreamController queue accounting diverged");
337
+ }
338
+ this.acceptedChars -= count;
339
+ let remaining = count;
340
+ while (remaining > 0) {
341
+ const chunk = this.chunks[this.headIndex];
342
+ const available = chunk.length - this.headOffset;
343
+ if (remaining < available) {
344
+ this.headOffset += remaining;
345
+ remaining = 0;
346
+ } else {
347
+ remaining -= available;
348
+ this.headIndex++;
349
+ this.headOffset = 0;
350
+ }
351
+ }
352
+ if (this.acceptedChars === 0) {
353
+ this.chunks = [];
354
+ this.headIndex = 0;
355
+ this.headOffset = 0;
356
+ } else if (this.headIndex >= 64 && this.headIndex * 2 >= this.chunks.length) {
357
+ this.chunks.splice(0, this.headIndex);
358
+ this.headIndex = 0;
359
+ }
360
+ }
361
+ takeAcceptedText() {
362
+ const parts = this.takeAcceptedParts();
363
+ return parts.length === 1 ? parts[0] : parts.join("");
364
+ }
365
+ takeAcceptedParts() {
366
+ const parts = this.peekAcceptedParts(this.acceptedChars);
367
+ this.chunks = [];
368
+ this.headIndex = 0;
369
+ this.headOffset = 0;
370
+ this.acceptedChars = 0;
371
+ return parts;
372
+ }
373
+ commitAllSubmitted() {
374
+ const blocked = this.blocked;
375
+ this.blocked = null;
376
+ const parts = this.takeAcceptedParts();
377
+ if (blocked) parts.push(blocked.chunk);
378
+ if (parts.length === 0) return;
379
+ try {
380
+ this.host.append(parts.length === 1 ? parts[0] : parts.join(""));
381
+ blocked?.resolve();
382
+ } catch (error) {
383
+ blocked?.reject(error);
384
+ this.fail(error);
385
+ throw error;
386
+ }
387
+ }
388
+ rejectPendingClose(reason) {
389
+ this.rejectClose?.(reason);
390
+ this.resolveClose = null;
391
+ this.rejectClose = null;
392
+ }
393
+ fail(reason) {
394
+ if (this.currentState !== "open") return;
395
+ this.currentState = "aborted";
396
+ this.terminalReason = reason;
397
+ this.cancelFrame();
398
+ this.chunks = [];
399
+ this.headIndex = 0;
400
+ this.headOffset = 0;
401
+ this.acceptedChars = 0;
402
+ const blocked = this.blocked;
403
+ this.blocked = null;
404
+ blocked?.reject(reason);
405
+ this.rejectPendingClose(reason);
406
+ this.cleanup();
407
+ }
408
+ cleanup() {
409
+ this.signal?.removeEventListener("abort", this.onSignalAbort);
410
+ if (this.released) return;
411
+ this.released = true;
412
+ this.host.release(this);
413
+ }
414
+ resetPacingIfIdle() {
415
+ if (this.acceptedChars !== 0 || this.blocked) return;
416
+ this.lastFrameAt = null;
417
+ this.graphemeCredit = 0;
418
+ }
419
+ };
420
+ function createStreamController(host, options = {}) {
421
+ return new StreamControllerImpl(host, options);
422
+ }
423
+
424
+ // src/Markdown.ts
16
425
  import { measureText, RichText, Stack, Table, Text, Image, UIComponent } from "@vectojs/ui";
17
426
 
18
427
  // src/MarkdownWorkerSource.ts
19
- var WORKER_SOURCE_STRING = '"use strict";(()=>{function N(){return{async:!1,breaks:!1,extensions:null,gfm:!0,hooks:null,pedantic:!1,renderer:null,silent:!1,tokenizer:null,walkTokens:null}}var T=N();function oe(r){T=r}var R={exec:()=>null};function A(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 k(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:A(r=>new RegExp(`^ {0,${r}}(?:[*+-]|\\\\d{1,9}[.)])((?:[ ][^\\\\n]*)?(?:\\\\n|$))`)),hrRegex:A(r=>new RegExp(`^ {0,${r}}((?:- *){3,}|(?:_ *){3,}|(?:\\\\* *){3,})(?:\\\\n+|$)`)),fencesBeginRegex:A(r=>new RegExp(`^ {0,${r}}(?:\\`\\`\\`|~~~)`)),headingBeginRegex:A(r=>new RegExp(`^ {0,${r}}#`)),htmlBeginRegex:A(r=>new RegExp(`^ {0,${r}}<(?:[a-z].*>|!--)`,"i")),blockquoteBeginRegex:A(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|$)|$)/,E=/^ {0,3}((?:-[\\t ]*){3,}|(?:_[ \\t]*){3,}|(?:\\*[ \\t]*){3,})(?:\\n+|$)/,Se=/^ {0,3}(#{1,6})(?=\\s|$)(.*)(?:\\n+|$)/,G=/ {0,3}(?:[*+-]|\\d{1,9}[.)])/,ce=/^(?!bull |blockCode|fences|blockquote|heading|html|table)((?:.|\\n(?!\\s*?\\n|bull |blockCode|fences|blockquote|heading|html|table))+?)\\n {0,3}(=+|-+) *(?:\\n+|$)/,he=k(ce).replace(/bull/g,G).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=k(ce).replace(/bull/g,G).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(),X=/^([^\\n]+(?:\\n(?!hr|heading|lheading|blockquote|fences|list|html|table|[ \\t]+\\n)[^\\n]+)*)/,ze=/^[^\\n]+/,W=/(?!\\s*\\])(?:\\\\[\\s\\S]|[^\\[\\]\\\\])+/,Ae=k(/^ {0,3}\\[(label)\\]: *(?:\\n[ \\t]*)?([^<\\s][^\\s]*|<.*?>)(?:(?: +(?:\\n[ \\t]*)?| *\\n[ \\t]*)(title))? *(?:\\n+|$)/).replace("label",W).replace("title",/(?:"(?:\\\\"?|[^"\\\\])*"|\'[^\'\\n]*(?:\\n[^\'\\n]+)*\\n?\'|\\([^()]*\\))/).getRegex(),Le=k(/^(bull)([ \\t][^\\n]*?)?(?:\\n|$)/).replace(/bull/g,G).getRegex(),Z="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",F=/<!--(?:-?>|[\\s\\S]*?(?:-->|$))/,_e=k("^ {0,3}(?:<(script|pre|style|textarea)[\\\\s>][\\\\s\\\\S]*?(?:</\\\\1>[^\\\\n]*\\\\n*|$)|comment[^\\\\n]*(\\\\n+|$)|<\\\\?[\\\\s\\\\S]*?(?:\\\\?>[^\\\\n]*\\\\n*|$)|<![A-Z][\\\\s\\\\S]*?(?:>[^\\\\n]*\\\\n*|$)|<!\\\\[CDATA\\\\[[\\\\s\\\\S]*?(?:\\\\]\\\\]>[^\\\\n]*\\\\n*|$)|</?(tag)(?: +|\\\\n|/?>)[\\\\s\\\\S]*?(?:(?:\\\\n[ ]*)+\\\\n|$)|<(?!script|pre|style|textarea)([a-z][\\\\w-]*)(?:attribute)*? */?>(?=[ \\\\t]*(?:\\\\n|$))[\\\\s\\\\S]*?(?:(?:\\\\n[ ]*)+\\\\n|$)|</(?!script|pre|style|textarea)[a-z][\\\\w-]*\\\\s*>(?=[ \\\\t]*(?:\\\\n|$))[\\\\s\\\\S]*?(?:(?:\\\\n[ ]*)+\\\\n|$))","i").replace("comment",F).replace("tag",Z).replace("attribute",/ +[a-zA-Z:_][\\w.:-]*(?: *= *"[^"\\n]*"| *= *\'[^\'\\n]*\'| *= *[^\\s"\'=<>`]+)?/).getRegex(),pe=r=>k(X).replace("hr",E).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",Z).getRegex(),Pe=pe(/ {0,3}(?:[*+-]|1[.)])[ \\t]+[^ \\t\\n]/),ve=pe(/ {0,3}(?:[*+-]|\\d{1,9}[.)])(?:[ \\t]|\\n|$)/),Ie=k(/^( {0,3}> ?(paragraph|[^\\n]*)(?:\\n|$))+/).replace("paragraph",ve).getRegex(),U={blockquote:Ie,code:$e,def:Ae,fences:Re,heading:Se,hr:E,html:_e,lheading:he,list:Le,newline:ye,paragraph:Pe,table:R,text:ze},te=k("^ *([^\\\\n ].*)\\\\n {0,3}((?:\\\\| *)?:?-+:? *(?:\\\\| *:?-+:? *)*(?:\\\\| *)?)(?:\\\\n((?:(?! *\\\\n|hr|heading|blockquote|code|fences|list|html).*(?:\\\\n|$))*)\\\\n*|$)").replace("hr",E).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",Z).getRegex(),Ee={...U,lheading:Te,table:te,paragraph:k(X).replace("hr",E).replace("heading"," {0,3}#{1,6}(?:\\\\s|$)").replace("|lheading","").replace("table",te).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",Z).getRegex()},Ce={...U,html:k(`^ *(?:comment *(?:\\\\n|\\\\s*$)|<(tag)[\\\\s\\\\S]+?</\\\\1> *(?:\\\\n{2,}|\\\\s*$)|<tag(?:"[^"]*"|\'[^\']*\'|\\\\s[^\'"/>\\\\s]*)*?/?> *(?:\\\\n{2,}|\\\\s*$))`).replace("comment",F).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:R,lheading:/^(.+?)\\n {0,3}(=+|-+) *(?:\\n+|$)/,paragraph:k(X).replace("hr",E).replace("heading",` *#{1,6} *[^\n]`).replace("lheading",he).replace("|table","").replace("blockquote"," {0,3}>").replace("|fences","").replace("|list","").replace("|html","").replace("|tag","").getRegex()},Be=/^\\\\([!"#$%&\'()*+,\\-./:;<=>?@\\[\\]\\\\^_`{|}~])/,qe=/^(`+)([^`]|[^`][\\s\\S]*?[^`])\\1(?!`)/,ue=/^( {2,}|\\\\)\\n(?!\\s*$)/,Me=/^(`+|[^`])(?:(?= {2,}\\n)|[\\s\\S]*?(?:(?=[\\\\<!\\[`*_]|\\b_|$)|[^ ](?= {2,}\\n)))/,L=/[\\p{P}\\p{S}]/u,D=/[\\s\\p{P}\\p{S}]/u,V=/[^\\s\\p{P}\\p{S}]/u,Ze=k(/^((?![*_])punctSpace)/,"u").replace(/punctSpace/g,D).getRegex(),ge=/(?!~)[\\p{P}\\p{S}]/u,De=/(?!~)[\\s\\p{P}\\p{S}]/u,Qe=/(?:[^\\s\\p{P}\\p{S}]|~)/u,je=k(/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(),ke=/^(?:\\*+(?:((?!\\*)punct)|([^\\s*]))?)|^_+(?:((?!_)punct)|([^\\s_]))?/,He=k(ke,"u").replace(/punct/g,L).getRegex(),Oe=k(ke,"u").replace(/punct/g,ge).getRegex(),de="^[^_*]*?__[^_*]*?\\\\*[^_*]*?(?=__)|[^*]+(?=[^*])|(?!\\\\*)punct(\\\\*+)(?=[\\\\s]|$)|notPunctSpace(\\\\*+)(?!\\\\*)(?=punctSpace|$)|(?!\\\\*)punctSpace(\\\\*+)(?=notPunctSpace)|[\\\\s](\\\\*+)(?!\\\\*)(?=punct)|(?!\\\\*)punct(\\\\*+)(?!\\\\*)(?=punct)|notPunctSpace(\\\\*+)(?=notPunctSpace)",Ne=k(de,"gu").replace(/notPunctSpace/g,V).replace(/punctSpace/g,D).replace(/punct/g,L).getRegex(),Ge=k(de,"gu").replace(/notPunctSpace/g,Qe).replace(/punctSpace/g,De).replace(/punct/g,ge).getRegex(),Xe=k("^[^_*]*?\\\\*\\\\*[^_*]*?_[^_*]*?(?=\\\\*\\\\*)|[^_]+(?=[^_])|(?!_)punct(_+)(?=[\\\\s]|$)|notPunctSpace(_+)(?!_)(?=punctSpace|$)|(?!_)punctSpace(_+)(?=notPunctSpace)|[\\\\s](_+)(?!_)(?=punct)|(?!_)punct(_+)(?!_)(?=punct)","gu").replace(/notPunctSpace/g,V).replace(/punctSpace/g,D).replace(/punct/g,L).getRegex(),We=k(/^~~?(?:((?!~)punct)|[^\\s~])/,"u").replace(/punct/g,L).getRegex(),Fe="^[^~]+(?=[^~])|(?!~)punct(~~?)(?=[\\\\s]|$)|notPunctSpace(~~?)(?!~)(?=punctSpace|$)|(?!~)punctSpace(~~?)(?=notPunctSpace)|[\\\\s](~~?)(?!~)(?=punct)|(?!~)punct(~~?)(?!~)(?=punct)|notPunctSpace(~~?)(?=notPunctSpace)",Ue=k(Fe,"gu").replace(/notPunctSpace/g,V).replace(/punctSpace/g,D).replace(/punct/g,L).getRegex(),Ve=k(/\\\\(punct)/,"gu").replace(/punct/g,L).getRegex(),Je=k(/^<(scheme:[^\\s\\x00-\\x1f<>]*|email)>/).replace("scheme",/[a-zA-Z][a-zA-Z0-9+.-]{1,31}/).replace("email",/[a-zA-Z0-9.!#$%&\'*+/=?^_`{|}~-]+(@)[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)+(?![-_])/).getRegex(),Ke=k(F).replace("(?:-->|$)","-->").getRegex(),Ye=k("^comment|^</[a-zA-Z][\\\\w:-]*\\\\s*>|^<[a-zA-Z][\\\\w-]*(?:attribute)*?\\\\s*/?>|^<\\\\?[\\\\s\\\\S]*?\\\\?>|^<![a-zA-Z]+\\\\s[\\\\s\\\\S]*?>|^<!\\\\[CDATA\\\\[[\\\\s\\\\S]*?\\\\]\\\\]>").replace("comment",Ke).replace("attribute",/\\s+[a-zA-Z:_][\\w.:-]*(?:\\s*=\\s*"[^"]*"|\\s*=\\s*\'[^\']*\'|\\s*=\\s*[^\\s"\'=<>`]+)?/).getRegex(),B=/(?:\\[(?:\\\\[\\s\\S]|[^\\[\\]\\\\])*\\]|\\\\[\\s\\S]|`+(?!`)[^`]*?`+(?!`)|``+(?=\\])|[^\\[\\]\\\\`])*?/,et=k(/^!?\\[(label)\\]\\(\\s*(href)(?:(?:[ \\t]+(?:\\n[ \\t]*)?|\\n[ \\t]*)(title))?\\s*\\)/).replace("label",B).replace("href",/<(?:\\\\.|[^\\n<>\\\\])+>|[^ \\t\\n\\x00-\\x1f]+|(?=\\))/).replace("title",/"(?:\\\\"?|[^"\\\\])*"|\'(?:\\\\\'?|[^\'\\\\])*\'|\\((?:\\\\\\)?|[^)\\\\])*\\)/).getRegex(),fe=k(/^!?\\[(label)\\]\\[(ref)\\]/).replace("label",B).replace("ref",W).getRegex(),xe=k(/^!?\\[(ref)\\](?:\\[\\])?/).replace("ref",W).getRegex(),tt=k("reflink|nolink(?!\\\\()","g").replace("reflink",fe).replace("nolink",xe).getRegex(),re=/[hH][tT][tT][pP][sS]?|[fF][tT][pP]/,J={_backpedal:R,anyPunctuation:Ve,autolink:Je,blockSkip:je,br:ue,code:qe,del:R,delLDelim:R,delRDelim:R,emStrongLDelim:He,emStrongRDelimAst:Ne,emStrongRDelimUnd:Xe,escape:Be,link:et,nolink:xe,punctuation:Ze,reflink:fe,reflinkSearch:tt,tag:Ye,text:Me,url:R},rt={...J,link:k(/^!?\\[(label)\\]\\((.*?)\\)/).replace("label",B).getRegex(),reflink:k(/^!?\\[(label)\\]\\s*\\[([^\\]]*)\\]/).replace("label",B).getRegex()},j={...J,emStrongRDelimAst:Ge,emStrongLDelim:Oe,delLDelim:We,delRDelim:Ue,url:k(/^((?:protocol):\\/\\/|www\\.)(?:[a-zA-Z0-9\\-]+\\.?)+[^\\s<]*|^email/).replace("protocol",re).replace("email",/[A-Za-z0-9._+-]+(@)[a-zA-Z0-9-_]+(?:\\.[a-zA-Z0-9-_]*[a-zA-Z0-9])+(?![-_])/).getRegex(),_backpedal:/(?:[^?!.,:;*_\'"~()&]+|\\([^)]*\\)|&(?![a-zA-Z0-9]+;$)|[?!.,:;*_\'"~)]+(?!$))+/,del:/^(~~?)(?=[^\\s~])((?:\\\\[\\s\\S]|[^\\\\])*?(?:\\\\[\\s\\S]|[^\\s~\\\\]))\\1(?=[^~]|$)/,text:k(/^(`+|~+|[^`~])(?:(?=[`~])|(?= {2,}\\n)|(?=[a-zA-Z0-9.!#$%&\'*+\\/=?_`{\\|}~-]+@)|[\\s\\S]*?(?:(?=[\\\\<!\\[`*~_]|\\b_|protocol:\\/\\/|www\\.|$)|[^ ](?= {2,}\\n)|[^a-zA-Z0-9.!#$%&\'*+\\/=?_`{\\|}~-](?=[a-zA-Z0-9.!#$%&\'*+\\/=?_`{\\|}~-]+@)))/).replace("protocol",re).getRegex()},nt={...j,br:k(ue).replace("{2,}","*").getRegex(),text:k(j.text).replace("\\\\b_","\\\\b_| {2,}\\\\n").replace(/\\{2,\\}/g,"*").getRegex()},C={normal:U,gfm:Ee,pedantic:Ce},v={normal:J,gfm:j,breaks:nt,pedantic:rt},st={"&":"&amp;","<":"&lt;",">":"&gt;",\'"\':"&quot;","\'":"&#39;"},ne=r=>st[r];function y(r,e){if(e){if(b.escapeTest.test(r))return r.replace(b.escapeReplace,ne)}else if(b.escapeTestNoEncode.test(r))return r.replace(b.escapeReplaceNoEncode,ne);return r}function se(r){try{r=encodeURI(r).replace(b.percentDecode,"%")}catch{return null}return r}function ie(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 $(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 le(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 ae(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||T}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]:le(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=$(t,"#");(this.options.pedantic||!s||this.rules.other.endingSpaceChar.test(s))&&(t=s.trim())}return{type:"heading",raw:$(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:$(e[0],`\n`)}}blockquote(r){let e=this.rules.block.blockquote.exec(r);if(e){let t=$(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 f=u,g=f.raw+`\n`+t.join(`\n`),x=this.blockquote(g);i[i.length-1]=x,s=s.substring(0,s.length-f.raw.length)+x.raw,n=n.substring(0,n.length-f.text.length)+x.text;break}else if(u?.type==="list"){let f=u,g=f.raw+`\n`+t.join(`\n`),x=this.list(g);i[i.length-1]=x,s=s.substring(0,s.length-u.raw.length)+x.raw,n=n.substring(0,n.length-f.raw.length)+x.raw,t=g.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],f=!h.trim(),g=0;if(this.options.pedantic?(g=2,p=h.trimStart()):f?g=e[1].length+1:(g=h.search(this.rules.other.nonSpaceChar),g=g>4?1:g,p=h.slice(g),g+=e[1].length),f&&this.rules.other.blankLine.test(u)&&(c+=u+`\n`,r=r.substring(u.length+1),o=!0),!o){let x=this.rules.other.nextBulletRegex(g),z=this.rules.other.hrRegex(g),Y=this.rules.other.fencesBeginRegex(g),ee=this.rules.other.headingBeginRegex(g),be=this.rules.other.htmlBeginRegex(g),we=this.rules.other.blockquoteBeginRegex(g);for(;r;){let Q=r.split(`\n`,1)[0],P;if(u=Q,this.options.pedantic?(u=u.replace(this.rules.other.listReplaceNesting," "),P=u):P=u.replace(this.rules.other.tabCharGlobal," "),Y.test(u)||ee.test(u)||be.test(u)||we.test(u)||x.test(u)||z.test(u))break;if(P.search(this.rules.other.nonSpaceChar)>=g||!u.trim())p+=`\n`+P.slice(g);else{if(f||h.replace(this.rules.other.tabCharGlobal," ").search(this.rules.other.nonSpaceChar)>=4||Y.test(h)||ee.test(h)||z.test(h))break;p+=`\n`+u}f=!u.trim(),c+=Q+`\n`,r=r.substring(Q.length+1),h=P.slice(g)}}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=le(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:$(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=ie(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:$(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(ie(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:$(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=$(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)),ae(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 ae(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 f=h.slice(1,-1);return{type:"em",raw:h,text:f,tokens:this.lexer.inlineTokens(f)}}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 H{tokens;options;state;inlineQueue;tokenizer;constructor(e){this.tokens=[],this.tokens.links=Object.create(null),this.options=e||T,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:C.normal,inline:v.normal};this.options.pedantic?(t.block=C.pedantic,t.inline=v.pedantic):this.options.gfm&&(t.block=C.gfm,this.options.breaks?t.inline=v.breaks:t.inline=v.gfm),this.tokenizer.rules=t}static get rules(){return{block:C,inline:v}}static lex(e,t){return new H(t).lex(e)}static lexInline(e,t){return new H(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)}},M=class{options;parser;constructor(r){this.options=r||T}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=se(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=se(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)}},K=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 O{options;renderer;textRenderer;constructor(e){this.options=e||T,this.options.renderer=this.options.renderer||new M,this.renderer=this.options.renderer,this.renderer.options=this.options,this.renderer.parser=this,this.textRenderer=new K}static parse(e,t){return new O(t).parse(e)}static parseInline(e,t){return new O(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}},I=class{options;block;constructor(r){this.options=r||T}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=N();options=this.setOptions;parse=this.parseMarkdown(!0);parseInline=this.parseMarkdown(!1);Parser=m;Renderer=M;TextRenderer=K;Lexer=w;Tokenizer=q;Hooks=I;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 M(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 I;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];I.passThroughHooks.has(i)?n[a]=c=>{if(this.defaults.async&&I.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}}},S=new ot;function d(r,e){return S.parse(r,e)}d.options=d.setOptions=function(r){return S.setOptions(r),d.defaults=S.defaults,oe(d.defaults),d};d.getDefaults=N;d.defaults=T;d.use=function(...r){return S.use(...r),d.defaults=S.defaults,oe(d.defaults),d};d.walkTokens=function(r,e){return S.walkTokens(r,e)};d.parseInline=S.parseInline;d.Parser=m;d.parser=m.parse;d.Renderer=M;d.TextRenderer=K;d.Lexer=w;d.lexer=w.lex;d.Tokenizer=q;d.Hooks=I;d.parse=d;var ct=d.options,ht=d.setOptions,pt=d.use,ut=d.walkTokens,gt=d.parseInline;var kt=m.parse,dt=w.lex;d.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 _=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}=e;if(c===!0){typeof l=="string"&&_.delete(l);return}let p=typeof l=="string"?l:null,h=typeof o=="number"?o:null,u,f=null;if(typeof n=="string"){if(p===null||h===null){self.postMessage({id:t,needResync:!0});return}let g=_.get(p);if(!g||g.version!==h){self.postMessage({id:t,needResync:!0});return}if(u=g.source+n,typeof i=="number"&&u.length!==i){_.delete(p),self.postMessage({id:t,needResync:!0});return}f=g.raws}else if(typeof s=="string"){if(u=s,Array.isArray(a))f=a;else if(p!==null&&h!==null){let g=_.get(p);if(g&&g.version===h)f=g.raws;else{self.postMessage({id:t,needResync:!0});return}}}else return;try{let g=d.lexer(u),x=0;if(f){let z=Math.min(f.length,g.length);for(;x<z&&f[x]===g[x].raw;x++);}p!==null&&h!==null&&_.set(p,{version:h+1,raws:g.map(z=>z.raw),source:u}),self.postMessage({id:t,matchLen:x,tail:g.slice(x)})}catch(g){p!==null&&_.delete(p),self.postMessage({id:t,error:String(g)})}};})();\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={"&":"&amp;","<":"&lt;",">":"&gt;",\'"\':"&quot;","\'":"&#39;"},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';
20
429
 
21
430
  // src/Markdown.ts
22
431
  var now = () => typeof performance !== "undefined" && typeof performance.now === "function" ? performance.now() : Date.now();
432
+ function lexMarkdown(text, userTiming) {
433
+ if (!userTiming) return marked.lexer(text);
434
+ const timing = beginVectoUserTiming(VECTO_USER_TIMING.markdown.parse);
435
+ try {
436
+ return marked.lexer(text);
437
+ } finally {
438
+ if (timing) endVectoUserTiming(timing);
439
+ }
440
+ }
23
441
  marked.use({
24
442
  extensions: [
25
443
  {
@@ -45,23 +463,183 @@ marked.use({
45
463
  }
46
464
  ]
47
465
  });
48
- var adaptor = liteAdaptor();
49
- RegisterHTMLHandler(adaptor);
50
- var tex = new TeX({ packages: AllPackages });
51
- var svg = new SVG({ fontCache: "local" });
52
- var htmlMathJax = mathjax.document("", { InputJax: tex, OutputJax: svg });
466
+ var mathConverter = null;
467
+ var mathLoad = null;
468
+ function interop(mod, key) {
469
+ const ns = mod;
470
+ if (typeof ns?.[key] !== "undefined") return ns;
471
+ const fallback = ns?.default;
472
+ if (fallback && typeof fallback[key] !== "undefined") return fallback;
473
+ throw new Error(`mathjax-full module is missing export "${key}"`);
474
+ }
475
+ function preloadMathJax() {
476
+ if (mathLoad) return mathLoad;
477
+ mathLoad = (async () => {
478
+ const [mathjaxMod, texMod, svgMod, adaptorMod, handlerMod, packagesMod] = await Promise.all([
479
+ import("mathjax-full/js/mathjax.js"),
480
+ import("mathjax-full/js/input/tex.js"),
481
+ import("mathjax-full/js/output/svg.js"),
482
+ import("mathjax-full/js/adaptors/liteAdaptor.js"),
483
+ import("mathjax-full/js/handlers/html.js"),
484
+ import("mathjax-full/js/input/tex/AllPackages.js")
485
+ ]);
486
+ const { mathjax } = interop(mathjaxMod, "mathjax");
487
+ const { TeX } = interop(texMod, "TeX");
488
+ const { SVG } = interop(svgMod, "SVG");
489
+ const { liteAdaptor } = interop(adaptorMod, "liteAdaptor");
490
+ const { RegisterHTMLHandler } = interop(handlerMod, "RegisterHTMLHandler");
491
+ const { AllPackages } = interop(packagesMod, "AllPackages");
492
+ const adaptor = liteAdaptor();
493
+ RegisterHTMLHandler(adaptor);
494
+ const tex = new TeX({ packages: AllPackages });
495
+ const svg = new SVG({ fontCache: "local" });
496
+ const htmlMathJax = mathjax.document("", { InputJax: tex, OutputJax: svg });
497
+ mathConverter = (formula, displayMode) => convertMathToSVGDataURI(
498
+ formula,
499
+ displayMode,
500
+ (f, d) => adaptor.innerHTML(htmlMathJax.convert(f, { display: d }))
501
+ );
502
+ })().catch((e) => {
503
+ console.error("MathJax failed to load; formulas will render as TeX source", e);
504
+ });
505
+ return mathLoad;
506
+ }
507
+ function isMathJaxReady() {
508
+ return mathConverter !== null;
509
+ }
510
+ var EX_PER_EM = 0.4421;
511
+ function exToPx(ex, fontSize) {
512
+ return ex * fontSize * EX_PER_EM;
513
+ }
514
+ function fontSizeFromFont(font) {
515
+ const pxIndex = font.indexOf("px");
516
+ if (pxIndex <= 0) return void 0;
517
+ let start = pxIndex;
518
+ while (start > 0) {
519
+ const ch = font[start - 1];
520
+ if (ch >= "0" && ch <= "9" || ch === ".") start--;
521
+ else break;
522
+ }
523
+ if (start === pxIndex) return void 0;
524
+ const size = parseFloat(font.slice(start, pxIndex));
525
+ return Number.isFinite(size) ? size : void 0;
526
+ }
527
+ var mathCache = /* @__PURE__ */ new Map();
528
+ var MATH_CACHE_LIMIT = 256;
529
+ var inlineMathRasters = /* @__PURE__ */ new Map();
530
+ var inlineMathRasterWaiters = /* @__PURE__ */ new Set();
531
+ function ensureInlineMathRaster(uri) {
532
+ const existing = inlineMathRasters.get(uri);
533
+ if (existing) return existing;
534
+ const entry = { decoded: false };
535
+ inlineMathRasters.set(uri, entry);
536
+ if (typeof globalThis.Image !== "undefined") {
537
+ const bitmap = new globalThis.Image();
538
+ bitmap.onload = () => {
539
+ entry.decoded = true;
540
+ for (const notify of inlineMathRasterWaiters) notify();
541
+ };
542
+ bitmap.src = uri;
543
+ entry.bitmap = bitmap;
544
+ }
545
+ return entry;
546
+ }
547
+ function paintInlineMath(uri, surface, box) {
548
+ const raster = ensureInlineMathRaster(uri);
549
+ if (!raster.decoded || !raster.bitmap) return;
550
+ surface.drawImage(raster.bitmap, box.x, box.y, box.width, box.height);
551
+ }
552
+ var MATH_LANGS = /* @__PURE__ */ new Set(["math", "latex", "tex"]);
553
+ function containsInlineMath(token) {
554
+ if (token.type === "inlineMath") return true;
555
+ const anyToken = token;
556
+ if (Array.isArray(anyToken.tokens) && anyToken.tokens.some(containsInlineMath)) {
557
+ return true;
558
+ }
559
+ if (Array.isArray(anyToken.items) && anyToken.items.some(containsInlineMath)) {
560
+ return true;
561
+ }
562
+ if (Array.isArray(anyToken.header) && anyToken.header.some(containsInlineMath)) {
563
+ return true;
564
+ }
565
+ if (Array.isArray(anyToken.rows)) {
566
+ for (const row of anyToken.rows) {
567
+ if (Array.isArray(row) && row.some(containsInlineMath)) return true;
568
+ }
569
+ }
570
+ return false;
571
+ }
572
+ var FENCE_OPEN_RE = /^ {0,3}(`{3,}|~{3,})/;
573
+ var FENCE_CLOSE_RE = /^ {0,3}(`+|~+)[ \t]*$/;
574
+ function isFenceClosed(raw) {
575
+ const lines = raw.split("\n");
576
+ const open = FENCE_OPEN_RE.exec(lines[0]);
577
+ if (!open) return false;
578
+ const marker = open[1][0];
579
+ const minLen = open[1].length;
580
+ for (let i = 1; i < lines.length; i++) {
581
+ const close = FENCE_CLOSE_RE.exec(lines[i]);
582
+ if (close && close[1][0] === marker && close[1].length >= minLen) return true;
583
+ }
584
+ return false;
585
+ }
586
+ function paragraphHasImage(token) {
587
+ return token.tokens?.some((child) => child.type === "image") === true;
588
+ }
589
+ function lastIndexOfImage(tokens) {
590
+ for (let i = tokens.length - 1; i >= 0; i--) {
591
+ if (tokens[i].type === "image") return i;
592
+ }
593
+ return -1;
594
+ }
595
+ function expectedImageParagraphChildren(tokens) {
596
+ let children = 0;
597
+ let inTextRun = false;
598
+ for (const token of tokens) {
599
+ if (token.type === "image") {
600
+ children++;
601
+ inTextRun = false;
602
+ } else if (!inTextRun) {
603
+ children++;
604
+ inTextRun = true;
605
+ }
606
+ }
607
+ return children;
608
+ }
609
+ function rendersAsMath(token) {
610
+ return MATH_LANGS.has((token.lang ?? "").toLowerCase()) && token.text.trim() !== "" && isFenceClosed(token.raw);
611
+ }
53
612
  function renderMathToSVGDataURI(formula, displayMode) {
613
+ const key = `${displayMode ? 1 : 0}\0${formula}`;
614
+ const hit = mathCache.get(key);
615
+ if (hit) return hit;
616
+ if (!mathConverter) return null;
617
+ const converted = mathConverter(formula, displayMode);
618
+ if (converted) {
619
+ if (mathCache.size >= MATH_CACHE_LIMIT) {
620
+ const oldest = mathCache.keys().next().value;
621
+ if (oldest !== void 0) mathCache.delete(oldest);
622
+ }
623
+ mathCache.set(key, converted);
624
+ }
625
+ return converted;
626
+ }
627
+ function convertMathToSVGDataURI(formula, displayMode, typeset) {
54
628
  try {
55
- const node = htmlMathJax.convert(formula, { display: displayMode });
56
- const svgString = adaptor.innerHTML(node);
629
+ const svgString = typeset(formula, displayMode);
57
630
  const wMatch = svgString.match(/width="([^"]+)ex"/);
58
631
  const hMatch = svgString.match(/height="([^"]+)ex"/);
59
632
  const wEx = wMatch ? parseFloat(wMatch[1]) : 10;
60
633
  const hEx = hMatch ? parseFloat(hMatch[1]) : 2;
61
- const width = wEx * 8;
62
- const height = hEx * 8;
634
+ const vMatch = svgString.match(/vertical-align:\s*(-?[\d.]+)ex/);
635
+ const depthEx = vMatch ? Math.max(0, -parseFloat(vMatch[1])) : 0;
63
636
  const base64 = btoa(unescape(encodeURIComponent(svgString)));
64
- return { uri: `data:image/svg+xml;base64,${base64}`, width, height };
637
+ return {
638
+ uri: `data:image/svg+xml;base64,${base64}`,
639
+ widthEx: wEx,
640
+ heightEx: hEx,
641
+ depthEx
642
+ };
65
643
  } catch (e) {
66
644
  console.error("MathJax error", e);
67
645
  return null;
@@ -73,9 +651,10 @@ var workerInstanceCounter = 0;
73
651
  var workerCallbacks = /* @__PURE__ */ new Map();
74
652
  function runSyncFallback(entry) {
75
653
  try {
76
- entry.cb(0, marked.lexer(entry.text), true);
654
+ entry.cb(0, lexMarkdown(entry.text, entry.userTiming), true);
77
655
  } catch (err) {
78
656
  console.warn("Markdown sync fallback parse failed", err);
657
+ entry.onDropped?.();
79
658
  }
80
659
  }
81
660
  if (typeof Worker !== "undefined") {
@@ -85,7 +664,7 @@ if (typeof Worker !== "undefined") {
85
664
  });
86
665
  markdownWorker = new Worker(URL.createObjectURL(blob));
87
666
  markdownWorker.onmessage = (e) => {
88
- const { id, matchLen, tail, error, needResync } = e.data;
667
+ const { id, matchLen, tail, error, needResync, lexerMs, sourceCharsLexed } = e.data;
89
668
  const entry = workerCallbacks.get(id);
90
669
  if (entry) {
91
670
  workerCallbacks.delete(id);
@@ -94,7 +673,10 @@ if (typeof Worker !== "undefined") {
94
673
  } else if (needResync) {
95
674
  runSyncFallback(entry);
96
675
  } else if (!error) {
97
- entry.cb(matchLen, tail);
676
+ entry.cb(matchLen, tail, false, {
677
+ lexerMs: typeof lexerMs === "number" ? lexerMs : 0,
678
+ sourceCharsLexed: typeof sourceCharsLexed === "number" ? sourceCharsLexed : 0
679
+ });
98
680
  } else {
99
681
  runSyncFallback(entry);
100
682
  }
@@ -598,13 +1180,13 @@ function codeAtlas() {
598
1180
  function decodeEntities(text) {
599
1181
  return text.replace(/&lt;/g, "<").replace(/&gt;/g, ">").replace(/&quot;/g, '"').replace(/&#39;/g, "'").replace(/&amp;/g, "&");
600
1182
  }
601
- function collectSpans(tokens, inherited, theme, out) {
1183
+ function collectSpans(tokens, inherited, theme, out, blockFontSize) {
602
1184
  for (const token of tokens) {
603
1185
  switch (token.type) {
604
1186
  case "strong": {
605
1187
  const t = token;
606
1188
  if (t.tokens) {
607
- collectSpans(t.tokens, { ...inherited, bold: true }, theme, out);
1189
+ collectSpans(t.tokens, { ...inherited, bold: true }, theme, out, blockFontSize);
608
1190
  } else {
609
1191
  out.push({
610
1192
  text: decodeEntities(t.text),
@@ -616,7 +1198,7 @@ function collectSpans(tokens, inherited, theme, out) {
616
1198
  case "em": {
617
1199
  const t = token;
618
1200
  if (t.tokens) {
619
- collectSpans(t.tokens, { ...inherited, italic: true }, theme, out);
1201
+ collectSpans(t.tokens, { ...inherited, italic: true }, theme, out, blockFontSize);
620
1202
  } else {
621
1203
  out.push({
622
1204
  text: decodeEntities(t.text),
@@ -652,10 +1234,31 @@ function collectSpans(tokens, inherited, theme, out) {
652
1234
  }
653
1235
  case "inlineMath": {
654
1236
  const t = token;
655
- out.push({
656
- text: decodeEntities(t.raw),
657
- style: { ...inherited, color: "#fcd34d" }
658
- });
1237
+ const runSize = inherited.fontSize ?? blockFontSize ?? theme.fontSize;
1238
+ const rendered = renderMathToSVGDataURI(t.text, false);
1239
+ if (rendered) {
1240
+ const uri = rendered.uri;
1241
+ out.push({
1242
+ text: OBJECT_REPLACEMENT,
1243
+ style: inherited,
1244
+ object: {
1245
+ width: exToPx(rendered.widthEx, runSize),
1246
+ height: exToPx(rendered.heightEx, runSize),
1247
+ depth: exToPx(rendered.depthEx, runSize),
1248
+ // The TeX source is the accessible name: without it a screen reader
1249
+ // receives only the invisible U+FFFC sentinel.
1250
+ alt: t.text,
1251
+ // Without this the box is reserved and stays empty. The engine does
1252
+ // not draw objects, and nothing else in the tree holds the raster.
1253
+ paint: (surface, box) => paintInlineMath(uri, surface, box)
1254
+ }
1255
+ });
1256
+ } else {
1257
+ out.push({
1258
+ text: decodeEntities(t.raw),
1259
+ style: { ...inherited, color: "#fcd34d" }
1260
+ });
1261
+ }
659
1262
  break;
660
1263
  }
661
1264
  case "link": {
@@ -666,7 +1269,7 @@ function collectSpans(tokens, inherited, theme, out) {
666
1269
  color: "#38bdf8"
667
1270
  };
668
1271
  if (t.tokens && t.tokens.length > 0) {
669
- collectSpans(t.tokens, linkStyle, theme, out);
1272
+ collectSpans(t.tokens, linkStyle, theme, out, blockFontSize);
670
1273
  } else {
671
1274
  out.push({ text: decodeEntities(t.text), style: linkStyle });
672
1275
  }
@@ -675,7 +1278,7 @@ function collectSpans(tokens, inherited, theme, out) {
675
1278
  case "text": {
676
1279
  const t = token;
677
1280
  if ("tokens" in t && t.tokens?.length) {
678
- collectSpans(t.tokens, inherited, theme, out);
1281
+ collectSpans(t.tokens, inherited, theme, out, blockFontSize);
679
1282
  } else {
680
1283
  const decoded = decodeEntities(t.text);
681
1284
  if (decoded) {
@@ -698,10 +1301,37 @@ function collectSpans(tokens, inherited, theme, out) {
698
1301
  }
699
1302
  }
700
1303
  }
1304
+ function findUnclosedInline(text) {
1305
+ let best = null;
1306
+ const tick = text.lastIndexOf("`");
1307
+ if (tick !== -1 && tick < text.length - 1) {
1308
+ return { kind: "codespan", at: tick, contentAt: tick + 1 };
1309
+ }
1310
+ if (tick !== -1) return null;
1311
+ const emphasis = /(\*{1,2}(?!\*)|_{1,2}(?!_))(?=[^\s])/g;
1312
+ for (let match = emphasis.exec(text); match !== null; match = emphasis.exec(text)) {
1313
+ const marker = match[1];
1314
+ const at = match.index;
1315
+ if (marker[0] === "_" && at > 0 && /[\w]/.test(text[at - 1])) continue;
1316
+ best = {
1317
+ kind: marker.length === 2 ? "strong" : "em",
1318
+ at,
1319
+ contentAt: at + marker.length
1320
+ };
1321
+ }
1322
+ const bracket = text.lastIndexOf("[");
1323
+ if (bracket !== -1 && bracket < text.length - 1 && (best === null || bracket > best.at)) {
1324
+ const closed = /\]\([^)]*\)/.test(text.slice(bracket));
1325
+ if (!closed) {
1326
+ best = { kind: "link", at: bracket, contentAt: bracket + 1 };
1327
+ }
1328
+ }
1329
+ return best;
1330
+ }
701
1331
  function renderInlineToRichText(tokens, fallbackText, font, color, maxWidth, theme, selectable, onLinkClick) {
702
1332
  const spans = [];
703
1333
  if (tokens && tokens.length > 0) {
704
- collectSpans(tokens, {}, theme, spans);
1334
+ collectSpans(tokens, {}, theme, spans, fontSizeFromFont(font));
705
1335
  }
706
1336
  if (spans.length === 0) {
707
1337
  spans.push({ text: decodeEntities(fallbackText) });
@@ -721,8 +1351,64 @@ var Markdown = class extends UIComponent {
721
1351
  theme;
722
1352
  onLinkClick;
723
1353
  selectable;
1354
+ activeBlockMetrics = null;
1355
+ /**
1356
+ * Called after a streamed append has re-laid-out the document.
1357
+ *
1358
+ * Not required for a `VirtualList` to track a streaming row's height: the list
1359
+ * re-reads `height` on every mounted row each frame, so it sees this entity grow
1360
+ * without being told. Prefer that over wiring this up — it fires from the append
1361
+ * path only, **not** from `setContent()`, so it is not a complete size signal.
1362
+ */
724
1363
  onLayoutUpdated;
725
1364
  rawMarkdown;
1365
+ streamController = null;
1366
+ /**
1367
+ * Trailing-unclosed-syntax policy of the active stream, or `'literal'` when no
1368
+ * stream is open.
1369
+ *
1370
+ * Held here rather than read back off the controller because it is a rendering
1371
+ * concern: `StreamController` owns buffering and pacing and has no view of the
1372
+ * entity tree, while the guess is a transform applied where spans are built.
1373
+ */
1374
+ streamIncompleteMode = "literal";
1375
+ /** End-of-stream callback of the active stream, if it supplied one. */
1376
+ streamOnStable = null;
1377
+ /**
1378
+ * The trailing paragraph entity currently showing an optimistic guess, plus the
1379
+ * token it was rendered from.
1380
+ *
1381
+ * Both halves are needed. The entity is what must be re-rendered to drop the
1382
+ * guess; the token is what it must be re-rendered FROM, and it is the only
1383
+ * copy — `this.tokens` has already moved on by the time an unwind is decided.
1384
+ * `null` means no guess is live, which is the state every `'literal'` stream
1385
+ * and every closed stream stays in.
1386
+ */
1387
+ optimisticTail = null;
1388
+ /** Resolvers waiting for every in-flight worker append to have been applied. */
1389
+ appendSettledWaiters = [];
1390
+ /** True only inside an `onStable` callback, to reject reentrant mutation. */
1391
+ inStableCallback = false;
1392
+ /** Set by {@link destroy} so late settlement work skips a torn-down tree. */
1393
+ isDestroyed = false;
1394
+ /**
1395
+ * This instance's entry in {@link inlineMathRasterWaiters}, or `undefined` if it
1396
+ * has never rendered inline math.
1397
+ *
1398
+ * Subscribed lazily so a document without formulas costs nothing, and held as a
1399
+ * field only so {@link destroy} can remove the exact closure it added.
1400
+ */
1401
+ inlineMathRepaint;
1402
+ /**
1403
+ * True while this document is waiting on the lazy MathJax load.
1404
+ *
1405
+ * Tracked per instance rather than read off the module state because it also
1406
+ * gates settlement: `await close()` and `onStable` must not resolve while a
1407
+ * formula is still showing TeX source, or a caller doing expensive one-time
1408
+ * work on a "final" document would measure and export placeholder boxes.
1409
+ */
1410
+ mathLoadPending = false;
1411
+ _userTiming;
726
1412
  tokens = [];
727
1413
  // At most one worker lex request in flight at a time. Required for the
728
1414
  // delta-transfer protocol below to be safe: the request captures a
@@ -737,19 +1423,38 @@ var Markdown = class extends UIComponent {
737
1423
  /**
738
1424
  * Streaming counters for the DevTools inspector.
739
1425
  *
740
- * Cheap enough to keep always-on (four integer increments per append) and the
741
- * only way to see, from outside, whether incremental reuse is actually working:
742
- * a stable-prefix ratio near 1 means the worker is matching almost everything
743
- * and only the tail is re-lexed, while a ratio near 0 means every chunk is
744
- * re-parsing the whole document.
1426
+ * Cheap enough to keep always-on (a handful of integer increments per append).
1427
+ *
1428
+ * These describe the **token diff and the transfer**, not the parser. `marked`
1429
+ * has no incremental lexing API, so the worker calls `marked.lexer()` on the
1430
+ * whole accumulated source for every chunk and the lexer's cost is O(document)
1431
+ * per append no matter how well the diff goes. That is what `lexerMs` and
1432
+ * `sourceCharsLexed` are for; an earlier version of these counters was named as
1433
+ * though a high prefix match meant less lexing, which sent readers to optimise
1434
+ * the already-solved transfer path.
745
1435
  */
746
1436
  streamStats = {
747
1437
  appends: 0,
748
1438
  workerResponses: 0,
749
- /** Sum of `matchLen` across responses, i.e. tokens reused rather than re-lexed. */
750
- tokensReused: 0,
751
- /** Sum of returned tail lengths, i.e. tokens the worker had to re-lex. */
752
- tokensRelexed: 0,
1439
+ /**
1440
+ * Sum of `matchLen`: leading tokens whose `raw` was unchanged, so the main
1441
+ * thread kept its existing token objects and child entities. A prefix match,
1442
+ * not a lexer saving — the worker still lexed them.
1443
+ */
1444
+ tokensPrefixMatched: 0,
1445
+ /**
1446
+ * Sum of returned tail lengths: tokens the worker sent back because their
1447
+ * `raw` differed. This is the structured-clone payload size in tokens, which
1448
+ * is what the delta protocol exists to keep small.
1449
+ */
1450
+ tokensReturned: 0,
1451
+ /** Total ms spent inside `marked.lexer()` across worker responses. */
1452
+ lexerMs: 0,
1453
+ /**
1454
+ * Characters handed to the lexer, summed across responses. Grows ~O(n^2) over
1455
+ * a stream of n chunks, because every chunk re-lexes the whole document.
1456
+ */
1457
+ sourceCharsLexed: 0,
753
1458
  /** Total round-trip ms across worker lex requests, dispatch to callback. */
754
1459
  workerMs: 0,
755
1460
  /** Longest single worker round trip, which is what a dropped frame feels. */
@@ -759,7 +1464,7 @@ var Markdown = class extends UIComponent {
759
1464
  * worker matched and did not re-read.
760
1465
  */
761
1466
  stablePrefixChars: 0,
762
- /** Source length of the tail that had to be re-lexed on the most recent append. */
1467
+ /** Source length of the tail whose tokens changed on the most recent append. */
763
1468
  changedTailChars: 0,
764
1469
  /** Child entities kept across reconciles, either untouched or updated in place. */
765
1470
  entitiesReused: 0,
@@ -832,6 +1537,7 @@ var Markdown = class extends UIComponent {
832
1537
  this.theme = { ...DEFAULT_THEME, ...opts.theme };
833
1538
  this.onLinkClick = opts.onLinkClick;
834
1539
  this.selectable = opts.selectable ?? true;
1540
+ this._userTiming = opts.userTiming ?? false;
835
1541
  this.content = new Stack({ direction: "vertical", gap: 16 });
836
1542
  this.add(this.content);
837
1543
  this.rawMarkdown = markdownText;
@@ -839,7 +1545,7 @@ var Markdown = class extends UIComponent {
839
1545
  this.renderMarkdown(markdownText);
840
1546
  }
841
1547
  renderMarkdown(text) {
842
- const tokens = marked.lexer(text);
1548
+ const tokens = lexMarkdown(text, this._userTiming);
843
1549
  this.setTokens(tokens);
844
1550
  for (const token of tokens) {
845
1551
  const el = this.renderToken(token);
@@ -850,12 +1556,53 @@ var Markdown = class extends UIComponent {
850
1556
  this.width = this.content.width;
851
1557
  this.height = this.content.height;
852
1558
  }
1559
+ /** Create a frame-coalesced stream bound to this Markdown instance. */
1560
+ createStream(options = {}) {
1561
+ if (this.streamController) {
1562
+ throw new Error("Markdown already has an active StreamController");
1563
+ }
1564
+ const controller = createStreamController(
1565
+ {
1566
+ append: (chunk) => this.appendMarkdownCore(chunk),
1567
+ release: (released) => {
1568
+ if (this.streamController !== released) return;
1569
+ this.streamController = null;
1570
+ this.streamIncompleteMode = "literal";
1571
+ this.streamOnStable = null;
1572
+ this.unwindOptimisticTail();
1573
+ },
1574
+ onClose: async () => {
1575
+ await this.waitForAppendSettled();
1576
+ if (this.isDestroyed) return;
1577
+ this.unwindOptimisticTail();
1578
+ const onStable = this.streamOnStable;
1579
+ if (!onStable) return;
1580
+ this.inStableCallback = true;
1581
+ try {
1582
+ onStable(Array.from(this.content.children));
1583
+ } finally {
1584
+ this.inStableCallback = false;
1585
+ }
1586
+ }
1587
+ },
1588
+ options
1589
+ );
1590
+ if (controller.state === "open") {
1591
+ this.streamController = controller;
1592
+ this.streamIncompleteMode = options.incompleteMode ?? "literal";
1593
+ this.streamOnStable = options.onStable ?? null;
1594
+ }
1595
+ return controller;
1596
+ }
853
1597
  /** Replace all markdown content (full rebuild). */
854
1598
  setContent(markdown) {
1599
+ this.assertNotInStableCallback("setContent");
1600
+ this.streamController?.abort(new Error("Markdown content was replaced"));
855
1601
  for (const id of this.pendingWorkerIds) workerCallbacks.delete(id);
856
1602
  this.pendingWorkerIds.clear();
857
1603
  this.appendInFlight = false;
858
1604
  this.appendPending = false;
1605
+ this.flushAppendSettledWaiters();
859
1606
  this.rawMarkdown = markdown;
860
1607
  this.workerSourceLen = 0;
861
1608
  while (this.content.children.length > 0) {
@@ -871,11 +1618,35 @@ var Markdown = class extends UIComponent {
871
1618
  * the whole subtree alive until the worker replied), then recurse into the
872
1619
  * content subtree via `super.destroy()` so every block's resources are freed.
873
1620
  */
1621
+ /**
1622
+ * Repaint this document when an inline formula's raster finishes decoding.
1623
+ *
1624
+ * Idempotent — called on every render of a math-bearing token, and the set holds
1625
+ * one closure per instance.
1626
+ */
1627
+ subscribeInlineMathRepaint() {
1628
+ if (this.inlineMathRepaint || this.isDestroyed) return;
1629
+ const repaint = () => {
1630
+ if (this.isDestroyed) return;
1631
+ this.scene?.markDirty();
1632
+ };
1633
+ this.inlineMathRepaint = repaint;
1634
+ inlineMathRasterWaiters.add(repaint);
1635
+ }
874
1636
  destroy() {
1637
+ this.isDestroyed = true;
1638
+ this.optimisticTail = null;
1639
+ this.streamController?.destroy();
875
1640
  for (const id of this.pendingWorkerIds) workerCallbacks.delete(id);
876
1641
  this.pendingWorkerIds.clear();
877
1642
  this.appendInFlight = false;
878
1643
  this.appendPending = false;
1644
+ this.mathLoadPending = false;
1645
+ this.flushAppendSettledWaiters();
1646
+ if (this.inlineMathRepaint) {
1647
+ inlineMathRasterWaiters.delete(this.inlineMathRepaint);
1648
+ this.inlineMathRepaint = void 0;
1649
+ }
879
1650
  markdownWorker?.postMessage({
880
1651
  instance: this.workerInstanceId,
881
1652
  dispose: true
@@ -886,15 +1657,17 @@ var Markdown = class extends UIComponent {
886
1657
  * Streaming and parse state — the markdown streaming inspector.
887
1658
  *
888
1659
  * Source length, chunk count, worker in-flight state, and the stable-prefix
889
- * versus re-lexed-tail split. That last ratio is the one worth watching: it is
1660
+ * versus changed-tail split. That last ratio is the one worth watching: it is
890
1661
  * how you tell incremental reuse is working from outside, and nothing else
891
1662
  * surfaces it. A ratio near 1 means the worker matched almost the whole prefix
892
- * and only re-lexed the tail; near 0 means every chunk re-parses the document.
1663
+ * and rebuilt only the tail's entities; near 0 means almost nothing was reused.
1664
+ * Neither says anything about lexer CPU, which is O(document) per append — that
1665
+ * is what the Parser cost group reports.
893
1666
  */
894
1667
  getDevtoolsDescriptor() {
895
1668
  const s = this.streamStats;
896
- const lexed = s.tokensReused + s.tokensRelexed;
897
- const reuseRatio = lexed > 0 ? s.tokensReused / lexed : 0;
1669
+ const diffedTokens = s.tokensPrefixMatched + s.tokensReturned;
1670
+ const tokenPrefixReuseRatio = diffedTokens > 0 ? s.tokensPrefixMatched / diffedTokens : 0;
898
1671
  return {
899
1672
  kind: "Markdown",
900
1673
  groups: [
@@ -966,7 +1739,7 @@ var Markdown = class extends UIComponent {
966
1739
  {
967
1740
  label: "changedTailChars",
968
1741
  value: s.changedTailChars,
969
- hint: "Source characters re-lexed on the last append. Growing with the document means O(document) per chunk",
1742
+ hint: "Source characters whose tokens changed on the last append. Growing with the document means the delta is not a delta",
970
1743
  readOnly: true
971
1744
  },
972
1745
  {
@@ -993,21 +1766,38 @@ var Markdown = class extends UIComponent {
993
1766
  label: "Incremental reuse",
994
1767
  fields: [
995
1768
  {
996
- label: "tokensReused",
997
- value: s.tokensReused,
998
- hint: "Sum of matchLen: prefix tokens the worker matched and did not re-lex",
1769
+ label: "tokensPrefixMatched",
1770
+ value: s.tokensPrefixMatched,
1771
+ hint: "Sum of matchLen: leading tokens whose raw was unchanged, so their entities were kept",
999
1772
  readOnly: true
1000
1773
  },
1001
1774
  {
1002
- label: "tokensRelexed",
1003
- value: s.tokensRelexed,
1004
- hint: "Sum of returned tail lengths: tokens the worker had to re-lex",
1775
+ label: "tokensReturned",
1776
+ value: s.tokensReturned,
1777
+ hint: "Sum of returned tail lengths: the changed suffix the worker cloned back",
1005
1778
  readOnly: true
1006
1779
  },
1007
1780
  {
1008
- label: "reuseRatio",
1009
- value: Math.round(reuseRatio * 1e3) / 1e3,
1010
- hint: "reused / (reused + relexed). Near 1 is healthy; near 0 means no reuse",
1781
+ label: "tokenPrefixReuseRatio",
1782
+ value: Math.round(tokenPrefixReuseRatio * 1e3) / 1e3,
1783
+ hint: "matched / (matched + returned). Near 1 means small transfers and high entity reuse \u2014 NOT less lexing",
1784
+ readOnly: true
1785
+ }
1786
+ ]
1787
+ },
1788
+ {
1789
+ label: "Parser cost",
1790
+ fields: [
1791
+ {
1792
+ label: "lexerMs",
1793
+ value: Math.round(s.lexerMs * 10) / 10,
1794
+ hint: "Total ms inside marked.lexer() \u2014 the whole source, every append",
1795
+ readOnly: true
1796
+ },
1797
+ {
1798
+ label: "sourceCharsLexed",
1799
+ value: s.sourceCharsLexed,
1800
+ hint: "Characters lexed, summed over appends. Grows ~O(n^2) across a stream",
1011
1801
  readOnly: true
1012
1802
  }
1013
1803
  ]
@@ -1015,13 +1805,22 @@ var Markdown = class extends UIComponent {
1015
1805
  ],
1016
1806
  notes: s.workerResponses === 0 && s.appends > 0 ? [
1017
1807
  "No worker responses yet: either the worker is unavailable and parsing ran synchronously on the main thread, or the first request is still in flight."
1018
- ] : reuseRatio > 0 && reuseRatio < 0.5 ? [
1019
- `Only ${Math.round(reuseRatio * 100)}% of lexed tokens were reused, so most of the document is being re-lexed per chunk. Expect O(document) work per append.`
1808
+ ] : tokenPrefixReuseRatio > 0 && tokenPrefixReuseRatio < 0.5 ? [
1809
+ `Only ${Math.round(tokenPrefixReuseRatio * 100)}% of tokens matched the prior prefix, so most of the token array is being returned and its entities rebuilt every chunk. Note the LEXER is O(document) per append regardless \u2014 see lexerMs.`
1020
1810
  ] : s.changedTailChars > 0 && this.rawMarkdown.length > 0 && s.changedTailChars / this.rawMarkdown.length > 0.5 ? [
1021
- `The last append re-lexed ${s.changedTailChars} of ${this.rawMarkdown.length} characters. A tail that grows with the document is the O(document)-per-chunk shape, even when the token reuse ratio looks healthy.`
1811
+ `The last append changed ${s.changedTailChars} of ${this.rawMarkdown.length} characters. A changed tail that grows with the document means the delta is not a delta, so almost every entity is rebuilt per chunk.`
1022
1812
  ] : void 0
1023
1813
  };
1024
1814
  }
1815
+ /** Enable or disable User Timing for subsequent parses. */
1816
+ setUserTiming(enabled) {
1817
+ this._userTiming = enabled;
1818
+ return this;
1819
+ }
1820
+ /** Whether Markdown parse User Timing is enabled. */
1821
+ get userTiming() {
1822
+ return this._userTiming;
1823
+ }
1025
1824
  /** Enable or disable native selection for existing and future Markdown text. */
1026
1825
  setSelectable(selectable) {
1027
1826
  this.selectable = selectable;
@@ -1036,11 +1835,16 @@ var Markdown = class extends UIComponent {
1036
1835
  }
1037
1836
  /** Append a markdown chunk incrementally. Reuses unchanged prefix entities. */
1038
1837
  appendMarkdown(chunk) {
1838
+ this.assertNotInStableCallback("appendMarkdown");
1839
+ this.streamController?.flush();
1840
+ return this.appendMarkdownCore(chunk);
1841
+ }
1842
+ appendMarkdownCore(chunk) {
1039
1843
  this.rawMarkdown += chunk;
1040
1844
  this.streamStats.appends++;
1041
1845
  if (!markdownWorker) {
1042
1846
  this.workerSourceLen = 0;
1043
- const newTokens = marked.lexer(this.rawMarkdown);
1847
+ const newTokens = lexMarkdown(this.rawMarkdown, this._userTiming);
1044
1848
  this.updateTokens(newTokens);
1045
1849
  return this;
1046
1850
  }
@@ -1076,11 +1880,15 @@ var Markdown = class extends UIComponent {
1076
1880
  const canSendDelta = !resync && this.workerSourceLen > 0 && this.workerSourceLen <= sentLength;
1077
1881
  this.pendingWorkerIds.add(id);
1078
1882
  workerCallbacks.set(id, {
1079
- cb: (matchLen, tail, local = false) => {
1883
+ cb: (matchLen, tail, local = false, lex) => {
1080
1884
  this.pendingWorkerIds.delete(id);
1081
1885
  this.streamStats.workerResponses++;
1082
- this.streamStats.tokensReused += matchLen;
1083
- this.streamStats.tokensRelexed += tail.length;
1886
+ this.streamStats.tokensPrefixMatched += matchLen;
1887
+ this.streamStats.tokensReturned += tail.length;
1888
+ if (lex) {
1889
+ this.streamStats.lexerMs += lex.lexerMs;
1890
+ this.streamStats.sourceCharsLexed += lex.sourceCharsLexed;
1891
+ }
1084
1892
  const elapsed = now() - dispatchedAt;
1085
1893
  this.streamStats.workerMs += elapsed;
1086
1894
  if (elapsed > this.streamStats.workerMsMax) this.streamStats.workerMsMax = elapsed;
@@ -1096,6 +1904,7 @@ var Markdown = class extends UIComponent {
1096
1904
  this.appendPending = false;
1097
1905
  this.dispatchAppend();
1098
1906
  }
1907
+ this.flushAppendSettledWaiters();
1099
1908
  },
1100
1909
  // The worker can't trust what it holds for this request; retry it once with
1101
1910
  // the full text and raws attached. `this.tokens` is untouched (no
@@ -1106,12 +1915,28 @@ var Markdown = class extends UIComponent {
1106
1915
  this.workerSourceLen = 0;
1107
1916
  this.dispatchAppend(true);
1108
1917
  },
1109
- text: this.rawMarkdown
1918
+ // Neither the worker nor the fallback lexer could produce tokens for this
1919
+ // request, so `this.tokens` stays as it was. Only the in-flight bookkeeping
1920
+ // needs unwinding — including any coalesced chunk waiting behind it, which
1921
+ // still has to be attempted.
1922
+ onDropped: () => {
1923
+ this.pendingWorkerIds.delete(id);
1924
+ this.appendInFlight = false;
1925
+ this.workerSourceLen = 0;
1926
+ if (this.appendPending) {
1927
+ this.appendPending = false;
1928
+ this.dispatchAppend(true);
1929
+ }
1930
+ this.flushAppendSettledWaiters();
1931
+ },
1932
+ text: this.rawMarkdown,
1933
+ userTiming: this._userTiming
1110
1934
  });
1111
1935
  markdownWorker.postMessage({
1112
1936
  id,
1113
1937
  instance: this.workerInstanceId,
1114
1938
  baseVersion,
1939
+ userTimingName: this._userTiming ? VECTO_USER_TIMING.markdown.parse : void 0,
1115
1940
  ...canSendDelta ? {
1116
1941
  append: this.rawMarkdown.slice(this.workerSourceLen),
1117
1942
  // What the worker's source must total once it applies this append. It
@@ -1125,6 +1950,647 @@ var Markdown = class extends UIComponent {
1125
1950
  }
1126
1951
  });
1127
1952
  }
1953
+ /**
1954
+ * Spans for one paragraph token exactly as `marked` produced it.
1955
+ *
1956
+ * The literal baseline: what every release renders, and what an optimistic
1957
+ * guess is unwound back to.
1958
+ */
1959
+ literalParagraphSpans(token) {
1960
+ const spans = [];
1961
+ if (token.tokens && token.tokens.length > 0) {
1962
+ collectSpans(token.tokens, {}, this.theme, spans);
1963
+ }
1964
+ if (spans.length === 0) spans.push({ text: token.text });
1965
+ return spans;
1966
+ }
1967
+ /**
1968
+ * Update a reused blockquote's tail child in place, or report that it cannot be.
1969
+ *
1970
+ * The render arm builds `container[border, innerStack]` where every inner block
1971
+ * sits in its own single-child `wrapper`, so the tail entity is
1972
+ * `innerStack.children.at(-1).children[0]`. Only the LAST inner block may be
1973
+ * updated: the inner token list is prefix-stable exactly like the top level (a
1974
+ * growing quote keeps its earlier blocks byte-identical), so anything before the
1975
+ * tail is untouched and anything more complicated than a changed tail falls back
1976
+ * to the caller's rebuild.
1977
+ *
1978
+ * Returns `false` without mutating anything when the shape is not the simple
1979
+ * grow-the-tail case, which is the signal for the caller to rebuild. Every early
1980
+ * return has to leave the entity untouched, or a rejected reuse would leave a
1981
+ * half-updated quote on screen.
1982
+ */
1983
+ /**
1984
+ * Build one list item's spans: inline content plus its marker.
1985
+ *
1986
+ * Shared by the `list` render arm and the streamed-reuse path below, because
1987
+ * the two must produce byte-identical spans — a reused list that disagreed with
1988
+ * a rebuilt one about its marker or its entity decoding would make a streamed
1989
+ * document differ from the same source pasted at once.
1990
+ */
1991
+ /**
1992
+ * Inline spans for one table cell.
1993
+ *
1994
+ * Always returns at least one span. A cell whose markup collapses to nothing —
1995
+ * an empty cell, but also a bare `<span>`, an image, or an HTML comment, none
1996
+ * of which `collectSpans` emits for — falls back to its decoded source text,
1997
+ * which is what the previous string-returning path rendered. That guarantee is
1998
+ * what lets every cell be a `RichText`: an empty cell would otherwise become a
1999
+ * `Text`, and since `Text` has `setText` while `RichText` has `setSpans` and
2000
+ * nothing converts between them, a cell that starts empty and later gains
2001
+ * content could not be updated in place. A streamed table needs exactly that,
2002
+ * because `marked` materializes a partial row as a full row of empty cells and
2003
+ * then fills them one at a time.
2004
+ */
2005
+ tableCellSpans(cell, t) {
2006
+ const spans = [];
2007
+ collectSpans(cell.tokens, {}, t, spans);
2008
+ if (spans.length === 0) spans.push({ text: decodeEntities(cell.text) });
2009
+ return spans;
2010
+ }
2011
+ /**
2012
+ * Spans for one run of consecutive non-image inline tokens.
2013
+ *
2014
+ * A paragraph holding an image renders as a `Stack` of alternating text runs
2015
+ * and images, and this is one text run. Shared by the render arm and
2016
+ * {@link updateImageParagraph} so a reused run cannot drift from a rebuilt one.
2017
+ *
2018
+ * The empty fallback mirrors `renderInlineToRichText('', …)`, which the render
2019
+ * arm passed for these runs: a run is only created when it has at least one
2020
+ * token, so the fallback is for tokens that emit no spans at all rather than
2021
+ * for an empty run.
2022
+ */
2023
+ inlineRunSpans(tokens, t) {
2024
+ const spans = [];
2025
+ if (tokens.length > 0) collectSpans(tokens, {}, t, spans);
2026
+ if (spans.length === 0) spans.push({ text: "" });
2027
+ return spans;
2028
+ }
2029
+ /** One text run of an image-bearing paragraph, as both paths build it. */
2030
+ inlineRunRichText(tokens, availableWidth, t) {
2031
+ return new RichText(this.inlineRunSpans(tokens, t), {
2032
+ font: `${t.fontSize}px ${t.bodyFont}`,
2033
+ color: t.textColor,
2034
+ maxWidth: availableWidth,
2035
+ linkColor: "#38bdf8",
2036
+ selectable: this.selectable,
2037
+ onLinkClick: this.onLinkClick
2038
+ });
2039
+ }
2040
+ /**
2041
+ * One image inside a paragraph, sized by a guess until its bitmap decodes.
2042
+ *
2043
+ * Width and height start at a 16:10 guess because the intrinsic size is not
2044
+ * known until the browser has the bitmap; `onLoad` corrects both from
2045
+ * `naturalWidth`/`naturalHeight`. Extracted from the render arm so the streamed
2046
+ * path reuses this exact entity rather than constructing a second variant.
2047
+ *
2048
+ * `markDirty()` is unconditional, matching the display-math sibling. It used
2049
+ * to sit inside the `naturalWidth && naturalHeight` check, which meant a
2050
+ * source that loads successfully while reporting a zero dimension left the
2051
+ * scene un-notified. `Image` sets `loaded` before invoking this callback, so
2052
+ * its `render()` starts drawing the bitmap either way — the cost was not a
2053
+ * stale placeholder but a box frozen at the guess: measured on Chromium and
2054
+ * Firefox, an `<svg width="0" height="0">` paragraph image kept 800x480 of
2055
+ * reserved layout forever while a normal raster corrected to 80x60. An
2056
+ * `onDemand` scene repaints only when marked, so nothing reclaimed it.
2057
+ *
2058
+ * The box is deliberately left at the guess when the bitmap reports zero.
2059
+ * Collapsing it to 0x0 would make the paragraph reflow correctly but would
2060
+ * also silently delete a reserved region on the strength of one browser
2061
+ * quirk, and `Image.render()` still blits whatever the bitmap holds. Sizing
2062
+ * policy for a zero-dimension source is a separate decision from notifying
2063
+ * the scene, which is the actual defect here.
2064
+ */
2065
+ paragraphImage(imgToken, availableWidth) {
2066
+ const initialWidth = Math.min(800, availableWidth);
2067
+ const initialHeight = Math.round(initialWidth * 0.6);
2068
+ const img = new Image(imgToken.href, {
2069
+ width: initialWidth,
2070
+ height: initialHeight,
2071
+ alt: imgToken.text,
2072
+ radius: 8,
2073
+ onLoad: () => {
2074
+ const bmp = img.bitmap;
2075
+ if (bmp && bmp.naturalWidth && bmp.naturalHeight) {
2076
+ const aspect = bmp.naturalHeight / bmp.naturalWidth;
2077
+ img.width = Math.min(bmp.naturalWidth, availableWidth);
2078
+ img.height = Math.round(img.width * aspect);
2079
+ }
2080
+ this.scene?.markDirty();
2081
+ }
2082
+ });
2083
+ return img;
2084
+ }
2085
+ /** One table cell entity, shared by the render arm and the streamed-table path. */
2086
+ tableCellRichText(cell, header, t) {
2087
+ return new RichText(this.tableCellSpans(cell, t), {
2088
+ font: `${t.fontSize - 2}px ${t.bodyFont}`,
2089
+ color: header ? t.headingColor : t.textColor,
2090
+ baseStyle: header ? { bold: true } : void 0,
2091
+ linkColor: "#38bdf8",
2092
+ selectable: this.selectable,
2093
+ onLinkClick: this.onLinkClick
2094
+ });
2095
+ }
2096
+ listItemSpans(token, index) {
2097
+ const item = token.items[index];
2098
+ const num = Number(token.start ?? 1) + index;
2099
+ const contentSpans = [];
2100
+ if (item.tokens && item.tokens.length > 0) {
2101
+ for (const inner of item.tokens) {
2102
+ if (inner.type === "text" && "tokens" in inner && inner.tokens?.length) {
2103
+ collectSpans(
2104
+ inner.tokens,
2105
+ {},
2106
+ this.theme,
2107
+ contentSpans
2108
+ );
2109
+ } else if ("tokens" in inner && inner.tokens?.length) {
2110
+ collectSpans(
2111
+ inner.tokens,
2112
+ {},
2113
+ this.theme,
2114
+ contentSpans
2115
+ );
2116
+ } else if ("text" in inner) {
2117
+ contentSpans.push({ text: decodeEntities(inner.text) });
2118
+ }
2119
+ }
2120
+ } else {
2121
+ contentSpans.push({ text: decodeEntities(item.text) });
2122
+ }
2123
+ const itemIsRtl = BidiResolver.getBaseLevel(contentSpans.map((s) => s.text).join("")) % 2 === 1;
2124
+ return itemIsRtl ? [...contentSpans, { text: token.ordered ? ` .${num}` : " \u2022" }] : [{ text: token.ordered ? `${num}. ` : "\u2022 " }, ...contentSpans];
2125
+ }
2126
+ /** Construct the `RichText` for one list item. */
2127
+ listItemRichText(token, index, availableWidth, t) {
2128
+ return new RichText(this.listItemSpans(token, index), {
2129
+ font: `${t.fontSize}px ${t.bodyFont}`,
2130
+ color: t.textColor,
2131
+ maxWidth: availableWidth,
2132
+ linkColor: "#38bdf8",
2133
+ selectable: this.selectable,
2134
+ onLinkClick: this.onLinkClick
2135
+ });
2136
+ }
2137
+ /**
2138
+ * Reuse a streamed list's `Stack` instead of rebuilding every item.
2139
+ *
2140
+ * Returns `false` to mean "rebuild instead", exactly like
2141
+ * {@link updateBlockquoteTail}, and every rejection path leaves the entity
2142
+ * untouched so a refused reuse cannot leave a half-updated list on screen.
2143
+ *
2144
+ * This is the shape a stream actually produces: items are APPENDED, and only
2145
+ * the last one grows. That matters for the ordinal marker, which is
2146
+ * position-derived (`start + index`) — under append an already-rendered item's
2147
+ * index never changes, so its marker stays correct. A mid-list insertion would
2148
+ * shift every later ordinal, but no stream produces one.
2149
+ *
2150
+ * Two traps this guards, both found by probing marked 18.0.7 rather than by
2151
+ * reading:
2152
+ *
2153
+ * - **A retained item's `raw` is NOT stable.** `items[1].raw` goes `"- two"` ->
2154
+ * `"- two\\n"` when item 3 arrives, so a byte-equality guard on `raw` fails on
2155
+ * every chunk and the fast path would never fire. `text` is stable; compare
2156
+ * that.
2157
+ * - **A tight list can become loose.** Adding a blank line flips
2158
+ * `token.loose`, which re-lexes every item's children from `text` to
2159
+ * `paragraph`. Item 0's own `text` is unchanged, so a naive guard would reuse
2160
+ * and keep stale spans. Bail when `loose` flips.
2161
+ */
2162
+ updateStreamedList(stack, oldToken, newToken) {
2163
+ if (!(stack instanceof Stack)) return false;
2164
+ if (newToken.items.length < oldToken.items.length || oldToken.items.length === 0) return false;
2165
+ if (oldToken.ordered !== newToken.ordered) return false;
2166
+ if ((oldToken.start ?? 1) !== (newToken.start ?? 1)) return false;
2167
+ if (oldToken.loose !== newToken.loose) return false;
2168
+ if (stack.children.length !== oldToken.items.length) return false;
2169
+ const lastRetained = oldToken.items.length - 1;
2170
+ for (let i = 0; i < lastRetained; i++) {
2171
+ if (oldToken.items[i].text !== newToken.items[i].text) return false;
2172
+ }
2173
+ const availableWidth = this.activeBlockMetrics?.availableWidth ?? this.maxWidth;
2174
+ const t = this.theme;
2175
+ const tailEntity = stack.children[lastRetained];
2176
+ if (oldToken.items[lastRetained].text !== newToken.items[lastRetained].text) {
2177
+ if (!("setSpans" in tailEntity)) return false;
2178
+ tailEntity.setSpans(
2179
+ this.listItemSpans(newToken, lastRetained)
2180
+ );
2181
+ }
2182
+ for (let i = oldToken.items.length; i < newToken.items.length; i++) {
2183
+ stack.add(this.listItemRichText(newToken, i, availableWidth, t));
2184
+ }
2185
+ const last = stack.children.at(-1);
2186
+ if (last) stack.resizeLastChild(last);
2187
+ return true;
2188
+ }
2189
+ /**
2190
+ * Reuse a streamed image-bearing paragraph's `Stack` instead of rebuilding it.
2191
+ *
2192
+ * Returns `false` to mean "rebuild instead", and every rejection happens before
2193
+ * any mutation, so a refused reuse leaves the entity exactly as it was.
2194
+ *
2195
+ * This was the last silent fallthrough in the in-place reuse path. A paragraph
2196
+ * holding an image renders as a `Stack` of alternating text runs and images
2197
+ * rather than one `RichText`, so it has no `setSpans` and failed the ordinary
2198
+ * paragraph gate — with no `else`, which is what made the miss invisible:
2199
+ * `inPlaceUpdates` stayed flat while `entitiesRebuilt` climbed. Measured on a
2200
+ * six-chunk stream, `inPlaceUpdates` 0 / `entitiesRebuilt` 4 with an image
2201
+ * against 4 / 0 for the identical shape without one. Every rebuild also
2202
+ * re-created the `Image`, discarding its decoded bitmap and its corrected
2203
+ * intrinsic size.
2204
+ *
2205
+ * It is *only* a performance path. The obvious worry — that a fresh `Image`
2206
+ * starts at `loaded = false` and so repaints its placeholder slab — was
2207
+ * measured and does not happen: sampling the real canvas pixel at the image
2208
+ * centre in both Chromium and Firefox gives zero placeholder frames after the
2209
+ * first paint, at 60ms and at 0ms between chunks, because a cached bitmap
2210
+ * decodes before the next frame.
2211
+ *
2212
+ * The reuse is deliberately narrow: **only a growing trailing text run**. Probed
2213
+ * against `marked@18.0.7`, that is the shape a stream actually produces once an
2214
+ * image has closed — the image token's `raw` and its index are then stable while
2215
+ * trailing prose grows, and the token list settles at
2216
+ * `[…, image, text]` and stops changing length. Anything else (a new image
2217
+ * arriving, an image token changing, a run appearing before the last image)
2218
+ * falls through to the rebuild, which is correct and rare.
2219
+ *
2220
+ * Note the child list is not one entity per token: consecutive non-image tokens
2221
+ * are merged into one `RichText` by the render arm's `flushText`, so
2222
+ * `[text, text, image]` is two children, not three. The guards therefore compare
2223
+ * *token runs* split at the last image, never token index against child index.
2224
+ */
2225
+ updateImageParagraph(entity, oldToken, newToken) {
2226
+ if (!(entity instanceof Stack)) return false;
2227
+ const oldTokens = oldToken.tokens;
2228
+ const newTokens = newToken.tokens;
2229
+ if (!oldTokens || !newTokens) return false;
2230
+ const oldLastImage = lastIndexOfImage(oldTokens);
2231
+ const newLastImage = lastIndexOfImage(newTokens);
2232
+ if (oldLastImage < 0 || newLastImage < 0) return false;
2233
+ if (oldLastImage !== newLastImage) return false;
2234
+ for (let i = 0; i <= newLastImage; i++) {
2235
+ if (oldTokens[i].raw !== newTokens[i].raw) return false;
2236
+ }
2237
+ const oldTail = oldTokens.slice(oldLastImage + 1);
2238
+ const newTail = newTokens.slice(newLastImage + 1);
2239
+ if (newTail.length === 0) return false;
2240
+ const oldTailRaw = oldTail.map((t2) => t2.raw).join("");
2241
+ const newTailRaw = newTail.map((t2) => t2.raw).join("");
2242
+ if (!newTailRaw.startsWith(oldTailRaw)) return false;
2243
+ const expectedOldChildren = expectedImageParagraphChildren(oldTokens);
2244
+ if (entity.children.length !== expectedOldChildren) return false;
2245
+ const t = this.theme;
2246
+ const availableWidth = this.activeBlockMetrics?.availableWidth ?? this.maxWidth;
2247
+ if (oldTail.length === 0) {
2248
+ entity.add(this.inlineRunRichText(newTail, availableWidth, t));
2249
+ } else {
2250
+ const tailEntity = entity.children[entity.children.length - 1];
2251
+ if (!(tailEntity instanceof RichText)) return false;
2252
+ tailEntity.setSpans(this.inlineRunSpans(newTail, t));
2253
+ }
2254
+ const last = entity.children[entity.children.length - 1];
2255
+ if (last) entity.resizeLastChild(last);
2256
+ return true;
2257
+ }
2258
+ /**
2259
+ * Reuse a streamed table's `Table` entity instead of rebuilding every cell.
2260
+ *
2261
+ * Returns `false` to mean "rebuild instead", and every rejection happens before
2262
+ * any mutation, so a refused reuse leaves the entity exactly as it was.
2263
+ *
2264
+ * A `table` token carries every row, so the rebuild path costs Θ(C·N²)
2265
+ * `RichText` constructions across a stream — and a further 2×, because
2266
+ * `Table.layout()` re-runs `fitCell` on every cell. This was the last block
2267
+ * type without an in-place path.
2268
+ *
2269
+ * Two shapes have to be handled, because of how `marked` lexes a growing table
2270
+ * (probed against 18.0.7): a partial row is materialized immediately as a FULL
2271
+ * row padded with empty cells, and its cells are then filled one at a time. A
2272
+ * 2×2 table passes through eleven distinct row states, of which only two are
2273
+ * clean row appends. So handling appends alone would reject most chunks and
2274
+ * leave the quadratic cost essentially in place:
2275
+ *
2276
+ * 1. the last row's cells are rewritten in place via `setSpans`, and
2277
+ * 2. genuinely new rows go through `Table.appendRows`.
2278
+ *
2279
+ * Cells are compared by `text`, never `raw` — a table cell has no `raw` at all
2280
+ * (its keys are `text`/`tokens`/`header`/`align`).
2281
+ */
2282
+ updateStreamedTable(entity, oldToken, newToken) {
2283
+ if (!(entity instanceof Table)) return false;
2284
+ if (oldToken.header.length !== newToken.header.length) return false;
2285
+ for (let c = 0; c < oldToken.header.length; c++) {
2286
+ if (oldToken.header[c].text !== newToken.header[c].text) return false;
2287
+ }
2288
+ if (newToken.rows.length < oldToken.rows.length) return false;
2289
+ if (entity.rows.length !== oldToken.rows.length) return false;
2290
+ const lastRetained = oldToken.rows.length - 1;
2291
+ for (let r = 0; r < lastRetained; r++) {
2292
+ const oldRow = oldToken.rows[r];
2293
+ const newRow = newToken.rows[r];
2294
+ for (let c = 0; c < oldToken.header.length; c++) {
2295
+ if (oldRow[c]?.text !== newRow[c]?.text) return false;
2296
+ }
2297
+ }
2298
+ if (lastRetained >= 0) {
2299
+ for (let c = 0; c < oldToken.header.length; c++) {
2300
+ const cell = entity.rows[lastRetained]?.[c];
2301
+ if (!(cell instanceof RichText)) return false;
2302
+ }
2303
+ }
2304
+ const t = this.theme;
2305
+ let changed = false;
2306
+ if (lastRetained >= 0) {
2307
+ const oldRow = oldToken.rows[lastRetained];
2308
+ const newRow = newToken.rows[lastRetained];
2309
+ for (let c = 0; c < oldToken.header.length; c++) {
2310
+ if (oldRow[c]?.text === newRow[c]?.text) continue;
2311
+ const cell = entity.rows[lastRetained][c];
2312
+ cell.setSpans(this.tableCellSpans(newRow[c], t));
2313
+ changed = true;
2314
+ }
2315
+ }
2316
+ if (newToken.rows.length > oldToken.rows.length) {
2317
+ const added = newToken.rows.slice(oldToken.rows.length).map((row) => row.map((cell) => this.tableCellRichText(cell, false, t)));
2318
+ entity.appendRows(added);
2319
+ } else if (changed) {
2320
+ entity.layout();
2321
+ }
2322
+ return true;
2323
+ }
2324
+ updateBlockquoteTail(container, oldInner, newInner) {
2325
+ if (oldInner.length !== newInner.length || newInner.length === 0) return false;
2326
+ const tail = newInner.length - 1;
2327
+ for (let i = 0; i < tail; i++) {
2328
+ if (oldInner[i].raw !== newInner[i].raw) return false;
2329
+ }
2330
+ const oldTail = oldInner[tail];
2331
+ const newTail = newInner[tail];
2332
+ if (oldTail.type !== newTail.type) return false;
2333
+ const innerStack = container.children[1];
2334
+ if (!(innerStack instanceof Stack)) return false;
2335
+ const wrapper = innerStack.children.at(-1);
2336
+ if (!wrapper || wrapper.children.length !== 1) return false;
2337
+ const entity = wrapper.children[0];
2338
+ if (!this.producesEntity(newTail)) return false;
2339
+ if (newTail.type === "paragraph" && "setSpans" in entity) {
2340
+ entity.setSpans(
2341
+ this.literalParagraphSpans(newTail)
2342
+ );
2343
+ } else if (newTail.type === "heading" && "setSpans" in entity) {
2344
+ if (oldTail.depth !== newTail.depth) {
2345
+ return false;
2346
+ }
2347
+ entity.setSpans(
2348
+ this.headingSpans(newTail)
2349
+ );
2350
+ } else if (newTail.type === "code" && entity instanceof CodeBlock && !rendersAsMath(newTail)) {
2351
+ const codeToken = newTail;
2352
+ entity.setCode(codeToken.text, codeToken.lang ?? void 0);
2353
+ } else {
2354
+ return false;
2355
+ }
2356
+ wrapper.width = entity.x + entity.width;
2357
+ wrapper.height = entity.height;
2358
+ innerStack.resizeLastChild(wrapper);
2359
+ const border = container.children[0];
2360
+ if (border instanceof QuoteBorder) border.height = innerStack.height || 20;
2361
+ container.height = Math.max(border?.height ?? 0, innerStack.height);
2362
+ return true;
2363
+ }
2364
+ /**
2365
+ * Spans for a heading being updated in place.
2366
+ *
2367
+ * Kept in lockstep with the `heading` arm of {@link renderToken}, which builds
2368
+ * its `RichText` through `renderInlineToRichText`: same `collectSpans` call and
2369
+ * the same `decodeEntities` fallback when a heading has no inline tokens (`##`
2370
+ * with no text yet, which a stream produces before its first word arrives). A
2371
+ * plain `token.text` fallback here would leave an entity-bearing heading
2372
+ * undecoded on the in-place path but decoded on a fresh render.
2373
+ */
2374
+ headingSpans(token) {
2375
+ const spans = [];
2376
+ if (token.tokens && token.tokens.length > 0) {
2377
+ collectSpans(token.tokens, {}, this.theme, spans);
2378
+ }
2379
+ if (spans.length === 0) spans.push({ text: decodeEntities(token.text) });
2380
+ return spans;
2381
+ }
2382
+ /**
2383
+ * Spans for the trailing paragraph with its last unclosed inline construct
2384
+ * rendered as though it had closed, or `null` when there is nothing to guess.
2385
+ *
2386
+ * `null` is the answer for every `'literal'` stream, every closed or absent
2387
+ * stream, and any trailing paragraph whose syntax is all balanced — so the
2388
+ * caller falls back to {@link literalParagraphSpans} and pays nothing.
2389
+ *
2390
+ * Only the paragraph's LAST inline token is scanned. An unclosed construct can
2391
+ * only be there: anything that closed is already its own `strong`/`em`/
2392
+ * `codespan`/`link` token, so a syntax character surviving into a trailing
2393
+ * plain-text run is one `marked` could not pair. Scanning the whole raw string
2394
+ * instead would re-find the markers of already-closed constructs.
2395
+ */
2396
+ optimisticParagraphSpans(token) {
2397
+ if (this.streamIncompleteMode !== "optimistic") return null;
2398
+ if (this.streamController?.state !== "open") return null;
2399
+ const inline = token.tokens;
2400
+ if (!inline || inline.length === 0) return null;
2401
+ let runLength = 1;
2402
+ let runText;
2403
+ const last = inline[inline.length - 1];
2404
+ const prev = inline.length > 1 ? inline[inline.length - 2] : null;
2405
+ const isFlatText = (token2) => token2.type === "text" && !token2.tokens?.length;
2406
+ if (last.type === "link" && last.raw === last.text && prev !== null && isFlatText(prev) && prev.text.endsWith("](")) {
2407
+ runLength = 2;
2408
+ runText = prev.text + last.raw;
2409
+ } else if (isFlatText(last)) {
2410
+ runText = last.text;
2411
+ } else {
2412
+ return null;
2413
+ }
2414
+ const found = findUnclosedInline(runText);
2415
+ if (!found) return null;
2416
+ const spans = [];
2417
+ if (inline.length > runLength) {
2418
+ collectSpans(inline.slice(0, -runLength), {}, this.theme, spans);
2419
+ }
2420
+ const head = runText.slice(0, found.at);
2421
+ if (head) spans.push({ text: decodeEntities(head) });
2422
+ let content = runText.slice(found.contentAt);
2423
+ if (found.kind === "link") {
2424
+ const close = content.indexOf("](");
2425
+ if (close !== -1) content = content.slice(0, close);
2426
+ }
2427
+ if (!content) return null;
2428
+ const style = this.optimisticStyle(found.kind);
2429
+ spans.push({ text: decodeEntities(content), style });
2430
+ return spans;
2431
+ }
2432
+ /** Display style for a guessed-closed construct. */
2433
+ optimisticStyle(kind) {
2434
+ switch (kind) {
2435
+ case "strong":
2436
+ return { bold: true };
2437
+ case "em":
2438
+ return { italic: true };
2439
+ case "codespan":
2440
+ return { color: this.theme.codeColor, fontFamily: this.theme.codeFont };
2441
+ // A link with no closing paren has no href, so it renders as plain text —
2442
+ // no link color and no click affordance for a destination nobody has yet.
2443
+ case "link":
2444
+ return void 0;
2445
+ }
2446
+ }
2447
+ /**
2448
+ * Re-render the paragraph currently showing a guess from its own tokens, with
2449
+ * no overlay, and forget it.
2450
+ *
2451
+ * Idempotent and free when no guess is live, which is what lets `close()`,
2452
+ * `abort()`, and a mid-stream staleness check all call it unconditionally.
2453
+ */
2454
+ /**
2455
+ * Start the MathJax load, and re-typeset this document once it resolves.
2456
+ *
2457
+ * Called from two places, for two different reasons:
2458
+ *
2459
+ * - When an OPEN math fence is rendered. This is a prefetch, and it is what
2460
+ * makes the lazy load invisible while streaming: the module starts loading
2461
+ * the moment a formula begins arriving, several chunks before its closing
2462
+ * fence, so by the time the fence closes the converter is usually already
2463
+ * installed and the formula typesets synchronously on the normal path.
2464
+ * - When a CLOSED fence could not be typeset because the module is not ready.
2465
+ * That is the case a rebuild actually exists for: a document constructed with
2466
+ * math already complete, or a stream that closed a fence faster than the
2467
+ * module loaded.
2468
+ *
2469
+ * Idempotent per instance. Concurrent callers coalesce onto the one cached
2470
+ * module promise, and `mathLoadPending` keeps a second rebuild from being
2471
+ * queued while the first is outstanding.
2472
+ */
2473
+ ensureMathJax() {
2474
+ if (mathConverter || this.mathLoadPending || this.isDestroyed) return;
2475
+ this.mathLoadPending = true;
2476
+ void preloadMathJax().then(() => {
2477
+ this.mathLoadPending = false;
2478
+ if (this.isDestroyed) return;
2479
+ if (mathConverter) this.retypesetFromTokens();
2480
+ this.flushAppendSettledWaiters();
2481
+ });
2482
+ }
2483
+ /**
2484
+ * Rebuild every block from the tokens already lexed, without re-lexing.
2485
+ *
2486
+ * Used only when MathJax arrives after a formula has already been rendered as
2487
+ * source. Rebuilding wholesale rather than surgically replacing the math blocks
2488
+ * is the deliberate choice: `tokenChildPrefix` maps token indices to child
2489
+ * slots positionally, so swapping one child in place would have to keep that
2490
+ * mapping, the `Stack`'s cached box, and every following sibling's position in
2491
+ * agreement by hand. Re-rendering the same token list in the same order leaves
2492
+ * the mapping trivially correct, and this runs at most once per document — the
2493
+ * same cost as the `setContent` rebuild that already exists.
2494
+ *
2495
+ * The optimistic tail is dropped first. Its `entity` is about to be destroyed,
2496
+ * so the pointer would dangle; unwinding restores literal spans, and if the
2497
+ * stream is still open the next chunk re-applies a guess.
2498
+ */
2499
+ retypesetFromTokens() {
2500
+ this.unwindOptimisticTail();
2501
+ const tokens = this.tokens;
2502
+ while (this.content.children.length > 0) {
2503
+ this.content.children[this.content.children.length - 1].destroy();
2504
+ }
2505
+ for (const token of tokens) {
2506
+ const el = this.renderToken(token);
2507
+ if (el) this.content.add(el);
2508
+ }
2509
+ this.width = this.content.width;
2510
+ this.height = this.content.height;
2511
+ this.scene?.markDirty();
2512
+ }
2513
+ unwindOptimisticTail() {
2514
+ const tail = this.optimisticTail;
2515
+ this.optimisticTail = null;
2516
+ if (!tail || this.isDestroyed) return;
2517
+ const entity = tail.entity;
2518
+ if (!entity.setSpans || entity.parent !== this.content) return;
2519
+ entity.setSpans(this.literalParagraphSpans(tail.token));
2520
+ if (this.content.children.at(-1) === entity) {
2521
+ this.content.resizeLastChild(entity);
2522
+ } else {
2523
+ this.content.layout();
2524
+ }
2525
+ this.width = this.content.width;
2526
+ this.height = this.content.height;
2527
+ this.scene?.markDirty();
2528
+ }
2529
+ /**
2530
+ * Drop a guess that is no longer on the document's trailing paragraph.
2531
+ *
2532
+ * A coalesced append can add a block after the paragraph that owns the guess,
2533
+ * at which point the guess is frozen — the construct can never close, because
2534
+ * no further text lands in that paragraph. Without this the stale styling would
2535
+ * survive until `close()`.
2536
+ *
2537
+ * `writtenThisPass` is the entity whose spans this reconcile already rewrote,
2538
+ * if any: for that one, literal spans are on screen already and re-rendering it
2539
+ * would be wasted layout, so only the bookkeeping is cleared.
2540
+ */
2541
+ dropStaleOptimisticTail(trailing, writtenThisPass) {
2542
+ const tail = this.optimisticTail;
2543
+ if (!tail || tail.entity === trailing) return;
2544
+ if (tail.entity === writtenThisPass) {
2545
+ this.optimisticTail = null;
2546
+ return;
2547
+ }
2548
+ this.unwindOptimisticTail();
2549
+ }
2550
+ /**
2551
+ * Resolve once every in-flight worker append has actually been applied.
2552
+ *
2553
+ * Committing text is not the same as the document reflecting it: `append()`
2554
+ * reaches `dispatchAppend()`, which `postMessage()`s and returns, and the reply
2555
+ * that runs `updateTokens()` lands later. Without waiting here, `close()` could
2556
+ * resolve — and `onStable` fire — against a document missing its last chunk.
2557
+ *
2558
+ * An outstanding lazy MathJax load counts as unsettled for the same reason. A
2559
+ * document whose formulas are still TeX source is not final in any sense a
2560
+ * caller of `onStable` cares about: the boxes are the wrong size, so measuring
2561
+ * or exporting there would capture placeholders.
2562
+ */
2563
+ waitForAppendSettled() {
2564
+ if (!this.appendInFlight && !this.mathLoadPending) return Promise.resolve();
2565
+ return new Promise((resolve) => {
2566
+ this.appendSettledWaiters.push(resolve);
2567
+ });
2568
+ }
2569
+ /**
2570
+ * Release settlement waiters, but only once nothing is outstanding.
2571
+ *
2572
+ * Called at the very END of the worker callback, after its coalesced-re-dispatch
2573
+ * check, rather than wherever `appendInFlight` goes false. Within that callback
2574
+ * `appendInFlight` is cleared and then, if another chunk arrived while the
2575
+ * request was in flight, set straight back to `true` by the re-dispatch — both
2576
+ * synchronously, before anything watching the flag could observe the gap. Only
2577
+ * checking here, after that, waits through the re-dispatch instead of resolving
2578
+ * one chunk early.
2579
+ */
2580
+ flushAppendSettledWaiters() {
2581
+ if (this.appendInFlight || this.mathLoadPending || this.appendSettledWaiters.length === 0) {
2582
+ return;
2583
+ }
2584
+ const waiters = this.appendSettledWaiters;
2585
+ this.appendSettledWaiters = [];
2586
+ for (const resolve of waiters) resolve();
2587
+ }
2588
+ /** Throw if a public mutation is attempted from inside an `onStable` callback. */
2589
+ assertNotInStableCallback(method) {
2590
+ if (this.inStableCallback) {
2591
+ throw new Error(`Markdown.${method}() cannot be called from an onStable callback`);
2592
+ }
2593
+ }
1128
2594
  updateTokens(newTokens, knownMatchLen) {
1129
2595
  const oldTokens = this.tokens;
1130
2596
  const oldChildren = [...this.content.children];
@@ -1144,11 +2610,18 @@ var Markdown = class extends UIComponent {
1144
2610
  }
1145
2611
  const oldTokenToChild = this.tokenChildPrefix;
1146
2612
  const rawMatchLen = matchLen;
2613
+ let pendingTail = null;
2614
+ let spansWrittenTo = null;
1147
2615
  const lastTokenSameType = matchLen === oldTokens.length - 1 && matchLen < newTokens.length && oldTokens[matchLen]?.type === newTokens[matchLen]?.type;
1148
2616
  if (lastTokenSameType && newTokens[matchLen]?.type === "code") {
1149
2617
  const existingEntity = oldChildren[oldTokenToChild[matchLen]];
1150
2618
  const codeToken = newTokens[matchLen];
1151
- if (existingEntity instanceof CodeBlock) {
2619
+ const oldCodeToken = oldTokens[matchLen];
2620
+ const isMath = rendersAsMath(codeToken);
2621
+ if (isMath && rendersAsMath(oldCodeToken) && oldCodeToken.text === codeToken.text) {
2622
+ this.streamStats.inPlaceUpdates++;
2623
+ matchLen++;
2624
+ } else if (existingEntity instanceof CodeBlock && !isMath) {
1152
2625
  existingEntity.setCode(codeToken.text, codeToken.lang ?? void 0);
1153
2626
  this.streamStats.inPlaceUpdates++;
1154
2627
  matchLen++;
@@ -1157,17 +2630,63 @@ var Markdown = class extends UIComponent {
1157
2630
  } else if (lastTokenSameType && newTokens[matchLen]?.type === "paragraph") {
1158
2631
  const entityIdx = oldTokenToChild[matchLen];
1159
2632
  const existingEntity = oldChildren[entityIdx];
1160
- if (existingEntity && "setSpans" in existingEntity) {
2633
+ if (existingEntity && "setSpans" in existingEntity && !paragraphHasImage(newTokens[matchLen])) {
1161
2634
  const pToken = newTokens[matchLen];
1162
- const t = this.theme;
1163
- const spans = [];
1164
- if (pToken.tokens && pToken.tokens.length > 0) {
1165
- collectSpans(pToken.tokens, {}, t, spans);
1166
- }
1167
- if (spans.length === 0) {
1168
- spans.push({ text: pToken.text });
1169
- }
1170
- existingEntity.setSpans(spans);
2635
+ const isTrailing = matchLen === newTokens.length - 1;
2636
+ const optimistic = isTrailing ? this.optimisticParagraphSpans(pToken) : null;
2637
+ existingEntity.setSpans(optimistic ?? this.literalParagraphSpans(pToken));
2638
+ spansWrittenTo = existingEntity;
2639
+ if (optimistic) pendingTail = { entity: existingEntity, token: pToken };
2640
+ this.streamStats.inPlaceUpdates++;
2641
+ matchLen++;
2642
+ this.content.resizeLastChild(existingEntity);
2643
+ } else if (existingEntity && this.updateImageParagraph(
2644
+ existingEntity,
2645
+ oldTokens[matchLen],
2646
+ newTokens[matchLen]
2647
+ )) {
2648
+ this.streamStats.inPlaceUpdates++;
2649
+ matchLen++;
2650
+ this.content.resizeLastChild(existingEntity);
2651
+ }
2652
+ } else if (lastTokenSameType && newTokens[matchLen]?.type === "heading") {
2653
+ const existingEntity = oldChildren[oldTokenToChild[matchLen]];
2654
+ const hToken = newTokens[matchLen];
2655
+ const oldToken = oldTokens[matchLen];
2656
+ if (existingEntity && "setSpans" in existingEntity && oldToken?.depth === hToken.depth) {
2657
+ existingEntity.setSpans(this.headingSpans(hToken));
2658
+ spansWrittenTo = existingEntity;
2659
+ this.streamStats.inPlaceUpdates++;
2660
+ matchLen++;
2661
+ this.content.resizeLastChild(existingEntity);
2662
+ }
2663
+ } else if (lastTokenSameType && newTokens[matchLen]?.type === "blockquote") {
2664
+ const existingEntity = oldChildren[oldTokenToChild[matchLen]];
2665
+ const newInner = newTokens[matchLen].tokens;
2666
+ const oldInner = oldTokens[matchLen].tokens;
2667
+ if (existingEntity instanceof MarkdownContainer && newInner && oldInner && this.updateBlockquoteTail(existingEntity, oldInner, newInner)) {
2668
+ this.streamStats.inPlaceUpdates++;
2669
+ matchLen++;
2670
+ this.content.resizeLastChild(existingEntity);
2671
+ }
2672
+ } else if (lastTokenSameType && newTokens[matchLen]?.type === "list") {
2673
+ const existingEntity = oldChildren[oldTokenToChild[matchLen]];
2674
+ if (existingEntity && this.updateStreamedList(
2675
+ existingEntity,
2676
+ oldTokens[matchLen],
2677
+ newTokens[matchLen]
2678
+ )) {
2679
+ this.streamStats.inPlaceUpdates++;
2680
+ matchLen++;
2681
+ this.content.resizeLastChild(existingEntity);
2682
+ }
2683
+ } else if (lastTokenSameType && newTokens[matchLen]?.type === "table") {
2684
+ const existingEntity = oldChildren[oldTokenToChild[matchLen]];
2685
+ if (existingEntity && this.updateStreamedTable(
2686
+ existingEntity,
2687
+ oldTokens[matchLen],
2688
+ newTokens[matchLen]
2689
+ )) {
1171
2690
  this.streamStats.inPlaceUpdates++;
1172
2691
  matchLen++;
1173
2692
  this.content.resizeLastChild(existingEntity);
@@ -1185,10 +2704,24 @@ var Markdown = class extends UIComponent {
1185
2704
  }
1186
2705
  }
1187
2706
  }
2707
+ const lastIndex = newTokens.length - 1;
1188
2708
  for (let i = matchLen; i < newTokens.length; i++) {
1189
2709
  const el = this.renderToken(newTokens[i]);
1190
- if (el) this.content.add(el);
2710
+ if (!el) continue;
2711
+ this.content.add(el);
2712
+ if (i === lastIndex && newTokens[i].type === "paragraph" && "setSpans" in el) {
2713
+ const pToken = newTokens[i];
2714
+ const optimistic = this.optimisticParagraphSpans(pToken);
2715
+ if (optimistic) {
2716
+ el.setSpans(optimistic);
2717
+ this.content.resizeLastChild(el);
2718
+ pendingTail = { entity: el, token: pToken };
2719
+ spansWrittenTo = el;
2720
+ }
2721
+ }
1191
2722
  }
2723
+ this.dropStaleOptimisticTail(pendingTail?.entity ?? null, spansWrittenTo);
2724
+ if (pendingTail) this.optimisticTail = pendingTail;
1192
2725
  this.setTokens(newTokens, rawMatchLen);
1193
2726
  this.width = this.content.width;
1194
2727
  this.height = this.content.height;
@@ -1197,6 +2730,19 @@ var Markdown = class extends UIComponent {
1197
2730
  this.onLayoutUpdated();
1198
2731
  }
1199
2732
  }
2733
+ /**
2734
+ * Render one nested block with a temporary width/margin context while
2735
+ * preserving `renderToken` as the subclass override seam.
2736
+ */
2737
+ renderTokenWithMetrics(token, metrics) {
2738
+ const previous = this.activeBlockMetrics;
2739
+ this.activeBlockMetrics = metrics;
2740
+ try {
2741
+ return this.renderToken(token);
2742
+ } finally {
2743
+ this.activeBlockMetrics = previous;
2744
+ }
2745
+ }
1200
2746
  /**
1201
2747
  * Whether {@link renderToken} produces a child entity for this token (vs
1202
2748
  * `null`). `updateTokens` maps token indices to child-entity indices, and the
@@ -1231,6 +2777,17 @@ var Markdown = class extends UIComponent {
1231
2777
  renderToken(token) {
1232
2778
  const t = this.theme;
1233
2779
  const bodyFont = `${t.fontSize}px ${t.bodyFont}`;
2780
+ const metrics = this.activeBlockMetrics ?? {
2781
+ marginBefore: 0,
2782
+ marginAfter: 0,
2783
+ indentStart: 0,
2784
+ availableWidth: this.maxWidth
2785
+ };
2786
+ const availableWidth = metrics.availableWidth;
2787
+ if (containsInlineMath(token)) {
2788
+ if (!mathConverter) this.ensureMathJax();
2789
+ this.subscribeInlineMathRepaint();
2790
+ }
1234
2791
  switch (token.type) {
1235
2792
  // ── Headings ─────────────────────────────────────────────────────
1236
2793
  case "heading": {
@@ -1243,7 +2800,7 @@ var Markdown = class extends UIComponent {
1243
2800
  hToken.text,
1244
2801
  headingFont,
1245
2802
  t.headingColor,
1246
- this.maxWidth,
2803
+ availableWidth,
1247
2804
  t,
1248
2805
  this.selectable,
1249
2806
  this.onLinkClick
@@ -1252,13 +2809,13 @@ var Markdown = class extends UIComponent {
1252
2809
  // ── Paragraphs ───────────────────────────────────────────────────
1253
2810
  case "paragraph": {
1254
2811
  const pToken = token;
1255
- if (!pToken.tokens || !pToken.tokens.some((t2) => t2.type === "image")) {
2812
+ if (!paragraphHasImage(pToken)) {
1256
2813
  return renderInlineToRichText(
1257
2814
  pToken.tokens,
1258
2815
  pToken.text,
1259
2816
  bodyFont,
1260
2817
  t.textColor,
1261
- this.maxWidth,
2818
+ availableWidth,
1262
2819
  t,
1263
2820
  this.selectable,
1264
2821
  this.onLinkClick
@@ -1267,48 +2824,19 @@ var Markdown = class extends UIComponent {
1267
2824
  const stack = new Stack({
1268
2825
  direction: "vertical",
1269
2826
  gap: 16,
1270
- maxWidth: this.maxWidth
2827
+ maxWidth: availableWidth
1271
2828
  });
1272
2829
  let currentTokens = [];
1273
2830
  const flushText = () => {
1274
2831
  if (currentTokens.length > 0) {
1275
- stack.add(
1276
- renderInlineToRichText(
1277
- currentTokens,
1278
- "",
1279
- bodyFont,
1280
- t.textColor,
1281
- this.maxWidth,
1282
- t,
1283
- this.selectable,
1284
- this.onLinkClick
1285
- )
1286
- );
2832
+ stack.add(this.inlineRunRichText(currentTokens, availableWidth, t));
1287
2833
  currentTokens = [];
1288
2834
  }
1289
2835
  };
1290
2836
  for (const child of pToken.tokens) {
1291
2837
  if (child.type === "image") {
1292
2838
  flushText();
1293
- const imgToken = child;
1294
- const initialWidth = Math.min(800, this.maxWidth);
1295
- const initialHeight = Math.round(initialWidth * 0.6);
1296
- const img = new Image(imgToken.href, {
1297
- width: initialWidth,
1298
- height: initialHeight,
1299
- alt: imgToken.text,
1300
- radius: 8,
1301
- onLoad: () => {
1302
- const bmp = img.bitmap;
1303
- if (bmp && bmp.naturalWidth && bmp.naturalHeight) {
1304
- const aspect = bmp.naturalHeight / bmp.naturalWidth;
1305
- img.width = Math.min(bmp.naturalWidth, this.maxWidth);
1306
- img.height = Math.round(img.width * aspect);
1307
- if (this.scene) this.scene.markDirty();
1308
- }
1309
- }
1310
- });
1311
- stack.add(img);
2839
+ stack.add(this.paragraphImage(child, availableWidth));
1312
2840
  } else {
1313
2841
  currentTokens.push(child);
1314
2842
  }
@@ -1320,13 +2848,22 @@ var Markdown = class extends UIComponent {
1320
2848
  case "code": {
1321
2849
  const codeToken = token;
1322
2850
  const lang = (codeToken.lang ?? "").toLowerCase();
1323
- if (lang === "math" || lang === "latex" || lang === "tex") {
2851
+ if (MATH_LANGS.has(lang)) this.ensureMathJax();
2852
+ if (rendersAsMath(codeToken)) {
1324
2853
  const mathData = renderMathToSVGDataURI(codeToken.text, true);
1325
2854
  if (mathData) {
2855
+ const intrinsicW = exToPx(mathData.widthEx, t.fontSize);
2856
+ const intrinsicH = exToPx(mathData.heightEx, t.fontSize);
1326
2857
  const mathImg = new Image(mathData.uri, {
1327
- width: Math.min(this.maxWidth, mathData.width),
1328
- height: mathData.height * Math.min(1, this.maxWidth / mathData.width),
1329
- alt: codeToken.text
2858
+ width: Math.min(availableWidth, intrinsicW),
2859
+ height: intrinsicH * Math.min(1, availableWidth / intrinsicW),
2860
+ alt: codeToken.text,
2861
+ // The SVG decodes asynchronously and Image paints a placeholder
2862
+ // until it lands. Without this an `onDemand` scene, which repaints
2863
+ // only when marked dirty, leaves the formula a blank slab forever.
2864
+ onLoad: () => {
2865
+ this.scene?.markDirty();
2866
+ }
1330
2867
  });
1331
2868
  const wrapper = new MarkdownContainer();
1332
2869
  mathImg.x = 16;
@@ -1337,20 +2874,27 @@ var Markdown = class extends UIComponent {
1337
2874
  return wrapper;
1338
2875
  }
1339
2876
  }
1340
- return new CodeBlock(codeToken.text, lang, this.maxWidth, t, this.selectable);
2877
+ return new CodeBlock(codeToken.text, lang, availableWidth, t, this.selectable);
1341
2878
  }
1342
2879
  // ── Blockquotes ──────────────────────────────────────────────────
1343
2880
  case "blockquote": {
1344
2881
  const bqToken = token;
1345
2882
  const innerStack = new Stack({ direction: "vertical", gap: 8 });
2883
+ const indentStart = Math.min(16, availableWidth);
2884
+ const childMetrics = {
2885
+ marginBefore: 0,
2886
+ marginAfter: 0,
2887
+ indentStart,
2888
+ availableWidth: Math.max(0, availableWidth - indentStart)
2889
+ };
1346
2890
  if (bqToken.tokens) {
1347
2891
  for (const inner of bqToken.tokens) {
1348
- const el = this.renderToken(inner);
2892
+ const el = this.renderTokenWithMetrics(inner, childMetrics);
1349
2893
  if (el) {
1350
2894
  const wrapper = new MarkdownContainer();
1351
- el.x = 16;
2895
+ el.x = childMetrics.indentStart;
1352
2896
  wrapper.add(el);
1353
- wrapper.width = el.width + 16;
2897
+ wrapper.width = el.width + childMetrics.indentStart;
1354
2898
  wrapper.height = el.height;
1355
2899
  innerStack.add(wrapper);
1356
2900
  }
@@ -1364,70 +2908,30 @@ var Markdown = class extends UIComponent {
1364
2908
  innerStack.y = 0;
1365
2909
  innerStack.x = 0;
1366
2910
  container.add(innerStack);
1367
- container.width = this.maxWidth;
2911
+ container.width = availableWidth;
1368
2912
  container.height = Math.max(border.height, innerStack.height);
1369
2913
  return container;
1370
2914
  }
1371
- // ── Lists ────────────────────────────────────────────────────────
2915
+ // ── Lists ────────────────────────────────────────────────
1372
2916
  case "list": {
1373
2917
  const listToken = token;
1374
2918
  const listStack = new Stack({ direction: "vertical", gap: 6 });
1375
2919
  for (let i = 0; i < listToken.items.length; i++) {
1376
- const item = listToken.items[i];
1377
- const num = Number(listToken.start ?? 1) + i;
1378
- const contentSpans = [];
1379
- if (item.tokens && item.tokens.length > 0) {
1380
- for (const inner of item.tokens) {
1381
- if (inner.type === "text" && "tokens" in inner && inner.tokens?.length) {
1382
- collectSpans(inner.tokens, {}, t, contentSpans);
1383
- } else if ("tokens" in inner && inner.tokens?.length) {
1384
- collectSpans(inner.tokens, {}, t, contentSpans);
1385
- } else if ("text" in inner) {
1386
- contentSpans.push({
1387
- text: decodeEntities(inner.text)
1388
- });
1389
- }
1390
- }
1391
- } else {
1392
- contentSpans.push({ text: decodeEntities(item.text) });
1393
- }
1394
- const itemIsRtl = BidiResolver.getBaseLevel(contentSpans.map((s) => s.text).join("")) % 2 === 1;
1395
- const itemSpans = itemIsRtl ? [...contentSpans, { text: listToken.ordered ? ` .${num}` : " \u2022" }] : [{ text: listToken.ordered ? `${num}. ` : "\u2022 " }, ...contentSpans];
1396
- const itemRt = new RichText(itemSpans, {
1397
- font: bodyFont,
1398
- color: t.textColor,
1399
- maxWidth: this.maxWidth - 24,
1400
- linkColor: "#38bdf8",
1401
- selectable: this.selectable,
1402
- onLinkClick: this.onLinkClick
1403
- });
1404
- itemRt.x = 12;
1405
- listStack.add(itemRt);
2920
+ listStack.add(this.listItemRichText(listToken, i, availableWidth, t));
1406
2921
  }
1407
2922
  return listStack;
1408
2923
  }
1409
2924
  // ── Table ────────────────────────────────────────────────────────
1410
2925
  case "table": {
1411
2926
  const tblToken = token;
1412
- const buildCell = (cell, header) => {
1413
- const spans = [];
1414
- collectSpans(cell.tokens, {}, t, spans);
1415
- if (spans.length === 0) return decodeEntities(cell.text);
1416
- return new RichText(spans, {
1417
- font: `${t.fontSize - 2}px ${t.bodyFont}`,
1418
- color: header ? t.headingColor : t.textColor,
1419
- baseStyle: header ? { bold: true } : void 0,
1420
- linkColor: "#38bdf8",
1421
- selectable: this.selectable,
1422
- onLinkClick: this.onLinkClick
1423
- });
1424
- };
1425
- const headers = tblToken.header.map((cell) => buildCell(cell, true));
1426
- const rows = tblToken.rows.map((row) => row.map((cell) => buildCell(cell, false)));
2927
+ const headers = tblToken.header.map((cell) => this.tableCellRichText(cell, true, t));
2928
+ const rows = tblToken.rows.map(
2929
+ (row) => row.map((cell) => this.tableCellRichText(cell, false, t))
2930
+ );
1427
2931
  return new Table({
1428
2932
  headers,
1429
2933
  rows,
1430
- width: this.maxWidth,
2934
+ width: availableWidth,
1431
2935
  textColor: t.textColor,
1432
2936
  headerTextColor: t.headingColor,
1433
2937
  font: `${t.fontSize - 2}px ${t.bodyFont}`,
@@ -1439,7 +2943,7 @@ var Markdown = class extends UIComponent {
1439
2943
  }
1440
2944
  // ── Horizontal rule ──────────────────────────────────────────────
1441
2945
  case "hr":
1442
- return new HorizontalRule(this.maxWidth, t.hrColor);
2946
+ return new HorizontalRule(availableWidth, t.hrColor);
1443
2947
  // ── Whitespace ───────────────────────────────────────────────────
1444
2948
  case "space":
1445
2949
  return null;
@@ -1457,7 +2961,7 @@ var Markdown = class extends UIComponent {
1457
2961
  return new Text(token.text, {
1458
2962
  font: bodyFont,
1459
2963
  color: t.textColor,
1460
- maxWidth: this.maxWidth,
2964
+ maxWidth: availableWidth,
1461
2965
  lineHeight: 24,
1462
2966
  selectable: this.selectable
1463
2967
  });
@@ -1473,5 +2977,7 @@ export {
1473
2977
  CodeBlock,
1474
2978
  Markdown,
1475
2979
  codeAtlas,
1476
- codeAtlasStats
2980
+ codeAtlasStats,
2981
+ isMathJaxReady,
2982
+ preloadMathJax
1477
2983
  };