@git-diff-view/react 0.0.11 → 0.0.12
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cjs/index.development.js +879 -847
- package/dist/cjs/index.development.js.map +1 -1
- package/dist/cjs/index.production.js +626 -595
- package/dist/cjs/index.production.js.map +1 -1
- package/dist/esm/index.mjs +811 -783
- package/dist/esm/index.mjs.map +1 -1
- package/package.json +1 -1
- package/readme.md +80 -56
|
@@ -72,334 +72,79 @@ typeof SuppressedError === "function" ? SuppressedError : function (error, suppr
|
|
|
72
72
|
return e.name = "SuppressedError", e.error = error, e.suppressed = suppressed, e;
|
|
73
73
|
};
|
|
74
74
|
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
}
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
let lineNumber = 1;
|
|
112
|
-
const syntaxObj = {};
|
|
113
|
-
const loopAST = (nodes, wrapper) => {
|
|
114
|
-
nodes.forEach((node) => {
|
|
115
|
-
if (node.type === "text") {
|
|
116
|
-
if (node.value.indexOf("\n") === -1) {
|
|
117
|
-
const valueLength = node.value.length;
|
|
118
|
-
if (!syntaxObj[lineNumber]) {
|
|
119
|
-
node.startIndex = 0;
|
|
120
|
-
node.endIndex = valueLength - 1;
|
|
121
|
-
const item = {
|
|
122
|
-
value: node.value,
|
|
123
|
-
lineNumber,
|
|
124
|
-
valueLength,
|
|
125
|
-
nodeList: [{ node, wrapper }],
|
|
126
|
-
};
|
|
127
|
-
syntaxObj[lineNumber] = item;
|
|
128
|
-
}
|
|
129
|
-
else {
|
|
130
|
-
node.startIndex = syntaxObj[lineNumber].valueLength;
|
|
131
|
-
node.endIndex = node.startIndex + valueLength - 1;
|
|
132
|
-
syntaxObj[lineNumber].value += node.value;
|
|
133
|
-
syntaxObj[lineNumber].valueLength += valueLength;
|
|
134
|
-
syntaxObj[lineNumber].nodeList.push({ node, wrapper });
|
|
135
|
-
}
|
|
136
|
-
node.lineNumber = lineNumber;
|
|
137
|
-
return;
|
|
138
|
-
}
|
|
139
|
-
const lines = node.value.split("\n");
|
|
140
|
-
node.children = node.children || [];
|
|
141
|
-
for (let i = 0; i < lines.length; i++) {
|
|
142
|
-
const _value = i === lines.length - 1 ? lines[i] : lines[i] + "\n";
|
|
143
|
-
const _lineNumber = i === 0 ? lineNumber : ++lineNumber;
|
|
144
|
-
const _valueLength = _value.length;
|
|
145
|
-
const _node = {
|
|
146
|
-
type: "text",
|
|
147
|
-
value: _value,
|
|
148
|
-
startIndex: Infinity,
|
|
149
|
-
endIndex: Infinity,
|
|
150
|
-
lineNumber: _lineNumber,
|
|
151
|
-
};
|
|
152
|
-
if (!syntaxObj[_lineNumber]) {
|
|
153
|
-
_node.startIndex = 0;
|
|
154
|
-
_node.endIndex = _valueLength - 1;
|
|
155
|
-
const item = {
|
|
156
|
-
value: _value,
|
|
157
|
-
lineNumber: _lineNumber,
|
|
158
|
-
valueLength: _valueLength,
|
|
159
|
-
nodeList: [{ node: _node, wrapper }],
|
|
160
|
-
};
|
|
161
|
-
syntaxObj[_lineNumber] = item;
|
|
162
|
-
}
|
|
163
|
-
else {
|
|
164
|
-
_node.startIndex = syntaxObj[_lineNumber].valueLength;
|
|
165
|
-
_node.endIndex = _node.startIndex + _valueLength - 1;
|
|
166
|
-
syntaxObj[_lineNumber].value += _value;
|
|
167
|
-
syntaxObj[_lineNumber].valueLength += _valueLength;
|
|
168
|
-
syntaxObj[_lineNumber].nodeList.push({ node: _node, wrapper });
|
|
169
|
-
}
|
|
170
|
-
node.children.push(_node);
|
|
171
|
-
}
|
|
172
|
-
node.lineNumber = lineNumber;
|
|
173
|
-
return;
|
|
174
|
-
}
|
|
175
|
-
if (node.children) {
|
|
176
|
-
loopAST(node.children, node);
|
|
177
|
-
node.lineNumber = lineNumber;
|
|
178
|
-
}
|
|
179
|
-
});
|
|
180
|
-
};
|
|
181
|
-
loopAST(ast.children);
|
|
182
|
-
return { syntaxFileObject: syntaxObj, syntaxFileLineNumber: lineNumber };
|
|
183
|
-
};
|
|
184
|
-
|
|
185
|
-
const lowlight = lowlight$1.createLowlight(lowlight$1.all);
|
|
186
|
-
// !SEE https://github.com/highlightjs/highlightjs-vue
|
|
187
|
-
lowlight.register("vue", function hljsDefineVue(hljs) {
|
|
188
|
-
return {
|
|
189
|
-
subLanguage: "xml",
|
|
190
|
-
contains: [
|
|
191
|
-
hljs.COMMENT("<!--", "-->", {
|
|
192
|
-
relevance: 10,
|
|
193
|
-
}),
|
|
194
|
-
{
|
|
195
|
-
begin: /^(\s*)(<script>)/gm,
|
|
196
|
-
end: /^(\s*)(<\/script>)/gm,
|
|
197
|
-
subLanguage: "javascript",
|
|
198
|
-
excludeBegin: true,
|
|
199
|
-
excludeEnd: true,
|
|
200
|
-
},
|
|
201
|
-
{
|
|
202
|
-
begin: /^(?:\s*)(?:<script\s+lang=(["'])ts\1>)/gm,
|
|
203
|
-
end: /^(\s*)(<\/script>)/gm,
|
|
204
|
-
subLanguage: "typescript",
|
|
205
|
-
excludeBegin: true,
|
|
206
|
-
excludeEnd: true,
|
|
207
|
-
},
|
|
208
|
-
{
|
|
209
|
-
begin: /^(\s*)(<style(\s+scoped)?>)/gm,
|
|
210
|
-
end: /^(\s*)(<\/style>)/gm,
|
|
211
|
-
subLanguage: "css",
|
|
212
|
-
excludeBegin: true,
|
|
213
|
-
excludeEnd: true,
|
|
214
|
-
},
|
|
215
|
-
{
|
|
216
|
-
begin: /^(?:\s*)(?:<style(?:\s+scoped)?\s+lang=(["'])(?:s[ca]ss)\1(?:\s+scoped)?>)/gm,
|
|
217
|
-
end: /^(\s*)(<\/style>)/gm,
|
|
218
|
-
subLanguage: "scss",
|
|
219
|
-
excludeBegin: true,
|
|
220
|
-
excludeEnd: true,
|
|
221
|
-
},
|
|
222
|
-
{
|
|
223
|
-
begin: /^(?:\s*)(?:<style(?:\s+scoped)?\s+lang=(["'])stylus\1(?:\s+scoped)?>)/gm,
|
|
224
|
-
end: /^(\s*)(<\/style>)/gm,
|
|
225
|
-
subLanguage: "stylus",
|
|
226
|
-
excludeBegin: true,
|
|
227
|
-
excludeEnd: true,
|
|
228
|
-
},
|
|
229
|
-
],
|
|
230
|
-
};
|
|
231
|
-
});
|
|
232
|
-
const instance = { name: "lowlight" };
|
|
233
|
-
let _maxLineToIgnoreSyntax = 2000;
|
|
234
|
-
const _ignoreSyntaxHighlightList = [];
|
|
235
|
-
Object.defineProperty(instance, "maxLineToIgnoreSyntax", {
|
|
236
|
-
get: () => _maxLineToIgnoreSyntax,
|
|
237
|
-
});
|
|
238
|
-
Object.defineProperty(instance, "setMaxLineToIgnoreSyntax", {
|
|
239
|
-
value: (v) => {
|
|
240
|
-
_maxLineToIgnoreSyntax = v;
|
|
241
|
-
},
|
|
242
|
-
});
|
|
243
|
-
Object.defineProperty(instance, "ignoreSyntaxHighlightList", {
|
|
244
|
-
get: () => _ignoreSyntaxHighlightList,
|
|
245
|
-
});
|
|
246
|
-
Object.defineProperty(instance, "setIgnoreSyntaxHighlightList", {
|
|
247
|
-
value: (v) => {
|
|
248
|
-
_ignoreSyntaxHighlightList.length = 0;
|
|
249
|
-
_ignoreSyntaxHighlightList.push(...v);
|
|
250
|
-
},
|
|
251
|
-
});
|
|
252
|
-
Object.defineProperty(instance, "getAST", {
|
|
253
|
-
value: (raw, fileName, lang) => {
|
|
254
|
-
let hasRegisteredLang = true;
|
|
255
|
-
if (!lowlight.registered(lang)) {
|
|
256
|
-
console.warn(`not support current lang: ${lang} yet`);
|
|
257
|
-
hasRegisteredLang = false;
|
|
258
|
-
}
|
|
259
|
-
if (fileName &&
|
|
260
|
-
highlighter.ignoreSyntaxHighlightList.some((item) => item instanceof RegExp ? item.test(fileName) : fileName === item)) {
|
|
261
|
-
console.warn(`ignore syntax for current file, because the fileName is in the ignoreSyntaxHighlightList: ${fileName}`);
|
|
262
|
-
return;
|
|
263
|
-
}
|
|
264
|
-
if (hasRegisteredLang) {
|
|
265
|
-
return lowlight.highlight(lang, raw);
|
|
266
|
-
}
|
|
267
|
-
else {
|
|
268
|
-
return lowlight.highlightAuto(raw);
|
|
269
|
-
}
|
|
270
|
-
},
|
|
271
|
-
});
|
|
272
|
-
Object.defineProperty(instance, "processAST", {
|
|
273
|
-
value: (ast) => {
|
|
274
|
-
return processAST(ast);
|
|
275
|
-
},
|
|
276
|
-
});
|
|
277
|
-
const highlighter = instance;
|
|
278
|
-
|
|
279
|
-
var _Cache_keyArray, _Cache_maxLength;
|
|
280
|
-
class Cache extends Map {
|
|
281
|
-
constructor() {
|
|
282
|
-
super(...arguments);
|
|
283
|
-
_Cache_keyArray.set(this, []);
|
|
284
|
-
_Cache_maxLength.set(this, 30);
|
|
285
|
-
}
|
|
286
|
-
setMaxLength(length) {
|
|
287
|
-
__classPrivateFieldSet(this, _Cache_maxLength, length, "f");
|
|
288
|
-
this._checkLength();
|
|
289
|
-
}
|
|
290
|
-
set(key, value) {
|
|
291
|
-
if (this.has(key))
|
|
292
|
-
return this;
|
|
293
|
-
__classPrivateFieldGet(this, _Cache_keyArray, "f").push(key);
|
|
294
|
-
this._checkLength();
|
|
295
|
-
return super.set(key, value);
|
|
296
|
-
}
|
|
297
|
-
_checkLength() {
|
|
298
|
-
while (__classPrivateFieldGet(this, _Cache_keyArray, "f").length > __classPrivateFieldGet(this, _Cache_maxLength, "f")) {
|
|
299
|
-
const key = __classPrivateFieldGet(this, _Cache_keyArray, "f").shift();
|
|
300
|
-
this.delete(key);
|
|
301
|
-
}
|
|
302
|
-
}
|
|
303
|
-
}
|
|
304
|
-
_Cache_keyArray = new WeakMap(), _Cache_maxLength = new WeakMap();
|
|
305
|
-
|
|
306
|
-
var _File_instances, _File_doCheck;
|
|
307
|
-
const map = new Cache();
|
|
308
|
-
const devKey = "@git-diff-cache";
|
|
309
|
-
map.setMaxLength(50);
|
|
310
|
-
map.name = "@git-diff-view/core";
|
|
311
|
-
if (typeof globalThis !== "undefined") {
|
|
312
|
-
if (Array.isArray(globalThis[devKey])) {
|
|
313
|
-
globalThis[devKey] = globalThis[devKey].filter((i) => i !== map);
|
|
314
|
-
if (globalThis[devKey].length > 0) {
|
|
315
|
-
console.warn("there are multiple instance of @git-diff-view/core in the one environment!");
|
|
316
|
-
}
|
|
317
|
-
globalThis[devKey].push(map);
|
|
318
|
-
}
|
|
319
|
-
else {
|
|
320
|
-
globalThis[devKey] = [map];
|
|
321
|
-
}
|
|
322
|
-
}
|
|
323
|
-
class File {
|
|
324
|
-
constructor(raw, lang, fileName) {
|
|
325
|
-
_File_instances.add(this);
|
|
326
|
-
this.raw = raw;
|
|
327
|
-
this.lang = lang;
|
|
328
|
-
this.fileName = fileName;
|
|
329
|
-
this.rawFile = {};
|
|
330
|
-
this.hasDoRaw = false;
|
|
331
|
-
this.syntaxFile = {};
|
|
332
|
-
this.hasDoSyntax = false;
|
|
333
|
-
this.maxLineNumber = 0;
|
|
334
|
-
Object.defineProperty(this, "__v_skip", { value: true });
|
|
335
|
-
}
|
|
336
|
-
doSyntax({ registerHighlighter }) {
|
|
337
|
-
if (!this.raw || this.hasDoSyntax)
|
|
338
|
-
return;
|
|
339
|
-
const _highlighter = registerHighlighter || highlighter;
|
|
340
|
-
if (this.syntaxLength) {
|
|
341
|
-
console.error("current file already doSyntax before!");
|
|
342
|
-
return;
|
|
343
|
-
}
|
|
344
|
-
if (this.rawLength > _highlighter.maxLineToIgnoreSyntax) {
|
|
345
|
-
console.warn(`ignore syntax for current file, because the rawLength is too long: ${this.rawLength}`);
|
|
346
|
-
return;
|
|
347
|
-
}
|
|
348
|
-
this.ast = _highlighter.getAST(this.raw, this.fileName, this.lang);
|
|
349
|
-
if (!this.ast)
|
|
350
|
-
return;
|
|
351
|
-
const { syntaxFileObject, syntaxFileLineNumber } = _highlighter.processAST(this.ast);
|
|
352
|
-
this.syntaxFile = syntaxFileObject;
|
|
353
|
-
this.syntaxLength = syntaxFileLineNumber;
|
|
354
|
-
this.highlighterName = _highlighter.name;
|
|
355
|
-
{
|
|
356
|
-
__classPrivateFieldGet(this, _File_instances, "m", _File_doCheck).call(this);
|
|
357
|
-
}
|
|
358
|
-
this.hasDoSyntax = true;
|
|
75
|
+
exports.DiffHunkExpansionType = void 0;
|
|
76
|
+
(function (DiffHunkExpansionType) {
|
|
77
|
+
/** The hunk header cannot be expanded at all. */
|
|
78
|
+
DiffHunkExpansionType["None"] = "None";
|
|
79
|
+
/**
|
|
80
|
+
* The hunk header can be expanded up exclusively. Only the first hunk can be
|
|
81
|
+
* expanded up exclusively.
|
|
82
|
+
*/
|
|
83
|
+
DiffHunkExpansionType["Up"] = "Up";
|
|
84
|
+
/**
|
|
85
|
+
* The hunk header can be expanded down exclusively. Only the last hunk (if
|
|
86
|
+
* it's the dummy hunk with only one line) can be expanded down exclusively.
|
|
87
|
+
*/
|
|
88
|
+
DiffHunkExpansionType["Down"] = "Down";
|
|
89
|
+
/** The hunk header can be expanded both up and down. */
|
|
90
|
+
DiffHunkExpansionType["Both"] = "Both";
|
|
91
|
+
/**
|
|
92
|
+
* The hunk header represents a short gap that, when expanded, will
|
|
93
|
+
* result in merging this hunk and the hunk above.
|
|
94
|
+
*/
|
|
95
|
+
DiffHunkExpansionType["Short"] = "Short";
|
|
96
|
+
})(exports.DiffHunkExpansionType || (exports.DiffHunkExpansionType = {}));
|
|
97
|
+
/** each diff is made up of a number of hunks */
|
|
98
|
+
class DiffHunk {
|
|
99
|
+
/**
|
|
100
|
+
* @param header The details from the diff hunk header about the line start and patch length.
|
|
101
|
+
* @param lines The contents - context and changes - of the diff section.
|
|
102
|
+
* @param unifiedDiffStart The diff hunk's start position in the overall file diff.
|
|
103
|
+
* @param unifiedDiffEnd The diff hunk's end position in the overall file diff.
|
|
104
|
+
*/
|
|
105
|
+
constructor(header, lines, unifiedDiffStart, unifiedDiffEnd, expansionType) {
|
|
106
|
+
this.header = header;
|
|
107
|
+
this.lines = lines;
|
|
108
|
+
this.unifiedDiffStart = unifiedDiffStart;
|
|
109
|
+
this.unifiedDiffEnd = unifiedDiffEnd;
|
|
110
|
+
this.expansionType = expansionType;
|
|
359
111
|
}
|
|
360
|
-
|
|
361
|
-
if (
|
|
362
|
-
return;
|
|
363
|
-
const rawString = this.raw;
|
|
364
|
-
const rawArray = rawString.split("\n");
|
|
365
|
-
this.rawLength = rawArray.length;
|
|
366
|
-
this.maxLineNumber = rawArray.length;
|
|
367
|
-
this.rawFile = {};
|
|
368
|
-
for (let i = 0; i < rawArray.length; i++) {
|
|
369
|
-
this.rawFile[i + 1] = i < rawArray.length - 1 ? rawArray[i] + "\n" : rawArray[i];
|
|
112
|
+
equals(other) {
|
|
113
|
+
if (this === other) {
|
|
114
|
+
return true;
|
|
370
115
|
}
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
// {}
|
|
378
|
-
// );
|
|
379
|
-
this.hasDoRaw = true;
|
|
116
|
+
return (this.header.equals(other.header) &&
|
|
117
|
+
this.unifiedDiffStart === other.unifiedDiffStart &&
|
|
118
|
+
this.unifiedDiffEnd === other.unifiedDiffEnd &&
|
|
119
|
+
this.expansionType === other.expansionType &&
|
|
120
|
+
this.lines.length === other.lines.length &&
|
|
121
|
+
this.lines.every((xLine, ix) => xLine.equals(other.lines[ix])));
|
|
380
122
|
}
|
|
381
123
|
}
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
124
|
+
/** details about the start and end of a diff hunk */
|
|
125
|
+
class DiffHunkHeader {
|
|
126
|
+
/**
|
|
127
|
+
* @param oldStartLine The line in the old (or original) file where this diff hunk starts.
|
|
128
|
+
* @param oldLineCount The number of lines in the old (or original) file that this diff hunk covers
|
|
129
|
+
* @param newStartLine The line in the new file where this diff hunk starts.
|
|
130
|
+
* @param newLineCount The number of lines in the new file that this diff hunk covers.
|
|
131
|
+
*/
|
|
132
|
+
constructor(oldStartLine, oldLineCount, newStartLine, newLineCount) {
|
|
133
|
+
this.oldStartLine = oldStartLine;
|
|
134
|
+
this.oldLineCount = oldLineCount;
|
|
135
|
+
this.newStartLine = newStartLine;
|
|
136
|
+
this.newLineCount = newLineCount;
|
|
392
137
|
}
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
return
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
}
|
|
402
|
-
|
|
138
|
+
toDiffLineRepresentation() {
|
|
139
|
+
return `@@ -${this.oldStartLine},${this.oldLineCount} +${this.newStartLine},${this.newLineCount} @@`;
|
|
140
|
+
}
|
|
141
|
+
equals(other) {
|
|
142
|
+
return (this.oldStartLine === other.oldStartLine &&
|
|
143
|
+
this.oldLineCount === other.oldLineCount &&
|
|
144
|
+
this.newStartLine === other.newStartLine &&
|
|
145
|
+
this.oldStartLine === other.oldStartLine);
|
|
146
|
+
}
|
|
147
|
+
}
|
|
403
148
|
|
|
404
149
|
exports.NewLineSymbol = void 0;
|
|
405
150
|
(function (NewLineSymbol) {
|
|
@@ -443,29 +188,19 @@ function relativeChanges(addition, deletion) {
|
|
|
443
188
|
const aEndStr = stringA.slice(-2);
|
|
444
189
|
const bEndStr = stringB.slice(-2);
|
|
445
190
|
const hasNewLineChanged = addition.noTrailingNewLine !== deletion.noTrailingNewLine;
|
|
446
|
-
|
|
191
|
+
const aSymbol = aEndStr === "\r\n" ? exports.NewLineSymbol.CRLF : aEndStr.endsWith("\r") ? exports.NewLineSymbol.CR : exports.NewLineSymbol.LF;
|
|
192
|
+
const bSymbol = bEndStr === "\r\n" ? exports.NewLineSymbol.CRLF : bEndStr.endsWith("\r") ? exports.NewLineSymbol.CR : exports.NewLineSymbol.LF;
|
|
193
|
+
if (_stringA === _stringB && (hasNewLineChanged || aSymbol !== bSymbol)) {
|
|
447
194
|
return {
|
|
448
195
|
stringARange: {
|
|
449
196
|
location: _stringA.length,
|
|
450
197
|
length: stringA.length - _stringA.length,
|
|
451
|
-
newLineSymbol: hasNewLineChanged
|
|
452
|
-
? exports.NewLineSymbol.NEWLINE
|
|
453
|
-
: aEndStr === "\r\n"
|
|
454
|
-
? exports.NewLineSymbol.CRLF
|
|
455
|
-
: aEndStr.endsWith("\r")
|
|
456
|
-
? exports.NewLineSymbol.CR
|
|
457
|
-
: exports.NewLineSymbol.LF,
|
|
198
|
+
newLineSymbol: hasNewLineChanged ? exports.NewLineSymbol.NEWLINE : aSymbol,
|
|
458
199
|
},
|
|
459
200
|
stringBRange: {
|
|
460
201
|
location: _stringB.length,
|
|
461
202
|
length: stringB.length - _stringB.length,
|
|
462
|
-
newLineSymbol: hasNewLineChanged
|
|
463
|
-
? exports.NewLineSymbol.NEWLINE
|
|
464
|
-
: bEndStr === "\r\n"
|
|
465
|
-
? exports.NewLineSymbol.CRLF
|
|
466
|
-
: bEndStr.endsWith("\r")
|
|
467
|
-
? exports.NewLineSymbol.CR
|
|
468
|
-
: exports.NewLineSymbol.LF,
|
|
203
|
+
newLineSymbol: hasNewLineChanged ? exports.NewLineSymbol.NEWLINE : bSymbol,
|
|
469
204
|
},
|
|
470
205
|
};
|
|
471
206
|
}
|
|
@@ -527,530 +262,801 @@ class DiffLine {
|
|
|
527
262
|
withNoTrailingNewLine(noTrailingNewLine) {
|
|
528
263
|
return new DiffLine(this.text, this.type, this.originalLineNumber, this.oldLineNumber, this.newLineNumber, noTrailingNewLine);
|
|
529
264
|
}
|
|
530
|
-
isIncludeableLine() {
|
|
531
|
-
return this.type === exports.DiffLineType.Add || this.type === exports.DiffLineType.Delete;
|
|
265
|
+
isIncludeableLine() {
|
|
266
|
+
return this.type === exports.DiffLineType.Add || this.type === exports.DiffLineType.Delete;
|
|
267
|
+
}
|
|
268
|
+
/** The content of the line, i.e., without the line type marker. */
|
|
269
|
+
get content() {
|
|
270
|
+
return this.text.substring(1);
|
|
271
|
+
}
|
|
272
|
+
equals(other) {
|
|
273
|
+
return (this.text === other.text &&
|
|
274
|
+
this.type === other.type &&
|
|
275
|
+
this.originalLineNumber === other.originalLineNumber &&
|
|
276
|
+
this.oldLineNumber === other.oldLineNumber &&
|
|
277
|
+
this.newLineNumber === other.newLineNumber &&
|
|
278
|
+
this.noTrailingNewLine === other.noTrailingNewLine);
|
|
279
|
+
}
|
|
280
|
+
clone(text) {
|
|
281
|
+
return new DiffLine(text, this.type, this.originalLineNumber, this.oldLineNumber, this.newLineNumber);
|
|
282
|
+
}
|
|
283
|
+
}
|
|
284
|
+
const checkDiffLineIncludeChange = (diffLine) => {
|
|
285
|
+
if (!diffLine)
|
|
286
|
+
return false;
|
|
287
|
+
return diffLine.type === exports.DiffLineType.Add || diffLine.type === exports.DiffLineType.Delete;
|
|
288
|
+
};
|
|
289
|
+
|
|
290
|
+
/** How many new lines will be added to a diff hunk by default. */
|
|
291
|
+
const DefaultDiffExpansionStep = 40;
|
|
292
|
+
function assertNever(_, message) {
|
|
293
|
+
throw new Error(message);
|
|
294
|
+
}
|
|
295
|
+
/** Utility function for getting the digit count of the largest line number in an array of diff hunks */
|
|
296
|
+
function getLargestLineNumber(hunks) {
|
|
297
|
+
var _a, _b;
|
|
298
|
+
if (hunks.length === 0) {
|
|
299
|
+
return 0;
|
|
300
|
+
}
|
|
301
|
+
for (let i = hunks.length - 1; i >= 0; i--) {
|
|
302
|
+
const hunk = hunks[i];
|
|
303
|
+
for (let j = hunk.lines.length - 1; j >= 0; j--) {
|
|
304
|
+
const line = hunk.lines[j];
|
|
305
|
+
if (line.type === exports.DiffLineType.Hunk) {
|
|
306
|
+
continue;
|
|
307
|
+
}
|
|
308
|
+
const newLineNumber = (_a = line.newLineNumber) !== null && _a !== void 0 ? _a : 0;
|
|
309
|
+
const oldLineNumber = (_b = line.oldLineNumber) !== null && _b !== void 0 ? _b : 0;
|
|
310
|
+
return newLineNumber > oldLineNumber ? newLineNumber : oldLineNumber;
|
|
311
|
+
}
|
|
312
|
+
}
|
|
313
|
+
return 0;
|
|
314
|
+
}
|
|
315
|
+
/**
|
|
316
|
+
* Calculates whether or not a hunk header can be expanded up, down, both, or if
|
|
317
|
+
* the space represented by the hunk header is short and expansion there would
|
|
318
|
+
* mean merging with the hunk above.
|
|
319
|
+
*
|
|
320
|
+
* @param hunkIndex Index of the hunk to evaluate within the whole diff.
|
|
321
|
+
* @param hunkHeader Header of the hunk to evaluate.
|
|
322
|
+
* @param previousHunk Hunk previous to the one to evaluate. Null if the
|
|
323
|
+
* evaluated hunk is the first one.
|
|
324
|
+
*/
|
|
325
|
+
function getHunkHeaderExpansionType(hunkIndex, hunkHeader, previousHunk) {
|
|
326
|
+
const distanceToPrevious = previousHunk === null
|
|
327
|
+
? Infinity
|
|
328
|
+
: hunkHeader.oldStartLine - previousHunk.header.oldStartLine - previousHunk.header.oldLineCount;
|
|
329
|
+
// In order to simplify the whole logic around expansion, only the hunk at the
|
|
330
|
+
// top can be expanded up exclusively, and only the hunk at the bottom (the
|
|
331
|
+
// dummy one, see getTextDiffWithBottomDummyHunk) can be expanded down
|
|
332
|
+
// exclusively.
|
|
333
|
+
// The rest of the hunks can be expanded both ways, except those which are too
|
|
334
|
+
// short and therefore the direction of expansion doesn't matter.
|
|
335
|
+
if (hunkIndex === 0) {
|
|
336
|
+
// The top hunk can only be expanded if there is content above it
|
|
337
|
+
if (hunkHeader.oldStartLine > 1 && hunkHeader.newStartLine > 1) {
|
|
338
|
+
return exports.DiffHunkExpansionType.Up;
|
|
339
|
+
}
|
|
340
|
+
else {
|
|
341
|
+
return exports.DiffHunkExpansionType.None;
|
|
342
|
+
}
|
|
343
|
+
}
|
|
344
|
+
else if (distanceToPrevious <= DefaultDiffExpansionStep) {
|
|
345
|
+
return exports.DiffHunkExpansionType.Short;
|
|
346
|
+
}
|
|
347
|
+
else {
|
|
348
|
+
return exports.DiffHunkExpansionType.Both;
|
|
349
|
+
}
|
|
350
|
+
}
|
|
351
|
+
const numIterator = (num, cb) => {
|
|
352
|
+
const re = [];
|
|
353
|
+
for (let i = 0; i < num; i++) {
|
|
354
|
+
re.push(cb(i));
|
|
355
|
+
}
|
|
356
|
+
return re;
|
|
357
|
+
};
|
|
358
|
+
const getLang = (fileName) => {
|
|
359
|
+
const dotIndex = fileName.lastIndexOf(".");
|
|
360
|
+
const extension = fileName.slice(dotIndex + 1);
|
|
361
|
+
return extension;
|
|
362
|
+
};
|
|
363
|
+
const getDiffRange = (additions, deletions) => {
|
|
364
|
+
if (additions.length === deletions.length) {
|
|
365
|
+
const len = additions.length;
|
|
366
|
+
for (let i = 0; i < len; i++) {
|
|
367
|
+
const addition = additions[i];
|
|
368
|
+
const deletion = deletions[i];
|
|
369
|
+
const hasDiffRange = hasRelativeChange(addition, deletion);
|
|
370
|
+
if (hasDiffRange) {
|
|
371
|
+
const { stringARange, stringBRange } = relativeChanges(addition, deletion);
|
|
372
|
+
addition.needRematch = true;
|
|
373
|
+
addition.range = stringARange;
|
|
374
|
+
deletion.needRematch = true;
|
|
375
|
+
deletion.range = stringBRange;
|
|
376
|
+
}
|
|
377
|
+
}
|
|
378
|
+
}
|
|
379
|
+
};
|
|
380
|
+
|
|
381
|
+
/* eslint-disable max-lines */
|
|
382
|
+
// !NOTE: ALL of the diff parse logic copy from desktop, SEE https://github.com/desktop/desktop
|
|
383
|
+
// https://en.wikipedia.org/wiki/Diff_utility
|
|
384
|
+
//
|
|
385
|
+
// @@ -l,s +l,s @@ optional section heading
|
|
386
|
+
//
|
|
387
|
+
// The hunk range information contains two hunk ranges. The range for the hunk of the original
|
|
388
|
+
// file is preceded by a minus symbol, and the range for the new file is preceded by a plus
|
|
389
|
+
// symbol. Each hunk range is of the format l,s where l is the starting line number and s is
|
|
390
|
+
// the number of lines the change hunk applies to for each respective file.
|
|
391
|
+
//
|
|
392
|
+
// In many versions of GNU diff, each range can omit the comma and trailing value s,
|
|
393
|
+
// in which case s defaults to 1
|
|
394
|
+
const diffHeaderRe = /^@@ -(\d+)(?:,(\d+))? \+(\d+)(?:,(\d+))? @@/;
|
|
395
|
+
/**
|
|
396
|
+
* Regular expression matching invisible bidirectional Unicode characters that
|
|
397
|
+
* may be interpreted or compiled differently than what it appears. More info:
|
|
398
|
+
* https://github.co/hiddenchars
|
|
399
|
+
*/
|
|
400
|
+
const HiddenBidiCharsRegex = /[\u202A-\u202E]|[\u2066-\u2069]/;
|
|
401
|
+
const DiffPrefixAdd = "+";
|
|
402
|
+
const DiffPrefixDelete = "-";
|
|
403
|
+
const DiffPrefixContext = " ";
|
|
404
|
+
const DiffPrefixNoNewline = "\\";
|
|
405
|
+
const DiffLinePrefixChars = new Set([
|
|
406
|
+
DiffPrefixAdd,
|
|
407
|
+
DiffPrefixDelete,
|
|
408
|
+
DiffPrefixContext,
|
|
409
|
+
DiffPrefixNoNewline,
|
|
410
|
+
]);
|
|
411
|
+
/**
|
|
412
|
+
* A parser for the GNU unified diff format
|
|
413
|
+
*
|
|
414
|
+
* See https://www.gnu.org/software/diffutils/manual/html_node/Detailed-Unified.html
|
|
415
|
+
*/
|
|
416
|
+
class DiffParser {
|
|
417
|
+
constructor() {
|
|
418
|
+
Object.defineProperty(this, "__v_skip", { value: true });
|
|
419
|
+
this.reset();
|
|
420
|
+
}
|
|
421
|
+
/**
|
|
422
|
+
* Resets the internal parser state so that it can be reused.
|
|
423
|
+
*
|
|
424
|
+
* This is done automatically at the end of each parse run.
|
|
425
|
+
*/
|
|
426
|
+
reset() {
|
|
427
|
+
this.ls = 0;
|
|
428
|
+
this.le = -1;
|
|
429
|
+
this.text = "";
|
|
430
|
+
}
|
|
431
|
+
/**
|
|
432
|
+
* Aligns the internal character pointers at the boundaries of
|
|
433
|
+
* the next line.
|
|
434
|
+
*
|
|
435
|
+
* Returns true if successful or false if the end of the diff
|
|
436
|
+
* has been reached.
|
|
437
|
+
*/
|
|
438
|
+
nextLine() {
|
|
439
|
+
this.ls = this.le + 1;
|
|
440
|
+
// We've reached the end of the diff
|
|
441
|
+
if (this.ls >= this.text.length) {
|
|
442
|
+
return false;
|
|
443
|
+
}
|
|
444
|
+
this.le = this.text.indexOf("\n", this.ls);
|
|
445
|
+
// If we can't find the next newline character we'll put our
|
|
446
|
+
// end pointer at the end of the diff string
|
|
447
|
+
if (this.le === -1) {
|
|
448
|
+
this.le = this.text.length;
|
|
449
|
+
}
|
|
450
|
+
// We've succeeded if there's anything to read in between the
|
|
451
|
+
// start and the end
|
|
452
|
+
return this.ls !== this.le;
|
|
453
|
+
}
|
|
454
|
+
/**
|
|
455
|
+
* Advances to the next line and returns it as a substring
|
|
456
|
+
* of the raw diff text. Returns null if end of diff was
|
|
457
|
+
* reached.
|
|
458
|
+
*/
|
|
459
|
+
readLine(header) {
|
|
460
|
+
if (header) {
|
|
461
|
+
return this.nextLine() ? this.text.substring(this.ls, this.le) : null;
|
|
462
|
+
}
|
|
463
|
+
else {
|
|
464
|
+
return this.nextLine() ? this.text.substring(this.ls + 1, this.le + 1) : null;
|
|
465
|
+
}
|
|
466
|
+
}
|
|
467
|
+
/** Tests if the current line starts with the given search text */
|
|
468
|
+
lineStartsWith(searchString) {
|
|
469
|
+
return this.text.startsWith(searchString, this.ls);
|
|
532
470
|
}
|
|
533
|
-
/**
|
|
534
|
-
|
|
535
|
-
return this.text.
|
|
471
|
+
/** Tests if the current line ends with the given search text */
|
|
472
|
+
lineEndsWith(searchString) {
|
|
473
|
+
return this.text.endsWith(searchString, this.le);
|
|
536
474
|
}
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
475
|
+
/**
|
|
476
|
+
* Returns the starting character of the next line without
|
|
477
|
+
* advancing the internal state. Returns null if advancing
|
|
478
|
+
* would mean reaching the end of the diff.
|
|
479
|
+
*/
|
|
480
|
+
peek() {
|
|
481
|
+
const p = this.le + 1;
|
|
482
|
+
return p < this.text.length ? this.text[p] : null;
|
|
544
483
|
}
|
|
545
|
-
|
|
546
|
-
|
|
484
|
+
/**
|
|
485
|
+
* Parse the diff header, meaning everything from the
|
|
486
|
+
* start of the diff output to the end of the line beginning
|
|
487
|
+
* with +++
|
|
488
|
+
*
|
|
489
|
+
* Example diff header:
|
|
490
|
+
*
|
|
491
|
+
* diff --git a/app/src/lib/diff-parser.ts b/app/src/lib/diff-parser.ts
|
|
492
|
+
* index e1d4871..3bd3ee0 100644
|
|
493
|
+
* --- a/app/src/lib/diff-parser.ts
|
|
494
|
+
* +++ b/app/src/lib/diff-parser.ts
|
|
495
|
+
*
|
|
496
|
+
* Returns an object with information extracted from the diff
|
|
497
|
+
* header (currently whether it's a binary patch) or null if
|
|
498
|
+
* the end of the diff was reached before the +++ line could be
|
|
499
|
+
* found (which is a valid state).
|
|
500
|
+
*/
|
|
501
|
+
parseDiffHeader() {
|
|
502
|
+
// TODO: There's information in here that we might want to
|
|
503
|
+
// capture, such as mode changes
|
|
504
|
+
while (this.nextLine()) {
|
|
505
|
+
if (this.lineStartsWith("Binary files ") && this.lineEndsWith("differ")) {
|
|
506
|
+
return { isBinary: true };
|
|
507
|
+
}
|
|
508
|
+
if (this.lineStartsWith("+++")) {
|
|
509
|
+
return { isBinary: false };
|
|
510
|
+
}
|
|
511
|
+
}
|
|
512
|
+
// It's not an error to not find the +++ line, see the
|
|
513
|
+
// 'parses diff of empty file' test in diff-parser-tests.ts
|
|
514
|
+
return null;
|
|
547
515
|
}
|
|
548
|
-
}
|
|
549
|
-
const checkDiffLineIncludeChange = (diffLine) => {
|
|
550
|
-
if (!diffLine)
|
|
551
|
-
return false;
|
|
552
|
-
return diffLine.type === exports.DiffLineType.Add || diffLine.type === exports.DiffLineType.Delete;
|
|
553
|
-
};
|
|
554
|
-
|
|
555
|
-
var DiffHunkExpansionType;
|
|
556
|
-
(function (DiffHunkExpansionType) {
|
|
557
|
-
/** The hunk header cannot be expanded at all. */
|
|
558
|
-
DiffHunkExpansionType["None"] = "None";
|
|
559
516
|
/**
|
|
560
|
-
*
|
|
561
|
-
*
|
|
517
|
+
* Attempts to convert a RegExp capture group into a number.
|
|
518
|
+
* If the group doesn't exist or wasn't captured the function
|
|
519
|
+
* will return the value of the defaultValue parameter or throw
|
|
520
|
+
* an error if no default value was provided. If the captured
|
|
521
|
+
* string can't be converted to a number an error will be thrown.
|
|
562
522
|
*/
|
|
563
|
-
|
|
523
|
+
numberFromGroup(m, group, defaultValue = null) {
|
|
524
|
+
const str = m[group];
|
|
525
|
+
if (!str) {
|
|
526
|
+
if (!defaultValue) {
|
|
527
|
+
throw new Error(`Group ${group} missing from regexp match and no defaultValue was provided`);
|
|
528
|
+
}
|
|
529
|
+
return defaultValue;
|
|
530
|
+
}
|
|
531
|
+
const num = parseInt(str, 10);
|
|
532
|
+
if (isNaN(num)) {
|
|
533
|
+
throw new Error(`Could not parse capture group ${group} into number: ${str}`);
|
|
534
|
+
}
|
|
535
|
+
return num;
|
|
536
|
+
}
|
|
564
537
|
/**
|
|
565
|
-
*
|
|
566
|
-
*
|
|
538
|
+
* Parses a hunk header or throws an error if the given line isn't
|
|
539
|
+
* a well-formed hunk header.
|
|
540
|
+
*
|
|
541
|
+
* We currently only extract the line number information and
|
|
542
|
+
* ignore any hunk headings.
|
|
543
|
+
*
|
|
544
|
+
* Example hunk header (text within ``):
|
|
545
|
+
*
|
|
546
|
+
* `@@ -84,10 +82,8 @@ export function parseRawDiff(lines: ReadonlyArray<string>): Diff {`
|
|
547
|
+
*
|
|
548
|
+
* Where everything after the last @@ is what's known as the hunk, or section, heading
|
|
567
549
|
*/
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
550
|
+
parseHunkHeader(line) {
|
|
551
|
+
const m = diffHeaderRe.exec(line);
|
|
552
|
+
if (!m) {
|
|
553
|
+
throw new Error(`Invalid hunk header format`);
|
|
554
|
+
}
|
|
555
|
+
// If endLines are missing default to 1, see diffHeaderRe docs
|
|
556
|
+
const oldStartLine = this.numberFromGroup(m, 1);
|
|
557
|
+
const oldLineCount = this.numberFromGroup(m, 2, 1);
|
|
558
|
+
const newStartLine = this.numberFromGroup(m, 3);
|
|
559
|
+
const newLineCount = this.numberFromGroup(m, 4, 1);
|
|
560
|
+
return new DiffHunkHeader(oldStartLine, oldLineCount, newStartLine, newLineCount);
|
|
561
|
+
}
|
|
571
562
|
/**
|
|
572
|
-
*
|
|
573
|
-
*
|
|
563
|
+
* Convenience function which lets us leverage the type system to
|
|
564
|
+
* prove exhaustive checks in parseHunk.
|
|
565
|
+
*
|
|
566
|
+
* Takes an arbitrary string and checks to see if the first character
|
|
567
|
+
* of that string is one of the allowed prefix characters for diff
|
|
568
|
+
* lines (ie lines in between hunk headers).
|
|
574
569
|
*/
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
570
|
+
parseLinePrefix(c) {
|
|
571
|
+
// Since we know that DiffLinePrefixChars and the DiffLinePrefix type
|
|
572
|
+
// include the same characters we can tell the type system that we
|
|
573
|
+
// now know that c[0] is one of the characters in the DifflinePrefix set
|
|
574
|
+
if (c && c.length && DiffLinePrefixChars.has(c[0])) {
|
|
575
|
+
return c[0];
|
|
576
|
+
}
|
|
577
|
+
return null;
|
|
578
|
+
}
|
|
579
579
|
/**
|
|
580
|
-
*
|
|
581
|
-
*
|
|
582
|
-
*
|
|
583
|
-
*
|
|
580
|
+
* Parses a hunk, including its header or throws an error if the diff doesn't
|
|
581
|
+
* contain a well-formed diff hunk at the current position.
|
|
582
|
+
*
|
|
583
|
+
* Expects that the position has been advanced to the beginning of a presumed
|
|
584
|
+
* diff hunk header.
|
|
585
|
+
*
|
|
586
|
+
* @param linesConsumed The number of unified diff lines consumed up until
|
|
587
|
+
* this point by the diff parser. Used to give the
|
|
588
|
+
* position and length (in lines) of the parsed hunk
|
|
589
|
+
* relative to the overall parsed diff. These numbers
|
|
590
|
+
* have no real meaning in the context of a diff and
|
|
591
|
+
* are only used to aid the app in line-selections.
|
|
584
592
|
*/
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
|
|
593
|
+
parseHunk(linesConsumed, hunkIndex, previousHunk) {
|
|
594
|
+
const headerLine = this.readLine(true);
|
|
595
|
+
if (!headerLine) {
|
|
596
|
+
throw new Error("Expected hunk header but reached end of diff");
|
|
597
|
+
}
|
|
598
|
+
const header = this.parseHunkHeader(headerLine);
|
|
599
|
+
const lines = new Array();
|
|
600
|
+
lines.push(new DiffLine(headerLine, exports.DiffLineType.Hunk, 1, null, null));
|
|
601
|
+
let c;
|
|
602
|
+
let rollingDiffBeforeCounter = header.oldStartLine;
|
|
603
|
+
let rollingDiffAfterCounter = header.newStartLine;
|
|
604
|
+
let diffLineNumber = linesConsumed;
|
|
605
|
+
while ((c = this.parseLinePrefix(this.peek()))) {
|
|
606
|
+
const line = this.readLine(false);
|
|
607
|
+
diffLineNumber++;
|
|
608
|
+
if (!line) {
|
|
609
|
+
throw new Error("Expected unified diff line but reached end of diff");
|
|
610
|
+
}
|
|
611
|
+
// A marker indicating that the last line in the original or the new file
|
|
612
|
+
// is missing a trailing newline. In other words, the presence of this marker
|
|
613
|
+
// means that the new and/or original file lacks a trailing newline.
|
|
614
|
+
//
|
|
615
|
+
// When we find it we have to look up the previous line and set the
|
|
616
|
+
// noTrailingNewLine flag
|
|
617
|
+
if (c === DiffPrefixNoNewline) {
|
|
618
|
+
// See https://github.com/git/git/blob/21f862b498925194f8f1ebe8203b7a7df756555b/apply.c#L1725-L1732
|
|
619
|
+
if (line.length < 12) {
|
|
620
|
+
throw new Error(`Expected "no newline at end of file" marker to be at least 12 bytes long`);
|
|
621
|
+
}
|
|
622
|
+
const previousLineIndex = lines.length - 1;
|
|
623
|
+
const previousLine = lines[previousLineIndex];
|
|
624
|
+
lines[previousLineIndex] = previousLine.withNoTrailingNewLine(true);
|
|
625
|
+
continue;
|
|
626
|
+
}
|
|
627
|
+
let diffLine;
|
|
628
|
+
if (c === DiffPrefixAdd) {
|
|
629
|
+
diffLine = new DiffLine(line, exports.DiffLineType.Add, diffLineNumber, null, rollingDiffAfterCounter++);
|
|
630
|
+
}
|
|
631
|
+
else if (c === DiffPrefixDelete) {
|
|
632
|
+
diffLine = new DiffLine(line, exports.DiffLineType.Delete, diffLineNumber, rollingDiffBeforeCounter++, null);
|
|
633
|
+
}
|
|
634
|
+
else if (c === DiffPrefixContext) {
|
|
635
|
+
diffLine = new DiffLine(line, exports.DiffLineType.Context, diffLineNumber, rollingDiffBeforeCounter++, rollingDiffAfterCounter++);
|
|
636
|
+
}
|
|
637
|
+
else {
|
|
638
|
+
return assertNever(c, `Unknown DiffLinePrefix: ${c}`);
|
|
639
|
+
}
|
|
640
|
+
lines.push(diffLine);
|
|
641
|
+
}
|
|
642
|
+
if (lines.length === 1) {
|
|
643
|
+
throw new Error("Malformed diff, empty hunk");
|
|
644
|
+
}
|
|
645
|
+
return new DiffHunk(header, lines, linesConsumed, linesConsumed + lines.length - 1, getHunkHeaderExpansionType(hunkIndex, header, previousHunk));
|
|
591
646
|
}
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
|
|
647
|
+
/**
|
|
648
|
+
* Parse a well-formed unified diff into hunks and lines.
|
|
649
|
+
*
|
|
650
|
+
* @param text A unified diff produced by git diff, git log --patch
|
|
651
|
+
* or any other git plumbing command that produces unified
|
|
652
|
+
* diffs.
|
|
653
|
+
*/
|
|
654
|
+
parse(text) {
|
|
655
|
+
this.text = text;
|
|
656
|
+
try {
|
|
657
|
+
const headerInfo = this.parseDiffHeader();
|
|
658
|
+
const headerEnd = this.le;
|
|
659
|
+
const header = this.text.substring(0, headerEnd);
|
|
660
|
+
// empty diff
|
|
661
|
+
if (!headerInfo) {
|
|
662
|
+
return {
|
|
663
|
+
header,
|
|
664
|
+
contents: "",
|
|
665
|
+
hunks: [],
|
|
666
|
+
isBinary: false,
|
|
667
|
+
maxLineNumber: 0,
|
|
668
|
+
hasHiddenBidiChars: false,
|
|
669
|
+
};
|
|
670
|
+
}
|
|
671
|
+
if (headerInfo.isBinary) {
|
|
672
|
+
return {
|
|
673
|
+
header,
|
|
674
|
+
contents: "",
|
|
675
|
+
hunks: [],
|
|
676
|
+
isBinary: true,
|
|
677
|
+
maxLineNumber: 0,
|
|
678
|
+
hasHiddenBidiChars: false,
|
|
679
|
+
};
|
|
680
|
+
}
|
|
681
|
+
const hunks = new Array();
|
|
682
|
+
let linesConsumed = 0;
|
|
683
|
+
let previousHunk = null;
|
|
684
|
+
do {
|
|
685
|
+
const hunk = this.parseHunk(linesConsumed, hunks.length, previousHunk);
|
|
686
|
+
hunks.push(hunk);
|
|
687
|
+
previousHunk = hunk;
|
|
688
|
+
linesConsumed += hunk.lines.length;
|
|
689
|
+
} while (this.peek());
|
|
690
|
+
const contents = this.text
|
|
691
|
+
.substring(headerEnd + 1, this.le)
|
|
692
|
+
// Note that this simply returns a reference to the
|
|
693
|
+
// substring if no match is found, it does not create
|
|
694
|
+
// a new string instance.
|
|
695
|
+
.replace(/\n\/g, "");
|
|
696
|
+
return {
|
|
697
|
+
header,
|
|
698
|
+
contents,
|
|
699
|
+
hunks,
|
|
700
|
+
isBinary: headerInfo.isBinary,
|
|
701
|
+
maxLineNumber: getLargestLineNumber(hunks),
|
|
702
|
+
hasHiddenBidiChars: HiddenBidiCharsRegex.test(text),
|
|
703
|
+
};
|
|
704
|
+
}
|
|
705
|
+
finally {
|
|
706
|
+
this.reset();
|
|
595
707
|
}
|
|
596
|
-
return (this.header.equals(other.header) &&
|
|
597
|
-
this.unifiedDiffStart === other.unifiedDiffStart &&
|
|
598
|
-
this.unifiedDiffEnd === other.unifiedDiffEnd &&
|
|
599
|
-
this.expansionType === other.expansionType &&
|
|
600
|
-
this.lines.length === other.lines.length &&
|
|
601
|
-
this.lines.every((xLine, ix) => xLine.equals(other.lines[ix])));
|
|
602
|
-
}
|
|
603
|
-
}
|
|
604
|
-
/** details about the start and end of a diff hunk */
|
|
605
|
-
class DiffHunkHeader {
|
|
606
|
-
/**
|
|
607
|
-
* @param oldStartLine The line in the old (or original) file where this diff hunk starts.
|
|
608
|
-
* @param oldLineCount The number of lines in the old (or original) file that this diff hunk covers
|
|
609
|
-
* @param newStartLine The line in the new file where this diff hunk starts.
|
|
610
|
-
* @param newLineCount The number of lines in the new file that this diff hunk covers.
|
|
611
|
-
*/
|
|
612
|
-
constructor(oldStartLine, oldLineCount, newStartLine, newLineCount) {
|
|
613
|
-
this.oldStartLine = oldStartLine;
|
|
614
|
-
this.oldLineCount = oldLineCount;
|
|
615
|
-
this.newStartLine = newStartLine;
|
|
616
|
-
this.newLineCount = newLineCount;
|
|
617
|
-
}
|
|
618
|
-
toDiffLineRepresentation() {
|
|
619
|
-
return `@@ -${this.oldStartLine},${this.oldLineCount} +${this.newStartLine},${this.newLineCount} @@`;
|
|
620
|
-
}
|
|
621
|
-
equals(other) {
|
|
622
|
-
return (this.oldStartLine === other.oldStartLine &&
|
|
623
|
-
this.oldLineCount === other.oldLineCount &&
|
|
624
|
-
this.newStartLine === other.newStartLine &&
|
|
625
|
-
this.oldStartLine === other.oldStartLine);
|
|
626
708
|
}
|
|
627
709
|
}
|
|
710
|
+
const parseInstance = new DiffParser();
|
|
628
711
|
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
|
|
644
|
-
|
|
645
|
-
|
|
712
|
+
/******************************************************************************
|
|
713
|
+
Copyright (c) Microsoft Corporation.
|
|
714
|
+
|
|
715
|
+
Permission to use, copy, modify, and/or distribute this software for any
|
|
716
|
+
purpose with or without fee is hereby granted.
|
|
717
|
+
|
|
718
|
+
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
|
|
719
|
+
REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
|
|
720
|
+
AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
|
|
721
|
+
INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
|
|
722
|
+
LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
|
|
723
|
+
OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
|
724
|
+
PERFORMANCE OF THIS SOFTWARE.
|
|
725
|
+
***************************************************************************** */
|
|
726
|
+
/* global Reflect, Promise, SuppressedError, Symbol */
|
|
727
|
+
|
|
728
|
+
|
|
729
|
+
function __classPrivateFieldGet(receiver, state, kind, f) {
|
|
730
|
+
if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a getter");
|
|
731
|
+
if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it");
|
|
732
|
+
return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver);
|
|
733
|
+
}
|
|
734
|
+
|
|
735
|
+
function __classPrivateFieldSet(receiver, state, value, kind, f) {
|
|
736
|
+
if (kind === "m") throw new TypeError("Private method is not writable");
|
|
737
|
+
if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a setter");
|
|
738
|
+
if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot write private member to an object whose class did not declare it");
|
|
739
|
+
return (kind === "a" ? f.call(receiver, value) : f ? f.value = value : state.set(receiver, value)), value;
|
|
740
|
+
}
|
|
741
|
+
|
|
742
|
+
typeof SuppressedError === "function" ? SuppressedError : function (error, suppressed, message) {
|
|
743
|
+
var e = new Error(message);
|
|
744
|
+
return e.name = "SuppressedError", e.error = error, e.suppressed = suppressed, e;
|
|
745
|
+
};
|
|
746
|
+
|
|
747
|
+
const processAST = (ast) => {
|
|
748
|
+
let lineNumber = 1;
|
|
749
|
+
const syntaxObj = {};
|
|
750
|
+
const loopAST = (nodes, wrapper) => {
|
|
751
|
+
nodes.forEach((node) => {
|
|
752
|
+
if (node.type === "text") {
|
|
753
|
+
if (node.value.indexOf("\n") === -1) {
|
|
754
|
+
const valueLength = node.value.length;
|
|
755
|
+
if (!syntaxObj[lineNumber]) {
|
|
756
|
+
node.startIndex = 0;
|
|
757
|
+
node.endIndex = valueLength - 1;
|
|
758
|
+
const item = {
|
|
759
|
+
value: node.value,
|
|
760
|
+
lineNumber,
|
|
761
|
+
valueLength,
|
|
762
|
+
nodeList: [{ node, wrapper }],
|
|
763
|
+
};
|
|
764
|
+
syntaxObj[lineNumber] = item;
|
|
765
|
+
}
|
|
766
|
+
else {
|
|
767
|
+
node.startIndex = syntaxObj[lineNumber].valueLength;
|
|
768
|
+
node.endIndex = node.startIndex + valueLength - 1;
|
|
769
|
+
syntaxObj[lineNumber].value += node.value;
|
|
770
|
+
syntaxObj[lineNumber].valueLength += valueLength;
|
|
771
|
+
syntaxObj[lineNumber].nodeList.push({ node, wrapper });
|
|
772
|
+
}
|
|
773
|
+
node.lineNumber = lineNumber;
|
|
774
|
+
return;
|
|
775
|
+
}
|
|
776
|
+
const lines = node.value.split("\n");
|
|
777
|
+
node.children = node.children || [];
|
|
778
|
+
for (let i = 0; i < lines.length; i++) {
|
|
779
|
+
const _value = i === lines.length - 1 ? lines[i] : lines[i] + "\n";
|
|
780
|
+
const _lineNumber = i === 0 ? lineNumber : ++lineNumber;
|
|
781
|
+
const _valueLength = _value.length;
|
|
782
|
+
const _node = {
|
|
783
|
+
type: "text",
|
|
784
|
+
value: _value,
|
|
785
|
+
startIndex: Infinity,
|
|
786
|
+
endIndex: Infinity,
|
|
787
|
+
lineNumber: _lineNumber,
|
|
788
|
+
};
|
|
789
|
+
if (!syntaxObj[_lineNumber]) {
|
|
790
|
+
_node.startIndex = 0;
|
|
791
|
+
_node.endIndex = _valueLength - 1;
|
|
792
|
+
const item = {
|
|
793
|
+
value: _value,
|
|
794
|
+
lineNumber: _lineNumber,
|
|
795
|
+
valueLength: _valueLength,
|
|
796
|
+
nodeList: [{ node: _node, wrapper }],
|
|
797
|
+
};
|
|
798
|
+
syntaxObj[_lineNumber] = item;
|
|
799
|
+
}
|
|
800
|
+
else {
|
|
801
|
+
_node.startIndex = syntaxObj[_lineNumber].valueLength;
|
|
802
|
+
_node.endIndex = _node.startIndex + _valueLength - 1;
|
|
803
|
+
syntaxObj[_lineNumber].value += _value;
|
|
804
|
+
syntaxObj[_lineNumber].valueLength += _valueLength;
|
|
805
|
+
syntaxObj[_lineNumber].nodeList.push({ node: _node, wrapper });
|
|
806
|
+
}
|
|
807
|
+
node.children.push(_node);
|
|
808
|
+
}
|
|
809
|
+
node.lineNumber = lineNumber;
|
|
810
|
+
return;
|
|
646
811
|
}
|
|
647
|
-
|
|
648
|
-
|
|
649
|
-
|
|
812
|
+
if (node.children) {
|
|
813
|
+
loopAST(node.children, node);
|
|
814
|
+
node.lineNumber = lineNumber;
|
|
815
|
+
}
|
|
816
|
+
});
|
|
817
|
+
};
|
|
818
|
+
loopAST(ast.children);
|
|
819
|
+
return { syntaxFileObject: syntaxObj, syntaxFileLineNumber: lineNumber };
|
|
820
|
+
};
|
|
821
|
+
|
|
822
|
+
const lowlight = lowlight$1.createLowlight(lowlight$1.all);
|
|
823
|
+
// !SEE https://github.com/highlightjs/highlightjs-vue
|
|
824
|
+
lowlight.register("vue", function hljsDefineVue(hljs) {
|
|
825
|
+
return {
|
|
826
|
+
subLanguage: "xml",
|
|
827
|
+
contains: [
|
|
828
|
+
hljs.COMMENT("<!--", "-->", {
|
|
829
|
+
relevance: 10,
|
|
830
|
+
}),
|
|
831
|
+
{
|
|
832
|
+
begin: /^(\s*)(<script>)/gm,
|
|
833
|
+
end: /^(\s*)(<\/script>)/gm,
|
|
834
|
+
subLanguage: "javascript",
|
|
835
|
+
excludeBegin: true,
|
|
836
|
+
excludeEnd: true,
|
|
837
|
+
},
|
|
838
|
+
{
|
|
839
|
+
begin: /^(?:\s*)(?:<script\s+lang=(["'])ts\1>)/gm,
|
|
840
|
+
end: /^(\s*)(<\/script>)/gm,
|
|
841
|
+
subLanguage: "typescript",
|
|
842
|
+
excludeBegin: true,
|
|
843
|
+
excludeEnd: true,
|
|
844
|
+
},
|
|
845
|
+
{
|
|
846
|
+
begin: /^(\s*)(<style(\s+scoped)?>)/gm,
|
|
847
|
+
end: /^(\s*)(<\/style>)/gm,
|
|
848
|
+
subLanguage: "css",
|
|
849
|
+
excludeBegin: true,
|
|
850
|
+
excludeEnd: true,
|
|
851
|
+
},
|
|
852
|
+
{
|
|
853
|
+
begin: /^(?:\s*)(?:<style(?:\s+scoped)?\s+lang=(["'])(?:s[ca]ss)\1(?:\s+scoped)?>)/gm,
|
|
854
|
+
end: /^(\s*)(<\/style>)/gm,
|
|
855
|
+
subLanguage: "scss",
|
|
856
|
+
excludeBegin: true,
|
|
857
|
+
excludeEnd: true,
|
|
858
|
+
},
|
|
859
|
+
{
|
|
860
|
+
begin: /^(?:\s*)(?:<style(?:\s+scoped)?\s+lang=(["'])stylus\1(?:\s+scoped)?>)/gm,
|
|
861
|
+
end: /^(\s*)(<\/style>)/gm,
|
|
862
|
+
subLanguage: "stylus",
|
|
863
|
+
excludeBegin: true,
|
|
864
|
+
excludeEnd: true,
|
|
865
|
+
},
|
|
866
|
+
],
|
|
867
|
+
};
|
|
868
|
+
});
|
|
869
|
+
const instance = { name: "lowlight" };
|
|
870
|
+
let _maxLineToIgnoreSyntax = 2000;
|
|
871
|
+
const _ignoreSyntaxHighlightList = [];
|
|
872
|
+
Object.defineProperty(instance, "maxLineToIgnoreSyntax", {
|
|
873
|
+
get: () => _maxLineToIgnoreSyntax,
|
|
874
|
+
});
|
|
875
|
+
Object.defineProperty(instance, "setMaxLineToIgnoreSyntax", {
|
|
876
|
+
value: (v) => {
|
|
877
|
+
_maxLineToIgnoreSyntax = v;
|
|
878
|
+
},
|
|
879
|
+
});
|
|
880
|
+
Object.defineProperty(instance, "ignoreSyntaxHighlightList", {
|
|
881
|
+
get: () => _ignoreSyntaxHighlightList,
|
|
882
|
+
});
|
|
883
|
+
Object.defineProperty(instance, "setIgnoreSyntaxHighlightList", {
|
|
884
|
+
value: (v) => {
|
|
885
|
+
_ignoreSyntaxHighlightList.length = 0;
|
|
886
|
+
_ignoreSyntaxHighlightList.push(...v);
|
|
887
|
+
},
|
|
888
|
+
});
|
|
889
|
+
Object.defineProperty(instance, "getAST", {
|
|
890
|
+
value: (raw, fileName, lang) => {
|
|
891
|
+
let hasRegisteredLang = true;
|
|
892
|
+
if (!lowlight.registered(lang)) {
|
|
893
|
+
console.warn(`not support current lang: ${lang} yet`);
|
|
894
|
+
hasRegisteredLang = false;
|
|
895
|
+
}
|
|
896
|
+
if (fileName &&
|
|
897
|
+
highlighter.ignoreSyntaxHighlightList.some((item) => item instanceof RegExp ? item.test(fileName) : fileName === item)) {
|
|
898
|
+
console.warn(`ignore syntax for current file, because the fileName is in the ignoreSyntaxHighlightList: ${fileName}`);
|
|
899
|
+
return;
|
|
650
900
|
}
|
|
651
|
-
|
|
652
|
-
|
|
653
|
-
}
|
|
654
|
-
/**
|
|
655
|
-
* Calculates whether or not a hunk header can be expanded up, down, both, or if
|
|
656
|
-
* the space represented by the hunk header is short and expansion there would
|
|
657
|
-
* mean merging with the hunk above.
|
|
658
|
-
*
|
|
659
|
-
* @param hunkIndex Index of the hunk to evaluate within the whole diff.
|
|
660
|
-
* @param hunkHeader Header of the hunk to evaluate.
|
|
661
|
-
* @param previousHunk Hunk previous to the one to evaluate. Null if the
|
|
662
|
-
* evaluated hunk is the first one.
|
|
663
|
-
*/
|
|
664
|
-
function getHunkHeaderExpansionType(hunkIndex, hunkHeader, previousHunk) {
|
|
665
|
-
const distanceToPrevious = previousHunk === null
|
|
666
|
-
? Infinity
|
|
667
|
-
: hunkHeader.oldStartLine - previousHunk.header.oldStartLine - previousHunk.header.oldLineCount;
|
|
668
|
-
// In order to simplify the whole logic around expansion, only the hunk at the
|
|
669
|
-
// top can be expanded up exclusively, and only the hunk at the bottom (the
|
|
670
|
-
// dummy one, see getTextDiffWithBottomDummyHunk) can be expanded down
|
|
671
|
-
// exclusively.
|
|
672
|
-
// The rest of the hunks can be expanded both ways, except those which are too
|
|
673
|
-
// short and therefore the direction of expansion doesn't matter.
|
|
674
|
-
if (hunkIndex === 0) {
|
|
675
|
-
// The top hunk can only be expanded if there is content above it
|
|
676
|
-
if (hunkHeader.oldStartLine > 1 && hunkHeader.newStartLine > 1) {
|
|
677
|
-
return DiffHunkExpansionType.Up;
|
|
901
|
+
if (hasRegisteredLang) {
|
|
902
|
+
return lowlight.highlight(lang, raw);
|
|
678
903
|
}
|
|
679
904
|
else {
|
|
680
|
-
return
|
|
681
|
-
}
|
|
682
|
-
}
|
|
683
|
-
else if (distanceToPrevious <= DefaultDiffExpansionStep) {
|
|
684
|
-
return DiffHunkExpansionType.Short;
|
|
685
|
-
}
|
|
686
|
-
else {
|
|
687
|
-
return DiffHunkExpansionType.Both;
|
|
688
|
-
}
|
|
689
|
-
}
|
|
690
|
-
const numIterator = (num, cb) => {
|
|
691
|
-
const re = [];
|
|
692
|
-
for (let i = 0; i < num; i++) {
|
|
693
|
-
re.push(cb(i));
|
|
694
|
-
}
|
|
695
|
-
return re;
|
|
696
|
-
};
|
|
697
|
-
const getLang = (fileName) => {
|
|
698
|
-
const dotIndex = fileName.lastIndexOf(".");
|
|
699
|
-
const extension = fileName.slice(dotIndex + 1);
|
|
700
|
-
return extension;
|
|
701
|
-
};
|
|
702
|
-
const getDiffRange = (additions, deletions) => {
|
|
703
|
-
if (additions.length === deletions.length) {
|
|
704
|
-
const len = additions.length;
|
|
705
|
-
for (let i = 0; i < len; i++) {
|
|
706
|
-
const addition = additions[i];
|
|
707
|
-
const deletion = deletions[i];
|
|
708
|
-
const hasDiffRange = hasRelativeChange(addition, deletion);
|
|
709
|
-
if (hasDiffRange) {
|
|
710
|
-
const { stringARange, stringBRange } = relativeChanges(addition, deletion);
|
|
711
|
-
addition.needRematch = true;
|
|
712
|
-
addition.range = stringARange;
|
|
713
|
-
deletion.needRematch = true;
|
|
714
|
-
deletion.range = stringBRange;
|
|
715
|
-
}
|
|
905
|
+
return lowlight.highlightAuto(raw);
|
|
716
906
|
}
|
|
717
|
-
}
|
|
718
|
-
};
|
|
907
|
+
},
|
|
908
|
+
});
|
|
909
|
+
Object.defineProperty(instance, "processAST", {
|
|
910
|
+
value: (ast) => {
|
|
911
|
+
return processAST(ast);
|
|
912
|
+
},
|
|
913
|
+
});
|
|
914
|
+
Object.defineProperty(instance, "hasRegisteredCurrentLang", {
|
|
915
|
+
value: (lang) => {
|
|
916
|
+
return lowlight.registered(lang);
|
|
917
|
+
},
|
|
918
|
+
});
|
|
919
|
+
const highlighter = instance;
|
|
719
920
|
|
|
720
|
-
|
|
721
|
-
|
|
722
|
-
// https://en.wikipedia.org/wiki/Diff_utility
|
|
723
|
-
//
|
|
724
|
-
// @@ -l,s +l,s @@ optional section heading
|
|
725
|
-
//
|
|
726
|
-
// The hunk range information contains two hunk ranges. The range for the hunk of the original
|
|
727
|
-
// file is preceded by a minus symbol, and the range for the new file is preceded by a plus
|
|
728
|
-
// symbol. Each hunk range is of the format l,s where l is the starting line number and s is
|
|
729
|
-
// the number of lines the change hunk applies to for each respective file.
|
|
730
|
-
//
|
|
731
|
-
// In many versions of GNU diff, each range can omit the comma and trailing value s,
|
|
732
|
-
// in which case s defaults to 1
|
|
733
|
-
const diffHeaderRe = /^@@ -(\d+)(?:,(\d+))? \+(\d+)(?:,(\d+))? @@/;
|
|
734
|
-
/**
|
|
735
|
-
* Regular expression matching invisible bidirectional Unicode characters that
|
|
736
|
-
* may be interpreted or compiled differently than what it appears. More info:
|
|
737
|
-
* https://github.co/hiddenchars
|
|
738
|
-
*/
|
|
739
|
-
const HiddenBidiCharsRegex = /[\u202A-\u202E]|[\u2066-\u2069]/;
|
|
740
|
-
const DiffPrefixAdd = "+";
|
|
741
|
-
const DiffPrefixDelete = "-";
|
|
742
|
-
const DiffPrefixContext = " ";
|
|
743
|
-
const DiffPrefixNoNewline = "\\";
|
|
744
|
-
const DiffLinePrefixChars = new Set([
|
|
745
|
-
DiffPrefixAdd,
|
|
746
|
-
DiffPrefixDelete,
|
|
747
|
-
DiffPrefixContext,
|
|
748
|
-
DiffPrefixNoNewline,
|
|
749
|
-
]);
|
|
750
|
-
/**
|
|
751
|
-
* A parser for the GNU unified diff format
|
|
752
|
-
*
|
|
753
|
-
* See https://www.gnu.org/software/diffutils/manual/html_node/Detailed-Unified.html
|
|
754
|
-
*/
|
|
755
|
-
class DiffParser {
|
|
921
|
+
var _Cache_keyArray, _Cache_maxLength;
|
|
922
|
+
class Cache extends Map {
|
|
756
923
|
constructor() {
|
|
757
|
-
|
|
758
|
-
|
|
759
|
-
|
|
760
|
-
/**
|
|
761
|
-
* Resets the internal parser state so that it can be reused.
|
|
762
|
-
*
|
|
763
|
-
* This is done automatically at the end of each parse run.
|
|
764
|
-
*/
|
|
765
|
-
reset() {
|
|
766
|
-
this.ls = 0;
|
|
767
|
-
this.le = -1;
|
|
768
|
-
this.text = "";
|
|
769
|
-
}
|
|
770
|
-
/**
|
|
771
|
-
* Aligns the internal character pointers at the boundaries of
|
|
772
|
-
* the next line.
|
|
773
|
-
*
|
|
774
|
-
* Returns true if successful or false if the end of the diff
|
|
775
|
-
* has been reached.
|
|
776
|
-
*/
|
|
777
|
-
nextLine() {
|
|
778
|
-
this.ls = this.le + 1;
|
|
779
|
-
// We've reached the end of the diff
|
|
780
|
-
if (this.ls >= this.text.length) {
|
|
781
|
-
return false;
|
|
782
|
-
}
|
|
783
|
-
this.le = this.text.indexOf("\n", this.ls);
|
|
784
|
-
// If we can't find the next newline character we'll put our
|
|
785
|
-
// end pointer at the end of the diff string
|
|
786
|
-
if (this.le === -1) {
|
|
787
|
-
this.le = this.text.length;
|
|
788
|
-
}
|
|
789
|
-
// We've succeeded if there's anything to read in between the
|
|
790
|
-
// start and the end
|
|
791
|
-
return this.ls !== this.le;
|
|
792
|
-
}
|
|
793
|
-
/**
|
|
794
|
-
* Advances to the next line and returns it as a substring
|
|
795
|
-
* of the raw diff text. Returns null if end of diff was
|
|
796
|
-
* reached.
|
|
797
|
-
*/
|
|
798
|
-
readLine(header) {
|
|
799
|
-
if (header) {
|
|
800
|
-
return this.nextLine() ? this.text.substring(this.ls, this.le) : null;
|
|
801
|
-
}
|
|
802
|
-
else {
|
|
803
|
-
return this.nextLine() ? this.text.substring(this.ls + 1, this.le + 1) : null;
|
|
804
|
-
}
|
|
805
|
-
}
|
|
806
|
-
/** Tests if the current line starts with the given search text */
|
|
807
|
-
lineStartsWith(searchString) {
|
|
808
|
-
return this.text.startsWith(searchString, this.ls);
|
|
809
|
-
}
|
|
810
|
-
/** Tests if the current line ends with the given search text */
|
|
811
|
-
lineEndsWith(searchString) {
|
|
812
|
-
return this.text.endsWith(searchString, this.le);
|
|
813
|
-
}
|
|
814
|
-
/**
|
|
815
|
-
* Returns the starting character of the next line without
|
|
816
|
-
* advancing the internal state. Returns null if advancing
|
|
817
|
-
* would mean reaching the end of the diff.
|
|
818
|
-
*/
|
|
819
|
-
peek() {
|
|
820
|
-
const p = this.le + 1;
|
|
821
|
-
return p < this.text.length ? this.text[p] : null;
|
|
822
|
-
}
|
|
823
|
-
/**
|
|
824
|
-
* Parse the diff header, meaning everything from the
|
|
825
|
-
* start of the diff output to the end of the line beginning
|
|
826
|
-
* with +++
|
|
827
|
-
*
|
|
828
|
-
* Example diff header:
|
|
829
|
-
*
|
|
830
|
-
* diff --git a/app/src/lib/diff-parser.ts b/app/src/lib/diff-parser.ts
|
|
831
|
-
* index e1d4871..3bd3ee0 100644
|
|
832
|
-
* --- a/app/src/lib/diff-parser.ts
|
|
833
|
-
* +++ b/app/src/lib/diff-parser.ts
|
|
834
|
-
*
|
|
835
|
-
* Returns an object with information extracted from the diff
|
|
836
|
-
* header (currently whether it's a binary patch) or null if
|
|
837
|
-
* the end of the diff was reached before the +++ line could be
|
|
838
|
-
* found (which is a valid state).
|
|
839
|
-
*/
|
|
840
|
-
parseDiffHeader() {
|
|
841
|
-
// TODO: There's information in here that we might want to
|
|
842
|
-
// capture, such as mode changes
|
|
843
|
-
while (this.nextLine()) {
|
|
844
|
-
if (this.lineStartsWith("Binary files ") && this.lineEndsWith("differ")) {
|
|
845
|
-
return { isBinary: true };
|
|
846
|
-
}
|
|
847
|
-
if (this.lineStartsWith("+++")) {
|
|
848
|
-
return { isBinary: false };
|
|
849
|
-
}
|
|
850
|
-
}
|
|
851
|
-
// It's not an error to not find the +++ line, see the
|
|
852
|
-
// 'parses diff of empty file' test in diff-parser-tests.ts
|
|
853
|
-
return null;
|
|
924
|
+
super(...arguments);
|
|
925
|
+
_Cache_keyArray.set(this, []);
|
|
926
|
+
_Cache_maxLength.set(this, 30);
|
|
854
927
|
}
|
|
855
|
-
|
|
856
|
-
|
|
857
|
-
|
|
858
|
-
* will return the value of the defaultValue parameter or throw
|
|
859
|
-
* an error if no default value was provided. If the captured
|
|
860
|
-
* string can't be converted to a number an error will be thrown.
|
|
861
|
-
*/
|
|
862
|
-
numberFromGroup(m, group, defaultValue = null) {
|
|
863
|
-
const str = m[group];
|
|
864
|
-
if (!str) {
|
|
865
|
-
if (!defaultValue) {
|
|
866
|
-
throw new Error(`Group ${group} missing from regexp match and no defaultValue was provided`);
|
|
867
|
-
}
|
|
868
|
-
return defaultValue;
|
|
869
|
-
}
|
|
870
|
-
const num = parseInt(str, 10);
|
|
871
|
-
if (isNaN(num)) {
|
|
872
|
-
throw new Error(`Could not parse capture group ${group} into number: ${str}`);
|
|
873
|
-
}
|
|
874
|
-
return num;
|
|
928
|
+
setMaxLength(length) {
|
|
929
|
+
__classPrivateFieldSet(this, _Cache_maxLength, length, "f");
|
|
930
|
+
this._checkLength();
|
|
875
931
|
}
|
|
876
|
-
|
|
877
|
-
|
|
878
|
-
|
|
879
|
-
|
|
880
|
-
|
|
881
|
-
|
|
882
|
-
|
|
883
|
-
|
|
884
|
-
|
|
885
|
-
|
|
886
|
-
|
|
887
|
-
* Where everything after the last @@ is what's known as the hunk, or section, heading
|
|
888
|
-
*/
|
|
889
|
-
parseHunkHeader(line) {
|
|
890
|
-
const m = diffHeaderRe.exec(line);
|
|
891
|
-
if (!m) {
|
|
892
|
-
throw new Error(`Invalid hunk header format`);
|
|
932
|
+
set(key, value) {
|
|
933
|
+
if (this.has(key))
|
|
934
|
+
return this;
|
|
935
|
+
__classPrivateFieldGet(this, _Cache_keyArray, "f").push(key);
|
|
936
|
+
this._checkLength();
|
|
937
|
+
return super.set(key, value);
|
|
938
|
+
}
|
|
939
|
+
_checkLength() {
|
|
940
|
+
while (__classPrivateFieldGet(this, _Cache_keyArray, "f").length > __classPrivateFieldGet(this, _Cache_maxLength, "f")) {
|
|
941
|
+
const key = __classPrivateFieldGet(this, _Cache_keyArray, "f").shift();
|
|
942
|
+
this.delete(key);
|
|
893
943
|
}
|
|
894
|
-
// If endLines are missing default to 1, see diffHeaderRe docs
|
|
895
|
-
const oldStartLine = this.numberFromGroup(m, 1);
|
|
896
|
-
const oldLineCount = this.numberFromGroup(m, 2, 1);
|
|
897
|
-
const newStartLine = this.numberFromGroup(m, 3);
|
|
898
|
-
const newLineCount = this.numberFromGroup(m, 4, 1);
|
|
899
|
-
return new DiffHunkHeader(oldStartLine, oldLineCount, newStartLine, newLineCount);
|
|
900
944
|
}
|
|
901
|
-
|
|
902
|
-
|
|
903
|
-
|
|
904
|
-
|
|
905
|
-
|
|
906
|
-
|
|
907
|
-
|
|
908
|
-
|
|
909
|
-
|
|
910
|
-
|
|
911
|
-
|
|
912
|
-
|
|
913
|
-
|
|
914
|
-
return c[0];
|
|
945
|
+
}
|
|
946
|
+
_Cache_keyArray = new WeakMap(), _Cache_maxLength = new WeakMap();
|
|
947
|
+
|
|
948
|
+
var _File_instances, _File_doCheck;
|
|
949
|
+
const map = new Cache();
|
|
950
|
+
const devKey = "@git-diff-cache";
|
|
951
|
+
map.setMaxLength(50);
|
|
952
|
+
map.name = "@git-diff-view/core";
|
|
953
|
+
if (typeof globalThis !== "undefined") {
|
|
954
|
+
if (Array.isArray(globalThis[devKey])) {
|
|
955
|
+
globalThis[devKey] = globalThis[devKey].filter((i) => i !== map);
|
|
956
|
+
if (globalThis[devKey].length > 0) {
|
|
957
|
+
console.warn("there are multiple instance of @git-diff-view/core in the one environment!");
|
|
915
958
|
}
|
|
916
|
-
|
|
959
|
+
globalThis[devKey].push(map);
|
|
917
960
|
}
|
|
918
|
-
|
|
919
|
-
|
|
920
|
-
|
|
921
|
-
|
|
922
|
-
|
|
923
|
-
|
|
924
|
-
|
|
925
|
-
|
|
926
|
-
|
|
927
|
-
|
|
928
|
-
|
|
929
|
-
|
|
930
|
-
|
|
931
|
-
|
|
932
|
-
|
|
933
|
-
|
|
934
|
-
|
|
935
|
-
|
|
961
|
+
else {
|
|
962
|
+
globalThis[devKey] = [map];
|
|
963
|
+
}
|
|
964
|
+
}
|
|
965
|
+
class File {
|
|
966
|
+
static createInstance(data) {
|
|
967
|
+
const file = new File(data === null || data === void 0 ? void 0 : data.raw, data === null || data === void 0 ? void 0 : data.lang, data === null || data === void 0 ? void 0 : data.fileName);
|
|
968
|
+
file.ast = data === null || data === void 0 ? void 0 : data.ast;
|
|
969
|
+
file.rawFile = data === null || data === void 0 ? void 0 : data.rawFile;
|
|
970
|
+
file.hasDoRaw = data === null || data === void 0 ? void 0 : data.hasDoRaw;
|
|
971
|
+
file.rawLength = data === null || data === void 0 ? void 0 : data.rawLength;
|
|
972
|
+
file.syntaxFile = data === null || data === void 0 ? void 0 : data.syntaxFile;
|
|
973
|
+
file.hasDoSyntax = data === null || data === void 0 ? void 0 : data.hasDoSyntax;
|
|
974
|
+
file.syntaxLength = data === null || data === void 0 ? void 0 : data.syntaxLength;
|
|
975
|
+
file.highlighterName = data === null || data === void 0 ? void 0 : data.highlighterName;
|
|
976
|
+
file.maxLineNumber = data === null || data === void 0 ? void 0 : data.maxLineNumber;
|
|
977
|
+
return file;
|
|
978
|
+
}
|
|
979
|
+
constructor(raw, lang, fileName) {
|
|
980
|
+
_File_instances.add(this);
|
|
981
|
+
this.raw = raw;
|
|
982
|
+
this.lang = lang;
|
|
983
|
+
this.fileName = fileName;
|
|
984
|
+
this.rawFile = {};
|
|
985
|
+
this.hasDoRaw = false;
|
|
986
|
+
this.syntaxFile = {};
|
|
987
|
+
this.hasDoSyntax = false;
|
|
988
|
+
this.maxLineNumber = 0;
|
|
989
|
+
Object.defineProperty(this, "__v_skip", { value: true });
|
|
990
|
+
}
|
|
991
|
+
doSyntax({ registerHighlighter }) {
|
|
992
|
+
if (!this.raw || this.hasDoSyntax)
|
|
993
|
+
return;
|
|
994
|
+
const _highlighter = registerHighlighter || highlighter;
|
|
995
|
+
if (this.syntaxLength) {
|
|
996
|
+
console.error("current file already doSyntax before!");
|
|
997
|
+
return;
|
|
936
998
|
}
|
|
937
|
-
|
|
938
|
-
|
|
939
|
-
|
|
940
|
-
let c;
|
|
941
|
-
let rollingDiffBeforeCounter = header.oldStartLine;
|
|
942
|
-
let rollingDiffAfterCounter = header.newStartLine;
|
|
943
|
-
let diffLineNumber = linesConsumed;
|
|
944
|
-
while ((c = this.parseLinePrefix(this.peek()))) {
|
|
945
|
-
const line = this.readLine(false);
|
|
946
|
-
diffLineNumber++;
|
|
947
|
-
if (!line) {
|
|
948
|
-
throw new Error("Expected unified diff line but reached end of diff");
|
|
949
|
-
}
|
|
950
|
-
// A marker indicating that the last line in the original or the new file
|
|
951
|
-
// is missing a trailing newline. In other words, the presence of this marker
|
|
952
|
-
// means that the new and/or original file lacks a trailing newline.
|
|
953
|
-
//
|
|
954
|
-
// When we find it we have to look up the previous line and set the
|
|
955
|
-
// noTrailingNewLine flag
|
|
956
|
-
if (c === DiffPrefixNoNewline) {
|
|
957
|
-
// See https://github.com/git/git/blob/21f862b498925194f8f1ebe8203b7a7df756555b/apply.c#L1725-L1732
|
|
958
|
-
if (line.length < 12) {
|
|
959
|
-
throw new Error(`Expected "no newline at end of file" marker to be at least 12 bytes long`);
|
|
960
|
-
}
|
|
961
|
-
const previousLineIndex = lines.length - 1;
|
|
962
|
-
const previousLine = lines[previousLineIndex];
|
|
963
|
-
lines[previousLineIndex] = previousLine.withNoTrailingNewLine(true);
|
|
964
|
-
continue;
|
|
965
|
-
}
|
|
966
|
-
let diffLine;
|
|
967
|
-
if (c === DiffPrefixAdd) {
|
|
968
|
-
diffLine = new DiffLine(line, exports.DiffLineType.Add, diffLineNumber, null, rollingDiffAfterCounter++);
|
|
969
|
-
}
|
|
970
|
-
else if (c === DiffPrefixDelete) {
|
|
971
|
-
diffLine = new DiffLine(line, exports.DiffLineType.Delete, diffLineNumber, rollingDiffBeforeCounter++, null);
|
|
972
|
-
}
|
|
973
|
-
else if (c === DiffPrefixContext) {
|
|
974
|
-
diffLine = new DiffLine(line, exports.DiffLineType.Context, diffLineNumber, rollingDiffBeforeCounter++, rollingDiffAfterCounter++);
|
|
975
|
-
}
|
|
976
|
-
else {
|
|
977
|
-
return assertNever(c, `Unknown DiffLinePrefix: ${c}`);
|
|
978
|
-
}
|
|
979
|
-
lines.push(diffLine);
|
|
999
|
+
if (this.rawLength > _highlighter.maxLineToIgnoreSyntax) {
|
|
1000
|
+
console.warn(`ignore syntax for current file, because the rawLength is too long: ${this.rawLength}`);
|
|
1001
|
+
return;
|
|
980
1002
|
}
|
|
981
|
-
|
|
982
|
-
|
|
1003
|
+
this.ast = _highlighter.getAST(this.raw, this.fileName, this.lang);
|
|
1004
|
+
if (!this.ast)
|
|
1005
|
+
return;
|
|
1006
|
+
const { syntaxFileObject, syntaxFileLineNumber } = _highlighter.processAST(this.ast);
|
|
1007
|
+
this.syntaxFile = syntaxFileObject;
|
|
1008
|
+
this.syntaxLength = syntaxFileLineNumber;
|
|
1009
|
+
this.highlighterName = _highlighter.name;
|
|
1010
|
+
{
|
|
1011
|
+
__classPrivateFieldGet(this, _File_instances, "m", _File_doCheck).call(this);
|
|
983
1012
|
}
|
|
984
|
-
|
|
1013
|
+
this.hasDoSyntax = true;
|
|
985
1014
|
}
|
|
986
|
-
|
|
987
|
-
|
|
988
|
-
|
|
989
|
-
|
|
990
|
-
|
|
991
|
-
|
|
992
|
-
|
|
993
|
-
|
|
994
|
-
|
|
995
|
-
|
|
996
|
-
const headerInfo = this.parseDiffHeader();
|
|
997
|
-
const headerEnd = this.le;
|
|
998
|
-
const header = this.text.substring(0, headerEnd);
|
|
999
|
-
// empty diff
|
|
1000
|
-
if (!headerInfo) {
|
|
1001
|
-
return {
|
|
1002
|
-
header,
|
|
1003
|
-
contents: "",
|
|
1004
|
-
hunks: [],
|
|
1005
|
-
isBinary: false,
|
|
1006
|
-
maxLineNumber: 0,
|
|
1007
|
-
hasHiddenBidiChars: false,
|
|
1008
|
-
};
|
|
1009
|
-
}
|
|
1010
|
-
if (headerInfo.isBinary) {
|
|
1011
|
-
return {
|
|
1012
|
-
header,
|
|
1013
|
-
contents: "",
|
|
1014
|
-
hunks: [],
|
|
1015
|
-
isBinary: true,
|
|
1016
|
-
maxLineNumber: 0,
|
|
1017
|
-
hasHiddenBidiChars: false,
|
|
1018
|
-
};
|
|
1019
|
-
}
|
|
1020
|
-
const hunks = new Array();
|
|
1021
|
-
let linesConsumed = 0;
|
|
1022
|
-
let previousHunk = null;
|
|
1023
|
-
do {
|
|
1024
|
-
const hunk = this.parseHunk(linesConsumed, hunks.length, previousHunk);
|
|
1025
|
-
hunks.push(hunk);
|
|
1026
|
-
previousHunk = hunk;
|
|
1027
|
-
linesConsumed += hunk.lines.length;
|
|
1028
|
-
} while (this.peek());
|
|
1029
|
-
const contents = this.text
|
|
1030
|
-
.substring(headerEnd + 1, this.le)
|
|
1031
|
-
// Note that this simply returns a reference to the
|
|
1032
|
-
// substring if no match is found, it does not create
|
|
1033
|
-
// a new string instance.
|
|
1034
|
-
.replace(/\n\/g, "");
|
|
1035
|
-
return {
|
|
1036
|
-
header,
|
|
1037
|
-
contents,
|
|
1038
|
-
hunks,
|
|
1039
|
-
isBinary: headerInfo.isBinary,
|
|
1040
|
-
maxLineNumber: getLargestLineNumber(hunks),
|
|
1041
|
-
hasHiddenBidiChars: HiddenBidiCharsRegex.test(text),
|
|
1042
|
-
};
|
|
1043
|
-
}
|
|
1044
|
-
finally {
|
|
1045
|
-
this.reset();
|
|
1015
|
+
doRaw() {
|
|
1016
|
+
if (!this.raw || this.hasDoRaw)
|
|
1017
|
+
return;
|
|
1018
|
+
const rawString = this.raw;
|
|
1019
|
+
const rawArray = rawString.split("\n");
|
|
1020
|
+
this.rawLength = rawArray.length;
|
|
1021
|
+
this.maxLineNumber = rawArray.length;
|
|
1022
|
+
this.rawFile = {};
|
|
1023
|
+
for (let i = 0; i < rawArray.length; i++) {
|
|
1024
|
+
this.rawFile[i + 1] = i < rawArray.length - 1 ? rawArray[i] + "\n" : rawArray[i];
|
|
1046
1025
|
}
|
|
1026
|
+
// reduce 对于大数组性能很差
|
|
1027
|
+
// this.rawFile = rawArray.reduce(
|
|
1028
|
+
// (p, item, index) => ({
|
|
1029
|
+
// ...p,
|
|
1030
|
+
// [index + 1]: index < rawArray.length - 1 ? item + "\n" : item,
|
|
1031
|
+
// }),
|
|
1032
|
+
// {}
|
|
1033
|
+
// );
|
|
1034
|
+
this.hasDoRaw = true;
|
|
1047
1035
|
}
|
|
1048
1036
|
}
|
|
1049
|
-
|
|
1037
|
+
_File_instances = new WeakSet(), _File_doCheck = function _File_doCheck() {
|
|
1038
|
+
if (this.rawLength && this.syntaxLength) {
|
|
1039
|
+
if (this.rawLength !== this.syntaxLength) {
|
|
1040
|
+
console.warn("the rawLength not match for the syntaxLength");
|
|
1041
|
+
}
|
|
1042
|
+
Object.values(this.syntaxFile).forEach(({ value, lineNumber }) => {
|
|
1043
|
+
if (value !== this.rawFile[lineNumber]) {
|
|
1044
|
+
console.log("some line not match:" + value + " __ " + this.rawFile[lineNumber] + " __ at: " + lineNumber + " lineNumber");
|
|
1045
|
+
}
|
|
1046
|
+
});
|
|
1047
|
+
}
|
|
1048
|
+
};
|
|
1049
|
+
const getFile = (raw, lang, fileName) => {
|
|
1050
|
+
const key = raw + "--" + "0.0.12" + "--" + lang;
|
|
1051
|
+
if (map.has(key))
|
|
1052
|
+
return map.get(key);
|
|
1053
|
+
const file = new File(raw, lang, fileName);
|
|
1054
|
+
map.set(key, file);
|
|
1055
|
+
return file;
|
|
1056
|
+
};
|
|
1057
|
+
const _cacheMap = map;
|
|
1050
1058
|
|
|
1051
|
-
|
|
1052
|
-
/* eslint-disable max-lines */
|
|
1053
|
-
var _DiffFile_instances, _DiffFile_oldFileResult, _DiffFile_newFileResult, _DiffFile_diffListResults, _DiffFile_diffLines, _DiffFile_oldFileDiffLines, _DiffFile_newFileDiffLines, _DiffFile_oldFileLines, _DiffFile_newFileLines, _DiffFile_oldFileSyntaxLines, _DiffFile_newFileSyntaxLines, _DiffFile_oldFilePlaceholderLines, _DiffFile_newFilePlaceholderLines, _DiffFile_splitLeftLines, _DiffFile_splitRightLines, _DiffFile_splitHunksLines, _DiffFile_unifiedLines, _DiffFile_unifiedHunksLines, _DiffFile_listeners, _DiffFile_hasInitRaw, _DiffFile_hasInitSyntax, _DiffFile_hasBuildSplit, _DiffFile_hasBuildUnified, _DiffFile_updateCount, _DiffFile_composeByDiff, _DiffFile_highlighterName, _DiffFile_id, _DiffFile_clonedInstance, _DiffFile_doDiff, _DiffFile_doFile, _DiffFile_composeRaw, _DiffFile_composeFile, _DiffFile_composeDiff, _DiffFile_composeSyntax, _DiffFile_getOldDiffLine, _DiffFile_getNewDiffLine, _DiffFile_getOldRawLine, _DiffFile_getNewRawLine;
|
|
1059
|
+
var _DiffFile_instances, _DiffFile_oldFileResult, _DiffFile_newFileResult, _DiffFile_diffListResults, _DiffFile_diffLines, _DiffFile_oldFileDiffLines, _DiffFile_newFileDiffLines, _DiffFile_oldFileLines, _DiffFile_newFileLines, _DiffFile_oldFileSyntaxLines, _DiffFile_newFileSyntaxLines, _DiffFile_oldFilePlaceholderLines, _DiffFile_newFilePlaceholderLines, _DiffFile_splitLeftLines, _DiffFile_splitRightLines, _DiffFile_splitHunksLines, _DiffFile_unifiedLines, _DiffFile_unifiedHunksLines, _DiffFile_listeners, _DiffFile_hasInitRaw, _DiffFile_hasInitSyntax, _DiffFile_hasBuildSplit, _DiffFile_hasBuildUnified, _DiffFile_updateCount, _DiffFile_composeByDiff, _DiffFile_composeByMerge, _DiffFile_composeByFullMerge, _DiffFile_highlighterName, _DiffFile_id, _DiffFile_clonedInstance, _DiffFile_doDiff, _DiffFile_doFile, _DiffFile_composeRaw, _DiffFile_composeFile, _DiffFile_composeDiff, _DiffFile_composeSyntax, _DiffFile_getOldDiffLine, _DiffFile_getNewDiffLine, _DiffFile_getOldRawLine, _DiffFile_getNewRawLine;
|
|
1054
1060
|
const composeLen = 40;
|
|
1055
1061
|
const idSet = new Set();
|
|
1056
1062
|
class DiffFile {
|
|
@@ -1058,7 +1064,12 @@ class DiffFile {
|
|
|
1058
1064
|
var _a, _b, _c, _d, _e, _f;
|
|
1059
1065
|
const instance = new DiffFile(((_a = data === null || data === void 0 ? void 0 : data.oldFile) === null || _a === void 0 ? void 0 : _a.fileName) || "", ((_b = data === null || data === void 0 ? void 0 : data.oldFile) === null || _b === void 0 ? void 0 : _b.content) || "", ((_c = data === null || data === void 0 ? void 0 : data.newFile) === null || _c === void 0 ? void 0 : _c.fileName) || "", ((_d = data === null || data === void 0 ? void 0 : data.newFile) === null || _d === void 0 ? void 0 : _d.content) || "", (data === null || data === void 0 ? void 0 : data.hunks) || [], ((_e = data === null || data === void 0 ? void 0 : data.oldFile) === null || _e === void 0 ? void 0 : _e.fileLang) || "", ((_f = data === null || data === void 0 ? void 0 : data.newFile) === null || _f === void 0 ? void 0 : _f.fileLang) || "");
|
|
1060
1066
|
if (bundle) {
|
|
1061
|
-
|
|
1067
|
+
if (bundle.isFullMerge) {
|
|
1068
|
+
instance._mergeFullBundle(bundle);
|
|
1069
|
+
}
|
|
1070
|
+
else {
|
|
1071
|
+
instance.mergeBundle(bundle);
|
|
1072
|
+
}
|
|
1062
1073
|
}
|
|
1063
1074
|
return instance;
|
|
1064
1075
|
}
|
|
@@ -1091,8 +1102,10 @@ class DiffFile {
|
|
|
1091
1102
|
_DiffFile_hasBuildUnified.set(this, false);
|
|
1092
1103
|
_DiffFile_updateCount.set(this, 0);
|
|
1093
1104
|
_DiffFile_composeByDiff.set(this, false);
|
|
1105
|
+
_DiffFile_composeByMerge.set(this, false);
|
|
1106
|
+
_DiffFile_composeByFullMerge.set(this, false);
|
|
1094
1107
|
_DiffFile_highlighterName.set(this, void 0);
|
|
1095
|
-
this._version_ = "0.0.
|
|
1108
|
+
this._version_ = "0.0.12";
|
|
1096
1109
|
this._oldFileContent = "";
|
|
1097
1110
|
this._oldFileLang = "";
|
|
1098
1111
|
this._newFileContent = "";
|
|
@@ -1100,9 +1113,9 @@ class DiffFile {
|
|
|
1100
1113
|
this.diffLineLength = 0;
|
|
1101
1114
|
this.splitLineLength = 0;
|
|
1102
1115
|
this.unifiedLineLength = 0;
|
|
1103
|
-
this.
|
|
1104
|
-
this.
|
|
1105
|
-
this.
|
|
1116
|
+
this.hasExpandSplitAll = false;
|
|
1117
|
+
this.hasExpandUnifiedAll = false;
|
|
1118
|
+
this.hasSomeLineCollapsed = false;
|
|
1106
1119
|
_DiffFile_id.set(this, "");
|
|
1107
1120
|
_DiffFile_clonedInstance.set(this, new Map());
|
|
1108
1121
|
this.getSplitLeftLine = (index) => {
|
|
@@ -1241,13 +1254,13 @@ class DiffFile {
|
|
|
1241
1254
|
Object.keys(__classPrivateFieldGet(this, _DiffFile_splitHunksLines, "f") || {}).forEach((key) => {
|
|
1242
1255
|
this.onSplitHunkExpand("all", +key, false);
|
|
1243
1256
|
});
|
|
1244
|
-
this.
|
|
1257
|
+
this.hasExpandSplitAll = true;
|
|
1245
1258
|
}
|
|
1246
1259
|
else {
|
|
1247
1260
|
Object.keys(__classPrivateFieldGet(this, _DiffFile_unifiedHunksLines, "f") || {}).forEach((key) => {
|
|
1248
1261
|
this.onUnifiedHunkExpand("all", +key, false);
|
|
1249
1262
|
});
|
|
1250
|
-
this.
|
|
1263
|
+
this.hasExpandUnifiedAll = true;
|
|
1251
1264
|
}
|
|
1252
1265
|
this.notifyAll();
|
|
1253
1266
|
};
|
|
@@ -1279,7 +1292,7 @@ class DiffFile {
|
|
|
1279
1292
|
__classPrivateFieldGet(this, _DiffFile_splitHunksLines, "f")[item.splitInfo.endHiddenIndex] = item;
|
|
1280
1293
|
}
|
|
1281
1294
|
});
|
|
1282
|
-
this.
|
|
1295
|
+
this.hasExpandSplitAll = false;
|
|
1283
1296
|
}
|
|
1284
1297
|
else {
|
|
1285
1298
|
Object.values(__classPrivateFieldGet(this, _DiffFile_unifiedLines, "f") || {}).forEach((item) => {
|
|
@@ -1301,7 +1314,7 @@ class DiffFile {
|
|
|
1301
1314
|
__classPrivateFieldGet(this, _DiffFile_unifiedHunksLines, "f")[item.unifiedInfo.endHiddenIndex] = item;
|
|
1302
1315
|
}
|
|
1303
1316
|
});
|
|
1304
|
-
this.
|
|
1317
|
+
this.hasExpandUnifiedAll = false;
|
|
1305
1318
|
}
|
|
1306
1319
|
this.notifyAll();
|
|
1307
1320
|
};
|
|
@@ -1353,7 +1366,7 @@ class DiffFile {
|
|
|
1353
1366
|
const unifiedLineLength = this.unifiedLineLength;
|
|
1354
1367
|
const composeByDiff = __classPrivateFieldGet(this, _DiffFile_composeByDiff, "f");
|
|
1355
1368
|
const highlighterName = __classPrivateFieldGet(this, _DiffFile_highlighterName, "f");
|
|
1356
|
-
const
|
|
1369
|
+
const hasSomeLineCollapsed = this.hasSomeLineCollapsed;
|
|
1357
1370
|
// split
|
|
1358
1371
|
const splitLeftLines = __classPrivateFieldGet(this, _DiffFile_splitLeftLines, "f");
|
|
1359
1372
|
const splitRightLines = __classPrivateFieldGet(this, _DiffFile_splitRightLines, "f");
|
|
@@ -1384,8 +1397,9 @@ class DiffFile {
|
|
|
1384
1397
|
unifiedHunkLines,
|
|
1385
1398
|
highlighterName,
|
|
1386
1399
|
composeByDiff,
|
|
1387
|
-
|
|
1400
|
+
hasSomeLineCollapsed,
|
|
1388
1401
|
version,
|
|
1402
|
+
isFullMerge: false,
|
|
1389
1403
|
};
|
|
1390
1404
|
};
|
|
1391
1405
|
this.mergeBundle = (data) => {
|
|
@@ -1405,12 +1419,14 @@ class DiffFile {
|
|
|
1405
1419
|
__classPrivateFieldSet(this, _DiffFile_newFilePlaceholderLines, data.newFilePlaceholderLines, "f");
|
|
1406
1420
|
this.splitLineLength = data.splitLineLength;
|
|
1407
1421
|
this.unifiedLineLength = data.unifiedLineLength;
|
|
1408
|
-
this.
|
|
1422
|
+
this.hasSomeLineCollapsed = data.hasSomeLineCollapsed;
|
|
1409
1423
|
__classPrivateFieldSet(this, _DiffFile_splitLeftLines, data.splitLeftLines, "f");
|
|
1410
1424
|
__classPrivateFieldSet(this, _DiffFile_splitRightLines, data.splitRightLines, "f");
|
|
1411
1425
|
__classPrivateFieldSet(this, _DiffFile_splitHunksLines, data.splitHunkLines, "f");
|
|
1412
1426
|
__classPrivateFieldSet(this, _DiffFile_unifiedLines, data.unifiedLines, "f");
|
|
1413
1427
|
__classPrivateFieldSet(this, _DiffFile_unifiedHunksLines, data.unifiedHunkLines, "f");
|
|
1428
|
+
// mark this instance as a merged instance
|
|
1429
|
+
__classPrivateFieldSet(this, _DiffFile_composeByMerge, true, "f");
|
|
1414
1430
|
if (this._version_ !== data.version) {
|
|
1415
1431
|
console.error("the version of the `diffInstance` is not match, some error may happen!");
|
|
1416
1432
|
}
|
|
@@ -1447,14 +1463,21 @@ class DiffFile {
|
|
|
1447
1463
|
return Object.assign(Object.assign({}, bundle), { oldFileResult,
|
|
1448
1464
|
newFileResult,
|
|
1449
1465
|
diffLines,
|
|
1450
|
-
diffListResults
|
|
1466
|
+
diffListResults,
|
|
1467
|
+
// get current instance is a fullMerge instance or not
|
|
1468
|
+
isFullMerge: __classPrivateFieldGet(this, _DiffFile_composeByMerge, "f") ? __classPrivateFieldGet(this, _DiffFile_composeByFullMerge, "f") : true });
|
|
1451
1469
|
};
|
|
1452
1470
|
this._mergeFullBundle = (data) => {
|
|
1453
1471
|
this.mergeBundle(data);
|
|
1454
|
-
|
|
1455
|
-
|
|
1456
|
-
|
|
1457
|
-
|
|
1472
|
+
try {
|
|
1473
|
+
__classPrivateFieldSet(this, _DiffFile_oldFileResult, File.createInstance(data.oldFileResult), "f");
|
|
1474
|
+
__classPrivateFieldSet(this, _DiffFile_newFileResult, File.createInstance(data.newFileResult), "f");
|
|
1475
|
+
__classPrivateFieldSet(this, _DiffFile_diffLines, data.diffLines, "f");
|
|
1476
|
+
__classPrivateFieldSet(this, _DiffFile_diffListResults, data.diffListResults, "f");
|
|
1477
|
+
__classPrivateFieldSet(this, _DiffFile_composeByFullMerge, data.isFullMerge, "f");
|
|
1478
|
+
}
|
|
1479
|
+
catch (_a) {
|
|
1480
|
+
}
|
|
1458
1481
|
};
|
|
1459
1482
|
this._destroy = () => {
|
|
1460
1483
|
this.clearId();
|
|
@@ -1529,6 +1552,10 @@ class DiffFile {
|
|
|
1529
1552
|
var _a, _b;
|
|
1530
1553
|
if (__classPrivateFieldGet(this, _DiffFile_hasInitSyntax, "f"))
|
|
1531
1554
|
return;
|
|
1555
|
+
if (__classPrivateFieldGet(this, _DiffFile_composeByMerge, "f") && !__classPrivateFieldGet(this, _DiffFile_composeByFullMerge, "f")) {
|
|
1556
|
+
console.error(`this instance can not do syntax because of the data missing, try to use '_getFullBundle' & '_mergeFullBundle' instead of 'getBundle' & 'mergeBundle'`);
|
|
1557
|
+
return;
|
|
1558
|
+
}
|
|
1532
1559
|
__classPrivateFieldGet(this, _DiffFile_instances, "m", _DiffFile_composeSyntax).call(this, { registerHighlighter });
|
|
1533
1560
|
__classPrivateFieldSet(this, _DiffFile_highlighterName, ((_a = __classPrivateFieldGet(this, _DiffFile_oldFileResult, "f")) === null || _a === void 0 ? void 0 : _a.highlighterName) || ((_b = __classPrivateFieldGet(this, _DiffFile_newFileResult, "f")) === null || _b === void 0 ? void 0 : _b.highlighterName) || __classPrivateFieldGet(this, _DiffFile_highlighterName, "f"), "f");
|
|
1534
1561
|
__classPrivateFieldSet(this, _DiffFile_hasInitSyntax, true, "f");
|
|
@@ -1631,7 +1658,7 @@ class DiffFile {
|
|
|
1631
1658
|
hideStart = len;
|
|
1632
1659
|
}
|
|
1633
1660
|
if (isHidden) {
|
|
1634
|
-
this.
|
|
1661
|
+
this.hasSomeLineCollapsed = true;
|
|
1635
1662
|
}
|
|
1636
1663
|
prevIsHidden = isHidden;
|
|
1637
1664
|
if (oldDiffLine && newDiffLine && !oldLineHasChange && !newLineHasChange) {
|
|
@@ -1762,7 +1789,7 @@ class DiffFile {
|
|
|
1762
1789
|
hideStart = len;
|
|
1763
1790
|
}
|
|
1764
1791
|
if (isHidden) {
|
|
1765
|
-
this.
|
|
1792
|
+
this.hasSomeLineCollapsed = true;
|
|
1766
1793
|
}
|
|
1767
1794
|
prevIsHidden = isHidden;
|
|
1768
1795
|
if (oldDiffLine && newDiffLine && !oldLineHasChange && !newLineHasChange) {
|
|
@@ -1808,7 +1835,7 @@ class DiffFile {
|
|
|
1808
1835
|
this.notifyAll();
|
|
1809
1836
|
}
|
|
1810
1837
|
}
|
|
1811
|
-
_DiffFile_oldFileResult = new WeakMap(), _DiffFile_newFileResult = new WeakMap(), _DiffFile_diffListResults = new WeakMap(), _DiffFile_diffLines = new WeakMap(), _DiffFile_oldFileDiffLines = new WeakMap(), _DiffFile_newFileDiffLines = new WeakMap(), _DiffFile_oldFileLines = new WeakMap(), _DiffFile_newFileLines = new WeakMap(), _DiffFile_oldFileSyntaxLines = new WeakMap(), _DiffFile_newFileSyntaxLines = new WeakMap(), _DiffFile_oldFilePlaceholderLines = new WeakMap(), _DiffFile_newFilePlaceholderLines = new WeakMap(), _DiffFile_splitLeftLines = new WeakMap(), _DiffFile_splitRightLines = new WeakMap(), _DiffFile_splitHunksLines = new WeakMap(), _DiffFile_unifiedLines = new WeakMap(), _DiffFile_unifiedHunksLines = new WeakMap(), _DiffFile_listeners = new WeakMap(), _DiffFile_hasInitRaw = new WeakMap(), _DiffFile_hasInitSyntax = new WeakMap(), _DiffFile_hasBuildSplit = new WeakMap(), _DiffFile_hasBuildUnified = new WeakMap(), _DiffFile_updateCount = new WeakMap(), _DiffFile_composeByDiff = new WeakMap(), _DiffFile_highlighterName = new WeakMap(), _DiffFile_id = new WeakMap(), _DiffFile_clonedInstance = new WeakMap(), _DiffFile_instances = new WeakSet(), _DiffFile_doDiff = function _DiffFile_doDiff() {
|
|
1838
|
+
_DiffFile_oldFileResult = new WeakMap(), _DiffFile_newFileResult = new WeakMap(), _DiffFile_diffListResults = new WeakMap(), _DiffFile_diffLines = new WeakMap(), _DiffFile_oldFileDiffLines = new WeakMap(), _DiffFile_newFileDiffLines = new WeakMap(), _DiffFile_oldFileLines = new WeakMap(), _DiffFile_newFileLines = new WeakMap(), _DiffFile_oldFileSyntaxLines = new WeakMap(), _DiffFile_newFileSyntaxLines = new WeakMap(), _DiffFile_oldFilePlaceholderLines = new WeakMap(), _DiffFile_newFilePlaceholderLines = new WeakMap(), _DiffFile_splitLeftLines = new WeakMap(), _DiffFile_splitRightLines = new WeakMap(), _DiffFile_splitHunksLines = new WeakMap(), _DiffFile_unifiedLines = new WeakMap(), _DiffFile_unifiedHunksLines = new WeakMap(), _DiffFile_listeners = new WeakMap(), _DiffFile_hasInitRaw = new WeakMap(), _DiffFile_hasInitSyntax = new WeakMap(), _DiffFile_hasBuildSplit = new WeakMap(), _DiffFile_hasBuildUnified = new WeakMap(), _DiffFile_updateCount = new WeakMap(), _DiffFile_composeByDiff = new WeakMap(), _DiffFile_composeByMerge = new WeakMap(), _DiffFile_composeByFullMerge = new WeakMap(), _DiffFile_highlighterName = new WeakMap(), _DiffFile_id = new WeakMap(), _DiffFile_clonedInstance = new WeakMap(), _DiffFile_instances = new WeakSet(), _DiffFile_doDiff = function _DiffFile_doDiff() {
|
|
1812
1839
|
if (!this._diffList)
|
|
1813
1840
|
return;
|
|
1814
1841
|
__classPrivateFieldSet(this, _DiffFile_diffListResults, this._diffList.map((s) => parseInstance.parse(s)), "f");
|
|
@@ -2122,7 +2149,7 @@ const getUnifiedContentLine = (diffFile) => {
|
|
|
2122
2149
|
return lines.filter((line) => line.type === exports.DiffFileLineType.content);
|
|
2123
2150
|
};
|
|
2124
2151
|
|
|
2125
|
-
const versions = "0.0.
|
|
2152
|
+
const versions = "0.0.12";
|
|
2126
2153
|
|
|
2127
2154
|
const useUnmount = (cb, deps) => {
|
|
2128
2155
|
const ref = React.useRef(cb);
|
|
@@ -3565,7 +3592,7 @@ const _InternalDiffView = (props) => {
|
|
|
3565
3592
|
]);
|
|
3566
3593
|
const value = React.useMemo(() => ({ useDiffContext }), [useDiffContext]);
|
|
3567
3594
|
return (React__namespace.createElement(DiffViewContext.Provider, { value: value },
|
|
3568
|
-
React__namespace.createElement("div", { className: "diff-tailwindcss-wrapper", "data-component": "git-diff-view", "data-version": `${"0.0.
|
|
3595
|
+
React__namespace.createElement("div", { className: "diff-tailwindcss-wrapper", "data-component": "git-diff-view", "data-version": `${"0.0.12"}`, "data-highlighter": diffFile._getHighlighterName() },
|
|
3569
3596
|
React__namespace.createElement("div", { className: "diff-style-root", style: {
|
|
3570
3597
|
// @ts-ignore
|
|
3571
3598
|
[diffFontSizeName]: diffViewFontSize + "px",
|
|
@@ -3618,14 +3645,18 @@ const DiffViewWithRef = (props, ref) => {
|
|
|
3618
3645
|
};
|
|
3619
3646
|
const DiffView = React.forwardRef(DiffViewWithRef);
|
|
3620
3647
|
DiffView.displayName = "DiffView";
|
|
3621
|
-
const version = "0.0.
|
|
3648
|
+
const version = "0.0.12";
|
|
3622
3649
|
|
|
3623
3650
|
exports.DefaultDiffExpansionStep = DefaultDiffExpansionStep;
|
|
3624
3651
|
exports.DiffFile = DiffFile;
|
|
3652
|
+
exports.DiffHunk = DiffHunk;
|
|
3653
|
+
exports.DiffHunkHeader = DiffHunkHeader;
|
|
3625
3654
|
exports.DiffLine = DiffLine;
|
|
3655
|
+
exports.DiffParser = DiffParser;
|
|
3626
3656
|
exports.DiffView = DiffView;
|
|
3627
3657
|
exports.DiffViewContext = DiffViewContext;
|
|
3628
3658
|
exports.File = File;
|
|
3659
|
+
exports.HiddenBidiCharsRegex = HiddenBidiCharsRegex;
|
|
3629
3660
|
exports._cacheMap = _cacheMap;
|
|
3630
3661
|
exports.assertNever = assertNever;
|
|
3631
3662
|
exports.checkDiffLineIncludeChange = checkDiffLineIncludeChange;
|
|
@@ -3643,6 +3674,7 @@ exports.getUnifiedLines = getUnifiedLines;
|
|
|
3643
3674
|
exports.hasRelativeChange = hasRelativeChange;
|
|
3644
3675
|
exports.highlighter = highlighter;
|
|
3645
3676
|
exports.numIterator = numIterator;
|
|
3677
|
+
exports.parseInstance = parseInstance;
|
|
3646
3678
|
exports.processAST = processAST;
|
|
3647
3679
|
exports.relativeChanges = relativeChanges;
|
|
3648
3680
|
exports.useDiffViewContext = useDiffViewContext;
|