react-diff-viewer-continued 4.0.1 → 4.0.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,12 +1,31 @@
1
- name: Release
1
+ name: Test & Release
2
2
  on:
3
3
  push:
4
- branches:
5
- - master
6
- - next
4
+
7
5
  jobs:
6
+ test:
7
+ name: Unit tests
8
+ runs-on: ubuntu-latest
9
+ steps:
10
+ - name: Checkout
11
+ uses: actions/checkout@v3
12
+ with:
13
+ fetch-depth: 0
14
+ - name: Setup Node.js
15
+ uses: actions/setup-node@v3
16
+ with:
17
+ node-version: 'lts/*'
18
+ - uses: pnpm/action-setup@v2.2.4
19
+ with:
20
+ version: latest
21
+ - name: Install dependencies
22
+ run: pnpm i
23
+ - name: Run unit tests
24
+ run: pnpm run test
8
25
  release:
9
26
  name: Release
27
+ needs: test
28
+ if: github.ref == 'refs/heads/master' || github.ref == 'refs/heads/next'
10
29
  runs-on: ubuntu-latest
11
30
  steps:
12
31
  - name: Checkout
@@ -5,4 +5,7 @@
5
5
  <orderEntry type="inheritedJdk" />
6
6
  <orderEntry type="sourceFolder" forTests="false" />
7
7
  </component>
8
+ <component name="SonarLintModuleSettings">
9
+ <option name="uniqueId" value="5762f64b-7b0e-41a1-a2ec-f15fa70aa6a1" />
10
+ </component>
8
11
  </module>
package/CHANGELOG.md CHANGED
@@ -1,3 +1,10 @@
1
+ ## [4.0.2](https://github.com/aeolun/react-diff-viewer-continued/compare/v4.0.1...v4.0.2) (2024-02-14)
2
+
3
+
4
+ ### Bug Fixes
5
+
6
+ * revert back to table based layout, add example image (fixes [#35](https://github.com/aeolun/react-diff-viewer-continued/issues/35), [#15](https://github.com/aeolun/react-diff-viewer-continued/issues/15), [#21](https://github.com/aeolun/react-diff-viewer-continued/issues/21)) ([a1571ab](https://github.com/aeolun/react-diff-viewer-continued/commit/a1571ab9940c8b917c2e845f537780e4b45efb01))
7
+
1
8
  ## [4.0.1](https://github.com/aeolun/react-diff-viewer-continued/compare/v4.0.0...v4.0.1) (2023-11-01)
2
9
 
3
10
 
package/LICENSE CHANGED
@@ -1,6 +1,6 @@
1
1
  MIT License
2
2
 
3
- Copyright (c) 2018 Pranesh Ravi
3
+ Copyright (c) 2023 Bart Riepe
4
4
 
5
5
  Permission is hereby granted, free of charge, to any person obtaining a copy
6
6
  of this software and associated documentation files (the "Software"), to deal
package/README.md CHANGED
@@ -12,6 +12,8 @@
12
12
 
13
13
  A simple and beautiful text diff viewer component made with [Diff](https://github.com/kpdecker/jsdiff) and [React](https://reactjs.org).
14
14
 
15
+ ![example image](./example.jpg)
16
+
15
17
  Inspired by the Github diff viewer, it includes features like split view, inline view, word diff, line highlight and more. It is highly customizable and it supports almost all languages.
16
18
 
17
19
  Most credit goes to [Pranesh Ravi](https://praneshravi.in) who created the [original diff viewer](https://github.com/praneshr/react-diff-viewer). I've just made a few modifications and updated the dependencies so they work with modern stacks.
package/example.jpg ADDED
Binary file
@@ -0,0 +1 @@
1
+ export declare function Expand(): import("react/jsx-runtime").JSX.Element;
@@ -0,0 +1 @@
1
+ export declare function Fold(): import("react/jsx-runtime").JSX.Element;
@@ -45,6 +45,7 @@ export interface ReactDiffViewerProps {
45
45
  }
46
46
  export interface ReactDiffViewerState {
47
47
  expandedBlocks?: number[];
48
+ noSelect?: 'left' | 'right';
48
49
  }
49
50
  declare class DiffViewer extends React.Component<ReactDiffViewerProps, ReactDiffViewerState> {
50
51
  private styles;
@@ -112,10 +113,7 @@ declare class DiffViewer extends React.Component<ReactDiffViewerProps, ReactDiff
112
113
  * @param obj.right Life diff information for the removed section of the inline view.
113
114
  * @param index React key for the lines.
114
115
  */
115
- renderInlineView: ({ left, right }: LineInformation, index: number) => {
116
- left: ReactElement[];
117
- right: ReactElement[];
118
- };
116
+ renderInlineView: ({ left, right }: LineInformation, index: number) => ReactElement;
119
117
  /**
120
118
  * Returns a function with clicked block number in the closure.
121
119
  *
@@ -139,4 +137,5 @@ declare class DiffViewer extends React.Component<ReactDiffViewerProps, ReactDiff
139
137
  render: () => ReactElement;
140
138
  }
141
139
  export default DiffViewer;
142
- export { ReactDiffViewerStylesOverride, DiffMethod };
140
+ export { DiffMethod };
141
+ export type { ReactDiffViewerStylesOverride };
@@ -35,9 +35,8 @@ Object.defineProperty(exports, "DiffMethod", { enumerable: true, get: function (
35
35
  const styles_1 = __importDefault(require("./styles"));
36
36
  const compute_hidden_blocks_1 = require("./compute-hidden-blocks");
37
37
  const expand_1 = require("./expand");
38
+ const memoize_one_1 = __importDefault(require("memoize-one"));
38
39
  const fold_1 = require("./fold");
39
- const m = require('memoize-one');
40
- const memoize = m.default || m;
41
40
  var LineNumberPrefix;
42
41
  (function (LineNumberPrefix) {
43
42
  LineNumberPrefix["LEFT"] = "L";
@@ -76,7 +75,7 @@ class DiffViewer extends React.Component {
76
75
  *
77
76
  * @param styles User supplied style overrides.
78
77
  */
79
- this.computeStyles = memoize(styles_1.default);
78
+ this.computeStyles = (0, memoize_one_1.default)(styles_1.default);
80
79
  /**
81
80
  * Returns a function with clicked line number in the closure. Returns an no-op function when no
82
81
  * onLineNumberClick handler is supplied.
@@ -98,6 +97,8 @@ class DiffViewer extends React.Component {
98
97
  this.renderWordDiff = (diffArray, renderer) => {
99
98
  return diffArray.map((wordDiff, i) => {
100
99
  const content = renderer ? renderer(wordDiff.value) : wordDiff.value;
100
+ if (typeof content !== 'string')
101
+ return;
101
102
  return wordDiff.type === compute_lines_1.DiffType.ADDED ?
102
103
  (0, jsx_runtime_1.jsx)("ins", { className: (0, classnames_1.default)(this.styles.wordDiff, {
103
104
  [this.styles.wordAdded]: wordDiff.type === compute_lines_1.DiffType.ADDED,
@@ -146,13 +147,13 @@ class DiffViewer extends React.Component {
146
147
  else if (removed && !hasWordDiff) {
147
148
  ElementType = 'del';
148
149
  }
149
- return ((0, jsx_runtime_1.jsxs)(ElementType, { className: this.styles.line, role: 'row', title: added && !hasWordDiff ? "Added line" : removed && !hasWordDiff ? "Removed line" : undefined, children: [!this.props.hideLineNumbers && ((0, jsx_runtime_1.jsx)("div", { onClick: lineNumber && this.onLineNumberClickProxy(lineNumberTemplate), className: (0, classnames_1.default)(this.styles.gutter, {
150
+ return ((0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [!this.props.hideLineNumbers && ((0, jsx_runtime_1.jsx)("td", { onClick: lineNumber && this.onLineNumberClickProxy(lineNumberTemplate), className: (0, classnames_1.default)(this.styles.gutter, {
150
151
  [this.styles.emptyGutter]: !lineNumber,
151
152
  [this.styles.diffAdded]: added,
152
153
  [this.styles.diffRemoved]: removed,
153
154
  [this.styles.diffChanged]: changed,
154
155
  [this.styles.highlightedGutter]: highlightLine,
155
- }), children: (0, jsx_runtime_1.jsx)("pre", { className: this.styles.lineNumber, children: lineNumber }) })), !this.props.splitView && !this.props.hideLineNumbers && ((0, jsx_runtime_1.jsx)("div", { onClick: additionalLineNumber &&
156
+ }), children: (0, jsx_runtime_1.jsx)("pre", { className: this.styles.lineNumber, children: lineNumber }) })), !this.props.splitView && !this.props.hideLineNumbers && ((0, jsx_runtime_1.jsx)("td", { onClick: additionalLineNumber &&
156
157
  this.onLineNumberClickProxy(additionalLineNumberTemplate), className: (0, classnames_1.default)(this.styles.gutter, {
157
158
  [this.styles.emptyGutter]: !additionalLineNumber,
158
159
  [this.styles.diffAdded]: added,
@@ -169,19 +170,27 @@ class DiffViewer extends React.Component {
169
170
  additionalPrefix,
170
171
  styles: this.styles,
171
172
  })
172
- : null, (0, jsx_runtime_1.jsx)("div", { className: (0, classnames_1.default)(this.styles.marker, {
173
+ : null, (0, jsx_runtime_1.jsx)("td", { className: (0, classnames_1.default)(this.styles.marker, {
173
174
  [this.styles.emptyLine]: !content,
174
175
  [this.styles.diffAdded]: added,
175
176
  [this.styles.diffRemoved]: removed,
176
177
  [this.styles.diffChanged]: changed,
177
178
  [this.styles.highlightedLine]: highlightLine,
178
- }), children: (0, jsx_runtime_1.jsxs)("pre", { children: [added && '+', removed && '-'] }) }), (0, jsx_runtime_1.jsx)("div", { className: (0, classnames_1.default)(this.styles.lineContent, {
179
+ }), children: (0, jsx_runtime_1.jsxs)("pre", { children: [added && '+', removed && '-'] }) }), (0, jsx_runtime_1.jsx)("td", { className: (0, classnames_1.default)(this.styles.content, {
179
180
  [this.styles.emptyLine]: !content,
180
181
  [this.styles.diffAdded]: added,
181
182
  [this.styles.diffRemoved]: removed,
182
183
  [this.styles.diffChanged]: changed,
183
184
  [this.styles.highlightedLine]: highlightLine,
184
- }), children: (0, jsx_runtime_1.jsx)("pre", { className: this.styles.contentText, children: content }) })] }));
185
+ left: prefix === LineNumberPrefix.LEFT,
186
+ right: prefix === LineNumberPrefix.RIGHT,
187
+ }), onMouseDown: () => {
188
+ const elements = document.getElementsByClassName(prefix === LineNumberPrefix.LEFT ? 'right' : 'left');
189
+ for (let i = 0; i < elements.length; i++) {
190
+ const element = elements.item(i);
191
+ element.classList.add(this.styles.noSelect);
192
+ }
193
+ }, title: added && !hasWordDiff ? "Added line" : removed && !hasWordDiff ? "Removed line" : undefined, children: (0, jsx_runtime_1.jsx)(ElementType, { className: this.styles.contentText, children: content }) })] }));
185
194
  };
186
195
  /**
187
196
  * Generates lines for split view.
@@ -192,14 +201,7 @@ class DiffViewer extends React.Component {
192
201
  * @param index React key for the lines.
193
202
  */
194
203
  this.renderSplitView = ({ left, right }, index) => {
195
- return {
196
- left: [
197
- this.renderLine(left.lineNumber, left.type, LineNumberPrefix.LEFT, left.value)
198
- ],
199
- right: [
200
- this.renderLine(right.lineNumber, right.type, LineNumberPrefix.RIGHT, right.value)
201
- ]
202
- };
204
+ return ((0, jsx_runtime_1.jsxs)("tr", { className: this.styles.line, children: [this.renderLine(left.lineNumber, left.type, LineNumberPrefix.LEFT, left.value), this.renderLine(right.lineNumber, right.type, LineNumberPrefix.RIGHT, right.value)] }, index));
203
205
  };
204
206
  /**
205
207
  * Generates lines for inline view.
@@ -212,42 +214,18 @@ class DiffViewer extends React.Component {
212
214
  this.renderInlineView = ({ left, right }, index) => {
213
215
  let content;
214
216
  if (left.type === compute_lines_1.DiffType.REMOVED && right.type === compute_lines_1.DiffType.ADDED) {
215
- return {
216
- left: [
217
- this.renderLine(left.lineNumber, left.type, LineNumberPrefix.LEFT, left.value, null),
218
- this.renderLine(null, right.type, LineNumberPrefix.RIGHT, right.value, right.lineNumber)
219
- ],
220
- right: []
221
- };
217
+ return ((0, jsx_runtime_1.jsxs)(React.Fragment, { children: [(0, jsx_runtime_1.jsx)("tr", { className: this.styles.line, children: this.renderLine(left.lineNumber, left.type, LineNumberPrefix.LEFT, left.value, null) }), (0, jsx_runtime_1.jsx)("tr", { className: this.styles.line, children: this.renderLine(null, right.type, LineNumberPrefix.RIGHT, right.value, right.lineNumber) })] }, index));
222
218
  }
223
219
  if (left.type === compute_lines_1.DiffType.REMOVED) {
224
- return {
225
- left: [
226
- this.renderLine(left.lineNumber, left.type, LineNumberPrefix.LEFT, left.value, null)
227
- ],
228
- right: []
229
- };
220
+ content = this.renderLine(left.lineNumber, left.type, LineNumberPrefix.LEFT, left.value, null);
230
221
  }
231
222
  if (left.type === compute_lines_1.DiffType.DEFAULT) {
232
- return {
233
- left: [
234
- this.renderLine(left.lineNumber, left.type, LineNumberPrefix.LEFT, left.value, right.lineNumber, LineNumberPrefix.RIGHT)
235
- ],
236
- right: []
237
- };
223
+ content = this.renderLine(left.lineNumber, left.type, LineNumberPrefix.LEFT, left.value, right.lineNumber, LineNumberPrefix.RIGHT);
238
224
  }
239
225
  if (right.type === compute_lines_1.DiffType.ADDED) {
240
- return {
241
- left: [
242
- this.renderLine(null, right.type, LineNumberPrefix.RIGHT, right.value, right.lineNumber)
243
- ],
244
- right: []
245
- };
226
+ content = this.renderLine(null, right.type, LineNumberPrefix.RIGHT, right.value, right.lineNumber);
246
227
  }
247
- return {
248
- left: [],
249
- right: []
250
- };
228
+ return ((0, jsx_runtime_1.jsx)("tr", { className: this.styles.line, children: content }, index));
251
229
  };
252
230
  /**
253
231
  * Returns a function with clicked block number in the closure.
@@ -267,14 +245,11 @@ class DiffViewer extends React.Component {
267
245
  this.renderSkippedLineIndicator = (num, blockNumber, leftBlockLineNumber, rightBlockLineNumber) => {
268
246
  const { hideLineNumbers, splitView } = this.props;
269
247
  const message = this.props.codeFoldMessageRenderer ? (this.props.codeFoldMessageRenderer(num, leftBlockLineNumber, rightBlockLineNumber)) : ((0, jsx_runtime_1.jsxs)("pre", { className: this.styles.codeFoldContent, children: ["Expand ", num, " lines ..."] }));
270
- const content = ((0, jsx_runtime_1.jsx)("div", { className: this.styles.codeFoldContentContainer, children: (0, jsx_runtime_1.jsx)("a", { onClick: this.onBlockClickProxy(blockNumber), tabIndex: 0, children: message }) }));
248
+ const content = ((0, jsx_runtime_1.jsx)("td", { className: this.styles.codeFoldContentContainer, children: (0, jsx_runtime_1.jsx)("a", { onClick: this.onBlockClickProxy(blockNumber), tabIndex: 0, children: message }) }));
271
249
  const isUnifiedViewWithoutLineNumbers = !splitView && !hideLineNumbers;
272
- return {
273
- left: [(0, jsx_runtime_1.jsxs)("div", { className: this.styles.codeFold, children: [!hideLineNumbers && (0, jsx_runtime_1.jsx)("div", { className: this.styles.codeFoldGutter }), this.props.renderGutter ? ((0, jsx_runtime_1.jsx)("div", { className: this.styles.codeFoldGutter })) : null, (0, jsx_runtime_1.jsx)("div", { className: (0, classnames_1.default)({
274
- [this.styles.codeFoldGutter]: isUnifiedViewWithoutLineNumbers,
275
- }) }), isUnifiedViewWithoutLineNumbers ? ((0, jsx_runtime_1.jsx)(React.Fragment, { children: content })) : ((0, jsx_runtime_1.jsx)(React.Fragment, { children: content }))] }, this.props.splitView ? `${leftBlockLineNumber}` : `${leftBlockLineNumber}-${rightBlockLineNumber}`)],
276
- right: this.props.splitView ? [(0, jsx_runtime_1.jsx)("div", { className: this.styles.codeFold }, `${rightBlockLineNumber}`)] : []
277
- };
250
+ return ((0, jsx_runtime_1.jsxs)("tr", { className: this.styles.codeFold, children: [!hideLineNumbers && (0, jsx_runtime_1.jsx)("td", { className: this.styles.codeFoldGutter }), this.props.renderGutter ? ((0, jsx_runtime_1.jsx)("td", { className: this.styles.codeFoldGutter })) : null, (0, jsx_runtime_1.jsx)("td", { className: (0, classnames_1.default)({
251
+ [this.styles.codeFoldGutter]: isUnifiedViewWithoutLineNumbers,
252
+ }) }), isUnifiedViewWithoutLineNumbers ? ((0, jsx_runtime_1.jsxs)(React.Fragment, { children: [(0, jsx_runtime_1.jsx)("td", {}), content] })) : ((0, jsx_runtime_1.jsxs)(React.Fragment, { children: [content, this.props.renderGutter ? (0, jsx_runtime_1.jsx)("td", {}) : null, (0, jsx_runtime_1.jsx)("td", {}), (0, jsx_runtime_1.jsx)("td", {}), !hideLineNumbers ? (0, jsx_runtime_1.jsx)("td", {}) : null] }))] }, `${leftBlockLineNumber}-${rightBlockLineNumber}`));
278
253
  };
279
254
  /**
280
255
  * Generates the entire diff view.
@@ -286,30 +261,28 @@ class DiffViewer extends React.Component {
286
261
  ? 0
287
262
  : Math.round(this.props.extraLinesSurroundingDiff);
288
263
  const { lineBlocks, blocks } = (0, compute_hidden_blocks_1.computeHiddenBlocks)(lineInformation, diffLines, extraLines);
289
- const leftLines = [];
290
- const rightLines = [];
291
- lineInformation.forEach((line, lineIndex) => {
264
+ const diffNodes = lineInformation.map((line, lineIndex) => {
292
265
  if (this.props.showDiffOnly) {
293
266
  const blockIndex = lineBlocks[lineIndex];
294
267
  if (blockIndex !== undefined) {
295
268
  const lastLineOfBlock = blocks[blockIndex].endLine === lineIndex;
296
269
  if (!this.state.expandedBlocks.includes(blockIndex) && lastLineOfBlock) {
297
- const { left, right } = this.renderSkippedLineIndicator(blocks[blockIndex].lines, blockIndex, line.left.lineNumber, line.right.lineNumber);
298
- leftLines.push(...left);
299
- rightLines.push(...right);
270
+ return ((0, jsx_runtime_1.jsx)(React.Fragment, { children: this.renderSkippedLineIndicator(blocks[blockIndex].lines, blockIndex, line.left.lineNumber, line.right.lineNumber) }, lineIndex));
300
271
  }
301
272
  else if (!this.state.expandedBlocks.includes(blockIndex)) {
302
273
  return null;
303
274
  }
304
275
  }
305
276
  }
306
- const { left, right } = splitView
277
+ return splitView
307
278
  ? this.renderSplitView(line, lineIndex)
308
279
  : this.renderInlineView(line, lineIndex);
309
- leftLines.push(...left);
310
- rightLines.push(...right);
311
280
  });
312
- return { leftLines, rightLines, lineInformation, blocks };
281
+ return {
282
+ diffNodes,
283
+ blocks,
284
+ lineInformation
285
+ };
313
286
  };
314
287
  this.render = () => {
315
288
  const { oldValue, newValue, useDarkTheme, leftTitle, rightTitle, splitView, hideLineNumbers, nonce, } = this.props;
@@ -320,6 +293,16 @@ class DiffViewer extends React.Component {
320
293
  }
321
294
  this.styles = this.computeStyles(this.props.styles, useDarkTheme, nonce);
322
295
  const nodes = this.renderDiff();
296
+ let colSpanOnSplitView = 3;
297
+ let colSpanOnInlineView = 4;
298
+ if (hideLineNumbers) {
299
+ colSpanOnSplitView -= 1;
300
+ colSpanOnInlineView -= 1;
301
+ }
302
+ if (this.props.renderGutter) {
303
+ colSpanOnSplitView += 1;
304
+ colSpanOnInlineView += 1;
305
+ }
323
306
  let deletions = 0, additions = 0;
324
307
  nodes.lineInformation.forEach((l) => {
325
308
  if (l.left.type === compute_lines_1.DiffType.ADDED) {
@@ -351,12 +334,24 @@ class DiffViewer extends React.Component {
351
334
  this.setState({
352
335
  expandedBlocks: allExpanded ? [] : nodes.blocks.map(b => b.index)
353
336
  });
354
- }, children: allExpanded ? (0, jsx_runtime_1.jsx)(fold_1.Fold, {}) : (0, jsx_runtime_1.jsx)(expand_1.Expand, {}) }), " ", totalChanges, " ", (0, jsx_runtime_1.jsx)("div", { style: { display: 'flex', gap: '1px' }, children: blocks }), " ", this.props.summary ? (0, jsx_runtime_1.jsx)("span", { children: this.props.summary }) : null] }), (0, jsx_runtime_1.jsxs)("div", { className: (0, classnames_1.default)(this.styles.diffContainer, {
337
+ }, children: allExpanded ? (0, jsx_runtime_1.jsx)(fold_1.Fold, {}) : (0, jsx_runtime_1.jsx)(expand_1.Expand, {}) }), " ", totalChanges, (0, jsx_runtime_1.jsx)("div", { style: { display: 'flex', gap: '1px' }, children: blocks }), this.props.summary ? (0, jsx_runtime_1.jsx)("span", { children: this.props.summary }) : null] }), (0, jsx_runtime_1.jsx)("table", { className: (0, classnames_1.default)(this.styles.diffContainer, {
355
338
  [this.styles.splitView]: splitView,
356
- }), children: [(0, jsx_runtime_1.jsxs)("div", { className: this.styles.column, role: 'table', title: `Diff information for ${leftTitle}`, children: [leftTitle ? (0, jsx_runtime_1.jsx)("div", { className: (0, classnames_1.default)(this.styles.titleBlock, this.styles.column), role: 'columnheader', children: (0, jsx_runtime_1.jsx)("pre", { className: this.styles.contentText, children: leftTitle }) }) : null, nodes.leftLines] }), nodes.rightLines.length > 0 ? (0, jsx_runtime_1.jsxs)("div", { className: this.styles.column, role: 'table', title: `Diff information for ${rightTitle}`, children: [rightTitle ? (0, jsx_runtime_1.jsx)("div", { className: (0, classnames_1.default)(this.styles.titleBlock, this.styles.column), role: 'columnheader', children: (0, jsx_runtime_1.jsx)("pre", { className: this.styles.contentText, children: rightTitle }) }) : null, nodes.rightLines] }) : null] })] }));
339
+ }), onMouseUp: () => {
340
+ const elements = document.getElementsByClassName('right');
341
+ for (let i = 0; i < elements.length; i++) {
342
+ const element = elements.item(i);
343
+ element.classList.remove(this.styles.noSelect);
344
+ }
345
+ const elementsLeft = document.getElementsByClassName('left');
346
+ for (let i = 0; i < elementsLeft.length; i++) {
347
+ const element = elementsLeft.item(i);
348
+ element.classList.remove(this.styles.noSelect);
349
+ }
350
+ }, children: (0, jsx_runtime_1.jsxs)("tbody", { children: [(0, jsx_runtime_1.jsxs)("tr", { children: [!this.props.hideLineNumbers ? (0, jsx_runtime_1.jsx)("td", { width: '50px' }) : null, !splitView && !this.props.hideLineNumbers ? (0, jsx_runtime_1.jsx)("td", { width: '50px' }) : null, this.props.renderGutter ? (0, jsx_runtime_1.jsx)("td", { width: '50px' }) : null, (0, jsx_runtime_1.jsx)("td", { width: '28px' }), (0, jsx_runtime_1.jsx)("td", { width: '100%' }), splitView ? (0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [!this.props.hideLineNumbers ? (0, jsx_runtime_1.jsx)("td", { width: '50px' }) : null, this.props.renderGutter ? (0, jsx_runtime_1.jsx)("td", { width: '50px' }) : null, (0, jsx_runtime_1.jsx)("td", { width: '28px' }), (0, jsx_runtime_1.jsx)("td", { width: '100%' })] }) : null] }), leftTitle || rightTitle ? (0, jsx_runtime_1.jsxs)("tr", { children: [(0, jsx_runtime_1.jsx)("td", { colSpan: (splitView ? colSpanOnSplitView : colSpanOnInlineView), className: (0, classnames_1.default)(this.styles.titleBlock, this.styles.column), role: 'columnheader', children: leftTitle ? (0, jsx_runtime_1.jsx)("pre", { className: this.styles.contentText, children: leftTitle }) : null }), splitView ? (0, jsx_runtime_1.jsx)("td", { colSpan: colSpanOnSplitView, className: (0, classnames_1.default)(this.styles.titleBlock, this.styles.column), role: 'columnheader', children: rightTitle ? (0, jsx_runtime_1.jsx)("pre", { className: this.styles.contentText, children: rightTitle }) : null }) : null] }) : null, nodes.diffNodes] }) })] }));
357
351
  };
358
352
  this.state = {
359
353
  expandedBlocks: [],
354
+ noSelect: undefined,
360
355
  };
361
356
  }
362
357
  }
@@ -24,6 +24,7 @@ export interface ReactDiffViewerStyles {
24
24
  titleBlock?: string;
25
25
  content?: string;
26
26
  column?: string;
27
+ noSelect?: string;
27
28
  splitView?: string;
28
29
  [key: string]: string | undefined;
29
30
  }
@@ -79,6 +80,7 @@ export interface ReactDiffViewerStylesOverride {
79
80
  codeFold?: CSSInterpolation;
80
81
  emptyLine?: CSSInterpolation;
81
82
  content?: CSSInterpolation;
83
+ noSelect?: CSSInterpolation;
82
84
  column?: CSSInterpolation;
83
85
  titleBlock?: CSSInterpolation;
84
86
  splitView?: CSSInterpolation;
@@ -62,7 +62,7 @@ exports.default = (styleOverride, useDarkTheme = false, nonce = '') => {
62
62
  gutterBackgroundDark: '#262933',
63
63
  highlightBackground: '#2a3967',
64
64
  highlightGutterBackground: '#2d4077',
65
- codeFoldGutterBackground: '#21232b',
65
+ codeFoldGutterBackground: '#262831',
66
66
  codeFoldBackground: '#262831',
67
67
  emptyLineBackground: '#363946',
68
68
  gutterColor: '#666c87',
@@ -77,9 +77,8 @@ exports.default = (styleOverride, useDarkTheme = false, nonce = '') => {
77
77
  const variables = useDarkTheme ? themeVariables.dark : themeVariables.light;
78
78
  const { css, cx } = (0, create_instance_1.default)({ key: 'react-diff', nonce });
79
79
  const content = css({
80
- width: '100%',
80
+ width: 'auto',
81
81
  label: 'content',
82
- flex: 1
83
82
  });
84
83
  const splitView = css({
85
84
  label: 'split-view',
@@ -98,6 +97,7 @@ exports.default = (styleOverride, useDarkTheme = false, nonce = '') => {
98
97
  width: '100%',
99
98
  minWidth: '1000px',
100
99
  overflowX: 'auto',
100
+ tableLayout: 'fixed',
101
101
  background: variables.diffViewerBackground,
102
102
  pre: {
103
103
  margin: 0,
@@ -107,7 +107,6 @@ exports.default = (styleOverride, useDarkTheme = false, nonce = '') => {
107
107
  },
108
108
  label: 'diff-container',
109
109
  borderCollapse: 'collapse',
110
- display: 'flex'
111
110
  });
112
111
  const lineContent = css({
113
112
  overflow: 'hidden',
@@ -115,14 +114,22 @@ exports.default = (styleOverride, useDarkTheme = false, nonce = '') => {
115
114
  });
116
115
  const contentText = css({
117
116
  color: variables.diffViewerColor,
117
+ whiteSpace: 'pre-wrap',
118
+ fontFamily: 'monospace',
119
+ textDecoration: 'none',
118
120
  label: 'content-text',
119
121
  });
122
+ const unselectable = css({
123
+ userSelect: 'none',
124
+ label: 'unselectable',
125
+ });
120
126
  const titleBlock = css({
121
127
  background: variables.diffViewerTitleBackground,
122
128
  padding: '0.5em',
123
129
  lineHeight: '1.4em',
124
130
  height: "2.4em",
125
131
  overflow: 'hidden',
132
+ width: '50%',
126
133
  borderBottom: `1px solid ${variables.diffViewerTitleBorderColor}`,
127
134
  label: 'title-block',
128
135
  ':last-child': {
@@ -185,7 +192,8 @@ exports.default = (styleOverride, useDarkTheme = false, nonce = '') => {
185
192
  const codeFoldGutter = css({
186
193
  backgroundColor: variables.codeFoldGutterBackground,
187
194
  label: 'code-fold-gutter',
188
- minWidth: '50px'
195
+ minWidth: '50px',
196
+ width: '50px'
189
197
  });
190
198
  const codeFoldContentContainer = css({
191
199
  padding: '8px 16px'
@@ -213,7 +221,6 @@ exports.default = (styleOverride, useDarkTheme = false, nonce = '') => {
213
221
  backgroundColor: variables.codeFoldBackground,
214
222
  height: 40,
215
223
  fontSize: 14,
216
- display: 'flex',
217
224
  alignItems: 'center',
218
225
  userSelect: 'none',
219
226
  fontWeight: 700,
@@ -229,7 +236,6 @@ exports.default = (styleOverride, useDarkTheme = false, nonce = '') => {
229
236
  const emptyLine = css({
230
237
  backgroundColor: variables.emptyLineBackground,
231
238
  label: 'empty-line',
232
- flex: 1,
233
239
  });
234
240
  const marker = css({
235
241
  width: 28,
@@ -261,6 +267,7 @@ exports.default = (styleOverride, useDarkTheme = false, nonce = '') => {
261
267
  const gutter = css({
262
268
  userSelect: 'none',
263
269
  minWidth: 50,
270
+ width: '50px',
264
271
  padding: '0 10px',
265
272
  whiteSpace: 'nowrap',
266
273
  label: 'gutter',
@@ -299,13 +306,9 @@ exports.default = (styleOverride, useDarkTheme = false, nonce = '') => {
299
306
  const line = css({
300
307
  verticalAlign: 'baseline',
301
308
  label: 'line',
302
- height: '1.6em',
303
- display: 'flex',
304
309
  textDecoration: 'none'
305
310
  });
306
- const column = css({
307
- flex: 1
308
- });
311
+ const column = css({});
309
312
  const defaultStyles = {
310
313
  diffContainer,
311
314
  diffRemoved,
@@ -325,6 +328,7 @@ exports.default = (styleOverride, useDarkTheme = false, nonce = '') => {
325
328
  blockAddition,
326
329
  blockDeletion,
327
330
  wordRemoved,
331
+ noSelect: unselectable,
328
332
  codeFoldGutter,
329
333
  codeFoldContentContainer,
330
334
  codeFold,
@@ -0,0 +1,35 @@
1
+ export function computeHiddenBlocks(lineInformation, diffLines, extraLines) {
2
+ let newBlockIndex = 0;
3
+ let currentBlock;
4
+ let lineBlocks = {};
5
+ let blocks = [];
6
+ lineInformation.forEach((line, lineIndex) => {
7
+ const isDiffLine = diffLines.some(diffLine => diffLine >= lineIndex - extraLines && diffLine <= lineIndex + extraLines);
8
+ if (!isDiffLine && currentBlock == undefined) {
9
+ // block begins
10
+ currentBlock = {
11
+ index: newBlockIndex,
12
+ startLine: lineIndex,
13
+ endLine: lineIndex,
14
+ lines: 1
15
+ };
16
+ blocks.push(currentBlock);
17
+ lineBlocks[lineIndex] = currentBlock.index;
18
+ newBlockIndex++;
19
+ }
20
+ else if (!isDiffLine) {
21
+ // block continues
22
+ currentBlock.endLine = lineIndex;
23
+ currentBlock.lines++;
24
+ lineBlocks[lineIndex] = currentBlock.index;
25
+ }
26
+ else {
27
+ // not a block anymore
28
+ currentBlock = undefined;
29
+ }
30
+ });
31
+ return {
32
+ lineBlocks,
33
+ blocks: blocks
34
+ };
35
+ }