8000 Merge pull request #514 from JHWelch/add-dark-mode · rtfpessoa/diff2html@b04a400 · GitHub
[go: up one dir, main page]

Skip to content

Commit b04a400

Browse files
authored
Merge pull request #514 from JHWelch/add-dark-mode
Add Dark & Auto color schemes
2 parents 8102d3c + 7410d25 commit b04a400

18 files changed

+1289
-107
lines changed

README.md

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -201,7 +201,7 @@ diff2htmlUi.draw();
201201

202202
```html
203203
<!-- Stylesheet -->
204-
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/9.13.1/styles/github.min.css" />
204+
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.8.0/styles/github.min.css" />
205205
<link rel="stylesheet" type="text/css" href="https://cdn.jsdelivr.net/npm/diff2html/bundles/css/diff2html.min.css" />
206206

207207
<!-- Javascripts -->
@@ -227,6 +227,21 @@ document.addEventListener('DOMContentLoaded', () => {
227227
});
228228
```
229229

230+
When using the `auto` color scheme, you will need to specify both the light and dark themes for highlight.js to use.
231+
232+
```html
233+
<link
234+
rel="stylesheet"
235+
href="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.8.0/styles/github.min.css"
236+
media="screen and (prefers-color-scheme: light)"
237+
/>
238+
<link
239+
rel="stylesheet"
240+
href="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.8.0/styles/github-dark.min.css"
241+
media="screen and (prefers-color-scheme: dark)"
242+
/>
243+
```
244+
230245
#### Collapsable File Summary List
231246

232247
> Add the dependencies.
@@ -386,6 +401,8 @@ The HTML output accepts a Javascript object with configuration. Possible options
386401
> [src/templates](https://github.com/rtfpessoa/diff2html/tree/master/src/templates)
387402
- `highlightLanguages`: Map of extension to language name, used for highlighting. This overrides the default language
388403
detection based on file extensions.
404+
- `colorScheme`: color scheme to use for the diff, default is `light`. Possible values are `light`, `dark`, and `auto`
405+
which will use the browser's preferred color scheme.
389406

390407
### Diff2Html Browser
391408

src/__tests__/diff2html-tests.ts

Lines changed: 298 additions & 14 deletions
Large diffs are not rendered by default.

src/__tests__/file-list-printer-tests.ts renamed to src/__tests__/file-list-renderer-tests.ts

Lines changed: 102 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,17 @@
1-
import { render } from '../file-list-renderer';
1+
import { FileListRenderer } from '../file-list-renderer';
22
import HoganJsUtils from '../hoganjs-utils';
3+
import { ColorSchemeType } from '../types';
34

4-
describe('FileListPrinter', () => {
5-
describe('generateFileList', () => {
5+
describe('FileListRenderer', () => {
6+
describe('render', () => {
67
it('should expose old and new files to templates', () => {
78
const hoganUtils = new HoganJsUtils({
89
rawTemplates: {
910
'file-summary-wrapper': '{{{files}}}',
1011
'file-summary-line': '{{oldName}}, {{newName}}, {{fileName}}',
1112
},
1213
});
14+
const fileListRenderer = new FileListRenderer(hoganUtils);
1315
const files = [
1416
{
1517
isCombined: false,
@@ -55,7 +57,7 @@ describe('FileListPrinter', () => {
5557
},
5658
];
5759

58-
const fileHtml = render(files, hoganUtils);
60+
const fileHtml = fileListRenderer.render(files);
5961

6062
expect(fileHtml).toMatchInlineSnapshot(`
6163
"my/file/name.js, my/file/name.js, my/file/name.js
@@ -67,6 +69,8 @@ describe('FileListPrinter', () => {
6769

6870
it('should work for all kinds of files', () => {
6971
const hoganUtils = new HoganJsUtils({});
72+
const fileListRenderer = new FileListRenderer(hoganUtils);
73+
7074
const files = [
7175
{
7276
isCombined: false,
@@ -111,9 +115,9 @@ describe('FileListPrinter', () => {
111115
isDeleted: true,
112116
},
113117
];
114-
const fileHtml = render(files, hoganUtils);
118+
const fileHtml = fileListRenderer.render(files);
115119
expect(fileHtml).toMatchInlineSnapshot(`
116-
"<div class="d2h-file-list-wrapper">
120+
"<div class="d2h-file-list-wrapper d2h-light-color-scheme">
117121
<div class="d2h-file-list-header">
118122
<span class="d2h-file-list-title">Files changed (4)</span>
119123
<a class="d2h-file-switch d2h-hide">hide</a>
@@ -172,5 +176,97 @@ describe('FileListPrinter', () => {
172176
</div>"
173177
`);
174178
});
179+
180+
describe('with dark colorScheme', () => {
181+
it('should include dark colorScheme', () => {
182+
const hoganUtils = new HoganJsUtils({});
183+
const fileListRenderer = new FileListRenderer(hoganUtils, {
184+
colorScheme: ColorSchemeType.DARK,
185+
});
186+
187+
const files = [
188+
{
189+
isCombined: false,
190+
isGitDiff: false,
191+
blocks: [],
192+
addedLines: 12,
193+
deletedLines: 41,
194+
language: 'js',
195+
oldName: 'my/file/name.js',
196+
newName: 'my/file/name.js',
197+
},
198+
];
199+
const fileHtml = fileListRenderer.render(files);
200+
expect(fileHtml).toMatchInlineSnapshot(`
201+
"<div class="d2h-file-list-wrapper d2h-dark-color-scheme">
202+
<div class="d2h-file-list-header">
203+
<span class="d2h-file-list-title">Files changed (1)</span>
204+
<a class="d2h-file-switch d2h-hide">hide</a>
205+
<a class="d2h-file-switch d2h-show">show</a>
206+
</div>
207+
<ol class="d2h-file-list">
208+
<li class="d2h-file-list-line">
209+
<span class="d2h-file-name-wrapper">
210+
<svg aria-hidden="true" class="d2h-icon d2h-changed" height="16" title="modified" version="1.1"
211+
viewBox="0 0 14 16" width="14">
212+
<path d="M13 1H1C0.45 1 0 1.45 0 2v12c0 0.55 0.45 1 1 1h12c0.55 0 1-0.45 1-1V2c0-0.55-0.45-1-1-1z m0 13H1V2h12v12zM4 8c0-1.66 1.34-3 3-3s3 1.34 3 3-1.34 3-3 3-3-1.34-3-3z"></path>
213+
</svg> <a href="#d2h-781444" class="d2h-file-name">my/file/name.js</a>
214+
<span class="d2h-file-stats">
215+
<span class="d2h-lines-added">+12</span>
216+
<span class="d2h-lines-deleted">-41</span>
217+
</span>
218+
</span>
219+
</li>
220+
</ol>
221+
</div>"
222+
`);
223+
});
224+
});
225+
226+
describe('with auto colorScheme', () => {
227+
it('should include auto colorScheme', () => {
228+
const hoganUtils = new HoganJsUtils({});
229+
const fileListRenderer = new FileListRenderer(hoganUtils, {
230+
colorScheme: ColorSchemeType.AUTO,
231+
});
232+
233+
const files = [
234+
{
235+
isCombined: false,
236+
isGitDiff: false,
237+
blocks: [],
238+
addedLines: 12,
239+
deletedLines: 41,
240+
language: 'js',
241+
oldName: 'my/file/name.js',
242+
newName: 'my/file/name.js',
243+
},
244+
];
245+
const fileHtml = fileListRenderer.render(files);
246+
expect(fileHtml).toMatchInlineSnapshot(`
247+
"<div class="d2h-file-list-wrapper d2h-auto-color-scheme">
248+
<div class="d2h-file-list-header">
249+
<span class="d2h-file-list-title">Files changed (1)</span>
250+
<a class="d2h-file-switch d2h-hide">hide</a>
251+
<a class="d2h-file-switch d2h-show">show</a>
252+
</div>
253+
<ol class="d2h-file-list">
254+
<li class="d2h-file-list-line">
255+
<span class="d2h-file-name-wrapper">
256+
<svg aria-hidden="true" class="d2h-icon d2h-changed" height="16" title="modified" version="1.1"
257+
viewBox="0 0 14 16" width="14">
258+
<path d="M13 1H1C0.45 1 0 1.45 0 2v12c0 0.55 0.45 1 1 1h12c0.55 0 1-0.45 1-1V2c0-0.55-0.45-1-1-1z m0 13H1V2h12v12zM4 8c0-1.66 1.34-3 3-3s3 1.34 3 3-1.34 3-3 3-3-1.34-3-3z"></path>
259+
</svg> <a href="#d2h-781444" class="d2h-file-name">my/file/name.js</a>
260+
<span class="d2h-file-stats">
261+
<span class="d2h-lines-added">+12</span>
262+
<span class="d2h-lines-deleted">-41</span>
263+
</span>
264+
</span>
265+
</li>
266+
</ol>
267+
</div>"
268+
`);
269+
});
270+
});
175271
});
176272
});

src/__tests__/line-by-line-tests.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -449,7 +449,7 @@ describe('LineByLineRenderer', () => {
449449
});
450450
const html = lineByLineRenderer.render(exampleJson);
451451
expect(html).toMatchInlineSnapshot(`
452-
"<div class="d2h-wrapper">
452+
"<div class="d2h-wrapper d2h-light-color-scheme">
453453
<div id="d2h-675094" class="d2h-file-wrapper" data-lang="txt">
454454
<div class="d2h-file-header">
455455
<span class="d2h-file-name-wrapper">
@@ -523,7 +523,7 @@ describe('LineByLineRenderer', () => {
523523
});
524524
const html = lineByLineRenderer.render(exampleJson);
525525
expect(html).toMatchInlineSnapshot(`
526-
"<div class="d2h-wrapper">
526+
"<div class="d2h-wrapper d2h-light-color-scheme">
527527
<div id="d2h-675094" class="d2h-file-wrapper" data-lang="js">
528528
<div class="d2h-file-header">
529529
<span class="d2h-file-name-wrapper">
@@ -583,7 +583,7 @@ describe('LineByLineRenderer', () => {
583583
const lineByLineRenderer = new LineByLineRenderer(hoganUtils);
584584
const html = lineByLineRenderer.render(exampleJson);
585585
expect(html).toMatchInlineSnapshot(`
586-
"<div class="d2h-wrapper">
586+
"<div class="d2h-wrapper d2h-light-color-scheme">
587587
<div id="d2h-675094" class="d2h-file-wrapper" data-lang="js">
588588
<div class="d2h-file-header">
589589
<span class="d2h-file-name-wrapper">

src/__tests__/side-by-side-printer-tests.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -278,7 +278,7 @@ describe('SideBySideRenderer', () => {
278278
const sideBySideRenderer = new SideBySideRenderer(hoganUtils, { matching: LineMatchingType.LINES });
279279
const html = sideBySideRenderer.render(exampleJson);
280280
expect(html).toMatchInlineSnapshot(`
281-
"<div class="d2h-wrapper">
281+
"<div class="d2h-wrapper d2h-light-color-scheme">
282282
<div id="d2h-675094" class="d2h-file-wrapper" data-lang="txt">
283283
<div class="d2h-file-header">
284284
<span class="d2h-file-name-wrapper">
@@ -363,7 +363,7 @@ describe('SideBySideRenderer', () => {
363363
const sideBySideRenderer = new SideBySideRenderer(hoganUtils, {});
364364
const html = sideBySideRenderer.render(exampleJson);
365365
expect(html).toMatchInlineSnapshot(`
366-
"<div class="d2h-wrapper">
366+
"<div class="d2h-wrapper d2h-light-color-scheme">
367367
<div id="d2h-675094" class="d2h-file-wrapper" data-lang="js">
368368
<div class="d2h-file-header">
369369
<span class="d2h-file-name-wrapper">
@@ -434,7 +434,7 @@ describe('SideBySideRenderer', () => {
434434
const sideBySideRenderer = new SideBySideRenderer(hoganUtils);
435435
const html = sideBySideRenderer.render(exampleJson);
436436
expect(html).toMatchInlineSnapshot(`
437-
"<div class="d2h-wrapper">
437+
"<div class="d2h-wrapper d2h-light-color-scheme">
438438
<div id="d2h-675094" class="d2h-file-wrapper" data-lang="js">
439439
<div class="d2h-file-header">
440440
<span class="d2h-file-name-wrapper">

src/diff2html.ts

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import * as DiffParser from './diff-parser';
2-
import * as fileListPrinter from './file-list-renderer';
2+
import { FileListRenderer } from './file-list-renderer';
33
import LineByLineRenderer, { LineByLineRendererConfig, defaultLineByLineRendererConfig } from './line-by-line-renderer';
44
import SideBySideRenderer, { SideBySideRendererConfig, defaultSideBySideRendererConfig } from './side-by-side-renderer';
55
import { DiffFile, OutputFormatType } from './types';
@@ -32,7 +32,10 @@ export function html(diffInput: string | DiffFile[], configuration: Diff2HtmlCon
3232

3333
const hoganUtils = new HoganJsUtils(config);
3434

35-
const fileList = config.drawFileList ? fileListPrinter.render(diffJson, hoganUtils) : '';
35+
const { colorScheme } = config;
36+
const fileListRendererConfig = { colorScheme };
37+
38+
const fileList = config.drawFileList ? new FileListRenderer(hoganUtils, fileListRendererConfig).render(diffJson) : '';
3639

3740
const diffOutput =
3841
config.outputFormat === 'side-by-side'

src/file-list-renderer.ts

Lines changed: 44 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -1,33 +1,52 @@
11
import * as renderUtils from './render-utils';
22
import HoganJsUtils from './hoganjs-utils';
3-
import { DiffFile } from './types';
3+
import { ColorSchemeType, DiffFile } from './types';
44

55
const baseTemplatesPath = 'file-summary';
66
const iconsBaseTemplatesPath = 'icon';
77

8-
export function render(diffFiles: DiffFile[], hoganUtils: HoganJsUtils): string {
9-
const files = diffFiles
10-
.map(file =>
11-
hoganUtils.render(
12-
baseTemplatesPath,
13-
'line',
14-
{
15-
fileHtmlId: renderUtils.getHtmlId(file),
16-
oldName: file.oldName,
17-
newName: file.newName,
18-
fileName: renderUtils.filenameDiff(file),
19-
deletedLines: '-' + file.deletedLines,
20-
addedLines: '+' + file.addedLines,
21-
},
22-
{
23-
fileIcon: hoganUtils.template(iconsBaseTemplatesPath, renderUtils.getFileIcon(file)),
24-
},
25-
),
26-
)
27-
.join('\n');
8+
export interface FileListRendererConfig {
9+
colorScheme?: ColorSchemeType;
10+
}
11+
12+
export const defaultFileListRendererConfig = {
13+
colorScheme: renderUtils.defaultRenderConfig.colorScheme,
14+
};
15+
16+
export class FileListRenderer {
17+
private readonly hoganUtils: HoganJsUtils;
18+
private readonly config: typeof defaultFileListRendererConfig;
19+
20+
constructor(hoganUtils: HoganJsUtils, config: FileListRendererConfig = {}) {
21+
this.hoganUtils = hoganUtils;
22+
this.config = { ...defaultFileListRendererConfig, ...config };
23+
}
24+
25+
render(diffFiles: DiffFile[]): string {
26+
const files = diffFiles
27+
.map(file =>
28+
this.hoganUtils.render(
29+
baseTemplatesPath,
30+
'line',
31+
{
32+
fileHtmlId: renderUtils.getHtmlId(file),
33+
oldName: file.oldName,
34+
newName: file.newName,
35+
fileName: renderUtils.filenameDiff(file),
36+
deletedLines: '-' + file.deletedLines,
37+
addedLines: '+' + file.addedLines,
38+
},
39+
{
40+
fileIcon: this.hoganUtils.template(iconsBaseTemplatesPath, renderUtils.getFileIcon(file)),
41+
},
42+
),
43+
)
44+
.join('\n');
2845

29-
return hoganUtils.render(baseTemplatesPath, 'wrapper', {
30-
filesNumber: diffFiles.length,
31-
files: files,
32-
});
46+
return this.hoganUtils.render(baseTemplatesPath, 'wrapper', {
47+
colorScheme: renderUtils.colorSchemeToCss(this.config.colorScheme),
48+
filesNumber: diffFiles.length,
49+
files: files,
50+
});
51+
}
3352
}

src/line-by-line-renderer.ts

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,10 @@ export default class LineByLineRenderer {
5252
})
5353
.join('\n');
5454

55-
return this.hoganUtils.render(genericTemplatesPath, 'wrapper', { content: diffsHtml });
55+
return this.hoganUtils.render(genericTemplatesPath, 'wrapper', {
56+
colorScheme: renderUtils.colorSchemeToCss(this.config.colorScheme),
57+
content: diffsHtml,
58+
});
5659
}
5760

5861
makeFileDiffHtml(file: DiffFile, diffs: string): string {

0 commit comments

Comments
 (0)
0