Word wrap enabled and structure changes in the output
This commit is contained in:
parent
4de87bf099
commit
7382dbc918
14 changed files with 19358 additions and 1539 deletions
17564
package-lock.json
generated
Normal file
17564
package-lock.json
generated
Normal file
File diff suppressed because it is too large
Load diff
|
|
@ -124,7 +124,7 @@
|
||||||
"mini-css-extract-plugin": "2.7.7",
|
"mini-css-extract-plugin": "2.7.7",
|
||||||
"mkdirp": "3.0.1",
|
"mkdirp": "3.0.1",
|
||||||
"nopt": "7.2.0",
|
"nopt": "7.2.0",
|
||||||
"postcss": "8.4.33",
|
"postcss": "^8.4.33",
|
||||||
"postcss-cli": "11.0.0",
|
"postcss-cli": "11.0.0",
|
||||||
"postcss-import": "16.0.0",
|
"postcss-import": "16.0.0",
|
||||||
"postcss-loader": "7.3.4",
|
"postcss-loader": "7.3.4",
|
||||||
|
|
|
||||||
|
|
@ -19,6 +19,7 @@ export const defaultDiff2HtmlConfig = {
|
||||||
...defaultSideBySideRendererConfig,
|
...defaultSideBySideRendererConfig,
|
||||||
outputFormat: OutputFormatType.LINE_BY_LINE,
|
outputFormat: OutputFormatType.LINE_BY_LINE,
|
||||||
drawFileList: true,
|
drawFileList: true,
|
||||||
|
lineFolding: false
|
||||||
};
|
};
|
||||||
|
|
||||||
export function parse(diffInput: string, configuration: Diff2HtmlConfig = {}): DiffFile[] {
|
export function parse(diffInput: string, configuration: Diff2HtmlConfig = {}): DiffFile[] {
|
||||||
|
|
|
||||||
|
|
@ -16,6 +16,7 @@ export interface LineByLineRendererConfig extends renderUtils.RenderConfig {
|
||||||
renderNothingWhenEmpty?: boolean;
|
renderNothingWhenEmpty?: boolean;
|
||||||
matchingMaxComparisons?: number;
|
matchingMaxComparisons?: number;
|
||||||
maxLineSizeInBlockForComparison?: number;
|
maxLineSizeInBlockForComparison?: number;
|
||||||
|
lineFolding?: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
export const defaultLineByLineRendererConfig = {
|
export const defaultLineByLineRendererConfig = {
|
||||||
|
|
@ -23,6 +24,7 @@ export const defaultLineByLineRendererConfig = {
|
||||||
renderNothingWhenEmpty: false,
|
renderNothingWhenEmpty: false,
|
||||||
matchingMaxComparisons: 2500,
|
matchingMaxComparisons: 2500,
|
||||||
maxLineSizeInBlockForComparison: 200,
|
maxLineSizeInBlockForComparison: 200,
|
||||||
|
lineFolding: true
|
||||||
};
|
};
|
||||||
|
|
||||||
const genericTemplatesPath = 'generic';
|
const genericTemplatesPath = 'generic';
|
||||||
|
|
@ -70,6 +72,7 @@ export default class LineByLineRenderer {
|
||||||
file: file,
|
file: file,
|
||||||
fileHtmlId: renderUtils.getHtmlId(file),
|
fileHtmlId: renderUtils.getHtmlId(file),
|
||||||
diffs: diffs,
|
diffs: diffs,
|
||||||
|
diffClass: (this.config.lineFolding) ? 'd2h-wrapped-file-diff' : '',
|
||||||
filePath: filePathTemplate.render(
|
filePath: filePathTemplate.render(
|
||||||
{
|
{
|
||||||
fileDiffName: renderUtils.filenameDiff(file),
|
fileDiffName: renderUtils.filenameDiff(file),
|
||||||
|
|
@ -96,11 +99,13 @@ export default class LineByLineRenderer {
|
||||||
|
|
||||||
return file.blocks
|
return file.blocks
|
||||||
.map(block => {
|
.map(block => {
|
||||||
let lines = this.hoganUtils.render(genericTemplatesPath, 'block-header', {
|
let lines = this.hoganUtils.render(genericTemplatesPath, 'line', {
|
||||||
CSSLineClass: renderUtils.CSSLineClass,
|
lineContent: this.hoganUtils.render(genericTemplatesPath, 'block-header', {
|
||||||
blockHeader: file.isTooBig ? block.header : renderUtils.escapeForHtml(block.header),
|
CSSLineClass: renderUtils.CSSLineClass,
|
||||||
lineClass: 'd2h-code-linenumber',
|
blockHeader: file.isTooBig ? block.header : renderUtils.escapeForHtml(block.header),
|
||||||
contentClass: 'd2h-code-line',
|
lineClass: 'd2h-code-linenumber',
|
||||||
|
contentClass: 'd2h-code-line',
|
||||||
|
})
|
||||||
});
|
});
|
||||||
|
|
||||||
this.applyLineGroupping(block).forEach(([contextLines, oldLines, newLines]) => {
|
this.applyLineGroupping(block).forEach(([contextLines, oldLines, newLines]) => {
|
||||||
|
|
@ -113,13 +118,15 @@ export default class LineByLineRenderer {
|
||||||
} else if (contextLines.length) {
|
} else if (contextLines.length) {
|
||||||
contextLines.forEach(line => {
|
contextLines.forEach(line => {
|
||||||
const { prefix, content } = renderUtils.deconstructLine(line.content, file.isCombined);
|
const { prefix, content } = renderUtils.deconstructLine(line.content, file.isCombined);
|
||||||
lines += this.generateSingleLineHtml(file, {
|
lines += this.hoganUtils.render(genericTemplatesPath, 'line', {
|
||||||
type: renderUtils.CSSLineClass.CONTEXT,
|
lineContent: this.generateSingleLineHtml(file, {
|
||||||
prefix: prefix,
|
type: renderUtils.CSSLineClass.CONTEXT,
|
||||||
content: content,
|
prefix: prefix,
|
||||||
oldNumber: line.oldNumber,
|
content: content,
|
||||||
newNumber: line.newNumber,
|
oldNumber: line.oldNumber,
|
||||||
});
|
newNumber: line.newNumber,
|
||||||
|
})
|
||||||
|
})
|
||||||
});
|
});
|
||||||
} else if (oldLines.length || newLines.length) {
|
} else if (oldLines.length || newLines.length) {
|
||||||
const { left, right } = this.processChangedLines(file, file.isCombined, oldLines, newLines);
|
const { left, right } = this.processChangedLines(file, file.isCombined, oldLines, newLines);
|
||||||
|
|
@ -253,8 +260,12 @@ export default class LineByLineRenderer {
|
||||||
|
|
||||||
generateLineHtml(file: DiffFile, oldLine?: DiffPreparedLine, newLine?: DiffPreparedLine): FileHtml {
|
generateLineHtml(file: DiffFile, oldLine?: DiffPreparedLine, newLine?: DiffPreparedLine): FileHtml {
|
||||||
return {
|
return {
|
||||||
left: this.generateSingleLineHtml(file, oldLine),
|
left: this.hoganUtils.render(genericTemplatesPath, 'line', {
|
||||||
right: this.generateSingleLineHtml(file, newLine),
|
lineContent: this.generateSingleLineHtml(file, oldLine)
|
||||||
|
}),
|
||||||
|
right: this.hoganUtils.render(genericTemplatesPath, 'line', {
|
||||||
|
lineContent: this.generateSingleLineHtml(file, newLine),
|
||||||
|
})
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -266,7 +277,7 @@ export default class LineByLineRenderer {
|
||||||
newNumber: line.newNumber || '',
|
newNumber: line.newNumber || '',
|
||||||
});
|
});
|
||||||
|
|
||||||
return this.hoganUtils.render(genericTemplatesPath, 'line', {
|
return this.hoganUtils.render(genericTemplatesPath, 'line-content', {
|
||||||
type: line.type,
|
type: line.type,
|
||||||
lineClass: 'd2h-code-linenumber',
|
lineClass: 'd2h-code-linenumber',
|
||||||
contentClass: 'd2h-code-line',
|
contentClass: 'd2h-code-line',
|
||||||
|
|
|
||||||
|
|
@ -46,6 +46,7 @@ export interface RenderConfig {
|
||||||
maxLineLengthHighlight?: number;
|
maxLineLengthHighlight?: number;
|
||||||
diffStyle?: DiffStyleType;
|
diffStyle?: DiffStyleType;
|
||||||
colorScheme?: ColorSchemeType;
|
colorScheme?: ColorSchemeType;
|
||||||
|
lineFolding?: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
export const defaultRenderConfig = {
|
export const defaultRenderConfig = {
|
||||||
|
|
|
||||||
|
|
@ -16,6 +16,7 @@ export interface SideBySideRendererConfig extends renderUtils.RenderConfig {
|
||||||
renderNothingWhenEmpty?: boolean;
|
renderNothingWhenEmpty?: boolean;
|
||||||
matchingMaxComparisons?: number;
|
matchingMaxComparisons?: number;
|
||||||
maxLineSizeInBlockForComparison?: number;
|
maxLineSizeInBlockForComparison?: number;
|
||||||
|
lineFolding?: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
export const defaultSideBySideRendererConfig = {
|
export const defaultSideBySideRendererConfig = {
|
||||||
|
|
@ -23,6 +24,7 @@ export const defaultSideBySideRendererConfig = {
|
||||||
renderNothingWhenEmpty: false,
|
renderNothingWhenEmpty: false,
|
||||||
matchingMaxComparisons: 2500,
|
matchingMaxComparisons: 2500,
|
||||||
maxLineSizeInBlockForComparison: 200,
|
maxLineSizeInBlockForComparison: 200,
|
||||||
|
lineFolding: true
|
||||||
};
|
};
|
||||||
|
|
||||||
const genericTemplatesPath = 'generic';
|
const genericTemplatesPath = 'generic';
|
||||||
|
|
@ -65,11 +67,12 @@ export default class SideBySideRenderer {
|
||||||
const filePathTemplate = this.hoganUtils.template(genericTemplatesPath, 'file-path');
|
const filePathTemplate = this.hoganUtils.template(genericTemplatesPath, 'file-path');
|
||||||
const fileIconTemplate = this.hoganUtils.template(iconsBaseTemplatesPath, 'file');
|
const fileIconTemplate = this.hoganUtils.template(iconsBaseTemplatesPath, 'file');
|
||||||
const fileTagTemplate = this.hoganUtils.template(tagsBaseTemplatesPath, renderUtils.getFileIcon(file));
|
const fileTagTemplate = this.hoganUtils.template(tagsBaseTemplatesPath, renderUtils.getFileIcon(file));
|
||||||
|
debugger;
|
||||||
return fileDiffTemplate.render({
|
return fileDiffTemplate.render({
|
||||||
file: file,
|
file: file,
|
||||||
fileHtmlId: renderUtils.getHtmlId(file),
|
fileHtmlId: renderUtils.getHtmlId(file),
|
||||||
diffs: diffs,
|
diffs: diffs,
|
||||||
|
diffClass: (this.config.lineFolding) ? 'd2h-wrapped-file-diff' : '',
|
||||||
filePath: filePathTemplate.render(
|
filePath: filePathTemplate.render(
|
||||||
{
|
{
|
||||||
fileDiffName: renderUtils.filenameDiff(file),
|
fileDiffName: renderUtils.filenameDiff(file),
|
||||||
|
|
@ -207,12 +210,28 @@ export default class SideBySideRenderer {
|
||||||
}
|
}
|
||||||
|
|
||||||
makeHeaderHtml(blockHeader: string, file?: DiffFile): string {
|
makeHeaderHtml(blockHeader: string, file?: DiffFile): string {
|
||||||
return this.hoganUtils.render(genericTemplatesPath, 'block-header', {
|
const lineFolding = this.config.lineFolding;
|
||||||
|
let headerContent = this.hoganUtils.render(genericTemplatesPath, 'block-header', {
|
||||||
CSSLineClass: renderUtils.CSSLineClass,
|
CSSLineClass: renderUtils.CSSLineClass,
|
||||||
blockHeader: file?.isTooBig ? blockHeader : renderUtils.escapeForHtml(blockHeader),
|
blockHeader: file?.isTooBig ? blockHeader : renderUtils.escapeForHtml(blockHeader),
|
||||||
lineClass: 'd2h-code-side-linenumber',
|
lineClass: 'd2h-code-side-linenumber',
|
||||||
contentClass: 'd2h-code-side-line',
|
contentClass: 'd2h-code-side-line',
|
||||||
});
|
});
|
||||||
|
if(blockHeader.length !== 0) {
|
||||||
|
if(lineFolding) {
|
||||||
|
headerContent += this.hoganUtils.render(genericTemplatesPath, 'block-header', {
|
||||||
|
CSSLineClass: renderUtils.CSSLineClass,
|
||||||
|
blockHeader: "",
|
||||||
|
lineClass: 'd2h-code-side-linenumber',
|
||||||
|
contentClass: 'd2h-code-side-line',
|
||||||
|
});
|
||||||
|
}
|
||||||
|
return this.hoganUtils.render(genericTemplatesPath, 'line', {
|
||||||
|
lineContent: headerContent
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
return blockHeader;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
processChangedLines(isCombined: boolean, oldLines: DiffLine[], newLines: DiffLine[]): FileHtml {
|
processChangedLines(isCombined: boolean, oldLines: DiffLine[], newLines: DiffLine[]): FileHtml {
|
||||||
|
|
@ -274,17 +293,31 @@ export default class SideBySideRenderer {
|
||||||
}
|
}
|
||||||
|
|
||||||
generateLineHtml(oldLine?: DiffPreparedLine, newLine?: DiffPreparedLine): FileHtml {
|
generateLineHtml(oldLine?: DiffPreparedLine, newLine?: DiffPreparedLine): FileHtml {
|
||||||
return {
|
const lineFolding = this.config.lineFolding;
|
||||||
left: this.generateSingleHtml(oldLine),
|
if(lineFolding) {
|
||||||
right: this.generateSingleHtml(newLine),
|
return {
|
||||||
};
|
left: this.hoganUtils.render(genericTemplatesPath, 'line', {
|
||||||
|
lineContent: this.generateSingleHtml(oldLine) + this.generateSingleHtml(newLine)
|
||||||
|
}),
|
||||||
|
right: ''
|
||||||
|
};
|
||||||
|
} else {
|
||||||
|
return {
|
||||||
|
left: this.hoganUtils.render(genericTemplatesPath, 'line', {
|
||||||
|
lineContent: this.generateSingleHtml(oldLine)
|
||||||
|
}),
|
||||||
|
right: this.hoganUtils.render(genericTemplatesPath, 'line', {
|
||||||
|
lineContent: this.generateSingleHtml(newLine),
|
||||||
|
})
|
||||||
|
};
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
generateSingleHtml(line?: DiffPreparedLine): string {
|
generateSingleHtml(line?: DiffPreparedLine): string {
|
||||||
const lineClass = 'd2h-code-side-linenumber';
|
const lineClass = 'd2h-code-side-linenumber';
|
||||||
const contentClass = 'd2h-code-side-line';
|
const contentClass = 'd2h-code-side-line';
|
||||||
|
|
||||||
return this.hoganUtils.render(genericTemplatesPath, 'line', {
|
return this.hoganUtils.render(genericTemplatesPath, 'line-content', {
|
||||||
type: line?.type || `${renderUtils.CSSLineClass.CONTEXT} d2h-emptyplaceholder`,
|
type: line?.type || `${renderUtils.CSSLineClass.CONTEXT} d2h-emptyplaceholder`,
|
||||||
lineClass: line !== undefined ? lineClass : `${lineClass} d2h-code-side-emptyplaceholder`,
|
lineClass: line !== undefined ? lineClass : `${lineClass} d2h-code-side-emptyplaceholder`,
|
||||||
contentClass: line !== undefined ? contentClass : `${contentClass} d2h-code-side-emptyplaceholder`,
|
contentClass: line !== undefined ? contentClass : `${contentClass} d2h-code-side-emptyplaceholder`,
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,5 @@
|
||||||
<tr>
|
<td class="{{lineClass}} {{CSSLineClass.INFO}}"></td>
|
||||||
<td class="{{lineClass}} {{CSSLineClass.INFO}}"></td>
|
<td class="{{CSSLineClass.INFO}}">
|
||||||
<td class="{{CSSLineClass.INFO}}">
|
<div class="{{contentClass}}">{{#blockHeader}}{{{blockHeader}}}{{/blockHeader}}{{^blockHeader}} {{/blockHeader}}</div>
|
||||||
<div class="{{contentClass}}">{{#blockHeader}}{{{blockHeader}}}{{/blockHeader}}{{^blockHeader}} {{/blockHeader}}</div>
|
</td>
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
|
|
|
||||||
19
src/templates/generic-line-content.mustache
Normal file
19
src/templates/generic-line-content.mustache
Normal file
|
|
@ -0,0 +1,19 @@
|
||||||
|
<td class="{{lineClass}} {{type}}">
|
||||||
|
{{{lineNumber}}}
|
||||||
|
</td>
|
||||||
|
<td class="{{type}}">
|
||||||
|
<div class="{{contentClass}}">
|
||||||
|
{{#prefix}}
|
||||||
|
<span class="d2h-code-line-prefix">{{{prefix}}}</span>
|
||||||
|
{{/prefix}}
|
||||||
|
{{^prefix}}
|
||||||
|
<span class="d2h-code-line-prefix"> </span>
|
||||||
|
{{/prefix}}
|
||||||
|
{{#content}}
|
||||||
|
<span class="d2h-code-line-ctn">{{{content}}}</span>
|
||||||
|
{{/content}}
|
||||||
|
{{^content}}
|
||||||
|
<span class="d2h-code-line-ctn"><br></span>
|
||||||
|
{{/content}}
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
|
@ -1,21 +1,5 @@
|
||||||
|
{{#lineContent}}
|
||||||
<tr>
|
<tr>
|
||||||
<td class="{{lineClass}} {{type}}">
|
{{{lineContent}}}
|
||||||
{{{lineNumber}}}
|
|
||||||
</td>
|
|
||||||
<td class="{{type}}">
|
|
||||||
<div class="{{contentClass}}">
|
|
||||||
{{#prefix}}
|
|
||||||
<span class="d2h-code-line-prefix">{{{prefix}}}</span>
|
|
||||||
{{/prefix}}
|
|
||||||
{{^prefix}}
|
|
||||||
<span class="d2h-code-line-prefix"> </span>
|
|
||||||
{{/prefix}}
|
|
||||||
{{#content}}
|
|
||||||
<span class="d2h-code-line-ctn">{{{content}}}</span>
|
|
||||||
{{/content}}
|
|
||||||
{{^content}}
|
|
||||||
<span class="d2h-code-line-ctn"><br></span>
|
|
||||||
{{/content}}
|
|
||||||
</div>
|
|
||||||
</td>
|
|
||||||
</tr>
|
</tr>
|
||||||
|
{{/lineContent}}
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@
|
||||||
<div class="d2h-file-header">
|
<div class="d2h-file-header">
|
||||||
{{{filePath}}}
|
{{{filePath}}}
|
||||||
</div>
|
</div>
|
||||||
<div class="d2h-file-diff">
|
<div class="d2h-file-diff {{diffClass}}">
|
||||||
<div class="d2h-code-wrapper">
|
<div class="d2h-code-wrapper">
|
||||||
<table class="d2h-diff-table">
|
<table class="d2h-diff-table">
|
||||||
<tbody class="d2h-diff-tbody">
|
<tbody class="d2h-diff-tbody">
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@
|
||||||
<div class="d2h-file-header">
|
<div class="d2h-file-header">
|
||||||
{{{filePath}}}
|
{{{filePath}}}
|
||||||
</div>
|
</div>
|
||||||
<div class="d2h-files-diff">
|
<div class="d2h-files-diff {{diffClass}}">
|
||||||
<div class="d2h-file-side-diff">
|
<div class="d2h-file-side-diff">
|
||||||
<div class="d2h-code-wrapper">
|
<div class="d2h-code-wrapper">
|
||||||
<table class="d2h-diff-table">
|
<table class="d2h-diff-table">
|
||||||
|
|
@ -12,6 +12,7 @@
|
||||||
</table>
|
</table>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
{{#diffs.right}}
|
||||||
<div class="d2h-file-side-diff">
|
<div class="d2h-file-side-diff">
|
||||||
<div class="d2h-code-wrapper">
|
<div class="d2h-code-wrapper">
|
||||||
<table class="d2h-diff-table">
|
<table class="d2h-diff-table">
|
||||||
|
|
@ -21,5 +22,6 @@
|
||||||
</table>
|
</table>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
{{/diffs.right}}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
|
|
@ -52,6 +52,12 @@
|
||||||
</select>
|
</select>
|
||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="column is-one-sixth-widescreen">
|
||||||
|
<label title="Show the file list summary before the diff">
|
||||||
|
<p>Line Folding</p>
|
||||||
|
<input class="options-label-value" id="diff-url-options-line-folding" type="checkbox" name="drawFileList"/>
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
<div class="column is-one-sixth-widescreen">
|
<div class="column is-one-sixth-widescreen">
|
||||||
<label title="Show the file list summary before the diff">
|
<label title="Show the file list summary before the diff">
|
||||||
<p>File Summary</p>
|
<p>File Summary</p>
|
||||||
|
|
|
||||||
|
|
@ -216,6 +216,7 @@ type Elements = {
|
||||||
};
|
};
|
||||||
checkboxes: {
|
checkboxes: {
|
||||||
drawFileList: HTMLInputElement;
|
drawFileList: HTMLInputElement;
|
||||||
|
lineFolding: HTMLInputElement;
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -276,6 +277,7 @@ document.addEventListener('DOMContentLoaded', async () => {
|
||||||
},
|
},
|
||||||
checkboxes: {
|
checkboxes: {
|
||||||
drawFileList: getHTMLInputElementById('diff-url-options-show-files'),
|
drawFileList: getHTMLInputElementById('diff-url-options-show-files'),
|
||||||
|
lineFolding: getHTMLInputElementById('diff-url-options-line-folding')
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -285,6 +287,7 @@ document.addEventListener('DOMContentLoaded', async () => {
|
||||||
config.outputFormat && (elements.options.outputFormat.value = config.outputFormat);
|
config.outputFormat && (elements.options.outputFormat.value = config.outputFormat);
|
||||||
config.colorScheme && (elements.options.colorScheme.value = config.colorScheme);
|
config.colorScheme && (elements.options.colorScheme.value = config.colorScheme);
|
||||||
config.drawFileList && (elements.checkboxes.drawFileList.checked = config.drawFileList);
|
config.drawFileList && (elements.checkboxes.drawFileList.checked = config.drawFileList);
|
||||||
|
config.lineFolding && (elements.checkboxes.lineFolding.checked = config.lineFolding);
|
||||||
config.matching && (elements.options.matching.value = config.matching);
|
config.matching && (elements.options.matching.value = config.matching);
|
||||||
config.matchWordsThreshold && (elements.options.wordsThreshold.value = config.matchWordsThreshold.toString());
|
config.matchWordsThreshold && (elements.options.wordsThreshold.value = config.matchWordsThreshold.toString());
|
||||||
config.matchingMaxComparisons &&
|
config.matchingMaxComparisons &&
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue