@particle-academy/fancy-code 0.7.0 → 0.8.0
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/README.md +20 -0
- package/dist/index.cjs +106 -45
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +52 -7
- package/dist/index.d.ts +52 -7
- package/dist/index.js +100 -45
- package/dist/index.js.map +1 -1
- package/package.json +5 -2
package/dist/index.d.cts
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
import * as react from 'react';
|
|
2
2
|
import { RefObject, ReactNode, CSSProperties } from 'react';
|
|
3
|
+
import { DiffAnnotations, LineChangeType } from '@particle-academy/fancy-file-commons';
|
|
4
|
+
export { languageFromFilename } from '@particle-academy/fancy-file-commons';
|
|
3
5
|
import { MediaKind, MediaViewerProps, InputTagProps, InputTagTriggers, InputTagAdapter } from '@particle-academy/react-fancy';
|
|
4
6
|
|
|
5
7
|
interface ThemeColors {
|
|
@@ -11,6 +13,9 @@ interface ThemeColors {
|
|
|
11
13
|
activeLineBackground: string;
|
|
12
14
|
selectionBackground: string;
|
|
13
15
|
cursorColor: string;
|
|
16
|
+
diffAdded?: string;
|
|
17
|
+
diffModified?: string;
|
|
18
|
+
diffRemoved?: string;
|
|
14
19
|
keyword: string;
|
|
15
20
|
string: string;
|
|
16
21
|
comment: string;
|
|
@@ -93,6 +98,15 @@ interface CodeEditorProps {
|
|
|
93
98
|
cursorLine?: number;
|
|
94
99
|
/** 1-based column for {@link cursorLine} (default 1). */
|
|
95
100
|
cursorColumn?: number;
|
|
101
|
+
/**
|
|
102
|
+
* Baseline document for the diff gutter. When set, the line-number column
|
|
103
|
+
* shows per-line change marks of the CURRENT value against this baseline —
|
|
104
|
+
* VS Code convention: a green bar for added lines, a blue bar for modified
|
|
105
|
+
* lines, and a red wedge where lines were deleted. Recomputed live as the
|
|
106
|
+
* user types (line-level only — cheap). `null`/omitted disables the gutter
|
|
107
|
+
* marks. Requires `lineNumbers`.
|
|
108
|
+
*/
|
|
109
|
+
diffBase?: string | null;
|
|
96
110
|
}
|
|
97
111
|
interface CodeEditorContextValue {
|
|
98
112
|
/** Get the current document text */
|
|
@@ -151,6 +165,18 @@ interface CodeEditorContextValue {
|
|
|
151
165
|
textareaRef: RefObject<HTMLTextAreaElement | null>;
|
|
152
166
|
/** Placeholder text */
|
|
153
167
|
placeholder?: string;
|
|
168
|
+
/**
|
|
169
|
+
* Totals of the live diff against {@link CodeEditorProps.diffBase} —
|
|
170
|
+
* `{ added, modified, removed }` — or `null` when no baseline is set.
|
|
171
|
+
* Handy for a status-bar chip or a host's save indicator.
|
|
172
|
+
*/
|
|
173
|
+
diffStats: {
|
|
174
|
+
added: number;
|
|
175
|
+
modified: number;
|
|
176
|
+
removed: number;
|
|
177
|
+
} | null;
|
|
178
|
+
/** @internal — per-line gutter annotations for the diff marks. */
|
|
179
|
+
_diffAnnotations: DiffAnnotations | null;
|
|
154
180
|
/** @internal */
|
|
155
181
|
_engineReturn: UseEditorEngineReturn | null;
|
|
156
182
|
/** @internal */
|
|
@@ -190,7 +216,7 @@ declare namespace CodeEditorStatusBar {
|
|
|
190
216
|
var displayName: string;
|
|
191
217
|
}
|
|
192
218
|
|
|
193
|
-
declare function CodeEditorRoot({ children, className, value: valueProp, defaultValue, onChange, language: languageProp, onLanguageChange, theme, readOnly, lineNumbers: lineNumbersProp, wordWrap: wordWrapProp, tabSize: tabSizeProp, placeholder, minHeight, maxHeight, cursorLine, cursorColumn, }: CodeEditorProps): react.JSX.Element;
|
|
219
|
+
declare function CodeEditorRoot({ children, className, value: valueProp, defaultValue, onChange, language: languageProp, onLanguageChange, theme, readOnly, lineNumbers: lineNumbersProp, wordWrap: wordWrapProp, tabSize: tabSizeProp, placeholder, minHeight, maxHeight, cursorLine, cursorColumn, diffBase, }: CodeEditorProps): react.JSX.Element;
|
|
194
220
|
declare namespace CodeEditorRoot {
|
|
195
221
|
var displayName: string;
|
|
196
222
|
}
|
|
@@ -270,11 +296,7 @@ interface ResolveFileKindInput {
|
|
|
270
296
|
/** MIME type — preferred over the filename when known. */
|
|
271
297
|
mime?: string;
|
|
272
298
|
}
|
|
273
|
-
|
|
274
|
-
* Resolve the fancy-code editor language for a filename. Returns `"plaintext"`
|
|
275
|
-
* (no syntax highlighting) for unknown or extension-less files.
|
|
276
|
-
*/
|
|
277
|
-
declare function languageFromFilename(filename?: string): string;
|
|
299
|
+
|
|
278
300
|
/**
|
|
279
301
|
* Decide whether a file is previewable media (image / video / audio / PDF) or
|
|
280
302
|
* text, from its MIME type (preferred) and/or filename. Media wins when the
|
|
@@ -352,6 +374,29 @@ declare namespace FileViewer {
|
|
|
352
374
|
var displayName: string;
|
|
353
375
|
}
|
|
354
376
|
|
|
377
|
+
/**
|
|
378
|
+
* Diff-gutter model — the pure mapping between fancy-file-commons line
|
|
379
|
+
* annotations and what the CodeEditor gutter renders per line-number row.
|
|
380
|
+
* Kept DOM-free (like engine/position.ts) so it's unit-testable; the panel
|
|
381
|
+
* only paints what this resolves.
|
|
382
|
+
*/
|
|
383
|
+
|
|
384
|
+
/** What one line-number row shows: its own change bar and/or a deletion wedge above. */
|
|
385
|
+
interface GutterDiffMark {
|
|
386
|
+
/** The line's own change (colored bar), if any. */
|
|
387
|
+
type?: LineChangeType;
|
|
388
|
+
/** True when one or more lines were deleted immediately above this line (wedge). */
|
|
389
|
+
deletedAbove: boolean;
|
|
390
|
+
}
|
|
391
|
+
/** Resolve the mark for a 1-based line, or null when the line is untouched. */
|
|
392
|
+
declare function gutterDiffMark(annotations: DiffAnnotations | null, line: number): GutterDiffMark | null;
|
|
393
|
+
/** Whether the deleted-at-EOF wedge should render under the last line. */
|
|
394
|
+
declare function hasDeletedAtEnd(annotations: DiffAnnotations | null): boolean;
|
|
395
|
+
/** The bar color for a change type, honoring theme overrides. */
|
|
396
|
+
declare function diffMarkColor(type: LineChangeType, colors: ThemeColors): string;
|
|
397
|
+
/** The deletion-wedge color, honoring theme overrides. */
|
|
398
|
+
declare function diffRemovedColor(colors: ThemeColors): string;
|
|
399
|
+
|
|
355
400
|
/**
|
|
356
401
|
* Tiny, dependency-free Markdown → HTML renderer for the MarkdownEditor preview
|
|
357
402
|
* pane. Covers the common subset — headings, bold/italic, inline + fenced code,
|
|
@@ -436,4 +481,4 @@ interface CodeEditorInputTagProps extends Omit<InputTagProps, "adapter"> {
|
|
|
436
481
|
*/
|
|
437
482
|
declare function CodeEditorInputTag(props: CodeEditorInputTagProps): react.JSX.Element;
|
|
438
483
|
|
|
439
|
-
export { CodeEditor, type CodeEditorContextValue, CodeEditorInputTag, type CodeEditorInputTagProps, type CodeEditorPanelProps, type CodeEditorProps, type CodeEditorStatusBarProps, type CodeEditorToolbarProps, type FileKind, FileViewer, type FileViewerProps, type LanguageDefinition, MarkdownEditor, type MarkdownEditorMode, type MarkdownEditorProps, type ResolveFileKindInput, type ThemeColors, type ThemeDefinition, type Token, type TokenType, type Tokenizer, getLanguage, getRegisteredLanguages, getRegisteredThemes, getTheme,
|
|
484
|
+
export { CodeEditor, type CodeEditorContextValue, CodeEditorInputTag, type CodeEditorInputTagProps, type CodeEditorPanelProps, type CodeEditorProps, type CodeEditorStatusBarProps, type CodeEditorToolbarProps, type FileKind, FileViewer, type FileViewerProps, type GutterDiffMark, type LanguageDefinition, MarkdownEditor, type MarkdownEditorMode, type MarkdownEditorProps, type ResolveFileKindInput, type ThemeColors, type ThemeDefinition, type Token, type TokenType, type Tokenizer, diffMarkColor, diffRemovedColor, getLanguage, getRegisteredLanguages, getRegisteredThemes, getTheme, gutterDiffMark, hasDeletedAtEnd, registerLanguage, registerTheme, renderMarkdown, resolveFileKind, tokenizeMarkdown, useCodeEditor, useCodeEditorInputTagAdapter };
|
package/dist/index.d.ts
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
import * as react from 'react';
|
|
2
2
|
import { RefObject, ReactNode, CSSProperties } from 'react';
|
|
3
|
+
import { DiffAnnotations, LineChangeType } from '@particle-academy/fancy-file-commons';
|
|
4
|
+
export { languageFromFilename } from '@particle-academy/fancy-file-commons';
|
|
3
5
|
import { MediaKind, MediaViewerProps, InputTagProps, InputTagTriggers, InputTagAdapter } from '@particle-academy/react-fancy';
|
|
4
6
|
|
|
5
7
|
interface ThemeColors {
|
|
@@ -11,6 +13,9 @@ interface ThemeColors {
|
|
|
11
13
|
activeLineBackground: string;
|
|
12
14
|
selectionBackground: string;
|
|
13
15
|
cursorColor: string;
|
|
16
|
+
diffAdded?: string;
|
|
17
|
+
diffModified?: string;
|
|
18
|
+
diffRemoved?: string;
|
|
14
19
|
keyword: string;
|
|
15
20
|
string: string;
|
|
16
21
|
comment: string;
|
|
@@ -93,6 +98,15 @@ interface CodeEditorProps {
|
|
|
93
98
|
cursorLine?: number;
|
|
94
99
|
/** 1-based column for {@link cursorLine} (default 1). */
|
|
95
100
|
cursorColumn?: number;
|
|
101
|
+
/**
|
|
102
|
+
* Baseline document for the diff gutter. When set, the line-number column
|
|
103
|
+
* shows per-line change marks of the CURRENT value against this baseline —
|
|
104
|
+
* VS Code convention: a green bar for added lines, a blue bar for modified
|
|
105
|
+
* lines, and a red wedge where lines were deleted. Recomputed live as the
|
|
106
|
+
* user types (line-level only — cheap). `null`/omitted disables the gutter
|
|
107
|
+
* marks. Requires `lineNumbers`.
|
|
108
|
+
*/
|
|
109
|
+
diffBase?: string | null;
|
|
96
110
|
}
|
|
97
111
|
interface CodeEditorContextValue {
|
|
98
112
|
/** Get the current document text */
|
|
@@ -151,6 +165,18 @@ interface CodeEditorContextValue {
|
|
|
151
165
|
textareaRef: RefObject<HTMLTextAreaElement | null>;
|
|
152
166
|
/** Placeholder text */
|
|
153
167
|
placeholder?: string;
|
|
168
|
+
/**
|
|
169
|
+
* Totals of the live diff against {@link CodeEditorProps.diffBase} —
|
|
170
|
+
* `{ added, modified, removed }` — or `null` when no baseline is set.
|
|
171
|
+
* Handy for a status-bar chip or a host's save indicator.
|
|
172
|
+
*/
|
|
173
|
+
diffStats: {
|
|
174
|
+
added: number;
|
|
175
|
+
modified: number;
|
|
176
|
+
removed: number;
|
|
177
|
+
} | null;
|
|
178
|
+
/** @internal — per-line gutter annotations for the diff marks. */
|
|
179
|
+
_diffAnnotations: DiffAnnotations | null;
|
|
154
180
|
/** @internal */
|
|
155
181
|
_engineReturn: UseEditorEngineReturn | null;
|
|
156
182
|
/** @internal */
|
|
@@ -190,7 +216,7 @@ declare namespace CodeEditorStatusBar {
|
|
|
190
216
|
var displayName: string;
|
|
191
217
|
}
|
|
192
218
|
|
|
193
|
-
declare function CodeEditorRoot({ children, className, value: valueProp, defaultValue, onChange, language: languageProp, onLanguageChange, theme, readOnly, lineNumbers: lineNumbersProp, wordWrap: wordWrapProp, tabSize: tabSizeProp, placeholder, minHeight, maxHeight, cursorLine, cursorColumn, }: CodeEditorProps): react.JSX.Element;
|
|
219
|
+
declare function CodeEditorRoot({ children, className, value: valueProp, defaultValue, onChange, language: languageProp, onLanguageChange, theme, readOnly, lineNumbers: lineNumbersProp, wordWrap: wordWrapProp, tabSize: tabSizeProp, placeholder, minHeight, maxHeight, cursorLine, cursorColumn, diffBase, }: CodeEditorProps): react.JSX.Element;
|
|
194
220
|
declare namespace CodeEditorRoot {
|
|
195
221
|
var displayName: string;
|
|
196
222
|
}
|
|
@@ -270,11 +296,7 @@ interface ResolveFileKindInput {
|
|
|
270
296
|
/** MIME type — preferred over the filename when known. */
|
|
271
297
|
mime?: string;
|
|
272
298
|
}
|
|
273
|
-
|
|
274
|
-
* Resolve the fancy-code editor language for a filename. Returns `"plaintext"`
|
|
275
|
-
* (no syntax highlighting) for unknown or extension-less files.
|
|
276
|
-
*/
|
|
277
|
-
declare function languageFromFilename(filename?: string): string;
|
|
299
|
+
|
|
278
300
|
/**
|
|
279
301
|
* Decide whether a file is previewable media (image / video / audio / PDF) or
|
|
280
302
|
* text, from its MIME type (preferred) and/or filename. Media wins when the
|
|
@@ -352,6 +374,29 @@ declare namespace FileViewer {
|
|
|
352
374
|
var displayName: string;
|
|
353
375
|
}
|
|
354
376
|
|
|
377
|
+
/**
|
|
378
|
+
* Diff-gutter model — the pure mapping between fancy-file-commons line
|
|
379
|
+
* annotations and what the CodeEditor gutter renders per line-number row.
|
|
380
|
+
* Kept DOM-free (like engine/position.ts) so it's unit-testable; the panel
|
|
381
|
+
* only paints what this resolves.
|
|
382
|
+
*/
|
|
383
|
+
|
|
384
|
+
/** What one line-number row shows: its own change bar and/or a deletion wedge above. */
|
|
385
|
+
interface GutterDiffMark {
|
|
386
|
+
/** The line's own change (colored bar), if any. */
|
|
387
|
+
type?: LineChangeType;
|
|
388
|
+
/** True when one or more lines were deleted immediately above this line (wedge). */
|
|
389
|
+
deletedAbove: boolean;
|
|
390
|
+
}
|
|
391
|
+
/** Resolve the mark for a 1-based line, or null when the line is untouched. */
|
|
392
|
+
declare function gutterDiffMark(annotations: DiffAnnotations | null, line: number): GutterDiffMark | null;
|
|
393
|
+
/** Whether the deleted-at-EOF wedge should render under the last line. */
|
|
394
|
+
declare function hasDeletedAtEnd(annotations: DiffAnnotations | null): boolean;
|
|
395
|
+
/** The bar color for a change type, honoring theme overrides. */
|
|
396
|
+
declare function diffMarkColor(type: LineChangeType, colors: ThemeColors): string;
|
|
397
|
+
/** The deletion-wedge color, honoring theme overrides. */
|
|
398
|
+
declare function diffRemovedColor(colors: ThemeColors): string;
|
|
399
|
+
|
|
355
400
|
/**
|
|
356
401
|
* Tiny, dependency-free Markdown → HTML renderer for the MarkdownEditor preview
|
|
357
402
|
* pane. Covers the common subset — headings, bold/italic, inline + fenced code,
|
|
@@ -436,4 +481,4 @@ interface CodeEditorInputTagProps extends Omit<InputTagProps, "adapter"> {
|
|
|
436
481
|
*/
|
|
437
482
|
declare function CodeEditorInputTag(props: CodeEditorInputTagProps): react.JSX.Element;
|
|
438
483
|
|
|
439
|
-
export { CodeEditor, type CodeEditorContextValue, CodeEditorInputTag, type CodeEditorInputTagProps, type CodeEditorPanelProps, type CodeEditorProps, type CodeEditorStatusBarProps, type CodeEditorToolbarProps, type FileKind, FileViewer, type FileViewerProps, type LanguageDefinition, MarkdownEditor, type MarkdownEditorMode, type MarkdownEditorProps, type ResolveFileKindInput, type ThemeColors, type ThemeDefinition, type Token, type TokenType, type Tokenizer, getLanguage, getRegisteredLanguages, getRegisteredThemes, getTheme,
|
|
484
|
+
export { CodeEditor, type CodeEditorContextValue, CodeEditorInputTag, type CodeEditorInputTagProps, type CodeEditorPanelProps, type CodeEditorProps, type CodeEditorStatusBarProps, type CodeEditorToolbarProps, type FileKind, FileViewer, type FileViewerProps, type GutterDiffMark, type LanguageDefinition, MarkdownEditor, type MarkdownEditorMode, type MarkdownEditorProps, type ResolveFileKindInput, type ThemeColors, type ThemeDefinition, type Token, type TokenType, type Tokenizer, diffMarkColor, diffRemovedColor, getLanguage, getRegisteredLanguages, getRegisteredThemes, getTheme, gutterDiffMark, hasDeletedAtEnd, registerLanguage, registerTheme, renderMarkdown, resolveFileKind, tokenizeMarkdown, useCodeEditor, useCodeEditorInputTagAdapter };
|
package/dist/index.js
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
|
-
import { createContext, useState, useCallback, useRef, useEffect,
|
|
1
|
+
import { createContext, useMemo, useState, useCallback, useRef, useEffect, useSyncExternalStore, useContext } from 'react';
|
|
2
2
|
import { cn, useControllableState, resolveMediaType, MediaViewer, textareaAdapter, InputTag } from '@particle-academy/react-fancy';
|
|
3
|
+
import { annotateLines, languageFromFilename } from '@particle-academy/fancy-file-commons';
|
|
4
|
+
export { languageFromFilename } from '@particle-academy/fancy-file-commons';
|
|
3
5
|
import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
|
|
4
6
|
|
|
5
7
|
// src/components/CodeEditor/CodeEditor.tsx
|
|
@@ -11,6 +13,24 @@ function useCodeEditor() {
|
|
|
11
13
|
}
|
|
12
14
|
return ctx;
|
|
13
15
|
}
|
|
16
|
+
|
|
17
|
+
// src/components/CodeEditor/diff-gutter.ts
|
|
18
|
+
function gutterDiffMark(annotations, line) {
|
|
19
|
+
if (!annotations) return null;
|
|
20
|
+
const a = annotations.byLine[line];
|
|
21
|
+
if (!a) return null;
|
|
22
|
+
return { type: a.type, deletedAbove: (a.deletedAbove ?? 0) > 0 };
|
|
23
|
+
}
|
|
24
|
+
function hasDeletedAtEnd(annotations) {
|
|
25
|
+
return (annotations?.deletedAtEnd ?? 0) > 0;
|
|
26
|
+
}
|
|
27
|
+
var FALLBACK = { added: "#3fb950", modified: "#4184e4", removed: "#f85149" };
|
|
28
|
+
function diffMarkColor(type, colors) {
|
|
29
|
+
return type === "added" ? colors.diffAdded ?? FALLBACK.added : colors.diffModified ?? FALLBACK.modified;
|
|
30
|
+
}
|
|
31
|
+
function diffRemovedColor(colors) {
|
|
32
|
+
return colors.diffRemoved ?? FALLBACK.removed;
|
|
33
|
+
}
|
|
14
34
|
function CodeEditorPanel({ className }) {
|
|
15
35
|
const {
|
|
16
36
|
_engineReturn: engine,
|
|
@@ -18,6 +38,7 @@ function CodeEditorPanel({ className }) {
|
|
|
18
38
|
wordWrap,
|
|
19
39
|
readOnly,
|
|
20
40
|
placeholder,
|
|
41
|
+
_diffAnnotations: diffAnnotations,
|
|
21
42
|
_maxHeight,
|
|
22
43
|
_minHeight
|
|
23
44
|
} = useCodeEditor();
|
|
@@ -38,25 +59,80 @@ function CodeEditorPanel({ className }) {
|
|
|
38
59
|
const gutterWidth = lineNumbers ? `${Math.max(String(lineCount).length, 2) * 0.75 + 1.5}em` : "0";
|
|
39
60
|
const lineNumberElements = useMemo(() => {
|
|
40
61
|
if (!lineNumbers) return null;
|
|
62
|
+
const removed = diffRemovedColor(themeColors);
|
|
41
63
|
const lines = [];
|
|
42
64
|
for (let i = 1; i <= lineCount; i++) {
|
|
65
|
+
const mark = gutterDiffMark(diffAnnotations, i);
|
|
43
66
|
lines.push(
|
|
44
|
-
/* @__PURE__ */
|
|
67
|
+
/* @__PURE__ */ jsxs(
|
|
45
68
|
"div",
|
|
46
69
|
{
|
|
70
|
+
"data-diff": mark?.type,
|
|
71
|
+
"data-diff-deleted-above": mark?.deletedAbove ? "" : void 0,
|
|
47
72
|
style: {
|
|
73
|
+
position: "relative",
|
|
48
74
|
color: i === activeLine ? themeColors.foreground : themeColors.gutterForeground,
|
|
49
75
|
backgroundColor: i === activeLine ? themeColors.activeLineBackground : void 0
|
|
50
76
|
},
|
|
51
77
|
className: "pr-3 text-right text-[13px] leading-[1.5] select-none",
|
|
52
|
-
children:
|
|
78
|
+
children: [
|
|
79
|
+
mark?.type && /* @__PURE__ */ jsx(
|
|
80
|
+
"span",
|
|
81
|
+
{
|
|
82
|
+
"aria-hidden": "true",
|
|
83
|
+
style: {
|
|
84
|
+
position: "absolute",
|
|
85
|
+
left: 0,
|
|
86
|
+
top: 0,
|
|
87
|
+
bottom: 0,
|
|
88
|
+
width: 3,
|
|
89
|
+
borderRadius: 2,
|
|
90
|
+
backgroundColor: diffMarkColor(mark.type, themeColors)
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
),
|
|
94
|
+
mark?.deletedAbove && /* @__PURE__ */ jsx(
|
|
95
|
+
"span",
|
|
96
|
+
{
|
|
97
|
+
"aria-hidden": "true",
|
|
98
|
+
style: {
|
|
99
|
+
position: "absolute",
|
|
100
|
+
left: 0,
|
|
101
|
+
top: -4,
|
|
102
|
+
width: 0,
|
|
103
|
+
height: 0,
|
|
104
|
+
borderLeft: `8px solid ${removed}`,
|
|
105
|
+
borderTop: "4px solid transparent",
|
|
106
|
+
borderBottom: "4px solid transparent"
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
),
|
|
110
|
+
i,
|
|
111
|
+
i === lineCount && hasDeletedAtEnd(diffAnnotations) && /* @__PURE__ */ jsx(
|
|
112
|
+
"span",
|
|
113
|
+
{
|
|
114
|
+
"aria-hidden": "true",
|
|
115
|
+
"data-diff-deleted-at-end": "",
|
|
116
|
+
style: {
|
|
117
|
+
position: "absolute",
|
|
118
|
+
left: 0,
|
|
119
|
+
bottom: -4,
|
|
120
|
+
width: 0,
|
|
121
|
+
height: 0,
|
|
122
|
+
borderLeft: `8px solid ${removed}`,
|
|
123
|
+
borderTop: "4px solid transparent",
|
|
124
|
+
borderBottom: "4px solid transparent"
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
)
|
|
128
|
+
]
|
|
53
129
|
},
|
|
54
130
|
i
|
|
55
131
|
)
|
|
56
132
|
);
|
|
57
133
|
}
|
|
58
134
|
return lines;
|
|
59
|
-
}, [lineNumbers, lineCount, activeLine, themeColors]);
|
|
135
|
+
}, [lineNumbers, lineCount, activeLine, themeColors, diffAnnotations]);
|
|
60
136
|
const containerStyle = {
|
|
61
137
|
backgroundColor: themeColors.background,
|
|
62
138
|
color: themeColors.foreground,
|
|
@@ -1258,6 +1334,9 @@ registerTheme({
|
|
|
1258
1334
|
activeLineBackground: "#f8fafc",
|
|
1259
1335
|
selectionBackground: "#dbeafe",
|
|
1260
1336
|
cursorColor: "#3b82f6",
|
|
1337
|
+
diffAdded: "#1a7f37",
|
|
1338
|
+
diffModified: "#0969da",
|
|
1339
|
+
diffRemoved: "#cf222e",
|
|
1261
1340
|
keyword: "#8b5cf6",
|
|
1262
1341
|
string: "#059669",
|
|
1263
1342
|
comment: "#94a3b8",
|
|
@@ -1286,6 +1365,9 @@ registerTheme({
|
|
|
1286
1365
|
activeLineBackground: "#27272a",
|
|
1287
1366
|
selectionBackground: "#1e3a5f",
|
|
1288
1367
|
cursorColor: "#60a5fa",
|
|
1368
|
+
diffAdded: "#3fb950",
|
|
1369
|
+
diffModified: "#4184e4",
|
|
1370
|
+
diffRemoved: "#f85149",
|
|
1289
1371
|
keyword: "#c084fc",
|
|
1290
1372
|
string: "#34d399",
|
|
1291
1373
|
comment: "#71717a",
|
|
@@ -1615,9 +1697,14 @@ function CodeEditorRoot({
|
|
|
1615
1697
|
minHeight,
|
|
1616
1698
|
maxHeight,
|
|
1617
1699
|
cursorLine,
|
|
1618
|
-
cursorColumn
|
|
1700
|
+
cursorColumn,
|
|
1701
|
+
diffBase
|
|
1619
1702
|
}) {
|
|
1620
1703
|
const [currentValue, setCurrentValue] = useControllableState(valueProp, defaultValue, onChange);
|
|
1704
|
+
const diffAnnotations = useMemo(
|
|
1705
|
+
() => diffBase == null ? null : annotateLines(diffBase, currentValue),
|
|
1706
|
+
[diffBase, currentValue]
|
|
1707
|
+
);
|
|
1621
1708
|
const isDark = useDarkMode();
|
|
1622
1709
|
const resolvedTheme = theme === "auto" ? isDark ? "dark" : "light" : theme;
|
|
1623
1710
|
const [currentLanguage, setCurrentLanguageState] = useState(() => {
|
|
@@ -1696,11 +1783,17 @@ function CodeEditorRoot({
|
|
|
1696
1783
|
selectionLength,
|
|
1697
1784
|
textareaRef: engineReturn.textareaRef,
|
|
1698
1785
|
placeholder,
|
|
1786
|
+
diffStats: diffAnnotations ? {
|
|
1787
|
+
added: diffAnnotations.added,
|
|
1788
|
+
modified: diffAnnotations.modified,
|
|
1789
|
+
removed: diffAnnotations.removed
|
|
1790
|
+
} : null,
|
|
1791
|
+
_diffAnnotations: diffAnnotations,
|
|
1699
1792
|
_engineReturn: engineReturn,
|
|
1700
1793
|
_minHeight: minHeight,
|
|
1701
1794
|
_maxHeight: maxHeight
|
|
1702
1795
|
}),
|
|
1703
|
-
[engineReturn, currentValue, currentLanguage, setLanguage, resolvedTheme, readOnly, showLineNumbers, isWordWrap, tabSizeProp, cursorPosition, selectionLength, setCurrentValue, placeholder, minHeight, maxHeight]
|
|
1796
|
+
[engineReturn, currentValue, currentLanguage, setLanguage, resolvedTheme, readOnly, showLineNumbers, isWordWrap, tabSizeProp, cursorPosition, selectionLength, setCurrentValue, placeholder, diffAnnotations, minHeight, maxHeight]
|
|
1704
1797
|
);
|
|
1705
1798
|
return /* @__PURE__ */ jsx(CodeEditorContext.Provider, { value: contextValue, children: /* @__PURE__ */ jsx(
|
|
1706
1799
|
"div",
|
|
@@ -1876,44 +1969,6 @@ function MarkdownEditor({
|
|
|
1876
1969
|
);
|
|
1877
1970
|
}
|
|
1878
1971
|
MarkdownEditor.displayName = "MarkdownEditor";
|
|
1879
|
-
var EXT_LANGUAGE = {
|
|
1880
|
-
js: "javascript",
|
|
1881
|
-
mjs: "javascript",
|
|
1882
|
-
cjs: "javascript",
|
|
1883
|
-
jsx: "javascript",
|
|
1884
|
-
json: "javascript",
|
|
1885
|
-
// the JS tokenizer highlights JSON acceptably
|
|
1886
|
-
jsonc: "javascript",
|
|
1887
|
-
ts: "typescript",
|
|
1888
|
-
mts: "typescript",
|
|
1889
|
-
cts: "typescript",
|
|
1890
|
-
tsx: "typescript",
|
|
1891
|
-
html: "html",
|
|
1892
|
-
htm: "html",
|
|
1893
|
-
xml: "html",
|
|
1894
|
-
xhtml: "html",
|
|
1895
|
-
vue: "html",
|
|
1896
|
-
php: "php",
|
|
1897
|
-
phtml: "php",
|
|
1898
|
-
py: "python",
|
|
1899
|
-
pyw: "python",
|
|
1900
|
-
go: "go",
|
|
1901
|
-
md: "markdown",
|
|
1902
|
-
markdown: "markdown",
|
|
1903
|
-
mkd: "markdown",
|
|
1904
|
-
mdx: "markdown"
|
|
1905
|
-
};
|
|
1906
|
-
function basename(filename) {
|
|
1907
|
-
return filename.split(/[?#]/, 1)[0].split(/[\\/]/).pop() ?? "";
|
|
1908
|
-
}
|
|
1909
|
-
function languageFromFilename(filename) {
|
|
1910
|
-
if (!filename) return "plaintext";
|
|
1911
|
-
const seg = basename(filename);
|
|
1912
|
-
const dot = seg.lastIndexOf(".");
|
|
1913
|
-
if (dot <= 0) return "plaintext";
|
|
1914
|
-
const ext = seg.slice(dot + 1).toLowerCase();
|
|
1915
|
-
return EXT_LANGUAGE[ext] ?? "plaintext";
|
|
1916
|
-
}
|
|
1917
1972
|
function resolveFileKind({ filename, mime }) {
|
|
1918
1973
|
const media = resolveMediaType({ mime, src: filename });
|
|
1919
1974
|
if (media !== "unknown") return { kind: "media", mediaKind: media };
|
|
@@ -1997,6 +2052,6 @@ function CodeEditorInputTag(props) {
|
|
|
1997
2052
|
return /* @__PURE__ */ jsx(InputTag, { adapter, ...props });
|
|
1998
2053
|
}
|
|
1999
2054
|
|
|
2000
|
-
export { CodeEditor, CodeEditorInputTag, FileViewer, MarkdownEditor, getLanguage, getRegisteredLanguages, getRegisteredThemes, getTheme,
|
|
2055
|
+
export { CodeEditor, CodeEditorInputTag, FileViewer, MarkdownEditor, diffMarkColor, diffRemovedColor, getLanguage, getRegisteredLanguages, getRegisteredThemes, getTheme, gutterDiffMark, hasDeletedAtEnd, registerLanguage, registerTheme, renderMarkdown, resolveFileKind, tokenizeMarkdown, useCodeEditor, useCodeEditorInputTagAdapter };
|
|
2001
2056
|
//# sourceMappingURL=index.js.map
|
|
2002
2057
|
//# sourceMappingURL=index.js.map
|