vzcode 2.0.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.
- package/dist/assets/{buildWorker-Dsx6rOdK.js → buildWorker-wLkQ0yz1.js} +64 -64
- package/dist/assets/{index-BM8tDh6M.css → index-BoFeK4GL.css} +1 -1
- package/dist/assets/{index-BgqNq-ww.js → index-DuUjtrt6.js} +107 -107
- package/dist/assets/{worker-BeBZGG1n.js → worker-DHxSPM7N.js} +78 -78
- package/dist/cli.js +113 -0
- package/dist/index.html +2 -2
- package/{src/ot.ts → dist/ot.js} +2 -14
- package/{src/randomId.ts → dist/randomId.js} +5 -6
- package/dist/runCode.js +20 -0
- package/dist/server/aiChatHandler/aiEditing.js +89 -0
- package/dist/server/aiChatHandler/chatOperations.js +360 -0
- package/dist/server/aiChatHandler/errorHandling.js +49 -0
- package/dist/server/aiChatHandler/index.js +112 -0
- package/dist/server/aiChatHandler/llmStreaming.js +284 -0
- package/dist/server/aiChatHandler/validation.js +19 -0
- package/dist/server/computeInitialDocument.js +146 -0
- package/{src/server/config.ts → dist/server/config.js} +4 -7
- package/{src/server/featureFlags.ts → dist/server/featureFlags.js} +0 -3
- package/dist/server/generateAIResponse.js +129 -0
- package/dist/server/handleAIAssist.js +39 -0
- package/dist/server/handleAICopilot.js +81 -0
- package/dist/server/index.js +297 -0
- package/dist/server/livekit.js +17 -0
- package/dist/server/prettier.js +90 -0
- package/{src/server/setupEnv.ts → dist/server/setupEnv.js} +1 -2
- package/dist/submitOperation.js +14 -0
- package/dist/types.js +1 -0
- package/dist/utils/fileDiff.js +66 -0
- package/package.json +23 -22
- package/src/client/AIAssist/AIAssistCodeMirrorKeyMap.ts +0 -42
- package/src/client/AIAssist/AIAssistWidget/index.tsx +0 -135
- package/src/client/AIAssist/AIAssistWidget/style.scss +0 -47
- package/src/client/AIAssist/Spinner.jsx +0 -76
- package/src/client/AIAssist/formatFile.ts +0 -27
- package/src/client/AIAssist/generateFilesContext.ts +0 -25
- package/src/client/AIAssist/index.ts +0 -2
- package/src/client/AIAssist/startAIAssist.ts +0 -95
- package/src/client/App/index.tsx +0 -153
- package/src/client/App/style.scss +0 -82
- package/src/client/App/usePending.ts +0 -51
- package/src/client/App/useShareDB.ts +0 -161
- package/src/client/CodeEditor/Copilot/index.ts +0 -74
- package/src/client/CodeEditor/InteractiveWidgets/boolToggler.ts +0 -12
- package/src/client/CodeEditor/InteractiveWidgets/colorPicker.ts +0 -68
- package/src/client/CodeEditor/InteractiveWidgets/colorsInTextPlugin.ts +0 -174
- package/src/client/CodeEditor/InteractiveWidgets/highlightWidgets.ts +0 -79
- package/src/client/CodeEditor/InteractiveWidgets/index.ts +0 -44
- package/src/client/CodeEditor/InteractiveWidgets/markdownCheckboxToggler.ts +0 -12
- package/src/client/CodeEditor/InteractiveWidgets/numberDragger.ts +0 -20
- package/src/client/CodeEditor/InteractiveWidgets/rotateWidget.ts +0 -143
- package/src/client/CodeEditor/InteractiveWidgets/urlClicker.test.ts +0 -48
- package/src/client/CodeEditor/InteractiveWidgets/urlClicker.ts +0 -12
- package/src/client/CodeEditor/InteractiveWidgets/vec2Slider.ts +0 -25
- package/src/client/CodeEditor/basicSetup.ts +0 -73
- package/src/client/CodeEditor/getOrCreateEditor.tsx +0 -615
- package/src/client/CodeEditor/index.tsx +0 -202
- package/src/client/CodeEditor/json1PresenceBroadcast.ts +0 -41
- package/src/client/CodeEditor/json1PresenceDisplay.ts +0 -350
- package/src/client/CodeEditor/rainbowBrackets.ts +0 -122
- package/src/client/CodeEditor/style.scss +0 -156
- package/src/client/CodeEditor/typescriptExtension/worker.ts +0 -32
- package/src/client/CodeErrorOverlay/index.tsx +0 -77
- package/src/client/CodeErrorOverlay/style.scss +0 -33
- package/src/client/Fonts/fonts.ts +0 -8
- package/src/client/Icons/AdjustmentSVG.tsx +0 -19
- package/src/client/Icons/BugSVG.tsx +0 -20
- package/src/client/Icons/CloseSVG.tsx +0 -19
- package/src/client/Icons/CssSVG.tsx +0 -16
- package/src/client/Icons/DirectoryArrowSVG.tsx +0 -19
- package/src/client/Icons/EditSVG.tsx +0 -19
- package/src/client/Icons/FileSVG.tsx +0 -19
- package/src/client/Icons/FolderSVG.tsx +0 -20
- package/src/client/Icons/GearSVG.tsx +0 -16
- package/src/client/Icons/HtmlSVG.tsx +0 -16
- package/src/client/Icons/JavaScriptSVG.tsx +0 -16
- package/src/client/Icons/JsonSVG.tsx +0 -16
- package/src/client/Icons/MarkdownSVG.tsx +0 -16
- package/src/client/Icons/MicSVG.tsx +0 -25
- package/src/client/Icons/NewSVG.tsx +0 -19
- package/src/client/Icons/PinSVG.tsx +0 -14
- package/src/client/Icons/PlaySVG.tsx +0 -16
- package/src/client/Icons/QuestionMarkSVG.tsx +0 -18
- package/src/client/Icons/ReactSVG.tsx +0 -16
- package/src/client/Icons/SearchSVG.tsx +0 -20
- package/src/client/Icons/SparklesSVG.tsx +0 -23
- package/src/client/Icons/SplitEditorSVG.tsx +0 -34
- package/src/client/Icons/StopSVG.tsx +0 -15
- package/src/client/Icons/SvelteSVG.tsx +0 -16
- package/src/client/Icons/TrashSVG.tsx +0 -19
- package/src/client/Icons/TypeScriptSVG.tsx +0 -16
- package/src/client/Icons/index.tsx +0 -24
- package/src/client/ImageViewer/index.tsx +0 -91
- package/src/client/ImageViewer/style.scss +0 -41
- package/src/client/PresenceNotifications/PresenceNotifications.test.ts +0 -134
- package/src/client/PresenceNotifications/index.tsx +0 -158
- package/src/client/PresenceNotifications/style.scss +0 -17
- package/src/client/RunCodeWidget/index.tsx +0 -117
- package/src/client/RunCodeWidget/style.scss +0 -24
- package/src/client/SplitPaneResizeContext.tsx +0 -159
- package/src/client/TabList/Tab.tsx +0 -73
- package/src/client/TabList/index.tsx +0 -35
- package/src/client/TabList/style.scss +0 -51
- package/src/client/VZCodeContext/index.tsx +0 -29
- package/src/client/VZCodeContext/types.ts +0 -249
- package/src/client/VZCodeContext/useVZCodeState.ts +0 -584
- package/src/client/VZKeyboardShortcutsDoc.tsx +0 -148
- package/src/client/VZLeft.tsx +0 -28
- package/src/client/VZMiddle.tsx +0 -172
- package/src/client/VZResizer/index.tsx +0 -128
- package/src/client/VZResizer/styles.scss +0 -33
- package/src/client/VZRight.tsx +0 -113
- package/src/client/VZSettings.tsx +0 -275
- package/src/client/VZSidebar/AIChat/ChatInput.tsx +0 -196
- package/src/client/VZSidebar/AIChat/DiffView.scss +0 -136
- package/src/client/VZSidebar/AIChat/DiffView.tsx +0 -176
- package/src/client/VZSidebar/AIChat/Message.tsx +0 -143
- package/src/client/VZSidebar/AIChat/MessageList.tsx +0 -205
- package/src/client/VZSidebar/AIChat/StreamingMessage.tsx +0 -35
- package/src/client/VZSidebar/AIChat/ThinkingScratchpad.tsx +0 -156
- package/src/client/VZSidebar/AIChat/TypingIndicator.tsx +0 -19
- package/src/client/VZSidebar/AIChat/index.tsx +0 -273
- package/src/client/VZSidebar/AIChat/styles.scss +0 -627
- package/src/client/VZSidebar/CreateDirModal.tsx +0 -111
- package/src/client/VZSidebar/CreateFileModal.tsx +0 -111
- package/src/client/VZSidebar/DeleteConfirmationModal.tsx +0 -76
- package/src/client/VZSidebar/DirectoryListing.tsx +0 -89
- package/src/client/VZSidebar/EmptyState.tsx +0 -11
- package/src/client/VZSidebar/FileListing.tsx +0 -91
- package/src/client/VZSidebar/FileTypeIcon.tsx +0 -49
- package/src/client/VZSidebar/Item.tsx +0 -237
- package/src/client/VZSidebar/Listing.tsx +0 -47
- package/src/client/VZSidebar/Search.tsx +0 -527
- package/src/client/VZSidebar/VisualEditor.tsx +0 -295
- package/src/client/VZSidebar/VoiceChatModal.tsx +0 -121
- package/src/client/VZSidebar/aiCopyPaste.ts +0 -199
- package/src/client/VZSidebar/index.tsx +0 -728
- package/src/client/VZSidebar/styles.scss +0 -612
- package/src/client/VZSidebar/useDragAndDrop.tsx +0 -408
- package/src/client/bootstrap.ts +0 -26
- package/src/client/buildWorker.ts +0 -3
- package/src/client/featureFlags.ts +0 -8
- package/src/client/generateRequestId.ts +0 -6
- package/src/client/getFileTree.ts +0 -53
- package/src/client/index.ts +0 -19
- package/src/client/main.jsx +0 -10
- package/src/client/presenceColor.ts +0 -8
- package/src/client/shouldTriggerRun.ts +0 -31
- package/src/client/sortFileTree.ts +0 -21
- package/src/client/tabsSearchParameters.test.ts +0 -79
- package/src/client/tabsSearchParameters.ts +0 -137
- package/src/client/themes/index.ts +0 -7
- package/src/client/themes/themes.ts +0 -77
- package/src/client/themes/uiwImports.ts +0 -32
- package/src/client/themes/useDynamicTheme.ts +0 -29
- package/src/client/themes/vizhubTheme/colors.ts +0 -80
- package/src/client/themes/vizhubTheme/index.ts +0 -193
- package/src/client/useActions.ts +0 -288
- package/src/client/useESLint/index.ts +0 -72
- package/src/client/useESLint/worker.ts +0 -113
- package/src/client/useEditorCache.ts +0 -35
- package/src/client/useFileCRUD.ts +0 -228
- package/src/client/useKeyboardShortcuts.ts +0 -451
- package/src/client/useOpenDirectories.ts +0 -99
- package/src/client/usePresenceAutoFollow.ts +0 -85
- package/src/client/usePrettier/index.ts +0 -178
- package/src/client/usePrettier/worker.ts +0 -109
- package/src/client/useRunCode.tsx +0 -15
- package/src/client/useRuntimeError.ts +0 -32
- package/src/client/useSubmitOperation.ts +0 -15
- package/src/client/useURLSync.ts +0 -137
- package/src/client/usernameLocalStorage.ts +0 -43
- package/src/client/utils/fileExtension.ts +0 -10
- package/src/client/utils/isImageFile.ts +0 -12
- package/src/client/vzReducer/aiChatReducer.ts +0 -44
- package/src/client/vzReducer/closeTabReducer.test.ts +0 -205
- package/src/client/vzReducer/closeTabsReducer.ts +0 -96
- package/src/client/vzReducer/createInitialState.ts +0 -38
- package/src/client/vzReducer/editorNoLongerWantsFocusReducer.ts +0 -9
- package/src/client/vzReducer/findPane.ts +0 -19
- package/src/client/vzReducer/index.ts +0 -250
- package/src/client/vzReducer/openTabReducer.test.ts +0 -127
- package/src/client/vzReducer/openTabReducer.ts +0 -74
- package/src/client/vzReducer/searchReducer.test.ts +0 -292
- package/src/client/vzReducer/searchReducer.ts +0 -181
- package/src/client/vzReducer/setActiveFileIdReducer.ts +0 -28
- package/src/client/vzReducer/setActiveFileLeftRightReducer.ts +0 -76
- package/src/client/vzReducer/setIsDocOpenReducer.ts +0 -9
- package/src/client/vzReducer/setIsSettingsOpenReducer.ts +0 -9
- package/src/client/vzReducer/setThemeReducer.ts +0 -9
- package/src/client/vzReducer/setUsernameReducer.ts +0 -9
- package/src/client/vzReducer/splitCurrentPaneReducer.ts +0 -66
- package/src/client/vzReducer/toggleAutoFollowReducer.ts +0 -12
- package/src/client/vzReducer/updatePane.ts +0 -40
- package/src/client/vzReducer/updatePresenceIndicatorReducer.ts +0 -30
- package/src/client/vzReducer/visualEditorReducer.ts +0 -9
- package/src/reactRouterExports.ts +0 -15
- package/src/runCode.ts +0 -27
- package/src/server/aiChatHandler/aiEditing.ts +0 -152
- package/src/server/aiChatHandler/chatOperations.ts +0 -510
- package/src/server/aiChatHandler/errorHandling.ts +0 -66
- package/src/server/aiChatHandler/index.ts +0 -200
- package/src/server/aiChatHandler/llmStreaming.ts +0 -419
- package/src/server/aiChatHandler/undoHandler.ts +0 -97
- package/src/server/aiChatHandler/validation.ts +0 -24
- package/src/server/computeInitialDocument.ts +0 -220
- package/src/server/generateAIResponse.ts +0 -188
- package/src/server/handleAIAssist.ts +0 -53
- package/src/server/handleAIChatUndo.ts +0 -2
- package/src/server/handleAICopilot.ts +0 -97
- package/src/server/index.ts +0 -388
- package/src/server/livekit.ts +0 -24
- package/src/server/prettier.ts +0 -115
- package/src/submitOperation.ts +0 -25
- package/src/types.ts +0 -205
- package/src/utils/fileDiff.ts +0 -117
- package/src/vite-env.d.ts +0 -10
- /package/{src/server/handleAIChatMessage.ts → dist/server/handleAIChatMessage.js} +0 -0
- /package/{src/server/isDirectory.ts → dist/server/isDirectory.js} +0 -0
|
@@ -1,99 +0,0 @@
|
|
|
1
|
-
import { useState, useCallback, useEffect } from 'react';
|
|
2
|
-
import type { Pane } from '../types';
|
|
3
|
-
import { VizContent } from '@vizhub/viz-types';
|
|
4
|
-
|
|
5
|
-
// TODO bring this feature back
|
|
6
|
-
// When a page is opened with an active file,
|
|
7
|
-
// make sure all the directories leading to that file
|
|
8
|
-
// are opened automatically.
|
|
9
|
-
export const initialOpenDirectories = (
|
|
10
|
-
activeFile: string | null,
|
|
11
|
-
): Set<VZPath> => {
|
|
12
|
-
const openDirectories = new Set<VZPath>();
|
|
13
|
-
if (activeFile) {
|
|
14
|
-
const path = activeFile.split('/');
|
|
15
|
-
for (let i = 1; i < path.length; i++) {
|
|
16
|
-
openDirectories.add(path.slice(0, i).join('/'));
|
|
17
|
-
}
|
|
18
|
-
}
|
|
19
|
-
return openDirectories;
|
|
20
|
-
};
|
|
21
|
-
|
|
22
|
-
type VZPath = string;
|
|
23
|
-
|
|
24
|
-
// Inspired by
|
|
25
|
-
// https://github.com/vizhub-core/vizhub/blob/main/vizhub-v2/packages/neoFrontend/src/pages/VizPage/Body/Editor/FilesSection/useOpenDirectories.js
|
|
26
|
-
// TODO move this into reducer
|
|
27
|
-
export const useOpenDirectories = ({
|
|
28
|
-
activePane,
|
|
29
|
-
content,
|
|
30
|
-
}: {
|
|
31
|
-
activePane: Pane;
|
|
32
|
-
content: VizContent;
|
|
33
|
-
}): {
|
|
34
|
-
isDirectoryOpen: (path: VZPath) => boolean;
|
|
35
|
-
toggleDirectory: (path: VZPath) => void;
|
|
36
|
-
} => {
|
|
37
|
-
// The set of open directories by path/
|
|
38
|
-
const [openDirectories, setOpenDirectories] = useState<
|
|
39
|
-
Set<VZPath>
|
|
40
|
-
>(new Set());
|
|
41
|
-
|
|
42
|
-
// (client-side only) initialize the open directories
|
|
43
|
-
// based on the open files from the URL params.
|
|
44
|
-
useEffect(() => {
|
|
45
|
-
if (
|
|
46
|
-
activePane.type === 'leafPane' &&
|
|
47
|
-
activePane?.activeFileId &&
|
|
48
|
-
content.files[activePane.activeFileId]
|
|
49
|
-
) {
|
|
50
|
-
const activeFileId = activePane.activeFileId;
|
|
51
|
-
const fileName = content.files[activeFileId].name;
|
|
52
|
-
const dirsToOpen = initialOpenDirectories(fileName);
|
|
53
|
-
setOpenDirectories((prev) => {
|
|
54
|
-
const updated = new Set(prev);
|
|
55
|
-
for (const dir of dirsToOpen) {
|
|
56
|
-
updated.add(dir);
|
|
57
|
-
}
|
|
58
|
-
return updated;
|
|
59
|
-
});
|
|
60
|
-
}
|
|
61
|
-
}, [activePane]);
|
|
62
|
-
|
|
63
|
-
// Whether a directory is open.
|
|
64
|
-
const isDirectoryOpen: (path: VZPath) => boolean =
|
|
65
|
-
useCallback(
|
|
66
|
-
(path) => openDirectories.has(path),
|
|
67
|
-
[openDirectories],
|
|
68
|
-
);
|
|
69
|
-
|
|
70
|
-
/**
|
|
71
|
-
* Toggles the state of a directory (open/close).
|
|
72
|
-
* If the directory is currently open, it will close it.
|
|
73
|
-
* If it's closed, it will open it.
|
|
74
|
-
*/
|
|
75
|
-
const toggleDirectory = useCallback(
|
|
76
|
-
(path: VZPath) => {
|
|
77
|
-
// Create a copy of the currently open directories
|
|
78
|
-
const updatedOpenDirectories = new Set(
|
|
79
|
-
openDirectories,
|
|
80
|
-
);
|
|
81
|
-
|
|
82
|
-
// Check if the directory is currently open
|
|
83
|
-
const directoryIsOpen = isDirectoryOpen(path);
|
|
84
|
-
|
|
85
|
-
// Toggle the directory's state
|
|
86
|
-
if (directoryIsOpen) {
|
|
87
|
-
updatedOpenDirectories.delete(path);
|
|
88
|
-
} else {
|
|
89
|
-
updatedOpenDirectories.add(path);
|
|
90
|
-
}
|
|
91
|
-
|
|
92
|
-
// Update the state with the modified set of open directories
|
|
93
|
-
setOpenDirectories(updatedOpenDirectories);
|
|
94
|
-
},
|
|
95
|
-
[openDirectories, isDirectoryOpen],
|
|
96
|
-
);
|
|
97
|
-
|
|
98
|
-
return { isDirectoryOpen, toggleDirectory };
|
|
99
|
-
};
|
|
@@ -1,85 +0,0 @@
|
|
|
1
|
-
import { useEffect, useRef } from 'react';
|
|
2
|
-
import { Presence, PresenceId } from '../types';
|
|
3
|
-
import { VizFileId } from '@vizhub/viz-types';
|
|
4
|
-
|
|
5
|
-
const DEBUG = false;
|
|
6
|
-
|
|
7
|
-
/**
|
|
8
|
-
* Custom hook that handles auto-following users by opening tabs when presence
|
|
9
|
-
* is received on files that are not currently open. This logic is independent
|
|
10
|
-
* of CodeMirror extensions and works regardless of editor cache state.
|
|
11
|
-
*/
|
|
12
|
-
export const usePresenceAutoFollow = ({
|
|
13
|
-
docPresence,
|
|
14
|
-
enableAutoFollow,
|
|
15
|
-
openTab,
|
|
16
|
-
activePane,
|
|
17
|
-
}) => {
|
|
18
|
-
// Track enableAutoFollow on a ref for use in event handlers
|
|
19
|
-
const enableAutoFollowRef = useRef(enableAutoFollow);
|
|
20
|
-
useEffect(() => {
|
|
21
|
-
enableAutoFollowRef.current = enableAutoFollow;
|
|
22
|
-
}, [enableAutoFollow]);
|
|
23
|
-
|
|
24
|
-
// Track active file for comparison
|
|
25
|
-
const activeFileIdRef = useRef(activePane?.activeFileId);
|
|
26
|
-
useEffect(() => {
|
|
27
|
-
activeFileIdRef.current = activePane?.activeFileId;
|
|
28
|
-
}, [activePane?.activeFileId]);
|
|
29
|
-
|
|
30
|
-
useEffect(() => {
|
|
31
|
-
if (!docPresence) return;
|
|
32
|
-
|
|
33
|
-
const handlePresenceReceive = (
|
|
34
|
-
id: PresenceId,
|
|
35
|
-
presence: Presence,
|
|
36
|
-
) => {
|
|
37
|
-
if (DEBUG) {
|
|
38
|
-
console.log(
|
|
39
|
-
`[usePresenceAutoFollow] Received presence for id ${id}`,
|
|
40
|
-
presence,
|
|
41
|
-
);
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
// If presence is null, the user has disconnected
|
|
45
|
-
if (!presence) {
|
|
46
|
-
return;
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
// If auto-follow is not enabled, do nothing
|
|
50
|
-
if (!enableAutoFollowRef.current) {
|
|
51
|
-
return;
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
// Extract the file ID from the presence path
|
|
55
|
-
// Presence path structure: [path, to, file, fileId, position]
|
|
56
|
-
// We want the fileId which should be at index 1 for files
|
|
57
|
-
const presenceFileId = presence.start[1] as VizFileId;
|
|
58
|
-
|
|
59
|
-
// If the presence is for the currently active file, do nothing
|
|
60
|
-
// (the CodeMirror extension will handle displaying the cursor)
|
|
61
|
-
if (presenceFileId === activeFileIdRef.current) {
|
|
62
|
-
return;
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
// If the presence is for a different file, open that tab
|
|
66
|
-
DEBUG &&
|
|
67
|
-
console.log(
|
|
68
|
-
`[usePresenceAutoFollow] Auto-opening tab for ${presence.username} in file ${presenceFileId}`,
|
|
69
|
-
);
|
|
70
|
-
|
|
71
|
-
openTab({
|
|
72
|
-
fileId: presenceFileId,
|
|
73
|
-
isTransient: true,
|
|
74
|
-
});
|
|
75
|
-
};
|
|
76
|
-
|
|
77
|
-
// Subscribe to presence changes
|
|
78
|
-
docPresence.on('receive', handlePresenceReceive);
|
|
79
|
-
|
|
80
|
-
// Cleanup subscription on unmount
|
|
81
|
-
return () => {
|
|
82
|
-
docPresence.off('receive', handlePresenceReceive);
|
|
83
|
-
};
|
|
84
|
-
}, [docPresence, openTab]);
|
|
85
|
-
};
|
|
@@ -1,178 +0,0 @@
|
|
|
1
|
-
import { VizFileId, VizContent } from '@vizhub/viz-types';
|
|
2
|
-
import { JSONOp, ShareDBDoc } from '../../types';
|
|
3
|
-
import { useEffect, useRef, useState } from 'react';
|
|
4
|
-
|
|
5
|
-
// The time in milliseconds by which auto-saving is debounced.
|
|
6
|
-
export const autoPrettierDebounceTimeMS = 1200;
|
|
7
|
-
|
|
8
|
-
// Computes a file extension from a file name.
|
|
9
|
-
// Example: 'foo.js' => '.js'
|
|
10
|
-
const extension = (fileName: string) => {
|
|
11
|
-
const match = fileName.match(/\.([^.]+)$/);
|
|
12
|
-
if (match) {
|
|
13
|
-
return match[1];
|
|
14
|
-
} else {
|
|
15
|
-
return '';
|
|
16
|
-
}
|
|
17
|
-
};
|
|
18
|
-
|
|
19
|
-
// export const shouldTriggerRun = (event: KeyboardEvent) => {
|
|
20
|
-
// if(event.ctrlKey && event.key === 's') {
|
|
21
|
-
// return true;
|
|
22
|
-
// }
|
|
23
|
-
// }
|
|
24
|
-
|
|
25
|
-
export const usePrettier = ({
|
|
26
|
-
shareDBDoc,
|
|
27
|
-
submitOperation,
|
|
28
|
-
prettierWorker,
|
|
29
|
-
}: {
|
|
30
|
-
shareDBDoc: ShareDBDoc<VizContent> | null;
|
|
31
|
-
submitOperation: (
|
|
32
|
-
next: (content: VizContent) => VizContent,
|
|
33
|
-
) => void;
|
|
34
|
-
prettierWorker: Worker;
|
|
35
|
-
}) => {
|
|
36
|
-
// The set of files that have been modified
|
|
37
|
-
// since the last Prettier run.
|
|
38
|
-
const dirtyFilesRef = useRef<Set<VizFileId>>(new Set());
|
|
39
|
-
|
|
40
|
-
// State to hold the error from Prettier
|
|
41
|
-
// `null` means no errors
|
|
42
|
-
// If this is a string, it's the
|
|
43
|
-
// error message from Prettier.
|
|
44
|
-
const [prettierError, setPrettierError] = useState<
|
|
45
|
-
string | null
|
|
46
|
-
>(null);
|
|
47
|
-
|
|
48
|
-
// A ref to keep track of whether an op is being applied.
|
|
49
|
-
// This is used to prevent Prettier from running
|
|
50
|
-
// when the op is coming from Prettier itself.
|
|
51
|
-
const isApplyingOpRef = useRef(false);
|
|
52
|
-
|
|
53
|
-
// We use a ref to keep track of the runPrettier function.
|
|
54
|
-
const runPrettierRef = useRef(null);
|
|
55
|
-
|
|
56
|
-
useEffect(() => {
|
|
57
|
-
if (!shareDBDoc) {
|
|
58
|
-
return;
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
// Get the message that comes back from the worker.
|
|
62
|
-
// This is the prettified text for a specific file.
|
|
63
|
-
const handleMessage = (event) => {
|
|
64
|
-
const { fileId, error, fileTextPrettified } =
|
|
65
|
-
event.data;
|
|
66
|
-
|
|
67
|
-
// Handle syntax errors
|
|
68
|
-
if (error) {
|
|
69
|
-
// If there's an error, set the error state
|
|
70
|
-
setPrettierError(error);
|
|
71
|
-
|
|
72
|
-
// Return early as there is no text change to apply.
|
|
73
|
-
return;
|
|
74
|
-
} else {
|
|
75
|
-
// Make sure the error overlay goes away
|
|
76
|
-
// when Prettier runs successfully with no errors.
|
|
77
|
-
setPrettierError(null);
|
|
78
|
-
}
|
|
79
|
-
|
|
80
|
-
isApplyingOpRef.current = true;
|
|
81
|
-
submitOperation((document) => ({
|
|
82
|
-
...document,
|
|
83
|
-
files: {
|
|
84
|
-
...document.files,
|
|
85
|
-
[fileId]: {
|
|
86
|
-
...document.files[fileId],
|
|
87
|
-
text: fileTextPrettified,
|
|
88
|
-
},
|
|
89
|
-
},
|
|
90
|
-
}));
|
|
91
|
-
isApplyingOpRef.current = false;
|
|
92
|
-
};
|
|
93
|
-
|
|
94
|
-
// Listen for messages from the worker.
|
|
95
|
-
prettierWorker.addEventListener(
|
|
96
|
-
'message',
|
|
97
|
-
handleMessage,
|
|
98
|
-
);
|
|
99
|
-
|
|
100
|
-
const runPrettier = async () => {
|
|
101
|
-
// Get the content of the document
|
|
102
|
-
const content = shareDBDoc.data;
|
|
103
|
-
|
|
104
|
-
// Get the files
|
|
105
|
-
const files = content.files;
|
|
106
|
-
|
|
107
|
-
// Get the set of dirty files
|
|
108
|
-
const dirtyFiles = dirtyFilesRef.current;
|
|
109
|
-
|
|
110
|
-
// Get the dirty files
|
|
111
|
-
const dirtyFileIds = Array.from(dirtyFiles);
|
|
112
|
-
|
|
113
|
-
// Clear the set of dirty files
|
|
114
|
-
dirtyFiles.clear();
|
|
115
|
-
|
|
116
|
-
// Run Prettier on each dirty file
|
|
117
|
-
for (const fileId of dirtyFileIds) {
|
|
118
|
-
// Get the file
|
|
119
|
-
const file = files[fileId];
|
|
120
|
-
|
|
121
|
-
// Craft the data to send to the worker
|
|
122
|
-
const data = {
|
|
123
|
-
fileText: file.text,
|
|
124
|
-
fileExtension: extension(file.name),
|
|
125
|
-
fileId,
|
|
126
|
-
};
|
|
127
|
-
|
|
128
|
-
// Run Prettier for this file
|
|
129
|
-
prettierWorker.postMessage(data);
|
|
130
|
-
}
|
|
131
|
-
};
|
|
132
|
-
runPrettierRef.current = runPrettier;
|
|
133
|
-
|
|
134
|
-
const handleOpBatch = (op: JSONOp) => {
|
|
135
|
-
// Only act on changes coming from the client
|
|
136
|
-
// OR changes coming from the AI Assist that we
|
|
137
|
-
// if (isLocal) {
|
|
138
|
-
// If the op is coming from Prettier itself,
|
|
139
|
-
// then do nothing.
|
|
140
|
-
if (isApplyingOpRef.current) {
|
|
141
|
-
// console.log('ignoring op from Prettier');
|
|
142
|
-
return;
|
|
143
|
-
}
|
|
144
|
-
|
|
145
|
-
// Check if the path of this op is the text content of a file
|
|
146
|
-
if (
|
|
147
|
-
op &&
|
|
148
|
-
op.length === 4 &&
|
|
149
|
-
op[0] === 'files' &&
|
|
150
|
-
typeof op[1] === 'string' &&
|
|
151
|
-
op[2] === 'text'
|
|
152
|
-
) {
|
|
153
|
-
// Get the file id
|
|
154
|
-
const fileId: VizFileId = op[1];
|
|
155
|
-
|
|
156
|
-
// Add the file id to the set of dirty files
|
|
157
|
-
dirtyFilesRef.current.add(fileId);
|
|
158
|
-
}
|
|
159
|
-
};
|
|
160
|
-
|
|
161
|
-
// Listen for changes
|
|
162
|
-
shareDBDoc.on('op batch', handleOpBatch);
|
|
163
|
-
|
|
164
|
-
// Clean up the event listeners
|
|
165
|
-
return () => {
|
|
166
|
-
prettierWorker.removeEventListener(
|
|
167
|
-
'message',
|
|
168
|
-
handleMessage,
|
|
169
|
-
);
|
|
170
|
-
|
|
171
|
-
shareDBDoc.removeListener('op batch', handleOpBatch);
|
|
172
|
-
};
|
|
173
|
-
}, [shareDBDoc]);
|
|
174
|
-
|
|
175
|
-
// Return the errors and run prettier function ref
|
|
176
|
-
// for use elsewhere.
|
|
177
|
-
return { prettierError, runPrettierRef };
|
|
178
|
-
};
|
|
@@ -1,109 +0,0 @@
|
|
|
1
|
-
import { format } from 'prettier/standalone';
|
|
2
|
-
import * as prettierPluginBabel from 'prettier/plugins/babel';
|
|
3
|
-
import * as prettierPluginEstree from 'prettier/plugins/estree';
|
|
4
|
-
import * as prettierPluginHtml from 'prettier/plugins/html';
|
|
5
|
-
import * as prettierPluginMarkdown from 'prettier/plugins/markdown';
|
|
6
|
-
import * as prettierPluginCSS from 'prettier/plugins/postcss';
|
|
7
|
-
import * as prettierPluginTypescript from 'prettier/plugins/typescript';
|
|
8
|
-
import * as prettierPluginSvelte from 'prettier-plugin-svelte/browser';
|
|
9
|
-
|
|
10
|
-
import { VizFileId } from '@vizhub/viz-types';
|
|
11
|
-
|
|
12
|
-
const enableSvelte = true;
|
|
13
|
-
|
|
14
|
-
const parsers = {
|
|
15
|
-
js: 'babel',
|
|
16
|
-
jsx: 'babel',
|
|
17
|
-
mjs: 'babel',
|
|
18
|
-
cjs: 'babel',
|
|
19
|
-
ts: 'typescript',
|
|
20
|
-
tsx: 'typescript',
|
|
21
|
-
css: 'css',
|
|
22
|
-
// '.less': 'less',
|
|
23
|
-
// '.scss': 'scss',
|
|
24
|
-
html: 'html',
|
|
25
|
-
json: 'json',
|
|
26
|
-
json5: 'json5',
|
|
27
|
-
md: 'markdown',
|
|
28
|
-
markdown: 'markdown',
|
|
29
|
-
// '.vue': 'vue',
|
|
30
|
-
};
|
|
31
|
-
|
|
32
|
-
if (enableSvelte) {
|
|
33
|
-
// @ts-ignore
|
|
34
|
-
parsers.svelte = 'svelte';
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
const plugins = [
|
|
38
|
-
prettierPluginBabel,
|
|
39
|
-
prettierPluginEstree,
|
|
40
|
-
prettierPluginHtml,
|
|
41
|
-
prettierPluginMarkdown,
|
|
42
|
-
prettierPluginTypescript,
|
|
43
|
-
prettierPluginCSS,
|
|
44
|
-
] as any; // Cast to any to resolve type conflict
|
|
45
|
-
|
|
46
|
-
if (enableSvelte) {
|
|
47
|
-
// @ts-ignore
|
|
48
|
-
plugins.push(prettierPluginSvelte);
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
onmessage = async ({
|
|
52
|
-
data,
|
|
53
|
-
}: {
|
|
54
|
-
data: {
|
|
55
|
-
// The text content of the file
|
|
56
|
-
fileText: string;
|
|
57
|
-
|
|
58
|
-
// The file extension
|
|
59
|
-
// Supported extensions: https://prettier.io/docs/en/options.html#parser
|
|
60
|
-
// The editor only supports
|
|
61
|
-
// - JavaScript
|
|
62
|
-
// - TypeScript
|
|
63
|
-
// - HTML
|
|
64
|
-
// - CSS
|
|
65
|
-
// - JSON
|
|
66
|
-
// - Markdown
|
|
67
|
-
|
|
68
|
-
fileExtension: string;
|
|
69
|
-
|
|
70
|
-
// The file id
|
|
71
|
-
fileId: VizFileId;
|
|
72
|
-
};
|
|
73
|
-
}) => {
|
|
74
|
-
const { fileExtension, fileText, fileId } = data;
|
|
75
|
-
const parser = parsers[fileExtension];
|
|
76
|
-
|
|
77
|
-
// If no parser is found, just do nothing.
|
|
78
|
-
// For example, if the user opens a CSV file,
|
|
79
|
-
// then we don't want to run Prettier on it,
|
|
80
|
-
// and we also don't want to show an error.
|
|
81
|
-
if (!parser) {
|
|
82
|
-
return;
|
|
83
|
-
}
|
|
84
|
-
|
|
85
|
-
try {
|
|
86
|
-
const fileTextPrettified = await format(fileText, {
|
|
87
|
-
parser,
|
|
88
|
-
plugins,
|
|
89
|
-
|
|
90
|
-
// This helps with Markdown files
|
|
91
|
-
proseWrap: 'always',
|
|
92
|
-
|
|
93
|
-
// Opinionated code style for JavaScript
|
|
94
|
-
singleQuote: true,
|
|
95
|
-
printWidth: 60,
|
|
96
|
-
});
|
|
97
|
-
|
|
98
|
-
postMessage({
|
|
99
|
-
fileId,
|
|
100
|
-
fileTextPrettified,
|
|
101
|
-
});
|
|
102
|
-
} catch (error) {
|
|
103
|
-
console.error(error);
|
|
104
|
-
postMessage({
|
|
105
|
-
fileId,
|
|
106
|
-
error: error.toString(),
|
|
107
|
-
});
|
|
108
|
-
}
|
|
109
|
-
};
|
|
@@ -1,15 +0,0 @@
|
|
|
1
|
-
import { useEffect, useRef } from 'react';
|
|
2
|
-
import { SubmitOperation } from '../types';
|
|
3
|
-
import { createRunCodeFunction } from '../runCode';
|
|
4
|
-
|
|
5
|
-
// Runs the code by flashing `isInteracting` to `true`.
|
|
6
|
-
export const useRunCode = (
|
|
7
|
-
submitOperation: SubmitOperation,
|
|
8
|
-
) => {
|
|
9
|
-
const runCodeRef = useRef(null);
|
|
10
|
-
useEffect(() => {
|
|
11
|
-
const runCode = createRunCodeFunction(submitOperation);
|
|
12
|
-
runCodeRef.current = runCode;
|
|
13
|
-
}, [submitOperation]);
|
|
14
|
-
return runCodeRef;
|
|
15
|
-
};
|
|
@@ -1,32 +0,0 @@
|
|
|
1
|
-
import { useCallback, useState } from 'react';
|
|
2
|
-
|
|
3
|
-
// Custom hook to manage runtime error state
|
|
4
|
-
export const useRuntimeError = () => {
|
|
5
|
-
// State to hold the runtime error message
|
|
6
|
-
// `null` means no errors
|
|
7
|
-
// If this is a string, it's the
|
|
8
|
-
// error message from runtime execution.
|
|
9
|
-
const [runtimeError, setRuntimeError] = useState<
|
|
10
|
-
string | null
|
|
11
|
-
>(null);
|
|
12
|
-
|
|
13
|
-
// Callback function to handle runtime errors
|
|
14
|
-
// This will be passed to the createRuntime function
|
|
15
|
-
const handleRuntimeError = useCallback(
|
|
16
|
-
(formattedErrorMessage: string) => {
|
|
17
|
-
setRuntimeError(formattedErrorMessage);
|
|
18
|
-
},
|
|
19
|
-
[],
|
|
20
|
-
);
|
|
21
|
-
|
|
22
|
-
// Function to clear runtime errors
|
|
23
|
-
const clearRuntimeError = useCallback(() => {
|
|
24
|
-
setRuntimeError(null);
|
|
25
|
-
}, []);
|
|
26
|
-
|
|
27
|
-
return {
|
|
28
|
-
runtimeError,
|
|
29
|
-
handleRuntimeError,
|
|
30
|
-
clearRuntimeError,
|
|
31
|
-
};
|
|
32
|
-
};
|
|
@@ -1,15 +0,0 @@
|
|
|
1
|
-
import { useCallback } from 'react';
|
|
2
|
-
import { ShareDBDoc } from '../types'; // Assuming ShareDBDoc is already generic
|
|
3
|
-
import { createSubmitOperation } from '../submitOperation';
|
|
4
|
-
|
|
5
|
-
// A generic helper function to submit diff-based operations to ShareDB
|
|
6
|
-
export const useSubmitOperation = <T>(
|
|
7
|
-
shareDBDoc: ShareDBDoc<T>,
|
|
8
|
-
): ((next: (data: T) => T) => void) => {
|
|
9
|
-
const submitOperation: (next: (data: T) => T) => void =
|
|
10
|
-
useCallback(() => {
|
|
11
|
-
return createSubmitOperation(shareDBDoc);
|
|
12
|
-
}, [shareDBDoc])();
|
|
13
|
-
|
|
14
|
-
return submitOperation;
|
|
15
|
-
};
|
package/src/client/useURLSync.ts
DELETED
|
@@ -1,137 +0,0 @@
|
|
|
1
|
-
import { TabState } from '../types';
|
|
2
|
-
import { VizFileId, VizContent } from '@vizhub/viz-types';
|
|
3
|
-
import { useEffect, useMemo, useRef } from 'react';
|
|
4
|
-
import {
|
|
5
|
-
TabStateParams,
|
|
6
|
-
decodeTabs,
|
|
7
|
-
encodeTabs,
|
|
8
|
-
} from './tabsSearchParameters';
|
|
9
|
-
import { useSearchParams } from '../reactRouterExports';
|
|
10
|
-
|
|
11
|
-
// Synchronizes the tab state with the URL parameters.
|
|
12
|
-
export const useURLSync = ({
|
|
13
|
-
content,
|
|
14
|
-
openTab,
|
|
15
|
-
setActiveFileId,
|
|
16
|
-
tabList,
|
|
17
|
-
activeFileId,
|
|
18
|
-
}: {
|
|
19
|
-
content: VizContent | null;
|
|
20
|
-
openTab: (tabState: TabState) => void;
|
|
21
|
-
setActiveFileId: (activeFileId: VizFileId) => void;
|
|
22
|
-
tabList: Array<TabState>;
|
|
23
|
-
activeFileId: VizFileId | null;
|
|
24
|
-
}) => {
|
|
25
|
-
// Use React router to get and set the search parameters.
|
|
26
|
-
const [searchParams, setSearchParams] = useSearchParams();
|
|
27
|
-
|
|
28
|
-
// Extract the tab state parameters from the search parameters.
|
|
29
|
-
const tabStateParams: TabStateParams = useMemo(
|
|
30
|
-
() => ({
|
|
31
|
-
file: searchParams.get('file'),
|
|
32
|
-
tabs: searchParams.get('tabs'),
|
|
33
|
-
}),
|
|
34
|
-
[searchParams],
|
|
35
|
-
);
|
|
36
|
-
|
|
37
|
-
// `true` after the state is updated based on the
|
|
38
|
-
// initial search parameters from the URL.
|
|
39
|
-
const isInitialized = useRef(false);
|
|
40
|
-
|
|
41
|
-
// Initialize the state based on the search parameters.
|
|
42
|
-
useEffect(() => {
|
|
43
|
-
// Do nothing if the state has already been initialized.
|
|
44
|
-
if (isInitialized.current) {
|
|
45
|
-
return;
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
// Wait for the content to be loaded.
|
|
49
|
-
if (!content) {
|
|
50
|
-
return;
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
// Decode the search parameters.
|
|
54
|
-
const { tabList, activeFileId } = decodeTabs({
|
|
55
|
-
tabStateParams,
|
|
56
|
-
content,
|
|
57
|
-
});
|
|
58
|
-
|
|
59
|
-
// Mark the state as initialized.
|
|
60
|
-
isInitialized.current = true;
|
|
61
|
-
|
|
62
|
-
// Update the state.
|
|
63
|
-
tabList.forEach(openTab);
|
|
64
|
-
setActiveFileId(activeFileId);
|
|
65
|
-
}, [
|
|
66
|
-
content,
|
|
67
|
-
searchParams,
|
|
68
|
-
setActiveFileId,
|
|
69
|
-
openTab,
|
|
70
|
-
isInitialized,
|
|
71
|
-
]);
|
|
72
|
-
|
|
73
|
-
// Track content in a ref so that we can use it in the
|
|
74
|
-
// effect below without triggering the effect when
|
|
75
|
-
// the content changes.
|
|
76
|
-
const contentRef = useRef(content);
|
|
77
|
-
useEffect(() => {
|
|
78
|
-
contentRef.current = content;
|
|
79
|
-
}, [content]);
|
|
80
|
-
|
|
81
|
-
// track setSearchParams in a ref so that we can use it in the
|
|
82
|
-
// effect below without triggering the effect on each render.
|
|
83
|
-
// The definition of `setSearchParams` changes on every render.
|
|
84
|
-
const setSearchParamsRef = useRef(setSearchParams);
|
|
85
|
-
useEffect(() => {
|
|
86
|
-
setSearchParamsRef.current = setSearchParams;
|
|
87
|
-
}, [setSearchParams]);
|
|
88
|
-
|
|
89
|
-
// Update the URL to match the current state whenever
|
|
90
|
-
// the active file or tab list changes.
|
|
91
|
-
useEffect(() => {
|
|
92
|
-
// Safety check to make sure the content is loaded.
|
|
93
|
-
// Should never happen.
|
|
94
|
-
if (!contentRef.current) {
|
|
95
|
-
return;
|
|
96
|
-
}
|
|
97
|
-
|
|
98
|
-
const newTabStateParams: TabStateParams = encodeTabs({
|
|
99
|
-
tabList,
|
|
100
|
-
activeFileId,
|
|
101
|
-
content: contentRef.current,
|
|
102
|
-
});
|
|
103
|
-
|
|
104
|
-
// Update the URL if the search parameters have changed.
|
|
105
|
-
setSearchParamsRef.current(
|
|
106
|
-
(oldSearchParams: URLSearchParams) => {
|
|
107
|
-
// Create a copy of the old search params
|
|
108
|
-
const updatedSearchParams = new URLSearchParams(
|
|
109
|
-
oldSearchParams,
|
|
110
|
-
);
|
|
111
|
-
|
|
112
|
-
// Set the 'file' parameter
|
|
113
|
-
if (newTabStateParams.file) {
|
|
114
|
-
updatedSearchParams.set(
|
|
115
|
-
'file',
|
|
116
|
-
newTabStateParams.file,
|
|
117
|
-
);
|
|
118
|
-
} else {
|
|
119
|
-
updatedSearchParams.delete('file'); // Remove 'file' if it's not present in newTabStateParams
|
|
120
|
-
}
|
|
121
|
-
|
|
122
|
-
// Set the 'tabs' parameter
|
|
123
|
-
if (newTabStateParams.tabs) {
|
|
124
|
-
updatedSearchParams.set(
|
|
125
|
-
'tabs',
|
|
126
|
-
newTabStateParams.tabs,
|
|
127
|
-
);
|
|
128
|
-
} else {
|
|
129
|
-
updatedSearchParams.delete('tabs'); // Remove 'tabs' if it's not present in newTabStateParams
|
|
130
|
-
}
|
|
131
|
-
|
|
132
|
-
// Return the updated search params
|
|
133
|
-
return updatedSearchParams;
|
|
134
|
-
},
|
|
135
|
-
);
|
|
136
|
-
}, [tabList, activeFileId]);
|
|
137
|
-
};
|