@tsrx/core 0.0.28 → 0.1.1
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 +131 -25
- package/src/scope.js +7 -0
- package/src/transform/jsx/ast-builders.js +1 -0
- package/src/transform/jsx/index.js +66 -0
- package/types/index.d.ts +12 -1
- package/types/parse.d.ts +1 -1
package/package.json
CHANGED
package/src/plugin.js
CHANGED
|
@@ -18,7 +18,7 @@ import { error } from './errors.js';
|
|
|
18
18
|
import { DIAGNOSTIC_CODES } from './diagnostics.js';
|
|
19
19
|
|
|
20
20
|
const JSX_EXPRESSION_VALUE_ERROR =
|
|
21
|
-
'JSX elements cannot be used as expressions. Wrap with `<>...</>` or `<tsx>...</tsx
|
|
21
|
+
'JSX elements cannot be used as expressions. Wrap JSX with `<>...</>` or `<tsx>...</tsx>`, wrap TSRX templates with `<tsrx>...</tsrx>`, or use elements as statements within a component.';
|
|
22
22
|
|
|
23
23
|
/** @type {WeakMap<Record<string, boolean>, Map<string, number>>} */
|
|
24
24
|
const argument_clash_first_positions = new WeakMap();
|
|
@@ -325,7 +325,10 @@ export function TSRXPlugin(config) {
|
|
|
325
325
|
}
|
|
326
326
|
|
|
327
327
|
const parent = this.#path.at(-1);
|
|
328
|
-
if (
|
|
328
|
+
if (
|
|
329
|
+
!parent ||
|
|
330
|
+
(parent.type !== 'Component' && parent.type !== 'Element' && parent.type !== 'Tsrx')
|
|
331
|
+
) {
|
|
329
332
|
return false;
|
|
330
333
|
}
|
|
331
334
|
|
|
@@ -1699,7 +1702,22 @@ export function TSRXPlugin(config) {
|
|
|
1699
1702
|
chunkStart = this.pos;
|
|
1700
1703
|
|
|
1701
1704
|
while (true) {
|
|
1702
|
-
if (this.pos >= this.input.length)
|
|
1705
|
+
if (this.pos >= this.input.length) {
|
|
1706
|
+
const inside_open_template = this.#path.findLast(
|
|
1707
|
+
(n) =>
|
|
1708
|
+
n.type === 'Element' ||
|
|
1709
|
+
n.type === 'Tsrx' ||
|
|
1710
|
+
n.type === 'TsxCompat' ||
|
|
1711
|
+
n.type === 'Tsx',
|
|
1712
|
+
);
|
|
1713
|
+
if (!inside_open_template) {
|
|
1714
|
+
while (this.curContext() === tstc.tc_expr) {
|
|
1715
|
+
this.context.pop();
|
|
1716
|
+
}
|
|
1717
|
+
return this.finishToken(tt.eof);
|
|
1718
|
+
}
|
|
1719
|
+
this.raise(this.start, 'Unterminated JSX contents');
|
|
1720
|
+
}
|
|
1703
1721
|
let ch = this.input.charCodeAt(this.pos);
|
|
1704
1722
|
|
|
1705
1723
|
switch (ch) {
|
|
@@ -1809,7 +1827,8 @@ export function TSRXPlugin(config) {
|
|
|
1809
1827
|
ch === 125 &&
|
|
1810
1828
|
(this.#path.length === 0 ||
|
|
1811
1829
|
this.#path.at(-1)?.type === 'Component' ||
|
|
1812
|
-
this.#path.at(-1)?.type === 'Element'
|
|
1830
|
+
this.#path.at(-1)?.type === 'Element' ||
|
|
1831
|
+
this.#path.at(-1)?.type === 'Tsrx')
|
|
1813
1832
|
) {
|
|
1814
1833
|
this.#resetTokenStartToCurrentPosition();
|
|
1815
1834
|
return original.readToken.call(this, ch);
|
|
@@ -1849,7 +1868,9 @@ export function TSRXPlugin(config) {
|
|
|
1849
1868
|
* Override jsx_parseElement to intercept expression-level JSX.
|
|
1850
1869
|
* This is called by acorn-jsx's parseExprAtom when it encounters <
|
|
1851
1870
|
* in expression position. Bare fragments are treated as shorthand
|
|
1852
|
-
* for <tsx>...</tsx
|
|
1871
|
+
* for <tsx>...</tsx>. <tsrx>...</tsrx> admits native TSRX
|
|
1872
|
+
* template syntax as an expression value. Other tags must still use
|
|
1873
|
+
* <tsx>, <tsrx>, or <tsx:*>.
|
|
1853
1874
|
* @type {Parse.Parser['jsx_parseElement']}
|
|
1854
1875
|
*/
|
|
1855
1876
|
jsx_parseElement() {
|
|
@@ -1859,11 +1880,12 @@ export function TSRXPlugin(config) {
|
|
|
1859
1880
|
return super.jsx_parseElement();
|
|
1860
1881
|
}
|
|
1861
1882
|
|
|
1862
|
-
// Check if the element being parsed IS a <tsx
|
|
1883
|
+
// Check if the element being parsed IS a <tsx>, <tsrx>, or <tsx:*> tag
|
|
1863
1884
|
// Current token is jsxTagStart, this.end is position after '<'
|
|
1864
1885
|
const tag_name_start = this.end;
|
|
1865
1886
|
const is_fragment_tag = this.input.charCodeAt(tag_name_start) === 62;
|
|
1866
1887
|
const char_after_tsx = this.input.charCodeAt(tag_name_start + 3);
|
|
1888
|
+
const char_after_tsrx = this.input.charCodeAt(tag_name_start + 4);
|
|
1867
1889
|
const is_tsx_tag =
|
|
1868
1890
|
this.input.startsWith('tsx', tag_name_start) &&
|
|
1869
1891
|
(tag_name_start + 3 >= this.input.length ||
|
|
@@ -1874,9 +1896,18 @@ export function TSRXPlugin(config) {
|
|
|
1874
1896
|
char_after_tsx === 10 || // newline
|
|
1875
1897
|
char_after_tsx === 13 || // carriage return
|
|
1876
1898
|
char_after_tsx === 58); // : (tsx:react)
|
|
1877
|
-
|
|
1878
|
-
|
|
1879
|
-
|
|
1899
|
+
const is_tsrx_tag =
|
|
1900
|
+
this.input.startsWith('tsrx', tag_name_start) &&
|
|
1901
|
+
(tag_name_start + 4 >= this.input.length ||
|
|
1902
|
+
char_after_tsrx === 62 || // >
|
|
1903
|
+
char_after_tsrx === 47 || // / (self-closing)
|
|
1904
|
+
char_after_tsrx === 32 || // space
|
|
1905
|
+
char_after_tsrx === 9 || // tab
|
|
1906
|
+
char_after_tsrx === 10 || // newline
|
|
1907
|
+
char_after_tsrx === 13); // carriage return
|
|
1908
|
+
|
|
1909
|
+
if (is_fragment_tag || is_tsx_tag || is_tsrx_tag) {
|
|
1910
|
+
// Use Ripple's parseElement to create a Tsx/Tsrx/TsxCompat node.
|
|
1880
1911
|
// Bare fragments (<></>) are shorthand for <tsx>...</tsx>.
|
|
1881
1912
|
this.next();
|
|
1882
1913
|
return /** @type {import('estree-jsx').JSXElement} */ (
|
|
@@ -1907,7 +1938,9 @@ export function TSRXPlugin(config) {
|
|
|
1907
1938
|
const start = this.start - 1;
|
|
1908
1939
|
const position = new acorn.Position(this.curLine, start - this.lineStart);
|
|
1909
1940
|
|
|
1910
|
-
const element = /** @type {AST.Element | AST.Tsx | AST.TsxCompat} */ (
|
|
1941
|
+
const element = /** @type {AST.Element | AST.Tsx | AST.Tsrx | AST.TsxCompat} */ (
|
|
1942
|
+
this.startNode()
|
|
1943
|
+
);
|
|
1911
1944
|
element.start = start;
|
|
1912
1945
|
/** @type {AST.NodeWithLocation} */ (element).loc.start = position;
|
|
1913
1946
|
element.metadata = { path: [] };
|
|
@@ -1928,6 +1961,11 @@ export function TSRXPlugin(config) {
|
|
|
1928
1961
|
!is_tsx_compat &&
|
|
1929
1962
|
open.name.type === 'JSXIdentifier' &&
|
|
1930
1963
|
open.name.name === 'tsx';
|
|
1964
|
+
const is_tsrx =
|
|
1965
|
+
!is_fragment &&
|
|
1966
|
+
!is_tsx_compat &&
|
|
1967
|
+
open.name.type === 'JSXIdentifier' &&
|
|
1968
|
+
open.name.name === 'tsrx';
|
|
1931
1969
|
|
|
1932
1970
|
if (is_tsx_compat) {
|
|
1933
1971
|
const namespace_node = /** @type {ESTreeJSX.JSXNamespacedName} */ (open.name);
|
|
@@ -1950,6 +1988,15 @@ export function TSRXPlugin(config) {
|
|
|
1950
1988
|
`TSX elements cannot be self-closing. '<tsx />' must have a closing tag '</tsx>'.`,
|
|
1951
1989
|
);
|
|
1952
1990
|
}
|
|
1991
|
+
} else if (is_tsrx) {
|
|
1992
|
+
/** @type {AST.Tsrx} */ (element).type = 'Tsrx';
|
|
1993
|
+
|
|
1994
|
+
if (open.selfClosing) {
|
|
1995
|
+
this.raise(
|
|
1996
|
+
open.start,
|
|
1997
|
+
`TSRX elements cannot be self-closing. '<tsrx />' must have a closing tag '</tsrx>'.`,
|
|
1998
|
+
);
|
|
1999
|
+
}
|
|
1953
2000
|
} else if (is_fragment) {
|
|
1954
2001
|
/** @type {AST.Tsx} */ (element).type = 'Tsx';
|
|
1955
2002
|
} else {
|
|
@@ -1987,7 +2034,7 @@ export function TSRXPlugin(config) {
|
|
|
1987
2034
|
}
|
|
1988
2035
|
}
|
|
1989
2036
|
|
|
1990
|
-
if (!is_tsx_compat && !is_tsx && !is_fragment) {
|
|
2037
|
+
if (!is_tsx_compat && !is_tsx && !is_tsrx && !is_fragment) {
|
|
1991
2038
|
/** @type {AST.Element} */ (element).id = /** @type {AST.Identifier} */ (
|
|
1992
2039
|
convert_from_jsx(/** @type {ESTreeJSX.JSXIdentifier} */ (open.name))
|
|
1993
2040
|
);
|
|
@@ -2181,6 +2228,7 @@ export function TSRXPlugin(config) {
|
|
|
2181
2228
|
parent?.type === 'Component' ||
|
|
2182
2229
|
parent?.type === 'Element' ||
|
|
2183
2230
|
parent?.type === 'Tsx' ||
|
|
2231
|
+
parent?.type === 'Tsrx' ||
|
|
2184
2232
|
parent?.type === 'TsxCompat';
|
|
2185
2233
|
|
|
2186
2234
|
if (curContext === tstc.tc_expr && !insideTemplate) {
|
|
@@ -2249,7 +2297,21 @@ export function TSRXPlugin(config) {
|
|
|
2249
2297
|
this.#popTsxTokenContextBeforeTemplateExpressionChild();
|
|
2250
2298
|
this.next();
|
|
2251
2299
|
}
|
|
2252
|
-
} else if (this.#path[this.#path.length - 1] === element) {
|
|
2300
|
+
} else if (element.type === 'Tsrx' && this.#path[this.#path.length - 1] === element) {
|
|
2301
|
+
this.#report_broken_markup_error(
|
|
2302
|
+
this.start,
|
|
2303
|
+
"Unclosed tag '<tsrx>'. Expected '</tsrx>' before end of component.",
|
|
2304
|
+
);
|
|
2305
|
+
element.unclosed = true;
|
|
2306
|
+
/** @type {AST.SourceLocation} */ (element.loc).end = {
|
|
2307
|
+
.../** @type {AST.SourceLocation} */ (element.openingElement.loc).end,
|
|
2308
|
+
};
|
|
2309
|
+
element.end = element.openingElement.end;
|
|
2310
|
+
this.#path.pop();
|
|
2311
|
+
} else if (
|
|
2312
|
+
element.type === 'Element' &&
|
|
2313
|
+
this.#path[this.#path.length - 1] === element
|
|
2314
|
+
) {
|
|
2253
2315
|
// Check if this element was properly closed
|
|
2254
2316
|
const tagName = this.getElementName(element.id);
|
|
2255
2317
|
this.#report_broken_markup_error(
|
|
@@ -2257,7 +2319,7 @@ export function TSRXPlugin(config) {
|
|
|
2257
2319
|
`Unclosed tag '<${tagName}>'. Expected '</${tagName}>' before end of component.`,
|
|
2258
2320
|
);
|
|
2259
2321
|
element.unclosed = true;
|
|
2260
|
-
element.loc.end = {
|
|
2322
|
+
/** @type {AST.SourceLocation} */ (element.loc).end = {
|
|
2261
2323
|
.../** @type {AST.SourceLocation} */ (element.openingElement.loc).end,
|
|
2262
2324
|
};
|
|
2263
2325
|
element.end = element.openingElement.end;
|
|
@@ -2272,6 +2334,7 @@ export function TSRXPlugin(config) {
|
|
|
2272
2334
|
parent?.type === 'Component' ||
|
|
2273
2335
|
parent?.type === 'Element' ||
|
|
2274
2336
|
parent?.type === 'Tsx' ||
|
|
2337
|
+
parent?.type === 'Tsrx' ||
|
|
2275
2338
|
parent?.type === 'TsxCompat';
|
|
2276
2339
|
|
|
2277
2340
|
if (curContext === tstc.tc_expr && !insideTemplate) {
|
|
@@ -2279,7 +2342,13 @@ export function TSRXPlugin(config) {
|
|
|
2279
2342
|
}
|
|
2280
2343
|
}
|
|
2281
2344
|
|
|
2282
|
-
if (
|
|
2345
|
+
if (
|
|
2346
|
+
element.closingElement &&
|
|
2347
|
+
!is_tsx_compat &&
|
|
2348
|
+
!is_tsx &&
|
|
2349
|
+
!is_tsrx &&
|
|
2350
|
+
element.closingElement.name
|
|
2351
|
+
) {
|
|
2283
2352
|
/** @type {unknown} */ (element.closingElement.name) = convert_from_jsx(
|
|
2284
2353
|
element.closingElement.name,
|
|
2285
2354
|
);
|
|
@@ -2480,10 +2549,26 @@ export function TSRXPlugin(config) {
|
|
|
2480
2549
|
this.context.pop();
|
|
2481
2550
|
}
|
|
2482
2551
|
return;
|
|
2483
|
-
} else if (
|
|
2552
|
+
} else if (
|
|
2553
|
+
this.type === tstt.jsxTagStart ||
|
|
2554
|
+
(this.input.charCodeAt(this.start) === 60 /* < */ &&
|
|
2555
|
+
this.input.charCodeAt(this.start + 1) === 47) /* / */
|
|
2556
|
+
) {
|
|
2484
2557
|
const startPos = this.start;
|
|
2485
2558
|
const startLoc = this.startLoc;
|
|
2486
|
-
this.
|
|
2559
|
+
if (this.type === tstt.jsxTagStart) {
|
|
2560
|
+
this.next();
|
|
2561
|
+
} else {
|
|
2562
|
+
// A control-flow block inside <tsrx> can leave the tokenizer
|
|
2563
|
+
// in normal JS mode, so `</tsrx>` may arrive as a relational
|
|
2564
|
+
// `<` token. Re-enter JSX closing-tag parsing manually.
|
|
2565
|
+
this.pos = startPos + 1;
|
|
2566
|
+
this.type = tstt.jsxTagStart;
|
|
2567
|
+
this.start = startPos;
|
|
2568
|
+
this.startLoc = startLoc;
|
|
2569
|
+
this.exprAllowed = false;
|
|
2570
|
+
this.next();
|
|
2571
|
+
}
|
|
2487
2572
|
if (this.value === '/' || this.type === tt.slash) {
|
|
2488
2573
|
// Consume '/'
|
|
2489
2574
|
this.next();
|
|
@@ -2500,6 +2585,7 @@ export function TSRXPlugin(config) {
|
|
|
2500
2585
|
!currentElement ||
|
|
2501
2586
|
(currentElement.type !== 'Element' &&
|
|
2502
2587
|
currentElement.type !== 'Tsx' &&
|
|
2588
|
+
currentElement.type !== 'Tsrx' &&
|
|
2503
2589
|
currentElement.type !== 'TsxCompat')
|
|
2504
2590
|
) {
|
|
2505
2591
|
this.raise(this.start, 'Unexpected closing tag');
|
|
@@ -2522,6 +2608,12 @@ export function TSRXPlugin(config) {
|
|
|
2522
2608
|
closingElement.name?.type === 'JSXNamespacedName'
|
|
2523
2609
|
? closingElement.name.namespace.name + ':' + closingElement.name.name.name
|
|
2524
2610
|
: this.getElementName(closingElement.name);
|
|
2611
|
+
} else if (currentElement.type === 'Tsrx') {
|
|
2612
|
+
openingTagName = 'tsrx';
|
|
2613
|
+
closingTagName =
|
|
2614
|
+
closingElement.name?.type === 'JSXNamespacedName'
|
|
2615
|
+
? closingElement.name.namespace.name + ':' + closingElement.name.name.name
|
|
2616
|
+
: this.getElementName(closingElement.name);
|
|
2525
2617
|
} else {
|
|
2526
2618
|
// Regular Element node (or fragment)
|
|
2527
2619
|
openingTagName = currentElement.id ? this.getElementName(currentElement.id) : null;
|
|
@@ -2544,7 +2636,12 @@ export function TSRXPlugin(config) {
|
|
|
2544
2636
|
const elem = this.#path[this.#path.length - 1];
|
|
2545
2637
|
|
|
2546
2638
|
// Stop at non-Element boundaries (Component, etc.)
|
|
2547
|
-
if (
|
|
2639
|
+
if (
|
|
2640
|
+
elem.type !== 'Element' &&
|
|
2641
|
+
elem.type !== 'Tsx' &&
|
|
2642
|
+
elem.type !== 'Tsrx' &&
|
|
2643
|
+
elem.type !== 'TsxCompat'
|
|
2644
|
+
) {
|
|
2548
2645
|
break;
|
|
2549
2646
|
}
|
|
2550
2647
|
|
|
@@ -2555,9 +2652,11 @@ export function TSRXPlugin(config) {
|
|
|
2555
2652
|
? elem.openingElement.name
|
|
2556
2653
|
? 'tsx'
|
|
2557
2654
|
: null
|
|
2558
|
-
: elem.
|
|
2559
|
-
?
|
|
2560
|
-
:
|
|
2655
|
+
: elem.type === 'Tsrx'
|
|
2656
|
+
? 'tsrx'
|
|
2657
|
+
: elem.id
|
|
2658
|
+
? this.getElementName(elem.id)
|
|
2659
|
+
: null;
|
|
2561
2660
|
|
|
2562
2661
|
// Found matching opening tag
|
|
2563
2662
|
if (elemName === closingTagName) {
|
|
@@ -2576,12 +2675,19 @@ export function TSRXPlugin(config) {
|
|
|
2576
2675
|
}
|
|
2577
2676
|
|
|
2578
2677
|
const elementToClose = this.#path[this.#path.length - 1];
|
|
2579
|
-
if (
|
|
2580
|
-
|
|
2581
|
-
|
|
2582
|
-
|
|
2678
|
+
if (
|
|
2679
|
+
elementToClose &&
|
|
2680
|
+
(elementToClose.type === 'Element' || elementToClose.type === 'Tsrx')
|
|
2681
|
+
) {
|
|
2682
|
+
const elementToCloseName =
|
|
2683
|
+
elementToClose.type === 'Tsrx'
|
|
2684
|
+
? 'tsrx'
|
|
2685
|
+
: /** @type {AST.Element} */ (elementToClose).id
|
|
2686
|
+
? this.getElementName(/** @type {AST.Element} */ (elementToClose).id)
|
|
2687
|
+
: null;
|
|
2583
2688
|
if (elementToCloseName === closingTagName) {
|
|
2584
|
-
/** @type {AST.Element} */ (elementToClose).closingElement =
|
|
2689
|
+
/** @type {AST.Element | AST.Tsrx} */ (elementToClose).closingElement =
|
|
2690
|
+
closingElement;
|
|
2585
2691
|
}
|
|
2586
2692
|
}
|
|
2587
2693
|
|
package/src/scope.js
CHANGED
|
@@ -127,6 +127,13 @@ export function create_scopes(ast, root, parent, error_options) {
|
|
|
127
127
|
next({ scope });
|
|
128
128
|
},
|
|
129
129
|
|
|
130
|
+
Tsrx(node, { state, next }) {
|
|
131
|
+
const scope = state.scope.child();
|
|
132
|
+
scopes.set(node, scope);
|
|
133
|
+
|
|
134
|
+
next({ scope });
|
|
135
|
+
},
|
|
136
|
+
|
|
130
137
|
TSModuleDeclaration(node, { state, next }) {
|
|
131
138
|
const is_submodule = node.metadata?.module_keyword === 'module';
|
|
132
139
|
if (is_submodule && node.id?.type === 'Identifier') {
|
|
@@ -390,6 +390,17 @@ export function createJsxTransform(platform) {
|
|
|
390
390
|
);
|
|
391
391
|
},
|
|
392
392
|
|
|
393
|
+
Tsrx(node, { next, path, state }) {
|
|
394
|
+
const inner = /** @type {any} */ (next() ?? node);
|
|
395
|
+
const in_jsx_child = in_jsx_child_context(path);
|
|
396
|
+
return /** @type {any} */ (
|
|
397
|
+
wrap_jsx_setup_declarations(
|
|
398
|
+
tsrx_node_to_jsx_expression(inner, state, in_jsx_child),
|
|
399
|
+
in_jsx_child,
|
|
400
|
+
)
|
|
401
|
+
);
|
|
402
|
+
},
|
|
403
|
+
|
|
393
404
|
TsxCompat(node, { next, path, state }) {
|
|
394
405
|
const inner = /** @type {any} */ (next() ?? node);
|
|
395
406
|
const in_jsx_child = in_jsx_child_context(path);
|
|
@@ -3379,6 +3390,8 @@ function to_jsx_child(node, transform_context) {
|
|
|
3379
3390
|
// We're inside a JSX child position by construction, so keep a
|
|
3380
3391
|
// JSXExpressionContainer wrapper for bare `{expr}` children.
|
|
3381
3392
|
return tsx_node_to_jsx_expression(node, true);
|
|
3393
|
+
case 'Tsrx':
|
|
3394
|
+
return tsrx_node_to_jsx_expression(node, transform_context, true);
|
|
3382
3395
|
case 'TsxCompat':
|
|
3383
3396
|
return tsx_compat_node_to_jsx_expression(node, transform_context, true);
|
|
3384
3397
|
case 'Element':
|
|
@@ -3413,6 +3426,59 @@ function to_jsx_child(node, transform_context) {
|
|
|
3413
3426
|
}
|
|
3414
3427
|
}
|
|
3415
3428
|
|
|
3429
|
+
/**
|
|
3430
|
+
* Lower a `<tsrx>` node's native TSRX template body to a JSX expression.
|
|
3431
|
+
* Unlike `<tsx>`, children have already been parsed and transformed through
|
|
3432
|
+
* the normal TSRX Element/Text/control-flow visitors.
|
|
3433
|
+
*
|
|
3434
|
+
* @param {any} node
|
|
3435
|
+
* @param {TransformContext} transform_context
|
|
3436
|
+
* @param {boolean} [in_jsx_child]
|
|
3437
|
+
* @returns {any}
|
|
3438
|
+
*/
|
|
3439
|
+
function tsrx_node_to_jsx_expression(node, transform_context, in_jsx_child = false) {
|
|
3440
|
+
const children = (node.children || []).filter(
|
|
3441
|
+
(/** @type {any} */ child) =>
|
|
3442
|
+
child &&
|
|
3443
|
+
child.type !== 'EmptyStatement' &&
|
|
3444
|
+
(child.type !== 'JSXText' || child.value.trim() !== ''),
|
|
3445
|
+
);
|
|
3446
|
+
|
|
3447
|
+
/** @type {any} */
|
|
3448
|
+
let expression;
|
|
3449
|
+
if (children.length === 0) {
|
|
3450
|
+
expression = create_null_literal();
|
|
3451
|
+
} else if (
|
|
3452
|
+
children.every(is_inline_element_child) &&
|
|
3453
|
+
!children_contain_return_semantics(children)
|
|
3454
|
+
) {
|
|
3455
|
+
const saved_inside_element_child = transform_context.inside_element_child;
|
|
3456
|
+
transform_context.inside_element_child = true;
|
|
3457
|
+
try {
|
|
3458
|
+
const render_nodes = children.map((/** @type {any} */ child) =>
|
|
3459
|
+
to_jsx_child(child, transform_context),
|
|
3460
|
+
);
|
|
3461
|
+
expression = build_return_expression(render_nodes) || create_null_literal();
|
|
3462
|
+
} finally {
|
|
3463
|
+
transform_context.inside_element_child = saved_inside_element_child;
|
|
3464
|
+
}
|
|
3465
|
+
} else {
|
|
3466
|
+
expression = statement_body_to_jsx_child(children, transform_context).expression;
|
|
3467
|
+
}
|
|
3468
|
+
|
|
3469
|
+
if (
|
|
3470
|
+
in_jsx_child &&
|
|
3471
|
+
expression.type !== 'JSXElement' &&
|
|
3472
|
+
expression.type !== 'JSXFragment' &&
|
|
3473
|
+
expression.type !== 'JSXText' &&
|
|
3474
|
+
expression.type !== 'JSXExpressionContainer'
|
|
3475
|
+
) {
|
|
3476
|
+
return to_jsx_expression_container(expression, node);
|
|
3477
|
+
}
|
|
3478
|
+
|
|
3479
|
+
return expression;
|
|
3480
|
+
}
|
|
3481
|
+
|
|
3416
3482
|
/**
|
|
3417
3483
|
* @param {any} node
|
|
3418
3484
|
* @param {TransformContext} transform_context
|
package/types/index.d.ts
CHANGED
|
@@ -205,6 +205,7 @@ declare module 'estree' {
|
|
|
205
205
|
interface NodeMap {
|
|
206
206
|
Component: Component;
|
|
207
207
|
Tsx: Tsx;
|
|
208
|
+
Tsrx: Tsrx;
|
|
208
209
|
TsxCompat: TsxCompat;
|
|
209
210
|
TSRXExpression: TSRXExpression;
|
|
210
211
|
Html: Html;
|
|
@@ -346,6 +347,16 @@ declare module 'estree' {
|
|
|
346
347
|
closingElement: ESTreeJSX.JSXClosingElement;
|
|
347
348
|
}
|
|
348
349
|
|
|
350
|
+
interface Tsrx extends AST.BaseNode {
|
|
351
|
+
type: 'Tsrx';
|
|
352
|
+
attributes: Array<any>;
|
|
353
|
+
children: AST.Node[];
|
|
354
|
+
selfClosing?: boolean;
|
|
355
|
+
unclosed?: boolean;
|
|
356
|
+
openingElement: ESTreeJSX.JSXOpeningElement;
|
|
357
|
+
closingElement: ESTreeJSX.JSXClosingElement;
|
|
358
|
+
}
|
|
359
|
+
|
|
349
360
|
interface TsxCompat extends AST.BaseNode {
|
|
350
361
|
type: 'TsxCompat';
|
|
351
362
|
kind: string;
|
|
@@ -479,7 +490,7 @@ declare module 'estree' {
|
|
|
479
490
|
|
|
480
491
|
export type TSRXStatement = AST.Statement | TSESTree.Statement;
|
|
481
492
|
|
|
482
|
-
export type NodeWithChildren = AST.Element | AST.Tsx | AST.TsxCompat;
|
|
493
|
+
export type NodeWithChildren = AST.Element | AST.Tsx | AST.Tsrx | AST.TsxCompat;
|
|
483
494
|
|
|
484
495
|
export namespace CSS {
|
|
485
496
|
export interface BaseNode extends AST.NodeWithMaybeComments {
|
package/types/parse.d.ts
CHANGED
|
@@ -1172,7 +1172,7 @@ export namespace Parse {
|
|
|
1172
1172
|
*/
|
|
1173
1173
|
parseTopLevel(node: AST.Program): AST.Program;
|
|
1174
1174
|
|
|
1175
|
-
parseElement(): AST.Element | AST.Tsx | AST.TsxCompat;
|
|
1175
|
+
parseElement(): AST.Element | AST.Tsx | AST.Tsrx | AST.TsxCompat;
|
|
1176
1176
|
|
|
1177
1177
|
parseDoubleQuotedTextChild(): AST.TextNode;
|
|
1178
1178
|
|