codekingpro/portable-devtools
114k
1"use strict";
2var __assign = (this && this.__assign) || function () {
3 __assign = Object.assign || function(t) {
4 for (var s, i = 1, n = arguments.length; i < n; i++) {
5 s = arguments[i];
6 for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
7 t[p] = s[p];
8 }
9 return t;
10 };
11 return __assign.apply(this, arguments);
12};
13Object.defineProperty(exports, "__esModule", { value: true });
14exports.OMIT_HEADERS = exports.FILE_HEADERS_ONLY = exports.INCLUDE_HEADERS = void 0;
15exports.structuredPatch = structuredPatch;
16exports.formatPatch = formatPatch;
17exports.createTwoFilesPatch = createTwoFilesPatch;
18exports.createPatch = createPatch;
19var line_js_1 = require("../diff/line.js");
20exports.INCLUDE_HEADERS = {
21 includeIndex: true,
22 includeUnderline: true,
23 includeFileHeaders: true
24};
25exports.FILE_HEADERS_ONLY = {
26 includeIndex: false,
27 includeUnderline: false,
28 includeFileHeaders: true
29};
30exports.OMIT_HEADERS = {
31 includeIndex: false,
32 includeUnderline: false,
33 includeFileHeaders: false
34};
35function structuredPatch(oldFileName, newFileName, oldStr, newStr, oldHeader, newHeader, options) {
36 var optionsObj;
37 if (!options) {
38 optionsObj = {};
39 }
40 else if (typeof options === 'function') {
41 optionsObj = { callback: options };
42 }
43 else {
44 optionsObj = options;
45 }
46 if (typeof optionsObj.context === 'undefined') {
47 optionsObj.context = 4;
48 }
49 // We copy this into its own variable to placate TypeScript, which thinks
50 // optionsObj.context might be undefined in the callbacks below.
51 var context = optionsObj.context;
52 // @ts-expect-error (runtime check for something that is correctly a static type error)
53 if (optionsObj.newlineIsToken) {
54 throw new Error('newlineIsToken may not be used with patch-generation functions, only with diffing functions');
55 }
56 if (!optionsObj.callback) {
57 return diffLinesResultToPatch((0, line_js_1.diffLines)(oldStr, newStr, optionsObj));
58 }
59 else {
60 var callback_1 = optionsObj.callback;
61 (0, line_js_1.diffLines)(oldStr, newStr, __assign(__assign({}, optionsObj), { callback: function (diff) {
62 var patch = diffLinesResultToPatch(diff);
63 // TypeScript is unhappy without the cast because it does not understand that `patch` may
64 // be undefined here only if `callback` is StructuredPatchCallbackAbortable:
65 callback_1(patch);
66 } }));
67 }
68 function diffLinesResultToPatch(diff) {
69 // STEP 1: Build up the patch with no "\ No newline at end of file" lines and with the arrays
70 // of lines containing trailing newline characters. We'll tidy up later...
71 if (!diff) {
72 return;
73 }
74 diff.push({ value: '', lines: [] }); // Append an empty value to make cleanup easier
75 function contextLines(lines) {
76 return lines.map(function (entry) { return ' ' + entry; });
77 }
78 var hunks = [];
79 var oldRangeStart = 0, newRangeStart = 0, curRange = [], oldLine = 1, newLine = 1;
80 for (var i = 0; i < diff.length; i++) {
81 var current = diff[i], lines = current.lines || splitLines(current.value);
82 current.lines = lines;
83 if (current.added || current.removed) {
84 // If we have previous context, start with that
85 if (!oldRangeStart) {
86 var prev = diff[i - 1];
87 oldRangeStart = oldLine;
88 newRangeStart = newLine;
89 if (prev) {
90 curRange = context > 0 ? contextLines(prev.lines.slice(-context)) : [];
91 oldRangeStart -= curRange.length;
92 newRangeStart -= curRange.length;
93 }
94 }
95 // Output our changes
96 for (var _i = 0, lines_1 = lines; _i < lines_1.length; _i++) {
97 var line = lines_1[_i];
98 curRange.push((current.added ? '+' : '-') + line);
99 }
100 // Track the updated file position
101 if (current.added) {
102 newLine += lines.length;
103 }
104 else {
105 oldLine += lines.length;
106 }
107 }
108 else {
109 // Identical context lines. Track line changes
110 if (oldRangeStart) {
111 // Close out any changes that have been output (or join overlapping)
112 if (lines.length <= context * 2 && i < diff.length - 2) {
113 // Overlapping
114 for (var _a = 0, _b = contextLines(lines); _a < _b.length; _a++) {
115 var line = _b[_a];
116 curRange.push(line);
117 }
118 }
119 else {
120 // end the range and output
121 var contextSize = Math.min(lines.length, context);
122 for (var _c = 0, _d = contextLines(lines.slice(0, contextSize)); _c < _d.length; _c++) {
123 var line = _d[_c];
124 curRange.push(line);
125 }
126 var hunk = {
127 oldStart: oldRangeStart,
128 oldLines: (oldLine - oldRangeStart + contextSize),
129 newStart: newRangeStart,
130 newLines: (newLine - newRangeStart + contextSize),
131 lines: curRange
132 };
133 hunks.push(hunk);
134 oldRangeStart = 0;
135 newRangeStart = 0;
136 curRange = [];
137 }
138 }
139 oldLine += lines.length;
140 newLine += lines.length;
141 }
142 }
143 // Step 2: eliminate the trailing `\n` from each line of each hunk, and, where needed, add
144 // "\ No newline at end of file".
145 for (var _e = 0, hunks_1 = hunks; _e < hunks_1.length; _e++) {
146 var hunk = hunks_1[_e];
147 for (var i = 0; i < hunk.lines.length; i++) {
148 if (hunk.lines[i].endsWith('\n')) {
149 hunk.lines[i] = hunk.lines[i].slice(0, -1);
150 }
151 else {
152 hunk.lines.splice(i + 1, 0, '\\ No newline at end of file');
153 i++; // Skip the line we just added, then continue iterating
154 }
155 }
156 }
157 return {
158 oldFileName: oldFileName, newFileName: newFileName,
159 oldHeader: oldHeader, newHeader: newHeader,
160 hunks: hunks
161 };
162 }
163}
164/**
165 * creates a unified diff patch.
166 * @param patch either a single structured patch object (as returned by `structuredPatch`) or an array of them (as returned by `parsePatch`)
167 */
168function formatPatch(patch, headerOptions) {
169 if (!headerOptions) {
170 headerOptions = exports.INCLUDE_HEADERS;
171 }
172 if (Array.isArray(patch)) {
173 if (patch.length > 1 && !headerOptions.includeFileHeaders) {
174 throw new Error('Cannot omit file headers on a multi-file patch. '
175 + '(The result would be unparseable; how would a tool trying to apply '
176 + 'the patch know which changes are to which file?)');
177 }
178 return patch.map(function (p) { return formatPatch(p, headerOptions); }).join('\n');
179 }
180 var ret = [];
181 if (headerOptions.includeIndex && patch.oldFileName == patch.newFileName) {
182 ret.push('Index: ' + patch.oldFileName);
183 }
184 if (headerOptions.includeUnderline) {
185 ret.push('===================================================================');
186 }
187 if (headerOptions.includeFileHeaders) {
188 ret.push('--- ' + patch.oldFileName + (typeof patch.oldHeader === 'undefined' ? '' : '\t' + patch.oldHeader));
189 ret.push('+++ ' + patch.newFileName + (typeof patch.newHeader === 'undefined' ? '' : '\t' + patch.newHeader));
190 }
191 for (var i = 0; i < patch.hunks.length; i++) {
192 var hunk = patch.hunks[i];
193 // Unified Diff Format quirk: If the chunk size is 0,
194 // the first number is one lower than one would expect.
195 // https://www.artima.com/weblogs/viewpost.jsp?thread=164293
196 if (hunk.oldLines === 0) {
197 hunk.oldStart -= 1;
198 }
199 if (hunk.newLines === 0) {
200 hunk.newStart -= 1;
201 }
202 ret.push('@@ -' + hunk.oldStart + ',' + hunk.oldLines
203 + ' +' + hunk.newStart + ',' + hunk.newLines
204 + ' @@');
205 for (var _i = 0, _a = hunk.lines; _i < _a.length; _i++) {
206 var line = _a[_i];
207 ret.push(line);
208 }
209 }
210 return ret.join('\n') + '\n';
211}
212function createTwoFilesPatch(oldFileName, newFileName, oldStr, newStr, oldHeader, newHeader, options) {
213 if (typeof options === 'function') {
214 options = { callback: options };
215 }
216 if (!(options === null || options === void 0 ? void 0 : options.callback)) {
217 var patchObj = structuredPatch(oldFileName, newFileName, oldStr, newStr, oldHeader, newHeader, options);
218 if (!patchObj) {
219 return;
220 }
221 return formatPatch(patchObj, options === null || options === void 0 ? void 0 : options.headerOptions);
222 }
223 else {
224 var callback_2 = options.callback;
225 structuredPatch(oldFileName, newFileName, oldStr, newStr, oldHeader, newHeader, __assign(__assign({}, options), { callback: function (patchObj) {
226 if (!patchObj) {
227 callback_2(undefined);
228 }
229 else {
230 callback_2(formatPatch(patchObj, options.headerOptions));
231 }
232 } }));
233 }
234}
235function createPatch(fileName, oldStr, newStr, oldHeader, newHeader, options) {
236 return createTwoFilesPatch(fileName, fileName, oldStr, newStr, oldHeader, newHeader, options);
237}
238/**
239 * Split `text` into an array of lines, including the trailing newline character (where present)
240 */
241function splitLines(text) {
242 var hasTrailingNl = text.endsWith('\n');
243 var result = text.split('\n').map(function (line) { return line + '\n'; });
244 if (hasTrailingNl) {
245 result.pop();
246 }
247 else {
248 result.push(result.pop().slice(0, -1));
249 }
250 return result;
251}
252 