vzcode 2.3.0 → 2.4.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/package.json +3 -2
- package/src/cli.ts +208 -0
- package/src/client/AIAssist/AIAssistCodeMirrorKeyMap.ts +42 -0
- package/src/client/AIAssist/AIAssistWidget/index.tsx +135 -0
- package/src/client/AIAssist/AIAssistWidget/style.scss +47 -0
- package/src/client/AIAssist/Spinner.jsx +76 -0
- package/src/client/AIAssist/formatFile.ts +27 -0
- package/src/client/AIAssist/generateFilesContext.ts +25 -0
- package/src/client/AIAssist/index.ts +2 -0
- package/src/client/AIAssist/startAIAssist.ts +95 -0
- package/src/client/App/index.tsx +152 -0
- package/src/client/App/style.scss +82 -0
- package/src/client/App/usePending.ts +51 -0
- package/src/client/App/useShareDB.ts +161 -0
- package/src/client/CodeEditor/Copilot/index.ts +74 -0
- package/src/client/CodeEditor/InteractiveWidgets/boolToggler.ts +12 -0
- package/src/client/CodeEditor/InteractiveWidgets/colorPicker.ts +68 -0
- package/src/client/CodeEditor/InteractiveWidgets/colorsInTextPlugin.ts +174 -0
- package/src/client/CodeEditor/InteractiveWidgets/highlightWidgets.ts +79 -0
- package/src/client/CodeEditor/InteractiveWidgets/index.ts +44 -0
- package/src/client/CodeEditor/InteractiveWidgets/markdownCheckboxToggler.ts +12 -0
- package/src/client/CodeEditor/InteractiveWidgets/numberDragger.ts +20 -0
- package/src/client/CodeEditor/InteractiveWidgets/rotateWidget.ts +143 -0
- package/src/client/CodeEditor/InteractiveWidgets/urlClicker.test.ts +48 -0
- package/src/client/CodeEditor/InteractiveWidgets/urlClicker.ts +12 -0
- package/src/client/CodeEditor/InteractiveWidgets/vec2Slider.ts +25 -0
- package/src/client/CodeEditor/basicSetup.ts +73 -0
- package/src/client/CodeEditor/getOrCreateEditor.tsx +615 -0
- package/src/client/CodeEditor/index.tsx +202 -0
- package/src/client/CodeEditor/json1PresenceBroadcast.ts +41 -0
- package/src/client/CodeEditor/json1PresenceDisplay.ts +350 -0
- package/src/client/CodeEditor/rainbowBrackets.ts +122 -0
- package/src/client/CodeEditor/style.scss +156 -0
- package/src/client/CodeEditor/typescriptExtension/worker.ts +32 -0
- package/src/client/CodeErrorOverlay/index.tsx +77 -0
- package/src/client/CodeErrorOverlay/style.scss +33 -0
- package/src/client/Fonts/fonts.ts +8 -0
- package/src/client/Icons/AdjustmentSVG.tsx +19 -0
- package/src/client/Icons/BugSVG.tsx +20 -0
- package/src/client/Icons/CloseSVG.tsx +19 -0
- package/src/client/Icons/CssSVG.tsx +16 -0
- package/src/client/Icons/DirectoryArrowSVG.tsx +19 -0
- package/src/client/Icons/EditSVG.tsx +19 -0
- package/src/client/Icons/FileSVG.tsx +19 -0
- package/src/client/Icons/FolderSVG.tsx +20 -0
- package/src/client/Icons/GearSVG.tsx +16 -0
- package/src/client/Icons/HtmlSVG.tsx +16 -0
- package/src/client/Icons/JavaScriptSVG.tsx +16 -0
- package/src/client/Icons/JsonSVG.tsx +16 -0
- package/src/client/Icons/MarkdownSVG.tsx +16 -0
- package/src/client/Icons/MicOffSVG.tsx +35 -0
- package/src/client/Icons/MicSVG.tsx +25 -0
- package/src/client/Icons/NewSVG.tsx +19 -0
- package/src/client/Icons/PinSVG.tsx +14 -0
- package/src/client/Icons/PlaySVG.tsx +16 -0
- package/src/client/Icons/QuestionMarkSVG.tsx +18 -0
- package/src/client/Icons/ReactSVG.tsx +16 -0
- package/src/client/Icons/SearchSVG.tsx +20 -0
- package/src/client/Icons/SparklesSVG.tsx +23 -0
- package/src/client/Icons/SplitEditorSVG.tsx +34 -0
- package/src/client/Icons/StopSVG.tsx +15 -0
- package/src/client/Icons/SvelteSVG.tsx +16 -0
- package/src/client/Icons/TrashSVG.tsx +19 -0
- package/src/client/Icons/TypeScriptSVG.tsx +16 -0
- package/src/client/Icons/index.tsx +26 -0
- package/src/client/ImageViewer/index.tsx +91 -0
- package/src/client/ImageViewer/style.scss +41 -0
- package/src/client/PresenceNotifications/PresenceNotifications.test.ts +134 -0
- package/src/client/PresenceNotifications/index.tsx +158 -0
- package/src/client/PresenceNotifications/style.scss +17 -0
- package/src/client/RunCodeWidget/index.tsx +117 -0
- package/src/client/RunCodeWidget/style.scss +24 -0
- package/src/client/SplitPaneResizeContext.tsx +159 -0
- package/src/client/TabList/Tab.tsx +73 -0
- package/src/client/TabList/index.tsx +35 -0
- package/src/client/TabList/style.scss +51 -0
- package/src/client/VZCodeContext/index.tsx +29 -0
- package/src/client/VZCodeContext/types.ts +248 -0
- package/src/client/VZCodeContext/useVZCodeState.ts +602 -0
- package/src/client/VZKeyboardShortcutsDoc.tsx +148 -0
- package/src/client/VZLeft.tsx +28 -0
- package/src/client/VZMiddle.tsx +172 -0
- package/src/client/VZResizer/index.tsx +128 -0
- package/src/client/VZResizer/styles.scss +33 -0
- package/src/client/VZRight.tsx +113 -0
- package/src/client/VZSettings.tsx +275 -0
- package/src/client/VZSidebar/AIChat/ChatInput.tsx +243 -0
- package/src/client/VZSidebar/AIChat/DiffView.scss +136 -0
- package/src/client/VZSidebar/AIChat/DiffView.tsx +176 -0
- package/src/client/VZSidebar/AIChat/Message.tsx +79 -0
- package/src/client/VZSidebar/AIChat/MessageList.tsx +190 -0
- package/src/client/VZSidebar/AIChat/StreamingMessage.tsx +35 -0
- package/src/client/VZSidebar/AIChat/ThinkingScratchpad.tsx +156 -0
- package/src/client/VZSidebar/AIChat/TypingIndicator.tsx +19 -0
- package/src/client/VZSidebar/AIChat/index.tsx +357 -0
- package/src/client/VZSidebar/AIChat/styles.scss +646 -0
- package/src/client/VZSidebar/AIChat/useSpeechRecognition.ts +117 -0
- package/src/client/VZSidebar/CreateDirModal.tsx +111 -0
- package/src/client/VZSidebar/CreateFileModal.tsx +111 -0
- package/src/client/VZSidebar/DeleteConfirmationModal.tsx +76 -0
- package/src/client/VZSidebar/DirectoryListing.tsx +89 -0
- package/src/client/VZSidebar/EmptyState.tsx +11 -0
- package/src/client/VZSidebar/FileListing.tsx +91 -0
- package/src/client/VZSidebar/FileTypeIcon.tsx +49 -0
- package/src/client/VZSidebar/Item.tsx +237 -0
- package/src/client/VZSidebar/Listing.tsx +47 -0
- package/src/client/VZSidebar/Search.tsx +527 -0
- package/src/client/VZSidebar/VisualEditor.tsx +282 -0
- package/src/client/VZSidebar/VoiceChatModal.tsx +121 -0
- package/src/client/VZSidebar/aiCopyPaste.ts +199 -0
- package/src/client/VZSidebar/index.tsx +728 -0
- package/src/client/VZSidebar/styles.scss +612 -0
- package/src/client/VZSidebar/useDragAndDrop.tsx +408 -0
- package/src/client/bootstrap.ts +26 -0
- package/src/client/buildWorker.ts +3 -0
- package/src/client/featureFlags.ts +8 -0
- package/src/client/generateRequestId.ts +6 -0
- package/src/client/getFileTree.ts +53 -0
- package/src/client/index.ts +19 -0
- package/src/client/main.jsx +10 -0
- package/src/client/presenceColor.ts +8 -0
- package/src/client/shouldTriggerRun.ts +31 -0
- package/src/client/sortFileTree.ts +21 -0
- package/src/client/tabsSearchParameters.test.ts +79 -0
- package/src/client/tabsSearchParameters.ts +137 -0
- package/src/client/themes/index.ts +7 -0
- package/src/client/themes/themes.ts +77 -0
- package/src/client/themes/uiwImports.ts +32 -0
- package/src/client/themes/useDynamicTheme.ts +29 -0
- package/src/client/themes/vizhubTheme/colors.ts +80 -0
- package/src/client/themes/vizhubTheme/index.ts +193 -0
- package/src/client/useActions.ts +288 -0
- package/src/client/useESLint/index.ts +72 -0
- package/src/client/useESLint/worker.ts +113 -0
- package/src/client/useEditorCache.ts +35 -0
- package/src/client/useFileCRUD.ts +228 -0
- package/src/client/useKeyboardShortcuts.ts +451 -0
- package/src/client/useOpenDirectories.ts +99 -0
- package/src/client/usePresenceAutoFollow.ts +85 -0
- package/src/client/usePrettier/index.ts +178 -0
- package/src/client/usePrettier/worker.ts +109 -0
- package/src/client/useRunCode.tsx +15 -0
- package/src/client/useRuntimeError.ts +32 -0
- package/src/client/useSubmitOperation.ts +15 -0
- package/src/client/useURLSync.ts +137 -0
- package/src/client/usernameLocalStorage.ts +43 -0
- package/src/client/utils/fileExtension.ts +10 -0
- package/src/client/utils/isImageFile.ts +12 -0
- package/src/client/vzReducer/aiChatReducer.ts +44 -0
- package/src/client/vzReducer/closeTabReducer.test.ts +205 -0
- package/src/client/vzReducer/closeTabsReducer.ts +96 -0
- package/src/client/vzReducer/createInitialState.ts +38 -0
- package/src/client/vzReducer/editorNoLongerWantsFocusReducer.ts +9 -0
- package/src/client/vzReducer/findPane.ts +19 -0
- package/src/client/vzReducer/index.ts +250 -0
- package/src/client/vzReducer/openTabReducer.test.ts +127 -0
- package/src/client/vzReducer/openTabReducer.ts +74 -0
- package/src/client/vzReducer/searchReducer.test.ts +292 -0
- package/src/client/vzReducer/searchReducer.ts +181 -0
- package/src/client/vzReducer/setActiveFileIdReducer.ts +28 -0
- package/src/client/vzReducer/setActiveFileLeftRightReducer.ts +76 -0
- package/src/client/vzReducer/setIsDocOpenReducer.ts +9 -0
- package/src/client/vzReducer/setIsSettingsOpenReducer.ts +9 -0
- package/src/client/vzReducer/setThemeReducer.ts +9 -0
- package/src/client/vzReducer/setUsernameReducer.ts +9 -0
- package/src/client/vzReducer/splitCurrentPaneReducer.ts +66 -0
- package/src/client/vzReducer/toggleAutoFollowReducer.ts +12 -0
- package/src/client/vzReducer/updatePane.ts +40 -0
- package/src/client/vzReducer/updatePresenceIndicatorReducer.ts +30 -0
- package/src/client/vzReducer/visualEditorReducer.ts +9 -0
- package/src/ot.ts +24 -0
- package/src/randomId.ts +15 -0
- package/src/reactRouterExports.ts +15 -0
- package/src/runCode.ts +27 -0
- package/src/server/aiChatHandler/aiEditing.ts +151 -0
- package/src/server/aiChatHandler/chatOperations.ts +476 -0
- package/src/server/aiChatHandler/errorHandling.ts +66 -0
- package/src/server/aiChatHandler/index.ts +199 -0
- package/src/server/aiChatHandler/llmStreaming.ts +419 -0
- package/src/server/aiChatHandler/validation.ts +24 -0
- package/src/server/computeInitialDocument.ts +220 -0
- package/src/server/config.ts +24 -0
- package/src/server/featureFlags.ts +8 -0
- package/src/server/generateAIResponse.ts +188 -0
- package/src/server/handleAIAssist.ts +53 -0
- package/src/server/handleAIChatMessage.ts +2 -0
- package/src/server/handleAICopilot.ts +97 -0
- package/src/server/index.ts +379 -0
- package/src/server/isDirectory.ts +1 -0
- package/src/server/livekit.ts +24 -0
- package/src/server/prettier.ts +115 -0
- package/src/server/setupEnv.ts +8 -0
- package/src/submitOperation.ts +25 -0
- package/src/types.ts +205 -0
- package/src/utils/fileDiff.ts +117 -0
- package/src/vite-env.d.ts +10 -0
package/src/types.ts
ADDED
|
@@ -0,0 +1,205 @@
|
|
|
1
|
+
import { VizContent, VizFileId } from '@vizhub/viz-types';
|
|
2
|
+
|
|
3
|
+
// ItemId
|
|
4
|
+
// * A unique ID for an item in the sidebar.
|
|
5
|
+
// * This could be either a file ID or a directory path.
|
|
6
|
+
export type ItemId = VizFileId | FileTreePath;
|
|
7
|
+
|
|
8
|
+
// FileTreePath
|
|
9
|
+
// * The path to the directory, e.g. "src/components", OR
|
|
10
|
+
// * The path to the file e.g. "src/components/HelloWorld.js".
|
|
11
|
+
export type FileTreePath = string;
|
|
12
|
+
|
|
13
|
+
// FileTree
|
|
14
|
+
// * A tree of files.
|
|
15
|
+
// * Each node in the tree is either a directory or a file.
|
|
16
|
+
// * Each directory has a `children` array.
|
|
17
|
+
// * Each file has a `file` object.
|
|
18
|
+
// * Each file has a `fileId` string.
|
|
19
|
+
// * Each directory has a `name` string.
|
|
20
|
+
// * Each directory has a `path` string.
|
|
21
|
+
export interface FileTree {
|
|
22
|
+
name: string;
|
|
23
|
+
path?: FileTreePath;
|
|
24
|
+
children?: Array<FileTree | FileTreeFile>;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
// FileTreeFile
|
|
28
|
+
// * A file in a file tree.
|
|
29
|
+
// * Each file has a `name` string.
|
|
30
|
+
// * Each file has a `file` object.
|
|
31
|
+
// * Each file has a `fileId` string.
|
|
32
|
+
export interface FileTreeFile {
|
|
33
|
+
name: string;
|
|
34
|
+
file: File;
|
|
35
|
+
fileId: VizFileId;
|
|
36
|
+
}
|
|
37
|
+
export type SearchMatch = Array<{
|
|
38
|
+
line: number;
|
|
39
|
+
index: number;
|
|
40
|
+
text: string;
|
|
41
|
+
}>;
|
|
42
|
+
export type SearchFileVisibility =
|
|
43
|
+
| 'open'
|
|
44
|
+
| 'flattened'
|
|
45
|
+
| 'closed';
|
|
46
|
+
export type SearchResult = { [id: string]: SearchFile };
|
|
47
|
+
|
|
48
|
+
export interface SearchFile {
|
|
49
|
+
name: string;
|
|
50
|
+
matches: SearchMatch;
|
|
51
|
+
visibility: SearchFileVisibility;
|
|
52
|
+
}
|
|
53
|
+
export interface SearchResults {
|
|
54
|
+
pattern: string;
|
|
55
|
+
results: SearchResult;
|
|
56
|
+
focusedIndex: number | null;
|
|
57
|
+
focusedChildIndex: number | null;
|
|
58
|
+
focused: boolean;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
// Representation of an open tab.
|
|
62
|
+
export type TabState = {
|
|
63
|
+
// `fileId`
|
|
64
|
+
// The ID of the file that the tab represents.
|
|
65
|
+
fileId: VizFileId;
|
|
66
|
+
|
|
67
|
+
// `isTransient`
|
|
68
|
+
// Represents whether the tab is temporary or persistent.
|
|
69
|
+
// * `true` if the tab is temporary, meaning its text
|
|
70
|
+
// appears as italic, and it will be automatically
|
|
71
|
+
// closed when the user switches to another file.
|
|
72
|
+
// If `true` and the tab is opened, the editor will not focus.
|
|
73
|
+
// * `false` or `undefined` if the tab is persistent, meaning its text
|
|
74
|
+
// appears as normal, and it will not be automatically
|
|
75
|
+
// closed when the user switches to another file.
|
|
76
|
+
// If `false` and the tab is opened, the editor will focus.
|
|
77
|
+
isTransient?: boolean;
|
|
78
|
+
};
|
|
79
|
+
|
|
80
|
+
// PaneId
|
|
81
|
+
// * A unique ID for a pane.
|
|
82
|
+
// * This is a random string.
|
|
83
|
+
export type PaneId = string;
|
|
84
|
+
|
|
85
|
+
// The leaf node of the tree data structure
|
|
86
|
+
export type LeafPane = {
|
|
87
|
+
type: 'leafPane';
|
|
88
|
+
// The list of tabs
|
|
89
|
+
// Mutually exclusive with `children`.
|
|
90
|
+
tabList: Array<TabState>;
|
|
91
|
+
|
|
92
|
+
// The ID of the file that is currently active
|
|
93
|
+
// within this leaf pane.
|
|
94
|
+
// Invariant: `activeFileId` is always in `tabList`.
|
|
95
|
+
activeFileId: VizFileId | null;
|
|
96
|
+
};
|
|
97
|
+
|
|
98
|
+
// Internal node of the tree data structure
|
|
99
|
+
export type SplitPane = {
|
|
100
|
+
type: 'splitPane';
|
|
101
|
+
|
|
102
|
+
// Which orientation is it? Vertical split or horizontal split?
|
|
103
|
+
// Applies only to `children`
|
|
104
|
+
orientation: 'vertical' | 'horizontal';
|
|
105
|
+
|
|
106
|
+
// The children panels
|
|
107
|
+
// Mutually exclusive with `tabList`.
|
|
108
|
+
children: Array<Pane>;
|
|
109
|
+
};
|
|
110
|
+
|
|
111
|
+
// The node data structure of the split pane tree
|
|
112
|
+
export type Pane = {
|
|
113
|
+
// Every pane gets a unique ID,
|
|
114
|
+
// so we can refer to it in actions.
|
|
115
|
+
id: PaneId;
|
|
116
|
+
|
|
117
|
+
// The type of the pane
|
|
118
|
+
// Either a leaf pane or a split pane.
|
|
119
|
+
type: 'leafPane' | 'splitPane';
|
|
120
|
+
} & (LeafPane | SplitPane);
|
|
121
|
+
|
|
122
|
+
export type JSONOp = any;
|
|
123
|
+
|
|
124
|
+
// `ShareDBDoc`
|
|
125
|
+
// A ShareDB Document.
|
|
126
|
+
// TODO better types? Integrate with upstream how?
|
|
127
|
+
// https://github.com/DefinitelyTyped/DefinitelyTyped/blob/master/types/sharedb/lib/sharedb.d.ts#L110
|
|
128
|
+
export type ShareDBDoc<T> = {
|
|
129
|
+
data: T;
|
|
130
|
+
ingestSnapshot: (snapshot: any, callback) => void;
|
|
131
|
+
subscribe: (callback) => void;
|
|
132
|
+
on: (
|
|
133
|
+
event: string,
|
|
134
|
+
callback: (op: JSONOp, source: boolean) => void,
|
|
135
|
+
) => void;
|
|
136
|
+
off: (
|
|
137
|
+
event: string,
|
|
138
|
+
callback: (op: JSONOp, source: boolean) => void,
|
|
139
|
+
) => void;
|
|
140
|
+
removeListener: (
|
|
141
|
+
event: string,
|
|
142
|
+
callback: (op: JSONOp, source: boolean) => void,
|
|
143
|
+
) => void;
|
|
144
|
+
submitOp: (
|
|
145
|
+
op: JSONOp,
|
|
146
|
+
options?: any,
|
|
147
|
+
callback?: () => void,
|
|
148
|
+
) => void;
|
|
149
|
+
whenNothingPending: (callback: () => void) => void;
|
|
150
|
+
};
|
|
151
|
+
|
|
152
|
+
// Example Presence object, from ShareDB:
|
|
153
|
+
// {
|
|
154
|
+
// "start": [
|
|
155
|
+
// "files",
|
|
156
|
+
// "71898298",
|
|
157
|
+
// "text",
|
|
158
|
+
// 415
|
|
159
|
+
// ],
|
|
160
|
+
// "end": [
|
|
161
|
+
// "files",
|
|
162
|
+
// "71898298",
|
|
163
|
+
// "text",
|
|
164
|
+
// 415
|
|
165
|
+
// ],
|
|
166
|
+
// "username": "Tim"
|
|
167
|
+
// }
|
|
168
|
+
export type Presence = {
|
|
169
|
+
start: Array<string | number>;
|
|
170
|
+
end: Array<string | number>;
|
|
171
|
+
username: Username;
|
|
172
|
+
};
|
|
173
|
+
|
|
174
|
+
// An item in the list of sidebar presence indicators.
|
|
175
|
+
// It needs to know:
|
|
176
|
+
// * What user the presence is associated with
|
|
177
|
+
// * What file the presence is associated with
|
|
178
|
+
export type PresenceIndicator = {
|
|
179
|
+
username: Username;
|
|
180
|
+
fileId: VizFileId;
|
|
181
|
+
};
|
|
182
|
+
|
|
183
|
+
// An id used for presence.
|
|
184
|
+
export type PresenceId = string;
|
|
185
|
+
|
|
186
|
+
// A user name for display in presence.
|
|
187
|
+
export type Username = string;
|
|
188
|
+
|
|
189
|
+
// The type of a convenience function called `submitOperation`,
|
|
190
|
+
// to submit an operation to ShareDB.
|
|
191
|
+
export type SubmitOperation = (
|
|
192
|
+
next: (content: VizContent) => VizContent,
|
|
193
|
+
) => void;
|
|
194
|
+
|
|
195
|
+
// A value that has the capacity to be changed in the visual editor
|
|
196
|
+
export type VisualEditorConfigEntry =
|
|
197
|
+
| {
|
|
198
|
+
type: 'number';
|
|
199
|
+
property: string;
|
|
200
|
+
label: string;
|
|
201
|
+
min: number;
|
|
202
|
+
max: number;
|
|
203
|
+
value: number;
|
|
204
|
+
}
|
|
205
|
+
| { type: 'boolean' };
|
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
import { createTwoFilesPatch } from 'diff';
|
|
2
|
+
import { VizFiles, VizFileId } from '@vizhub/viz-types';
|
|
3
|
+
|
|
4
|
+
export interface UnifiedFilesDiff {
|
|
5
|
+
[fileId: VizFileId]: string; // Unified diff string
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Generate a unified diff for a single file using the diff library
|
|
10
|
+
*/
|
|
11
|
+
export function generateFileUnifiedDiff(
|
|
12
|
+
fileId: VizFileId,
|
|
13
|
+
fileName: string,
|
|
14
|
+
beforeContent: string,
|
|
15
|
+
afterContent: string,
|
|
16
|
+
): string {
|
|
17
|
+
// Only generate diff if there are actual changes
|
|
18
|
+
if (beforeContent === afterContent) {
|
|
19
|
+
return '';
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
// Use the diff library's createTwoFilesPatch function to generate unified diff
|
|
23
|
+
const unifiedDiff = createTwoFilesPatch(
|
|
24
|
+
fileName,
|
|
25
|
+
fileName,
|
|
26
|
+
beforeContent,
|
|
27
|
+
afterContent,
|
|
28
|
+
'',
|
|
29
|
+
'',
|
|
30
|
+
{ context: 3 },
|
|
31
|
+
);
|
|
32
|
+
|
|
33
|
+
return unifiedDiff;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* Generate unified diffs for multiple files
|
|
38
|
+
*/
|
|
39
|
+
export function generateFilesUnifiedDiff(
|
|
40
|
+
beforeFiles: VizFiles,
|
|
41
|
+
afterFiles: VizFiles,
|
|
42
|
+
): UnifiedFilesDiff {
|
|
43
|
+
const result: UnifiedFilesDiff = {};
|
|
44
|
+
const allFileIds = new Set([
|
|
45
|
+
...Object.keys(beforeFiles),
|
|
46
|
+
...Object.keys(afterFiles),
|
|
47
|
+
]);
|
|
48
|
+
|
|
49
|
+
for (const fileId of allFileIds) {
|
|
50
|
+
const beforeFile = beforeFiles[fileId];
|
|
51
|
+
const afterFile = afterFiles[fileId];
|
|
52
|
+
|
|
53
|
+
const beforeContent = beforeFile?.text || '';
|
|
54
|
+
const afterContent = afterFile?.text || '';
|
|
55
|
+
const fileName =
|
|
56
|
+
afterFile?.name || beforeFile?.name || fileId;
|
|
57
|
+
|
|
58
|
+
const unifiedDiff = generateFileUnifiedDiff(
|
|
59
|
+
fileId,
|
|
60
|
+
fileName,
|
|
61
|
+
beforeContent,
|
|
62
|
+
afterContent,
|
|
63
|
+
);
|
|
64
|
+
|
|
65
|
+
// Only include files that have changes
|
|
66
|
+
if (unifiedDiff) {
|
|
67
|
+
result[fileId] = unifiedDiff;
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
return result;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
/**
|
|
75
|
+
* Create a snapshot of current files for diff comparison
|
|
76
|
+
*/
|
|
77
|
+
export function createFilesSnapshot(
|
|
78
|
+
files: VizFiles,
|
|
79
|
+
): VizFiles {
|
|
80
|
+
return JSON.parse(JSON.stringify(files));
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
/**
|
|
84
|
+
* Parse unified diff to extract basic statistics
|
|
85
|
+
*/
|
|
86
|
+
export function parseUnifiedDiffStats(
|
|
87
|
+
unifiedDiff: string,
|
|
88
|
+
): {
|
|
89
|
+
additions: number;
|
|
90
|
+
deletions: number;
|
|
91
|
+
} {
|
|
92
|
+
const lines = unifiedDiff.split('\n');
|
|
93
|
+
let additions = 0;
|
|
94
|
+
let deletions = 0;
|
|
95
|
+
|
|
96
|
+
for (const line of lines) {
|
|
97
|
+
if (line.startsWith('+') && !line.startsWith('+++')) {
|
|
98
|
+
additions++;
|
|
99
|
+
} else if (
|
|
100
|
+
line.startsWith('-') &&
|
|
101
|
+
!line.startsWith('---')
|
|
102
|
+
) {
|
|
103
|
+
deletions++;
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
return { additions, deletions };
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
/**
|
|
111
|
+
* Combine multiple unified diffs into a single diff string
|
|
112
|
+
*/
|
|
113
|
+
export function combineUnifiedDiffs(
|
|
114
|
+
unifiedDiffs: UnifiedFilesDiff,
|
|
115
|
+
): string {
|
|
116
|
+
return Object.values(unifiedDiffs).join('\n');
|
|
117
|
+
}
|