opencode-gbk-tools 0.1.2 → 0.1.3
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.
|
@@ -16320,6 +16320,20 @@ function assertNotBinary(buffer) {
|
|
|
16320
16320
|
throw createGbkError("GBK_BINARY_FILE", "\u7591\u4F3C\u4E8C\u8FDB\u5236\u6587\u4EF6\uFF0C\u65E0\u6CD5\u6309 GBK \u6587\u672C\u5904\u7406");
|
|
16321
16321
|
}
|
|
16322
16322
|
}
|
|
16323
|
+
function detectNewlineStyle(text) {
|
|
16324
|
+
const crlfCount = (text.match(/\r\n/g) ?? []).length;
|
|
16325
|
+
const lfCount = (text.match(/(^|[^\r])\n/g) ?? []).length;
|
|
16326
|
+
if (crlfCount > 0 && lfCount === 0) {
|
|
16327
|
+
return "crlf";
|
|
16328
|
+
}
|
|
16329
|
+
if (lfCount > 0 && crlfCount === 0) {
|
|
16330
|
+
return "lf";
|
|
16331
|
+
}
|
|
16332
|
+
if (crlfCount > 0 && lfCount > 0) {
|
|
16333
|
+
return "mixed";
|
|
16334
|
+
}
|
|
16335
|
+
return "none";
|
|
16336
|
+
}
|
|
16323
16337
|
function applyLineRange(text, startLine, endLine) {
|
|
16324
16338
|
if (startLine === void 0 && endLine === void 0) {
|
|
16325
16339
|
return {
|
|
@@ -16401,6 +16415,84 @@ function resolveEditScope(text, input) {
|
|
|
16401
16415
|
rangeEnd: anchored.rangeStart + lineRanged.rangeEnd
|
|
16402
16416
|
};
|
|
16403
16417
|
}
|
|
16418
|
+
function normalizeNewlines(text) {
|
|
16419
|
+
return text.replace(/\r\n/g, "\n");
|
|
16420
|
+
}
|
|
16421
|
+
function trimRightSpaces(text) {
|
|
16422
|
+
return text.replace(/[ \t]+$/g, "");
|
|
16423
|
+
}
|
|
16424
|
+
function splitNormalizedLines(text) {
|
|
16425
|
+
return normalizeNewlines(text).split("\n");
|
|
16426
|
+
}
|
|
16427
|
+
function trimTrailingEmptyLines(lines) {
|
|
16428
|
+
const result = [...lines];
|
|
16429
|
+
while (result.length > 0 && trimRightSpaces(result[result.length - 1]) === "") {
|
|
16430
|
+
result.pop();
|
|
16431
|
+
}
|
|
16432
|
+
return result;
|
|
16433
|
+
}
|
|
16434
|
+
function getNearestContext(content, oldString) {
|
|
16435
|
+
const lines = content.split(/\r?\n/);
|
|
16436
|
+
const oldLines = normalizeNewlines(oldString).split("\n").filter(Boolean);
|
|
16437
|
+
const firstToken = oldLines[0] || oldString.trim();
|
|
16438
|
+
for (let index = 0; index < lines.length; index += 1) {
|
|
16439
|
+
if (lines[index].includes(firstToken)) {
|
|
16440
|
+
return lines.slice(index, index + 4).join("\n");
|
|
16441
|
+
}
|
|
16442
|
+
}
|
|
16443
|
+
return lines.slice(0, 4).join("\n");
|
|
16444
|
+
}
|
|
16445
|
+
function buildNoMatchMessage(content, oldString) {
|
|
16446
|
+
return [
|
|
16447
|
+
"\u672A\u627E\u5230\u9700\u8981\u66FF\u6362\u7684\u6587\u672C\u3002",
|
|
16448
|
+
"oldString \u5FC5\u987B\u4E0E\u6587\u4EF6\u5B9E\u9645\u5185\u5BB9\u5B8C\u5168\u5BF9\u5E94\uFF0C\u6216\u4EC5\u5728\u6362\u884C/\u5C3E\u968F\u7A7A\u884C\u4E0A\u5B58\u5728\u8F7B\u5FAE\u5DEE\u5F02\u3002",
|
|
16449
|
+
"\u6700\u63A5\u8FD1\u7684\u4E0A\u4E0B\u6587\uFF1A",
|
|
16450
|
+
getNearestContext(content, oldString)
|
|
16451
|
+
].join("\n");
|
|
16452
|
+
}
|
|
16453
|
+
function tryLooseBlockReplace(content, oldString, newString) {
|
|
16454
|
+
const normalizedContent = normalizeNewlines(content);
|
|
16455
|
+
const contentLines = splitNormalizedLines(content);
|
|
16456
|
+
const oldLines = trimTrailingEmptyLines(splitNormalizedLines(oldString));
|
|
16457
|
+
const newLines = splitNormalizedLines(newString);
|
|
16458
|
+
if (oldLines.length === 0) {
|
|
16459
|
+
return null;
|
|
16460
|
+
}
|
|
16461
|
+
for (let start = 0; start < contentLines.length; start += 1) {
|
|
16462
|
+
let contentIndex = start;
|
|
16463
|
+
let oldIndex = 0;
|
|
16464
|
+
while (oldIndex < oldLines.length && contentIndex < contentLines.length) {
|
|
16465
|
+
const expected = trimRightSpaces(oldLines[oldIndex]);
|
|
16466
|
+
const actual = trimRightSpaces(contentLines[contentIndex]);
|
|
16467
|
+
if (expected === actual) {
|
|
16468
|
+
oldIndex += 1;
|
|
16469
|
+
contentIndex += 1;
|
|
16470
|
+
continue;
|
|
16471
|
+
}
|
|
16472
|
+
if (actual === "") {
|
|
16473
|
+
contentIndex += 1;
|
|
16474
|
+
continue;
|
|
16475
|
+
}
|
|
16476
|
+
if (expected === "") {
|
|
16477
|
+
oldIndex += 1;
|
|
16478
|
+
continue;
|
|
16479
|
+
}
|
|
16480
|
+
break;
|
|
16481
|
+
}
|
|
16482
|
+
if (oldIndex === oldLines.length) {
|
|
16483
|
+
const replacedNormalized = [
|
|
16484
|
+
...contentLines.slice(0, start),
|
|
16485
|
+
...newLines,
|
|
16486
|
+
...contentLines.slice(contentIndex)
|
|
16487
|
+
].join("\n");
|
|
16488
|
+
return {
|
|
16489
|
+
occurrencesBefore: 1,
|
|
16490
|
+
content: detectNewlineStyle(content) === "crlf" ? replacedNormalized.replace(/\n/g, "\r\n") : replacedNormalized
|
|
16491
|
+
};
|
|
16492
|
+
}
|
|
16493
|
+
}
|
|
16494
|
+
return null;
|
|
16495
|
+
}
|
|
16404
16496
|
function countOccurrences(text, target) {
|
|
16405
16497
|
if (target.length === 0) {
|
|
16406
16498
|
throw createGbkError("GBK_EMPTY_OLD_STRING", "oldString \u4E0D\u80FD\u4E3A\u7A7A");
|
|
@@ -16575,12 +16667,28 @@ async function replaceGbkFileText(input) {
|
|
|
16575
16667
|
const current = await readWholeGbkTextFile(resolved);
|
|
16576
16668
|
const scope = resolveEditScope(current.content, input);
|
|
16577
16669
|
const occurrencesBefore = countOccurrences(scope.selectedText, input.oldString);
|
|
16670
|
+
if (!replaceAll && occurrencesBefore === 0) {
|
|
16671
|
+
const loose = tryLooseBlockReplace(scope.selectedText, input.oldString, input.newString);
|
|
16672
|
+
if (loose !== null) {
|
|
16673
|
+
const outputText2 = `${current.content.slice(0, scope.rangeStart)}${loose.content}${current.content.slice(scope.rangeEnd)}`;
|
|
16674
|
+
const buffer2 = import_iconv_lite.default.encode(outputText2, current.encoding);
|
|
16675
|
+
await fs2.writeFile(current.filePath, buffer2);
|
|
16676
|
+
return {
|
|
16677
|
+
filePath: current.filePath,
|
|
16678
|
+
encoding: current.encoding,
|
|
16679
|
+
replacements: 1,
|
|
16680
|
+
occurrencesBefore: loose.occurrencesBefore,
|
|
16681
|
+
bytesRead: current.bytesRead,
|
|
16682
|
+
bytesWritten: buffer2.byteLength
|
|
16683
|
+
};
|
|
16684
|
+
}
|
|
16685
|
+
}
|
|
16578
16686
|
if (replaceAll) {
|
|
16579
16687
|
if (occurrencesBefore === 0) {
|
|
16580
|
-
throw createGbkError("GBK_NO_MATCH",
|
|
16688
|
+
throw createGbkError("GBK_NO_MATCH", buildNoMatchMessage(scope.selectedText, input.oldString));
|
|
16581
16689
|
}
|
|
16582
16690
|
} else if (occurrencesBefore === 0) {
|
|
16583
|
-
throw createGbkError("GBK_NO_MATCH",
|
|
16691
|
+
throw createGbkError("GBK_NO_MATCH", buildNoMatchMessage(scope.selectedText, input.oldString));
|
|
16584
16692
|
} else if (occurrencesBefore > 1) {
|
|
16585
16693
|
throw createGbkError("GBK_MULTIPLE_MATCHES", `\u627E\u5230\u591A\u4E2A\u5339\u914D\u9879: ${input.oldString}`);
|
|
16586
16694
|
}
|
package/dist/plugin/index.js
CHANGED
|
@@ -16466,6 +16466,84 @@ function resolveEditScope(text, input) {
|
|
|
16466
16466
|
rangeEnd: anchored.rangeStart + lineRanged.rangeEnd
|
|
16467
16467
|
};
|
|
16468
16468
|
}
|
|
16469
|
+
function normalizeNewlines(text) {
|
|
16470
|
+
return text.replace(/\r\n/g, "\n");
|
|
16471
|
+
}
|
|
16472
|
+
function trimRightSpaces(text) {
|
|
16473
|
+
return text.replace(/[ \t]+$/g, "");
|
|
16474
|
+
}
|
|
16475
|
+
function splitNormalizedLines(text) {
|
|
16476
|
+
return normalizeNewlines(text).split("\n");
|
|
16477
|
+
}
|
|
16478
|
+
function trimTrailingEmptyLines(lines) {
|
|
16479
|
+
const result = [...lines];
|
|
16480
|
+
while (result.length > 0 && trimRightSpaces(result[result.length - 1]) === "") {
|
|
16481
|
+
result.pop();
|
|
16482
|
+
}
|
|
16483
|
+
return result;
|
|
16484
|
+
}
|
|
16485
|
+
function getNearestContext(content, oldString) {
|
|
16486
|
+
const lines = content.split(/\r?\n/);
|
|
16487
|
+
const oldLines = normalizeNewlines(oldString).split("\n").filter(Boolean);
|
|
16488
|
+
const firstToken = oldLines[0] || oldString.trim();
|
|
16489
|
+
for (let index = 0; index < lines.length; index += 1) {
|
|
16490
|
+
if (lines[index].includes(firstToken)) {
|
|
16491
|
+
return lines.slice(index, index + 4).join("\n");
|
|
16492
|
+
}
|
|
16493
|
+
}
|
|
16494
|
+
return lines.slice(0, 4).join("\n");
|
|
16495
|
+
}
|
|
16496
|
+
function buildNoMatchMessage(content, oldString) {
|
|
16497
|
+
return [
|
|
16498
|
+
"\u672A\u627E\u5230\u9700\u8981\u66FF\u6362\u7684\u6587\u672C\u3002",
|
|
16499
|
+
"oldString \u5FC5\u987B\u4E0E\u6587\u4EF6\u5B9E\u9645\u5185\u5BB9\u5B8C\u5168\u5BF9\u5E94\uFF0C\u6216\u4EC5\u5728\u6362\u884C/\u5C3E\u968F\u7A7A\u884C\u4E0A\u5B58\u5728\u8F7B\u5FAE\u5DEE\u5F02\u3002",
|
|
16500
|
+
"\u6700\u63A5\u8FD1\u7684\u4E0A\u4E0B\u6587\uFF1A",
|
|
16501
|
+
getNearestContext(content, oldString)
|
|
16502
|
+
].join("\n");
|
|
16503
|
+
}
|
|
16504
|
+
function tryLooseBlockReplace(content, oldString, newString) {
|
|
16505
|
+
const normalizedContent = normalizeNewlines(content);
|
|
16506
|
+
const contentLines = splitNormalizedLines(content);
|
|
16507
|
+
const oldLines = trimTrailingEmptyLines(splitNormalizedLines(oldString));
|
|
16508
|
+
const newLines = splitNormalizedLines(newString);
|
|
16509
|
+
if (oldLines.length === 0) {
|
|
16510
|
+
return null;
|
|
16511
|
+
}
|
|
16512
|
+
for (let start = 0; start < contentLines.length; start += 1) {
|
|
16513
|
+
let contentIndex = start;
|
|
16514
|
+
let oldIndex = 0;
|
|
16515
|
+
while (oldIndex < oldLines.length && contentIndex < contentLines.length) {
|
|
16516
|
+
const expected = trimRightSpaces(oldLines[oldIndex]);
|
|
16517
|
+
const actual = trimRightSpaces(contentLines[contentIndex]);
|
|
16518
|
+
if (expected === actual) {
|
|
16519
|
+
oldIndex += 1;
|
|
16520
|
+
contentIndex += 1;
|
|
16521
|
+
continue;
|
|
16522
|
+
}
|
|
16523
|
+
if (actual === "") {
|
|
16524
|
+
contentIndex += 1;
|
|
16525
|
+
continue;
|
|
16526
|
+
}
|
|
16527
|
+
if (expected === "") {
|
|
16528
|
+
oldIndex += 1;
|
|
16529
|
+
continue;
|
|
16530
|
+
}
|
|
16531
|
+
break;
|
|
16532
|
+
}
|
|
16533
|
+
if (oldIndex === oldLines.length) {
|
|
16534
|
+
const replacedNormalized = [
|
|
16535
|
+
...contentLines.slice(0, start),
|
|
16536
|
+
...newLines,
|
|
16537
|
+
...contentLines.slice(contentIndex)
|
|
16538
|
+
].join("\n");
|
|
16539
|
+
return {
|
|
16540
|
+
occurrencesBefore: 1,
|
|
16541
|
+
content: detectNewlineStyle(content) === "crlf" ? replacedNormalized.replace(/\n/g, "\r\n") : replacedNormalized
|
|
16542
|
+
};
|
|
16543
|
+
}
|
|
16544
|
+
}
|
|
16545
|
+
return null;
|
|
16546
|
+
}
|
|
16469
16547
|
function countOccurrences(text, target) {
|
|
16470
16548
|
if (target.length === 0) {
|
|
16471
16549
|
throw createGbkError("GBK_EMPTY_OLD_STRING", "oldString \u4E0D\u80FD\u4E3A\u7A7A");
|
|
@@ -16783,12 +16861,28 @@ async function replaceGbkFileText(input) {
|
|
|
16783
16861
|
const current = await readWholeGbkTextFile(resolved);
|
|
16784
16862
|
const scope = resolveEditScope(current.content, input);
|
|
16785
16863
|
const occurrencesBefore = countOccurrences(scope.selectedText, input.oldString);
|
|
16864
|
+
if (!replaceAll && occurrencesBefore === 0) {
|
|
16865
|
+
const loose = tryLooseBlockReplace(scope.selectedText, input.oldString, input.newString);
|
|
16866
|
+
if (loose !== null) {
|
|
16867
|
+
const outputText2 = `${current.content.slice(0, scope.rangeStart)}${loose.content}${current.content.slice(scope.rangeEnd)}`;
|
|
16868
|
+
const buffer2 = import_iconv_lite.default.encode(outputText2, current.encoding);
|
|
16869
|
+
await fs2.writeFile(current.filePath, buffer2);
|
|
16870
|
+
return {
|
|
16871
|
+
filePath: current.filePath,
|
|
16872
|
+
encoding: current.encoding,
|
|
16873
|
+
replacements: 1,
|
|
16874
|
+
occurrencesBefore: loose.occurrencesBefore,
|
|
16875
|
+
bytesRead: current.bytesRead,
|
|
16876
|
+
bytesWritten: buffer2.byteLength
|
|
16877
|
+
};
|
|
16878
|
+
}
|
|
16879
|
+
}
|
|
16786
16880
|
if (replaceAll) {
|
|
16787
16881
|
if (occurrencesBefore === 0) {
|
|
16788
|
-
throw createGbkError("GBK_NO_MATCH",
|
|
16882
|
+
throw createGbkError("GBK_NO_MATCH", buildNoMatchMessage(scope.selectedText, input.oldString));
|
|
16789
16883
|
}
|
|
16790
16884
|
} else if (occurrencesBefore === 0) {
|
|
16791
|
-
throw createGbkError("GBK_NO_MATCH",
|
|
16885
|
+
throw createGbkError("GBK_NO_MATCH", buildNoMatchMessage(scope.selectedText, input.oldString));
|
|
16792
16886
|
} else if (occurrencesBefore > 1) {
|
|
16793
16887
|
throw createGbkError("GBK_MULTIPLE_MATCHES", `\u627E\u5230\u591A\u4E2A\u5339\u914D\u9879: ${input.oldString}`);
|
|
16794
16888
|
}
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
{
|
|
2
2
|
"manifestVersion": 1,
|
|
3
3
|
"packageName": "opencode-gbk-tools",
|
|
4
|
-
"packageVersion": "0.1.
|
|
4
|
+
"packageVersion": "0.1.3",
|
|
5
5
|
"artifacts": [
|
|
6
6
|
{
|
|
7
7
|
"relativePath": "tools/gbk_edit.js",
|
|
8
8
|
"kind": "tool",
|
|
9
|
-
"expectedHash": "
|
|
9
|
+
"expectedHash": "c23a8f2fe0dea3f6099cf5ecc27eecc7f5acd85b5f5beb41da09418646a4225a",
|
|
10
10
|
"hashAlgorithm": "sha256"
|
|
11
11
|
},
|
|
12
12
|
{
|