@kubohiroya/turbowarp-plus-editor-git 0.16.1 → 0.17.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/README.ja.md +14 -0
- package/README.md +14 -0
- package/dist/filesystem.d.ts +2 -2
- package/dist/github-pull-requests.d.ts +20 -0
- package/dist/index.d.ts +3 -2
- package/dist/index.js +177 -14
- package/dist/local-operations.d.ts +8 -1
- package/dist/messages.d.ts +8 -0
- package/dist/{project-asset-paths-KV715791.js → project-asset-paths-nL5sV35A.js} +653 -1
- package/dist/{project-comparison-1rggIJse.js → project-comparison-DjMlwyp8.js} +10 -654
- package/dist/project-source-diff.js +2 -1
- package/dist/pull-request-panel.d.ts +25 -1
- package/dist/remote-operations.d.ts +23 -0
- package/dist/{repository-BYno-5f8.js → repository-xIv0iZkj.js} +346 -7
- package/dist/repository.d.ts +32 -0
- package/dist/repository.js +1 -1
- package/package.json +1 -1
- package/src/filesystem.ts +2 -1
- package/src/github-pull-requests.ts +7 -0
- package/src/index.tsx +31 -3
- package/src/local-operations.ts +23 -3
- package/src/messages.ts +8 -0
- package/src/pull-request-panel.tsx +125 -14
- package/src/remote-operations.ts +84 -3
- package/src/repository.ts +133 -1
- package/test/smart-http-fixture.js +20 -0
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { n as init_objectSpread2, t as _objectSpread2 } from "./objectSpread2-Dkd68nJH.js";
|
|
1
2
|
// node_modules/diff/libesm/diff/base.js
|
|
2
3
|
var Diff = class {
|
|
3
4
|
diff(oldStr, newStr, options = {}) {
|
|
@@ -518,6 +519,518 @@ var ArrayDiff = class extends Diff {
|
|
|
518
519
|
}
|
|
519
520
|
};
|
|
520
521
|
new ArrayDiff();
|
|
522
|
+
// node_modules/diff/libesm/patch/line-endings.js
|
|
523
|
+
function unixToWin(patch) {
|
|
524
|
+
if (Array.isArray(patch)) return patch.map((p) => unixToWin(p));
|
|
525
|
+
return Object.assign(Object.assign({}, patch), { hunks: patch.hunks.map((hunk) => Object.assign(Object.assign({}, hunk), { lines: hunk.lines.map((line, i) => {
|
|
526
|
+
var _a;
|
|
527
|
+
return line.startsWith("\\") || line.endsWith("\r") || ((_a = hunk.lines[i + 1]) === null || _a === void 0 ? void 0 : _a.startsWith("\\")) ? line : line + "\r";
|
|
528
|
+
}) })) });
|
|
529
|
+
}
|
|
530
|
+
function winToUnix(patch) {
|
|
531
|
+
if (Array.isArray(patch)) return patch.map((p) => winToUnix(p));
|
|
532
|
+
return Object.assign(Object.assign({}, patch), { hunks: patch.hunks.map((hunk) => Object.assign(Object.assign({}, hunk), { lines: hunk.lines.map((line) => line.endsWith("\r") ? line.substring(0, line.length - 1) : line) })) });
|
|
533
|
+
}
|
|
534
|
+
/**
|
|
535
|
+
* Returns true if the patch consistently uses Unix line endings (or only involves one line and has
|
|
536
|
+
* no line endings).
|
|
537
|
+
*/
|
|
538
|
+
function isUnix(patch) {
|
|
539
|
+
if (!Array.isArray(patch)) patch = [patch];
|
|
540
|
+
return !patch.some((index) => index.hunks.some((hunk) => hunk.lines.some((line) => !line.startsWith("\\") && line.endsWith("\r"))));
|
|
541
|
+
}
|
|
542
|
+
/**
|
|
543
|
+
* Returns true if the patch uses Windows line endings and only Windows line endings.
|
|
544
|
+
*/
|
|
545
|
+
function isWin(patch) {
|
|
546
|
+
if (!Array.isArray(patch)) patch = [patch];
|
|
547
|
+
return patch.some((index) => index.hunks.some((hunk) => hunk.lines.some((line) => line.endsWith("\r")))) && patch.every((index) => index.hunks.every((hunk) => hunk.lines.every((line, i) => {
|
|
548
|
+
var _a;
|
|
549
|
+
return line.startsWith("\\") || line.endsWith("\r") || ((_a = hunk.lines[i + 1]) === null || _a === void 0 ? void 0 : _a.startsWith("\\"));
|
|
550
|
+
})));
|
|
551
|
+
}
|
|
552
|
+
// node_modules/diff/libesm/patch/parse.js
|
|
553
|
+
/**
|
|
554
|
+
* Parses a unified diff format patch into a structured patch object.
|
|
555
|
+
*
|
|
556
|
+
* `parsePatch` has some understanding of Git's particular dialect of unified diff format.
|
|
557
|
+
* When parsing a Git patch, each index in the result may contain additional
|
|
558
|
+
* fields (`isRename`, `isBinary`, etc) not included in the data structure returned by
|
|
559
|
+
* `structuredPatch`; see the `StructuredPatch` interface for a full list.
|
|
560
|
+
*
|
|
561
|
+
* @return a JSON object representation of the patch, suitable for use with the `applyPatch`
|
|
562
|
+
* method. This parses to the same structure returned by `structuredPatch`, except that
|
|
563
|
+
* `oldFileName` and `newFileName` may be `undefined` if the patch doesn't contain enough
|
|
564
|
+
* information to determine them (e.g. a hunk-only patch with no file headers).
|
|
565
|
+
*/
|
|
566
|
+
function parsePatch(uniDiff) {
|
|
567
|
+
const diffstr = uniDiff.split(/\n/), list = [];
|
|
568
|
+
let i = 0;
|
|
569
|
+
function isGitDiffHeader(line) {
|
|
570
|
+
return /^diff --git /.test(line);
|
|
571
|
+
}
|
|
572
|
+
function isDiffHeader(line) {
|
|
573
|
+
return isGitDiffHeader(line) || /^Index:\s/.test(line) || /^diff(?: -r \w+)+\s/.test(line);
|
|
574
|
+
}
|
|
575
|
+
function isFileHeader(line) {
|
|
576
|
+
return /^(---|\+\+\+)\s/.test(line);
|
|
577
|
+
}
|
|
578
|
+
function isHunkHeader(line) {
|
|
579
|
+
return /^@@\s/.test(line);
|
|
580
|
+
}
|
|
581
|
+
function parseIndex() {
|
|
582
|
+
var _a;
|
|
583
|
+
const index = {};
|
|
584
|
+
index.hunks = [];
|
|
585
|
+
list.push(index);
|
|
586
|
+
let seenDiffHeader = false;
|
|
587
|
+
while (i < diffstr.length) {
|
|
588
|
+
const line = diffstr[i];
|
|
589
|
+
if (isFileHeader(line) || isHunkHeader(line)) break;
|
|
590
|
+
if (isGitDiffHeader(line)) {
|
|
591
|
+
if (seenDiffHeader) return;
|
|
592
|
+
seenDiffHeader = true;
|
|
593
|
+
index.isGit = true;
|
|
594
|
+
const paths = parseGitDiffHeader(line);
|
|
595
|
+
if (paths) {
|
|
596
|
+
index.oldFileName = paths.oldFileName;
|
|
597
|
+
index.newFileName = paths.newFileName;
|
|
598
|
+
}
|
|
599
|
+
i++;
|
|
600
|
+
while (i < diffstr.length) {
|
|
601
|
+
const extLine = diffstr[i];
|
|
602
|
+
if (isFileHeader(extLine) || isHunkHeader(extLine) || isDiffHeader(extLine)) break;
|
|
603
|
+
const renameFromMatch = /^rename from (.*)/.exec(extLine);
|
|
604
|
+
if (renameFromMatch) {
|
|
605
|
+
index.oldFileName = "a/" + unquoteIfQuoted(renameFromMatch[1]);
|
|
606
|
+
index.isRename = true;
|
|
607
|
+
}
|
|
608
|
+
const renameToMatch = /^rename to (.*)/.exec(extLine);
|
|
609
|
+
if (renameToMatch) {
|
|
610
|
+
index.newFileName = "b/" + unquoteIfQuoted(renameToMatch[1]);
|
|
611
|
+
index.isRename = true;
|
|
612
|
+
}
|
|
613
|
+
const copyFromMatch = /^copy from (.*)/.exec(extLine);
|
|
614
|
+
if (copyFromMatch) {
|
|
615
|
+
index.oldFileName = "a/" + unquoteIfQuoted(copyFromMatch[1]);
|
|
616
|
+
index.isCopy = true;
|
|
617
|
+
}
|
|
618
|
+
const copyToMatch = /^copy to (.*)/.exec(extLine);
|
|
619
|
+
if (copyToMatch) {
|
|
620
|
+
index.newFileName = "b/" + unquoteIfQuoted(copyToMatch[1]);
|
|
621
|
+
index.isCopy = true;
|
|
622
|
+
}
|
|
623
|
+
const newFileModeMatch = /^new file mode (\d+)/.exec(extLine);
|
|
624
|
+
if (newFileModeMatch) {
|
|
625
|
+
index.isCreate = true;
|
|
626
|
+
index.newMode = newFileModeMatch[1];
|
|
627
|
+
}
|
|
628
|
+
const deletedFileModeMatch = /^deleted file mode (\d+)/.exec(extLine);
|
|
629
|
+
if (deletedFileModeMatch) {
|
|
630
|
+
index.isDelete = true;
|
|
631
|
+
index.oldMode = deletedFileModeMatch[1];
|
|
632
|
+
}
|
|
633
|
+
const oldModeMatch = /^old mode (\d+)/.exec(extLine);
|
|
634
|
+
if (oldModeMatch) index.oldMode = oldModeMatch[1];
|
|
635
|
+
const newModeMatch = /^new mode (\d+)/.exec(extLine);
|
|
636
|
+
if (newModeMatch) index.newMode = newModeMatch[1];
|
|
637
|
+
if (/^Binary files /.test(extLine)) index.isBinary = true;
|
|
638
|
+
i++;
|
|
639
|
+
}
|
|
640
|
+
continue;
|
|
641
|
+
} else if (isDiffHeader(line)) {
|
|
642
|
+
if (seenDiffHeader) return;
|
|
643
|
+
seenDiffHeader = true;
|
|
644
|
+
const headerMatch = /^(?:Index:|diff(?: -r \w+)+)\s+/.exec(line);
|
|
645
|
+
if (headerMatch) index.index = line.substring(headerMatch[0].length).trim();
|
|
646
|
+
}
|
|
647
|
+
i++;
|
|
648
|
+
}
|
|
649
|
+
parseFileHeader(index);
|
|
650
|
+
parseFileHeader(index);
|
|
651
|
+
if (index.oldFileName === void 0 !== (index.newFileName === void 0)) throw new Error("Missing " + (index.oldFileName !== void 0 ? "\"+++ ...\"" : "\"--- ...\"") + " file header for " + ((_a = index.oldFileName) !== null && _a !== void 0 ? _a : index.newFileName));
|
|
652
|
+
while (i < diffstr.length) {
|
|
653
|
+
const line = diffstr[i];
|
|
654
|
+
if (isDiffHeader(line) || isFileHeader(line) || /^===================================================================/.test(line)) break;
|
|
655
|
+
else if (isHunkHeader(line)) index.hunks.push(parseHunk());
|
|
656
|
+
else i++;
|
|
657
|
+
}
|
|
658
|
+
}
|
|
659
|
+
/**
|
|
660
|
+
* Parses the old and new filenames from a `diff --git` header line.
|
|
661
|
+
*
|
|
662
|
+
* The format is:
|
|
663
|
+
* diff --git a/<old-path> b/<new-path>
|
|
664
|
+
*
|
|
665
|
+
* When filenames contain special characters (including newlines, tabs,
|
|
666
|
+
* backslashes, or double quotes), Git quotes them with C-style escaping:
|
|
667
|
+
* diff --git "a/file\twith\ttabs.txt" "b/file\twith\ttabs.txt"
|
|
668
|
+
*
|
|
669
|
+
* When filenames don't contain special characters and the old and new names
|
|
670
|
+
* are the same, we can unambiguously split on ` b/` by finding where the
|
|
671
|
+
* two halves (including their a/ and b/ prefixes) yield matching bare names.
|
|
672
|
+
*
|
|
673
|
+
* A pathological case exists in which we cannot reliably determine the paths
|
|
674
|
+
* from the `diff --git` header. This case is when the following are true:
|
|
675
|
+
* - the old and new file paths differ
|
|
676
|
+
* - they are both unquoted (i.e. contain no special characters)
|
|
677
|
+
* - at least one of the underlying file paths includes the substring ` b/`
|
|
678
|
+
* In this scenario, we do not know which occurrence of ` b/` indicates the
|
|
679
|
+
* start of the new file path, so the header is inherently ambiguous. We thus
|
|
680
|
+
* select a possible interpretation arbitrarily and return that.
|
|
681
|
+
*
|
|
682
|
+
* Fortunately, this ambiguity should never matter, because in any patch
|
|
683
|
+
* genuinely output by Git in which this pathological scenario occurs, there
|
|
684
|
+
* must also be `rename from`/`rename to` or `copy from`/`copy to` extended
|
|
685
|
+
* headers present below the `diff --git` header. `parseIndex` will parse
|
|
686
|
+
* THOSE headers, from which we CAN unambiguously determine the filenames,
|
|
687
|
+
* and will discard the result returned by this function.
|
|
688
|
+
*
|
|
689
|
+
* Returns null if the header can't be parsed at all — e.g. a quoted filename
|
|
690
|
+
* has an unterminated quote, or if the unquoted header doesn't match the
|
|
691
|
+
* expected `a/... b/...` format. In that case, the caller (parseIndex)
|
|
692
|
+
* skips setting oldFileName/newFileName from this header, but they may
|
|
693
|
+
* still be set later from `---`/`+++` lines or `rename from`/`rename to`
|
|
694
|
+
* extended headers; if none of those are present either, they'll remain
|
|
695
|
+
* undefined in the output.
|
|
696
|
+
*/
|
|
697
|
+
function parseGitDiffHeader(line) {
|
|
698
|
+
const rest = line.substring(11);
|
|
699
|
+
if (rest.startsWith("\"")) {
|
|
700
|
+
const oldPath = parseQuotedFileName(rest);
|
|
701
|
+
if (oldPath === null) return null;
|
|
702
|
+
const afterOld = rest.substring(oldPath.rawLength + 1);
|
|
703
|
+
let newFileName;
|
|
704
|
+
if (afterOld.startsWith("\"")) {
|
|
705
|
+
const newPath = parseQuotedFileName(afterOld);
|
|
706
|
+
if (newPath === null) return null;
|
|
707
|
+
newFileName = newPath.fileName;
|
|
708
|
+
} else newFileName = afterOld;
|
|
709
|
+
return {
|
|
710
|
+
oldFileName: oldPath.fileName,
|
|
711
|
+
newFileName
|
|
712
|
+
};
|
|
713
|
+
}
|
|
714
|
+
const quoteIdx = rest.indexOf("\"");
|
|
715
|
+
if (quoteIdx > 0) {
|
|
716
|
+
const oldFileName = rest.substring(0, quoteIdx - 1);
|
|
717
|
+
const newPath = parseQuotedFileName(rest.substring(quoteIdx));
|
|
718
|
+
if (newPath === null) return null;
|
|
719
|
+
return {
|
|
720
|
+
oldFileName,
|
|
721
|
+
newFileName: newPath.fileName
|
|
722
|
+
};
|
|
723
|
+
}
|
|
724
|
+
if (rest.startsWith("a/")) {
|
|
725
|
+
const splits = [];
|
|
726
|
+
let idx = 0;
|
|
727
|
+
while (true) {
|
|
728
|
+
idx = rest.indexOf(" b/", idx + 1);
|
|
729
|
+
if (idx === -1) break;
|
|
730
|
+
splits.push(idx);
|
|
731
|
+
}
|
|
732
|
+
if (splits.length > 0) {
|
|
733
|
+
const mid = splits[Math.floor(splits.length / 2)];
|
|
734
|
+
return {
|
|
735
|
+
oldFileName: rest.substring(0, mid),
|
|
736
|
+
newFileName: rest.substring(mid + 1)
|
|
737
|
+
};
|
|
738
|
+
}
|
|
739
|
+
}
|
|
740
|
+
return null;
|
|
741
|
+
}
|
|
742
|
+
/**
|
|
743
|
+
* If `s` starts with a double quote, unquotes it using C-style escape
|
|
744
|
+
* rules (as used by Git). Otherwise returns `s` as-is.
|
|
745
|
+
*/
|
|
746
|
+
function unquoteIfQuoted(s) {
|
|
747
|
+
if (s.startsWith("\"")) {
|
|
748
|
+
const parsed = parseQuotedFileName(s);
|
|
749
|
+
if (parsed) return parsed.fileName;
|
|
750
|
+
}
|
|
751
|
+
return s;
|
|
752
|
+
}
|
|
753
|
+
/**
|
|
754
|
+
* Parses a C-style quoted filename as used by Git or GNU `diff -u`.
|
|
755
|
+
* Returns the unescaped filename and the raw length consumed (including quotes).
|
|
756
|
+
*/
|
|
757
|
+
function parseQuotedFileName(s) {
|
|
758
|
+
if (!s.startsWith("\"")) return null;
|
|
759
|
+
let result = "";
|
|
760
|
+
let j = 1;
|
|
761
|
+
while (j < s.length) {
|
|
762
|
+
if (s[j] === "\"") return {
|
|
763
|
+
fileName: result,
|
|
764
|
+
rawLength: j + 1
|
|
765
|
+
};
|
|
766
|
+
if (s[j] === "\\" && j + 1 < s.length) {
|
|
767
|
+
j++;
|
|
768
|
+
switch (s[j]) {
|
|
769
|
+
case "a":
|
|
770
|
+
result += "\x07";
|
|
771
|
+
break;
|
|
772
|
+
case "b":
|
|
773
|
+
result += "\b";
|
|
774
|
+
break;
|
|
775
|
+
case "f":
|
|
776
|
+
result += "\f";
|
|
777
|
+
break;
|
|
778
|
+
case "n":
|
|
779
|
+
result += "\n";
|
|
780
|
+
break;
|
|
781
|
+
case "r":
|
|
782
|
+
result += "\r";
|
|
783
|
+
break;
|
|
784
|
+
case "t":
|
|
785
|
+
result += " ";
|
|
786
|
+
break;
|
|
787
|
+
case "v":
|
|
788
|
+
result += "\v";
|
|
789
|
+
break;
|
|
790
|
+
case "\\":
|
|
791
|
+
result += "\\";
|
|
792
|
+
break;
|
|
793
|
+
case "\"":
|
|
794
|
+
result += "\"";
|
|
795
|
+
break;
|
|
796
|
+
case "0":
|
|
797
|
+
case "1":
|
|
798
|
+
case "2":
|
|
799
|
+
case "3":
|
|
800
|
+
case "4":
|
|
801
|
+
case "5":
|
|
802
|
+
case "6":
|
|
803
|
+
case "7": {
|
|
804
|
+
if (j + 2 >= s.length || s[j + 1] < "0" || s[j + 1] > "7" || s[j + 2] < "0" || s[j + 2] > "7") return null;
|
|
805
|
+
const bytes = [parseInt(s.substring(j, j + 3), 8)];
|
|
806
|
+
j += 3;
|
|
807
|
+
while (s[j] === "\\" && s[j + 1] >= "0" && s[j + 1] <= "7") {
|
|
808
|
+
if (j + 3 >= s.length || s[j + 2] < "0" || s[j + 2] > "7" || s[j + 3] < "0" || s[j + 3] > "7") return null;
|
|
809
|
+
bytes.push(parseInt(s.substring(j + 1, j + 4), 8));
|
|
810
|
+
j += 4;
|
|
811
|
+
}
|
|
812
|
+
result += new TextDecoder("utf-8").decode(new Uint8Array(bytes));
|
|
813
|
+
continue;
|
|
814
|
+
}
|
|
815
|
+
default: return null;
|
|
816
|
+
}
|
|
817
|
+
} else result += s[j];
|
|
818
|
+
j++;
|
|
819
|
+
}
|
|
820
|
+
return null;
|
|
821
|
+
}
|
|
822
|
+
function parseFileHeader(index) {
|
|
823
|
+
const fileHeaderMatch = /^(---|\+\+\+)\s+/.exec(diffstr[i]);
|
|
824
|
+
if (fileHeaderMatch) {
|
|
825
|
+
const prefix = fileHeaderMatch[1], data = diffstr[i].substring(3).trim().split(" ", 2), header = (data[1] || "").trim();
|
|
826
|
+
let fileName = data[0];
|
|
827
|
+
if (fileName.startsWith("\"")) fileName = unquoteIfQuoted(fileName);
|
|
828
|
+
else fileName = fileName.replace(/\\\\/g, "\\");
|
|
829
|
+
if (prefix === "---") {
|
|
830
|
+
index.oldFileName = fileName;
|
|
831
|
+
index.oldHeader = header;
|
|
832
|
+
} else {
|
|
833
|
+
index.newFileName = fileName;
|
|
834
|
+
index.newHeader = header;
|
|
835
|
+
}
|
|
836
|
+
i++;
|
|
837
|
+
}
|
|
838
|
+
}
|
|
839
|
+
function parseHunk() {
|
|
840
|
+
var _a;
|
|
841
|
+
const chunkHeaderIndex = i, chunkHeader = diffstr[i++].split(/@@ -(\d+)(?:,(\d+))? \+(\d+)(?:,(\d+))? @@/);
|
|
842
|
+
const hunk = {
|
|
843
|
+
oldStart: +chunkHeader[1],
|
|
844
|
+
oldLines: typeof chunkHeader[2] === "undefined" ? 1 : +chunkHeader[2],
|
|
845
|
+
newStart: +chunkHeader[3],
|
|
846
|
+
newLines: typeof chunkHeader[4] === "undefined" ? 1 : +chunkHeader[4],
|
|
847
|
+
lines: []
|
|
848
|
+
};
|
|
849
|
+
if (hunk.oldLines === 0) hunk.oldStart += 1;
|
|
850
|
+
if (hunk.newLines === 0) hunk.newStart += 1;
|
|
851
|
+
let addCount = 0, removeCount = 0;
|
|
852
|
+
for (; i < diffstr.length && (removeCount < hunk.oldLines || addCount < hunk.newLines || ((_a = diffstr[i]) === null || _a === void 0 ? void 0 : _a.startsWith("\\"))); i++) {
|
|
853
|
+
const operation = diffstr[i].length == 0 && i != diffstr.length - 1 ? " " : diffstr[i][0];
|
|
854
|
+
if (operation === "+" || operation === "-" || operation === " " || operation === "\\") {
|
|
855
|
+
hunk.lines.push(diffstr[i]);
|
|
856
|
+
if (operation === "+") addCount++;
|
|
857
|
+
else if (operation === "-") removeCount++;
|
|
858
|
+
else if (operation === " ") {
|
|
859
|
+
addCount++;
|
|
860
|
+
removeCount++;
|
|
861
|
+
}
|
|
862
|
+
} else throw new Error(`Hunk at line ${chunkHeaderIndex + 1} contained invalid line ${diffstr[i]}`);
|
|
863
|
+
}
|
|
864
|
+
if (!addCount && hunk.newLines === 1) hunk.newLines = 0;
|
|
865
|
+
if (!removeCount && hunk.oldLines === 1) hunk.oldLines = 0;
|
|
866
|
+
if (addCount !== hunk.newLines) throw new Error("Added line count did not match for hunk at line " + (chunkHeaderIndex + 1));
|
|
867
|
+
if (removeCount !== hunk.oldLines) throw new Error("Removed line count did not match for hunk at line " + (chunkHeaderIndex + 1));
|
|
868
|
+
if (i < diffstr.length && diffstr[i] && /^[+ -]/.test(diffstr[i]) && !isFileHeader(diffstr[i])) throw new Error("Hunk at line " + (chunkHeaderIndex + 1) + " has more lines than expected (expected " + hunk.oldLines + " old lines and " + hunk.newLines + " new lines)");
|
|
869
|
+
return hunk;
|
|
870
|
+
}
|
|
871
|
+
while (i < diffstr.length) parseIndex();
|
|
872
|
+
return list;
|
|
873
|
+
}
|
|
874
|
+
// node_modules/diff/libesm/util/distance-iterator.js
|
|
875
|
+
function distance_iterator_default(start, minLine, maxLine) {
|
|
876
|
+
let wantForward = true, backwardExhausted = false, forwardExhausted = false, localOffset = 1;
|
|
877
|
+
return function iterator() {
|
|
878
|
+
if (wantForward && !forwardExhausted) {
|
|
879
|
+
if (backwardExhausted) localOffset++;
|
|
880
|
+
else wantForward = false;
|
|
881
|
+
if (start + localOffset <= maxLine) return start + localOffset;
|
|
882
|
+
forwardExhausted = true;
|
|
883
|
+
}
|
|
884
|
+
if (!backwardExhausted) {
|
|
885
|
+
if (!forwardExhausted) wantForward = true;
|
|
886
|
+
if (minLine <= start - localOffset) return start - localOffset++;
|
|
887
|
+
backwardExhausted = true;
|
|
888
|
+
return iterator();
|
|
889
|
+
}
|
|
890
|
+
};
|
|
891
|
+
}
|
|
892
|
+
// node_modules/diff/libesm/patch/apply.js
|
|
893
|
+
/**
|
|
894
|
+
* attempts to apply a unified diff patch.
|
|
895
|
+
*
|
|
896
|
+
* Hunks are applied first to last.
|
|
897
|
+
* `applyPatch` first tries to apply the first hunk at the line number specified in the hunk header, and with all context lines matching exactly.
|
|
898
|
+
* If that fails, it tries scanning backwards and forwards, one line at a time, to find a place to apply the hunk where the context lines match exactly.
|
|
899
|
+
* If that still fails, and `fuzzFactor` is greater than zero, it increments the maximum number of mismatches (missing, extra, or changed context lines) that there can be between the hunk context and a region where we are trying to apply the patch such that the hunk will still be considered to match.
|
|
900
|
+
* Regardless of `fuzzFactor`, lines to be deleted in the hunk *must* be present for a hunk to match, and the context lines *immediately* before and after an insertion must match exactly.
|
|
901
|
+
*
|
|
902
|
+
* Once a hunk is successfully fitted, the process begins again with the next hunk.
|
|
903
|
+
* Regardless of `fuzzFactor`, later hunks must be applied later in the file than earlier hunks.
|
|
904
|
+
*
|
|
905
|
+
* If a hunk cannot be successfully fitted *anywhere* with fewer than `fuzzFactor` mismatches, `applyPatch` fails and returns `false`.
|
|
906
|
+
*
|
|
907
|
+
* If a hunk is successfully fitted but not at the line number specified by the hunk header, all subsequent hunks have their target line number adjusted accordingly.
|
|
908
|
+
* (e.g. if the first hunk is applied 10 lines below where the hunk header said it should fit, `applyPatch` will *start* looking for somewhere to apply the second hunk 10 lines below where its hunk header says it goes.)
|
|
909
|
+
*
|
|
910
|
+
* If the patch was applied successfully, returns a string containing the patched text.
|
|
911
|
+
* If the patch could not be applied (because some hunks in the patch couldn't be fitted to the text in `source`), `applyPatch` returns false.
|
|
912
|
+
*
|
|
913
|
+
* @param patch a string diff or the output from the `parsePatch` or `structuredPatch` methods.
|
|
914
|
+
*/
|
|
915
|
+
function applyPatch(source, patch, options = {}) {
|
|
916
|
+
let patches;
|
|
917
|
+
if (typeof patch === "string") patches = parsePatch(patch);
|
|
918
|
+
else if (Array.isArray(patch)) patches = patch;
|
|
919
|
+
else patches = [patch];
|
|
920
|
+
if (patches.length > 1) throw new Error("applyPatch only works with a single input.");
|
|
921
|
+
return applyStructuredPatch(source, patches[0], options);
|
|
922
|
+
}
|
|
923
|
+
function applyStructuredPatch(source, patch, options = {}) {
|
|
924
|
+
if (options.autoConvertLineEndings || options.autoConvertLineEndings == null) {
|
|
925
|
+
if (hasOnlyWinLineEndings(source) && isUnix(patch)) patch = unixToWin(patch);
|
|
926
|
+
else if (hasOnlyUnixLineEndings(source) && isWin(patch)) patch = winToUnix(patch);
|
|
927
|
+
}
|
|
928
|
+
const lines = source.split("\n"), hunks = patch.hunks, compareLine = options.compareLine || ((lineNumber, line, operation, patchContent) => line === patchContent), fuzzFactor = options.fuzzFactor || 0;
|
|
929
|
+
let minLine = 0;
|
|
930
|
+
if (fuzzFactor < 0 || !Number.isInteger(fuzzFactor)) throw new Error("fuzzFactor must be a non-negative integer");
|
|
931
|
+
if (!hunks.length) return source;
|
|
932
|
+
let prevLine = "", removeEOFNL = false, addEOFNL = false;
|
|
933
|
+
for (let i = 0; i < hunks[hunks.length - 1].lines.length; i++) {
|
|
934
|
+
const line = hunks[hunks.length - 1].lines[i];
|
|
935
|
+
if (line[0] == "\\") {
|
|
936
|
+
if (prevLine[0] == "+") removeEOFNL = true;
|
|
937
|
+
else if (prevLine[0] == "-") addEOFNL = true;
|
|
938
|
+
}
|
|
939
|
+
prevLine = line;
|
|
940
|
+
}
|
|
941
|
+
if (removeEOFNL) {
|
|
942
|
+
if (addEOFNL) {
|
|
943
|
+
if (!fuzzFactor && lines[lines.length - 1] == "") return false;
|
|
944
|
+
} else if (lines[lines.length - 1] == "") lines.pop();
|
|
945
|
+
else if (!fuzzFactor) return false;
|
|
946
|
+
} else if (addEOFNL) {
|
|
947
|
+
if (lines[lines.length - 1] != "") lines.push("");
|
|
948
|
+
else if (!fuzzFactor) return false;
|
|
949
|
+
}
|
|
950
|
+
/**
|
|
951
|
+
* Checks if the hunk can be made to fit at the provided location with at most `maxErrors`
|
|
952
|
+
* insertions, substitutions, or deletions, while ensuring also that:
|
|
953
|
+
* - lines deleted in the hunk match exactly, and
|
|
954
|
+
* - wherever an insertion operation or block of insertion operations appears in the hunk, the
|
|
955
|
+
* immediately preceding and following lines of context match exactly
|
|
956
|
+
*
|
|
957
|
+
* `toPos` should be set such that lines[toPos] is meant to match hunkLines[0].
|
|
958
|
+
*
|
|
959
|
+
* If the hunk can be applied, returns an object with properties `oldLineLastI` and
|
|
960
|
+
* `replacementLines`. Otherwise, returns null.
|
|
961
|
+
*/
|
|
962
|
+
function applyHunk(hunkLines, toPos, maxErrors, hunkLinesI = 0, lastContextLineMatched = true, patchedLines = [], patchedLinesLength = 0) {
|
|
963
|
+
let nConsecutiveOldContextLines = 0;
|
|
964
|
+
let nextContextLineMustMatch = false;
|
|
965
|
+
for (; hunkLinesI < hunkLines.length; hunkLinesI++) {
|
|
966
|
+
const hunkLine = hunkLines[hunkLinesI], operation = hunkLine.length > 0 ? hunkLine[0] : " ", content = hunkLine.length > 0 ? hunkLine.substr(1) : hunkLine;
|
|
967
|
+
if (operation === "-") {
|
|
968
|
+
if (compareLine(toPos + 1, lines[toPos], operation, content)) {
|
|
969
|
+
toPos++;
|
|
970
|
+
nConsecutiveOldContextLines = 0;
|
|
971
|
+
} else {
|
|
972
|
+
if (!maxErrors || lines[toPos] == null) return null;
|
|
973
|
+
patchedLines[patchedLinesLength] = lines[toPos];
|
|
974
|
+
return applyHunk(hunkLines, toPos + 1, maxErrors - 1, hunkLinesI, false, patchedLines, patchedLinesLength + 1);
|
|
975
|
+
}
|
|
976
|
+
}
|
|
977
|
+
if (operation === "+") {
|
|
978
|
+
if (!lastContextLineMatched) return null;
|
|
979
|
+
patchedLines[patchedLinesLength] = content;
|
|
980
|
+
patchedLinesLength++;
|
|
981
|
+
nConsecutiveOldContextLines = 0;
|
|
982
|
+
nextContextLineMustMatch = true;
|
|
983
|
+
}
|
|
984
|
+
if (operation === " ") {
|
|
985
|
+
nConsecutiveOldContextLines++;
|
|
986
|
+
patchedLines[patchedLinesLength] = lines[toPos];
|
|
987
|
+
if (compareLine(toPos + 1, lines[toPos], operation, content)) {
|
|
988
|
+
patchedLinesLength++;
|
|
989
|
+
lastContextLineMatched = true;
|
|
990
|
+
nextContextLineMustMatch = false;
|
|
991
|
+
toPos++;
|
|
992
|
+
} else {
|
|
993
|
+
if (nextContextLineMustMatch || !maxErrors) return null;
|
|
994
|
+
return lines[toPos] && (applyHunk(hunkLines, toPos + 1, maxErrors - 1, hunkLinesI + 1, false, patchedLines, patchedLinesLength + 1) || applyHunk(hunkLines, toPos + 1, maxErrors - 1, hunkLinesI, false, patchedLines, patchedLinesLength + 1)) || applyHunk(hunkLines, toPos, maxErrors - 1, hunkLinesI + 1, false, patchedLines, patchedLinesLength);
|
|
995
|
+
}
|
|
996
|
+
}
|
|
997
|
+
}
|
|
998
|
+
patchedLinesLength -= nConsecutiveOldContextLines;
|
|
999
|
+
toPos -= nConsecutiveOldContextLines;
|
|
1000
|
+
patchedLines.length = patchedLinesLength;
|
|
1001
|
+
return {
|
|
1002
|
+
patchedLines,
|
|
1003
|
+
oldLineLastI: toPos - 1
|
|
1004
|
+
};
|
|
1005
|
+
}
|
|
1006
|
+
const resultLines = [];
|
|
1007
|
+
let prevHunkOffset = 0;
|
|
1008
|
+
for (let i = 0; i < hunks.length; i++) {
|
|
1009
|
+
const hunk = hunks[i];
|
|
1010
|
+
let hunkResult;
|
|
1011
|
+
const maxLine = lines.length - hunk.oldLines + fuzzFactor;
|
|
1012
|
+
let toPos;
|
|
1013
|
+
for (let maxErrors = 0; maxErrors <= fuzzFactor; maxErrors++) {
|
|
1014
|
+
toPos = hunk.oldStart + prevHunkOffset - 1;
|
|
1015
|
+
const iterator = distance_iterator_default(toPos, minLine, maxLine);
|
|
1016
|
+
for (; toPos !== void 0; toPos = iterator()) {
|
|
1017
|
+
hunkResult = applyHunk(hunk.lines, toPos, maxErrors);
|
|
1018
|
+
if (hunkResult) break;
|
|
1019
|
+
}
|
|
1020
|
+
if (hunkResult) break;
|
|
1021
|
+
}
|
|
1022
|
+
if (!hunkResult) return false;
|
|
1023
|
+
for (let i = minLine; i < toPos; i++) resultLines.push(lines[i]);
|
|
1024
|
+
for (let i = 0; i < hunkResult.patchedLines.length; i++) {
|
|
1025
|
+
const line = hunkResult.patchedLines[i];
|
|
1026
|
+
resultLines.push(line);
|
|
1027
|
+
}
|
|
1028
|
+
minLine = hunkResult.oldLineLastI + 1;
|
|
1029
|
+
prevHunkOffset = toPos + 1 - hunk.oldStart;
|
|
1030
|
+
}
|
|
1031
|
+
for (let i = minLine; i < lines.length; i++) resultLines.push(lines[i]);
|
|
1032
|
+
return resultLines.join("\n");
|
|
1033
|
+
}
|
|
521
1034
|
// node_modules/diff/libesm/patch/create.js
|
|
522
1035
|
/**
|
|
523
1036
|
* Returns true if the filename contains characters that require C-style
|
|
@@ -736,6 +1249,145 @@ function splitLines(text) {
|
|
|
736
1249
|
else result.push(result.pop().slice(0, -1));
|
|
737
1250
|
return result;
|
|
738
1251
|
}
|
|
1252
|
+
// \0@oxc-project+runtime@0.156.0/helpers/esm/objectWithoutPropertiesLoose.js
|
|
1253
|
+
init_objectSpread2();
|
|
1254
|
+
function _objectWithoutPropertiesLoose(r, e) {
|
|
1255
|
+
if (null == r) return {};
|
|
1256
|
+
var t = {};
|
|
1257
|
+
for (var n in r) if ({}.hasOwnProperty.call(r, n)) {
|
|
1258
|
+
if (e.includes(n)) continue;
|
|
1259
|
+
t[n] = r[n];
|
|
1260
|
+
}
|
|
1261
|
+
return t;
|
|
1262
|
+
}
|
|
1263
|
+
// \0@oxc-project+runtime@0.156.0/helpers/esm/objectWithoutProperties.js
|
|
1264
|
+
function _objectWithoutProperties(e, t) {
|
|
1265
|
+
if (null == e) return {};
|
|
1266
|
+
var o, r, i = _objectWithoutPropertiesLoose(e, t);
|
|
1267
|
+
if (Object.getOwnPropertySymbols) {
|
|
1268
|
+
var s = Object.getOwnPropertySymbols(e);
|
|
1269
|
+
for (r = 0; r < s.length; r++) o = s[r], t.includes(o) || {}.propertyIsEnumerable.call(e, o) && (i[o] = e[o]);
|
|
1270
|
+
}
|
|
1271
|
+
return i;
|
|
1272
|
+
}
|
|
1273
|
+
// src/project-source-patch.ts
|
|
1274
|
+
var _excluded = ["blocks"];
|
|
1275
|
+
var isRecord = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
|
|
1276
|
+
function readProject(source) {
|
|
1277
|
+
const project = JSON.parse(source);
|
|
1278
|
+
if (!isRecord(project) || !Array.isArray(project.targets) || !project.targets.every((target) => isRecord(target) && typeof target.name === "string" && typeof target.isStage === "boolean" && (target.blocks === void 0 || isRecord(target.blocks)))) throw new Error("Expected a project.source.json with Scratch targets and blocks.");
|
|
1279
|
+
const parsed = project;
|
|
1280
|
+
return _objectSpread2(_objectSpread2({}, parsed), {}, { targets: parsed.targets.map((target) => {
|
|
1281
|
+
var _target$blocks;
|
|
1282
|
+
return _objectSpread2(_objectSpread2({}, target), {}, { blocks: (_target$blocks = target.blocks) !== null && _target$blocks !== void 0 ? _target$blocks : {} });
|
|
1283
|
+
}) });
|
|
1284
|
+
}
|
|
1285
|
+
/** Reads one version of a project.source.json. `null` stands for a version in which the file does not exist. */
|
|
1286
|
+
function parseProjectSource(source) {
|
|
1287
|
+
return source === null ? { targets: [] } : readProject(source);
|
|
1288
|
+
}
|
|
1289
|
+
/** Keep the original lines and include enough context to render both sides from the patch alone. */
|
|
1290
|
+
function createProjectSourceDiff(before, after) {
|
|
1291
|
+
readProject(before);
|
|
1292
|
+
readProject(after);
|
|
1293
|
+
const patch = createTwoFilesPatch("a/project.source.json", "b/project.source.json", before, after, void 0, void 0, {
|
|
1294
|
+
context: Infinity,
|
|
1295
|
+
timeout: 1e3
|
|
1296
|
+
});
|
|
1297
|
+
if (patch === void 0) throw new Error("Project source diff exceeded its time limit.");
|
|
1298
|
+
return "diff --git a/project.source.json b/project.source.json\n" + patch.replace(/^=+\n/, "");
|
|
1299
|
+
}
|
|
1300
|
+
function readProjectSourceDiff(patch, beforeSource) {
|
|
1301
|
+
const [file, extra] = parsePatch(patch);
|
|
1302
|
+
if (!file || extra || !file.oldFileName || !file.newFileName) throw new Error("Expected a single unified text diff.");
|
|
1303
|
+
if (beforeSource !== void 0) {
|
|
1304
|
+
const before = readProject(beforeSource);
|
|
1305
|
+
const after = applyPatch(beforeSource, file);
|
|
1306
|
+
if (after === false) throw new Error("The original project does not match this diff.");
|
|
1307
|
+
return [before, readProject(after)];
|
|
1308
|
+
}
|
|
1309
|
+
if (!file.hunks.length) return null;
|
|
1310
|
+
const before = [], after = [];
|
|
1311
|
+
for (const hunk of file.hunks) {
|
|
1312
|
+
if (hunk.oldStart !== before.length + 1 || hunk.newStart !== after.length + 1) throw new Error("The diff omits project context.");
|
|
1313
|
+
for (const line of hunk.lines) {
|
|
1314
|
+
if (line.startsWith(" ") || line.startsWith("-")) before.push(line.slice(1));
|
|
1315
|
+
if (line.startsWith(" ") || line.startsWith("+")) after.push(line.slice(1));
|
|
1316
|
+
}
|
|
1317
|
+
}
|
|
1318
|
+
return [readProject(before.join("\n")), readProject(after.join("\n"))];
|
|
1319
|
+
}
|
|
1320
|
+
function equal(a, b) {
|
|
1321
|
+
if (a === b) return true;
|
|
1322
|
+
if (Array.isArray(a) && Array.isArray(b)) return a.length === b.length && a.every((value, i) => equal(value, b[i]));
|
|
1323
|
+
if (!isRecord(a) || !isRecord(b)) return false;
|
|
1324
|
+
const keys = Object.keys(a);
|
|
1325
|
+
return keys.length === Object.keys(b).length && keys.every((key) => Object.hasOwn(b, key) && equal(a[key], b[key]));
|
|
1326
|
+
}
|
|
1327
|
+
var targetKey = (target) => target.isStage ? "stage" : "sprite:" + target.name;
|
|
1328
|
+
function changedParts(before, after) {
|
|
1329
|
+
if (!isRecord(before) || !isRecord(after)) return [];
|
|
1330
|
+
const result = [];
|
|
1331
|
+
const visibleInput = (input) => {
|
|
1332
|
+
var _input$;
|
|
1333
|
+
return Array.isArray(input) ? (_input$ = input[1]) !== null && _input$ !== void 0 ? _input$ : input[2] : input;
|
|
1334
|
+
};
|
|
1335
|
+
for (const group of ["inputs", "fields"]) {
|
|
1336
|
+
const oldGroup = isRecord(before[group]) ? before[group] : {};
|
|
1337
|
+
const newGroup = isRecord(after[group]) ? after[group] : {};
|
|
1338
|
+
for (const name of /* @__PURE__ */ new Set([...Object.keys(oldGroup), ...Object.keys(newGroup)])) {
|
|
1339
|
+
const a = oldGroup[name], b = newGroup[name];
|
|
1340
|
+
if (group === "inputs" ? !equal(visibleInput(a), visibleInput(b)) : !equal(a, b)) result.push({
|
|
1341
|
+
kind: group === "inputs" ? "input" : "field",
|
|
1342
|
+
name
|
|
1343
|
+
});
|
|
1344
|
+
}
|
|
1345
|
+
}
|
|
1346
|
+
return result;
|
|
1347
|
+
}
|
|
1348
|
+
function compareProjectBlocks(before, after) {
|
|
1349
|
+
const oldTargets = new Map(before.targets.map((target) => [targetKey(target), target]));
|
|
1350
|
+
const newTargets = new Map(after.targets.map((target) => [targetKey(target), target]));
|
|
1351
|
+
const changes = [];
|
|
1352
|
+
let unchanged = 0;
|
|
1353
|
+
for (const key of /* @__PURE__ */ new Set([...oldTargets.keys(), ...newTargets.keys()])) {
|
|
1354
|
+
var _oldTarget$blocks, _newTarget$blocks;
|
|
1355
|
+
const oldTarget = oldTargets.get(key), newTarget = newTargets.get(key);
|
|
1356
|
+
const oldBlocks = (_oldTarget$blocks = oldTarget === null || oldTarget === void 0 ? void 0 : oldTarget.blocks) !== null && _oldTarget$blocks !== void 0 ? _oldTarget$blocks : {}, newBlocks = (_newTarget$blocks = newTarget === null || newTarget === void 0 ? void 0 : newTarget.blocks) !== null && _newTarget$blocks !== void 0 ? _newTarget$blocks : {};
|
|
1357
|
+
for (const id of /* @__PURE__ */ new Set([...Object.keys(oldBlocks), ...Object.keys(newBlocks)])) {
|
|
1358
|
+
const hadBlock = Object.hasOwn(oldBlocks, id), hasBlock = Object.hasOwn(newBlocks, id);
|
|
1359
|
+
const a = oldBlocks[id], b = newBlocks[id];
|
|
1360
|
+
if (hadBlock && hasBlock && equal(a, b)) {
|
|
1361
|
+
unchanged++;
|
|
1362
|
+
continue;
|
|
1363
|
+
}
|
|
1364
|
+
const fields = isRecord(a) && isRecord(b) ? [.../* @__PURE__ */ new Set([...Object.keys(a), ...Object.keys(b)])].filter((field) => !equal(a[field], b[field])) : [];
|
|
1365
|
+
changes.push({
|
|
1366
|
+
key: JSON.stringify([key, id]),
|
|
1367
|
+
before: hadBlock && oldTarget ? {
|
|
1368
|
+
target: oldTarget,
|
|
1369
|
+
id
|
|
1370
|
+
} : void 0,
|
|
1371
|
+
after: hasBlock && newTarget ? {
|
|
1372
|
+
target: newTarget,
|
|
1373
|
+
id
|
|
1374
|
+
} : void 0,
|
|
1375
|
+
kind: !hadBlock ? "added" : !hasBlock ? "removed" : "updated",
|
|
1376
|
+
fields,
|
|
1377
|
+
parts: changedParts(a, b)
|
|
1378
|
+
});
|
|
1379
|
+
}
|
|
1380
|
+
}
|
|
1381
|
+
const withoutBlocks = (project) => _objectSpread2(_objectSpread2({}, project), {}, { targets: project.targets.map((_ref) => {
|
|
1382
|
+
let { blocks: _ } = _ref;
|
|
1383
|
+
return _objectWithoutProperties(_ref, _excluded);
|
|
1384
|
+
}) });
|
|
1385
|
+
return {
|
|
1386
|
+
changes,
|
|
1387
|
+
unchanged,
|
|
1388
|
+
otherChanges: !equal(withoutBlocks(before), withoutBlocks(after))
|
|
1389
|
+
};
|
|
1390
|
+
}
|
|
739
1391
|
// src/project-asset-paths.ts
|
|
740
1392
|
/** The largest asset a thumbnail reads. */
|
|
741
1393
|
var assetLimit = 10485760;
|
|
@@ -758,4 +1410,4 @@ function assetsDirectoryParts(settings) {
|
|
|
758
1410
|
const parts = value.split("/");
|
|
759
1411
|
return parts.every((part) => part && part !== "." && part !== ".." && part.toLowerCase() !== ".git" && !/[\\\0-\x1f\x7f]/.test(part)) ? parts : null;
|
|
760
1412
|
}
|
|
761
|
-
export {
|
|
1413
|
+
export { compareProjectBlocks as a, isRecord as c, targetKey as d, createTwoFilesPatch as f, isAssetName as i, parseProjectSource as l, assetsDirectoryParts as n, createProjectSourceDiff as o, folderSettingsLimit as r, equal as s, assetLimit as t, readProjectSourceDiff as u };
|