@simon_he/vue-tui 1.0.0 → 1.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{TSelect-BwJJbuTt.js → TSelect-HzILuti9.js} +89 -40
- package/dist/{TTree-DK_DQBYm.js → TTree-ChOot2Bh.js} +108 -26
- package/dist/agent.cjs +673 -165
- package/dist/agent.js +2 -2
- package/dist/experimental.cjs +583 -121
- package/dist/experimental.js +1 -1
- package/dist/index.cjs +215 -76
- package/dist/index.js +2 -2
- package/dist/{tlog-theme-qPBt5rge.js → tlog-theme-CvLFNMwk.js} +539 -100
- package/dist/vue/components/TVirtualRows.d.ts +18 -0
- package/dist/vue/transcript/types.d.ts +4 -0
- package/dist/vue.cjs +215 -76
- package/dist/vue.js +2 -2
- package/package.json +6 -5
package/dist/experimental.cjs
CHANGED
|
@@ -2533,6 +2533,13 @@ function normalizeInt(value) {
|
|
|
2533
2533
|
const n = Math.floor(Number(value));
|
|
2534
2534
|
return Number.isFinite(n) ? n : 0;
|
|
2535
2535
|
}
|
|
2536
|
+
function normalizeChangedRange(range, count) {
|
|
2537
|
+
if (!range)
|
|
2538
|
+
return null;
|
|
2539
|
+
const start = clamp3(normalizeInt(range.start), 0, count);
|
|
2540
|
+
const end = clamp3(normalizeInt(range.end), start, count);
|
|
2541
|
+
return { start, end };
|
|
2542
|
+
}
|
|
2536
2543
|
function getWheelScrollInput2(e) {
|
|
2537
2544
|
const deltaY = Number(e.deltaY ?? 0);
|
|
2538
2545
|
const deltaMode = typeof e.deltaMode === "number" ? e.deltaMode : void 0;
|
|
@@ -2557,6 +2564,10 @@ var TVirtualRows = (0, import_vue10.defineComponent)({
|
|
|
2557
2564
|
zIndex: { type: Number, default: 0 },
|
|
2558
2565
|
itemCount: { type: Number, required: true },
|
|
2559
2566
|
itemVersion: { type: Number, required: true },
|
|
2567
|
+
itemChangedRange: {
|
|
2568
|
+
type: Function,
|
|
2569
|
+
default: void 0
|
|
2570
|
+
},
|
|
2560
2571
|
getItem: { type: Function, required: true },
|
|
2561
2572
|
paintItem: {
|
|
2562
2573
|
type: Function,
|
|
@@ -2756,6 +2767,23 @@ var TVirtualRows = (0, import_vue10.defineComponent)({
|
|
|
2756
2767
|
function invalidateSelf(priority = "normal") {
|
|
2757
2768
|
scheduler.invalidate({ priority, plane: plane.value, reason: "scroll" });
|
|
2758
2769
|
}
|
|
2770
|
+
function markScrollDamage(prevTop, nextTop, strategy = "auto") {
|
|
2771
|
+
const r = normalizedRect();
|
|
2772
|
+
const h14 = r.h;
|
|
2773
|
+
const delta = nextTop - prevTop;
|
|
2774
|
+
if (h14 <= 0 || !delta)
|
|
2775
|
+
return;
|
|
2776
|
+
const size = terminal.size();
|
|
2777
|
+
const ownsFullRows = Math.floor(r.x) === 0 && Math.floor(r.w) >= size.cols;
|
|
2778
|
+
const withinTerminalRows = r.y >= 0 && r.y + h14 <= size.rows;
|
|
2779
|
+
const canUseScrollPlane = strategy === "auto" && props.rowScrollMode === "unsafe-full-row" && rendererCapabilities.value.scrollOperations && ownsFullRows && withinTerminalRows && !isClipped() && Math.abs(delta) < h14 && !dirtyRowsHint?.length;
|
|
2780
|
+
if (canUseScrollPlane) {
|
|
2781
|
+
render.unsafeScrollPlaneRows(plane.value, r.y, r.y + h14, delta);
|
|
2782
|
+
markRowsDirty(exposedRowsForDelta2(r.y, h14, delta));
|
|
2783
|
+
} else {
|
|
2784
|
+
markViewportDirty();
|
|
2785
|
+
}
|
|
2786
|
+
}
|
|
2759
2787
|
function applyScrollTop(nextTop, options) {
|
|
2760
2788
|
const r = normalizedRect();
|
|
2761
2789
|
const h14 = r.h;
|
|
@@ -2776,16 +2804,7 @@ var TVirtualRows = (0, import_vue10.defineComponent)({
|
|
|
2776
2804
|
setCurrentScrollTop(clampedTop);
|
|
2777
2805
|
if (options?.emitUpdate !== false)
|
|
2778
2806
|
emit("update:scrollTop", clampedTop);
|
|
2779
|
-
|
|
2780
|
-
const ownsFullRows = Math.floor(r.x) === 0 && Math.floor(r.w) >= size.cols;
|
|
2781
|
-
const withinTerminalRows = r.y >= 0 && r.y + h14 <= size.rows;
|
|
2782
|
-
const canUseScrollPlane = (options?.strategy ?? "auto") === "auto" && props.rowScrollMode === "unsafe-full-row" && rendererCapabilities.value.scrollOperations && ownsFullRows && withinTerminalRows && !isClipped() && Math.abs(delta) < h14 && !dirtyRowsHint?.length;
|
|
2783
|
-
if (canUseScrollPlane) {
|
|
2784
|
-
render.unsafeScrollPlaneRows(plane.value, r.y, r.y + h14, delta);
|
|
2785
|
-
markRowsDirty(exposedRowsForDelta2(r.y, h14, delta));
|
|
2786
|
-
} else {
|
|
2787
|
-
markViewportDirty();
|
|
2788
|
-
}
|
|
2807
|
+
markScrollDamage(prevTop, clampedTop, options?.strategy);
|
|
2789
2808
|
if (options?.emitScroll)
|
|
2790
2809
|
emitScroll(clampedTop);
|
|
2791
2810
|
return true;
|
|
@@ -2852,8 +2871,11 @@ var TVirtualRows = (0, import_vue10.defineComponent)({
|
|
|
2852
2871
|
invalidateSelf("normal");
|
|
2853
2872
|
}
|
|
2854
2873
|
function invalidateRange(start, end) {
|
|
2874
|
+
markItemRangeDirty(start, end);
|
|
2875
|
+
}
|
|
2876
|
+
function markItemRangeDirty(start, end) {
|
|
2855
2877
|
if (!hasPaintableViewport())
|
|
2856
|
-
return;
|
|
2878
|
+
return false;
|
|
2857
2879
|
const r = normalizedRect();
|
|
2858
2880
|
const { y: clipY } = clipOffsets();
|
|
2859
2881
|
const top = currentScrollTop() + clipY;
|
|
@@ -2866,9 +2888,10 @@ var TVirtualRows = (0, import_vue10.defineComponent)({
|
|
|
2866
2888
|
rows.push(y);
|
|
2867
2889
|
}
|
|
2868
2890
|
if (!rows.length)
|
|
2869
|
-
return;
|
|
2891
|
+
return true;
|
|
2870
2892
|
markRowsDirty(rows);
|
|
2871
2893
|
invalidateSelf("normal");
|
|
2894
|
+
return true;
|
|
2872
2895
|
}
|
|
2873
2896
|
function invalidateIndex(index) {
|
|
2874
2897
|
const n = normalizeInt(index);
|
|
@@ -3108,8 +3131,9 @@ var TVirtualRows = (0, import_vue10.defineComponent)({
|
|
|
3108
3131
|
return;
|
|
3109
3132
|
}
|
|
3110
3133
|
cancelWheelScrollFrame();
|
|
3134
|
+
const prevTop = controlledScrollTop.value;
|
|
3111
3135
|
controlledScrollTop.value = nextTop;
|
|
3112
|
-
|
|
3136
|
+
markScrollDamage(prevTop, nextTop);
|
|
3113
3137
|
selection.refresh(pendingSelectionScrollFocusRemap ? { remapFocus: true } : void 0);
|
|
3114
3138
|
pendingSelectionScrollFocusRemap = false;
|
|
3115
3139
|
invalidateSelf("high");
|
|
@@ -3133,7 +3157,7 @@ var TVirtualRows = (0, import_vue10.defineComponent)({
|
|
|
3133
3157
|
() => absRect.value.w,
|
|
3134
3158
|
() => absRect.value.h
|
|
3135
3159
|
],
|
|
3136
|
-
() => {
|
|
3160
|
+
(next, prev) => {
|
|
3137
3161
|
resetWheelScrollState(wheelState);
|
|
3138
3162
|
const nextTop = clampScrollTop(currentScrollTop());
|
|
3139
3163
|
if (isScrollControlled()) {
|
|
@@ -3144,6 +3168,16 @@ var TVirtualRows = (0, import_vue10.defineComponent)({
|
|
|
3144
3168
|
} else {
|
|
3145
3169
|
setCurrentScrollTop(nextTop);
|
|
3146
3170
|
}
|
|
3171
|
+
const onlyItemVersionChanged = Boolean(
|
|
3172
|
+
prev && next[0] === prev[0] && next[1] !== prev[1] && next[2] === prev[2] && next[3] === prev[3] && next[4] === prev[4] && next[5] === prev[5] && next[6] === prev[6] && next[7] === prev[7] && next[8] === prev[8] && next[9] === prev[9]
|
|
3173
|
+
);
|
|
3174
|
+
if (onlyItemVersionChanged) {
|
|
3175
|
+
const changedRange = normalizeChangedRange(props.itemChangedRange?.(), itemCount.value);
|
|
3176
|
+
if (changedRange) {
|
|
3177
|
+
markItemRangeDirty(changedRange.start, changedRange.end);
|
|
3178
|
+
return;
|
|
3179
|
+
}
|
|
3180
|
+
}
|
|
3147
3181
|
markViewportDirty();
|
|
3148
3182
|
invalidateSelf("normal");
|
|
3149
3183
|
},
|
|
@@ -3171,7 +3205,6 @@ var TVirtualRows = (0, import_vue10.defineComponent)({
|
|
|
3171
3205
|
absRect.value,
|
|
3172
3206
|
fullRect.value,
|
|
3173
3207
|
itemCount.value,
|
|
3174
|
-
props.itemVersion,
|
|
3175
3208
|
props.getItem,
|
|
3176
3209
|
props.paintItem,
|
|
3177
3210
|
props.selectionSpanText,
|
|
@@ -3260,8 +3293,11 @@ var EMPTY_LAYOUT = Object.freeze({
|
|
|
3260
3293
|
visualRows: Object.freeze([]),
|
|
3261
3294
|
rowStarts: /* @__PURE__ */ new Map(),
|
|
3262
3295
|
rowEnds: /* @__PURE__ */ new Map(),
|
|
3263
|
-
regions: Object.freeze([])
|
|
3296
|
+
regions: Object.freeze([]),
|
|
3297
|
+
fixedRows: false,
|
|
3298
|
+
rowCount: 0
|
|
3264
3299
|
});
|
|
3300
|
+
var MAX_KEYED_ROW_LAYOUT_CACHE_ENTRIES = 2048;
|
|
3265
3301
|
function clamp4(n, min, max) {
|
|
3266
3302
|
return Math.max(min, Math.min(max, n));
|
|
3267
3303
|
}
|
|
@@ -3269,6 +3305,13 @@ function normalizeInt2(value) {
|
|
|
3269
3305
|
const n = Math.floor(Number(value));
|
|
3270
3306
|
return Number.isFinite(n) ? n : 0;
|
|
3271
3307
|
}
|
|
3308
|
+
function normalizedChangedRange(range, count) {
|
|
3309
|
+
if (!range)
|
|
3310
|
+
return null;
|
|
3311
|
+
const start = clamp4(normalizeInt2(range.start), 0, count);
|
|
3312
|
+
const end = clamp4(normalizeInt2(range.end), start, count);
|
|
3313
|
+
return { start, end };
|
|
3314
|
+
}
|
|
3272
3315
|
function sourceSegmentsForRegion(row) {
|
|
3273
3316
|
if (row.kind === "message")
|
|
3274
3317
|
return row.segments;
|
|
@@ -3305,8 +3348,27 @@ function rowHasRegionId(row, rowKey, id) {
|
|
|
3305
3348
|
}
|
|
3306
3349
|
return false;
|
|
3307
3350
|
}
|
|
3308
|
-
function
|
|
3309
|
-
|
|
3351
|
+
function cachedLayoutHasRegionId(entry, id) {
|
|
3352
|
+
if (!entry || !id)
|
|
3353
|
+
return false;
|
|
3354
|
+
for (const visualRow of entry.visualRows) {
|
|
3355
|
+
if (visualRow.hitRegions.some((region) => region.id === id))
|
|
3356
|
+
return true;
|
|
3357
|
+
}
|
|
3358
|
+
return false;
|
|
3359
|
+
}
|
|
3360
|
+
function rowLayoutIdentityKey(rowKey, rowVersion) {
|
|
3361
|
+
return JSON.stringify([rowKey, rowVersion]);
|
|
3362
|
+
}
|
|
3363
|
+
function reindexVisualRows(rows, rowIndex) {
|
|
3364
|
+
return rows.map((visualRow) => ({
|
|
3365
|
+
...visualRow,
|
|
3366
|
+
rowIndex,
|
|
3367
|
+
hitRegions: visualRow.hitRegions.map((region) => ({ ...region, rowIndex }))
|
|
3368
|
+
}));
|
|
3369
|
+
}
|
|
3370
|
+
function sameCachedLayout(entry, next, matchRowIndex = true) {
|
|
3371
|
+
return Boolean(entry) && (next.usesSourceRowVersion || entry.version === next.version) && entry.rowVersion === next.rowVersion && entry.usesSourceRowVersion === next.usesSourceRowVersion && (next.usesSourceRowVersion || entry.row === next.row) && (!matchRowIndex || entry.rowIndex === next.rowIndex) && entry.rowKey === next.rowKey && entry.width === next.width && entry.wrap === next.wrap && entry.baseStyle === next.baseStyle && entry.hoverStyle === next.hoverStyle && entry.focusStyle === next.focusStyle && entry.hoverRegionId === next.hoverRegionId && entry.focusedRegionId === next.focusedRegionId;
|
|
3310
3372
|
}
|
|
3311
3373
|
var TTranscriptView = (0, import_vue11.defineComponent)({
|
|
3312
3374
|
name: "TTranscriptView",
|
|
@@ -3356,6 +3418,10 @@ var TTranscriptView = (0, import_vue11.defineComponent)({
|
|
|
3356
3418
|
const hoveredRegion = (0, import_vue11.ref)(null);
|
|
3357
3419
|
const focusedRegion = (0, import_vue11.ref)(null);
|
|
3358
3420
|
const rowLayoutCache = /* @__PURE__ */ new Map();
|
|
3421
|
+
const keyedRowLayoutCache = /* @__PURE__ */ new Map();
|
|
3422
|
+
let previousWrappedLayout = null;
|
|
3423
|
+
let previousWrappedDeps = null;
|
|
3424
|
+
let canUseWrappedChangedRangeRepaint = false;
|
|
3359
3425
|
let warnedLargeFlattenedRows = false;
|
|
3360
3426
|
function isScrollControlled() {
|
|
3361
3427
|
return Object.prototype.hasOwnProperty.call(instance?.vnode.props ?? {}, "scrollTop");
|
|
@@ -3363,14 +3429,181 @@ var TTranscriptView = (0, import_vue11.defineComponent)({
|
|
|
3363
3429
|
function currentScrollTop() {
|
|
3364
3430
|
return normalizeInt2(isScrollControlled() ? props.scrollTop : innerScrollTop.value);
|
|
3365
3431
|
}
|
|
3432
|
+
function currentScrollTopForRowCount(count) {
|
|
3433
|
+
const viewportRows = Math.max(0, normalizeInt2(props.h));
|
|
3434
|
+
const maxTop = Math.max(0, count - viewportRows);
|
|
3435
|
+
return clamp4(currentScrollTop(), 0, maxTop);
|
|
3436
|
+
}
|
|
3437
|
+
function rememberKeyedRowLayout(entry) {
|
|
3438
|
+
if (!entry.usesSourceRowVersion)
|
|
3439
|
+
return;
|
|
3440
|
+
keyedRowLayoutCache.set(rowLayoutIdentityKey(entry.rowKey, entry.rowVersion), entry);
|
|
3441
|
+
if (keyedRowLayoutCache.size <= MAX_KEYED_ROW_LAYOUT_CACHE_ENTRIES)
|
|
3442
|
+
return;
|
|
3443
|
+
const first = keyedRowLayoutCache.keys().next().value;
|
|
3444
|
+
if (first != null)
|
|
3445
|
+
keyedRowLayoutCache.delete(first);
|
|
3446
|
+
}
|
|
3447
|
+
function layoutSourceRow(rowIndex, options) {
|
|
3448
|
+
const sourceRowVersion = props.source.getRowVersion?.(rowIndex);
|
|
3449
|
+
let cached = rowLayoutCache.get(rowIndex);
|
|
3450
|
+
const usesSourceRowVersion = sourceRowVersion != null;
|
|
3451
|
+
let row = cached?.row;
|
|
3452
|
+
let rowKey = cached?.rowKey;
|
|
3453
|
+
let canUseCachedRow = false;
|
|
3454
|
+
if (usesSourceRowVersion && cached?.usesSourceRowVersion && cached.rowVersion === sourceRowVersion) {
|
|
3455
|
+
if (props.source.getRowKey) {
|
|
3456
|
+
rowKey = props.source.getRowKey(rowIndex);
|
|
3457
|
+
canUseCachedRow = rowKey === cached.rowKey;
|
|
3458
|
+
} else {
|
|
3459
|
+
rowKey = cached.rowKey;
|
|
3460
|
+
canUseCachedRow = true;
|
|
3461
|
+
}
|
|
3462
|
+
}
|
|
3463
|
+
if (!canUseCachedRow && usesSourceRowVersion && props.source.getRowKey) {
|
|
3464
|
+
rowKey = props.source.getRowKey(rowIndex);
|
|
3465
|
+
cached = keyedRowLayoutCache.get(rowLayoutIdentityKey(rowKey, sourceRowVersion));
|
|
3466
|
+
if (cached) {
|
|
3467
|
+
row = cached.row;
|
|
3468
|
+
canUseCachedRow = true;
|
|
3469
|
+
}
|
|
3470
|
+
}
|
|
3471
|
+
if (!canUseCachedRow || row == null || rowKey == null) {
|
|
3472
|
+
row = props.source.getRow(rowIndex);
|
|
3473
|
+
rowKey = props.source.getRowKey?.(rowIndex) ?? row.key;
|
|
3474
|
+
canUseCachedRow = false;
|
|
3475
|
+
}
|
|
3476
|
+
const nextHoverRegionId = canUseCachedRow ? cachedLayoutHasRegionId(cached, options.hoverRegionId) ? options.hoverRegionId : null : rowHasRegionId(row, rowKey, options.hoverRegionId) ? options.hoverRegionId : null;
|
|
3477
|
+
const nextFocusedRegionId = canUseCachedRow ? cachedLayoutHasRegionId(cached, options.focusedRegionId) ? options.focusedRegionId : null : rowHasRegionId(row, rowKey, options.focusedRegionId) ? options.focusedRegionId : null;
|
|
3478
|
+
const cacheKey = {
|
|
3479
|
+
version: props.version,
|
|
3480
|
+
rowVersion: sourceRowVersion ?? props.version,
|
|
3481
|
+
usesSourceRowVersion,
|
|
3482
|
+
row,
|
|
3483
|
+
rowIndex,
|
|
3484
|
+
rowKey,
|
|
3485
|
+
width: options.width,
|
|
3486
|
+
wrap: props.wrap,
|
|
3487
|
+
baseStyle: options.baseStyle,
|
|
3488
|
+
hoverStyle: props.hoverStyle,
|
|
3489
|
+
focusStyle: props.focusStyle,
|
|
3490
|
+
hoverRegionId: nextHoverRegionId,
|
|
3491
|
+
focusedRegionId: nextFocusedRegionId
|
|
3492
|
+
};
|
|
3493
|
+
const cacheMatches = sameCachedLayout(cached, cacheKey);
|
|
3494
|
+
const reindexableCacheMatches = !cacheMatches && canUseCachedRow && sameCachedLayout(cached, cacheKey, false);
|
|
3495
|
+
const rows = cacheMatches ? cached.visualRows : reindexableCacheMatches ? reindexVisualRows(cached.visualRows, rowIndex) : layoutTranscriptRow({
|
|
3496
|
+
row,
|
|
3497
|
+
rowIndex,
|
|
3498
|
+
rowKey,
|
|
3499
|
+
width: options.width,
|
|
3500
|
+
baseStyle: options.baseStyle,
|
|
3501
|
+
hoverRegionId: nextHoverRegionId,
|
|
3502
|
+
focusedRegionId: nextFocusedRegionId,
|
|
3503
|
+
hoverStyle: props.hoverStyle,
|
|
3504
|
+
focusStyle: props.focusStyle,
|
|
3505
|
+
wrap: props.wrap
|
|
3506
|
+
});
|
|
3507
|
+
if (rows !== cached?.visualRows) {
|
|
3508
|
+
const entry = { ...cacheKey, visualRows: rows };
|
|
3509
|
+
rowLayoutCache.set(rowIndex, entry);
|
|
3510
|
+
rememberKeyedRowLayout(entry);
|
|
3511
|
+
}
|
|
3512
|
+
return { rows, cacheHit: cacheMatches || reindexableCacheMatches };
|
|
3513
|
+
}
|
|
3514
|
+
function pruneRowLayoutCache(count) {
|
|
3515
|
+
for (const rowIndex of rowLayoutCache.keys()) {
|
|
3516
|
+
if (rowIndex >= count)
|
|
3517
|
+
rowLayoutCache.delete(rowIndex);
|
|
3518
|
+
}
|
|
3519
|
+
}
|
|
3520
|
+
function sameWrappedDeps(a, b) {
|
|
3521
|
+
return Boolean(a) && a.width === b.width && a.baseStyle === b.baseStyle && a.hoverStyle === b.hoverStyle && a.focusStyle === b.focusStyle && a.hoverRegionId === b.hoverRegionId && a.focusedRegionId === b.focusedRegionId;
|
|
3522
|
+
}
|
|
3523
|
+
function visibleRegionsForVisualRows(visualRows) {
|
|
3524
|
+
const top = clamp4(currentScrollTop(), 0, visualRows.length);
|
|
3525
|
+
const bottom = Math.min(visualRows.length, top + Math.max(0, normalizeInt2(props.h)));
|
|
3526
|
+
const regions = [];
|
|
3527
|
+
for (let index = top; index < bottom; index++) {
|
|
3528
|
+
regions.push(...visualRows[index]?.hitRegions ?? []);
|
|
3529
|
+
}
|
|
3530
|
+
return regions;
|
|
3531
|
+
}
|
|
3532
|
+
function tryUpdateWrappedLayoutFromChangedRange(count, changedRange, deps) {
|
|
3533
|
+
const previous = previousWrappedLayout;
|
|
3534
|
+
if (!previous || previous.fixedRows || previous.rowCount !== count)
|
|
3535
|
+
return null;
|
|
3536
|
+
if (!changedRange || !sameWrappedDeps(previousWrappedDeps, deps))
|
|
3537
|
+
return null;
|
|
3538
|
+
const changedCount = changedRange.end - changedRange.start;
|
|
3539
|
+
if (changedCount <= 0) {
|
|
3540
|
+
canUseWrappedChangedRangeRepaint = true;
|
|
3541
|
+
return {
|
|
3542
|
+
state: { ...previous, regions: visibleRegionsForVisualRows(previous.visualRows) },
|
|
3543
|
+
cacheHit: count,
|
|
3544
|
+
cacheMiss: 0
|
|
3545
|
+
};
|
|
3546
|
+
}
|
|
3547
|
+
const oldVisualStart = previous.rowStarts.get(changedRange.start);
|
|
3548
|
+
const oldVisualEnd = previous.rowEnds.get(changedRange.end - 1);
|
|
3549
|
+
if (oldVisualStart == null || oldVisualEnd == null)
|
|
3550
|
+
return null;
|
|
3551
|
+
const nextRows = [];
|
|
3552
|
+
const changedRowHeights = [];
|
|
3553
|
+
let cacheHit = count - changedCount;
|
|
3554
|
+
let cacheMiss = 0;
|
|
3555
|
+
for (let rowIndex = changedRange.start; rowIndex < changedRange.end; rowIndex++) {
|
|
3556
|
+
const result = layoutSourceRow(rowIndex, {
|
|
3557
|
+
width: deps.width,
|
|
3558
|
+
baseStyle: deps.baseStyle,
|
|
3559
|
+
hoverRegionId: deps.hoverRegionId,
|
|
3560
|
+
focusedRegionId: deps.focusedRegionId
|
|
3561
|
+
});
|
|
3562
|
+
if (result.cacheHit)
|
|
3563
|
+
cacheHit++;
|
|
3564
|
+
else
|
|
3565
|
+
cacheMiss++;
|
|
3566
|
+
changedRowHeights.push(result.rows.length);
|
|
3567
|
+
nextRows.push(...result.rows);
|
|
3568
|
+
}
|
|
3569
|
+
if (nextRows.length !== oldVisualEnd - oldVisualStart)
|
|
3570
|
+
return null;
|
|
3571
|
+
canUseWrappedChangedRangeRepaint = true;
|
|
3572
|
+
const visualRows = previous.visualRows;
|
|
3573
|
+
for (let index = 0; index < nextRows.length; index++) {
|
|
3574
|
+
visualRows[oldVisualStart + index] = nextRows[index];
|
|
3575
|
+
}
|
|
3576
|
+
const rowStarts = previous.rowStarts;
|
|
3577
|
+
const rowEnds = previous.rowEnds;
|
|
3578
|
+
let visualCursor = oldVisualStart;
|
|
3579
|
+
for (let rowIndex = changedRange.start, offset = 0; rowIndex < changedRange.end; rowIndex++, offset++) {
|
|
3580
|
+
rowStarts.set(rowIndex, visualCursor);
|
|
3581
|
+
visualCursor += changedRowHeights[offset] ?? 0;
|
|
3582
|
+
rowEnds.set(rowIndex, visualCursor);
|
|
3583
|
+
}
|
|
3584
|
+
const state = {
|
|
3585
|
+
visualRows,
|
|
3586
|
+
rowStarts,
|
|
3587
|
+
rowEnds,
|
|
3588
|
+
regions: visibleRegionsForVisualRows(visualRows),
|
|
3589
|
+
fixedRows: false,
|
|
3590
|
+
rowCount: count
|
|
3591
|
+
};
|
|
3592
|
+
previousWrappedLayout = state;
|
|
3593
|
+
return { state, cacheHit, cacheMiss };
|
|
3594
|
+
}
|
|
3366
3595
|
const layoutState = (0, import_vue11.computed)(() => {
|
|
3367
3596
|
void props.version;
|
|
3597
|
+
canUseWrappedChangedRangeRepaint = false;
|
|
3368
3598
|
const perfEnabled = observability.framePerf.enabled.value;
|
|
3369
3599
|
const perfStartedAt = perfEnabled ? framePerfNow() : 0;
|
|
3370
3600
|
const width = Math.max(1, Math.floor(props.w));
|
|
3371
3601
|
const count = Math.max(0, normalizeInt2(props.source.rowCount()));
|
|
3372
3602
|
if (!count) {
|
|
3373
3603
|
rowLayoutCache.clear();
|
|
3604
|
+
keyedRowLayoutCache.clear();
|
|
3605
|
+
previousWrappedLayout = null;
|
|
3606
|
+
previousWrappedDeps = null;
|
|
3374
3607
|
if (perfEnabled) {
|
|
3375
3608
|
observability.framePerf.recordComponent({
|
|
3376
3609
|
name: "TTranscriptView",
|
|
@@ -3387,7 +3620,10 @@ var TTranscriptView = (0, import_vue11.defineComponent)({
|
|
|
3387
3620
|
}
|
|
3388
3621
|
return EMPTY_LAYOUT;
|
|
3389
3622
|
}
|
|
3623
|
+
const fixedRows = props.wrap === false;
|
|
3390
3624
|
const visualRows = [];
|
|
3625
|
+
if (fixedRows)
|
|
3626
|
+
visualRows.length = count;
|
|
3391
3627
|
const rowStarts = /* @__PURE__ */ new Map();
|
|
3392
3628
|
const rowEnds = /* @__PURE__ */ new Map();
|
|
3393
3629
|
const regions = [];
|
|
@@ -3396,59 +3632,81 @@ var TTranscriptView = (0, import_vue11.defineComponent)({
|
|
|
3396
3632
|
const focusedRegionId = focusedRegion.value?.id ?? null;
|
|
3397
3633
|
let cacheHit = 0;
|
|
3398
3634
|
let cacheMiss = 0;
|
|
3399
|
-
|
|
3400
|
-
|
|
3401
|
-
|
|
3402
|
-
|
|
3403
|
-
|
|
3404
|
-
|
|
3405
|
-
|
|
3406
|
-
|
|
3407
|
-
|
|
3408
|
-
|
|
3409
|
-
|
|
3410
|
-
|
|
3411
|
-
|
|
3412
|
-
|
|
3413
|
-
|
|
3414
|
-
|
|
3415
|
-
|
|
3416
|
-
|
|
3417
|
-
|
|
3418
|
-
|
|
3419
|
-
|
|
3420
|
-
|
|
3421
|
-
|
|
3422
|
-
|
|
3423
|
-
|
|
3424
|
-
|
|
3425
|
-
|
|
3426
|
-
|
|
3427
|
-
|
|
3428
|
-
row
|
|
3429
|
-
|
|
3430
|
-
|
|
3431
|
-
|
|
3432
|
-
|
|
3433
|
-
|
|
3434
|
-
|
|
3435
|
-
|
|
3436
|
-
|
|
3437
|
-
|
|
3438
|
-
|
|
3439
|
-
|
|
3440
|
-
|
|
3441
|
-
|
|
3442
|
-
|
|
3443
|
-
|
|
3635
|
+
const sourceChangedRange = normalizedChangedRange(props.source.getChangedRange?.(), count);
|
|
3636
|
+
const wrappedDeps = {
|
|
3637
|
+
width,
|
|
3638
|
+
baseStyle,
|
|
3639
|
+
hoverStyle: props.hoverStyle,
|
|
3640
|
+
focusStyle: props.focusStyle,
|
|
3641
|
+
hoverRegionId,
|
|
3642
|
+
focusedRegionId
|
|
3643
|
+
};
|
|
3644
|
+
if (fixedRows) {
|
|
3645
|
+
previousWrappedLayout = null;
|
|
3646
|
+
previousWrappedDeps = null;
|
|
3647
|
+
const top = currentScrollTopForRowCount(count);
|
|
3648
|
+
const bottom = Math.min(count, top + Math.max(0, normalizeInt2(props.h)));
|
|
3649
|
+
for (let rowIndex = top; rowIndex < bottom; rowIndex++) {
|
|
3650
|
+
rowStarts.set(rowIndex, rowIndex);
|
|
3651
|
+
rowEnds.set(rowIndex, rowIndex + 1);
|
|
3652
|
+
const result = layoutSourceRow(rowIndex, {
|
|
3653
|
+
width,
|
|
3654
|
+
baseStyle,
|
|
3655
|
+
hoverRegionId,
|
|
3656
|
+
focusedRegionId
|
|
3657
|
+
});
|
|
3658
|
+
if (result.cacheHit)
|
|
3659
|
+
cacheHit++;
|
|
3660
|
+
else
|
|
3661
|
+
cacheMiss++;
|
|
3662
|
+
const row = result.rows[0];
|
|
3663
|
+
visualRows[rowIndex] = row;
|
|
3664
|
+
regions.push(...row.hitRegions);
|
|
3665
|
+
}
|
|
3666
|
+
} else {
|
|
3667
|
+
const incremental = tryUpdateWrappedLayoutFromChangedRange(
|
|
3668
|
+
count,
|
|
3669
|
+
sourceChangedRange,
|
|
3670
|
+
wrappedDeps
|
|
3671
|
+
);
|
|
3672
|
+
if (incremental) {
|
|
3673
|
+
if (perfEnabled) {
|
|
3674
|
+
observability.framePerf.recordComponent({
|
|
3675
|
+
name: "TTranscriptView",
|
|
3676
|
+
id: instance?.uid == null ? void 0 : String(instance.uid),
|
|
3677
|
+
phase: "layout",
|
|
3678
|
+
durationMs: framePerfNow() - perfStartedAt,
|
|
3679
|
+
itemCount: count,
|
|
3680
|
+
renderedCount: incremental.state.visualRows.length,
|
|
3681
|
+
cacheHit: incremental.cacheHit,
|
|
3682
|
+
cacheMiss: incremental.cacheMiss,
|
|
3683
|
+
width,
|
|
3684
|
+
version: props.version
|
|
3685
|
+
});
|
|
3686
|
+
}
|
|
3687
|
+
return incremental.state;
|
|
3688
|
+
}
|
|
3689
|
+
for (let rowIndex = 0; rowIndex < count; rowIndex++) {
|
|
3690
|
+
rowStarts.set(rowIndex, visualRows.length);
|
|
3691
|
+
const result = layoutSourceRow(rowIndex, {
|
|
3692
|
+
width,
|
|
3693
|
+
baseStyle,
|
|
3694
|
+
hoverRegionId,
|
|
3695
|
+
focusedRegionId
|
|
3696
|
+
});
|
|
3697
|
+
if (result.cacheHit)
|
|
3698
|
+
cacheHit++;
|
|
3699
|
+
else
|
|
3700
|
+
cacheMiss++;
|
|
3701
|
+
for (const visualRow of result.rows) {
|
|
3702
|
+
visualRows.push(visualRow);
|
|
3703
|
+
regions.push(...visualRow.hitRegions);
|
|
3704
|
+
}
|
|
3705
|
+
rowEnds.set(rowIndex, visualRows.length);
|
|
3444
3706
|
}
|
|
3445
|
-
rowEnds.set(rowIndex, visualRows.length);
|
|
3446
|
-
}
|
|
3447
|
-
for (const rowIndex of rowLayoutCache.keys()) {
|
|
3448
|
-
if (rowIndex >= count)
|
|
3449
|
-
rowLayoutCache.delete(rowIndex);
|
|
3450
3707
|
}
|
|
3451
|
-
|
|
3708
|
+
pruneRowLayoutCache(count);
|
|
3709
|
+
if (!warnedLargeFlattenedRows && !fixedRows && globalThis.__VT_DEBUG_PERF__ && visualRows.length > 5e3) {
|
|
3452
3710
|
warnedLargeFlattenedRows = true;
|
|
3453
3711
|
console.warn(
|
|
3454
3712
|
"[vue-tui] TTranscriptView flattens all transcript rows; use TLogView or windowed source for large retained output."
|
|
@@ -3461,14 +3719,22 @@ var TTranscriptView = (0, import_vue11.defineComponent)({
|
|
|
3461
3719
|
phase: "layout",
|
|
3462
3720
|
durationMs: framePerfNow() - perfStartedAt,
|
|
3463
3721
|
itemCount: count,
|
|
3464
|
-
renderedCount: visualRows.length,
|
|
3722
|
+
renderedCount: fixedRows ? cacheHit + cacheMiss : visualRows.length,
|
|
3465
3723
|
cacheHit,
|
|
3466
3724
|
cacheMiss,
|
|
3467
3725
|
width,
|
|
3468
3726
|
version: props.version
|
|
3469
3727
|
});
|
|
3470
3728
|
}
|
|
3471
|
-
|
|
3729
|
+
const state = { visualRows, rowStarts, rowEnds, regions, fixedRows, rowCount: count };
|
|
3730
|
+
if (fixedRows) {
|
|
3731
|
+
previousWrappedLayout = null;
|
|
3732
|
+
previousWrappedDeps = null;
|
|
3733
|
+
} else {
|
|
3734
|
+
previousWrappedLayout = state;
|
|
3735
|
+
previousWrappedDeps = wrappedDeps;
|
|
3736
|
+
}
|
|
3737
|
+
return state;
|
|
3472
3738
|
});
|
|
3473
3739
|
const maxScrollTop = (0, import_vue11.computed)(
|
|
3474
3740
|
() => Math.max(0, layoutState.value.visualRows.length - Math.max(0, normalizeInt2(props.h)))
|
|
@@ -3517,8 +3783,11 @@ var TTranscriptView = (0, import_vue11.defineComponent)({
|
|
|
3517
3783
|
return [];
|
|
3518
3784
|
const rows = layoutState.value.visualRows;
|
|
3519
3785
|
const indexes = [];
|
|
3520
|
-
|
|
3521
|
-
|
|
3786
|
+
const top = layoutState.value.fixedRows ? clamp4(currentScrollTop(), 0, rows.length) : 0;
|
|
3787
|
+
const bottom = layoutState.value.fixedRows ? Math.min(rows.length, top + Math.max(0, normalizeInt2(props.h))) : rows.length;
|
|
3788
|
+
for (let i = top; i < bottom; i++) {
|
|
3789
|
+
const row = getVisualRow(i);
|
|
3790
|
+
if (row?.hitRegions.some((candidate) => candidate.id === region.id))
|
|
3522
3791
|
indexes.push(i);
|
|
3523
3792
|
}
|
|
3524
3793
|
return indexes;
|
|
@@ -3551,7 +3820,7 @@ var TTranscriptView = (0, import_vue11.defineComponent)({
|
|
|
3551
3820
|
const seen = /* @__PURE__ */ new Set();
|
|
3552
3821
|
const regions = [];
|
|
3553
3822
|
for (let i = top; i < bottom; i++) {
|
|
3554
|
-
for (const region of
|
|
3823
|
+
for (const region of getVisualRow(i)?.hitRegions ?? []) {
|
|
3555
3824
|
if (seen.has(region.id))
|
|
3556
3825
|
continue;
|
|
3557
3826
|
seen.add(region.id);
|
|
@@ -3565,7 +3834,7 @@ var TTranscriptView = (0, import_vue11.defineComponent)({
|
|
|
3565
3834
|
const top = clamp4(currentScrollTop(), 0, rows.length);
|
|
3566
3835
|
const bottom = Math.min(rows.length, top + Math.max(0, normalizeInt2(props.h)));
|
|
3567
3836
|
for (let i = top; i < bottom; i++) {
|
|
3568
|
-
if (
|
|
3837
|
+
if (getVisualRow(i)?.hitRegions.some((region) => region.id === id))
|
|
3569
3838
|
return true;
|
|
3570
3839
|
}
|
|
3571
3840
|
return false;
|
|
@@ -3632,8 +3901,8 @@ var TTranscriptView = (0, import_vue11.defineComponent)({
|
|
|
3632
3901
|
}
|
|
3633
3902
|
function scrollToRow(index, options) {
|
|
3634
3903
|
const rowIndex = clamp4(normalizeInt2(index), 0, Math.max(0, props.source.rowCount() - 1));
|
|
3635
|
-
const visualIndex = layoutState.value.rowStarts.get(rowIndex) ?? 0;
|
|
3636
|
-
const rowEnd = layoutState.value.rowEnds.get(rowIndex) ?? visualIndex + 1;
|
|
3904
|
+
const visualIndex = layoutState.value.fixedRows ? rowIndex : layoutState.value.rowStarts.get(rowIndex) ?? 0;
|
|
3905
|
+
const rowEnd = layoutState.value.fixedRows ? rowIndex + 1 : layoutState.value.rowEnds.get(rowIndex) ?? visualIndex + 1;
|
|
3637
3906
|
const viewportRows = Math.max(1, normalizeInt2(props.h));
|
|
3638
3907
|
const rowHeight = Math.max(1, rowEnd - visualIndex);
|
|
3639
3908
|
let top = visualIndex;
|
|
@@ -3646,8 +3915,8 @@ var TTranscriptView = (0, import_vue11.defineComponent)({
|
|
|
3646
3915
|
setScrollTop(top);
|
|
3647
3916
|
}
|
|
3648
3917
|
function invalidateRow(index) {
|
|
3649
|
-
const start = layoutState.value.rowStarts.get(index);
|
|
3650
|
-
const end = layoutState.value.rowEnds.get(index);
|
|
3918
|
+
const start = layoutState.value.fixedRows ? index : layoutState.value.rowStarts.get(index);
|
|
3919
|
+
const end = layoutState.value.fixedRows ? index + 1 : layoutState.value.rowEnds.get(index);
|
|
3651
3920
|
if (start == null || end == null)
|
|
3652
3921
|
return;
|
|
3653
3922
|
rowsRef.value?.invalidateRange(start, end);
|
|
@@ -3655,12 +3924,27 @@ var TTranscriptView = (0, import_vue11.defineComponent)({
|
|
|
3655
3924
|
function invalidateRange(start, end) {
|
|
3656
3925
|
const first = clamp4(normalizeInt2(start), 0, props.source.rowCount());
|
|
3657
3926
|
const last = clamp4(normalizeInt2(end), first, props.source.rowCount());
|
|
3658
|
-
const visualStart = layoutState.value.rowStarts.get(first);
|
|
3659
|
-
const visualEnd = layoutState.value.rowEnds.get(last - 1);
|
|
3927
|
+
const visualStart = layoutState.value.fixedRows ? first : layoutState.value.rowStarts.get(first);
|
|
3928
|
+
const visualEnd = layoutState.value.fixedRows ? last : layoutState.value.rowEnds.get(last - 1);
|
|
3660
3929
|
if (visualStart == null || visualEnd == null)
|
|
3661
3930
|
return;
|
|
3662
3931
|
rowsRef.value?.invalidateRange(visualStart, visualEnd);
|
|
3663
3932
|
}
|
|
3933
|
+
function virtualRowsChangedRange() {
|
|
3934
|
+
const state = layoutState.value;
|
|
3935
|
+
const changedRange = normalizedChangedRange(props.source.getChangedRange?.(), state.rowCount);
|
|
3936
|
+
if (!changedRange)
|
|
3937
|
+
return null;
|
|
3938
|
+
if (state.fixedRows || changedRange.end <= changedRange.start)
|
|
3939
|
+
return changedRange;
|
|
3940
|
+
if (!canUseWrappedChangedRangeRepaint)
|
|
3941
|
+
return null;
|
|
3942
|
+
const visualStart = state.rowStarts.get(changedRange.start);
|
|
3943
|
+
const visualEnd = state.rowEnds.get(changedRange.end - 1);
|
|
3944
|
+
if (visualStart == null || visualEnd == null)
|
|
3945
|
+
return null;
|
|
3946
|
+
return { start: visualStart, end: visualEnd };
|
|
3947
|
+
}
|
|
3664
3948
|
expose({
|
|
3665
3949
|
scrollToBottom,
|
|
3666
3950
|
scrollToTop,
|
|
@@ -3764,7 +4048,22 @@ var TTranscriptView = (0, import_vue11.defineComponent)({
|
|
|
3764
4048
|
return text;
|
|
3765
4049
|
}
|
|
3766
4050
|
function getVisualRow(index) {
|
|
3767
|
-
|
|
4051
|
+
const state = layoutState.value;
|
|
4052
|
+
const cached = state.visualRows[index];
|
|
4053
|
+
if (cached || !state.fixedRows)
|
|
4054
|
+
return cached;
|
|
4055
|
+
if (index < 0 || index >= state.visualRows.length)
|
|
4056
|
+
return void 0;
|
|
4057
|
+
const result = layoutSourceRow(index, {
|
|
4058
|
+
width: Math.max(1, Math.floor(props.w)),
|
|
4059
|
+
baseStyle: props.style ?? defaultStyle.value,
|
|
4060
|
+
hoverRegionId: hoveredRegion.value?.id ?? null,
|
|
4061
|
+
focusedRegionId: focusedRegion.value?.id ?? null
|
|
4062
|
+
});
|
|
4063
|
+
const row = result.rows[0];
|
|
4064
|
+
if (row)
|
|
4065
|
+
state.visualRows[index] = row;
|
|
4066
|
+
return row;
|
|
3768
4067
|
}
|
|
3769
4068
|
function selectionTextForVisualRow(visualRow) {
|
|
3770
4069
|
if (!visualRow)
|
|
@@ -3792,6 +4091,7 @@ var TTranscriptView = (0, import_vue11.defineComponent)({
|
|
|
3792
4091
|
zIndex: props.zIndex,
|
|
3793
4092
|
itemCount: layoutState.value.visualRows.length,
|
|
3794
4093
|
itemVersion: props.version,
|
|
4094
|
+
itemChangedRange: virtualRowsChangedRange,
|
|
3795
4095
|
getItem: getVisualRow,
|
|
3796
4096
|
paintItem: paintVisualRow,
|
|
3797
4097
|
renderItemNodes: renderVisualRowNodes,
|
|
@@ -4675,6 +4975,20 @@ function wrapStyledSegmentsByCells(segments, width) {
|
|
|
4675
4975
|
rowCells += cells;
|
|
4676
4976
|
};
|
|
4677
4977
|
for (const seg of segments) {
|
|
4978
|
+
const cells = textCellWidth(seg.text);
|
|
4979
|
+
if (cells === seg.text.length) {
|
|
4980
|
+
for (let i = 0; i < seg.text.length; ) {
|
|
4981
|
+
if (rowCells >= width)
|
|
4982
|
+
openRow();
|
|
4983
|
+
const take = Math.min(width - rowCells, seg.text.length - i);
|
|
4984
|
+
if (take <= 0)
|
|
4985
|
+
break;
|
|
4986
|
+
row.push({ text: seg.text.slice(i, i + take), cells: take, style: seg.style });
|
|
4987
|
+
rowCells += take;
|
|
4988
|
+
i += take;
|
|
4989
|
+
}
|
|
4990
|
+
continue;
|
|
4991
|
+
}
|
|
4678
4992
|
forEachTextCellSegment(seg.text, (piece) => {
|
|
4679
4993
|
if (!piece.text || piece.cells <= 0)
|
|
4680
4994
|
return;
|
|
@@ -4683,6 +4997,116 @@ function wrapStyledSegmentsByCells(segments, width) {
|
|
|
4683
4997
|
}
|
|
4684
4998
|
return rows;
|
|
4685
4999
|
}
|
|
5000
|
+
function countWrappedTextRows(text, width) {
|
|
5001
|
+
width = Math.max(1, Math.floor(width));
|
|
5002
|
+
if (!text)
|
|
5003
|
+
return 1;
|
|
5004
|
+
const cells = textCellWidth(text);
|
|
5005
|
+
if (cells <= 0)
|
|
5006
|
+
return 1;
|
|
5007
|
+
if (cells === text.length)
|
|
5008
|
+
return Math.max(1, Math.ceil(cells / width));
|
|
5009
|
+
let rows = 1;
|
|
5010
|
+
let rowCells = 0;
|
|
5011
|
+
forEachTextCellSegment(text, (piece) => {
|
|
5012
|
+
if (!piece.text || piece.cells <= 0)
|
|
5013
|
+
return;
|
|
5014
|
+
const pieceCells = piece.cells;
|
|
5015
|
+
if (rowCells > 0 && rowCells + pieceCells > width) {
|
|
5016
|
+
rows++;
|
|
5017
|
+
rowCells = 0;
|
|
5018
|
+
}
|
|
5019
|
+
if (pieceCells > width) {
|
|
5020
|
+
let remaining = pieceCells;
|
|
5021
|
+
while (remaining > 0) {
|
|
5022
|
+
if (rowCells >= width) {
|
|
5023
|
+
rows++;
|
|
5024
|
+
rowCells = 0;
|
|
5025
|
+
}
|
|
5026
|
+
const take = Math.min(width - rowCells, remaining);
|
|
5027
|
+
rowCells += take;
|
|
5028
|
+
remaining -= take;
|
|
5029
|
+
}
|
|
5030
|
+
return;
|
|
5031
|
+
}
|
|
5032
|
+
if (rowCells >= width) {
|
|
5033
|
+
rows++;
|
|
5034
|
+
rowCells = 0;
|
|
5035
|
+
}
|
|
5036
|
+
rowCells += pieceCells;
|
|
5037
|
+
});
|
|
5038
|
+
return rows;
|
|
5039
|
+
}
|
|
5040
|
+
function countWrappedPlainTextRows(text, width) {
|
|
5041
|
+
width = Math.max(1, Math.floor(width));
|
|
5042
|
+
if (!text)
|
|
5043
|
+
return 1;
|
|
5044
|
+
let rows = 0;
|
|
5045
|
+
let rowCells = 0;
|
|
5046
|
+
let sawText = false;
|
|
5047
|
+
forEachTextCellSegment(text, (piece) => {
|
|
5048
|
+
if (!piece.text || piece.cells <= 0)
|
|
5049
|
+
return;
|
|
5050
|
+
sawText = true;
|
|
5051
|
+
const cells = piece.cells;
|
|
5052
|
+
if (rowCells > 0 && rowCells + cells > width) {
|
|
5053
|
+
rows++;
|
|
5054
|
+
rowCells = 0;
|
|
5055
|
+
}
|
|
5056
|
+
rowCells += cells;
|
|
5057
|
+
if (rowCells >= width) {
|
|
5058
|
+
rows++;
|
|
5059
|
+
rowCells = 0;
|
|
5060
|
+
}
|
|
5061
|
+
});
|
|
5062
|
+
return Math.max(1, rows + (rowCells > 0 || !sawText ? 1 : 0));
|
|
5063
|
+
}
|
|
5064
|
+
function countAsciiAnsiTextCells(text) {
|
|
5065
|
+
let cells = 0;
|
|
5066
|
+
for (let i = 0; i < text.length; i++) {
|
|
5067
|
+
const code = text.charCodeAt(i);
|
|
5068
|
+
if (code > 127)
|
|
5069
|
+
return null;
|
|
5070
|
+
if (code === 27) {
|
|
5071
|
+
const next = text[i + 1];
|
|
5072
|
+
if (next === "[") {
|
|
5073
|
+
let j = i + 2;
|
|
5074
|
+
while (j < text.length) {
|
|
5075
|
+
const c = text.charCodeAt(j);
|
|
5076
|
+
if (c >= 64 && c <= 126)
|
|
5077
|
+
break;
|
|
5078
|
+
j++;
|
|
5079
|
+
}
|
|
5080
|
+
if (j >= text.length)
|
|
5081
|
+
return null;
|
|
5082
|
+
i = j;
|
|
5083
|
+
continue;
|
|
5084
|
+
}
|
|
5085
|
+
if (next === "]") {
|
|
5086
|
+
let j = i + 2;
|
|
5087
|
+
while (j < text.length) {
|
|
5088
|
+
const c = text.charCodeAt(j);
|
|
5089
|
+
if (c === 7)
|
|
5090
|
+
break;
|
|
5091
|
+
if (c === 27 && text[j + 1] === "\\") {
|
|
5092
|
+
j++;
|
|
5093
|
+
break;
|
|
5094
|
+
}
|
|
5095
|
+
j++;
|
|
5096
|
+
}
|
|
5097
|
+
if (j >= text.length)
|
|
5098
|
+
return null;
|
|
5099
|
+
i = j;
|
|
5100
|
+
continue;
|
|
5101
|
+
}
|
|
5102
|
+
return null;
|
|
5103
|
+
}
|
|
5104
|
+
if (code <= 31 || code === 127)
|
|
5105
|
+
return null;
|
|
5106
|
+
cells++;
|
|
5107
|
+
}
|
|
5108
|
+
return cells;
|
|
5109
|
+
}
|
|
4686
5110
|
var TLogView = (0, import_vue12.defineComponent)({
|
|
4687
5111
|
name: "TLogView",
|
|
4688
5112
|
props: {
|
|
@@ -4821,6 +5245,7 @@ var TLogView = (0, import_vue12.defineComponent)({
|
|
|
4821
5245
|
const renderLineCache = /* @__PURE__ */ new Map();
|
|
4822
5246
|
const wrapLineCache = /* @__PURE__ */ new Map();
|
|
4823
5247
|
const ansiLineCache = /* @__PURE__ */ new Map();
|
|
5248
|
+
const ansiTextCache = /* @__PURE__ */ new Map();
|
|
4824
5249
|
const ansiWrapCache = /* @__PURE__ */ new Map();
|
|
4825
5250
|
const ansiRowCache = /* @__PURE__ */ new Map();
|
|
4826
5251
|
const linkifyLineCache = /* @__PURE__ */ new Map();
|
|
@@ -4942,6 +5367,9 @@ var TLogView = (0, import_vue12.defineComponent)({
|
|
|
4942
5367
|
function ansiLineCacheKey(key, baseStyleKey, linkKey) {
|
|
4943
5368
|
return JSON.stringify(["ansi-line", key, baseStyleKey, linksEnabled() ? 1 : 0, linkKey]);
|
|
4944
5369
|
}
|
|
5370
|
+
function ansiTextCacheKey(key) {
|
|
5371
|
+
return JSON.stringify(["ansi-text", key]);
|
|
5372
|
+
}
|
|
4945
5373
|
function linkifyLineCacheKey(key, baseStyleKey, linkKey, optionsKey) {
|
|
4946
5374
|
return JSON.stringify(["linkify-line", key, baseStyleKey, linkKey, optionsKey]);
|
|
4947
5375
|
}
|
|
@@ -5004,6 +5432,15 @@ var TLogView = (0, import_vue12.defineComponent)({
|
|
|
5004
5432
|
ansiLineCache.delete(entry.key);
|
|
5005
5433
|
}
|
|
5006
5434
|
}
|
|
5435
|
+
function trimAnsiTextCache() {
|
|
5436
|
+
const max = DEFAULT_LOG_RENDER_CACHE_SIZE;
|
|
5437
|
+
if (ansiTextCache.size <= max)
|
|
5438
|
+
return;
|
|
5439
|
+
const entries = Array.from(ansiTextCache.values()).sort((a, b) => a.touchedAt - b.touchedAt);
|
|
5440
|
+
for (const entry of entries.slice(0, ansiTextCache.size - max)) {
|
|
5441
|
+
ansiTextCache.delete(entry.key);
|
|
5442
|
+
}
|
|
5443
|
+
}
|
|
5007
5444
|
function trimAnsiWrapCache() {
|
|
5008
5445
|
const max = DEFAULT_LOG_WRAP_CACHE_SIZE;
|
|
5009
5446
|
if (ansiWrapCache.size <= max)
|
|
@@ -5059,6 +5496,7 @@ var TLogView = (0, import_vue12.defineComponent)({
|
|
|
5059
5496
|
renderLineCache.clear();
|
|
5060
5497
|
wrapLineCache.clear();
|
|
5061
5498
|
ansiLineCache.clear();
|
|
5499
|
+
ansiTextCache.clear();
|
|
5062
5500
|
ansiWrapCache.clear();
|
|
5063
5501
|
ansiRowCache.clear();
|
|
5064
5502
|
linkifyLineCache.clear();
|
|
@@ -5144,6 +5582,24 @@ var TLogView = (0, import_vue12.defineComponent)({
|
|
|
5144
5582
|
});
|
|
5145
5583
|
return segments;
|
|
5146
5584
|
}
|
|
5585
|
+
function ansiPlainTextForLine(index, count) {
|
|
5586
|
+
if (index < 0 || index >= count)
|
|
5587
|
+
return "";
|
|
5588
|
+
const rawKey = lineKey(index);
|
|
5589
|
+
const key = ansiTextCacheKey(rawKey);
|
|
5590
|
+
const cached = ansiTextCache.get(key);
|
|
5591
|
+
if (cached) {
|
|
5592
|
+
cached.touchedAt = ++cacheClock;
|
|
5593
|
+
return cached.value;
|
|
5594
|
+
}
|
|
5595
|
+
const text = sanitizeAnsiInlineText(props.source.getLine(index));
|
|
5596
|
+
ansiTextCache.set(key, {
|
|
5597
|
+
key,
|
|
5598
|
+
value: text,
|
|
5599
|
+
touchedAt: ++cacheClock
|
|
5600
|
+
});
|
|
5601
|
+
return text;
|
|
5602
|
+
}
|
|
5147
5603
|
function ansiWrappedRowsForLine(index, count, width, baseStyle, baseStyleKey, linkKey = linkStyleCacheKey()) {
|
|
5148
5604
|
if (index < 0 || index >= count)
|
|
5149
5605
|
return [[]];
|
|
@@ -5539,10 +5995,9 @@ var TLogView = (0, import_vue12.defineComponent)({
|
|
|
5539
5995
|
lineMatches.push(matchIndex);
|
|
5540
5996
|
invalidateSearchMarkers();
|
|
5541
5997
|
}
|
|
5542
|
-
function searchableTextForLine(index, count
|
|
5543
|
-
if (props.ansi)
|
|
5544
|
-
return
|
|
5545
|
-
}
|
|
5998
|
+
function searchableTextForLine(index, count) {
|
|
5999
|
+
if (props.ansi)
|
|
6000
|
+
return ansiPlainTextForLine(index, count);
|
|
5546
6001
|
return sanitizeInlineText(props.source.getLine(index));
|
|
5547
6002
|
}
|
|
5548
6003
|
function normalizeSearchResultPreviewWidth(value) {
|
|
@@ -5557,8 +6012,8 @@ var TLogView = (0, import_vue12.defineComponent)({
|
|
|
5557
6012
|
return DEFAULT_SEARCH_RESULTS_CONTEXT_CELLS;
|
|
5558
6013
|
return Math.max(0, n);
|
|
5559
6014
|
}
|
|
5560
|
-
function previewForMatch(match, count,
|
|
5561
|
-
const text = searchableTextForLine(match.index, count
|
|
6015
|
+
function previewForMatch(match, count, options) {
|
|
6016
|
+
const text = searchableTextForLine(match.index, count);
|
|
5562
6017
|
const totalCells = textCellWidth(text);
|
|
5563
6018
|
const matchCells = Math.max(1, match.endCell - match.startCell);
|
|
5564
6019
|
const previewWidth = Math.max(options.previewWidth, matchCells);
|
|
@@ -5593,7 +6048,7 @@ var TLogView = (0, import_vue12.defineComponent)({
|
|
|
5593
6048
|
matchEndCell
|
|
5594
6049
|
};
|
|
5595
6050
|
}
|
|
5596
|
-
function cachedLineSearchMatches(index, count, search
|
|
6051
|
+
function cachedLineSearchMatches(index, count, search) {
|
|
5597
6052
|
const rawKey = lineKey(index);
|
|
5598
6053
|
const key = searchLineCacheKey(rawKey, search.key);
|
|
5599
6054
|
const cached = searchLineCache.get(key);
|
|
@@ -5601,9 +6056,7 @@ var TLogView = (0, import_vue12.defineComponent)({
|
|
|
5601
6056
|
cached.touchedAt = ++cacheClock;
|
|
5602
6057
|
return cached.matches;
|
|
5603
6058
|
}
|
|
5604
|
-
const matches = search.findLineMatches(
|
|
5605
|
-
searchableTextForLine(index, count, baseStyle, baseStyleKey)
|
|
5606
|
-
);
|
|
6059
|
+
const matches = search.findLineMatches(searchableTextForLine(index, count));
|
|
5607
6060
|
searchLineCache.set(key, {
|
|
5608
6061
|
key,
|
|
5609
6062
|
matches,
|
|
@@ -5611,10 +6064,10 @@ var TLogView = (0, import_vue12.defineComponent)({
|
|
|
5611
6064
|
});
|
|
5612
6065
|
return matches;
|
|
5613
6066
|
}
|
|
5614
|
-
function scanSearchLine(index, count, search,
|
|
6067
|
+
function scanSearchLine(index, count, search, maxMatches, absoluteBase) {
|
|
5615
6068
|
if (searchMatches.length >= maxMatches)
|
|
5616
6069
|
return;
|
|
5617
|
-
const lineMatches = cachedLineSearchMatches(index, count, search
|
|
6070
|
+
const lineMatches = cachedLineSearchMatches(index, count, search);
|
|
5618
6071
|
for (const match of lineMatches) {
|
|
5619
6072
|
if (searchMatches.length >= maxMatches)
|
|
5620
6073
|
return;
|
|
@@ -5644,19 +6097,9 @@ var TLogView = (0, import_vue12.defineComponent)({
|
|
|
5644
6097
|
const count = lineCount();
|
|
5645
6098
|
const maxMatches = maxSearchMatches();
|
|
5646
6099
|
const absoluteBase = firstLineIndex();
|
|
5647
|
-
const base = props.style ?? defaultStyle.value;
|
|
5648
|
-
const baseStyleKey = styleCacheKey(base);
|
|
5649
6100
|
let scanned = 0;
|
|
5650
6101
|
while (searchCursor < count && searchMatches.length < maxMatches && (scanned === 0 || ctx.now() - started < budget)) {
|
|
5651
|
-
scanSearchLine(
|
|
5652
|
-
searchCursor,
|
|
5653
|
-
count,
|
|
5654
|
-
compiledSearch,
|
|
5655
|
-
base,
|
|
5656
|
-
baseStyleKey,
|
|
5657
|
-
maxMatches,
|
|
5658
|
-
absoluteBase
|
|
5659
|
-
);
|
|
6102
|
+
scanSearchLine(searchCursor, count, compiledSearch, maxMatches, absoluteBase);
|
|
5660
6103
|
searchCursor++;
|
|
5661
6104
|
scanned++;
|
|
5662
6105
|
}
|
|
@@ -5677,6 +6120,7 @@ var TLogView = (0, import_vue12.defineComponent)({
|
|
|
5677
6120
|
emitSearchMarkers(true);
|
|
5678
6121
|
markViewportDirty();
|
|
5679
6122
|
ctx.invalidate({ priority: "low", plane: plane.value, reason: "data" });
|
|
6123
|
+
trimAnsiTextCache();
|
|
5680
6124
|
trimSearchLineCache();
|
|
5681
6125
|
}
|
|
5682
6126
|
function requestSearchScan() {
|
|
@@ -5948,22 +6392,39 @@ var TLogView = (0, import_vue12.defineComponent)({
|
|
|
5948
6392
|
if (count > visualIndexLineCount)
|
|
5949
6393
|
appendEstimatedVisualLines(visualIndexLineCount, count);
|
|
5950
6394
|
}
|
|
5951
|
-
function measureVisualLine(index) {
|
|
6395
|
+
function measureVisualLine(index, options) {
|
|
5952
6396
|
ensureVisualIndex();
|
|
5953
6397
|
if (index < 0 || index >= visualIndexLineCount)
|
|
5954
6398
|
return 0;
|
|
5955
6399
|
const key = lineKey(index);
|
|
5956
6400
|
if (visualKeys[index] === key)
|
|
5957
6401
|
return 0;
|
|
5958
|
-
|
|
5959
|
-
|
|
5960
|
-
|
|
5961
|
-
|
|
5962
|
-
|
|
5963
|
-
|
|
5964
|
-
|
|
5965
|
-
|
|
5966
|
-
|
|
6402
|
+
let nextCount;
|
|
6403
|
+
if (options?.countOnly === true) {
|
|
6404
|
+
if (props.ansi) {
|
|
6405
|
+
const raw = props.source.getLine(index);
|
|
6406
|
+
const asciiCells = countAsciiAnsiTextCells(raw);
|
|
6407
|
+
nextCount = asciiCells == null ? countWrappedTextRows(
|
|
6408
|
+
ansiPlainTextForLine(index, visualIndexLineCount),
|
|
6409
|
+
visualIndexWidth
|
|
6410
|
+
) : Math.max(1, Math.ceil(asciiCells / visualIndexWidth));
|
|
6411
|
+
} else {
|
|
6412
|
+
nextCount = countWrappedPlainTextRows(
|
|
6413
|
+
sanitizeInlineText(props.source.getLine(index)),
|
|
6414
|
+
visualIndexWidth
|
|
6415
|
+
);
|
|
6416
|
+
}
|
|
6417
|
+
} else {
|
|
6418
|
+
const base = props.style ?? defaultStyle.value;
|
|
6419
|
+
const rows = props.ansi ? ansiWrappedRowsForLine(
|
|
6420
|
+
index,
|
|
6421
|
+
visualIndexLineCount,
|
|
6422
|
+
visualIndexWidth,
|
|
6423
|
+
base,
|
|
6424
|
+
styleCacheKey(base)
|
|
6425
|
+
) : wrappedRowsForLine(index, visualIndexLineCount, visualIndexWidth);
|
|
6426
|
+
nextCount = Math.max(1, rows.length);
|
|
6427
|
+
}
|
|
5967
6428
|
const prevCount = visualCounts[index] ?? 1;
|
|
5968
6429
|
if (nextCount !== prevCount) {
|
|
5969
6430
|
visualCounts[index] = nextCount;
|
|
@@ -6009,6 +6470,7 @@ var TLogView = (0, import_vue12.defineComponent)({
|
|
|
6009
6470
|
if (visualMeasureCursor >= target) {
|
|
6010
6471
|
syncVisualIndexStatus();
|
|
6011
6472
|
emitVisualIndex();
|
|
6473
|
+
trimAnsiTextCache();
|
|
6012
6474
|
return;
|
|
6013
6475
|
}
|
|
6014
6476
|
const started = ctx.now();
|
|
@@ -6020,7 +6482,7 @@ var TLogView = (0, import_vue12.defineComponent)({
|
|
|
6020
6482
|
const effectiveTop = currentScrollTop() + topAdjustment;
|
|
6021
6483
|
const start = visualStartForLine(index);
|
|
6022
6484
|
const prevCount = visualCounts[index] ?? 1;
|
|
6023
|
-
const delta = measureVisualLine(index);
|
|
6485
|
+
const delta = measureVisualLine(index, { countOnly: true });
|
|
6024
6486
|
if (delta !== 0 && effectiveTop >= start + prevCount)
|
|
6025
6487
|
topAdjustment += delta;
|
|
6026
6488
|
visualMeasureCursor++;
|
|
@@ -6056,6 +6518,7 @@ var TLogView = (0, import_vue12.defineComponent)({
|
|
|
6056
6518
|
}
|
|
6057
6519
|
syncVisualIndexStatus();
|
|
6058
6520
|
emitVisualIndex();
|
|
6521
|
+
trimAnsiTextCache();
|
|
6059
6522
|
}
|
|
6060
6523
|
function requestVisualIndexMeasurement(restartFrom = measuredLineCount) {
|
|
6061
6524
|
if (!props.wrap) {
|
|
@@ -6069,6 +6532,7 @@ var TLogView = (0, import_vue12.defineComponent)({
|
|
|
6069
6532
|
if (measuredLineCount >= target) {
|
|
6070
6533
|
syncVisualIndexStatus();
|
|
6071
6534
|
emitVisualIndex();
|
|
6535
|
+
trimAnsiTextCache();
|
|
6072
6536
|
return;
|
|
6073
6537
|
}
|
|
6074
6538
|
const generation = ++visualMeasureGeneration;
|
|
@@ -6661,7 +7125,7 @@ var TLogView = (0, import_vue12.defineComponent)({
|
|
|
6661
7125
|
emitScroll(clampedTop);
|
|
6662
7126
|
return true;
|
|
6663
7127
|
}
|
|
6664
|
-
const scrollPlan =
|
|
7128
|
+
const scrollPlan = prepareUnsafeFullRowScroll({
|
|
6665
7129
|
render,
|
|
6666
7130
|
plane: plane.value,
|
|
6667
7131
|
rect: r,
|
|
@@ -6672,7 +7136,7 @@ var TLogView = (0, import_vue12.defineComponent)({
|
|
|
6672
7136
|
isClipped: isClipped(),
|
|
6673
7137
|
hasPendingDirtyRows: Boolean(dirtyRowsHint?.length),
|
|
6674
7138
|
strategy
|
|
6675
|
-
})
|
|
7139
|
+
});
|
|
6676
7140
|
if (scrollPlan) {
|
|
6677
7141
|
const rows = options?.extraDirtyRows?.length ? [...scrollPlan.exposedRows, ...options.extraDirtyRows] : scrollPlan.exposedRows;
|
|
6678
7142
|
if (markRowsDirty(rows)) {
|
|
@@ -7237,14 +7701,12 @@ var TLogView = (0, import_vue12.defineComponent)({
|
|
|
7237
7701
|
}));
|
|
7238
7702
|
}
|
|
7239
7703
|
const count = lineCount();
|
|
7240
|
-
const base = props.style ?? defaultStyle.value;
|
|
7241
|
-
const baseStyleKey = styleCacheKey(base);
|
|
7242
7704
|
const previewWidth = normalizeSearchResultPreviewWidth(options?.previewWidth);
|
|
7243
7705
|
const contextCells = normalizeSearchResultContextCells(options?.contextCells);
|
|
7244
7706
|
return searchMatches.slice(offset, offset + limit).map((match, index) => ({
|
|
7245
7707
|
matchIndex: offset + index,
|
|
7246
7708
|
match: copySearchMatch(match),
|
|
7247
|
-
preview: previewForMatch(match, count,
|
|
7709
|
+
preview: previewForMatch(match, count, {
|
|
7248
7710
|
previewWidth,
|
|
7249
7711
|
contextCells
|
|
7250
7712
|
})
|