@ripple-ts/language-server 0.3.3 → 0.3.4

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/CHANGELOG.md CHANGED
@@ -1,5 +1,12 @@
1
1
  # @ripple-ts/language-server
2
2
 
3
+ ## 0.3.4
4
+
5
+ ### Patch Changes
6
+
7
+ - Updated dependencies []:
8
+ - @ripple-ts/typescript-plugin@0.3.4
9
+
3
10
  ## 0.3.3
4
11
 
5
12
  ### Patch Changes
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ripple-ts/language-server",
3
- "version": "0.3.3",
3
+ "version": "0.3.4",
4
4
  "description": "Language Server Protocol implementation for Ripple",
5
5
  "main": "index.js",
6
6
  "bin": {
@@ -19,10 +19,10 @@
19
19
  "volar-service-typescript": "0.0.70",
20
20
  "vscode-languageserver-textdocument": "^1.0.12",
21
21
  "vscode-uri": "^3.1.0",
22
- "@ripple-ts/typescript-plugin": "0.3.3"
22
+ "@ripple-ts/typescript-plugin": "0.3.4"
23
23
  },
24
24
  "devDependencies": {
25
- "ripple": "0.3.3"
25
+ "ripple": "0.3.4"
26
26
  },
27
27
  "peerDependencies": {
28
28
  "typescript": "^5.9.3"
@@ -171,32 +171,24 @@ function generateImportEdit(documentText, importName) {
171
171
  */
172
172
  const RIPPLE_SNIPPETS = [
173
173
  {
174
- label: '#ripple.',
174
+ label: '#style',
175
175
  kind: CompletionItemKind.Snippet,
176
- detail: 'Ripple namespace APIs',
176
+ detail: 'Scoped CSS class reference',
177
177
  documentation:
178
- 'Type #ripple. to access all built-in Ripple namespace APIs (track, map, set, style, server, etc.).',
179
- insertText: '#ripple.',
178
+ 'Produces a scoped CSS class string for passing to child components.\nThe class must be defined as a standalone selector in <style>.\n\nUsage: <Child cls={#style.highlight} />',
179
+ insertText: '#style.${1:className}',
180
180
  insertTextFormat: InsertTextFormat.Snippet,
181
- sortText: '0-#-namespace',
181
+ sortText: '0-#-style',
182
182
  },
183
183
  {
184
- label: '#ripple[]',
184
+ label: '#server',
185
185
  kind: CompletionItemKind.Snippet,
186
- detail: 'Ripple Reactive Array Literal, shorthand for new RippleArray',
187
- documentation: 'Create a new Ripple Array Literal',
188
- insertText: '#ripple[${1}]',
189
- insertTextFormat: InsertTextFormat.Snippet,
190
- sortText: '0-#-array-literal',
191
- },
192
- {
193
- label: '#ripple{}',
194
- kind: CompletionItemKind.Snippet,
195
- detail: 'Ripple Reactive Object Literal, shorthand for new RippleObject',
196
- documentation: 'Create a new Ripple Object Literal',
197
- insertText: '#ripple{${1}}',
186
+ detail: 'Server-only code block (module level)',
187
+ documentation:
188
+ 'Marks a block as server-only. Code inside is tree-shaken on the client.\nMust be at module top level.\n\nUsage:\n#server {\n export async function loadData() { ... }\n}',
189
+ insertText: '#server {\n\t$0\n}',
198
190
  insertTextFormat: InsertTextFormat.Snippet,
199
- sortText: '0-#-object-literal',
191
+ sortText: '0-#-server',
200
192
  },
201
193
  {
202
194
  label: 'component',
@@ -331,174 +323,6 @@ const RIPPLE_SNIPPETS = [
331
323
  },
332
324
  ];
333
325
 
334
- /**
335
- * All #ripple.* namespace completions — no imports required.
336
- * Shown when the cursor follows `#ripple` or `#ripple.`
337
- * @type {CompletionItem[]}
338
- */
339
- const RIPPLE_NAMESPACE_SNIPPETS = [
340
- {
341
- label: '#ripple.track',
342
- kind: CompletionItemKind.Snippet,
343
- detail: 'Reactive tracked value (no import needed)',
344
- documentation:
345
- 'Creates a reactive tracked value. Equivalent to track() but requires no import.\n\nUsage: let count = #ripple.track(0);\nDerived: let double = #ripple.track(() => @count * 2);',
346
- insertText: '#ripple.track(${1:initialValue})',
347
- insertTextFormat: InsertTextFormat.Snippet,
348
- sortText: '0-ripple-track',
349
- },
350
- {
351
- label: '#ripple.trackSplit',
352
- kind: CompletionItemKind.Snippet,
353
- detail: 'Reactive prop splitting (no import needed)',
354
- documentation:
355
- "Destructures props while preserving reactivity. Equivalent to trackSplit() but requires no import.\n\nUsage: const [children, rest] = #ripple.trackSplit(props, ['children']);",
356
- insertText: "#ripple.trackSplit(${1:props}, ['${2:children}'])",
357
- insertTextFormat: InsertTextFormat.Snippet,
358
- sortText: '0-ripple-trackSplit',
359
- },
360
- {
361
- label: '#ripple.effect',
362
- kind: CompletionItemKind.Snippet,
363
- detail: 'Reactive effect (no import needed)',
364
- documentation:
365
- 'Registers a reactive side effect. Equivalent to effect() but requires no import.\n\nUsage: #ripple.effect(() => {\n console.log(@count);\n});',
366
- insertText: '#ripple.effect(() => {\n\t$0\n})',
367
- insertTextFormat: InsertTextFormat.Snippet,
368
- sortText: '0-ripple-effect',
369
- },
370
- {
371
- label: '#ripple.untrack',
372
- kind: CompletionItemKind.Snippet,
373
- detail: 'Read without dependency tracking (no import needed)',
374
- documentation:
375
- 'Reads reactive values without creating dependencies. Equivalent to untrack() but requires no import.\n\nUsage: const snapshot = #ripple.untrack(() => @count);',
376
- insertText: '#ripple.untrack(() => ${1:@value})',
377
- insertTextFormat: InsertTextFormat.Snippet,
378
- sortText: '0-ripple-untrack',
379
- },
380
- {
381
- label: '#ripple.validate',
382
- kind: CompletionItemKind.Snippet,
383
- detail: 'Validation wrapper (no import needed)',
384
- documentation:
385
- "Wraps a value with validation logic.\n\nUsage: let email = #ripple.validate(#ripple.track(''));",
386
- insertText: '#ripple.validate(${1})',
387
- insertTextFormat: InsertTextFormat.Snippet,
388
- sortText: '0-ripple-validate',
389
- },
390
- {
391
- label: '#ripple.context',
392
- kind: CompletionItemKind.Snippet,
393
- detail: 'Create a Context (no import needed)',
394
- documentation:
395
- "Creates a reactive context. Equivalent to new Context() but requires no import.\n\nUsage: const ThemeCtx = #ripple.context('light');",
396
- insertText: '#ripple.context(${1:defaultValue})',
397
- insertTextFormat: InsertTextFormat.Snippet,
398
- sortText: '0-ripple-context',
399
- },
400
- {
401
- label: '#ripple.array',
402
- kind: CompletionItemKind.Snippet,
403
- detail: 'RippleArray class reference (no import needed)',
404
- documentation:
405
- 'Reference to the RippleArray class. Use for static methods or as a type annotation.\n\nUsage: const copy = #ripple.array.from(existing);',
406
- insertText: '#ripple.array',
407
- insertTextFormat: InsertTextFormat.Snippet,
408
- sortText: '0-ripple-array',
409
- },
410
- {
411
- label: '#ripple.object',
412
- kind: CompletionItemKind.Snippet,
413
- detail: 'RippleObject class reference (no import needed)',
414
- documentation:
415
- 'Reference to the RippleObject class. Use for static methods or as a type annotation.\n\nUsage: const obj = #ripple.object({ a: 1 });',
416
- insertText: '#ripple.object',
417
- insertTextFormat: InsertTextFormat.Snippet,
418
- sortText: '0-ripple-object',
419
- },
420
- {
421
- label: '#ripple.map',
422
- kind: CompletionItemKind.Snippet,
423
- detail: 'RippleMap (no import needed)',
424
- documentation:
425
- 'Creates a reactive Map. Equivalent to new RippleMap() but requires no import.\n\nUsage: const map = #ripple.map([[key, value]]);',
426
- insertText: '#ripple.map(${1})',
427
- insertTextFormat: InsertTextFormat.Snippet,
428
- sortText: '0-ripple-map',
429
- },
430
- {
431
- label: '#ripple.set',
432
- kind: CompletionItemKind.Snippet,
433
- detail: 'RippleSet (no import needed)',
434
- documentation:
435
- 'Creates a reactive Set. Equivalent to new RippleSet() but requires no import.\n\nUsage: const set = #ripple.set([1, 2, 3]);',
436
- insertText: '#ripple.set(${1})',
437
- insertTextFormat: InsertTextFormat.Snippet,
438
- sortText: '0-ripple-set',
439
- },
440
- {
441
- label: '#ripple.date',
442
- kind: CompletionItemKind.Snippet,
443
- detail: 'RippleDate (no import needed)',
444
- documentation:
445
- 'Creates a reactive Date. Equivalent to new RippleDate() but requires no import.\n\nUsage: const today = #ripple.date();',
446
- insertText: '#ripple.date(${1})',
447
- insertTextFormat: InsertTextFormat.Snippet,
448
- sortText: '0-ripple-date',
449
- },
450
- {
451
- label: '#ripple.url',
452
- kind: CompletionItemKind.Snippet,
453
- detail: 'RippleURL (no import needed)',
454
- documentation:
455
- "Creates a reactive URL. Equivalent to new RippleURL() but requires no import.\n\nUsage: const url = #ripple.url('https://example.com');",
456
- insertText: "#ripple.url('${1:https://example.com}')",
457
- insertTextFormat: InsertTextFormat.Snippet,
458
- sortText: '0-ripple-url',
459
- },
460
- {
461
- label: '#ripple.urlSearchParams',
462
- kind: CompletionItemKind.Snippet,
463
- detail: 'RippleURLSearchParams (no import needed)',
464
- documentation:
465
- 'Creates a reactive URLSearchParams. Equivalent to new RippleURLSearchParams() but requires no import.\n\nUsage: const params = #ripple.urlSearchParams(${1});',
466
- insertText: '#ripple.urlSearchParams(${1})',
467
- insertTextFormat: InsertTextFormat.Snippet,
468
- sortText: '0-ripple-urlSearchParams',
469
- },
470
- {
471
- label: '#ripple.mediaQuery',
472
- kind: CompletionItemKind.Snippet,
473
- detail: 'Reactive CSS media query (no import needed)',
474
- documentation:
475
- "Creates a reactive media query that tracks whether the query currently matches.\n\nUsage: const isMobile = #ripple.mediaQuery('(max-width: 768px)');",
476
- insertText: "#ripple.mediaQuery('${1:(max-width: 768px)}')",
477
- insertTextFormat: InsertTextFormat.Snippet,
478
- sortText: '0-ripple-mediaQuery',
479
- },
480
- {
481
- label: '#ripple.style',
482
- kind: CompletionItemKind.Snippet,
483
- detail: 'Scoped CSS class reference (no import needed)',
484
- documentation:
485
- 'Produces a scoped CSS class string for passing to child components.\nThe class must be defined as a standalone selector in <style>.\n\nUsage: <Child cls={#ripple.style.highlight} />',
486
- insertText: '#ripple.style.${1:className}',
487
- insertTextFormat: InsertTextFormat.Snippet,
488
- sortText: '0-ripple-style',
489
- },
490
- {
491
- label: '#ripple.server',
492
- kind: CompletionItemKind.Snippet,
493
- detail: 'Server-only code block (module level)',
494
- documentation:
495
- 'Marks a block as server-only. Code inside is tree-shaken on the client.\nMust be at module top level.\n\nUsage:\n#ripple.server {\n export async function loadData() { ... }\n}',
496
- insertText: '#ripple.server {\n\t$0\n}',
497
- insertTextFormat: InsertTextFormat.Snippet,
498
- sortText: '0-ripple-server',
499
- },
500
- ];
501
-
502
326
  /**
503
327
  * Import suggestions for Ripple
504
328
  */
@@ -545,38 +369,6 @@ const RIPPLE_IMPORTS = [
545
369
  // },
546
370
  ];
547
371
 
548
- /**
549
- * @param {string} line
550
- * @returns {RegExpMatchArray | null}
551
- */
552
- function get_ripple_namespace_match(line) {
553
- return line.match(/#ripple(?:\.(\w*))?$/);
554
- }
555
-
556
- /**
557
- * @param {RegExpMatchArray} namespace_match
558
- * @param {{ line: number, character: number }} position
559
- * @returns {CompletionItem[]}
560
- */
561
- function create_ripple_namespace_completion_items(namespace_match, position) {
562
- const start_character = position.character - namespace_match[0].length;
563
-
564
- return RIPPLE_NAMESPACE_SNIPPETS.map((snippet) => ({
565
- ...snippet,
566
- filterText: snippet.label,
567
- textEdit: {
568
- range: {
569
- start: {
570
- line: position.line,
571
- character: start_character,
572
- },
573
- end: position,
574
- },
575
- newText: snippet.insertText ?? snippet.label,
576
- },
577
- }));
578
- }
579
-
580
372
  /**
581
373
  * @returns {LanguageServicePlugin}
582
374
  */
@@ -587,9 +379,8 @@ function createCompletionPlugin() {
587
379
  completionProvider: {
588
380
  // Trigger on Ripple-specific syntax:
589
381
  // '<' - JSX/HTML tags
590
- // '#' - RippleMap/RippleSet shortcuts
591
- // '.' - #ripple namespace member access
592
- triggerCharacters: ['<', '#', '.'],
382
+ // '#' - #style, #server keywords
383
+ triggerCharacters: ['<', '#'],
593
384
  resolveProvider: false,
594
385
  },
595
386
  },
@@ -648,15 +439,6 @@ function createCompletionPlugin() {
648
439
  return { items, isIncomplete: false };
649
440
  }
650
441
 
651
- const ripple_namespace_match = get_ripple_namespace_match(line);
652
-
653
- if (ripple_namespace_match) {
654
- items.push(
655
- ...create_ripple_namespace_completion_items(ripple_namespace_match, position),
656
- );
657
- return { items, isIncomplete: false };
658
- }
659
-
660
442
  // @ accessor hint when typing after @
661
443
  if (/@\w*$/.test(line)) {
662
444
  items.push({
@@ -667,9 +449,9 @@ function createCompletionPlugin() {
667
449
  });
668
450
  }
669
451
 
670
- // RippleMap/RippleSet completions when typing T...
452
+ // RippleMap/RippleSet completions when typing R, M...
671
453
  // Also detects if 'new' is already typed before it to avoid duplicating
672
- const trackedMatch = line.match(/(new\s+)?[T,M,#]([\w\.]*)$/);
454
+ const trackedMatch = line.match(/(new\s+)?[R,M]([\w\.]*)$/);
673
455
 
674
456
  if (trackedMatch) {
675
457
  const hasNew = !!trackedMatch[1];