@tsrx/core 0.0.8 → 0.0.9

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.
@@ -1,8 +1,8 @@
1
1
  /**
2
2
  * Framework-agnostic CSS scoping utilities shared between the `@tsrx/react`
3
3
  * and `@tsrx/solid` transforms. These walk the template AST and annotate
4
- * `Element` nodes with a hash class so scope-qualified selectors
5
- * (e.g. `.foo.hash`) match after rendering.
4
+ * template nodes with a hash class so scope-qualified selectors (e.g.
5
+ * `.foo.hash`) match after rendering.
6
6
  */
7
7
 
8
8
  import { walk } from 'zimmerframe';
@@ -61,15 +61,42 @@ export function is_composite_element(node) {
61
61
  return node.id.type === 'MemberExpression';
62
62
  }
63
63
 
64
+ /**
65
+ * @param {any} node
66
+ * @returns {boolean}
67
+ */
68
+ function is_style_jsx_element(node) {
69
+ const name = node?.openingElement?.name;
70
+ return node?.type === 'JSXElement' && name?.type === 'JSXIdentifier' && name.name === 'style';
71
+ }
72
+
73
+ /**
74
+ * @param {any} node
75
+ * @returns {boolean}
76
+ */
77
+ function is_composite_jsx_element(node) {
78
+ const name = node?.openingElement?.name;
79
+ if (node?.type !== 'JSXElement' || !name) {
80
+ return false;
81
+ }
82
+
83
+ if (name.type === 'JSXIdentifier') {
84
+ return /^[A-Z]/.test(name.name);
85
+ }
86
+
87
+ return name.type === 'JSXMemberExpression';
88
+ }
89
+
64
90
  /**
65
91
  * Recursively walk `Element` nodes within a component body and add the hash
66
92
  * class name so scope-qualified selectors (e.g. `.foo.hash`) match.
67
93
  *
68
94
  * @param {any} node
69
95
  * @param {string} hash
96
+ * @param {'class' | 'className'} [jsx_class_attr_name='class']
70
97
  * @returns {any}
71
98
  */
72
- export function annotate_with_hash(node, hash) {
99
+ export function annotate_with_hash(node, hash, jsx_class_attr_name = 'class') {
73
100
  if (!node || typeof node !== 'object') return node;
74
101
  if (
75
102
  node.type === 'Component' ||
@@ -87,7 +114,19 @@ export function annotate_with_hash(node, hash) {
87
114
  if (Array.isArray(node.children)) {
88
115
  node.children = node.children
89
116
  .filter((/** @type {any} */ child) => !is_style_element(child))
90
- .map((/** @type {any} */ child) => annotate_with_hash(child, hash));
117
+ .map((/** @type {any} */ child) => annotate_with_hash(child, hash, jsx_class_attr_name));
118
+ }
119
+ return node;
120
+ }
121
+
122
+ if (node.type === 'JSXElement') {
123
+ if (!is_style_jsx_element(node) && !is_composite_jsx_element(node)) {
124
+ add_hash_class_to_jsx_element(node, hash, jsx_class_attr_name);
125
+ }
126
+ if (Array.isArray(node.children)) {
127
+ node.children = node.children.map((/** @type {any} */ child) =>
128
+ annotate_with_hash(child, hash, jsx_class_attr_name),
129
+ );
91
130
  }
92
131
  return node;
93
132
  }
@@ -99,9 +138,11 @@ export function annotate_with_hash(node, hash) {
99
138
 
100
139
  const value = node[key];
101
140
  if (Array.isArray(value)) {
102
- node[key] = value.map((/** @type {any} */ child) => annotate_with_hash(child, hash));
141
+ node[key] = value.map((/** @type {any} */ child) =>
142
+ annotate_with_hash(child, hash, jsx_class_attr_name),
143
+ );
103
144
  } else if (value && typeof value === 'object') {
104
- node[key] = annotate_with_hash(value, hash);
145
+ node[key] = annotate_with_hash(value, hash, jsx_class_attr_name);
105
146
  }
106
147
  }
107
148
 
@@ -111,14 +152,15 @@ export function annotate_with_hash(node, hash) {
111
152
  /**
112
153
  * @param {any} component
113
154
  * @param {string} hash
155
+ * @param {'class' | 'className'} [jsx_class_attr_name='class']
114
156
  * @returns {void}
115
157
  */
116
- export function annotate_component_with_hash(component, hash) {
158
+ export function annotate_component_with_hash(component, hash, jsx_class_attr_name = 'class') {
117
159
  /** @type {any[]} */
118
160
  const body = component.body;
119
161
  component.body = body
120
162
  .filter((/** @type {any} */ child) => !is_style_element(child))
121
- .map((/** @type {any} */ child) => annotate_with_hash(child, hash));
163
+ .map((/** @type {any} */ child) => annotate_with_hash(child, hash, jsx_class_attr_name));
122
164
  }
123
165
 
124
166
  /**
@@ -178,3 +220,73 @@ export function add_hash_class(element, hash) {
178
220
  ],
179
221
  };
180
222
  }
223
+
224
+ /**
225
+ * @param {any} element
226
+ * @param {string} hash
227
+ * @param {'class' | 'className'} jsx_class_attr_name
228
+ * @returns {void}
229
+ */
230
+ function add_hash_class_to_jsx_element(element, hash, jsx_class_attr_name) {
231
+ const attrs = element.openingElement?.attributes || (element.openingElement.attributes = []);
232
+ const existing = attrs.find(
233
+ (/** @type {any} */ attr) =>
234
+ attr?.type === 'JSXAttribute' &&
235
+ attr.name?.type === 'JSXIdentifier' &&
236
+ (attr.name.name === 'class' || attr.name.name === 'className'),
237
+ );
238
+
239
+ if (!existing) {
240
+ attrs.push({
241
+ type: 'JSXAttribute',
242
+ name: { type: 'JSXIdentifier', name: jsx_class_attr_name, metadata: { path: [] } },
243
+ value: { type: 'Literal', value: hash, raw: JSON.stringify(hash) },
244
+ shorthand: false,
245
+ metadata: { path: [] },
246
+ });
247
+ return;
248
+ }
249
+
250
+ if (existing.name.name !== jsx_class_attr_name) {
251
+ existing.name = {
252
+ type: 'JSXIdentifier',
253
+ name: jsx_class_attr_name,
254
+ metadata: existing.name.metadata || { path: [] },
255
+ };
256
+ }
257
+
258
+ const value = existing.value;
259
+ if (!value) {
260
+ existing.value = { type: 'Literal', value: hash, raw: JSON.stringify(hash) };
261
+ return;
262
+ }
263
+
264
+ if (value.type === 'Literal' && typeof value.value === 'string') {
265
+ const merged = `${value.value} ${hash}`;
266
+ existing.value = { type: 'Literal', value: merged, raw: JSON.stringify(merged) };
267
+ return;
268
+ }
269
+
270
+ const expression = value.type === 'JSXExpressionContainer' ? value.expression : value;
271
+ existing.value = {
272
+ type: 'JSXExpressionContainer',
273
+ expression: {
274
+ type: 'TemplateLiteral',
275
+ expressions: [expression],
276
+ quasis: [
277
+ {
278
+ type: 'TemplateElement',
279
+ value: { raw: '', cooked: '' },
280
+ tail: false,
281
+ },
282
+ {
283
+ type: 'TemplateElement',
284
+ value: { raw: ` ${hash}`, cooked: ` ${hash}` },
285
+ tail: true,
286
+ },
287
+ ],
288
+ metadata: { path: [] },
289
+ },
290
+ metadata: { path: [] },
291
+ };
292
+ }
@@ -52,7 +52,6 @@ import {
52
52
  mapping_data_verify_complete,
53
53
  build_line_offsets,
54
54
  get_mapping_from_node,
55
- maybe_get_mapping_from_node,
56
55
  } from '../source-map-utils.js';
57
56
 
58
57
  const LABEL_TO_COMPONENT_REPLACE_REGEX = /(function|\((property|method)\))/;
@@ -670,21 +669,9 @@ export function convert_source_map_to_mappings(
670
669
  return;
671
670
  } else if (node.type === 'JSXExpressionContainer') {
672
671
  if (node.loc) {
673
- // Use maybe_get_mapping_from_node because a transform may set the
674
- // container's loc to the source range of the original `{...}`
675
- // construct (e.g. a Ripple TSRXExpression or Text node), while
676
- // esrap only emits a segment for the inner expression. In that
677
- // case the container's start/end won't resolve — skip rather
678
- // than hard-failing, and rely on the inner expression's mapping.
679
- const mapping = maybe_get_mapping_from_node(
680
- node,
681
- src_to_gen_map,
682
- gen_line_offsets,
683
- mapping_data_verify_only,
672
+ mappings.push(
673
+ get_mapping_from_node(node, src_to_gen_map, gen_line_offsets, mapping_data_verify_only),
684
674
  );
685
- if (!(mapping instanceof Error)) {
686
- mappings.push(mapping);
687
- }
688
675
  }
689
676
  // Visit the expression inside {}
690
677
  if (node.expression) {
@@ -742,36 +729,22 @@ export function convert_source_map_to_mappings(
742
729
 
743
730
  if ((closing?.loc || opening.loc) && (closing || opening.selfClosing)) {
744
731
  // Add the whole closing tag or the self-closing.
745
- // For self-closing elements, use maybe_get_mapping_from_node because
746
- // attribute transforms (e.g. class→className, {ref fn}→ref={fn}) can shift
747
- // the position of `/>` in the generated output, making the source map
748
- // entry for the opening element's end position unresolvable.
749
732
  const target_node = closing ? closing : opening;
750
- const mapping = closing
751
- ? get_mapping_from_node(
752
- target_node,
753
- src_to_gen_map,
754
- gen_line_offsets,
755
- mapping_data_verify_only,
756
- )
757
- : maybe_get_mapping_from_node(
758
- target_node,
759
- src_to_gen_map,
760
- gen_line_offsets,
761
- mapping_data_verify_only,
762
- );
763
-
764
- if (!(mapping instanceof Error)) {
765
- // The generated code includes a semicolon after the closing or self-closed tag
766
- // We're extending the mapping to include the semicolon
767
- // because the diagnostics errors can include the whole element
768
- // and we need to account for the semicolon as it's a part of the diagnostic
769
- // At the same time, we could've instead applied this logic to the whole `node` element
770
- // but since we already map the opening - start, we just need the proper end
771
- // and it was causing some issues with mappings
772
- mapping.generatedLengths = [mapping.generatedLengths[0] + 1];
773
- mappings.push(mapping);
774
- }
733
+ const mapping = get_mapping_from_node(
734
+ target_node,
735
+ src_to_gen_map,
736
+ gen_line_offsets,
737
+ mapping_data_verify_only,
738
+ );
739
+ // The generated code includes a semicolon after the closing or self-closed tag
740
+ // We're extending the mapping to include the semicolon
741
+ // because the diagnostics errors can include the whole element
742
+ // and we need to account for the semicolon as it's a part of the diagnostic
743
+ // At the same time, we could've instead applied this logic to the whole `node` element
744
+ // but since we already map the opening - start, we just need the proper end
745
+ // and it was causing some issues with mappings
746
+ mapping.generatedLengths = [mapping.generatedLengths[0] + 1];
747
+ mappings.push(mapping);
775
748
  }
776
749
 
777
750
  if (closing) {
@@ -1621,7 +1594,7 @@ export function convert_source_map_to_mappings(
1621
1594
  // Generic spans can be emitted by downstream transforms with sparse source-map
1622
1595
  // coverage around the angle-bracket delimiters. Skip missing whole-node mappings
1623
1596
  // instead of crashing Volar, and rely on child type-node mappings instead.
1624
- const mapping = maybe_get_mapping_from_node(
1597
+ const mapping = get_mapping_from_node(
1625
1598
  node,
1626
1599
  src_to_gen_map,
1627
1600
  gen_line_offsets,
@@ -2070,6 +2043,15 @@ export function convert_source_map_to_mappings(
2070
2043
  visit(node.typeArguments);
2071
2044
  }
2072
2045
  return;
2046
+ } else if (node.type === 'TSTypePredicate') {
2047
+ // Type predicate: `x is T` / `asserts x is T` / `asserts x`
2048
+ if (node.parameterName) {
2049
+ visit(node.parameterName);
2050
+ }
2051
+ if (node.typeAnnotation) {
2052
+ visit(node.typeAnnotation);
2053
+ }
2054
+ return;
2073
2055
  }
2074
2056
 
2075
2057
  throw new Error(`Unhandled AST node type in mapping walker: ${node.type}`);
package/types/index.d.ts CHANGED
@@ -5,8 +5,16 @@ import type { Parse } from './parse.js';
5
5
  import type * as ESRap from 'esrap';
6
6
  import type { Position } from 'acorn';
7
7
  import type { RequireAllOrNone } from '../src/helpers.js';
8
+ import type {
9
+ JsxPlatform,
10
+ JsxPlatformHooks,
11
+ JsxTransformOptions,
12
+ JsxTransformResult,
13
+ createJsxTransform,
14
+ } from './jsx-platform';
8
15
 
9
- export type { Parse };
16
+ export type { Parse, JsxPlatform, JsxPlatformHooks, JsxTransformOptions, JsxTransformResult };
17
+ export { createJsxTransform };
10
18
 
11
19
  /**
12
20
  * Compile error interface
@@ -76,7 +84,7 @@ interface FunctionLikeTS {
76
84
  typeAnnotation?: AST.TSTypeAnnotation;
77
85
  }
78
86
 
79
- // Ripple augmentation for ESTree function nodes
87
+ // TSRX augmentation for ESTree function nodes
80
88
  declare module 'estree' {
81
89
  interface Program {
82
90
  innerComments?: Comment[] | undefined;
@@ -164,7 +172,7 @@ declare module 'estree' {
164
172
  was_expression?: boolean;
165
173
  }
166
174
 
167
- // Include TypeScript node types and Ripple-specific nodes in NodeMap
175
+ // Include TypeScript node types and TSRX-specific nodes in NodeMap
168
176
  interface NodeMap {
169
177
  Component: Component;
170
178
  Tsx: Tsx;
@@ -291,7 +299,7 @@ declare module 'estree' {
291
299
  }
292
300
 
293
301
  /**
294
- * Ripple custom interfaces and types section
302
+ * TSRX custom interfaces and types section
295
303
  */
296
304
  interface Component extends AST.BaseNode {
297
305
  type: 'Component';
@@ -398,7 +406,7 @@ declare module 'estree' {
398
406
  }
399
407
 
400
408
  /**
401
- * Ripple attribute nodes
409
+ * TSRX attribute nodes
402
410
  */
403
411
  interface Attribute extends AST.BaseNode {
404
412
  type: 'Attribute';
@@ -424,20 +432,20 @@ declare module 'estree' {
424
432
  }
425
433
 
426
434
  /**
427
- * Ripple's extended Declaration type that includes Component
435
+ * TSRX's extended Declaration type that includes Component
428
436
  * Use this instead of Declaration when you need Component support
429
437
  */
430
438
  export type TSRXDeclaration = AST.Declaration | Component | AST.TSDeclareFunction;
431
439
 
432
440
  /**
433
- * Ripple's extended ExportNamedDeclaration with Component support
441
+ * TSRX's extended ExportNamedDeclaration with Component support
434
442
  */
435
443
  interface TSRXExportNamedDeclaration extends Omit<AST.ExportNamedDeclaration, 'declaration'> {
436
444
  declaration?: TSRXDeclaration | null | undefined;
437
445
  }
438
446
 
439
447
  /**
440
- * Ripple's extended Program with Component support
448
+ * TSRX's extended Program with Component support
441
449
  */
442
450
  interface TSRXProgram extends Omit<Program, 'body'> {
443
451
  body: (Program['body'][number] | Component | FunctionExpression)[];
@@ -1046,7 +1054,13 @@ declare module 'estree' {
1046
1054
  > {
1047
1055
  params: TypeNode[];
1048
1056
  }
1049
- interface TSTypePredicate extends AcornTSNode<TSESTree.TSTypePredicate> {}
1057
+ interface TSTypePredicate extends Omit<
1058
+ AcornTSNode<TSESTree.TSTypePredicate>,
1059
+ 'parameterName' | 'typeAnnotation'
1060
+ > {
1061
+ parameterName: AST.Identifier | AST.TSThisType;
1062
+ typeAnnotation: AST.TSTypeAnnotation | null;
1063
+ }
1050
1064
  interface TSTypeQuery extends Omit<
1051
1065
  AcornTSNode<TSESTree.TSTypeQuery>,
1052
1066
  'exprName' | 'typeArguments'
@@ -1148,7 +1162,7 @@ export interface AnalysisResult {
1148
1162
  }
1149
1163
 
1150
1164
  /**
1151
- * Configuration for Ripple parser plugin
1165
+ * Configuration for the TSRX parser plugin
1152
1166
  */
1153
1167
  export interface TSRXPluginConfig {
1154
1168
  allowSatisfies?: boolean;
@@ -0,0 +1,193 @@
1
+ import type * as AST from 'estree';
2
+ import type { RawSourceMap } from 'source-map';
3
+
4
+ /**
5
+ * Result returned by a JSX platform transform (React, Preact, Solid).
6
+ */
7
+ export interface JsxTransformResult {
8
+ ast: AST.Program;
9
+ code: string;
10
+ /**
11
+ * Esrap-shaped source map over the generated TSX. Consumed by
12
+ * `create_volar_mappings_result` to build Volar code mappings and by
13
+ * downstream Vite / Rollup plugins to chain source maps.
14
+ */
15
+ map: RawSourceMap;
16
+ css: { code: string; hash: string } | null;
17
+ }
18
+
19
+ /**
20
+ * Optional per-call compile options passed to a created JSX transform.
21
+ */
22
+ export interface JsxTransformOptions {
23
+ /**
24
+ * Override the import source used for `Suspense` in try-block transforms.
25
+ * Falls back to `platform.imports.suspense`. Preact uses this to let the
26
+ * host pick `preact/compat` vs. another compat entry point.
27
+ */
28
+ suspenseSource?: string;
29
+ }
30
+
31
+ /**
32
+ * Override hooks for the parts of the transform that differ substantially
33
+ * between platforms. Every hook is optional — when omitted, the factory
34
+ * uses its React/Preact-style default.
35
+ *
36
+ * Solid uses all of these: control-flow statements become `<Show>` /
37
+ * `<For>` / `<Switch>/<Match>` / `<Errored>/<Loading>` JSX; component
38
+ * bodies are hoisted to preserve setup-once semantics; module imports
39
+ * come from `solid-js` instead of `react`; element attributes support
40
+ * composite-element / textContent shortcuts.
41
+ *
42
+ * The `ctx` parameter is the active `TransformContext` — see the
43
+ * target's transform.js for its shape; platform-owned fields can be
44
+ * read and written freely.
45
+ */
46
+ export interface JsxPlatformHooks {
47
+ /**
48
+ * Per-statement control-flow rewrites. Each hook receives the original
49
+ * Ripple statement (with children already walked) and returns a JSX
50
+ * child (or an expression container wrapping one).
51
+ */
52
+ controlFlow?: {
53
+ ifStatement?: (node: any, ctx: any) => any;
54
+ forOf?: (node: any, ctx: any) => any;
55
+ switchStatement?: (node: any, ctx: any) => any;
56
+ tryStatement?: (node: any, ctx: any) => any;
57
+ };
58
+ /**
59
+ * Lower a `component` declaration to a FunctionDeclaration. React / Preact
60
+ * use a default that extracts hooks, hoists statics, and handles async
61
+ * bodies. Solid replaces this with a setup-once implementation that
62
+ * hoists post-early-return JSX into a reactive `<Show>`.
63
+ */
64
+ componentToFunction?: (component: any, ctx: any, helperState?: any) => any;
65
+ /**
66
+ * Inject module-level imports after the main walk. Default: import
67
+ * `Suspense` from `platform.imports.suspense` and `TsrxErrorBoundary`
68
+ * from `platform.imports.errorBoundary` if the walk flagged them.
69
+ * Solid injects `Show`, `For`, `Switch`, `Match`, `Errored`, `Loading`
70
+ * from `solid-js`.
71
+ */
72
+ injectImports?: (program: AST.Program, ctx: any, suspenseSource: string) => void;
73
+ /**
74
+ * Transform a Ripple element's attributes to JSX attributes. Default
75
+ * is "map over `to_jsx_attribute`". Solid replaces this to route
76
+ * attributes through its composite-element handling.
77
+ */
78
+ transformElementAttributes?: (attrs: any[], ctx: any, element: any) => any[];
79
+ /**
80
+ * Lower a Ripple `Element` node to a JSXElement. Default is the
81
+ * factory's `to_jsx_element`. The hook receives the walker-transformed
82
+ * node (`inner`, with children already lowered) plus the element's
83
+ * raw pre-walk children — Solid uses the latter to detect a lone
84
+ * `Text` child it can hoist to a `textContent` attribute before the
85
+ * generic text→JSXExpressionContainer transform runs.
86
+ */
87
+ transformElement?: (inner: any, ctx: any, rawChildren: any[]) => any;
88
+ /**
89
+ * Custom validation for a component body that uses top-level `await`.
90
+ * Default: enforce `validation.requireUseServerForAwait`. Solid rejects
91
+ * component-level await outright with a keyword-precise location.
92
+ */
93
+ validateComponentAwait?: (
94
+ awaitNode: any,
95
+ component: any,
96
+ ctx: any,
97
+ moduleUsesServerDirective: boolean,
98
+ source: string,
99
+ ) => void;
100
+ /**
101
+ * Factory-managed state extra fields. Returns a record merged into the
102
+ * initial `transform_context`. Lets solid seed its `needs_show` /
103
+ * `needs_for` / etc. flags without forking the factory.
104
+ */
105
+ initialState?: () => Record<string, unknown>;
106
+ }
107
+
108
+ /**
109
+ * A JSX platform descriptor is the parameter to `createJsxTransform`. It
110
+ * declares how to render a Ripple AST as valid TSX for the target platform
111
+ * (React, Preact, Solid). The shared transformer in `@tsrx/core` reads this
112
+ * descriptor at each platform-specific decision point instead of branching
113
+ * on the platform name.
114
+ */
115
+ export interface JsxPlatform {
116
+ /**
117
+ * Human-readable platform name, used in error messages
118
+ * (e.g. "React TSRX does not support …").
119
+ */
120
+ name: string;
121
+
122
+ imports: {
123
+ /**
124
+ * Module to import `Suspense` from when a `try { ... } pending { ... }`
125
+ * block appears. React: `'react'`. Preact: `'preact/compat'`.
126
+ */
127
+ suspense: string;
128
+ /**
129
+ * Module to import `TsrxErrorBoundary` from when a `try { ... } catch (...)`
130
+ * block appears. Usually `'@tsrx/<platform>/error-boundary'`.
131
+ */
132
+ errorBoundary: string;
133
+ };
134
+
135
+ jsx: {
136
+ /**
137
+ * Rewrite Ripple's `class` attribute to React's `className`. React: true.
138
+ * Preact and Solid accept `class` natively, so: false.
139
+ */
140
+ rewriteClassAttr: boolean;
141
+ /**
142
+ * Accepted values of `kind` in `<tsx:kind>` compat blocks. React accepts
143
+ * only `'react'`. Preact accepts both `'preact'` and `'react'`.
144
+ */
145
+ acceptedTsxKinds: readonly string[];
146
+ };
147
+
148
+ validation: {
149
+ /**
150
+ * Require a top-level `"use server"` directive before a component may
151
+ * contain top-level `await`. Preact/Solid: true. React: false.
152
+ *
153
+ * Solid keeps this enabled as a fallback invariant (if its custom await
154
+ * validator hook is removed, the default factory validation still rejects
155
+ * component-level `await` without `"use server"`).
156
+ */
157
+ requireUseServerForAwait: boolean;
158
+ /**
159
+ * When `false`, skip scanning for a top-level `"use server"` directive
160
+ * while a custom `validateComponentAwait` hook is present.
161
+ *
162
+ * This is useful for platforms whose custom validator never uses the
163
+ * directive signal (for example Solid, which always rejects component-level
164
+ * `await`), while still keeping `requireUseServerForAwait: true` as a
165
+ * fallback if the custom validator is removed.
166
+ *
167
+ * Default: `true`.
168
+ */
169
+ scanUseServerDirectiveForAwaitWithCustomValidator?: boolean;
170
+ };
171
+
172
+ /**
173
+ * Optional overrides for parts of the transform that diverge substantially
174
+ * between platforms (control flow, component lowering, imports, element
175
+ * attributes). When absent, each hook falls back to the React/Preact-style
176
+ * default baked into the factory.
177
+ */
178
+ hooks?: JsxPlatformHooks;
179
+ }
180
+
181
+ /**
182
+ * Build a `transform()` function for a specific JSX platform. The returned
183
+ * function takes a parsed Ripple AST and produces a TSX module plus source
184
+ * map and optional CSS.
185
+ */
186
+ export function createJsxTransform(
187
+ platform: JsxPlatform,
188
+ ): (
189
+ ast: AST.Program,
190
+ source: string,
191
+ filename?: string,
192
+ options?: JsxTransformOptions,
193
+ ) => JsxTransformResult;
package/types/parse.d.ts CHANGED
@@ -1,8 +1,8 @@
1
1
  /**
2
- * Type definitions for Ripple's extended Acorn parser
2
+ * Type definitions for TSRX's extended Acorn parser
3
3
  *
4
4
  * These types cover internal properties and static class members that aren't
5
- * included in Acorn's official type definitions but are used by Ripple's parser.
5
+ * included in Acorn's official type definitions but are used by the TSRX parser.
6
6
  *
7
7
  * Based on acorn source code: https://github.com/acornjs/acorn
8
8
  * and @sveltejs/acorn-typescript: https://github.com/sveltejs/acorn-typescript
@@ -433,7 +433,7 @@ export namespace Parse {
433
433
  * Extended Parser instance with internal properties
434
434
  *
435
435
  * These properties are used internally by Acorn but not exposed in official types.
436
- * They are accessed by Ripple's custom parser plugin for whitespace handling,
436
+ * They are accessed by the TSRX parser plugin for whitespace handling,
437
437
  * JSX parsing, and other advanced features.
438
438
  */
439
439
  export interface Parser {
@@ -1705,7 +1705,7 @@ export namespace Parse {
1705
1705
  }
1706
1706
 
1707
1707
  /**
1708
- * The constructor/class type for the extended Ripple parser.
1708
+ * The constructor/class type for the extended TSRX parser.
1709
1709
  * This represents the static side of the parser class after extending with plugins.
1710
1710
  */
1711
1711
  export interface ParserConstructor {
@@ -1716,7 +1716,7 @@ export namespace Parse {
1716
1716
  tokContexts: TokContexts;
1717
1717
  /** TypeScript extensions when using acorn-typescript */
1718
1718
  acornTypeScript: AcornTypeScriptExtensions;
1719
- /** Static parse method that returns Ripple's extended Program type */
1719
+ /** Static parse method that returns TSRX's extended Program type */
1720
1720
  parse(input: string, options: Options): AST.Program;
1721
1721
  /** Static parseExpressionAt method */
1722
1722
  parseExpressionAt(input: string, pos: number, options: Options): AST.Expression;