@nocturnium/svelte-ide 1.0.0 → 1.0.2
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/README.md +43 -47
- package/dist/components/agents/AgentActivityPanel.svelte +3 -1
- package/dist/components/agents/AgentAvatar.svelte +127 -35
- package/dist/components/agents/AgentCursor.svelte +15 -5
- package/dist/components/agents/AgentPresenceBar.svelte +7 -2
- package/dist/components/ai/AIConversationList.svelte +39 -34
- package/dist/components/ai/AIInlineEdit.svelte +1 -3
- package/dist/components/ai/AIMessage.svelte +5 -5
- package/dist/components/ai/AIMessageActions.svelte +18 -3
- package/dist/components/ai/AIMessageContent.svelte +22 -20
- package/dist/components/ai/AIPanel.svelte +17 -9
- package/dist/components/ai/AISuggestionWidget.svelte +1 -3
- package/dist/components/ai/AIToolCallDisplay.svelte +10 -14
- package/dist/components/core/Badge.svelte +9 -1
- package/dist/components/core/ConnectionStatus.svelte +73 -68
- package/dist/components/core/ErrorBoundary.svelte +56 -56
- package/dist/components/core/ErrorBoundary.svelte.d.ts +5 -5
- package/dist/components/core/Icon.svelte +22 -11
- package/dist/components/core/ResizeHandle.svelte +1 -1
- package/dist/components/core/Tooltip.svelte +1 -7
- package/dist/components/editor/AIFocusLayer.svelte +15 -7
- package/dist/components/editor/Breadcrumbs.svelte +18 -6
- package/dist/components/editor/BreakpointLayer.svelte +51 -60
- package/dist/components/editor/CognitiveLoadMeter.svelte +4 -2
- package/dist/components/editor/CollaborativeEditor.svelte +1 -5
- package/dist/components/editor/CommandPalette.svelte +1 -4
- package/dist/components/editor/ComplexityLayer.svelte +8 -6
- package/dist/components/editor/ConflictZoneLayer.svelte +2 -8
- package/dist/components/editor/ContextLens.svelte +1 -4
- package/dist/components/editor/CustomEditor.svelte +85 -41
- package/dist/components/editor/DebugConsole.svelte +8 -17
- package/dist/components/editor/EchoCursorLayer.svelte +3 -1
- package/dist/components/editor/EditorGutter.svelte +8 -2
- package/dist/components/editor/EditorLines.svelte +6 -3
- package/dist/components/editor/EditorPane.svelte +1 -6
- package/dist/components/editor/EditorSelections.svelte +29 -11
- package/dist/components/editor/FileExplorer.svelte +26 -4
- package/dist/components/editor/FileIcon.svelte +3 -1
- package/dist/components/editor/FindReplace.svelte +16 -4
- package/dist/components/editor/GhostBracketLayer.svelte +2 -2
- package/dist/components/editor/GitBlameLayer.svelte +2 -1
- package/dist/components/editor/InlineDiagnosticsLayer.svelte +4 -13
- package/dist/components/editor/InlineDiffLayer.svelte +18 -9
- package/dist/components/editor/Minimap.svelte +16 -9
- package/dist/components/editor/PluginPreviewSandbox.svelte +3 -2
- package/dist/components/editor/ProblemsPanel.svelte +11 -35
- package/dist/components/editor/QuickActionsMenu.svelte +5 -14
- package/dist/components/editor/SnippetPalette.svelte +11 -12
- package/dist/components/editor/StructureMap.svelte +2 -1
- package/dist/components/editor/SymbolOutline.svelte +14 -19
- package/dist/components/editor/TimelineScrubber.svelte +7 -6
- package/dist/components/editor/core/complexity-analyzer.js +42 -12
- package/dist/components/editor/core/conflict-predictor.js +2 -4
- package/dist/components/editor/core/folding.d.ts +9 -0
- package/dist/components/editor/core/folding.js +40 -5
- package/dist/components/editor/core/multi-cursor.js +4 -8
- package/dist/components/editor/core/navigation.js +2 -6
- package/dist/components/editor/core/quick-actions.js +22 -17
- package/dist/components/editor/core/search.js +2 -6
- package/dist/components/editor/core/semantic-analyzer.js +1 -3
- package/dist/components/editor/core/snippet-manager.js +4 -3
- package/dist/components/editor/core/state.js +2 -2
- package/dist/components/editor/core/timeline.js +1 -3
- package/dist/components/editor/editor-input.js +9 -6
- package/dist/components/editor/editor-multicursor.js +2 -2
- package/dist/components/editor/tokenizer/languages/css.js +146 -24
- package/dist/components/editor/tokenizer/languages/go.js +76 -13
- package/dist/components/editor/tokenizer/languages/javascript.d.ts +13 -2
- package/dist/components/editor/tokenizer/languages/javascript.js +278 -84
- package/dist/components/editor/tokenizer/languages/python.js +116 -19
- package/dist/components/editor/tokenizer/languages/svelte.js +20 -7
- package/dist/components/layout/IDELayout.svelte +6 -2
- package/dist/components/layout/StatusBar.svelte +32 -20
- package/dist/components/lsp/AutocompleteWidget.svelte +19 -19
- package/dist/components/lsp/DiagnosticMarker.svelte +61 -52
- package/dist/components/lsp/DiagnosticsPanel.svelte +45 -27
- package/dist/components/lsp/HoverTooltip.svelte +56 -61
- package/dist/components/lsp/LSPEditor.svelte +7 -18
- package/dist/components/lsp/SignatureHelpWidget.svelte +12 -9
- package/dist/components/plugins/PluginCard.svelte +3 -13
- package/dist/components/plugins/PluginProposalForm.svelte +19 -31
- package/dist/components/vfs/LockConflictDialog.svelte +112 -45
- package/dist/components/vfs/LockIndicator.svelte +0 -1
- package/dist/components/vfs/LockOverlay.svelte +53 -53
- package/dist/components/vfs/LockOverlay.svelte.d.ts +5 -5
- package/dist/components/vfs/VersionConflictDialog.svelte +107 -77
- package/dist/services/error-handling.js +1 -7
- package/dist/services/mock-ai.js +9 -7
- package/dist/stores/agents.svelte.js +50 -10
- package/dist/stores/ai.svelte.js +66 -18
- package/dist/stores/collaboration.svelte.js +70 -14
- package/dist/stores/editor.svelte.js +50 -10
- package/dist/stores/plugin.svelte.js +60 -12
- package/dist/stores/vfs.svelte.js +77 -19
- package/dist/styles/theme.css +16 -7
- package/package.json +186 -1
|
@@ -4,48 +4,205 @@
|
|
|
4
4
|
import { createToken } from '../base';
|
|
5
5
|
// JavaScript/TypeScript keywords
|
|
6
6
|
const keywords = new Set([
|
|
7
|
-
'await',
|
|
8
|
-
'
|
|
9
|
-
'
|
|
10
|
-
'
|
|
11
|
-
'
|
|
7
|
+
'await',
|
|
8
|
+
'break',
|
|
9
|
+
'case',
|
|
10
|
+
'catch',
|
|
11
|
+
'class',
|
|
12
|
+
'const',
|
|
13
|
+
'continue',
|
|
14
|
+
'debugger',
|
|
15
|
+
'default',
|
|
16
|
+
'delete',
|
|
17
|
+
'do',
|
|
18
|
+
'else',
|
|
19
|
+
'enum',
|
|
20
|
+
'export',
|
|
21
|
+
'extends',
|
|
22
|
+
'finally',
|
|
23
|
+
'for',
|
|
24
|
+
'function',
|
|
25
|
+
'if',
|
|
26
|
+
'import',
|
|
27
|
+
'in',
|
|
28
|
+
'instanceof',
|
|
29
|
+
'let',
|
|
30
|
+
'new',
|
|
31
|
+
'of',
|
|
32
|
+
'return',
|
|
33
|
+
'static',
|
|
34
|
+
'super',
|
|
35
|
+
'switch',
|
|
36
|
+
'this',
|
|
37
|
+
'throw',
|
|
38
|
+
'try',
|
|
39
|
+
'typeof',
|
|
40
|
+
'var',
|
|
41
|
+
'void',
|
|
42
|
+
'while',
|
|
43
|
+
'with',
|
|
44
|
+
'yield',
|
|
45
|
+
'async',
|
|
46
|
+
'from',
|
|
47
|
+
'as',
|
|
48
|
+
'get',
|
|
49
|
+
'set'
|
|
12
50
|
]);
|
|
13
51
|
// TypeScript-specific keywords
|
|
14
52
|
const tsKeywords = new Set([
|
|
15
|
-
'abstract',
|
|
16
|
-
'
|
|
17
|
-
'
|
|
18
|
-
'
|
|
53
|
+
'abstract',
|
|
54
|
+
'any',
|
|
55
|
+
'as',
|
|
56
|
+
'asserts',
|
|
57
|
+
'bigint',
|
|
58
|
+
'boolean',
|
|
59
|
+
'declare',
|
|
60
|
+
'infer',
|
|
61
|
+
'interface',
|
|
62
|
+
'is',
|
|
63
|
+
'keyof',
|
|
64
|
+
'module',
|
|
65
|
+
'namespace',
|
|
66
|
+
'never',
|
|
67
|
+
'null',
|
|
68
|
+
'number',
|
|
69
|
+
'object',
|
|
70
|
+
'override',
|
|
71
|
+
'private',
|
|
72
|
+
'protected',
|
|
73
|
+
'public',
|
|
74
|
+
'readonly',
|
|
75
|
+
'require',
|
|
76
|
+
'string',
|
|
77
|
+
'symbol',
|
|
78
|
+
'type',
|
|
79
|
+
'undefined',
|
|
80
|
+
'unique',
|
|
81
|
+
'unknown',
|
|
82
|
+
'void'
|
|
19
83
|
]);
|
|
20
84
|
// Control flow keywords
|
|
21
85
|
const controlKeywords = new Set([
|
|
22
|
-
'if',
|
|
23
|
-
'
|
|
86
|
+
'if',
|
|
87
|
+
'else',
|
|
88
|
+
'for',
|
|
89
|
+
'while',
|
|
90
|
+
'do',
|
|
91
|
+
'switch',
|
|
92
|
+
'case',
|
|
93
|
+
'default',
|
|
94
|
+
'break',
|
|
95
|
+
'continue',
|
|
96
|
+
'return',
|
|
97
|
+
'throw',
|
|
98
|
+
'try',
|
|
99
|
+
'catch',
|
|
100
|
+
'finally',
|
|
101
|
+
'await',
|
|
102
|
+
'yield'
|
|
24
103
|
]);
|
|
25
104
|
// Built-in constants
|
|
26
105
|
const builtins = new Set(['true', 'false', 'null', 'undefined', 'NaN', 'Infinity']);
|
|
27
106
|
// Built-in type names
|
|
28
107
|
const builtinTypes = new Set([
|
|
29
|
-
'Array',
|
|
30
|
-
'
|
|
31
|
-
'
|
|
32
|
-
'
|
|
108
|
+
'Array',
|
|
109
|
+
'Object',
|
|
110
|
+
'String',
|
|
111
|
+
'Number',
|
|
112
|
+
'Boolean',
|
|
113
|
+
'Function',
|
|
114
|
+
'Symbol',
|
|
115
|
+
'Promise',
|
|
116
|
+
'Map',
|
|
117
|
+
'Set',
|
|
118
|
+
'WeakMap',
|
|
119
|
+
'WeakSet',
|
|
120
|
+
'Date',
|
|
121
|
+
'RegExp',
|
|
122
|
+
'Error',
|
|
123
|
+
'TypeError',
|
|
124
|
+
'ReferenceError',
|
|
125
|
+
'SyntaxError',
|
|
126
|
+
'JSON',
|
|
127
|
+
'Math',
|
|
128
|
+
'console',
|
|
129
|
+
'window',
|
|
130
|
+
'document',
|
|
131
|
+
'globalThis',
|
|
132
|
+
'Buffer',
|
|
133
|
+
'process'
|
|
33
134
|
]);
|
|
34
135
|
/**
|
|
35
136
|
* Tokens after which a regex literal can appear (expression start context)
|
|
36
137
|
*/
|
|
37
138
|
const REGEX_VALID_AFTER = new Set([
|
|
38
139
|
// Keywords that expect expressions
|
|
39
|
-
'return',
|
|
40
|
-
'
|
|
140
|
+
'return',
|
|
141
|
+
'throw',
|
|
142
|
+
'case',
|
|
143
|
+
'in',
|
|
144
|
+
'of',
|
|
145
|
+
'typeof',
|
|
146
|
+
'instanceof',
|
|
147
|
+
'void',
|
|
148
|
+
'delete',
|
|
149
|
+
'new',
|
|
150
|
+
'await',
|
|
151
|
+
'yield',
|
|
152
|
+
'default',
|
|
153
|
+
'extends',
|
|
154
|
+
'else',
|
|
155
|
+
'do',
|
|
41
156
|
// Operators
|
|
42
|
-
'=',
|
|
43
|
-
'
|
|
44
|
-
'
|
|
45
|
-
'
|
|
46
|
-
'
|
|
157
|
+
'=',
|
|
158
|
+
'==',
|
|
159
|
+
'===',
|
|
160
|
+
'!=',
|
|
161
|
+
'!==',
|
|
162
|
+
'<',
|
|
163
|
+
'>',
|
|
164
|
+
'<=',
|
|
165
|
+
'>=',
|
|
166
|
+
'+',
|
|
167
|
+
'-',
|
|
168
|
+
'*',
|
|
169
|
+
'/',
|
|
170
|
+
'%',
|
|
171
|
+
'**',
|
|
172
|
+
'&',
|
|
173
|
+
'|',
|
|
174
|
+
'^',
|
|
175
|
+
'~',
|
|
176
|
+
'!',
|
|
177
|
+
'&&',
|
|
178
|
+
'||',
|
|
179
|
+
'??',
|
|
180
|
+
'?',
|
|
181
|
+
':',
|
|
182
|
+
',',
|
|
183
|
+
';',
|
|
184
|
+
'+=',
|
|
185
|
+
'-=',
|
|
186
|
+
'*=',
|
|
187
|
+
'/=',
|
|
188
|
+
'%=',
|
|
189
|
+
'**=',
|
|
190
|
+
'&=',
|
|
191
|
+
'|=',
|
|
192
|
+
'^=',
|
|
193
|
+
'&&=',
|
|
194
|
+
'||=',
|
|
195
|
+
'??=',
|
|
196
|
+
'<<',
|
|
197
|
+
'>>',
|
|
198
|
+
'>>>',
|
|
199
|
+
'<<=',
|
|
200
|
+
'>>=',
|
|
201
|
+
'>>>=',
|
|
47
202
|
// Opening brackets
|
|
48
|
-
'(',
|
|
203
|
+
'(',
|
|
204
|
+
'[',
|
|
205
|
+
'{',
|
|
49
206
|
// Arrow
|
|
50
207
|
'=>'
|
|
51
208
|
]);
|
|
@@ -54,8 +211,11 @@ const REGEX_VALID_AFTER = new Set([
|
|
|
54
211
|
*/
|
|
55
212
|
const DIVISION_VALID_AFTER = new Set([
|
|
56
213
|
// These token types indicate an expression just ended
|
|
57
|
-
')',
|
|
58
|
-
'
|
|
214
|
+
')',
|
|
215
|
+
']',
|
|
216
|
+
'}', // Closing brackets
|
|
217
|
+
'++',
|
|
218
|
+
'--' // Postfix operators
|
|
59
219
|
]);
|
|
60
220
|
export class JavaScriptTokenizer {
|
|
61
221
|
language;
|
|
@@ -65,8 +225,12 @@ export class JavaScriptTokenizer {
|
|
|
65
225
|
this.isTypeScript = options.typescript ?? false;
|
|
66
226
|
this.isJSX = options.jsx ?? false;
|
|
67
227
|
this.language = this.isTypeScript
|
|
68
|
-
?
|
|
69
|
-
|
|
228
|
+
? this.isJSX
|
|
229
|
+
? 'tsx'
|
|
230
|
+
: 'typescript'
|
|
231
|
+
: this.isJSX
|
|
232
|
+
? 'jsx'
|
|
233
|
+
: 'javascript';
|
|
70
234
|
}
|
|
71
235
|
getInitialState() {
|
|
72
236
|
return {
|
|
@@ -99,22 +263,39 @@ export class JavaScriptTokenizer {
|
|
|
99
263
|
return { lineNumber, tokens, text: line, state };
|
|
100
264
|
}
|
|
101
265
|
}
|
|
102
|
-
// Handle template literal continuation
|
|
103
|
-
if (state.inTemplateLiteral && (state.templateDepth ?? 0) > 0) {
|
|
104
|
-
const result = this.tokenizeTemplateLiteralContinuation(line, pos, state);
|
|
105
|
-
tokens.push(...result.tokens);
|
|
106
|
-
pos = result.pos;
|
|
107
|
-
if (pos >= line.length) {
|
|
108
|
-
return { lineNumber, tokens, text: line, state };
|
|
109
|
-
}
|
|
110
|
-
}
|
|
111
266
|
while (pos < line.length) {
|
|
267
|
+
// Template literals: scan the string portion (between the backticks and
|
|
268
|
+
// `${` / `}`) as a single string.template token. The interpolation
|
|
269
|
+
// expression is tokenized as ordinary code below, tracking brace depth in
|
|
270
|
+
// state.templateDepth so the closing backtick is recognised. This fixes the
|
|
271
|
+
// leak where an unclosed template state bled onto every following line.
|
|
272
|
+
const inStringPortion = state.inTemplateLiteral && (state.templateDepth ?? 0) === 0;
|
|
273
|
+
const startsTemplate = !state.inTemplateLiteral && line[pos] === '`';
|
|
274
|
+
if (inStringPortion || startsTemplate) {
|
|
275
|
+
const result = this.scanTemplateString(line, pos, state, startsTemplate);
|
|
276
|
+
tokens.push(...result.tokens);
|
|
277
|
+
pos = result.pos;
|
|
278
|
+
continue;
|
|
279
|
+
}
|
|
112
280
|
const remaining = line.slice(pos);
|
|
113
281
|
const token = this.getNextToken(remaining, pos, state);
|
|
114
282
|
if (token) {
|
|
115
283
|
tokens.push(token);
|
|
116
284
|
this.updateLastToken(token, state);
|
|
117
285
|
pos = token.end;
|
|
286
|
+
// Track brace nesting inside a ${...} interpolation so we know when it
|
|
287
|
+
// closes and we return to the template's string portion. Braces inside
|
|
288
|
+
// strings/comments are separate token types, so they aren't miscounted.
|
|
289
|
+
if (state.inTemplateLiteral &&
|
|
290
|
+
(state.templateDepth ?? 0) > 0 &&
|
|
291
|
+
token.type === 'punctuation.brace') {
|
|
292
|
+
if (token.text === '{') {
|
|
293
|
+
state.templateDepth = (state.templateDepth ?? 0) + 1;
|
|
294
|
+
}
|
|
295
|
+
else if (token.text === '}') {
|
|
296
|
+
state.templateDepth = Math.max(0, (state.templateDepth ?? 1) - 1);
|
|
297
|
+
}
|
|
298
|
+
}
|
|
118
299
|
}
|
|
119
300
|
else {
|
|
120
301
|
// No match - shouldn't happen but handle gracefully
|
|
@@ -150,10 +331,10 @@ export class JavaScriptTokenizer {
|
|
|
150
331
|
return createToken('comment.block', text, pos);
|
|
151
332
|
}
|
|
152
333
|
}
|
|
153
|
-
// Template literals
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
334
|
+
// Template literals are handled in tokenizeLine's main loop
|
|
335
|
+
// (scanTemplateString) so the string portions and the ${...} interpolation
|
|
336
|
+
// expression are tokenized separately. A backtick only reaches here while
|
|
337
|
+
// inside an interpolation (a nested template); fall through to consume it.
|
|
157
338
|
// Regular strings
|
|
158
339
|
if (text.startsWith('"') || text.startsWith("'")) {
|
|
159
340
|
return this.tokenizeString(text, pos, text[0]);
|
|
@@ -239,7 +420,11 @@ export class JavaScriptTokenizer {
|
|
|
239
420
|
if (keywords.has(word)) {
|
|
240
421
|
if (controlKeywords.has(word))
|
|
241
422
|
return 'keyword.control';
|
|
242
|
-
if (word === 'function' ||
|
|
423
|
+
if (word === 'function' ||
|
|
424
|
+
word === 'class' ||
|
|
425
|
+
word === 'const' ||
|
|
426
|
+
word === 'let' ||
|
|
427
|
+
word === 'var') {
|
|
243
428
|
return 'keyword.definition';
|
|
244
429
|
}
|
|
245
430
|
if (word === 'import' || word === 'export' || word === 'from' || word === 'as') {
|
|
@@ -253,7 +438,20 @@ export class JavaScriptTokenizer {
|
|
|
253
438
|
return 'keyword.definition';
|
|
254
439
|
}
|
|
255
440
|
// Type keywords like 'string', 'number', 'boolean' etc
|
|
256
|
-
if ([
|
|
441
|
+
if ([
|
|
442
|
+
'string',
|
|
443
|
+
'number',
|
|
444
|
+
'boolean',
|
|
445
|
+
'any',
|
|
446
|
+
'unknown',
|
|
447
|
+
'never',
|
|
448
|
+
'void',
|
|
449
|
+
'null',
|
|
450
|
+
'undefined',
|
|
451
|
+
'object',
|
|
452
|
+
'symbol',
|
|
453
|
+
'bigint'
|
|
454
|
+
].includes(word)) {
|
|
257
455
|
return 'type.builtin';
|
|
258
456
|
}
|
|
259
457
|
return 'keyword.storage';
|
|
@@ -371,59 +569,55 @@ export class JavaScriptTokenizer {
|
|
|
371
569
|
// Unterminated string at end of line
|
|
372
570
|
return createToken('string', text, pos);
|
|
373
571
|
}
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
if (text[i] === '$' && text[i + 1] === '{') {
|
|
388
|
-
// Template expression - for simplicity, tokenize up to this point
|
|
389
|
-
if (result.length > 1) {
|
|
390
|
-
// Return string part first
|
|
391
|
-
state.inTemplateLiteral = true;
|
|
392
|
-
state.templateDepth = (state.templateDepth ?? 0) + 1;
|
|
393
|
-
return createToken('string.template', result, pos);
|
|
394
|
-
}
|
|
395
|
-
}
|
|
396
|
-
result += text[i];
|
|
397
|
-
i++;
|
|
398
|
-
}
|
|
399
|
-
// Multi-line template literal
|
|
400
|
-
state.inTemplateLiteral = true;
|
|
401
|
-
return createToken('string.template', result, pos);
|
|
402
|
-
}
|
|
403
|
-
tokenizeTemplateLiteralContinuation(line, startPos, state) {
|
|
404
|
-
const tokens = [];
|
|
572
|
+
/**
|
|
573
|
+
* Scan the string portion of a template literal, starting at `startPos`. Emits
|
|
574
|
+
* one `string.template` token for the run of literal characters and stops at one
|
|
575
|
+
* of three boundaries:
|
|
576
|
+
* - a closing backtick → ends the literal (clears template state);
|
|
577
|
+
* - a `${` → emits the `${` delimiter and enters interpolation
|
|
578
|
+
* (templateDepth = 1) so the expression is tokenized as code by the caller;
|
|
579
|
+
* - end of line → the literal spans lines and continues next line.
|
|
580
|
+
*
|
|
581
|
+
* `isStart` is true when this is the opening backtick (vs. a continuation of a
|
|
582
|
+
* multi-line literal or the resumption after a `${…}` interpolation).
|
|
583
|
+
*/
|
|
584
|
+
scanTemplateString(line, startPos, state, isStart) {
|
|
405
585
|
let pos = startPos;
|
|
406
586
|
let result = '';
|
|
587
|
+
if (isStart) {
|
|
588
|
+
state.inTemplateLiteral = true;
|
|
589
|
+
state.templateDepth = 0;
|
|
590
|
+
result = '`';
|
|
591
|
+
pos += 1;
|
|
592
|
+
}
|
|
407
593
|
while (pos < line.length) {
|
|
408
|
-
|
|
594
|
+
const ch = line[pos];
|
|
595
|
+
if (ch === '\\' && pos + 1 < line.length) {
|
|
409
596
|
result += line.slice(pos, pos + 2);
|
|
410
597
|
pos += 2;
|
|
411
598
|
continue;
|
|
412
599
|
}
|
|
413
|
-
if (
|
|
600
|
+
if (ch === '`') {
|
|
414
601
|
result += '`';
|
|
415
|
-
tokens.push(createToken('string.template', result, startPos));
|
|
416
602
|
state.inTemplateLiteral = false;
|
|
417
|
-
state.templateDepth =
|
|
418
|
-
return { tokens, pos: pos + 1 };
|
|
603
|
+
state.templateDepth = 0;
|
|
604
|
+
return { tokens: [createToken('string.template', result, startPos)], pos: pos + 1 };
|
|
419
605
|
}
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
606
|
+
if (ch === '$' && line[pos + 1] === '{') {
|
|
607
|
+
const tokens = [];
|
|
608
|
+
if (result) {
|
|
609
|
+
tokens.push(createToken('string.template', result, startPos));
|
|
610
|
+
}
|
|
611
|
+
tokens.push(createToken('string.template', '${', startPos + result.length));
|
|
612
|
+
state.templateDepth = 1;
|
|
613
|
+
return { tokens, pos: pos + 2 };
|
|
614
|
+
}
|
|
615
|
+
result += ch;
|
|
616
|
+
pos += 1;
|
|
425
617
|
}
|
|
426
|
-
|
|
618
|
+
// End of line inside the string portion → multi-line template literal.
|
|
619
|
+
state.inTemplateLiteral = true;
|
|
620
|
+
return { tokens: result ? [createToken('string.template', result, startPos)] : [], pos };
|
|
427
621
|
}
|
|
428
622
|
tokenizeJSXTag(text, pos, _state) {
|
|
429
623
|
// Simple JSX tag detection
|
|
@@ -4,29 +4,126 @@
|
|
|
4
4
|
import { createToken } from '../base';
|
|
5
5
|
// Python keywords
|
|
6
6
|
const keywords = new Set([
|
|
7
|
-
'and',
|
|
8
|
-
'
|
|
9
|
-
'
|
|
10
|
-
'
|
|
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',
|
|
14
|
-
'
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
'
|
|
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',
|
|
21
|
-
'
|
|
22
|
-
'
|
|
23
|
-
'
|
|
24
|
-
'
|
|
25
|
-
'
|
|
26
|
-
'
|
|
27
|
-
'
|
|
28
|
-
'
|
|
29
|
-
'
|
|
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',
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
'
|
|
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:',
|
|
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:
|
|
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:
|
|
283
|
+
transition:
|
|
284
|
+
opacity 0.1s ease,
|
|
285
|
+
filter 0.1s ease;
|
|
282
286
|
}
|
|
283
287
|
|
|
284
288
|
.ide-layout__status-bar {
|