1 | var __assign = (this && this.__assign) || function () {
|
2 | __assign = Object.assign || function(t) {
|
3 | for (var s, i = 1, n = arguments.length; i < n; i++) {
|
4 | s = arguments[i];
|
5 | for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
|
6 | t[p] = s[p];
|
7 | }
|
8 | return t;
|
9 | };
|
10 | return __assign.apply(this, arguments);
|
11 | };
|
12 | import * as jsDiff from 'diff';
|
13 | import { unifyPath, hashCode } from './utils';
|
14 | import * as rematch from './rematch';
|
15 | import { LineMatchingType, DiffStyleType, LineType } from './types';
|
16 | export var CSSLineClass = {
|
17 | INSERTS: 'd2h-ins',
|
18 | DELETES: 'd2h-del',
|
19 | CONTEXT: 'd2h-cntx',
|
20 | INFO: 'd2h-info',
|
21 | INSERT_CHANGES: 'd2h-ins d2h-change',
|
22 | DELETE_CHANGES: 'd2h-del d2h-change',
|
23 | };
|
24 | export var defaultRenderConfig = {
|
25 | matching: LineMatchingType.NONE,
|
26 | matchWordsThreshold: 0.25,
|
27 | maxLineLengthHighlight: 10000,
|
28 | diffStyle: DiffStyleType.WORD,
|
29 | };
|
30 | var separator = '/';
|
31 | var distance = rematch.newDistanceFn(function (change) { return change.value; });
|
32 | var matcher = rematch.newMatcherFn(distance);
|
33 | function isDevNullName(name) {
|
34 | return name.indexOf('dev/null') !== -1;
|
35 | }
|
36 | function removeInsElements(line) {
|
37 | return line.replace(/(<ins[^>]*>((.|\n)*?)<\/ins>)/g, '');
|
38 | }
|
39 | function removeDelElements(line) {
|
40 | return line.replace(/(<del[^>]*>((.|\n)*?)<\/del>)/g, '');
|
41 | }
|
42 | export function toCSSClass(lineType) {
|
43 | switch (lineType) {
|
44 | case LineType.CONTEXT:
|
45 | return CSSLineClass.CONTEXT;
|
46 | case LineType.INSERT:
|
47 | return CSSLineClass.INSERTS;
|
48 | case LineType.DELETE:
|
49 | return CSSLineClass.DELETES;
|
50 | }
|
51 | }
|
52 | function prefixLength(isCombined) {
|
53 | return isCombined ? 2 : 1;
|
54 | }
|
55 | export function escapeForHtml(str) {
|
56 | return str
|
57 | .slice(0)
|
58 | .replace(/&/g, '&')
|
59 | .replace(/</g, '<')
|
60 | .replace(/>/g, '>')
|
61 | .replace(/"/g, '"')
|
62 | .replace(/'/g, ''')
|
63 | .replace(/\//g, '/');
|
64 | }
|
65 | export function deconstructLine(line, isCombined, escape) {
|
66 | if (escape === void 0) { escape = true; }
|
67 | var indexToSplit = prefixLength(isCombined);
|
68 | return {
|
69 | prefix: line.substring(0, indexToSplit),
|
70 | content: escape ? escapeForHtml(line.substring(indexToSplit)) : line.substring(indexToSplit),
|
71 | };
|
72 | }
|
73 | export function filenameDiff(file) {
|
74 | var oldFilename = unifyPath(file.oldName);
|
75 | var newFilename = unifyPath(file.newName);
|
76 | if (oldFilename !== newFilename && !isDevNullName(oldFilename) && !isDevNullName(newFilename)) {
|
77 | var prefixPaths = [];
|
78 | var suffixPaths = [];
|
79 | var oldFilenameParts = oldFilename.split(separator);
|
80 | var newFilenameParts = newFilename.split(separator);
|
81 | var oldFilenamePartsSize = oldFilenameParts.length;
|
82 | var newFilenamePartsSize = newFilenameParts.length;
|
83 | var i = 0;
|
84 | var j = oldFilenamePartsSize - 1;
|
85 | var k = newFilenamePartsSize - 1;
|
86 | while (i < j && i < k) {
|
87 | if (oldFilenameParts[i] === newFilenameParts[i]) {
|
88 | prefixPaths.push(newFilenameParts[i]);
|
89 | i += 1;
|
90 | }
|
91 | else {
|
92 | break;
|
93 | }
|
94 | }
|
95 | while (j > i && k > i) {
|
96 | if (oldFilenameParts[j] === newFilenameParts[k]) {
|
97 | suffixPaths.unshift(newFilenameParts[k]);
|
98 | j -= 1;
|
99 | k -= 1;
|
100 | }
|
101 | else {
|
102 | break;
|
103 | }
|
104 | }
|
105 | var finalPrefix = prefixPaths.join(separator);
|
106 | var finalSuffix = suffixPaths.join(separator);
|
107 | var oldRemainingPath = oldFilenameParts.slice(i, j + 1).join(separator);
|
108 | var newRemainingPath = newFilenameParts.slice(i, k + 1).join(separator);
|
109 | if (finalPrefix.length && finalSuffix.length) {
|
110 | return (finalPrefix + separator + '{' + oldRemainingPath + ' → ' + newRemainingPath + '}' + separator + finalSuffix);
|
111 | }
|
112 | else if (finalPrefix.length) {
|
113 | return finalPrefix + separator + '{' + oldRemainingPath + ' → ' + newRemainingPath + '}';
|
114 | }
|
115 | else if (finalSuffix.length) {
|
116 | return '{' + oldRemainingPath + ' → ' + newRemainingPath + '}' + separator + finalSuffix;
|
117 | }
|
118 | return oldFilename + ' → ' + newFilename;
|
119 | }
|
120 | else if (!isDevNullName(newFilename)) {
|
121 | return newFilename;
|
122 | }
|
123 | else {
|
124 | return oldFilename;
|
125 | }
|
126 | }
|
127 | export function getHtmlId(file) {
|
128 | return "d2h-" + hashCode(filenameDiff(file)).toString().slice(-6);
|
129 | }
|
130 | export function getFileIcon(file) {
|
131 | var templateName = 'file-changed';
|
132 | if (file.isRename) {
|
133 | templateName = 'file-renamed';
|
134 | }
|
135 | else if (file.isCopy) {
|
136 | templateName = 'file-renamed';
|
137 | }
|
138 | else if (file.isNew) {
|
139 | templateName = 'file-added';
|
140 | }
|
141 | else if (file.isDeleted) {
|
142 | templateName = 'file-deleted';
|
143 | }
|
144 | else if (file.newName !== file.oldName) {
|
145 | templateName = 'file-renamed';
|
146 | }
|
147 | return templateName;
|
148 | }
|
149 | export function diffHighlight(diffLine1, diffLine2, isCombined, config) {
|
150 | if (config === void 0) { config = {}; }
|
151 | var _a = __assign(__assign({}, defaultRenderConfig), config), matching = _a.matching, maxLineLengthHighlight = _a.maxLineLengthHighlight, matchWordsThreshold = _a.matchWordsThreshold, diffStyle = _a.diffStyle;
|
152 | var line1 = deconstructLine(diffLine1, isCombined, false);
|
153 | var line2 = deconstructLine(diffLine2, isCombined, false);
|
154 | if (line1.content.length > maxLineLengthHighlight || line2.content.length > maxLineLengthHighlight) {
|
155 | return {
|
156 | oldLine: {
|
157 | prefix: line1.prefix,
|
158 | content: line1.content,
|
159 | },
|
160 | newLine: {
|
161 | prefix: line2.prefix,
|
162 | content: line2.content,
|
163 | },
|
164 | };
|
165 | }
|
166 | var diff = diffStyle === 'char'
|
167 | ? jsDiff.diffChars(line1.content, line2.content)
|
168 | : jsDiff.diffWordsWithSpace(line1.content, line2.content);
|
169 | var changedWords = [];
|
170 | if (diffStyle === 'word' && matching === 'words') {
|
171 | var removed = diff.filter(function (element) { return element.removed; });
|
172 | var added = diff.filter(function (element) { return element.added; });
|
173 | var chunks = matcher(added, removed);
|
174 | chunks.forEach(function (chunk) {
|
175 | if (chunk[0].length === 1 && chunk[1].length === 1) {
|
176 | var dist = distance(chunk[0][0], chunk[1][0]);
|
177 | if (dist < matchWordsThreshold) {
|
178 | changedWords.push(chunk[0][0]);
|
179 | changedWords.push(chunk[1][0]);
|
180 | }
|
181 | }
|
182 | });
|
183 | }
|
184 | var highlightedLine = diff.reduce(function (highlightedLine, part) {
|
185 | var elemType = part.added ? 'ins' : part.removed ? 'del' : null;
|
186 | var addClass = changedWords.indexOf(part) > -1 ? ' class="d2h-change"' : '';
|
187 | var escapedValue = escapeForHtml(part.value);
|
188 | return elemType !== null
|
189 | ? highlightedLine + "<" + elemType + addClass + ">" + escapedValue + "</" + elemType + ">"
|
190 | : "" + highlightedLine + escapedValue;
|
191 | }, '');
|
192 | return {
|
193 | oldLine: {
|
194 | prefix: line1.prefix,
|
195 | content: removeInsElements(highlightedLine),
|
196 | },
|
197 | newLine: {
|
198 | prefix: line2.prefix,
|
199 | content: removeDelElements(highlightedLine),
|
200 | },
|
201 | };
|
202 | }
|
203 |
|
\ | No newline at end of file |