@lvce-editor/find-widget-worker 3.1.0 → 3.2.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/dist/findWidgetWorkerMain.js +105 -19
- package/package.json +1 -1
|
@@ -1181,16 +1181,16 @@ const focusIndex = async (state, index) => {
|
|
|
1181
1181
|
const {
|
|
1182
1182
|
editorUid,
|
|
1183
1183
|
matches,
|
|
1184
|
-
matchIndex
|
|
1185
|
-
value
|
|
1184
|
+
matchIndex
|
|
1186
1185
|
} = state;
|
|
1187
1186
|
if (index === matchIndex) {
|
|
1188
1187
|
return state;
|
|
1189
1188
|
}
|
|
1190
1189
|
// // TODO find next match and highlight it
|
|
1191
|
-
const matchRowIndex = matches[index *
|
|
1192
|
-
const matchColumnIndex = matches[index *
|
|
1193
|
-
const
|
|
1190
|
+
const matchRowIndex = matches[index * 3];
|
|
1191
|
+
const matchColumnIndex = matches[index * 3 + 1];
|
|
1192
|
+
const matchLength = matches[index * 3 + 2];
|
|
1193
|
+
const newSelections = new Uint32Array([matchRowIndex, matchColumnIndex, matchRowIndex, matchColumnIndex + matchLength]);
|
|
1194
1194
|
await setSelections(editorUid, newSelections);
|
|
1195
1195
|
return {
|
|
1196
1196
|
...state,
|
|
@@ -1287,7 +1287,7 @@ const findRegexMatches = (lines, regex) => {
|
|
|
1287
1287
|
if (!lastMatch) {
|
|
1288
1288
|
break;
|
|
1289
1289
|
}
|
|
1290
|
-
matches.push(i, lastMatch.index);
|
|
1290
|
+
matches.push(i, lastMatch.index, lastMatch[0].length);
|
|
1291
1291
|
} while (true);
|
|
1292
1292
|
}
|
|
1293
1293
|
return new Uint32Array(matches);
|
|
@@ -1318,7 +1318,7 @@ const findMatches = (lines, searchString, options) => {
|
|
|
1318
1318
|
};
|
|
1319
1319
|
|
|
1320
1320
|
const getMatchCount = matches => {
|
|
1321
|
-
return matches.length /
|
|
1321
|
+
return matches.length / 3;
|
|
1322
1322
|
};
|
|
1323
1323
|
|
|
1324
1324
|
const measureTextHeight = (value, lineHeight) => {
|
|
@@ -1459,6 +1459,47 @@ const applyEdits = async (editorId, edits) => {
|
|
|
1459
1459
|
await invoke('Editor.applyDocumentEdits', editorId, edits);
|
|
1460
1460
|
};
|
|
1461
1461
|
|
|
1462
|
+
/**
|
|
1463
|
+
* Apply regex replacement with back-reference substitution ($1, $2, etc.)
|
|
1464
|
+
*/
|
|
1465
|
+
const applyRegexReplacement = (originalText, regex, replacement) => {
|
|
1466
|
+
// Create a non-global version of the regex to get capture groups
|
|
1467
|
+
const flags = regex.flags.replace('g', '');
|
|
1468
|
+
const nonGlobalRegex = new RegExp(regex.source, flags);
|
|
1469
|
+
const match = nonGlobalRegex.exec(originalText);
|
|
1470
|
+
if (!match) {
|
|
1471
|
+
return replacement;
|
|
1472
|
+
}
|
|
1473
|
+
|
|
1474
|
+
// Replace $n back-references with captured groups
|
|
1475
|
+
let result = replacement;
|
|
1476
|
+
|
|
1477
|
+
// Handle $& (entire match)
|
|
1478
|
+
result = result.replaceAll('$&', match[0]);
|
|
1479
|
+
|
|
1480
|
+
// Handle $` (text before match) - in this context it's empty since we're matching the whole text
|
|
1481
|
+
result = result.replaceAll('$`', '');
|
|
1482
|
+
|
|
1483
|
+
// Handle $' (text after match) - in this context it's empty since we're matching the whole text
|
|
1484
|
+
result = result.replaceAll("$'", '');
|
|
1485
|
+
|
|
1486
|
+
// Handle $$ (literal $)
|
|
1487
|
+
result = result.replaceAll('$$', '\u0000DOLLAR\u0000');
|
|
1488
|
+
|
|
1489
|
+
// Handle $n and $nn (numbered capture groups)
|
|
1490
|
+
result = result.replaceAll(/\$(\d{1,2})/g, (_match, groupNumber) => {
|
|
1491
|
+
const index = Number.parseInt(groupNumber, 10);
|
|
1492
|
+
if (index < match.length) {
|
|
1493
|
+
return match[index] ?? '';
|
|
1494
|
+
}
|
|
1495
|
+
return `$${groupNumber}`;
|
|
1496
|
+
});
|
|
1497
|
+
|
|
1498
|
+
// Restore literal $
|
|
1499
|
+
result = result.replaceAll('\u0000DOLLAR\u0000', '$');
|
|
1500
|
+
return result;
|
|
1501
|
+
};
|
|
1502
|
+
|
|
1462
1503
|
/**
|
|
1463
1504
|
* Preserves the case pattern of the original text when replacing.
|
|
1464
1505
|
* Supports uppercase, lowercase, PascalCase, and camelCase patterns.
|
|
@@ -1498,24 +1539,47 @@ const preserveCase$1 = (originalText, replacementText) => {
|
|
|
1498
1539
|
return replacementText;
|
|
1499
1540
|
};
|
|
1500
1541
|
|
|
1501
|
-
const getEdits = (matches, value, replacement, startIndex, replaceAll, lines, preserveCaseOption = false) => {
|
|
1542
|
+
const getEdits = (matches, value, replacement, startIndex, replaceAll, lines, preserveCaseOption = false, options) => {
|
|
1502
1543
|
if (value.length === 0 || matches.length === 0) {
|
|
1503
1544
|
return [];
|
|
1504
1545
|
}
|
|
1505
1546
|
const edits = [];
|
|
1506
|
-
const totalMatches = Math.floor(matches.length /
|
|
1547
|
+
const totalMatches = Math.floor(matches.length / 3);
|
|
1507
1548
|
const fromIndex = replaceAll ? 0 : Math.max(0, startIndex);
|
|
1508
1549
|
const toIndex = replaceAll ? totalMatches : Math.min(totalMatches, fromIndex + 1);
|
|
1550
|
+
|
|
1551
|
+
// Build regex once if using regular expressions
|
|
1552
|
+
let regex;
|
|
1553
|
+
if (options?.useRegularExpression) {
|
|
1554
|
+
const {
|
|
1555
|
+
error,
|
|
1556
|
+
regex: builtRegex
|
|
1557
|
+
} = buildRegex(value, options);
|
|
1558
|
+
if (!error) {
|
|
1559
|
+
regex = builtRegex;
|
|
1560
|
+
}
|
|
1561
|
+
}
|
|
1509
1562
|
for (let i = fromIndex; i < toIndex; i++) {
|
|
1510
|
-
const rowIndex = matches[i *
|
|
1511
|
-
const startColumnIndex = matches[i *
|
|
1512
|
-
const
|
|
1563
|
+
const rowIndex = matches[i * 3];
|
|
1564
|
+
const startColumnIndex = matches[i * 3 + 1];
|
|
1565
|
+
const matchLength = matches[i * 3 + 2];
|
|
1566
|
+
const endColumnIndex = startColumnIndex + matchLength;
|
|
1513
1567
|
|
|
1514
1568
|
// Get the original text that was matched
|
|
1515
1569
|
const originalText = lines[rowIndex].slice(startColumnIndex, endColumnIndex);
|
|
1516
1570
|
|
|
1571
|
+
// Apply regex replacement with back-references if enabled
|
|
1572
|
+
let finalReplacement;
|
|
1573
|
+
if (options?.useRegularExpression && regex) {
|
|
1574
|
+
finalReplacement = applyRegexReplacement(originalText, regex, replacement);
|
|
1575
|
+
} else {
|
|
1576
|
+
finalReplacement = replacement;
|
|
1577
|
+
}
|
|
1578
|
+
|
|
1517
1579
|
// Apply case preservation if enabled
|
|
1518
|
-
|
|
1580
|
+
if (preserveCaseOption) {
|
|
1581
|
+
finalReplacement = preserveCase$1(originalText, finalReplacement);
|
|
1582
|
+
}
|
|
1519
1583
|
|
|
1520
1584
|
// Convert row/column positions to character offsets
|
|
1521
1585
|
let startOffset = 0;
|
|
@@ -1542,16 +1606,22 @@ const replace$1 = async state => {
|
|
|
1542
1606
|
const {
|
|
1543
1607
|
editorUid,
|
|
1544
1608
|
lines,
|
|
1609
|
+
matchCase,
|
|
1545
1610
|
matches,
|
|
1546
1611
|
matchIndex,
|
|
1612
|
+
matchWholeWord,
|
|
1547
1613
|
preserveCase,
|
|
1548
1614
|
replacement,
|
|
1615
|
+
useRegularExpression,
|
|
1549
1616
|
value
|
|
1550
1617
|
} = state;
|
|
1551
|
-
const
|
|
1618
|
+
const options = {
|
|
1619
|
+
matchCase,
|
|
1620
|
+
matchWholeWord,
|
|
1621
|
+
useRegularExpression
|
|
1622
|
+
};
|
|
1623
|
+
const edits = getEdits(matches, value, replacement, matchIndex, false, lines, preserveCase, options);
|
|
1552
1624
|
await applyEdits(editorUid, edits);
|
|
1553
|
-
// TODO ask editor worker to apply edit
|
|
1554
|
-
// TODO ask editor worker for new lines?
|
|
1555
1625
|
return {
|
|
1556
1626
|
...state
|
|
1557
1627
|
};
|
|
@@ -1561,12 +1631,20 @@ const replaceAll$1 = state => {
|
|
|
1561
1631
|
const {
|
|
1562
1632
|
editorUid,
|
|
1563
1633
|
lines,
|
|
1634
|
+
matchCase,
|
|
1564
1635
|
matches,
|
|
1636
|
+
matchWholeWord,
|
|
1565
1637
|
preserveCase,
|
|
1566
1638
|
replacement,
|
|
1639
|
+
useRegularExpression,
|
|
1567
1640
|
value
|
|
1568
1641
|
} = state;
|
|
1569
|
-
const
|
|
1642
|
+
const options = {
|
|
1643
|
+
matchCase,
|
|
1644
|
+
matchWholeWord,
|
|
1645
|
+
useRegularExpression
|
|
1646
|
+
};
|
|
1647
|
+
const edits = getEdits(matches, value, replacement, 0, true, lines, preserveCase, options);
|
|
1570
1648
|
void applyEdits(editorUid, edits);
|
|
1571
1649
|
return {
|
|
1572
1650
|
...state
|
|
@@ -1605,7 +1683,7 @@ const handleFindWidgetFocus = (state, focusKey) => {
|
|
|
1605
1683
|
const {
|
|
1606
1684
|
focus
|
|
1607
1685
|
} = state;
|
|
1608
|
-
if (focus === focusKey) {
|
|
1686
|
+
if (!focusKey || focus === focusKey) {
|
|
1609
1687
|
return state;
|
|
1610
1688
|
}
|
|
1611
1689
|
return {
|
|
@@ -1619,6 +1697,7 @@ const handleFindFocus = state => {
|
|
|
1619
1697
|
return handleFindWidgetFocus(state, FindWidget$1);
|
|
1620
1698
|
};
|
|
1621
1699
|
|
|
1700
|
+
// TODO maybe use one handleFocus function with a name parameter
|
|
1622
1701
|
const handleReplaceFocus = state => {
|
|
1623
1702
|
return handleFindWidgetFocus(state, FocusFindWidgetReplace);
|
|
1624
1703
|
};
|
|
@@ -1822,6 +1901,10 @@ const getKeyBindings = () => {
|
|
|
1822
1901
|
command: 'FindWidget.focusPreviousMatchButton',
|
|
1823
1902
|
key: Tab,
|
|
1824
1903
|
when: FocusFindWidgetReplace$1
|
|
1904
|
+
}, {
|
|
1905
|
+
command: 'FindWidget.replace',
|
|
1906
|
+
key: Enter,
|
|
1907
|
+
when: FocusFindWidgetReplace$1
|
|
1825
1908
|
}, {
|
|
1826
1909
|
command: 'FindWidget.replaceAll',
|
|
1827
1910
|
key: Alt | CtrlCmd | Enter,
|
|
@@ -1916,6 +1999,9 @@ const getLines = async editorUid => {
|
|
|
1916
1999
|
};
|
|
1917
2000
|
|
|
1918
2001
|
const getSelectedText = (lines, selections) => {
|
|
2002
|
+
if (selections.length === 0) {
|
|
2003
|
+
return '';
|
|
2004
|
+
}
|
|
1919
2005
|
const startRowIndex = selections[0];
|
|
1920
2006
|
const startColumnIndex = selections[1];
|
|
1921
2007
|
const endColumnIndex = selections[3];
|
|
@@ -2514,7 +2600,7 @@ const getEventListeners = (uid, widgetId) => {
|
|
|
2514
2600
|
params: ['executeWidgetCommand', 'FindWidget', 'FindWidget.handleBlur', 0, widgetId]
|
|
2515
2601
|
}, {
|
|
2516
2602
|
name: HandleReplaceInput,
|
|
2517
|
-
params: ['executeWidgetCommand', 'FindWidget', 'FindWidget.handleReplaceInput', 0, widgetId]
|
|
2603
|
+
params: ['executeWidgetCommand', 'FindWidget', 'FindWidget.handleReplaceInput', 0, widgetId, TargetValue]
|
|
2518
2604
|
}, {
|
|
2519
2605
|
name: HandleReplaceFocus,
|
|
2520
2606
|
params: ['executeWidgetCommand', 'FindWidget', 'FindWidget.handleReplaceFocus', 0, widgetId]
|