react-diff-viewer-continued 4.0.1 → 4.0.3
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.
- package/.github/workflows/release.yml +23 -4
- package/.idea/react-diff-viewer-continued.iml +3 -0
- package/CHANGELOG.md +14 -0
- package/LICENSE +1 -1
- package/README.md +5 -3
- package/example.jpg +0 -0
- package/lib/{src → cjs/src}/compute-lines.d.ts +2 -1
- package/lib/{src → cjs/src}/compute-lines.js +2 -1
- package/lib/cjs/src/expand.d.ts +1 -0
- package/lib/cjs/src/fold.d.ts +1 -0
- package/lib/{src → cjs/src}/index.d.ts +6 -6
- package/lib/{src → cjs/src}/index.js +61 -66
- package/lib/{src → cjs/src}/styles.d.ts +2 -0
- package/lib/{src → cjs/src}/styles.js +16 -12
- package/lib/esm/src/compute-hidden-blocks.js +35 -0
- package/lib/esm/src/compute-lines.js +203 -0
- package/lib/esm/src/expand.js +4 -0
- package/lib/esm/src/fold.js +4 -0
- package/lib/esm/src/index.js +345 -0
- package/lib/esm/src/styles.js +348 -0
- package/package.json +22 -52
- package/tsconfig.esm.json +11 -0
- package/tsconfig.json +5 -1
- package/vitest.config.ts +5 -0
- package/.eslintrc +0 -13
- package/.github/workflows/test.yml +0 -25
- package/.prettierrc +0 -4
- package/jest.config.js +0 -5
- package/lib/src/expand.d.ts +0 -1
- package/lib/src/fold.d.ts +0 -1
- package/webpack.config.js +0 -60
- /package/lib/{src → cjs/src}/compute-hidden-blocks.d.ts +0 -0
- /package/lib/{src → cjs/src}/compute-hidden-blocks.js +0 -0
- /package/lib/{src → cjs/src}/expand.js +0 -0
- /package/lib/{src → cjs/src}/fold.js +0 -0
|
@@ -1,12 +1,31 @@
|
|
|
1
|
-
name: Release
|
|
1
|
+
name: Test & Release
|
|
2
2
|
on:
|
|
3
3
|
push:
|
|
4
|
-
|
|
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
|
package/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,17 @@
|
|
|
1
|
+
## [4.0.3](https://github.com/aeolun/react-diff-viewer-continued/compare/v4.0.2...v4.0.3) (2024-05-23)
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
### Reverts
|
|
5
|
+
|
|
6
|
+
* Revert "refactoring attempt" ([6a9789b](https://github.com/aeolun/react-diff-viewer-continued/commit/6a9789b0af0221bf32be11d1af9d4db3337008f4))
|
|
7
|
+
|
|
8
|
+
## [4.0.2](https://github.com/aeolun/react-diff-viewer-continued/compare/v4.0.1...v4.0.2) (2024-02-14)
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
### Bug Fixes
|
|
12
|
+
|
|
13
|
+
* 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))
|
|
14
|
+
|
|
1
15
|
## [4.0.1](https://github.com/aeolun/react-diff-viewer-continued/compare/v4.0.0...v4.0.1) (2023-11-01)
|
|
2
16
|
|
|
3
17
|
|
package/LICENSE
CHANGED
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
|
+

|
|
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.
|
|
@@ -69,11 +71,11 @@ class Diff extends PureComponent {
|
|
|
69
71
|
|
|
70
72
|
| Prop | Type | Default | Description |
|
|
71
73
|
|---------------------------|---------------------------|--------------------------------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
|
|
72
|
-
| oldValue | `string
|
|
73
|
-
| newValue | `string
|
|
74
|
+
| oldValue | `string \| Object` | `''` | Old value as string (or Object if using `diffJson`). |
|
|
75
|
+
| newValue | `string \| Object` | `''` | New value as string (or Object if using `diffJson`). |
|
|
74
76
|
| splitView | `boolean` | `true` | Switch between `unified` and `split` view. |
|
|
75
77
|
| disableWordDiff | `boolean` | `false` | Show and hide word diff in a diff line. |
|
|
76
|
-
| compareMethod | `DiffMethod` | `DiffMethod.CHARS` | JsDiff text diff method used for diffing strings. Check out the [guide](https://github.com/praneshr/react-diff-viewer/tree/v3.0.0#text-block-diff-comparison) to use different methods.
|
|
78
|
+
| compareMethod | `DiffMethod \| (string, string) => diff.Change[]` | `DiffMethod.CHARS` | Uses an existing diff method when a `DiffMethod` enum is passed. If a function is passed, that function is used as the diff method. <br /> <br /> JsDiff text diff method used for diffing strings. Check out the [guide](https://github.com/praneshr/react-diff-viewer/tree/v3.0.0#text-block-diff-comparison) to use different methods. |
|
|
77
79
|
| renderGutter | `(diffData) => ReactNode` | `undefined` | Function that can be used to render an extra gutter with various information next to the line number. |
|
|
78
80
|
| hideLineNumbers | `boolean` | `false` | Show and hide line numbers. |
|
|
79
81
|
| alwaysShowLines | `string[]` | `[]` | List of lines to always be shown, regardless of diff status. Line number are prefixed with `L` and `R` for the left and right section of the diff viewer, respectively. For example, `L-20` means 20th line in the left pane. `extraLinesSurroundingDiff` applies to these lines as well. |
|
package/example.jpg
ADDED
|
Binary file
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import * as diff from 'diff';
|
|
1
2
|
export declare enum DiffType {
|
|
2
3
|
DEFAULT = 0,
|
|
3
4
|
ADDED = 1,
|
|
@@ -51,5 +52,5 @@ export interface JsDiffChangeObject {
|
|
|
51
52
|
* @param linesOffset line number to start counting from
|
|
52
53
|
* @param showLines lines that are always shown, regardless of diff
|
|
53
54
|
*/
|
|
54
|
-
declare const computeLineInformation: (oldString: string | Object, newString: string | Object, disableWordDiff?: boolean, lineCompareMethod?: string, linesOffset?: number, showLines?: string[]) => ComputedLineInformation;
|
|
55
|
+
declare const computeLineInformation: (oldString: string | Object, newString: string | Object, disableWordDiff?: boolean, lineCompareMethod?: DiffMethod | ((oldStr: string, newStr: string) => diff.Change[]), linesOffset?: number, showLines?: string[]) => ComputedLineInformation;
|
|
55
56
|
export { computeLineInformation };
|
|
@@ -66,7 +66,8 @@ const constructLines = (value) => {
|
|
|
66
66
|
* @param compareMethod JsDiff text diff method from https://github.com/kpdecker/jsdiff/tree/v4.0.1#api
|
|
67
67
|
*/
|
|
68
68
|
const computeDiff = (oldValue, newValue, compareMethod = DiffMethod.CHARS) => {
|
|
69
|
-
const
|
|
69
|
+
const compareFunc = (typeof (compareMethod) === 'string') ? jsDiff[compareMethod] : compareMethod;
|
|
70
|
+
const diffArray = compareFunc(oldValue, newValue);
|
|
70
71
|
const computedDiff = {
|
|
71
72
|
left: [],
|
|
72
73
|
right: [],
|
|
@@ -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;
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import * as React from 'react';
|
|
2
2
|
import { ReactElement } from 'react';
|
|
3
3
|
import { DiffInformation, DiffMethod, DiffType, LineInformation } from './compute-lines';
|
|
4
|
+
import { Change } from 'diff';
|
|
4
5
|
import { ReactDiffViewerStyles, ReactDiffViewerStylesOverride } from './styles';
|
|
5
6
|
export declare enum LineNumberPrefix {
|
|
6
7
|
LEFT = "L",
|
|
@@ -12,7 +13,7 @@ export interface ReactDiffViewerProps {
|
|
|
12
13
|
splitView?: boolean;
|
|
13
14
|
linesOffset?: number;
|
|
14
15
|
disableWordDiff?: boolean;
|
|
15
|
-
compareMethod?: DiffMethod;
|
|
16
|
+
compareMethod?: DiffMethod | ((oldStr: string, newStr: string) => Change[]);
|
|
16
17
|
extraLinesSurroundingDiff?: number;
|
|
17
18
|
hideLineNumbers?: boolean;
|
|
18
19
|
/**
|
|
@@ -45,6 +46,7 @@ export interface ReactDiffViewerProps {
|
|
|
45
46
|
}
|
|
46
47
|
export interface ReactDiffViewerState {
|
|
47
48
|
expandedBlocks?: number[];
|
|
49
|
+
noSelect?: 'left' | 'right';
|
|
48
50
|
}
|
|
49
51
|
declare class DiffViewer extends React.Component<ReactDiffViewerProps, ReactDiffViewerState> {
|
|
50
52
|
private styles;
|
|
@@ -112,10 +114,7 @@ declare class DiffViewer extends React.Component<ReactDiffViewerProps, ReactDiff
|
|
|
112
114
|
* @param obj.right Life diff information for the removed section of the inline view.
|
|
113
115
|
* @param index React key for the lines.
|
|
114
116
|
*/
|
|
115
|
-
renderInlineView: ({ left, right }: LineInformation, index: number) =>
|
|
116
|
-
left: ReactElement[];
|
|
117
|
-
right: ReactElement[];
|
|
118
|
-
};
|
|
117
|
+
renderInlineView: ({ left, right }: LineInformation, index: number) => ReactElement;
|
|
119
118
|
/**
|
|
120
119
|
* Returns a function with clicked block number in the closure.
|
|
121
120
|
*
|
|
@@ -139,4 +138,5 @@ declare class DiffViewer extends React.Component<ReactDiffViewerProps, ReactDiff
|
|
|
139
138
|
render: () => ReactElement;
|
|
140
139
|
}
|
|
141
140
|
export default DiffViewer;
|
|
142
|
-
export {
|
|
141
|
+
export { DiffMethod };
|
|
142
|
+
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 =
|
|
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)(
|
|
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)("
|
|
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)("
|
|
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)("
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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)("
|
|
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
|
-
|
|
274
|
-
|
|
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,40 +261,48 @@ 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
|
|
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
|
-
|
|
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
|
-
|
|
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 {
|
|
281
|
+
return {
|
|
282
|
+
diffNodes,
|
|
283
|
+
blocks,
|
|
284
|
+
lineInformation
|
|
285
|
+
};
|
|
313
286
|
};
|
|
314
287
|
this.render = () => {
|
|
315
|
-
const { oldValue, newValue, useDarkTheme, leftTitle, rightTitle, splitView, hideLineNumbers, nonce, } = this.props;
|
|
316
|
-
if (
|
|
288
|
+
const { oldValue, newValue, useDarkTheme, leftTitle, rightTitle, splitView, compareMethod, hideLineNumbers, nonce, } = this.props;
|
|
289
|
+
if (typeof (compareMethod) === 'string' && compareMethod !== compute_lines_1.DiffMethod.JSON) {
|
|
317
290
|
if (typeof oldValue !== 'string' || typeof newValue !== 'string') {
|
|
318
291
|
throw Error('"oldValue" and "newValue" should be strings');
|
|
319
292
|
}
|
|
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,
|
|
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
|
-
}),
|
|
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: '#
|
|
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: '
|
|
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
|
+
}
|