draftify-cli 1.0.62 → 1.0.64
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/repl.js +115 -6
- package/package.json +1 -1
package/dist/repl.js
CHANGED
|
@@ -668,26 +668,135 @@ async function startRepl(initialUsername) {
|
|
|
668
668
|
search = search.replace(/\r\n/g, '\n');
|
|
669
669
|
replace = replace.replace(/\r\n/g, '\n');
|
|
670
670
|
if (normalizedFile.includes(search)) {
|
|
671
|
+
// === STRATEGY 1: Exact match ===
|
|
671
672
|
fileContent = normalizedFile.replace(search, () => replace);
|
|
672
673
|
diffApplied = true;
|
|
673
674
|
}
|
|
674
675
|
else {
|
|
675
|
-
//
|
|
676
|
+
// === STRATEGY 2: Trimmed match ===
|
|
676
677
|
const trimmedSearch = search.trim();
|
|
677
678
|
if (trimmedSearch && normalizedFile.includes(trimmedSearch)) {
|
|
678
679
|
fileContent = normalizedFile.replace(trimmedSearch, () => replace.trim());
|
|
679
680
|
diffApplied = true;
|
|
680
681
|
}
|
|
681
682
|
else {
|
|
682
|
-
//
|
|
683
|
+
// === STRATEGY 3: Whitespace-flexible regex ===
|
|
683
684
|
const escapedSearch = trimmedSearch.replace(/[.*+?^${}()|[\]\\]/g, '\\$&').replace(/\s+/g, '\\s+');
|
|
684
|
-
const
|
|
685
|
-
if (
|
|
686
|
-
fileContent = normalizedFile.replace(
|
|
685
|
+
const wsRegex = new RegExp(escapedSearch);
|
|
686
|
+
if (wsRegex.test(normalizedFile)) {
|
|
687
|
+
fileContent = normalizedFile.replace(wsRegex, () => replace.trim());
|
|
687
688
|
diffApplied = true;
|
|
688
689
|
}
|
|
689
690
|
else {
|
|
690
|
-
|
|
691
|
+
// === STRATEGY 4: Line-by-line fuzzy matching ===
|
|
692
|
+
// Find the region in the file that best matches the search block
|
|
693
|
+
const searchLines = trimmedSearch.split('\n').map(l => l.trim()).filter(l => l.length > 0);
|
|
694
|
+
const fileLines = normalizedFile.split('\n');
|
|
695
|
+
if (searchLines.length > 0) {
|
|
696
|
+
let bestStartIdx = -1;
|
|
697
|
+
let bestEndIdx = -1;
|
|
698
|
+
let bestScore = 0;
|
|
699
|
+
// Slide a window over the file lines to find the best matching region
|
|
700
|
+
for (let i = 0; i <= fileLines.length - searchLines.length; i++) {
|
|
701
|
+
let matchedCount = 0;
|
|
702
|
+
let lastMatchIdx = i - 1;
|
|
703
|
+
for (const searchLine of searchLines) {
|
|
704
|
+
// Look for this search line within a reasonable range
|
|
705
|
+
for (let j = lastMatchIdx + 1; j < Math.min(i + searchLines.length + 5, fileLines.length); j++) {
|
|
706
|
+
if (fileLines[j].trim() === searchLine) {
|
|
707
|
+
matchedCount++;
|
|
708
|
+
lastMatchIdx = j;
|
|
709
|
+
break;
|
|
710
|
+
}
|
|
711
|
+
}
|
|
712
|
+
}
|
|
713
|
+
const score = matchedCount / searchLines.length;
|
|
714
|
+
if (score > bestScore && score >= 0.6) {
|
|
715
|
+
bestScore = score;
|
|
716
|
+
bestStartIdx = i;
|
|
717
|
+
bestEndIdx = Math.min(lastMatchIdx, i + searchLines.length + 4);
|
|
718
|
+
}
|
|
719
|
+
}
|
|
720
|
+
if (bestStartIdx >= 0 && bestScore >= 0.6) {
|
|
721
|
+
const before = fileLines.slice(0, bestStartIdx).join('\n');
|
|
722
|
+
const after = fileLines.slice(bestEndIdx + 1).join('\n');
|
|
723
|
+
fileContent = before + (before ? '\n' : '') + replace.trim() + (after ? '\n' : '') + after;
|
|
724
|
+
diffApplied = true;
|
|
725
|
+
ui_1.ui.info(`Fuzzy matched diff for ${filePath} (${Math.round(bestScore * 100)}% confidence)`);
|
|
726
|
+
}
|
|
727
|
+
else {
|
|
728
|
+
// === STRATEGY 5: Anchor line matching (first + last non-empty line) ===
|
|
729
|
+
const firstSearchLine = searchLines[0];
|
|
730
|
+
const lastSearchLine = searchLines[searchLines.length - 1];
|
|
731
|
+
let anchorStart = -1;
|
|
732
|
+
let anchorEnd = -1;
|
|
733
|
+
for (let i = 0; i < fileLines.length; i++) {
|
|
734
|
+
if (fileLines[i].trim() === firstSearchLine) {
|
|
735
|
+
anchorStart = i;
|
|
736
|
+
break;
|
|
737
|
+
}
|
|
738
|
+
}
|
|
739
|
+
if (anchorStart >= 0) {
|
|
740
|
+
for (let i = anchorStart + 1; i < fileLines.length; i++) {
|
|
741
|
+
if (fileLines[i].trim() === lastSearchLine) {
|
|
742
|
+
anchorEnd = i;
|
|
743
|
+
break;
|
|
744
|
+
}
|
|
745
|
+
}
|
|
746
|
+
}
|
|
747
|
+
if (anchorStart >= 0 && anchorEnd >= 0 && (anchorEnd - anchorStart) <= searchLines.length * 2) {
|
|
748
|
+
const before = fileLines.slice(0, anchorStart).join('\n');
|
|
749
|
+
const after = fileLines.slice(anchorEnd + 1).join('\n');
|
|
750
|
+
fileContent = before + (before ? '\n' : '') + replace.trim() + (after ? '\n' : '') + after;
|
|
751
|
+
diffApplied = true;
|
|
752
|
+
ui_1.ui.info(`Anchor-matched diff for ${filePath} (first/last line anchors)`);
|
|
753
|
+
}
|
|
754
|
+
else {
|
|
755
|
+
// === STRATEGY 6: Partial content - find longest unique line sequence ===
|
|
756
|
+
// Use the 3 longest unique lines from the search as anchors
|
|
757
|
+
const uniqueSearchLines = searchLines
|
|
758
|
+
.filter(l => l.length > 10)
|
|
759
|
+
.sort((a, b) => b.length - a.length)
|
|
760
|
+
.slice(0, 3);
|
|
761
|
+
if (uniqueSearchLines.length >= 2) {
|
|
762
|
+
const firstUnique = uniqueSearchLines[0];
|
|
763
|
+
const secondUnique = uniqueSearchLines[1];
|
|
764
|
+
let uStart = -1, uEnd = -1;
|
|
765
|
+
for (let i = 0; i < fileLines.length; i++) {
|
|
766
|
+
if (fileLines[i].trim().includes(firstUnique) || firstUnique.includes(fileLines[i].trim())) {
|
|
767
|
+
if (uStart < 0)
|
|
768
|
+
uStart = i;
|
|
769
|
+
uEnd = i;
|
|
770
|
+
}
|
|
771
|
+
if (fileLines[i].trim().includes(secondUnique) || secondUnique.includes(fileLines[i].trim())) {
|
|
772
|
+
if (uStart < 0)
|
|
773
|
+
uStart = i;
|
|
774
|
+
uEnd = i;
|
|
775
|
+
}
|
|
776
|
+
}
|
|
777
|
+
if (uStart >= 0 && uEnd >= uStart) {
|
|
778
|
+
// Expand slightly to capture the full block
|
|
779
|
+
const expandedStart = Math.max(0, uStart - 1);
|
|
780
|
+
const expandedEnd = Math.min(fileLines.length - 1, uEnd + 1);
|
|
781
|
+
const before = fileLines.slice(0, expandedStart).join('\n');
|
|
782
|
+
const after = fileLines.slice(expandedEnd + 1).join('\n');
|
|
783
|
+
fileContent = before + (before ? '\n' : '') + replace.trim() + (after ? '\n' : '') + after;
|
|
784
|
+
diffApplied = true;
|
|
785
|
+
ui_1.ui.info(`Partial-matched diff for ${filePath} (unique line anchors)`);
|
|
786
|
+
}
|
|
787
|
+
else {
|
|
788
|
+
ui_1.ui.error(`Could not apply diff to ${filePath}: SEARCH block not matched (all 6 strategies failed).`);
|
|
789
|
+
}
|
|
790
|
+
}
|
|
791
|
+
else {
|
|
792
|
+
ui_1.ui.error(`Could not apply diff to ${filePath}: SEARCH block not matched (all strategies failed).`);
|
|
793
|
+
}
|
|
794
|
+
}
|
|
795
|
+
}
|
|
796
|
+
}
|
|
797
|
+
else {
|
|
798
|
+
ui_1.ui.error(`Could not apply diff to ${filePath}: SEARCH block is empty.`);
|
|
799
|
+
}
|
|
691
800
|
}
|
|
692
801
|
}
|
|
693
802
|
}
|