@simon_he/vue-tui 1.1.3 → 1.1.5

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.
Files changed (52) hide show
  1. package/README.md +18 -18
  2. package/dist/{TMermaidText-frVr8Ysb.js → TMermaidText-wLnMMvVS.js} +1 -1
  3. package/dist/{TSelect-Dx34M1pF.js → TSelect-CMBOOFwK.js} +5 -5
  4. package/dist/{TTree-DdAjCPHu.js → TTree-kk8ntrpg.js} +6 -5
  5. package/dist/agent/mermaid.d.cts +2 -2
  6. package/dist/agent/mermaid.d.ts +2 -2
  7. package/dist/agent.cjs +542 -266
  8. package/dist/agent.js +25 -82
  9. package/dist/{block-source-Crro3mxi.js → block-source-DhzajB9H.js} +299 -239
  10. package/dist/cli.cjs +57 -16
  11. package/dist/cli.js +70 -15
  12. package/dist/core.js +3 -3
  13. package/dist/{hyperlink-_1FAj7Wq.js → create-terminal-Db_-UGVQ.js} +474 -102
  14. package/dist/{dom-renderer-DXx8fWzD.js → dom-renderer-BfwAEQMf.js} +3 -2
  15. package/dist/experimental.cjs +103 -66
  16. package/dist/experimental.js +20 -74
  17. package/dist/hyperlink-clbb_ha_.js +100 -0
  18. package/dist/index.js +8 -8
  19. package/dist/{linkify-BjI4zVfY.js → linkify-CL9wwnZN.js} +3 -3
  20. package/dist/markdown.cjs +521 -212
  21. package/dist/markdown.d.cts +3 -0
  22. package/dist/markdown.d.ts +3 -0
  23. package/dist/markdown.js +75 -8
  24. package/dist/math-image-BZhmfUeu.js +308 -0
  25. package/dist/mermaid-N3kGTHFy.js +1697 -0
  26. package/dist/mermaid.cjs +1460 -6
  27. package/dist/mermaid.d.cts +4 -0
  28. package/dist/mermaid.d.ts +4 -0
  29. package/dist/mermaid.js +7 -5
  30. package/dist/{rect-DUpeDfBg.js → rect-JzWMJxxc.js} +1 -1
  31. package/dist/renderer/cli/stdout-renderer.d.ts +44 -0
  32. package/dist/renderer/terminal-graphics.d.ts +61 -0
  33. package/dist/renderer-dom.js +4 -4
  34. package/dist/{terminal-graphics-Bbe83wSr.js → terminal-graphics-2FTRg9x3.js} +90 -2
  35. package/dist/{tlog-theme-i6S_Oftd.js → tlog-theme-B91Wv7Zj.js} +5 -4
  36. package/dist/vue/components/TAgentTerminalGraphic.d.ts +1 -1
  37. package/dist/vue/components/TMarkdownText.d.ts +70 -2
  38. package/dist/vue/components/TMermaidImage.d.ts +920 -0
  39. package/dist/vue/components/TMermaidText.d.ts +2 -2
  40. package/dist/vue/components/TVirtualMarkdown.d.ts +70 -2
  41. package/dist/vue/markdown/ast.d.ts +5 -0
  42. package/dist/vue/markdown/document.d.ts +3 -0
  43. package/dist/vue/markdown/math-image.d.ts +68 -0
  44. package/dist/vue/markdown/theme.d.ts +12 -0
  45. package/dist/vue/markdown/types.d.ts +12 -2
  46. package/dist/vue/mermaid/beautiful-mermaid.d.ts +284 -240
  47. package/dist/vue/mermaid/mermaid-image.d.ts +73 -0
  48. package/dist/vue.js +9 -9
  49. package/package.json +24 -10
  50. package/dist/mermaid-BNhM1jAZ.js +0 -123
  51. package/dist/width-GqllnV8C.js +0 -474
  52. /package/dist/{ansi-palette-CH6jc2Z7.js → ansi-palette-BHF1rN7R.js} +0 -0
package/dist/mermaid.cjs CHANGED
@@ -28,11 +28,22 @@ __export(mermaid_exports, {
28
28
  TBeautifulMermaid: () => TBeautifulMermaid,
29
29
  TBeautifulMermaidText: () => TBeautifulMermaidText,
30
30
  TMermaid: () => TMermaid,
31
+ TMermaidImage: () => TMermaidImage,
31
32
  TMermaidText: () => TMermaidText2,
32
33
  beautifulMermaidRenderer: () => beautifulMermaidRenderer,
34
+ clearMermaidImageCache: () => clearMermaidImageCache,
33
35
  createBeautifulMermaidRenderer: () => createBeautifulMermaidRenderer,
36
+ getCachedMermaidImage: () => getCachedMermaidImage,
37
+ getMermaidImage: () => getMermaidImage,
38
+ isMermaidImageRendererReady: () => isMermaidImageRendererReady,
34
39
  isSimpleMermaidFlowchartSource: () => isSimpleMermaidFlowchartSource,
35
- markMermaidRenderErrorFatal: () => markMermaidRenderErrorFatal
40
+ loadMermaidImageRenderer: () => loadMermaidImageRenderer,
41
+ markMermaidRenderErrorFatal: () => markMermaidRenderErrorFatal,
42
+ normalizeMermaidImageOptions: () => normalizeMermaidImageOptions,
43
+ resolveMermaidImageColor: () => resolveMermaidImageColor,
44
+ resolveMermaidSvgForResvg: () => resolveMermaidSvgForResvg,
45
+ setMermaidImageRasterizer: () => setMermaidImageRasterizer,
46
+ subscribeMermaidImage: () => subscribeMermaidImage
36
47
  });
37
48
  module.exports = __toCommonJS(mermaid_exports);
38
49
 
@@ -1385,8 +1396,8 @@ var tMermaidTextProps = {
1385
1396
  return snapshot && snapshot.source === source.value && hasVisibleRenderedOutput(snapshot.lines) ? snapshot.lines : sourceLines.value;
1386
1397
  }), currentStyle = (0, import_vue8.computed)(() => props.style ?? defaultStyle.value), fullHeight = (0, import_vue8.computed)(() => {
1387
1398
  if (props.h != null) {
1388
- let h3 = Math.floor(Number(props.h));
1389
- return Number.isFinite(h3) ? Math.max(0, h3) : 0;
1399
+ let h4 = Math.floor(Number(props.h));
1400
+ return Number.isFinite(h4) ? Math.max(0, h4) : 0;
1390
1401
  }
1391
1402
  let autoContentHeight = Math.max(1, displayLines.value.length);
1392
1403
  return reservesBoxRows.value ? autoContentHeight + 2 : autoContentHeight;
@@ -1587,7 +1598,1427 @@ var tMermaidTextProps = {
1587
1598
  });
1588
1599
 
1589
1600
  // src/vue/mermaid/beautiful-mermaid.ts
1601
+ var import_vue10 = require("vue");
1602
+
1603
+ // src/vue/components/TMermaidImage.ts
1590
1604
  var import_vue9 = require("vue");
1605
+
1606
+ // src/core/terminal/create-terminal.ts
1607
+ var TERMINAL_PLANE_INTERNALS = Symbol.for("@simon_he/vue-tui:v1:terminal-plane-internals"), TERMINAL_ROOT = Symbol.for("@simon_he/vue-tui:v1:terminal-root");
1608
+ function getRootTerminal(terminal) {
1609
+ return terminal[TERMINAL_ROOT] ?? terminal;
1610
+ }
1611
+
1612
+ // src/renderer/terminal-graphics.ts
1613
+ var ESC2 = "\x1B", BEL2 = "\x07", ST = `${ESC2}\\`, ESC_RE = "\\u001B", BEL_RE = "\\u0007", CSI_RE = new RegExp(`${ESC_RE}\\[[0-?]*[ -/]*[@-~]`, "g"), OSC_RE = new RegExp(`${ESC_RE}\\][\\s\\S]*?(?:${BEL_RE}|${ESC_RE}\\\\)`, "g"), DCS_RE = new RegExp(`${ESC_RE}P[\\s\\S]*?${ESC_RE}\\\\`, "g"), APC_RE = new RegExp(`${ESC_RE}_[\\s\\S]*?${ESC_RE}\\\\`, "g"), C1_CSI_RE = new RegExp("\\u009B[0-?]*[ -/]*[@-~]", "g"), C1_OSC_RE = new RegExp(`\\u009D[\\s\\S]*?(?:${BEL_RE}|\\u009C)`, "g"), C1_DCS_RE = new RegExp("\\u0090[\\s\\S]*?\\u009C", "g"), C1_APC_RE = new RegExp("\\u009F[\\s\\S]*?\\u009C", "g"), MAX_TERMINAL_GRAPHICS_SEQUENCE_CHARS = 16 * 1024 * 1024;
1614
+ var MAX_TERMINAL_GRAPHIC_CELLS = 1e4, TERMINAL_GRAPHICS_REGISTRY = Symbol.for("@simon_he/vue-tui:v1:terminal-graphics"), terminalGraphicsGlobal = globalThis, terminalGraphicsRegistry = terminalGraphicsGlobal[TERMINAL_GRAPHICS_REGISTRY] ?? {
1615
+ outputs: /* @__PURE__ */ new WeakMap(),
1616
+ outputVersions: /* @__PURE__ */ new WeakMap(),
1617
+ outputListeners: /* @__PURE__ */ new WeakMap()
1618
+ };
1619
+ terminalGraphicsGlobal[TERMINAL_GRAPHICS_REGISTRY] = terminalGraphicsRegistry;
1620
+ var terminalGraphicsOutputs = terminalGraphicsRegistry.outputs, terminalGraphicsOutputVersions = terminalGraphicsRegistry.outputVersions, terminalGraphicsOutputListeners = terminalGraphicsRegistry.outputListeners;
1621
+ function getTerminalGraphicsOutput(terminal) {
1622
+ return terminalGraphicsOutputs.get(getRootTerminal(terminal)) ?? null;
1623
+ }
1624
+ function getTerminalGraphicsOutputVersion(terminal) {
1625
+ return terminalGraphicsOutputVersions.get(getRootTerminal(terminal)) ?? 0;
1626
+ }
1627
+ function subscribeTerminalGraphicsOutput(terminal, listener) {
1628
+ let rootTerminal = getRootTerminal(terminal), listeners = terminalGraphicsOutputListeners.get(rootTerminal);
1629
+ return listeners || (listeners = /* @__PURE__ */ new Set(), terminalGraphicsOutputListeners.set(rootTerminal, listeners)), listeners.add(listener), () => {
1630
+ listeners.delete(listener), listeners.size === 0 && terminalGraphicsOutputListeners.delete(rootTerminal);
1631
+ };
1632
+ }
1633
+ function stableTerminalGraphicNumericId(input, options = {}) {
1634
+ let min = Math.floor(options.min ?? 1), max = Math.floor(options.max ?? 2147483647), span = Math.max(1, max - min + 1), hash = 2166136261;
1635
+ for (let index = 0; index < input.length; index += 1)
1636
+ hash ^= input.charCodeAt(index), hash = Math.imul(hash, 16777619);
1637
+ return min + (hash >>> 0) % span;
1638
+ }
1639
+ function positiveGraphicInt(value, max) {
1640
+ let n = Math.trunc(Number(value));
1641
+ return !Number.isFinite(n) || n <= 0 ? null : Math.min(max, n);
1642
+ }
1643
+ function normalizeTerminalGraphicSize(width, height) {
1644
+ let w = positiveGraphicInt(width, MAX_TERMINAL_GRAPHIC_CELLS), h4 = positiveGraphicInt(height, MAX_TERMINAL_GRAPHIC_CELLS);
1645
+ return w == null || h4 == null || w * h4 > MAX_TERMINAL_GRAPHIC_CELLS ? null : { width: w, height: h4 };
1646
+ }
1647
+ function isBase64ish(value) {
1648
+ return /^[A-Za-z0-9+/=]*$/.test(value);
1649
+ }
1650
+ var KITTY_UINT32_MAX = 4294967295, KITTY_INT32_MIN = -2147483648, KITTY_INT32_MAX = 2147483647;
1651
+ function validateIterm2Dimension(value) {
1652
+ return /^auto$/i.test(value) || /^(?:[1-9]\d{0,4})(?:px|%)?$/.test(value);
1653
+ }
1654
+ function uint32Control(key, value, min = 0) {
1655
+ if (value == null)
1656
+ return "";
1657
+ let n = Math.floor(value);
1658
+ return Number.isSafeInteger(n) && n >= min && n <= KITTY_UINT32_MAX ? `${key}=${n}` : "";
1659
+ }
1660
+ function int32Control(key, value) {
1661
+ if (value == null)
1662
+ return "";
1663
+ let n = Math.floor(value);
1664
+ return Number.isSafeInteger(n) && n >= KITTY_INT32_MIN && n <= KITTY_INT32_MAX ? `${key}=${n}` : "";
1665
+ }
1666
+ function sanitizeBase64(value) {
1667
+ let data = String(value ?? "").replace(/\s+/g, "");
1668
+ return isBase64ish(data) ? data : "";
1669
+ }
1670
+ function kittyGraphicCellControls(columns, rows) {
1671
+ if (columns == null && rows == null)
1672
+ return [];
1673
+ let size = normalizeTerminalGraphicSize(columns ?? 1, rows ?? 1);
1674
+ return size ? [columns == null ? "" : `c=${size.width}`, rows == null ? "" : `r=${size.height}`] : [];
1675
+ }
1676
+ function kittyGraphicSourceControls(sourceX, sourceY, sourceWidth, sourceHeight) {
1677
+ return [
1678
+ uint32Control("x", sourceX),
1679
+ uint32Control("y", sourceY),
1680
+ uint32Control("w", sourceWidth, 1),
1681
+ uint32Control("h", sourceHeight, 1)
1682
+ ];
1683
+ }
1684
+ function chunkBase64(value, chunkSize) {
1685
+ let normalizedSize = Math.max(4, Math.floor(chunkSize / 4) * 4), chunks = [];
1686
+ for (let index = 0; index < value.length; index += normalizedSize)
1687
+ chunks.push(value.slice(index, index + normalizedSize));
1688
+ return chunks.length ? chunks : [""];
1689
+ }
1690
+ function createKittyPlacementSequence(options) {
1691
+ let imageId = uint32Control("i", options.imageId), imageNumber = uint32Control("I", options.imageNumber);
1692
+ if (!imageId && !imageNumber)
1693
+ return "";
1694
+ let controls = [
1695
+ "a=p",
1696
+ options.quiet === !1 ? "" : "q=2",
1697
+ options.noCursorMove === !1 ? "" : "C=1",
1698
+ imageId,
1699
+ imageNumber,
1700
+ uint32Control("p", options.placementId),
1701
+ ...kittyGraphicCellControls(options.columns, options.rows),
1702
+ ...kittyGraphicSourceControls(
1703
+ options.sourceX,
1704
+ options.sourceY,
1705
+ options.sourceWidth,
1706
+ options.sourceHeight
1707
+ ),
1708
+ int32Control("z", options.zIndex)
1709
+ ].filter(Boolean);
1710
+ return `${ESC2}_G${controls.join(",")}${ST}`;
1711
+ }
1712
+ function createKittyGraphicsSequence(base64Png, options = {}) {
1713
+ let data = sanitizeBase64(base64Png);
1714
+ if (!data)
1715
+ return "";
1716
+ let chunks = chunkBase64(data, options.chunkSize ?? 4096), baseControls = [
1717
+ "a=T",
1718
+ "f=100",
1719
+ options.quiet === !1 ? "" : "q=2",
1720
+ options.noCursorMove === !1 ? "" : "C=1",
1721
+ uint32Control("i", options.imageId),
1722
+ uint32Control("I", options.imageNumber),
1723
+ uint32Control("p", options.placementId),
1724
+ ...kittyGraphicCellControls(options.columns, options.rows),
1725
+ ...kittyGraphicSourceControls(
1726
+ options.sourceX,
1727
+ options.sourceY,
1728
+ options.sourceWidth,
1729
+ options.sourceHeight
1730
+ ),
1731
+ int32Control("z", options.zIndex)
1732
+ ].filter(Boolean);
1733
+ return chunks.map((chunk, index) => {
1734
+ let last = index === chunks.length - 1, controls = index === 0 ? [...baseControls, chunks.length > 1 ? `m=${last ? 0 : 1}` : ""] : [options.quiet === !1 ? "" : "q=2", `m=${last ? 0 : 1}`].filter(Boolean);
1735
+ return `${ESC2}_G${controls.filter(Boolean).join(",")};${chunk}${ST}`;
1736
+ }).join("");
1737
+ }
1738
+ function createKittyDeleteGraphicsSequence(options = {}) {
1739
+ let controls = ["a=d"];
1740
+ if (options.allVisible)
1741
+ controls.push(`d=${options.freeImageData ? "A" : "a"}`);
1742
+ else if (options.imageId != null) {
1743
+ let imageId = uint32Control("i", options.imageId), placementId = uint32Control("p", options.placementId);
1744
+ if (!imageId || options.placementId != null && !placementId)
1745
+ return "";
1746
+ controls.push(`d=${options.freeImageData ? "I" : "i"}`), controls.push(imageId), controls.push(placementId);
1747
+ } else if (options.currentCell)
1748
+ controls.push(`d=${options.freeImageData ? "C" : "c"}`);
1749
+ else
1750
+ return "";
1751
+ return options.quiet !== !1 && controls.push("q=2"), `${ESC2}_G${controls.filter(Boolean).join(",")}${ST}`;
1752
+ }
1753
+ function createIterm2InlineImageSequence(base64Data, options = {}) {
1754
+ let data = sanitizeBase64(base64Data);
1755
+ if (!data)
1756
+ return "";
1757
+ let params = [
1758
+ "inline=1",
1759
+ options.width != null ? `width=${formatItermDimension(options.width)}` : "",
1760
+ options.height != null ? `height=${formatItermDimension(options.height)}` : "",
1761
+ `preserveAspectRatio=${options.preserveAspectRatio === !1 ? 0 : 1}`,
1762
+ options.doNotMoveCursor === !1 ? "" : "doNotMoveCursor=1"
1763
+ ].filter(Boolean);
1764
+ return `${ESC2}]1337;File=${params.join(";")}:${data}${BEL2}`;
1765
+ }
1766
+ function formatItermDimension(value) {
1767
+ if (typeof value == "number") {
1768
+ let n = Math.floor(value);
1769
+ return Number.isFinite(n) ? String(Math.min(99999, Math.max(1, n))) : "auto";
1770
+ }
1771
+ let raw = String(value ?? "").trim();
1772
+ return validateIterm2Dimension(raw) ? raw : "auto";
1773
+ }
1774
+ function resolveKittyPngSourceCrop(rect, fullRect, sourceWidth, sourceHeight) {
1775
+ if (fullRect.w <= 0 || fullRect.h <= 0)
1776
+ return null;
1777
+ let offsetX = Math.max(0, rect.x - fullRect.x), offsetY = Math.max(0, rect.y - fullRect.y), visibleW = Math.max(0, Math.min(rect.w, fullRect.w - offsetX)), visibleH = Math.max(0, Math.min(rect.h, fullRect.h - offsetY));
1778
+ if (offsetX <= 0 && offsetY <= 0 && visibleW >= fullRect.w && visibleH >= fullRect.h)
1779
+ return null;
1780
+ let sourceX = Math.max(
1781
+ 0,
1782
+ Math.min(sourceWidth - 1, Math.floor(offsetX * sourceWidth / fullRect.w))
1783
+ ), sourceY = Math.max(
1784
+ 0,
1785
+ Math.min(sourceHeight - 1, Math.floor(offsetY * sourceHeight / fullRect.h))
1786
+ ), sourceRight = Math.max(
1787
+ sourceX + 1,
1788
+ Math.min(sourceWidth, Math.ceil((offsetX + visibleW) * sourceWidth / fullRect.w))
1789
+ ), sourceBottom = Math.max(
1790
+ sourceY + 1,
1791
+ Math.min(sourceHeight, Math.ceil((offsetY + visibleH) * sourceHeight / fullRect.h))
1792
+ );
1793
+ return {
1794
+ sourceX,
1795
+ sourceY,
1796
+ sourceWidth: sourceRight - sourceX,
1797
+ sourceHeight: sourceBottom - sourceY
1798
+ };
1799
+ }
1800
+ function createTerminalGraphicPngSequence(options) {
1801
+ if (options.protocol === "kitty") {
1802
+ let placement = {
1803
+ columns: options.placementColumns,
1804
+ rows: options.placementRows
1805
+ };
1806
+ if (options.rect && options.fullRect && options.sourceWidth && options.sourceHeight) {
1807
+ let crop = resolveKittyPngSourceCrop(
1808
+ options.rect,
1809
+ options.fullRect,
1810
+ options.sourceWidth,
1811
+ options.sourceHeight
1812
+ );
1813
+ crop && (placement = { ...placement, ...crop });
1814
+ }
1815
+ let transmissionPlacement = options.cropTransmission !== !1 ? placement : {
1816
+ columns: options.transmissionColumns ?? options.placementColumns,
1817
+ rows: options.transmissionRows ?? options.placementRows
1818
+ };
1819
+ return {
1820
+ type: "sequence",
1821
+ protocol: "kitty",
1822
+ sequence: createKittyGraphicsSequence(options.base64, {
1823
+ imageId: options.imageId,
1824
+ placementId: options.placementId,
1825
+ zIndex: options.zIndex,
1826
+ ...transmissionPlacement
1827
+ }),
1828
+ resizeSequence: createKittyPlacementSequence({
1829
+ imageId: options.imageId,
1830
+ placementId: options.placementId,
1831
+ zIndex: options.zIndex,
1832
+ ...placement
1833
+ }),
1834
+ clearSequence: createKittyDeleteGraphicsSequence({
1835
+ imageId: options.imageId,
1836
+ placementId: options.placementId,
1837
+ freeImageData: options.freeImageData
1838
+ }),
1839
+ ...options.fallback != null ? { fallback: options.fallback } : {},
1840
+ ...options.cols != null ? { cols: options.cols } : {},
1841
+ ...options.rows != null ? { rows: options.rows } : {},
1842
+ ...options.sourceWidth != null ? { sourceWidth: options.sourceWidth } : {},
1843
+ ...options.sourceHeight != null ? { sourceHeight: options.sourceHeight } : {},
1844
+ ...options.zIndex != null ? { zIndex: options.zIndex } : {}
1845
+ };
1846
+ }
1847
+ return options.protocol === "iterm2" ? {
1848
+ type: "sequence",
1849
+ protocol: "iterm2",
1850
+ sequence: createIterm2InlineImageSequence(options.base64, {
1851
+ width: options.cols,
1852
+ height: options.rows,
1853
+ preserveAspectRatio: !0,
1854
+ doNotMoveCursor: !0
1855
+ }),
1856
+ ...options.fallback != null ? { fallback: options.fallback } : {},
1857
+ ...options.cols != null ? { cols: options.cols } : {},
1858
+ ...options.rows != null ? { rows: options.rows } : {},
1859
+ ...options.sourceWidth != null ? { sourceWidth: options.sourceWidth } : {},
1860
+ ...options.sourceHeight != null ? { sourceHeight: options.sourceHeight } : {}
1861
+ } : null;
1862
+ }
1863
+
1864
+ // src/vue/markdown/math-image.ts
1865
+ var DEFAULT_MATH_IMAGE_OPTIONS = Object.freeze({
1866
+ cellWidthPx: 8,
1867
+ cellHeightPx: 16,
1868
+ scale: 2,
1869
+ color: "#f8f8f2",
1870
+ maxWidthCells: 0,
1871
+ baselineRatio: 0.78
1872
+ });
1873
+ var NAMED_STYLE_FG_HEX = Object.freeze({
1874
+ black: "#000000",
1875
+ red: "#e53935",
1876
+ green: "#43a047",
1877
+ yellow: "#fdd835",
1878
+ blue: "#1e88e5",
1879
+ magenta: "#d81b60",
1880
+ cyan: "#00acc1",
1881
+ white: "#ffffff",
1882
+ gray: "#9e9e9e",
1883
+ grey: "#9e9e9e",
1884
+ blackBright: "#4a4a4a",
1885
+ redBright: "#ff6e6e",
1886
+ greenBright: "#69db7c",
1887
+ yellowBright: "#ffe066",
1888
+ blueBright: "#74c0fc",
1889
+ magentaBright: "#f783ac",
1890
+ cyanBright: "#3bc9db",
1891
+ whiteBright: "#f8f8f2",
1892
+ grayBright: "#bdbdbd",
1893
+ greyBright: "#bdbdbd"
1894
+ });
1895
+ function resolveMarkdownMathColor(fg) {
1896
+ if (typeof fg != "string" || !fg)
1897
+ return;
1898
+ let trimmed = fg.trim();
1899
+ return trimmed.startsWith("#") && /^#[0-9a-f]{3,8}$/i.test(trimmed) ? trimmed.toLowerCase() : NAMED_STYLE_FG_HEX[trimmed.toLowerCase()];
1900
+ }
1901
+
1902
+ // src/vue/mermaid/mermaid-image.ts
1903
+ var DEFAULT_MERMAID_IMAGE_OPTIONS = Object.freeze({
1904
+ cellWidthPx: 8,
1905
+ cellHeightPx: 16,
1906
+ scale: 2,
1907
+ bg: "#1e1e2e",
1908
+ fg: "#f8f8f2",
1909
+ maxWidthCells: 0,
1910
+ maxHeightCells: 0,
1911
+ padding: 40
1912
+ }), MAX_CACHE_ENTRIES = 48, MAX_FAILED_ENTRIES = 96, mermaidImageCache = /* @__PURE__ */ new Map(), mermaidImageFailed = /* @__PURE__ */ new Set(), mermaidImageInflight = /* @__PURE__ */ new Map(), mermaidImageListeners = /* @__PURE__ */ new Set(), customRasterizer = null, builtinRasterizerLoad = null, builtinRasterizerReady = !1;
1913
+ function normalizeMermaidImageOptions(options) {
1914
+ return {
1915
+ cellWidthPx: Math.max(
1916
+ 1,
1917
+ Math.floor(options?.cellWidthPx ?? DEFAULT_MERMAID_IMAGE_OPTIONS.cellWidthPx)
1918
+ ),
1919
+ cellHeightPx: Math.max(
1920
+ 1,
1921
+ Math.floor(options?.cellHeightPx ?? DEFAULT_MERMAID_IMAGE_OPTIONS.cellHeightPx)
1922
+ ),
1923
+ scale: Math.max(1, Math.floor(options?.scale ?? DEFAULT_MERMAID_IMAGE_OPTIONS.scale)),
1924
+ bg: options?.bg ?? DEFAULT_MERMAID_IMAGE_OPTIONS.bg,
1925
+ fg: options?.fg ?? DEFAULT_MERMAID_IMAGE_OPTIONS.fg,
1926
+ maxWidthCells: Math.max(0, Math.floor(options?.maxWidthCells ?? 0)),
1927
+ maxHeightCells: Math.max(0, Math.floor(options?.maxHeightCells ?? 0)),
1928
+ padding: Math.max(0, Math.floor(options?.padding ?? DEFAULT_MERMAID_IMAGE_OPTIONS.padding))
1929
+ };
1930
+ }
1931
+ function resolveMermaidImageColor(fg) {
1932
+ return resolveMarkdownMathColor(fg);
1933
+ }
1934
+ function setMermaidImageRasterizer(rasterizer) {
1935
+ customRasterizer = rasterizer;
1936
+ }
1937
+ function subscribeMermaidImage(listener) {
1938
+ return mermaidImageListeners.add(listener), () => mermaidImageListeners.delete(listener);
1939
+ }
1940
+ function isMermaidImageRendererReady() {
1941
+ return customRasterizer != null || builtinRasterizerReady;
1942
+ }
1943
+ async function loadMermaidImageRenderer() {
1944
+ return isMermaidImageRendererReady() ? !0 : (builtinRasterizerReady = (customRasterizer ?? await loadBuiltinMermaidRasterizer()) != null, builtinRasterizerReady);
1945
+ }
1946
+ function hashMermaidImageKey(value) {
1947
+ let hash = 2166136261;
1948
+ for (let i = 0; i < value.length; i++)
1949
+ hash ^= value.charCodeAt(i), hash = Math.imul(hash, 16777619);
1950
+ return (hash >>> 0).toString(36);
1951
+ }
1952
+ function mermaidImageCacheKey(code, options) {
1953
+ return hashMermaidImageKey(
1954
+ [
1955
+ code,
1956
+ options.cellWidthPx,
1957
+ options.cellHeightPx,
1958
+ options.scale,
1959
+ options.bg,
1960
+ options.fg,
1961
+ options.maxWidthCells,
1962
+ options.maxHeightCells,
1963
+ options.padding
1964
+ ].join("")
1965
+ );
1966
+ }
1967
+ function notifyMermaidImageListeners() {
1968
+ for (let listener of mermaidImageListeners)
1969
+ try {
1970
+ listener();
1971
+ } catch {
1972
+ }
1973
+ }
1974
+ function getCachedMermaidImage(code, options) {
1975
+ return mermaidImageCache.get(mermaidImageCacheKey(code, normalizeMermaidImageOptions(options))) ?? null;
1976
+ }
1977
+ function clearMermaidImageCache() {
1978
+ mermaidImageCache.clear(), mermaidImageFailed.clear();
1979
+ }
1980
+ function evictOldestMermaidImageEntry() {
1981
+ let oldest = mermaidImageCache.keys().next().value;
1982
+ oldest != null && mermaidImageCache.delete(oldest);
1983
+ }
1984
+ async function getMermaidImage(code, options) {
1985
+ let source = String(code ?? "").trim();
1986
+ if (!source)
1987
+ return null;
1988
+ let normalized = normalizeMermaidImageOptions(options), key = mermaidImageCacheKey(source, normalized), cached = mermaidImageCache.get(key);
1989
+ if (cached)
1990
+ return cached;
1991
+ if (mermaidImageFailed.has(key))
1992
+ return null;
1993
+ let inflight = mermaidImageInflight.get(key);
1994
+ if (inflight)
1995
+ return inflight;
1996
+ let pending = (async () => {
1997
+ try {
1998
+ let rasterizer = customRasterizer ?? await loadBuiltinMermaidRasterizer();
1999
+ if (!rasterizer)
2000
+ return null;
2001
+ let result = await rasterizer(source, normalized);
2002
+ if (result && result.base64)
2003
+ mermaidImageCache.set(key, result), mermaidImageCache.size > MAX_CACHE_ENTRIES && evictOldestMermaidImageEntry(), notifyMermaidImageListeners();
2004
+ else if (result === null && (mermaidImageFailed.add(key), mermaidImageFailed.size > MAX_FAILED_ENTRIES)) {
2005
+ let oldest = mermaidImageFailed.values().next().value;
2006
+ oldest != null && mermaidImageFailed.delete(oldest);
2007
+ }
2008
+ return result;
2009
+ } catch {
2010
+ return null;
2011
+ } finally {
2012
+ mermaidImageInflight.delete(key);
2013
+ }
2014
+ })();
2015
+ return mermaidImageInflight.set(key, pending), pending;
2016
+ }
2017
+ function base64FromBytes(bytes) {
2018
+ let binary = "";
2019
+ for (let offset = 0; offset < bytes.length; offset += 32768)
2020
+ binary += String.fromCharCode(...bytes.subarray(offset, offset + 32768));
2021
+ return typeof btoa == "function" ? btoa(binary) : Buffer.from(bytes).toString("base64");
2022
+ }
2023
+ function positiveInt(value) {
2024
+ let n = Math.floor(Number(value));
2025
+ return Number.isFinite(n) && n > 0 ? n : void 0;
2026
+ }
2027
+ function clampCellsToLimits(widthCells, heightCells, maxWidthCells, maxHeightCells) {
2028
+ let w = widthCells, h4 = heightCells;
2029
+ return maxWidthCells > 0 && w > maxWidthCells && (h4 = Math.max(1, Math.round(h4 * maxWidthCells / w)), w = maxWidthCells), maxHeightCells > 0 && h4 > maxHeightCells && (w = Math.max(1, Math.round(w * maxHeightCells / h4)), h4 = maxHeightCells), { widthCells: Math.max(1, w), heightCells: Math.max(1, h4) };
2030
+ }
2031
+ var RESVG_MODULE_ID = "@resvg/resvg-js";
2032
+ function svgRenderFunction(mod) {
2033
+ let candidates = [
2034
+ mod.renderMermaidSVGAsync,
2035
+ mod.renderMermaidSVG,
2036
+ mod.renderMermaid,
2037
+ mod.default?.renderMermaidSVGAsync,
2038
+ mod.default?.renderMermaidSVG
2039
+ ];
2040
+ for (let candidate of candidates)
2041
+ if (typeof candidate == "function")
2042
+ return candidate;
2043
+ return null;
2044
+ }
2045
+ function resolveMermaidSvgForResvg(svg, fallbackBg, fallbackFg) {
2046
+ let { bg, fg } = extractSvgRootStyleColors(svg, fallbackBg, fallbackFg), variables = extractSvgCssVariables(svg), root = { bg, fg }, resolved = svg, guard = 0;
2047
+ for (; (resolved.includes("var(") || resolved.includes("color-mix(")) && guard++ < 500; ) {
2048
+ let varIndex = resolved.lastIndexOf("var("), mixIndex = resolved.lastIndexOf("color-mix("), at = Math.max(varIndex, mixIndex);
2049
+ if (at < 0)
2050
+ break;
2051
+ let open = resolved.indexOf("(", at), close = findMatchingSvgParen(resolved, open);
2052
+ if (open < 0 || close < 0)
2053
+ break;
2054
+ let expr = resolved.slice(at, close + 1), color = resolveSvgColorExpr(expr, root, variables);
2055
+ resolved = resolved.slice(0, at) + color + resolved.slice(close + 1);
2056
+ }
2057
+ return stripSvgStyleBlocks(resolved);
2058
+ }
2059
+ function extractSvgRootStyleColors(svg, fallbackBg, fallbackFg) {
2060
+ let bg = fallbackBg, fg = fallbackFg, styleMatch = /<svg\b[^>]*\bstyle="([^"]*)"/i.exec(svg);
2061
+ if (styleMatch?.[1]) {
2062
+ let bgMatch = /(?:^|;)\s*--bg\s*:\s*([^;]+)/i.exec(styleMatch[1]), fgMatch = /(?:^|;)\s*--fg\s*:\s*([^;]+)/i.exec(styleMatch[1]);
2063
+ bgMatch?.[1] && (bg = bgMatch[1].trim()), fgMatch?.[1] && (fg = fgMatch[1].trim());
2064
+ }
2065
+ return { bg, fg };
2066
+ }
2067
+ function extractSvgCssVariables(svg) {
2068
+ let map = /* @__PURE__ */ new Map(), styleMatch = /<style[^>]*>([\s\S]*?)<\/style>/i.exec(svg);
2069
+ if (!styleMatch?.[1])
2070
+ return map;
2071
+ let declaration = /(--[A-Za-z0-9_-]+)\s*:\s*([^;{}]+);/g, match;
2072
+ for (; (match = declaration.exec(styleMatch[1])) !== null; )
2073
+ map.set(match[1], match[2].trim());
2074
+ return map;
2075
+ }
2076
+ function stripSvgStyleBlocks(svg) {
2077
+ return svg.replace(/<style[^>]*>[\s\S]*?<\/style>/gi, "");
2078
+ }
2079
+ function findMatchingSvgParen(input, openIndex) {
2080
+ let depth = 0;
2081
+ for (let i = openIndex; i < input.length; i++) {
2082
+ let ch = input[i];
2083
+ if (ch === "(")
2084
+ depth++;
2085
+ else if (ch === ")" && (depth--, depth === 0))
2086
+ return i;
2087
+ }
2088
+ return -1;
2089
+ }
2090
+ function findTopLevelSvgComma(input) {
2091
+ let depth = 0;
2092
+ for (let i = 0; i < input.length; i++) {
2093
+ let ch = input[i];
2094
+ if (ch === "(")
2095
+ depth++;
2096
+ else if (ch === ")")
2097
+ depth--;
2098
+ else if (ch === "," && depth === 0)
2099
+ return i;
2100
+ }
2101
+ return -1;
2102
+ }
2103
+ function normalizeHexColor(value) {
2104
+ let match = /^#([0-9a-f]{3}|[0-9a-f]{6})$/i.exec(value.trim());
2105
+ if (!match)
2106
+ return null;
2107
+ let hex = match[1];
2108
+ return hex.length === 3 && (hex = hex.split("").map((ch) => ch + ch).join("")), `#${hex.toLowerCase()}`;
2109
+ }
2110
+ function mixSrgbColors(aHex, bHex, percent) {
2111
+ let a = parseHexRgb(aHex), b = parseHexRgb(bHex), p = Math.max(0, Math.min(100, percent)) / 100, mix = (x, y) => Math.round(x * p + y * (1 - p)), toHex = (value) => value.toString(16).padStart(2, "0");
2112
+ return `#${toHex(mix(a[0], b[0]))}${toHex(mix(a[1], b[1]))}${toHex(mix(a[2], b[2]))}`;
2113
+ }
2114
+ function parseHexRgb(hex) {
2115
+ return [
2116
+ parseInt(hex.slice(1, 3), 16),
2117
+ parseInt(hex.slice(3, 5), 16),
2118
+ parseInt(hex.slice(5, 7), 16)
2119
+ ];
2120
+ }
2121
+ function resolveSvgColorExpr(expr, root, variables) {
2122
+ let value = expr.trim();
2123
+ if (value.startsWith("var(")) {
2124
+ let close = findMatchingSvgParen(value, 3);
2125
+ if (close < 0)
2126
+ return value;
2127
+ let inner = value.slice(4, close).trim(), comma = findTopLevelSvgComma(inner), name = (comma < 0 ? inner : inner.slice(0, comma)).trim(), fallback = comma < 0 ? "" : inner.slice(comma + 1).trim(), direct = name === "--fg" ? root.fg : name === "--bg" ? root.bg : variables.get(name);
2128
+ return direct != null ? resolveSvgColorExpr(direct, root, variables) : fallback ? resolveSvgColorExpr(fallback, root, variables) : value;
2129
+ }
2130
+ if (value.startsWith("color-mix(")) {
2131
+ let close = findMatchingSvgParen(value, 9);
2132
+ if (close < 0)
2133
+ return value;
2134
+ let afterMethod = value.slice(10, close).trim().replace(/^in\s+srgb\s*,\s*/i, ""), comma = findTopLevelSvgComma(afterMethod);
2135
+ if (comma < 0)
2136
+ return value;
2137
+ let left = afterMethod.slice(0, comma).trim(), right = afterMethod.slice(comma + 1).trim(), leftMatch = /^([^%\s]+)\s+([\d.]+)%$/.exec(left) ?? /^([\d.]+)%\s+([^%\s]+)$/.exec(left);
2138
+ if (!leftMatch)
2139
+ return value;
2140
+ let a = normalizeHexColor(resolveSvgColorExpr(leftMatch[1], root, variables)), b = normalizeHexColor(resolveSvgColorExpr(right, root, variables));
2141
+ return !a || !b ? value : mixSrgbColors(a, b, Number(leftMatch[2]));
2142
+ }
2143
+ return normalizeHexColor(value) ?? value;
2144
+ }
2145
+ function loadBuiltinMermaidRasterizer() {
2146
+ return builtinRasterizerLoad || (builtinRasterizerLoad = (async () => {
2147
+ try {
2148
+ let [mermaidMod, resvgMod] = await Promise.all([
2149
+ import("beautiful-mermaid").then(
2150
+ (mod) => mod,
2151
+ () => null
2152
+ ),
2153
+ import(RESVG_MODULE_ID).then(
2154
+ (mod) => mod,
2155
+ () => null
2156
+ )
2157
+ ]), renderSvg = svgRenderFunction(mermaidMod ?? {}), Resvg = resvgMod?.Resvg;
2158
+ return !renderSvg || typeof Resvg != "function" ? null : async (code, options) => {
2159
+ let svg = await renderSvg(code, {
2160
+ bg: options.bg,
2161
+ fg: options.fg,
2162
+ padding: options.padding,
2163
+ transparent: !0
2164
+ }), svgText = String(svg ?? "");
2165
+ if (!svgText.includes("<svg"))
2166
+ return null;
2167
+ let resolvedSvg = resolveMermaidSvgForResvg(svgText, options.bg, options.fg), rendered = new Resvg(resolvedSvg, {
2168
+ background: "rgba(0,0,0,0)"
2169
+ }).render(), naturalWidth = positiveInt(rendered?.width), naturalHeight = positiveInt(rendered?.height), png = typeof rendered?.asPng == "function" ? rendered.asPng() : void 0;
2170
+ if (!png || png.length < 8 || naturalWidth == null || naturalHeight == null)
2171
+ return null;
2172
+ let rawWidthCells = Math.max(
2173
+ 1,
2174
+ Math.round(naturalWidth / (options.cellWidthPx * options.scale))
2175
+ ), rawHeightCells = Math.max(
2176
+ 1,
2177
+ Math.round(naturalHeight / (options.cellHeightPx * options.scale))
2178
+ ), { widthCells, heightCells } = clampCellsToLimits(
2179
+ rawWidthCells,
2180
+ rawHeightCells,
2181
+ options.maxWidthCells,
2182
+ options.maxHeightCells
2183
+ );
2184
+ return {
2185
+ base64: base64FromBytes(png),
2186
+ widthCells,
2187
+ heightCells,
2188
+ naturalWidth,
2189
+ naturalHeight
2190
+ };
2191
+ };
2192
+ } catch {
2193
+ return null;
2194
+ }
2195
+ })()), builtinRasterizerLoad;
2196
+ }
2197
+
2198
+ // src/vue/components/TMermaidImage.ts
2199
+ var UNICODE_MERMAID_IMAGE_BOX_CHARS = Object.freeze({
2200
+ tl: "\u250C",
2201
+ tr: "\u2510",
2202
+ bl: "\u2514",
2203
+ br: "\u2518",
2204
+ h: "\u2500",
2205
+ v: "\u2502"
2206
+ }), ASCII_MERMAID_IMAGE_BOX_CHARS = Object.freeze({
2207
+ tl: "+",
2208
+ tr: "+",
2209
+ bl: "+",
2210
+ br: "+",
2211
+ h: "-",
2212
+ v: "|"
2213
+ }), DEFAULT_MERMAID_IMAGE_COPIED_DURATION_MS = 1200, DEFAULT_MERMAID_IMAGE_MAX_RENDER_SOURCE_CHARS = 2e4, DEFAULT_MERMAID_IMAGE_MAX_RENDER_SOURCE_LINES = 400, ESC3 = "\x1B", BEL3 = "\x07", TERMINAL_ESCAPE_RE2 = new RegExp(
2214
+ [
2215
+ `${ESC3}\\][\\s\\S]*?(?:${BEL3}|${ESC3}\\\\)`,
2216
+ `${ESC3}[PX^_][\\s\\S]*?${ESC3}\\\\`,
2217
+ `${ESC3}\\[[0-?]*[ -/]*[@-~]`,
2218
+ `${ESC3}[@-Z\\\\-_]`
2219
+ ].join("|"),
2220
+ "g"
2221
+ );
2222
+ function stripTerminalEscapes2(value) {
2223
+ return value.replace(TERMINAL_ESCAPE_RE2, "");
2224
+ }
2225
+ function normalizeNonNegativeInt2(value, fallback) {
2226
+ let n = Number(value);
2227
+ return Number.isFinite(n) ? Math.max(0, Math.floor(n)) : fallback;
2228
+ }
2229
+ function countLinesUpTo2(value, max) {
2230
+ if (max <= 0)
2231
+ return 0;
2232
+ let lines = 1;
2233
+ for (let index = 0; index < value.length; index++) {
2234
+ let code = value.charCodeAt(index);
2235
+ if (!(code !== 10 && code !== 13) && (lines++, code === 13 && value.charCodeAt(index + 1) === 10 && index++, lines > max))
2236
+ return lines;
2237
+ }
2238
+ return lines;
2239
+ }
2240
+ function splitRenderedOutput2(value) {
2241
+ let lines = sanitizeTextBlock(
2242
+ stripTerminalEscapes2(String(value ?? "")).replace(/\r\n?/g, `
2243
+ `)
2244
+ ).split(`
2245
+ `);
2246
+ return lines.length ? lines : [""];
2247
+ }
2248
+ function fitImageCells(cells, maxW, maxH) {
2249
+ if (maxW <= 0 || maxH <= 0)
2250
+ return null;
2251
+ let w = Math.max(1, Math.floor(cells.widthCells)), h4 = Math.max(1, Math.floor(cells.heightCells));
2252
+ return w > maxW && (h4 = Math.max(1, Math.round(h4 * maxW / w)), w = maxW), h4 > maxH && (w = Math.max(1, Math.round(w * maxH / h4)), h4 = maxH), { displayW: Math.max(1, w), displayH: Math.max(1, h4) };
2253
+ }
2254
+ var tMermaidImageProps = {
2255
+ x: { type: Number, required: !0 },
2256
+ y: { type: Number, required: !0 },
2257
+ w: { type: Number, required: !0 },
2258
+ h: { type: Number, default: void 0 },
2259
+ zIndex: { type: Number, default: 0 },
2260
+ content: { type: String, default: "" },
2261
+ code: { type: String, default: void 0 },
2262
+ style: { type: Object, default: void 0 },
2263
+ clear: { type: Boolean, default: !0 },
2264
+ final: { type: Boolean, default: !0 },
2265
+ streaming: { type: Boolean, default: !1 },
2266
+ // Image pipeline. Without a renderer the built-in lazy rasterizer
2267
+ // (beautiful-mermaid SVG + @resvg/resvg-js) is used; when graphics are
2268
+ // unsupported or the rasterizer is missing, the raw source is shown.
2269
+ renderer: {
2270
+ type: Function,
2271
+ default: void 0
2272
+ },
2273
+ cellWidthPx: { type: Number, default: void 0 },
2274
+ cellHeightPx: { type: Number, default: void 0 },
2275
+ scale: { type: Number, default: void 0 },
2276
+ bg: { type: String, default: void 0 },
2277
+ fg: { type: String, default: void 0 },
2278
+ maxWidthCells: { type: Number, default: void 0 },
2279
+ maxHeightCells: { type: Number, default: void 0 },
2280
+ padding: { type: Number, default: void 0 },
2281
+ // Adaptive ANSI fallback. When the terminal has no graphics protocol (or the
2282
+ // image rasterizer fails for this source), the component renders the diagram
2283
+ // as ASCII text through a text renderer before falling back to the raw
2284
+ // source. Without a textRenderer the component stays image-or-raw.
2285
+ textRenderer: {
2286
+ type: Function,
2287
+ default: void 0
2288
+ },
2289
+ // Eligibility guard for the ANSI fallback; returning false keeps the raw
2290
+ // source visible (e.g. only render simple flowcharts as ASCII).
2291
+ shouldRenderSource: {
2292
+ type: Function,
2293
+ default: void 0
2294
+ },
2295
+ // Spacing/theme options forwarded to the ANSI text renderer.
2296
+ textOptions: {
2297
+ type: Object,
2298
+ default: void 0
2299
+ },
2300
+ // Box chrome (mirrors TMermaidText).
2301
+ box: { type: Boolean, default: !0 },
2302
+ title: { type: String, default: "mermaid" },
2303
+ copyButton: { type: Boolean, default: !0 },
2304
+ copyText: { type: String, default: "copy" },
2305
+ copiedText: { type: String, default: "copied" },
2306
+ copiedDurationMs: { type: Number, default: DEFAULT_MERMAID_IMAGE_COPIED_DURATION_MS },
2307
+ renderTimeoutMs: { type: Number, default: 0 },
2308
+ maxRenderSourceChars: { type: Number, default: DEFAULT_MERMAID_IMAGE_MAX_RENDER_SOURCE_CHARS },
2309
+ maxRenderSourceLines: { type: Number, default: DEFAULT_MERMAID_IMAGE_MAX_RENDER_SOURCE_LINES },
2310
+ // Clicking the diagram (or the copy button) copies the full raw mermaid source.
2311
+ copyOnClick: { type: Boolean, default: !0 },
2312
+ ascii: { type: Boolean, default: !1 },
2313
+ // Wheel zoom (Kitty graphics only): with the zoom modifier held, wheel over
2314
+ // the image zooms centered on the mouse, clamped to the container area.
2315
+ // Without the modifier the wheel passes through to the surrounding scroll
2316
+ // container (historical-message scrolling is never blocked). iTerm2 has no
2317
+ // in-place resize sequence, so zoom stays disabled there.
2318
+ zoomOnWheel: { type: Boolean, default: !0 },
2319
+ zoomModifier: {
2320
+ type: String,
2321
+ default: "metaCtrl"
2322
+ },
2323
+ minZoom: { type: Number, default: 1 },
2324
+ maxZoom: { type: Number, default: 6 },
2325
+ zoomSensitivity: { type: Number, default: 2e-3 }
2326
+ }, TMermaidImage = (0, import_vue9.defineComponent)({
2327
+ name: "TMermaidImage",
2328
+ props: tMermaidImageProps,
2329
+ emits: {
2330
+ copy: (_payload) => !0
2331
+ },
2332
+ setup(props, { emit }) {
2333
+ let instance = (0, import_vue9.getCurrentInstance)(), terminalContext = useTerminal(), { terminal, defaultStyle, scheduler, widthProvider } = terminalContext, layout = useLayout(), { visible, rootProps } = useVisibility(), parentEventZ = (0, import_vue9.inject)(EventZIndexContextKey, (0, import_vue9.computed)(() => 0)), imageCells = (0, import_vue9.shallowRef)(null), textSnapshot = (0, import_vue9.shallowRef)(null), zoomScale = (0, import_vue9.shallowRef)(1), panX = (0, import_vue9.shallowRef)(0), panY = (0, import_vue9.shallowRef)(0), documentVersion = (0, import_vue9.shallowRef)(0), copied = (0, import_vue9.shallowRef)(!1), dragState = null, dragMoved = !1, lastDragAt = 0, DRAG_CLICK_SUPPRESS_MS = 250, builtOnce = !1, renderVersion = 0, alive = !0, frameTaskId = `TMermaidImage:${instance?.uid ?? "unknown"}:mermaid-image`, uid = instance?.uid ?? 0, copiedTimer = null, copyRequestVersion = 0, activeGraphicId = null, activeImageSignature = "", source = (0, import_vue9.computed)(() => props.code ?? props.content ?? ""), waitingForStreamingSourceToFinish = (0, import_vue9.computed)(() => props.streaming && !props.final), graphicsOutputVersion = (0, import_vue9.shallowRef)(getTerminalGraphicsOutputVersion(terminal)), graphicsOutput = (0, import_vue9.computed)(() => (graphicsOutputVersion.value, getTerminalGraphicsOutput(terminal))), graphicsProtocol = (0, import_vue9.computed)(() => {
2334
+ let output = graphicsOutput.value;
2335
+ if (!output?.capabilities.supported)
2336
+ return null;
2337
+ let protocol = output.capabilities.preferredProtocol;
2338
+ return protocol === "kitty" || protocol === "iterm2" ? protocol : null;
2339
+ });
2340
+ function bump() {
2341
+ documentVersion.value++;
2342
+ }
2343
+ function clearCopiedTimer() {
2344
+ copiedTimer != null && (clearTimeout(copiedTimer), copiedTimer = null);
2345
+ }
2346
+ function setCopied(next, repaint = !0) {
2347
+ next || clearCopiedTimer(), copied.value !== next && (copied.value = next, repaint && bump());
2348
+ }
2349
+ function resetCopyFeedback(repaint = !0) {
2350
+ copyRequestVersion++, setCopied(!1, repaint);
2351
+ }
2352
+ function showCopiedFeedback() {
2353
+ clearCopiedTimer();
2354
+ let duration = normalizeNonNegativeInt2(
2355
+ props.copiedDurationMs,
2356
+ DEFAULT_MERMAID_IMAGE_COPIED_DURATION_MS
2357
+ );
2358
+ if (duration <= 0) {
2359
+ setCopied(!1);
2360
+ return;
2361
+ }
2362
+ setCopied(!0), copiedTimer = setTimeout(() => {
2363
+ copiedTimer = null, alive && setCopied(!1);
2364
+ }, duration);
2365
+ }
2366
+ function queueClearGraphic() {
2367
+ if (activeGraphicId == null)
2368
+ return;
2369
+ let id = activeGraphicId;
2370
+ activeGraphicId = null;
2371
+ try {
2372
+ graphicsOutput.value?.clear?.(id);
2373
+ } catch {
2374
+ }
2375
+ }
2376
+ function clampZoom(zoom) {
2377
+ let min = Number.isFinite(Number(props.minZoom)) ? Math.max(0.05, Number(props.minZoom)) : 1, max = Number.isFinite(Number(props.maxZoom)) ? Math.max(min, Number(props.maxZoom)) : Math.max(min, 6);
2378
+ return Math.min(max, Math.max(min, zoom));
2379
+ }
2380
+ function zoomSensitivity() {
2381
+ let value = Number(props.zoomSensitivity);
2382
+ return Number.isFinite(value) && value > 0 ? value : 2e-3;
2383
+ }
2384
+ function wheelZoomFactor(deltaY, deltaMode) {
2385
+ let sign = deltaY > 0 ? -1 : 1, sensitivity = zoomSensitivity(), abs = Math.abs(deltaY), magnitude = (deltaMode ?? 0) === 1 || abs > 0 && abs <= 3 && Number.isInteger(deltaY) ? 100 : abs;
2386
+ return Math.exp(sign * magnitude * sensitivity);
2387
+ }
2388
+ function resetZoomState() {
2389
+ zoomScale.value === 1 && panX.value === 0 && panY.value === 0 || (zoomScale.value = 1, panX.value = 0, panY.value = 0, dragState = null);
2390
+ }
2391
+ function hasZoomModifier(event) {
2392
+ let modifier = props.zoomModifier ?? "metaCtrl";
2393
+ return modifier === "none" ? !0 : modifier === "meta" ? event.metaKey === !0 : modifier === "ctrl" ? event.ctrlKey === !0 : event.ctrlKey === !0 || event.metaKey === !0;
2394
+ }
2395
+ function clampPan() {
2396
+ let inner = innerRectFrom(fullRect.value), fit = displayFit.value;
2397
+ if (!fit || inner.w <= 0 || inner.h <= 0)
2398
+ return;
2399
+ let zoom = clampZoom(zoomScale.value), fullW = fit.displayW * zoom, fullH = fit.displayH * zoom, fitOriginX = inner.x + (inner.w > fit.displayW ? Math.floor((inner.w - fit.displayW) / 2) : 0), nextX = panX.value, nextY = panY.value;
2400
+ fullW <= inner.w ? nextX = 0 : nextX = Math.min(
2401
+ inner.x - fitOriginX,
2402
+ Math.max(inner.x + inner.w - fullW - fitOriginX, nextX)
2403
+ ), fullH <= inner.h ? nextY = 0 : nextY = Math.min(0, Math.max(inner.h - fullH, nextY)), nextX !== panX.value && (panX.value = nextX), nextY !== panY.value && (panY.value = nextY);
2404
+ }
2405
+ function setImageCells(cells) {
2406
+ let signature = cells ? cells.base64 : "";
2407
+ signature !== activeImageSignature && (activeImageSignature = signature, resetZoomState()), imageCells.value = cells;
2408
+ }
2409
+ let hasBox = (0, import_vue9.computed)(() => props.box !== !1), normalizedWidth = (0, import_vue9.computed)(() => {
2410
+ let width = Math.floor(Number(props.w));
2411
+ return Number.isFinite(width) ? Math.max(0, width) : 0;
2412
+ }), reservesBoxRows = (0, import_vue9.computed)(() => hasBox.value && normalizedWidth.value >= 2), boxChars = (0, import_vue9.computed)(
2413
+ () => props.ascii ? ASCII_MERMAID_IMAGE_BOX_CHARS : UNICODE_MERMAID_IMAGE_BOX_CHARS
2414
+ ), sourceLines = (0, import_vue9.computed)(() => splitRenderedOutput2(source.value)), displayLines = (0, import_vue9.computed)(() => {
2415
+ let snapshot = textSnapshot.value;
2416
+ return snapshot && snapshot.source === source.value && hasVisibleTextOutput(snapshot.lines) ? snapshot.lines : sourceLines.value;
2417
+ }), currentStyle = (0, import_vue9.computed)(() => props.style ?? defaultStyle.value), innerWidth = (0, import_vue9.computed)(() => {
2418
+ let w = normalizedWidth.value;
2419
+ return reservesBoxRows.value ? Math.max(0, w - 2) : w;
2420
+ }), fixedInnerHeight = (0, import_vue9.computed)(() => {
2421
+ if (props.h == null)
2422
+ return 0;
2423
+ let h4 = Math.floor(Number(props.h));
2424
+ if (!Number.isFinite(h4))
2425
+ return 0;
2426
+ let value = Math.max(0, h4);
2427
+ return reservesBoxRows.value ? Math.max(0, value - 2) : value;
2428
+ }), autoHeight = (0, import_vue9.computed)(() => props.h == null), displayFit = (0, import_vue9.computed)(() => {
2429
+ let cells = imageCells.value;
2430
+ return cells ? autoHeight.value ? fitImageCells(cells, innerWidth.value, Number.MAX_SAFE_INTEGER) : fitImageCells(cells, innerWidth.value, fixedInnerHeight.value) : null;
2431
+ }), contentHeight = (0, import_vue9.computed)(() => autoHeight.value ? displayFit.value?.displayH ?? Math.max(1, displayLines.value.length) : fixedInnerHeight.value), fullHeight = (0, import_vue9.computed)(() => {
2432
+ if (props.h != null) {
2433
+ let h4 = Math.floor(Number(props.h));
2434
+ return Number.isFinite(h4) ? Math.max(0, h4) : 0;
2435
+ }
2436
+ return reservesBoxRows.value ? contentHeight.value + 2 : contentHeight.value;
2437
+ }), fullRect = (0, import_vue9.computed)(() => translateRect(
2438
+ { x: props.x, y: props.y, w: props.w, h: fullHeight.value },
2439
+ layout.originX,
2440
+ layout.originY
2441
+ )), absRect = (0, import_vue9.computed)(() => {
2442
+ let translated = fullRect.value;
2443
+ return layout.clipRect ? intersectRect(translated, layout.clipRect) ?? { x: 0, y: 0, w: 0, h: 0 } : translated;
2444
+ }), copyLabel = (0, import_vue9.computed)(() => copied.value ? props.copiedText : props.copyText);
2445
+ function cellWidth(value) {
2446
+ return withTextWidthProvider(widthProvider, () => textCellWidth(value));
2447
+ }
2448
+ function sliceCells(text, maxCells) {
2449
+ return withTextWidthProvider(widthProvider, () => sliceByCells(text, maxCells));
2450
+ }
2451
+ function sliceCellsRange(text, startCells, endCells) {
2452
+ return withTextWidthProvider(
2453
+ widthProvider,
2454
+ () => sliceByCellsRange(text, startCells, endCells)
2455
+ );
2456
+ }
2457
+ function padCells(text, width) {
2458
+ return withTextWidthProvider(widthProvider, () => padEndByCells(text, width));
2459
+ }
2460
+ function resolveImageOptions() {
2461
+ let resolvedFg = props.fg ?? resolveMermaidImageColor(currentStyle.value.fg) ?? void 0;
2462
+ return normalizeMermaidImageOptions({
2463
+ cellWidthPx: props.cellWidthPx,
2464
+ cellHeightPx: props.cellHeightPx,
2465
+ scale: props.scale,
2466
+ bg: props.bg,
2467
+ fg: resolvedFg,
2468
+ maxWidthCells: props.maxWidthCells,
2469
+ maxHeightCells: props.maxHeightCells,
2470
+ padding: props.padding
2471
+ });
2472
+ }
2473
+ function hasVisibleTextOutput(lines) {
2474
+ return lines.some((line) => line.trim().length > 0);
2475
+ }
2476
+ function resolveTextOptions() {
2477
+ return {
2478
+ ...props.textOptions ?? {},
2479
+ useAscii: props.ascii,
2480
+ colorMode: "none"
2481
+ };
2482
+ }
2483
+ function textRenderSignature(code) {
2484
+ return [
2485
+ code,
2486
+ props.ascii ? "a" : "",
2487
+ JSON.stringify(props.textOptions ?? null),
2488
+ props.textRenderer != null ? "r" : "",
2489
+ props.shouldRenderSource != null ? "g" : ""
2490
+ ].join("");
2491
+ }
2492
+ async function renderTextWithTimeout(renderer, code, options) {
2493
+ let timeoutMs = normalizeNonNegativeInt2(props.renderTimeoutMs, 0);
2494
+ if (timeoutMs <= 0)
2495
+ return await renderer(code, options);
2496
+ let timer = null;
2497
+ try {
2498
+ return await Promise.race([
2499
+ Promise.resolve().then(() => renderer(code, options)),
2500
+ new Promise((_resolve, reject) => {
2501
+ timer = setTimeout(() => reject(new Error("Mermaid text render timeout")), timeoutMs);
2502
+ })
2503
+ ]);
2504
+ } finally {
2505
+ timer != null && clearTimeout(timer);
2506
+ }
2507
+ }
2508
+ async function runCustomRasterizer(code, options) {
2509
+ let renderer = props.renderer;
2510
+ if (!renderer)
2511
+ return null;
2512
+ let timeoutMs = normalizeNonNegativeInt2(props.renderTimeoutMs, 0), run = () => renderer(code, options);
2513
+ if (timeoutMs <= 0)
2514
+ return await run() ?? null;
2515
+ let timer = null;
2516
+ try {
2517
+ return await Promise.race([
2518
+ run(),
2519
+ new Promise((resolve) => {
2520
+ timer = setTimeout(() => resolve(null), timeoutMs);
2521
+ })
2522
+ ]) ?? null;
2523
+ } finally {
2524
+ timer != null && clearTimeout(timer);
2525
+ }
2526
+ }
2527
+ function shouldSkipRenderForSize(code) {
2528
+ let maxChars = normalizeNonNegativeInt2(
2529
+ props.maxRenderSourceChars,
2530
+ DEFAULT_MERMAID_IMAGE_MAX_RENDER_SOURCE_CHARS
2531
+ );
2532
+ if (maxChars > 0 && code.length > maxChars)
2533
+ return !0;
2534
+ let maxLines = normalizeNonNegativeInt2(
2535
+ props.maxRenderSourceLines,
2536
+ DEFAULT_MERMAID_IMAGE_MAX_RENDER_SOURCE_LINES
2537
+ );
2538
+ return maxLines > 0 && countLinesUpTo2(code, maxLines) > maxLines;
2539
+ }
2540
+ async function rasterizeWithTimeout(code, options) {
2541
+ let timeoutMs = normalizeNonNegativeInt2(props.renderTimeoutMs, 0);
2542
+ if (timeoutMs <= 0)
2543
+ return await getMermaidImage(code, options);
2544
+ let timer = null;
2545
+ try {
2546
+ return await Promise.race([
2547
+ getMermaidImage(code, options),
2548
+ new Promise((resolve) => {
2549
+ timer = setTimeout(() => resolve(null), timeoutMs);
2550
+ })
2551
+ ]);
2552
+ } finally {
2553
+ timer != null && clearTimeout(timer);
2554
+ }
2555
+ }
2556
+ async function renderTextFallback(version) {
2557
+ let code = source.value, renderer = props.textRenderer;
2558
+ if (!renderer)
2559
+ return;
2560
+ let guard = props.shouldRenderSource;
2561
+ if (guard) {
2562
+ let eligible = !1;
2563
+ try {
2564
+ eligible = guard(code, { final: props.final, streaming: props.streaming });
2565
+ } catch {
2566
+ eligible = !1;
2567
+ }
2568
+ if (!eligible)
2569
+ return;
2570
+ }
2571
+ try {
2572
+ let rendered = await renderTextWithTimeout(renderer, code, resolveTextOptions());
2573
+ if (!alive || version !== renderVersion)
2574
+ return;
2575
+ let lines = splitRenderedOutput2(rendered);
2576
+ if (!hasVisibleTextOutput(lines))
2577
+ return;
2578
+ textSnapshot.value = (0, import_vue9.markRaw)({
2579
+ source: code,
2580
+ signature: textRenderSignature(code),
2581
+ lines: (0, import_vue9.markRaw)(lines)
2582
+ }), bump();
2583
+ } catch {
2584
+ }
2585
+ }
2586
+ async function renderPresentation(version) {
2587
+ let code = source.value;
2588
+ if (!code.trim()) {
2589
+ if (!alive || version !== renderVersion)
2590
+ return;
2591
+ setImageCells(null), textSnapshot.value = null, bump();
2592
+ return;
2593
+ }
2594
+ if (waitingForStreamingSourceToFinish.value || shouldSkipRenderForSize(code)) {
2595
+ if (!alive || version !== renderVersion)
2596
+ return;
2597
+ setImageCells(null), textSnapshot.value = null, bump();
2598
+ return;
2599
+ }
2600
+ let protocol = graphicsProtocol.value, options = resolveImageOptions(), cached = protocol && !props.renderer ? getCachedMermaidImage(code, options) : null;
2601
+ if (cached) {
2602
+ if (!alive || version !== renderVersion)
2603
+ return;
2604
+ setImageCells(cached), textSnapshot.value = null, bump();
2605
+ return;
2606
+ }
2607
+ let currentSignature = textRenderSignature(code), keepText = textSnapshot.value != null && textSnapshot.value.source === code && textSnapshot.value.signature === currentSignature;
2608
+ if (keepText || (setImageCells(null), textSnapshot.value = null, bump()), protocol) {
2609
+ let result = null;
2610
+ if (props.renderer)
2611
+ result = await runCustomRasterizer(code, options);
2612
+ else if (isMermaidImageRendererReady())
2613
+ result = await rasterizeWithTimeout(code, options);
2614
+ else {
2615
+ loadMermaidImageRenderer().then((ready) => {
2616
+ !alive || version !== renderVersion || !ready || renderPresentation(version);
2617
+ });
2618
+ return;
2619
+ }
2620
+ if (!alive || version !== renderVersion)
2621
+ return;
2622
+ if (result) {
2623
+ setImageCells(result), textSnapshot.value = null, bump();
2624
+ return;
2625
+ }
2626
+ }
2627
+ keepText || await renderTextFallback(version);
2628
+ }
2629
+ function scheduleRender() {
2630
+ let version = ++renderVersion;
2631
+ if (resetCopyFeedback(!1), setImageCells(null), waitingForStreamingSourceToFinish.value) {
2632
+ builtOnce = !0, scheduler.cancelFrameTask?.(frameTaskId), bump();
2633
+ return;
2634
+ }
2635
+ if (!builtOnce || !props.streaming) {
2636
+ builtOnce = !0, renderPresentation(version);
2637
+ return;
2638
+ }
2639
+ scheduler.queueFrameTask({
2640
+ id: frameTaskId,
2641
+ reason: "stream",
2642
+ priority: "low",
2643
+ sync: !1,
2644
+ run: () => {
2645
+ alive && version === renderVersion && renderPresentation(version);
2646
+ }
2647
+ }) === !1 && renderPresentation(version);
2648
+ }
2649
+ (0, import_vue9.watch)(
2650
+ [
2651
+ source,
2652
+ () => props.renderer,
2653
+ () => props.cellWidthPx,
2654
+ () => props.cellHeightPx,
2655
+ () => props.scale,
2656
+ () => props.bg,
2657
+ () => props.fg,
2658
+ () => props.maxWidthCells,
2659
+ () => props.maxHeightCells,
2660
+ () => props.padding,
2661
+ () => props.streaming,
2662
+ () => props.final,
2663
+ () => props.maxRenderSourceChars,
2664
+ () => props.maxRenderSourceLines,
2665
+ () => props.textRenderer,
2666
+ () => props.shouldRenderSource,
2667
+ () => props.textOptions,
2668
+ () => props.ascii,
2669
+ () => props.zoomModifier
2670
+ ],
2671
+ () => {
2672
+ scheduleRender();
2673
+ },
2674
+ { immediate: !0, deep: !0 }
2675
+ );
2676
+ let unsubscribeMermaidImage = subscribeMermaidImage(() => {
2677
+ if (!alive || !graphicsProtocol.value || props.renderer)
2678
+ return;
2679
+ let cached = getCachedMermaidImage(source.value, resolveImageOptions());
2680
+ cached && alive && (setImageCells(cached), textSnapshot.value = null, bump());
2681
+ }), unsubscribeGraphicsOutput = subscribeTerminalGraphicsOutput(terminal, () => {
2682
+ alive && (graphicsOutputVersion.value = getTerminalGraphicsOutputVersion(terminal), scheduleRender());
2683
+ });
2684
+ (0, import_vue9.onBeforeUnmount)(() => {
2685
+ alive = !1, renderVersion++, clearCopiedTimer(), queueClearGraphic(), unsubscribeMermaidImage(), unsubscribeGraphicsOutput(), scheduler.cancelFrameTask?.(frameTaskId);
2686
+ });
2687
+ function canDrawBox(width, height) {
2688
+ return hasBox.value && Math.floor(width) >= 2 && Math.floor(height) >= 2;
2689
+ }
2690
+ function headerCopySegment(width) {
2691
+ if (!hasBox.value || !props.copyButton)
2692
+ return null;
2693
+ let rowWidth = Math.max(0, Math.floor(width));
2694
+ if (rowWidth < 4)
2695
+ return null;
2696
+ let label = sanitizeInlineText(copyLabel.value);
2697
+ if (!label)
2698
+ return null;
2699
+ let maxCells = Math.max(0, rowWidth - 2), text = sliceCells(` ${label} `, maxCells), cells = cellWidth(text);
2700
+ return !text || cells <= 0 ? null : {
2701
+ text,
2702
+ start: Math.max(1, rowWidth - cells - 1),
2703
+ cells
2704
+ };
2705
+ }
2706
+ function headerTitleSegment(width, copy) {
2707
+ if (!hasBox.value)
2708
+ return null;
2709
+ let rowWidth = Math.max(0, Math.floor(width));
2710
+ if (rowWidth < 4)
2711
+ return null;
2712
+ let title = sanitizeInlineText(props.title);
2713
+ if (!title)
2714
+ return null;
2715
+ let titleStart = 1, titleEnd = copy ? Math.max(titleStart, copy.start - 1) : rowWidth - 1, maxCells = Math.max(0, titleEnd - titleStart);
2716
+ if (maxCells <= 0)
2717
+ return null;
2718
+ let text = sliceCells(` ${title} `, maxCells), cells = cellWidth(text);
2719
+ return !text || cells <= 0 ? null : {
2720
+ text,
2721
+ start: titleStart,
2722
+ cells
2723
+ };
2724
+ }
2725
+ function overlayCells(row, segment, width) {
2726
+ let rowWidth = Math.max(0, Math.floor(width)), start = Math.max(0, Math.floor(segment.start));
2727
+ if (rowWidth <= 1 || start >= rowWidth - 1 || segment.cells <= 0)
2728
+ return row;
2729
+ let maxCells = Math.max(0, rowWidth - 1 - start), text = sliceCells(segment.text, maxCells), cells = cellWidth(text);
2730
+ return !text || cells <= 0 ? row : `${sliceCells(row, start)}${text}${sliceCellsRange(row, start + cells, rowWidth)}`;
2731
+ }
2732
+ function boxRow(rowIndex, width, height) {
2733
+ let rowWidth = Math.max(0, Math.floor(width)), rowHeight = Math.max(0, Math.floor(height));
2734
+ if (!canDrawBox(rowWidth, rowHeight))
2735
+ return contentLine(rowIndex, rowWidth, props.clear);
2736
+ let chars = boxChars.value, innerW = Math.max(0, rowWidth - 2);
2737
+ if (rowIndex === 0) {
2738
+ let row = `${chars.tl}${repeatChar(chars.h, innerW)}${chars.tr}`, copy = headerCopySegment(rowWidth), title = headerTitleSegment(rowWidth, copy);
2739
+ return title && (row = overlayCells(row, title, rowWidth)), copy && (row = overlayCells(row, copy, rowWidth)), row;
2740
+ }
2741
+ return rowIndex === rowHeight - 1 ? `${chars.bl}${repeatChar(chars.h, innerW)}${chars.br}` : `${chars.v}${contentLine(rowIndex - 1, innerW, !0)}${chars.v}`;
2742
+ }
2743
+ function contentLine(rowIndex, width, pad) {
2744
+ let src = imageCells.value != null && displayFit.value != null && graphicsProtocol.value != null ? spaces(width) : displayLines.value[rowIndex] ?? "", clipped = sliceCells(src, width);
2745
+ return pad ? padCells(clipped, width) : clipped;
2746
+ }
2747
+ function innerRectFrom(full) {
2748
+ let x = Math.floor(full.x) + (reservesBoxRows.value ? 1 : 0), y = Math.floor(full.y) + (reservesBoxRows.value ? 1 : 0), w = Math.max(0, Math.floor(full.w) - (reservesBoxRows.value ? 2 : 0)), h4 = Math.max(0, Math.floor(full.h) - (reservesBoxRows.value ? 2 : 0));
2749
+ return { x, y, w, h: h4 };
2750
+ }
2751
+ function queueImageGraphic(full, fit) {
2752
+ let protocol = graphicsProtocol.value, cells = imageCells.value;
2753
+ if (!protocol || !cells) {
2754
+ queueClearGraphic();
2755
+ return;
2756
+ }
2757
+ let inner = innerRectFrom(full);
2758
+ if (inner.w <= 0 || inner.h <= 0) {
2759
+ queueClearGraphic();
2760
+ return;
2761
+ }
2762
+ let zoom = clampZoom(zoomScale.value), fitW = fit.displayW, fitH = fit.displayH, fullRect2 = {
2763
+ x: inner.x + (inner.w > fitW ? Math.floor((inner.w - fitW) / 2) : 0) + panX.value,
2764
+ y: inner.y + panY.value,
2765
+ w: fitW * zoom,
2766
+ h: fitH * zoom
2767
+ }, visible2 = intersectRect(fullRect2, inner);
2768
+ if (!visible2 || visible2.w < 1 || visible2.h < 1) {
2769
+ queueClearGraphic();
2770
+ return;
2771
+ }
2772
+ let rectX = Math.max(inner.x, Math.round(visible2.x)), rectY = Math.max(inner.y, Math.round(visible2.y)), rect = {
2773
+ x: rectX,
2774
+ y: rectY,
2775
+ w: Math.max(1, Math.min(inner.x + inner.w, rectX + Math.round(visible2.w)) - rectX),
2776
+ h: Math.max(1, Math.min(inner.y + inner.h, rectY + Math.round(visible2.h)) - rectY)
2777
+ }, imageId = stableTerminalGraphicNumericId(`mermaid-image:${uid}:${renderVersion}:img`), placementId = stableTerminalGraphicNumericId(
2778
+ `mermaid-image:${uid}:${renderVersion}:plc`
2779
+ ), built = createTerminalGraphicPngSequence({
2780
+ protocol,
2781
+ base64: cells.base64,
2782
+ imageId,
2783
+ placementId,
2784
+ cols: cells.widthCells,
2785
+ rows: cells.heightCells,
2786
+ sourceWidth: cells.naturalWidth,
2787
+ sourceHeight: cells.naturalHeight,
2788
+ placementColumns: rect.w,
2789
+ placementRows: rect.h,
2790
+ // Keep the initial transmission stable at the fit size without a
2791
+ // source crop so wheel zoom can replace the placement (a=p) without
2792
+ // re-sending the PNG, and every placement references the full image.
2793
+ transmissionColumns: fitW,
2794
+ transmissionRows: fitH,
2795
+ cropTransmission: !1,
2796
+ rect,
2797
+ fullRect: fullRect2,
2798
+ zIndex: -1,
2799
+ fallback: source.value
2800
+ });
2801
+ if (!built) {
2802
+ queueClearGraphic();
2803
+ return;
2804
+ }
2805
+ let id = `mermaid-image:${uid}:${renderVersion}`, output = graphicsOutput.value;
2806
+ if (!output) {
2807
+ queueClearGraphic();
2808
+ return;
2809
+ }
2810
+ if (activeGraphicId != null && activeGraphicId !== id) {
2811
+ try {
2812
+ output.clear?.(activeGraphicId);
2813
+ } catch {
2814
+ }
2815
+ activeGraphicId = null;
2816
+ }
2817
+ output.queue({
2818
+ id,
2819
+ x: rect.x,
2820
+ y: rect.y,
2821
+ w: rect.w,
2822
+ h: rect.h,
2823
+ protocol,
2824
+ sequence: built.sequence,
2825
+ resizeSequence: built.resizeSequence,
2826
+ clearSequence: built.clearSequence,
2827
+ fallbackText: source.value,
2828
+ // Same image data + placement id: let the stdout renderer replace the
2829
+ // placement with the resize sequence instead of re-sending the PNG.
2830
+ placementMoveWithoutClear: protocol === "kitty"
2831
+ }) ? activeGraphicId = id : queueClearGraphic();
2832
+ }
2833
+ let copyHitRect = (0, import_vue9.computed)(() => {
2834
+ let full = fullRect.value;
2835
+ if (!visible.value || !props.copyButton || !canDrawBox(full.w, full.h))
2836
+ return { x: 0, y: 0, w: 0, h: 0 };
2837
+ let copy = headerCopySegment(Math.max(0, Math.floor(full.w)));
2838
+ if (!copy)
2839
+ return { x: 0, y: 0, w: 0, h: 0 };
2840
+ let raw = {
2841
+ x: Math.floor(full.x) + copy.start,
2842
+ y: Math.floor(full.y),
2843
+ w: copy.cells,
2844
+ h: 1
2845
+ };
2846
+ return layout.clipRect ? intersectRect(raw, layout.clipRect) ?? { x: 0, y: 0, w: 0, h: 0 } : raw;
2847
+ }), contentHitRect = (0, import_vue9.computed)(() => {
2848
+ if (!visible.value)
2849
+ return { x: 0, y: 0, w: 0, h: 0 };
2850
+ let full = fullRect.value;
2851
+ if (full.w <= 0 || full.h <= 0)
2852
+ return { x: 0, y: 0, w: 0, h: 0 };
2853
+ let inner = innerRectFrom(full);
2854
+ return inner.w <= 0 || inner.h <= 0 ? { x: 0, y: 0, w: 0, h: 0 } : layout.clipRect ? intersectRect(inner, layout.clipRect) ?? { x: 0, y: 0, w: 0, h: 0 } : inner;
2855
+ });
2856
+ function clipboardCanWrite2(api) {
2857
+ return api.canWrite ?? api.supported;
2858
+ }
2859
+ async function writeClipboardText(text) {
2860
+ let contextClipboard = terminalContext.clipboard;
2861
+ if (contextClipboard) {
2862
+ if (!clipboardCanWrite2(contextClipboard))
2863
+ throw new Error("Clipboard write not available in this runtime");
2864
+ await contextClipboard.writeText(text);
2865
+ return;
2866
+ }
2867
+ let navClipboard = globalThis.navigator?.clipboard;
2868
+ if (navClipboard && typeof navClipboard.writeText == "function") {
2869
+ await navClipboard.writeText(text);
2870
+ return;
2871
+ }
2872
+ throw new Error("Clipboard write not available in this runtime");
2873
+ }
2874
+ async function copySource() {
2875
+ let text = source.value, requestVersion = ++copyRequestVersion, ok = !1, copyError;
2876
+ try {
2877
+ await writeClipboardText(text), ok = !0;
2878
+ } catch (err) {
2879
+ copyError = err;
2880
+ }
2881
+ if (!alive)
2882
+ return;
2883
+ requestVersion === copyRequestVersion && source.value === text && (ok ? showCopiedFeedback() : setCopied(!1)), emit("copy", ok ? { text, ok } : { text, ok, error: copyError });
2884
+ }
2885
+ function onCopyClick(event) {
2886
+ event.preventDefault(), event.stopPropagation(), !(Date.now() - lastDragAt < DRAG_CLICK_SUPPRESS_MS) && copySource();
2887
+ }
2888
+ function onCopyKeydown(event) {
2889
+ event.key !== "Enter" && event.key !== " " || (event.preventDefault(), event.stopPropagation(), copySource());
2890
+ }
2891
+ let zoomEnabled = (0, import_vue9.computed)(
2892
+ () => props.zoomOnWheel !== !1 && imageCells.value != null && displayFit.value != null && graphicsProtocol.value === "kitty" && contentHitRect.value.w > 0 && contentHitRect.value.h > 0
2893
+ ), dragEnabled = (0, import_vue9.computed)(
2894
+ () => props.zoomOnWheel !== !1 && imageCells.value != null && displayFit.value != null && graphicsProtocol.value === "kitty" && zoomScale.value > 1 && contentHitRect.value.w > 0 && contentHitRect.value.h > 0
2895
+ );
2896
+ function onWheel(event) {
2897
+ if (!zoomEnabled.value || !hasZoomModifier(event))
2898
+ return;
2899
+ event.preventDefault(), event.stopPropagation();
2900
+ let deltaY = event.deltaY ?? 0;
2901
+ if (!Number.isFinite(deltaY) || deltaY === 0)
2902
+ return;
2903
+ let inner = innerRectFrom(fullRect.value), fit = displayFit.value;
2904
+ if (!fit || inner.w <= 0 || inner.h <= 0)
2905
+ return;
2906
+ let currentZoom = clampZoom(zoomScale.value), fitW = fit.displayW, fitH = fit.displayH, fitOriginX = inner.x + (inner.w > fitW ? Math.floor((inner.w - fitW) / 2) : 0), fullX = fitOriginX + panX.value, fullY = inner.y + panY.value, mouseX = event.cellX, mouseY = event.cellY, fx = currentZoom > 0 ? (mouseX - fullX) / (fitW * currentZoom) : 0.5, fy = currentZoom > 0 ? (mouseY - fullY) / (fitH * currentZoom) : 0.5, nextZoom = clampZoom(currentZoom * wheelZoomFactor(deltaY, event.deltaMode));
2907
+ if (nextZoom === currentZoom)
2908
+ return;
2909
+ let nextW = fitW * nextZoom, nextH = fitH * nextZoom, nextX = mouseX - fx * nextW, nextY = mouseY - fy * nextH;
2910
+ nextW <= inner.w ? nextX = inner.x + (inner.w - nextW) / 2 : nextX = Math.min(inner.x, Math.max(inner.x + inner.w - nextW, nextX)), nextH <= inner.h ? nextY = inner.y + (inner.h - nextH) / 2 : nextY = Math.min(inner.y, Math.max(inner.y + inner.h - nextH, nextY)), zoomScale.value = nextZoom, panX.value = nextX - fitOriginX, panY.value = nextY - inner.y, clampPan(), bump();
2911
+ }
2912
+ function onPointerDown(event) {
2913
+ dragEnabled.value && (event.preventDefault(), event.stopPropagation(), dragState = {
2914
+ startX: event.cellX,
2915
+ startY: event.cellY,
2916
+ panStartX: panX.value,
2917
+ panStartY: panY.value
2918
+ }, dragMoved = !1);
2919
+ }
2920
+ function onPointerMove(event) {
2921
+ let drag = dragState;
2922
+ if (!drag)
2923
+ return;
2924
+ event.preventDefault(), event.stopPropagation();
2925
+ let dx = event.cellX - drag.startX, dy = event.cellY - drag.startY;
2926
+ !dragMoved && Math.abs(dx) + Math.abs(dy) >= 1 && (dragMoved = !0), dragMoved && (panX.value = drag.panStartX + dx, panY.value = drag.panStartY + dy, clampPan(), bump());
2927
+ }
2928
+ function onPointerUp(event) {
2929
+ dragState && (event.preventDefault(), event.stopPropagation(), dragState = null, dragMoved && (lastDragAt = Date.now()));
2930
+ }
2931
+ let copyNodeActive = (0, import_vue9.computed)(
2932
+ () => visible.value && props.copyButton && copyHitRect.value.w > 0 && copyHitRect.value.h > 0
2933
+ );
2934
+ useTerminalNode(() => ({
2935
+ rect: copyHitRect.value,
2936
+ zIndex: (parentEventZ.value ?? 0) + props.zIndex + 1,
2937
+ visible: copyNodeActive.value,
2938
+ focusable: copyNodeActive.value,
2939
+ selectable: !1,
2940
+ handlers: copyNodeActive.value ? {
2941
+ click: onCopyClick,
2942
+ keydown: onCopyKeydown
2943
+ } : {}
2944
+ }));
2945
+ let contentNodeActive = (0, import_vue9.computed)(
2946
+ () => visible.value && (props.copyOnClick || zoomEnabled.value || dragEnabled.value) && contentHitRect.value.w > 0 && contentHitRect.value.h > 0
2947
+ );
2948
+ return useTerminalNode(() => ({
2949
+ rect: contentHitRect.value,
2950
+ zIndex: (parentEventZ.value ?? 0) + props.zIndex,
2951
+ visible: contentNodeActive.value,
2952
+ focusable: !1,
2953
+ selectable: !1,
2954
+ handlers: contentNodeActive.value ? {
2955
+ click: props.copyOnClick ? onCopyClick : void 0,
2956
+ wheel: zoomEnabled.value ? onWheel : void 0,
2957
+ pointerdown: dragEnabled.value ? onPointerDown : void 0,
2958
+ pointermove: dragEnabled.value ? onPointerMove : void 0,
2959
+ pointerup: dragEnabled.value ? onPointerUp : void 0
2960
+ } : {}
2961
+ })), useRenderNode(() => ({
2962
+ zIndex: props.zIndex,
2963
+ rect: visible.value ? absRect.value : { x: 0, y: 0, w: 0, h: 0 },
2964
+ deps: [
2965
+ visible.value,
2966
+ absRect.value,
2967
+ fullRect.value,
2968
+ imageCells.value,
2969
+ displayFit.value,
2970
+ zoomScale.value,
2971
+ panX.value,
2972
+ panY.value,
2973
+ textSnapshot.value,
2974
+ displayLines.value,
2975
+ sourceLines.value,
2976
+ currentStyle.value,
2977
+ props.clear,
2978
+ hasBox.value,
2979
+ boxChars.value,
2980
+ props.title,
2981
+ props.copyButton,
2982
+ copyLabel.value,
2983
+ graphicsOutputVersion.value,
2984
+ documentVersion.value
2985
+ ],
2986
+ paint: (dirtyRows) => {
2987
+ withTextWidthProvider(widthProvider, () => {
2988
+ if (!visible.value) {
2989
+ queueClearGraphic();
2990
+ return;
2991
+ }
2992
+ let r = absRect.value, full = fullRect.value;
2993
+ if (r.w <= 0 || r.h <= 0) {
2994
+ queueClearGraphic();
2995
+ return;
2996
+ }
2997
+ let style = currentStyle.value, dx = Math.max(0, Math.floor(r.x - full.x)), fullY = Math.floor(full.y), fullW = Math.max(0, Math.floor(full.w)), fullH = Math.max(0, Math.floor(full.h)), blank = props.clear ? spaces(r.w) : "", paintRow = (y) => {
2998
+ if (y < r.y || y >= r.y + r.h)
2999
+ return;
3000
+ let rowIndex = y - fullY;
3001
+ if (rowIndex < 0 || rowIndex >= fullH) {
3002
+ props.clear && terminal.write(blank, { x: r.x, y, style });
3003
+ return;
3004
+ }
3005
+ let src = boxRow(rowIndex, fullW, fullH), clipped = dx > 0 ? sliceCellsRange(src, dx, dx + r.w) : sliceCells(src, r.w), value = props.clear ? padCells(clipped, r.w) : clipped;
3006
+ (value || props.clear) && terminal.write(value, { x: r.x, y, style });
3007
+ };
3008
+ if (imageCells.value && displayFit.value ? queueImageGraphic(full, displayFit.value) : queueClearGraphic(), dirtyRows?.length) {
3009
+ for (let y of dirtyRows)
3010
+ paintRow(y);
3011
+ return;
3012
+ }
3013
+ for (let y = r.y; y < r.y + r.h; y++)
3014
+ paintRow(y);
3015
+ });
3016
+ }
3017
+ })), () => (0, import_vue9.h)("span", rootProps);
3018
+ }
3019
+ });
3020
+
3021
+ // src/vue/mermaid/beautiful-mermaid.ts
1591
3022
  var BEAUTIFUL_MERMAID_INSTALL_HINT = "Install beautiful-mermaid and use TMermaidText from @simon_he/vue-tui/mermaid or @simon_he/vue-tui/agent/mermaid, or pass a custom renderer prop.", MISSING_BEAUTIFUL_MERMAID_ERROR_CODE = "VUE_TUI_MISSING_BEAUTIFUL_MERMAID", INVALID_BEAUTIFUL_MERMAID_EXPORT_ERROR_CODE = "VUE_TUI_INVALID_BEAUTIFUL_MERMAID_EXPORT", cachedBeautifulMermaid = null;
1592
3023
  function functionValue(value) {
1593
3024
  return typeof value == "function" ? value : null;
@@ -1680,7 +3111,7 @@ var beautifulMermaidRenderer = async (code, options) => {
1680
3111
  function createBeautifulMermaidRenderer() {
1681
3112
  return beautifulMermaidRenderer;
1682
3113
  }
1683
- var TMermaidText2 = (0, import_vue9.defineComponent)({
3114
+ var TMermaidText2 = (0, import_vue10.defineComponent)({
1684
3115
  name: "TMermaidText",
1685
3116
  inheritAttrs: !1,
1686
3117
  props: tMermaidTextProps,
@@ -1690,7 +3121,7 @@ var TMermaidText2 = (0, import_vue9.defineComponent)({
1690
3121
  setup(props, { attrs, emit, slots }) {
1691
3122
  return () => {
1692
3123
  let renderer = props.renderer ?? beautifulMermaidRenderer, shouldRenderSource = props.shouldRenderSource ?? isSimpleMermaidFlowchartSource;
1693
- return (0, import_vue9.h)(
3124
+ return (0, import_vue10.h)(
1694
3125
  TMermaidText,
1695
3126
  {
1696
3127
  ...attrs,
@@ -1704,4 +3135,27 @@ var TMermaidText2 = (0, import_vue9.defineComponent)({
1704
3135
  );
1705
3136
  };
1706
3137
  }
1707
- }), TMermaid = TMermaidText2, TBeautifulMermaidText = TMermaidText2, TBeautifulMermaid = TMermaidText2;
3138
+ }), TMermaid = (0, import_vue10.defineComponent)({
3139
+ name: "TMermaid",
3140
+ inheritAttrs: !1,
3141
+ props: tMermaidImageProps,
3142
+ emits: {
3143
+ copy: (_payload) => !0
3144
+ },
3145
+ setup(props, { attrs, emit, slots }) {
3146
+ return () => {
3147
+ let { renderer: _legacyTextRenderer, ...rest } = props, textRenderer = props.textRenderer ?? props.renderer ?? beautifulMermaidRenderer;
3148
+ return (0, import_vue10.h)(
3149
+ TMermaidImage,
3150
+ {
3151
+ ...attrs,
3152
+ ...rest,
3153
+ textRenderer,
3154
+ shouldRenderSource: props.shouldRenderSource ?? isSimpleMermaidFlowchartSource,
3155
+ onCopy: (payload) => emit("copy", payload)
3156
+ },
3157
+ slots
3158
+ );
3159
+ };
3160
+ }
3161
+ }), TBeautifulMermaidText = TMermaidText2, TBeautifulMermaid = TMermaid;