@git-diff-view/react 0.0.25 → 0.0.27

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.
Files changed (65) hide show
  1. package/dist/cjs/index.development.js +543 -376
  2. package/dist/cjs/index.development.js.map +1 -1
  3. package/dist/cjs/index.production.js +543 -376
  4. package/dist/cjs/index.production.js.map +1 -1
  5. package/dist/css/diff-view-pure.css +5 -1
  6. package/dist/css/diff-view.css +6 -2
  7. package/dist/esm/index.mjs +485 -321
  8. package/dist/esm/index.mjs.map +1 -1
  9. package/index.d.ts +317 -23
  10. package/package.json +8 -7
  11. package/src/_base.css +3 -0
  12. package/src/_base_pure.css +2 -0
  13. package/src/_com.css +172 -0
  14. package/src/_theme.css +2 -0
  15. package/src/components/DiffAddWidget.tsx +86 -0
  16. package/src/components/DiffContent.tsx +367 -0
  17. package/src/components/DiffContent_v2.tsx +344 -0
  18. package/src/components/DiffExpand.tsx +25 -0
  19. package/src/components/DiffNoNewLine.tsx +10 -0
  20. package/src/components/DiffSplitContentLineNormal.tsx +164 -0
  21. package/src/components/DiffSplitContentLineWrap.tsx +234 -0
  22. package/src/components/DiffSplitExtendLineNormal.tsx +150 -0
  23. package/src/components/DiffSplitExtendLineWrap.tsx +133 -0
  24. package/src/components/DiffSplitHunkLineNormal.tsx +316 -0
  25. package/src/components/DiffSplitHunkLineWrap.tsx +340 -0
  26. package/src/components/DiffSplitView.tsx +46 -0
  27. package/src/components/DiffSplitViewNormal.tsx +205 -0
  28. package/src/components/DiffSplitViewWrap.tsx +141 -0
  29. package/src/components/DiffSplitWidgetLineNormal.tsx +149 -0
  30. package/src/components/DiffSplitWidgetLineWrap.tsx +127 -0
  31. package/src/components/DiffUnifiedContentLine.tsx +342 -0
  32. package/src/components/DiffUnifiedExtendLine.tsx +103 -0
  33. package/src/components/DiffUnifiedHunkLine.tsx +148 -0
  34. package/src/components/DiffUnifiedView.tsx +159 -0
  35. package/src/components/DiffUnifiedWidgetLine.tsx +104 -0
  36. package/src/components/DiffView.tsx +365 -0
  37. package/src/components/DiffViewContext.ts +11 -0
  38. package/src/components/DiffWidgetContext.ts +17 -0
  39. package/src/components/tools.ts +132 -0
  40. package/src/components/v2/DiffSplitContentLineNormal_v2.tsx +152 -0
  41. package/src/components/v2/DiffSplitContentLineWrap_v2.tsx +259 -0
  42. package/src/components/v2/DiffSplitExtendLineNormal_v2.tsx +146 -0
  43. package/src/components/v2/DiffSplitExtendLineWrap_v2.tsx +123 -0
  44. package/src/components/v2/DiffSplitHunkLineNormal_v2.tsx +302 -0
  45. package/src/components/v2/DiffSplitHunkLineWrap_v2.tsx +326 -0
  46. package/src/components/v2/DiffSplitViewLineNormal_v2.tsx +33 -0
  47. package/src/components/v2/DiffSplitViewLineWrap_v2.tsx +24 -0
  48. package/src/components/v2/DiffSplitViewNormal_v2.tsx +159 -0
  49. package/src/components/v2/DiffSplitViewWrap_v2.tsx +104 -0
  50. package/src/components/v2/DiffSplitView_v2.tsx +47 -0
  51. package/src/components/v2/DiffSplitWidgetLineNormal_v2.tsx +132 -0
  52. package/src/components/v2/DiffSplitWidgetLineWrap_v2.tsx +119 -0
  53. package/src/global.d.ts +12 -0
  54. package/src/hooks/useCallbackRef.ts +18 -0
  55. package/src/hooks/useDomWidth.ts +67 -0
  56. package/src/hooks/useIsMounted.ts +11 -0
  57. package/src/hooks/useSafeLayout.ts +5 -0
  58. package/src/hooks/useSyncHeight.ts +87 -0
  59. package/src/hooks/useTextWidth.ts +27 -0
  60. package/src/hooks/useUnmount.ts +10 -0
  61. package/src/index.ts +3 -0
  62. package/src/tailwind.css +3 -0
  63. package/src/tailwind_pure.css +3 -0
  64. package/styles/diff-view-pure.css +5 -1
  65. package/styles/diff-view.css +6 -2
package/src/_com.css ADDED
@@ -0,0 +1,172 @@
1
+ * {
2
+ box-sizing: border-box;
3
+ }
4
+
5
+ [data-theme="light"] .diff-style-root {
6
+ --diff-border--: #dedede;
7
+ --diff-add-content--: #e6ffec;
8
+ --diff-del-content--: #ffebe9;
9
+ --diff-add-lineNumber--: #ccffd8;
10
+ --diff-del-lineNumber--: #ffd7d5;
11
+ --diff-plain-content--: #ffffff;
12
+ --diff-expand-content--: #fafafa;
13
+ --diff-plain-lineNumber--: #fafafa;
14
+ --diff-expand-lineNumber--: #fafafa;
15
+ --diff-plain-lineNumber-color--: #555555;
16
+ --diff-expand-lineNumber-color--: #555555;
17
+ --diff-hunk-content--: #ddf4ff;
18
+ --diff-hunk-lineNumber--: #c7ecff;
19
+ --diff-hunk-lineNumber-hover--: #0969da;
20
+ --diff-add-content-highlight--: #abf2bc;
21
+ --diff-del-content-highlight--: #ffb3ad;
22
+ --diff-add-widget--: #0969d2;
23
+ --diff-add-widget-color--: #ffffff;
24
+ --diff-empty-content--: #fafafa;
25
+ --diff-hunk-content-color--: #777777;
26
+
27
+ color: black;
28
+ }
29
+
30
+ .diff-style-root .diff-line-syntax-raw *,
31
+ [data-theme="light"] .diff-line-syntax-raw * {
32
+ color: var(--diff-view-light, inherit);
33
+ font-weight: var(--diff-view-light-font-weight, inherit);
34
+ }
35
+
36
+ [data-theme="dark"] .diff-style-root {
37
+ --diff-border--: #3d444d;
38
+ --diff-add-content--: #14261f;
39
+ --diff-del-content--: #311b1f;
40
+ --diff-add-lineNumber--: #1f4429;
41
+ --diff-del-lineNumber--: #552527;
42
+ --diff-plain-content--: #0d1117;
43
+ --diff-expand-content--: #161b22;
44
+ --diff-plain-lineNumber--: #161b22;
45
+ --diff-expand-lineNumber--: #161b22;
46
+ --diff-plain-lineNumber-color--: #a0aaab;
47
+ --diff-expand-lineNumber-color--: #a0aaab;
48
+ --diff-hunk-content--: #131d2e;
49
+ --diff-hunk-lineNumber--: #204274;
50
+ --diff-hunk-lineNumber-hover--: #1f6feb;
51
+ --diff-add-content-highlight--: #1f572d;
52
+ --diff-del-content-highlight--: #80312f;
53
+ --diff-add-widget--: #0969d2;
54
+ --diff-add-widget-color--: #ffffff;
55
+ --diff-empty-content--: #161b22;
56
+ --diff-hunk-content-color--: #9298a0;
57
+
58
+ color: white;
59
+ }
60
+
61
+ [data-theme="dark"] .diff-line-syntax-raw * {
62
+ color: var(--diff-view-dark, inherit);
63
+ font-weight: var(--diff-view-dark-font-weight, inherit);
64
+ }
65
+
66
+ table,
67
+ tr,
68
+ td {
69
+ border-color: transparent;
70
+ border-width: 0px;
71
+ text-align: left;
72
+ }
73
+
74
+ .diff-line-old-num,
75
+ .diff-line-new-num,
76
+ .diff-line-num {
77
+ text-align: right;
78
+ }
79
+
80
+ .diff-style-root tr {
81
+ content-visibility: auto;
82
+ }
83
+
84
+ .diff-add-widget-wrapper {
85
+ transform-origin: center;
86
+ transform: translateX(-50%) !important;
87
+ }
88
+
89
+ .diff-line-old-content .diff-add-widget-wrapper,
90
+ .diff-line-new-content .diff-add-widget-wrapper {
91
+ transform: translateX(50%) !important;
92
+ }
93
+
94
+ .diff-add-widget-wrapper:hover {
95
+ transform: translateX(-50%) scale(1.1) !important;
96
+ }
97
+
98
+ .diff-line-old-content .diff-add-widget-wrapper:hover,
99
+ .diff-line-new-content .diff-add-widget-wrapper:hover {
100
+ transform: translateX(50%) scale(1.1) !important;
101
+ }
102
+
103
+ .diff-widget-tooltip {
104
+ position: relative;
105
+ }
106
+
107
+ .diff-add-widget,
108
+ .diff-widget-tooltip {
109
+ font-family: inherit;
110
+ font-feature-settings: inherit;
111
+ font-variation-settings: inherit;
112
+ font-size: 100%;
113
+ font-weight: inherit;
114
+ line-height: inherit;
115
+ letter-spacing: inherit;
116
+ color: inherit;
117
+ margin: 0;
118
+ text-transform: none;
119
+ border-width: 0px;
120
+ background-color: transparent;
121
+ background-image: none;
122
+ }
123
+
124
+ .diff-widget-tooltip::after {
125
+ display: none;
126
+ box-sizing: border-box;
127
+ background-color: #555555;
128
+ position: absolute;
129
+ content: attr(data-title);
130
+ font-size: 11px;
131
+ padding: 1px 2px;
132
+ border-radius: 4px;
133
+ overflow: hidden;
134
+ top: 50%;
135
+ white-space: nowrap;
136
+ transform: translateY(-50%);
137
+ left: calc(100% + 8px);
138
+ color: #ffffff;
139
+ }
140
+
141
+ .diff-widget-tooltip::before {
142
+ display: none;
143
+ box-sizing: border-box;
144
+ content: "";
145
+ position: absolute;
146
+ top: 50%;
147
+ left: calc(100% - 2px);
148
+ transform: translateY(-50%);
149
+ border: 6px solid transparent;
150
+ border-right-color: #555555;
151
+ }
152
+
153
+ .diff-widget-tooltip:hover {
154
+ background-color: var(--diff-hunk-lineNumber-hover--);
155
+ color: white;
156
+ }
157
+
158
+ .diff-widget-tooltip:hover::before {
159
+ display: block;
160
+ }
161
+
162
+ .diff-widget-tooltip:hover::after {
163
+ display: block;
164
+ }
165
+
166
+ .diff-line-extend-wrapper * {
167
+ color: initial;
168
+ }
169
+
170
+ .diff-line-widget-wrapper * {
171
+ color: initial;
172
+ }
package/src/_theme.css ADDED
@@ -0,0 +1,2 @@
1
+ @import url(highlight.js/styles/github.css);
2
+ @import url(highlight.js/styles/github-dark.css);
@@ -0,0 +1,86 @@
1
+ import { addWidgetBGName, addWidgetColorName, diffFontSizeName } from "@git-diff-view/utils";
2
+ import * as React from "react";
3
+
4
+ import type { SplitSide } from "./DiffView";
5
+ import type { DiffFile } from "@git-diff-view/core";
6
+
7
+ export const DiffSplitAddWidget = ({
8
+ side,
9
+ className,
10
+ lineNumber,
11
+ onWidgetClick,
12
+ onOpenAddWidget,
13
+ }: {
14
+ index: number;
15
+ lineNumber: number;
16
+ diffFile: DiffFile;
17
+ side: SplitSide;
18
+ className?: string;
19
+ onWidgetClick?: (lineNumber: number, side: SplitSide) => void;
20
+ onOpenAddWidget: (lineNumber: number, side: SplitSide) => void;
21
+ }) => {
22
+ return (
23
+ <div
24
+ className={
25
+ "diff-add-widget-wrapper invisible select-none transition-transform hover:scale-110 group-hover:visible" +
26
+ (className ? " " + className : "")
27
+ }
28
+ style={{
29
+ width: `calc(var(${diffFontSizeName}) * 1.4)`,
30
+ height: `calc(var(${diffFontSizeName}) * 1.4)`,
31
+ }}
32
+ >
33
+ <button
34
+ className="diff-add-widget z-[1] flex h-full w-full origin-center cursor-pointer items-center justify-center rounded-md text-[1.2em]"
35
+ style={{
36
+ color: `var(${addWidgetColorName})`,
37
+ backgroundColor: `var(${addWidgetBGName})`,
38
+ }}
39
+ onClick={() => {
40
+ onOpenAddWidget(lineNumber, side);
41
+ onWidgetClick?.(lineNumber, side);
42
+ }}
43
+ >
44
+ +
45
+ </button>
46
+ </div>
47
+ );
48
+ };
49
+
50
+ export const DiffUnifiedAddWidget = ({
51
+ lineNumber,
52
+ side,
53
+ onWidgetClick,
54
+ onOpenAddWidget,
55
+ }: {
56
+ index: number;
57
+ diffFile: DiffFile;
58
+ lineNumber: number;
59
+ side: SplitSide;
60
+ onWidgetClick?: (lineNumber: number, side: SplitSide) => void;
61
+ onOpenAddWidget: (lineNumber: number, side: SplitSide) => void;
62
+ }) => {
63
+ return (
64
+ <div
65
+ className="diff-add-widget-wrapper invisible absolute left-[100%] top-[1px] translate-x-[-50%] select-none transition-transform hover:scale-110 group-hover:visible"
66
+ style={{
67
+ width: `calc(var(${diffFontSizeName}) * 1.4)`,
68
+ height: `calc(var(${diffFontSizeName}) * 1.4)`,
69
+ }}
70
+ >
71
+ <button
72
+ className="diff-add-widget z-[1] flex h-full w-full origin-center cursor-pointer items-center justify-center rounded-md text-[1.2em]"
73
+ style={{
74
+ color: `var(${addWidgetColorName})`,
75
+ backgroundColor: `var(${addWidgetBGName})`,
76
+ }}
77
+ onClick={() => {
78
+ onOpenAddWidget(lineNumber, side);
79
+ onWidgetClick?.(lineNumber, side);
80
+ }}
81
+ >
82
+ +
83
+ </button>
84
+ </div>
85
+ );
86
+ };
@@ -0,0 +1,367 @@
1
+ /* eslint-disable max-lines */
2
+ import {
3
+ DiffLineType,
4
+ NewLineSymbol,
5
+ getSyntaxDiffTemplate,
6
+ getSyntaxLineTemplate,
7
+ getPlainDiffTemplate,
8
+ getPlainLineTemplate,
9
+ } from "@git-diff-view/core";
10
+ import {
11
+ memoFunc,
12
+ addContentHighlightBGName,
13
+ delContentHighlightBGName,
14
+ diffFontSizeName,
15
+ getSymbol,
16
+ } from "@git-diff-view/utils";
17
+ import * as React from "react";
18
+
19
+ import { DiffNoNewLine } from "./DiffNoNewLine";
20
+
21
+ import type { DiffFile, DiffLine, File } from "@git-diff-view/core";
22
+
23
+ const temp = {};
24
+
25
+ const formatStringToCamelCase = (str: string) => {
26
+ if (str.startsWith("--")) return str;
27
+ const splitted = str.split("-");
28
+ if (splitted.length === 1) return splitted[0];
29
+ return (
30
+ splitted[0] +
31
+ splitted
32
+ .slice(1)
33
+ .map((word) => word[0].toUpperCase() + word.slice(1))
34
+ .join("")
35
+ );
36
+ };
37
+
38
+ export const getStyleObjectFromString = memoFunc((str: string) => {
39
+ if (!str) return temp;
40
+ const style = {};
41
+ str.split(";").forEach((el) => {
42
+ const [property, value] = el.split(":");
43
+ if (!property) return;
44
+
45
+ const formattedProperty = formatStringToCamelCase(property.trim());
46
+ style[formattedProperty] = value.trim();
47
+ });
48
+ return style;
49
+ });
50
+
51
+ const DiffString = ({
52
+ rawLine,
53
+ diffLine,
54
+ operator,
55
+ plainLine,
56
+ enableWrap,
57
+ }: {
58
+ rawLine: string;
59
+ diffLine?: DiffLine;
60
+ operator?: "add" | "del";
61
+ plainLine?: File["plainFile"][number];
62
+ enableWrap?: boolean;
63
+ }) => {
64
+ const changes = diffLine?.changes;
65
+
66
+ if (changes?.hasLineChange) {
67
+ const isNewLineSymbolChanged = changes.newLineSymbol;
68
+
69
+ if (!diffLine?.plainTemplate && typeof getPlainDiffTemplate === "function") {
70
+ getPlainDiffTemplate({ diffLine, rawLine, operator });
71
+ }
72
+
73
+ if (diffLine?.plainTemplate) {
74
+ return (
75
+ <span className="diff-line-content-raw">
76
+ <span data-template dangerouslySetInnerHTML={{ __html: diffLine.plainTemplate }} />
77
+ {isNewLineSymbolChanged === NewLineSymbol.NEWLINE && (
78
+ <span
79
+ data-no-newline-at-end-of-file-symbol
80
+ className={enableWrap ? "block !text-red-500" : "inline-block align-middle !text-red-500"}
81
+ style={{
82
+ width: `var(${diffFontSizeName})`,
83
+ height: `var(${diffFontSizeName})`,
84
+ }}
85
+ >
86
+ <DiffNoNewLine />
87
+ </span>
88
+ )}
89
+ </span>
90
+ );
91
+ } else {
92
+ // TODO remove
93
+ const range = changes.range;
94
+ const str1 = rawLine.slice(0, range.location);
95
+ const str2 = rawLine.slice(range.location, range.location + range.length);
96
+ const str3 = rawLine.slice(range.location + range.length);
97
+ const isLast = str2.includes("\n");
98
+ const _str2 = isLast ? str2.replace("\n", "").replace("\r", "") : str2;
99
+ return (
100
+ <span className="diff-line-content-raw">
101
+ <span data-range-start={range.location} data-range-end={range.location + range.length}>
102
+ {str1}
103
+ <span
104
+ data-diff-highlight
105
+ className="rounded-[0.2em]"
106
+ style={{
107
+ backgroundColor:
108
+ operator === "add" ? `var(${addContentHighlightBGName})` : `var(${delContentHighlightBGName})`,
109
+ }}
110
+ >
111
+ {isLast ? (
112
+ <>
113
+ {_str2}
114
+ <span data-newline-symbol>{getSymbol(isNewLineSymbolChanged)}</span>
115
+ </>
116
+ ) : (
117
+ str2
118
+ )}
119
+ </span>
120
+ {str3}
121
+ </span>
122
+ {isNewLineSymbolChanged === NewLineSymbol.NEWLINE && (
123
+ <span
124
+ data-no-newline-at-end-of-file-symbol
125
+ className={enableWrap ? "block !text-red-500" : "inline-block align-middle !text-red-500"}
126
+ style={{
127
+ width: `var(${diffFontSizeName})`,
128
+ height: `var(${diffFontSizeName})`,
129
+ }}
130
+ >
131
+ <DiffNoNewLine />
132
+ </span>
133
+ )}
134
+ </span>
135
+ );
136
+ }
137
+ }
138
+
139
+ if (plainLine && !plainLine?.template) {
140
+ plainLine.template = getPlainLineTemplate(plainLine.value);
141
+ }
142
+
143
+ if (plainLine?.template) {
144
+ return (
145
+ <span className="diff-line-content-raw">
146
+ <span data-template dangerouslySetInnerHTML={{ __html: plainLine.template }} />
147
+ </span>
148
+ );
149
+ }
150
+
151
+ return <span className="diff-line-content-raw">{rawLine}</span>;
152
+ };
153
+
154
+ const DiffSyntax = ({
155
+ rawLine,
156
+ diffLine,
157
+ operator,
158
+ syntaxLine,
159
+ enableWrap,
160
+ }: {
161
+ rawLine: string;
162
+ diffLine?: DiffLine;
163
+ syntaxLine?: File["syntaxFile"][number];
164
+ operator?: "add" | "del";
165
+ enableWrap?: boolean;
166
+ }) => {
167
+ if (!syntaxLine) {
168
+ return <DiffString rawLine={rawLine} diffLine={diffLine} operator={operator} />;
169
+ }
170
+
171
+ const changes = diffLine?.changes;
172
+
173
+ if (changes?.hasLineChange) {
174
+ const isNewLineSymbolChanged = changes.newLineSymbol;
175
+
176
+ if (!diffLine?.syntaxTemplate && typeof getSyntaxDiffTemplate === "function") {
177
+ getSyntaxDiffTemplate({ diffLine, syntaxLine, operator });
178
+ }
179
+
180
+ if (diffLine?.syntaxTemplate) {
181
+ return (
182
+ <span className="diff-line-syntax-raw">
183
+ <span data-template dangerouslySetInnerHTML={{ __html: diffLine.syntaxTemplate }} />
184
+ {isNewLineSymbolChanged === NewLineSymbol.NEWLINE && (
185
+ <span
186
+ data-no-newline-at-end-of-file-symbol
187
+ className={enableWrap ? "block !text-red-500" : "inline-block align-middle !text-red-500"}
188
+ style={{
189
+ width: `var(${diffFontSizeName})`,
190
+ height: `var(${diffFontSizeName})`,
191
+ }}
192
+ >
193
+ <DiffNoNewLine />
194
+ </span>
195
+ )}
196
+ </span>
197
+ );
198
+ } else {
199
+ // TODO remove
200
+ const range = changes.range;
201
+
202
+ return (
203
+ <span className="diff-line-syntax-raw">
204
+ <span data-range-start={range.location} data-range-end={range.location + range.length}>
205
+ {syntaxLine.nodeList?.map(({ node, wrapper }, index) => {
206
+ if (node.endIndex < range.location || range.location + range.length < node.startIndex) {
207
+ return (
208
+ <span
209
+ key={index}
210
+ data-start={node.startIndex}
211
+ data-end={node.endIndex}
212
+ className={wrapper?.properties?.className?.join(" ")}
213
+ style={getStyleObjectFromString(wrapper?.properties?.style || "")}
214
+ >
215
+ {node.value}
216
+ </span>
217
+ );
218
+ } else {
219
+ const index1 = range.location - node.startIndex;
220
+ const index2 = index1 < 0 ? 0 : index1;
221
+ const str1 = node.value.slice(0, index2);
222
+ const str2 = node.value.slice(index2, index1 + range.length);
223
+ const str3 = node.value.slice(index1 + range.length);
224
+ const isStart = str1.length || range.location === node.startIndex;
225
+ const isEnd = str3.length || node.endIndex === range.location + range.length - 1;
226
+ const isLast = str2.includes("\n");
227
+ const _str2 = isLast ? str2.replace("\n", "").replace("\r", "") : str2;
228
+ return (
229
+ <span
230
+ key={index}
231
+ data-start={node.startIndex}
232
+ data-end={node.endIndex}
233
+ className={wrapper?.properties?.className?.join(" ")}
234
+ style={getStyleObjectFromString(wrapper?.properties?.style || "")}
235
+ >
236
+ {str1}
237
+ <span
238
+ data-diff-highlight
239
+ style={{
240
+ backgroundColor:
241
+ operator === "add"
242
+ ? `var(${addContentHighlightBGName})`
243
+ : `var(${delContentHighlightBGName})`,
244
+ borderTopLeftRadius: isStart ? "0.2em" : undefined,
245
+ borderBottomLeftRadius: isStart ? "0.2em" : undefined,
246
+ borderTopRightRadius: isEnd || isLast ? "0.2em" : undefined,
247
+ borderBottomRightRadius: isEnd || isLast ? "0.2em" : undefined,
248
+ }}
249
+ >
250
+ {isLast ? (
251
+ <>
252
+ {_str2}
253
+ <span data-newline-symbol>{getSymbol(isNewLineSymbolChanged)}</span>
254
+ </>
255
+ ) : (
256
+ str2
257
+ )}
258
+ </span>
259
+ {str3}
260
+ </span>
261
+ );
262
+ }
263
+ })}
264
+ </span>
265
+ {isNewLineSymbolChanged === NewLineSymbol.NEWLINE && (
266
+ <span
267
+ data-no-newline-at-end-of-file-symbol
268
+ className={enableWrap ? "block !text-red-500" : "inline-block align-middle !text-red-500"}
269
+ style={{
270
+ width: `var(${diffFontSizeName})`,
271
+ height: `var(${diffFontSizeName})`,
272
+ }}
273
+ >
274
+ <DiffNoNewLine />
275
+ </span>
276
+ )}
277
+ </span>
278
+ );
279
+ }
280
+ }
281
+
282
+ if (!syntaxLine.template) {
283
+ syntaxLine.template = getSyntaxLineTemplate(syntaxLine);
284
+ }
285
+
286
+ if (syntaxLine?.template) {
287
+ return (
288
+ <span className="diff-line-syntax-raw">
289
+ <span data-template dangerouslySetInnerHTML={{ __html: syntaxLine.template }} />
290
+ </span>
291
+ );
292
+ }
293
+
294
+ return (
295
+ <span className="diff-line-syntax-raw">
296
+ {syntaxLine?.nodeList?.map(({ node, wrapper }, index) => (
297
+ <span
298
+ key={index}
299
+ data-start={node.startIndex}
300
+ data-end={node.endIndex}
301
+ className={wrapper?.properties?.className?.join(" ")}
302
+ style={getStyleObjectFromString(wrapper?.properties?.style || "")}
303
+ >
304
+ {node.value}
305
+ </span>
306
+ ))}
307
+ </span>
308
+ );
309
+ };
310
+
311
+ export const DiffContent = ({
312
+ diffLine,
313
+ rawLine,
314
+ plainLine,
315
+ syntaxLine,
316
+ enableWrap,
317
+ enableHighlight,
318
+ }: {
319
+ rawLine: string;
320
+ plainLine?: File["plainFile"][number];
321
+ syntaxLine?: File["syntaxFile"][number];
322
+ diffLine?: DiffLine;
323
+ diffFile: DiffFile;
324
+ enableWrap: boolean;
325
+ enableHighlight: boolean;
326
+ }) => {
327
+ const isAdded = diffLine?.type === DiffLineType.Add;
328
+
329
+ const isDelete = diffLine?.type === DiffLineType.Delete;
330
+
331
+ const isMaxLineLengthToIgnoreSyntax = syntaxLine?.nodeList?.length > 150;
332
+
333
+ return (
334
+ <div
335
+ className="diff-line-content-item pl-[2.0em]"
336
+ // data-val={rawLine}
337
+ style={{
338
+ whiteSpace: enableWrap ? "pre-wrap" : "pre",
339
+ wordBreak: enableWrap ? "break-all" : "initial",
340
+ }}
341
+ >
342
+ <span
343
+ data-operator={isAdded ? "+" : isDelete ? "-" : undefined}
344
+ className="diff-line-content-operator ml-[-1.5em] inline-block w-[1.5em] select-none indent-[0.2em]"
345
+ >
346
+ {isAdded ? "+" : isDelete ? "-" : " "}
347
+ </span>
348
+ {enableHighlight && syntaxLine && !isMaxLineLengthToIgnoreSyntax ? (
349
+ <DiffSyntax
350
+ operator={isAdded ? "add" : isDelete ? "del" : undefined}
351
+ rawLine={rawLine}
352
+ diffLine={diffLine}
353
+ syntaxLine={syntaxLine}
354
+ enableWrap={enableWrap}
355
+ />
356
+ ) : (
357
+ <DiffString
358
+ operator={isAdded ? "add" : isDelete ? "del" : undefined}
359
+ rawLine={rawLine}
360
+ diffLine={diffLine}
361
+ plainLine={plainLine}
362
+ enableWrap={enableWrap}
363
+ />
364
+ )}
365
+ </div>
366
+ );
367
+ };