@tsrx/core 0.1.26 → 0.1.28
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 +67 -32
- package/src/transform/jsx/helpers.js +7 -8
- package/src/transform/jsx/index.js +126 -10
- package/src/utils/builders.js +38 -0
- package/types/index.d.ts +31 -9
package/package.json
CHANGED
package/src/plugin.js
CHANGED
|
@@ -55,27 +55,6 @@ const CharCode = Object.freeze({
|
|
|
55
55
|
closeBrace: 125,
|
|
56
56
|
});
|
|
57
57
|
|
|
58
|
-
/**
|
|
59
|
-
* Keywords after which a `/` begins a regex literal rather than division, used
|
|
60
|
-
* by the look-ahead scanners to track expression position in script content.
|
|
61
|
-
*/
|
|
62
|
-
const REGEX_PRECEDING_KEYWORDS = new Set([
|
|
63
|
-
'return',
|
|
64
|
-
'typeof',
|
|
65
|
-
'instanceof',
|
|
66
|
-
'in',
|
|
67
|
-
'of',
|
|
68
|
-
'new',
|
|
69
|
-
'delete',
|
|
70
|
-
'void',
|
|
71
|
-
'do',
|
|
72
|
-
'else',
|
|
73
|
-
'yield',
|
|
74
|
-
'await',
|
|
75
|
-
'case',
|
|
76
|
-
'throw',
|
|
77
|
-
]);
|
|
78
|
-
|
|
79
58
|
// Transparent wrappers to look through when validating a dynamic tag
|
|
80
59
|
// expression (`<{expr}>`), and syntax that disqualifies one outright.
|
|
81
60
|
const DYNAMIC_TAG_WRAPPER_TYPES = new Set([
|
|
@@ -568,7 +547,7 @@ export function TSRXPlugin(config) {
|
|
|
568
547
|
let index = start;
|
|
569
548
|
let value = '';
|
|
570
549
|
while (index < this.input.length) {
|
|
571
|
-
if (this.#isTemplateLineCommentStart(index)) {
|
|
550
|
+
if (this.#isTemplateLineCommentStart(index, start)) {
|
|
572
551
|
const comment_start = index;
|
|
573
552
|
const comment_start_loc = acorn.getLineInfo(this.input, comment_start);
|
|
574
553
|
index += 2;
|
|
@@ -596,11 +575,32 @@ export function TSRXPlugin(config) {
|
|
|
596
575
|
}
|
|
597
576
|
continue;
|
|
598
577
|
}
|
|
578
|
+
if (this.#isTemplateBlockCommentStart(index)) {
|
|
579
|
+
const comment_start = index;
|
|
580
|
+
const comment_start_loc = acorn.getLineInfo(this.input, comment_start);
|
|
581
|
+
const close = this.input.indexOf('*/', index + 2);
|
|
582
|
+
const value_end = close === -1 ? this.input.length : close;
|
|
583
|
+
index = close === -1 ? this.input.length : close + 2;
|
|
584
|
+
if (this.options.onComment && comment_start >= token_end) {
|
|
585
|
+
const comment_end_loc = acorn.getLineInfo(this.input, index);
|
|
586
|
+
this.options.onComment(
|
|
587
|
+
true,
|
|
588
|
+
this.input.slice(comment_start + 2, value_end),
|
|
589
|
+
comment_start,
|
|
590
|
+
index,
|
|
591
|
+
new acorn.Position(comment_start_loc.line, comment_start_loc.column),
|
|
592
|
+
new acorn.Position(comment_end_loc.line, comment_end_loc.column),
|
|
593
|
+
/** @type {any} */ (null),
|
|
594
|
+
);
|
|
595
|
+
}
|
|
596
|
+
continue;
|
|
597
|
+
}
|
|
599
598
|
const ch = this.input.charCodeAt(index);
|
|
600
599
|
if (
|
|
601
600
|
ch === CharCode.lessThan ||
|
|
602
601
|
ch === CharCode.openBrace ||
|
|
603
602
|
ch === CharCode.closeBrace ||
|
|
603
|
+
this.#isCodeBlockStart(index) ||
|
|
604
604
|
this.#isJSXControlFlowDirectiveAt(index)
|
|
605
605
|
) {
|
|
606
606
|
break;
|
|
@@ -962,13 +962,41 @@ export function TSRXPlugin(config) {
|
|
|
962
962
|
}
|
|
963
963
|
|
|
964
964
|
/**
|
|
965
|
+
* A `//` is a comment only when nothing but whitespace precedes it on its
|
|
966
|
+
* line, or — given `run_start`, the position where the current text run
|
|
967
|
+
* began (right after a sibling element, code block, or expression
|
|
968
|
+
* container) — since that boundary. Once real text has begun, `//` is
|
|
969
|
+
* literal so inline text like `https://…` stays text.
|
|
965
970
|
* @param {number} index
|
|
971
|
+
* @param {number} [run_start]
|
|
966
972
|
*/
|
|
967
|
-
#isTemplateLineCommentStart(index) {
|
|
973
|
+
#isTemplateLineCommentStart(index, run_start = -1) {
|
|
974
|
+
if (
|
|
975
|
+
this.input.charCodeAt(index) !== CharCode.slash ||
|
|
976
|
+
this.input.charCodeAt(index + 1) !== CharCode.slash
|
|
977
|
+
) {
|
|
978
|
+
return false;
|
|
979
|
+
}
|
|
980
|
+
if (this.#isLineStartPosition(index)) return true;
|
|
981
|
+
if (run_start < 0) return false;
|
|
982
|
+
for (let i = index - 1; i >= run_start; i--) {
|
|
983
|
+
const ch = this.input.charCodeAt(i);
|
|
984
|
+
if (ch === CharCode.lineFeed || ch === CharCode.carriageReturn) return false;
|
|
985
|
+
if (ch !== CharCode.space && ch !== CharCode.tab) return false;
|
|
986
|
+
}
|
|
987
|
+
return true;
|
|
988
|
+
}
|
|
989
|
+
|
|
990
|
+
/**
|
|
991
|
+
* Unlike `//` (which is only a comment at line-start so inline text like
|
|
992
|
+
* `https://…` stays text), `/*` starts a comment anywhere in template
|
|
993
|
+
* text, matching `jsx_readToken`.
|
|
994
|
+
* @param {number} index
|
|
995
|
+
*/
|
|
996
|
+
#isTemplateBlockCommentStart(index) {
|
|
968
997
|
return (
|
|
969
998
|
this.input.charCodeAt(index) === CharCode.slash &&
|
|
970
|
-
this.input.charCodeAt(index + 1) === CharCode.
|
|
971
|
-
this.#isLineStartPosition(index)
|
|
999
|
+
this.input.charCodeAt(index + 1) === CharCode.asterisk
|
|
972
1000
|
);
|
|
973
1001
|
}
|
|
974
1002
|
|
|
@@ -984,7 +1012,8 @@ export function TSRXPlugin(config) {
|
|
|
984
1012
|
ch === CharCode.openBrace ||
|
|
985
1013
|
ch === CharCode.closeBrace ||
|
|
986
1014
|
this.#isJSXControlFlowDirectiveAt(index) ||
|
|
987
|
-
this.#isTemplateLineCommentStart(index)
|
|
1015
|
+
this.#isTemplateLineCommentStart(index, start) ||
|
|
1016
|
+
this.#isTemplateBlockCommentStart(index)
|
|
988
1017
|
) {
|
|
989
1018
|
break;
|
|
990
1019
|
}
|
|
@@ -2005,9 +2034,10 @@ export function TSRXPlugin(config) {
|
|
|
2005
2034
|
);
|
|
2006
2035
|
const closingEnd = closingStart + '</style>'.length;
|
|
2007
2036
|
const closingEndInfo = acorn.getLineInfo(this.input, closingEnd);
|
|
2008
|
-
const closingElement =
|
|
2009
|
-
|
|
2010
|
-
|
|
2037
|
+
const closingElement =
|
|
2038
|
+
/** @type {ESTreeJSX.TSRXJSXClosingElement & AST.NodeWithLocation} */ (
|
|
2039
|
+
this.startNodeAt(closingStart, closingStartLoc)
|
|
2040
|
+
);
|
|
2011
2041
|
closingElement.name = name;
|
|
2012
2042
|
this.finishNodeAt(
|
|
2013
2043
|
closingElement,
|
|
@@ -2700,7 +2730,10 @@ export function TSRXPlugin(config) {
|
|
|
2700
2730
|
this.pos++;
|
|
2701
2731
|
return this.finishToken(tt.arrow);
|
|
2702
2732
|
}
|
|
2703
|
-
if (code === CharCode.lessThan) {
|
|
2733
|
+
if (code === CharCode.lessThan && this.type !== tstt.jsxText) {
|
|
2734
|
+
// After a JSX text token a `<` can only open a tag; without this guard
|
|
2735
|
+
// text ending in an identifier character (`hello<div>`) would read as
|
|
2736
|
+
// the start of a type argument list (`hello<T>`).
|
|
2704
2737
|
const next = this.input.charCodeAt(this.pos + 1);
|
|
2705
2738
|
if (
|
|
2706
2739
|
next !== CharCode.slash &&
|
|
@@ -4208,8 +4241,10 @@ export function TSRXPlugin(config) {
|
|
|
4208
4241
|
} else {
|
|
4209
4242
|
if (is_style) {
|
|
4210
4243
|
/** @type {AST.JSXStyleElement} */ (node).type = 'JSXStyleElement';
|
|
4211
|
-
/** @type {AST.JSXStyleElement} */ (node).openingElement =
|
|
4212
|
-
|
|
4244
|
+
/** @type {AST.JSXStyleElement} */ (node).openingElement =
|
|
4245
|
+
/** @type {AST.JSXStyleElement['openingElement']} */ (open);
|
|
4246
|
+
/** @type {AST.JSXStyleElement} */ (node).closingElement =
|
|
4247
|
+
/** @type {AST.JSXStyleElement['closingElement']} */ (null);
|
|
4213
4248
|
} else {
|
|
4214
4249
|
/** @type {ESTreeJSX.JSXElement} */ (node).type = 'JSXElement';
|
|
4215
4250
|
/** @type {ESTreeJSX.JSXElement} */ (node).openingElement = open;
|
|
@@ -4,20 +4,19 @@
|
|
|
4
4
|
import tsx from 'esrap/languages/tsx';
|
|
5
5
|
|
|
6
6
|
/**
|
|
7
|
-
* Zimmerframe provides `path` as the ancestor chain. A native template node
|
|
8
|
-
*
|
|
9
|
-
* renders as a standalone expression (e.g. a return value).
|
|
7
|
+
* Zimmerframe provides `path` as the ancestor chain. A native template node in
|
|
8
|
+
* the children list of any JSX element/fragment renders as a JSX child;
|
|
9
|
+
* anywhere else it renders as a standalone expression (e.g. a return value).
|
|
10
|
+
* The parent may be a parsed native template node or a synthetic fragment the
|
|
11
|
+
* transform built around render children — either way a bare expression in a
|
|
12
|
+
* child slot would print as JSX text.
|
|
10
13
|
*
|
|
11
14
|
* @param {any[]} path
|
|
12
15
|
* @returns {boolean}
|
|
13
16
|
*/
|
|
14
17
|
export function in_jsx_child_context(path) {
|
|
15
18
|
const parent = path[path.length - 1];
|
|
16
|
-
return (
|
|
17
|
-
!!parent &&
|
|
18
|
-
(parent.type === 'JSXElement' || parent.type === 'JSXFragment') &&
|
|
19
|
-
parent.metadata?.native_tsrx
|
|
20
|
-
);
|
|
19
|
+
return !!parent && (parent.type === 'JSXElement' || parent.type === 'JSXFragment');
|
|
21
20
|
}
|
|
22
21
|
|
|
23
22
|
/**
|
|
@@ -146,10 +146,57 @@ function mark_nested_function_return_jsx(node, inside_function = false, seen = n
|
|
|
146
146
|
}
|
|
147
147
|
|
|
148
148
|
/**
|
|
149
|
-
*
|
|
150
|
-
*
|
|
151
|
-
*
|
|
152
|
-
*
|
|
149
|
+
* Lower a `@{ … }` code block that appears as an element/fragment child,
|
|
150
|
+
* paying only for what the block uses while keeping each block its own
|
|
151
|
+
* lexical scope:
|
|
152
|
+
*
|
|
153
|
+
* - no setup code: the scope is unobservable, so the render output merges
|
|
154
|
+
* directly into the children list (template-only chains collapse to the
|
|
155
|
+
* innermost output, empty chains to nothing);
|
|
156
|
+
* - code-only: a plain `{ … }` statement block — statements run in source
|
|
157
|
+
* order, scoped, and render nothing (the render pipeline already handles
|
|
158
|
+
* statements interleaved with JSX children);
|
|
159
|
+
* - setup code + render output: kept as a `JSXCodeBlock` (with any nested
|
|
160
|
+
* chain simplified) for the context-aware lowering into a scoped IIFE
|
|
161
|
+
* (`transform_jsx_code_block` / `build_render_statements`).
|
|
162
|
+
*
|
|
163
|
+
* Always returns zero or one node.
|
|
164
|
+
* @param {any} block
|
|
165
|
+
* @returns {any[]}
|
|
166
|
+
*/
|
|
167
|
+
function lower_code_block_child(block) {
|
|
168
|
+
const body = block.body || [];
|
|
169
|
+
const render = block.render ?? null;
|
|
170
|
+
|
|
171
|
+
if (body.length === 0) {
|
|
172
|
+
if (render == null) return [];
|
|
173
|
+
if (render.type === 'JSXCodeBlock') return lower_code_block_child(render);
|
|
174
|
+
return [render];
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
if (render?.type === 'JSXCodeBlock') {
|
|
178
|
+
const inner = lower_code_block_child(render);
|
|
179
|
+
if (inner.length === 0) {
|
|
180
|
+
return [b.block(body, block)];
|
|
181
|
+
}
|
|
182
|
+
if (inner[0].type === 'BlockStatement') {
|
|
183
|
+
return [b.block([...body, inner[0]], block)];
|
|
184
|
+
}
|
|
185
|
+
// The chain still renders — simplify the render to the lowered inner
|
|
186
|
+
// node and leave the block for the context-aware lowering.
|
|
187
|
+
return [{ ...block, render: inner[0] }];
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
if (render == null) {
|
|
191
|
+
return [b.block(body, block)];
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
return [block];
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
/**
|
|
198
|
+
* Lower `@{ … }` code blocks that appear as element/fragment children (see
|
|
199
|
+
* `lower_code_block_child`). This is the element-scoped equivalent of
|
|
153
200
|
* `transform_function`'s body lowering — function and arrow bodies are never
|
|
154
201
|
* element children, so they are untouched here.
|
|
155
202
|
* @param {any} node
|
|
@@ -170,9 +217,7 @@ function expand_child_code_blocks(node, seen = new Set()) {
|
|
|
170
217
|
node.children.some((/** @type {any} */ c) => c?.type === 'JSXCodeBlock')
|
|
171
218
|
) {
|
|
172
219
|
node.children = node.children.flatMap((/** @type {any} */ child) =>
|
|
173
|
-
child?.type === 'JSXCodeBlock'
|
|
174
|
-
? [...child.body, ...(child.render != null ? [child.render] : [])]
|
|
175
|
-
: [child],
|
|
220
|
+
child?.type === 'JSXCodeBlock' ? lower_code_block_child(child) : [child],
|
|
176
221
|
);
|
|
177
222
|
}
|
|
178
223
|
|
|
@@ -801,6 +846,79 @@ function build_component_statements(body_nodes, transform_context) {
|
|
|
801
846
|
return build_render_statements(body_nodes, false, transform_context);
|
|
802
847
|
}
|
|
803
848
|
|
|
849
|
+
/**
|
|
850
|
+
* Statements for one `@{ … }` scope level: the setup statements followed by
|
|
851
|
+
* the lowered chain continuation. A nested level that declares anything is
|
|
852
|
+
* kept in a nested plain `{ … }` block, so a whole chain shares a single
|
|
853
|
+
* closure while still scoping each level; the generated `return` exits that
|
|
854
|
+
* closure.
|
|
855
|
+
* @param {any} block
|
|
856
|
+
* @param {TransformContext} transform_context
|
|
857
|
+
* @returns {{ statements: any[], has_render: boolean }}
|
|
858
|
+
*/
|
|
859
|
+
function code_block_scope_statements(block, transform_context) {
|
|
860
|
+
const statements = [...(block.body || [])];
|
|
861
|
+
const render = block.render ?? null;
|
|
862
|
+
|
|
863
|
+
if (render == null) {
|
|
864
|
+
return { statements, has_render: false };
|
|
865
|
+
}
|
|
866
|
+
|
|
867
|
+
if (render.type === 'JSXCodeBlock') {
|
|
868
|
+
const inner = code_block_scope_statements(render, transform_context);
|
|
869
|
+
if (inner.statements.length > 0) {
|
|
870
|
+
if ((render.body || []).length > 0) {
|
|
871
|
+
statements.push(b.block(inner.statements, render));
|
|
872
|
+
} else {
|
|
873
|
+
statements.push(...inner.statements);
|
|
874
|
+
}
|
|
875
|
+
}
|
|
876
|
+
return { statements, has_render: inner.has_render };
|
|
877
|
+
}
|
|
878
|
+
|
|
879
|
+
return {
|
|
880
|
+
statements: [...statements, ...build_render_statements([render], true, transform_context)],
|
|
881
|
+
has_render: true,
|
|
882
|
+
};
|
|
883
|
+
}
|
|
884
|
+
|
|
885
|
+
/**
|
|
886
|
+
* Lower a `@{ … }` code block that appears in a component/IIFE statement
|
|
887
|
+
* stream, keeping each block its own lexical scope:
|
|
888
|
+
*
|
|
889
|
+
* - no setup code: the scope is unobservable, so the render output (if any)
|
|
890
|
+
* merges directly into the stream;
|
|
891
|
+
* - code-only: a plain `{ … }` statement block;
|
|
892
|
+
* - setup code + render output: a scoped IIFE expression child whose value is
|
|
893
|
+
* the render output, with nested chains folded into the one closure.
|
|
894
|
+
*
|
|
895
|
+
* Always returns zero or one node.
|
|
896
|
+
* @param {any} block
|
|
897
|
+
* @param {TransformContext} transform_context
|
|
898
|
+
* @returns {any[]}
|
|
899
|
+
*/
|
|
900
|
+
function lower_code_block_stream_node(block, transform_context) {
|
|
901
|
+
const body = block.body || [];
|
|
902
|
+
const render = block.render ?? null;
|
|
903
|
+
|
|
904
|
+
if (body.length === 0) {
|
|
905
|
+
if (render == null) return [];
|
|
906
|
+
if (render.type === 'JSXCodeBlock') {
|
|
907
|
+
return lower_code_block_stream_node(render, transform_context);
|
|
908
|
+
}
|
|
909
|
+
return [render];
|
|
910
|
+
}
|
|
911
|
+
|
|
912
|
+
const { statements, has_render } = code_block_scope_statements(block, transform_context);
|
|
913
|
+
|
|
914
|
+
if (!has_render) {
|
|
915
|
+
return [b.block(statements, block)];
|
|
916
|
+
}
|
|
917
|
+
|
|
918
|
+
const iife = b.call(b.arrow([], b.block(statements, block)));
|
|
919
|
+
return [to_jsx_expression_container(iife, block)];
|
|
920
|
+
}
|
|
921
|
+
|
|
804
922
|
/**
|
|
805
923
|
* @param {any[]} body_nodes
|
|
806
924
|
* @param {boolean} return_null_when_empty
|
|
@@ -809,9 +927,7 @@ function build_component_statements(body_nodes, transform_context) {
|
|
|
809
927
|
*/
|
|
810
928
|
function build_render_statements(body_nodes, return_null_when_empty, transform_context) {
|
|
811
929
|
body_nodes = body_nodes.flatMap((node) =>
|
|
812
|
-
node?.type === 'JSXCodeBlock'
|
|
813
|
-
? [...node.body, ...(node.render != null ? [node.render] : [])]
|
|
814
|
-
: [node],
|
|
930
|
+
node?.type === 'JSXCodeBlock' ? lower_code_block_stream_node(node, transform_context) : [node],
|
|
815
931
|
);
|
|
816
932
|
|
|
817
933
|
const statements = [];
|
package/src/utils/builders.js
CHANGED
|
@@ -1249,6 +1249,44 @@ export function jsx_fragment(children = [], attributes = []) {
|
|
|
1249
1249
|
};
|
|
1250
1250
|
}
|
|
1251
1251
|
|
|
1252
|
+
/**
|
|
1253
|
+
* Ripple's internal fragment template node (the normalized form of a
|
|
1254
|
+
* `JSXFragment`).
|
|
1255
|
+
* @param {AST.Node[]} [children]
|
|
1256
|
+
* @param {AST.NodeWithLocation} [loc_info]
|
|
1257
|
+
* @returns {AST.TsrxFragment}
|
|
1258
|
+
*/
|
|
1259
|
+
export function tsrx_fragment(children = [], loc_info) {
|
|
1260
|
+
const node = /** @type {AST.TsrxFragment} */ (
|
|
1261
|
+
/** @type {unknown} */ ({
|
|
1262
|
+
type: 'TsrxFragment',
|
|
1263
|
+
children,
|
|
1264
|
+
attributes: [],
|
|
1265
|
+
selfClosing: false,
|
|
1266
|
+
metadata: { path: [] },
|
|
1267
|
+
})
|
|
1268
|
+
);
|
|
1269
|
+
|
|
1270
|
+
return set_location(node, loc_info);
|
|
1271
|
+
}
|
|
1272
|
+
|
|
1273
|
+
/**
|
|
1274
|
+
* Ripple's internal expression template child (the normalized form of a
|
|
1275
|
+
* `JSXExpressionContainer` child).
|
|
1276
|
+
* @param {AST.Expression} expression
|
|
1277
|
+
* @param {AST.NodeWithLocation} [loc_info]
|
|
1278
|
+
* @returns {AST.TSRXExpression}
|
|
1279
|
+
*/
|
|
1280
|
+
export function tsrx_expression(expression, loc_info) {
|
|
1281
|
+
const node = /** @type {AST.TSRXExpression} */ ({
|
|
1282
|
+
type: 'TSRXExpression',
|
|
1283
|
+
expression,
|
|
1284
|
+
metadata: { path: [] },
|
|
1285
|
+
});
|
|
1286
|
+
|
|
1287
|
+
return set_location(node, loc_info);
|
|
1288
|
+
}
|
|
1289
|
+
|
|
1252
1290
|
/**
|
|
1253
1291
|
* @param {AST.Expression | ESTreeJSX.JSXEmptyExpression} expression
|
|
1254
1292
|
* @param {AST.NodeWithLocation} [loc_info]
|
package/types/index.d.ts
CHANGED
|
@@ -170,6 +170,17 @@ declare module 'estree' {
|
|
|
170
170
|
interface SimpleCallExpression {
|
|
171
171
|
metadata: BaseNodeMetaData & {
|
|
172
172
|
hash?: string;
|
|
173
|
+
/**
|
|
174
|
+
* A generated `(() => @{ … })()` inline-component IIFE for a code
|
|
175
|
+
* block; collapsible once the block's statements lower into the
|
|
176
|
+
* component callback.
|
|
177
|
+
*/
|
|
178
|
+
tsrx_code_block_component?: boolean;
|
|
179
|
+
/**
|
|
180
|
+
* A generated zero-argument scope IIFE for a `@{ … }` code-block
|
|
181
|
+
* chain level; runs synchronously inside its `with_scope` wrapper.
|
|
182
|
+
*/
|
|
183
|
+
tsrx_code_block_scope?: boolean;
|
|
173
184
|
};
|
|
174
185
|
}
|
|
175
186
|
|
|
@@ -253,6 +264,9 @@ declare module 'estree' {
|
|
|
253
264
|
TsrxFragment: TsrxFragment;
|
|
254
265
|
Text: Text;
|
|
255
266
|
TSRXJSXElement: TSRXJSXElement;
|
|
267
|
+
TSRXJSXFragment: TSRXJSXFragment;
|
|
268
|
+
TSRXJSXOpeningElement: ESTreeJSX.TSRXJSXOpeningElement;
|
|
269
|
+
TSRXJSXClosingElement: ESTreeJSX.TSRXJSXClosingElement;
|
|
256
270
|
TSRXExpression: TSRXExpression;
|
|
257
271
|
Attribute: Attribute;
|
|
258
272
|
SpreadAttribute: SpreadAttribute;
|
|
@@ -320,7 +334,14 @@ declare module 'estree' {
|
|
|
320
334
|
closingElement?: ESTreeJSX.JSXClosingFragment | null;
|
|
321
335
|
selfClosing?: boolean;
|
|
322
336
|
attributes?: Array<Attribute | SpreadAttribute>;
|
|
323
|
-
metadata: BaseNodeMetaData
|
|
337
|
+
metadata: BaseNodeMetaData & {
|
|
338
|
+
/**
|
|
339
|
+
* A synthetic wrapper for a nested code-block render chain
|
|
340
|
+
* (`@{ @{ … } }`), so render-slot consumers see a template node;
|
|
341
|
+
* template-children lowering unwraps it.
|
|
342
|
+
*/
|
|
343
|
+
tsrx_code_block_chain?: boolean;
|
|
344
|
+
};
|
|
324
345
|
start: number;
|
|
325
346
|
end: number;
|
|
326
347
|
}
|
|
@@ -346,7 +367,11 @@ declare module 'estree' {
|
|
|
346
367
|
| AST.JSXCodeBlock;
|
|
347
368
|
|
|
348
369
|
interface TSRXJSXElement
|
|
349
|
-
extends
|
|
370
|
+
extends
|
|
371
|
+
Omit<ESTreeJSX.JSXElement, 'children' | 'openingElement' | 'closingElement'>,
|
|
372
|
+
AST.NodeWithMaybeComments {
|
|
373
|
+
openingElement: ESTreeJSX.TSRXJSXOpeningElement;
|
|
374
|
+
closingElement: ESTreeJSX.TSRXJSXClosingElement | null;
|
|
350
375
|
children: TSRXJSXChild[];
|
|
351
376
|
metadata: BaseNodeMetaData & {
|
|
352
377
|
ts_name?: string;
|
|
@@ -366,13 +391,10 @@ declare module 'estree' {
|
|
|
366
391
|
innerComments?: AST.Comment[] | undefined;
|
|
367
392
|
}
|
|
368
393
|
|
|
369
|
-
interface JSXStyleElement extends AST.
|
|
394
|
+
interface JSXStyleElement extends Omit<AST.TSRXJSXElement, 'type' | 'children'> {
|
|
370
395
|
type: 'JSXStyleElement';
|
|
371
|
-
openingElement: ESTreeJSX.JSXOpeningElement;
|
|
372
|
-
closingElement: ESTreeJSX.JSXClosingElement | null;
|
|
373
396
|
children: AST.CSS.StyleSheet[];
|
|
374
397
|
css?: string;
|
|
375
|
-
metadata: BaseNodeMetaData;
|
|
376
398
|
unclosed?: boolean;
|
|
377
399
|
}
|
|
378
400
|
|
|
@@ -520,7 +542,7 @@ declare module 'estree' {
|
|
|
520
542
|
|
|
521
543
|
type TSRXStatement = AST.Statement | TSESTree.Statement;
|
|
522
544
|
|
|
523
|
-
type NodeWithChildren = TSRXJSXElement | TSRXJSXFragment | JSXStyleElement;
|
|
545
|
+
type NodeWithChildren = TSRXJSXElement | TSRXJSXFragment | JSXStyleElement | ESTreeJSX.JSXElement;
|
|
524
546
|
|
|
525
547
|
export namespace CSS {
|
|
526
548
|
export interface BaseNode extends AST.NodeWithMaybeComments {
|
|
@@ -736,11 +758,11 @@ declare module 'estree-jsx' {
|
|
|
736
758
|
}
|
|
737
759
|
|
|
738
760
|
interface TSRXJSXOpeningElement extends Omit<JSXOpeningElement, 'name'> {
|
|
739
|
-
name: AST.MemberExpression | JSXIdentifier | JSXNamespacedName;
|
|
761
|
+
name: AST.MemberExpression | JSXIdentifier | JSXNamespacedName | JSXExpressionContainer;
|
|
740
762
|
}
|
|
741
763
|
|
|
742
764
|
interface TSRXJSXClosingElement extends Omit<JSXClosingElement, 'name'> {
|
|
743
|
-
name: AST.MemberExpression | JSXIdentifier | JSXNamespacedName;
|
|
765
|
+
name: AST.MemberExpression | JSXIdentifier | JSXNamespacedName | JSXExpressionContainer;
|
|
744
766
|
}
|
|
745
767
|
|
|
746
768
|
interface ExpressionMap {
|