mirror of
https://github.com/cline/cline.git
synced 2026-09-04 11:44:01 +08:00
Compare commits
6 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| f13cbc3b9f | |||
| bc58b8e10a | |||
| b5e397fb8e | |||
| 14623fc690 | |||
| f9eaab5e37 | |||
| 7991fb349f |
@@ -0,0 +1,5 @@
|
||||
---
|
||||
"claude-dev": patch
|
||||
---
|
||||
|
||||
Fix bug where replace_in_file would not be able to handle for out-of-order SEARCH/REPLACE blocks
|
||||
@@ -1,9 +1,9 @@
|
||||
import { constructNewFileContent as cnfc2 } from "./diff"
|
||||
import { constructNewFileContent as cnfc } from "./diff"
|
||||
import { describe, it } from "mocha"
|
||||
import { expect } from "chai"
|
||||
|
||||
async function cnfc(diffContent: string, originalContent: string, isFinal: boolean): Promise<string> {
|
||||
return cnfc2(diffContent, originalContent, isFinal, "v1")
|
||||
async function cnfc2(diffContent: string, originalContent: string, isFinal: boolean): Promise<string> {
|
||||
return cnfc(diffContent, originalContent, isFinal, "v2")
|
||||
}
|
||||
|
||||
describe("constructNewFileContent", () => {
|
||||
@@ -175,4 +175,136 @@ replaced
|
||||
expect(err).to.be.an("error")
|
||||
}
|
||||
})
|
||||
|
||||
it("should handle missing final REPLACE marker when isFinal is true", async () => {
|
||||
const original = "line1\nline2\nline3"
|
||||
const diff = `------- SEARCH
|
||||
line2
|
||||
=======
|
||||
replaced`
|
||||
// Note: missing +++++++ REPLACE marker
|
||||
|
||||
const result1 = await cnfc(diff, original, true) // isFinal = true
|
||||
|
||||
// Should still work and replace line2 with "replaced"
|
||||
const expected = "line1\nreplaced\nline3"
|
||||
|
||||
expect(result1).to.equal(expected)
|
||||
})
|
||||
|
||||
it("should handle missing final REPLACE marker with multiple lines of replacement", async () => {
|
||||
const original = "function test() {\n\tconst a = 1;\n\treturn a;\n}"
|
||||
const diff = `------- SEARCH
|
||||
const a = 1;
|
||||
return a;
|
||||
=======
|
||||
const a = 42;
|
||||
console.log('updated');
|
||||
return a;`
|
||||
// Note: missing +++++++ REPLACE marker
|
||||
|
||||
const result1 = await cnfc(diff, original, true) // isFinal = true
|
||||
const expected = "function test() {\n\tconst a = 42;\n\tconsole.log('updated');\n\treturn a;\n}"
|
||||
|
||||
expect(result1).to.equal(expected)
|
||||
})
|
||||
|
||||
// it("should NOT process incomplete replacement when isFinal is false", async () => {
|
||||
// const original = "line1\nline2\nline3"
|
||||
// const diff = `------- SEARCH
|
||||
// line2
|
||||
// =======
|
||||
// replaced`
|
||||
// // Note: missing +++++++ REPLACE marker AND isFinal = false
|
||||
|
||||
// const result1 = await cnfc(diff, original, false) // isFinal = false
|
||||
|
||||
// // Should not make any changes since the block is incomplete
|
||||
// const expected = "line1\nline2\nline3"
|
||||
|
||||
// expect(result1).to.equal(expected)
|
||||
// })
|
||||
})
|
||||
|
||||
// Test cases for out-of-order search/replace blocks
|
||||
|
||||
describe("Diff Format Out of Order Cases", () => {
|
||||
it("should handle out-of-order replacements with different positions", async () => {
|
||||
const isFinal = true
|
||||
const original = "first\nsecond\nthird\nfourth\n"
|
||||
const diff = `------- SEARCH
|
||||
fourth
|
||||
=======
|
||||
new fourth
|
||||
+++++++ REPLACE
|
||||
------- SEARCH
|
||||
second
|
||||
=======
|
||||
new second
|
||||
+++++++ REPLACE`
|
||||
const result1 = await cnfc(diff, original, isFinal)
|
||||
const expectedResult = "first\nnew second\nthird\nnew fourth\n"
|
||||
expect(result1).to.equal(expectedResult)
|
||||
})
|
||||
|
||||
it("should handle multiple out-of-order replacements", async () => {
|
||||
const isFinal = true
|
||||
const original = "one\ntwo\nthree\nfour\nfive\n"
|
||||
const diff = `------- SEARCH
|
||||
four
|
||||
=======
|
||||
fourth
|
||||
+++++++ REPLACE
|
||||
------- SEARCH
|
||||
two
|
||||
=======
|
||||
second
|
||||
+++++++ REPLACE
|
||||
------- SEARCH
|
||||
five
|
||||
=======
|
||||
fifth
|
||||
+++++++ REPLACE`
|
||||
const result1 = await cnfc(diff, original, isFinal)
|
||||
const expectedResult = "one\nsecond\nthree\nfourth\nfifth\n"
|
||||
expect(result1).to.equal(expectedResult)
|
||||
})
|
||||
|
||||
it("should handle out-of-order replacements with indentation", async () => {
|
||||
const isFinal = true
|
||||
const original = "function test() {\n\tconst a = 1;\n\tconst b = 2;\n\tconst c = 3;\n\n}"
|
||||
const diff = `------- SEARCH
|
||||
const c = 3;
|
||||
=======
|
||||
const c = 30;
|
||||
+++++++ REPLACE
|
||||
------- SEARCH
|
||||
const a = 1;
|
||||
=======
|
||||
const a = 10;
|
||||
+++++++ REPLACE`
|
||||
const result1 = await cnfc(diff, original, isFinal)
|
||||
const expectedResult = "function test() {\n\tconst a = 10;\n\tconst b = 2;\n\tconst c = 30;\n\n}"
|
||||
expect(result1).to.equal(expectedResult)
|
||||
})
|
||||
|
||||
it("should handle out-of-order replacements with empty lines", async () => {
|
||||
const isFinal = true
|
||||
const original = "header\n\nbody\n\nfooter\n"
|
||||
const diff = `------- SEARCH
|
||||
footer
|
||||
=======
|
||||
new footer
|
||||
+++++++ REPLACE
|
||||
------- SEARCH
|
||||
|
||||
body
|
||||
|
||||
=======
|
||||
new body content
|
||||
+++++++ REPLACE`
|
||||
const result1 = await cnfc(diff, original, isFinal)
|
||||
const expectedResult = "header\nnew body content\nnew footer\n"
|
||||
expect(result1).to.equal(expectedResult)
|
||||
})
|
||||
})
|
||||
|
||||
@@ -5,6 +5,24 @@ const REPLACE_BLOCK_END = "+++++++ REPLACE"
|
||||
const SEARCH_BLOCK_CHAR = "-"
|
||||
const REPLACE_BLOCK_CHAR = "+"
|
||||
|
||||
// Replace the exact string constants with flexible regex patterns
|
||||
const SEARCH_BLOCK_START_REGEX = /^[-]{3,} SEARCH$/
|
||||
const SEARCH_BLOCK_END_REGEX = /^[=]{3,}$/
|
||||
const REPLACE_BLOCK_END_REGEX = /^[+]{3,} REPLACE$/
|
||||
|
||||
// Helper functions to check if a line matches the flexible patterns
|
||||
function isSearchBlockStart(line: string): boolean {
|
||||
return SEARCH_BLOCK_START_REGEX.test(line)
|
||||
}
|
||||
|
||||
function isSearchBlockEnd(line: string): boolean {
|
||||
return SEARCH_BLOCK_END_REGEX.test(line)
|
||||
}
|
||||
|
||||
function isReplaceBlockEnd(line: string): boolean {
|
||||
return REPLACE_BLOCK_END_REGEX.test(line)
|
||||
}
|
||||
|
||||
/**
|
||||
* Attempts a line-trimmed fallback match for the given search content in the original content.
|
||||
* It tries to match `searchContent` lines against a block of lines in `originalContent` starting
|
||||
@@ -211,7 +229,7 @@ export async function constructNewFileContent(
|
||||
diffContent: string,
|
||||
originalContent: string,
|
||||
isFinal: boolean,
|
||||
version: "v1" | "v2" = "v2",
|
||||
version: "v1" | "v2" = "v1",
|
||||
): Promise<string> {
|
||||
const constructor = constructNewFileContentVersionMapping[version]
|
||||
if (!constructor) {
|
||||
@@ -228,9 +246,6 @@ const constructNewFileContentVersionMapping: Record<
|
||||
v2: constructNewFileContentV2,
|
||||
} as const
|
||||
|
||||
/**
|
||||
* @deprecated
|
||||
*/
|
||||
async function constructNewFileContentV1(diffContent: string, originalContent: string, isFinal: boolean): Promise<string> {
|
||||
let result = ""
|
||||
let lastProcessedIndex = 0
|
||||
@@ -243,6 +258,10 @@ async function constructNewFileContentV1(diffContent: string, originalContent: s
|
||||
let searchMatchIndex = -1
|
||||
let searchEndIndex = -1
|
||||
|
||||
// Track all replacements to handle out-of-order edits
|
||||
let replacements: Array<{ start: number; end: number; content: string }> = []
|
||||
let pendingOutOfOrderReplacement = false
|
||||
|
||||
let lines = diffContent.split("\n")
|
||||
|
||||
// If the last line looks like a partial marker but isn't recognized,
|
||||
@@ -251,22 +270,22 @@ async function constructNewFileContentV1(diffContent: string, originalContent: s
|
||||
if (
|
||||
lines.length > 0 &&
|
||||
(lastLine.startsWith(SEARCH_BLOCK_CHAR) || lastLine.startsWith("=") || lastLine.startsWith(REPLACE_BLOCK_CHAR)) &&
|
||||
lastLine !== SEARCH_BLOCK_START &&
|
||||
lastLine !== SEARCH_BLOCK_END &&
|
||||
lastLine !== REPLACE_BLOCK_END
|
||||
!isSearchBlockStart(lastLine) &&
|
||||
!isSearchBlockEnd(lastLine) &&
|
||||
!isReplaceBlockEnd(lastLine)
|
||||
) {
|
||||
lines.pop()
|
||||
}
|
||||
|
||||
for (const line of lines) {
|
||||
if (line === SEARCH_BLOCK_START) {
|
||||
if (isSearchBlockStart(line)) {
|
||||
inSearch = true
|
||||
currentSearchContent = ""
|
||||
currentReplaceContent = ""
|
||||
continue
|
||||
}
|
||||
|
||||
if (line === SEARCH_BLOCK_END) {
|
||||
if (isSearchBlockEnd(line)) {
|
||||
inSearch = false
|
||||
inReplace = true
|
||||
|
||||
@@ -314,31 +333,51 @@ async function constructNewFileContentV1(diffContent: string, originalContent: s
|
||||
if (blockMatch) {
|
||||
;[searchMatchIndex, searchEndIndex] = blockMatch
|
||||
} else {
|
||||
throw new Error(
|
||||
`The SEARCH block:\n${currentSearchContent.trimEnd()}\n...does not match anything in the file or was searched out of order in the provided blocks.`,
|
||||
)
|
||||
// Last resort: search the entire file from the beginning
|
||||
const fullFileIndex = originalContent.indexOf(currentSearchContent, 0)
|
||||
if (fullFileIndex !== -1) {
|
||||
// Found in the file - could be out of order
|
||||
searchMatchIndex = fullFileIndex
|
||||
searchEndIndex = fullFileIndex + currentSearchContent.length
|
||||
if (searchMatchIndex < lastProcessedIndex) {
|
||||
pendingOutOfOrderReplacement = true
|
||||
}
|
||||
} else {
|
||||
throw new Error(
|
||||
`The SEARCH block:\n${currentSearchContent.trimEnd()}\n...does not match anything in the file.`,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Output everything up to the match location
|
||||
result += originalContent.slice(lastProcessedIndex, searchMatchIndex)
|
||||
// Check if this is an out-of-order replacement
|
||||
if (searchMatchIndex < lastProcessedIndex) {
|
||||
pendingOutOfOrderReplacement = true
|
||||
}
|
||||
|
||||
// For in-order replacements, output everything up to the match location
|
||||
if (!pendingOutOfOrderReplacement) {
|
||||
result += originalContent.slice(lastProcessedIndex, searchMatchIndex)
|
||||
}
|
||||
continue
|
||||
}
|
||||
|
||||
if (line === REPLACE_BLOCK_END) {
|
||||
if (isReplaceBlockEnd(line)) {
|
||||
// Finished one replace block
|
||||
|
||||
// // Remove the artificially added linebreak in the last line of the REPLACE block
|
||||
// if (result.endsWith("\r\n")) {
|
||||
// result = result.slice(0, -2)
|
||||
// } else if (result.endsWith("\n")) {
|
||||
// result = result.slice(0, -1)
|
||||
// }
|
||||
// Store this replacement
|
||||
replacements.push({
|
||||
start: searchMatchIndex,
|
||||
end: searchEndIndex,
|
||||
content: currentReplaceContent,
|
||||
})
|
||||
|
||||
// Advance lastProcessedIndex to after the matched section
|
||||
lastProcessedIndex = searchEndIndex
|
||||
// If this was an in-order replacement, advance lastProcessedIndex
|
||||
if (!pendingOutOfOrderReplacement) {
|
||||
lastProcessedIndex = searchEndIndex
|
||||
}
|
||||
|
||||
// Reset for next block
|
||||
inSearch = false
|
||||
@@ -347,6 +386,7 @@ async function constructNewFileContentV1(diffContent: string, originalContent: s
|
||||
currentReplaceContent = ""
|
||||
searchMatchIndex = -1
|
||||
searchEndIndex = -1
|
||||
pendingOutOfOrderReplacement = false
|
||||
continue
|
||||
}
|
||||
|
||||
@@ -358,16 +398,59 @@ async function constructNewFileContentV1(diffContent: string, originalContent: s
|
||||
currentSearchContent += line + "\n"
|
||||
} else if (inReplace) {
|
||||
currentReplaceContent += line + "\n"
|
||||
// Output replacement lines immediately if we know the insertion point
|
||||
if (searchMatchIndex !== -1) {
|
||||
// Only output replacement lines immediately for in-order replacements
|
||||
if (searchMatchIndex !== -1 && !pendingOutOfOrderReplacement) {
|
||||
result += line + "\n"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// If this is the final chunk, append any remaining original content
|
||||
if (isFinal && lastProcessedIndex < originalContent.length) {
|
||||
result += originalContent.slice(lastProcessedIndex)
|
||||
// If this is the final chunk, we need to apply all replacements and build the final result
|
||||
if (isFinal) {
|
||||
// Handle the case where we're still in replace mode when processing ends
|
||||
// and this is the final chunk - treat it as if we encountered the REPLACE marker
|
||||
if (inReplace && searchMatchIndex !== -1) {
|
||||
// Store this replacement
|
||||
replacements.push({
|
||||
start: searchMatchIndex,
|
||||
end: searchEndIndex,
|
||||
content: currentReplaceContent,
|
||||
})
|
||||
|
||||
// If this was an in-order replacement, advance lastProcessedIndex
|
||||
if (!pendingOutOfOrderReplacement) {
|
||||
lastProcessedIndex = searchEndIndex
|
||||
}
|
||||
|
||||
// Reset state
|
||||
inSearch = false
|
||||
inReplace = false
|
||||
currentSearchContent = ""
|
||||
currentReplaceContent = ""
|
||||
searchMatchIndex = -1
|
||||
searchEndIndex = -1
|
||||
pendingOutOfOrderReplacement = false
|
||||
}
|
||||
// end of handling missing replace marker
|
||||
|
||||
// Sort replacements by start position
|
||||
replacements.sort((a, b) => a.start - b.start)
|
||||
|
||||
// Rebuild the entire result by applying all replacements
|
||||
result = ""
|
||||
let currentPos = 0
|
||||
|
||||
for (const replacement of replacements) {
|
||||
// Add original content up to this replacement
|
||||
result += originalContent.slice(currentPos, replacement.start)
|
||||
// Add the replacement content
|
||||
result += replacement.content
|
||||
// Move position to after the replaced section
|
||||
currentPos = replacement.end
|
||||
}
|
||||
|
||||
// Add any remaining original content
|
||||
result += originalContent.slice(currentPos)
|
||||
}
|
||||
|
||||
return result
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
import { constructNewFileContent as cnfc2 } from "./diff"
|
||||
import { constructNewFileContent as cnfc } from "./diff"
|
||||
import { describe, it } from "mocha"
|
||||
import { expect } from "chai"
|
||||
|
||||
async function cnfc(diffContent: string, originalContent: string, isFinal: boolean): Promise<string> {
|
||||
return cnfc2(diffContent, originalContent, isFinal, "v1")
|
||||
async function cnfc2(diffContent: string, originalContent: string, isFinal: boolean): Promise<string> {
|
||||
return cnfc(diffContent, originalContent, isFinal, "v2")
|
||||
}
|
||||
|
||||
describe("Diff Format Edge Cases", () => {
|
||||
@@ -17,8 +17,9 @@ new content
|
||||
+++++++ REPLACE`
|
||||
const result1 = await cnfc(diff, original, isFinal)
|
||||
const result2 = await cnfc2(diff, original, isFinal)
|
||||
expect(result1).to.equal("new content\n")
|
||||
expect(result2).to.equal("before\nnew content\nafter")
|
||||
const expectedResult = "before\nnew content\nafter"
|
||||
expect(result1).to.equal(expectedResult)
|
||||
expect(result2).to.equal(expectedResult)
|
||||
})
|
||||
|
||||
it("should handle SEARCH prefix symbols - more than 7", async () => {
|
||||
@@ -31,8 +32,9 @@ new content
|
||||
+++++++ REPLACE`
|
||||
const result1 = await cnfc(diff, original, isFinal)
|
||||
const result2 = await cnfc2(diff, original, isFinal)
|
||||
expect(result1).to.equal("new content\n")
|
||||
expect(result2).to.equal("before\nnew content\nafter")
|
||||
const expectedResult = "before\nnew content\nafter"
|
||||
expect(result1).to.equal(expectedResult)
|
||||
expect(result2).to.equal(expectedResult)
|
||||
})
|
||||
|
||||
it("should handle SEARCH - less than 7 and REPLACE = less than 7", async () => {
|
||||
@@ -45,8 +47,9 @@ new content
|
||||
+++++++ REPLACE`
|
||||
const result1 = await cnfc(diff, original, isFinal)
|
||||
const result2 = await cnfc2(diff, original, isFinal)
|
||||
expect(result1).to.equal("r")
|
||||
expect(result2).to.equal("before\nnew content\nafter")
|
||||
const expectedResult = "before\nnew content\nafter"
|
||||
expect(result1).to.equal(expectedResult)
|
||||
expect(result2).to.equal(expectedResult)
|
||||
})
|
||||
|
||||
it("should handle SEARCH - less than 7 and REPLACE = more than 7", async () => {
|
||||
@@ -59,7 +62,7 @@ new content
|
||||
+++++++ REPLACE`
|
||||
const result1 = await cnfc(diff, original, isFinal)
|
||||
const result2 = await cnfc2(diff, original, isFinal)
|
||||
expect(result1).to.equal("r")
|
||||
expect(result1).to.equal("before\nnew content\nafter")
|
||||
expect(result2).to.equal("before\nnew content\nafter")
|
||||
})
|
||||
|
||||
@@ -73,8 +76,9 @@ new content
|
||||
+++++++ REPLACE`
|
||||
const result1 = await cnfc(diff, original, isFinal)
|
||||
const result2 = await cnfc2(diff, original, isFinal)
|
||||
expect(result1).to.equal("r")
|
||||
expect(result2).to.equal("before\nnew content\nafter")
|
||||
const expectedResult = "before\nnew content\nafter"
|
||||
expect(result1).to.equal(expectedResult)
|
||||
expect(result2).to.equal(expectedResult)
|
||||
})
|
||||
|
||||
it("should handle SEARCH - more than 7 and REPLACE = less than 7", async () => {
|
||||
@@ -87,8 +91,9 @@ new content
|
||||
+++++++ REPLACE`
|
||||
const result1 = await cnfc(diff, original, isFinal)
|
||||
const result2 = await cnfc2(diff, original, isFinal)
|
||||
expect(result1).to.equal("r")
|
||||
expect(result2).to.equal("before\nnew content\nafter")
|
||||
const expectedResult = "before\nnew content\nafter"
|
||||
expect(result1).to.equal(expectedResult)
|
||||
expect(result2).to.equal(expectedResult)
|
||||
})
|
||||
|
||||
it("should handle consecutive SEARCH-REPLACE with second block SEARCH - less than 7", async () => {
|
||||
@@ -106,8 +111,9 @@ second new content
|
||||
+++++++ REPLACE`
|
||||
const result1 = await cnfc(diff, original, isFinal)
|
||||
const result2 = await cnfc2(diff, original, isFinal)
|
||||
expect(result1).to.equal("before\nfirst new content\nsecond new content\n")
|
||||
expect(result2).to.equal("before\nfirst new content\nafter\nsecond new content\nend")
|
||||
const expectedResult = "before\nfirst new content\nafter\nsecond new content\nend"
|
||||
expect(result1).to.equal(expectedResult)
|
||||
expect(result2).to.equal(expectedResult)
|
||||
})
|
||||
|
||||
it("should handle consecutive SEARCH-REPLACE with second block SEARCH - less than 7 and REPLACE = less than 7", async () => {
|
||||
@@ -125,7 +131,8 @@ second new content
|
||||
+++++++ REPLACE`
|
||||
const result1 = await cnfc(diff, original, isFinal)
|
||||
const result2 = await cnfc2(diff, original, isFinal)
|
||||
expect(result1).to.equal("before\nfirst new content\nd")
|
||||
expect(result2).to.equal("before\nfirst new content\nafter\nsecond new content\nend")
|
||||
const expectedResult = "before\nfirst new content\nafter\nsecond new content\nend"
|
||||
expect(result1).to.equal(expectedResult)
|
||||
expect(result2).to.equal(expectedResult)
|
||||
})
|
||||
})
|
||||
|
||||
@@ -1,361 +1,361 @@
|
||||
import { constructNewFileContent as cnfc2 } from "./diff"
|
||||
import { describe, it } from "mocha"
|
||||
import { expect } from "chai"
|
||||
// import { constructNewFileContent as cnfc } from "./diff"
|
||||
// import { describe, it } from "mocha"
|
||||
// import { expect } from "chai"
|
||||
|
||||
async function cnfc(diffContent: string, originalContent: string, isFinal: boolean): Promise<string> {
|
||||
return cnfc2(diffContent, originalContent, isFinal, "v1")
|
||||
}
|
||||
// async function cnfc2(diffContent: string, originalContent: string, isFinal: boolean): Promise<string> {
|
||||
// return cnfc(diffContent, originalContent, isFinal, "v2")
|
||||
// }
|
||||
|
||||
describe("Diff Format Edge Cases", () => {
|
||||
it("should handle missing search block", async () => {
|
||||
const original = "line1\nline2"
|
||||
const diff = `=======
|
||||
new content
|
||||
+++++++ REPLACE`
|
||||
const result1 = await cnfc(diff, original, true)
|
||||
expect(result1).to.equal("new content\n")
|
||||
try {
|
||||
await cnfc2(diff, original, true)
|
||||
expect.fail("Expected an error to be thrown")
|
||||
} catch (err) {
|
||||
expect(err).to.be.an("error")
|
||||
}
|
||||
})
|
||||
// describe("Diff Format Edge Cases", () => {
|
||||
// it("should handle missing search block", async () => {
|
||||
// const original = "line1\nline2"
|
||||
// const diff = `=======
|
||||
// new content
|
||||
// +++++++ REPLACE`
|
||||
// const result1 = await cnfc(diff, original, true)
|
||||
// expect(result1).to.equal("new content\n")
|
||||
// try {
|
||||
// await cnfc2(diff, original, true)
|
||||
// expect.fail("Expected an error to be thrown")
|
||||
// } catch (err) {
|
||||
// expect(err).to.be.an("error")
|
||||
// }
|
||||
// })
|
||||
|
||||
it("should handle consecutive search blocks", async () => {
|
||||
const original = "text"
|
||||
const diff = `------- SEARCH
|
||||
=======
|
||||
replaced
|
||||
+++++++ REPLACE
|
||||
------- SEARCH
|
||||
=======
|
||||
another
|
||||
+++++++ REPLACE`
|
||||
const result1 = await cnfc(diff, original, true)
|
||||
expect(result1).to.equal("replaced\nanother\n")
|
||||
try {
|
||||
await cnfc2(diff, original, true)
|
||||
expect.fail("Expected an error to be thrown")
|
||||
} catch (err) {
|
||||
expect(err).to.be.an("error")
|
||||
}
|
||||
})
|
||||
// it("should handle consecutive search blocks", async () => {
|
||||
// const original = "text"
|
||||
// const diff = `------- SEARCH
|
||||
// =======
|
||||
// replaced
|
||||
// +++++++ REPLACE
|
||||
// ------- SEARCH
|
||||
// =======
|
||||
// another
|
||||
// +++++++ REPLACE`
|
||||
// const result1 = await cnfc(diff, original, true)
|
||||
// expect(result1).to.equal("replaced\nanother\n")
|
||||
// try {
|
||||
// await cnfc2(diff, original, true)
|
||||
// expect.fail("Expected an error to be thrown")
|
||||
// } catch (err) {
|
||||
// expect(err).to.be.an("error")
|
||||
// }
|
||||
// })
|
||||
|
||||
it("should handle reverse markers order", async () => {
|
||||
const original = "content"
|
||||
const diff = `+++++++ SEARCH
|
||||
=======
|
||||
invalid
|
||||
------- REPLACE`
|
||||
const result1 = await cnfc(diff, original, true)
|
||||
expect(result1).to.equal("invalid\ncontent")
|
||||
try {
|
||||
await cnfc2(diff, original, true)
|
||||
expect.fail("Expected an error to be thrown")
|
||||
} catch (err) {
|
||||
expect(err).to.be.an("error")
|
||||
}
|
||||
})
|
||||
// it("should handle reverse markers order", async () => {
|
||||
// const original = "content"
|
||||
// const diff = `+++++++ SEARCH
|
||||
// =======
|
||||
// invalid
|
||||
// ------- REPLACE`
|
||||
// const result1 = await cnfc(diff, original, true)
|
||||
// expect(result1).to.equal("invalid\ncontent")
|
||||
// try {
|
||||
// await cnfc2(diff, original, true)
|
||||
// expect.fail("Expected an error to be thrown")
|
||||
// } catch (err) {
|
||||
// expect(err).to.be.an("error")
|
||||
// }
|
||||
// })
|
||||
|
||||
it("should handle incomplete block structure", async () => {
|
||||
const original = "valid text"
|
||||
const diff = `------- SEARCH
|
||||
text
|
||||
+++++++ REPLACE`
|
||||
const result1 = await cnfc(diff, original, true)
|
||||
expect(result1).to.equal("t")
|
||||
try {
|
||||
await cnfc2(diff, original, true)
|
||||
expect.fail("Expected an error to be thrown")
|
||||
} catch (err) {
|
||||
expect(err).to.be.an("error")
|
||||
}
|
||||
})
|
||||
// it("should handle incomplete block structure", async () => {
|
||||
// const original = "valid text"
|
||||
// const diff = `------- SEARCH
|
||||
// text
|
||||
// +++++++ REPLACE`
|
||||
// const result1 = await cnfc(diff, original, true)
|
||||
// expect(result1).to.equal("t")
|
||||
// try {
|
||||
// await cnfc2(diff, original, true)
|
||||
// expect.fail("Expected an error to be thrown")
|
||||
// } catch (err) {
|
||||
// expect(err).to.be.an("error")
|
||||
// }
|
||||
// })
|
||||
|
||||
it("should handle empty search block", async () => {
|
||||
const original = "any content"
|
||||
const diff = `------- SEARCH
|
||||
=======
|
||||
inserted
|
||||
+++++++ REPLACE`
|
||||
const result1 = await cnfc(diff, original, true)
|
||||
const result2 = await cnfc2(diff, original, true)
|
||||
expect(result1).to.equal("inserted\n")
|
||||
expect(result1).to.equal(result2)
|
||||
})
|
||||
// it("should handle empty search block", async () => {
|
||||
// const original = "any content"
|
||||
// const diff = `------- SEARCH
|
||||
// =======
|
||||
// inserted
|
||||
// +++++++ REPLACE`
|
||||
// const result1 = await cnfc(diff, original, true)
|
||||
// const result2 = await cnfc2(diff, original, true)
|
||||
// expect(result1).to.equal("inserted\n")
|
||||
// expect(result1).to.equal(result2)
|
||||
// })
|
||||
|
||||
it("should handle mixed line endings", async () => {
|
||||
const original = "line1\r\nline2"
|
||||
const diff = `------- SEARCH
|
||||
line1\r
|
||||
=======
|
||||
line1
|
||||
+++++++ REPLACE`
|
||||
const result1 = await cnfc(diff, original, true)
|
||||
const result2 = await cnfc2(diff, original, true)
|
||||
expect(result1).to.equal("line1\nline2")
|
||||
expect(result1).to.equal(result2)
|
||||
})
|
||||
// it("should handle mixed line endings", async () => {
|
||||
// const original = "line1\r\nline2"
|
||||
// const diff = `------- SEARCH
|
||||
// line1\r
|
||||
// =======
|
||||
// line1
|
||||
// +++++++ REPLACE`
|
||||
// const result1 = await cnfc(diff, original, true)
|
||||
// const result2 = await cnfc2(diff, original, true)
|
||||
// expect(result1).to.equal("line1\nline2")
|
||||
// expect(result1).to.equal(result2)
|
||||
// })
|
||||
|
||||
it("should handle special characters in search", async () => {
|
||||
const original = "text with $^.*\nend"
|
||||
const diff = `------- SEARCH
|
||||
$^.*
|
||||
=======
|
||||
replaced
|
||||
+++++++ REPLACE`
|
||||
const result1 = await cnfc(diff, original, true)
|
||||
const result2 = await cnfc2(diff, original, true)
|
||||
expect(result1).to.equal("text with replaced\nend")
|
||||
expect(result1).to.equal(result2)
|
||||
})
|
||||
// it("should handle special characters in search", async () => {
|
||||
// const original = "text with $^.*\nend"
|
||||
// const diff = `------- SEARCH
|
||||
// $^.*
|
||||
// =======
|
||||
// replaced
|
||||
// +++++++ REPLACE`
|
||||
// const result1 = await cnfc(diff, original, true)
|
||||
// const result2 = await cnfc2(diff, original, true)
|
||||
// expect(result1).to.equal("text with replaced\nend")
|
||||
// expect(result1).to.equal(result2)
|
||||
// })
|
||||
|
||||
it("should handle special regex chars and nested search markers", async () => {
|
||||
const original = `text with $^.*\n--- SEARCH\nend`
|
||||
const diff = `------- SEARCH
|
||||
$^.*
|
||||
=======
|
||||
replaced
|
||||
+++++++ REPLACE
|
||||
// it("should handle special regex chars and nested search markers", async () => {
|
||||
// const original = `text with $^.*\n--- SEARCH\nend`
|
||||
// const diff = `------- SEARCH
|
||||
// $^.*
|
||||
// =======
|
||||
// replaced
|
||||
// +++++++ REPLACE
|
||||
|
||||
------- SEARCH
|
||||
--- SEARCH
|
||||
=======
|
||||
before
|
||||
+++++++ REPLACE`
|
||||
const result1 = await cnfc(diff, original, true)
|
||||
const result2 = await cnfc2(diff, original, true)
|
||||
expect(result1).to.equal("text with replaced\nbefore\nend")
|
||||
expect(result1).to.equal(result2)
|
||||
})
|
||||
// ------- SEARCH
|
||||
// --- SEARCH
|
||||
// =======
|
||||
// before
|
||||
// +++++++ REPLACE`
|
||||
// const result1 = await cnfc(diff, original, true)
|
||||
// const result2 = await cnfc2(diff, original, true)
|
||||
// expect(result1).to.equal("text with replaced\nbefore\nend")
|
||||
// expect(result1).to.equal(result2)
|
||||
// })
|
||||
|
||||
it("cnfc2 should handle invalid search marker format", async () => {
|
||||
const original = `text with $^.*\n--- SEARCH\nend`
|
||||
const diff = `--- SEARCH
|
||||
$^.*
|
||||
=======
|
||||
replaced
|
||||
+++++++ REPLACE
|
||||
// it("cnfc2 should handle invalid search marker format", async () => {
|
||||
// const original = `text with $^.*\n--- SEARCH\nend`
|
||||
// const diff = `--- SEARCH
|
||||
// $^.*
|
||||
// =======
|
||||
// replaced
|
||||
// +++++++ REPLACE
|
||||
|
||||
------- SEARCH
|
||||
--- SEARCH
|
||||
=======
|
||||
before
|
||||
+++++++ REPLACE`
|
||||
try {
|
||||
await cnfc(diff, original, true)
|
||||
expect.fail("Expected an error to be thrown")
|
||||
} catch (err) {
|
||||
expect(err).to.be.an("error")
|
||||
}
|
||||
const result2 = await cnfc2(diff, original, true)
|
||||
expect(result2).to.equal("text with replaced\nbefore\nend")
|
||||
})
|
||||
// ------- SEARCH
|
||||
// --- SEARCH
|
||||
// =======
|
||||
// before
|
||||
// +++++++ REPLACE`
|
||||
// try {
|
||||
// await cnfc(diff, original, true)
|
||||
// expect.fail("Expected an error to be thrown")
|
||||
// } catch (err) {
|
||||
// expect(err).to.be.an("error")
|
||||
// }
|
||||
// const result2 = await cnfc2(diff, original, true)
|
||||
// expect(result2).to.equal("text with replaced\nbefore\nend")
|
||||
// })
|
||||
|
||||
it("cnfc2 should throw error for incomplete search marker", async () => {
|
||||
const original = `text with $^.*\n--- SEARCH\nend`
|
||||
const diff = `--- SEARCH
|
||||
$^.*
|
||||
=======
|
||||
replaced
|
||||
+++++++ REPLACE
|
||||
// it("cnfc2 should throw error for incomplete search marker", async () => {
|
||||
// const original = `text with $^.*\n--- SEARCH\nend`
|
||||
// const diff = `--- SEARCH
|
||||
// $^.*
|
||||
// =======
|
||||
// replaced
|
||||
// +++++++ REPLACE
|
||||
|
||||
------ SEARCH
|
||||
--- SEARCH
|
||||
=======
|
||||
before
|
||||
+++++++ REPLACE`
|
||||
const result1 = await cnfc(diff, original, true)
|
||||
expect(result1).to.equal("replaced\nbefore\n")
|
||||
try {
|
||||
await cnfc2(diff, original, true)
|
||||
expect.fail("Expected an error to be thrown")
|
||||
} catch (err) {
|
||||
expect(err).to.be.an("error")
|
||||
}
|
||||
})
|
||||
// ------ SEARCH
|
||||
// --- SEARCH
|
||||
// =======
|
||||
// before
|
||||
// +++++++ REPLACE`
|
||||
// const result1 = await cnfc(diff, original, true)
|
||||
// expect(result1).to.equal("replaced\nbefore\n")
|
||||
// try {
|
||||
// await cnfc2(diff, original, true)
|
||||
// expect.fail("Expected an error to be thrown")
|
||||
// } catch (err) {
|
||||
// expect(err).to.be.an("error")
|
||||
// }
|
||||
// })
|
||||
|
||||
it("cnfc2 should handle custom nested search markers", async () => {
|
||||
const original = `text with $^.*\n--- SEARCH2\nend`
|
||||
const diff = `--- SEARCH
|
||||
$^.*
|
||||
=======
|
||||
replaced
|
||||
+++++++ REPLACE
|
||||
// it("cnfc2 should handle custom nested search markers", async () => {
|
||||
// const original = `text with $^.*\n--- SEARCH2\nend`
|
||||
// const diff = `--- SEARCH
|
||||
// $^.*
|
||||
// =======
|
||||
// replaced
|
||||
// +++++++ REPLACE
|
||||
|
||||
------ SEARCH
|
||||
--- SEARCH2
|
||||
=======
|
||||
before
|
||||
+++++++ REPLACE`
|
||||
const result1 = await cnfc(diff, original, true)
|
||||
const result2 = await cnfc2(diff, original, true)
|
||||
expect(result1).to.equal("replaced\nbefore\n")
|
||||
expect(result2).to.equal("text with replaced\nbefore\nend")
|
||||
})
|
||||
// ------ SEARCH
|
||||
// --- SEARCH2
|
||||
// =======
|
||||
// before
|
||||
// +++++++ REPLACE`
|
||||
// const result1 = await cnfc(diff, original, true)
|
||||
// const result2 = await cnfc2(diff, original, true)
|
||||
// expect(result1).to.equal("replaced\nbefore\n")
|
||||
// expect(result2).to.equal("text with replaced\nbefore\nend")
|
||||
// })
|
||||
|
||||
it("cnfc2 should handle text containing nested search markers", async () => {
|
||||
const original = `text with $^.*\ntext with --- SEARCH2\nend`
|
||||
const diff = `--- SEARCH
|
||||
$^.*
|
||||
=======
|
||||
replaced
|
||||
+++++++ REPLACE
|
||||
// it("cnfc2 should handle text containing nested search markers", async () => {
|
||||
// const original = `text with $^.*\ntext with --- SEARCH2\nend`
|
||||
// const diff = `--- SEARCH
|
||||
// $^.*
|
||||
// =======
|
||||
// replaced
|
||||
// +++++++ REPLACE
|
||||
|
||||
------ SEARCH
|
||||
text with --- SEARCH2
|
||||
=======
|
||||
before
|
||||
+++++++ REPLACE`
|
||||
const result1 = await cnfc(diff, original, true)
|
||||
const result2 = await cnfc2(diff, original, true)
|
||||
expect(result1).to.equal("replaced\nbefore\n")
|
||||
expect(result2).to.equal("text with replaced\nbefore\nend")
|
||||
})
|
||||
// ------ SEARCH
|
||||
// text with --- SEARCH2
|
||||
// =======
|
||||
// before
|
||||
// +++++++ REPLACE`
|
||||
// const result1 = await cnfc(diff, original, true)
|
||||
// const result2 = await cnfc2(diff, original, true)
|
||||
// expect(result1).to.equal("replaced\nbefore\n")
|
||||
// expect(result2).to.equal("text with replaced\nbefore\nend")
|
||||
// })
|
||||
|
||||
it("cnfc2 should handle missing replacement marker in lenient mode", async () => {
|
||||
const original = `text with $^.*\ntext with --- SEARCH2\nend`
|
||||
const diff = `--- SEARCH
|
||||
$^.*
|
||||
=======
|
||||
replaced
|
||||
+++++++ REPLACE
|
||||
// it("cnfc2 should handle missing replacement marker in lenient mode", async () => {
|
||||
// const original = `text with $^.*\ntext with --- SEARCH2\nend`
|
||||
// const diff = `--- SEARCH
|
||||
// $^.*
|
||||
// =======
|
||||
// replaced
|
||||
// +++++++ REPLACE
|
||||
|
||||
------ SEARCH
|
||||
text with --- SEARCH2
|
||||
=======
|
||||
before`
|
||||
const result1 = await cnfc(diff, original, false)
|
||||
const result2 = await cnfc2(diff, original, false)
|
||||
expect(result1).to.equal("replaced\nbefore\n")
|
||||
expect(result2).to.equal("text with replaced\nbefore\n")
|
||||
})
|
||||
// ------ SEARCH
|
||||
// text with --- SEARCH2
|
||||
// =======
|
||||
// before`
|
||||
// const result1 = await cnfc(diff, original, false)
|
||||
// const result2 = await cnfc2(diff, original, false)
|
||||
// expect(result1).to.equal("replaced\nbefore\n")
|
||||
// expect(result2).to.equal("text with replaced\nbefore\n")
|
||||
// })
|
||||
|
||||
it("cnfc2 should throw error for missing replacement marker in strict mode", async () => {
|
||||
const original = `text with $^.*\ntext with --- SEARCH2\nend`
|
||||
const diff = `--- SEARCH
|
||||
$^.*
|
||||
=======
|
||||
replaced
|
||||
+++++++ REPLACE
|
||||
// it("cnfc2 should throw error for missing replacement marker in strict mode", async () => {
|
||||
// const original = `text with $^.*\ntext with --- SEARCH2\nend`
|
||||
// const diff = `--- SEARCH
|
||||
// $^.*
|
||||
// =======
|
||||
// replaced
|
||||
// +++++++ REPLACE
|
||||
|
||||
------ SEARCH
|
||||
text with --- SEARCH2
|
||||
=======
|
||||
before`
|
||||
const result1 = await cnfc(diff, original, true)
|
||||
expect(result1).to.equal("replaced\nbefore\n")
|
||||
try {
|
||||
await cnfc2(diff, original, true)
|
||||
expect.fail("Expected an error to be thrown")
|
||||
} catch (err) {
|
||||
expect(err).to.be.an("error")
|
||||
}
|
||||
})
|
||||
// ------ SEARCH
|
||||
// text with --- SEARCH2
|
||||
// =======
|
||||
// before`
|
||||
// const result1 = await cnfc(diff, original, true)
|
||||
// expect(result1).to.equal("replaced\nbefore\n")
|
||||
// try {
|
||||
// await cnfc2(diff, original, true)
|
||||
// expect.fail("Expected an error to be thrown")
|
||||
// } catch (err) {
|
||||
// expect(err).to.be.an("error")
|
||||
// }
|
||||
// })
|
||||
|
||||
it("cnfc2 should handle long text with multiple search-replace blocks", async () => {
|
||||
const original = `This is a long text with multiple sections.
|
||||
Section 1: Lorem ipsum dolor sit amet
|
||||
Section 2: consectetur adipiscing elit
|
||||
Section 3: sed do eiusmod tempor
|
||||
Section 4: incididunt ut labore
|
||||
Section 5: et dolore magna aliqua`
|
||||
// it("cnfc2 should handle long text with multiple search-replace blocks", async () => {
|
||||
// const original = `This is a long text with multiple sections.
|
||||
// Section 1: Lorem ipsum dolor sit amet
|
||||
// Section 2: consectetur adipiscing elit
|
||||
// Section 3: sed do eiusmod tempor
|
||||
// Section 4: incididunt ut labore
|
||||
// Section 5: et dolore magna aliqua`
|
||||
|
||||
const diff = `--- SEARCH
|
||||
Section 1: Lorem ipsum dolor sit amet
|
||||
=======
|
||||
Section 1: Replaced text
|
||||
+++++++ REPLACE
|
||||
// const diff = `--- SEARCH
|
||||
// Section 1: Lorem ipsum dolor sit amet
|
||||
// =======
|
||||
// Section 1: Replaced text
|
||||
// +++++++ REPLACE
|
||||
|
||||
------- SEARCH
|
||||
Section 3: sed do eiusmod tempor
|
||||
=======
|
||||
Section 3: Modified content
|
||||
+++++++ REPLACE
|
||||
// ------- SEARCH
|
||||
// Section 3: sed do eiusmod tempor
|
||||
// =======
|
||||
// Section 3: Modified content
|
||||
// +++++++ REPLACE
|
||||
|
||||
------- SEARCH
|
||||
Section 5: et dolore magna aliqua
|
||||
=======
|
||||
Section 5: Final replacement
|
||||
+++++++ REPLACE`
|
||||
// ------- SEARCH
|
||||
// Section 5: et dolore magna aliqua
|
||||
// =======
|
||||
// Section 5: Final replacement
|
||||
// +++++++ REPLACE`
|
||||
|
||||
const expected = `This is a long text with multiple sections.
|
||||
Section 1: Replaced text
|
||||
Section 2: consectetur adipiscing elit
|
||||
Section 3: Modified content
|
||||
Section 4: incididunt ut labore
|
||||
Section 5: Final replacement
|
||||
`
|
||||
// const expected = `This is a long text with multiple sections.
|
||||
// Section 1: Replaced text
|
||||
// Section 2: consectetur adipiscing elit
|
||||
// Section 3: Modified content
|
||||
// Section 4: incididunt ut labore
|
||||
// Section 5: Final replacement
|
||||
// `
|
||||
|
||||
const result = await cnfc2(diff, original, true)
|
||||
expect(result).to.equal(expected)
|
||||
})
|
||||
// const result = await cnfc2(diff, original, true)
|
||||
// expect(result).to.equal(expected)
|
||||
// })
|
||||
|
||||
// Test diff containing special regex characters and nested search markers
|
||||
const diff = `--- SEARCH
|
||||
$^.*
|
||||
=======
|
||||
replaced
|
||||
+++++++ REPLACE
|
||||
// // Test diff containing special regex characters and nested search markers
|
||||
// const diff = `--- SEARCH
|
||||
// $^.*
|
||||
// =======
|
||||
// replaced
|
||||
// +++++++ REPLACE
|
||||
|
||||
------ SEARCH
|
||||
--- SEARCH
|
||||
=======
|
||||
before
|
||||
+++++++ REPLACE`
|
||||
// expected1 shows the incremental results when processing the diff line by line
|
||||
// Each element represents the result after processing that line number
|
||||
const expected1 = [
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
"replaced\n",
|
||||
"replaced\n",
|
||||
"replaced\n",
|
||||
"replaced\n",
|
||||
"replaced\n",
|
||||
"replaced\n",
|
||||
"replaced\nbefore\n",
|
||||
]
|
||||
// expected2 shows the results when processing with original content
|
||||
// Each element represents the result after processing that line number
|
||||
const expected2 = [
|
||||
"",
|
||||
"",
|
||||
"text with ",
|
||||
"text with replaced\n",
|
||||
"text with replaced\n",
|
||||
"text with replaced\n",
|
||||
"text with replaced\n",
|
||||
"text with replaced\n",
|
||||
new Error(),
|
||||
new Error(),
|
||||
]
|
||||
const diffLines = diff.split("\n")
|
||||
for (let i = 1; i < diffLines.length; i++) {
|
||||
it(`cnfc2 should handle partial diff configuration (line ${i})`, async () => {
|
||||
const original = `text with $^.*\n--- SEARCH\nend`
|
||||
const result1 = await cnfc(diffLines.slice(0, i).join("\n"), original, i === diffLines.length - 1)
|
||||
expect(result1).to.equal(expected1[i - 1])
|
||||
})
|
||||
}
|
||||
// ------ SEARCH
|
||||
// --- SEARCH
|
||||
// =======
|
||||
// before
|
||||
// +++++++ REPLACE`
|
||||
// // expected1 shows the incremental results when processing the diff line by line
|
||||
// // Each element represents the result after processing that line number
|
||||
// const expected1 = [
|
||||
// "",
|
||||
// "",
|
||||
// "",
|
||||
// "replaced\n",
|
||||
// "replaced\n",
|
||||
// "replaced\n",
|
||||
// "replaced\n",
|
||||
// "replaced\n",
|
||||
// "replaced\n",
|
||||
// "replaced\nbefore\n",
|
||||
// ]
|
||||
// // expected2 shows the results when processing with original content
|
||||
// // Each element represents the result after processing that line number
|
||||
// const expected2 = [
|
||||
// "",
|
||||
// "",
|
||||
// "text with ",
|
||||
// "text with replaced\n",
|
||||
// "text with replaced\n",
|
||||
// "text with replaced\n",
|
||||
// "text with replaced\n",
|
||||
// "text with replaced\n",
|
||||
// new Error(),
|
||||
// new Error(),
|
||||
// ]
|
||||
// const diffLines = diff.split("\n")
|
||||
// for (let i = 1; i < diffLines.length; i++) {
|
||||
// it(`cnfc2 should handle partial diff configuration (line ${i})`, async () => {
|
||||
// const original = `text with $^.*\n--- SEARCH\nend`
|
||||
// const result1 = await cnfc(diffLines.slice(0, i).join("\n"), original, i === diffLines.length - 1)
|
||||
// expect(result1).to.equal(expected1[i - 1])
|
||||
// })
|
||||
// }
|
||||
|
||||
for (let i = 1; i < diffLines.length; i++) {
|
||||
it(`cnfc2 should handle partial diff configuration (line ${i})`, async () => {
|
||||
const original = `text with $^.*\n--- SEARCH\nend`
|
||||
let expected = expected2[i - 1]
|
||||
if (expected instanceof Error) {
|
||||
try {
|
||||
await cnfc2(diffLines.slice(0, i).join("\n"), original, true)
|
||||
expect.fail("Expected an error to be thrown")
|
||||
} catch (err) {
|
||||
expect(err).to.be.an("error")
|
||||
}
|
||||
} else {
|
||||
const result2 = await cnfc2(diffLines.slice(0, i).join("\n"), original, i === diffLines.length - 1)
|
||||
expect(result2).to.equal(expected)
|
||||
}
|
||||
})
|
||||
}
|
||||
})
|
||||
// for (let i = 1; i < diffLines.length; i++) {
|
||||
// it(`cnfc2 should handle partial diff configuration (line ${i})`, async () => {
|
||||
// const original = `text with $^.*\n--- SEARCH\nend`
|
||||
// let expected = expected2[i - 1]
|
||||
// if (expected instanceof Error) {
|
||||
// try {
|
||||
// await cnfc2(diffLines.slice(0, i).join("\n"), original, true)
|
||||
// expect.fail("Expected an error to be thrown")
|
||||
// } catch (err) {
|
||||
// expect(err).to.be.an("error")
|
||||
// }
|
||||
// } else {
|
||||
// const result2 = await cnfc2(diffLines.slice(0, i).join("\n"), original, i === diffLines.length - 1)
|
||||
// expect(result2).to.equal(expected)
|
||||
// }
|
||||
// })
|
||||
// }
|
||||
// })
|
||||
|
||||
@@ -40,7 +40,7 @@ const CodeAccordian = ({
|
||||
|
||||
const numberOfEdits = useMemo(() => {
|
||||
if (code) {
|
||||
return (code.match(/\+{7} REPLACE/g) || []).length || undefined
|
||||
return (code.match(/[-]{3,} SEARCH/g) || []).length || undefined
|
||||
}
|
||||
return undefined
|
||||
}, [code])
|
||||
|
||||
Reference in New Issue
Block a user