@nocturnium/svelte-ide 1.0.0 → 1.0.1

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 (95) hide show
  1. package/README.md +43 -47
  2. package/dist/components/agents/AgentActivityPanel.svelte +3 -1
  3. package/dist/components/agents/AgentAvatar.svelte +127 -35
  4. package/dist/components/agents/AgentCursor.svelte +15 -5
  5. package/dist/components/agents/AgentPresenceBar.svelte +7 -2
  6. package/dist/components/ai/AIConversationList.svelte +39 -34
  7. package/dist/components/ai/AIInlineEdit.svelte +1 -3
  8. package/dist/components/ai/AIMessage.svelte +5 -5
  9. package/dist/components/ai/AIMessageActions.svelte +18 -3
  10. package/dist/components/ai/AIMessageContent.svelte +22 -20
  11. package/dist/components/ai/AIPanel.svelte +17 -9
  12. package/dist/components/ai/AISuggestionWidget.svelte +1 -3
  13. package/dist/components/ai/AIToolCallDisplay.svelte +10 -14
  14. package/dist/components/core/Badge.svelte +9 -1
  15. package/dist/components/core/ConnectionStatus.svelte +73 -68
  16. package/dist/components/core/ErrorBoundary.svelte +56 -56
  17. package/dist/components/core/ErrorBoundary.svelte.d.ts +5 -5
  18. package/dist/components/core/Icon.svelte +22 -11
  19. package/dist/components/core/ResizeHandle.svelte +1 -1
  20. package/dist/components/core/Tooltip.svelte +1 -7
  21. package/dist/components/editor/AIFocusLayer.svelte +15 -7
  22. package/dist/components/editor/Breadcrumbs.svelte +18 -6
  23. package/dist/components/editor/BreakpointLayer.svelte +51 -60
  24. package/dist/components/editor/CognitiveLoadMeter.svelte +4 -2
  25. package/dist/components/editor/CollaborativeEditor.svelte +1 -5
  26. package/dist/components/editor/CommandPalette.svelte +1 -4
  27. package/dist/components/editor/ComplexityLayer.svelte +8 -6
  28. package/dist/components/editor/ConflictZoneLayer.svelte +2 -8
  29. package/dist/components/editor/ContextLens.svelte +1 -4
  30. package/dist/components/editor/CustomEditor.svelte +85 -41
  31. package/dist/components/editor/DebugConsole.svelte +8 -17
  32. package/dist/components/editor/EchoCursorLayer.svelte +3 -1
  33. package/dist/components/editor/EditorGutter.svelte +8 -2
  34. package/dist/components/editor/EditorLines.svelte +6 -3
  35. package/dist/components/editor/EditorPane.svelte +1 -6
  36. package/dist/components/editor/EditorSelections.svelte +29 -11
  37. package/dist/components/editor/FileExplorer.svelte +26 -4
  38. package/dist/components/editor/FileIcon.svelte +3 -1
  39. package/dist/components/editor/FindReplace.svelte +16 -4
  40. package/dist/components/editor/GhostBracketLayer.svelte +2 -2
  41. package/dist/components/editor/GitBlameLayer.svelte +2 -1
  42. package/dist/components/editor/InlineDiagnosticsLayer.svelte +4 -13
  43. package/dist/components/editor/InlineDiffLayer.svelte +18 -9
  44. package/dist/components/editor/Minimap.svelte +16 -9
  45. package/dist/components/editor/PluginPreviewSandbox.svelte +3 -2
  46. package/dist/components/editor/ProblemsPanel.svelte +11 -35
  47. package/dist/components/editor/QuickActionsMenu.svelte +5 -14
  48. package/dist/components/editor/SnippetPalette.svelte +11 -12
  49. package/dist/components/editor/StructureMap.svelte +2 -1
  50. package/dist/components/editor/SymbolOutline.svelte +14 -19
  51. package/dist/components/editor/TimelineScrubber.svelte +7 -6
  52. package/dist/components/editor/core/complexity-analyzer.js +42 -12
  53. package/dist/components/editor/core/conflict-predictor.js +2 -4
  54. package/dist/components/editor/core/folding.d.ts +9 -0
  55. package/dist/components/editor/core/folding.js +40 -5
  56. package/dist/components/editor/core/multi-cursor.js +4 -8
  57. package/dist/components/editor/core/navigation.js +2 -6
  58. package/dist/components/editor/core/quick-actions.js +22 -17
  59. package/dist/components/editor/core/search.js +2 -6
  60. package/dist/components/editor/core/semantic-analyzer.js +1 -3
  61. package/dist/components/editor/core/snippet-manager.js +4 -3
  62. package/dist/components/editor/core/state.js +2 -2
  63. package/dist/components/editor/core/timeline.js +1 -3
  64. package/dist/components/editor/editor-input.js +9 -6
  65. package/dist/components/editor/editor-multicursor.js +2 -2
  66. package/dist/components/editor/tokenizer/languages/css.js +146 -24
  67. package/dist/components/editor/tokenizer/languages/go.js +76 -13
  68. package/dist/components/editor/tokenizer/languages/javascript.js +210 -29
  69. package/dist/components/editor/tokenizer/languages/python.js +116 -19
  70. package/dist/components/editor/tokenizer/languages/svelte.js +20 -7
  71. package/dist/components/layout/IDELayout.svelte +6 -2
  72. package/dist/components/layout/StatusBar.svelte +32 -20
  73. package/dist/components/lsp/AutocompleteWidget.svelte +19 -19
  74. package/dist/components/lsp/DiagnosticMarker.svelte +61 -52
  75. package/dist/components/lsp/DiagnosticsPanel.svelte +45 -27
  76. package/dist/components/lsp/HoverTooltip.svelte +56 -61
  77. package/dist/components/lsp/LSPEditor.svelte +7 -18
  78. package/dist/components/lsp/SignatureHelpWidget.svelte +12 -9
  79. package/dist/components/plugins/PluginCard.svelte +3 -13
  80. package/dist/components/plugins/PluginProposalForm.svelte +19 -31
  81. package/dist/components/vfs/LockConflictDialog.svelte +112 -45
  82. package/dist/components/vfs/LockIndicator.svelte +0 -1
  83. package/dist/components/vfs/LockOverlay.svelte +53 -53
  84. package/dist/components/vfs/LockOverlay.svelte.d.ts +5 -5
  85. package/dist/components/vfs/VersionConflictDialog.svelte +107 -77
  86. package/dist/services/error-handling.js +1 -7
  87. package/dist/services/mock-ai.js +9 -7
  88. package/dist/stores/agents.svelte.js +50 -10
  89. package/dist/stores/ai.svelte.js +66 -18
  90. package/dist/stores/collaboration.svelte.js +70 -14
  91. package/dist/stores/editor.svelte.js +50 -10
  92. package/dist/stores/plugin.svelte.js +60 -12
  93. package/dist/stores/vfs.svelte.js +77 -19
  94. package/dist/styles/theme.css +16 -7
  95. package/package.json +186 -1
@@ -4,29 +4,126 @@
4
4
  import { createToken } from '../base';
5
5
  // Python keywords
6
6
  const keywords = new Set([
7
- 'and', 'as', 'assert', 'async', 'await', 'break', 'class', 'continue',
8
- 'def', 'del', 'elif', 'else', 'except', 'finally', 'for', 'from',
9
- 'global', 'if', 'import', 'in', 'is', 'lambda', 'nonlocal', 'not',
10
- 'or', 'pass', 'raise', 'return', 'try', 'while', 'with', 'yield'
7
+ 'and',
8
+ 'as',
9
+ 'assert',
10
+ 'async',
11
+ 'await',
12
+ 'break',
13
+ 'class',
14
+ 'continue',
15
+ 'def',
16
+ 'del',
17
+ 'elif',
18
+ 'else',
19
+ 'except',
20
+ 'finally',
21
+ 'for',
22
+ 'from',
23
+ 'global',
24
+ 'if',
25
+ 'import',
26
+ 'in',
27
+ 'is',
28
+ 'lambda',
29
+ 'nonlocal',
30
+ 'not',
31
+ 'or',
32
+ 'pass',
33
+ 'raise',
34
+ 'return',
35
+ 'try',
36
+ 'while',
37
+ 'with',
38
+ 'yield'
11
39
  ]);
12
40
  const controlKeywords = new Set([
13
- 'if', 'elif', 'else', 'for', 'while', 'try', 'except', 'finally',
14
- 'with', 'break', 'continue', 'return', 'raise', 'yield', 'await'
15
- ]);
16
- const builtins = new Set([
17
- 'True', 'False', 'None', 'self', 'cls'
41
+ 'if',
42
+ 'elif',
43
+ 'else',
44
+ 'for',
45
+ 'while',
46
+ 'try',
47
+ 'except',
48
+ 'finally',
49
+ 'with',
50
+ 'break',
51
+ 'continue',
52
+ 'return',
53
+ 'raise',
54
+ 'yield',
55
+ 'await'
18
56
  ]);
57
+ const builtins = new Set(['True', 'False', 'None', 'self', 'cls']);
19
58
  const builtinFunctions = new Set([
20
- 'abs', 'all', 'any', 'ascii', 'bin', 'bool', 'bytearray', 'bytes',
21
- 'callable', 'chr', 'classmethod', 'compile', 'complex', 'delattr',
22
- 'dict', 'dir', 'divmod', 'enumerate', 'eval', 'exec', 'filter',
23
- 'float', 'format', 'frozenset', 'getattr', 'globals', 'hasattr',
24
- 'hash', 'help', 'hex', 'id', 'input', 'int', 'isinstance', 'issubclass',
25
- 'iter', 'len', 'list', 'locals', 'map', 'max', 'memoryview', 'min',
26
- 'next', 'object', 'oct', 'open', 'ord', 'pow', 'print', 'property',
27
- 'range', 'repr', 'reversed', 'round', 'set', 'setattr', 'slice',
28
- 'sorted', 'staticmethod', 'str', 'sum', 'super', 'tuple', 'type',
29
- 'vars', 'zip', '__import__'
59
+ 'abs',
60
+ 'all',
61
+ 'any',
62
+ 'ascii',
63
+ 'bin',
64
+ 'bool',
65
+ 'bytearray',
66
+ 'bytes',
67
+ 'callable',
68
+ 'chr',
69
+ 'classmethod',
70
+ 'compile',
71
+ 'complex',
72
+ 'delattr',
73
+ 'dict',
74
+ 'dir',
75
+ 'divmod',
76
+ 'enumerate',
77
+ 'eval',
78
+ 'exec',
79
+ 'filter',
80
+ 'float',
81
+ 'format',
82
+ 'frozenset',
83
+ 'getattr',
84
+ 'globals',
85
+ 'hasattr',
86
+ 'hash',
87
+ 'help',
88
+ 'hex',
89
+ 'id',
90
+ 'input',
91
+ 'int',
92
+ 'isinstance',
93
+ 'issubclass',
94
+ 'iter',
95
+ 'len',
96
+ 'list',
97
+ 'locals',
98
+ 'map',
99
+ 'max',
100
+ 'memoryview',
101
+ 'min',
102
+ 'next',
103
+ 'object',
104
+ 'oct',
105
+ 'open',
106
+ 'ord',
107
+ 'pow',
108
+ 'print',
109
+ 'property',
110
+ 'range',
111
+ 'repr',
112
+ 'reversed',
113
+ 'round',
114
+ 'set',
115
+ 'setattr',
116
+ 'slice',
117
+ 'sorted',
118
+ 'staticmethod',
119
+ 'str',
120
+ 'sum',
121
+ 'super',
122
+ 'tuple',
123
+ 'type',
124
+ 'vars',
125
+ 'zip',
126
+ '__import__'
30
127
  ]);
31
128
  export class PythonTokenizer {
32
129
  language = 'python';
@@ -27,13 +27,26 @@ function reindexTokens(tokens) {
27
27
  * Svelte keywords and directives
28
28
  */
29
29
  const SVELTE_BLOCK_KEYWORDS = new Set([
30
- 'if', 'else', 'each', 'await', 'then', 'catch', 'key', 'snippet'
31
- ]);
32
- const SVELTE_TAG_KEYWORDS = new Set([
33
- 'html', 'debug', 'const', 'render'
30
+ 'if',
31
+ 'else',
32
+ 'each',
33
+ 'await',
34
+ 'then',
35
+ 'catch',
36
+ 'key',
37
+ 'snippet'
34
38
  ]);
39
+ const SVELTE_TAG_KEYWORDS = new Set(['html', 'debug', 'const', 'render']);
35
40
  const SVELTE_ATTRIBUTE_PREFIXES = [
36
- 'bind:', 'on:', 'use:', 'transition:', 'in:', 'out:', 'animate:', 'let:', 'class:'
41
+ 'bind:',
42
+ 'on:',
43
+ 'use:',
44
+ 'transition:',
45
+ 'in:',
46
+ 'out:',
47
+ 'animate:',
48
+ 'let:',
49
+ 'class:'
37
50
  ];
38
51
  /**
39
52
  * Svelte tokenizer
@@ -266,10 +279,10 @@ export class SvelteTokenizer {
266
279
  const attrMatch = tag.substring(pos).match(/^([\w:-]+)(?:=)?/);
267
280
  if (attrMatch) {
268
281
  const attrName = attrMatch[1];
269
- const isSvelteAttr = SVELTE_ATTRIBUTE_PREFIXES.some(prefix => attrName.startsWith(prefix));
282
+ const isSvelteAttr = SVELTE_ATTRIBUTE_PREFIXES.some((prefix) => attrName.startsWith(prefix));
270
283
  if (isSvelteAttr) {
271
284
  // Highlight Svelte-specific attributes
272
- const prefixMatch = SVELTE_ATTRIBUTE_PREFIXES.find(p => attrName.startsWith(p));
285
+ const prefixMatch = SVELTE_ATTRIBUTE_PREFIXES.find((p) => attrName.startsWith(p));
273
286
  if (prefixMatch) {
274
287
  tokens.push({ type: 'keyword.control', text: prefixMatch });
275
288
  tokens.push({ type: 'tag.attribute', text: attrName.substring(prefixMatch.length) });
@@ -231,7 +231,9 @@
231
231
  .ide-layout--resizing .ide-layout__sidebar > :global(*) {
232
232
  opacity: 0.5;
233
233
  filter: blur(1px);
234
- transition: opacity 0.1s ease, filter 0.1s ease;
234
+ transition:
235
+ opacity 0.1s ease,
236
+ filter 0.1s ease;
235
237
  }
236
238
 
237
239
  .ide-layout__main {
@@ -278,7 +280,9 @@
278
280
  .ide-layout--resizing .ide-layout__panel > :global(*) {
279
281
  opacity: 0.5;
280
282
  filter: blur(1px);
281
- transition: opacity 0.1s ease, filter 0.1s ease;
283
+ transition:
284
+ opacity 0.1s ease,
285
+ filter 0.1s ease;
282
286
  }
283
287
 
284
288
  .ide-layout__status-bar {
@@ -87,9 +87,7 @@
87
87
  let featuredAgent = $derived.by(() => {
88
88
  // Prefer agent working on current file
89
89
  if (currentFilePath) {
90
- const agentOnFile = busyAgents.find(a =>
91
- a.currentTask?.files?.includes(currentFilePath)
92
- );
90
+ const agentOnFile = busyAgents.find((a) => a.currentTask?.files?.includes(currentFilePath));
93
91
  if (agentOnFile) return agentOnFile;
94
92
  }
95
93
  // Otherwise show first busy agent
@@ -107,10 +105,18 @@
107
105
  const phase = featuredAgent.currentTask?.progress?.phase;
108
106
  let action = 'working';
109
107
  switch (phase) {
110
- case 'planning': action = 'planning'; break;
111
- case 'implementing': action = 'coding'; break;
112
- case 'testing': action = 'testing'; break;
113
- case 'complete': action = 'done'; break;
108
+ case 'planning':
109
+ action = 'planning';
110
+ break;
111
+ case 'implementing':
112
+ action = 'coding';
113
+ break;
114
+ case 'testing':
115
+ action = 'testing';
116
+ break;
117
+ case 'complete':
118
+ action = 'done';
119
+ break;
114
120
  }
115
121
 
116
122
  const otherBusy = busyAgents.length - 1;
@@ -120,14 +126,10 @@
120
126
 
121
127
  // Lock context for current file
122
128
  let currentFileLock = $derived(
123
- currentFilePath ? locks.find(l => l.path === currentFilePath) : undefined
124
- );
125
- let isMyLock = $derived(
126
- currentFileLock && userId ? currentFileLock.holder === userId : false
127
- );
128
- let otherLocks = $derived(
129
- locks.filter(l => l.path !== currentFilePath)
129
+ currentFilePath ? locks.find((l) => l.path === currentFilePath) : undefined
130
130
  );
131
+ let isMyLock = $derived(currentFileLock && userId ? currentFileLock.holder === userId : false);
132
+ let otherLocks = $derived(locks.filter((l) => l.path !== currentFilePath));
131
133
 
132
134
  // Lock expiry countdown
133
135
  let lockExpiryText = $state<string | null>(null);
@@ -196,7 +198,7 @@
196
198
  return `${currentFileLock.holder} is editing this file.`;
197
199
  }
198
200
  if (locks.length === 0) return 'No files locked';
199
- const holders = [...new Set(locks.map(l => l.holder))];
201
+ const holders = [...new Set(locks.map((l) => l.holder))];
200
202
  return `Locked by: ${holders.join(', ')}`;
201
203
  });
202
204
  </script>
@@ -434,8 +436,13 @@
434
436
  }
435
437
 
436
438
  @keyframes ai-dot-shimmer {
437
- 0%, 100% { background-position: 0% 50%; }
438
- 50% { background-position: 100% 50%; }
439
+ 0%,
440
+ 100% {
441
+ background-position: 0% 50%;
442
+ }
443
+ 50% {
444
+ background-position: 100% 50%;
445
+ }
439
446
  }
440
447
 
441
448
  /* Lock Status */
@@ -468,8 +475,13 @@
468
475
  }
469
476
 
470
477
  @keyframes expiry-pulse {
471
- 0%, 100% { opacity: 1; }
472
- 50% { opacity: 0.6; }
478
+ 0%,
479
+ 100% {
480
+ opacity: 1;
481
+ }
482
+ 50% {
483
+ opacity: 0.6;
484
+ }
473
485
  }
474
486
 
475
487
  .status-bar__separator {
@@ -493,7 +505,7 @@
493
505
 
494
506
  /* Responsive: hide less important info on narrow screens */
495
507
  @media (max-width: 600px) {
496
- .status-bar__right > :nth-child(n+3):nth-child(-n+5) {
508
+ .status-bar__right > :nth-child(n + 3):nth-child(-n + 5) {
497
509
  display: none;
498
510
  }
499
511
  }
@@ -1,3 +1,22 @@
1
+ <script module lang="ts">
2
+ // SVG icons for completion item kinds
3
+ function getKindSVG(kind?: number): string {
4
+ const icons: Record<number, string> = {
5
+ 2: '<path d="M4 4h4v2H4v4H2V4h2zm10 0h2v6h-4V8h2V4zm-6 8h4v4H8v-4zm8 0h2v4h-4v-2h2v-2z" fill="currentColor"/>',
6
+ 3: '<path d="M4 4h8v2H4v8H2V4h2zm6 4h4v8h-2v-6H8V8h2z" fill="currentColor"/>',
7
+ 6: '<path d="M4 4h8v4H8V6H6v4H4V4zm0 8h2v4H4v-4zm4 0h8v4H8v-4z" fill="currentColor"/>',
8
+ 7: '<path d="M4 4h8v2H4v8H2V4h2zm4 4h6v8H6V8h2zm2 2v4h2v-4h-2z" fill="currentColor"/>',
9
+ 8: '<path d="M6 4h8v2H6v8H4V4h2zm6 4h2v8H8v-2h4V8z" fill="currentColor"/>',
10
+ 9: '<path d="M2 4h4v2H2v8h8v2H2V4zm6 2h8v10H8V6zm2 2v6h4V8h-4z" fill="currentColor"/>',
11
+ 13: '<path d="M4 4h8v2H4v8H2V4h2zm4 4h6v8H6V8h2zm2 2v2h2v-2h-2z" fill="currentColor"/>',
12
+ 14: '<path d="M4 6h10v2H4v6H2V6h2zm4 4h6v6H6v-6h2zm2 2v2h2v-2h-2z" fill="currentColor"/>',
13
+ 15: '<path d="M4 4v12h12V4H4zm2 2h8v8H6V6z" fill="currentColor"/>',
14
+ 21: '<path d="M8 2l6 6-6 6-6-6 6-6zm0 2.83L4.83 8 8 11.17 11.17 8 8 4.83z" fill="currentColor"/>'
15
+ };
16
+ return `<svg viewBox="0 0 16 16" width="16" height="16">${icons[kind ?? 1] ?? '<circle cx="8" cy="8" r="4" fill="currentColor"/>'}</svg>`;
17
+ }
18
+ </script>
19
+
1
20
  <script lang="ts">
2
21
  /**
3
22
  * AutocompleteWidget - LSP completion suggestions dropdown
@@ -206,25 +225,6 @@
206
225
  {/if}
207
226
  </div>
208
227
 
209
- <script module lang="ts">
210
- // SVG icons for completion item kinds
211
- function getKindSVG(kind?: number): string {
212
- const icons: Record<number, string> = {
213
- 2: '<path d="M4 4h4v2H4v4H2V4h2zm10 0h2v6h-4V8h2V4zm-6 8h4v4H8v-4zm8 0h2v4h-4v-2h2v-2z" fill="currentColor"/>',
214
- 3: '<path d="M4 4h8v2H4v8H2V4h2zm6 4h4v8h-2v-6H8V8h2z" fill="currentColor"/>',
215
- 6: '<path d="M4 4h8v4H8V6H6v4H4V4zm0 8h2v4H4v-4zm4 0h8v4H8v-4z" fill="currentColor"/>',
216
- 7: '<path d="M4 4h8v2H4v8H2V4h2zm4 4h6v8H6V8h2zm2 2v4h2v-4h-2z" fill="currentColor"/>',
217
- 8: '<path d="M6 4h8v2H6v8H4V4h2zm6 4h2v8H8v-2h4V8z" fill="currentColor"/>',
218
- 9: '<path d="M2 4h4v2H2v8h8v2H2V4zm6 2h8v10H8V6zm2 2v6h4V8h-4z" fill="currentColor"/>',
219
- 13: '<path d="M4 4h8v2H4v8H2V4h2zm4 4h6v8H6V8h2zm2 2v2h2v-2h-2z" fill="currentColor"/>',
220
- 14: '<path d="M4 6h10v2H4v6H2V6h2zm4 4h6v6H6v-6h2zm2 2v2h2v-2h-2z" fill="currentColor"/>',
221
- 15: '<path d="M4 4v12h12V4H4zm2 2h8v8H6V6z" fill="currentColor"/>',
222
- 21: '<path d="M8 2l6 6-6 6-6-6 6-6zm0 2.83L4.83 8 8 11.17 11.17 8 8 4.83z" fill="currentColor"/>'
223
- };
224
- return `<svg viewBox="0 0 16 16" width="16" height="16">${icons[kind ?? 1] ?? '<circle cx="8" cy="8" r="4" fill="currentColor"/>'}</svg>`;
225
- }
226
- </script>
227
-
228
228
  <style>
229
229
  .autocomplete-widget {
230
230
  position: fixed;
@@ -1,3 +1,43 @@
1
+ <script module lang="ts">
2
+ function getGutterIcon(severity?: number): string {
3
+ const color =
4
+ severity === 1
5
+ ? 'var(--ide-error)'
6
+ : severity === 2
7
+ ? 'var(--ide-warning)'
8
+ : severity === 3
9
+ ? 'var(--ide-info)'
10
+ : 'var(--ide-text-muted)';
11
+
12
+ switch (severity) {
13
+ case 1: // Error - filled circle with X
14
+ return `<svg viewBox="0 0 16 16" width="12" height="12">
15
+ <circle cx="8" cy="8" r="6" fill="${color}"/>
16
+ <path d="M5.5 5.5l5 5M10.5 5.5l-5 5" stroke="var(--ide-bg-primary)" stroke-width="1.5" stroke-linecap="round"/>
17
+ </svg>`;
18
+ case 2: // Warning - triangle
19
+ return `<svg viewBox="0 0 16 16" width="12" height="12">
20
+ <path d="M8 2L1 14h14L8 2z" fill="${color}"/>
21
+ <path d="M8 6v4M8 12v1" stroke="var(--ide-bg-primary)" stroke-width="1.5" stroke-linecap="round"/>
22
+ </svg>`;
23
+ case 3: // Info - circle with i
24
+ return `<svg viewBox="0 0 16 16" width="12" height="12">
25
+ <circle cx="8" cy="8" r="6" fill="${color}"/>
26
+ <path d="M8 5v1M8 8v4" stroke="var(--ide-bg-primary)" stroke-width="1.5" stroke-linecap="round"/>
27
+ </svg>`;
28
+ case 4: // Hint - lightbulb outline
29
+ return `<svg viewBox="0 0 16 16" width="12" height="12">
30
+ <path d="M8 1a5 5 0 013 9v2a1 1 0 01-1 1H6a1 1 0 01-1-1v-2a5 5 0 013-9z" fill="none" stroke="${color}" stroke-width="1.2"/>
31
+ <path d="M6 14h4" stroke="${color}" stroke-width="1.2" stroke-linecap="round"/>
32
+ </svg>`;
33
+ default:
34
+ return `<svg viewBox="0 0 16 16" width="12" height="12">
35
+ <circle cx="8" cy="8" r="4" fill="${color}"/>
36
+ </svg>`;
37
+ }
38
+ }
39
+ </script>
40
+
1
41
  <script lang="ts">
2
42
  /**
3
43
  * DiagnosticMarker - Inline diagnostic indicator
@@ -18,30 +58,35 @@
18
58
  class?: string;
19
59
  }
20
60
 
21
- let {
22
- diagnostic,
23
- type = 'inline',
24
- onClick,
25
- class: className = ''
26
- }: Props = $props();
61
+ let { diagnostic, type = 'inline', onClick, class: className = '' }: Props = $props();
27
62
 
28
63
  function getSeverityClass(severity?: DiagnosticSeverity): string {
29
64
  switch (severity) {
30
- case 1: return 'error';
31
- case 2: return 'warning';
32
- case 3: return 'info';
33
- case 4: return 'hint';
34
- default: return 'info';
65
+ case 1:
66
+ return 'error';
67
+ case 2:
68
+ return 'warning';
69
+ case 3:
70
+ return 'info';
71
+ case 4:
72
+ return 'hint';
73
+ default:
74
+ return 'info';
35
75
  }
36
76
  }
37
77
 
38
78
  function getSeverityLabel(severity?: DiagnosticSeverity): string {
39
79
  switch (severity) {
40
- case 1: return 'Error';
41
- case 2: return 'Warning';
42
- case 3: return 'Info';
43
- case 4: return 'Hint';
44
- default: return 'Diagnostic';
80
+ case 1:
81
+ return 'Error';
82
+ case 2:
83
+ return 'Warning';
84
+ case 3:
85
+ return 'Info';
86
+ case 4:
87
+ return 'Hint';
88
+ default:
89
+ return 'Diagnostic';
45
90
  }
46
91
  }
47
92
  </script>
@@ -67,42 +112,6 @@
67
112
  ></span>
68
113
  {/if}
69
114
 
70
- <script module lang="ts">
71
- function getGutterIcon(severity?: number): string {
72
- const color = severity === 1 ? 'var(--ide-error)' :
73
- severity === 2 ? 'var(--ide-warning)' :
74
- severity === 3 ? 'var(--ide-info)' :
75
- 'var(--ide-text-muted)';
76
-
77
- switch (severity) {
78
- case 1: // Error - filled circle with X
79
- return `<svg viewBox="0 0 16 16" width="12" height="12">
80
- <circle cx="8" cy="8" r="6" fill="${color}"/>
81
- <path d="M5.5 5.5l5 5M10.5 5.5l-5 5" stroke="var(--ide-bg-primary)" stroke-width="1.5" stroke-linecap="round"/>
82
- </svg>`;
83
- case 2: // Warning - triangle
84
- return `<svg viewBox="0 0 16 16" width="12" height="12">
85
- <path d="M8 2L1 14h14L8 2z" fill="${color}"/>
86
- <path d="M8 6v4M8 12v1" stroke="var(--ide-bg-primary)" stroke-width="1.5" stroke-linecap="round"/>
87
- </svg>`;
88
- case 3: // Info - circle with i
89
- return `<svg viewBox="0 0 16 16" width="12" height="12">
90
- <circle cx="8" cy="8" r="6" fill="${color}"/>
91
- <path d="M8 5v1M8 8v4" stroke="var(--ide-bg-primary)" stroke-width="1.5" stroke-linecap="round"/>
92
- </svg>`;
93
- case 4: // Hint - lightbulb outline
94
- return `<svg viewBox="0 0 16 16" width="12" height="12">
95
- <path d="M8 1a5 5 0 013 9v2a1 1 0 01-1 1H6a1 1 0 01-1-1v-2a5 5 0 013-9z" fill="none" stroke="${color}" stroke-width="1.2"/>
96
- <path d="M6 14h4" stroke="${color}" stroke-width="1.2" stroke-linecap="round"/>
97
- </svg>`;
98
- default:
99
- return `<svg viewBox="0 0 16 16" width="12" height="12">
100
- <circle cx="8" cy="8" r="4" fill="${color}"/>
101
- </svg>`;
102
- }
103
- }
104
- </script>
105
-
106
115
  <style>
107
116
  .diagnostic-gutter {
108
117
  display: flex;
@@ -1,3 +1,25 @@
1
+ <script module lang="ts">
2
+ const errorIcon = `<svg viewBox="0 0 16 16" width="14" height="14"><circle cx="8" cy="8" r="7" fill="currentColor"/><path d="M5.5 5.5l5 5M10.5 5.5l-5 5" stroke="var(--ide-bg-primary)" stroke-width="1.5"/></svg>`;
3
+ const warningIcon = `<svg viewBox="0 0 16 16" width="14" height="14"><path d="M8 1L1 15h14L8 1z" fill="currentColor"/><path d="M8 6v4M8 12v1" stroke="var(--ide-bg-primary)" stroke-width="1.5" stroke-linecap="round"/></svg>`;
4
+ const infoIcon = `<svg viewBox="0 0 16 16" width="14" height="14"><circle cx="8" cy="8" r="7" fill="currentColor"/><path d="M8 5v1M8 8v4" stroke="var(--ide-bg-primary)" stroke-width="1.5" stroke-linecap="round"/></svg>`;
5
+ const checkIcon = `<svg viewBox="0 0 16 16" width="24" height="24"><circle cx="8" cy="8" r="7" fill="var(--ide-success)" opacity="0.2"/><path d="M5 8l2 2 4-4" stroke="var(--ide-success)" stroke-width="1.5" fill="none" stroke-linecap="round" stroke-linejoin="round"/></svg>`;
6
+
7
+ function getSeveritySVG(severity?: number): string {
8
+ switch (severity) {
9
+ case 1:
10
+ return errorIcon;
11
+ case 2:
12
+ return warningIcon;
13
+ case 3:
14
+ return infoIcon;
15
+ case 4:
16
+ return `<svg viewBox="0 0 16 16" width="14" height="14"><circle cx="8" cy="8" r="7" fill="currentColor"/><path d="M8 4v5M8 11v1" stroke="var(--ide-bg-primary)" stroke-width="1.5" stroke-linecap="round"/></svg>`;
17
+ default:
18
+ return infoIcon;
19
+ }
20
+ }
21
+ </script>
22
+
1
23
  <script lang="ts">
2
24
  /**
3
25
  * DiagnosticsPanel - LSP diagnostics list display
@@ -62,10 +84,18 @@
62
84
  diagnostics.forEach((diags) => {
63
85
  for (const diag of diags) {
64
86
  switch (diag.severity) {
65
- case 1: result.errors++; break;
66
- case 2: result.warnings++; break;
67
- case 3: result.info++; break;
68
- case 4: result.hints++; break;
87
+ case 1:
88
+ result.errors++;
89
+ break;
90
+ case 2:
91
+ result.warnings++;
92
+ break;
93
+ case 3:
94
+ result.info++;
95
+ break;
96
+ case 4:
97
+ result.hints++;
98
+ break;
69
99
  }
70
100
  }
71
101
  });
@@ -74,11 +104,16 @@
74
104
 
75
105
  function getSeverityIcon(severity?: DiagnosticSeverity): string {
76
106
  switch (severity) {
77
- case 1: return 'error';
78
- case 2: return 'warning';
79
- case 3: return 'info';
80
- case 4: return 'hint';
81
- default: return 'info';
107
+ case 1:
108
+ return 'error';
109
+ case 2:
110
+ return 'warning';
111
+ case 3:
112
+ return 'info';
113
+ case 4:
114
+ return 'hint';
115
+ default:
116
+ return 'info';
82
117
  }
83
118
  }
84
119
 
@@ -149,7 +184,7 @@
149
184
  {#if allDiagnostics().length === 0}
150
185
  <div class="diagnostics-panel__empty">
151
186
  <!-- eslint-disable-next-line svelte/no-at-html-tags -- SVG icons are static string literals defined in this file, not user content -->
152
- <span class="diagnostics-panel__empty-icon">{@html checkIcon}</span>
187
+ <span class="diagnostics-panel__empty-icon">{@html checkIcon}</span>
153
188
  <span>No problems detected</span>
154
189
  </div>
155
190
  {:else}
@@ -180,23 +215,6 @@
180
215
  </div>
181
216
  </div>
182
217
 
183
- <script module lang="ts">
184
- const errorIcon = `<svg viewBox="0 0 16 16" width="14" height="14"><circle cx="8" cy="8" r="7" fill="currentColor"/><path d="M5.5 5.5l5 5M10.5 5.5l-5 5" stroke="var(--ide-bg-primary)" stroke-width="1.5"/></svg>`;
185
- const warningIcon = `<svg viewBox="0 0 16 16" width="14" height="14"><path d="M8 1L1 15h14L8 1z" fill="currentColor"/><path d="M8 6v4M8 12v1" stroke="var(--ide-bg-primary)" stroke-width="1.5" stroke-linecap="round"/></svg>`;
186
- const infoIcon = `<svg viewBox="0 0 16 16" width="14" height="14"><circle cx="8" cy="8" r="7" fill="currentColor"/><path d="M8 5v1M8 8v4" stroke="var(--ide-bg-primary)" stroke-width="1.5" stroke-linecap="round"/></svg>`;
187
- const checkIcon = `<svg viewBox="0 0 16 16" width="24" height="24"><circle cx="8" cy="8" r="7" fill="var(--ide-success)" opacity="0.2"/><path d="M5 8l2 2 4-4" stroke="var(--ide-success)" stroke-width="1.5" fill="none" stroke-linecap="round" stroke-linejoin="round"/></svg>`;
188
-
189
- function getSeveritySVG(severity?: number): string {
190
- switch (severity) {
191
- case 1: return errorIcon;
192
- case 2: return warningIcon;
193
- case 3: return infoIcon;
194
- case 4: return `<svg viewBox="0 0 16 16" width="14" height="14"><circle cx="8" cy="8" r="7" fill="currentColor"/><path d="M8 4v5M8 11v1" stroke="var(--ide-bg-primary)" stroke-width="1.5" stroke-linecap="round"/></svg>`;
195
- default: return infoIcon;
196
- }
197
- }
198
- </script>
199
-
200
218
  <style>
201
219
  .diagnostics-panel {
202
220
  display: flex;