@lvce-editor/editor-worker 19.72.5 → 19.72.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/editorWorkerMain.js +150 -60
- package/package.json +1 -1
package/dist/editorWorkerMain.js
CHANGED
|
@@ -2463,77 +2463,132 @@ const getHorizontalVisibleRange = (line, deltaX, width, averageCharWidth, tabSiz
|
|
|
2463
2463
|
start
|
|
2464
2464
|
};
|
|
2465
2465
|
};
|
|
2466
|
-
const
|
|
2467
|
-
const fallback =
|
|
2468
|
-
const range = getHorizontalVisibleRange(line, deltaX, width, averageCharWidth, tabSize, threshold);
|
|
2466
|
+
const getHorizontalVisibleRangesMeasured = async (requests, measureWidths) => {
|
|
2467
|
+
const fallback = request => {
|
|
2468
|
+
const range = getHorizontalVisibleRange(request.line, request.deltaX, request.width, request.averageCharWidth, request.tabSize, request.threshold);
|
|
2469
2469
|
return {
|
|
2470
2470
|
...range,
|
|
2471
|
-
difference: getHorizontalVisibleDifference(line, range.start, deltaX, averageCharWidth, tabSize)
|
|
2471
|
+
difference: getHorizontalVisibleDifference(request.line, range.start, request.deltaX, request.averageCharWidth, request.tabSize)
|
|
2472
2472
|
};
|
|
2473
2473
|
};
|
|
2474
|
-
|
|
2475
|
-
|
|
2474
|
+
const results = requests.map(request => fallback(request));
|
|
2475
|
+
const boundariesByLine = [];
|
|
2476
|
+
const measurementsByLine = [];
|
|
2477
|
+
const cursors = [];
|
|
2478
|
+
for (let lineIndex = 0; lineIndex < requests.length; lineIndex++) {
|
|
2479
|
+
const request = requests[lineIndex];
|
|
2480
|
+
if (request.line.length <= request.threshold) {
|
|
2481
|
+
continue;
|
|
2482
|
+
}
|
|
2483
|
+
const segments = getSegments(request.line);
|
|
2484
|
+
const boundaries = [0, ...segments.map(({
|
|
2485
|
+
index,
|
|
2486
|
+
segment
|
|
2487
|
+
}) => index + segment.length)];
|
|
2488
|
+
boundariesByLine[lineIndex] = boundaries;
|
|
2489
|
+
measurementsByLine[lineIndex] = new Map([[0, 0]]);
|
|
2490
|
+
const scrollOffset = Math.max(0, Number.isFinite(request.deltaX) ? request.deltaX : 0);
|
|
2491
|
+
const viewportWidth = Number.isFinite(request.width) ? Math.max(0, request.width) : Infinity;
|
|
2492
|
+
cursors.push({
|
|
2493
|
+
high: boundaries.length,
|
|
2494
|
+
isStart: true,
|
|
2495
|
+
lineIndex,
|
|
2496
|
+
low: 0,
|
|
2497
|
+
target: scrollOffset
|
|
2498
|
+
});
|
|
2499
|
+
cursors.push({
|
|
2500
|
+
high: boundaries.length,
|
|
2501
|
+
isStart: false,
|
|
2502
|
+
lineIndex,
|
|
2503
|
+
low: 0,
|
|
2504
|
+
target: scrollOffset + viewportWidth
|
|
2505
|
+
});
|
|
2476
2506
|
}
|
|
2477
|
-
|
|
2478
|
-
|
|
2479
|
-
|
|
2480
|
-
|
|
2481
|
-
index,
|
|
2482
|
-
segment
|
|
2483
|
-
}) => index + segment.length)];
|
|
2484
|
-
const measurements = new Map([[0, 0]]);
|
|
2485
|
-
const measureBoundary = async boundaryIndex => {
|
|
2486
|
-
const cached = measurements.get(boundaryIndex);
|
|
2487
|
-
if (cached !== undefined) {
|
|
2488
|
-
return cached;
|
|
2489
|
-
}
|
|
2490
|
-
const prefix = line.slice(0, boundaries[boundaryIndex]).replaceAll('\t', () => ' '.repeat(tabSize));
|
|
2491
|
-
const measured = await measureWidth(prefix);
|
|
2492
|
-
measurements.set(boundaryIndex, measured);
|
|
2493
|
-
return measured;
|
|
2494
|
-
};
|
|
2495
|
-
const findGreatestBoundaryAtMost = async target => {
|
|
2496
|
-
let low = 0;
|
|
2497
|
-
let high = boundaries.length;
|
|
2498
|
-
while (low < high) {
|
|
2499
|
-
const middle = Math.floor((low + high) / 2);
|
|
2500
|
-
if ((await measureBoundary(middle)) <= target) {
|
|
2501
|
-
low = middle + 1;
|
|
2502
|
-
} else {
|
|
2503
|
-
high = middle;
|
|
2507
|
+
try {
|
|
2508
|
+
const addPendingMeasurement = (cursor, pending) => {
|
|
2509
|
+
if (cursor.low >= cursor.high) {
|
|
2510
|
+
return;
|
|
2504
2511
|
}
|
|
2505
|
-
|
|
2506
|
-
|
|
2507
|
-
|
|
2508
|
-
|
|
2509
|
-
|
|
2510
|
-
|
|
2511
|
-
|
|
2512
|
-
|
|
2513
|
-
|
|
2514
|
-
|
|
2512
|
+
const boundaryIndex = Math.floor((cursor.low + cursor.high) / 2);
|
|
2513
|
+
if (measurementsByLine[cursor.lineIndex].has(boundaryIndex)) {
|
|
2514
|
+
return;
|
|
2515
|
+
}
|
|
2516
|
+
const request = requests[cursor.lineIndex];
|
|
2517
|
+
const prefix = request.line.slice(0, boundariesByLine[cursor.lineIndex][boundaryIndex]).replaceAll('\t', () => ' '.repeat(request.tabSize));
|
|
2518
|
+
pending.set(`${cursor.lineIndex}:${boundaryIndex}`, {
|
|
2519
|
+
boundaryIndex,
|
|
2520
|
+
lineIndex: cursor.lineIndex,
|
|
2521
|
+
text: prefix
|
|
2522
|
+
});
|
|
2523
|
+
};
|
|
2524
|
+
const updateCursor = cursor => {
|
|
2525
|
+
if (cursor.low >= cursor.high) {
|
|
2526
|
+
return;
|
|
2527
|
+
}
|
|
2528
|
+
const middle = Math.floor((cursor.low + cursor.high) / 2);
|
|
2529
|
+
const measured = measurementsByLine[cursor.lineIndex].get(middle);
|
|
2530
|
+
if (measured === undefined) {
|
|
2531
|
+
return;
|
|
2532
|
+
}
|
|
2533
|
+
if (cursor.isStart ? measured <= cursor.target : measured < cursor.target) {
|
|
2534
|
+
cursor.low = middle + 1;
|
|
2515
2535
|
} else {
|
|
2516
|
-
high = middle;
|
|
2536
|
+
cursor.high = middle;
|
|
2537
|
+
}
|
|
2538
|
+
};
|
|
2539
|
+
while (cursors.some(({
|
|
2540
|
+
high,
|
|
2541
|
+
low
|
|
2542
|
+
}) => low < high)) {
|
|
2543
|
+
const pending = new Map();
|
|
2544
|
+
for (const cursor of cursors) {
|
|
2545
|
+
addPendingMeasurement(cursor, pending);
|
|
2546
|
+
}
|
|
2547
|
+
if (pending.size > 0) {
|
|
2548
|
+
const entries = pending.values().toArray();
|
|
2549
|
+
const measuredWidths = await measureWidths(entries.map(({
|
|
2550
|
+
text
|
|
2551
|
+
}) => text));
|
|
2552
|
+
if (measuredWidths.length !== entries.length) {
|
|
2553
|
+
throw new Error('Text measurement returned an unexpected number of widths');
|
|
2554
|
+
}
|
|
2555
|
+
for (let i = 0; i < entries.length; i++) {
|
|
2556
|
+
const {
|
|
2557
|
+
boundaryIndex,
|
|
2558
|
+
lineIndex
|
|
2559
|
+
} = entries[i];
|
|
2560
|
+
measurementsByLine[lineIndex].set(boundaryIndex, measuredWidths[i]);
|
|
2561
|
+
}
|
|
2562
|
+
}
|
|
2563
|
+
for (const cursor of cursors) {
|
|
2564
|
+
updateCursor(cursor);
|
|
2517
2565
|
}
|
|
2518
2566
|
}
|
|
2519
|
-
|
|
2520
|
-
|
|
2521
|
-
|
|
2522
|
-
|
|
2523
|
-
|
|
2524
|
-
|
|
2525
|
-
|
|
2526
|
-
|
|
2527
|
-
|
|
2567
|
+
for (let lineIndex = 0; lineIndex < boundariesByLine.length; lineIndex++) {
|
|
2568
|
+
const boundaries = boundariesByLine[lineIndex];
|
|
2569
|
+
if (!boundaries) {
|
|
2570
|
+
continue;
|
|
2571
|
+
}
|
|
2572
|
+
const request = requests[lineIndex];
|
|
2573
|
+
const lineCursors = cursors.filter(cursor => cursor.lineIndex === lineIndex);
|
|
2574
|
+
const startBoundary = Math.max(0, lineCursors[0].low - 1);
|
|
2575
|
+
const endBoundary = Math.min(boundaries.length - 1, lineCursors[1].low);
|
|
2576
|
+
const start = boundaries[startBoundary];
|
|
2577
|
+
let end = boundaries[endBoundary];
|
|
2578
|
+
if (end < request.line.length) {
|
|
2579
|
+
end = boundaries[Math.min(boundaries.length - 1, endBoundary + 1)];
|
|
2580
|
+
}
|
|
2581
|
+
const scrollOffset = Math.max(0, Number.isFinite(request.deltaX) ? request.deltaX : 0);
|
|
2582
|
+
results[lineIndex] = {
|
|
2583
|
+
difference: (measurementsByLine[lineIndex].get(startBoundary) ?? 0) - scrollOffset,
|
|
2584
|
+
end,
|
|
2585
|
+
start
|
|
2586
|
+
};
|
|
2528
2587
|
}
|
|
2529
|
-
return {
|
|
2530
|
-
difference: (await measureBoundary(startBoundary)) - scrollOffset,
|
|
2531
|
-
end,
|
|
2532
|
-
start
|
|
2533
|
-
};
|
|
2534
2588
|
} catch {
|
|
2535
|
-
|
|
2589
|
+
// Keep the existing approximate range fallback when worker measurement fails.
|
|
2536
2590
|
}
|
|
2591
|
+
return results;
|
|
2537
2592
|
};
|
|
2538
2593
|
const getHorizontalVisibleDifference = (line, start, deltaX, averageCharWidth, tabSize) => {
|
|
2539
2594
|
const charWidth = averageCharWidth > 0 ? averageCharWidth : 1;
|
|
@@ -2953,6 +3008,10 @@ const measureTextWidthSlow = async (text, fontWeight, fontSize, fontFamily, lett
|
|
|
2953
3008
|
return width;
|
|
2954
3009
|
};
|
|
2955
3010
|
|
|
3011
|
+
const measureTextWidthsSlow = async (texts, fontWeight, fontSize, fontFamily, letterSpacing, isMonoSpaceFont, charWidth) => {
|
|
3012
|
+
return await invoke$e('TextMeasurement.measureTextWidths', texts, fontWeight, fontSize, fontFamily, letterSpacing, isMonoSpaceFont, charWidth);
|
|
3013
|
+
};
|
|
3014
|
+
|
|
2956
3015
|
const measureTextWidth = async (text, fontWeight, fontSize, fontFamily, letterSpacing, isMonoSpaceFont, charWidth) => {
|
|
2957
3016
|
// TODO maybe have a property for the whole text document
|
|
2958
3017
|
// whether the document is ASCII or not
|
|
@@ -2963,6 +3022,29 @@ const measureTextWidth = async (text, fontWeight, fontSize, fontFamily, letterSp
|
|
|
2963
3022
|
}
|
|
2964
3023
|
return await measureTextWidthSlow(text, fontWeight, fontSize, fontFamily, letterSpacing, isMonoSpaceFont, charWidth);
|
|
2965
3024
|
};
|
|
3025
|
+
const measureTextWidths = async (texts, fontWeight, fontSize, fontFamily, letterSpacing, isMonoSpaceFont, charWidth) => {
|
|
3026
|
+
const widths = Array.from({
|
|
3027
|
+
length: texts.length
|
|
3028
|
+
}, (_, index) => index);
|
|
3029
|
+
const slowTexts = [];
|
|
3030
|
+
const slowIndexes = [];
|
|
3031
|
+
for (let i = 0; i < texts.length; i++) {
|
|
3032
|
+
const text = texts[i];
|
|
3033
|
+
if (isMonoSpaceFont && isAscii(text)) {
|
|
3034
|
+
widths[i] = await measureTextWidthFast(text, charWidth);
|
|
3035
|
+
} else {
|
|
3036
|
+
slowTexts.push(text);
|
|
3037
|
+
slowIndexes.push(i);
|
|
3038
|
+
}
|
|
3039
|
+
}
|
|
3040
|
+
if (slowTexts.length > 0) {
|
|
3041
|
+
const slowWidths = await measureTextWidthsSlow(slowTexts, fontWeight, fontSize, fontFamily, letterSpacing, isMonoSpaceFont, charWidth);
|
|
3042
|
+
for (let i = 0; i < slowWidths.length; i++) {
|
|
3043
|
+
widths[slowIndexes[i]] = slowWidths[i];
|
|
3044
|
+
}
|
|
3045
|
+
}
|
|
3046
|
+
return widths;
|
|
3047
|
+
};
|
|
2966
3048
|
|
|
2967
3049
|
const Dot = '.';
|
|
2968
3050
|
const DoubleQuote$1 = '"';
|
|
@@ -3487,10 +3569,18 @@ const getLineInfosViewport = async (editor, tokens, embeddedResults, minLineY, m
|
|
|
3487
3569
|
const tokenMap = get$5(languageId);
|
|
3488
3570
|
let offset = minLineOffset;
|
|
3489
3571
|
const tabSize = editor.tabSize ?? 2;
|
|
3572
|
+
const measuredRanges = await getHorizontalVisibleRangesMeasured(lines.slice(minLineY, maxLineY).map(line => ({
|
|
3573
|
+
averageCharWidth,
|
|
3574
|
+
deltaX,
|
|
3575
|
+
line,
|
|
3576
|
+
tabSize,
|
|
3577
|
+
threshold: horizontalVirtualizationThreshold,
|
|
3578
|
+
width
|
|
3579
|
+
})), texts => measureTextWidths(texts, editor.fontWeight, editor.fontSize, editor.fontFamily, editor.letterSpacing, editor.isMonospaceFont, editor.charWidth));
|
|
3490
3580
|
for (let i = minLineY; i < maxLineY; i++) {
|
|
3491
3581
|
const line = lines[i];
|
|
3492
3582
|
const normalize = shouldNormalizeText(line);
|
|
3493
|
-
const measuredRange =
|
|
3583
|
+
const measuredRange = measuredRanges[i - minLineY];
|
|
3494
3584
|
|
|
3495
3585
|
// Use decorations that were pre-computed (includes links and diagnostics)
|
|
3496
3586
|
// Filter decorations to only include those for this line
|