@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.
- package/README.md +18 -18
- package/dist/{TMermaidText-frVr8Ysb.js → TMermaidText-wLnMMvVS.js} +1 -1
- package/dist/{TSelect-Dx34M1pF.js → TSelect-CMBOOFwK.js} +5 -5
- package/dist/{TTree-DdAjCPHu.js → TTree-kk8ntrpg.js} +6 -5
- package/dist/agent/mermaid.d.cts +2 -2
- package/dist/agent/mermaid.d.ts +2 -2
- package/dist/agent.cjs +542 -266
- package/dist/agent.js +25 -82
- package/dist/{block-source-Crro3mxi.js → block-source-DhzajB9H.js} +299 -239
- package/dist/cli.cjs +57 -16
- package/dist/cli.js +70 -15
- package/dist/core.js +3 -3
- package/dist/{hyperlink-_1FAj7Wq.js → create-terminal-Db_-UGVQ.js} +474 -102
- package/dist/{dom-renderer-DXx8fWzD.js → dom-renderer-BfwAEQMf.js} +3 -2
- package/dist/experimental.cjs +103 -66
- package/dist/experimental.js +20 -74
- package/dist/hyperlink-clbb_ha_.js +100 -0
- package/dist/index.js +8 -8
- package/dist/{linkify-BjI4zVfY.js → linkify-CL9wwnZN.js} +3 -3
- package/dist/markdown.cjs +521 -212
- package/dist/markdown.d.cts +3 -0
- package/dist/markdown.d.ts +3 -0
- package/dist/markdown.js +75 -8
- package/dist/math-image-BZhmfUeu.js +308 -0
- package/dist/mermaid-N3kGTHFy.js +1697 -0
- package/dist/mermaid.cjs +1460 -6
- package/dist/mermaid.d.cts +4 -0
- package/dist/mermaid.d.ts +4 -0
- package/dist/mermaid.js +7 -5
- package/dist/{rect-DUpeDfBg.js → rect-JzWMJxxc.js} +1 -1
- package/dist/renderer/cli/stdout-renderer.d.ts +44 -0
- package/dist/renderer/terminal-graphics.d.ts +61 -0
- package/dist/renderer-dom.js +4 -4
- package/dist/{terminal-graphics-Bbe83wSr.js → terminal-graphics-2FTRg9x3.js} +90 -2
- package/dist/{tlog-theme-i6S_Oftd.js → tlog-theme-B91Wv7Zj.js} +5 -4
- package/dist/vue/components/TAgentTerminalGraphic.d.ts +1 -1
- package/dist/vue/components/TMarkdownText.d.ts +70 -2
- package/dist/vue/components/TMermaidImage.d.ts +920 -0
- package/dist/vue/components/TMermaidText.d.ts +2 -2
- package/dist/vue/components/TVirtualMarkdown.d.ts +70 -2
- package/dist/vue/markdown/ast.d.ts +5 -0
- package/dist/vue/markdown/document.d.ts +3 -0
- package/dist/vue/markdown/math-image.d.ts +68 -0
- package/dist/vue/markdown/theme.d.ts +12 -0
- package/dist/vue/markdown/types.d.ts +12 -2
- package/dist/vue/mermaid/beautiful-mermaid.d.ts +284 -240
- package/dist/vue/mermaid/mermaid-image.d.ts +73 -0
- package/dist/vue.js +9 -9
- package/package.json +24 -10
- package/dist/mermaid-BNhM1jAZ.js +0 -123
- package/dist/width-GqllnV8C.js +0 -474
- /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
|
-
|
|
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
|
|
1389
|
-
return Number.isFinite(
|
|
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,
|
|
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,
|
|
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 =
|
|
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;
|