@tsrx/core 0.1.45 → 0.1.47

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/types/index.d.ts CHANGED
@@ -24,11 +24,23 @@ export type {
24
24
  };
25
25
  export { createJsxTransform };
26
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;
27
+ /** Result of extracting a branch body into a generated helper component. */
28
+ export interface JsxHelperComponent {
29
+ setup_statements: AST.Statement[];
30
+ component_element: ESTreeJSX.JSXElement;
31
+ }
32
+
33
+ export function collectStyleRefAttributes(
34
+ node: AST.Node | AST.Node[],
35
+ refs?: ESTreeJSX.JSXAttribute[],
36
+ ): ESTreeJSX.JSXAttribute[];
37
+ export function createStyleClassMap(
38
+ component: AST.Node,
39
+ css: AST.CSS.StyleSheet,
40
+ ): AST.ObjectExpression;
41
+ export function createStyleClassMapFromStylesheet(css: AST.CSS.StyleSheet): AST.ObjectExpression;
30
42
  export function createStyleRefSetupStatements(
31
- refAttributes: any[],
43
+ refAttributes: ESTreeJSX.JSXAttribute[],
32
44
  styleMap: AST.Expression,
33
45
  options?: {
34
46
  allowMutableRefTarget?: boolean;
@@ -36,7 +48,9 @@ export function createStyleRefSetupStatements(
36
48
  visitExpression?: (expression: AST.Expression) => AST.Expression;
37
49
  },
38
50
  ): AST.Statement[];
39
- export function getStyleElementStylesheet(styleElement: any): any | null;
51
+ export function getStyleElementStylesheet(
52
+ styleElement: AST.JSXStyleElement,
53
+ ): AST.CSS.StyleSheet | null;
40
54
 
41
55
  /**
42
56
  * Compile error interface
@@ -119,11 +133,11 @@ interface BaseNodeMetaData {
119
133
  /** Memoized `<> … </>` wrapper for a value-position directive (see get_directive_value_wrapper). */
120
134
  tsrx_value_wrapper?: AST.TSRXJSXFragment;
121
135
  ts_name?: string;
122
- delegated?: any;
136
+ delegated?: boolean;
123
137
  returned_tsrx_return?: AST.ReturnStatement;
124
138
  styleScopeHash?: string;
125
139
  css?: {
126
- scopedClasses: Map<string, { start: number; end: number; selector: any }>;
140
+ scopedClasses: TopScopedClasses;
127
141
  hash: string;
128
142
  };
129
143
  elementLeadingComments?: AST.Comment[];
@@ -139,6 +153,12 @@ interface BaseNodeMetaData {
139
153
  generated_loop_skip_if?: boolean;
140
154
  lazy_id?: string;
141
155
  disable_verification?: boolean;
156
+ extra_source_mappings?: AST.NodeWithLocation[];
157
+ generated_setup_declarations?: AST.Statement[];
158
+ has_unmappable_value?: boolean;
159
+ synthetic_ref?: boolean;
160
+ tsrx_reactive_block?: boolean;
161
+ vapor_pending_fallback?: ESTreeJSX.JSXRenderNode;
142
162
  lazy_param_binding_mappings?: Array<{
143
163
  source: AST.Identifier;
144
164
  generated: AST.Identifier | AST.Literal;
@@ -156,8 +176,8 @@ interface FunctionMetaData extends BaseNodeMetaData {
156
176
  /** Top-level scoped classes collected while pruning the component's CSS. */
157
177
  topScopedClasses?: TopScopedClasses;
158
178
  synthetic_children?: boolean;
159
- generated_helpers?: any[];
160
- generated_statics?: any[];
179
+ generated_helpers?: AST.Statement[];
180
+ generated_statics?: AST.Statement[];
161
181
  }
162
182
 
163
183
  // Strip parent, loc, and range from TSESTree nodes to match @sveltejs/acorn-typescript output
@@ -445,6 +465,36 @@ declare module 'estree' {
445
465
  | JSXSwitchExpression
446
466
  | JSXTryExpression;
447
467
 
468
+ /** A statement-form template directive after its parser node has been retyped. */
469
+ type JSXTemplateStatement =
470
+ | (AST.IfStatement & { statementType: 'IfStatement' })
471
+ | (AST.ForOfStatement & { statementType: 'ForOfStatement' })
472
+ | (AST.SwitchStatement & { statementType: 'SwitchStatement' })
473
+ | (AST.TryStatement & { statementType: 'TryStatement' });
474
+
475
+ /** A source node that the shared JSX transform can lower into a JSX child. */
476
+ type TSRXRenderChild =
477
+ | ESTreeJSX.JSXElement
478
+ | ESTreeJSX.JSXFragment
479
+ | ESTreeJSX.JSXExpressionContainer
480
+ | ESTreeJSX.JSXText
481
+ | JSXTemplateDirective
482
+ | JSXTemplateStatement;
483
+
484
+ /** An AST node that represents component-level `await` during validation. */
485
+ type TSRXAwaitNode = AST.AwaitExpression | AST.ForOfStatement | JSXForOfExpression;
486
+
487
+ /** Any node that can be the rendered output of a TSRX template or statement container. */
488
+ type TSRXRenderOutput =
489
+ | ESTreeJSX.JSXElement
490
+ | ESTreeJSX.JSXFragment
491
+ | JSXStyleElement
492
+ | JSXCodeBlock
493
+ | JSXTemplateDirective;
494
+
495
+ /** A parser node whose body uses native TSRX template semantics. */
496
+ type NativeTSRXNode = TSRXJSXElement | TSRXJSXFragment | JSXStyleElement | JSXCodeBlock;
497
+
448
498
  interface ParenthesizedExpression extends AST.BaseNode {
449
499
  type: 'ParenthesizedExpression';
450
500
  expression: AST.Expression;
@@ -472,14 +522,24 @@ declare module 'estree' {
472
522
  type CommentWithLocation = AST.Comment & NodeWithLocation;
473
523
 
474
524
  interface TryStatement {
525
+ statementType?: 'TryStatement';
475
526
  pending?: AST.BlockStatement | null;
476
527
  }
477
528
 
529
+ interface IfStatement {
530
+ statementType?: 'IfStatement';
531
+ }
532
+
533
+ interface SwitchStatement {
534
+ statementType?: 'SwitchStatement';
535
+ }
536
+
478
537
  interface CatchClause {
479
538
  resetParam?: AST.Pattern | null;
480
539
  }
481
540
 
482
541
  interface ForOfStatement {
542
+ statementType?: 'ForOfStatement';
483
543
  index?: AST.Identifier | null;
484
544
  key?: AST.Expression | null;
485
545
  empty?: AST.BlockStatement | null;
@@ -725,6 +785,27 @@ declare module 'estree' {
725
785
  }
726
786
 
727
787
  declare module 'estree-jsx' {
788
+ /** A node that can be returned from a platform hook into a JSX render slot. */
789
+ type JSXRenderNode = AST.Expression | JSXExpressionContainer | JSXText | JSXSpreadChild;
790
+
791
+ /** A JSX child produced by the transform's render-body lowering. */
792
+ type JSXRenderChild = JSXElement | JSXFragment | JSXExpressionContainer | JSXText;
793
+
794
+ /** An attribute accepted by and emitted from the shared JSX transformer. */
795
+ type JSXAttributeNode = JSXAttribute | JSXSpreadAttribute;
796
+
797
+ /** A `ref` attribute whose value has been narrowed to a non-empty expression. */
798
+ interface JSXRefAttribute extends JSXAttribute {
799
+ name: JSXIdentifier;
800
+ value: JSXExpressionContainer & { expression: AST.Expression };
801
+ }
802
+
803
+ /** A child accepted while TSRX JSX is being lowered to standard ESTree JSX. */
804
+ type JSXTransformChild =
805
+ | JSXElement['children'][number]
806
+ | AST.TSRXJSXElement
807
+ | AST.TSRXJSXFragment;
808
+
728
809
  interface JSXAttribute {
729
810
  shorthand: boolean;
730
811
  }
@@ -777,7 +858,8 @@ declare module 'estree-jsx' {
777
858
  | JSXIdentifier
778
859
  | JSXNamespacedName
779
860
  | JSXExpressionContainer
780
- | import('estree').MemberExpression;
861
+ | AST.Identifier
862
+ | AST.MemberExpression;
781
863
  }
782
864
 
783
865
  interface TSRXJSXClosingElement extends Omit<JSXClosingElement, 'name'> {
@@ -787,7 +869,8 @@ declare module 'estree-jsx' {
787
869
  | JSXIdentifier
788
870
  | JSXNamespacedName
789
871
  | JSXExpressionContainer
790
- | import('estree').MemberExpression;
872
+ | AST.Identifier
873
+ | AST.MemberExpression;
791
874
  }
792
875
 
793
876
  interface ExpressionMap {
@@ -1269,6 +1352,30 @@ export interface AnalyzeOptions extends ParseOptions, Pick<CompileOptions, 'mode
1269
1352
  to_ts?: boolean;
1270
1353
  }
1271
1354
 
1355
+ /** Options for the target-neutral TSRX semantic analysis pass. */
1356
+ export interface TSRXAnalysisOptions extends ParseOptions {
1357
+ typeOnly?: boolean;
1358
+ to_ts?: boolean;
1359
+ }
1360
+
1361
+ /** Traversal state used by the target-neutral TSRX semantic analysis pass. */
1362
+ export interface TSRXAnalysisState {
1363
+ filename: string | null;
1364
+ collect: boolean;
1365
+ errors: CompileError[];
1366
+ comments: AST.CommentWithLocation[];
1367
+ function: AST.Function | null;
1368
+ function_body_is_code_block: boolean;
1369
+ inside_template_output: boolean;
1370
+ }
1371
+
1372
+ /** Result of target-neutral TSRX semantic analysis. */
1373
+ export interface TSRXAnalysisResult {
1374
+ ast: AST.Program;
1375
+ errors: CompileError[];
1376
+ comments: AST.CommentWithLocation[];
1377
+ }
1378
+
1272
1379
  /**
1273
1380
  * Result of parsing operation
1274
1381
  */
@@ -1,6 +1,7 @@
1
1
  import type * as AST from 'estree';
2
+ import type * as ESTreeJSX from 'estree-jsx';
2
3
  import type { RawSourceMap } from 'source-map';
3
- import type { CompileError } from './index';
4
+ import type { CompileError, JsxHelperComponent } from './index';
4
5
 
5
6
  /**
6
7
  * Result returned by a JSX platform transform (React, Preact, Solid).
@@ -25,10 +26,8 @@ export interface JsxTransformResult {
25
26
  }
26
27
 
27
28
  /**
28
- * Shared base for the per-call transform context that the JSX factory passes
29
- * into every visitor and helper. Platform-specific transforms (e.g. Solid)
30
- * extend this with their own `needs_*` flags via `hooks.initialState`; helpers
31
- * defined in `@tsrx/core` only ever rely on these base fields.
29
+ * Per-call transform context that the JSX factory passes into every visitor
30
+ * and platform hook.
32
31
  */
33
32
  export interface JsxTransformContext {
34
33
  platform: JsxPlatform;
@@ -43,14 +42,22 @@ export interface JsxTransformContext {
43
42
  needs_dynamic_factory: boolean;
44
43
  needs_for_of_iterable: boolean;
45
44
  needs_iteration_value_type: boolean;
45
+ needs_show: boolean;
46
+ needs_for: boolean;
47
+ needs_switch: boolean;
48
+ needs_match: boolean;
49
+ needs_errored: boolean;
50
+ needs_loading: boolean;
51
+ needs_define_vapor_component: boolean;
52
+ needs_vapor_for: boolean;
46
53
  stylesheets: AST.CSS.StyleSheet[];
47
54
  type_only_style_anchors: AST.Statement[];
48
55
  module_scoped_hook_components: boolean;
49
56
  helper_state: {
50
57
  base_name: string;
51
58
  next_id: number;
52
- helpers: any[];
53
- statics: any[];
59
+ helpers: AST.Statement[];
60
+ statics: AST.Statement[];
54
61
  } | null;
55
62
  hook_helpers_enabled: boolean;
56
63
  available_bindings: Map<string, AST.Identifier>;
@@ -138,10 +145,13 @@ export interface JsxPlatformHooks {
138
145
  * child (or an expression container wrapping one).
139
146
  */
140
147
  controlFlow?: {
141
- ifStatement?: (node: any, ctx: any) => any;
142
- forOf?: (node: any, ctx: any) => any;
143
- switchStatement?: (node: any, ctx: any) => any;
144
- tryStatement?: (node: any, ctx: any) => any;
148
+ ifStatement?: (node: AST.IfStatement, ctx: JsxTransformContext) => ESTreeJSX.JSXRenderNode;
149
+ forOf?: (node: AST.ForOfStatement, ctx: JsxTransformContext) => ESTreeJSX.JSXRenderNode;
150
+ switchStatement?: (
151
+ node: AST.SwitchStatement,
152
+ ctx: JsxTransformContext,
153
+ ) => ESTreeJSX.JSXRenderNode;
154
+ tryStatement?: (node: AST.TryStatement, ctx: JsxTransformContext) => ESTreeJSX.JSXRenderNode;
145
155
  };
146
156
  /**
147
157
  * Mark a top-level call expression inside a control-flow branch as requiring
@@ -149,14 +159,19 @@ export interface JsxPlatformHooks {
149
159
  * branch instead of once per parent rerender. Vue uses this for branch-local
150
160
  * Composition API state like `ref()`.
151
161
  */
152
- isTopLevelSetupCall?: (callExpression: any, ctx: any) => boolean;
162
+ isTopLevelSetupCall?: (callExpression: AST.CallExpression, ctx: JsxTransformContext) => boolean;
153
163
  /**
154
164
  * Wrap a hoisted helper component declaration emitted by the shared control-
155
165
  * flow splitter. The default is the plain function declaration; Vue uses
156
166
  * this to wrap helpers in `defineVaporComponent(...)` so branch-local setup
157
167
  * state behaves like normal component state.
158
168
  */
159
- wrapHelperComponent?: (helperFn: any, helperId: any, ctx: any, sourceNode: any) => any;
169
+ wrapHelperComponent?: (
170
+ helperFn: AST.FunctionDeclaration,
171
+ helperId: AST.Identifier,
172
+ ctx: JsxTransformContext,
173
+ sourceNode: AST.NodeWithLocation | undefined,
174
+ ) => AST.Statement;
160
175
  /**
161
176
  * Emit hook-isolation helper components as unique module-scope declarations
162
177
  * instead of lazily creating and caching them from the parent component body.
@@ -171,27 +186,38 @@ export interface JsxPlatformHooks {
171
186
  * Solid injects `Show`, `For`, `Switch`, `Match`, `Errored`, `Loading`
172
187
  * from `solid-js`.
173
188
  */
174
- injectImports?: (program: AST.Program, ctx: any, suspenseSource: string) => void;
189
+ injectImports?: (program: AST.Program, ctx: JsxTransformContext, suspenseSource: string) => void;
175
190
  /**
176
- * Transform a Ripple element's attributes to JSX attributes. Default
177
- * is "map over `to_jsx_attribute`" plus the shared multi-`ref` merge
178
- * pass. Platforms that own a `transformElement` hook (e.g. Solid) bypass
179
- * this entirely — they never reach the dispatch path that would call
180
- * it — and run their own attribute pass inside their `transformElement`.
191
+ * Transform a Ripple element's parser-native JSX attributes. The result
192
+ * is passed through the shared multi-`ref` merge. Platforms that own a
193
+ * `transformElement` hook (e.g. Solid) run their own attribute pass inside
194
+ * that hook.
181
195
  */
182
- transformElementAttributes?: (attrs: any[], ctx: any, element: any) => any[];
196
+ transformElementAttributes?: (
197
+ attrs: ESTreeJSX.JSXAttributeNode[],
198
+ ctx: JsxTransformContext,
199
+ element: AST.TSRXJSXElement,
200
+ ) => ESTreeJSX.JSXAttributeNode[];
183
201
  /**
184
- * Rewrite or normalize raw Ripple attributes before the shared
185
- * `to_jsx_attribute()` mapping runs.
202
+ * Rewrite parser-native JSX attributes before platform transformation.
186
203
  */
187
- preprocessElementAttributes?: (attrs: any[], ctx: any, element: any) => any[];
204
+ preprocessElementAttributes?: (
205
+ attrs: ESTreeJSX.JSXAttributeNode[],
206
+ ctx: JsxTransformContext,
207
+ element: AST.TSRXJSXElement,
208
+ ) => ESTreeJSX.JSXAttributeNode[];
188
209
  /**
189
210
  * Optionally replace the default React-style `.map(...)` lowering for a
190
211
  * `for...of` body after the shared transform has already produced its render
191
212
  * statements and applied any explicit or implicit keys. Vue uses this to hand
192
213
  * the loop to the downstream Vapor JSX compiler as a typed `VaporFor` component.
193
214
  */
194
- renderForOf?: (node: any, loopParams: any[], bodyStatements: any[], ctx: any) => any | null;
215
+ renderForOf?: (
216
+ node: AST.ForOfStatement,
217
+ loopParams: AST.Pattern[],
218
+ bodyStatements: AST.Statement[],
219
+ ctx: JsxTransformContext,
220
+ ) => ESTreeJSX.JSXExpressionContainer | null;
195
221
  /**
196
222
  * Optionally replace the default React-style pending lowering for
197
223
  * `@try { ... } @pending { ... }`. The default emits
@@ -200,35 +226,35 @@ export interface JsxPlatformHooks {
200
226
  * `v-slots`.
201
227
  */
202
228
  createPendingBoundary?: (
203
- tryContent: any,
204
- fallbackContent: any,
205
- ctx: any,
206
- node: any,
207
- ) => any | null;
229
+ tryContent: ESTreeJSX.JSXRenderNode,
230
+ fallbackContent: ESTreeJSX.JSXRenderNode,
231
+ ctx: JsxTransformContext,
232
+ node: AST.TryStatement,
233
+ ) => ESTreeJSX.JSXRenderNode | null;
208
234
  /**
209
235
  * Optionally create a generated component for a catch fallback body while
210
236
  * the catch parameters are still in scope. Platforms can use this to reuse
211
237
  * one mapped catch-body component from multiple runtime catch sites.
212
238
  */
213
239
  createErrorFallbackComponent?: (
214
- catchBodyNodes: any[],
215
- catchParams: any[],
216
- ctx: any,
217
- node: any,
218
- ) => any | null;
240
+ catchBodyNodes: AST.Statement[],
241
+ catchParams: AST.Pattern[],
242
+ ctx: JsxTransformContext,
243
+ node: AST.TryStatement,
244
+ ) => JsxHelperComponent | null;
219
245
  /**
220
246
  * Optionally replace the default `try/catch` boundary wrapper. The hook
221
247
  * receives the current render content, the original try-body content before
222
248
  * any pending wrapper, and the generated catch fallback function.
223
249
  */
224
250
  createErrorBoundary?: (
225
- tryContent: any,
226
- rawTryContent: any,
227
- fallbackFn: any,
228
- ctx: any,
229
- node: any,
230
- info?: { fallbackComponent?: any },
231
- ) => any | null;
251
+ tryContent: ESTreeJSX.JSXRenderNode,
252
+ rawTryContent: ESTreeJSX.JSXRenderNode,
253
+ fallbackFn: AST.ArrowFunctionExpression,
254
+ ctx: JsxTransformContext,
255
+ node: AST.TryStatement,
256
+ info?: { fallbackComponent?: JsxHelperComponent | null },
257
+ ) => ESTreeJSX.JSXRenderNode | null;
232
258
  /**
233
259
  * Optionally move the primary `try { ... }` render content into an explicit
234
260
  * error-boundary prop instead of rendering it as the boundary's JSX children.
@@ -236,7 +262,11 @@ export interface JsxPlatformHooks {
236
262
  * zero-argument function. If a `pending` block exists, `tryContent` is the
237
263
  * already-created pending boundary so catch wrappers still enclose it.
238
264
  */
239
- createErrorBoundaryContent?: (tryContent: any, ctx: any, node: any) => any | null;
265
+ createErrorBoundaryContent?: (
266
+ tryContent: ESTreeJSX.JSXRenderNode,
267
+ ctx: JsxTransformContext,
268
+ node: AST.TryStatement,
269
+ ) => AST.Expression | null;
240
270
  /**
241
271
  * Customize lowering for a native JSX element. Default is the
242
272
  * factory's `to_jsx_element`. The hook receives the walker-transformed
@@ -245,7 +275,11 @@ export interface JsxPlatformHooks {
245
275
  * `JSXText` child it can hoist to a `textContent` attribute before the
246
276
  * generic text→JSXExpressionContainer transform runs.
247
277
  */
248
- transformElement?: (inner: any, ctx: any, rawChildren: any[]) => any;
278
+ transformElement?: (
279
+ inner: AST.TSRXJSXElement,
280
+ ctx: JsxTransformContext,
281
+ rawChildren: AST.Node[],
282
+ ) => ESTreeJSX.JSXRenderNode;
249
283
  /**
250
284
  * Optionally rewrite a host element's children into attributes or another
251
285
  * specialized child shape after generic attribute lowering but before the
@@ -258,27 +292,27 @@ export interface JsxPlatformHooks {
258
292
  * back to the default child handling.
259
293
  */
260
294
  transformElementChildren?: (
261
- element: any,
262
- walkedChildren: any[],
263
- rawChildren: any[],
264
- attrs: any[],
265
- ctx: any,
266
- ) => { children: any[]; selfClosing?: boolean } | null;
295
+ element: AST.TSRXJSXElement,
296
+ walkedChildren: AST.Node[],
297
+ rawChildren: AST.Node[],
298
+ attrs: ESTreeJSX.JSXAttributeNode[],
299
+ ctx: JsxTransformContext,
300
+ ) => { children: ESTreeJSX.JSXElement['children']; selfClosing?: boolean } | null;
267
301
  /**
268
302
  * Decide whether a JSX subtree may be hoisted to module scope when it is
269
303
  * otherwise statically safe. Targets can use this to keep runtime-sensitive
270
304
  * JSX, such as component invocations, inside render/setup execution.
271
305
  */
272
- canHoistStaticNode?: (node: any, ctx: any) => boolean;
306
+ canHoistStaticNode?: (node: ESTreeJSX.JSXElement, ctx: JsxTransformContext) => boolean;
273
307
  /**
274
308
  * Custom validation for a component body that uses top-level `await`.
275
309
  * Default: enforce `validation.requireUseServerForAwait`. Solid rejects
276
310
  * component-level await outright with a keyword-precise location.
277
311
  */
278
312
  validateComponentAwait?: (
279
- awaitNode: any,
280
- component: any,
281
- ctx: any,
313
+ awaitNode: AST.TSRXAwaitNode,
314
+ component: AST.Function,
315
+ ctx: JsxTransformContext,
282
316
  moduleUsesServerDirective: boolean,
283
317
  source: string,
284
318
  ) => void;
@@ -287,7 +321,7 @@ export interface JsxPlatformHooks {
287
321
  * initial `transform_context`. Lets solid seed its `needs_show` /
288
322
  * `needs_for` / etc. flags without forking the factory.
289
323
  */
290
- initialState?: () => Record<string, unknown>;
324
+ initialState?: () => Partial<JsxTransformContext>;
291
325
  }
292
326
 
293
327
  /**