@davmash/bygone 0.8.12 → 0.8.13
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.md +1 -1
- package/docs/releasing.md +5 -0
- package/media/webview.js +1 -1
- package/out/changeTour.js +1319 -33
- package/out/standalone-main.js +1311 -31
- package/out/tourCoverage.js +1319 -33
- package/package.json +1 -1
- package/web/presenter.css +12 -0
- package/web/web-host.js +5 -5
package/out/standalone-main.js
CHANGED
|
@@ -4077,16 +4077,41 @@ var require_changeTour = __commonJS({
|
|
|
4077
4077
|
}
|
|
4078
4078
|
validateMultiPanelFiles(value.files, panels.length, index);
|
|
4079
4079
|
validateMultiPanelSteps(value.steps, panels.length, index, true);
|
|
4080
|
-
if (Array.isArray(value.steps) && value.steps.length !== panels.length - 1) {
|
|
4081
|
-
throw new Error(`scenes[${index}].steps must match the number of explanation stages.`);
|
|
4082
|
-
}
|
|
4083
4080
|
if (Array.isArray(value.steps)) {
|
|
4081
|
+
let previousPairIndex = -1;
|
|
4084
4082
|
value.steps.forEach((step, stepIndex) => {
|
|
4085
|
-
|
|
4086
|
-
|
|
4087
|
-
|
|
4083
|
+
if (!isRecord2(step)) return;
|
|
4084
|
+
const pairIndex = Number(step.pairIndex);
|
|
4085
|
+
if (pairIndex < previousPairIndex) {
|
|
4086
|
+
throw new Error(`scenes[${index}].steps must remain grouped in explanation stage order.`);
|
|
4087
|
+
}
|
|
4088
|
+
previousPairIndex = pairIndex;
|
|
4089
|
+
if (step.stageId !== void 0) requireString(step.stageId, `scenes[${index}].steps[${stepIndex}].stageId`);
|
|
4090
|
+
if (step.stageIndex !== void 0) requireNonNegativeInteger(step.stageIndex, `scenes[${index}].steps[${stepIndex}].stageIndex`);
|
|
4091
|
+
if (step.focusIndex !== void 0) requireNonNegativeInteger(step.focusIndex, `scenes[${index}].steps[${stepIndex}].focusIndex`);
|
|
4092
|
+
if (step.focusCount !== void 0) requirePositiveInteger(step.focusCount, `scenes[${index}].steps[${stepIndex}].focusCount`);
|
|
4093
|
+
if (step.stageIndex !== void 0 && Number(step.stageIndex) !== pairIndex) {
|
|
4094
|
+
throw new Error(`scenes[${index}].steps[${stepIndex}].stageIndex must match pairIndex.`);
|
|
4095
|
+
}
|
|
4096
|
+
if (step.focusIndex !== void 0 && step.focusCount !== void 0 && Number(step.focusIndex) >= Number(step.focusCount)) {
|
|
4097
|
+
throw new Error(`scenes[${index}].steps[${stepIndex}].focusIndex must be less than focusCount.`);
|
|
4088
4098
|
}
|
|
4089
4099
|
});
|
|
4100
|
+
for (let stageIndex = 0; stageIndex < panels.length - 1; stageIndex += 1) {
|
|
4101
|
+
const panel = panels[stageIndex + 1];
|
|
4102
|
+
const stageSteps = value.steps.filter((step) => isRecord2(step) && Number(step.pairIndex) === stageIndex);
|
|
4103
|
+
if (!isRecord2(panel) || stageSteps.length === 0) {
|
|
4104
|
+
throw new Error(`scenes[${index}].steps must cover every explanation stage.`);
|
|
4105
|
+
}
|
|
4106
|
+
const firstStep = stageSteps[0];
|
|
4107
|
+
const fallbackStageId = isRecord2(firstStep) ? firstStep.id : void 0;
|
|
4108
|
+
if (stageSteps.some((step) => {
|
|
4109
|
+
if (!isRecord2(step)) return true;
|
|
4110
|
+
return (step.stageId ?? fallbackStageId) !== panel.stageId;
|
|
4111
|
+
})) {
|
|
4112
|
+
throw new Error(`scenes[${index}].panels must align with explanation stage ids.`);
|
|
4113
|
+
}
|
|
4114
|
+
}
|
|
4090
4115
|
}
|
|
4091
4116
|
}
|
|
4092
4117
|
function validateMultiPanelFiles(value, panelCount, index) {
|
|
@@ -4115,7 +4140,6 @@ var require_changeTour = __commonJS({
|
|
|
4115
4140
|
if (deconstructed) {
|
|
4116
4141
|
requireStringArray(step.introducedHunks, `scenes[${index}].steps[${stepIndex}].introducedHunks`);
|
|
4117
4142
|
if (step.introducedHunks.length === 0) throw new Error(`scenes[${index}].steps[${stepIndex}].introducedHunks must be non-empty.`);
|
|
4118
|
-
if (Number(step.pairIndex) !== stepIndex) throw new Error(`scenes[${index}].steps[${stepIndex}].pairIndex must match its explanation stage.`);
|
|
4119
4143
|
}
|
|
4120
4144
|
if (step.side !== "left" && step.side !== "right") throw new Error(`scenes[${index}].steps[${stepIndex}].side must be left or right.`);
|
|
4121
4145
|
if (step.startLine !== void 0) requirePositiveInteger(step.startLine, `scenes[${index}].steps[${stepIndex}].startLine`);
|
|
@@ -4755,6 +4779,7 @@ var require_changeTour = __commonJS({
|
|
|
4755
4779
|
for (const { stage, claims } of stageClaims) {
|
|
4756
4780
|
const introducedHunks = [];
|
|
4757
4781
|
const introducedFiles = [];
|
|
4782
|
+
const introducedChanges = [];
|
|
4758
4783
|
for (const claim of claims) {
|
|
4759
4784
|
const cumulative = cumulativeByFile.get(claim.file) || /* @__PURE__ */ new Set();
|
|
4760
4785
|
claim.ids.forEach((id) => {
|
|
@@ -4763,6 +4788,12 @@ var require_changeTour = __commonJS({
|
|
|
4763
4788
|
});
|
|
4764
4789
|
cumulativeByFile.set(claim.file, cumulative);
|
|
4765
4790
|
if (!introducedFiles.includes(claim.file.path)) introducedFiles.push(claim.file.path);
|
|
4791
|
+
const introducedChange = introducedChanges.find((change) => change.file === claim.file.path);
|
|
4792
|
+
if (introducedChange) {
|
|
4793
|
+
introducedChange.hunks.push(...claim.ids);
|
|
4794
|
+
} else {
|
|
4795
|
+
introducedChanges.push({ file: claim.file.path, hunks: [...claim.ids] });
|
|
4796
|
+
}
|
|
4766
4797
|
}
|
|
4767
4798
|
stages.push({
|
|
4768
4799
|
id: stage.id,
|
|
@@ -4770,6 +4801,7 @@ var require_changeTour = __commonJS({
|
|
|
4770
4801
|
narration: stage.narration,
|
|
4771
4802
|
introducedHunks,
|
|
4772
4803
|
introducedFiles,
|
|
4804
|
+
introducedChanges,
|
|
4773
4805
|
cumulativeHunks: [...cumulativeByFile.values()].flatMap((ids) => [...ids]),
|
|
4774
4806
|
files: materializableFiles.map((file) => buildFileState(
|
|
4775
4807
|
file,
|
|
@@ -4834,6 +4866,1195 @@ var require_changeTour = __commonJS({
|
|
|
4834
4866
|
appliedHunks: [...selected]
|
|
4835
4867
|
};
|
|
4836
4868
|
}
|
|
4869
|
+
function Diff2() {
|
|
4870
|
+
}
|
|
4871
|
+
Diff2.prototype = {
|
|
4872
|
+
diff: function diff2(oldString, newString) {
|
|
4873
|
+
var _options$timeout;
|
|
4874
|
+
var options = arguments.length > 2 && arguments[2] !== void 0 ? arguments[2] : {};
|
|
4875
|
+
var callback = options.callback;
|
|
4876
|
+
if (typeof options === "function") {
|
|
4877
|
+
callback = options;
|
|
4878
|
+
options = {};
|
|
4879
|
+
}
|
|
4880
|
+
this.options = options;
|
|
4881
|
+
var self2 = this;
|
|
4882
|
+
function done(value) {
|
|
4883
|
+
if (callback) {
|
|
4884
|
+
setTimeout(function() {
|
|
4885
|
+
callback(void 0, value);
|
|
4886
|
+
}, 0);
|
|
4887
|
+
return true;
|
|
4888
|
+
} else {
|
|
4889
|
+
return value;
|
|
4890
|
+
}
|
|
4891
|
+
}
|
|
4892
|
+
oldString = this.castInput(oldString);
|
|
4893
|
+
newString = this.castInput(newString);
|
|
4894
|
+
oldString = this.removeEmpty(this.tokenize(oldString));
|
|
4895
|
+
newString = this.removeEmpty(this.tokenize(newString));
|
|
4896
|
+
var newLen = newString.length, oldLen = oldString.length;
|
|
4897
|
+
var editLength = 1;
|
|
4898
|
+
var maxEditLength = newLen + oldLen;
|
|
4899
|
+
if (options.maxEditLength) {
|
|
4900
|
+
maxEditLength = Math.min(maxEditLength, options.maxEditLength);
|
|
4901
|
+
}
|
|
4902
|
+
var maxExecutionTime = (_options$timeout = options.timeout) !== null && _options$timeout !== void 0 ? _options$timeout : Infinity;
|
|
4903
|
+
var abortAfterTimestamp = Date.now() + maxExecutionTime;
|
|
4904
|
+
var bestPath = [{
|
|
4905
|
+
oldPos: -1,
|
|
4906
|
+
lastComponent: void 0
|
|
4907
|
+
}];
|
|
4908
|
+
var newPos = this.extractCommon(bestPath[0], newString, oldString, 0);
|
|
4909
|
+
if (bestPath[0].oldPos + 1 >= oldLen && newPos + 1 >= newLen) {
|
|
4910
|
+
return done([{
|
|
4911
|
+
value: this.join(newString),
|
|
4912
|
+
count: newString.length
|
|
4913
|
+
}]);
|
|
4914
|
+
}
|
|
4915
|
+
var minDiagonalToConsider = -Infinity, maxDiagonalToConsider = Infinity;
|
|
4916
|
+
function execEditLength() {
|
|
4917
|
+
for (var diagonalPath = Math.max(minDiagonalToConsider, -editLength); diagonalPath <= Math.min(maxDiagonalToConsider, editLength); diagonalPath += 2) {
|
|
4918
|
+
var basePath = void 0;
|
|
4919
|
+
var removePath = bestPath[diagonalPath - 1], addPath = bestPath[diagonalPath + 1];
|
|
4920
|
+
if (removePath) {
|
|
4921
|
+
bestPath[diagonalPath - 1] = void 0;
|
|
4922
|
+
}
|
|
4923
|
+
var canAdd = false;
|
|
4924
|
+
if (addPath) {
|
|
4925
|
+
var addPathNewPos = addPath.oldPos - diagonalPath;
|
|
4926
|
+
canAdd = addPath && 0 <= addPathNewPos && addPathNewPos < newLen;
|
|
4927
|
+
}
|
|
4928
|
+
var canRemove = removePath && removePath.oldPos + 1 < oldLen;
|
|
4929
|
+
if (!canAdd && !canRemove) {
|
|
4930
|
+
bestPath[diagonalPath] = void 0;
|
|
4931
|
+
continue;
|
|
4932
|
+
}
|
|
4933
|
+
if (!canRemove || canAdd && removePath.oldPos + 1 < addPath.oldPos) {
|
|
4934
|
+
basePath = self2.addToPath(addPath, true, void 0, 0);
|
|
4935
|
+
} else {
|
|
4936
|
+
basePath = self2.addToPath(removePath, void 0, true, 1);
|
|
4937
|
+
}
|
|
4938
|
+
newPos = self2.extractCommon(basePath, newString, oldString, diagonalPath);
|
|
4939
|
+
if (basePath.oldPos + 1 >= oldLen && newPos + 1 >= newLen) {
|
|
4940
|
+
return done(buildValues2(self2, basePath.lastComponent, newString, oldString, self2.useLongestToken));
|
|
4941
|
+
} else {
|
|
4942
|
+
bestPath[diagonalPath] = basePath;
|
|
4943
|
+
if (basePath.oldPos + 1 >= oldLen) {
|
|
4944
|
+
maxDiagonalToConsider = Math.min(maxDiagonalToConsider, diagonalPath - 1);
|
|
4945
|
+
}
|
|
4946
|
+
if (newPos + 1 >= newLen) {
|
|
4947
|
+
minDiagonalToConsider = Math.max(minDiagonalToConsider, diagonalPath + 1);
|
|
4948
|
+
}
|
|
4949
|
+
}
|
|
4950
|
+
}
|
|
4951
|
+
editLength++;
|
|
4952
|
+
}
|
|
4953
|
+
if (callback) {
|
|
4954
|
+
(function exec() {
|
|
4955
|
+
setTimeout(function() {
|
|
4956
|
+
if (editLength > maxEditLength || Date.now() > abortAfterTimestamp) {
|
|
4957
|
+
return callback();
|
|
4958
|
+
}
|
|
4959
|
+
if (!execEditLength()) {
|
|
4960
|
+
exec();
|
|
4961
|
+
}
|
|
4962
|
+
}, 0);
|
|
4963
|
+
})();
|
|
4964
|
+
} else {
|
|
4965
|
+
while (editLength <= maxEditLength && Date.now() <= abortAfterTimestamp) {
|
|
4966
|
+
var ret = execEditLength();
|
|
4967
|
+
if (ret) {
|
|
4968
|
+
return ret;
|
|
4969
|
+
}
|
|
4970
|
+
}
|
|
4971
|
+
}
|
|
4972
|
+
},
|
|
4973
|
+
addToPath: function addToPath2(path9, added, removed, oldPosInc) {
|
|
4974
|
+
var last = path9.lastComponent;
|
|
4975
|
+
if (last && last.added === added && last.removed === removed) {
|
|
4976
|
+
return {
|
|
4977
|
+
oldPos: path9.oldPos + oldPosInc,
|
|
4978
|
+
lastComponent: {
|
|
4979
|
+
count: last.count + 1,
|
|
4980
|
+
added,
|
|
4981
|
+
removed,
|
|
4982
|
+
previousComponent: last.previousComponent
|
|
4983
|
+
}
|
|
4984
|
+
};
|
|
4985
|
+
} else {
|
|
4986
|
+
return {
|
|
4987
|
+
oldPos: path9.oldPos + oldPosInc,
|
|
4988
|
+
lastComponent: {
|
|
4989
|
+
count: 1,
|
|
4990
|
+
added,
|
|
4991
|
+
removed,
|
|
4992
|
+
previousComponent: last
|
|
4993
|
+
}
|
|
4994
|
+
};
|
|
4995
|
+
}
|
|
4996
|
+
},
|
|
4997
|
+
extractCommon: function extractCommon2(basePath, newString, oldString, diagonalPath) {
|
|
4998
|
+
var newLen = newString.length, oldLen = oldString.length, oldPos = basePath.oldPos, newPos = oldPos - diagonalPath, commonCount = 0;
|
|
4999
|
+
while (newPos + 1 < newLen && oldPos + 1 < oldLen && this.equals(newString[newPos + 1], oldString[oldPos + 1])) {
|
|
5000
|
+
newPos++;
|
|
5001
|
+
oldPos++;
|
|
5002
|
+
commonCount++;
|
|
5003
|
+
}
|
|
5004
|
+
if (commonCount) {
|
|
5005
|
+
basePath.lastComponent = {
|
|
5006
|
+
count: commonCount,
|
|
5007
|
+
previousComponent: basePath.lastComponent
|
|
5008
|
+
};
|
|
5009
|
+
}
|
|
5010
|
+
basePath.oldPos = oldPos;
|
|
5011
|
+
return newPos;
|
|
5012
|
+
},
|
|
5013
|
+
equals: function equals2(left, right) {
|
|
5014
|
+
if (this.options.comparator) {
|
|
5015
|
+
return this.options.comparator(left, right);
|
|
5016
|
+
} else {
|
|
5017
|
+
return left === right || this.options.ignoreCase && left.toLowerCase() === right.toLowerCase();
|
|
5018
|
+
}
|
|
5019
|
+
},
|
|
5020
|
+
removeEmpty: function removeEmpty2(array) {
|
|
5021
|
+
var ret = [];
|
|
5022
|
+
for (var i = 0; i < array.length; i++) {
|
|
5023
|
+
if (array[i]) {
|
|
5024
|
+
ret.push(array[i]);
|
|
5025
|
+
}
|
|
5026
|
+
}
|
|
5027
|
+
return ret;
|
|
5028
|
+
},
|
|
5029
|
+
castInput: function castInput2(value) {
|
|
5030
|
+
return value;
|
|
5031
|
+
},
|
|
5032
|
+
tokenize: function tokenize2(value) {
|
|
5033
|
+
return value.split("");
|
|
5034
|
+
},
|
|
5035
|
+
join: function join4(chars) {
|
|
5036
|
+
return chars.join("");
|
|
5037
|
+
}
|
|
5038
|
+
};
|
|
5039
|
+
function buildValues2(diff2, lastComponent, newString, oldString, useLongestToken) {
|
|
5040
|
+
var components = [];
|
|
5041
|
+
var nextComponent;
|
|
5042
|
+
while (lastComponent) {
|
|
5043
|
+
components.push(lastComponent);
|
|
5044
|
+
nextComponent = lastComponent.previousComponent;
|
|
5045
|
+
delete lastComponent.previousComponent;
|
|
5046
|
+
lastComponent = nextComponent;
|
|
5047
|
+
}
|
|
5048
|
+
components.reverse();
|
|
5049
|
+
var componentPos = 0, componentLen = components.length, newPos = 0, oldPos = 0;
|
|
5050
|
+
for (; componentPos < componentLen; componentPos++) {
|
|
5051
|
+
var component = components[componentPos];
|
|
5052
|
+
if (!component.removed) {
|
|
5053
|
+
if (!component.added && useLongestToken) {
|
|
5054
|
+
var value = newString.slice(newPos, newPos + component.count);
|
|
5055
|
+
value = value.map(function(value2, i) {
|
|
5056
|
+
var oldValue = oldString[oldPos + i];
|
|
5057
|
+
return oldValue.length > value2.length ? oldValue : value2;
|
|
5058
|
+
});
|
|
5059
|
+
component.value = diff2.join(value);
|
|
5060
|
+
} else {
|
|
5061
|
+
component.value = diff2.join(newString.slice(newPos, newPos + component.count));
|
|
5062
|
+
}
|
|
5063
|
+
newPos += component.count;
|
|
5064
|
+
if (!component.added) {
|
|
5065
|
+
oldPos += component.count;
|
|
5066
|
+
}
|
|
5067
|
+
} else {
|
|
5068
|
+
component.value = diff2.join(oldString.slice(oldPos, oldPos + component.count));
|
|
5069
|
+
oldPos += component.count;
|
|
5070
|
+
if (componentPos && components[componentPos - 1].added) {
|
|
5071
|
+
var tmp = components[componentPos - 1];
|
|
5072
|
+
components[componentPos - 1] = components[componentPos];
|
|
5073
|
+
components[componentPos] = tmp;
|
|
5074
|
+
}
|
|
5075
|
+
}
|
|
5076
|
+
}
|
|
5077
|
+
var finalComponent = components[componentLen - 1];
|
|
5078
|
+
if (componentLen > 1 && typeof finalComponent.value === "string" && (finalComponent.added || finalComponent.removed) && diff2.equals("", finalComponent.value)) {
|
|
5079
|
+
components[componentLen - 2].value += finalComponent.value;
|
|
5080
|
+
components.pop();
|
|
5081
|
+
}
|
|
5082
|
+
return components;
|
|
5083
|
+
}
|
|
5084
|
+
var characterDiff2 = new Diff2();
|
|
5085
|
+
function diffChars2(oldStr, newStr, options) {
|
|
5086
|
+
return characterDiff2.diff(oldStr, newStr, options);
|
|
5087
|
+
}
|
|
5088
|
+
var extendedWordChars2 = /^[A-Za-z\xC0-\u02C6\u02C8-\u02D7\u02DE-\u02FF\u1E00-\u1EFF]+$/;
|
|
5089
|
+
var reWhitespace2 = /\S/;
|
|
5090
|
+
var wordDiff2 = new Diff2();
|
|
5091
|
+
wordDiff2.equals = function(left, right) {
|
|
5092
|
+
if (this.options.ignoreCase) {
|
|
5093
|
+
left = left.toLowerCase();
|
|
5094
|
+
right = right.toLowerCase();
|
|
5095
|
+
}
|
|
5096
|
+
return left === right || this.options.ignoreWhitespace && !reWhitespace2.test(left) && !reWhitespace2.test(right);
|
|
5097
|
+
};
|
|
5098
|
+
wordDiff2.tokenize = function(value) {
|
|
5099
|
+
var tokens = value.split(/([^\S\r\n]+|[()[\]{}'"\r\n]|\b)/);
|
|
5100
|
+
for (var i = 0; i < tokens.length - 1; i++) {
|
|
5101
|
+
if (!tokens[i + 1] && tokens[i + 2] && extendedWordChars2.test(tokens[i]) && extendedWordChars2.test(tokens[i + 2])) {
|
|
5102
|
+
tokens[i] += tokens[i + 2];
|
|
5103
|
+
tokens.splice(i + 1, 2);
|
|
5104
|
+
i--;
|
|
5105
|
+
}
|
|
5106
|
+
}
|
|
5107
|
+
return tokens;
|
|
5108
|
+
};
|
|
5109
|
+
function diffWordsWithSpace2(oldStr, newStr, options) {
|
|
5110
|
+
return wordDiff2.diff(oldStr, newStr, options);
|
|
5111
|
+
}
|
|
5112
|
+
var lineDiff2 = new Diff2();
|
|
5113
|
+
lineDiff2.tokenize = function(value) {
|
|
5114
|
+
if (this.options.stripTrailingCr) {
|
|
5115
|
+
value = value.replace(/\r\n/g, "\n");
|
|
5116
|
+
}
|
|
5117
|
+
var retLines = [], linesAndNewlines = value.split(/(\n|\r\n)/);
|
|
5118
|
+
if (!linesAndNewlines[linesAndNewlines.length - 1]) {
|
|
5119
|
+
linesAndNewlines.pop();
|
|
5120
|
+
}
|
|
5121
|
+
for (var i = 0; i < linesAndNewlines.length; i++) {
|
|
5122
|
+
var line = linesAndNewlines[i];
|
|
5123
|
+
if (i % 2 && !this.options.newlineIsToken) {
|
|
5124
|
+
retLines[retLines.length - 1] += line;
|
|
5125
|
+
} else {
|
|
5126
|
+
if (this.options.ignoreWhitespace) {
|
|
5127
|
+
line = line.trim();
|
|
5128
|
+
}
|
|
5129
|
+
retLines.push(line);
|
|
5130
|
+
}
|
|
5131
|
+
}
|
|
5132
|
+
return retLines;
|
|
5133
|
+
};
|
|
5134
|
+
var sentenceDiff2 = new Diff2();
|
|
5135
|
+
sentenceDiff2.tokenize = function(value) {
|
|
5136
|
+
return value.split(/(\S.+?[.!?])(?=\s+|$)/);
|
|
5137
|
+
};
|
|
5138
|
+
var cssDiff2 = new Diff2();
|
|
5139
|
+
cssDiff2.tokenize = function(value) {
|
|
5140
|
+
return value.split(/([{}:;,]|\s+)/);
|
|
5141
|
+
};
|
|
5142
|
+
function _typeof2(obj) {
|
|
5143
|
+
"@babel/helpers - typeof";
|
|
5144
|
+
if (typeof Symbol === "function" && typeof Symbol.iterator === "symbol") {
|
|
5145
|
+
_typeof2 = function(obj2) {
|
|
5146
|
+
return typeof obj2;
|
|
5147
|
+
};
|
|
5148
|
+
} else {
|
|
5149
|
+
_typeof2 = function(obj2) {
|
|
5150
|
+
return obj2 && typeof Symbol === "function" && obj2.constructor === Symbol && obj2 !== Symbol.prototype ? "symbol" : typeof obj2;
|
|
5151
|
+
};
|
|
5152
|
+
}
|
|
5153
|
+
return _typeof2(obj);
|
|
5154
|
+
}
|
|
5155
|
+
var objectPrototypeToString2 = Object.prototype.toString;
|
|
5156
|
+
var jsonDiff2 = new Diff2();
|
|
5157
|
+
jsonDiff2.useLongestToken = true;
|
|
5158
|
+
jsonDiff2.tokenize = lineDiff2.tokenize;
|
|
5159
|
+
jsonDiff2.castInput = function(value) {
|
|
5160
|
+
var _this$options = this.options, undefinedReplacement = _this$options.undefinedReplacement, _this$options$stringi = _this$options.stringifyReplacer, stringifyReplacer = _this$options$stringi === void 0 ? function(k, v) {
|
|
5161
|
+
return typeof v === "undefined" ? undefinedReplacement : v;
|
|
5162
|
+
} : _this$options$stringi;
|
|
5163
|
+
return typeof value === "string" ? value : JSON.stringify(canonicalize2(value, null, null, stringifyReplacer), stringifyReplacer, " ");
|
|
5164
|
+
};
|
|
5165
|
+
jsonDiff2.equals = function(left, right) {
|
|
5166
|
+
return Diff2.prototype.equals.call(jsonDiff2, left.replace(/,([\r\n])/g, "$1"), right.replace(/,([\r\n])/g, "$1"));
|
|
5167
|
+
};
|
|
5168
|
+
function canonicalize2(obj, stack, replacementStack, replacer, key) {
|
|
5169
|
+
stack = stack || [];
|
|
5170
|
+
replacementStack = replacementStack || [];
|
|
5171
|
+
if (replacer) {
|
|
5172
|
+
obj = replacer(key, obj);
|
|
5173
|
+
}
|
|
5174
|
+
var i;
|
|
5175
|
+
for (i = 0; i < stack.length; i += 1) {
|
|
5176
|
+
if (stack[i] === obj) {
|
|
5177
|
+
return replacementStack[i];
|
|
5178
|
+
}
|
|
5179
|
+
}
|
|
5180
|
+
var canonicalizedObj;
|
|
5181
|
+
if ("[object Array]" === objectPrototypeToString2.call(obj)) {
|
|
5182
|
+
stack.push(obj);
|
|
5183
|
+
canonicalizedObj = new Array(obj.length);
|
|
5184
|
+
replacementStack.push(canonicalizedObj);
|
|
5185
|
+
for (i = 0; i < obj.length; i += 1) {
|
|
5186
|
+
canonicalizedObj[i] = canonicalize2(obj[i], stack, replacementStack, replacer, key);
|
|
5187
|
+
}
|
|
5188
|
+
stack.pop();
|
|
5189
|
+
replacementStack.pop();
|
|
5190
|
+
return canonicalizedObj;
|
|
5191
|
+
}
|
|
5192
|
+
if (obj && obj.toJSON) {
|
|
5193
|
+
obj = obj.toJSON();
|
|
5194
|
+
}
|
|
5195
|
+
if (_typeof2(obj) === "object" && obj !== null) {
|
|
5196
|
+
stack.push(obj);
|
|
5197
|
+
canonicalizedObj = {};
|
|
5198
|
+
replacementStack.push(canonicalizedObj);
|
|
5199
|
+
var sortedKeys = [], _key;
|
|
5200
|
+
for (_key in obj) {
|
|
5201
|
+
if (obj.hasOwnProperty(_key)) {
|
|
5202
|
+
sortedKeys.push(_key);
|
|
5203
|
+
}
|
|
5204
|
+
}
|
|
5205
|
+
sortedKeys.sort();
|
|
5206
|
+
for (i = 0; i < sortedKeys.length; i += 1) {
|
|
5207
|
+
_key = sortedKeys[i];
|
|
5208
|
+
canonicalizedObj[_key] = canonicalize2(obj[_key], stack, replacementStack, replacer, _key);
|
|
5209
|
+
}
|
|
5210
|
+
stack.pop();
|
|
5211
|
+
replacementStack.pop();
|
|
5212
|
+
} else {
|
|
5213
|
+
canonicalizedObj = obj;
|
|
5214
|
+
}
|
|
5215
|
+
return canonicalizedObj;
|
|
5216
|
+
}
|
|
5217
|
+
var arrayDiff2 = new Diff2();
|
|
5218
|
+
arrayDiff2.tokenize = function(value) {
|
|
5219
|
+
return value.slice();
|
|
5220
|
+
};
|
|
5221
|
+
arrayDiff2.join = arrayDiff2.removeEmpty = function(value) {
|
|
5222
|
+
return value;
|
|
5223
|
+
};
|
|
5224
|
+
function diffArrays2(oldArr, newArr, callback) {
|
|
5225
|
+
return arrayDiff2.diff(oldArr, newArr, callback);
|
|
5226
|
+
}
|
|
5227
|
+
var DEFAULT_MAX_INLINE_HIGHLIGHT_LINE_LENGTH2 = 500;
|
|
5228
|
+
var DEFAULT_DIFF_TIMEOUT_MS2 = 100;
|
|
5229
|
+
var MAX_INLINE_HIGHLIGHT_LINE_LENGTH2 = readPositiveIntegerEnv4(
|
|
5230
|
+
"BYGONE_MAX_INLINE_HIGHLIGHT_LINE_LENGTH",
|
|
5231
|
+
DEFAULT_MAX_INLINE_HIGHLIGHT_LINE_LENGTH2
|
|
5232
|
+
);
|
|
5233
|
+
var DIFF_TIMEOUT_MS2 = readPositiveIntegerEnv4("BYGONE_DIFF_TIMEOUT_MS", DEFAULT_DIFF_TIMEOUT_MS2);
|
|
5234
|
+
function buildTwoWayDiffModel3(leftContent, rightContent, options = {}) {
|
|
5235
|
+
const leftLines = normalizeLines2(leftContent);
|
|
5236
|
+
const rightLines = normalizeLines2(rightContent);
|
|
5237
|
+
const changes = diffArrays2(leftLines, rightLines, {
|
|
5238
|
+
timeout: options.timeoutMs ?? DIFF_TIMEOUT_MS2
|
|
5239
|
+
});
|
|
5240
|
+
if (!changes) {
|
|
5241
|
+
return buildConservativeTwoWayDiffModel2(leftLines, rightLines);
|
|
5242
|
+
}
|
|
5243
|
+
const rows = [];
|
|
5244
|
+
const renderedLeftLines = [];
|
|
5245
|
+
const renderedRightLines = [];
|
|
5246
|
+
const blocks = [];
|
|
5247
|
+
let leftLineNumber = 1;
|
|
5248
|
+
let rightLineNumber = 1;
|
|
5249
|
+
for (let index = 0; index < changes.length; index++) {
|
|
5250
|
+
const change = changes[index];
|
|
5251
|
+
const removedLines = change.removed ? change.value : [];
|
|
5252
|
+
const addedLines = change.added ? change.value : [];
|
|
5253
|
+
if (!change.added && !change.removed) {
|
|
5254
|
+
for (const line of change.value) {
|
|
5255
|
+
renderedLeftLines.push(makeDiffLine2("context", line, leftLineNumber));
|
|
5256
|
+
renderedRightLines.push(makeDiffLine2("context", line, rightLineNumber));
|
|
5257
|
+
rows.push(makeDiffRow2(
|
|
5258
|
+
makeDiffCell2("context", line, leftLineNumber++),
|
|
5259
|
+
makeDiffCell2("context", line, rightLineNumber++)
|
|
5260
|
+
));
|
|
5261
|
+
}
|
|
5262
|
+
continue;
|
|
5263
|
+
}
|
|
5264
|
+
if (change.removed && index + 1 < changes.length && changes[index + 1].added) {
|
|
5265
|
+
const nextChange = changes[index + 1];
|
|
5266
|
+
const leftStart = renderedLeftLines.length;
|
|
5267
|
+
const rightStart = renderedRightLines.length;
|
|
5268
|
+
const alignedLines = alignReplacementLines2(removedLines, nextChange.value);
|
|
5269
|
+
for (const { left: removedLine, right: addedLine } of alignedLines) {
|
|
5270
|
+
let renderedLeftLine;
|
|
5271
|
+
let renderedRightLine;
|
|
5272
|
+
if (removedLine !== void 0) {
|
|
5273
|
+
renderedLeftLine = makeDiffLine2("removed", removedLine, leftLineNumber);
|
|
5274
|
+
renderedLeftLines.push(renderedLeftLine);
|
|
5275
|
+
}
|
|
5276
|
+
if (addedLine !== void 0) {
|
|
5277
|
+
renderedRightLine = makeDiffLine2("added", addedLine, rightLineNumber);
|
|
5278
|
+
renderedRightLines.push(renderedRightLine);
|
|
5279
|
+
}
|
|
5280
|
+
if (renderedLeftLine && renderedRightLine) {
|
|
5281
|
+
applyInlineHighlightPair2(renderedLeftLine, renderedRightLine);
|
|
5282
|
+
}
|
|
5283
|
+
rows.push(makeDiffRow2(
|
|
5284
|
+
removedLine === void 0 ? makePlaceholder2() : makeDiffCell2("removed", removedLine, leftLineNumber++),
|
|
5285
|
+
addedLine === void 0 ? makePlaceholder2() : makeDiffCell2("added", addedLine, rightLineNumber++)
|
|
5286
|
+
));
|
|
5287
|
+
}
|
|
5288
|
+
blocks.push(makeDiffBlock2("replace", leftStart, renderedLeftLines.length, rightStart, renderedRightLines.length));
|
|
5289
|
+
index++;
|
|
5290
|
+
continue;
|
|
5291
|
+
}
|
|
5292
|
+
if (change.removed) {
|
|
5293
|
+
const leftStart = renderedLeftLines.length;
|
|
5294
|
+
const rightStart = renderedRightLines.length;
|
|
5295
|
+
for (const line of removedLines) {
|
|
5296
|
+
renderedLeftLines.push(makeDiffLine2("removed", line, leftLineNumber));
|
|
5297
|
+
rows.push(makeDiffRow2(
|
|
5298
|
+
makeDiffCell2("removed", line, leftLineNumber++),
|
|
5299
|
+
makePlaceholder2()
|
|
5300
|
+
));
|
|
5301
|
+
}
|
|
5302
|
+
blocks.push(makeDiffBlock2("delete", leftStart, renderedLeftLines.length, rightStart, renderedRightLines.length));
|
|
5303
|
+
continue;
|
|
5304
|
+
}
|
|
5305
|
+
if (change.added) {
|
|
5306
|
+
const leftStart = renderedLeftLines.length;
|
|
5307
|
+
const rightStart = renderedRightLines.length;
|
|
5308
|
+
for (const line of addedLines) {
|
|
5309
|
+
renderedRightLines.push(makeDiffLine2("added", line, rightLineNumber));
|
|
5310
|
+
rows.push(makeDiffRow2(
|
|
5311
|
+
makePlaceholder2(),
|
|
5312
|
+
makeDiffCell2("added", line, rightLineNumber++)
|
|
5313
|
+
));
|
|
5314
|
+
}
|
|
5315
|
+
blocks.push(makeDiffBlock2("insert", leftStart, renderedLeftLines.length, rightStart, renderedRightLines.length));
|
|
5316
|
+
}
|
|
5317
|
+
}
|
|
5318
|
+
const hasChanges = rows.some((row) => row.left.kind !== "context" || row.right.kind !== "context");
|
|
5319
|
+
return {
|
|
5320
|
+
rows,
|
|
5321
|
+
leftLines: renderedLeftLines,
|
|
5322
|
+
rightLines: renderedRightLines,
|
|
5323
|
+
blocks,
|
|
5324
|
+
hasChanges
|
|
5325
|
+
};
|
|
5326
|
+
}
|
|
5327
|
+
function buildConservativeTwoWayDiffModel2(leftLines, rightLines) {
|
|
5328
|
+
const renderedLeftLines = leftLines.map((line, index) => makeDiffLine2("removed", line, index + 1));
|
|
5329
|
+
const renderedRightLines = rightLines.map((line, index) => makeDiffLine2("added", line, index + 1));
|
|
5330
|
+
const rows = [
|
|
5331
|
+
...leftLines.map((line, index) => makeDiffRow2(
|
|
5332
|
+
makeDiffCell2("removed", line, index + 1),
|
|
5333
|
+
makePlaceholder2()
|
|
5334
|
+
)),
|
|
5335
|
+
...rightLines.map((line, index) => makeDiffRow2(
|
|
5336
|
+
makePlaceholder2(),
|
|
5337
|
+
makeDiffCell2("added", line, index + 1)
|
|
5338
|
+
))
|
|
5339
|
+
];
|
|
5340
|
+
let blockKind = "replace";
|
|
5341
|
+
if (leftLines.length === 0) {
|
|
5342
|
+
blockKind = "insert";
|
|
5343
|
+
} else if (rightLines.length === 0) {
|
|
5344
|
+
blockKind = "delete";
|
|
5345
|
+
}
|
|
5346
|
+
return {
|
|
5347
|
+
rows,
|
|
5348
|
+
leftLines: renderedLeftLines,
|
|
5349
|
+
rightLines: renderedRightLines,
|
|
5350
|
+
blocks: rows.length === 0 ? [] : [makeDiffBlock2(blockKind, 0, leftLines.length, 0, rightLines.length)],
|
|
5351
|
+
hasChanges: rows.length > 0
|
|
5352
|
+
};
|
|
5353
|
+
}
|
|
5354
|
+
function normalizeLines2(content) {
|
|
5355
|
+
if (content.length === 0) {
|
|
5356
|
+
return [];
|
|
5357
|
+
}
|
|
5358
|
+
const lines = content.replace(/\r\n/g, "\n").split("\n");
|
|
5359
|
+
if (lines[lines.length - 1] === "") {
|
|
5360
|
+
lines.pop();
|
|
5361
|
+
}
|
|
5362
|
+
return lines;
|
|
5363
|
+
}
|
|
5364
|
+
var MAX_ALIGNMENT_CELLS2 = 1e4;
|
|
5365
|
+
var MAX_SCORING_LINE_LENGTH2 = 2e3;
|
|
5366
|
+
var MINIMUM_MATCH_SCORE2 = 0.52;
|
|
5367
|
+
var MINIMUM_SINGLE_PAIR_SCORE2 = 0.35;
|
|
5368
|
+
var MINIMUM_CONTEXTUAL_MATCH_SCORE2 = 0.38;
|
|
5369
|
+
var MINIMUM_CONTEXTUAL_RUN_SCORE2 = 0.33;
|
|
5370
|
+
var HIGH_CONFIDENCE_MATCH_SCORE2 = 0.86;
|
|
5371
|
+
var AMBIGUITY_MARGIN2 = 0.08;
|
|
5372
|
+
var CONTEXTUAL_AMBIGUITY_MARGIN2 = 0.05;
|
|
5373
|
+
var GAP_PENALTY2 = -0.12;
|
|
5374
|
+
var MAX_BOUNDED_CANDIDATES2 = 5e3;
|
|
5375
|
+
var MAX_LARGE_HUNK_ANCHORS2 = 2e3;
|
|
5376
|
+
var MAX_RARE_TOKEN_OCCURRENCES2 = 4;
|
|
5377
|
+
var MAX_CONTEXTUAL_HUNK_LINES2 = 8;
|
|
5378
|
+
var MAX_CONTEXTUAL_LENGTH_DELTA2 = 4;
|
|
5379
|
+
function alignReplacementLines2(leftLines, rightLines) {
|
|
5380
|
+
if (leftLines.length === 0) {
|
|
5381
|
+
return rightLines.map((right) => ({ right }));
|
|
5382
|
+
}
|
|
5383
|
+
if (rightLines.length === 0) {
|
|
5384
|
+
return leftLines.map((left) => ({ left }));
|
|
5385
|
+
}
|
|
5386
|
+
if (leftLines.length === 1 && rightLines.length === 1) {
|
|
5387
|
+
const singletonScore = scoreReplacementLinePair2(leftLines[0], rightLines[0]);
|
|
5388
|
+
if ((singletonScore.eligible || singletonScore.score >= MINIMUM_SINGLE_PAIR_SCORE2) && haveCompatibleLineRoles2(leftLines[0], rightLines[0]) && isInformativeLine2(normalizeMatchingContent2(leftLines[0])) && isInformativeLine2(normalizeMatchingContent2(rightLines[0]))) {
|
|
5389
|
+
return [{ left: leftLines[0], right: rightLines[0] }];
|
|
5390
|
+
}
|
|
5391
|
+
return [{ left: leftLines[0] }, { right: rightLines[0] }];
|
|
5392
|
+
}
|
|
5393
|
+
if (leftLines.length * rightLines.length > MAX_ALIGNMENT_CELLS2) {
|
|
5394
|
+
return alignLargeReplacementLines2(leftLines, rightLines);
|
|
5395
|
+
}
|
|
5396
|
+
const pairScores = buildPairScores2(leftLines, rightLines);
|
|
5397
|
+
const scores = Array.from(
|
|
5398
|
+
{ length: leftLines.length + 1 },
|
|
5399
|
+
() => new Array(rightLines.length + 1).fill(Number.NEGATIVE_INFINITY)
|
|
5400
|
+
);
|
|
5401
|
+
const moves = Array.from(
|
|
5402
|
+
{ length: leftLines.length + 1 },
|
|
5403
|
+
() => new Array(rightLines.length + 1).fill(null)
|
|
5404
|
+
);
|
|
5405
|
+
scores[0][0] = 0;
|
|
5406
|
+
for (let leftIndex2 = 1; leftIndex2 <= leftLines.length; leftIndex2++) {
|
|
5407
|
+
scores[leftIndex2][0] = scores[leftIndex2 - 1][0] + GAP_PENALTY2;
|
|
5408
|
+
moves[leftIndex2][0] = "left";
|
|
5409
|
+
}
|
|
5410
|
+
for (let rightIndex2 = 1; rightIndex2 <= rightLines.length; rightIndex2++) {
|
|
5411
|
+
scores[0][rightIndex2] = scores[0][rightIndex2 - 1] + GAP_PENALTY2;
|
|
5412
|
+
moves[0][rightIndex2] = "right";
|
|
5413
|
+
}
|
|
5414
|
+
for (let leftIndex2 = 1; leftIndex2 <= leftLines.length; leftIndex2++) {
|
|
5415
|
+
for (let rightIndex2 = 1; rightIndex2 <= rightLines.length; rightIndex2++) {
|
|
5416
|
+
const pairScore = pairScores[leftIndex2 - 1][rightIndex2 - 1];
|
|
5417
|
+
const candidates = [
|
|
5418
|
+
{ move: "left", score: scores[leftIndex2 - 1][rightIndex2] + GAP_PENALTY2 },
|
|
5419
|
+
{ move: "right", score: scores[leftIndex2][rightIndex2 - 1] + GAP_PENALTY2 },
|
|
5420
|
+
{
|
|
5421
|
+
move: "match",
|
|
5422
|
+
score: pairScore === null ? Number.NEGATIVE_INFINITY : scores[leftIndex2 - 1][rightIndex2 - 1] + pairScore
|
|
5423
|
+
}
|
|
5424
|
+
];
|
|
5425
|
+
const best = candidates.reduce((current, candidate) => candidate.score > current.score ? candidate : current);
|
|
5426
|
+
scores[leftIndex2][rightIndex2] = best.score;
|
|
5427
|
+
moves[leftIndex2][rightIndex2] = best.move;
|
|
5428
|
+
}
|
|
5429
|
+
}
|
|
5430
|
+
const aligned = [];
|
|
5431
|
+
let leftIndex = leftLines.length;
|
|
5432
|
+
let rightIndex = rightLines.length;
|
|
5433
|
+
while (leftIndex > 0 || rightIndex > 0) {
|
|
5434
|
+
const move = moves[leftIndex][rightIndex];
|
|
5435
|
+
if (move === "match") {
|
|
5436
|
+
aligned.push({ left: leftLines[--leftIndex], right: rightLines[--rightIndex] });
|
|
5437
|
+
} else if (move === "left") {
|
|
5438
|
+
aligned.push({ left: leftLines[--leftIndex] });
|
|
5439
|
+
} else {
|
|
5440
|
+
aligned.push({ right: rightLines[--rightIndex] });
|
|
5441
|
+
}
|
|
5442
|
+
}
|
|
5443
|
+
return aligned.reverse();
|
|
5444
|
+
}
|
|
5445
|
+
function scoreReplacementLinePair2(left, right) {
|
|
5446
|
+
const normalizedLeft = normalizeMatchingContent2(left);
|
|
5447
|
+
const normalizedRight = normalizeMatchingContent2(right);
|
|
5448
|
+
const leftInformative = isInformativeLine2(normalizedLeft);
|
|
5449
|
+
const rightInformative = isInformativeLine2(normalizedRight);
|
|
5450
|
+
if (!leftInformative || !rightInformative || normalizedLeft.length > MAX_SCORING_LINE_LENGTH2 || normalizedRight.length > MAX_SCORING_LINE_LENGTH2) {
|
|
5451
|
+
return {
|
|
5452
|
+
score: 0,
|
|
5453
|
+
eligible: false,
|
|
5454
|
+
characterSimilarity: 0,
|
|
5455
|
+
tokenSimilarity: 0,
|
|
5456
|
+
lengthSimilarity: 0
|
|
5457
|
+
};
|
|
5458
|
+
}
|
|
5459
|
+
if (normalizedLeft === normalizedRight) {
|
|
5460
|
+
return {
|
|
5461
|
+
score: 1,
|
|
5462
|
+
eligible: true,
|
|
5463
|
+
characterSimilarity: 1,
|
|
5464
|
+
tokenSimilarity: 1,
|
|
5465
|
+
lengthSimilarity: 1
|
|
5466
|
+
};
|
|
5467
|
+
}
|
|
5468
|
+
const leftTokens = tokenizeMatchingContent2(normalizedLeft);
|
|
5469
|
+
const rightTokens = tokenizeMatchingContent2(normalizedRight);
|
|
5470
|
+
const characterSimilarity = lineSimilarity2(normalizedLeft, normalizedRight);
|
|
5471
|
+
const tokenSimilarity = multisetDiceSimilarity2(leftTokens, rightTokens);
|
|
5472
|
+
const lengthSimilarity = Math.min(normalizedLeft.length, normalizedRight.length) / Math.max(normalizedLeft.length, normalizedRight.length);
|
|
5473
|
+
const boundarySimilarity = tokenBoundarySimilarity2(leftTokens, rightTokens);
|
|
5474
|
+
const score = characterSimilarity * 0.52 + tokenSimilarity * 0.32 + lengthSimilarity * 0.1 + boundarySimilarity * 0.06;
|
|
5475
|
+
const hasContentEvidence = characterSimilarity >= 0.52 || tokenSimilarity >= 0.45 || characterSimilarity >= 0.48 && tokenSimilarity >= 0.28;
|
|
5476
|
+
return {
|
|
5477
|
+
score,
|
|
5478
|
+
eligible: hasContentEvidence && score >= MINIMUM_MATCH_SCORE2,
|
|
5479
|
+
characterSimilarity,
|
|
5480
|
+
tokenSimilarity,
|
|
5481
|
+
lengthSimilarity
|
|
5482
|
+
};
|
|
5483
|
+
}
|
|
5484
|
+
function buildPairScores2(leftLines, rightLines) {
|
|
5485
|
+
const scored = leftLines.map((left) => rightLines.map((right) => scoreReplacementLinePair2(left, right)));
|
|
5486
|
+
const structuralPairs = collectUniqueStructuralPairs2(leftLines, rightLines);
|
|
5487
|
+
const leftRankings = scored.map((row) => rankEligibleScores2(row));
|
|
5488
|
+
const rightRankings = rightLines.map((_right, rightIndex) => rankEligibleScores2(scored.map((row) => row[rightIndex])));
|
|
5489
|
+
const accepted = scored.map((row, leftIndex) => row.map((candidate, rightIndex) => {
|
|
5490
|
+
if (structuralPairs.has(`${leftIndex}:${rightIndex}`)) {
|
|
5491
|
+
return Math.max(candidate.score, 1);
|
|
5492
|
+
}
|
|
5493
|
+
if (!candidate.eligible) {
|
|
5494
|
+
return null;
|
|
5495
|
+
}
|
|
5496
|
+
const leftRanking = leftRankings[leftIndex];
|
|
5497
|
+
const rightRanking = rightRankings[rightIndex];
|
|
5498
|
+
const isBestOnBothSides = candidate.score === leftRanking.best && candidate.score === rightRanking.best;
|
|
5499
|
+
const requiredMargin = candidate.score >= HIGH_CONFIDENCE_MATCH_SCORE2 ? AMBIGUITY_MARGIN2 / 2 : AMBIGUITY_MARGIN2;
|
|
5500
|
+
const hasLeftMargin = leftRanking.best - leftRanking.second >= requiredMargin;
|
|
5501
|
+
const hasRightMargin = rightRanking.best - rightRanking.second >= requiredMargin;
|
|
5502
|
+
return isBestOnBothSides && hasLeftMargin && hasRightMargin ? candidate.score : null;
|
|
5503
|
+
}));
|
|
5504
|
+
if (Math.max(leftLines.length, rightLines.length) > MAX_CONTEXTUAL_HUNK_LINES2 || Math.abs(leftLines.length - rightLines.length) > MAX_CONTEXTUAL_LENGTH_DELTA2) {
|
|
5505
|
+
return accepted;
|
|
5506
|
+
}
|
|
5507
|
+
const isContextualCandidate = (candidate, leftIndex, rightIndex) => candidate.score >= MINIMUM_CONTEXTUAL_MATCH_SCORE2 && haveCompatibleLineRoles2(leftLines[leftIndex], rightLines[rightIndex]) && Math.abs(leftIndex - rightIndex) <= MAX_CONTEXTUAL_LENGTH_DELTA2;
|
|
5508
|
+
const leftContextRankings = scored.map((row, leftIndex) => rankScores2(row, (candidate, rightIndex) => isContextualCandidate(candidate, leftIndex, rightIndex)));
|
|
5509
|
+
const rightContextRankings = rightLines.map((_right, rightIndex) => rankScores2(
|
|
5510
|
+
scored.map((row) => row[rightIndex]),
|
|
5511
|
+
(candidate, leftIndex) => isContextualCandidate(candidate, leftIndex, rightIndex)
|
|
5512
|
+
));
|
|
5513
|
+
const isWeakRunCandidate = (candidate, leftIndex, rightIndex) => candidate.score >= MINIMUM_CONTEXTUAL_RUN_SCORE2 && haveCompatibleLineRoles2(leftLines[leftIndex], rightLines[rightIndex]) && Math.abs(leftIndex - rightIndex) <= MAX_CONTEXTUAL_LENGTH_DELTA2;
|
|
5514
|
+
const leftWeakRankings = scored.map((row, leftIndex) => rankScores2(row, (candidate, rightIndex) => isWeakRunCandidate(candidate, leftIndex, rightIndex)));
|
|
5515
|
+
const rightWeakRankings = rightLines.map((_right, rightIndex) => rankScores2(
|
|
5516
|
+
scored.map((row) => row[rightIndex]),
|
|
5517
|
+
(candidate, leftIndex) => isWeakRunCandidate(candidate, leftIndex, rightIndex)
|
|
5518
|
+
));
|
|
5519
|
+
const isUnambiguousContextualCandidate = (leftIndex, rightIndex) => {
|
|
5520
|
+
const candidate = scored[leftIndex][rightIndex];
|
|
5521
|
+
if (!isContextualCandidate(candidate, leftIndex, rightIndex)) {
|
|
5522
|
+
return false;
|
|
5523
|
+
}
|
|
5524
|
+
const leftRanking = leftContextRankings[leftIndex];
|
|
5525
|
+
const rightRanking = rightContextRankings[rightIndex];
|
|
5526
|
+
return candidate.score === leftRanking.best && candidate.score === rightRanking.best && leftRanking.best - leftRanking.second >= CONTEXTUAL_AMBIGUITY_MARGIN2 && rightRanking.best - rightRanking.second >= CONTEXTUAL_AMBIGUITY_MARGIN2;
|
|
5527
|
+
};
|
|
5528
|
+
const isUnambiguousWeakRunAnchor = (leftIndex, rightIndex) => {
|
|
5529
|
+
const candidate = scored[leftIndex][rightIndex];
|
|
5530
|
+
if (!isWeakRunCandidate(candidate, leftIndex, rightIndex)) {
|
|
5531
|
+
return false;
|
|
5532
|
+
}
|
|
5533
|
+
const leftRanking = leftWeakRankings[leftIndex];
|
|
5534
|
+
const rightRanking = rightWeakRankings[rightIndex];
|
|
5535
|
+
return candidate.score === leftRanking.best && candidate.score === rightRanking.best && leftRanking.best - leftRanking.second >= CONTEXTUAL_AMBIGUITY_MARGIN2 && rightRanking.best - rightRanking.second >= CONTEXTUAL_AMBIGUITY_MARGIN2;
|
|
5536
|
+
};
|
|
5537
|
+
return accepted.map((row, leftIndex) => row.map((acceptedScore, rightIndex) => {
|
|
5538
|
+
if (acceptedScore !== null) {
|
|
5539
|
+
return acceptedScore;
|
|
5540
|
+
}
|
|
5541
|
+
const hasLocalSupport = isUnambiguousContextualCandidate(leftIndex, rightIndex) && (hasAcceptedDiagonalNeighbor2(accepted, leftIndex, rightIndex) || hasContextualDiagonalNeighbor2(
|
|
5542
|
+
scored,
|
|
5543
|
+
leftIndex,
|
|
5544
|
+
rightIndex,
|
|
5545
|
+
isUnambiguousContextualCandidate
|
|
5546
|
+
));
|
|
5547
|
+
const hasRunSupport = hasAnchoredWeakDiagonalRun2(
|
|
5548
|
+
scored,
|
|
5549
|
+
leftIndex,
|
|
5550
|
+
rightIndex,
|
|
5551
|
+
(candidateLeftIndex, candidateRightIndex) => isWeakRunCandidate(
|
|
5552
|
+
scored[candidateLeftIndex][candidateRightIndex],
|
|
5553
|
+
candidateLeftIndex,
|
|
5554
|
+
candidateRightIndex
|
|
5555
|
+
),
|
|
5556
|
+
isUnambiguousWeakRunAnchor
|
|
5557
|
+
);
|
|
5558
|
+
if (!hasLocalSupport && !hasRunSupport) {
|
|
5559
|
+
return null;
|
|
5560
|
+
}
|
|
5561
|
+
return scored[leftIndex][rightIndex].score;
|
|
5562
|
+
}));
|
|
5563
|
+
}
|
|
5564
|
+
function hasAcceptedDiagonalNeighbor2(accepted, leftIndex, rightIndex) {
|
|
5565
|
+
return leftIndex > 0 && rightIndex > 0 && accepted[leftIndex - 1][rightIndex - 1] !== null || leftIndex + 1 < accepted.length && rightIndex + 1 < accepted[leftIndex + 1].length && accepted[leftIndex + 1][rightIndex + 1] !== null;
|
|
5566
|
+
}
|
|
5567
|
+
function hasContextualDiagonalNeighbor2(scored, leftIndex, rightIndex, isCandidate) {
|
|
5568
|
+
return leftIndex > 0 && rightIndex > 0 && isCandidate(leftIndex - 1, rightIndex - 1) || leftIndex + 1 < scored.length && rightIndex + 1 < scored[leftIndex + 1].length && isCandidate(leftIndex + 1, rightIndex + 1);
|
|
5569
|
+
}
|
|
5570
|
+
function hasAnchoredWeakDiagonalRun2(scored, leftIndex, rightIndex, isCandidate, isAnchor) {
|
|
5571
|
+
let startLeft = leftIndex;
|
|
5572
|
+
let startRight = rightIndex;
|
|
5573
|
+
while (startLeft > 0 && startRight > 0 && isCandidate(startLeft - 1, startRight - 1)) {
|
|
5574
|
+
startLeft--;
|
|
5575
|
+
startRight--;
|
|
5576
|
+
}
|
|
5577
|
+
let endLeft = leftIndex;
|
|
5578
|
+
let endRight = rightIndex;
|
|
5579
|
+
let scoreTotal = scored[leftIndex][rightIndex].score;
|
|
5580
|
+
let length = 1;
|
|
5581
|
+
while (endLeft + 1 < scored.length && endRight + 1 < scored[endLeft + 1].length && isCandidate(endLeft + 1, endRight + 1)) {
|
|
5582
|
+
endLeft++;
|
|
5583
|
+
endRight++;
|
|
5584
|
+
scoreTotal += scored[endLeft][endRight].score;
|
|
5585
|
+
length++;
|
|
5586
|
+
}
|
|
5587
|
+
for (let scanLeft = leftIndex - 1, scanRight = rightIndex - 1; scanLeft >= startLeft && scanRight >= startRight; scanLeft--, scanRight--) {
|
|
5588
|
+
scoreTotal += scored[scanLeft][scanRight].score;
|
|
5589
|
+
length++;
|
|
5590
|
+
}
|
|
5591
|
+
return length >= 3 && scoreTotal / length >= MINIMUM_CONTEXTUAL_MATCH_SCORE2 && isAnchor(startLeft, startRight) && isAnchor(endLeft, endRight);
|
|
5592
|
+
}
|
|
5593
|
+
function rankScores2(scores, include) {
|
|
5594
|
+
let best = Number.NEGATIVE_INFINITY;
|
|
5595
|
+
let second = Number.NEGATIVE_INFINITY;
|
|
5596
|
+
scores.forEach((candidate, index) => {
|
|
5597
|
+
if (!include(candidate, index)) {
|
|
5598
|
+
return;
|
|
5599
|
+
}
|
|
5600
|
+
if (candidate.score > best) {
|
|
5601
|
+
second = best;
|
|
5602
|
+
best = candidate.score;
|
|
5603
|
+
} else if (candidate.score > second) {
|
|
5604
|
+
second = candidate.score;
|
|
5605
|
+
}
|
|
5606
|
+
});
|
|
5607
|
+
return { best, second };
|
|
5608
|
+
}
|
|
5609
|
+
function rankEligibleScores2(scores) {
|
|
5610
|
+
let best = Number.NEGATIVE_INFINITY;
|
|
5611
|
+
let second = Number.NEGATIVE_INFINITY;
|
|
5612
|
+
for (const candidate of scores) {
|
|
5613
|
+
if (!candidate.eligible) {
|
|
5614
|
+
continue;
|
|
5615
|
+
}
|
|
5616
|
+
if (candidate.score > best) {
|
|
5617
|
+
second = best;
|
|
5618
|
+
best = candidate.score;
|
|
5619
|
+
} else if (candidate.score > second) {
|
|
5620
|
+
second = candidate.score;
|
|
5621
|
+
}
|
|
5622
|
+
}
|
|
5623
|
+
return { best, second };
|
|
5624
|
+
}
|
|
5625
|
+
function alignLargeReplacementLines2(leftLines, rightLines) {
|
|
5626
|
+
const anchors = collectLargeHunkAnchors2(leftLines, rightLines);
|
|
5627
|
+
const aligned = [];
|
|
5628
|
+
let leftStart = 0;
|
|
5629
|
+
let rightStart = 0;
|
|
5630
|
+
for (const anchor of anchors) {
|
|
5631
|
+
appendBoundedSegment2(
|
|
5632
|
+
aligned,
|
|
5633
|
+
leftLines.slice(leftStart, anchor.leftIndex),
|
|
5634
|
+
rightLines.slice(rightStart, anchor.rightIndex)
|
|
5635
|
+
);
|
|
5636
|
+
aligned.push({ left: leftLines[anchor.leftIndex], right: rightLines[anchor.rightIndex] });
|
|
5637
|
+
leftStart = anchor.leftIndex + 1;
|
|
5638
|
+
rightStart = anchor.rightIndex + 1;
|
|
5639
|
+
}
|
|
5640
|
+
appendBoundedSegment2(aligned, leftLines.slice(leftStart), rightLines.slice(rightStart));
|
|
5641
|
+
return aligned;
|
|
5642
|
+
}
|
|
5643
|
+
function collectLargeHunkAnchors2(leftLines, rightLines) {
|
|
5644
|
+
const candidatePairs = collectRareTokenCandidatePairs2(leftLines, rightLines);
|
|
5645
|
+
if (candidatePairs === null) {
|
|
5646
|
+
return [];
|
|
5647
|
+
}
|
|
5648
|
+
const structuralPairs = collectUniqueStructuralPairs2(leftLines, rightLines);
|
|
5649
|
+
const scored = candidatePairs.map(({ leftIndex, rightIndex, exact }) => ({
|
|
5650
|
+
leftIndex,
|
|
5651
|
+
rightIndex,
|
|
5652
|
+
exact,
|
|
5653
|
+
structural: structuralPairs.has(`${leftIndex}:${rightIndex}`),
|
|
5654
|
+
match: scoreReplacementLinePair2(leftLines[leftIndex], rightLines[rightIndex])
|
|
5655
|
+
})).filter((candidate) => candidate.exact || candidate.structural || candidate.match.eligible);
|
|
5656
|
+
const leftRankings = rankAnchorCandidates2(scored, "leftIndex");
|
|
5657
|
+
const rightRankings = rankAnchorCandidates2(scored, "rightIndex");
|
|
5658
|
+
const confident = scored.filter((candidate) => {
|
|
5659
|
+
if (candidate.exact || candidate.structural) {
|
|
5660
|
+
return true;
|
|
5661
|
+
}
|
|
5662
|
+
const leftRanking = leftRankings.get(candidate.leftIndex);
|
|
5663
|
+
const rightRanking = rightRankings.get(candidate.rightIndex);
|
|
5664
|
+
if (!leftRanking || !rightRanking || candidate.match.score !== leftRanking.best || candidate.match.score !== rightRanking.best) {
|
|
5665
|
+
return false;
|
|
5666
|
+
}
|
|
5667
|
+
const requiredMargin = candidate.match.score >= HIGH_CONFIDENCE_MATCH_SCORE2 ? AMBIGUITY_MARGIN2 / 2 : AMBIGUITY_MARGIN2;
|
|
5668
|
+
return leftRanking.best - leftRanking.second >= requiredMargin && rightRanking.best - rightRanking.second >= requiredMargin;
|
|
5669
|
+
});
|
|
5670
|
+
const anchors = selectMaximumWeightMonotonicAnchors2(confident, rightLines.length);
|
|
5671
|
+
return anchors.length <= MAX_LARGE_HUNK_ANCHORS2 ? anchors : [];
|
|
5672
|
+
}
|
|
5673
|
+
function collectRareTokenCandidatePairs2(leftLines, rightLines) {
|
|
5674
|
+
const leftExact = buildLinePostings2(leftLines, normalizeMatchingContent2);
|
|
5675
|
+
const rightExact = buildLinePostings2(rightLines, normalizeMatchingContent2);
|
|
5676
|
+
const pairs = /* @__PURE__ */ new Map();
|
|
5677
|
+
for (const [line, leftIndices] of leftExact) {
|
|
5678
|
+
const rightIndices = rightExact.get(line);
|
|
5679
|
+
if (!isInformativeLine2(line) || leftIndices.length !== 1 || (rightIndices == null ? void 0 : rightIndices.length) !== 1) {
|
|
5680
|
+
continue;
|
|
5681
|
+
}
|
|
5682
|
+
const leftIndex = leftIndices[0];
|
|
5683
|
+
const rightIndex = rightIndices[0];
|
|
5684
|
+
pairs.set(`${leftIndex}:${rightIndex}`, { leftIndex, rightIndex, exact: true });
|
|
5685
|
+
if (pairs.size > MAX_BOUNDED_CANDIDATES2) {
|
|
5686
|
+
return null;
|
|
5687
|
+
}
|
|
5688
|
+
}
|
|
5689
|
+
const leftTokens = buildTokenPostings2(leftLines);
|
|
5690
|
+
const rightTokens = buildTokenPostings2(rightLines);
|
|
5691
|
+
for (const [token, leftIndices] of leftTokens) {
|
|
5692
|
+
const rightIndices = rightTokens.get(token);
|
|
5693
|
+
if (!rightIndices || leftIndices.length > MAX_RARE_TOKEN_OCCURRENCES2 || rightIndices.length > MAX_RARE_TOKEN_OCCURRENCES2) {
|
|
5694
|
+
continue;
|
|
5695
|
+
}
|
|
5696
|
+
for (const leftIndex of leftIndices) {
|
|
5697
|
+
for (const rightIndex of rightIndices) {
|
|
5698
|
+
const key = `${leftIndex}:${rightIndex}`;
|
|
5699
|
+
if (!pairs.has(key)) {
|
|
5700
|
+
pairs.set(key, { leftIndex, rightIndex, exact: false });
|
|
5701
|
+
if (pairs.size > MAX_BOUNDED_CANDIDATES2) {
|
|
5702
|
+
return null;
|
|
5703
|
+
}
|
|
5704
|
+
}
|
|
5705
|
+
}
|
|
5706
|
+
}
|
|
5707
|
+
}
|
|
5708
|
+
return [...pairs.values()];
|
|
5709
|
+
}
|
|
5710
|
+
function buildLinePostings2(lines, keyForLine) {
|
|
5711
|
+
const postings = /* @__PURE__ */ new Map();
|
|
5712
|
+
lines.forEach((line, index) => {
|
|
5713
|
+
const key = keyForLine(line);
|
|
5714
|
+
const indices = postings.get(key) ?? [];
|
|
5715
|
+
indices.push(index);
|
|
5716
|
+
postings.set(key, indices);
|
|
5717
|
+
});
|
|
5718
|
+
return postings;
|
|
5719
|
+
}
|
|
5720
|
+
function buildTokenPostings2(lines) {
|
|
5721
|
+
const postings = /* @__PURE__ */ new Map();
|
|
5722
|
+
lines.forEach((line, index) => {
|
|
5723
|
+
const tokens = new Set(tokenizeMatchingContent2(normalizeMatchingContent2(line)).filter(isMeaningfulAnchorToken2));
|
|
5724
|
+
for (const token of tokens) {
|
|
5725
|
+
const indices = postings.get(token) ?? [];
|
|
5726
|
+
indices.push(index);
|
|
5727
|
+
postings.set(token, indices);
|
|
5728
|
+
}
|
|
5729
|
+
});
|
|
5730
|
+
return postings;
|
|
5731
|
+
}
|
|
5732
|
+
function isMeaningfulAnchorToken2(token) {
|
|
5733
|
+
return token.length >= 2 && /[\p{L}\p{N}_$]/u.test(token);
|
|
5734
|
+
}
|
|
5735
|
+
function rankAnchorCandidates2(candidates, indexKey) {
|
|
5736
|
+
const grouped = /* @__PURE__ */ new Map();
|
|
5737
|
+
for (const candidate of candidates) {
|
|
5738
|
+
const scores = grouped.get(candidate[indexKey]) ?? [];
|
|
5739
|
+
scores.push(candidate.match);
|
|
5740
|
+
grouped.set(candidate[indexKey], scores);
|
|
5741
|
+
}
|
|
5742
|
+
return new Map([...grouped].map(([index, scores]) => [index, rankEligibleScores2(scores)]));
|
|
5743
|
+
}
|
|
5744
|
+
function selectMaximumWeightMonotonicAnchors2(candidates, rightLength) {
|
|
5745
|
+
const ordered = [...candidates].sort((left, right) => left.leftIndex - right.leftIndex || left.rightIndex - right.rightIndex);
|
|
5746
|
+
const treeScores = new Array(rightLength + 2).fill(0);
|
|
5747
|
+
const treeCandidates = new Array(rightLength + 2).fill(-1);
|
|
5748
|
+
const bestScores = new Array(ordered.length).fill(0);
|
|
5749
|
+
const previous = new Array(ordered.length).fill(-1);
|
|
5750
|
+
for (let start = 0; start < ordered.length; ) {
|
|
5751
|
+
let end = start + 1;
|
|
5752
|
+
while (end < ordered.length && ordered[end].leftIndex === ordered[start].leftIndex) {
|
|
5753
|
+
end++;
|
|
5754
|
+
}
|
|
5755
|
+
for (let index = start; index < end; index++) {
|
|
5756
|
+
const prior = queryAnchorTree2(treeScores, treeCandidates, ordered[index].rightIndex);
|
|
5757
|
+
const anchorBonus = ordered[index].exact || ordered[index].structural ? 0.5 : 0;
|
|
5758
|
+
bestScores[index] = prior.score + ordered[index].match.score + anchorBonus;
|
|
5759
|
+
previous[index] = prior.candidateIndex;
|
|
5760
|
+
}
|
|
5761
|
+
for (let index = start; index < end; index++) {
|
|
5762
|
+
updateAnchorTree2(
|
|
5763
|
+
treeScores,
|
|
5764
|
+
treeCandidates,
|
|
5765
|
+
ordered[index].rightIndex + 1,
|
|
5766
|
+
bestScores[index],
|
|
5767
|
+
index
|
|
5768
|
+
);
|
|
5769
|
+
}
|
|
5770
|
+
start = end;
|
|
5771
|
+
}
|
|
5772
|
+
const best = queryAnchorTree2(treeScores, treeCandidates, rightLength + 1);
|
|
5773
|
+
const anchors = [];
|
|
5774
|
+
for (let index = best.candidateIndex; index >= 0; index = previous[index]) {
|
|
5775
|
+
anchors.push({ leftIndex: ordered[index].leftIndex, rightIndex: ordered[index].rightIndex });
|
|
5776
|
+
}
|
|
5777
|
+
return anchors.reverse();
|
|
5778
|
+
}
|
|
5779
|
+
function queryAnchorTree2(scores, candidates, position) {
|
|
5780
|
+
let score = 0;
|
|
5781
|
+
let candidateIndex = -1;
|
|
5782
|
+
for (let index = position; index > 0; index -= index & -index) {
|
|
5783
|
+
if (scores[index] > score) {
|
|
5784
|
+
score = scores[index];
|
|
5785
|
+
candidateIndex = candidates[index];
|
|
5786
|
+
}
|
|
5787
|
+
}
|
|
5788
|
+
return { score, candidateIndex };
|
|
5789
|
+
}
|
|
5790
|
+
function updateAnchorTree2(scores, candidates, position, score, candidateIndex) {
|
|
5791
|
+
for (let index = position; index < scores.length; index += index & -index) {
|
|
5792
|
+
if (score > scores[index]) {
|
|
5793
|
+
scores[index] = score;
|
|
5794
|
+
candidates[index] = candidateIndex;
|
|
5795
|
+
}
|
|
5796
|
+
}
|
|
5797
|
+
}
|
|
5798
|
+
function appendBoundedSegment2(aligned, leftLines, rightLines) {
|
|
5799
|
+
if (leftLines.length * rightLines.length <= MAX_ALIGNMENT_CELLS2) {
|
|
5800
|
+
aligned.push(...alignReplacementLines2(leftLines, rightLines));
|
|
5801
|
+
return;
|
|
5802
|
+
}
|
|
5803
|
+
aligned.push(...leftLines.map((left) => ({ left })));
|
|
5804
|
+
aligned.push(...rightLines.map((right) => ({ right })));
|
|
5805
|
+
}
|
|
5806
|
+
function normalizeMatchingContent2(line) {
|
|
5807
|
+
return line.trim().replace(/\s+/g, " ");
|
|
5808
|
+
}
|
|
5809
|
+
function collectUniqueStructuralPairs2(leftLines, rightLines) {
|
|
5810
|
+
const leftPostings = buildStructuralPostings2(leftLines);
|
|
5811
|
+
const rightPostings = buildStructuralPostings2(rightLines);
|
|
5812
|
+
const pairs = /* @__PURE__ */ new Set();
|
|
5813
|
+
for (const [key, leftIndices] of leftPostings) {
|
|
5814
|
+
const rightIndices = rightPostings.get(key);
|
|
5815
|
+
if (leftIndices.length === 1 && (rightIndices == null ? void 0 : rightIndices.length) === 1) {
|
|
5816
|
+
pairs.add(`${leftIndices[0]}:${rightIndices[0]}`);
|
|
5817
|
+
}
|
|
5818
|
+
}
|
|
5819
|
+
return pairs;
|
|
5820
|
+
}
|
|
5821
|
+
function buildStructuralPostings2(lines) {
|
|
5822
|
+
const postings = /* @__PURE__ */ new Map();
|
|
5823
|
+
lines.forEach((line, index) => {
|
|
5824
|
+
const key = declarationAnchorKey2(line);
|
|
5825
|
+
if (!key) {
|
|
5826
|
+
return;
|
|
5827
|
+
}
|
|
5828
|
+
const indices = postings.get(key) ?? [];
|
|
5829
|
+
indices.push(index);
|
|
5830
|
+
postings.set(key, indices);
|
|
5831
|
+
});
|
|
5832
|
+
return postings;
|
|
5833
|
+
}
|
|
5834
|
+
function haveCompatibleLineRoles2(left, right) {
|
|
5835
|
+
const leftKey = declarationAnchorKey2(left);
|
|
5836
|
+
const rightKey = declarationAnchorKey2(right);
|
|
5837
|
+
if (!leftKey || !rightKey) {
|
|
5838
|
+
return leftKey === rightKey;
|
|
5839
|
+
}
|
|
5840
|
+
return leftKey.split(":", 1)[0] === rightKey.split(":", 1)[0];
|
|
5841
|
+
}
|
|
5842
|
+
function declarationAnchorKey2(line) {
|
|
5843
|
+
const normalized = normalizeMatchingContent2(line);
|
|
5844
|
+
const patterns = [
|
|
5845
|
+
["function", /^(?:(?:export|default)\s+)*(?:async\s+)?function\s*\*?\s*([\p{L}_$][\p{L}\p{N}_$]*)\s*\(/u],
|
|
5846
|
+
["function", /^(?:async\s+)?def\s+([\p{L}_][\p{L}\p{N}_]*)\s*\(/u],
|
|
5847
|
+
["function", /^(?:pub(?:\([^)]*\))?\s+)?(?:async\s+)?fn\s+([\p{L}_][\p{L}\p{N}_]*)\s*(?:<[^>]*>)?\s*\(/u],
|
|
5848
|
+
["function", /^func\s+(?:\([^)]*\)\s*)?([\p{L}_][\p{L}\p{N}_]*)\s*\(/u],
|
|
5849
|
+
["class", /^(?:(?:export|default|abstract|public)\s+)*class\s+([\p{L}_$][\p{L}\p{N}_$]*)\b/u]
|
|
5850
|
+
];
|
|
5851
|
+
for (const [kind, pattern] of patterns) {
|
|
5852
|
+
const match = normalized.match(pattern);
|
|
5853
|
+
if (match) {
|
|
5854
|
+
return `${kind}:${match[1]}`;
|
|
5855
|
+
}
|
|
5856
|
+
}
|
|
5857
|
+
return null;
|
|
5858
|
+
}
|
|
5859
|
+
function isInformativeLine2(line) {
|
|
5860
|
+
if (line.length < 3) {
|
|
5861
|
+
return false;
|
|
5862
|
+
}
|
|
5863
|
+
return /[\p{L}\p{N}_$]/u.test(line) && !/^[\s()[\]{};,.:+\-*/=>|&!?'"`]+$/.test(line);
|
|
5864
|
+
}
|
|
5865
|
+
function tokenizeMatchingContent2(line) {
|
|
5866
|
+
return line.toLowerCase().match(new RegExp("[\\p{L}_$][\\p{L}\\p{N}_$]*|\\p{N}+(?:\\.\\p{N}+)?|[^\\s\\p{L}\\p{N}_$]", "gu")) ?? [];
|
|
5867
|
+
}
|
|
5868
|
+
function multisetDiceSimilarity2(leftTokens, rightTokens) {
|
|
5869
|
+
if (leftTokens.length + rightTokens.length === 0) {
|
|
5870
|
+
return 1;
|
|
5871
|
+
}
|
|
5872
|
+
const remaining = /* @__PURE__ */ new Map();
|
|
5873
|
+
leftTokens.forEach((token) => remaining.set(token, (remaining.get(token) ?? 0) + 1));
|
|
5874
|
+
let common = 0;
|
|
5875
|
+
for (const token of rightTokens) {
|
|
5876
|
+
const count = remaining.get(token) ?? 0;
|
|
5877
|
+
if (count > 0) {
|
|
5878
|
+
common++;
|
|
5879
|
+
remaining.set(token, count - 1);
|
|
5880
|
+
}
|
|
5881
|
+
}
|
|
5882
|
+
return 2 * common / (leftTokens.length + rightTokens.length);
|
|
5883
|
+
}
|
|
5884
|
+
function tokenBoundarySimilarity2(leftTokens, rightTokens) {
|
|
5885
|
+
if (leftTokens.length === 0 || rightTokens.length === 0) {
|
|
5886
|
+
return 0;
|
|
5887
|
+
}
|
|
5888
|
+
const sameStart = leftTokens[0] === rightTokens[0] ? 0.5 : 0;
|
|
5889
|
+
const sameEnd = leftTokens[leftTokens.length - 1] === rightTokens[rightTokens.length - 1] ? 0.5 : 0;
|
|
5890
|
+
return sameStart + sameEnd;
|
|
5891
|
+
}
|
|
5892
|
+
function lineSimilarity2(left, right) {
|
|
5893
|
+
const maxLength = left.length + right.length;
|
|
5894
|
+
if (maxLength === 0) {
|
|
5895
|
+
return 1;
|
|
5896
|
+
}
|
|
5897
|
+
const commonLength = diffChars2(left, right).filter((change) => !change.added && !change.removed).reduce((total, change) => total + change.value.length, 0);
|
|
5898
|
+
return 2 * commonLength / maxLength;
|
|
5899
|
+
}
|
|
5900
|
+
function applyInlineHighlightPair2(leftLine, rightLine) {
|
|
5901
|
+
if (leftLine.content.length > MAX_INLINE_HIGHLIGHT_LINE_LENGTH2 || rightLine.content.length > MAX_INLINE_HIGHLIGHT_LINE_LENGTH2) {
|
|
5902
|
+
return;
|
|
5903
|
+
}
|
|
5904
|
+
const { leftSegments, rightSegments, hasInlineChanges } = buildInlineSegments2(leftLine.content, rightLine.content);
|
|
5905
|
+
if (hasInlineChanges) {
|
|
5906
|
+
leftLine.segments = leftSegments;
|
|
5907
|
+
rightLine.segments = rightSegments;
|
|
5908
|
+
}
|
|
5909
|
+
}
|
|
5910
|
+
function buildInlineSegments2(leftContent, rightContent) {
|
|
5911
|
+
const changes = diffWordsWithSpace2(leftContent, rightContent);
|
|
5912
|
+
const leftSegments = [];
|
|
5913
|
+
const rightSegments = [];
|
|
5914
|
+
let hasInlineChanges = false;
|
|
5915
|
+
for (const change of changes) {
|
|
5916
|
+
const value = change.value;
|
|
5917
|
+
if (!change.added && !change.removed) {
|
|
5918
|
+
const contextSegment = {
|
|
5919
|
+
kind: "context",
|
|
5920
|
+
text: value,
|
|
5921
|
+
emphasis: false
|
|
5922
|
+
};
|
|
5923
|
+
leftSegments.push(contextSegment);
|
|
5924
|
+
rightSegments.push(contextSegment);
|
|
5925
|
+
continue;
|
|
5926
|
+
}
|
|
5927
|
+
const emphasis = /[^\s]/.test(value);
|
|
5928
|
+
hasInlineChanges = hasInlineChanges || emphasis;
|
|
5929
|
+
if (change.removed) {
|
|
5930
|
+
leftSegments.push({
|
|
5931
|
+
kind: "removed",
|
|
5932
|
+
text: value,
|
|
5933
|
+
emphasis
|
|
5934
|
+
});
|
|
5935
|
+
}
|
|
5936
|
+
if (change.added) {
|
|
5937
|
+
rightSegments.push({
|
|
5938
|
+
kind: "added",
|
|
5939
|
+
text: value,
|
|
5940
|
+
emphasis
|
|
5941
|
+
});
|
|
5942
|
+
}
|
|
5943
|
+
}
|
|
5944
|
+
return {
|
|
5945
|
+
leftSegments,
|
|
5946
|
+
rightSegments,
|
|
5947
|
+
hasInlineChanges
|
|
5948
|
+
};
|
|
5949
|
+
}
|
|
5950
|
+
function makePlaceholder2() {
|
|
5951
|
+
return {
|
|
5952
|
+
kind: "placeholder",
|
|
5953
|
+
content: "",
|
|
5954
|
+
lineNumber: null
|
|
5955
|
+
};
|
|
5956
|
+
}
|
|
5957
|
+
function makeDiffCell2(kind, content, lineNumber) {
|
|
5958
|
+
return { kind, content, lineNumber };
|
|
5959
|
+
}
|
|
5960
|
+
function makeDiffLine2(kind, content, lineNumber) {
|
|
5961
|
+
return { kind, content, lineNumber };
|
|
5962
|
+
}
|
|
5963
|
+
function makeDiffRow2(left, right) {
|
|
5964
|
+
return { left, right };
|
|
5965
|
+
}
|
|
5966
|
+
function makeDiffBlock2(kind, leftStart, leftEnd, rightStart, rightEnd) {
|
|
5967
|
+
return { kind, leftStart, leftEnd, rightStart, rightEnd };
|
|
5968
|
+
}
|
|
5969
|
+
function readPositiveIntegerEnv4(name, fallback) {
|
|
5970
|
+
var _a;
|
|
5971
|
+
const value = typeof process !== "undefined" ? (_a = process.env) == null ? void 0 : _a[name] : void 0;
|
|
5972
|
+
const parsed = Number.parseInt(value ?? "", 10);
|
|
5973
|
+
return Number.isFinite(parsed) && parsed > 0 ? parsed : fallback;
|
|
5974
|
+
}
|
|
5975
|
+
var MAX_AUTOMATIC_TOUR_FOCUS_RANGES = 4;
|
|
5976
|
+
var NEARBY_TOUR_FOCUS_LINE_GAP = 8;
|
|
5977
|
+
var LARGE_TOUR_FOCUS_RANGE_LINES = 120;
|
|
5978
|
+
var TOUR_FOCUS_BOUNDARY_SEARCH_LINES = 12;
|
|
5979
|
+
function getChangeSourceRange(diffModel, blockIndex, side) {
|
|
5980
|
+
var _a, _b, _c;
|
|
5981
|
+
const block = diffModel == null ? void 0 : diffModel.blocks[blockIndex];
|
|
5982
|
+
const lines = side === "left" ? diffModel == null ? void 0 : diffModel.leftLines : diffModel == null ? void 0 : diffModel.rightLines;
|
|
5983
|
+
if (!block || !(lines == null ? void 0 : lines.length)) {
|
|
5984
|
+
return void 0;
|
|
5985
|
+
}
|
|
5986
|
+
const start = side === "left" ? block.leftStart : block.rightStart;
|
|
5987
|
+
const end = side === "left" ? block.leftEnd : block.rightEnd;
|
|
5988
|
+
const changedLines = lines.slice(start, end);
|
|
5989
|
+
const startLine = ((_a = changedLines[0]) == null ? void 0 : _a.lineNumber) ?? ((_b = lines[Math.min(start, lines.length - 1)]) == null ? void 0 : _b.lineNumber);
|
|
5990
|
+
if (!Number.isInteger(startLine)) {
|
|
5991
|
+
return void 0;
|
|
5992
|
+
}
|
|
5993
|
+
return {
|
|
5994
|
+
startLine,
|
|
5995
|
+
endLine: ((_c = changedLines.at(-1)) == null ? void 0 : _c.lineNumber) ?? startLine
|
|
5996
|
+
};
|
|
5997
|
+
}
|
|
5998
|
+
function buildTourFocusRanges(diffModel, side) {
|
|
5999
|
+
const ranges = diffModel.blocks.map((_, blockIndex) => getChangeSourceRange(diffModel, blockIndex, side)).filter((range) => Boolean(range));
|
|
6000
|
+
if (ranges.length === 0) return [];
|
|
6001
|
+
const nearby = ranges.reduce((grouped, range) => {
|
|
6002
|
+
const previous = grouped.at(-1);
|
|
6003
|
+
if (previous && range.startLine - previous.endLine <= NEARBY_TOUR_FOCUS_LINE_GAP) {
|
|
6004
|
+
previous.endLine = Math.max(previous.endLine, range.endLine);
|
|
6005
|
+
} else {
|
|
6006
|
+
grouped.push({ ...range });
|
|
6007
|
+
}
|
|
6008
|
+
return grouped;
|
|
6009
|
+
}, []);
|
|
6010
|
+
const capped = capFocusRanges(nearby, MAX_AUTOMATIC_TOUR_FOCUS_RANGES);
|
|
6011
|
+
if (capped.length !== 1) return capped;
|
|
6012
|
+
const [only] = capped;
|
|
6013
|
+
const lineCount = only.endLine - only.startLine + 1;
|
|
6014
|
+
if (lineCount < LARGE_TOUR_FOCUS_RANGE_LINES) return capped;
|
|
6015
|
+
const lines = side === "left" ? diffModel.leftLines : diffModel.rightLines;
|
|
6016
|
+
const partCount = Math.min(
|
|
6017
|
+
MAX_AUTOMATIC_TOUR_FOCUS_RANGES,
|
|
6018
|
+
Math.ceil(lineCount / LARGE_TOUR_FOCUS_RANGE_LINES)
|
|
6019
|
+
);
|
|
6020
|
+
const boundaries = [];
|
|
6021
|
+
for (let partIndex = 1; partIndex < partCount; partIndex += 1) {
|
|
6022
|
+
const target = only.startLine + Math.round(lineCount * partIndex / partCount) - 1;
|
|
6023
|
+
boundaries.push(findBlankLineBoundary(lines, target, only.startLine, only.endLine));
|
|
6024
|
+
}
|
|
6025
|
+
const uniqueBoundaries = [...new Set(boundaries)].filter((line) => line >= only.startLine && line < only.endLine).sort((left, right) => left - right);
|
|
6026
|
+
const split = [];
|
|
6027
|
+
let startLine = only.startLine;
|
|
6028
|
+
for (const endLine of uniqueBoundaries) {
|
|
6029
|
+
split.push({ startLine, endLine });
|
|
6030
|
+
startLine = endLine + 1;
|
|
6031
|
+
}
|
|
6032
|
+
split.push({ startLine, endLine: only.endLine });
|
|
6033
|
+
return split;
|
|
6034
|
+
}
|
|
6035
|
+
function capFocusRanges(ranges, maximum) {
|
|
6036
|
+
if (ranges.length <= maximum) return ranges.map((range) => ({ ...range }));
|
|
6037
|
+
const capped = [];
|
|
6038
|
+
for (let index = 0; index < maximum; index += 1) {
|
|
6039
|
+
const startIndex = Math.floor(index * ranges.length / maximum);
|
|
6040
|
+
const endIndex = Math.floor((index + 1) * ranges.length / maximum) - 1;
|
|
6041
|
+
capped.push({
|
|
6042
|
+
startLine: ranges[startIndex].startLine,
|
|
6043
|
+
endLine: ranges[endIndex].endLine
|
|
6044
|
+
});
|
|
6045
|
+
}
|
|
6046
|
+
return capped;
|
|
6047
|
+
}
|
|
6048
|
+
function findBlankLineBoundary(lines, target, minimum, maximum) {
|
|
6049
|
+
for (let distance = 0; distance <= TOUR_FOCUS_BOUNDARY_SEARCH_LINES; distance += 1) {
|
|
6050
|
+
for (const candidate of distance === 0 ? [target] : [target + distance, target - distance]) {
|
|
6051
|
+
if (candidate < minimum || candidate >= maximum) continue;
|
|
6052
|
+
const line = lines.find((entry) => entry.lineNumber === candidate);
|
|
6053
|
+
if ((line == null ? void 0 : line.content.trim()) === "") return candidate;
|
|
6054
|
+
}
|
|
6055
|
+
}
|
|
6056
|
+
return Math.min(Math.max(target, minimum), maximum - 1);
|
|
6057
|
+
}
|
|
4837
6058
|
var import_child_process32 = require("child_process");
|
|
4838
6059
|
var CHANGE_TOUR_CONTEXT_VERSION = 1;
|
|
4839
6060
|
var DEFAULT_MAX_PATCH_BYTES = 128 * 1024;
|
|
@@ -5162,7 +6383,8 @@ var require_changeTour = __commonJS({
|
|
|
5162
6383
|
repoRoot,
|
|
5163
6384
|
authoredScene,
|
|
5164
6385
|
authoredScene.base || ((_a = source.range) == null ? void 0 : _a.base),
|
|
5165
|
-
authoredScene.target || ((_b = source.range) == null ? void 0 : _b.head)
|
|
6386
|
+
authoredScene.target || ((_b = source.range) == null ? void 0 : _b.head),
|
|
6387
|
+
[...available.keys()]
|
|
5166
6388
|
);
|
|
5167
6389
|
scenes.push(deconstructedScene);
|
|
5168
6390
|
sceneIds.push(deconstructedScene.id);
|
|
@@ -5208,7 +6430,7 @@ var require_changeTour = __commonJS({
|
|
|
5208
6430
|
}
|
|
5209
6431
|
return { scenes, chapters };
|
|
5210
6432
|
}
|
|
5211
|
-
function buildDeconstructedManifestScene(repoRoot, source, baseRef, targetRef) {
|
|
6433
|
+
function buildDeconstructedManifestScene(repoRoot, source, baseRef, targetRef, availableFilePaths = []) {
|
|
5212
6434
|
const compiled = buildDeconstructedScene(repoRoot, source, { baseRef, headRef: targetRef });
|
|
5213
6435
|
const panels = [{
|
|
5214
6436
|
id: "explanation-baseline",
|
|
@@ -5220,9 +6442,15 @@ var require_changeTour = __commonJS({
|
|
|
5220
6442
|
role: "stage",
|
|
5221
6443
|
stageId: stage.id
|
|
5222
6444
|
}))];
|
|
5223
|
-
const
|
|
6445
|
+
const materializablePaths = new Set(compiled.baselineFiles.map((file) => file.path));
|
|
6446
|
+
const includedPaths = availableFilePaths.length > 0 ? availableFilePaths.filter((filePath) => materializablePaths.has(filePath)).sort() : [...materializablePaths].sort();
|
|
6447
|
+
const missingIntroducedPath = compiled.stages.flatMap((stage) => stage.introducedFiles).find((filePath) => !includedPaths.includes(filePath));
|
|
6448
|
+
if (missingIntroducedPath) {
|
|
6449
|
+
throw new Error(`Deconstructed tour file is not renderable: ${missingIntroducedPath}`);
|
|
6450
|
+
}
|
|
6451
|
+
const introducedPaths = new Set(compiled.stages.flatMap((stage) => stage.introducedFiles));
|
|
5224
6452
|
let totalContentBytes = 0;
|
|
5225
|
-
const files = includedPaths.
|
|
6453
|
+
const files = includedPaths.flatMap((filePath) => {
|
|
5226
6454
|
const states = [
|
|
5227
6455
|
compiled.baselineFiles.find((file) => file.path === filePath),
|
|
5228
6456
|
...compiled.stages.map((stage) => stage.files.find((file) => file.path === filePath))
|
|
@@ -5230,18 +6458,23 @@ var require_changeTour = __commonJS({
|
|
|
5230
6458
|
if (states.some((state) => !state)) {
|
|
5231
6459
|
throw new Error(`Deconstructed scene ${source.id} is missing virtual state for ${filePath}.`);
|
|
5232
6460
|
}
|
|
5233
|
-
|
|
6461
|
+
const fileContentBytes = states.reduce((total, state) => total + Buffer.byteLength((state == null ? void 0 : state.content) || "", "utf8"), 0);
|
|
6462
|
+
const exceedsFileLimit = states.some((state) => {
|
|
6463
|
+
const content = Buffer.from((state == null ? void 0 : state.content) || "", "utf8");
|
|
6464
|
+
return content.length > DEFAULT_MAX_TOUR_FILE_BYTES || hasLineLongerThan(content, DEFAULT_MAX_TOUR_LINE_BYTES);
|
|
6465
|
+
});
|
|
6466
|
+
const exceedsSceneLimit = totalContentBytes + fileContentBytes > DEFAULT_MAX_STACK_CONTENT_BYTES;
|
|
6467
|
+
if (exceedsFileLimit || exceedsSceneLimit) {
|
|
6468
|
+
if (introducedPaths.has(filePath)) {
|
|
6469
|
+
throw new Error(exceedsFileLimit ? `Deconstructed tour file is too large to present: ${filePath}` : `Deconstructed tour content exceeds ${DEFAULT_MAX_STACK_CONTENT_BYTES} bytes.`);
|
|
6470
|
+
}
|
|
6471
|
+
return [];
|
|
6472
|
+
}
|
|
6473
|
+
totalContentBytes += fileContentBytes;
|
|
6474
|
+
return [{
|
|
5234
6475
|
path: filePath,
|
|
5235
6476
|
panels: states.map((state, index) => {
|
|
5236
6477
|
if (!state) throw new Error(`Missing virtual state for ${filePath}.`);
|
|
5237
|
-
const content = Buffer.from(state.content, "utf8");
|
|
5238
|
-
if (content.length > DEFAULT_MAX_TOUR_FILE_BYTES || hasLineLongerThan(content, DEFAULT_MAX_TOUR_LINE_BYTES)) {
|
|
5239
|
-
throw new Error(`Deconstructed tour file is too large to present: ${filePath}`);
|
|
5240
|
-
}
|
|
5241
|
-
totalContentBytes += content.length;
|
|
5242
|
-
if (totalContentBytes > DEFAULT_MAX_STACK_CONTENT_BYTES) {
|
|
5243
|
-
throw new Error(`Deconstructed tour content exceeds ${DEFAULT_MAX_STACK_CONTENT_BYTES} bytes.`);
|
|
5244
|
-
}
|
|
5245
6478
|
return {
|
|
5246
6479
|
id: panels[index].id,
|
|
5247
6480
|
label: `${panels[index].label} / ${filePath}${state.exists ? "" : " (absent)"}`,
|
|
@@ -5250,9 +6483,10 @@ var require_changeTour = __commonJS({
|
|
|
5250
6483
|
exists: state.exists
|
|
5251
6484
|
};
|
|
5252
6485
|
})
|
|
5253
|
-
};
|
|
6486
|
+
}];
|
|
5254
6487
|
});
|
|
5255
6488
|
if (files.length === 0) throw new Error(`Deconstructed scene ${source.id} has no staged files.`);
|
|
6489
|
+
const steps = buildDeconstructedFocusSteps(source.id, compiled.stages, files);
|
|
5256
6490
|
return {
|
|
5257
6491
|
id: source.id,
|
|
5258
6492
|
kind: "deconstructed-diff",
|
|
@@ -5270,17 +6504,63 @@ var require_changeTour = __commonJS({
|
|
|
5270
6504
|
},
|
|
5271
6505
|
panels,
|
|
5272
6506
|
files,
|
|
5273
|
-
steps
|
|
5274
|
-
id: stage.id,
|
|
5275
|
-
title: stage.title,
|
|
5276
|
-
body: stage.narration,
|
|
5277
|
-
file: stage.introducedFiles[0],
|
|
5278
|
-
pairIndex: index,
|
|
5279
|
-
side: "right",
|
|
5280
|
-
introducedHunks: stage.introducedHunks
|
|
5281
|
-
}))
|
|
6507
|
+
steps
|
|
5282
6508
|
};
|
|
5283
6509
|
}
|
|
6510
|
+
function buildDeconstructedFocusSteps(sceneId, stages, files) {
|
|
6511
|
+
const reservedIds = new Set(stages.map((stage) => stage.id));
|
|
6512
|
+
const usedIds = /* @__PURE__ */ new Set();
|
|
6513
|
+
return stages.flatMap((stage, stageIndex) => {
|
|
6514
|
+
const focuses = stage.introducedChanges.flatMap((change) => {
|
|
6515
|
+
const file = files.find((candidate) => candidate.path === change.file);
|
|
6516
|
+
const left = file == null ? void 0 : file.panels[stageIndex];
|
|
6517
|
+
const right = file == null ? void 0 : file.panels[stageIndex + 1];
|
|
6518
|
+
if (!file || !left || !right) {
|
|
6519
|
+
throw new Error(`Deconstructed scene ${sceneId} is missing comparison state for ${change.file}.`);
|
|
6520
|
+
}
|
|
6521
|
+
const diffModel = buildTwoWayDiffModel3(left.content, right.content);
|
|
6522
|
+
const side = left.exists && !right.exists ? "left" : "right";
|
|
6523
|
+
const ranges = buildTourFocusRanges(diffModel, side);
|
|
6524
|
+
if (ranges.length === 0) {
|
|
6525
|
+
throw new Error(`Deconstructed stage ${stage.id} has no visible change for ${change.file}.`);
|
|
6526
|
+
}
|
|
6527
|
+
return ranges.map((range) => ({
|
|
6528
|
+
file: change.file,
|
|
6529
|
+
hunks: change.hunks,
|
|
6530
|
+
side,
|
|
6531
|
+
...range
|
|
6532
|
+
}));
|
|
6533
|
+
});
|
|
6534
|
+
return focuses.map((focus, focusIndex) => ({
|
|
6535
|
+
id: focusIndex === 0 ? claimDeconstructedStageId(stage.id, usedIds) : claimDeconstructedFocusId(`${stage.id}-focus-${focusIndex + 1}`, reservedIds, usedIds),
|
|
6536
|
+
title: focuses.length === 1 ? stage.title : `${stage.title} \xB7 ${focus.file} \xB7 Focus ${focusIndex + 1}/${focuses.length}`,
|
|
6537
|
+
body: stage.narration,
|
|
6538
|
+
file: focus.file,
|
|
6539
|
+
pairIndex: stageIndex,
|
|
6540
|
+
side: focus.side,
|
|
6541
|
+
startLine: focus.startLine,
|
|
6542
|
+
endLine: focus.endLine,
|
|
6543
|
+
introducedHunks: [...focus.hunks],
|
|
6544
|
+
stageId: stage.id,
|
|
6545
|
+
stageIndex,
|
|
6546
|
+
focusIndex,
|
|
6547
|
+
focusCount: focuses.length
|
|
6548
|
+
}));
|
|
6549
|
+
});
|
|
6550
|
+
}
|
|
6551
|
+
function claimDeconstructedStageId(stageId, usedIds) {
|
|
6552
|
+
usedIds.add(stageId);
|
|
6553
|
+
return stageId;
|
|
6554
|
+
}
|
|
6555
|
+
function claimDeconstructedFocusId(preferredId, reservedIds, usedIds) {
|
|
6556
|
+
let candidate = preferredId;
|
|
6557
|
+
let suffix = 2;
|
|
6558
|
+
while (usedIds.has(candidate) || reservedIds.has(candidate)) {
|
|
6559
|
+
candidate = `${preferredId}-${suffix++}`;
|
|
6560
|
+
}
|
|
6561
|
+
usedIds.add(candidate);
|
|
6562
|
+
return candidate;
|
|
6563
|
+
}
|
|
5284
6564
|
function buildStackedScene(repoRoot, source, availableFilePaths) {
|
|
5285
6565
|
const stack = source.stack.map((entry) => ({
|
|
5286
6566
|
id: entry.id,
|
|
@@ -9297,7 +10577,7 @@ var require_package = __commonJS({
|
|
|
9297
10577
|
displayName: "Bygone",
|
|
9298
10578
|
desktopName: "com.davidmashburn.bygone.desktop",
|
|
9299
10579
|
description: "See how change happened. Visual diff and file history for VS Code.",
|
|
9300
|
-
version: "0.8.
|
|
10580
|
+
version: "0.8.13",
|
|
9301
10581
|
author: "David Mashburn",
|
|
9302
10582
|
license: "MIT",
|
|
9303
10583
|
private: false,
|