ripple 0.2.184 → 0.2.186

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/package.json CHANGED
@@ -3,7 +3,7 @@
3
3
  "description": "Ripple is an elegant TypeScript UI framework",
4
4
  "license": "MIT",
5
5
  "author": "Dominic Gannaway",
6
- "version": "0.2.184",
6
+ "version": "0.2.186",
7
7
  "type": "module",
8
8
  "module": "src/runtime/index-client.js",
9
9
  "main": "src/runtime/index-client.js",
@@ -86,6 +86,6 @@
86
86
  "vscode-languageserver-types": "^3.17.5"
87
87
  },
88
88
  "peerDependencies": {
89
- "ripple": "0.2.184"
89
+ "ripple": "0.2.186"
90
90
  }
91
91
  }
@@ -24,6 +24,12 @@ export interface CompileResult {
24
24
  css: string;
25
25
  }
26
26
 
27
+ export interface DefinitionLocation {
28
+ embeddedId: string; // e.g., 'style_0', 'style_1'
29
+ start: number; // start offset
30
+ end: number; // end offset
31
+ }
32
+
27
33
  export interface PluginActionOverrides {
28
34
  /** Whether to enable word document highlighting for this mapping */
29
35
  wordHighlight?: {
@@ -40,13 +46,17 @@ export interface PluginActionOverrides {
40
46
  /** Custom definition info for this mapping, false to disable */
41
47
  definition?:
42
48
  | {
43
- description: string;
49
+ description?: string; // just for reference
50
+ // Generic location for embedded content (CSS, etc.)
51
+ location?: DefinitionLocation;
44
52
  }
45
53
  | false;
46
54
  }
47
55
 
48
56
  export interface CustomMappingData extends PluginActionOverrides {
49
57
  generatedLengths: number[];
58
+ embeddedId?: string; // e.g. css regions: 'style_0', 'style_1', etc.
59
+ content?: string; // (e.g., css code)
50
60
  }
51
61
 
52
62
  export interface MappingData extends VolarCodeInformation {
@@ -61,7 +71,6 @@ export interface VolarMappingsResult {
61
71
  code: string;
62
72
  mappings: CodeMapping[];
63
73
  cssMappings: CodeMapping[];
64
- cssSources: string[];
65
74
  }
66
75
 
67
76
  /**
@@ -1,13 +1,10 @@
1
- /** @import * as AST from 'estree' */
2
- /** @import * as ESTreeJSX from 'estree-jsx' */
3
- /** @import { Parse } from '#parser' */
4
-
5
1
  /**
6
- * @import {
7
- * RipplePluginConfig
8
- * } from '#compiler' */
9
-
10
- /** @import { ParseOptions } from 'ripple/compiler' */
2
+ @import * as AST from 'estree'
3
+ @import * as ESTreeJSX from 'estree-jsx'
4
+ @import { Parse } from '#parser'
5
+ @import { RipplePluginConfig } from '#compiler';
6
+ @import { ParseOptions } from 'ripple/compiler'
7
+ */
11
8
 
12
9
  import * as acorn from 'acorn';
13
10
  import { tsPlugin } from '@sveltejs/acorn-typescript';
@@ -1741,6 +1738,7 @@ function RipplePlugin(config) {
1741
1738
  throw new Error('Components can only have one style tag');
1742
1739
  }
1743
1740
  component.css = parsed_css;
1741
+ /** @type {AST.Element} */ (element).metadata.styleScopeHash = parsed_css.hash;
1744
1742
  }
1745
1743
 
1746
1744
  const newLines = content.match(regex_newline_characters)?.length;
@@ -2167,6 +2165,7 @@ function RipplePlugin(config) {
2167
2165
  * @param {string} source
2168
2166
  * @param {AST.CommentWithLocation[]} comments
2169
2167
  * @param {number} [index=0] - Starting index
2168
+ * @returns {{onComment: Parse.Options['onComment'], add_comments: (ast: AST.Node) => void}}
2170
2169
  */
2171
2170
  function get_comment_handlers(source, comments, index = 0) {
2172
2171
  /**
@@ -2230,11 +2229,7 @@ function get_comment_handlers(source, comments, index = 0) {
2230
2229
  context,
2231
2230
  }));
2232
2231
 
2233
- /**
2234
- * @param {AST.Node} ast
2235
- */
2236
2232
  walk(ast, null, {
2237
- /** @param {AST.Node} node */
2238
2233
  _(node, { next, path }) {
2239
2234
  const metadata = node?.metadata;
2240
2235
 
@@ -41,7 +41,7 @@ function is_global(relative_selector) {
41
41
  export function analyze_css(css) {
42
42
  walk(
43
43
  css,
44
- { rule: /** @type {AST.CSS.Rule | null} */ (null) },
44
+ /** @type {{ rule: AST.CSS.Rule | null }} */ ({ rule: null }),
45
45
  {
46
46
  Rule(node, context) {
47
47
  node.metadata.parent_rule = context.state.rule;
@@ -90,7 +90,7 @@ export function analyze_css(css) {
90
90
  // Set the rule metadata before analyzing children
91
91
  node.metadata.rule = context.state.rule;
92
92
 
93
- context.next(); // analyse relevant selectors first
93
+ context.next(); // analyze relevant selectors first
94
94
 
95
95
  {
96
96
  const global = node.children.find(is_global);
@@ -6,7 +6,6 @@
6
6
  AnalysisContext,
7
7
  ScopeInterface,
8
8
  Visitors,
9
- Visitor,
10
9
  } from '#compiler';
11
10
  */
12
11
  /** @import * as AST from 'estree' */
@@ -423,6 +422,11 @@ const visitors = {
423
422
  context.visit(node.discriminant, context.state);
424
423
 
425
424
  for (const switch_case of node.cases) {
425
+ // Fallthrough
426
+ if (switch_case.consequent.length === 0) {
427
+ continue;
428
+ }
429
+
426
430
  // Validate that each cases ends in a break statement, except for the last case
427
431
  const last = switch_case.consequent?.[switch_case.consequent.length - 1];
428
432
 
@@ -5,13 +5,17 @@
5
5
  import { walk } from 'zimmerframe';
6
6
  import { is_element_dom_element } from '../../utils.js';
7
7
 
8
- const seen = new Set();
9
8
  const regex_backslash_and_following_character = /\\(.)/g;
10
9
  /** @type {Direction} */
11
10
  const FORWARD = 0;
12
11
  /** @type {Direction} */
13
12
  const BACKWARD = 1;
14
13
 
14
+ // this will be set for every prune_css call
15
+ // since the code is synchronous, this is safe
16
+ /** @type {string} */
17
+ let css_hash;
18
+
15
19
  // CSS selector constants
16
20
  /**
17
21
  * @param {number} start
@@ -196,6 +200,47 @@ function apply_selector(relative_selectors, rule, element, direction) {
196
200
  if (matched) {
197
201
  if (!is_outer_global(relative_selector)) {
198
202
  relative_selector.metadata.scoped = true;
203
+
204
+ // Store scoped class information on element for language server features
205
+ if (!relative_selector.metadata.is_global && !relative_selector.metadata.is_global_like) {
206
+ // Extract class selectors from the relative selector
207
+ for (const selector of relative_selector.selectors) {
208
+ if (selector.type === 'ClassSelector') {
209
+ const name = selector.name.replace(regex_backslash_and_following_character, '$1');
210
+
211
+ if (!element.metadata.css) {
212
+ element.metadata.css = {
213
+ scopedClasses: new Map(),
214
+ topScopedClasses: new Map(),
215
+ hash: css_hash,
216
+ };
217
+ }
218
+
219
+ // Store class name → CSS location in scopedClasses
220
+ if (!element.metadata.css.scopedClasses.has(name)) {
221
+ element.metadata.css.scopedClasses.set(name, {
222
+ start: selector.start,
223
+ end: selector.end,
224
+ selector: selector,
225
+ });
226
+ }
227
+
228
+ // Also store in topScopedClasses if standalone
229
+ // Standalone = only this ClassSelector in the RelativeSelector, no pseudo-classes/elements
230
+ const isStandalone =
231
+ relative_selector.selectors.length === 1 &&
232
+ relative_selector.selectors[0] === selector;
233
+
234
+ if (isStandalone && !element.metadata.css.topScopedClasses.has(name)) {
235
+ element.metadata.css.topScopedClasses.set(name, {
236
+ start: selector.start,
237
+ end: selector.end,
238
+ selector: selector,
239
+ });
240
+ }
241
+ }
242
+ }
243
+ }
199
244
  }
200
245
 
201
246
  element.metadata.scoped = true;
@@ -1005,6 +1050,8 @@ function rule_has_animation(rule) {
1005
1050
  * @return {void}
1006
1051
  */
1007
1052
  export function prune_css(css, element) {
1053
+ css_hash = css.hash;
1054
+
1008
1055
  /** @type {Visitors<AST.CSS.Node, null>} */
1009
1056
  const visitors = {
1010
1057
  Rule(node, context) {
@@ -1017,8 +1064,6 @@ export function prune_css(css, element) {
1017
1064
  ComplexSelector(node, context) {
1018
1065
  const selectors = get_relative_selectors(node);
1019
1066
 
1020
- seen.clear();
1021
-
1022
1067
  const rule = /** @type {AST.CSS.Rule} */ (node.metadata.rule);
1023
1068
 
1024
1069
  if (apply_selector(selectors, rule, element, BACKWARD) || rule_has_animation(rule)) {