react-diff-viewer-continued 3.3.1 → 4.0.1

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.
@@ -3,6 +3,7 @@ on:
3
3
  push:
4
4
  branches:
5
5
  - master
6
+ - next
6
7
  jobs:
7
8
  release:
8
9
  name: Release
package/CHANGELOG.md CHANGED
@@ -1,9 +1,31 @@
1
- ## [3.3.1](https://github.com/aeolun/react-diff-viewer-continued/compare/v3.3.0...v3.3.1) (2023-10-18)
1
+ ## [4.0.1](https://github.com/aeolun/react-diff-viewer-continued/compare/v4.0.0...v4.0.1) (2023-11-01)
2
2
 
3
3
 
4
4
  ### Bug Fixes
5
5
 
6
- * correct imports (fixes [#31](https://github.com/aeolun/react-diff-viewer-continued/issues/31)) ([64a05a9](https://github.com/aeolun/react-diff-viewer-continued/commit/64a05a99e4cbde494597d923b73b9740cb1661cb))
6
+ * publish files on 4.x ([650c249](https://github.com/aeolun/react-diff-viewer-continued/commit/650c249c5bf1d8b27d780b65555df5ae0f5d9e2b))
7
+
8
+ # [4.0.0](https://github.com/aeolun/react-diff-viewer-continued/compare/v3.3.0...v4.0.0) (2023-10-19)
9
+
10
+
11
+ ### Bug Fixes
12
+
13
+ * do not trim trailing newlines (fixes [#27](https://github.com/aeolun/react-diff-viewer-continued/issues/27)) ([ee4d53f](https://github.com/aeolun/react-diff-viewer-continued/commit/ee4d53f8e2ba3e374b51bffef3a00d3fe6206d02))
14
+ * use semantic elements for diff elements (fixes [#23](https://github.com/aeolun/react-diff-viewer-continued/issues/23)) ([a6222c7](https://github.com/aeolun/react-diff-viewer-continued/commit/a6222c7af151e7dc29046c8eac916271866b4899))
15
+
16
+
17
+ * feat!: diff/flexbox based layout, text selectable per side (fixes #15) ([9f6c4d5](https://github.com/aeolun/react-diff-viewer-continued/commit/9f6c4d59e84ecb44761c39e172ffab6a689d5779)), closes [#15](https://github.com/aeolun/react-diff-viewer-continued/issues/15)
18
+
19
+
20
+ ### Features
21
+
22
+ * add summary element and fold expansion/folding (fixes [#22](https://github.com/aeolun/react-diff-viewer-continued/issues/22), [#21](https://github.com/aeolun/react-diff-viewer-continued/issues/21)) ([e47cbe1](https://github.com/aeolun/react-diff-viewer-continued/commit/e47cbe1286a2143b0f8078a683e96edea0ed967b))
23
+
24
+
25
+ ### BREAKING CHANGES
26
+
27
+ * This completely modifies the way react-diff-viewer-continued is rendered. The overall
28
+ layout should be more or less the same, but with the new layout probably come new bugs.
7
29
 
8
30
  # [3.3.0](https://github.com/aeolun/react-diff-viewer-continued/compare/v3.2.6...v3.3.0) (2023-10-17)
9
31
 
@@ -1,5 +1,5 @@
1
1
  import { LineInformation } from "./compute-lines";
2
- interface Block {
2
+ export interface Block {
3
3
  index: number;
4
4
  startLine: number;
5
5
  endLine: number;
@@ -112,7 +112,7 @@ const computeLineInformation = (oldString, newString, disableWordDiff = false, l
112
112
  let diffArray = [];
113
113
  // Use diffLines for strings, and diffJson for objects...
114
114
  if (typeof oldString === 'string' && typeof newString === 'string') {
115
- diffArray = diff.diffLines(oldString.trimRight(), newString.trimRight(), {
115
+ diffArray = diff.diffLines(oldString, newString, {
116
116
  newlineIsToken: false,
117
117
  ignoreWhitespace: false,
118
118
  ignoreCase: false,
@@ -0,0 +1 @@
1
+ export declare function Expand(): JSX.Element;
@@ -0,0 +1,8 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.Expand = void 0;
4
+ const jsx_runtime_1 = require("react/jsx-runtime");
5
+ function Expand() {
6
+ return (0, jsx_runtime_1.jsx)("svg", { xmlns: "http://www.w3.org/2000/svg", viewBox: "0 0 16 16", width: "16", height: "16", children: (0, jsx_runtime_1.jsx)("path", { d: "m8.177.677 2.896 2.896a.25.25 0 0 1-.177.427H8.75v1.25a.75.75 0 0 1-1.5 0V4H5.104a.25.25 0 0 1-.177-.427L7.823.677a.25.25 0 0 1 .354 0ZM7.25 10.75a.75.75 0 0 1 1.5 0V12h2.146a.25.25 0 0 1 .177.427l-2.896 2.896a.25.25 0 0 1-.354 0l-2.896-2.896A.25.25 0 0 1 5.104 12H7.25v-1.25Zm-5-2a.75.75 0 0 0 0-1.5h-.5a.75.75 0 0 0 0 1.5h.5ZM6 8a.75.75 0 0 1-.75.75h-.5a.75.75 0 0 1 0-1.5h.5A.75.75 0 0 1 6 8Zm2.25.75a.75.75 0 0 0 0-1.5h-.5a.75.75 0 0 0 0 1.5h.5ZM12 8a.75.75 0 0 1-.75.75h-.5a.75.75 0 0 1 0-1.5h.5A.75.75 0 0 1 12 8Zm2.25.75a.75.75 0 0 0 0-1.5h-.5a.75.75 0 0 0 0 1.5h.5Z" }) });
7
+ }
8
+ exports.Expand = Expand;
@@ -0,0 +1 @@
1
+ export declare function Fold(): JSX.Element;
@@ -0,0 +1,8 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.Fold = void 0;
4
+ const jsx_runtime_1 = require("react/jsx-runtime");
5
+ function Fold() {
6
+ return (0, jsx_runtime_1.jsx)("svg", { xmlns: "http://www.w3.org/2000/svg", viewBox: "0 0 16 16", width: "16", height: "16", children: (0, jsx_runtime_1.jsx)("path", { d: "M10.896 2H8.75V.75a.75.75 0 0 0-1.5 0V2H5.104a.25.25 0 0 0-.177.427l2.896 2.896a.25.25 0 0 0 .354 0l2.896-2.896A.25.25 0 0 0 10.896 2ZM8.75 15.25a.75.75 0 0 1-1.5 0V14H5.104a.25.25 0 0 1-.177-.427l2.896-2.896a.25.25 0 0 1 .354 0l2.896 2.896a.25.25 0 0 1-.177.427H8.75v1.25Zm-6.5-6.5a.75.75 0 0 0 0-1.5h-.5a.75.75 0 0 0 0 1.5h.5ZM6 8a.75.75 0 0 1-.75.75h-.5a.75.75 0 0 1 0-1.5h.5A.75.75 0 0 1 6 8Zm2.25.75a.75.75 0 0 0 0-1.5h-.5a.75.75 0 0 0 0 1.5h.5ZM12 8a.75.75 0 0 1-.75.75h-.5a.75.75 0 0 1 0-1.5h.5A.75.75 0 0 1 12 8Zm2.25.75a.75.75 0 0 0 0-1.5h-.5a.75.75 0 0 0 0 1.5h.5Z" }) });
7
+ }
8
+ exports.Fold = Fold;
@@ -1,7 +1,7 @@
1
1
  import * as React from 'react';
2
+ import { ReactElement } from 'react';
2
3
  import { DiffInformation, DiffMethod, DiffType, LineInformation } from './compute-lines';
3
4
  import { ReactDiffViewerStyles, ReactDiffViewerStylesOverride } from './styles';
4
- import { ReactElement } from "react";
5
5
  export declare enum LineNumberPrefix {
6
6
  LEFT = "L",
7
7
  RIGHT = "R"
@@ -35,6 +35,10 @@ export interface ReactDiffViewerProps {
35
35
  highlightLines?: string[];
36
36
  styles?: ReactDiffViewerStylesOverride;
37
37
  useDarkTheme?: boolean;
38
+ /**
39
+ * Used to describe the thing being diffed
40
+ */
41
+ summary?: string | ReactElement;
38
42
  leftTitle?: string | ReactElement;
39
43
  rightTitle?: string | ReactElement;
40
44
  nonce?: string;
@@ -108,7 +112,10 @@ declare class DiffViewer extends React.Component<ReactDiffViewerProps, ReactDiff
108
112
  * @param obj.right Life diff information for the removed section of the inline view.
109
113
  * @param index React key for the lines.
110
114
  */
111
- renderInlineView: ({ left, right }: LineInformation, index: number) => ReactElement;
115
+ renderInlineView: ({ left, right }: LineInformation, index: number) => {
116
+ left: ReactElement[];
117
+ right: ReactElement[];
118
+ };
112
119
  /**
113
120
  * Returns a function with clicked block number in the closure.
114
121
  *
package/lib/src/index.js CHANGED
@@ -34,6 +34,8 @@ const compute_lines_1 = require("./compute-lines");
34
34
  Object.defineProperty(exports, "DiffMethod", { enumerable: true, get: function () { return compute_lines_1.DiffMethod; } });
35
35
  const styles_1 = __importDefault(require("./styles"));
36
36
  const compute_hidden_blocks_1 = require("./compute-hidden-blocks");
37
+ const expand_1 = require("./expand");
38
+ const fold_1 = require("./fold");
37
39
  const m = require('memoize-one');
38
40
  const memoize = m.default || m;
39
41
  var LineNumberPrefix;
@@ -95,10 +97,14 @@ class DiffViewer extends React.Component {
95
97
  */
96
98
  this.renderWordDiff = (diffArray, renderer) => {
97
99
  return diffArray.map((wordDiff, i) => {
98
- return ((0, jsx_runtime_1.jsx)("span", { className: (0, classnames_1.default)(this.styles.wordDiff, {
99
- [this.styles.wordAdded]: wordDiff.type === compute_lines_1.DiffType.ADDED,
100
- [this.styles.wordRemoved]: wordDiff.type === compute_lines_1.DiffType.REMOVED,
101
- }), children: renderer ? renderer(wordDiff.value) : wordDiff.value }, i));
100
+ const content = renderer ? renderer(wordDiff.value) : wordDiff.value;
101
+ return wordDiff.type === compute_lines_1.DiffType.ADDED ?
102
+ (0, jsx_runtime_1.jsx)("ins", { className: (0, classnames_1.default)(this.styles.wordDiff, {
103
+ [this.styles.wordAdded]: wordDiff.type === compute_lines_1.DiffType.ADDED,
104
+ }), children: content }, i)
105
+ : wordDiff.type === compute_lines_1.DiffType.REMOVED ? (0, jsx_runtime_1.jsx)("del", { className: (0, classnames_1.default)(this.styles.wordDiff, {
106
+ [this.styles.wordRemoved]: wordDiff.type === compute_lines_1.DiffType.REMOVED,
107
+ }), children: content }, i) : (0, jsx_runtime_1.jsx)("span", { className: (0, classnames_1.default)(this.styles.wordDiff), children: content }, i);
102
108
  });
103
109
  };
104
110
  /**
@@ -123,7 +129,8 @@ class DiffViewer extends React.Component {
123
129
  const removed = type === compute_lines_1.DiffType.REMOVED;
124
130
  const changed = type === compute_lines_1.DiffType.CHANGED;
125
131
  let content;
126
- if (Array.isArray(value)) {
132
+ const hasWordDiff = Array.isArray(value);
133
+ if (hasWordDiff) {
127
134
  content = this.renderWordDiff(value, this.props.renderContent);
128
135
  }
129
136
  else if (this.props.renderContent) {
@@ -132,13 +139,20 @@ class DiffViewer extends React.Component {
132
139
  else {
133
140
  content = value;
134
141
  }
135
- return ((0, jsx_runtime_1.jsxs)(React.Fragment, { children: [!this.props.hideLineNumbers && ((0, jsx_runtime_1.jsx)("td", { onClick: lineNumber && this.onLineNumberClickProxy(lineNumberTemplate), className: (0, classnames_1.default)(this.styles.gutter, {
142
+ let ElementType = 'div';
143
+ if (added && !hasWordDiff) {
144
+ ElementType = 'ins';
145
+ }
146
+ else if (removed && !hasWordDiff) {
147
+ ElementType = 'del';
148
+ }
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, {
136
150
  [this.styles.emptyGutter]: !lineNumber,
137
151
  [this.styles.diffAdded]: added,
138
152
  [this.styles.diffRemoved]: removed,
139
153
  [this.styles.diffChanged]: changed,
140
154
  [this.styles.highlightedGutter]: highlightLine,
141
- }), 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 &&
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 &&
142
156
  this.onLineNumberClickProxy(additionalLineNumberTemplate), className: (0, classnames_1.default)(this.styles.gutter, {
143
157
  [this.styles.emptyGutter]: !additionalLineNumber,
144
158
  [this.styles.diffAdded]: added,
@@ -155,13 +169,13 @@ class DiffViewer extends React.Component {
155
169
  additionalPrefix,
156
170
  styles: this.styles,
157
171
  })
158
- : null, (0, jsx_runtime_1.jsx)("td", { className: (0, classnames_1.default)(this.styles.marker, {
172
+ : null, (0, jsx_runtime_1.jsx)("div", { className: (0, classnames_1.default)(this.styles.marker, {
159
173
  [this.styles.emptyLine]: !content,
160
174
  [this.styles.diffAdded]: added,
161
175
  [this.styles.diffRemoved]: removed,
162
176
  [this.styles.diffChanged]: changed,
163
177
  [this.styles.highlightedLine]: highlightLine,
164
- }), children: (0, jsx_runtime_1.jsxs)("pre", { children: [added && '+', removed && '-'] }) }), (0, jsx_runtime_1.jsx)("td", { className: (0, classnames_1.default)(this.styles.content, {
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, {
165
179
  [this.styles.emptyLine]: !content,
166
180
  [this.styles.diffAdded]: added,
167
181
  [this.styles.diffRemoved]: removed,
@@ -178,7 +192,14 @@ class DiffViewer extends React.Component {
178
192
  * @param index React key for the lines.
179
193
  */
180
194
  this.renderSplitView = ({ left, right }, index) => {
181
- 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));
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
+ };
182
203
  };
183
204
  /**
184
205
  * Generates lines for inline view.
@@ -191,18 +212,42 @@ class DiffViewer extends React.Component {
191
212
  this.renderInlineView = ({ left, right }, index) => {
192
213
  let content;
193
214
  if (left.type === compute_lines_1.DiffType.REMOVED && right.type === compute_lines_1.DiffType.ADDED) {
194
- 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));
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
+ };
195
222
  }
196
223
  if (left.type === compute_lines_1.DiffType.REMOVED) {
197
- content = this.renderLine(left.lineNumber, left.type, LineNumberPrefix.LEFT, left.value, null);
224
+ return {
225
+ left: [
226
+ this.renderLine(left.lineNumber, left.type, LineNumberPrefix.LEFT, left.value, null)
227
+ ],
228
+ right: []
229
+ };
198
230
  }
199
231
  if (left.type === compute_lines_1.DiffType.DEFAULT) {
200
- content = this.renderLine(left.lineNumber, left.type, LineNumberPrefix.LEFT, left.value, right.lineNumber, LineNumberPrefix.RIGHT);
232
+ return {
233
+ left: [
234
+ this.renderLine(left.lineNumber, left.type, LineNumberPrefix.LEFT, left.value, right.lineNumber, LineNumberPrefix.RIGHT)
235
+ ],
236
+ right: []
237
+ };
201
238
  }
202
239
  if (right.type === compute_lines_1.DiffType.ADDED) {
203
- content = this.renderLine(null, right.type, LineNumberPrefix.RIGHT, right.value, right.lineNumber);
240
+ return {
241
+ left: [
242
+ this.renderLine(null, right.type, LineNumberPrefix.RIGHT, right.value, right.lineNumber)
243
+ ],
244
+ right: []
245
+ };
204
246
  }
205
- return ((0, jsx_runtime_1.jsx)("tr", { className: this.styles.line, children: content }, index));
247
+ return {
248
+ left: [],
249
+ right: []
250
+ };
206
251
  };
207
252
  /**
208
253
  * Returns a function with clicked block number in the closure.
@@ -222,11 +267,14 @@ class DiffViewer extends React.Component {
222
267
  this.renderSkippedLineIndicator = (num, blockNumber, leftBlockLineNumber, rightBlockLineNumber) => {
223
268
  const { hideLineNumbers, splitView } = this.props;
224
269
  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 ..."] }));
225
- const content = ((0, jsx_runtime_1.jsx)("td", { children: (0, jsx_runtime_1.jsx)("a", { onClick: this.onBlockClickProxy(blockNumber), tabIndex: 0, children: message }) }));
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 }) }));
226
271
  const isUnifiedViewWithoutLineNumbers = !splitView && !hideLineNumbers;
227
- 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)({
228
- [this.styles.codeFoldGutter]: isUnifiedViewWithoutLineNumbers,
229
- }) }), 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", {}), (0, jsx_runtime_1.jsx)("td", {})] }, `${leftBlockLineNumber}-${rightBlockLineNumber}`));
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
+ };
230
278
  };
231
279
  /**
232
280
  * Generates the entire diff view.
@@ -238,24 +286,30 @@ class DiffViewer extends React.Component {
238
286
  ? 0
239
287
  : Math.round(this.props.extraLinesSurroundingDiff);
240
288
  const { lineBlocks, blocks } = (0, compute_hidden_blocks_1.computeHiddenBlocks)(lineInformation, diffLines, extraLines);
241
- return lineInformation.map((line, lineIndex) => {
289
+ const leftLines = [];
290
+ const rightLines = [];
291
+ lineInformation.forEach((line, lineIndex) => {
242
292
  if (this.props.showDiffOnly) {
243
293
  const blockIndex = lineBlocks[lineIndex];
244
294
  if (blockIndex !== undefined) {
245
295
  const lastLineOfBlock = blocks[blockIndex].endLine === lineIndex;
246
296
  if (!this.state.expandedBlocks.includes(blockIndex) && lastLineOfBlock) {
247
- return ((0, jsx_runtime_1.jsx)(React.Fragment, { children: this.renderSkippedLineIndicator(blocks[blockIndex].lines, blockIndex, line.left.lineNumber, line.right.lineNumber) }, lineIndex));
297
+ const { left, right } = this.renderSkippedLineIndicator(blocks[blockIndex].lines, blockIndex, line.left.lineNumber, line.right.lineNumber);
298
+ leftLines.push(...left);
299
+ rightLines.push(...right);
248
300
  }
249
301
  else if (!this.state.expandedBlocks.includes(blockIndex)) {
250
302
  return null;
251
303
  }
252
304
  }
253
305
  }
254
- const diffNodes = splitView
306
+ const { left, right } = splitView
255
307
  ? this.renderSplitView(line, lineIndex)
256
308
  : this.renderInlineView(line, lineIndex);
257
- return diffNodes;
309
+ leftLines.push(...left);
310
+ rightLines.push(...right);
258
311
  });
312
+ return { leftLines, rightLines, lineInformation, blocks };
259
313
  };
260
314
  this.render = () => {
261
315
  const { oldValue, newValue, useDarkTheme, leftTitle, rightTitle, splitView, hideLineNumbers, nonce, } = this.props;
@@ -266,14 +320,40 @@ class DiffViewer extends React.Component {
266
320
  }
267
321
  this.styles = this.computeStyles(this.props.styles, useDarkTheme, nonce);
268
322
  const nodes = this.renderDiff();
269
- const colSpanOnSplitView = hideLineNumbers ? 2 : 3;
270
- const colSpanOnInlineView = hideLineNumbers ? 2 : 4;
271
- let columnExtension = this.props.renderGutter ? 1 : 0;
272
- const title = (leftTitle || rightTitle) && ((0, jsx_runtime_1.jsxs)("tr", { children: [(0, jsx_runtime_1.jsx)("td", { colSpan: (splitView ? colSpanOnSplitView : colSpanOnInlineView) +
273
- columnExtension, className: this.styles.titleBlock, children: (0, jsx_runtime_1.jsx)("pre", { className: this.styles.contentText, children: leftTitle }) }), splitView && ((0, jsx_runtime_1.jsx)("td", { colSpan: colSpanOnSplitView + columnExtension, className: this.styles.titleBlock, children: (0, jsx_runtime_1.jsx)("pre", { className: this.styles.contentText, children: rightTitle }) }))] }));
274
- return ((0, jsx_runtime_1.jsx)("table", { className: (0, classnames_1.default)(this.styles.diffContainer, {
275
- [this.styles.splitView]: splitView,
276
- }), children: (0, jsx_runtime_1.jsxs)("tbody", { children: [title, nodes] }) }));
323
+ let deletions = 0, additions = 0;
324
+ nodes.lineInformation.forEach((l) => {
325
+ if (l.left.type === compute_lines_1.DiffType.ADDED) {
326
+ additions++;
327
+ }
328
+ if (l.right.type === compute_lines_1.DiffType.ADDED) {
329
+ additions++;
330
+ }
331
+ if (l.left.type === compute_lines_1.DiffType.REMOVED) {
332
+ deletions++;
333
+ }
334
+ if (l.right.type === compute_lines_1.DiffType.REMOVED) {
335
+ deletions++;
336
+ }
337
+ });
338
+ const totalChanges = deletions + additions;
339
+ const percentageAddition = Math.round((additions / totalChanges) * 100);
340
+ const blocks = [];
341
+ for (let i = 0; i < 5; i++) {
342
+ if (percentageAddition > i * 20) {
343
+ blocks.push((0, jsx_runtime_1.jsx)("span", { className: (0, classnames_1.default)(this.styles.block, this.styles.blockAddition) }, i));
344
+ }
345
+ else {
346
+ blocks.push((0, jsx_runtime_1.jsx)("span", { className: (0, classnames_1.default)(this.styles.block, this.styles.blockDeletion) }, i));
347
+ }
348
+ }
349
+ const allExpanded = this.state.expandedBlocks.length === nodes.blocks.length;
350
+ return ((0, jsx_runtime_1.jsxs)("div", { children: [(0, jsx_runtime_1.jsxs)("div", { className: this.styles.summary, role: 'banner', children: [(0, jsx_runtime_1.jsx)("a", { style: { cursor: 'pointer' }, onClick: () => {
351
+ this.setState({
352
+ expandedBlocks: allExpanded ? [] : nodes.blocks.map(b => b.index)
353
+ });
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, {
355
+ [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] })] }));
277
357
  };
278
358
  this.state = {
279
359
  expandedBlocks: [],
@@ -7,6 +7,7 @@ export interface ReactDiffViewerStyles {
7
7
  line?: string;
8
8
  highlightedGutter?: string;
9
9
  contentText?: string;
10
+ lineContent?: string;
10
11
  gutter?: string;
11
12
  highlightedLine?: string;
12
13
  lineNumber?: string;
@@ -15,11 +16,14 @@ export interface ReactDiffViewerStyles {
15
16
  wordAdded?: string;
16
17
  wordRemoved?: string;
17
18
  codeFoldGutter?: string;
19
+ summary?: string;
20
+ codeFoldContentContainer?: string;
18
21
  emptyGutter?: string;
19
22
  emptyLine?: string;
20
23
  codeFold?: string;
21
24
  titleBlock?: string;
22
25
  content?: string;
26
+ column?: string;
23
27
  splitView?: string;
24
28
  [key: string]: string | undefined;
25
29
  }
@@ -71,9 +75,11 @@ export interface ReactDiffViewerStylesOverride {
71
75
  wordAdded?: CSSInterpolation;
72
76
  wordRemoved?: CSSInterpolation;
73
77
  codeFoldGutter?: CSSInterpolation;
78
+ codeFoldContentContainer?: CSSInterpolation;
74
79
  codeFold?: CSSInterpolation;
75
80
  emptyLine?: CSSInterpolation;
76
81
  content?: CSSInterpolation;
82
+ column?: CSSInterpolation;
77
83
  titleBlock?: CSSInterpolation;
78
84
  splitView?: CSSInterpolation;
79
85
  }
package/lib/src/styles.js CHANGED
@@ -70,7 +70,7 @@ exports.default = (styleOverride, useDarkTheme = false, nonce = '') => {
70
70
  removedGutterColor: '#8c8c8c',
71
71
  codeFoldContentColor: '#656a8b',
72
72
  diffViewerTitleBackground: '#2f323e',
73
- diffViewerTitleColor: '#555a7b',
73
+ diffViewerTitleColor: '#757a9b',
74
74
  diffViewerTitleBorderColor: '#353846',
75
75
  }, (overrideVariables.dark || {})),
76
76
  };
@@ -79,27 +79,39 @@ exports.default = (styleOverride, useDarkTheme = false, nonce = '') => {
79
79
  const content = css({
80
80
  width: '100%',
81
81
  label: 'content',
82
+ flex: 1
82
83
  });
83
84
  const splitView = css({
84
- [`.${content}`]: {
85
- width: '50%',
86
- },
87
85
  label: 'split-view',
88
86
  });
87
+ const summary = css({
88
+ background: variables.diffViewerTitleBackground,
89
+ color: variables.diffViewerTitleColor,
90
+ padding: '0.5em 1em',
91
+ display: 'flex',
92
+ alignItems: 'center',
93
+ gap: '0.5em',
94
+ fontFamily: "monospace",
95
+ fill: variables.diffViewerTitleColor,
96
+ });
89
97
  const diffContainer = css({
90
98
  width: '100%',
99
+ minWidth: '1000px',
100
+ overflowX: 'auto',
91
101
  background: variables.diffViewerBackground,
92
102
  pre: {
93
103
  margin: 0,
94
104
  whiteSpace: 'pre-wrap',
95
- lineHeight: '25px',
105
+ lineHeight: '1.6em',
106
+ width: 'fit-content'
96
107
  },
97
108
  label: 'diff-container',
98
109
  borderCollapse: 'collapse',
110
+ display: 'flex'
99
111
  });
100
- const codeFoldContent = css({
101
- color: variables.codeFoldContentColor,
102
- label: 'code-fold-content',
112
+ const lineContent = css({
113
+ overflow: 'hidden',
114
+ width: '100%'
103
115
  });
104
116
  const contentText = css({
105
117
  color: variables.diffViewerColor,
@@ -107,7 +119,10 @@ exports.default = (styleOverride, useDarkTheme = false, nonce = '') => {
107
119
  });
108
120
  const titleBlock = css({
109
121
  background: variables.diffViewerTitleBackground,
110
- padding: 10,
122
+ padding: '0.5em',
123
+ lineHeight: '1.4em',
124
+ height: "2.4em",
125
+ overflow: 'hidden',
111
126
  borderBottom: `1px solid ${variables.diffViewerTitleBorderColor}`,
112
127
  label: 'title-block',
113
128
  ':last-child': {
@@ -159,20 +174,48 @@ exports.default = (styleOverride, useDarkTheme = false, nonce = '') => {
159
174
  });
160
175
  const wordAdded = css({
161
176
  background: variables.wordAddedBackground,
177
+ textDecoration: 'none',
162
178
  label: 'word-added',
163
179
  });
164
180
  const wordRemoved = css({
165
181
  background: variables.wordRemovedBackground,
182
+ textDecoration: 'none',
166
183
  label: 'word-removed',
167
184
  });
168
185
  const codeFoldGutter = css({
169
186
  backgroundColor: variables.codeFoldGutterBackground,
170
187
  label: 'code-fold-gutter',
188
+ minWidth: '50px'
189
+ });
190
+ const codeFoldContentContainer = css({
191
+ padding: '8px 16px'
192
+ });
193
+ const codeFoldContent = css({
194
+ color: variables.codeFoldContentColor,
195
+ label: 'code-fold-content',
196
+ });
197
+ const block = css({
198
+ display: 'block',
199
+ width: '10px',
200
+ height: '10px',
201
+ backgroundColor: '#ddd',
202
+ borderWidth: '1px',
203
+ borderStyle: 'solid',
204
+ borderColor: variables.diffViewerTitleBorderColor
205
+ });
206
+ const blockAddition = css({
207
+ backgroundColor: variables.wordAddedBackground
208
+ });
209
+ const blockDeletion = css({
210
+ backgroundColor: variables.wordRemovedBackground
171
211
  });
172
212
  const codeFold = css({
173
213
  backgroundColor: variables.codeFoldBackground,
174
214
  height: 40,
175
215
  fontSize: 14,
216
+ display: 'flex',
217
+ alignItems: 'center',
218
+ userSelect: 'none',
176
219
  fontWeight: 700,
177
220
  label: 'code-fold',
178
221
  a: {
@@ -186,9 +229,10 @@ exports.default = (styleOverride, useDarkTheme = false, nonce = '') => {
186
229
  const emptyLine = css({
187
230
  backgroundColor: variables.emptyLineBackground,
188
231
  label: 'empty-line',
232
+ flex: 1,
189
233
  });
190
234
  const marker = css({
191
- width: 25,
235
+ width: 28,
192
236
  paddingLeft: 10,
193
237
  paddingRight: 10,
194
238
  userSelect: 'none',
@@ -255,6 +299,12 @@ exports.default = (styleOverride, useDarkTheme = false, nonce = '') => {
255
299
  const line = css({
256
300
  verticalAlign: 'baseline',
257
301
  label: 'line',
302
+ height: '1.6em',
303
+ display: 'flex',
304
+ textDecoration: 'none'
305
+ });
306
+ const column = css({
307
+ flex: 1
258
308
  });
259
309
  const defaultStyles = {
260
310
  diffContainer,
@@ -267,16 +317,23 @@ exports.default = (styleOverride, useDarkTheme = false, nonce = '') => {
267
317
  highlightedLine,
268
318
  gutter,
269
319
  line,
320
+ lineContent,
270
321
  wordDiff,
271
322
  wordAdded,
323
+ summary,
324
+ block,
325
+ blockAddition,
326
+ blockDeletion,
272
327
  wordRemoved,
273
328
  codeFoldGutter,
329
+ codeFoldContentContainer,
274
330
  codeFold,
275
331
  emptyGutter,
276
332
  emptyLine,
277
333
  lineNumber,
278
334
  contentText,
279
335
  content,
336
+ column,
280
337
  codeFoldContent,
281
338
  titleBlock,
282
339
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "react-diff-viewer-continued",
3
- "version": "3.3.1",
3
+ "version": "4.0.1",
4
4
  "private": false,
5
5
  "description": "Continuation of a simple and beautiful text diff viewer component made with diff and React",
6
6
  "keywords": [
package/release.config.js CHANGED
@@ -1,5 +1,4 @@
1
1
  module.exports = {
2
- branches: ['master'],
3
2
  plugins: [
4
3
  '@semantic-release/commit-analyzer',
5
4
  '@semantic-release/release-notes-generator',