vzcode 2.2.0 → 2.3.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.
Files changed (220) hide show
  1. package/dist/assets/{buildWorker-Dsx6rOdK.js → buildWorker-wLkQ0yz1.js} +64 -64
  2. package/dist/assets/{index-BM8tDh6M.css → index-BoFeK4GL.css} +1 -1
  3. package/dist/assets/{index-CpxqGhXj.js → index-DuUjtrt6.js} +150 -150
  4. package/dist/assets/{worker-BeBZGG1n.js → worker-DHxSPM7N.js} +78 -78
  5. package/dist/cli.js +113 -0
  6. package/dist/index.html +2 -2
  7. package/{src/ot.ts → dist/ot.js} +2 -14
  8. package/{src/randomId.ts → dist/randomId.js} +5 -6
  9. package/dist/runCode.js +20 -0
  10. package/dist/server/aiChatHandler/aiEditing.js +89 -0
  11. package/dist/server/aiChatHandler/chatOperations.js +360 -0
  12. package/dist/server/aiChatHandler/errorHandling.js +49 -0
  13. package/dist/server/aiChatHandler/index.js +112 -0
  14. package/dist/server/aiChatHandler/llmStreaming.js +284 -0
  15. package/dist/server/aiChatHandler/validation.js +19 -0
  16. package/dist/server/computeInitialDocument.js +146 -0
  17. package/{src/server/config.ts → dist/server/config.js} +4 -7
  18. package/{src/server/featureFlags.ts → dist/server/featureFlags.js} +0 -3
  19. package/dist/server/generateAIResponse.js +129 -0
  20. package/dist/server/handleAIAssist.js +39 -0
  21. package/dist/server/handleAICopilot.js +81 -0
  22. package/dist/server/index.js +297 -0
  23. package/dist/server/livekit.js +17 -0
  24. package/dist/server/prettier.js +90 -0
  25. package/{src/server/setupEnv.ts → dist/server/setupEnv.js} +1 -2
  26. package/dist/submitOperation.js +14 -0
  27. package/dist/types.js +1 -0
  28. package/dist/utils/fileDiff.js +66 -0
  29. package/package.json +22 -22
  30. package/src/client/AIAssist/AIAssistCodeMirrorKeyMap.ts +0 -42
  31. package/src/client/AIAssist/AIAssistWidget/index.tsx +0 -135
  32. package/src/client/AIAssist/AIAssistWidget/style.scss +0 -47
  33. package/src/client/AIAssist/Spinner.jsx +0 -76
  34. package/src/client/AIAssist/formatFile.ts +0 -27
  35. package/src/client/AIAssist/generateFilesContext.ts +0 -25
  36. package/src/client/AIAssist/index.ts +0 -2
  37. package/src/client/AIAssist/startAIAssist.ts +0 -95
  38. package/src/client/App/index.tsx +0 -153
  39. package/src/client/App/style.scss +0 -82
  40. package/src/client/App/usePending.ts +0 -51
  41. package/src/client/App/useShareDB.ts +0 -161
  42. package/src/client/CodeEditor/Copilot/index.ts +0 -74
  43. package/src/client/CodeEditor/InteractiveWidgets/boolToggler.ts +0 -12
  44. package/src/client/CodeEditor/InteractiveWidgets/colorPicker.ts +0 -68
  45. package/src/client/CodeEditor/InteractiveWidgets/colorsInTextPlugin.ts +0 -174
  46. package/src/client/CodeEditor/InteractiveWidgets/highlightWidgets.ts +0 -79
  47. package/src/client/CodeEditor/InteractiveWidgets/index.ts +0 -44
  48. package/src/client/CodeEditor/InteractiveWidgets/markdownCheckboxToggler.ts +0 -12
  49. package/src/client/CodeEditor/InteractiveWidgets/numberDragger.ts +0 -20
  50. package/src/client/CodeEditor/InteractiveWidgets/rotateWidget.ts +0 -143
  51. package/src/client/CodeEditor/InteractiveWidgets/urlClicker.test.ts +0 -48
  52. package/src/client/CodeEditor/InteractiveWidgets/urlClicker.ts +0 -12
  53. package/src/client/CodeEditor/InteractiveWidgets/vec2Slider.ts +0 -25
  54. package/src/client/CodeEditor/basicSetup.ts +0 -73
  55. package/src/client/CodeEditor/getOrCreateEditor.tsx +0 -615
  56. package/src/client/CodeEditor/index.tsx +0 -202
  57. package/src/client/CodeEditor/json1PresenceBroadcast.ts +0 -41
  58. package/src/client/CodeEditor/json1PresenceDisplay.ts +0 -350
  59. package/src/client/CodeEditor/rainbowBrackets.ts +0 -122
  60. package/src/client/CodeEditor/style.scss +0 -156
  61. package/src/client/CodeEditor/typescriptExtension/worker.ts +0 -32
  62. package/src/client/CodeErrorOverlay/index.tsx +0 -77
  63. package/src/client/CodeErrorOverlay/style.scss +0 -33
  64. package/src/client/Fonts/fonts.ts +0 -8
  65. package/src/client/Icons/AdjustmentSVG.tsx +0 -19
  66. package/src/client/Icons/BugSVG.tsx +0 -20
  67. package/src/client/Icons/CloseSVG.tsx +0 -19
  68. package/src/client/Icons/CssSVG.tsx +0 -16
  69. package/src/client/Icons/DirectoryArrowSVG.tsx +0 -19
  70. package/src/client/Icons/EditSVG.tsx +0 -19
  71. package/src/client/Icons/FileSVG.tsx +0 -19
  72. package/src/client/Icons/FolderSVG.tsx +0 -20
  73. package/src/client/Icons/GearSVG.tsx +0 -16
  74. package/src/client/Icons/HtmlSVG.tsx +0 -16
  75. package/src/client/Icons/JavaScriptSVG.tsx +0 -16
  76. package/src/client/Icons/JsonSVG.tsx +0 -16
  77. package/src/client/Icons/MarkdownSVG.tsx +0 -16
  78. package/src/client/Icons/MicOffSVG.tsx +0 -35
  79. package/src/client/Icons/MicSVG.tsx +0 -25
  80. package/src/client/Icons/NewSVG.tsx +0 -19
  81. package/src/client/Icons/PinSVG.tsx +0 -14
  82. package/src/client/Icons/PlaySVG.tsx +0 -16
  83. package/src/client/Icons/QuestionMarkSVG.tsx +0 -18
  84. package/src/client/Icons/ReactSVG.tsx +0 -16
  85. package/src/client/Icons/SearchSVG.tsx +0 -20
  86. package/src/client/Icons/SparklesSVG.tsx +0 -23
  87. package/src/client/Icons/SplitEditorSVG.tsx +0 -34
  88. package/src/client/Icons/StopSVG.tsx +0 -15
  89. package/src/client/Icons/SvelteSVG.tsx +0 -16
  90. package/src/client/Icons/TrashSVG.tsx +0 -19
  91. package/src/client/Icons/TypeScriptSVG.tsx +0 -16
  92. package/src/client/Icons/index.tsx +0 -26
  93. package/src/client/ImageViewer/index.tsx +0 -91
  94. package/src/client/ImageViewer/style.scss +0 -41
  95. package/src/client/PresenceNotifications/PresenceNotifications.test.ts +0 -134
  96. package/src/client/PresenceNotifications/index.tsx +0 -158
  97. package/src/client/PresenceNotifications/style.scss +0 -17
  98. package/src/client/RunCodeWidget/index.tsx +0 -117
  99. package/src/client/RunCodeWidget/style.scss +0 -24
  100. package/src/client/SplitPaneResizeContext.tsx +0 -159
  101. package/src/client/TabList/Tab.tsx +0 -73
  102. package/src/client/TabList/index.tsx +0 -35
  103. package/src/client/TabList/style.scss +0 -51
  104. package/src/client/VZCodeContext/index.tsx +0 -29
  105. package/src/client/VZCodeContext/types.ts +0 -249
  106. package/src/client/VZCodeContext/useVZCodeState.ts +0 -584
  107. package/src/client/VZKeyboardShortcutsDoc.tsx +0 -148
  108. package/src/client/VZLeft.tsx +0 -28
  109. package/src/client/VZMiddle.tsx +0 -172
  110. package/src/client/VZResizer/index.tsx +0 -128
  111. package/src/client/VZResizer/styles.scss +0 -33
  112. package/src/client/VZRight.tsx +0 -113
  113. package/src/client/VZSettings.tsx +0 -275
  114. package/src/client/VZSidebar/AIChat/ChatInput.tsx +0 -239
  115. package/src/client/VZSidebar/AIChat/DiffView.scss +0 -136
  116. package/src/client/VZSidebar/AIChat/DiffView.tsx +0 -176
  117. package/src/client/VZSidebar/AIChat/Message.tsx +0 -143
  118. package/src/client/VZSidebar/AIChat/MessageList.tsx +0 -205
  119. package/src/client/VZSidebar/AIChat/StreamingMessage.tsx +0 -35
  120. package/src/client/VZSidebar/AIChat/ThinkingScratchpad.tsx +0 -156
  121. package/src/client/VZSidebar/AIChat/TypingIndicator.tsx +0 -19
  122. package/src/client/VZSidebar/AIChat/index.tsx +0 -273
  123. package/src/client/VZSidebar/AIChat/styles.scss +0 -627
  124. package/src/client/VZSidebar/AIChat/useSpeechRecognition.ts +0 -117
  125. package/src/client/VZSidebar/CreateDirModal.tsx +0 -111
  126. package/src/client/VZSidebar/CreateFileModal.tsx +0 -111
  127. package/src/client/VZSidebar/DeleteConfirmationModal.tsx +0 -76
  128. package/src/client/VZSidebar/DirectoryListing.tsx +0 -89
  129. package/src/client/VZSidebar/EmptyState.tsx +0 -11
  130. package/src/client/VZSidebar/FileListing.tsx +0 -91
  131. package/src/client/VZSidebar/FileTypeIcon.tsx +0 -49
  132. package/src/client/VZSidebar/Item.tsx +0 -237
  133. package/src/client/VZSidebar/Listing.tsx +0 -47
  134. package/src/client/VZSidebar/Search.tsx +0 -527
  135. package/src/client/VZSidebar/VisualEditor.tsx +0 -282
  136. package/src/client/VZSidebar/VoiceChatModal.tsx +0 -121
  137. package/src/client/VZSidebar/aiCopyPaste.ts +0 -199
  138. package/src/client/VZSidebar/index.tsx +0 -728
  139. package/src/client/VZSidebar/styles.scss +0 -612
  140. package/src/client/VZSidebar/useDragAndDrop.tsx +0 -408
  141. package/src/client/bootstrap.ts +0 -26
  142. package/src/client/buildWorker.ts +0 -3
  143. package/src/client/featureFlags.ts +0 -8
  144. package/src/client/generateRequestId.ts +0 -6
  145. package/src/client/getFileTree.ts +0 -53
  146. package/src/client/index.ts +0 -19
  147. package/src/client/main.jsx +0 -10
  148. package/src/client/presenceColor.ts +0 -8
  149. package/src/client/shouldTriggerRun.ts +0 -31
  150. package/src/client/sortFileTree.ts +0 -21
  151. package/src/client/tabsSearchParameters.test.ts +0 -79
  152. package/src/client/tabsSearchParameters.ts +0 -137
  153. package/src/client/themes/index.ts +0 -7
  154. package/src/client/themes/themes.ts +0 -77
  155. package/src/client/themes/uiwImports.ts +0 -32
  156. package/src/client/themes/useDynamicTheme.ts +0 -29
  157. package/src/client/themes/vizhubTheme/colors.ts +0 -80
  158. package/src/client/themes/vizhubTheme/index.ts +0 -193
  159. package/src/client/useActions.ts +0 -288
  160. package/src/client/useESLint/index.ts +0 -72
  161. package/src/client/useESLint/worker.ts +0 -113
  162. package/src/client/useEditorCache.ts +0 -35
  163. package/src/client/useFileCRUD.ts +0 -228
  164. package/src/client/useKeyboardShortcuts.ts +0 -451
  165. package/src/client/useOpenDirectories.ts +0 -99
  166. package/src/client/usePresenceAutoFollow.ts +0 -85
  167. package/src/client/usePrettier/index.ts +0 -178
  168. package/src/client/usePrettier/worker.ts +0 -109
  169. package/src/client/useRunCode.tsx +0 -15
  170. package/src/client/useRuntimeError.ts +0 -32
  171. package/src/client/useSubmitOperation.ts +0 -15
  172. package/src/client/useURLSync.ts +0 -137
  173. package/src/client/usernameLocalStorage.ts +0 -43
  174. package/src/client/utils/fileExtension.ts +0 -10
  175. package/src/client/utils/isImageFile.ts +0 -12
  176. package/src/client/vzReducer/aiChatReducer.ts +0 -44
  177. package/src/client/vzReducer/closeTabReducer.test.ts +0 -205
  178. package/src/client/vzReducer/closeTabsReducer.ts +0 -96
  179. package/src/client/vzReducer/createInitialState.ts +0 -38
  180. package/src/client/vzReducer/editorNoLongerWantsFocusReducer.ts +0 -9
  181. package/src/client/vzReducer/findPane.ts +0 -19
  182. package/src/client/vzReducer/index.ts +0 -250
  183. package/src/client/vzReducer/openTabReducer.test.ts +0 -127
  184. package/src/client/vzReducer/openTabReducer.ts +0 -74
  185. package/src/client/vzReducer/searchReducer.test.ts +0 -292
  186. package/src/client/vzReducer/searchReducer.ts +0 -181
  187. package/src/client/vzReducer/setActiveFileIdReducer.ts +0 -28
  188. package/src/client/vzReducer/setActiveFileLeftRightReducer.ts +0 -76
  189. package/src/client/vzReducer/setIsDocOpenReducer.ts +0 -9
  190. package/src/client/vzReducer/setIsSettingsOpenReducer.ts +0 -9
  191. package/src/client/vzReducer/setThemeReducer.ts +0 -9
  192. package/src/client/vzReducer/setUsernameReducer.ts +0 -9
  193. package/src/client/vzReducer/splitCurrentPaneReducer.ts +0 -66
  194. package/src/client/vzReducer/toggleAutoFollowReducer.ts +0 -12
  195. package/src/client/vzReducer/updatePane.ts +0 -40
  196. package/src/client/vzReducer/updatePresenceIndicatorReducer.ts +0 -30
  197. package/src/client/vzReducer/visualEditorReducer.ts +0 -9
  198. package/src/reactRouterExports.ts +0 -15
  199. package/src/runCode.ts +0 -27
  200. package/src/server/aiChatHandler/aiEditing.ts +0 -152
  201. package/src/server/aiChatHandler/chatOperations.ts +0 -510
  202. package/src/server/aiChatHandler/errorHandling.ts +0 -66
  203. package/src/server/aiChatHandler/index.ts +0 -200
  204. package/src/server/aiChatHandler/llmStreaming.ts +0 -419
  205. package/src/server/aiChatHandler/undoHandler.ts +0 -97
  206. package/src/server/aiChatHandler/validation.ts +0 -24
  207. package/src/server/computeInitialDocument.ts +0 -220
  208. package/src/server/generateAIResponse.ts +0 -188
  209. package/src/server/handleAIAssist.ts +0 -53
  210. package/src/server/handleAIChatUndo.ts +0 -2
  211. package/src/server/handleAICopilot.ts +0 -97
  212. package/src/server/index.ts +0 -388
  213. package/src/server/livekit.ts +0 -24
  214. package/src/server/prettier.ts +0 -115
  215. package/src/submitOperation.ts +0 -25
  216. package/src/types.ts +0 -205
  217. package/src/utils/fileDiff.ts +0 -117
  218. package/src/vite-env.d.ts +0 -10
  219. /package/{src/server/handleAIChatMessage.ts → dist/server/handleAIChatMessage.js} +0 -0
  220. /package/{src/server/isDirectory.ts → dist/server/isDirectory.js} +0 -0
@@ -1,615 +0,0 @@
1
- import { createRoot } from 'react-dom/client';
2
- import { EditorView } from 'codemirror';
3
- import {
4
- Compartment,
5
- EditorState,
6
- StateField,
7
- } from '@codemirror/state';
8
- import { javascript } from '@codemirror/lang-javascript';
9
- import { svelte } from '@replit/codemirror-lang-svelte';
10
- import { json } from '@codemirror/lang-json';
11
- import { markdown } from '@codemirror/lang-markdown';
12
- import { html } from '@codemirror/lang-html';
13
- import { css } from '@codemirror/lang-css';
14
- import { json1Sync } from 'codemirror-ot';
15
-
16
- import { autocompletion } from '@codemirror/autocomplete';
17
- import { indentationMarkers } from '@replit/codemirror-indentation-markers';
18
- // import { showMinimap } from '@replit/codemirror-minimap';
19
- import { vscodeKeymap } from '@replit/codemirror-vscode-keymap';
20
- import {
21
- Diagnostic,
22
- linter,
23
- lintGutter,
24
- } from '@codemirror/lint';
25
-
26
- import { json1Presence, textUnicode } from '../../ot';
27
- import {
28
- PaneId,
29
- ShareDBDoc,
30
- TabState,
31
- Username,
32
- } from '../../types';
33
- import { VizFileId, VizContent } from '@vizhub/viz-types';
34
- import { json1PresenceBroadcast } from './json1PresenceBroadcast';
35
- import { json1PresenceDisplay } from './json1PresenceDisplay';
36
- import {
37
- colorsInTextPlugin,
38
- rotationIndicator,
39
- widgets,
40
- } from './InteractiveWidgets';
41
- import {
42
- EditorCache,
43
- editorCacheKey,
44
- EditorCacheValue,
45
- } from '../useEditorCache';
46
- import { ThemeLabel, themeOptionsByLabel } from '../themes';
47
- import {
48
- keymap,
49
- Decoration,
50
- WidgetType,
51
- ViewUpdate,
52
- ViewPlugin,
53
- DecorationSet,
54
- } from '@codemirror/view';
55
- import { Range } from '@codemirror/state';
56
- import { syntaxTree } from '@codemirror/language';
57
- import { RegExpCursor } from '@codemirror/search';
58
- import { basicSetup } from './basicSetup';
59
- import { InteractRule } from '@replit/codemirror-interact';
60
- import rainbowBrackets from './rainbowBrackets';
61
- import { cssLanguage } from '@codemirror/lang-css';
62
- import { javascriptLanguage } from '@codemirror/lang-javascript';
63
- import { copilot } from './Copilot';
64
- import { type WorkerShape } from '@valtown/codemirror-ts/src/worker';
65
- import * as Comlink from 'comlink';
66
- import {
67
- tsAutocompleteWorker,
68
- tsFacetWorker,
69
- tsHoverWorker,
70
- tsLinterWorker,
71
- tsSyncWorker,
72
- } from '@valtown/codemirror-ts';
73
- import { getFileExtension } from '../utils/fileExtension';
74
- import { SparklesSVG } from '../Icons/SparklesSVG';
75
- import { VZCodeContext } from '../VZCodeContext';
76
- import { useContext, useMemo } from 'react';
77
- import { handleAIChatMessage } from '../../server/aiChatHandler';
78
-
79
- const DEBUG = false;
80
-
81
- // Define a StateField to store the file name.
82
- // This should be defined at the module level if it's to be imported by other modules.
83
- export const fileNameStateField = StateField.define<string>(
84
- {
85
- create: () => '', // Default initial value
86
- update: (value, tr) => value, // Typically set once at creation for a given editor instance
87
- },
88
- );
89
-
90
- // Enables TypeScript +JSX support in CodeMirror.
91
- const tsx = () =>
92
- javascript({ jsx: true, typescript: true });
93
-
94
- // Lazy initialization of worker
95
- let worker: Comlink.Remote<WorkerShape> | null = null;
96
- const initializeWorker = async () => {
97
- if (worker === null) {
98
- const innerWorker = new Worker(
99
- new URL(
100
- './typescriptExtension/worker.ts',
101
- import.meta.url,
102
- ),
103
- {
104
- type: 'module',
105
- },
106
- );
107
- worker = Comlink.wrap<WorkerShape>(innerWorker);
108
- await worker.initialize();
109
- }
110
- return worker;
111
- };
112
-
113
- const htmlConfig = {
114
- matchClosingTags: true,
115
- selfClosingTags: false,
116
- autoCloseTags: true,
117
- extraTags: {},
118
- extraGlobalAttributes: {},
119
- nestedLanguages: [
120
- {
121
- tag: 'script',
122
- language: javascript,
123
- parser: javascriptLanguage.parser,
124
- },
125
- {
126
- tag: 'style',
127
- language: css,
128
- parser: cssLanguage.parser,
129
- },
130
- ],
131
- nestedAttributes: [],
132
- };
133
-
134
- // Language extensions for CodeMirror.
135
- // Keys are file extensions.
136
- // Values are CodeMirror extensions.
137
- // TODO consider moving this to a separate file.
138
- const languageExtensions = {
139
- json,
140
- tsx,
141
- js: tsx,
142
- jsx: tsx,
143
- ts: tsx,
144
- html: () => html(htmlConfig),
145
- css,
146
- md: markdown,
147
- svelte,
148
- };
149
-
150
- // Exported utility function to get language extension for a file extension
151
- export const getLanguageExtension = (
152
- fileExtension: string,
153
- ) => {
154
- const languageFunc = languageExtensions[fileExtension];
155
- return languageFunc ? languageFunc() : undefined;
156
- };
157
-
158
- // Gets a value at a path in an object.
159
- // e.g. getAtPath({a: {b: 1}}, ['a', 'b']) === 1
160
- const getAtPath = (obj, path) => {
161
- let current = obj;
162
- for (const key of path) {
163
- if (!current) return undefined;
164
- current = current[key];
165
- }
166
- return current;
167
- };
168
-
169
- // Extend the EditorCacheValue type to include the compartments and the updateRainbowBrackets method
170
- interface ExtendedEditorCacheValue
171
- extends EditorCacheValue {
172
- themeCompartment: Compartment;
173
- languageCompartment: Compartment;
174
- rainbowBracketsCompartment: Compartment;
175
- updateRainbowBrackets: (enabled: boolean) => void;
176
- }
177
-
178
- // Gets or creates an `editorCache` entry for the given file id.
179
- // Looks in `editorCache` first, and if not found, creates a new editor.
180
- export const getOrCreateEditor = async ({
181
- paneId = 'root',
182
- fileId,
183
- shareDBDoc,
184
- filesPath,
185
- localPresence,
186
- docPresence,
187
- theme,
188
- onInteract,
189
- editorCache,
190
- usernameRef,
191
- customInteractRules,
192
- enableAutoFollowRef,
193
- aiCopilotEndpoint,
194
- esLintSource,
195
- rainbowBracketsEnabled = true,
196
- setIsAIChatOpen,
197
- setAIChatMessage,
198
- handleSendMessage,
199
- }: {
200
- // TODO pass this in from the outside
201
- paneId?: PaneId;
202
- fileId: VizFileId;
203
-
204
- // The ShareDB document that contains the file.
205
- // Used when the editor is created for:
206
- // * Figuring out the initial text
207
- // * Figuring out the initial language extension
208
- // based on the file extension.
209
- // It's also passed into the `json1Sync` extension,
210
- // which is used for multiplayer editing.
211
- // This can be `undefined` in the case where we are
212
- // viewing files read-only, in which case multiplayer
213
- // editing is not enabled.
214
- shareDBDoc: ShareDBDoc<VizContent>;
215
-
216
- filesPath: string[];
217
- localPresence: any;
218
- docPresence: any;
219
- theme: ThemeLabel;
220
- onInteract?: () => void;
221
- editorCache: EditorCache;
222
- usernameRef: React.MutableRefObject<Username>;
223
- aiAssistEndpoint?: string;
224
- customInteractRules?: Array<InteractRule>;
225
-
226
- // Ref to a boolean that determines whether to
227
- // enable auto-following the cursors of remote users.
228
- enableAutoFollowRef: React.MutableRefObject<boolean>;
229
- aiCopilotEndpoint?: string;
230
- esLintSource: (
231
- view: EditorView,
232
- ) => Promise<readonly Diagnostic[]>;
233
- rainbowBracketsEnabled?: boolean; // New parameter type
234
- setIsAIChatOpen: (isAIChatOpen: boolean) => void;
235
- setAIChatMessage: (message: string) => void;
236
- handleSendMessage: any; // TODO fix types
237
- }): Promise<ExtendedEditorCacheValue> => {
238
- // Cache hit
239
-
240
- const cacheKey = editorCacheKey(fileId, paneId);
241
-
242
- if (editorCache.has(cacheKey)) {
243
- return editorCache.get(
244
- cacheKey,
245
- ) as ExtendedEditorCacheValue;
246
- }
247
-
248
- // Cache miss
249
-
250
- // Compute `text` and `fileExtension` from the ShareDB document.
251
- const textPath = [...filesPath, fileId, 'text'];
252
- const namePath = [...filesPath, fileId, 'name'];
253
- const content = shareDBDoc.data;
254
- const text = getAtPath(content, textPath);
255
- const name = getAtPath(content, namePath);
256
-
257
- const fileExtension = getFileExtension(name);
258
-
259
- // Create a compartment for the theme so that it can be changed dynamically.
260
- // Inspired by: https://github.com/craftzdog/cm6-themes/blob/main/example/index.ts
261
- let themeCompartment = new Compartment();
262
-
263
- // Create a compartment for rainbow brackets so that it can be enabled/disabled dynamically.
264
- let rainbowBracketsCompartment = new Compartment();
265
-
266
- // The CodeMirror extensions to use.
267
- // const extensions = [autocompletion(), html(htmlConfig)]
268
- const extensions = [];
269
-
270
- // Initialize the fileNameStateField with the actual file name
271
- extensions.push(fileNameStateField.init(() => name));
272
-
273
- // This plugin implements multiplayer editing,
274
- // real-time synchronozation of changes across clients.
275
- // Does not deal with showing others' cursors.
276
- if (shareDBDoc) {
277
- extensions.push(
278
- json1Sync({
279
- shareDBDoc,
280
- path: textPath,
281
- json1: json1Presence,
282
- textUnicode,
283
- }),
284
- );
285
-
286
- // Deals with broadcasting changes in cursor location and selection.
287
- if (localPresence) {
288
- extensions.push(
289
- json1PresenceBroadcast({
290
- path: textPath,
291
- localPresence,
292
- usernameRef,
293
- }),
294
- );
295
- }
296
-
297
- // Deals with receiving the broadcast from other clients and displaying them.
298
- if (docPresence) {
299
- extensions.push(
300
- json1PresenceDisplay({
301
- path: textPath,
302
- docPresence,
303
- enableAutoFollowRef,
304
- }),
305
- );
306
- }
307
- } else {
308
- // If the ShareDB document is not provided,
309
- // then we do not allow editing.
310
- extensions.push(EditorView.editable.of(false));
311
- }
312
-
313
- extensions.push(colorsInTextPlugin);
314
-
315
- // This is the "basic setup" for CodeMirror,
316
- // which actually adds a ton on functionality.
317
- // TODO vet this functionality, and determine how much
318
- // we want to replace with
319
- // https://github.com/vizhub-core/vzcode/issues/134
320
- extensions.push(basicSetup);
321
-
322
- if (esLintSource) {
323
- extensions.push(lintGutter()); // Show lint icons in the gutter
324
- extensions.push(
325
- linter(esLintSource, {
326
- // You can configure linter options here, e.g., delay
327
- delay: 750,
328
- }),
329
- );
330
- }
331
-
332
- // This supports dynamic changing of the theme.
333
- extensions.push(
334
- themeCompartment.of(themeOptionsByLabel[theme].value),
335
- );
336
-
337
- // Adds compartment for rainbow brackets with initial toggle state.
338
- extensions.push(
339
- rainbowBracketsCompartment.of(
340
- rainbowBracketsEnabled ? rainbowBrackets() : [],
341
- ),
342
- );
343
-
344
- // TODO handle dynamic changing of the file extension.
345
- // TODO handle dynamic file extensions by making
346
- // the CodeMirror language extension dynamic
347
- // using a Compartment.
348
- const languageCompartment = new Compartment();
349
- // See https://github.com/vizhub-core/vzcode/issues/55
350
-
351
- const languageExtension =
352
- getLanguageExtension(fileExtension);
353
- if (languageExtension) {
354
- extensions.push(
355
- languageCompartment.of(languageExtension),
356
- );
357
- } else {
358
- // Not sure if this case even works.
359
- // TODO manually test this case by creating a file
360
- // that has no extension, opening it up,
361
- // and then adding an extension.
362
- // console.warn(
363
- // `No language extension for file extension: ${fileExtension}`,
364
- // );
365
- // We still need to push the compartment,
366
- // otherwise the compartment won't work when
367
- // a file extension _is_ added later on.
368
- extensions.push(languageCompartment.of([]));
369
- }
370
-
371
- // Enable line wrapping for Markdown files
372
- if (fileExtension === 'md') {
373
- extensions.push(EditorView.lineWrapping);
374
- }
375
-
376
- // Add interactive widgets.
377
- // Includes the Alt+drag functionality for numbers.
378
- // Calls `onInteract` when one of those widgets is interacted with.
379
- // This can be used to trigger a transition to throttled mode
380
- // for hot reloading.
381
- // TODO consider leveraging the new `dragEnd` event handler.
382
- // and removing the `onInteract` callback, replacing it with
383
- // `onInteractStart` and `onInteractEnd`.
384
- // That may be tricky for one-off interactions though, like
385
- // the boolean checkboxes. The color pickers are also tricky,
386
- // as they would also need to be able to handle `onInteractEnd`.
387
- // See https://github.com/replit/codemirror-interact/issues/14
388
- extensions.push(
389
- widgets({ onInteract, customInteractRules }),
390
- );
391
-
392
- // TODO fix the bugginess in this one where
393
- // the highlight persists after the mouse leaves.
394
- // extensions.push(highlightWidgets);
395
-
396
- extensions.push(rotationIndicator);
397
-
398
- // extensions.push(
399
- // AIAssistCodeMirrorKeyMap({
400
- // shareDBDoc,
401
- // fileId,
402
- // tabList,
403
- // aiAssistEndpoint,
404
- // aiAssistOptions,
405
- // }),
406
- // );
407
-
408
- // Add the extension that provides indentation markers.
409
- extensions.push(
410
- indentationMarkers({
411
- // thickness: 2,
412
- colors: {
413
- light: '#4d586b',
414
- dark: '#4d586b',
415
- activeLight: '#8e949f',
416
- activeDark: '#8e949f',
417
- },
418
- }),
419
- );
420
-
421
- if (name.endsWith('ts') || name.endsWith('tsx')) {
422
- // Initialize worker if needed
423
- const tsWorker = await initializeWorker();
424
-
425
- extensions.push(
426
- ...[
427
- tsFacetWorker.of({ worker: tsWorker, path: name }),
428
- tsSyncWorker(),
429
- tsLinterWorker(),
430
- autocompletion({
431
- override: [tsAutocompleteWorker()],
432
- }),
433
- tsHoverWorker(),
434
- ],
435
- );
436
- }
437
-
438
- // Show the minimap
439
- // See https://github.com/replit/codemirror-minimap#usage
440
- // This extension has poor performance, so it's disabled for now.
441
- // extensions.push(
442
- // showMinimap.compute(['doc'], () => ({
443
- // create: () => ({
444
- // dom: document.createElement('div'),
445
- // }),
446
- // // Without this, performance is terrible.
447
- // displayText: 'blocks',
448
- // })),
449
- // );
450
-
451
- // VSCode keybindings
452
- // See https://github.com/replit/codemirror-vscode-keymap#usage
453
- // extensions.push(keymap.of(vscodeKeymap));
454
- extensions.push(
455
- keymap.of(
456
- vscodeKeymap.map((binding) => {
457
- // Here we override the Shift+Enter behavior specifically,
458
- // as that can be used to trigger a manual save/Prettier,
459
- // and the default behavior from the keymap interferes.
460
- if (binding.key === 'Enter') {
461
- delete binding.shift;
462
- }
463
- return binding;
464
- }),
465
- ),
466
- );
467
-
468
- // Adds copilot completions
469
- DEBUG &&
470
- console.log(
471
- '[getOrCreateEditor] aiCopilotEndpoint: ',
472
- aiCopilotEndpoint,
473
- );
474
- if (aiCopilotEndpoint) {
475
- extensions.push(copilot({ aiCopilotEndpoint }));
476
- }
477
-
478
- // const { setIsAIChatOpen } = useContext(VZCodeContext);
479
-
480
- // Widget appears after instances of "todo" in code editor, allowing AI to implement todo tasks when clicked
481
- function createToDoPlugin() {
482
- // setIsAIChatOpen: (open: boolean) => void,
483
- class ToDoWidget extends WidgetType {
484
- constructor() {
485
- super();
486
- }
487
-
488
- eq(other: ToDoWidget) {
489
- return false;
490
- }
491
-
492
- toDOM() {
493
- const wrap = document.createElement('i');
494
- wrap.style.display = 'inline-flex'; // prevent block expansion
495
- wrap.style.alignItems = 'center';
496
- wrap.style.justifyContent = 'center';
497
- wrap.className = 'icon-button icon-button-dark';
498
- const reactContainer =
499
- document.createElement('div');
500
- wrap.appendChild(reactContainer);
501
-
502
- const root = createRoot(reactContainer);
503
- root.render(
504
- <div
505
- onClick={() => {
506
- setIsAIChatOpen(true);
507
- // setAIChatMessage('Implement the TODO');
508
- handleSendMessage('Implement the TODO');
509
- }}
510
- >
511
- <SparklesSVG width={14} height={14} />
512
- </div>,
513
- );
514
- return wrap;
515
- }
516
-
517
- ignoreEvent() {
518
- return false;
519
- }
520
- }
521
-
522
- function toDoWidgets(editor: EditorView) {
523
- const { state } = editor;
524
- const tree = syntaxTree(state);
525
- const findToDo = new RegExpCursor(state.doc, 'todo', {
526
- ignoreCase: true,
527
- });
528
- const widgets: Range<Decoration>[] = [];
529
-
530
- while (!findToDo.next().done) {
531
- const { from, to } = findToDo.value;
532
- const node = tree.resolve(from);
533
- let inComment = false;
534
-
535
- // Walk up the parents until we hit the root, looking for a comment node
536
- for (let cur: any = node; cur; cur = cur.parent) {
537
- if (
538
- cur.type.is('Comment') || // grammars that group comments
539
- cur.type.is('comment') || // generic lowercase group
540
- /Comment$/.test(cur.type.name) // fallback for e.g. LineComment
541
- ) {
542
- inComment = true;
543
- break;
544
- }
545
- }
546
- if (!inComment) continue; // skip non-comment TODOs
547
-
548
- const deco = Decoration.widget({
549
- widget: new ToDoWidget(),
550
- side: 1,
551
- }).range(to);
552
- widgets.push(deco);
553
- }
554
- return Decoration.set(widgets);
555
- }
556
-
557
- const todoPlugin = ViewPlugin.fromClass(
558
- class {
559
- decorations: DecorationSet;
560
-
561
- constructor(view: EditorView) {
562
- this.decorations = toDoWidgets(view);
563
- }
564
-
565
- update(update: ViewUpdate) {
566
- if (
567
- update.docChanged ||
568
- update.viewportChanged ||
569
- syntaxTree(update.startState) !==
570
- syntaxTree(update.state)
571
- )
572
- this.decorations = toDoWidgets(update.view);
573
- }
574
- },
575
- {
576
- decorations: (v) => v.decorations,
577
- },
578
- );
579
-
580
- return todoPlugin;
581
- }
582
-
583
- extensions.push(createToDoPlugin());
584
-
585
- const editor = new EditorView({
586
- state: EditorState.create({
587
- doc: text,
588
- extensions,
589
- }),
590
- });
591
-
592
- const editorCacheValue: ExtendedEditorCacheValue = {
593
- editor,
594
- themeCompartment,
595
- languageCompartment,
596
- rainbowBracketsCompartment,
597
- updateRainbowBrackets: (enabled) => {
598
- editor.dispatch({
599
- effects: rainbowBracketsCompartment.reconfigure(
600
- enabled ? rainbowBrackets() : [],
601
- ),
602
- });
603
- },
604
- };
605
-
606
- // Populate the cache.
607
- editorCache.set(cacheKey, editorCacheValue);
608
-
609
- // Initialize rainbow brackets based on the toggle state
610
- editorCacheValue.updateRainbowBrackets(
611
- rainbowBracketsEnabled,
612
- );
613
-
614
- return editorCacheValue;
615
- };