1 | "use strict";
|
2 | var __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 | };
|
13 | var __importStar = (this && this.__importStar) || function (mod) {
|
14 | if (mod && mod.__esModule) return mod;
|
15 | var result = {};
|
16 | if (mod != null) for (var k in mod) if (Object.hasOwnProperty.call(mod, k)) result[k] = mod[k];
|
17 | result["default"] = mod;
|
18 | return result;
|
19 | };
|
20 | Object.defineProperty(exports, "__esModule", { value: true });
|
21 | var Rematch = __importStar(require("./rematch"));
|
22 | var renderUtils = __importStar(require("./render-utils"));
|
23 | var types_1 = require("./types");
|
24 | exports.defaultSideBySideRendererConfig = __assign(__assign({}, renderUtils.defaultRenderConfig), { renderNothingWhenEmpty: false, matchingMaxComparisons: 2500, maxLineSizeInBlockForComparison: 200 });
|
25 | var genericTemplatesPath = 'generic';
|
26 | var baseTemplatesPath = 'side-by-side';
|
27 | var iconsBaseTemplatesPath = 'icon';
|
28 | var tagsBaseTemplatesPath = 'tag';
|
29 | var SideBySideRenderer = (function () {
|
30 | function SideBySideRenderer(hoganUtils, config) {
|
31 | if (config === void 0) { config = {}; }
|
32 | this.hoganUtils = hoganUtils;
|
33 | this.config = __assign(__assign({}, exports.defaultSideBySideRendererConfig), config);
|
34 | }
|
35 | SideBySideRenderer.prototype.render = function (diffFiles) {
|
36 | var _this = this;
|
37 | var diffsHtml = diffFiles
|
38 | .map(function (file) {
|
39 | var diffs;
|
40 | if (file.blocks.length) {
|
41 | diffs = _this.generateFileHtml(file);
|
42 | }
|
43 | else {
|
44 | diffs = _this.generateEmptyDiff();
|
45 | }
|
46 | return _this.makeFileDiffHtml(file, diffs);
|
47 | })
|
48 | .join('\n');
|
49 | return this.hoganUtils.render(genericTemplatesPath, 'wrapper', { content: diffsHtml });
|
50 | };
|
51 | SideBySideRenderer.prototype.makeFileDiffHtml = function (file, diffs) {
|
52 | if (this.config.renderNothingWhenEmpty && Array.isArray(file.blocks) && file.blocks.length === 0)
|
53 | return '';
|
54 | var fileDiffTemplate = this.hoganUtils.template(baseTemplatesPath, 'file-diff');
|
55 | var filePathTemplate = this.hoganUtils.template(genericTemplatesPath, 'file-path');
|
56 | var fileIconTemplate = this.hoganUtils.template(iconsBaseTemplatesPath, 'file');
|
57 | var fileTagTemplate = this.hoganUtils.template(tagsBaseTemplatesPath, renderUtils.getFileIcon(file));
|
58 | return fileDiffTemplate.render({
|
59 | file: file,
|
60 | fileHtmlId: renderUtils.getHtmlId(file),
|
61 | diffs: diffs,
|
62 | filePath: filePathTemplate.render({
|
63 | fileDiffName: renderUtils.filenameDiff(file),
|
64 | }, {
|
65 | fileIcon: fileIconTemplate,
|
66 | fileTag: fileTagTemplate,
|
67 | }),
|
68 | });
|
69 | };
|
70 | SideBySideRenderer.prototype.generateEmptyDiff = function () {
|
71 | return {
|
72 | right: '',
|
73 | left: this.hoganUtils.render(genericTemplatesPath, 'empty-diff', {
|
74 | contentClass: 'd2h-code-side-line',
|
75 | CSSLineClass: renderUtils.CSSLineClass,
|
76 | }),
|
77 | };
|
78 | };
|
79 | SideBySideRenderer.prototype.generateFileHtml = function (file) {
|
80 | var _this = this;
|
81 | var matcher = Rematch.newMatcherFn(Rematch.newDistanceFn(function (e) { return renderUtils.deconstructLine(e.content, file.isCombined).content; }));
|
82 | return file.blocks
|
83 | .map(function (block) {
|
84 | var fileHtml = {
|
85 | left: _this.makeHeaderHtml(block.header),
|
86 | right: _this.makeHeaderHtml(''),
|
87 | };
|
88 | _this.applyLineGroupping(block).forEach(function (_a) {
|
89 | var contextLines = _a[0], oldLines = _a[1], newLines = _a[2];
|
90 | if (oldLines.length && newLines.length && !contextLines.length) {
|
91 | _this.applyRematchMatching(oldLines, newLines, matcher).map(function (_a) {
|
92 | var oldLines = _a[0], newLines = _a[1];
|
93 | var _b = _this.processChangedLines(file.isCombined, oldLines, newLines), left = _b.left, right = _b.right;
|
94 | fileHtml.left += left;
|
95 | fileHtml.right += right;
|
96 | });
|
97 | }
|
98 | else if (contextLines.length) {
|
99 | contextLines.forEach(function (line) {
|
100 | var _a = renderUtils.deconstructLine(line.content, file.isCombined), prefix = _a.prefix, content = _a.content;
|
101 | var _b = _this.generateLineHtml({
|
102 | type: renderUtils.CSSLineClass.CONTEXT,
|
103 | prefix: prefix,
|
104 | content: content,
|
105 | number: line.oldNumber,
|
106 | }, {
|
107 | type: renderUtils.CSSLineClass.CONTEXT,
|
108 | prefix: prefix,
|
109 | content: content,
|
110 | number: line.newNumber,
|
111 | }), left = _b.left, right = _b.right;
|
112 | fileHtml.left += left;
|
113 | fileHtml.right += right;
|
114 | });
|
115 | }
|
116 | else if (oldLines.length || newLines.length) {
|
117 | var _b = _this.processChangedLines(file.isCombined, oldLines, newLines), left = _b.left, right = _b.right;
|
118 | fileHtml.left += left;
|
119 | fileHtml.right += right;
|
120 | }
|
121 | else {
|
122 | console.error('Unknown state reached while processing groups of lines', contextLines, oldLines, newLines);
|
123 | }
|
124 | });
|
125 | return fileHtml;
|
126 | })
|
127 | .reduce(function (accomulated, html) {
|
128 | return { left: accomulated.left + html.left, right: accomulated.right + html.right };
|
129 | }, { left: '', right: '' });
|
130 | };
|
131 | SideBySideRenderer.prototype.applyLineGroupping = function (block) {
|
132 | var blockLinesGroups = [];
|
133 | var oldLines = [];
|
134 | var newLines = [];
|
135 | for (var i = 0; i < block.lines.length; i++) {
|
136 | var diffLine = block.lines[i];
|
137 | if ((diffLine.type !== types_1.LineType.INSERT && newLines.length) ||
|
138 | (diffLine.type === types_1.LineType.CONTEXT && oldLines.length > 0)) {
|
139 | blockLinesGroups.push([[], oldLines, newLines]);
|
140 | oldLines = [];
|
141 | newLines = [];
|
142 | }
|
143 | if (diffLine.type === types_1.LineType.CONTEXT) {
|
144 | blockLinesGroups.push([[diffLine], [], []]);
|
145 | }
|
146 | else if (diffLine.type === types_1.LineType.INSERT && oldLines.length === 0) {
|
147 | blockLinesGroups.push([[], [], [diffLine]]);
|
148 | }
|
149 | else if (diffLine.type === types_1.LineType.INSERT && oldLines.length > 0) {
|
150 | newLines.push(diffLine);
|
151 | }
|
152 | else if (diffLine.type === types_1.LineType.DELETE) {
|
153 | oldLines.push(diffLine);
|
154 | }
|
155 | }
|
156 | if (oldLines.length || newLines.length) {
|
157 | blockLinesGroups.push([[], oldLines, newLines]);
|
158 | oldLines = [];
|
159 | newLines = [];
|
160 | }
|
161 | return blockLinesGroups;
|
162 | };
|
163 | SideBySideRenderer.prototype.applyRematchMatching = function (oldLines, newLines, matcher) {
|
164 | var comparisons = oldLines.length * newLines.length;
|
165 | var maxLineSizeInBlock = Math.max.apply(null, [0].concat(oldLines.concat(newLines).map(function (elem) { return elem.content.length; })));
|
166 | var doMatching = comparisons < this.config.matchingMaxComparisons &&
|
167 | maxLineSizeInBlock < this.config.maxLineSizeInBlockForComparison &&
|
168 | (this.config.matching === 'lines' || this.config.matching === 'words');
|
169 | return doMatching ? matcher(oldLines, newLines) : [[oldLines, newLines]];
|
170 | };
|
171 | SideBySideRenderer.prototype.makeHeaderHtml = function (blockHeader) {
|
172 | return this.hoganUtils.render(genericTemplatesPath, 'block-header', {
|
173 | CSSLineClass: renderUtils.CSSLineClass,
|
174 | blockHeader: blockHeader,
|
175 | lineClass: 'd2h-code-side-linenumber',
|
176 | contentClass: 'd2h-code-side-line',
|
177 | });
|
178 | };
|
179 | SideBySideRenderer.prototype.processChangedLines = function (isCombined, oldLines, newLines) {
|
180 | var fileHtml = {
|
181 | right: '',
|
182 | left: '',
|
183 | };
|
184 | var maxLinesNumber = Math.max(oldLines.length, newLines.length);
|
185 | for (var i = 0; i < maxLinesNumber; i++) {
|
186 | var oldLine = oldLines[i];
|
187 | var newLine = newLines[i];
|
188 | var diff = oldLine !== undefined && newLine !== undefined
|
189 | ? renderUtils.diffHighlight(oldLine.content, newLine.content, isCombined, this.config)
|
190 | : undefined;
|
191 | var preparedOldLine = oldLine !== undefined && oldLine.oldNumber !== undefined
|
192 | ? __assign(__assign({}, (diff !== undefined
|
193 | ? {
|
194 | prefix: diff.oldLine.prefix,
|
195 | content: diff.oldLine.content,
|
196 | type: renderUtils.CSSLineClass.DELETE_CHANGES,
|
197 | }
|
198 | : __assign(__assign({}, renderUtils.deconstructLine(oldLine.content, isCombined)), { type: renderUtils.toCSSClass(oldLine.type) }))), { number: oldLine.oldNumber }) : undefined;
|
199 | var preparedNewLine = newLine !== undefined && newLine.newNumber !== undefined
|
200 | ? __assign(__assign({}, (diff !== undefined
|
201 | ? {
|
202 | prefix: diff.newLine.prefix,
|
203 | content: diff.newLine.content,
|
204 | type: renderUtils.CSSLineClass.INSERT_CHANGES,
|
205 | }
|
206 | : __assign(__assign({}, renderUtils.deconstructLine(newLine.content, isCombined)), { type: renderUtils.toCSSClass(newLine.type) }))), { number: newLine.newNumber }) : undefined;
|
207 | var _a = this.generateLineHtml(preparedOldLine, preparedNewLine), left = _a.left, right = _a.right;
|
208 | fileHtml.left += left;
|
209 | fileHtml.right += right;
|
210 | }
|
211 | return fileHtml;
|
212 | };
|
213 | SideBySideRenderer.prototype.generateLineHtml = function (oldLine, newLine) {
|
214 | return {
|
215 | left: this.generateSingleHtml(oldLine),
|
216 | right: this.generateSingleHtml(newLine),
|
217 | };
|
218 | };
|
219 | SideBySideRenderer.prototype.generateSingleHtml = function (line) {
|
220 | var _a, _b, _c, _d, _e;
|
221 | var lineClass = 'd2h-code-side-linenumber';
|
222 | var contentClass = 'd2h-code-side-line';
|
223 | return this.hoganUtils.render(genericTemplatesPath, 'line', {
|
224 | type: ((_a = line) === null || _a === void 0 ? void 0 : _a.type) || renderUtils.CSSLineClass.CONTEXT + " d2h-emptyplaceholder",
|
225 | lineClass: line !== undefined ? lineClass : lineClass + " d2h-code-side-emptyplaceholder",
|
226 | contentClass: line !== undefined ? contentClass : contentClass + " d2h-code-side-emptyplaceholder",
|
227 | prefix: ((_b = line) === null || _b === void 0 ? void 0 : _b.prefix) === ' ' ? ' ' : (_c = line) === null || _c === void 0 ? void 0 : _c.prefix,
|
228 | content: (_d = line) === null || _d === void 0 ? void 0 : _d.content,
|
229 | lineNumber: (_e = line) === null || _e === void 0 ? void 0 : _e.number,
|
230 | });
|
231 | };
|
232 | return SideBySideRenderer;
|
233 | }());
|
234 | exports.default = SideBySideRenderer;
|
235 |
|
\ | No newline at end of file |