@tsrx/core 0.1.16 → 0.1.18

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/src/utils/ast.js CHANGED
@@ -37,12 +37,7 @@ export function is_function_node(node) {
37
37
  * @returns {boolean}
38
38
  */
39
39
  export function is_function_or_component_node(node) {
40
- return (
41
- node.type === 'FunctionDeclaration' ||
42
- node.type === 'FunctionExpression' ||
43
- node.type === 'ArrowFunctionExpression' ||
44
- node.type === 'Component'
45
- );
40
+ return is_function_node(node);
46
41
  }
47
42
 
48
43
  /**
@@ -54,32 +49,29 @@ export function is_class_node(node) {
54
49
  }
55
50
 
56
51
  /**
57
- * @param {AST.Node} node
58
- * @returns {boolean}
59
- */
60
- export function is_component_node(node) {
61
- return node.type === 'Component';
62
- }
63
-
64
- /**
65
- * Returns the closest component in an ancestry path. By default, function and
66
- * class boundaries stop the search so callers only match direct component
67
- * body/control-flow nodes.
52
+ * Returns the closest native TSRX function in an ancestry path. By default,
53
+ * function and class boundaries stop the search so callers only match direct
54
+ * native TSRX function body/control-flow nodes.
68
55
  *
69
56
  * @param {AST.Node[]} path
70
57
  * @param {boolean} [includes_functions=false]
71
- * @returns {AST.Component | undefined}
58
+ * @returns {AST.Function | undefined}
72
59
  */
73
60
  export function get_component_from_path(path, includes_functions = false) {
74
61
  for (let i = path.length - 1; i >= 0; i -= 1) {
75
62
  const node = path[i];
76
63
 
77
- if (!includes_functions && (is_function_node(node) || is_class_node(node))) {
78
- return;
64
+ if (is_function_node(node)) {
65
+ if (/** @type {any} */ (node).metadata?.native_tsrx_function) {
66
+ return /** @type {AST.Function} */ (node);
67
+ }
68
+ if (!includes_functions) {
69
+ return;
70
+ }
79
71
  }
80
72
 
81
- if (is_component_node(node)) {
82
- return /** @type {AST.Component} */ (node);
73
+ if (!includes_functions && is_class_node(node)) {
74
+ return;
83
75
  }
84
76
  }
85
77
  }
@@ -87,7 +79,7 @@ export function get_component_from_path(path, includes_functions = false) {
87
79
  /**
88
80
  * @param {AST.Node[] | { path: AST.Node[] }} context_or_path
89
81
  * @param {boolean} [includes_functions=false]
90
- * @returns {AST.Component | undefined}
82
+ * @returns {AST.Function | undefined}
91
83
  */
92
84
  export function is_inside_component(context_or_path, includes_functions = false) {
93
85
  const path = Array.isArray(context_or_path) ? context_or_path : context_or_path.path;
@@ -77,24 +77,6 @@ export function arrow(params, body, async = false, type_parameters, loc_info) {
77
77
  return set_location(node, loc_info);
78
78
  }
79
79
 
80
- /**
81
- * @param {AST.Identifier} id
82
- * @param {AST.Pattern[]} params
83
- * @param {AST.Node[]} body
84
- * @returns {AST.Component}
85
- */
86
- export function component(id, params, body) {
87
- return {
88
- type: 'Component',
89
- id,
90
- params,
91
- body,
92
- css: null,
93
- metadata: { path: [] },
94
- default: false,
95
- };
96
- }
97
-
98
80
  /**
99
81
  * @param {AST.AssignmentOperator} operator
100
82
  * @param {AST.Pattern} left
package/types/index.d.ts CHANGED
@@ -11,7 +11,6 @@ import type {
11
11
  JsxTransformContext,
12
12
  JsxTransformOptions,
13
13
  JsxTransformResult,
14
- componentToFunctionDeclaration,
15
14
  createJsxTransform,
16
15
  } from './jsx-platform';
17
16
 
@@ -23,7 +22,21 @@ export type {
23
22
  JsxTransformOptions,
24
23
  JsxTransformResult,
25
24
  };
26
- export { createJsxTransform, componentToFunctionDeclaration };
25
+ export { createJsxTransform };
26
+
27
+ export function collectStyleRefAttributes(node: any, refs?: any[]): any[];
28
+ export function createStyleClassMap(component: any, css: any): AST.ObjectExpression;
29
+ export function createStyleClassMapFromStylesheet(css: any): AST.ObjectExpression;
30
+ export function createStyleRefSetupStatements(
31
+ refAttributes: any[],
32
+ styleMap: AST.Expression,
33
+ options?: {
34
+ allowMutableRefTarget?: boolean;
35
+ createTempIdentifier?: () => AST.Identifier;
36
+ visitExpression?: (expression: AST.Expression) => AST.Expression;
37
+ },
38
+ ): AST.Statement[];
39
+ export function getStyleElementStylesheet(styleElement: any): any | null;
27
40
 
28
41
  /**
29
42
  * Compile error interface
@@ -77,10 +90,11 @@ interface BaseNodeMetaData {
77
90
  has_continue?: boolean;
78
91
  is_reactive?: boolean;
79
92
  lone_return?: boolean;
93
+ regular_js?: boolean;
94
+ returned_tsrx_child?: boolean;
80
95
  forceMapping?: boolean;
81
96
  lazy_id?: string;
82
97
  disable_verification?: boolean;
83
- lazy_param_is_component?: boolean;
84
98
  lazy_param_binding_mappings?: Array<{
85
99
  source: AST.Identifier;
86
100
  generated: AST.Identifier | AST.Literal;
@@ -88,11 +102,11 @@ interface BaseNodeMetaData {
88
102
  }
89
103
 
90
104
  interface FunctionMetaData extends BaseNodeMetaData {
91
- // needed for volar tokens to recognize component functions
92
- is_component?: boolean;
105
+ native_tsrx_function?: boolean;
93
106
  is_method?: boolean;
94
107
  tracked?: boolean;
95
108
  has_lazy_descendants?: boolean;
109
+ synthetic_children?: boolean;
96
110
  }
97
111
 
98
112
  // Strip parent, loc, and range from TSESTree nodes to match @sveltejs/acorn-typescript output
@@ -142,6 +156,13 @@ declare module 'estree' {
142
156
  };
143
157
  }
144
158
 
159
+ interface ReturnStatement {
160
+ metadata: BaseNodeMetaData & {
161
+ invalid_tsrx_template_return?: boolean;
162
+ generated_loop_continue_return?: boolean;
163
+ };
164
+ }
165
+
145
166
  type Accessibility = 'public' | 'protected' | 'private'; // missing in acorn-typescript types
146
167
  interface MethodDefinition {
147
168
  typeParameters?: TSTypeParameterDeclaration;
@@ -204,26 +225,19 @@ declare module 'estree' {
204
225
 
205
226
  // Include TypeScript node types and TSRX-specific nodes in NodeMap
206
227
  interface NodeMap {
207
- Component: Component;
208
228
  Tsx: Tsx;
209
229
  Tsrx: Tsrx;
210
230
  TsxCompat: TsxCompat;
211
231
  TSRXExpression: TSRXExpression;
212
- Html: Html;
213
- Style: Style;
214
232
  Element: Element;
215
233
  Text: TextNode;
216
234
  Attribute: Attribute;
217
- RefAttribute: RefAttribute;
218
- RefExpression: RefExpression;
219
235
  SpreadAttribute: SpreadAttribute;
220
236
  ParenthesizedExpression: ParenthesizedExpression;
221
237
  ScriptContent: ScriptContent;
222
238
  }
223
239
 
224
240
  interface ExpressionMap {
225
- Style: Style;
226
- RefExpression: RefExpression;
227
241
  Text: TextNode;
228
242
  JSXEmptyExpression: ESTreeJSX.JSXEmptyExpression;
229
243
  ParenthesizedExpression: ParenthesizedExpression;
@@ -319,25 +333,6 @@ declare module 'estree' {
319
333
  trailingComments?: AST.Comment[] | undefined;
320
334
  }
321
335
 
322
- /**
323
- * TSRX custom interfaces and types section
324
- */
325
- interface Component extends AST.BaseNode {
326
- type: 'Component';
327
- // null is for anonymous components, e.g. `component(props) => {}`
328
- id: AST.Identifier | null;
329
- params: AST.Pattern[];
330
- body: AST.Node[];
331
- css: CSS.StyleSheet | null;
332
- metadata: BaseNodeMetaData & {
333
- arrow?: boolean;
334
- topScopedClasses?: TopScopedClasses;
335
- styleClasses?: StyleClasses;
336
- };
337
- default: boolean;
338
- typeParameters?: AST.TSTypeParameterDeclaration;
339
- }
340
-
341
336
  interface Tsx extends AST.BaseNode {
342
337
  type: 'Tsx';
343
338
  attributes: Array<any>;
@@ -369,17 +364,6 @@ declare module 'estree' {
369
364
  closingElement: ESTreeJSX.JSXClosingElement;
370
365
  }
371
366
 
372
- interface Html extends AST.BaseNode {
373
- type: 'Html';
374
- expression: AST.Expression;
375
- }
376
-
377
- interface Style extends AST.BaseExpression {
378
- type: 'Style';
379
- value: AST.Literal;
380
- loc?: AST.SourceLocation;
381
- }
382
-
383
367
  export interface TSRXExpression extends AST.BaseExpression {
384
368
  type: 'TSRXExpression';
385
369
  expression: AST.Expression;
@@ -445,49 +429,23 @@ declare module 'estree' {
445
429
  };
446
430
  }
447
431
 
448
- interface RefAttribute extends AST.BaseNode {
449
- type: 'RefAttribute';
450
- argument: AST.Expression;
451
- loc?: AST.SourceLocation;
452
- }
453
-
454
- interface RefExpression extends AST.BaseNode {
455
- type: 'RefExpression';
456
- argument: AST.Expression;
457
- loc?: AST.SourceLocation;
458
- }
459
-
460
432
  interface SpreadAttribute extends AST.BaseNode {
461
433
  type: 'SpreadAttribute';
462
434
  argument: AST.Expression;
463
435
  loc?: AST.SourceLocation;
464
436
  }
465
437
 
466
- /**
467
- * TSRX's extended Declaration type that includes Component
468
- * Use this instead of Declaration when you need Component support
469
- */
470
- export type TSRXDeclaration = AST.Declaration | Component | AST.TSDeclareFunction;
438
+ export type TSRXDeclaration = AST.Declaration | AST.TSDeclareFunction;
471
439
 
472
- /**
473
- * TSRX's extended ExportNamedDeclaration with Component support
474
- */
475
440
  interface TSRXExportNamedDeclaration extends Omit<AST.ExportNamedDeclaration, 'declaration'> {
476
441
  declaration?: TSRXDeclaration | null | undefined;
477
442
  }
478
443
 
479
- /**
480
- * TSRX's extended Program with Component support
481
- */
482
444
  interface TSRXProgram extends Omit<Program, 'body'> {
483
- body: (Program['body'][number] | Component | FunctionExpression)[];
445
+ body: (Program['body'][number] | FunctionExpression)[];
484
446
  }
485
447
 
486
- interface TSRXProperty extends Omit<AST.Property, 'value'> {
487
- value: AST.Property['value'] | Component;
488
- }
489
-
490
- export type TSRXAttribute = AST.Attribute | AST.SpreadAttribute | AST.RefAttribute;
448
+ export type TSRXAttribute = AST.Attribute | AST.SpreadAttribute;
491
449
 
492
450
  export type TSRXStatement = AST.Statement | TSESTree.Statement;
493
451
 
@@ -692,7 +650,6 @@ declare module 'estree-jsx' {
692
650
  }
693
651
 
694
652
  interface JSXExpressionContainer {
695
- html?: boolean;
696
653
  text?: boolean;
697
654
  style?: boolean;
698
655
  }
@@ -1213,7 +1170,6 @@ export type DeclarationKind =
1213
1170
  | 'function'
1214
1171
  | 'param'
1215
1172
  | 'rest_param'
1216
- | 'component'
1217
1173
  | 'import'
1218
1174
  | 'module'
1219
1175
  | 'using'
@@ -1268,6 +1224,7 @@ export interface Binding {
1268
1224
  lazy_array_index?: number;
1269
1225
  lazy_array_source_tracked?: boolean;
1270
1226
  lazy_array_rest?: boolean;
1227
+ typeAnnotation?: AST.TypeNode;
1271
1228
  } | null;
1272
1229
  /** Kind of binding */
1273
1230
  kind: BindingKind;
@@ -1378,10 +1335,11 @@ export interface BaseState {
1378
1335
  ancestor_server_block: AST.TSModuleDeclaration | undefined;
1379
1336
  inside_head?: boolean;
1380
1337
  keep_component_style?: boolean;
1338
+ regular_js?: boolean;
1381
1339
 
1382
1340
  /** Common For All */
1383
1341
  to_ts: boolean;
1384
- component?: AST.Component;
1342
+ component?: AST.Function;
1385
1343
  }
1386
1344
 
1387
1345
  export interface AnalysisState extends BaseState {
@@ -1425,6 +1383,7 @@ export interface TransformServerState extends BaseState {
1425
1383
  template_child?: boolean;
1426
1384
  skip_regular_blocks?: boolean;
1427
1385
  in_regular_block?: boolean;
1386
+ is_tsrx_element?: boolean;
1428
1387
  jsx_to_tsrx_element?: boolean;
1429
1388
  }
1430
1389
 
@@ -1461,6 +1420,7 @@ export interface TransformClientState extends BaseState {
1461
1420
  return_flags?: Map<AST.ReturnStatement, { name: string; tracked: boolean }>;
1462
1421
  is_tsrx_element?: boolean;
1463
1422
  jsx_to_tsrx_element?: boolean;
1423
+ template_child?: boolean;
1464
1424
  ref_target_type?: AST.TypeNode;
1465
1425
  }
1466
1426
 
@@ -36,11 +36,12 @@ export interface JsxTransformContext {
36
36
  needs_error_boundary: boolean;
37
37
  needs_suspense: boolean;
38
38
  needs_merge_refs: boolean;
39
- needs_ref_prop: boolean;
40
39
  needs_normalize_spread_props: boolean;
40
+ needs_normalize_spread_props_for_ref_attr: boolean;
41
41
  needs_fragment: boolean;
42
42
  needs_for_of_iterable: boolean;
43
43
  needs_iteration_value_type: boolean;
44
+ stylesheets: AST.CSS.StyleSheet[];
44
45
  module_scoped_hook_components: boolean;
45
46
  helper_state: {
46
47
  base_name: string;
@@ -48,10 +49,12 @@ export interface JsxTransformContext {
48
49
  helpers: any[];
49
50
  statics: any[];
50
51
  } | null;
52
+ hook_helpers_enabled: boolean;
51
53
  available_bindings: Map<string, AST.Identifier>;
52
54
  lazy_next_id: number;
53
- current_css_hash: string | null;
54
55
  inside_element_child?: boolean;
56
+ /** Full source text for source-aware diagnostics. */
57
+ source: string;
55
58
  /** Source filename for diagnostics; null when the caller did not supply one. */
56
59
  filename: string | null;
57
60
  /** True when recoverable errors should be collected onto `errors` instead of thrown. */
@@ -144,18 +147,6 @@ export interface JsxPlatformHooks {
144
147
  * Composition API state like `ref()`.
145
148
  */
146
149
  isTopLevelSetupCall?: (callExpression: any, ctx: any) => boolean;
147
- /**
148
- * Lower a `component` declaration to the replacement node for its current
149
- * position. React / Preact use the default helper and return a
150
- * `FunctionDeclaration`. Other targets may return a variable declaration or
151
- * an expression that wraps the shared lowered function body (for example,
152
- * `defineVaporComponent(...)`).
153
- *
154
- * The default lowering is exported as `componentToFunctionDeclaration()` so
155
- * platform hooks can build on it instead of reimplementing component body
156
- * handling.
157
- */
158
- componentToFunction?: (component: any, ctx: any, helperState?: any) => any;
159
150
  /**
160
151
  * Wrap a hoisted helper component declaration emitted by the shared control-
161
152
  * flow splitter. The default is the plain function declaration; Vue uses
@@ -163,6 +154,13 @@ export interface JsxPlatformHooks {
163
154
  * state behaves like normal component state.
164
155
  */
165
156
  wrapHelperComponent?: (helperFn: any, helperId: any, ctx: any, sourceNode: any) => any;
157
+ /**
158
+ * Wrap an uppercase JavaScript function that returns native TSRX as a target
159
+ * component. Vue uses this to turn `function App() { return <></>; }` into a
160
+ * `defineVaporComponent(function App() { ... })` binding while lowercase
161
+ * TSRX-returning callbacks stay plain functions.
162
+ */
163
+ wrapNativeFunctionComponent?: (fn: any, ctx: any, path: any[]) => any;
166
164
  /**
167
165
  * Emit hook-isolation helper components as unique module-scope declarations
168
166
  * instead of lazily creating and caching them from the parent component body.
@@ -170,6 +168,11 @@ export interface JsxPlatformHooks {
170
168
  * Compiler's Rules of Hooks validation.
171
169
  */
172
170
  moduleScopedHookComponents?: boolean;
171
+ /**
172
+ * Split ordinary uppercase function component bodies when an early
173
+ * conditional return would make later React/Preact hooks conditional.
174
+ */
175
+ componentBodyHookHelpers?: boolean;
173
176
  /**
174
177
  * Inject module-level imports after the main walk. Default: import
175
178
  * `Suspense` from `platform.imports.suspense` and `TsrxErrorBoundary`
@@ -188,9 +191,7 @@ export interface JsxPlatformHooks {
188
191
  transformElementAttributes?: (attrs: any[], ctx: any, element: any) => any[];
189
192
  /**
190
193
  * Rewrite or normalize raw Ripple attributes before the shared
191
- * `to_jsx_attribute()` mapping runs. Targets can use this to merge multiple
192
- * keyword attributes, such as collapsing repeated `{ref ...}` entries into a
193
- * single `RefAttribute` backed by an array expression.
194
+ * `to_jsx_attribute()` mapping runs.
194
195
  */
195
196
  preprocessElementAttributes?: (attrs: any[], ctx: any, element: any) => any[];
196
197
  /**
@@ -260,7 +261,7 @@ export interface JsxPlatformHooks {
260
261
  * default child-to-JSX conversion runs.
261
262
  *
262
263
  * This lets a target support target-native DOM content props such as
263
- * `textContent` / `innerHTML` without forking the whole element lowering.
264
+ * `textContent` without forking the whole element lowering.
264
265
  * The hook may mutate `attrs` directly and either return a replacement
265
266
  * `children` array (plus optional `selfClosing` override) or `null` to fall
266
267
  * back to the default child handling.
@@ -336,8 +337,7 @@ export interface JsxPlatform {
336
337
  */
337
338
  mergeRefs?: string;
338
339
  /**
339
- * Module to import named-ref-prop helpers from when compiling
340
- * `prop={ref expr}` or normalizing host spreads containing named refs.
340
+ * Module to import host-spread normalization helpers from.
341
341
  */
342
342
  refProp?: string;
343
343
  /**
@@ -354,10 +354,15 @@ export interface JsxPlatform {
354
354
 
355
355
  jsx: {
356
356
  /**
357
- * Rewrite Ripple's `class` attribute to React's `className`. React: true.
358
- * Preact and Solid accept `class` natively, so: false.
357
+ * Rewrite Ripple's `class` attribute to `className` for legacy targets
358
+ * that require it. First-party targets keep authored `class`.
359
359
  */
360
360
  rewriteClassAttr: boolean;
361
+ /**
362
+ * Attribute name to use when TSRX injects scoped CSS classes. This does
363
+ * not rewrite authored attributes.
364
+ */
365
+ classAttrName?: 'class' | 'className';
361
366
  /**
362
367
  * Accepted values of `kind` in `<tsx:kind>` compat blocks. React accepts
363
368
  * only `'react'`. Preact accepts both `'preact'` and `'react'`.
@@ -383,8 +388,6 @@ export interface JsxPlatform {
383
388
  * explicit `ref={normalized.ref}` attribute.
384
389
  */
385
390
  hostSpreadRefStrategy?: 'explicit-ref-attr';
386
- /** Native host prop used when lowering a sole child `{html ...}`. */
387
- htmlProp?: 'dangerouslySetInnerHTML' | 'innerHTML';
388
391
  };
389
392
 
390
393
  validation: {
@@ -442,9 +445,3 @@ export function createJsxTransform(
442
445
  filename?: string,
443
446
  options?: JsxTransformOptions,
444
447
  ) => JsxTransformResult;
445
-
446
- export function componentToFunctionDeclaration(
447
- component: any,
448
- ctx: any,
449
- helperState?: any,
450
- ): AST.FunctionDeclaration | AST.FunctionExpression | AST.ArrowFunctionExpression;
package/types/parse.d.ts CHANGED
@@ -930,7 +930,7 @@ export namespace Parse {
930
930
  refDestructuringErrors?: DestructuringErrors,
931
931
  forInit?: ForInit,
932
932
  forNew?: boolean,
933
- ): AST.Component | AST.Identifier | AST.Literal;
933
+ ): AST.Expression;
934
934
 
935
935
  /** Default handler for parseExprAtom when no other case matches */
936
936
  parseExprAtomDefault(): AST.Expression;
@@ -1180,17 +1180,6 @@ export namespace Parse {
1180
1180
  body: (AST.Statement | AST.Node | ESTreeJSX.JSXText | ESTreeJSX.JSXElement['children'])[],
1181
1181
  ): void;
1182
1182
 
1183
- parseComponent(
1184
- params?:
1185
- | {
1186
- requireName?: boolean;
1187
- isDefault?: boolean;
1188
- declareName?: boolean;
1189
- skipName?: boolean;
1190
- }
1191
- | undefined,
1192
- ): AST.Component;
1193
-
1194
1183
  /**
1195
1184
  * Parse a statement
1196
1185
  * @param context Statement context ("for", "if", "label", etc.)
@@ -1204,11 +1193,9 @@ export namespace Parse {
1204
1193
  exports?: AST.ExportSpecifier,
1205
1194
  ):
1206
1195
  | AST.TSRXExpression
1207
- | AST.Html
1208
1196
  | AST.TextNode
1209
1197
  | ESTreeJSX.JSXEmptyExpression
1210
1198
  | ESTreeJSX.JSXExpressionContainer
1211
- | AST.Component
1212
1199
  | AST.ExpressionStatement
1213
1200
  | ReturnType<Parser['parseElement']>
1214
1201
  | AST.Statement;
@@ -1469,7 +1456,7 @@ export namespace Parse {
1469
1456
  parseExportSpecifiers(exports?: Exports): AST.ExportSpecifier[];
1470
1457
 
1471
1458
  /** Parse export default declaration */
1472
- parseExportDefaultDeclaration(): AST.Declaration | AST.Expression | AST.Component;
1459
+ parseExportDefaultDeclaration(): AST.Declaration | AST.Expression;
1473
1460
 
1474
1461
  /** Check if export statement should be parsed */
1475
1462
  shouldParseExportStatement(): boolean;
@@ -37,3 +37,6 @@ export function normalize_spread_props<T extends Record<PropertyKey, any> | null
37
37
  props: T,
38
38
  ...outer_refs: unknown[]
39
39
  ): T | Record<PropertyKey, any>;
40
+ export function normalize_spread_props_for_ref_attr<
41
+ T extends Record<PropertyKey, any> | null | undefined,
42
+ >(props: T, ...outer_refs: unknown[]): T | Record<PropertyKey, any>;