vzcode 1.8.0 → 1.10.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/{index-CU0jqXHm.js → index-DXNuoOqQ.js} +55 -55
- package/dist/index.html +1 -1
- package/package.json +7 -7
- package/src/client/CodeEditor/getOrCreateEditor.ts +46 -13
- package/src/client/Icons/index.tsx +0 -1
- package/src/client/VZSidebar/FileListing.tsx +38 -4
- package/src/client/VZSidebar/Item.tsx +2 -1
- package/src/client/VZSidebar/Search.tsx +4 -40
- package/src/client/useKeyboardShortcuts.ts +26 -2
- package/src/client/vzReducer/createInitialState.ts +1 -0
- package/src/client/Icons/SearchFileSVG.tsx +0 -19
package/dist/index.html
CHANGED
|
@@ -20,7 +20,7 @@
|
|
|
20
20
|
href="https://fonts.googleapis.com/css2?family=Poppins:wght@300;400;500;600;700&display=swap"
|
|
21
21
|
rel="stylesheet"
|
|
22
22
|
/>
|
|
23
|
-
<script type="module" crossorigin src="/assets/index-
|
|
23
|
+
<script type="module" crossorigin src="/assets/index-DXNuoOqQ.js"></script>
|
|
24
24
|
<link rel="stylesheet" crossorigin href="/assets/index-BKRpkJER.css">
|
|
25
25
|
</head>
|
|
26
26
|
<body>
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "vzcode",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.10.0",
|
|
4
4
|
"description": "Multiplayer code editor system",
|
|
5
5
|
"main": "src/index.ts",
|
|
6
6
|
"type": "module",
|
|
@@ -14,7 +14,7 @@
|
|
|
14
14
|
"test-interactive": "cd test/sampleDirectories/kitchenSink && node ../../../src/server/index.js",
|
|
15
15
|
"prettier": "prettier {*.*,**/*.*} --write",
|
|
16
16
|
"tsc": "tsc --noEmit",
|
|
17
|
-
"dev": "EDITOR_PORT=5173 concurrently \"npm run test-interactive\" \"vite\"",
|
|
17
|
+
"dev": "set EDITOR_PORT=5173 && concurrently \"npm run test-interactive\" \"vite\"",
|
|
18
18
|
"build": "vite build",
|
|
19
19
|
"build-release": "vite build --mode release",
|
|
20
20
|
"preview": "concurrently \"npm run test-interactive\" \"vite preview\"",
|
|
@@ -140,14 +140,14 @@
|
|
|
140
140
|
"json0-ot-diff": "^1.1.2",
|
|
141
141
|
"ngrok": "^4.3.3",
|
|
142
142
|
"open": "^10.1.0",
|
|
143
|
-
"openai": "^4.52.
|
|
143
|
+
"openai": "^4.52.4",
|
|
144
144
|
"prettier-plugin-svelte": "^3.2.5",
|
|
145
145
|
"react": "^18.3.1",
|
|
146
146
|
"react-bootstrap": "^2.10.4",
|
|
147
147
|
"react-dom": "^18.3.1",
|
|
148
148
|
"react-router-dom": "^6.24.1",
|
|
149
149
|
"sharedb": "^5.0.2",
|
|
150
|
-
"sharedb-client-browser": "^5.0.
|
|
150
|
+
"sharedb-client-browser": "^5.0.2",
|
|
151
151
|
"vizhub-ui": "^3.23.0",
|
|
152
152
|
"ws": "^8.18.0"
|
|
153
153
|
},
|
|
@@ -160,10 +160,10 @@
|
|
|
160
160
|
"sass": "^1.77.6",
|
|
161
161
|
"typescript": "^5.5.3",
|
|
162
162
|
"vite": "^5.3.3",
|
|
163
|
-
"vitest": "^
|
|
163
|
+
"vitest": "^2.0.1"
|
|
164
164
|
},
|
|
165
165
|
"optionalDependencies": {
|
|
166
|
-
"@rollup/rollup-darwin-arm64": "^4.18.
|
|
167
|
-
"@rollup/rollup-win32-x64-msvc": "^4.18.
|
|
166
|
+
"@rollup/rollup-darwin-arm64": "^4.18.1",
|
|
167
|
+
"@rollup/rollup-win32-x64-msvc": "^4.18.1"
|
|
168
168
|
}
|
|
169
169
|
}
|
|
@@ -40,6 +40,8 @@ import { keymap } from '@codemirror/view';
|
|
|
40
40
|
import { basicSetup } from './basicSetup';
|
|
41
41
|
import { InteractRule } from '@replit/codemirror-interact';
|
|
42
42
|
import rainbowBrackets from '../CodeEditor/rainbowBrackets';
|
|
43
|
+
import { cssLanguage } from '@codemirror/lang-css';
|
|
44
|
+
import { javascriptLanguage } from '@codemirror/lang-javascript';
|
|
43
45
|
|
|
44
46
|
// Feature flag to enable TypeScript completions & TypeScript Linter.
|
|
45
47
|
const enableTypeScriptCompletions = true;
|
|
@@ -49,6 +51,26 @@ const enableTypeScriptLinter = true;
|
|
|
49
51
|
const tsx = () =>
|
|
50
52
|
javascript({ jsx: true, typescript: true });
|
|
51
53
|
|
|
54
|
+
const htmlConfig = {
|
|
55
|
+
matchClosingTags: true,
|
|
56
|
+
selfClosingTags: false,
|
|
57
|
+
autoCloseTags: true,
|
|
58
|
+
extraTags: {},
|
|
59
|
+
extraGlobalAttributes: {},
|
|
60
|
+
nestedLanguages: [
|
|
61
|
+
{
|
|
62
|
+
tag: 'script',
|
|
63
|
+
language: javascript,
|
|
64
|
+
parser: javascriptLanguage.parser,
|
|
65
|
+
},
|
|
66
|
+
{
|
|
67
|
+
tag: 'style',
|
|
68
|
+
language: css,
|
|
69
|
+
parser: cssLanguage.parser,
|
|
70
|
+
},
|
|
71
|
+
],
|
|
72
|
+
nestedAttributes: [],
|
|
73
|
+
};
|
|
52
74
|
// Language extensions for CodeMirror.
|
|
53
75
|
// Keys are file extensions.
|
|
54
76
|
// Values are CodeMirror extensions.
|
|
@@ -59,7 +81,7 @@ const languageExtensions = {
|
|
|
59
81
|
js: tsx,
|
|
60
82
|
jsx: tsx,
|
|
61
83
|
ts: tsx,
|
|
62
|
-
html,
|
|
84
|
+
html: () => html(htmlConfig),
|
|
63
85
|
css,
|
|
64
86
|
md: markdown,
|
|
65
87
|
svelte,
|
|
@@ -146,6 +168,7 @@ export const getOrCreateEditor = ({
|
|
|
146
168
|
let themeCompartment = new Compartment();
|
|
147
169
|
|
|
148
170
|
// The CodeMirror extensions to use.
|
|
171
|
+
// const extensions = [autocompletion(), html(htmlConfig)]
|
|
149
172
|
const extensions = [];
|
|
150
173
|
|
|
151
174
|
// This plugin implements multiplayer editing,
|
|
@@ -266,18 +289,28 @@ export const getOrCreateEditor = ({
|
|
|
266
289
|
// );
|
|
267
290
|
|
|
268
291
|
// Add the extension that provides TypeScript completions.
|
|
269
|
-
if (
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
292
|
+
// only add this if it's TS-compatible (.js, .jsx, .ts, .tsx)
|
|
293
|
+
const isTypeScript =
|
|
294
|
+
fileExtension === 'js' ||
|
|
295
|
+
fileExtension === 'jsx' ||
|
|
296
|
+
fileExtension === 'ts' ||
|
|
297
|
+
fileExtension === 'tsx';
|
|
298
|
+
|
|
299
|
+
extensions.push(
|
|
300
|
+
autocompletion(
|
|
301
|
+
isTypeScript
|
|
302
|
+
? {
|
|
303
|
+
override: [
|
|
304
|
+
typeScriptCompletions({
|
|
305
|
+
typeScriptWorker,
|
|
306
|
+
fileName: name,
|
|
307
|
+
}),
|
|
308
|
+
],
|
|
309
|
+
}
|
|
310
|
+
: undefined,
|
|
311
|
+
),
|
|
312
|
+
);
|
|
313
|
+
|
|
281
314
|
if (shareDBDoc && enableTypeScriptLinter) {
|
|
282
315
|
extensions.push(
|
|
283
316
|
linter(
|
|
@@ -13,7 +13,6 @@ export { QuestionMarkSVG } from './QuestionMarkSVG';
|
|
|
13
13
|
export { PinSVG } from './PinSVG';
|
|
14
14
|
export { FolderSVG } from './FolderSVG';
|
|
15
15
|
export { SearchSVG } from './SearchSVG';
|
|
16
|
-
export { SearchFileSVG } from './SearchFileSVG';
|
|
17
16
|
export { JavaScriptSVG } from './JavaScriptSVG';
|
|
18
17
|
export { TypeScriptSVG } from './TypeScriptSVG';
|
|
19
18
|
export { ReactSVG } from './ReactSVG';
|
|
@@ -1,9 +1,45 @@
|
|
|
1
1
|
import { useCallback, useContext } from 'react';
|
|
2
2
|
import { Item } from './Item';
|
|
3
3
|
import { FileId } from '../../types';
|
|
4
|
-
import {
|
|
4
|
+
import {
|
|
5
|
+
FileSVG,
|
|
6
|
+
JavaScriptSVG,
|
|
7
|
+
TypeScriptSVG,
|
|
8
|
+
ReactSVG,
|
|
9
|
+
SvelteSVG,
|
|
10
|
+
JsonSVG,
|
|
11
|
+
MarkdownSVG,
|
|
12
|
+
HtmlSVG,
|
|
13
|
+
CssSVG,
|
|
14
|
+
} from '../Icons';
|
|
5
15
|
import { VZCodeContext } from '../VZCodeContext';
|
|
6
16
|
|
|
17
|
+
export function getExtensionIcon(fileName: string) {
|
|
18
|
+
const extension = fileName.split('.');
|
|
19
|
+
|
|
20
|
+
switch (extension[extension.length - 1]) {
|
|
21
|
+
case 'jsx':
|
|
22
|
+
case 'tsx':
|
|
23
|
+
return <ReactSVG />;
|
|
24
|
+
case 'js':
|
|
25
|
+
return <JavaScriptSVG />;
|
|
26
|
+
case 'ts':
|
|
27
|
+
return <TypeScriptSVG />;
|
|
28
|
+
case 'json':
|
|
29
|
+
return <JsonSVG />;
|
|
30
|
+
case 'md':
|
|
31
|
+
return <MarkdownSVG />;
|
|
32
|
+
case 'html':
|
|
33
|
+
return <HtmlSVG />;
|
|
34
|
+
case 'css':
|
|
35
|
+
return <CssSVG />;
|
|
36
|
+
case 'svelte':
|
|
37
|
+
return <SvelteSVG />;
|
|
38
|
+
default:
|
|
39
|
+
return <FileSVG />;
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
|
|
7
43
|
export const FileListing = ({
|
|
8
44
|
name,
|
|
9
45
|
fileId,
|
|
@@ -49,9 +85,7 @@ export const FileListing = ({
|
|
|
49
85
|
handleRenameClick={handleRenameClick}
|
|
50
86
|
isActive={isActive}
|
|
51
87
|
>
|
|
52
|
-
<i className="file-icon">
|
|
53
|
-
<FileSVG />
|
|
54
|
-
</i>
|
|
88
|
+
<i className="file-icon">{getExtensionIcon(name)}</i>
|
|
55
89
|
{name}
|
|
56
90
|
</Item>
|
|
57
91
|
);
|
|
@@ -12,6 +12,7 @@ import { Tooltip, OverlayTrigger } from '../bootstrap';
|
|
|
12
12
|
import { DeleteConfirmationModal } from './DeleteConfirmationModal';
|
|
13
13
|
import { VZCodeContext } from '../VZCodeContext';
|
|
14
14
|
import { ItemId } from '../../types';
|
|
15
|
+
import { getExtensionIcon } from './FileListing';
|
|
15
16
|
|
|
16
17
|
// TODO support renaming directories
|
|
17
18
|
// See https://github.com/vizhub-core/vzcode/issues/103
|
|
@@ -169,7 +170,7 @@ export const Item = ({
|
|
|
169
170
|
{isRenaming ? (
|
|
170
171
|
<>
|
|
171
172
|
<i className="file-icon">
|
|
172
|
-
|
|
173
|
+
{getExtensionIcon(renameValue)}
|
|
173
174
|
</i>
|
|
174
175
|
<input
|
|
175
176
|
className="rename-input"
|
|
@@ -1,16 +1,3 @@
|
|
|
1
|
-
import {
|
|
2
|
-
JavaScriptSVG,
|
|
3
|
-
TypeScriptSVG,
|
|
4
|
-
ReactSVG,
|
|
5
|
-
SvelteSVG,
|
|
6
|
-
JsonSVG,
|
|
7
|
-
MarkdownSVG,
|
|
8
|
-
HtmlSVG,
|
|
9
|
-
CssSVG,
|
|
10
|
-
SearchFileSVG,
|
|
11
|
-
DirectoryArrowSVG,
|
|
12
|
-
CloseSVG,
|
|
13
|
-
} from '../Icons';
|
|
14
1
|
import {
|
|
15
2
|
useRef,
|
|
16
3
|
useEffect,
|
|
@@ -21,30 +8,8 @@ import { Form } from '../bootstrap';
|
|
|
21
8
|
import { VZCodeContext } from '../VZCodeContext';
|
|
22
9
|
import { SearchFile } from '../../types';
|
|
23
10
|
import { EditorView } from 'codemirror';
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
switch (extension) {
|
|
27
|
-
case 'jsx':
|
|
28
|
-
case 'tsx':
|
|
29
|
-
return <ReactSVG />;
|
|
30
|
-
case 'js':
|
|
31
|
-
return <JavaScriptSVG />;
|
|
32
|
-
case 'ts':
|
|
33
|
-
return <TypeScriptSVG />;
|
|
34
|
-
case 'json':
|
|
35
|
-
return <JsonSVG />;
|
|
36
|
-
case 'md':
|
|
37
|
-
return <MarkdownSVG />;
|
|
38
|
-
case 'html':
|
|
39
|
-
return <HtmlSVG />;
|
|
40
|
-
case 'css':
|
|
41
|
-
return <CssSVG />;
|
|
42
|
-
case 'svelte':
|
|
43
|
-
return <SvelteSVG />;
|
|
44
|
-
default:
|
|
45
|
-
return <SearchFileSVG />;
|
|
46
|
-
}
|
|
47
|
-
}
|
|
11
|
+
import { getExtensionIcon } from './FileListing';
|
|
12
|
+
import { CloseSVG, DirectoryArrowSVG } from '../Icons';
|
|
48
13
|
|
|
49
14
|
function jumpToPattern(
|
|
50
15
|
editor: EditorView,
|
|
@@ -102,6 +67,7 @@ export const Search = () => {
|
|
|
102
67
|
return () => clearTimeout(delaySearch);
|
|
103
68
|
} else {
|
|
104
69
|
setIsMounted(true);
|
|
70
|
+
inputRef.current.focus();
|
|
105
71
|
}
|
|
106
72
|
}, [pattern]);
|
|
107
73
|
|
|
@@ -151,9 +117,7 @@ export const Search = () => {
|
|
|
151
117
|
<DirectoryArrowSVG />
|
|
152
118
|
</div>
|
|
153
119
|
<div className="search-file-name">
|
|
154
|
-
{getExtensionIcon(
|
|
155
|
-
file.name.split('.')[1],
|
|
156
|
-
)}
|
|
120
|
+
{getExtensionIcon(file.name)}
|
|
157
121
|
<h5>{file.name}</h5>
|
|
158
122
|
</div>
|
|
159
123
|
</div>
|
|
@@ -4,6 +4,7 @@ import { syntaxTree } from '@codemirror/language';
|
|
|
4
4
|
import { SyntaxNode, SyntaxNodeRef } from '@lezer/common';
|
|
5
5
|
import { EditorView } from '@codemirror/view';
|
|
6
6
|
import { EditorState } from '@codemirror/state';
|
|
7
|
+
import { FileId } from '../types';
|
|
7
8
|
|
|
8
9
|
/*
|
|
9
10
|
The following is a helpful resource for the following Code Mirror Syntax Tree methods below
|
|
@@ -170,6 +171,17 @@ export const useKeyboardShortcuts = ({
|
|
|
170
171
|
sidebarRef,
|
|
171
172
|
editorCache,
|
|
172
173
|
codeEditorRef,
|
|
174
|
+
}: {
|
|
175
|
+
closeTabs: (fileIds: FileId[]) => void;
|
|
176
|
+
activeFileId: FileId | null;
|
|
177
|
+
handleOpenCreateFileModal: () => void;
|
|
178
|
+
setActiveFileLeft: () => void;
|
|
179
|
+
setActiveFileRight: () => void;
|
|
180
|
+
runPrettierRef: React.MutableRefObject<() => void>;
|
|
181
|
+
runCodeRef: React.MutableRefObject<() => void>;
|
|
182
|
+
sidebarRef: React.RefObject<HTMLDivElement>;
|
|
183
|
+
editorCache: Map<string, { editor: EditorView }>;
|
|
184
|
+
codeEditorRef: React.RefObject<HTMLDivElement>;
|
|
173
185
|
}) => {
|
|
174
186
|
useEffect(() => {
|
|
175
187
|
const handleKeyPress = (event: KeyboardEvent) => {
|
|
@@ -205,7 +217,9 @@ export const useKeyboardShortcuts = ({
|
|
|
205
217
|
// TODO clean this up so we can remove `activeFileId`
|
|
206
218
|
// as a dependency
|
|
207
219
|
// TODO closeActiveTab()
|
|
208
|
-
|
|
220
|
+
if (activeFileId) {
|
|
221
|
+
closeTabs([activeFileId]);
|
|
222
|
+
}
|
|
209
223
|
return;
|
|
210
224
|
}
|
|
211
225
|
|
|
@@ -261,7 +275,8 @@ export const useKeyboardShortcuts = ({
|
|
|
261
275
|
const jumpToDefinitionHandler = (
|
|
262
276
|
event: MouseEvent,
|
|
263
277
|
): void => {
|
|
264
|
-
// Ensure the current destination node is defined
|
|
278
|
+
// Ensure the current destination node is defined
|
|
279
|
+
// and current cursor position matches highlighted element
|
|
265
280
|
if (
|
|
266
281
|
!definingNode ||
|
|
267
282
|
(event.target as HTMLSpanElement) !==
|
|
@@ -270,6 +285,11 @@ export const useKeyboardShortcuts = ({
|
|
|
270
285
|
return;
|
|
271
286
|
}
|
|
272
287
|
|
|
288
|
+
// Don't crash if no active file
|
|
289
|
+
if (!activeFileId) {
|
|
290
|
+
return;
|
|
291
|
+
}
|
|
292
|
+
|
|
273
293
|
// Move current cursor and center view in the editor to destination node
|
|
274
294
|
const editor: EditorView =
|
|
275
295
|
editorCache.get(activeFileId).editor;
|
|
@@ -300,6 +320,10 @@ export const useKeyboardShortcuts = ({
|
|
|
300
320
|
};
|
|
301
321
|
|
|
302
322
|
const handleMouseOver = (event: MouseEvent) => {
|
|
323
|
+
if (!activeFileId) {
|
|
324
|
+
return;
|
|
325
|
+
}
|
|
326
|
+
|
|
303
327
|
const editor: EditorView =
|
|
304
328
|
editorCache.get(activeFileId).editor;
|
|
305
329
|
const tree = syntaxTree(editor.state);
|
|
@@ -1,19 +0,0 @@
|
|
|
1
|
-
export const SearchFileSVG = () => {
|
|
2
|
-
return (
|
|
3
|
-
<svg
|
|
4
|
-
xmlns="http://www.w3.org/2000/svg"
|
|
5
|
-
width="24"
|
|
6
|
-
height="24"
|
|
7
|
-
fill="none"
|
|
8
|
-
viewBox="0 0 24 24"
|
|
9
|
-
>
|
|
10
|
-
<path
|
|
11
|
-
stroke="currentColor"
|
|
12
|
-
strokeLinecap="round"
|
|
13
|
-
strokeLinejoin="round"
|
|
14
|
-
strokeWidth="1.5"
|
|
15
|
-
d="M19.5 14.25v-2.625a3.375 3.375 0 0 0-3.375-3.375h-1.5A1.125 1.125 0 0 1 13.5 7.125v-1.5a3.375 3.375 0 0 0-3.375-3.375H8.25m0 12.75h7.5m-7.5 3H12M10.5 2.25H5.625c-.621 0-1.125.504-1.125 1.125v17.25c0 .621.504 1.125 1.125 1.125h12.75c.621 0 1.125-.504 1.125-1.125V11.25a9 9 0 0 0-9-9Z"
|
|
16
|
-
/>
|
|
17
|
-
</svg>
|
|
18
|
-
);
|
|
19
|
-
};
|