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