@simon_he/vue-tui 1.1.5 → 1.1.6

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/agent.cjs CHANGED
@@ -5673,7 +5673,7 @@ function pickBestTerminalGraphicsProtocol(protocols) {
5673
5673
  }
5674
5674
  function detectCandidates(env) {
5675
5675
  let candidates = [], term = String(envString(env, "TERM") ?? "").toLowerCase(), termProgram = String(envString(env, "TERM_PROGRAM") ?? "").toLowerCase(), termProgramVersion = String(envString(env, "TERM_PROGRAM_VERSION") ?? "").toLowerCase();
5676
- return (envString(env, "KITTY_WINDOW_ID") || envString(env, "GHOSTTY_RESOURCES_DIR") || /(?:^|-)kitty(?:-|$)/i.test(term) || term.includes("ghostty") || termProgram.includes("ghostty")) && candidates.push("kitty"), (termProgram.includes("iterm") || termProgram.includes("wezterm") || envString(env, "WEZTERM_PANE") || envString(env, "WEZTERM_EXECUTABLE")) && candidates.push("iterm2"), (truthy(envString(env, "VUE_TUI_SIXEL")) || truthy(envString(env, "VUE_TUI_GRAPHICS_SIXEL")) || String(envString(env, "TERMINAL_GRAPHICS") ?? "").toLowerCase().includes("sixel") || /\bsixel\b/i.test(`${term} ${termProgram} ${termProgramVersion}`)) && candidates.push("sixel"), uniqueProtocols(candidates);
5676
+ return (envString(env, "KITTY_WINDOW_ID") || envString(env, "GHOSTTY_RESOURCES_DIR") || /(?:^|-)kitty(?:-|$)/i.test(term) || term.includes("ghostty") || termProgram.includes("ghostty") || termProgram.includes("wezterm") || envString(env, "WEZTERM_PANE") || envString(env, "WEZTERM_EXECUTABLE")) && candidates.push("kitty"), termProgram.includes("iterm") && candidates.push("iterm2"), (truthy(envString(env, "VUE_TUI_SIXEL")) || truthy(envString(env, "VUE_TUI_GRAPHICS_SIXEL")) || String(envString(env, "TERMINAL_GRAPHICS") ?? "").toLowerCase().includes("sixel") || /\bsixel\b/i.test(`${term} ${termProgram} ${termProgramVersion}`)) && candidates.push("sixel"), uniqueProtocols(candidates);
5677
5677
  }
5678
5678
  function capabilitiesFor(protocol, input) {
5679
5679
  let supported = protocol === "kitty" || protocol === "iterm2" || protocol === "sixel", candidates = uniqueProtocols([...input.candidates ?? (supported ? [protocol] : [])]);
@@ -6377,6 +6377,7 @@ var tAgentTerminalGraphicProps = {
6377
6377
  suspendRenderWhileScrolling: { type: Boolean, default: !0 },
6378
6378
  scrolling: { type: Boolean, default: !1 },
6379
6379
  scrollVersion: { type: Number, default: 0 },
6380
+ /** Advanced Kitty-only opt-in for moving an unchanged image via a reusable placement sequence. */
6380
6381
  placementMoveWithoutClear: { type: Boolean, default: !1 },
6381
6382
  preserveRawWhileRendering: { type: Boolean, default: !1 },
6382
6383
  suspended: { type: Boolean, default: !1 },
@@ -15111,7 +15112,7 @@ function loadBuiltinMathRasterizer() {
15111
15112
  })()), builtinRasterizerLoad;
15112
15113
  }
15113
15114
 
15114
- // node_modules/.pnpm/stream-markdown-parser@1.1.9/node_modules/stream-markdown-parser/dist/index.js
15115
+ // node_modules/.pnpm/stream-markdown-parser@1.2.3/node_modules/stream-markdown-parser/dist/index.js
15115
15116
  var __create2 = Object.create, __defProp$1 = Object.defineProperty, __getOwnPropDesc2 = Object.getOwnPropertyDescriptor, __getOwnPropNames2 = Object.getOwnPropertyNames, __getProtoOf2 = Object.getPrototypeOf, __hasOwnProp2 = Object.prototype.hasOwnProperty, __commonJS = (cb, mod) => function() {
15116
15117
  return mod || (0, cb[__getOwnPropNames2(cb)[0]])((mod = { exports: {} }).exports, mod), mod.exports;
15117
15118
  }, __export$1 = (all) => {
@@ -25015,7 +25016,23 @@ function shouldDemoteFilenameLikeLinkify(linkText, context = {}) {
25015
25016
  let extension = String(extensionMatch[1] ?? "").toLowerCase();
25016
25017
  return isMarketTickerLikeText(linkText, extension, context.marketTicker === !0) ? !0 : FILENAMEISH_LINK_EXTENSIONS.has(extension) ? !AMBIGUOUS_BARE_DOMAIN_EXTENSIONS.has(extension) || context.filename ? !0 : hasStrongFilenameSignals(linkText) : !!(context.explicitFilename && EXPLICIT_FILENAME_CONTEXT_ONLY_EXTENSIONS.has(extension) || context.filename && FILENAME_CONTEXT_ONLY_EXTENSIONS.has(extension));
25017
25018
  }
25019
+ var syntheticLinkOrigins = /* @__PURE__ */ new WeakMap(), cacheStableLinkValidators = /* @__PURE__ */ new WeakSet();
25020
+ function setSyntheticLinkOrigin(token, origin) {
25021
+ return syntheticLinkOrigins.set(token, origin), token;
25022
+ }
25023
+ function readSyntheticLinkOrigin(token) {
25024
+ return syntheticLinkOrigins.get(token);
25025
+ }
25026
+ function registerCacheStableLinkValidator(validateLink$1) {
25027
+ cacheStableLinkValidators.add(validateLink$1);
25028
+ }
25029
+ function isCacheStableLinkValidator(validateLink$1) {
25030
+ return validateLink$1 === void 0 || cacheStableLinkValidators.has(validateLink$1);
25031
+ }
25018
25032
  var LINKIFY_HARD_STOP_CHARS = ["\uFF01"];
25033
+ function getSyntheticLinkOrigin(markup) {
25034
+ return markup === "linkify" || markup === "autolink" ? markup : "recovery";
25035
+ }
25019
25036
  function textToken(content) {
25020
25037
  return {
25021
25038
  type: "text",
@@ -25061,13 +25078,13 @@ function pushEmClose(arr, type) {
25061
25078
  nesting: -1
25062
25079
  }));
25063
25080
  }
25064
- function createLinkToken(text$1, href, loading) {
25081
+ function createLinkToken(text$1, href, loading, origin = "recovery") {
25065
25082
  let title = "";
25066
25083
  if (href.includes('"')) {
25067
25084
  let temps = href.split('"');
25068
25085
  href = temps[0].trim(), title = temps[1].trim();
25069
25086
  }
25070
- return {
25087
+ return setSyntheticLinkOrigin({
25071
25088
  type: "link",
25072
25089
  loading,
25073
25090
  href,
@@ -25079,7 +25096,7 @@ function createLinkToken(text$1, href, loading) {
25079
25096
  raw: text$1
25080
25097
  }],
25081
25098
  raw: `[${text$1}](${href})`
25082
- };
25099
+ }, origin);
25083
25100
  }
25084
25101
  function appendToLinkToken(link$1, suffix) {
25085
25102
  if (!(!link$1 || !suffix) && (link$1.href = String(link$1.href ?? "") + suffix, link$1.text = String(link$1.text ?? "") + suffix, link$1.raw = `[${link$1.text}](${link$1.href})`, Array.isArray(link$1.children) && link$1.children.length)) {
@@ -25243,13 +25260,13 @@ function fixLinkToken(tokens, raw) {
25243
25260
  } else if (curToken?.type === "text" && curToken.content?.endsWith("(") && tokens[i + 1]?.type === "link_open") {
25244
25261
  let match = curToken.content.match(/\[([^\]]+)\]/);
25245
25262
  if (match) {
25246
- let beforeText = curToken.content.slice(0, match.index), emphasisMatch = beforeText.match(/(\*+)$/), replacerTokens = [];
25263
+ let beforeText = curToken.content.slice(0, match.index), emphasisMatch = beforeText.match(/(\*+)$/), origin = getSyntheticLinkOrigin(tokens[i + 1]?.markup), replacerTokens = [];
25247
25264
  if (emphasisMatch) {
25248
25265
  beforeText = beforeText.slice(0, emphasisMatch.index), beforeText && replacerTokens.push(textToken(beforeText));
25249
25266
  let text$1 = match[1], type = emphasisMatch[1].length;
25250
25267
  pushEmOpen(replacerTokens, type);
25251
25268
  let href = tokens[i + 2]?.content || "";
25252
- if (tokens[i + 4]?.type === "text" && !tokens[i + 4].content?.startsWith(")") && (href += tokens[i + 4]?.content || "", tokens[i + 4].content = ""), replacerTokens.push(createLinkToken(text$1, href, !tokens[i + 4]?.content?.startsWith(")"))), pushEmClose(replacerTokens, type), tokens[i + 4]?.type === "text") {
25269
+ if (tokens[i + 4]?.type === "text" && !tokens[i + 4].content?.startsWith(")") && (href += tokens[i + 4]?.content || "", tokens[i + 4].content = ""), replacerTokens.push(createLinkToken(text$1, href, !tokens[i + 4]?.content?.startsWith(")"), origin)), pushEmClose(replacerTokens, type), tokens[i + 4]?.type === "text") {
25253
25270
  let afterText = tokens[i + 4].content?.replace(/^\)\**/, "");
25254
25271
  afterText && replacerTokens.push(textToken(afterText)), tokens.splice(i, 5, ...replacerTokens);
25255
25272
  } else
@@ -25261,7 +25278,7 @@ function fixLinkToken(tokens, raw) {
25261
25278
  let type = emphasisMatch$1[0].length;
25262
25279
  text$1 = text$1.replace(/^\*+/, "").replace(/\*+$/, "");
25263
25280
  let href$1 = tokens[i + 2]?.content || "";
25264
- if (tokens[i + 4]?.type === "text" && !tokens[i + 4].content?.startsWith(")") && (href$1 += tokens[i + 4]?.content || "", tokens[i + 4].content = ""), pushEmOpen(replacerTokens, type), replacerTokens.push(createLinkToken(text$1, href$1, !tokens[i + 4]?.content?.startsWith(")"))), pushEmClose(replacerTokens, type), tokens[i + 4]?.type === "text") {
25281
+ if (tokens[i + 4]?.type === "text" && !tokens[i + 4].content?.startsWith(")") && (href$1 += tokens[i + 4]?.content || "", tokens[i + 4].content = ""), pushEmOpen(replacerTokens, type), replacerTokens.push(createLinkToken(text$1, href$1, !tokens[i + 4]?.content?.startsWith(")"), origin)), pushEmClose(replacerTokens, type), tokens[i + 4]?.type === "text") {
25265
25282
  let afterText = tokens[i + 4].content?.replace(/^\)/, "");
25266
25283
  afterText && replacerTokens.push(textToken(afterText)), tokens.splice(i, 5, ...replacerTokens);
25267
25284
  } else
@@ -25270,7 +25287,7 @@ function fixLinkToken(tokens, raw) {
25270
25287
  continue;
25271
25288
  }
25272
25289
  let href = tokens[i + 2]?.content || "";
25273
- if (tokens[i + 4]?.type === "text" && !tokens[i + 4].content?.startsWith(")") && (href += tokens[i + 4]?.content || "", tokens[i + 4].content = ""), replacerTokens.push(createLinkToken(text$1, href, !tokens[i + 4]?.content?.startsWith(")"))), tokens[i + 4]?.type === "text") {
25290
+ if (tokens[i + 4]?.type === "text" && !tokens[i + 4].content?.startsWith(")") && (href += tokens[i + 4]?.content || "", tokens[i + 4].content = ""), replacerTokens.push(createLinkToken(text$1, href, !tokens[i + 4]?.content?.startsWith(")"), origin)), tokens[i + 4]?.type === "text") {
25274
25291
  let afterText = tokens[i + 4].content?.replace(/^\)/, "");
25275
25292
  afterText && replacerTokens.push(textToken(afterText)), tokens.splice(i, 5, ...replacerTokens);
25276
25293
  } else
@@ -25284,11 +25301,11 @@ function fixLinkToken(tokens, raw) {
25284
25301
  let replacerTokens = [], text$1 = tokens[i - 3].content || "", href = curToken.attrs?.find((attr) => attr[0] === "href")?.[1] || "";
25285
25302
  if (tokens[i + 3]?.type === "text") {
25286
25303
  let m = (tokens[i + 3]?.content ?? "").indexOf(")"), loading = m === -1;
25287
- m === -1 && (href += tokens[i + 3]?.content?.slice(0, m) || "", tokens[i + 3].content = ""), replacerTokens.push(createLinkToken(text$1, href, loading));
25304
+ m === -1 && (href += tokens[i + 3]?.content?.slice(0, m) || "", tokens[i + 3].content = ""), replacerTokens.push(createLinkToken(text$1, href, loading, "linkify"));
25288
25305
  let afterText = tokens[i + 3].content?.replace(/^\)\**/, "");
25289
25306
  afterText && replacerTokens.push(textToken(afterText)), tokens.splice(i - 4, 8, ...replacerTokens);
25290
25307
  } else
25291
- replacerTokens.push({
25308
+ replacerTokens.push(setSyntheticLinkOrigin({
25292
25309
  type: "link",
25293
25310
  loading: !0,
25294
25311
  href,
@@ -25300,7 +25317,7 @@ function fixLinkToken(tokens, raw) {
25300
25317
  raw: href
25301
25318
  }],
25302
25319
  raw: `[${text$1}](${href})`
25303
- }), tokens.splice(i - 4, 7, ...replacerTokens);
25320
+ }, "linkify")), tokens.splice(i - 4, 7, ...replacerTokens);
25304
25321
  continue;
25305
25322
  } else if (tokens[i - 1].content === "](" && tokens[i - 3]?.type === "text" && tokens[i - 3].content?.endsWith(")"))
25306
25323
  if (tokens[i - 2]?.type === "strong_open") {
@@ -25334,7 +25351,7 @@ function fixLinkToken(tokens, raw) {
25334
25351
  count += 1;
25335
25352
  }
25336
25353
  }
25337
- let linkToken = {
25354
+ let linkToken = setSyntheticLinkOrigin({
25338
25355
  type: "link",
25339
25356
  loading: !1,
25340
25357
  href,
@@ -25346,7 +25363,7 @@ function fixLinkToken(tokens, raw) {
25346
25363
  raw: text$1
25347
25364
  }],
25348
25365
  raw: `[${text$1}](${href})`
25349
- };
25366
+ }, curToken.markup ? getSyntheticLinkOrigin(curToken.markup) : "explicit");
25350
25367
  if (replacerTokens.push(linkToken), emphasisMatch) {
25351
25368
  let type = emphasisMatch[1].length;
25352
25369
  pushEmClose(replacerTokens, type);
@@ -26876,10 +26893,14 @@ function factory(opts = {}) {
26876
26893
  ...experimental
26877
26894
  }
26878
26895
  });
26879
- return hasCustomValidateLink || md.set({ validateLink: (url) => !isUnsafeHtmlUrl(url, {
26880
- tagName: "a",
26881
- attrName: "href"
26882
- }) }), applyInlineUrlValidation(md), applyLinkifyCandidateFilter(md), (opts.enableMath ?? !0) && applyMath(md, {
26896
+ if (!hasCustomValidateLink) {
26897
+ let validateLink$1 = (url) => !isUnsafeHtmlUrl(url, {
26898
+ tagName: "a",
26899
+ attrName: "href"
26900
+ });
26901
+ registerCacheStableLinkValidator(validateLink$1), md.set({ validateLink: validateLink$1 });
26902
+ }
26903
+ return applyInlineUrlValidation(md), applyLinkifyCandidateFilter(md), (opts.enableMath ?? !0) && applyMath(md, {
26883
26904
  ...getDefaultMathOptions() ?? {},
26884
26905
  ...opts.mathOptions ?? {}
26885
26906
  }), (opts.enableContainers ?? !0) && applyContainers(md), opts.enableFixIndentedCodeBlock !== !1 && applyFixIndentedCodeBlock(md), applyFixLinkTokens(md), applyFixStrongTokens(md), applyFixListItem(md), applyFixTableTokens(md), applyRenderRules(md), applyFixHtmlInlineTokens(md, { customHtmlTags: opts.customHtmlTags }), md;
@@ -26928,7 +26949,11 @@ function parseEmphasisToken(tokens, startIndex, options) {
26928
26949
  nextIndex: i < tokens.length ? i + 1 : tokens.length
26929
26950
  };
26930
26951
  }
26931
- var TRAILING_FENCE_LINE_RE = /\r?\n[ \t]*`+\s*$/, DIFF_HEADER_PREFIXES = [
26952
+ function TRAILING_OWN_FENCE_LINE_RE(marker, minLen) {
26953
+ return /* @__PURE__ */ new RegExp(`\r?
26954
+ [ \\t]*${marker}{${minLen},}[ \\t]*$`);
26955
+ }
26956
+ var DIFF_HEADER_PREFIXES = [
26932
26957
  "diff ",
26933
26958
  "index ",
26934
26959
  "--- ",
@@ -26981,7 +27006,11 @@ function parseFenceToken(token) {
26981
27006
  let s = info, sp = s.indexOf(" ");
26982
27007
  return sp === -1 ? "" : String(s.slice(sp + 1) ?? "");
26983
27008
  })() : info, content = String(token.content ?? "");
26984
- if (TRAILING_FENCE_LINE_RE.test(content) && (content = content.replace(TRAILING_FENCE_LINE_RE, "")), diff) {
27009
+ if (!closed && token.markup) {
27010
+ let marker = token.markup[0], minLen = token.markup.length, trailingFenceLineRe = TRAILING_OWN_FENCE_LINE_RE(marker, minLen);
27011
+ trailingFenceLineRe.test(content) && (content = content.replace(trailingFenceLineRe, ""));
27012
+ }
27013
+ if (diff) {
26985
27014
  let { original, updated } = splitUnifiedDiff(content, closed === !0);
26986
27015
  return {
26987
27016
  type: "code_block",
@@ -28274,11 +28303,11 @@ function parseInlineTokens(tokens, raw, pPreToken, options) {
28274
28303
  content
28275
28304
  });
28276
28305
  if (currentTextNode) {
28277
- currentTextNode.content += stripTrailingMidStateMarker(textNode.content, token, markerFlags), currentTextNode.raw += textNode.raw;
28306
+ currentTextNode.content += options?.final ? textNode.content : stripTrailingMidStateMarker(textNode.content, token, markerFlags), currentTextNode.raw += textNode.raw;
28278
28307
  return;
28279
28308
  }
28280
28309
  let maybeMath = preToken?.tag === "br" && tokens[i - 2]?.content === "[";
28281
- nextToken || (textNode.content = stripTrailingMidStateMarker(textNode.content, token, markerFlags)), currentTextNode = textNode, currentTextNode.center = maybeMath, result.push(currentTextNode);
28310
+ nextToken || (textNode.content = options?.final ? textNode.content : stripTrailingMidStateMarker(textNode.content, token, markerFlags)), currentTextNode = textNode, currentTextNode.center = maybeMath, result.push(currentTextNode);
28282
28311
  }
28283
28312
  function handleTextToken(token) {
28284
28313
  let rawContent = String(token.content ?? ""), rawMarkerFlags = getInlineTextMarkerFlags(rawContent), rawHasBackslash = (rawMarkerFlags & INLINE_TEXT_MARKER_BACKSLASH) !== 0, rawSource = tokens.length === 1 && rawHasBackslash && typeof raw == "string" ? String(raw) : "", content = rawSource ? decodeVisibleTextFromRaw(rawSource) : rawHasBackslash ? rawContent.replace(ESCAPED_PUNCTUATION_RE, "$1") : rawContent, markerFlags = content === rawContent ? rawMarkerFlags : getInlineTextMarkerFlags(content);
@@ -28301,7 +28330,7 @@ function parseInlineTokens(tokens, raw, pPreToken, options) {
28301
28330
  i++;
28302
28331
  return;
28303
28332
  }
28304
- if (!nextToken && markerFlags & INLINE_TEXT_MARKER_OPEN_PAREN && /[^\]]\s*\(\s*$/.test(content) && (content = content.replace(/\(\s*$/, "")), !content) {
28333
+ if (!nextToken && options?.final !== !0 && markerFlags & INLINE_TEXT_MARKER_OPEN_PAREN && /[^\]]\s*\(\s*$/.test(content) && (content = content.replace(/\(\s*$/, "")), !content) {
28305
28334
  i++;
28306
28335
  return;
28307
28336
  }
@@ -29639,16 +29668,23 @@ function recordInternalNodeSourceRange(node, token, options) {
29639
29668
  end: offsets[Math.max(0, Math.trunc(endLine))] ?? source.length
29640
29669
  });
29641
29670
  }
29642
- var tolerantMathBoundaryStreamCache = /* @__PURE__ */ new WeakMap(), pendingExplicitMathTailCache = /* @__PURE__ */ new WeakMap(), TOLERANT_BOUNDARY_SPLIT_OPENERS = ["$$", "\\["], STREAMING_ADMONITION_OPEN_RE = /(^|\r?\n)[\t ]*:::[\t ]*(?:warning|info|note|tip|danger|caution|error)(?=[\t ]|\r?\n|$)[^\r\n]*(?:\r?\n[\t ]*)*$/, structuredStreamCache = /* @__PURE__ */ new WeakMap(), topLevelStreamParseMode = /* @__PURE__ */ new WeakMap(), REUSABLE_INLINE_TOKEN_TYPES = /* @__PURE__ */ new Set([
29671
+ var tolerantMathBoundaryStreamCache = /* @__PURE__ */ new WeakMap(), pendingExplicitMathTailCache = /* @__PURE__ */ new WeakMap(), TOLERANT_BOUNDARY_SPLIT_OPENERS = ["$", "\\["], STREAMING_ADMONITION_OPEN_RE = /(^|\r?\n)[\t ]*:::[\t ]*(?:warning|info|note|tip|danger|caution|error)(?=[\t ]|\r?\n|$)[^\r\n]*(?:\r?\n[\t ]*)*$/, SAFE_MARKDOWN_WINDOW_MARGIN = 1024, SAFE_MARKDOWN_WINDOW_OVERLAP = 16, safeMarkdownCache = /* @__PURE__ */ new WeakMap(), structuredStreamCache = /* @__PURE__ */ new WeakMap(), topLevelStreamParseMode = /* @__PURE__ */ new WeakMap(), REUSABLE_INLINE_TOKEN_TYPES = /* @__PURE__ */ new Set([
29643
29672
  "code_inline",
29644
29673
  "em_close",
29645
29674
  "em_open",
29646
29675
  "emoji",
29647
29676
  "hardbreak",
29677
+ "html_block",
29678
+ "html_inline",
29679
+ "image",
29648
29680
  "ins_close",
29649
29681
  "ins_open",
29682
+ "link",
29683
+ "link_close",
29684
+ "link_open",
29650
29685
  "mark_close",
29651
29686
  "mark_open",
29687
+ "math_inline",
29652
29688
  "s_close",
29653
29689
  "s_open",
29654
29690
  "softbreak",
@@ -29668,6 +29704,7 @@ var tolerantMathBoundaryStreamCache = /* @__PURE__ */ new WeakMap(), pendingExpl
29668
29704
  "code_block",
29669
29705
  "fence",
29670
29706
  "hr",
29707
+ "inline",
29671
29708
  "math_block"
29672
29709
  ]);
29673
29710
  function getParserNow() {
@@ -29699,21 +29736,38 @@ function processTokensWithTiming(tokens, options, timing) {
29699
29736
  let startedAt = getParserNow(), result = processTokens(tokens, options);
29700
29737
  return addTiming(timing, "processTokensMs", getParserNow() - startedAt), result;
29701
29738
  }
29702
- function hasOnlyReusableInlineTokens(tokens) {
29739
+ function hasOnlyReusableInlineTokens(tokens, validateLink$1) {
29703
29740
  return tokens.every((token) => {
29704
- if (!REUSABLE_INLINE_TOKEN_TYPES.has(token.type))
29741
+ if (!REUSABLE_INLINE_TOKEN_TYPES.has(token.type) || (token.type === "link" || token.type === "link_open" || token.type === "link_close") && !isCacheStableLinkValidator(validateLink$1))
29705
29742
  return !1;
29743
+ if (token.type === "link") {
29744
+ let origin = readSyntheticLinkOrigin(token);
29745
+ if (origin !== "explicit" && origin !== "linkify" && origin !== "autolink")
29746
+ return !1;
29747
+ }
29748
+ if (token.type === "link_open" || token.type === "link_close") {
29749
+ let markup = token.markup ?? "";
29750
+ if (markup !== "" && markup !== "linkify" && markup !== "autolink")
29751
+ return !1;
29752
+ }
29706
29753
  let children = token.children;
29707
- return !Array.isArray(children) || hasOnlyReusableInlineTokens(children);
29754
+ return !Array.isArray(children) || hasOnlyReusableInlineTokens(children, validateLink$1);
29708
29755
  });
29709
29756
  }
29710
- function getReusableTopLevelTokenGroups(tokens) {
29757
+ function getReusableTopLevelPairedCloseType(tokenType) {
29758
+ let known = REUSABLE_TOP_LEVEL_PAIRED_TOKEN_TYPES.get(tokenType);
29759
+ if (known)
29760
+ return known;
29761
+ let containerMatch = /^container_(.+)_open$/.exec(tokenType);
29762
+ return containerMatch ? `container_${containerMatch[1]}_close` : void 0;
29763
+ }
29764
+ function getReusableTopLevelTokenGroups(tokens, validateLink$1) {
29711
29765
  let groupStarts = [], mixed = !1, index = 0;
29712
29766
  for (; index < tokens.length; ) {
29713
29767
  let token = tokens[index];
29714
29768
  if (!token || token.level !== 0)
29715
29769
  return null;
29716
- let closeType = REUSABLE_TOP_LEVEL_PAIRED_TOKEN_TYPES.get(token.type), groupEnd = index + 1;
29770
+ let closeType = getReusableTopLevelPairedCloseType(token.type), groupEnd = index + 1;
29717
29771
  if (closeType) {
29718
29772
  if (token.nesting !== 1)
29719
29773
  return null;
@@ -29745,7 +29799,7 @@ function getReusableTopLevelTokenGroups(tokens) {
29745
29799
  if (current.type !== "inline")
29746
29800
  continue;
29747
29801
  let children = current.children;
29748
- if (!Array.isArray(children) || !hasOnlyReusableInlineTokens(children))
29802
+ if (!Array.isArray(children) || !hasOnlyReusableInlineTokens(children, validateLink$1))
29749
29803
  return null;
29750
29804
  }
29751
29805
  groupStarts.push(index), index = groupEnd;
@@ -29780,24 +29834,36 @@ function updateStructuredStreamCache(md, source, tokens, groups, nodes, options)
29780
29834
  source,
29781
29835
  nodes,
29782
29836
  stableGroupCount: groups.mixed ? Math.max(0, groupStarts.length - 1) : sourceEndsWithBlankLine(source) ? groupStarts.length : Math.max(0, groupStarts.length - 1),
29783
- requireClosingStrong: options.requireClosingStrong
29837
+ requireClosingStrong: options.requireClosingStrong,
29838
+ validateLink: options.validateLink
29784
29839
  });
29785
29840
  }
29786
29841
  function hasStableStructuredStreamGroupBoundaries(previous, tokens, groupStarts, stableGroupCount) {
29842
+ let lastGroupIndex = groupStarts.length - 1;
29787
29843
  for (let index = 0; index < stableGroupCount; index++) {
29788
29844
  let start = groupStarts[index], end = groupStarts[index + 1] ?? tokens.length, boundary = previous.groupBoundaries[index];
29789
- if (!boundary || boundary.firstToken !== tokens[start] || boundary.lastToken !== tokens[end - 1] || boundary.tokenCount !== end - start)
29845
+ if (!boundary || boundary.tokenCount !== end - start)
29846
+ return !1;
29847
+ if (!(boundary.firstToken === tokens[start] && boundary.lastToken === tokens[end - 1]) && (index >= lastGroupIndex || !isSameTokenShapeForReuse(boundary.firstToken, tokens[start]) || !isSameTokenShapeForReuse(boundary.lastToken, tokens[end - 1])))
29790
29848
  return !1;
29791
29849
  }
29792
29850
  return !0;
29793
29851
  }
29794
29852
  function processTopLevelTokensWithReuse(md, source, tokens, options, timing) {
29795
- let owner = md, groups = getReusableTopLevelTokenGroups(tokens);
29796
- if (!(shouldUseTopLevelStreamParse(md, options) && canReuseStructuredStreamNodes(options) && groups !== null))
29853
+ let owner = md, structuredReuseDisabled = options.__disableStructuredReuse === !0;
29854
+ if (!(shouldUseTopLevelStreamParse(md, options) && canReuseStructuredStreamNodes(options)))
29855
+ return structuredReuseDisabled || structuredStreamCache.delete(owner), processTokensWithTiming(tokens, options, timing);
29856
+ if (structuredReuseDisabled)
29857
+ return processTokensWithTiming(tokens, options, timing);
29858
+ let groups = getReusableTopLevelTokenGroups(tokens, options.validateLink);
29859
+ if (!groups)
29797
29860
  return structuredStreamCache.delete(owner), processTokensWithTiming(tokens, options, timing);
29798
29861
  let groupStarts = groups.starts, previous = structuredStreamCache.get(owner), mode = topLevelStreamParseMode.get(owner), stableGroupCount = previous && groups.mixed ? Math.min(previous.stableGroupCount, Math.max(0, previous.groupBoundaries.length - 1)) : previous?.stableGroupCount ?? 0;
29799
- if (previous && stableGroupCount > 0 && previous.requireClosingStrong === options.requireClosingStrong && source.startsWith(previous.source) && groupStarts.length >= stableGroupCount && (mode === "append" || mode === "tail") && hasStableStructuredStreamGroupBoundaries(previous, tokens, groupStarts, stableGroupCount)) {
29800
- let tailStart = groupStarts[stableGroupCount] ?? tokens.length, tailNodes = processTokensWithTiming(tokens.slice(tailStart), options, timing), expectedTailNodes = groupStarts.length - stableGroupCount;
29862
+ if (previous && stableGroupCount > 0 && previous.requireClosingStrong === options.requireClosingStrong && previous.validateLink === options.validateLink && source.startsWith(previous.source) && groupStarts.length >= stableGroupCount && (mode === "append" || mode === "tail") && hasStableStructuredStreamGroupBoundaries(previous, tokens, groupStarts, stableGroupCount)) {
29863
+ let tailStart = groupStarts[stableGroupCount] ?? tokens.length, tailNodes = processTokensWithTiming(tokens.slice(tailStart), {
29864
+ ...options,
29865
+ __linkifyDemotionSeed: previous.nodes.slice(0, stableGroupCount).map((node) => String(node.raw ?? ""))
29866
+ }, timing), expectedTailNodes = groupStarts.length - stableGroupCount;
29801
29867
  if (tailNodes.length === expectedTailNodes) {
29802
29868
  let result$1 = previous.nodes.slice(0, stableGroupCount).concat(tailNodes);
29803
29869
  return addTiming(timing, "processTokensReusedTopLevelNodes", stableGroupCount), updateStructuredStreamCache(md, source, tokens, groups, result$1, options), result$1;
@@ -30405,6 +30471,22 @@ function sameTokenMap(left, right) {
30405
30471
  let leftMap = left?.map, rightMap = right?.map;
30406
30472
  return leftMap === rightMap ? !0 : !Array.isArray(leftMap) || !Array.isArray(rightMap) ? !1 : leftMap.length === rightMap.length && leftMap.every((value, index) => value === rightMap[index]);
30407
30473
  }
30474
+ function sameTokenAttrs(left, right) {
30475
+ let leftAttrs = left?.attrs, rightAttrs = right?.attrs;
30476
+ if (leftAttrs === rightAttrs)
30477
+ return !0;
30478
+ if (!Array.isArray(leftAttrs) || !Array.isArray(rightAttrs) || leftAttrs.length !== rightAttrs.length)
30479
+ return !1;
30480
+ for (let index = 0; index < leftAttrs.length; index++) {
30481
+ let leftAttr = leftAttrs[index], rightAttr = rightAttrs[index];
30482
+ if (leftAttr[0] !== rightAttr[0] || leftAttr[1] !== rightAttr[1])
30483
+ return !1;
30484
+ }
30485
+ return !0;
30486
+ }
30487
+ function isSameTokenShapeForReuse(left, right) {
30488
+ return !!left && !!right && left.type === right.type && left.tag === right.tag && left.nesting === right.nesting && left.level === right.level && left.markup === right.markup && left.content === right.content && left.info === right.info && sameTokenMap(left, right) && sameTokenAttrs(left, right);
30489
+ }
30408
30490
  function isSameTokenShape(left, right) {
30409
30491
  return !!left && !!right && left.type === right.type && left.tag === right.tag && left.nesting === right.nesting && left.markup === right.markup && left.content === right.content && sameTokenMap(left, right);
30410
30492
  }
@@ -30832,7 +30914,8 @@ function hasTopLevelHtmlBlock(nodes) {
30832
30914
  function parseDetailsFragmentChildren(fragment, md, options) {
30833
30915
  return fragment.trim() ? parseMarkdownToStructure(fragment, md, {
30834
30916
  ...options,
30835
- __disableStreamParse: !0
30917
+ __disableStreamParse: !0,
30918
+ __disableStructuredReuse: !0
30836
30919
  }) : [];
30837
30920
  }
30838
30921
  function parseSummaryChildren(fragment, md, options) {
@@ -31028,54 +31111,7 @@ function stripDanglingHtmlLikeTail(markdown) {
31028
31111
  }
31029
31112
  }
31030
31113
  return !0;
31031
- }, isInsideFencedCodeBlock = (src, pos) => {
31032
- let inFence = !1, fenceChar = "", fenceLen = 0, isIndentWs = (ch) => ch === " " || ch === " ", parseFenceMarker = (line) => {
31033
- let i = 0;
31034
- for (; i < line.length && isIndentWs(line[i]); )
31035
- i++;
31036
- let ch = line[i];
31037
- if (ch !== "`" && ch !== "~")
31038
- return null;
31039
- let j = i;
31040
- for (; j < line.length && line[j] === ch; )
31041
- j++;
31042
- let len = j - i;
31043
- return len < 3 ? null : {
31044
- markerChar: ch,
31045
- markerLen: len,
31046
- rest: line.slice(j)
31047
- };
31048
- }, stripBlockquotePrefix = (line) => {
31049
- let i = 0;
31050
- for (; i < line.length && isIndentWs(line[i]); )
31051
- i++;
31052
- let saw = !1;
31053
- for (; i < line.length && line[i] === ">"; )
31054
- for (saw = !0, i++; i < line.length && isIndentWs(line[i]); )
31055
- i++;
31056
- return saw ? line.slice(i) : null;
31057
- }, matchFence = (rawLine) => {
31058
- let direct = parseFenceMarker(rawLine);
31059
- if (direct)
31060
- return direct;
31061
- let afterQuote = stripBlockquotePrefix(rawLine);
31062
- return afterQuote == null ? null : parseFenceMarker(afterQuote);
31063
- }, offset = 0, lines = src.split(/\r?\n/);
31064
- for (let line of lines) {
31065
- let lineStart = offset, lineEnd$2 = offset + line.length;
31066
- if (pos < lineStart)
31067
- break;
31068
- let fenceMatch = matchFence(line);
31069
- if (fenceMatch) {
31070
- let markerChar = fenceMatch.markerChar, markerLen = fenceMatch.markerLen;
31071
- inFence ? markerChar === fenceChar && markerLen >= fenceLen && /^\s*$/.test(fenceMatch.rest) && (inFence = !1, fenceChar = "", fenceLen = 0) : (inFence = !0, fenceChar = markerChar, fenceLen = markerLen);
31072
- }
31073
- if (pos <= lineEnd$2)
31074
- break;
31075
- offset = lineEnd$2 + 1;
31076
- }
31077
- return inFence;
31078
- }, s = String(markdown ?? ""), lastLt = s.lastIndexOf("<");
31114
+ }, isInsideFencedCodeBlock = (src, pos) => isInsideOpenMarkdownFenceBeforeOffset(src, pos), s = String(markdown ?? ""), lastLt = s.lastIndexOf("<");
31079
31115
  if (lastLt === -1 || isInsideFencedCodeBlock(s, lastLt))
31080
31116
  return s;
31081
31117
  if (lastLt > 0) {
@@ -31721,9 +31757,76 @@ function ensureBlankLineBeforeCustomHtmlBlocks(markdown, tags) {
31721
31757
  }
31722
31758
  return out;
31723
31759
  }
31724
- function parseMarkdownToStructure(markdown, md, options = {}) {
31725
- let timing = getParseTiming(options), parseStartedAt = timing ? getParserNow() : 0, isFinal = !!options.final, sourceMarkdown = (markdown ?? "").toString(), safeMarkdown = sourceMarkdown.replace(/([^\\])\r(ight|ho)/g, "$1\\r$2").replace(/([^\\])\r?\n(abla|eq|ot|exists)/g, "$1\\n$2");
31726
- if (shouldResetTopLevelStreamCacheForFinalAutoParse(md, options) && (md.stream.reset(), clearTolerantMathBoundaryStreamCache(md)), isFinal || (safeMarkdown.endsWith("- *") && (safeMarkdown = safeMarkdown.replace(/- \*$/, "- \\*")), /(?:^|\n)\s*-\s*$/.test(safeMarkdown) ? safeMarkdown = safeMarkdown.replace(/(?:^|\n)\s*-\s*$/, (m) => m.startsWith(`
31760
+ function createLatexSplitMathScanner(source) {
31761
+ let inFence = !1, fenceMarker = "", fenceLen = 0, inDollarBlock = !1, inBracketMath = !1, singleDollarOpen = !1, scanned = 0, processLine = (line, _lineStartOffset) => {
31762
+ let fenceMatch = matchMarkdownFenceMarker(line);
31763
+ if (fenceMatch) {
31764
+ inFence ? fenceMatch.markerChar === fenceMarker && fenceMatch.markerLen >= fenceLen && /^\s*$/.test(fenceMatch.rest) && (inFence = !1, fenceMarker = "", fenceLen = 0) : (inFence = !0, fenceMarker = fenceMatch.markerChar, fenceLen = fenceMatch.markerLen);
31765
+ return;
31766
+ }
31767
+ if (inFence)
31768
+ return;
31769
+ let i = 0;
31770
+ for (; i < line.length; ) {
31771
+ if (inDollarBlock) {
31772
+ line.startsWith("$$", i) && !isEscapedDelimiterAt(line, i) ? (inDollarBlock = !1, i += 2) : i++;
31773
+ continue;
31774
+ }
31775
+ if (inBracketMath) {
31776
+ line.startsWith("\\]", i) && !isEscapedDelimiterAt(line, i) ? (inBracketMath = !1, i += 2) : i++;
31777
+ continue;
31778
+ }
31779
+ let ch = line[i];
31780
+ if (ch === "`") {
31781
+ let runLen = countRepeatedChar(line, i, "`"), closeIndex = findCodeSpanCloseIndex(line, i + runLen, runLen);
31782
+ if (closeIndex === -1)
31783
+ break;
31784
+ i = closeIndex + runLen;
31785
+ continue;
31786
+ }
31787
+ if (ch === "\\") {
31788
+ let next = line[i + 1];
31789
+ next === "[" && !isEscapedDelimiterAt(line, i) ? (inBracketMath = !0, i += 2) : (next === "]" && isEscapedDelimiterAt(line, i), i += 2);
31790
+ continue;
31791
+ }
31792
+ if (ch === "$") {
31793
+ if (line[i + 1] === "$" && !isEscapedDelimiterAt(line, i)) {
31794
+ inDollarBlock = !0, singleDollarOpen = !1, i += 2;
31795
+ continue;
31796
+ }
31797
+ if (singleDollarOpen) {
31798
+ singleDollarOpen = !1, i++;
31799
+ continue;
31800
+ }
31801
+ let after = line[i + 1];
31802
+ (after === void 0 || after !== " " && after !== " " && !/\d/.test(after)) && (singleDollarOpen = !0), i++;
31803
+ continue;
31804
+ }
31805
+ i++;
31806
+ }
31807
+ };
31808
+ return {
31809
+ scanTo: (target) => {
31810
+ for (; scanned < target; ) {
31811
+ let newlineIndex = source.indexOf(`
31812
+ `, scanned), lineEndRaw = newlineIndex === -1 || newlineIndex >= target ? target : newlineIndex, lineEnd$2 = lineEndRaw > scanned && source[lineEndRaw - 1] === "\r" ? lineEndRaw - 1 : lineEndRaw;
31813
+ if (processLine(source.slice(scanned, lineEnd$2), scanned), newlineIndex === -1 || newlineIndex >= target) {
31814
+ scanned = target;
31815
+ break;
31816
+ }
31817
+ singleDollarOpen = !1, scanned = newlineIndex + 1;
31818
+ }
31819
+ },
31820
+ inMath: () => inDollarBlock || inBracketMath || singleDollarOpen
31821
+ };
31822
+ }
31823
+ function transformStreamingSafeMarkdown(source, isFinal, md, options) {
31824
+ let safeMarkdown = source.replace(/([^\\])\r(ight|ho)/g, "$1\\r$2"), latexSplitMathScanner = createLatexSplitMathScanner(safeMarkdown);
31825
+ if (safeMarkdown = safeMarkdown.replace(/([^\\])\r?\n(abla|eq|ot|exists)/g, (full, before, cmd, offset) => {
31826
+ latexSplitMathScanner.scanTo(offset + 1);
31827
+ let shouldReconstruct = latexSplitMathScanner.inMath();
31828
+ return latexSplitMathScanner.scanTo(offset + full.length), shouldReconstruct ? `${before}\\n${cmd}` : full;
31829
+ }), isFinal || (safeMarkdown.endsWith("- *") && (safeMarkdown = safeMarkdown.replace(/- \*$/, "- \\*")), /(?:^|\n)\s*-\s*$/.test(safeMarkdown) ? safeMarkdown = safeMarkdown.replace(/(?:^|\n)\s*-\s*$/, (m) => m.startsWith(`
31727
31830
  `) ? `
31728
31831
  ` : "") : /(?:^|\n)\s*--\s*$/.test(safeMarkdown) ? safeMarkdown = safeMarkdown.replace(/(?:^|\n)\s*--\s*$/, (m) => m.startsWith(`
31729
31832
  `) ? `
@@ -31735,7 +31838,7 @@ function parseMarkdownToStructure(markdown, md, options = {}) {
31735
31838
  ` : "")) : /(?:^|\n)\s*\d+[.)]\s+\*{1,3}\s*$/.test(safeMarkdown) ? safeMarkdown = safeMarkdown.replace(/((?:^|\n)\s*\d+[.)]\s+)(\*{1,3})\s*$/, (_, prefix, stars) => `${prefix}${stars.split("").map(() => "\\*").join("")}`) : /(?:^|\n)\s*\d+[.)]\s*$/.test(safeMarkdown) ? safeMarkdown = safeMarkdown.replace(/(?:^|\n)\s*\d+[.)]\s*$/, (m) => m.startsWith(`
31736
31839
  `) ? `
31737
31840
  ` : "") : /\n[[(]\n*$/.test(safeMarkdown) && (safeMarkdown = safeMarkdown.replace(/(\n\[|\n\()+\n*$/g, `
31738
- `)), safeMarkdown = stripPendingExplicitMathTail(safeMarkdown, md), safeMarkdown = getStreamingAdmonitionOpenTailReplacement(safeMarkdown, options.customHtmlTags) ?? safeMarkdown), options.customHtmlTags?.length && safeMarkdown.includes("<")) {
31841
+ `)), safeMarkdown = getStreamingAdmonitionOpenTailReplacement(safeMarkdown, options.customHtmlTags) ?? safeMarkdown), options.customHtmlTags?.length && safeMarkdown.includes("<")) {
31739
31842
  let tags = normalizeCustomHtmlTags(options.customHtmlTags);
31740
31843
  if (tags.length && (safeMarkdown = ensureBlankLineBeforeInlineMultilineCustomHtmlBlocks(safeMarkdown, tags), safeMarkdown = normalizeCustomHtmlOpeningTagSameLine(safeMarkdown, tags), safeMarkdown = ensureBlankLineBeforeCustomHtmlBlocks(safeMarkdown, tags), safeMarkdown = ensureBlankLineAfterCustomHtmlCloseBeforeBlockMarkerSameLine(safeMarkdown, tags), safeMarkdown.includes("</")))
31741
31844
  for (let tag of tags) {
@@ -31743,7 +31846,26 @@ function parseMarkdownToStructure(markdown, md, options = {}) {
31743
31846
  safeMarkdown = safeMarkdown.replace(re, "$1$2$2");
31744
31847
  }
31745
31848
  }
31746
- isFinal || (safeMarkdown = stripDanglingHtmlLikeTail(safeMarkdown));
31849
+ return isFinal || (safeMarkdown = stripDanglingHtmlLikeTail(safeMarkdown)), safeMarkdown;
31850
+ }
31851
+ function getSafeMarkdown(md, sourceMarkdown, isFinal, options) {
31852
+ let owner = md, mode = `${isFinal ? "final" : "stream"}:${(options.customHtmlTags ?? []).join(",")}`, previous = safeMarkdownCache.get(owner), safeMarkdown;
31853
+ if (!isFinal && !options.customHtmlTags?.length && previous && previous.mode === mode && sourceMarkdown.length >= previous.source.length && sourceMarkdown.startsWith(previous.source)) {
31854
+ let windowStart = Math.max(0, previous.source.length - SAFE_MARKDOWN_WINDOW_MARGIN - SAFE_MARKDOWN_WINDOW_OVERLAP), transformed = transformStreamingSafeMarkdown(sourceMarkdown.slice(windowStart), isFinal, md, options), overlapLength = previous.source.length - windowStart;
31855
+ safeMarkdown = transformed.length >= overlapLength && transformed.slice(0, overlapLength) === previous.safeMarkdown.slice(-overlapLength) ? previous.safeMarkdown.slice(0, previous.safeMarkdown.length - overlapLength) + transformed : transformStreamingSafeMarkdown(sourceMarkdown, isFinal, md, options);
31856
+ } else
31857
+ safeMarkdown = transformStreamingSafeMarkdown(sourceMarkdown, isFinal, md, options);
31858
+ return isFinal || (safeMarkdown = stripPendingExplicitMathTail(safeMarkdown, md)), safeMarkdownCache.set(owner, {
31859
+ source: sourceMarkdown,
31860
+ safeMarkdown,
31861
+ mode
31862
+ }), safeMarkdown;
31863
+ }
31864
+ function parseMarkdownToStructure(markdown, md, options = {}) {
31865
+ let timing = getParseTiming(options), parseStartedAt = timing ? getParserNow() : 0, isFinal = !!options.final, sourceMarkdown = (markdown ?? "").toString();
31866
+ shouldResetTopLevelStreamCacheForFinalAutoParse(md, options) && (md.stream.reset(), clearTolerantMathBoundaryStreamCache(md), safeMarkdownCache.delete(md));
31867
+ let safeMarkdown = getSafeMarkdown(md, sourceMarkdown, isFinal, options);
31868
+ timing && addTiming(timing, "safeMarkdownMs", getParserNow() - parseStartedAt);
31747
31869
  let standaloneHtmlDocument = parseStandaloneHtmlDocument(safeMarkdown);
31748
31870
  if (standaloneHtmlDocument) {
31749
31871
  if (options.includeSourceMap) {
@@ -31760,8 +31882,8 @@ function parseMarkdownToStructure(markdown, md, options = {}) {
31760
31882
  }
31761
31883
  return finishParsedNodes(standaloneHtmlDocument, options, timing, parseStartedAt);
31762
31884
  }
31763
- let tokens = parseTopLevelTokens(md, safeMarkdown, { __markstreamFinal: isFinal }, options);
31764
- if (!tokens || !Array.isArray(tokens))
31885
+ let tokenizeStartedAt = timing ? getParserNow() : 0, tokens = parseTopLevelTokens(md, safeMarkdown, { __markstreamFinal: isFinal }, options);
31886
+ if (timing && addTiming(timing, "tokenizeMs", getParserNow() - tokenizeStartedAt), !tokens || !Array.isArray(tokens))
31765
31887
  return finishParsedNodes([], options, timing, parseStartedAt);
31766
31888
  let pre = options.preTransformTokens, post = options.postTransformTokens, transformedTokens = tokens;
31767
31889
  pre && typeof pre == "function" && (transformedTokens = pre(transformedTokens) || transformedTokens);
@@ -31783,7 +31905,11 @@ function parseMarkdownToStructure(markdown, md, options = {}) {
31783
31905
  }, timing) : result = postResult;
31784
31906
  }
31785
31907
  }
31786
- if (hasTopLevelHtmlBlock(result) && (result = mergeSplitTopLevelHtmlBlocks(result, isFinal, safeMarkdown, internalOptions), result = combineStructuredDetailsHtmlBlocks(result, safeMarkdown, md, internalOptions, isFinal)[0], result = structureGenericHtmlBlockChildren(result, md, internalOptions, isFinal)), isFinal) {
31908
+ if (hasTopLevelHtmlBlock(result)) {
31909
+ let htmlPassesStartedAt = timing ? getParserNow() : 0;
31910
+ result = mergeSplitTopLevelHtmlBlocks(result, isFinal, safeMarkdown, internalOptions), result = combineStructuredDetailsHtmlBlocks(result, safeMarkdown, md, internalOptions, isFinal)[0], result = structureGenericHtmlBlockChildren(result, md, internalOptions, isFinal), timing && addTiming(timing, "htmlBlockPassesMs", getParserNow() - htmlPassesStartedAt);
31911
+ }
31912
+ if (isFinal) {
31787
31913
  let seen = /* @__PURE__ */ new WeakSet(), finalizeHtmlBlockLoading = (value) => {
31788
31914
  if (!value || typeof value != "object" || seen.has(value))
31789
31915
  return;
@@ -31804,7 +31930,11 @@ function parseMarkdownToStructure(markdown, md, options = {}) {
31804
31930
  function processTokens(tokens, options) {
31805
31931
  if (!tokens || !Array.isArray(tokens))
31806
31932
  return [];
31807
- let result = [], linkifyContext = createLinkifyDemotionContextTracker(options), includeSourceMap = options?.includeSourceMap === !0, i = 0;
31933
+ let result = [], linkifyContext = createLinkifyDemotionContextTracker(options), seedRaws = options?.__linkifyDemotionSeed;
31934
+ if (Array.isArray(seedRaws) && seedRaws.length)
31935
+ for (let raw of seedRaws)
31936
+ linkifyContext.remember(String(raw ?? ""));
31937
+ let includeSourceMap = options?.includeSourceMap === !0, i = 0;
31808
31938
  for (; i < tokens.length; ) {
31809
31939
  let handled = parseCommonBlockToken(tokens, i, linkifyContext.options(), containerTokenHandlers);
31810
31940
  if (handled) {
@@ -33535,11 +33665,60 @@ function mergeStyle11(base, overlay) {
33535
33665
  let merged = Object.freeze({ ...base, ...overlay });
33536
33666
  return bucket.set(overlay, merged), merged;
33537
33667
  }
33538
- var activeMarkdownImageGraphics = /* @__PURE__ */ new WeakMap();
33668
+ var activeMarkdownImageGraphics = /* @__PURE__ */ new WeakMap(), markdownImageGraphicIdCache = /* @__PURE__ */ new WeakMap(), preparedMarkdownImageGraphicCache = /* @__PURE__ */ new WeakMap();
33539
33669
  function markdownImageGraphicId(segment, identity) {
33540
- return `md-image:${stableTerminalGraphicNumericId(
33670
+ let cachedIds = markdownImageGraphicIdCache.get(segment);
33671
+ cachedIds || (cachedIds = /* @__PURE__ */ new Map(), markdownImageGraphicIdCache.set(segment, cachedIds));
33672
+ let cached = cachedIds.get(identity);
33673
+ if (cached)
33674
+ return cached;
33675
+ let id = `md-image:${stableTerminalGraphicNumericId(
33541
33676
  `${identity}:${segment.src ?? segment.tex ?? ""}:${segment.displayWidth ?? 0}:${segment.displayHeight ?? 0}:${segment.base64 ?? ""}`
33542
33677
  )}`;
33678
+ return cachedIds.set(identity, id), id;
33679
+ }
33680
+ function prepareMarkdownImageGraphic(segment, identity, protocol, placement) {
33681
+ if (!segment.base64)
33682
+ return null;
33683
+ let preparedByVariant = preparedMarkdownImageGraphicCache.get(segment);
33684
+ preparedByVariant || (preparedByVariant = /* @__PURE__ */ new Map(), preparedMarkdownImageGraphicCache.set(segment, preparedByVariant));
33685
+ let cacheKey = `${identity}\0${protocol}\0${placement.width}\0${placement.height}\0${placement.sourceX ?? ""}\0${placement.sourceY ?? ""}\0${placement.sourceWidth ?? ""}\0${placement.sourceHeight ?? ""}`, cached = preparedByVariant.get(cacheKey);
33686
+ if (cached)
33687
+ return cached;
33688
+ let id = markdownImageGraphicId(segment, identity), imageId = stableTerminalGraphicNumericId(`image:${id}`), placementId = stableTerminalGraphicNumericId(`placement:${id}`), sequence = protocol === "kitty" ? createKittyGraphicsSequence(segment.base64, {
33689
+ imageId,
33690
+ placementId,
33691
+ columns: placement.width,
33692
+ rows: placement.height,
33693
+ sourceX: placement.sourceX,
33694
+ sourceY: placement.sourceY,
33695
+ sourceWidth: placement.sourceWidth,
33696
+ sourceHeight: placement.sourceHeight,
33697
+ zIndex: -1
33698
+ }) : protocol === "iterm2" ? createIterm2InlineImageSequence(segment.base64, {
33699
+ width: placement.width,
33700
+ height: placement.height,
33701
+ preserveAspectRatio: !0,
33702
+ doNotMoveCursor: !0
33703
+ }) : "";
33704
+ if (!sequence)
33705
+ return null;
33706
+ let prepared = Object.freeze({
33707
+ id,
33708
+ sequence,
33709
+ clearSequence: protocol === "kitty" ? createKittyDeleteGraphicsSequence({ imageId, placementId }) : void 0,
33710
+ resizeSequence: protocol === "kitty" ? createKittyPlacementSequence({
33711
+ imageId,
33712
+ placementId,
33713
+ columns: placement.width,
33714
+ rows: placement.height,
33715
+ sourceX: placement.sourceX,
33716
+ sourceY: placement.sourceY,
33717
+ sourceWidth: placement.sourceWidth,
33718
+ sourceHeight: placement.sourceHeight
33719
+ }) : void 0
33720
+ });
33721
+ return preparedByVariant.set(cacheKey, prepared), prepared;
33543
33722
  }
33544
33723
  function rememberMarkdownImageGraphic(terminal, id, rect) {
33545
33724
  let active = activeMarkdownImageGraphics.get(terminal);
@@ -33570,57 +33749,47 @@ function clearMarkdownImageGraphics(terminal, rect) {
33570
33749
  for (let [id, item] of active)
33571
33750
  rect && (item.x >= rect.x + rect.w || item.x + item.w <= rect.x || item.y >= rect.y + rect.h || item.y + item.h <= rect.y) || clearTrackedMarkdownImageGraphic(terminal, id);
33572
33751
  }
33573
- function queueMarkdownImageGraphic(terminal, segment, identity, rect) {
33752
+ function queueMarkdownImageGraphic(terminal, segment, identity, rect, placementOverride) {
33574
33753
  if (!segment.base64)
33575
33754
  return "unavailable";
33576
33755
  let output = getTerminalGraphicsOutput(terminal), protocol = output?.capabilities.preferredProtocol;
33577
33756
  if (!output?.capabilities.supported || !isTerminalGraphicsProtocol(protocol))
33578
33757
  return "unavailable";
33579
- let width = Math.max(1, Math.floor(segment.displayWidth ?? rect.w)), height = Math.max(1, Math.floor(segment.displayHeight ?? 1)), id = markdownImageGraphicId(segment, identity), imageId = stableTerminalGraphicNumericId(`image:${id}`), placementId = stableTerminalGraphicNumericId(`placement:${id}`), sequence = protocol === "kitty" ? createKittyGraphicsSequence(segment.base64, {
33580
- imageId,
33581
- placementId,
33582
- columns: width,
33583
- rows: height,
33584
- zIndex: -1
33585
- }) : protocol === "iterm2" ? createIterm2InlineImageSequence(segment.base64, {
33586
- width,
33587
- height,
33588
- preserveAspectRatio: !0,
33589
- doNotMoveCursor: !0
33590
- }) : "";
33591
- if (!sequence)
33758
+ let placement = placementOverride ?? {
33759
+ width: Math.max(1, Math.floor(segment.displayWidth ?? rect.w)),
33760
+ height: Math.max(1, Math.floor(segment.displayHeight ?? 1))
33761
+ }, prepared = prepareMarkdownImageGraphic(segment, identity, protocol, placement);
33762
+ if (!prepared)
33592
33763
  return "unavailable";
33593
- let clearSequence = protocol === "kitty" ? createKittyDeleteGraphicsSequence({
33594
- imageId,
33595
- placementId
33596
- }) : void 0, resizeSequence = protocol === "kitty" ? createKittyPlacementSequence({
33597
- imageId,
33598
- placementId,
33599
- columns: width,
33600
- rows: height
33601
- }) : void 0, accepted = output.queue({
33602
- id,
33764
+ let accepted = output.queue({
33765
+ id: prepared.id,
33603
33766
  x: rect.x,
33604
33767
  y: rect.y,
33605
- w: width,
33606
- h: height,
33768
+ w: placement.width,
33769
+ h: placement.height,
33607
33770
  protocol,
33608
- sequence,
33609
- resizeSequence,
33610
- clearSequence,
33771
+ sequence: prepared.sequence,
33772
+ resizeSequence: prepared.resizeSequence,
33773
+ clearSequence: prepared.clearSequence,
33774
+ placementMoveWithoutClear: protocol === "kitty",
33611
33775
  fallbackText: segment.alt ?? (segment.kind === "math" ? segment.raw ?? segment.tex ?? "math" : "image")
33612
33776
  });
33613
33777
  return markdownImageDebug(
33614
- `queue id=${id}`,
33778
+ `queue id=${prepared.id}`,
33615
33779
  `accepted=${accepted ? "true" : "false"}`,
33616
33780
  `x=${rect.x}`,
33617
33781
  `y=${rect.y}`,
33618
- `w=${width}`,
33619
- `h=${height}`,
33782
+ `w=${placement.width}`,
33783
+ `h=${placement.height}`,
33620
33784
  `visibleW=${rect.w}`,
33621
33785
  `displayW=${segment.displayWidth ?? ""}`,
33622
33786
  `displayH=${segment.displayHeight ?? ""}`
33623
- ), accepted && rememberMarkdownImageGraphic(terminal, id, { x: rect.x, y: rect.y, w: width, h: height }), accepted ? "queued" : "rejected";
33787
+ ), accepted && rememberMarkdownImageGraphic(terminal, prepared.id, {
33788
+ x: rect.x,
33789
+ y: rect.y,
33790
+ w: placement.width,
33791
+ h: placement.height
33792
+ }), accepted ? "queued" : "rejected";
33624
33793
  }
33625
33794
  function collectVisibleMarkdownImageGraphicIds(rows, options) {
33626
33795
  let keepIds = /* @__PURE__ */ new Set();
@@ -33636,7 +33805,7 @@ function collectVisibleMarkdownImageGraphicIds(rows, options) {
33636
33805
  let logicalX = 0;
33637
33806
  for (let [segmentIndex, segment] of row.segments.entries()) {
33638
33807
  let segmentStart = logicalX, segmentEnd = logicalX + segment.cells;
33639
- if (logicalX = segmentEnd, !segment.graphic || segmentEnd <= clipStart || segmentStart >= clipEnd || Math.max(segmentStart, clipStart) !== segmentStart)
33808
+ if (logicalX = segmentEnd, !segment.graphic || segmentEnd <= clipStart || segmentStart >= clipEnd)
33640
33809
  continue;
33641
33810
  let height = Math.max(1, Math.floor(segment.graphic.displayHeight ?? 1));
33642
33811
  if (rowIndex + height <= firstRow || rowIndex >= lastRow)
@@ -33652,10 +33821,74 @@ function collectVisibleMarkdownImageGraphicIds(rows, options) {
33652
33821
  }
33653
33822
  return keepIds;
33654
33823
  }
33824
+ function queueClippedVisibleMarkdownImageGraphics(terminal, rows, options) {
33825
+ let queuedIds = /* @__PURE__ */ new Set(), output = getTerminalGraphicsOutput(terminal);
33826
+ if (options.w <= 0 || options.h <= 0 || !output?.capabilities.supported || output.capabilities.preferredProtocol !== "kitty")
33827
+ return queuedIds;
33828
+ let clipStart = Math.max(0, Math.floor(options.clipStart)), firstRow = Math.min(rows.length, Math.max(0, Math.floor(options.rowOffset))), lastRow = Math.min(rows.length, firstRow + Math.max(0, Math.floor(options.h))), scanStart = firstRow;
33829
+ for (; scanStart > 0 && (rows[scanStart]?.segments.length ?? 0) === 0; )
33830
+ scanStart--;
33831
+ for (let rowIndex = scanStart; rowIndex < lastRow; rowIndex++) {
33832
+ let row = rows[rowIndex];
33833
+ if (!row)
33834
+ continue;
33835
+ let logicalX = 0;
33836
+ for (let [segmentIndex, segment] of row.segments.entries()) {
33837
+ let segmentStart = logicalX;
33838
+ if (logicalX += segment.cells, !segment.graphic?.base64)
33839
+ continue;
33840
+ let fullWidth = Math.max(1, Math.floor(segment.graphic.displayWidth ?? segment.cells)), fullHeight = Math.max(1, Math.floor(segment.graphic.displayHeight ?? 1)), fullRect = {
33841
+ x: options.x + segmentStart - clipStart,
33842
+ y: options.y + rowIndex - firstRow,
33843
+ w: fullWidth,
33844
+ h: fullHeight
33845
+ }, visibleRect = {
33846
+ x: Math.max(options.x, fullRect.x),
33847
+ y: Math.max(options.y, fullRect.y),
33848
+ w: Math.min(options.x + options.w, fullRect.x + fullRect.w) - Math.max(options.x, fullRect.x),
33849
+ h: Math.min(options.y + options.h, fullRect.y + fullRect.h) - Math.max(options.y, fullRect.y)
33850
+ };
33851
+ if (visibleRect.w <= 0 || visibleRect.h <= 0 || visibleRect.x === fullRect.x && visibleRect.y === fullRect.y && visibleRect.w === fullRect.w && visibleRect.h === fullRect.h || options.isGraphicCovered?.(visibleRect))
33852
+ continue;
33853
+ let naturalWidth = Math.floor(segment.graphic.naturalWidth ?? 0), naturalHeight = Math.floor(segment.graphic.naturalHeight ?? 0);
33854
+ if (naturalWidth <= 0 || naturalHeight <= 0)
33855
+ continue;
33856
+ let offsetX = visibleRect.x - fullRect.x, offsetY = visibleRect.y - fullRect.y, sourceX = Math.floor(offsetX * naturalWidth / fullWidth), sourceY = Math.floor(offsetY * naturalHeight / fullHeight), sourceRight = Math.max(
33857
+ sourceX + 1,
33858
+ Math.min(naturalWidth, Math.ceil((offsetX + visibleRect.w) * naturalWidth / fullWidth))
33859
+ ), sourceBottom = Math.max(
33860
+ sourceY + 1,
33861
+ Math.min(
33862
+ naturalHeight,
33863
+ Math.ceil((offsetY + visibleRect.h) * naturalHeight / fullHeight)
33864
+ )
33865
+ ), identity = `${row.key}:${segmentIndex}`;
33866
+ queueMarkdownImageGraphic(
33867
+ terminal,
33868
+ segment.graphic,
33869
+ identity,
33870
+ { x: visibleRect.x, y: visibleRect.y, w: visibleRect.w },
33871
+ {
33872
+ width: visibleRect.w,
33873
+ height: visibleRect.h,
33874
+ sourceX,
33875
+ sourceY,
33876
+ sourceWidth: sourceRight - sourceX,
33877
+ sourceHeight: sourceBottom - sourceY
33878
+ }
33879
+ ) === "queued" && queuedIds.add(markdownImageGraphicId(segment.graphic, identity));
33880
+ }
33881
+ }
33882
+ return queuedIds;
33883
+ }
33655
33884
  function paintMarkdownVisualRow(terminal, row, options) {
33656
33885
  let clipStart = Math.max(0, Math.floor(options.clipStart ?? 0)), clipEnd = clipStart + options.w;
33657
33886
  if (!row) {
33658
- options.clear !== !1 && (terminal.write(spaces(options.w), { x: options.x, y: options.y, style: options.baseStyle }), clearStaleMarkdownImageGraphicsForRow(terminal, options.y, /* @__PURE__ */ new Set(), options.keepGraphicIds));
33887
+ options.clear !== !1 && (terminal.write(spaces(options.w), {
33888
+ x: options.x,
33889
+ y: options.y,
33890
+ style: options.baseStyle
33891
+ }), clearStaleMarkdownImageGraphicsForRow(terminal, options.y, /* @__PURE__ */ new Set(), options.keepGraphicIds));
33659
33892
  return;
33660
33893
  }
33661
33894
  let logicalX = 0, used = 0, queuedGraphics = /* @__PURE__ */ new Set();
@@ -33686,12 +33919,12 @@ function paintMarkdownVisualRow(terminal, row, options) {
33686
33919
  y: options.y,
33687
33920
  w: Math.max(1, Math.floor(segment.graphic.displayWidth ?? visibleCells)),
33688
33921
  h: Math.max(1, Math.floor(segment.graphic.displayHeight ?? 1))
33689
- }, queueResult = !(options.isGraphicCovered?.(graphicRect) === !0) && visibleStart === segmentStart && visibleCells > 0 && queueMarkdownImageGraphic(terminal, segment.graphic, `${row.key}:${segmentIndex}`, {
33922
+ }, graphicCovered = options.isGraphicCovered?.(graphicRect) === !0, graphicId = markdownImageGraphicId(segment.graphic, `${row.key}:${segmentIndex}`), queueResult = options.prequeuedGraphicIds?.has(graphicId) === !0 ? "queued" : !graphicCovered && visibleStart === segmentStart && visibleCells > 0 && queueMarkdownImageGraphic(terminal, segment.graphic, `${row.key}:${segmentIndex}`, {
33690
33923
  x: cellX,
33691
33924
  y: options.y,
33692
33925
  w: visibleCells
33693
33926
  }), graphicAvailable = queueResult || canAttemptMarkdownImageGraphic(terminal, segment.graphic), queuedGraphic = queueResult === "queued", suppressFallback = queuedGraphic || queueResult === "rejected" || graphicAvailable === !0;
33694
- queuedGraphic && queuedGraphics.add(markdownImageGraphicId(segment.graphic, `${row.key}:${segmentIndex}`)), terminal.write(
33927
+ queuedGraphic && queuedGraphics.add(graphicId), terminal.write(
33695
33928
  suppressFallback ? spaces(visibleCells) : sliceByCellsRange(
33696
33929
  segment.fallbackText ?? segment.graphic.alt ?? (segment.graphic.kind === "math" ? segment.graphic.raw ?? segment.graphic.tex ?? "math" : "image"),
33697
33930
  0,
@@ -33772,23 +34005,36 @@ function markdownStyleSignature(style) {
33772
34005
  style.href ?? ""
33773
34006
  ].join("") : "";
33774
34007
  }
34008
+ var markdownRowSignatureCache = /* @__PURE__ */ new WeakMap(), markdownRowGraphicSignatureCache = /* @__PURE__ */ new WeakMap();
33775
34009
  function markdownRowSignature(row) {
33776
- return row ? [
34010
+ if (!row)
34011
+ return "";
34012
+ let cached = markdownRowSignatureCache.get(row);
34013
+ if (cached != null)
34014
+ return cached;
34015
+ let signature = [
33777
34016
  row.key,
33778
34017
  row.plainText,
33779
34018
  row.segments.map(
33780
34019
  (segment) => `${segment.text}${segment.cells}${markdownStyleSignature(segment.style)}${segment.graphic?.src ?? ""}${segment.graphic?.base64 ?? ""}${segment.fallbackText ?? ""}`
33781
34020
  ).join("")
33782
- ].join("") : "";
34021
+ ].join("");
34022
+ return markdownRowSignatureCache.set(row, signature), signature;
33783
34023
  }
33784
34024
  function getWheelScrollInput4(e) {
33785
34025
  let deltaY = Number(e.deltaY ?? 0), deltaMode = typeof e.deltaMode == "number" ? e.deltaMode : void 0;
33786
34026
  return Number.isInteger(deltaY) && deltaY !== 0 && Math.abs(deltaY) >= 100 && Math.abs(deltaY) % 100 === 0 && deltaMode == null ? { deltaY: deltaY / 100, mode: "line" } : deltaMode === 1 ? { deltaY, mode: "line" } : deltaMode === 0 ? { deltaY, mode: "pixel" } : { deltaY, mode: "auto" };
33787
34027
  }
33788
34028
  function rowGraphicSignature(row) {
33789
- return row ? row.segments.map(
33790
- (segment) => segment.graphic ? `${segment.graphic.kind}${segment.graphic.src}${segment.graphic.base64 ?? ""}` : ""
33791
- ).join("") : "";
34029
+ if (!row)
34030
+ return "";
34031
+ let cached = markdownRowGraphicSignatureCache.get(row);
34032
+ if (cached != null)
34033
+ return cached;
34034
+ let signature = row.segments.filter((segment) => segment.graphic).map(
34035
+ (segment) => `${segment.graphic.kind}${segment.graphic.src}${segment.graphic.base64 ?? ""}`
34036
+ ).join("");
34037
+ return markdownRowGraphicSignatureCache.set(row, signature), signature;
33792
34038
  }
33793
34039
  var TVirtualMarkdown = (0, import_vue33.defineComponent)({
33794
34040
  name: "TVirtualMarkdown",
@@ -33839,6 +34085,10 @@ var TVirtualMarkdown = (0, import_vue33.defineComponent)({
33839
34085
  imageOcclusionRects: {
33840
34086
  type: Array,
33841
34087
  default: void 0
34088
+ },
34089
+ rowScrollMode: {
34090
+ type: String,
34091
+ default: "off"
33842
34092
  }
33843
34093
  },
33844
34094
  emits: {
@@ -33852,7 +34102,16 @@ var TVirtualMarkdown = (0, import_vue33.defineComponent)({
33852
34102
  linkAction: (_payload) => !0
33853
34103
  },
33854
34104
  setup(props, { emit }) {
33855
- let instance = (0, import_vue33.getCurrentInstance)(), { terminal, defaultStyle, events, scheduler, selection, widthProvider } = useTerminal(), layout = useLayout(), { visible, rootProps } = useVisibility(), parentEventZ = (0, import_vue33.inject)(EventZIndexContextKey, (0, import_vue33.computed)(() => 0)), eventZ = (0, import_vue33.computed)(() => (parentEventZ.value ?? 0) + (props.zIndex ?? 0)), internalScrollTop = (0, import_vue33.ref)(0), documentVersion = (0, import_vue33.ref)(0), rows = (0, import_vue33.shallowRef)((0, import_vue33.markRaw)([])), pendingSelectionScrollFocusRemap = !1, wheelState = createWheelScrollState(), builtOnce = !1, rebuildVersion = 0, layoutCache, alive = !0, parser = (0, import_vue33.shallowRef)(
34105
+ let instance = (0, import_vue33.getCurrentInstance)(), {
34106
+ terminal,
34107
+ defaultStyle,
34108
+ events,
34109
+ scheduler,
34110
+ selection,
34111
+ widthProvider,
34112
+ render,
34113
+ rendererCapabilities
34114
+ } = useTerminal(), layout = useLayout(), { visible, rootProps } = useVisibility(), parentEventZ = (0, import_vue33.inject)(EventZIndexContextKey, (0, import_vue33.computed)(() => 0)), plane = (0, import_vue33.inject)(RenderPlaneContextKey, (0, import_vue33.ref)("default")), eventZ = (0, import_vue33.computed)(() => (parentEventZ.value ?? 0) + (props.zIndex ?? 0)), internalScrollTop = (0, import_vue33.ref)(0), documentVersion = (0, import_vue33.ref)(0), rows = (0, import_vue33.shallowRef)((0, import_vue33.markRaw)([])), pendingSelectionScrollFocusRemap = !1, wheelState = createWheelScrollState(), builtOnce = !1, rebuildVersion = 0, layoutCache, alive = !0, dirtyRowsHint, renderNodeId = null, parser = (0, import_vue33.shallowRef)(
33856
34115
  (0, import_vue33.markRaw)(
33857
34116
  createTuiMarkdownParser({
33858
34117
  streaming: props.streaming,
@@ -33927,7 +34186,16 @@ var TVirtualMarkdown = (0, import_vue33.defineComponent)({
33927
34186
  let nextRows = nextLayout.rows;
33928
34187
  rows.value = (0, import_vue33.markRaw)(nextRows), enqueuePendingMathImages(), reconcileScrollTop();
33929
34188
  let nextScrollTop = internalScrollTop.value, nextVisibleRows = visibleRowSignatures(nextRows, nextScrollTop), nextVisibleGraphics = visibleRowGraphics(nextRows, nextScrollTop), visibleChanged = prevVisibleRows.length !== nextVisibleRows.length || prevVisibleRows.some((row, index) => row !== nextVisibleRows[index]) || prevVisibleGraphics.some((row, index) => row !== nextVisibleGraphics[index]);
33930
- (!builtOnce || prevScrollTop !== nextScrollTop || visibleChanged) && (documentVersion.value++, selection.refresh());
34189
+ if (!builtOnce || prevScrollTop !== nextScrollTop || visibleChanged) {
34190
+ if (visibleChanged && prevScrollTop === nextScrollTop && prevVisibleGraphics.every((signature) => !signature) && nextVisibleGraphics.every((signature) => !signature)) {
34191
+ let rect = normalizedRect(), changedRows = [], count = Math.max(prevVisibleRows.length, nextVisibleRows.length);
34192
+ for (let index = 0; index < count; index++)
34193
+ prevVisibleRows[index] !== nextVisibleRows[index] && changedRows.push(rect.y + index);
34194
+ markRowsDirty(changedRows);
34195
+ } else
34196
+ markRowsDirty(viewportRows());
34197
+ documentVersion.value++, selection.refresh();
34198
+ }
33931
34199
  }
33932
34200
  function scheduleRebuild() {
33933
34201
  let currentVersion = ++rebuildVersion;
@@ -33984,16 +34252,60 @@ var TVirtualMarkdown = (0, import_vue33.defineComponent)({
33984
34252
  out.push(rowGraphicSignature(sourceRows[index]));
33985
34253
  return out;
33986
34254
  }
34255
+ function viewportRows() {
34256
+ let rect = normalizedRect(), result = [];
34257
+ for (let y = rect.y; y < rect.y + rect.h; y++)
34258
+ result.push(y);
34259
+ return result;
34260
+ }
34261
+ function exposedRowsForDelta2(y, height, delta) {
34262
+ let result = [];
34263
+ if (delta > 0)
34264
+ for (let offset = height - delta; offset < height; offset++)
34265
+ result.push(y + offset);
34266
+ else
34267
+ for (let offset = 0; offset < -delta; offset++)
34268
+ result.push(y + offset);
34269
+ return result;
34270
+ }
34271
+ function markRowsDirty(nextRows) {
34272
+ let rows2 = new Set(dirtyRowsHint);
34273
+ for (let y of nextRows)
34274
+ rows2.add(y);
34275
+ dirtyRowsHint = Array.from(rows2).sort((a, b) => a - b), renderNodeId && render.markDirtyRows(renderNodeId, dirtyRowsHint);
34276
+ }
34277
+ function visibleGraphicsAt(scrollTop) {
34278
+ let rect = normalizedRect(), { x: clipX, y: clipY } = clipOffsets();
34279
+ return collectVisibleMarkdownImageGraphicIds(rows.value, {
34280
+ x: rect.x,
34281
+ y: rect.y,
34282
+ w: rect.w,
34283
+ h: rect.h,
34284
+ rowOffset: scrollTop + clipY,
34285
+ clipStart: clipX
34286
+ }).size > 0;
34287
+ }
34288
+ function isClipped() {
34289
+ let rect = normalizedRect(), full = normalizedFullRect();
34290
+ return rect.x !== full.x || rect.y !== full.y || rect.w !== full.w || rect.h !== full.h;
34291
+ }
34292
+ function markScrollDamage(prevTop, nextTop) {
34293
+ let rect = normalizedRect(), delta = nextTop - prevTop;
34294
+ if (rect.h <= 0 || !delta)
34295
+ return;
34296
+ let size = terminal.size();
34297
+ props.rowScrollMode === "unsafe-full-row" && rendererCapabilities.value.scrollOperations && rect.x === 0 && rect.w >= size.cols && rect.y >= 0 && rect.y + rect.h <= size.rows && !isClipped() && Math.abs(delta) < rect.h && !dirtyRowsHint?.length && !visibleGraphicsAt(prevTop) ? (render.unsafeScrollPlaneRows(plane.value, rect.y, rect.y + rect.h, delta), markRowsDirty(exposedRowsForDelta2(rect.y, rect.h, delta))) : markRowsDirty(viewportRows());
34298
+ }
33987
34299
  function hasControlledScrollTop() {
33988
34300
  return Object.prototype.hasOwnProperty.call(instance?.vnode.props ?? {}, "scrollTop");
33989
34301
  }
33990
34302
  function applyControlledScrollTop(next, remapSelectionFocus = !1) {
33991
34303
  let desired = Math.floor(Number(next) || 0), clamped = clamp18(desired, 0, maxScrollTop()), changed = internalScrollTop.value !== clamped;
33992
- changed && (internalScrollTop.value = clamped), desired !== clamped && (emit("update:scrollTop", clamped), emit("scroll", clamped)), (changed || remapSelectionFocus) && selection.refresh(remapSelectionFocus ? { remapFocus: !0 } : void 0);
34304
+ changed && (markScrollDamage(internalScrollTop.value, clamped), internalScrollTop.value = clamped), desired !== clamped && (emit("update:scrollTop", clamped), emit("scroll", clamped)), (changed || remapSelectionFocus) && selection.refresh(remapSelectionFocus ? { remapFocus: !0 } : void 0);
33993
34305
  }
33994
34306
  function setScrollTop(next, emitChange = !0, refreshOptions) {
33995
34307
  let desired = Math.floor(Number(next) || 0), clamped = clamp18(desired, 0, maxScrollTop()), changed = internalScrollTop.value !== clamped;
33996
- changed && (internalScrollTop.value = clamped), emitChange && (changed || refreshOptions?.emitClampEvenIfUnchanged && desired !== clamped) && (emit("update:scrollTop", clamped), emit("scroll", clamped)), (changed || refreshOptions?.remapSelectionFocus) && selection.refresh(refreshOptions?.remapSelectionFocus ? { remapFocus: !0 } : void 0);
34308
+ changed && (markScrollDamage(internalScrollTop.value, clamped), internalScrollTop.value = clamped), emitChange && (changed || refreshOptions?.emitClampEvenIfUnchanged && desired !== clamped) && (emit("update:scrollTop", clamped), emit("scroll", clamped)), (changed || refreshOptions?.remapSelectionFocus) && selection.refresh(refreshOptions?.remapSelectionFocus ? { remapFocus: !0 } : void 0);
33997
34309
  }
33998
34310
  function reconcileScrollTop() {
33999
34311
  let desired = hasControlledScrollTop() ? Math.floor(Number(props.scrollTop) || 0) : internalScrollTop.value, clamped = clamp18(desired, 0, maxScrollTop());
@@ -34204,16 +34516,18 @@ var TVirtualMarkdown = (0, import_vue33.defineComponent)({
34204
34516
  keydown: onKeydown
34205
34517
  }
34206
34518
  }));
34207
- return (0, import_vue33.watchEffect)(() => {
34519
+ (0, import_vue33.watchEffect)(() => {
34208
34520
  if (!props.autoFocus || !visible.value)
34209
34521
  return;
34210
34522
  let manager = events.value, nodeId = eventNode.id.value;
34211
34523
  nodeId && manager && manager.getFocused() !== nodeId && manager.focus(nodeId);
34212
34524
  }), (0, import_vue33.onBeforeUnmount)(() => {
34213
34525
  alive = !1, rebuildVersion++, unsubscribeGraphicsOutput(), unsubscribeMathRenderer(), unsubscribeMathImage(), clearMarkdownImageGraphics(terminal, fullRect.value);
34214
- }), useRenderNode(() => ({
34526
+ });
34527
+ let renderNode = useRenderNode(() => ({
34215
34528
  zIndex: props.zIndex,
34216
34529
  rect: visible.value ? normalizedRect() : { x: 0, y: 0, w: 0, h: 0 },
34530
+ dirtyRowsHint,
34217
34531
  deps: [
34218
34532
  visible.value,
34219
34533
  absRect.value,
@@ -34226,13 +34540,25 @@ var TVirtualMarkdown = (0, import_vue33.defineComponent)({
34226
34540
  props.imageOcclusionRects
34227
34541
  ],
34228
34542
  paint: (dirtyRows) => {
34229
- withTextWidthProvider(widthProvider, () => {
34543
+ dirtyRowsHint = void 0, withTextWidthProvider(widthProvider, () => {
34230
34544
  if (!visible.value)
34231
34545
  return;
34232
34546
  let r = normalizedRect();
34233
34547
  if (r.w <= 0 || r.h <= 0)
34234
34548
  return;
34235
- let baseStyle = props.style ?? defaultStyle.value, { x: clipX, y: clipY } = clipOffsets(), isGraphicCovered = (rect) => props.imageOcclusionRects?.some((item) => intersectRect(rect, item)) === !0, keepGraphicIds = collectVisibleMarkdownImageGraphicIds(rows.value, {
34549
+ let baseStyle = props.style ?? defaultStyle.value, { x: clipX, y: clipY } = clipOffsets(), isGraphicCovered = (rect) => props.imageOcclusionRects?.some((item) => intersectRect(rect, item)) === !0, prequeuedGraphicIds = queueClippedVisibleMarkdownImageGraphics(
34550
+ terminal,
34551
+ rows.value,
34552
+ {
34553
+ x: r.x,
34554
+ y: r.y,
34555
+ w: r.w,
34556
+ h: r.h,
34557
+ rowOffset: internalScrollTop.value + clipY,
34558
+ clipStart: clipX,
34559
+ isGraphicCovered
34560
+ }
34561
+ ), keepGraphicIds = collectVisibleMarkdownImageGraphicIds(rows.value, {
34236
34562
  x: r.x,
34237
34563
  y: r.y,
34238
34564
  w: r.w,
@@ -34252,6 +34578,7 @@ var TVirtualMarkdown = (0, import_vue33.defineComponent)({
34252
34578
  baseStyle,
34253
34579
  clear: !0,
34254
34580
  keepGraphicIds,
34581
+ prequeuedGraphicIds,
34255
34582
  isGraphicCovered
34256
34583
  });
34257
34584
  };
@@ -34264,7 +34591,10 @@ var TVirtualMarkdown = (0, import_vue33.defineComponent)({
34264
34591
  paintRow(y);
34265
34592
  });
34266
34593
  }
34267
- })), () => (0, import_vue33.h)("span", rootProps);
34594
+ }));
34595
+ return (0, import_vue33.watchEffect)(() => {
34596
+ renderNodeId = renderNode.id.value;
34597
+ }), () => (0, import_vue33.h)("span", rootProps);
34268
34598
  }
34269
34599
  });
34270
34600