@simon_he/vue-tui 1.0.2 → 1.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +84 -26
- package/dist/TMermaidText-frVr8Ysb.js +885 -0
- package/dist/{TSelect-DR0FomSu.js → TSelect-tJ87rKPM.js} +59 -242
- package/dist/{TTree-kzhlB5P0.js → TTree-CGdE-CYu.js} +138 -102
- package/dist/agent/mermaid.cjs +2 -0
- package/dist/agent/mermaid.d.cts +2 -0
- package/dist/agent/mermaid.d.ts +2 -0
- package/dist/agent/mermaid.js +1 -0
- package/dist/agent.cjs +31188 -24907
- package/dist/agent.d.cts +11 -1
- package/dist/agent.d.ts +11 -1
- package/dist/agent.js +516 -11
- package/dist/{block-source-CKUOnkgT.js → block-source-CrlmaBM5.js} +1039 -66
- package/dist/cli/input.d.ts +8 -0
- package/dist/cli/stdin-buffer.d.ts +1 -1
- package/dist/cli/video/ffmpeg-frame-source.d.ts +10 -0
- package/dist/cli/video/png-frame-parser.d.ts +4 -0
- package/dist/cli/video/raw-frame-parser.d.ts +1 -0
- package/dist/cli/video/yt-dlp-frame-source.d.ts +11 -0
- package/dist/cli.cjs +5146 -6767
- package/dist/cli.d.cts +5 -1
- package/dist/cli.d.ts +5 -1
- package/dist/cli.js +2869 -154
- package/dist/core/buffer/eaw-ranges-unicode-17.d.ts +14 -0
- package/dist/core/perf/instrumentation-noop.d.ts +48 -0
- package/dist/core/perf/instrumentation.d.ts +136 -0
- package/dist/core/terminal/create-terminal.d.ts +1 -0
- package/dist/core.cjs +843 -1469
- package/dist/core.js +4 -5
- package/dist/create-terminal-app.d.ts +24 -1
- package/dist/debug-logger-CmsGI4of.js +74 -0
- package/dist/{dom-renderer-BniJSQyX.js → dom-renderer-DXx8fWzD.js} +2 -3
- package/dist/experimental/3d/bun/contributor-avatar-atlas.d.ts +12 -0
- package/dist/experimental/3d/bun/png.d.ts +1 -0
- package/dist/experimental/3d/bun/terminal-badge-scene.d.ts +11 -0
- package/dist/experimental/3d/bun/terminal-badge.wgsl.d.ts +1 -0
- package/dist/experimental/3d/bun/webgpu-renderer.d.ts +26 -0
- package/dist/experimental/3d/bun.cjs +7271 -0
- package/dist/experimental/3d/bun.d.cts +4 -0
- package/dist/experimental/3d/bun.d.ts +4 -0
- package/dist/experimental/3d/bun.js +7390 -0
- package/dist/experimental/video/node.cjs +497 -0
- package/dist/experimental/video/node.d.cts +4 -0
- package/dist/experimental/video/node.d.ts +4 -0
- package/dist/experimental/video/node.js +610 -0
- package/dist/experimental.cjs +6876 -6192
- package/dist/experimental.d.cts +7 -0
- package/dist/experimental.d.ts +7 -0
- package/dist/experimental.js +3005 -9
- package/dist/frame-perf-CHpWhbC4.js +111 -0
- package/dist/{create-terminal-DBFNYr8f.js → hyperlink-_1FAj7Wq.js} +440 -13
- package/dist/index.cjs +5017 -10339
- package/dist/index.js +14 -13
- package/dist/{linkify-D_gzn9Xq.js → linkify-D68T7rdW.js} +193 -3
- package/dist/markdown.cjs +21295 -12691
- package/dist/markdown.d.cts +1 -1
- package/dist/markdown.d.ts +1 -1
- package/dist/markdown.js +211 -51
- package/dist/mermaid-BNhM1jAZ.js +123 -0
- package/dist/mermaid.cjs +1707 -0
- package/dist/mermaid.d.cts +3 -0
- package/dist/mermaid.d.ts +3 -0
- package/dist/mermaid.js +6 -0
- package/dist/observability/frame-perf-store.d.ts +2 -1
- package/dist/observability/frame-perf.d.ts +33 -0
- package/dist/observability.cjs +106 -107
- package/dist/observability.d.cts +2 -2
- package/dist/observability.d.ts +2 -2
- package/dist/observability.js +3 -3
- package/dist/{wheel-scroll-vBRaQ7p-.js → rect-DUpeDfBg.js} +253 -117
- package/dist/renderer/cli/stdout-metrics.d.ts +10 -0
- package/dist/renderer/cli/stdout-renderer.d.ts +3 -0
- package/dist/renderer/terminal-graphic-render-queue.d.ts +50 -0
- package/dist/renderer/terminal-graphics-trace.d.ts +53 -0
- package/dist/renderer/terminal-graphics.d.ts +147 -0
- package/dist/renderer-dom.cjs +364 -903
- package/dist/renderer-dom.js +4 -5
- package/dist/runtime/index.d.ts +2 -0
- package/dist/{runtime-rfcZCyJq.js → runtime-Byf8XXOT.js} +28 -15
- package/dist/runtime.cjs +427 -889
- package/dist/runtime.js +2 -2
- package/dist/terminal-graphics-Bbe83wSr.js +597 -0
- package/dist/{terminal-selection-DBinO6p5.js → terminal-selection-4W1SJj4c.js} +4 -1
- package/dist/{tlog-theme-CvLFNMwk.js → tlog-theme-Bul2Na3u.js} +1237 -12
- package/dist/{trace-CjzYeIxN.js → trace-Bh8WnoMo.js} +5 -0
- package/dist/vue/agent/create-png-terminal-graphic-renderer.d.ts +19 -0
- package/dist/vue/components/T3DViewport.d.ts +473 -0
- package/dist/vue/components/TAgentTerminalGraphic.d.ts +494 -0
- package/dist/vue/components/TCharts.d.ts +1121 -0
- package/dist/vue/components/TFeedback.d.ts +1 -1
- package/dist/vue/components/TFlex.d.ts +389 -0
- package/dist/vue/components/TForm.d.ts +4 -4
- package/dist/vue/components/TLogSearchBar.d.ts +3 -3
- package/dist/vue/components/TLogSearchPager.d.ts +2 -2
- package/dist/vue/components/TMarkdownText.d.ts +162 -4
- package/dist/vue/components/TMermaidText.d.ts +900 -0
- package/dist/vue/components/TVideo.d.ts +291 -0
- package/dist/vue/components/TVirtualList.d.ts +9 -0
- package/dist/vue/components/TVirtualMarkdown.d.ts +170 -9
- package/dist/vue/components/TVirtualRows.d.ts +9 -0
- package/dist/vue/components/TerminalProvider.d.ts +2 -0
- package/dist/vue/context.d.ts +24 -0
- package/dist/vue/index.d.ts +5 -0
- package/dist/vue/layout/flex.d.ts +67 -0
- package/dist/vue/markdown/ast.d.ts +5 -2
- package/dist/vue/markdown/document.d.ts +5 -0
- package/dist/vue/markdown/image-actions.d.ts +14 -0
- package/dist/vue/markdown/image.d.ts +11 -0
- package/dist/vue/markdown/link-actions.d.ts +14 -0
- package/dist/vue/markdown/math-actions.d.ts +14 -0
- package/dist/vue/markdown/math.d.ts +6 -0
- package/dist/vue/markdown/render.d.ts +28 -0
- package/dist/vue/markdown/types.d.ts +78 -0
- package/dist/vue/mermaid/beautiful-mermaid.d.ts +1436 -0
- package/dist/vue/render/render-manager.d.ts +7 -0
- package/dist/vue/video/types.d.ts +39 -0
- package/dist/vue.cjs +7207 -12437
- package/dist/vue.js +704 -38
- package/dist/wheel-scroll-DASkEZr-.js +106 -0
- package/dist/{hyperlink-Bn02UXJb.js → width-GqllnV8C.js} +166 -111
- package/package.json +119 -14
- package/dist/frame-perf-C6Xfg85O.js +0 -24
- package/dist/sgr-BmzxEjAO.js +0 -304
- /package/dist/{ansi-palette-CNXqFciC.js → ansi-palette-CH6jc2Z7.js} +0 -0
- /package/dist/{path-suggest-BNqcuE3-.js → path-suggest-Dndu4dTi.js} +0 -0
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
//#region src/observability/frame-perf.ts
|
|
2
|
+
const FRAME_PERF_REASON_PRIORITY = {
|
|
3
|
+
unknown: 0,
|
|
4
|
+
manual: 1,
|
|
5
|
+
data: 2,
|
|
6
|
+
selection: 3,
|
|
7
|
+
stream: 4,
|
|
8
|
+
resize: 5,
|
|
9
|
+
scroll: 6,
|
|
10
|
+
input: 7
|
|
11
|
+
};
|
|
12
|
+
const EMPTY_METRIC_STATS = Object.freeze({
|
|
13
|
+
avg: 0,
|
|
14
|
+
max: 0,
|
|
15
|
+
min: 0
|
|
16
|
+
});
|
|
17
|
+
function metricStats(values) {
|
|
18
|
+
if (!values.length) return EMPTY_METRIC_STATS;
|
|
19
|
+
let sum = 0;
|
|
20
|
+
let max = Number.NEGATIVE_INFINITY;
|
|
21
|
+
let min = Number.POSITIVE_INFINITY;
|
|
22
|
+
for (const value of values) {
|
|
23
|
+
sum += value;
|
|
24
|
+
if (value > max) max = value;
|
|
25
|
+
if (value < min) min = value;
|
|
26
|
+
}
|
|
27
|
+
return {
|
|
28
|
+
avg: sum / values.length,
|
|
29
|
+
max,
|
|
30
|
+
min
|
|
31
|
+
};
|
|
32
|
+
}
|
|
33
|
+
function summarizeFramePerf(samples) {
|
|
34
|
+
const durationMs = [];
|
|
35
|
+
const renderManagerMs = [];
|
|
36
|
+
const commitMs = [];
|
|
37
|
+
const domFlushMs = [];
|
|
38
|
+
const stdoutFlushMs = [];
|
|
39
|
+
const dirtyRows = [];
|
|
40
|
+
const scannedNodes = [];
|
|
41
|
+
const paintedNodes = [];
|
|
42
|
+
const reasons = {};
|
|
43
|
+
const activePlanes = {};
|
|
44
|
+
let fullDirtyFrames = 0;
|
|
45
|
+
let coalescedInvalidates = 0;
|
|
46
|
+
let coalescedFrameTasks = 0;
|
|
47
|
+
let droppedUpdates = 0;
|
|
48
|
+
let maxQueueDepth = 0;
|
|
49
|
+
let rowBucketFallbacks = 0;
|
|
50
|
+
for (const sample of samples) {
|
|
51
|
+
durationMs.push(sample.durationMs);
|
|
52
|
+
renderManagerMs.push(sample.renderManagerMs);
|
|
53
|
+
commitMs.push(sample.commitMs);
|
|
54
|
+
scannedNodes.push(sample.scannedNodes);
|
|
55
|
+
paintedNodes.push(sample.paintedNodes);
|
|
56
|
+
if (sample.domFlushMs != null) domFlushMs.push(sample.domFlushMs);
|
|
57
|
+
if (sample.stdoutFlushMs != null) stdoutFlushMs.push(sample.stdoutFlushMs);
|
|
58
|
+
if (sample.dirtyRows == null) fullDirtyFrames++;
|
|
59
|
+
else dirtyRows.push(sample.dirtyRows);
|
|
60
|
+
reasons[sample.reason] = (reasons[sample.reason] ?? 0) + 1;
|
|
61
|
+
const planes = sample.activePlanes;
|
|
62
|
+
if (!planes) activePlanes.all = (activePlanes.all ?? 0) + 1;
|
|
63
|
+
else for (const plane of planes) activePlanes[plane] = (activePlanes[plane] ?? 0) + 1;
|
|
64
|
+
coalescedInvalidates += sample.coalescedInvalidates;
|
|
65
|
+
coalescedFrameTasks += sample.coalescedFrameTasks;
|
|
66
|
+
droppedUpdates += sample.droppedUpdates;
|
|
67
|
+
if (sample.queueDepth > maxQueueDepth) maxQueueDepth = sample.queueDepth;
|
|
68
|
+
rowBucketFallbacks += sample.rowBucketFallbacks?.length ?? 0;
|
|
69
|
+
}
|
|
70
|
+
const first = samples[0] ?? null;
|
|
71
|
+
const latest = samples[samples.length - 1] ?? null;
|
|
72
|
+
return {
|
|
73
|
+
frames: samples.length,
|
|
74
|
+
firstFrameId: first?.frameId ?? null,
|
|
75
|
+
latestFrameId: latest?.frameId ?? null,
|
|
76
|
+
windowMs: first && latest ? Math.max(0, latest.startedAt - first.startedAt) : 0,
|
|
77
|
+
durationMs: metricStats(durationMs),
|
|
78
|
+
renderManagerMs: metricStats(renderManagerMs),
|
|
79
|
+
commitMs: metricStats(commitMs),
|
|
80
|
+
domFlushMs: metricStats(domFlushMs),
|
|
81
|
+
stdoutFlushMs: metricStats(stdoutFlushMs),
|
|
82
|
+
dirtyRows: {
|
|
83
|
+
avg: dirtyRows.length ? dirtyRows.reduce((sum, value) => sum + value, 0) / dirtyRows.length : 0,
|
|
84
|
+
max: dirtyRows.length ? Math.max(...dirtyRows) : 0,
|
|
85
|
+
sampledFrames: dirtyRows.length,
|
|
86
|
+
fullFrames: fullDirtyFrames
|
|
87
|
+
},
|
|
88
|
+
scannedNodes: metricStats(scannedNodes),
|
|
89
|
+
paintedNodes: metricStats(paintedNodes),
|
|
90
|
+
coalescedInvalidates,
|
|
91
|
+
coalescedFrameTasks,
|
|
92
|
+
droppedUpdates,
|
|
93
|
+
maxQueueDepth,
|
|
94
|
+
rowBucketFallbacks,
|
|
95
|
+
reasons,
|
|
96
|
+
activePlanes
|
|
97
|
+
};
|
|
98
|
+
}
|
|
99
|
+
function framePerfNow() {
|
|
100
|
+
const p = globalThis.performance;
|
|
101
|
+
if (p && typeof p.now === "function") return p.now();
|
|
102
|
+
return Date.now();
|
|
103
|
+
}
|
|
104
|
+
function mergeFramePerfReason(prev, next) {
|
|
105
|
+
const a = prev ?? "unknown";
|
|
106
|
+
const b = next ?? "unknown";
|
|
107
|
+
return FRAME_PERF_REASON_PRIORITY[b] > FRAME_PERF_REASON_PRIORITY[a] ? b : a;
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
//#endregion
|
|
111
|
+
export { framePerfNow, mergeFramePerfReason, summarizeFramePerf };
|
|
@@ -1,5 +1,4 @@
|
|
|
1
|
-
import { charCellWidth, segmentedGraphemes } from "./
|
|
2
|
-
import { parseAnsiSgr } from "./sgr-BmzxEjAO.js";
|
|
1
|
+
import { charCellWidth, segmentedGraphemes } from "./width-GqllnV8C.js";
|
|
3
2
|
|
|
4
3
|
//#region src/core/render-plane.ts
|
|
5
4
|
const TERMINAL_RENDER_PLANES = [
|
|
@@ -9,6 +8,309 @@ const TERMINAL_RENDER_PLANES = [
|
|
|
9
8
|
"overlay"
|
|
10
9
|
];
|
|
11
10
|
|
|
11
|
+
//#endregion
|
|
12
|
+
//#region src/core/ansi/sgr.ts
|
|
13
|
+
const ESC = "\x1B";
|
|
14
|
+
function ansi16ToColorName(code) {
|
|
15
|
+
switch (code) {
|
|
16
|
+
case 30: return "black";
|
|
17
|
+
case 31: return "red";
|
|
18
|
+
case 32: return "green";
|
|
19
|
+
case 33: return "yellow";
|
|
20
|
+
case 34: return "blue";
|
|
21
|
+
case 35: return "magenta";
|
|
22
|
+
case 36: return "cyan";
|
|
23
|
+
case 37: return "white";
|
|
24
|
+
case 90: return "blackBright";
|
|
25
|
+
case 91: return "redBright";
|
|
26
|
+
case 92: return "greenBright";
|
|
27
|
+
case 93: return "yellowBright";
|
|
28
|
+
case 94: return "blueBright";
|
|
29
|
+
case 95: return "magentaBright";
|
|
30
|
+
case 96: return "cyanBright";
|
|
31
|
+
case 97: return "whiteBright";
|
|
32
|
+
default: return void 0;
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
function ansi16BgToColorName(code) {
|
|
36
|
+
const fgCode = code >= 40 && code <= 47 ? code - 10 : code >= 100 && code <= 107 ? code - 10 : null;
|
|
37
|
+
if (fgCode == null) return void 0;
|
|
38
|
+
return ansi16ToColorName(fgCode);
|
|
39
|
+
}
|
|
40
|
+
const ANSI16_RGB = {
|
|
41
|
+
black: {
|
|
42
|
+
r: 0,
|
|
43
|
+
g: 0,
|
|
44
|
+
b: 0
|
|
45
|
+
},
|
|
46
|
+
red: {
|
|
47
|
+
r: 201,
|
|
48
|
+
g: 27,
|
|
49
|
+
b: 0
|
|
50
|
+
},
|
|
51
|
+
green: {
|
|
52
|
+
r: 0,
|
|
53
|
+
g: 194,
|
|
54
|
+
b: 0
|
|
55
|
+
},
|
|
56
|
+
yellow: {
|
|
57
|
+
r: 199,
|
|
58
|
+
g: 196,
|
|
59
|
+
b: 0
|
|
60
|
+
},
|
|
61
|
+
blue: {
|
|
62
|
+
r: 2,
|
|
63
|
+
g: 37,
|
|
64
|
+
b: 199
|
|
65
|
+
},
|
|
66
|
+
magenta: {
|
|
67
|
+
r: 201,
|
|
68
|
+
g: 48,
|
|
69
|
+
b: 199
|
|
70
|
+
},
|
|
71
|
+
cyan: {
|
|
72
|
+
r: 0,
|
|
73
|
+
g: 197,
|
|
74
|
+
b: 199
|
|
75
|
+
},
|
|
76
|
+
white: {
|
|
77
|
+
r: 199,
|
|
78
|
+
g: 199,
|
|
79
|
+
b: 199
|
|
80
|
+
},
|
|
81
|
+
blackBright: {
|
|
82
|
+
r: 104,
|
|
83
|
+
g: 104,
|
|
84
|
+
b: 104
|
|
85
|
+
},
|
|
86
|
+
redBright: {
|
|
87
|
+
r: 255,
|
|
88
|
+
g: 110,
|
|
89
|
+
b: 103
|
|
90
|
+
},
|
|
91
|
+
greenBright: {
|
|
92
|
+
r: 95,
|
|
93
|
+
g: 250,
|
|
94
|
+
b: 104
|
|
95
|
+
},
|
|
96
|
+
yellowBright: {
|
|
97
|
+
r: 255,
|
|
98
|
+
g: 252,
|
|
99
|
+
b: 103
|
|
100
|
+
},
|
|
101
|
+
blueBright: {
|
|
102
|
+
r: 104,
|
|
103
|
+
g: 113,
|
|
104
|
+
b: 255
|
|
105
|
+
},
|
|
106
|
+
magentaBright: {
|
|
107
|
+
r: 255,
|
|
108
|
+
g: 118,
|
|
109
|
+
b: 255
|
|
110
|
+
},
|
|
111
|
+
cyanBright: {
|
|
112
|
+
r: 95,
|
|
113
|
+
g: 253,
|
|
114
|
+
b: 255
|
|
115
|
+
},
|
|
116
|
+
whiteBright: {
|
|
117
|
+
r: 255,
|
|
118
|
+
g: 255,
|
|
119
|
+
b: 255
|
|
120
|
+
}
|
|
121
|
+
};
|
|
122
|
+
function nearestAnsi16(r, g, b) {
|
|
123
|
+
let best = "white";
|
|
124
|
+
let bestDist = Number.POSITIVE_INFINITY;
|
|
125
|
+
for (const [name, rgb] of Object.entries(ANSI16_RGB)) {
|
|
126
|
+
const dr = r - rgb.r;
|
|
127
|
+
const dg = g - rgb.g;
|
|
128
|
+
const db = b - rgb.b;
|
|
129
|
+
const d = dr * dr + dg * dg + db * db;
|
|
130
|
+
if (d < bestDist) {
|
|
131
|
+
bestDist = d;
|
|
132
|
+
best = name;
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
return best;
|
|
136
|
+
}
|
|
137
|
+
function ansi256ToRgb(index) {
|
|
138
|
+
const n = Math.max(0, Math.min(255, Math.trunc(index)));
|
|
139
|
+
if (n < 16) {
|
|
140
|
+
const map = [
|
|
141
|
+
"black",
|
|
142
|
+
"red",
|
|
143
|
+
"green",
|
|
144
|
+
"yellow",
|
|
145
|
+
"blue",
|
|
146
|
+
"magenta",
|
|
147
|
+
"cyan",
|
|
148
|
+
"white",
|
|
149
|
+
"blackBright",
|
|
150
|
+
"redBright",
|
|
151
|
+
"greenBright",
|
|
152
|
+
"yellowBright",
|
|
153
|
+
"blueBright",
|
|
154
|
+
"magentaBright",
|
|
155
|
+
"cyanBright",
|
|
156
|
+
"whiteBright"
|
|
157
|
+
];
|
|
158
|
+
const name = map[n] ?? "white";
|
|
159
|
+
return ANSI16_RGB[name];
|
|
160
|
+
}
|
|
161
|
+
if (n >= 232) {
|
|
162
|
+
const c = 8 + (n - 232) * 10;
|
|
163
|
+
return {
|
|
164
|
+
r: c,
|
|
165
|
+
g: c,
|
|
166
|
+
b: c
|
|
167
|
+
};
|
|
168
|
+
}
|
|
169
|
+
const i = n - 16;
|
|
170
|
+
const rr = Math.floor(i / 36);
|
|
171
|
+
const gg = Math.floor(i % 36 / 6);
|
|
172
|
+
const bb = i % 6;
|
|
173
|
+
const toComponent = (v) => v === 0 ? 0 : 55 + v * 40;
|
|
174
|
+
return {
|
|
175
|
+
r: toComponent(rr),
|
|
176
|
+
g: toComponent(gg),
|
|
177
|
+
b: toComponent(bb)
|
|
178
|
+
};
|
|
179
|
+
}
|
|
180
|
+
function applyAnsiSgrStyle(current, codes) {
|
|
181
|
+
let next = { ...current };
|
|
182
|
+
for (let i = 0; i < codes.length; i++) {
|
|
183
|
+
const code = codes[i];
|
|
184
|
+
if (code === 0) {
|
|
185
|
+
next = {};
|
|
186
|
+
continue;
|
|
187
|
+
}
|
|
188
|
+
if (code === 1) next = {
|
|
189
|
+
...next,
|
|
190
|
+
bold: true
|
|
191
|
+
};
|
|
192
|
+
else if (code === 2) next = {
|
|
193
|
+
...next,
|
|
194
|
+
dim: true
|
|
195
|
+
};
|
|
196
|
+
else if (code === 3) next = {
|
|
197
|
+
...next,
|
|
198
|
+
italic: true
|
|
199
|
+
};
|
|
200
|
+
else if (code === 4) next = {
|
|
201
|
+
...next,
|
|
202
|
+
underline: true
|
|
203
|
+
};
|
|
204
|
+
else if (code === 7) next = {
|
|
205
|
+
...next,
|
|
206
|
+
inverse: true
|
|
207
|
+
};
|
|
208
|
+
else if (code === 22) next = {
|
|
209
|
+
...next,
|
|
210
|
+
bold: false,
|
|
211
|
+
dim: false
|
|
212
|
+
};
|
|
213
|
+
else if (code === 23) next = {
|
|
214
|
+
...next,
|
|
215
|
+
italic: false
|
|
216
|
+
};
|
|
217
|
+
else if (code === 24) next = {
|
|
218
|
+
...next,
|
|
219
|
+
underline: false
|
|
220
|
+
};
|
|
221
|
+
else if (code === 27) next = {
|
|
222
|
+
...next,
|
|
223
|
+
inverse: false
|
|
224
|
+
};
|
|
225
|
+
else if (code === 39) next = {
|
|
226
|
+
...next,
|
|
227
|
+
fg: void 0
|
|
228
|
+
};
|
|
229
|
+
else if (code === 49) next = {
|
|
230
|
+
...next,
|
|
231
|
+
bg: void 0
|
|
232
|
+
};
|
|
233
|
+
else if (code >= 30 && code <= 37 || code >= 90 && code <= 97) {
|
|
234
|
+
const fg = ansi16ToColorName(code);
|
|
235
|
+
next = {
|
|
236
|
+
...next,
|
|
237
|
+
fg: fg ?? next.fg
|
|
238
|
+
};
|
|
239
|
+
} else if (code >= 40 && code <= 47 || code >= 100 && code <= 107) {
|
|
240
|
+
const bg = ansi16BgToColorName(code);
|
|
241
|
+
next = {
|
|
242
|
+
...next,
|
|
243
|
+
bg: bg ?? next.bg
|
|
244
|
+
};
|
|
245
|
+
} else if (code === 38 || code === 48) {
|
|
246
|
+
const mode = codes[i + 1];
|
|
247
|
+
if (mode === 5) {
|
|
248
|
+
const idx = codes[i + 2];
|
|
249
|
+
if (idx != null) {
|
|
250
|
+
const { r, g, b } = ansi256ToRgb(idx);
|
|
251
|
+
const name = nearestAnsi16(r, g, b);
|
|
252
|
+
next = code === 38 ? {
|
|
253
|
+
...next,
|
|
254
|
+
fg: name
|
|
255
|
+
} : {
|
|
256
|
+
...next,
|
|
257
|
+
bg: name
|
|
258
|
+
};
|
|
259
|
+
}
|
|
260
|
+
i += 2;
|
|
261
|
+
} else if (mode === 2) {
|
|
262
|
+
const r = codes[i + 2];
|
|
263
|
+
const g = codes[i + 3];
|
|
264
|
+
const b = codes[i + 4];
|
|
265
|
+
if (r != null && g != null && b != null) {
|
|
266
|
+
const name = nearestAnsi16(r, g, b);
|
|
267
|
+
next = code === 38 ? {
|
|
268
|
+
...next,
|
|
269
|
+
fg: name
|
|
270
|
+
} : {
|
|
271
|
+
...next,
|
|
272
|
+
bg: name
|
|
273
|
+
};
|
|
274
|
+
}
|
|
275
|
+
i += 4;
|
|
276
|
+
}
|
|
277
|
+
}
|
|
278
|
+
}
|
|
279
|
+
return next;
|
|
280
|
+
}
|
|
281
|
+
function parseAnsiSgr(input, baseStyle = {}) {
|
|
282
|
+
const segments = [];
|
|
283
|
+
let style = { ...baseStyle };
|
|
284
|
+
let lastIndex = 0;
|
|
285
|
+
for (let i = 0; i < input.length; i++) {
|
|
286
|
+
if (input[i] !== ESC || input[i + 1] !== "[") continue;
|
|
287
|
+
let j = i + 2;
|
|
288
|
+
while (j < input.length) {
|
|
289
|
+
const c = input.charCodeAt(j);
|
|
290
|
+
if (c >= 48 && c <= 57 || c === 59) {
|
|
291
|
+
j++;
|
|
292
|
+
continue;
|
|
293
|
+
}
|
|
294
|
+
break;
|
|
295
|
+
}
|
|
296
|
+
if (j >= input.length || input[j] !== "m") continue;
|
|
297
|
+
if (i > lastIndex) segments.push({
|
|
298
|
+
text: input.slice(lastIndex, i),
|
|
299
|
+
style
|
|
300
|
+
});
|
|
301
|
+
const body = input.slice(i + 2, j);
|
|
302
|
+
const codes = body.split(";").filter(Boolean).map((n) => Number.parseInt(n, 10)).filter((n) => Number.isFinite(n));
|
|
303
|
+
style = applyAnsiSgrStyle(style, codes.length ? codes : [0]);
|
|
304
|
+
lastIndex = j + 1;
|
|
305
|
+
i = j;
|
|
306
|
+
}
|
|
307
|
+
if (lastIndex < input.length) segments.push({
|
|
308
|
+
text: input.slice(lastIndex),
|
|
309
|
+
style
|
|
310
|
+
});
|
|
311
|
+
return segments;
|
|
312
|
+
}
|
|
313
|
+
|
|
12
314
|
//#endregion
|
|
13
315
|
//#region src/core/buffer/buffer.ts
|
|
14
316
|
const DEFAULT_STYLE = Object.freeze({});
|
|
@@ -427,9 +729,12 @@ function resizeBuffer(buffer, cols, rows) {
|
|
|
427
729
|
const nextCols = Math.max(0, Math.floor(cols));
|
|
428
730
|
const nextRows = Math.max(0, Math.floor(rows));
|
|
429
731
|
if (nextCols === buffer.cols && nextRows === buffer.rows) return;
|
|
732
|
+
const prevRows = buffer.rows;
|
|
733
|
+
const prevDirtyAll = buffer.dirtyAll;
|
|
734
|
+
const prevDirtyBits = buffer.dirtyBits;
|
|
430
735
|
const blank = createBlankCell();
|
|
431
736
|
const nextGrid = Array.from({ length: nextRows }, () => Array.from({ length: nextCols }, () => blank));
|
|
432
|
-
const copyRows = Math.min(
|
|
737
|
+
const copyRows = Math.min(prevRows, nextRows);
|
|
433
738
|
const copyCols = Math.min(buffer.cols, nextCols);
|
|
434
739
|
for (let y = 0; y < copyRows; y++) {
|
|
435
740
|
const src = getBufferRow(buffer, y);
|
|
@@ -453,10 +758,21 @@ function resizeBuffer(buffer, cols, rows) {
|
|
|
453
758
|
buffer.cols = nextCols;
|
|
454
759
|
buffer.rows = nextRows;
|
|
455
760
|
buffer.dirtyBits = new Uint8Array(nextRows);
|
|
456
|
-
buffer.dirtyCount =
|
|
457
|
-
buffer.dirtyMin =
|
|
458
|
-
buffer.dirtyMax =
|
|
459
|
-
buffer.dirtyAll = nextRows > 0;
|
|
761
|
+
buffer.dirtyCount = 0;
|
|
762
|
+
buffer.dirtyMin = Number.POSITIVE_INFINITY;
|
|
763
|
+
buffer.dirtyMax = -1;
|
|
764
|
+
buffer.dirtyAll = prevDirtyAll && nextRows > 0;
|
|
765
|
+
if (buffer.dirtyAll) {
|
|
766
|
+
buffer.dirtyCount = nextRows;
|
|
767
|
+
buffer.dirtyMin = 0;
|
|
768
|
+
buffer.dirtyMax = nextRows - 1;
|
|
769
|
+
} else for (let y = 0; y < copyRows; y++) {
|
|
770
|
+
if (prevDirtyBits[y] !== 1) continue;
|
|
771
|
+
buffer.dirtyBits[y] = 1;
|
|
772
|
+
buffer.dirtyCount++;
|
|
773
|
+
if (y < buffer.dirtyMin) buffer.dirtyMin = y;
|
|
774
|
+
if (y > buffer.dirtyMax) buffer.dirtyMax = y;
|
|
775
|
+
}
|
|
460
776
|
buffer.cursorX = clamp(buffer.cursorX, 0, Math.max(0, nextCols));
|
|
461
777
|
buffer.cursorY = clamp(buffer.cursorY, 0, Math.max(0, nextRows - 1));
|
|
462
778
|
if (buffer.fingerprintFn) {
|
|
@@ -529,6 +845,10 @@ function mergePlanes(prev, next) {
|
|
|
529
845
|
return Array.from(merged);
|
|
530
846
|
}
|
|
531
847
|
const TERMINAL_PLANE_INTERNALS = Symbol.for("@simon_he/vue-tui:v1:terminal-plane-internals");
|
|
848
|
+
const TERMINAL_ROOT = Symbol.for("@simon_he/vue-tui:v1:terminal-root");
|
|
849
|
+
function getRootTerminal(terminal) {
|
|
850
|
+
return terminal[TERMINAL_ROOT] ?? terminal;
|
|
851
|
+
}
|
|
532
852
|
function createCoverage(cols, rows) {
|
|
533
853
|
return Array.from({ length: rows }, () => new Uint8Array(cols));
|
|
534
854
|
}
|
|
@@ -612,6 +932,8 @@ function markPlaneCoverageRange(state, x0, y0, x1, y1, value) {
|
|
|
612
932
|
}
|
|
613
933
|
}
|
|
614
934
|
function markPlaneCoverageForPut(state, x, y, ch, prevCell) {
|
|
935
|
+
if (!Number.isSafeInteger(x) || !Number.isSafeInteger(y)) return;
|
|
936
|
+
if (x < 0 || x >= state.buffer.cols || y < 0 || y >= state.buffer.rows) return;
|
|
615
937
|
const row = state.coverage[y];
|
|
616
938
|
if (!row) return;
|
|
617
939
|
if (prevCell?.continuation && x > 0) row[x - 1] = 1;
|
|
@@ -727,10 +1049,14 @@ function createTerminal(opts) {
|
|
|
727
1049
|
}
|
|
728
1050
|
function putForPlane(plane, x, y, ch, style) {
|
|
729
1051
|
const state = getPlaneState(plane);
|
|
730
|
-
if (
|
|
731
|
-
const
|
|
732
|
-
|
|
733
|
-
|
|
1052
|
+
if (typeof x !== "number" || typeof y !== "number") return;
|
|
1053
|
+
const cellX = Math.floor(x);
|
|
1054
|
+
const cellY = Math.floor(y);
|
|
1055
|
+
if (!Number.isFinite(cellX) || !Number.isFinite(cellY)) return;
|
|
1056
|
+
if (cellY < 0 || cellY >= state.buffer.rows || cellX < 0 || cellX >= state.buffer.cols) return;
|
|
1057
|
+
const prevCell = getBufferCell(state.buffer, cellX, cellY);
|
|
1058
|
+
putCell(state.buffer, cellX, cellY, ch, style);
|
|
1059
|
+
markPlaneCoverageForPut(state, cellX, cellY, ch, prevCell);
|
|
734
1060
|
}
|
|
735
1061
|
function writeAtForPlane(plane, text, x, y, style) {
|
|
736
1062
|
const state = getPlaneState(plane);
|
|
@@ -1233,6 +1559,7 @@ function createTerminal(opts) {
|
|
|
1233
1559
|
return getRowFingerprints(state.buffer, yy);
|
|
1234
1560
|
}
|
|
1235
1561
|
};
|
|
1562
|
+
api[TERMINAL_ROOT] = base;
|
|
1236
1563
|
planeTerminals.set(plane, api);
|
|
1237
1564
|
return api;
|
|
1238
1565
|
}
|
|
@@ -1314,7 +1641,7 @@ function createTerminal(opts) {
|
|
|
1314
1641
|
const rows = collectAndClearDirtyRows(state.buffer);
|
|
1315
1642
|
if (rows === null) {
|
|
1316
1643
|
composeAllRows = true;
|
|
1317
|
-
|
|
1644
|
+
continue;
|
|
1318
1645
|
}
|
|
1319
1646
|
for (const y of rows) dirtyRows.add(y);
|
|
1320
1647
|
}
|
|
@@ -1436,8 +1763,108 @@ function createTerminal(opts) {
|
|
|
1436
1763
|
scrollRowsForPlane(plane, startY, endY, lines);
|
|
1437
1764
|
}
|
|
1438
1765
|
};
|
|
1766
|
+
base[TERMINAL_ROOT] = base;
|
|
1439
1767
|
return base;
|
|
1440
1768
|
}
|
|
1441
1769
|
|
|
1442
1770
|
//#endregion
|
|
1443
|
-
|
|
1771
|
+
//#region src/utils/url-safety.ts
|
|
1772
|
+
const ENCODED_ASCII_CONTROL_RE = /%(?:0[0-9a-f]|1[0-9a-f]|7f)/i;
|
|
1773
|
+
function hasControlCodePoint(value) {
|
|
1774
|
+
for (let i = 0; i < value.length; i++) {
|
|
1775
|
+
const code = value.charCodeAt(i);
|
|
1776
|
+
if (code <= 31 || code >= 127 && code <= 159) return true;
|
|
1777
|
+
}
|
|
1778
|
+
return false;
|
|
1779
|
+
}
|
|
1780
|
+
function hasEncodedControl(value) {
|
|
1781
|
+
let current = String(value ?? "");
|
|
1782
|
+
for (let depth = 0; depth < 3; depth++) {
|
|
1783
|
+
if (ENCODED_ASCII_CONTROL_RE.test(current)) return true;
|
|
1784
|
+
let decoded;
|
|
1785
|
+
try {
|
|
1786
|
+
decoded = decodeURIComponent(current);
|
|
1787
|
+
} catch {
|
|
1788
|
+
return true;
|
|
1789
|
+
}
|
|
1790
|
+
if (hasControlCodePoint(decoded)) return true;
|
|
1791
|
+
if (decoded === current) return false;
|
|
1792
|
+
current = decoded;
|
|
1793
|
+
}
|
|
1794
|
+
return ENCODED_ASCII_CONTROL_RE.test(current) || hasControlCodePoint(current);
|
|
1795
|
+
}
|
|
1796
|
+
|
|
1797
|
+
//#endregion
|
|
1798
|
+
//#region src/core/hyperlink.ts
|
|
1799
|
+
const SCHEME_RE = /^[a-z][a-z0-9+.-]*:/i;
|
|
1800
|
+
const BLOCKED_SCHEME_RE = /^(?:javascript|data|vbscript):/i;
|
|
1801
|
+
const SAFE_RELATIVE_HREF_RE = /^(?:[A-Za-z0-9._~!$&()*+,;=:@/?#-]|%[0-9A-Fa-f]{2})+$/u;
|
|
1802
|
+
function normalizeRawHref(value) {
|
|
1803
|
+
if (typeof value !== "string") return null;
|
|
1804
|
+
const raw = value.trim();
|
|
1805
|
+
if (!raw) return null;
|
|
1806
|
+
if (raw !== value) return null;
|
|
1807
|
+
for (let i = 0; i < value.length; i++) {
|
|
1808
|
+
const code = value.charCodeAt(i);
|
|
1809
|
+
if (code <= 31 || code >= 127 && code <= 159) return null;
|
|
1810
|
+
}
|
|
1811
|
+
if (/\s/u.test(raw)) return null;
|
|
1812
|
+
if (raw.startsWith("//")) return null;
|
|
1813
|
+
if (BLOCKED_SCHEME_RE.test(raw)) return null;
|
|
1814
|
+
if (hasEncodedControl(raw)) return null;
|
|
1815
|
+
return raw;
|
|
1816
|
+
}
|
|
1817
|
+
function hrefScheme(raw) {
|
|
1818
|
+
return raw.match(SCHEME_RE)?.[0].toLowerCase() ?? null;
|
|
1819
|
+
}
|
|
1820
|
+
function parseSafeAbsoluteUrl(raw) {
|
|
1821
|
+
if (raw.includes("\\")) return null;
|
|
1822
|
+
try {
|
|
1823
|
+
return new URL(raw);
|
|
1824
|
+
} catch {
|
|
1825
|
+
return null;
|
|
1826
|
+
}
|
|
1827
|
+
}
|
|
1828
|
+
function sanitizeAbsoluteHref(raw, options = {}) {
|
|
1829
|
+
const url = parseSafeAbsoluteUrl(raw);
|
|
1830
|
+
if (!url) return null;
|
|
1831
|
+
if (url.protocol === "http:" || url.protocol === "https:") {
|
|
1832
|
+
if (!/^https?:\/\//i.test(raw)) return null;
|
|
1833
|
+
return options.preserveHttpHref ? raw : url.toString();
|
|
1834
|
+
}
|
|
1835
|
+
if (url.protocol === "mailto:") return raw;
|
|
1836
|
+
return null;
|
|
1837
|
+
}
|
|
1838
|
+
function isSafeNormalizedRelativeHref(raw) {
|
|
1839
|
+
if (raw.includes("\\")) return false;
|
|
1840
|
+
if (raw.startsWith("//")) return false;
|
|
1841
|
+
if (SCHEME_RE.test(raw)) return false;
|
|
1842
|
+
if (hasEncodedControl(raw)) return false;
|
|
1843
|
+
if (!SAFE_RELATIVE_HREF_RE.test(raw)) return false;
|
|
1844
|
+
return raw.startsWith("#") || raw.startsWith("?") || raw.startsWith("/") || raw.startsWith("./") || raw.startsWith("../") || /^[A-Za-z0-9._~-]/u.test(raw);
|
|
1845
|
+
}
|
|
1846
|
+
function isSafeRelativeHref(value) {
|
|
1847
|
+
const raw = normalizeRawHref(value);
|
|
1848
|
+
return raw != null && isSafeNormalizedRelativeHref(raw);
|
|
1849
|
+
}
|
|
1850
|
+
function sanitizeTerminalHref(value, options = {}) {
|
|
1851
|
+
const raw = normalizeRawHref(value);
|
|
1852
|
+
if (!raw) return null;
|
|
1853
|
+
const sanitized = sanitizeAbsoluteHref(raw, { preserveHttpHref: true });
|
|
1854
|
+
if (sanitized) return sanitized;
|
|
1855
|
+
if (options.allowFileUrls) {
|
|
1856
|
+
const url = parseSafeAbsoluteUrl(raw);
|
|
1857
|
+
if (url?.protocol === "file:") return url.toString();
|
|
1858
|
+
}
|
|
1859
|
+
return null;
|
|
1860
|
+
}
|
|
1861
|
+
function sanitizeDomHref(value, options = {}) {
|
|
1862
|
+
const raw = normalizeRawHref(value);
|
|
1863
|
+
if (!raw) return null;
|
|
1864
|
+
const scheme = hrefScheme(raw);
|
|
1865
|
+
if (!scheme) return options.allowRelative !== false && isSafeNormalizedRelativeHref(raw) ? raw : null;
|
|
1866
|
+
return sanitizeAbsoluteHref(raw);
|
|
1867
|
+
}
|
|
1868
|
+
|
|
1869
|
+
//#endregion
|
|
1870
|
+
export { TERMINAL_RENDER_PLANES, applyAnsiSgrStyle, createTerminal, getPlaneTerminal, getRootTerminal, hasEncodedControl, isSafeRelativeHref, parseAnsiSgr, resetPlaneRowsForRender, sanitizeDomHref, sanitizeTerminalHref, scrollPlaneRows };
|