vzcode 2.18.0 → 2.21.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-D6-he0oi.js +476 -0
- package/dist/assets/{index-BvGPtSrr.css → index-fYq6iaqF.css} +1 -1
- package/dist/assets/{worker-y5jhqCTR.js → worker-Cm3I3tnR.js} +57 -57
- package/dist/assets/{worker-ClF0pBYr.js → worker-KiuLM-X4.js} +71 -71
- package/dist/index.html +2 -2
- package/dist/server/aiChatHandler/chatOperations.js +3 -4
- package/dist/server/aiChatHandler/llmStreaming.js +57 -4
- package/dist/server/prettier.js +18 -16
- package/dist/utils/fileDiff.js +25 -1
- package/package.json +31 -31
- package/src/client/CodeEditor/getOrCreateEditor.tsx +263 -256
- package/src/client/VZRight.tsx +4 -0
- package/src/client/VZSidebar/AIChat/ChatInput.tsx +1 -1
- package/src/client/VZSidebar/AIChat/DiffView.scss +37 -1
- package/src/client/VZSidebar/AIChat/DiffView.tsx +55 -16
- package/src/client/featureFlags.ts +7 -0
- package/src/server/aiChatHandler/chatOperations.ts +3 -4
- package/src/server/aiChatHandler/llmStreaming.ts +87 -4
- package/src/server/prettier.ts +30 -31
- package/src/types.ts +5 -0
- package/src/utils/fileDiff.ts +36 -2
- package/dist/assets/index-DuDXdJWC.js +0 -477
|
@@ -67,8 +67,10 @@ import {
|
|
|
67
67
|
} from '@valtown/codemirror-ts';
|
|
68
68
|
import { getFileExtension } from '../utils/fileExtension';
|
|
69
69
|
import { SparklesSVG } from '../Icons/SparklesSVG';
|
|
70
|
+
import { MINIMAL_EXTENSIONS } from '../featureFlags';
|
|
70
71
|
|
|
71
72
|
const DEBUG = false;
|
|
73
|
+
const enableToDoPlugin = false;
|
|
72
74
|
|
|
73
75
|
// Define a StateField to store the file name.
|
|
74
76
|
// This should be defined at the module level if it's to be imported by other modules.
|
|
@@ -253,8 +255,10 @@ export const getOrCreateEditor = async ({
|
|
|
253
255
|
// Create a compartment for rainbow brackets so that it can be enabled/disabled dynamically.
|
|
254
256
|
const rainbowBracketsCompartment = new Compartment();
|
|
255
257
|
|
|
258
|
+
// Create a compartment for language so that it can be changed dynamically.
|
|
259
|
+
const languageCompartment = new Compartment();
|
|
260
|
+
|
|
256
261
|
// The CodeMirror extensions to use.
|
|
257
|
-
// const extensions = [autocompletion(), html(htmlConfig)]
|
|
258
262
|
const extensions = [];
|
|
259
263
|
|
|
260
264
|
// Initialize the fileNameStateField with the actual file name
|
|
@@ -273,26 +277,29 @@ export const getOrCreateEditor = async ({
|
|
|
273
277
|
}),
|
|
274
278
|
);
|
|
275
279
|
|
|
276
|
-
//
|
|
277
|
-
if (
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
280
|
+
// Only add presence extensions if MINIMAL_EXTENSIONS is false
|
|
281
|
+
if (!MINIMAL_EXTENSIONS) {
|
|
282
|
+
// Deals with broadcasting changes in cursor location and selection.
|
|
283
|
+
if (localPresence) {
|
|
284
|
+
extensions.push(
|
|
285
|
+
json1PresenceBroadcast({
|
|
286
|
+
path: textPath,
|
|
287
|
+
localPresence,
|
|
288
|
+
usernameRef,
|
|
289
|
+
}),
|
|
290
|
+
);
|
|
291
|
+
}
|
|
286
292
|
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
293
|
+
// Deals with receiving the broadcast from other clients and displaying them.
|
|
294
|
+
if (docPresence) {
|
|
295
|
+
extensions.push(
|
|
296
|
+
json1PresenceDisplay({
|
|
297
|
+
path: textPath,
|
|
298
|
+
docPresence,
|
|
299
|
+
enableAutoFollowRef,
|
|
300
|
+
}),
|
|
301
|
+
);
|
|
302
|
+
}
|
|
296
303
|
}
|
|
297
304
|
} else {
|
|
298
305
|
// If the ShareDB document is not provided,
|
|
@@ -300,44 +307,7 @@ export const getOrCreateEditor = async ({
|
|
|
300
307
|
extensions.push(EditorView.editable.of(false));
|
|
301
308
|
}
|
|
302
309
|
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
// This is the "basic setup" for CodeMirror,
|
|
306
|
-
// which actually adds a ton on functionality.
|
|
307
|
-
// TODO vet this functionality, and determine how much
|
|
308
|
-
// we want to replace with
|
|
309
|
-
// https://github.com/vizhub-core/vzcode/issues/134
|
|
310
|
-
extensions.push(basicSetup);
|
|
311
|
-
|
|
312
|
-
if (esLintSource) {
|
|
313
|
-
extensions.push(lintGutter()); // Show lint icons in the gutter
|
|
314
|
-
extensions.push(
|
|
315
|
-
linter(esLintSource, {
|
|
316
|
-
// You can configure linter options here, e.g., delay
|
|
317
|
-
delay: 750,
|
|
318
|
-
}),
|
|
319
|
-
);
|
|
320
|
-
}
|
|
321
|
-
|
|
322
|
-
// This supports dynamic changing of the theme.
|
|
323
|
-
extensions.push(
|
|
324
|
-
themeCompartment.of(themeOptionsByLabel[theme].value),
|
|
325
|
-
);
|
|
326
|
-
|
|
327
|
-
// Adds compartment for rainbow brackets with initial toggle state.
|
|
328
|
-
extensions.push(
|
|
329
|
-
rainbowBracketsCompartment.of(
|
|
330
|
-
rainbowBracketsEnabled ? rainbowBrackets() : [],
|
|
331
|
-
),
|
|
332
|
-
);
|
|
333
|
-
|
|
334
|
-
// TODO handle dynamic changing of the file extension.
|
|
335
|
-
// TODO handle dynamic file extensions by making
|
|
336
|
-
// the CodeMirror language extension dynamic
|
|
337
|
-
// using a Compartment.
|
|
338
|
-
const languageCompartment = new Compartment();
|
|
339
|
-
// See https://github.com/vizhub-core/vzcode/issues/55
|
|
340
|
-
|
|
310
|
+
// Add language extension (needed for both minimal and full modes)
|
|
341
311
|
const languageExtension =
|
|
342
312
|
getLanguageExtension(fileExtension);
|
|
343
313
|
if (languageExtension) {
|
|
@@ -345,232 +315,269 @@ export const getOrCreateEditor = async ({
|
|
|
345
315
|
languageCompartment.of(languageExtension),
|
|
346
316
|
);
|
|
347
317
|
} else {
|
|
348
|
-
// Not sure if this case even works.
|
|
349
|
-
// TODO manually test this case by creating a file
|
|
350
|
-
// that has no extension, opening it up,
|
|
351
|
-
// and then adding an extension.
|
|
352
|
-
// console.warn(
|
|
353
|
-
// `No language extension for file extension: ${fileExtension}`,
|
|
354
|
-
// );
|
|
355
|
-
// We still need to push the compartment,
|
|
356
|
-
// otherwise the compartment won't work when
|
|
357
|
-
// a file extension _is_ added later on.
|
|
358
318
|
extensions.push(languageCompartment.of([]));
|
|
359
319
|
}
|
|
360
320
|
|
|
361
|
-
//
|
|
362
|
-
if (
|
|
363
|
-
extensions
|
|
364
|
-
|
|
321
|
+
// If MINIMAL_EXTENSIONS is true, only include the JSON1 OT extension and essential functionality
|
|
322
|
+
if (MINIMAL_EXTENSIONS) {
|
|
323
|
+
// Only the most basic extensions are added
|
|
324
|
+
// The JSON1 OT extension and language extension are already added above
|
|
325
|
+
} else {
|
|
326
|
+
// Full feature set - include all extensions
|
|
327
|
+
extensions.push(colorsInTextPlugin);
|
|
328
|
+
|
|
329
|
+
// This is the "basic setup" for CodeMirror,
|
|
330
|
+
// which actually adds a ton on functionality.
|
|
331
|
+
// TODO vet this functionality, and determine how much
|
|
332
|
+
// we want to replace with
|
|
333
|
+
// https://github.com/vizhub-core/vzcode/issues/134
|
|
334
|
+
extensions.push(basicSetup);
|
|
335
|
+
|
|
336
|
+
if (esLintSource) {
|
|
337
|
+
extensions.push(lintGutter()); // Show lint icons in the gutter
|
|
338
|
+
extensions.push(
|
|
339
|
+
linter(esLintSource, {
|
|
340
|
+
// You can configure linter options here, e.g., delay
|
|
341
|
+
delay: 750,
|
|
342
|
+
}),
|
|
343
|
+
);
|
|
344
|
+
}
|
|
365
345
|
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
// for hot reloading.
|
|
371
|
-
// TODO consider leveraging the new `dragEnd` event handler.
|
|
372
|
-
// and removing the `onInteract` callback, replacing it with
|
|
373
|
-
// `onInteractStart` and `onInteractEnd`.
|
|
374
|
-
// That may be tricky for one-off interactions though, like
|
|
375
|
-
// the boolean checkboxes. The color pickers are also tricky,
|
|
376
|
-
// as they would also need to be able to handle `onInteractEnd`.
|
|
377
|
-
// See https://github.com/replit/codemirror-interact/issues/14
|
|
378
|
-
extensions.push(
|
|
379
|
-
widgets({ onInteract, customInteractRules }),
|
|
380
|
-
);
|
|
346
|
+
// This supports dynamic changing of the theme.
|
|
347
|
+
extensions.push(
|
|
348
|
+
themeCompartment.of(themeOptionsByLabel[theme].value),
|
|
349
|
+
);
|
|
381
350
|
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
// extensions.push(
|
|
389
|
-
// AIAssistCodeMirrorKeyMap({
|
|
390
|
-
// shareDBDoc,
|
|
391
|
-
// fileId,
|
|
392
|
-
// tabList,
|
|
393
|
-
// aiAssistEndpoint,
|
|
394
|
-
// aiAssistOptions,
|
|
395
|
-
// }),
|
|
396
|
-
// );
|
|
397
|
-
|
|
398
|
-
// Add the extension that provides indentation markers.
|
|
399
|
-
extensions.push(
|
|
400
|
-
indentationMarkers({
|
|
401
|
-
// thickness: 2,
|
|
402
|
-
colors: {
|
|
403
|
-
light: '#4d586b',
|
|
404
|
-
dark: '#4d586b',
|
|
405
|
-
activeLight: '#8e949f',
|
|
406
|
-
activeDark: '#8e949f',
|
|
407
|
-
},
|
|
408
|
-
}),
|
|
409
|
-
);
|
|
351
|
+
// Adds compartment for rainbow brackets with initial toggle state.
|
|
352
|
+
extensions.push(
|
|
353
|
+
rainbowBracketsCompartment.of(
|
|
354
|
+
rainbowBracketsEnabled ? rainbowBrackets() : [],
|
|
355
|
+
),
|
|
356
|
+
);
|
|
410
357
|
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
358
|
+
// Enable line wrapping for Markdown files
|
|
359
|
+
if (fileExtension === 'md') {
|
|
360
|
+
extensions.push(EditorView.lineWrapping);
|
|
361
|
+
}
|
|
414
362
|
|
|
363
|
+
// Add interactive widgets.
|
|
364
|
+
// Includes the Alt+drag functionality for numbers.
|
|
365
|
+
// Calls `onInteract` when one of those widgets is interacted with.
|
|
366
|
+
// This can be used to trigger a transition to throttled mode
|
|
367
|
+
// for hot reloading.
|
|
368
|
+
// TODO consider leveraging the new `dragEnd` event handler.
|
|
369
|
+
// and removing the `onInteract` callback, replacing it with
|
|
370
|
+
// `onInteractStart` and `onInteractEnd`.
|
|
371
|
+
// That may be tricky for one-off interactions though, like
|
|
372
|
+
// the boolean checkboxes. The color pickers are also tricky,
|
|
373
|
+
// as they would also need to be able to handle `onInteractEnd`.
|
|
374
|
+
// See https://github.com/replit/codemirror-interact/issues/14
|
|
415
375
|
extensions.push(
|
|
416
|
-
|
|
417
|
-
tsFacetWorker.of({ worker: tsWorker, path: name }),
|
|
418
|
-
tsSyncWorker(),
|
|
419
|
-
tsLinterWorker(),
|
|
420
|
-
autocompletion({
|
|
421
|
-
override: [tsAutocompleteWorker()],
|
|
422
|
-
}),
|
|
423
|
-
tsHoverWorker(),
|
|
424
|
-
],
|
|
376
|
+
widgets({ onInteract, customInteractRules }),
|
|
425
377
|
);
|
|
426
|
-
}
|
|
427
378
|
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
// extensions.push(
|
|
432
|
-
// showMinimap.compute(['doc'], () => ({
|
|
433
|
-
// create: () => ({
|
|
434
|
-
// dom: document.createElement('div'),
|
|
435
|
-
// }),
|
|
436
|
-
// // Without this, performance is terrible.
|
|
437
|
-
// displayText: 'blocks',
|
|
438
|
-
// })),
|
|
439
|
-
// );
|
|
440
|
-
|
|
441
|
-
// VSCode keybindings
|
|
442
|
-
// See https://github.com/replit/codemirror-vscode-keymap#usage
|
|
443
|
-
// extensions.push(keymap.of(vscodeKeymap));
|
|
444
|
-
extensions.push(
|
|
445
|
-
keymap.of(
|
|
446
|
-
vscodeKeymap.map((binding) => {
|
|
447
|
-
// Here we override the Shift+Enter behavior specifically,
|
|
448
|
-
// as that can be used to trigger a manual save/Prettier,
|
|
449
|
-
// and the default behavior from the keymap interferes.
|
|
450
|
-
if (binding.key === 'Enter') {
|
|
451
|
-
delete binding.shift;
|
|
452
|
-
}
|
|
453
|
-
return binding;
|
|
454
|
-
}),
|
|
455
|
-
),
|
|
456
|
-
);
|
|
379
|
+
// TODO fix the bugginess in this one where
|
|
380
|
+
// the highlight persists after the mouse leaves.
|
|
381
|
+
// extensions.push(highlightWidgets);
|
|
457
382
|
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
383
|
+
extensions.push(rotationIndicator);
|
|
384
|
+
|
|
385
|
+
// extensions.push(
|
|
386
|
+
// AIAssistCodeMirrorKeyMap({
|
|
387
|
+
// shareDBDoc,
|
|
388
|
+
// fileId,
|
|
389
|
+
// tabList,
|
|
390
|
+
// aiAssistEndpoint,
|
|
391
|
+
// aiAssistOptions,
|
|
392
|
+
// }),
|
|
393
|
+
// );
|
|
394
|
+
|
|
395
|
+
// Add the extension that provides indentation markers.
|
|
396
|
+
extensions.push(
|
|
397
|
+
indentationMarkers({
|
|
398
|
+
// thickness: 2,
|
|
399
|
+
colors: {
|
|
400
|
+
light: '#4d586b',
|
|
401
|
+
dark: '#4d586b',
|
|
402
|
+
activeLight: '#8e949f',
|
|
403
|
+
activeDark: '#8e949f',
|
|
404
|
+
},
|
|
405
|
+
}),
|
|
463
406
|
);
|
|
464
|
-
if (aiCopilotEndpoint) {
|
|
465
|
-
extensions.push(copilot({ aiCopilotEndpoint }));
|
|
466
|
-
}
|
|
467
407
|
|
|
468
|
-
|
|
408
|
+
if (name.endsWith('ts') || name.endsWith('tsx')) {
|
|
409
|
+
// Initialize worker if needed
|
|
410
|
+
const tsWorker = await initializeWorker();
|
|
469
411
|
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
412
|
+
extensions.push(
|
|
413
|
+
...[
|
|
414
|
+
tsFacetWorker.of({
|
|
415
|
+
worker: tsWorker,
|
|
416
|
+
path: name,
|
|
417
|
+
}),
|
|
418
|
+
tsSyncWorker(),
|
|
419
|
+
tsLinterWorker(),
|
|
420
|
+
autocompletion({
|
|
421
|
+
override: [tsAutocompleteWorker()],
|
|
422
|
+
}),
|
|
423
|
+
tsHoverWorker(),
|
|
424
|
+
],
|
|
425
|
+
);
|
|
426
|
+
}
|
|
477
427
|
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
428
|
+
// Show the minimap
|
|
429
|
+
// See https://github.com/replit/codemirror-minimap#usage
|
|
430
|
+
// This extension has poor performance, so it's disabled for now.
|
|
431
|
+
// extensions.push(
|
|
432
|
+
// showMinimap.compute(['doc'], () => ({
|
|
433
|
+
// create: () => ({
|
|
434
|
+
// dom: document.createElement('div'),
|
|
435
|
+
// }),
|
|
436
|
+
// // Without this, performance is terrible.
|
|
437
|
+
// displayText: 'blocks',
|
|
438
|
+
// })),
|
|
439
|
+
// );
|
|
481
440
|
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
handleSendMessage('Implement the TODO');
|
|
499
|
-
}}
|
|
500
|
-
>
|
|
501
|
-
<SparklesSVG width={14} height={14} />
|
|
502
|
-
</div>,
|
|
503
|
-
);
|
|
504
|
-
return wrap;
|
|
505
|
-
}
|
|
441
|
+
// VSCode keybindings
|
|
442
|
+
// See https://github.com/replit/codemirror-vscode-keymap#usage
|
|
443
|
+
// extensions.push(keymap.of(vscodeKeymap));
|
|
444
|
+
extensions.push(
|
|
445
|
+
keymap.of(
|
|
446
|
+
vscodeKeymap.map((binding) => {
|
|
447
|
+
// Here we override the Shift+Enter behavior specifically,
|
|
448
|
+
// as that can be used to trigger a manual save/Prettier,
|
|
449
|
+
// and the default behavior from the keymap interferes.
|
|
450
|
+
if (binding.key === 'Enter') {
|
|
451
|
+
delete binding.shift;
|
|
452
|
+
}
|
|
453
|
+
return binding;
|
|
454
|
+
}),
|
|
455
|
+
),
|
|
456
|
+
);
|
|
506
457
|
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
458
|
+
// Adds copilot completions
|
|
459
|
+
DEBUG &&
|
|
460
|
+
console.log(
|
|
461
|
+
'[getOrCreateEditor] aiCopilotEndpoint: ',
|
|
462
|
+
aiCopilotEndpoint,
|
|
463
|
+
);
|
|
464
|
+
if (aiCopilotEndpoint) {
|
|
465
|
+
extensions.push(copilot({ aiCopilotEndpoint }));
|
|
510
466
|
}
|
|
511
467
|
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
while (!findToDo.next().done) {
|
|
521
|
-
const { from, to } = findToDo.value;
|
|
522
|
-
const node = tree.resolve(from);
|
|
523
|
-
let inComment = false;
|
|
524
|
-
|
|
525
|
-
// Walk up the parents until we hit the root, looking for a comment node
|
|
526
|
-
for (let cur: any = node; cur; cur = cur.parent) {
|
|
527
|
-
if (
|
|
528
|
-
cur.type.is('Comment') || // grammars that group comments
|
|
529
|
-
cur.type.is('comment') || // generic lowercase group
|
|
530
|
-
/Comment$/.test(cur.type.name) // fallback for e.g. LineComment
|
|
531
|
-
) {
|
|
532
|
-
inComment = true;
|
|
533
|
-
break;
|
|
534
|
-
}
|
|
468
|
+
// const { setIsAIChatOpen } = useContext(VZCodeContext);
|
|
469
|
+
|
|
470
|
+
// Widget appears after instances of "todo" in code editor, allowing AI to implement todo tasks when clicked
|
|
471
|
+
function createToDoPlugin() {
|
|
472
|
+
// setIsAIChatOpen: (open: boolean) => void,
|
|
473
|
+
class ToDoWidget extends WidgetType {
|
|
474
|
+
constructor() {
|
|
475
|
+
super();
|
|
535
476
|
}
|
|
536
|
-
if (!inComment) continue; // skip non-comment TODOs
|
|
537
477
|
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
}).range(to);
|
|
542
|
-
widgets.push(deco);
|
|
543
|
-
}
|
|
544
|
-
return Decoration.set(widgets);
|
|
545
|
-
}
|
|
478
|
+
eq(_other: ToDoWidget) {
|
|
479
|
+
return false;
|
|
480
|
+
}
|
|
546
481
|
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
482
|
+
toDOM() {
|
|
483
|
+
const wrap = document.createElement('i');
|
|
484
|
+
wrap.style.display = 'inline-flex'; // prevent block expansion
|
|
485
|
+
wrap.style.alignItems = 'center';
|
|
486
|
+
wrap.style.justifyContent = 'center';
|
|
487
|
+
wrap.className = 'icon-button icon-button-dark';
|
|
488
|
+
const reactContainer =
|
|
489
|
+
document.createElement('div');
|
|
490
|
+
wrap.appendChild(reactContainer);
|
|
491
|
+
|
|
492
|
+
const root = createRoot(reactContainer);
|
|
493
|
+
root.render(
|
|
494
|
+
<div
|
|
495
|
+
onClick={() => {
|
|
496
|
+
setIsAIChatOpen(true);
|
|
497
|
+
// setAIChatMessage('Implement the TODO');
|
|
498
|
+
handleSendMessage('Implement the TODO');
|
|
499
|
+
}}
|
|
500
|
+
>
|
|
501
|
+
<SparklesSVG width={14} height={14} />
|
|
502
|
+
</div>,
|
|
503
|
+
);
|
|
504
|
+
return wrap;
|
|
505
|
+
}
|
|
550
506
|
|
|
551
|
-
|
|
552
|
-
|
|
507
|
+
ignoreEvent() {
|
|
508
|
+
return false;
|
|
553
509
|
}
|
|
510
|
+
}
|
|
511
|
+
|
|
512
|
+
function toDoWidgets(editor: EditorView) {
|
|
513
|
+
const { state } = editor;
|
|
514
|
+
const tree = syntaxTree(state);
|
|
515
|
+
const findToDo = new RegExpCursor(
|
|
516
|
+
state.doc,
|
|
517
|
+
'todo',
|
|
518
|
+
{
|
|
519
|
+
ignoreCase: true,
|
|
520
|
+
},
|
|
521
|
+
);
|
|
522
|
+
const widgets: Range<Decoration>[] = [];
|
|
523
|
+
|
|
524
|
+
while (!findToDo.next().done) {
|
|
525
|
+
const { from, to } = findToDo.value;
|
|
526
|
+
const node = tree.resolve(from);
|
|
527
|
+
let inComment = false;
|
|
528
|
+
|
|
529
|
+
// Walk up the parents until we hit the root, looking for a comment node
|
|
530
|
+
for (let cur: any = node; cur; cur = cur.parent) {
|
|
531
|
+
if (
|
|
532
|
+
cur.type.is('Comment') || // grammars that group comments
|
|
533
|
+
cur.type.is('comment') || // generic lowercase group
|
|
534
|
+
/Comment$/.test(cur.type.name) // fallback for e.g. LineComment
|
|
535
|
+
) {
|
|
536
|
+
inComment = true;
|
|
537
|
+
break;
|
|
538
|
+
}
|
|
539
|
+
}
|
|
540
|
+
if (!inComment) continue; // skip non-comment TODOs
|
|
554
541
|
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
syntaxTree(update.state)
|
|
561
|
-
)
|
|
562
|
-
this.decorations = toDoWidgets(update.view);
|
|
542
|
+
const deco = Decoration.widget({
|
|
543
|
+
widget: new ToDoWidget(),
|
|
544
|
+
side: 1,
|
|
545
|
+
}).range(to);
|
|
546
|
+
widgets.push(deco);
|
|
563
547
|
}
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
decorations: (v) => v.decorations,
|
|
567
|
-
},
|
|
568
|
-
);
|
|
548
|
+
return Decoration.set(widgets);
|
|
549
|
+
}
|
|
569
550
|
|
|
570
|
-
|
|
571
|
-
|
|
551
|
+
const todoPlugin = ViewPlugin.fromClass(
|
|
552
|
+
class {
|
|
553
|
+
decorations: DecorationSet;
|
|
554
|
+
|
|
555
|
+
constructor(view: EditorView) {
|
|
556
|
+
this.decorations = toDoWidgets(view);
|
|
557
|
+
}
|
|
572
558
|
|
|
573
|
-
|
|
559
|
+
update(update: ViewUpdate) {
|
|
560
|
+
if (
|
|
561
|
+
update.docChanged ||
|
|
562
|
+
update.viewportChanged ||
|
|
563
|
+
syntaxTree(update.startState) !==
|
|
564
|
+
syntaxTree(update.state)
|
|
565
|
+
)
|
|
566
|
+
this.decorations = toDoWidgets(update.view);
|
|
567
|
+
}
|
|
568
|
+
},
|
|
569
|
+
{
|
|
570
|
+
decorations: (v) => v.decorations,
|
|
571
|
+
},
|
|
572
|
+
);
|
|
573
|
+
|
|
574
|
+
return todoPlugin;
|
|
575
|
+
}
|
|
576
|
+
|
|
577
|
+
if (enableToDoPlugin) {
|
|
578
|
+
extensions.push(createToDoPlugin());
|
|
579
|
+
}
|
|
580
|
+
}
|
|
574
581
|
|
|
575
582
|
const editor = new EditorView({
|
|
576
583
|
state: EditorState.create({
|
package/src/client/VZRight.tsx
CHANGED
|
@@ -92,6 +92,10 @@ export const VZRight = () => {
|
|
|
92
92
|
enableHotReloading: isInteracting,
|
|
93
93
|
enableSourcemap: true,
|
|
94
94
|
vizId: 'example-viz',
|
|
95
|
+
|
|
96
|
+
// Don't clear the console here in VZCode, since
|
|
97
|
+
// we often want to see debug logs across multiple runs.
|
|
98
|
+
clearConsole: false,
|
|
95
99
|
});
|
|
96
100
|
isFirstRunRef.current = false;
|
|
97
101
|
}
|
|
@@ -11,7 +11,7 @@
|
|
|
11
11
|
display: flex;
|
|
12
12
|
align-items: center;
|
|
13
13
|
gap: 8px;
|
|
14
|
-
font-size:
|
|
14
|
+
font-size: 14px;
|
|
15
15
|
color: var(--bs-secondary-color);
|
|
16
16
|
|
|
17
17
|
.files-changed {
|
|
@@ -134,4 +134,40 @@
|
|
|
134
134
|
background-color: var(--d2h-bg-color);
|
|
135
135
|
}
|
|
136
136
|
}
|
|
137
|
+
|
|
138
|
+
.deleted-file {
|
|
139
|
+
margin-bottom: 8px;
|
|
140
|
+
border: 1px solid #30363d;
|
|
141
|
+
border-radius: 6px;
|
|
142
|
+
background-color: rgb(41, 44, 52);
|
|
143
|
+
overflow: hidden;
|
|
144
|
+
|
|
145
|
+
.deleted-file-header {
|
|
146
|
+
display: flex;
|
|
147
|
+
justify-content: space-between;
|
|
148
|
+
align-items: center;
|
|
149
|
+
padding: 12px 16px;
|
|
150
|
+
background-color: #161b22;
|
|
151
|
+
border-bottom: 1px solid #30363d;
|
|
152
|
+
|
|
153
|
+
.deleted-file-name {
|
|
154
|
+
color: #e6edf3;
|
|
155
|
+
font-weight: 600;
|
|
156
|
+
font-family:
|
|
157
|
+
'SFMono-Regular', Consolas, 'Liberation Mono',
|
|
158
|
+
Menlo, monospace;
|
|
159
|
+
font-size: 14px;
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
.deleted-file-status {
|
|
163
|
+
color: #f85149;
|
|
164
|
+
font-weight: 600;
|
|
165
|
+
font-size: 14px;
|
|
166
|
+
background-color: rgba(248, 81, 73, 0.1);
|
|
167
|
+
padding: 4px 8px;
|
|
168
|
+
border-radius: 4px;
|
|
169
|
+
border: 1px solid rgba(248, 81, 73, 0.4);
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
}
|
|
137
173
|
}
|