vzcode 0.17.0 → 0.19.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 (38) hide show
  1. package/README.md +47 -39
  2. package/dist/assets/index-0053b846.css +1 -0
  3. package/dist/assets/index-34134182.js +118 -0
  4. package/dist/index.html +15 -5
  5. package/package.json +4 -4
  6. package/src/client/App.tsx +92 -52
  7. package/src/client/CodeEditor/getOrCreateEditor.ts +33 -9
  8. package/src/client/CodeEditor/index.tsx +15 -11
  9. package/src/client/CodeEditor/json1PresenceBroadcast.js +10 -3
  10. package/src/client/CodeEditor/json1PresenceDisplay.js +7 -2
  11. package/src/client/CodeEditor/widgets.ts +5 -1
  12. package/src/client/Resizer/index.tsx +96 -0
  13. package/src/client/Resizer/styles.scss +29 -0
  14. package/src/client/Settings.tsx +29 -21
  15. package/src/client/Sidebar/DirectoryArrowSVG.jsx +4 -1
  16. package/src/client/Sidebar/DirectoryListing.tsx +17 -5
  17. package/src/client/Sidebar/FileListing.tsx +4 -1
  18. package/src/client/Sidebar/Listing.tsx +9 -2
  19. package/src/client/Sidebar/index.tsx +30 -8
  20. package/src/client/Sidebar/styles.scss +0 -1
  21. package/src/client/SplitPaneResizeContext.tsx +77 -0
  22. package/src/client/TabList/index.tsx +7 -2
  23. package/src/client/diff.js +7 -1
  24. package/src/client/featureFlags.js +2 -1
  25. package/src/client/sortFileTree.ts +3 -1
  26. package/src/client/style.scss +18 -12
  27. package/src/client/themes.ts +10 -8
  28. package/src/client/useDynamicTheme.ts +5 -2
  29. package/src/client/useOpenDirectories.ts +11 -8
  30. package/src/client/usePrettier/index.ts +76 -57
  31. package/src/client/usePrettier/worker.ts +4 -1
  32. package/src/client/useTabsState.ts +10 -3
  33. package/src/randomId.js +14 -1
  34. package/src/server/computeInitialDocument.js +18 -5
  35. package/src/server/index.js +7 -2
  36. package/src/types.ts +11 -4
  37. package/dist/assets/index-ab3ae13e.js +0 -115
  38. package/dist/assets/index-ccd52a89.css +0 -1
@@ -1,5 +1,9 @@
1
1
  import { JSONOp } from 'ot-json1';
2
- import { FileId, ShareDBDoc, VZCodeContent } from '../../types';
2
+ import {
3
+ FileId,
4
+ ShareDBDoc,
5
+ VZCodeContent,
6
+ } from '../../types';
3
7
  import { useEffect, useRef } from 'react';
4
8
 
5
9
  // The time in milliseconds by which auto-saving is debounced.
@@ -18,7 +22,9 @@ const extension = (fileName: string) => {
18
22
 
19
23
  export const usePrettier = (
20
24
  shareDBDoc: ShareDBDoc<VZCodeContent> | null,
21
- submitOperation: (next: (content: VZCodeContent) => VZCodeContent) => void,
25
+ submitOperation: (
26
+ next: (content: VZCodeContent) => VZCodeContent,
27
+ ) => void,
22
28
  prettierWorker: Worker,
23
29
  ) => {
24
30
  // The set of files that have been modified
@@ -38,7 +44,8 @@ export const usePrettier = (
38
44
  // Get the message that comes back from the worker.
39
45
  // This is the prettified text for a specific file.
40
46
  const handleMessage = (event) => {
41
- const { fileId, error, fileTextPrettified } = event.data;
47
+ const { fileId, error, fileTextPrettified } =
48
+ event.data;
42
49
  if (error) {
43
50
  console.log(error);
44
51
  return;
@@ -59,7 +66,10 @@ export const usePrettier = (
59
66
  };
60
67
 
61
68
  // Listen for messages from the worker.
62
- prettierWorker.addEventListener('message', handleMessage);
69
+ prettierWorker.addEventListener(
70
+ 'message',
71
+ handleMessage,
72
+ );
63
73
 
64
74
  const runPrettier = async () => {
65
75
  // Get the content of the document
@@ -95,64 +105,73 @@ export const usePrettier = (
95
105
  let debounceTimeout;
96
106
  function debouncePrettier() {
97
107
  clearTimeout(debounceTimeout);
98
- debounceTimeout = setTimeout(runPrettier, autoPrettierDebounceTimeMS);
108
+ debounceTimeout = setTimeout(
109
+ runPrettier,
110
+ autoPrettierDebounceTimeMS,
111
+ );
99
112
  }
100
113
 
101
114
  // Listen for changes
102
- shareDBDoc.on('op batch', (op: JSONOp, isLocal: boolean) => {
103
- // Only act on changes coming from the client
104
- if (isLocal) {
105
- // If the op is coming from Prettier itself,
106
- // then do nothing.
107
- if (isApplyingOpRef.current) {
108
- // console.log('ignoring op from Prettier');
109
- return;
115
+ shareDBDoc.on(
116
+ 'op batch',
117
+ (op: JSONOp, isLocal: boolean) => {
118
+ // Only act on changes coming from the client
119
+ if (isLocal) {
120
+ // If the op is coming from Prettier itself,
121
+ // then do nothing.
122
+ if (isApplyingOpRef.current) {
123
+ // console.log('ignoring op from Prettier');
124
+ return;
125
+ }
126
+
127
+ // Example op that we want to act on:
128
+ // op [
129
+ // "files",
130
+ // "2514857669",
131
+ // "text",
132
+ // {
133
+ // "es": [
134
+ // 18,
135
+ // "d"
136
+ // ]
137
+ // }
138
+ // ]
139
+
140
+ // Check if the path of this op is the text content of a file
141
+ if (
142
+ op &&
143
+ op.length === 4 &&
144
+ op[0] === 'files' &&
145
+ typeof op[1] === 'string' &&
146
+ op[2] === 'text'
147
+ ) {
148
+ // Get the file id
149
+ const fileId: FileId = op[1];
150
+
151
+ // Add the file id to the set of dirty files
152
+ dirtyFiles.add(fileId);
153
+
154
+ // Debounce running Prettier
155
+ debouncePrettier();
156
+
157
+ // console.log('Op is for file', fileId);
158
+ }
159
+ } else {
160
+ // console.log('ignoring op from remote', op, isLocal);
110
161
  }
111
162
 
112
- // Example op that we want to act on:
113
- // op [
114
- // "files",
115
- // "2514857669",
116
- // "text",
117
- // {
118
- // "es": [
119
- // 18,
120
- // "d"
121
- // ]
122
- // }
123
- // ]
124
-
125
- // Check if the path of this op is the text content of a file
126
- if (
127
- op &&
128
- op.length === 4 &&
129
- op[0] === 'files' &&
130
- typeof op[1] === 'string' &&
131
- op[2] === 'text'
132
- ) {
133
- // Get the file id
134
- const fileId: FileId = op[1];
135
-
136
- // Add the file id to the set of dirty files
137
- dirtyFiles.add(fileId);
138
-
139
- // Debounce running Prettier
140
- debouncePrettier();
141
-
142
- // console.log('Op is for file', fileId);
143
- }
144
- } else {
145
- // console.log('ignoring op from remote', op, isLocal);
146
- }
163
+ // In the event that the component unmounts,
164
+ return () => {
165
+ // Remove the event listener
166
+ prettierWorker.removeEventListener(
167
+ 'message',
168
+ handleMessage,
169
+ );
147
170
 
148
- // In the event that the component unmounts,
149
- return () => {
150
- // Remove the event listener
151
- prettierWorker.removeEventListener('message', handleMessage);
152
-
153
- // Clear the timeout
154
- clearTimeout(debounceTimeout);
155
- };
156
- });
171
+ // Clear the timeout
172
+ clearTimeout(debounceTimeout);
173
+ };
174
+ },
175
+ );
157
176
  }, [shareDBDoc]);
158
177
  };
@@ -78,7 +78,10 @@ onmessage = async ({
78
78
  }
79
79
 
80
80
  try {
81
- const fileTextPrettified = await format(fileText, { parser, plugins });
81
+ const fileTextPrettified = await format(fileText, {
82
+ parser,
83
+ plugins,
84
+ });
82
85
 
83
86
  postMessage({
84
87
  fileId,
@@ -11,20 +11,27 @@ export const useTabsState = (
11
11
  // Called when a tab is closed.
12
12
  const closeTab = useCallback(
13
13
  (fileIdToRemove: FileId) => {
14
- const i = tabList.findIndex((fileId) => fileId === fileIdToRemove);
14
+ const i = tabList.findIndex(
15
+ (fileId) => fileId === fileIdToRemove,
16
+ );
15
17
 
16
18
  // Support calling `closeTab` on a fileId that is not open,
17
19
  // such as when a file is deleted..
18
20
  if (i !== -1) {
19
21
  // Remove the tab from the tab list.
20
- const newTabList = [...tabList.slice(0, i), ...tabList.slice(i + 1)];
22
+ const newTabList = [
23
+ ...tabList.slice(0, i),
24
+ ...tabList.slice(i + 1),
25
+ ];
21
26
  setTabList(newTabList);
22
27
 
23
28
  // If we are closing the active file,
24
29
  if (activeFileId === fileIdToRemove) {
25
30
  // set the new active file to the next tab over,
26
31
  if (newTabList.length > 0) {
27
- setActiveFileId(i === 0 ? newTabList[i] : newTabList[i - 1]);
32
+ setActiveFileId(
33
+ i === 0 ? newTabList[i] : newTabList[i - 1],
34
+ );
28
35
  } else {
29
36
  // or clear out the active file
30
37
  // if we've closed the last tab.
package/src/randomId.js CHANGED
@@ -1,2 +1,15 @@
1
1
  // Generate a random ID string consisting of digits.
2
- export const randomId = () => Math.floor(Math.random() * 10000000000) + '';
2
+ const numDigits = 8;
3
+ export const randomId = () => {
4
+ let randomString = '';
5
+ for (let i = 0; i < numDigits; i++) {
6
+ randomString += Math.floor(Math.random() * 10);
7
+ }
8
+ return randomString;
9
+ };
10
+
11
+ // const probabilityOfCollision =
12
+ // 1 - Math.pow(1 - 1 / Math.pow(10, numDigits), numRuns);
13
+ // Using this formula, the probability of generating the same ID twice
14
+ // when using 8 digits and running the code 1000 times is approximately
15
+ // 0.0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001
@@ -1,7 +1,10 @@
1
1
  import fs from 'fs';
2
2
  import path from 'path';
3
3
  import { randomId } from '../randomId.js';
4
- import { enableDirectories, debugDirectories } from './featureFlags.js';
4
+ import {
5
+ enableDirectories,
6
+ debugDirectories,
7
+ } from './featureFlags.js';
5
8
 
6
9
  const isDirectory = (file) => file.endsWith('/');
7
10
 
@@ -36,10 +39,17 @@ export const computeInitialDocument = ({ fullPath }) => {
36
39
 
37
40
  while (unsearchedDirectories.length !== 0) {
38
41
  const currentDirectory = unsearchedDirectories.pop();
39
- const currentDirectoryPath = path.join(fullPath, currentDirectory);
42
+ const currentDirectoryPath = path.join(
43
+ fullPath,
44
+ currentDirectory,
45
+ );
40
46
  const newFiles = fs
41
- .readdirSync(currentDirectoryPath, { withFileTypes: true })
42
- .filter((dirent) => (enableDirectories ? true : dirent.isFile()))
47
+ .readdirSync(currentDirectoryPath, {
48
+ withFileTypes: true,
49
+ })
50
+ .filter((dirent) =>
51
+ enableDirectories ? true : dirent.isFile(),
52
+ )
43
53
 
44
54
  // Add a trailing slash for directories
45
55
  .map((dirent) => {
@@ -64,7 +74,10 @@ export const computeInitialDocument = ({ fullPath }) => {
64
74
  initialDocument.files[id] = {
65
75
  text: isDirectory(file)
66
76
  ? null
67
- : fs.readFileSync(path.join(fullPath, file), 'utf-8'),
77
+ : fs.readFileSync(
78
+ path.join(fullPath, file),
79
+ 'utf-8',
80
+ ),
68
81
  name: file,
69
82
  };
70
83
  });
@@ -163,7 +163,10 @@ function throttleSave() {
163
163
  let debounceTimeout;
164
164
  function debounceSave() {
165
165
  clearTimeout(debounceTimeout);
166
- debounceTimeout = setTimeout(save, autoSaveDebounceTimeMS);
166
+ debounceTimeout = setTimeout(
167
+ save,
168
+ autoSaveDebounceTimeMS,
169
+ );
167
170
  }
168
171
 
169
172
  // Subscribe to listen for modifications
@@ -186,7 +189,9 @@ server.listen(port, async () => {
186
189
  open(url);
187
190
  })();
188
191
  } else {
189
- console.log(`Editor is live at http://localhost:${port}`);
192
+ console.log(
193
+ `Editor is live at http://localhost:${port}`,
194
+ );
190
195
  open(`http://localhost:${port}`);
191
196
  }
192
197
  });
package/src/types.ts CHANGED
@@ -67,9 +67,16 @@ export type ShareDBDoc<T> = {
67
67
  data: T;
68
68
  ingestSnapshot: (snapshot: any, callback) => void;
69
69
  subscribe: (callback) => void;
70
- on: (event: string, callback: (op: JSONOp, source: boolean) => void) => void;
70
+ on: (
71
+ event: string,
72
+ callback: (op: JSONOp, source: boolean) => void,
73
+ ) => void;
71
74
  off: (event: string, callback: () => void) => void;
72
- submitOp: (op: JSONOp, options?: any, callback?: () => void) => void;
75
+ submitOp: (
76
+ op: JSONOp,
77
+ options?: any,
78
+ callback?: () => void,
79
+ ) => void;
73
80
  };
74
81
 
75
82
  // The ShareDB document type for VZCode.
@@ -82,7 +89,7 @@ export type VZCodeContent = {
82
89
  // * `true` when the user is interacting
83
90
  // via interactive code widgets (e.g. Alt+drag)
84
91
  // * Hot reloading is throttled when this is `true`.
85
- // * `false` when they are not (e.g. normal typing)
92
+ // * `false` or `undefined` when they are not (e.g. normal typing)
86
93
  // * Hot reloading is debounced when this is `false`.
87
- isInteracting: boolean;
94
+ isInteracting?: boolean;
88
95
  };