@tsrx/core 0.1.34 → 0.1.36
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 +1 -1
- package/src/plugin.js +29 -0
- package/src/scope.js +18 -4
- package/src/transform/jsx/helpers.js +0 -4
- package/src/transform/jsx/index.js +1 -1
- package/src/utils/builders.js +12 -64
- package/types/index.d.ts +121 -99
package/package.json
CHANGED
package/src/plugin.js
CHANGED
|
@@ -259,6 +259,13 @@ export function TSRXPlugin(config) {
|
|
|
259
259
|
// `#filterTemplateScriptContexts`.
|
|
260
260
|
/** @type {number[]} */
|
|
261
261
|
#expressionContainerContextBaselines = [];
|
|
262
|
+
// `#path` length at the start of each open `{ … }` expression container.
|
|
263
|
+
// Raw template text inside a container belongs only to an element opened
|
|
264
|
+
// inside it (`{<div> a</div>}`); at the container's own expression level
|
|
265
|
+
// (`{cond ? (<Outer>…</Outer>) : null}` after the `)`) the next characters
|
|
266
|
+
// are JS, and reading them as raw text would swallow tokens like `: null`.
|
|
267
|
+
/** @type {number[]} */
|
|
268
|
+
#expressionContainerPathBaselines = [];
|
|
262
269
|
#consumeContainerBraceAfterScope = false;
|
|
263
270
|
#scriptJSXElementDepth = 0;
|
|
264
271
|
#forceScriptJSXElementDepth = 0;
|
|
@@ -936,6 +943,26 @@ export function TSRXPlugin(config) {
|
|
|
936
943
|
if (!current_template_node || this.#isJSXControlFlowDirectiveAt(this.pos)) {
|
|
937
944
|
return false;
|
|
938
945
|
}
|
|
946
|
+
// Inside an expression container (only reachable with
|
|
947
|
+
// `allow_inside_expression_container`), raw text belongs to an element
|
|
948
|
+
// opened inside the container. When the innermost native template element
|
|
949
|
+
// sits below the container's path baseline we are at the container's own
|
|
950
|
+
// expression level — e.g. after `(<Outer>…</Outer>)` in
|
|
951
|
+
// `{cond ? (<Outer>…</Outer>) : null}` — and the following characters are
|
|
952
|
+
// JS tokens, not template text.
|
|
953
|
+
if (this.#jsxExpressionContainerDepth > 0 && !this.#openingNativeTemplateNode) {
|
|
954
|
+
const path_baseline = this.#expressionContainerPathBaselines.at(-1) ?? 0;
|
|
955
|
+
let inside_container = false;
|
|
956
|
+
for (let i = this.#path.length - 1; i >= path_baseline; i--) {
|
|
957
|
+
if (this.#isNativeTemplateNode(this.#path[i])) {
|
|
958
|
+
inside_container = true;
|
|
959
|
+
break;
|
|
960
|
+
}
|
|
961
|
+
}
|
|
962
|
+
if (!inside_container) {
|
|
963
|
+
return false;
|
|
964
|
+
}
|
|
965
|
+
}
|
|
939
966
|
if (this.#isTemplateLineCommentStart(this.pos)) {
|
|
940
967
|
return false;
|
|
941
968
|
}
|
|
@@ -3377,6 +3404,7 @@ export function TSRXPlugin(config) {
|
|
|
3377
3404
|
// container must not strip anything below this floor (see
|
|
3378
3405
|
// `#filterTemplateScriptContexts`).
|
|
3379
3406
|
this.#expressionContainerContextBaselines.push(this.context.length);
|
|
3407
|
+
this.#expressionContainerPathBaselines.push(this.#path.length);
|
|
3380
3408
|
pushed_context_baseline = true;
|
|
3381
3409
|
|
|
3382
3410
|
node.expression =
|
|
@@ -3398,6 +3426,7 @@ export function TSRXPlugin(config) {
|
|
|
3398
3426
|
this.#jsxExpressionContainerDepth--;
|
|
3399
3427
|
if (pushed_context_baseline) {
|
|
3400
3428
|
this.#expressionContainerContextBaselines.pop();
|
|
3429
|
+
this.#expressionContainerPathBaselines.pop();
|
|
3401
3430
|
}
|
|
3402
3431
|
}
|
|
3403
3432
|
|
package/src/scope.js
CHANGED
|
@@ -63,10 +63,9 @@ export function create_scopes(ast, root, parent, error_options) {
|
|
|
63
63
|
const scope = state.scope.child(true);
|
|
64
64
|
scopes.set(node, scope);
|
|
65
65
|
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
}
|
|
66
|
+
// Only a `@for` directive can declare an `index` binding.
|
|
67
|
+
if (node.type === 'JSXForExpression' && node.index) {
|
|
68
|
+
state.scope.declare(node.index, 'normal', 'let');
|
|
70
69
|
}
|
|
71
70
|
|
|
72
71
|
next({ scope });
|
|
@@ -181,6 +180,21 @@ export function create_scopes(ast, root, parent, error_options) {
|
|
|
181
180
|
SwitchStatement: create_block_scope,
|
|
182
181
|
JSXForExpression: create_block_scope,
|
|
183
182
|
JSXSwitchExpression: create_block_scope,
|
|
183
|
+
// Each `@{ … }` code block is its own lexical scope, whether it is a
|
|
184
|
+
// function body or a template child — its bindings never leak out.
|
|
185
|
+
JSXCodeBlock(node, context) {
|
|
186
|
+
const parent = context.path.at(-1);
|
|
187
|
+
if (
|
|
188
|
+
parent?.type === 'FunctionDeclaration' ||
|
|
189
|
+
parent?.type === 'FunctionExpression' ||
|
|
190
|
+
parent?.type === 'ArrowFunctionExpression'
|
|
191
|
+
) {
|
|
192
|
+
// The function already created a scope for its body.
|
|
193
|
+
context.next();
|
|
194
|
+
} else {
|
|
195
|
+
create_block_scope(node, context);
|
|
196
|
+
}
|
|
197
|
+
},
|
|
184
198
|
BlockStatement(node, context) {
|
|
185
199
|
const parent = context.path.at(-1);
|
|
186
200
|
if (
|
|
@@ -243,7 +243,6 @@ export function tsx_with_ts_locations() {
|
|
|
243
243
|
export function is_template_if_node(node) {
|
|
244
244
|
return (
|
|
245
245
|
node?.type === 'JSXIfExpression' ||
|
|
246
|
-
node?.metadata?.tsrxDirective === 'if' ||
|
|
247
246
|
(node?.type === 'IfStatement' && node?.statementType === 'IfStatement')
|
|
248
247
|
);
|
|
249
248
|
}
|
|
@@ -255,7 +254,6 @@ export function is_template_if_node(node) {
|
|
|
255
254
|
export function is_template_for_of_node(node) {
|
|
256
255
|
return (
|
|
257
256
|
node?.type === 'JSXForExpression' ||
|
|
258
|
-
node?.metadata?.tsrxDirective === 'for' ||
|
|
259
257
|
(node?.type === 'ForOfStatement' && node?.statementType === 'ForOfStatement')
|
|
260
258
|
);
|
|
261
259
|
}
|
|
@@ -267,7 +265,6 @@ export function is_template_for_of_node(node) {
|
|
|
267
265
|
export function is_template_switch_node(node) {
|
|
268
266
|
return (
|
|
269
267
|
node?.type === 'JSXSwitchExpression' ||
|
|
270
|
-
node?.metadata?.tsrxDirective === 'switch' ||
|
|
271
268
|
(node?.type === 'SwitchStatement' && node?.statementType === 'SwitchStatement')
|
|
272
269
|
);
|
|
273
270
|
}
|
|
@@ -279,7 +276,6 @@ export function is_template_switch_node(node) {
|
|
|
279
276
|
export function is_template_try_node(node) {
|
|
280
277
|
return (
|
|
281
278
|
node?.type === 'JSXTryExpression' ||
|
|
282
|
-
node?.metadata?.tsrxDirective === 'try' ||
|
|
283
279
|
(node?.type === 'TryStatement' && node?.statementType === 'TryStatement')
|
|
284
280
|
);
|
|
285
281
|
}
|
|
@@ -2302,7 +2302,7 @@ function create_style_anchor_name(transform_context) {
|
|
|
2302
2302
|
}
|
|
2303
2303
|
|
|
2304
2304
|
/**
|
|
2305
|
-
* @param {
|
|
2305
|
+
* @param {AST.TSRXJSXElement} element
|
|
2306
2306
|
*/
|
|
2307
2307
|
function disable_style_anchor_verification(element) {
|
|
2308
2308
|
if (element.openingElement?.name) {
|
package/src/utils/builders.js
CHANGED
|
@@ -368,26 +368,6 @@ export function literal(value, raw, loc_info) {
|
|
|
368
368
|
return set_location(node, loc_info);
|
|
369
369
|
}
|
|
370
370
|
|
|
371
|
-
/**
|
|
372
|
-
* Ripple template `Text` node wrapping a string literal of `value`. Used by the
|
|
373
|
-
* Ripple normalizer when lowering a JSX text child to a template Text node.
|
|
374
|
-
*
|
|
375
|
-
* Remove once Ripple transformers move to the parser's JSX AST
|
|
376
|
-
*
|
|
377
|
-
* @param {string} value
|
|
378
|
-
* @param {AST.NodeWithLocation} [loc_info]
|
|
379
|
-
* @returns {AST.Text}
|
|
380
|
-
*/
|
|
381
|
-
export function text(value, loc_info) {
|
|
382
|
-
const node = /** @type {AST.Text} */ ({
|
|
383
|
-
type: 'Text',
|
|
384
|
-
expression: literal(value, JSON.stringify(value), loc_info),
|
|
385
|
-
metadata: { path: [] },
|
|
386
|
-
});
|
|
387
|
-
|
|
388
|
-
return set_location(node, loc_info);
|
|
389
|
-
}
|
|
390
|
-
|
|
391
371
|
/**
|
|
392
372
|
* @param {AST.Expression | AST.Super} object
|
|
393
373
|
* @param {string | AST.Expression | AST.PrivateIdentifier} property
|
|
@@ -1219,10 +1199,13 @@ export function jsx_element_fresh(
|
|
|
1219
1199
|
}
|
|
1220
1200
|
|
|
1221
1201
|
/**
|
|
1222
|
-
*
|
|
1223
|
-
* @
|
|
1224
|
-
*
|
|
1225
|
-
* @
|
|
1202
|
+
* Elements carry the parser's widened TSRX shape (dynamic-tag names, lowered
|
|
1203
|
+
* template children) — see {@link jsx_fragment}. A `JSXStyleElement` shares
|
|
1204
|
+
* the element shape and may be re-emitted as an empty `<style>` element.
|
|
1205
|
+
* @param {AST.TSRXJSXElement | AST.JSXStyleElement} node
|
|
1206
|
+
* @param {ESTreeJSX.TSRXJSXOpeningElement['attributes']} attributes
|
|
1207
|
+
* @param {AST.TSRXJSXElement['children']} children
|
|
1208
|
+
* @returns {AST.TSRXJSXElement}
|
|
1226
1209
|
*/
|
|
1227
1210
|
export function jsx_element(node, attributes = [], children = []) {
|
|
1228
1211
|
return {
|
|
@@ -1248,9 +1231,12 @@ export function jsx_element(node, attributes = [], children = []) {
|
|
|
1248
1231
|
}
|
|
1249
1232
|
|
|
1250
1233
|
/**
|
|
1251
|
-
*
|
|
1234
|
+
* Fragments carry the parser's widened TSRX shape: template lowering places
|
|
1235
|
+
* any node in `children` (statement blocks, directives, code-block IIFEs),
|
|
1236
|
+
* not just printable JSX children.
|
|
1237
|
+
* @param {AST.TSRXJSXFragment['children']} children
|
|
1252
1238
|
* @param {ESTreeJSX.JSXOpeningFragment['attributes']} [attributes]
|
|
1253
|
-
* @returns {
|
|
1239
|
+
* @returns {AST.TSRXJSXFragment}
|
|
1254
1240
|
*/
|
|
1255
1241
|
export function jsx_fragment(children = [], attributes = []) {
|
|
1256
1242
|
return {
|
|
@@ -1269,44 +1255,6 @@ export function jsx_fragment(children = [], attributes = []) {
|
|
|
1269
1255
|
};
|
|
1270
1256
|
}
|
|
1271
1257
|
|
|
1272
|
-
/**
|
|
1273
|
-
* Ripple's internal fragment template node (the normalized form of a
|
|
1274
|
-
* `JSXFragment`).
|
|
1275
|
-
* @param {AST.Node[]} [children]
|
|
1276
|
-
* @param {AST.NodeWithLocation} [loc_info]
|
|
1277
|
-
* @returns {AST.TsrxFragment}
|
|
1278
|
-
*/
|
|
1279
|
-
export function tsrx_fragment(children = [], loc_info) {
|
|
1280
|
-
const node = /** @type {AST.TsrxFragment} */ (
|
|
1281
|
-
/** @type {unknown} */ ({
|
|
1282
|
-
type: 'TsrxFragment',
|
|
1283
|
-
children,
|
|
1284
|
-
attributes: [],
|
|
1285
|
-
selfClosing: false,
|
|
1286
|
-
metadata: { path: [] },
|
|
1287
|
-
})
|
|
1288
|
-
);
|
|
1289
|
-
|
|
1290
|
-
return set_location(node, loc_info);
|
|
1291
|
-
}
|
|
1292
|
-
|
|
1293
|
-
/**
|
|
1294
|
-
* Ripple's internal expression template child (the normalized form of a
|
|
1295
|
-
* `JSXExpressionContainer` child).
|
|
1296
|
-
* @param {AST.Expression} expression
|
|
1297
|
-
* @param {AST.NodeWithLocation} [loc_info]
|
|
1298
|
-
* @returns {AST.TSRXExpression}
|
|
1299
|
-
*/
|
|
1300
|
-
export function tsrx_expression(expression, loc_info) {
|
|
1301
|
-
const node = /** @type {AST.TSRXExpression} */ ({
|
|
1302
|
-
type: 'TSRXExpression',
|
|
1303
|
-
expression,
|
|
1304
|
-
metadata: { path: [] },
|
|
1305
|
-
});
|
|
1306
|
-
|
|
1307
|
-
return set_location(node, loc_info);
|
|
1308
|
-
}
|
|
1309
|
-
|
|
1310
1258
|
/**
|
|
1311
1259
|
* @param {AST.Expression | ESTreeJSX.JSXEmptyExpression} expression
|
|
1312
1260
|
* @param {AST.NodeWithLocation} [loc_info]
|
package/types/index.d.ts
CHANGED
|
@@ -88,7 +88,28 @@ interface BaseNodeMetaData {
|
|
|
88
88
|
dynamicElement?: boolean;
|
|
89
89
|
templateMode?: 'script' | 'template';
|
|
90
90
|
script_only?: boolean;
|
|
91
|
-
|
|
91
|
+
/** A synthetic wrapper for a nested `@{ @{ ... } }` code-block render chain. */
|
|
92
|
+
tsrx_code_block_chain?: boolean;
|
|
93
|
+
/** A synthesized render-body fragment (see create_native_tsrx_render_function). */
|
|
94
|
+
tsrx_render_fragment?: boolean;
|
|
95
|
+
/** A merged text run produced by normalize_children - renders through the text path. */
|
|
96
|
+
tsrx_text?: boolean;
|
|
97
|
+
/** Control-flow node renders as the sole child of its parent (controlled anchor). */
|
|
98
|
+
is_controlled?: boolean;
|
|
99
|
+
/** Control-flow node is the root of a render body - anchors on `__anchor`. */
|
|
100
|
+
root_controlled?: boolean;
|
|
101
|
+
/** Append target set by transform_children when all siblings are static component children. */
|
|
102
|
+
append_into?: AST.Identifier;
|
|
103
|
+
/** Generated pattern id substituted for a destructured keyed `@for` left. */
|
|
104
|
+
tsrx_for_pattern_id?: AST.Identifier;
|
|
105
|
+
/** Memoized render-body statements (see get_native_tsrx_function_body). */
|
|
106
|
+
tsrx_render_body?: AST.Node[];
|
|
107
|
+
/** Memoized resolved render slot of a `@{ … }` code block (see get_code_block_render). */
|
|
108
|
+
tsrx_render_slot?: { render: AST.Node | null };
|
|
109
|
+
/** Memoized template-child lowering of a `@{ … }` code block (see get_code_block_template_child). */
|
|
110
|
+
tsrx_template_child?: { child: AST.Node | null };
|
|
111
|
+
/** Memoized `<> … </>` wrapper for a value-position directive (see get_directive_value_wrapper). */
|
|
112
|
+
tsrx_value_wrapper?: AST.TSRXJSXFragment;
|
|
92
113
|
ts_name?: string;
|
|
93
114
|
delegated?: any;
|
|
94
115
|
returned_tsrx_return?: AST.ReturnStatement;
|
|
@@ -122,6 +143,10 @@ interface FunctionMetaData extends BaseNodeMetaData {
|
|
|
122
143
|
is_method?: boolean;
|
|
123
144
|
tracked?: boolean;
|
|
124
145
|
has_lazy_descendants?: boolean;
|
|
146
|
+
/** The component's extracted `<style>` stylesheet (element-level scoped-class info lives on BaseNodeMetaData's `css`). */
|
|
147
|
+
component_css?: AST.CSS.StyleSheet | null;
|
|
148
|
+
/** Top-level scoped classes collected while pruning the component's CSS. */
|
|
149
|
+
topScopedClasses?: TopScopedClasses;
|
|
125
150
|
synthetic_children?: boolean;
|
|
126
151
|
generated_helpers?: any[];
|
|
127
152
|
generated_statics?: any[];
|
|
@@ -248,30 +273,17 @@ declare module 'estree' {
|
|
|
248
273
|
tracked?: boolean;
|
|
249
274
|
}
|
|
250
275
|
|
|
251
|
-
interface SimpleLiteral extends AST.LiteralNode {}
|
|
252
|
-
interface RegExpLiteral extends AST.LiteralNode {}
|
|
253
|
-
interface BigIntLiteral extends AST.LiteralNode {}
|
|
254
|
-
|
|
255
276
|
interface TrackedNode {
|
|
256
277
|
tracked?: boolean;
|
|
257
278
|
}
|
|
258
279
|
|
|
259
|
-
interface LiteralNode {
|
|
260
|
-
was_expression?: boolean;
|
|
261
|
-
}
|
|
262
|
-
|
|
263
280
|
// Include TypeScript node types and TSRX-specific nodes in NodeMap
|
|
264
281
|
interface NodeMap {
|
|
265
|
-
|
|
266
|
-
TsrxFragment: TsrxFragment;
|
|
267
|
-
Text: Text;
|
|
282
|
+
JSXSpreadChild: ESTreeJSX.JSXSpreadChild;
|
|
268
283
|
TSRXJSXElement: TSRXJSXElement;
|
|
269
284
|
TSRXJSXFragment: TSRXJSXFragment;
|
|
270
285
|
TSRXJSXOpeningElement: ESTreeJSX.TSRXJSXOpeningElement;
|
|
271
286
|
TSRXJSXClosingElement: ESTreeJSX.TSRXJSXClosingElement;
|
|
272
|
-
TSRXExpression: TSRXExpression;
|
|
273
|
-
Attribute: Attribute;
|
|
274
|
-
SpreadAttribute: SpreadAttribute;
|
|
275
287
|
JSXCodeBlock: JSXCodeBlock;
|
|
276
288
|
JSXStyleElement: JSXStyleElement;
|
|
277
289
|
JSXIfExpression: JSXIfExpression;
|
|
@@ -282,10 +294,8 @@ declare module 'estree' {
|
|
|
282
294
|
}
|
|
283
295
|
|
|
284
296
|
interface ExpressionMap {
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
Text: Text;
|
|
288
|
-
TSRXExpression: TSRXExpression;
|
|
297
|
+
TSRXJSXElement: TSRXJSXElement;
|
|
298
|
+
TSRXJSXFragment: TSRXJSXFragment;
|
|
289
299
|
JSXCodeBlock: JSXCodeBlock;
|
|
290
300
|
JSXStyleElement: JSXStyleElement;
|
|
291
301
|
JSXIfExpression: JSXIfExpression;
|
|
@@ -299,69 +309,6 @@ declare module 'estree' {
|
|
|
299
309
|
|
|
300
310
|
type TraversableAstNode = AST.Node & Record<string, unknown>;
|
|
301
311
|
|
|
302
|
-
// Ripple-normalized template node shapes. The core parser emits JSX-shaped
|
|
303
|
-
// TSRX nodes; @tsrx/ripple creates these during its normalization pass.
|
|
304
|
-
interface Attribute extends AST.BaseNode {
|
|
305
|
-
type: 'Attribute';
|
|
306
|
-
name: AST.Identifier;
|
|
307
|
-
value: any;
|
|
308
|
-
shorthand?: boolean;
|
|
309
|
-
metadata: BaseNodeMetaData;
|
|
310
|
-
}
|
|
311
|
-
|
|
312
|
-
interface SpreadAttribute extends AST.BaseNode {
|
|
313
|
-
type: 'SpreadAttribute';
|
|
314
|
-
argument: AST.Expression;
|
|
315
|
-
metadata: BaseNodeMetaData;
|
|
316
|
-
}
|
|
317
|
-
|
|
318
|
-
interface Element extends AST.BaseExpression {
|
|
319
|
-
type: 'Element';
|
|
320
|
-
id: AST.Expression;
|
|
321
|
-
attributes: Array<Attribute | SpreadAttribute>;
|
|
322
|
-
children: AST.Node[];
|
|
323
|
-
openingElement: ESTreeJSX.JSXOpeningElement;
|
|
324
|
-
closingElement: ESTreeJSX.JSXClosingElement | null;
|
|
325
|
-
selfClosing?: boolean;
|
|
326
|
-
unclosed?: boolean;
|
|
327
|
-
isDynamic?: boolean;
|
|
328
|
-
css?: string;
|
|
329
|
-
metadata: BaseNodeMetaData;
|
|
330
|
-
start: number;
|
|
331
|
-
end: number;
|
|
332
|
-
}
|
|
333
|
-
|
|
334
|
-
interface TsrxFragment extends AST.BaseExpression {
|
|
335
|
-
type: 'TsrxFragment';
|
|
336
|
-
children: AST.Node[];
|
|
337
|
-
openingElement?: ESTreeJSX.JSXOpeningFragment;
|
|
338
|
-
closingElement?: ESTreeJSX.JSXClosingFragment | null;
|
|
339
|
-
selfClosing?: boolean;
|
|
340
|
-
attributes?: Array<Attribute | SpreadAttribute>;
|
|
341
|
-
metadata: BaseNodeMetaData & {
|
|
342
|
-
/**
|
|
343
|
-
* A synthetic wrapper for a nested code-block render chain
|
|
344
|
-
* (`@{ @{ … } }`), so render-slot consumers see a template node;
|
|
345
|
-
* template-children lowering unwraps it.
|
|
346
|
-
*/
|
|
347
|
-
tsrx_code_block_chain?: boolean;
|
|
348
|
-
};
|
|
349
|
-
start: number;
|
|
350
|
-
end: number;
|
|
351
|
-
}
|
|
352
|
-
|
|
353
|
-
interface Text extends AST.BaseExpression {
|
|
354
|
-
type: 'Text';
|
|
355
|
-
expression: AST.Expression;
|
|
356
|
-
metadata: BaseNodeMetaData;
|
|
357
|
-
}
|
|
358
|
-
|
|
359
|
-
interface TSRXExpression extends AST.BaseExpression {
|
|
360
|
-
type: 'TSRXExpression';
|
|
361
|
-
expression: AST.Expression;
|
|
362
|
-
metadata: BaseNodeMetaData;
|
|
363
|
-
}
|
|
364
|
-
|
|
365
312
|
type TSRXJSXChild =
|
|
366
313
|
| ESTreeJSX.JSXText
|
|
367
314
|
| ESTreeJSX.JSXExpressionContainer
|
|
@@ -376,7 +323,16 @@ declare module 'estree' {
|
|
|
376
323
|
AST.NodeWithMaybeComments {
|
|
377
324
|
openingElement: ESTreeJSX.TSRXJSXOpeningElement;
|
|
378
325
|
closingElement: ESTreeJSX.TSRXJSXClosingElement | null;
|
|
379
|
-
|
|
326
|
+
/** The parser marks dynamic `<{expr}>` tags; lower_dynamic_element clears it on its copy. */
|
|
327
|
+
isDynamic?: boolean;
|
|
328
|
+
/** Loose-mode recovery: the element was never closed. */
|
|
329
|
+
unclosed?: boolean;
|
|
330
|
+
/**
|
|
331
|
+
* The parser emits {@link TSRXJSXChild}; the compile pre-passes lower
|
|
332
|
+
* template children in place (retyped directives, code-block IIFEs,
|
|
333
|
+
* merged text runs), so any node can appear here by transform time.
|
|
334
|
+
*/
|
|
335
|
+
children: AST.Node[];
|
|
380
336
|
metadata: BaseNodeMetaData & {
|
|
381
337
|
ts_name?: string;
|
|
382
338
|
};
|
|
@@ -384,7 +340,8 @@ declare module 'estree' {
|
|
|
384
340
|
|
|
385
341
|
interface TSRXJSXFragment
|
|
386
342
|
extends Omit<ESTreeJSX.JSXFragment, 'children'>, AST.NodeWithMaybeComments {
|
|
387
|
-
children
|
|
343
|
+
/** See {@link TSRXJSXElement}'s `children`. */
|
|
344
|
+
children: AST.Node[];
|
|
388
345
|
}
|
|
389
346
|
|
|
390
347
|
interface JSXCodeBlock extends AST.BaseExpression {
|
|
@@ -411,22 +368,39 @@ declare module 'estree' {
|
|
|
411
368
|
metadata: BaseNodeMetaData;
|
|
412
369
|
}
|
|
413
370
|
|
|
414
|
-
interface
|
|
371
|
+
interface JSXForExpressionBase extends AST.BaseExpression {
|
|
415
372
|
type: 'JSXForExpression';
|
|
416
|
-
|
|
417
|
-
body: AST.
|
|
418
|
-
init?: AST.VariableDeclaration | AST.Expression | null;
|
|
419
|
-
test?: AST.Expression | null;
|
|
420
|
-
update?: AST.Expression | null;
|
|
421
|
-
left?: AST.VariableDeclaration | AST.Pattern;
|
|
422
|
-
right?: AST.Expression;
|
|
423
|
-
await?: boolean;
|
|
373
|
+
/** The parser raises unless the directive body is a `{ … }` block. */
|
|
374
|
+
body: AST.BlockStatement;
|
|
424
375
|
index?: AST.Identifier | null;
|
|
425
376
|
key?: AST.Expression | null;
|
|
426
377
|
empty?: AST.BlockStatement | null;
|
|
427
378
|
metadata: BaseNodeMetaData;
|
|
428
379
|
}
|
|
429
380
|
|
|
381
|
+
interface JSXForOfExpression extends JSXForExpressionBase {
|
|
382
|
+
statementType: 'ForOfStatement';
|
|
383
|
+
left: AST.VariableDeclaration | AST.Pattern;
|
|
384
|
+
right: AST.Expression;
|
|
385
|
+
await?: boolean;
|
|
386
|
+
}
|
|
387
|
+
|
|
388
|
+
interface JSXForInExpression extends JSXForExpressionBase {
|
|
389
|
+
statementType: 'ForInStatement';
|
|
390
|
+
left: AST.VariableDeclaration | AST.Pattern;
|
|
391
|
+
right: AST.Expression;
|
|
392
|
+
}
|
|
393
|
+
|
|
394
|
+
interface JSXForPlainExpression extends JSXForExpressionBase {
|
|
395
|
+
statementType: 'ForStatement';
|
|
396
|
+
init?: AST.VariableDeclaration | AST.Expression | null;
|
|
397
|
+
test?: AST.Expression | null;
|
|
398
|
+
update?: AST.Expression | null;
|
|
399
|
+
}
|
|
400
|
+
|
|
401
|
+
/** `@for` — discriminated on `statementType` (for-of / for-in / for(;;)). */
|
|
402
|
+
type JSXForExpression = JSXForOfExpression | JSXForInExpression | JSXForPlainExpression;
|
|
403
|
+
|
|
430
404
|
interface JSXSwitchExpression extends AST.BaseExpression {
|
|
431
405
|
type: 'JSXSwitchExpression';
|
|
432
406
|
statementType: 'SwitchStatement';
|
|
@@ -445,6 +419,13 @@ declare module 'estree' {
|
|
|
445
419
|
metadata: BaseNodeMetaData;
|
|
446
420
|
}
|
|
447
421
|
|
|
422
|
+
/** A `@if`/`@for`/`@switch`/`@try` template control-flow directive. */
|
|
423
|
+
type JSXTemplateDirective =
|
|
424
|
+
| JSXIfExpression
|
|
425
|
+
| JSXForExpression
|
|
426
|
+
| JSXSwitchExpression
|
|
427
|
+
| JSXTryExpression;
|
|
428
|
+
|
|
448
429
|
interface ParenthesizedExpression extends AST.BaseNode {
|
|
449
430
|
type: 'ParenthesizedExpression';
|
|
450
431
|
expression: AST.Expression;
|
|
@@ -764,11 +745,27 @@ declare module 'estree-jsx' {
|
|
|
764
745
|
}
|
|
765
746
|
|
|
766
747
|
interface TSRXJSXOpeningElement extends Omit<JSXOpeningElement, 'name'> {
|
|
767
|
-
|
|
748
|
+
/** The parser marks dynamic `<{expr}>` tags; lower_dynamic_element clears it on its copy. */
|
|
749
|
+
isDynamic?: boolean;
|
|
750
|
+
// AST.MemberExpression: the parser never produces it, but the to_ts
|
|
751
|
+
// transform plants the visited member chain (`<Foo.Bar>`) into the name
|
|
752
|
+
// slot for the TSX printer and its source mappings.
|
|
753
|
+
name:
|
|
754
|
+
| JSXMemberExpression
|
|
755
|
+
| JSXIdentifier
|
|
756
|
+
| JSXNamespacedName
|
|
757
|
+
| JSXExpressionContainer
|
|
758
|
+
| import('estree').MemberExpression;
|
|
768
759
|
}
|
|
769
760
|
|
|
770
761
|
interface TSRXJSXClosingElement extends Omit<JSXClosingElement, 'name'> {
|
|
771
|
-
|
|
762
|
+
// See TSRXJSXOpeningElement's `name`.
|
|
763
|
+
name:
|
|
764
|
+
| JSXMemberExpression
|
|
765
|
+
| JSXIdentifier
|
|
766
|
+
| JSXNamespacedName
|
|
767
|
+
| JSXExpressionContainer
|
|
768
|
+
| import('estree').MemberExpression;
|
|
772
769
|
}
|
|
773
770
|
|
|
774
771
|
interface ExpressionMap {
|
|
@@ -1116,8 +1113,10 @@ declare module 'estree' {
|
|
|
1116
1113
|
> {
|
|
1117
1114
|
typeAnnotation: TypeNode;
|
|
1118
1115
|
}
|
|
1119
|
-
interface TSTypeAssertion extends AcornTSNode<TSESTree.TSTypeAssertion> {
|
|
1116
|
+
interface TSTypeAssertion extends Omit<AcornTSNode<TSESTree.TSTypeAssertion>, 'typeAnnotation'> {
|
|
1117
|
+
// Have to override it to use our Expression for required properties like metadata
|
|
1120
1118
|
expression: AST.Expression;
|
|
1119
|
+
typeAnnotation: TypeNode;
|
|
1121
1120
|
}
|
|
1122
1121
|
interface TSTypeLiteral extends Omit<AcornTSNode<TSESTree.TSTypeLiteral>, 'members'> {
|
|
1123
1122
|
members: TypeElement[];
|
|
@@ -1452,7 +1451,7 @@ export interface AnalysisState extends BaseState {
|
|
|
1452
1451
|
filename: string;
|
|
1453
1452
|
};
|
|
1454
1453
|
};
|
|
1455
|
-
elements?: Array<
|
|
1454
|
+
elements?: Array<AST.TSRXJSXElement | AST.JSXStyleElement>;
|
|
1456
1455
|
function_depth?: number;
|
|
1457
1456
|
collect?: boolean;
|
|
1458
1457
|
metadata: BaseStateMetaData & {
|
|
@@ -1531,7 +1530,25 @@ export interface TransformClientState extends BaseState {
|
|
|
1531
1530
|
}
|
|
1532
1531
|
|
|
1533
1532
|
/** Override zimmerframe types and provide our own */
|
|
1534
|
-
|
|
1533
|
+
/**
|
|
1534
|
+
* Where stock `@types/estree-jsx` and the TSRX parser shapes share a `type`
|
|
1535
|
+
* tag, visitors receive the TSRX shape — the parser only ever produces that
|
|
1536
|
+
* one (dynamic tag names, code-block children, `metadata`, `start`/`end`).
|
|
1537
|
+
* Interface merging cannot widen the stock interfaces' property types, so the
|
|
1538
|
+
* TSRXJSX* variants override the plain ones here instead.
|
|
1539
|
+
*/
|
|
1540
|
+
interface VisitorNodeOverrides {
|
|
1541
|
+
JSXElement: AST.TSRXJSXElement;
|
|
1542
|
+
JSXFragment: AST.TSRXJSXFragment;
|
|
1543
|
+
JSXOpeningElement: ESTreeJSX.TSRXJSXOpeningElement;
|
|
1544
|
+
JSXClosingElement: ESTreeJSX.TSRXJSXClosingElement;
|
|
1545
|
+
}
|
|
1546
|
+
|
|
1547
|
+
type NodeOf<T extends string, X> = T extends keyof VisitorNodeOverrides
|
|
1548
|
+
? VisitorNodeOverrides[T]
|
|
1549
|
+
: X extends { type: T }
|
|
1550
|
+
? X
|
|
1551
|
+
: never;
|
|
1535
1552
|
|
|
1536
1553
|
type SpecializedVisitors<T extends AST.Node | AST.CSS.Node, U> = {
|
|
1537
1554
|
[K in T['type']]?: Visitor<NodeOf<K, T>, U, T>;
|
|
@@ -1545,7 +1562,12 @@ export type CatchAllVisitor<T, U, V> = (
|
|
|
1545
1562
|
visit: VisitFn<V>,
|
|
1546
1563
|
) => V | void;
|
|
1547
1564
|
|
|
1548
|
-
|
|
1565
|
+
/**
|
|
1566
|
+
* A visitor may replace a node with several: zimmerframe stores the returned
|
|
1567
|
+
* array verbatim in the parent's statement list and the printer flattens
|
|
1568
|
+
* nested statement arrays.
|
|
1569
|
+
*/
|
|
1570
|
+
export type Visitor<T, U, V> = (node: T, context: Context<V, U>) => V | V[] | void;
|
|
1549
1571
|
|
|
1550
1572
|
export type Visitors<T extends AST.Node | AST.CSS.Node, U> = T['type'] extends '_'
|
|
1551
1573
|
? never
|