react-diff-viewer-continued 3.3.0 → 3.3.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.
- package/CHANGELOG.md +7 -0
- package/lib/src/compute-hidden-blocks.d.ts +13 -0
- package/lib/src/compute-hidden-blocks.js +39 -0
- package/lib/src/compute-lines.d.ts +55 -0
- package/lib/src/compute-lines.js +228 -0
- package/lib/src/index.d.ts +135 -0
- package/lib/src/index.js +298 -0
- package/lib/src/styles.d.ts +81 -0
- package/lib/src/styles.js +291 -0
- package/package.json +3 -3
package/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,10 @@
|
|
|
1
|
+
## [3.3.1](https://github.com/aeolun/react-diff-viewer-continued/compare/v3.3.0...v3.3.1) (2023-10-18)
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
### Bug Fixes
|
|
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))
|
|
7
|
+
|
|
1
8
|
# [3.3.0](https://github.com/aeolun/react-diff-viewer-continued/compare/v3.2.6...v3.3.0) (2023-10-17)
|
|
2
9
|
|
|
3
10
|
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { LineInformation } from "./compute-lines";
|
|
2
|
+
interface Block {
|
|
3
|
+
index: number;
|
|
4
|
+
startLine: number;
|
|
5
|
+
endLine: number;
|
|
6
|
+
lines: number;
|
|
7
|
+
}
|
|
8
|
+
interface HiddenBlocks {
|
|
9
|
+
lineBlocks: Record<number, number>;
|
|
10
|
+
blocks: Block[];
|
|
11
|
+
}
|
|
12
|
+
export declare function computeHiddenBlocks(lineInformation: LineInformation[], diffLines: number[], extraLines: number): HiddenBlocks;
|
|
13
|
+
export {};
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.computeHiddenBlocks = void 0;
|
|
4
|
+
function computeHiddenBlocks(lineInformation, diffLines, extraLines) {
|
|
5
|
+
let newBlockIndex = 0;
|
|
6
|
+
let currentBlock;
|
|
7
|
+
let lineBlocks = {};
|
|
8
|
+
let blocks = [];
|
|
9
|
+
lineInformation.forEach((line, lineIndex) => {
|
|
10
|
+
const isDiffLine = diffLines.some(diffLine => diffLine >= lineIndex - extraLines && diffLine <= lineIndex + extraLines);
|
|
11
|
+
if (!isDiffLine && currentBlock == undefined) {
|
|
12
|
+
// block begins
|
|
13
|
+
currentBlock = {
|
|
14
|
+
index: newBlockIndex,
|
|
15
|
+
startLine: lineIndex,
|
|
16
|
+
endLine: lineIndex,
|
|
17
|
+
lines: 1
|
|
18
|
+
};
|
|
19
|
+
blocks.push(currentBlock);
|
|
20
|
+
lineBlocks[lineIndex] = currentBlock.index;
|
|
21
|
+
newBlockIndex++;
|
|
22
|
+
}
|
|
23
|
+
else if (!isDiffLine) {
|
|
24
|
+
// block continues
|
|
25
|
+
currentBlock.endLine = lineIndex;
|
|
26
|
+
currentBlock.lines++;
|
|
27
|
+
lineBlocks[lineIndex] = currentBlock.index;
|
|
28
|
+
}
|
|
29
|
+
else {
|
|
30
|
+
// not a block anymore
|
|
31
|
+
currentBlock = undefined;
|
|
32
|
+
}
|
|
33
|
+
});
|
|
34
|
+
return {
|
|
35
|
+
lineBlocks,
|
|
36
|
+
blocks: blocks
|
|
37
|
+
};
|
|
38
|
+
}
|
|
39
|
+
exports.computeHiddenBlocks = computeHiddenBlocks;
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
export declare enum DiffType {
|
|
2
|
+
DEFAULT = 0,
|
|
3
|
+
ADDED = 1,
|
|
4
|
+
REMOVED = 2,
|
|
5
|
+
CHANGED = 3
|
|
6
|
+
}
|
|
7
|
+
export declare enum DiffMethod {
|
|
8
|
+
CHARS = "diffChars",
|
|
9
|
+
WORDS = "diffWords",
|
|
10
|
+
WORDS_WITH_SPACE = "diffWordsWithSpace",
|
|
11
|
+
LINES = "diffLines",
|
|
12
|
+
TRIMMED_LINES = "diffTrimmedLines",
|
|
13
|
+
SENTENCES = "diffSentences",
|
|
14
|
+
CSS = "diffCss",
|
|
15
|
+
JSON = "diffJson"
|
|
16
|
+
}
|
|
17
|
+
export interface DiffInformation {
|
|
18
|
+
value?: string | DiffInformation[];
|
|
19
|
+
lineNumber?: number;
|
|
20
|
+
type?: DiffType;
|
|
21
|
+
}
|
|
22
|
+
export interface LineInformation {
|
|
23
|
+
left?: DiffInformation;
|
|
24
|
+
right?: DiffInformation;
|
|
25
|
+
}
|
|
26
|
+
export interface ComputedLineInformation {
|
|
27
|
+
lineInformation: LineInformation[];
|
|
28
|
+
diffLines: number[];
|
|
29
|
+
}
|
|
30
|
+
export interface ComputedDiffInformation {
|
|
31
|
+
left?: DiffInformation[];
|
|
32
|
+
right?: DiffInformation[];
|
|
33
|
+
}
|
|
34
|
+
export interface JsDiffChangeObject {
|
|
35
|
+
added?: boolean;
|
|
36
|
+
removed?: boolean;
|
|
37
|
+
value?: string;
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* [TODO]: Think about moving common left and right value assignment to a
|
|
41
|
+
* common place. Better readability?
|
|
42
|
+
*
|
|
43
|
+
* Computes line wise information based in the js diff information passed. Each
|
|
44
|
+
* line contains information about left and right section. Left side denotes
|
|
45
|
+
* deletion and right side denotes addition.
|
|
46
|
+
*
|
|
47
|
+
* @param oldString Old string to compare.
|
|
48
|
+
* @param newString New string to compare with old string.
|
|
49
|
+
* @param disableWordDiff Flag to enable/disable word diff.
|
|
50
|
+
* @param lineCompareMethod JsDiff text diff method from https://github.com/kpdecker/jsdiff/tree/v4.0.1#api
|
|
51
|
+
* @param linesOffset line number to start counting from
|
|
52
|
+
* @param showLines lines that are always shown, regardless of diff
|
|
53
|
+
*/
|
|
54
|
+
declare const computeLineInformation: (oldString: string | Object, newString: string | Object, disableWordDiff?: boolean, lineCompareMethod?: string, linesOffset?: number, showLines?: string[]) => ComputedLineInformation;
|
|
55
|
+
export { computeLineInformation };
|
|
@@ -0,0 +1,228 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || function (mod) {
|
|
19
|
+
if (mod && mod.__esModule) return mod;
|
|
20
|
+
var result = {};
|
|
21
|
+
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
|
|
22
|
+
__setModuleDefault(result, mod);
|
|
23
|
+
return result;
|
|
24
|
+
};
|
|
25
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
26
|
+
exports.computeLineInformation = exports.DiffMethod = exports.DiffType = void 0;
|
|
27
|
+
const diff = __importStar(require("diff"));
|
|
28
|
+
const jsDiff = diff;
|
|
29
|
+
var DiffType;
|
|
30
|
+
(function (DiffType) {
|
|
31
|
+
DiffType[DiffType["DEFAULT"] = 0] = "DEFAULT";
|
|
32
|
+
DiffType[DiffType["ADDED"] = 1] = "ADDED";
|
|
33
|
+
DiffType[DiffType["REMOVED"] = 2] = "REMOVED";
|
|
34
|
+
DiffType[DiffType["CHANGED"] = 3] = "CHANGED";
|
|
35
|
+
})(DiffType || (exports.DiffType = DiffType = {}));
|
|
36
|
+
// See https://github.com/kpdecker/jsdiff/tree/v4.0.1#api for more info on the below JsDiff methods
|
|
37
|
+
var DiffMethod;
|
|
38
|
+
(function (DiffMethod) {
|
|
39
|
+
DiffMethod["CHARS"] = "diffChars";
|
|
40
|
+
DiffMethod["WORDS"] = "diffWords";
|
|
41
|
+
DiffMethod["WORDS_WITH_SPACE"] = "diffWordsWithSpace";
|
|
42
|
+
DiffMethod["LINES"] = "diffLines";
|
|
43
|
+
DiffMethod["TRIMMED_LINES"] = "diffTrimmedLines";
|
|
44
|
+
DiffMethod["SENTENCES"] = "diffSentences";
|
|
45
|
+
DiffMethod["CSS"] = "diffCss";
|
|
46
|
+
DiffMethod["JSON"] = "diffJson";
|
|
47
|
+
})(DiffMethod || (exports.DiffMethod = DiffMethod = {}));
|
|
48
|
+
/**
|
|
49
|
+
* Splits diff text by new line and computes final list of diff lines based on
|
|
50
|
+
* conditions.
|
|
51
|
+
*
|
|
52
|
+
* @param value Diff text from the js diff module.
|
|
53
|
+
*/
|
|
54
|
+
const constructLines = (value) => {
|
|
55
|
+
if (value === '')
|
|
56
|
+
return [];
|
|
57
|
+
const lines = value.replace(/\n$/, '').split('\n');
|
|
58
|
+
return lines;
|
|
59
|
+
};
|
|
60
|
+
/**
|
|
61
|
+
* Computes word diff information in the line.
|
|
62
|
+
* [TODO]: Consider adding options argument for JsDiff text block comparison
|
|
63
|
+
*
|
|
64
|
+
* @param oldValue Old word in the line.
|
|
65
|
+
* @param newValue New word in the line.
|
|
66
|
+
* @param compareMethod JsDiff text diff method from https://github.com/kpdecker/jsdiff/tree/v4.0.1#api
|
|
67
|
+
*/
|
|
68
|
+
const computeDiff = (oldValue, newValue, compareMethod = DiffMethod.CHARS) => {
|
|
69
|
+
const diffArray = jsDiff[compareMethod](oldValue, newValue);
|
|
70
|
+
const computedDiff = {
|
|
71
|
+
left: [],
|
|
72
|
+
right: [],
|
|
73
|
+
};
|
|
74
|
+
diffArray.forEach(({ added, removed, value }) => {
|
|
75
|
+
const diffInformation = {};
|
|
76
|
+
if (added) {
|
|
77
|
+
diffInformation.type = DiffType.ADDED;
|
|
78
|
+
diffInformation.value = value;
|
|
79
|
+
computedDiff.right.push(diffInformation);
|
|
80
|
+
}
|
|
81
|
+
if (removed) {
|
|
82
|
+
diffInformation.type = DiffType.REMOVED;
|
|
83
|
+
diffInformation.value = value;
|
|
84
|
+
computedDiff.left.push(diffInformation);
|
|
85
|
+
}
|
|
86
|
+
if (!removed && !added) {
|
|
87
|
+
diffInformation.type = DiffType.DEFAULT;
|
|
88
|
+
diffInformation.value = value;
|
|
89
|
+
computedDiff.right.push(diffInformation);
|
|
90
|
+
computedDiff.left.push(diffInformation);
|
|
91
|
+
}
|
|
92
|
+
return diffInformation;
|
|
93
|
+
});
|
|
94
|
+
return computedDiff;
|
|
95
|
+
};
|
|
96
|
+
/**
|
|
97
|
+
* [TODO]: Think about moving common left and right value assignment to a
|
|
98
|
+
* common place. Better readability?
|
|
99
|
+
*
|
|
100
|
+
* Computes line wise information based in the js diff information passed. Each
|
|
101
|
+
* line contains information about left and right section. Left side denotes
|
|
102
|
+
* deletion and right side denotes addition.
|
|
103
|
+
*
|
|
104
|
+
* @param oldString Old string to compare.
|
|
105
|
+
* @param newString New string to compare with old string.
|
|
106
|
+
* @param disableWordDiff Flag to enable/disable word diff.
|
|
107
|
+
* @param lineCompareMethod JsDiff text diff method from https://github.com/kpdecker/jsdiff/tree/v4.0.1#api
|
|
108
|
+
* @param linesOffset line number to start counting from
|
|
109
|
+
* @param showLines lines that are always shown, regardless of diff
|
|
110
|
+
*/
|
|
111
|
+
const computeLineInformation = (oldString, newString, disableWordDiff = false, lineCompareMethod = DiffMethod.CHARS, linesOffset = 0, showLines = []) => {
|
|
112
|
+
let diffArray = [];
|
|
113
|
+
// Use diffLines for strings, and diffJson for objects...
|
|
114
|
+
if (typeof oldString === 'string' && typeof newString === 'string') {
|
|
115
|
+
diffArray = diff.diffLines(oldString.trimRight(), newString.trimRight(), {
|
|
116
|
+
newlineIsToken: false,
|
|
117
|
+
ignoreWhitespace: false,
|
|
118
|
+
ignoreCase: false,
|
|
119
|
+
});
|
|
120
|
+
}
|
|
121
|
+
else {
|
|
122
|
+
diffArray = diff.diffJson(oldString, newString);
|
|
123
|
+
}
|
|
124
|
+
let rightLineNumber = linesOffset;
|
|
125
|
+
let leftLineNumber = linesOffset;
|
|
126
|
+
let lineInformation = [];
|
|
127
|
+
let counter = 0;
|
|
128
|
+
const diffLines = [];
|
|
129
|
+
const ignoreDiffIndexes = [];
|
|
130
|
+
const getLineInformation = (value, diffIndex, added, removed, evaluateOnlyFirstLine) => {
|
|
131
|
+
const lines = constructLines(value);
|
|
132
|
+
return lines
|
|
133
|
+
.map((line, lineIndex) => {
|
|
134
|
+
const left = {};
|
|
135
|
+
const right = {};
|
|
136
|
+
if (ignoreDiffIndexes.includes(`${diffIndex}-${lineIndex}`) ||
|
|
137
|
+
(evaluateOnlyFirstLine && lineIndex !== 0)) {
|
|
138
|
+
return undefined;
|
|
139
|
+
}
|
|
140
|
+
if (added || removed) {
|
|
141
|
+
let countAsChange = true;
|
|
142
|
+
if (removed) {
|
|
143
|
+
leftLineNumber += 1;
|
|
144
|
+
left.lineNumber = leftLineNumber;
|
|
145
|
+
left.type = DiffType.REMOVED;
|
|
146
|
+
left.value = line || ' ';
|
|
147
|
+
// When the current line is of type REMOVED, check the next item in
|
|
148
|
+
// the diff array whether it is of type ADDED. If true, the current
|
|
149
|
+
// diff will be marked as both REMOVED and ADDED. Meaning, the
|
|
150
|
+
// current line is a modification.
|
|
151
|
+
const nextDiff = diffArray[diffIndex + 1];
|
|
152
|
+
if (nextDiff && nextDiff.added) {
|
|
153
|
+
const nextDiffLines = constructLines(nextDiff.value)[lineIndex];
|
|
154
|
+
if (nextDiffLines) {
|
|
155
|
+
const nextDiffLineInfo = getLineInformation(nextDiffLines, diffIndex, true, false, true);
|
|
156
|
+
const { value: rightValue, lineNumber, type, } = nextDiffLineInfo[0].right;
|
|
157
|
+
// When identified as modification, push the next diff to ignore
|
|
158
|
+
// list as the next value will be added in this line computation as
|
|
159
|
+
// right and left values.
|
|
160
|
+
ignoreDiffIndexes.push(`${diffIndex + 1}-${lineIndex}`);
|
|
161
|
+
right.lineNumber = lineNumber;
|
|
162
|
+
if (left.value === rightValue) {
|
|
163
|
+
// The new value is exactly the same as the old
|
|
164
|
+
countAsChange = false;
|
|
165
|
+
right.type = 0;
|
|
166
|
+
left.type = 0;
|
|
167
|
+
right.value = rightValue;
|
|
168
|
+
}
|
|
169
|
+
else {
|
|
170
|
+
right.type = type;
|
|
171
|
+
// Do char level diff and assign the corresponding values to the
|
|
172
|
+
// left and right diff information object.
|
|
173
|
+
if (disableWordDiff) {
|
|
174
|
+
right.value = rightValue;
|
|
175
|
+
}
|
|
176
|
+
else {
|
|
177
|
+
const computedDiff = computeDiff(line, rightValue, lineCompareMethod);
|
|
178
|
+
right.value = computedDiff.right;
|
|
179
|
+
left.value = computedDiff.left;
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
else {
|
|
186
|
+
rightLineNumber += 1;
|
|
187
|
+
right.lineNumber = rightLineNumber;
|
|
188
|
+
right.type = DiffType.ADDED;
|
|
189
|
+
right.value = line;
|
|
190
|
+
}
|
|
191
|
+
if (countAsChange && !evaluateOnlyFirstLine) {
|
|
192
|
+
if (!diffLines.includes(counter)) {
|
|
193
|
+
diffLines.push(counter);
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
else {
|
|
198
|
+
leftLineNumber += 1;
|
|
199
|
+
rightLineNumber += 1;
|
|
200
|
+
left.lineNumber = leftLineNumber;
|
|
201
|
+
left.type = DiffType.DEFAULT;
|
|
202
|
+
left.value = line;
|
|
203
|
+
right.lineNumber = rightLineNumber;
|
|
204
|
+
right.type = DiffType.DEFAULT;
|
|
205
|
+
right.value = line;
|
|
206
|
+
}
|
|
207
|
+
if ((showLines === null || showLines === void 0 ? void 0 : showLines.includes(`L-${left.lineNumber}`)) || (showLines === null || showLines === void 0 ? void 0 : showLines.includes(`R-${right.lineNumber}`)) && !diffLines.includes(counter)) {
|
|
208
|
+
diffLines.push(counter);
|
|
209
|
+
}
|
|
210
|
+
if (!evaluateOnlyFirstLine) {
|
|
211
|
+
counter += 1;
|
|
212
|
+
}
|
|
213
|
+
return { right, left };
|
|
214
|
+
})
|
|
215
|
+
.filter(Boolean);
|
|
216
|
+
};
|
|
217
|
+
diffArray.forEach(({ added, removed, value }, index) => {
|
|
218
|
+
lineInformation = [
|
|
219
|
+
...lineInformation,
|
|
220
|
+
...getLineInformation(value, index, added, removed),
|
|
221
|
+
];
|
|
222
|
+
});
|
|
223
|
+
return {
|
|
224
|
+
lineInformation,
|
|
225
|
+
diffLines,
|
|
226
|
+
};
|
|
227
|
+
};
|
|
228
|
+
exports.computeLineInformation = computeLineInformation;
|
|
@@ -0,0 +1,135 @@
|
|
|
1
|
+
import * as React from 'react';
|
|
2
|
+
import { DiffInformation, DiffMethod, DiffType, LineInformation } from './compute-lines';
|
|
3
|
+
import { ReactDiffViewerStyles, ReactDiffViewerStylesOverride } from './styles';
|
|
4
|
+
import { ReactElement } from "react";
|
|
5
|
+
export declare enum LineNumberPrefix {
|
|
6
|
+
LEFT = "L",
|
|
7
|
+
RIGHT = "R"
|
|
8
|
+
}
|
|
9
|
+
export interface ReactDiffViewerProps {
|
|
10
|
+
oldValue: string | Object;
|
|
11
|
+
newValue: string | Object;
|
|
12
|
+
splitView?: boolean;
|
|
13
|
+
linesOffset?: number;
|
|
14
|
+
disableWordDiff?: boolean;
|
|
15
|
+
compareMethod?: DiffMethod;
|
|
16
|
+
extraLinesSurroundingDiff?: number;
|
|
17
|
+
hideLineNumbers?: boolean;
|
|
18
|
+
/**
|
|
19
|
+
* Show the lines indicated here. Specified as L20 or R18 for respectively line 20 on the left or line 18 on the right.
|
|
20
|
+
*/
|
|
21
|
+
alwaysShowLines?: string[];
|
|
22
|
+
showDiffOnly?: boolean;
|
|
23
|
+
renderContent?: (source: string) => ReactElement;
|
|
24
|
+
codeFoldMessageRenderer?: (totalFoldedLines: number, leftStartLineNumber: number, rightStartLineNumber: number) => ReactElement;
|
|
25
|
+
onLineNumberClick?: (lineId: string, event: React.MouseEvent<HTMLTableCellElement>) => void;
|
|
26
|
+
renderGutter?: (data: {
|
|
27
|
+
lineNumber: number;
|
|
28
|
+
type: DiffType;
|
|
29
|
+
prefix: LineNumberPrefix;
|
|
30
|
+
value: string | DiffInformation[];
|
|
31
|
+
additionalLineNumber: number;
|
|
32
|
+
additionalPrefix: LineNumberPrefix;
|
|
33
|
+
styles: ReactDiffViewerStyles;
|
|
34
|
+
}) => ReactElement;
|
|
35
|
+
highlightLines?: string[];
|
|
36
|
+
styles?: ReactDiffViewerStylesOverride;
|
|
37
|
+
useDarkTheme?: boolean;
|
|
38
|
+
leftTitle?: string | ReactElement;
|
|
39
|
+
rightTitle?: string | ReactElement;
|
|
40
|
+
nonce?: string;
|
|
41
|
+
}
|
|
42
|
+
export interface ReactDiffViewerState {
|
|
43
|
+
expandedBlocks?: number[];
|
|
44
|
+
}
|
|
45
|
+
declare class DiffViewer extends React.Component<ReactDiffViewerProps, ReactDiffViewerState> {
|
|
46
|
+
private styles;
|
|
47
|
+
static defaultProps: ReactDiffViewerProps;
|
|
48
|
+
constructor(props: ReactDiffViewerProps);
|
|
49
|
+
/**
|
|
50
|
+
* Resets code block expand to the initial stage. Will be exposed to the parent component via
|
|
51
|
+
* refs.
|
|
52
|
+
*/
|
|
53
|
+
resetCodeBlocks: () => boolean;
|
|
54
|
+
/**
|
|
55
|
+
* Pushes the target expanded code block to the state. During the re-render,
|
|
56
|
+
* this value is used to expand/fold unmodified code.
|
|
57
|
+
*/
|
|
58
|
+
private onBlockExpand;
|
|
59
|
+
/**
|
|
60
|
+
* Computes final styles for the diff viewer. It combines the default styles with the user
|
|
61
|
+
* supplied overrides. The computed styles are cached with performance in mind.
|
|
62
|
+
*
|
|
63
|
+
* @param styles User supplied style overrides.
|
|
64
|
+
*/
|
|
65
|
+
private computeStyles;
|
|
66
|
+
/**
|
|
67
|
+
* Returns a function with clicked line number in the closure. Returns an no-op function when no
|
|
68
|
+
* onLineNumberClick handler is supplied.
|
|
69
|
+
*
|
|
70
|
+
* @param id Line id of a line.
|
|
71
|
+
*/
|
|
72
|
+
private onLineNumberClickProxy;
|
|
73
|
+
/**
|
|
74
|
+
* Maps over the word diff and constructs the required React elements to show word diff.
|
|
75
|
+
*
|
|
76
|
+
* @param diffArray Word diff information derived from line information.
|
|
77
|
+
* @param renderer Optional renderer to format diff words. Useful for syntax highlighting.
|
|
78
|
+
*/
|
|
79
|
+
private renderWordDiff;
|
|
80
|
+
/**
|
|
81
|
+
* Maps over the line diff and constructs the required react elements to show line diff. It calls
|
|
82
|
+
* renderWordDiff when encountering word diff. This takes care of both inline and split view line
|
|
83
|
+
* renders.
|
|
84
|
+
*
|
|
85
|
+
* @param lineNumber Line number of the current line.
|
|
86
|
+
* @param type Type of diff of the current line.
|
|
87
|
+
* @param prefix Unique id to prefix with the line numbers.
|
|
88
|
+
* @param value Content of the line. It can be a string or a word diff array.
|
|
89
|
+
* @param additionalLineNumber Additional line number to be shown. Useful for rendering inline
|
|
90
|
+
* diff view. Right line number will be passed as additionalLineNumber.
|
|
91
|
+
* @param additionalPrefix Similar to prefix but for additional line number.
|
|
92
|
+
*/
|
|
93
|
+
private renderLine;
|
|
94
|
+
/**
|
|
95
|
+
* Generates lines for split view.
|
|
96
|
+
*
|
|
97
|
+
* @param obj Line diff information.
|
|
98
|
+
* @param obj.left Life diff information for the left pane of the split view.
|
|
99
|
+
* @param obj.right Life diff information for the right pane of the split view.
|
|
100
|
+
* @param index React key for the lines.
|
|
101
|
+
*/
|
|
102
|
+
private renderSplitView;
|
|
103
|
+
/**
|
|
104
|
+
* Generates lines for inline view.
|
|
105
|
+
*
|
|
106
|
+
* @param obj Line diff information.
|
|
107
|
+
* @param obj.left Life diff information for the added section of the inline view.
|
|
108
|
+
* @param obj.right Life diff information for the removed section of the inline view.
|
|
109
|
+
* @param index React key for the lines.
|
|
110
|
+
*/
|
|
111
|
+
renderInlineView: ({ left, right }: LineInformation, index: number) => ReactElement;
|
|
112
|
+
/**
|
|
113
|
+
* Returns a function with clicked block number in the closure.
|
|
114
|
+
*
|
|
115
|
+
* @param id Cold fold block id.
|
|
116
|
+
*/
|
|
117
|
+
private onBlockClickProxy;
|
|
118
|
+
/**
|
|
119
|
+
* Generates cold fold block. It also uses the custom message renderer when available to show
|
|
120
|
+
* cold fold messages.
|
|
121
|
+
*
|
|
122
|
+
* @param num Number of skipped lines between two blocks.
|
|
123
|
+
* @param blockNumber Code fold block id.
|
|
124
|
+
* @param leftBlockLineNumber First left line number after the current code fold block.
|
|
125
|
+
* @param rightBlockLineNumber First right line number after the current code fold block.
|
|
126
|
+
*/
|
|
127
|
+
private renderSkippedLineIndicator;
|
|
128
|
+
/**
|
|
129
|
+
* Generates the entire diff view.
|
|
130
|
+
*/
|
|
131
|
+
private renderDiff;
|
|
132
|
+
render: () => ReactElement;
|
|
133
|
+
}
|
|
134
|
+
export default DiffViewer;
|
|
135
|
+
export { ReactDiffViewerStylesOverride, DiffMethod };
|
package/lib/src/index.js
ADDED
|
@@ -0,0 +1,298 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || function (mod) {
|
|
19
|
+
if (mod && mod.__esModule) return mod;
|
|
20
|
+
var result = {};
|
|
21
|
+
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
|
|
22
|
+
__setModuleDefault(result, mod);
|
|
23
|
+
return result;
|
|
24
|
+
};
|
|
25
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
26
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
27
|
+
};
|
|
28
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
29
|
+
exports.DiffMethod = exports.LineNumberPrefix = void 0;
|
|
30
|
+
const jsx_runtime_1 = require("react/jsx-runtime");
|
|
31
|
+
const React = __importStar(require("react"));
|
|
32
|
+
const classnames_1 = __importDefault(require("classnames"));
|
|
33
|
+
const compute_lines_1 = require("./compute-lines");
|
|
34
|
+
Object.defineProperty(exports, "DiffMethod", { enumerable: true, get: function () { return compute_lines_1.DiffMethod; } });
|
|
35
|
+
const styles_1 = __importDefault(require("./styles"));
|
|
36
|
+
const compute_hidden_blocks_1 = require("./compute-hidden-blocks");
|
|
37
|
+
const m = require('memoize-one');
|
|
38
|
+
const memoize = m.default || m;
|
|
39
|
+
var LineNumberPrefix;
|
|
40
|
+
(function (LineNumberPrefix) {
|
|
41
|
+
LineNumberPrefix["LEFT"] = "L";
|
|
42
|
+
LineNumberPrefix["RIGHT"] = "R";
|
|
43
|
+
})(LineNumberPrefix || (exports.LineNumberPrefix = LineNumberPrefix = {}));
|
|
44
|
+
class DiffViewer extends React.Component {
|
|
45
|
+
constructor(props) {
|
|
46
|
+
super(props);
|
|
47
|
+
/**
|
|
48
|
+
* Resets code block expand to the initial stage. Will be exposed to the parent component via
|
|
49
|
+
* refs.
|
|
50
|
+
*/
|
|
51
|
+
this.resetCodeBlocks = () => {
|
|
52
|
+
if (this.state.expandedBlocks.length > 0) {
|
|
53
|
+
this.setState({
|
|
54
|
+
expandedBlocks: [],
|
|
55
|
+
});
|
|
56
|
+
return true;
|
|
57
|
+
}
|
|
58
|
+
return false;
|
|
59
|
+
};
|
|
60
|
+
/**
|
|
61
|
+
* Pushes the target expanded code block to the state. During the re-render,
|
|
62
|
+
* this value is used to expand/fold unmodified code.
|
|
63
|
+
*/
|
|
64
|
+
this.onBlockExpand = (id) => {
|
|
65
|
+
const prevState = this.state.expandedBlocks.slice();
|
|
66
|
+
prevState.push(id);
|
|
67
|
+
this.setState({
|
|
68
|
+
expandedBlocks: prevState,
|
|
69
|
+
});
|
|
70
|
+
};
|
|
71
|
+
/**
|
|
72
|
+
* Computes final styles for the diff viewer. It combines the default styles with the user
|
|
73
|
+
* supplied overrides. The computed styles are cached with performance in mind.
|
|
74
|
+
*
|
|
75
|
+
* @param styles User supplied style overrides.
|
|
76
|
+
*/
|
|
77
|
+
this.computeStyles = memoize(styles_1.default);
|
|
78
|
+
/**
|
|
79
|
+
* Returns a function with clicked line number in the closure. Returns an no-op function when no
|
|
80
|
+
* onLineNumberClick handler is supplied.
|
|
81
|
+
*
|
|
82
|
+
* @param id Line id of a line.
|
|
83
|
+
*/
|
|
84
|
+
this.onLineNumberClickProxy = (id) => {
|
|
85
|
+
if (this.props.onLineNumberClick) {
|
|
86
|
+
return (e) => this.props.onLineNumberClick(id, e);
|
|
87
|
+
}
|
|
88
|
+
return () => { };
|
|
89
|
+
};
|
|
90
|
+
/**
|
|
91
|
+
* Maps over the word diff and constructs the required React elements to show word diff.
|
|
92
|
+
*
|
|
93
|
+
* @param diffArray Word diff information derived from line information.
|
|
94
|
+
* @param renderer Optional renderer to format diff words. Useful for syntax highlighting.
|
|
95
|
+
*/
|
|
96
|
+
this.renderWordDiff = (diffArray, renderer) => {
|
|
97
|
+
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));
|
|
102
|
+
});
|
|
103
|
+
};
|
|
104
|
+
/**
|
|
105
|
+
* Maps over the line diff and constructs the required react elements to show line diff. It calls
|
|
106
|
+
* renderWordDiff when encountering word diff. This takes care of both inline and split view line
|
|
107
|
+
* renders.
|
|
108
|
+
*
|
|
109
|
+
* @param lineNumber Line number of the current line.
|
|
110
|
+
* @param type Type of diff of the current line.
|
|
111
|
+
* @param prefix Unique id to prefix with the line numbers.
|
|
112
|
+
* @param value Content of the line. It can be a string or a word diff array.
|
|
113
|
+
* @param additionalLineNumber Additional line number to be shown. Useful for rendering inline
|
|
114
|
+
* diff view. Right line number will be passed as additionalLineNumber.
|
|
115
|
+
* @param additionalPrefix Similar to prefix but for additional line number.
|
|
116
|
+
*/
|
|
117
|
+
this.renderLine = (lineNumber, type, prefix, value, additionalLineNumber, additionalPrefix) => {
|
|
118
|
+
const lineNumberTemplate = `${prefix}-${lineNumber}`;
|
|
119
|
+
const additionalLineNumberTemplate = `${additionalPrefix}-${additionalLineNumber}`;
|
|
120
|
+
const highlightLine = this.props.highlightLines.includes(lineNumberTemplate) ||
|
|
121
|
+
this.props.highlightLines.includes(additionalLineNumberTemplate);
|
|
122
|
+
const added = type === compute_lines_1.DiffType.ADDED;
|
|
123
|
+
const removed = type === compute_lines_1.DiffType.REMOVED;
|
|
124
|
+
const changed = type === compute_lines_1.DiffType.CHANGED;
|
|
125
|
+
let content;
|
|
126
|
+
if (Array.isArray(value)) {
|
|
127
|
+
content = this.renderWordDiff(value, this.props.renderContent);
|
|
128
|
+
}
|
|
129
|
+
else if (this.props.renderContent) {
|
|
130
|
+
content = this.props.renderContent(value);
|
|
131
|
+
}
|
|
132
|
+
else {
|
|
133
|
+
content = value;
|
|
134
|
+
}
|
|
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, {
|
|
136
|
+
[this.styles.emptyGutter]: !lineNumber,
|
|
137
|
+
[this.styles.diffAdded]: added,
|
|
138
|
+
[this.styles.diffRemoved]: removed,
|
|
139
|
+
[this.styles.diffChanged]: changed,
|
|
140
|
+
[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 &&
|
|
142
|
+
this.onLineNumberClickProxy(additionalLineNumberTemplate), className: (0, classnames_1.default)(this.styles.gutter, {
|
|
143
|
+
[this.styles.emptyGutter]: !additionalLineNumber,
|
|
144
|
+
[this.styles.diffAdded]: added,
|
|
145
|
+
[this.styles.diffRemoved]: removed,
|
|
146
|
+
[this.styles.diffChanged]: changed,
|
|
147
|
+
[this.styles.highlightedGutter]: highlightLine,
|
|
148
|
+
}), children: (0, jsx_runtime_1.jsx)("pre", { className: this.styles.lineNumber, children: additionalLineNumber }) })), this.props.renderGutter
|
|
149
|
+
? this.props.renderGutter({
|
|
150
|
+
lineNumber,
|
|
151
|
+
type,
|
|
152
|
+
prefix,
|
|
153
|
+
value,
|
|
154
|
+
additionalLineNumber,
|
|
155
|
+
additionalPrefix,
|
|
156
|
+
styles: this.styles,
|
|
157
|
+
})
|
|
158
|
+
: null, (0, jsx_runtime_1.jsx)("td", { className: (0, classnames_1.default)(this.styles.marker, {
|
|
159
|
+
[this.styles.emptyLine]: !content,
|
|
160
|
+
[this.styles.diffAdded]: added,
|
|
161
|
+
[this.styles.diffRemoved]: removed,
|
|
162
|
+
[this.styles.diffChanged]: changed,
|
|
163
|
+
[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, {
|
|
165
|
+
[this.styles.emptyLine]: !content,
|
|
166
|
+
[this.styles.diffAdded]: added,
|
|
167
|
+
[this.styles.diffRemoved]: removed,
|
|
168
|
+
[this.styles.diffChanged]: changed,
|
|
169
|
+
[this.styles.highlightedLine]: highlightLine,
|
|
170
|
+
}), children: (0, jsx_runtime_1.jsx)("pre", { className: this.styles.contentText, children: content }) })] }));
|
|
171
|
+
};
|
|
172
|
+
/**
|
|
173
|
+
* Generates lines for split view.
|
|
174
|
+
*
|
|
175
|
+
* @param obj Line diff information.
|
|
176
|
+
* @param obj.left Life diff information for the left pane of the split view.
|
|
177
|
+
* @param obj.right Life diff information for the right pane of the split view.
|
|
178
|
+
* @param index React key for the lines.
|
|
179
|
+
*/
|
|
180
|
+
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));
|
|
182
|
+
};
|
|
183
|
+
/**
|
|
184
|
+
* Generates lines for inline view.
|
|
185
|
+
*
|
|
186
|
+
* @param obj Line diff information.
|
|
187
|
+
* @param obj.left Life diff information for the added section of the inline view.
|
|
188
|
+
* @param obj.right Life diff information for the removed section of the inline view.
|
|
189
|
+
* @param index React key for the lines.
|
|
190
|
+
*/
|
|
191
|
+
this.renderInlineView = ({ left, right }, index) => {
|
|
192
|
+
let content;
|
|
193
|
+
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));
|
|
195
|
+
}
|
|
196
|
+
if (left.type === compute_lines_1.DiffType.REMOVED) {
|
|
197
|
+
content = this.renderLine(left.lineNumber, left.type, LineNumberPrefix.LEFT, left.value, null);
|
|
198
|
+
}
|
|
199
|
+
if (left.type === compute_lines_1.DiffType.DEFAULT) {
|
|
200
|
+
content = this.renderLine(left.lineNumber, left.type, LineNumberPrefix.LEFT, left.value, right.lineNumber, LineNumberPrefix.RIGHT);
|
|
201
|
+
}
|
|
202
|
+
if (right.type === compute_lines_1.DiffType.ADDED) {
|
|
203
|
+
content = this.renderLine(null, right.type, LineNumberPrefix.RIGHT, right.value, right.lineNumber);
|
|
204
|
+
}
|
|
205
|
+
return ((0, jsx_runtime_1.jsx)("tr", { className: this.styles.line, children: content }, index));
|
|
206
|
+
};
|
|
207
|
+
/**
|
|
208
|
+
* Returns a function with clicked block number in the closure.
|
|
209
|
+
*
|
|
210
|
+
* @param id Cold fold block id.
|
|
211
|
+
*/
|
|
212
|
+
this.onBlockClickProxy = (id) => () => this.onBlockExpand(id);
|
|
213
|
+
/**
|
|
214
|
+
* Generates cold fold block. It also uses the custom message renderer when available to show
|
|
215
|
+
* cold fold messages.
|
|
216
|
+
*
|
|
217
|
+
* @param num Number of skipped lines between two blocks.
|
|
218
|
+
* @param blockNumber Code fold block id.
|
|
219
|
+
* @param leftBlockLineNumber First left line number after the current code fold block.
|
|
220
|
+
* @param rightBlockLineNumber First right line number after the current code fold block.
|
|
221
|
+
*/
|
|
222
|
+
this.renderSkippedLineIndicator = (num, blockNumber, leftBlockLineNumber, rightBlockLineNumber) => {
|
|
223
|
+
const { hideLineNumbers, splitView } = this.props;
|
|
224
|
+
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 }) }));
|
|
226
|
+
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}`));
|
|
230
|
+
};
|
|
231
|
+
/**
|
|
232
|
+
* Generates the entire diff view.
|
|
233
|
+
*/
|
|
234
|
+
this.renderDiff = () => {
|
|
235
|
+
const { oldValue, newValue, splitView, disableWordDiff, compareMethod, linesOffset, } = this.props;
|
|
236
|
+
const { lineInformation, diffLines } = (0, compute_lines_1.computeLineInformation)(oldValue, newValue, disableWordDiff, compareMethod, linesOffset, this.props.alwaysShowLines);
|
|
237
|
+
const extraLines = this.props.extraLinesSurroundingDiff < 0
|
|
238
|
+
? 0
|
|
239
|
+
: Math.round(this.props.extraLinesSurroundingDiff);
|
|
240
|
+
const { lineBlocks, blocks } = (0, compute_hidden_blocks_1.computeHiddenBlocks)(lineInformation, diffLines, extraLines);
|
|
241
|
+
return lineInformation.map((line, lineIndex) => {
|
|
242
|
+
if (this.props.showDiffOnly) {
|
|
243
|
+
const blockIndex = lineBlocks[lineIndex];
|
|
244
|
+
if (blockIndex !== undefined) {
|
|
245
|
+
const lastLineOfBlock = blocks[blockIndex].endLine === lineIndex;
|
|
246
|
+
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));
|
|
248
|
+
}
|
|
249
|
+
else if (!this.state.expandedBlocks.includes(blockIndex)) {
|
|
250
|
+
return null;
|
|
251
|
+
}
|
|
252
|
+
}
|
|
253
|
+
}
|
|
254
|
+
const diffNodes = splitView
|
|
255
|
+
? this.renderSplitView(line, lineIndex)
|
|
256
|
+
: this.renderInlineView(line, lineIndex);
|
|
257
|
+
return diffNodes;
|
|
258
|
+
});
|
|
259
|
+
};
|
|
260
|
+
this.render = () => {
|
|
261
|
+
const { oldValue, newValue, useDarkTheme, leftTitle, rightTitle, splitView, hideLineNumbers, nonce, } = this.props;
|
|
262
|
+
if (this.props.compareMethod !== compute_lines_1.DiffMethod.JSON) {
|
|
263
|
+
if (typeof oldValue !== 'string' || typeof newValue !== 'string') {
|
|
264
|
+
throw Error('"oldValue" and "newValue" should be strings');
|
|
265
|
+
}
|
|
266
|
+
}
|
|
267
|
+
this.styles = this.computeStyles(this.props.styles, useDarkTheme, nonce);
|
|
268
|
+
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] }) }));
|
|
277
|
+
};
|
|
278
|
+
this.state = {
|
|
279
|
+
expandedBlocks: [],
|
|
280
|
+
};
|
|
281
|
+
}
|
|
282
|
+
}
|
|
283
|
+
DiffViewer.defaultProps = {
|
|
284
|
+
oldValue: '',
|
|
285
|
+
newValue: '',
|
|
286
|
+
splitView: true,
|
|
287
|
+
highlightLines: [],
|
|
288
|
+
disableWordDiff: false,
|
|
289
|
+
compareMethod: compute_lines_1.DiffMethod.CHARS,
|
|
290
|
+
styles: {},
|
|
291
|
+
hideLineNumbers: false,
|
|
292
|
+
extraLinesSurroundingDiff: 3,
|
|
293
|
+
showDiffOnly: true,
|
|
294
|
+
useDarkTheme: false,
|
|
295
|
+
linesOffset: 0,
|
|
296
|
+
nonce: '',
|
|
297
|
+
};
|
|
298
|
+
exports.default = DiffViewer;
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
import { CSSInterpolation } from '@emotion/css';
|
|
2
|
+
export interface ReactDiffViewerStyles {
|
|
3
|
+
diffContainer?: string;
|
|
4
|
+
diffRemoved?: string;
|
|
5
|
+
diffAdded?: string;
|
|
6
|
+
diffChanged?: string;
|
|
7
|
+
line?: string;
|
|
8
|
+
highlightedGutter?: string;
|
|
9
|
+
contentText?: string;
|
|
10
|
+
gutter?: string;
|
|
11
|
+
highlightedLine?: string;
|
|
12
|
+
lineNumber?: string;
|
|
13
|
+
marker?: string;
|
|
14
|
+
wordDiff?: string;
|
|
15
|
+
wordAdded?: string;
|
|
16
|
+
wordRemoved?: string;
|
|
17
|
+
codeFoldGutter?: string;
|
|
18
|
+
emptyGutter?: string;
|
|
19
|
+
emptyLine?: string;
|
|
20
|
+
codeFold?: string;
|
|
21
|
+
titleBlock?: string;
|
|
22
|
+
content?: string;
|
|
23
|
+
splitView?: string;
|
|
24
|
+
[key: string]: string | undefined;
|
|
25
|
+
}
|
|
26
|
+
export interface ReactDiffViewerStylesVariables {
|
|
27
|
+
diffViewerBackground?: string;
|
|
28
|
+
diffViewerTitleBackground?: string;
|
|
29
|
+
diffViewerColor?: string;
|
|
30
|
+
diffViewerTitleColor?: string;
|
|
31
|
+
diffViewerTitleBorderColor?: string;
|
|
32
|
+
addedBackground?: string;
|
|
33
|
+
addedColor?: string;
|
|
34
|
+
removedBackground?: string;
|
|
35
|
+
removedColor?: string;
|
|
36
|
+
changedBackground?: string;
|
|
37
|
+
wordAddedBackground?: string;
|
|
38
|
+
wordRemovedBackground?: string;
|
|
39
|
+
addedGutterBackground?: string;
|
|
40
|
+
removedGutterBackground?: string;
|
|
41
|
+
gutterBackground?: string;
|
|
42
|
+
gutterBackgroundDark?: string;
|
|
43
|
+
highlightBackground?: string;
|
|
44
|
+
highlightGutterBackground?: string;
|
|
45
|
+
codeFoldGutterBackground?: string;
|
|
46
|
+
codeFoldBackground?: string;
|
|
47
|
+
emptyLineBackground?: string;
|
|
48
|
+
gutterColor?: string;
|
|
49
|
+
addedGutterColor?: string;
|
|
50
|
+
removedGutterColor?: string;
|
|
51
|
+
codeFoldContentColor?: string;
|
|
52
|
+
}
|
|
53
|
+
export interface ReactDiffViewerStylesOverride {
|
|
54
|
+
variables?: {
|
|
55
|
+
dark?: ReactDiffViewerStylesVariables;
|
|
56
|
+
light?: ReactDiffViewerStylesVariables;
|
|
57
|
+
};
|
|
58
|
+
diffContainer?: CSSInterpolation;
|
|
59
|
+
diffRemoved?: CSSInterpolation;
|
|
60
|
+
diffAdded?: CSSInterpolation;
|
|
61
|
+
diffChanged?: CSSInterpolation;
|
|
62
|
+
marker?: CSSInterpolation;
|
|
63
|
+
emptyGutter?: CSSInterpolation;
|
|
64
|
+
highlightedLine?: CSSInterpolation;
|
|
65
|
+
lineNumber?: CSSInterpolation;
|
|
66
|
+
highlightedGutter?: CSSInterpolation;
|
|
67
|
+
contentText?: CSSInterpolation;
|
|
68
|
+
gutter?: CSSInterpolation;
|
|
69
|
+
line?: CSSInterpolation;
|
|
70
|
+
wordDiff?: CSSInterpolation;
|
|
71
|
+
wordAdded?: CSSInterpolation;
|
|
72
|
+
wordRemoved?: CSSInterpolation;
|
|
73
|
+
codeFoldGutter?: CSSInterpolation;
|
|
74
|
+
codeFold?: CSSInterpolation;
|
|
75
|
+
emptyLine?: CSSInterpolation;
|
|
76
|
+
content?: CSSInterpolation;
|
|
77
|
+
titleBlock?: CSSInterpolation;
|
|
78
|
+
splitView?: CSSInterpolation;
|
|
79
|
+
}
|
|
80
|
+
declare const _default: (styleOverride: ReactDiffViewerStylesOverride, useDarkTheme?: boolean, nonce?: string) => ReactDiffViewerStyles;
|
|
81
|
+
export default _default;
|
|
@@ -0,0 +1,291 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __rest = (this && this.__rest) || function (s, e) {
|
|
3
|
+
var t = {};
|
|
4
|
+
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
|
|
5
|
+
t[p] = s[p];
|
|
6
|
+
if (s != null && typeof Object.getOwnPropertySymbols === "function")
|
|
7
|
+
for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
|
|
8
|
+
if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
|
|
9
|
+
t[p[i]] = s[p[i]];
|
|
10
|
+
}
|
|
11
|
+
return t;
|
|
12
|
+
};
|
|
13
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
14
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
15
|
+
};
|
|
16
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
|
+
const create_instance_1 = __importDefault(require("@emotion/css/create-instance"));
|
|
18
|
+
// eslint-disable-next-line import/no-anonymous-default-export
|
|
19
|
+
exports.default = (styleOverride, useDarkTheme = false, nonce = '') => {
|
|
20
|
+
const { variables: overrideVariables = {} } = styleOverride, styles = __rest(styleOverride, ["variables"]);
|
|
21
|
+
const themeVariables = {
|
|
22
|
+
light: Object.assign({
|
|
23
|
+
diffViewerBackground: '#fff',
|
|
24
|
+
diffViewerColor: '#212529',
|
|
25
|
+
addedBackground: '#e6ffed',
|
|
26
|
+
addedColor: '#24292e',
|
|
27
|
+
removedBackground: '#ffeef0',
|
|
28
|
+
removedColor: '#24292e',
|
|
29
|
+
changedBackground: '#fffbdd',
|
|
30
|
+
wordAddedBackground: '#acf2bd',
|
|
31
|
+
wordRemovedBackground: '#fdb8c0',
|
|
32
|
+
addedGutterBackground: '#cdffd8',
|
|
33
|
+
removedGutterBackground: '#ffdce0',
|
|
34
|
+
gutterBackground: '#f7f7f7',
|
|
35
|
+
gutterBackgroundDark: '#f3f1f1',
|
|
36
|
+
highlightBackground: '#fffbdd',
|
|
37
|
+
highlightGutterBackground: '#fff5b1',
|
|
38
|
+
codeFoldGutterBackground: '#dbedff',
|
|
39
|
+
codeFoldBackground: '#f1f8ff',
|
|
40
|
+
emptyLineBackground: '#fafbfc',
|
|
41
|
+
gutterColor: '#212529',
|
|
42
|
+
addedGutterColor: '#212529',
|
|
43
|
+
removedGutterColor: '#212529',
|
|
44
|
+
codeFoldContentColor: '#212529',
|
|
45
|
+
diffViewerTitleBackground: '#fafbfc',
|
|
46
|
+
diffViewerTitleColor: '#212529',
|
|
47
|
+
diffViewerTitleBorderColor: '#eee',
|
|
48
|
+
}, (overrideVariables.light || {})),
|
|
49
|
+
dark: Object.assign({
|
|
50
|
+
diffViewerBackground: '#2e303c',
|
|
51
|
+
diffViewerColor: '#FFF',
|
|
52
|
+
addedBackground: '#044B53',
|
|
53
|
+
addedColor: 'white',
|
|
54
|
+
removedBackground: '#632F34',
|
|
55
|
+
removedColor: 'white',
|
|
56
|
+
changedBackground: '#3e302c',
|
|
57
|
+
wordAddedBackground: '#055d67',
|
|
58
|
+
wordRemovedBackground: '#7d383f',
|
|
59
|
+
addedGutterBackground: '#034148',
|
|
60
|
+
removedGutterBackground: '#632b30',
|
|
61
|
+
gutterBackground: '#2c2f3a',
|
|
62
|
+
gutterBackgroundDark: '#262933',
|
|
63
|
+
highlightBackground: '#2a3967',
|
|
64
|
+
highlightGutterBackground: '#2d4077',
|
|
65
|
+
codeFoldGutterBackground: '#21232b',
|
|
66
|
+
codeFoldBackground: '#262831',
|
|
67
|
+
emptyLineBackground: '#363946',
|
|
68
|
+
gutterColor: '#666c87',
|
|
69
|
+
addedGutterColor: '#8c8c8c',
|
|
70
|
+
removedGutterColor: '#8c8c8c',
|
|
71
|
+
codeFoldContentColor: '#656a8b',
|
|
72
|
+
diffViewerTitleBackground: '#2f323e',
|
|
73
|
+
diffViewerTitleColor: '#555a7b',
|
|
74
|
+
diffViewerTitleBorderColor: '#353846',
|
|
75
|
+
}, (overrideVariables.dark || {})),
|
|
76
|
+
};
|
|
77
|
+
const variables = useDarkTheme ? themeVariables.dark : themeVariables.light;
|
|
78
|
+
const { css, cx } = (0, create_instance_1.default)({ key: 'react-diff', nonce });
|
|
79
|
+
const content = css({
|
|
80
|
+
width: '100%',
|
|
81
|
+
label: 'content',
|
|
82
|
+
});
|
|
83
|
+
const splitView = css({
|
|
84
|
+
[`.${content}`]: {
|
|
85
|
+
width: '50%',
|
|
86
|
+
},
|
|
87
|
+
label: 'split-view',
|
|
88
|
+
});
|
|
89
|
+
const diffContainer = css({
|
|
90
|
+
width: '100%',
|
|
91
|
+
background: variables.diffViewerBackground,
|
|
92
|
+
pre: {
|
|
93
|
+
margin: 0,
|
|
94
|
+
whiteSpace: 'pre-wrap',
|
|
95
|
+
lineHeight: '25px',
|
|
96
|
+
},
|
|
97
|
+
label: 'diff-container',
|
|
98
|
+
borderCollapse: 'collapse',
|
|
99
|
+
});
|
|
100
|
+
const codeFoldContent = css({
|
|
101
|
+
color: variables.codeFoldContentColor,
|
|
102
|
+
label: 'code-fold-content',
|
|
103
|
+
});
|
|
104
|
+
const contentText = css({
|
|
105
|
+
color: variables.diffViewerColor,
|
|
106
|
+
label: 'content-text',
|
|
107
|
+
});
|
|
108
|
+
const titleBlock = css({
|
|
109
|
+
background: variables.diffViewerTitleBackground,
|
|
110
|
+
padding: 10,
|
|
111
|
+
borderBottom: `1px solid ${variables.diffViewerTitleBorderColor}`,
|
|
112
|
+
label: 'title-block',
|
|
113
|
+
':last-child': {
|
|
114
|
+
borderLeft: `1px solid ${variables.diffViewerTitleBorderColor}`,
|
|
115
|
+
},
|
|
116
|
+
[`.${contentText}`]: {
|
|
117
|
+
color: variables.diffViewerTitleColor,
|
|
118
|
+
},
|
|
119
|
+
});
|
|
120
|
+
const lineNumber = css({
|
|
121
|
+
color: variables.gutterColor,
|
|
122
|
+
label: 'line-number',
|
|
123
|
+
});
|
|
124
|
+
const diffRemoved = css({
|
|
125
|
+
background: variables.removedBackground,
|
|
126
|
+
color: variables.removedColor,
|
|
127
|
+
pre: {
|
|
128
|
+
color: variables.removedColor,
|
|
129
|
+
},
|
|
130
|
+
[`.${lineNumber}`]: {
|
|
131
|
+
color: variables.removedGutterColor,
|
|
132
|
+
},
|
|
133
|
+
label: 'diff-removed',
|
|
134
|
+
});
|
|
135
|
+
const diffAdded = css({
|
|
136
|
+
background: variables.addedBackground,
|
|
137
|
+
color: variables.addedColor,
|
|
138
|
+
pre: {
|
|
139
|
+
color: variables.addedColor,
|
|
140
|
+
},
|
|
141
|
+
[`.${lineNumber}`]: {
|
|
142
|
+
color: variables.addedGutterColor,
|
|
143
|
+
},
|
|
144
|
+
label: 'diff-added',
|
|
145
|
+
});
|
|
146
|
+
const diffChanged = css({
|
|
147
|
+
background: variables.changedBackground,
|
|
148
|
+
[`.${lineNumber}`]: {
|
|
149
|
+
color: variables.gutterColor,
|
|
150
|
+
},
|
|
151
|
+
label: 'diff-changed',
|
|
152
|
+
});
|
|
153
|
+
const wordDiff = css({
|
|
154
|
+
padding: 2,
|
|
155
|
+
display: 'inline-flex',
|
|
156
|
+
borderRadius: 4,
|
|
157
|
+
wordBreak: 'break-all',
|
|
158
|
+
label: 'word-diff',
|
|
159
|
+
});
|
|
160
|
+
const wordAdded = css({
|
|
161
|
+
background: variables.wordAddedBackground,
|
|
162
|
+
label: 'word-added',
|
|
163
|
+
});
|
|
164
|
+
const wordRemoved = css({
|
|
165
|
+
background: variables.wordRemovedBackground,
|
|
166
|
+
label: 'word-removed',
|
|
167
|
+
});
|
|
168
|
+
const codeFoldGutter = css({
|
|
169
|
+
backgroundColor: variables.codeFoldGutterBackground,
|
|
170
|
+
label: 'code-fold-gutter',
|
|
171
|
+
});
|
|
172
|
+
const codeFold = css({
|
|
173
|
+
backgroundColor: variables.codeFoldBackground,
|
|
174
|
+
height: 40,
|
|
175
|
+
fontSize: 14,
|
|
176
|
+
fontWeight: 700,
|
|
177
|
+
label: 'code-fold',
|
|
178
|
+
a: {
|
|
179
|
+
textDecoration: 'underline !important',
|
|
180
|
+
cursor: 'pointer',
|
|
181
|
+
pre: {
|
|
182
|
+
display: 'inline',
|
|
183
|
+
},
|
|
184
|
+
},
|
|
185
|
+
});
|
|
186
|
+
const emptyLine = css({
|
|
187
|
+
backgroundColor: variables.emptyLineBackground,
|
|
188
|
+
label: 'empty-line',
|
|
189
|
+
});
|
|
190
|
+
const marker = css({
|
|
191
|
+
width: 25,
|
|
192
|
+
paddingLeft: 10,
|
|
193
|
+
paddingRight: 10,
|
|
194
|
+
userSelect: 'none',
|
|
195
|
+
label: 'marker',
|
|
196
|
+
[`&.${diffAdded}`]: {
|
|
197
|
+
pre: {
|
|
198
|
+
color: variables.addedColor,
|
|
199
|
+
},
|
|
200
|
+
},
|
|
201
|
+
[`&.${diffRemoved}`]: {
|
|
202
|
+
pre: {
|
|
203
|
+
color: variables.removedColor,
|
|
204
|
+
},
|
|
205
|
+
},
|
|
206
|
+
});
|
|
207
|
+
const highlightedLine = css({
|
|
208
|
+
background: variables.highlightBackground,
|
|
209
|
+
label: 'highlighted-line',
|
|
210
|
+
[`.${wordAdded}, .${wordRemoved}`]: {
|
|
211
|
+
backgroundColor: 'initial',
|
|
212
|
+
},
|
|
213
|
+
});
|
|
214
|
+
const highlightedGutter = css({
|
|
215
|
+
label: 'highlighted-gutter',
|
|
216
|
+
});
|
|
217
|
+
const gutter = css({
|
|
218
|
+
userSelect: 'none',
|
|
219
|
+
minWidth: 50,
|
|
220
|
+
padding: '0 10px',
|
|
221
|
+
whiteSpace: 'nowrap',
|
|
222
|
+
label: 'gutter',
|
|
223
|
+
textAlign: 'right',
|
|
224
|
+
background: variables.gutterBackground,
|
|
225
|
+
'&:hover': {
|
|
226
|
+
cursor: 'pointer',
|
|
227
|
+
background: variables.gutterBackgroundDark,
|
|
228
|
+
pre: {
|
|
229
|
+
opacity: 1,
|
|
230
|
+
},
|
|
231
|
+
},
|
|
232
|
+
pre: {
|
|
233
|
+
opacity: 0.5,
|
|
234
|
+
},
|
|
235
|
+
[`&.${diffAdded}`]: {
|
|
236
|
+
background: variables.addedGutterBackground,
|
|
237
|
+
},
|
|
238
|
+
[`&.${diffRemoved}`]: {
|
|
239
|
+
background: variables.removedGutterBackground,
|
|
240
|
+
},
|
|
241
|
+
[`&.${highlightedGutter}`]: {
|
|
242
|
+
background: variables.highlightGutterBackground,
|
|
243
|
+
'&:hover': {
|
|
244
|
+
background: variables.highlightGutterBackground,
|
|
245
|
+
},
|
|
246
|
+
},
|
|
247
|
+
});
|
|
248
|
+
const emptyGutter = css({
|
|
249
|
+
'&:hover': {
|
|
250
|
+
background: variables.gutterBackground,
|
|
251
|
+
cursor: 'initial',
|
|
252
|
+
},
|
|
253
|
+
label: 'empty-gutter',
|
|
254
|
+
});
|
|
255
|
+
const line = css({
|
|
256
|
+
verticalAlign: 'baseline',
|
|
257
|
+
label: 'line',
|
|
258
|
+
});
|
|
259
|
+
const defaultStyles = {
|
|
260
|
+
diffContainer,
|
|
261
|
+
diffRemoved,
|
|
262
|
+
diffAdded,
|
|
263
|
+
diffChanged,
|
|
264
|
+
splitView,
|
|
265
|
+
marker,
|
|
266
|
+
highlightedGutter,
|
|
267
|
+
highlightedLine,
|
|
268
|
+
gutter,
|
|
269
|
+
line,
|
|
270
|
+
wordDiff,
|
|
271
|
+
wordAdded,
|
|
272
|
+
wordRemoved,
|
|
273
|
+
codeFoldGutter,
|
|
274
|
+
codeFold,
|
|
275
|
+
emptyGutter,
|
|
276
|
+
emptyLine,
|
|
277
|
+
lineNumber,
|
|
278
|
+
contentText,
|
|
279
|
+
content,
|
|
280
|
+
codeFoldContent,
|
|
281
|
+
titleBlock,
|
|
282
|
+
};
|
|
283
|
+
const computerOverrideStyles = Object.keys(styles).reduce((acc, key) => (Object.assign(Object.assign({}, acc), {
|
|
284
|
+
[key]: css(styles[key]),
|
|
285
|
+
})), {});
|
|
286
|
+
return Object.keys(defaultStyles).reduce((acc, key) => (Object.assign(Object.assign({}, acc), {
|
|
287
|
+
[key]: computerOverrideStyles[key]
|
|
288
|
+
? cx(defaultStyles[key], computerOverrideStyles[key])
|
|
289
|
+
: defaultStyles[key],
|
|
290
|
+
})), {});
|
|
291
|
+
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "react-diff-viewer-continued",
|
|
3
|
-
"version": "3.3.
|
|
3
|
+
"version": "3.3.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": [
|
|
@@ -19,8 +19,8 @@
|
|
|
19
19
|
"Pranesh Ravi<praneshpranesh@gmail.com>",
|
|
20
20
|
"Bart Riepe <bart@serial-experiments.com>"
|
|
21
21
|
],
|
|
22
|
-
"main": "lib/index",
|
|
23
|
-
"typings": "lib/index",
|
|
22
|
+
"main": "lib/src/index",
|
|
23
|
+
"typings": "lib/src/index",
|
|
24
24
|
"scripts": {
|
|
25
25
|
"build": "tsc --outDir lib/",
|
|
26
26
|
"build:examples": "webpack --progress",
|