@tsrx/core 0.0.21 → 0.0.23
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/README.md +1 -1
- package/package.json +1 -1
- package/src/identifier-utils.js +1 -2
- package/src/index.js +0 -1
- package/src/plugin.js +142 -99
- package/src/scope.js +12 -4
- package/src/transform/jsx/helpers.js +33 -1
- package/src/transform/jsx/index.js +115 -9
- package/src/transform/segments.js +36 -6
- package/src/utils/builders.js +9 -1
- package/types/index.d.ts +23 -33
- package/types/parse.d.ts +2 -5
package/README.md
CHANGED
|
@@ -42,7 +42,7 @@ The TSRX website is the canonical source for language documentation:
|
|
|
42
42
|
- [Getting Started](https://tsrx.dev/getting-started) — install TSRX for React,
|
|
43
43
|
Preact, Solid, Vue, or Ripple and configure editor/AI tooling.
|
|
44
44
|
- [Features](https://tsrx.dev/features) — examples of components, statement
|
|
45
|
-
templates, control flow, scoped styles,
|
|
45
|
+
templates, control flow, scoped styles, submodules, and lazy destructuring.
|
|
46
46
|
- [Specification](https://tsrx.dev/specification) — the current grammar and
|
|
47
47
|
parser-level semantics.
|
|
48
48
|
|
package/package.json
CHANGED
package/src/identifier-utils.js
CHANGED
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
export const IDENTIFIER_OBFUSCATION_PREFIX = '_$_';
|
|
2
|
-
export const
|
|
3
|
-
export const SERVER_IDENTIFIER = IDENTIFIER_OBFUSCATION_PREFIX + encode_utf16_char('#') + 'server';
|
|
2
|
+
export const SERVER_IDENTIFIER = IDENTIFIER_OBFUSCATION_PREFIX + 'server_$_';
|
|
4
3
|
export const CSS_HASH_IDENTIFIER = IDENTIFIER_OBFUSCATION_PREFIX + 'hash';
|
|
5
4
|
|
|
6
5
|
const DECODE_UTF16_REGEX = /_u([0-9a-fA-F]{4})_/g;
|
package/src/index.js
CHANGED
package/src/plugin.js
CHANGED
|
@@ -189,7 +189,7 @@ function previous_word_before(input, pos) {
|
|
|
189
189
|
/**
|
|
190
190
|
* Acorn parser plugin for Ripple syntax extensions.
|
|
191
191
|
* Adds support for: component declarations, &[]/&{} lazy destructuring,
|
|
192
|
-
*
|
|
192
|
+
* submodule imports, TSRX directives, and enhanced JSX handling.
|
|
193
193
|
*
|
|
194
194
|
* @param {import('../types/index').TSRXPluginConfig} [config] - Plugin configuration
|
|
195
195
|
* @returns {(Parser: Parse.ParserConstructor) => Parse.ParserConstructor} Parser extension function
|
|
@@ -221,6 +221,22 @@ export function TSRXPlugin(config) {
|
|
|
221
221
|
#filename = null;
|
|
222
222
|
#functionBodyDepth = 0;
|
|
223
223
|
|
|
224
|
+
/**
|
|
225
|
+
* @type {Parse.Parser['finishNode']}
|
|
226
|
+
*/
|
|
227
|
+
finishNode(node, type) {
|
|
228
|
+
const finished = super.finishNode(node, type);
|
|
229
|
+
if (type === 'TSModuleDeclaration') {
|
|
230
|
+
const start = /** @type {number} */ (finished.start);
|
|
231
|
+
const source = this.input.slice(start, start + 'namespace'.length);
|
|
232
|
+
finished.metadata ??= { path: [] };
|
|
233
|
+
finished.metadata.module_keyword = source.startsWith('namespace')
|
|
234
|
+
? 'namespace'
|
|
235
|
+
: 'module';
|
|
236
|
+
}
|
|
237
|
+
return finished;
|
|
238
|
+
}
|
|
239
|
+
|
|
224
240
|
/**
|
|
225
241
|
* @param {Parse.Options} options
|
|
226
242
|
* @param {string} input
|
|
@@ -234,6 +250,13 @@ export function TSRXPlugin(config) {
|
|
|
234
250
|
this.#filename = tsrx_options?.filename || null;
|
|
235
251
|
}
|
|
236
252
|
|
|
253
|
+
#resetTokenStartToCurrentPosition() {
|
|
254
|
+
if (this.start !== this.pos) {
|
|
255
|
+
this.start = this.pos;
|
|
256
|
+
this.startLoc = this.curPosition();
|
|
257
|
+
}
|
|
258
|
+
}
|
|
259
|
+
|
|
237
260
|
#previousNonWhitespaceChar() {
|
|
238
261
|
let index = this.pos - 1;
|
|
239
262
|
while (index >= 0) {
|
|
@@ -820,44 +843,6 @@ export function TSRXPlugin(config) {
|
|
|
820
843
|
}
|
|
821
844
|
}
|
|
822
845
|
|
|
823
|
-
if (code === 35) {
|
|
824
|
-
// # character
|
|
825
|
-
if (this.pos + 1 < this.input.length) {
|
|
826
|
-
/** @param {string} value */
|
|
827
|
-
const startsWith = (value) =>
|
|
828
|
-
this.input.slice(this.pos, this.pos + value.length) === value;
|
|
829
|
-
/** @param {number} length */
|
|
830
|
-
const char_after = (length) =>
|
|
831
|
-
this.pos + length < this.input.length ? this.input.charCodeAt(this.pos + length) : -1;
|
|
832
|
-
/** @param {number} ch */
|
|
833
|
-
const is_ripple_delimiter = (ch) =>
|
|
834
|
-
ch === 40 || // (
|
|
835
|
-
ch === 41 || // )
|
|
836
|
-
ch === 60 || // <
|
|
837
|
-
ch === 46 || // .
|
|
838
|
-
ch === 44 || // ,
|
|
839
|
-
ch === 59 || // ;
|
|
840
|
-
ch === 91 || // [
|
|
841
|
-
ch === 93 || // ]
|
|
842
|
-
ch === 123 || // {
|
|
843
|
-
ch === 125 || // }
|
|
844
|
-
ch === 32 || // space
|
|
845
|
-
ch === 9 || // tab
|
|
846
|
-
ch === 10 || // newline
|
|
847
|
-
ch === 13 || // carriage return
|
|
848
|
-
ch === -1; // EOF
|
|
849
|
-
|
|
850
|
-
if (startsWith('#server') && is_ripple_delimiter(char_after(7))) {
|
|
851
|
-
this.pos += 7;
|
|
852
|
-
return this.finishToken(tt.name, '#server');
|
|
853
|
-
}
|
|
854
|
-
|
|
855
|
-
if (startsWith('#style') && is_ripple_delimiter(char_after(6))) {
|
|
856
|
-
this.pos += 6;
|
|
857
|
-
return this.finishToken(tt.name, '#style');
|
|
858
|
-
}
|
|
859
|
-
}
|
|
860
|
-
}
|
|
861
846
|
this.#allowTagStartAfterDoubleQuotedText = false;
|
|
862
847
|
return super.getTokenFromCode(code);
|
|
863
848
|
}
|
|
@@ -970,22 +955,6 @@ export function TSRXPlugin(config) {
|
|
|
970
955
|
* @type {Parse.Parser['parseExprAtom']}
|
|
971
956
|
*/
|
|
972
957
|
parseExprAtom(refDestructuringErrors, forNew, forInit) {
|
|
973
|
-
const lookahead_type = this.lookahead().type;
|
|
974
|
-
const is_next_call_token = lookahead_type === tt.parenL || lookahead_type === tt.relational;
|
|
975
|
-
|
|
976
|
-
// Check if this is #server identifier for server function calls
|
|
977
|
-
if (this.type === tt.name && this.value === '#server') {
|
|
978
|
-
const node = this.startNode();
|
|
979
|
-
this.next();
|
|
980
|
-
return /** @type {AST.ServerIdentifier} */ (this.finishNode(node, 'ServerIdentifier'));
|
|
981
|
-
}
|
|
982
|
-
|
|
983
|
-
if (this.type === tt.name && this.value === '#style') {
|
|
984
|
-
const node = this.startNode();
|
|
985
|
-
this.next();
|
|
986
|
-
return /** @type {AST.StyleIdentifier} */ (this.finishNode(node, 'StyleIdentifier'));
|
|
987
|
-
}
|
|
988
|
-
|
|
989
958
|
// Check if this is a component expression (e.g., in object literal values)
|
|
990
959
|
if (this.type === tt.name && this.value === 'component') {
|
|
991
960
|
return this.parseComponent();
|
|
@@ -1015,9 +984,9 @@ export function TSRXPlugin(config) {
|
|
|
1015
984
|
|
|
1016
985
|
/**
|
|
1017
986
|
* Override checkLocalExport to check all scopes in the scope stack.
|
|
1018
|
-
* This is needed because
|
|
1019
|
-
* from within
|
|
1020
|
-
* declared in the
|
|
987
|
+
* This is needed because submodules create nested scopes, but exports
|
|
988
|
+
* from within submodules should still be valid if the identifier is
|
|
989
|
+
* declared in the submodule scope (not just the top-level module scope).
|
|
1021
990
|
* @type {Parse.Parser['checkLocalExport']}
|
|
1022
991
|
*/
|
|
1023
992
|
checkLocalExport(id) {
|
|
@@ -1036,31 +1005,6 @@ export function TSRXPlugin(config) {
|
|
|
1036
1005
|
this.undefinedExports[name] = id;
|
|
1037
1006
|
}
|
|
1038
1007
|
|
|
1039
|
-
/**
|
|
1040
|
-
* @type {Parse.Parser['parseServerBlock']}
|
|
1041
|
-
*/
|
|
1042
|
-
parseServerBlock() {
|
|
1043
|
-
const node = /** @type {AST.ServerBlock} */ (this.startNode());
|
|
1044
|
-
this.next();
|
|
1045
|
-
|
|
1046
|
-
const body = /** @type {AST.ServerBlockStatement} */ (this.startNode());
|
|
1047
|
-
node.body = body;
|
|
1048
|
-
body.body = [];
|
|
1049
|
-
|
|
1050
|
-
this.expect(tt.braceL);
|
|
1051
|
-
this.enterScope(0);
|
|
1052
|
-
while (this.type !== tt.braceR) {
|
|
1053
|
-
const stmt = /** @type {AST.Statement} */ (this.parseStatement(null, true));
|
|
1054
|
-
body.body.push(stmt);
|
|
1055
|
-
}
|
|
1056
|
-
this.next();
|
|
1057
|
-
this.exitScope();
|
|
1058
|
-
this.finishNode(body, 'BlockStatement');
|
|
1059
|
-
|
|
1060
|
-
this.awaitPos = 0;
|
|
1061
|
-
return this.finishNode(node, 'ServerBlock');
|
|
1062
|
-
}
|
|
1063
|
-
|
|
1064
1008
|
/**
|
|
1065
1009
|
* Parse a component - common implementation used by statements, expressions, and export defaults
|
|
1066
1010
|
* @type {Parse.Parser['parseComponent']}
|
|
@@ -1415,10 +1359,26 @@ export function TSRXPlugin(config) {
|
|
|
1415
1359
|
'"text" is a TSRX keyword and must be used in the form {text some_value}',
|
|
1416
1360
|
);
|
|
1417
1361
|
}
|
|
1362
|
+
} else if (
|
|
1363
|
+
this.type === tt.name &&
|
|
1364
|
+
this.value === 'style' &&
|
|
1365
|
+
this.lookahead().type === tt.string
|
|
1366
|
+
) {
|
|
1367
|
+
node.style = true;
|
|
1368
|
+
this.next();
|
|
1418
1369
|
}
|
|
1419
1370
|
|
|
1420
1371
|
node.expression =
|
|
1421
1372
|
this.type === tt.braceR ? this.jsx_parseEmptyExpression() : this.parseExpression();
|
|
1373
|
+
if (
|
|
1374
|
+
node.style &&
|
|
1375
|
+
(node.expression.type !== 'Literal' || typeof node.expression.value !== 'string')
|
|
1376
|
+
) {
|
|
1377
|
+
this.raise(
|
|
1378
|
+
/** @type {number} */ (node.expression.start),
|
|
1379
|
+
'"style" is a TSRX keyword and must be used in the form {style "class_name"}',
|
|
1380
|
+
);
|
|
1381
|
+
}
|
|
1422
1382
|
this.expect(tt.braceR);
|
|
1423
1383
|
|
|
1424
1384
|
return this.finishNode(node, 'JSXExpressionContainer');
|
|
@@ -1812,6 +1772,7 @@ export function TSRXPlugin(config) {
|
|
|
1812
1772
|
break;
|
|
1813
1773
|
}
|
|
1814
1774
|
// If not a comment, fall through to default case
|
|
1775
|
+
this.#resetTokenStartToCurrentPosition();
|
|
1815
1776
|
this.context.push(b_stat);
|
|
1816
1777
|
this.exprAllowed = true;
|
|
1817
1778
|
return original.readToken.call(this, ch);
|
|
@@ -1831,6 +1792,7 @@ export function TSRXPlugin(config) {
|
|
|
1831
1792
|
this.#path.at(-1)?.type === 'Component' ||
|
|
1832
1793
|
this.#path.at(-1)?.type === 'Element')
|
|
1833
1794
|
) {
|
|
1795
|
+
this.#resetTokenStartToCurrentPosition();
|
|
1834
1796
|
return original.readToken.call(this, ch);
|
|
1835
1797
|
}
|
|
1836
1798
|
this.raise(
|
|
@@ -1855,6 +1817,7 @@ export function TSRXPlugin(config) {
|
|
|
1855
1817
|
} else if (ch === 32 || ch === 9) {
|
|
1856
1818
|
++this.pos;
|
|
1857
1819
|
} else {
|
|
1820
|
+
this.#resetTokenStartToCurrentPosition();
|
|
1858
1821
|
this.context.push(b_stat);
|
|
1859
1822
|
this.exprAllowed = true;
|
|
1860
1823
|
return original.readToken.call(this, ch);
|
|
@@ -1986,6 +1949,14 @@ export function TSRXPlugin(config) {
|
|
|
1986
1949
|
if (attr.value !== null) {
|
|
1987
1950
|
if (attr.value.type === 'JSXExpressionContainer') {
|
|
1988
1951
|
const expression = attr.value.expression;
|
|
1952
|
+
if (attr.value.style) {
|
|
1953
|
+
/** @type {AST.Style} */ (/** @type {unknown} */ (attr.value)).type = 'Style';
|
|
1954
|
+
/** @type {AST.Style} */ (/** @type {unknown} */ (attr.value)).value =
|
|
1955
|
+
/** @type {AST.Literal} */ (expression);
|
|
1956
|
+
delete (/** @type {any} */ (attr.value).expression);
|
|
1957
|
+
delete (/** @type {any} */ (attr.value).style);
|
|
1958
|
+
continue;
|
|
1959
|
+
}
|
|
1989
1960
|
if (expression.type === 'Literal') {
|
|
1990
1961
|
expression.was_expression = true;
|
|
1991
1962
|
}
|
|
@@ -2455,11 +2426,23 @@ export function TSRXPlugin(config) {
|
|
|
2455
2426
|
// Keep JSXEmptyExpression as-is (for prettier to handle comments)
|
|
2456
2427
|
// but convert other expressions to Html/TSRXExpression/Text nodes
|
|
2457
2428
|
if (node.expression.type !== 'JSXEmptyExpression') {
|
|
2458
|
-
/** @type {AST.TSRXExpression | AST.Html | AST.TextNode} */ (
|
|
2429
|
+
/** @type {AST.TSRXExpression | AST.Html | AST.TextNode | AST.Style} */ (
|
|
2459
2430
|
/** @type {unknown} */ (node)
|
|
2460
|
-
).type = node.html
|
|
2431
|
+
).type = node.html
|
|
2432
|
+
? 'Html'
|
|
2433
|
+
: node.text
|
|
2434
|
+
? 'Text'
|
|
2435
|
+
: node.style
|
|
2436
|
+
? 'Style'
|
|
2437
|
+
: 'TSRXExpression';
|
|
2438
|
+
if (node.style) {
|
|
2439
|
+
/** @type {AST.Style} */ (/** @type {unknown} */ (node)).value =
|
|
2440
|
+
/** @type {AST.Literal} */ (node.expression);
|
|
2441
|
+
delete (/** @type {any} */ (node).expression);
|
|
2442
|
+
}
|
|
2461
2443
|
delete node.html;
|
|
2462
2444
|
delete node.text;
|
|
2445
|
+
delete node.style;
|
|
2463
2446
|
}
|
|
2464
2447
|
body.push(node);
|
|
2465
2448
|
} else if (this.type === tt.string && this.input.charCodeAt(this.start) === 34) {
|
|
@@ -2601,6 +2584,66 @@ export function TSRXPlugin(config) {
|
|
|
2601
2584
|
this.parseTemplateBody(body);
|
|
2602
2585
|
}
|
|
2603
2586
|
|
|
2587
|
+
/**
|
|
2588
|
+
* Parse proposal-style imports from an inline module declaration:
|
|
2589
|
+
* `import { foo } from server;`
|
|
2590
|
+
*
|
|
2591
|
+
* Acorn's import parser currently requires a string literal source. TSRX
|
|
2592
|
+
* extends only the source position; all specifier parsing stays delegated
|
|
2593
|
+
* to Acorn/@sveltejs/acorn-typescript.
|
|
2594
|
+
* @type {Parse.Parser['parseImport']}
|
|
2595
|
+
*/
|
|
2596
|
+
parseImport(node) {
|
|
2597
|
+
const tokenIsIdentifier = /** @type {any} */ (Parser.acornTypeScript).tokenIsIdentifier;
|
|
2598
|
+
const parser = /** @type {any} */ (this);
|
|
2599
|
+
const import_node = /** @type {any} */ (node);
|
|
2600
|
+
let enterHead = parser.lookahead();
|
|
2601
|
+
import_node.importKind = 'value';
|
|
2602
|
+
parser.importOrExportOuterKind = 'value';
|
|
2603
|
+
if (tokenIsIdentifier(enterHead.type) || this.match(tt.star) || this.match(tt.braceL)) {
|
|
2604
|
+
let ahead = parser.lookahead(2);
|
|
2605
|
+
if (
|
|
2606
|
+
ahead.type !== tt.comma &&
|
|
2607
|
+
!parser.isContextualWithState('from', ahead) &&
|
|
2608
|
+
ahead.type !== tt.eq &&
|
|
2609
|
+
parser.ts_eatContextualWithState('type', 1, enterHead)
|
|
2610
|
+
) {
|
|
2611
|
+
parser.importOrExportOuterKind = 'type';
|
|
2612
|
+
import_node.importKind = 'type';
|
|
2613
|
+
enterHead = parser.lookahead();
|
|
2614
|
+
ahead = parser.lookahead(2);
|
|
2615
|
+
}
|
|
2616
|
+
if (tokenIsIdentifier(enterHead.type) && ahead.type === tt.eq) {
|
|
2617
|
+
this.next();
|
|
2618
|
+
const importNode = parser.tsParseImportEqualsDeclaration(node);
|
|
2619
|
+
parser.importOrExportOuterKind = 'value';
|
|
2620
|
+
return importNode;
|
|
2621
|
+
}
|
|
2622
|
+
}
|
|
2623
|
+
this.next();
|
|
2624
|
+
if (this.type === tt.string) {
|
|
2625
|
+
import_node.specifiers = [];
|
|
2626
|
+
import_node.source = this.parseExprAtom();
|
|
2627
|
+
} else {
|
|
2628
|
+
import_node.specifiers = this.parseImportSpecifiers();
|
|
2629
|
+
this.expectContextual('from');
|
|
2630
|
+
if (this.type === tt.string) {
|
|
2631
|
+
import_node.source = this.parseExprAtom();
|
|
2632
|
+
} else if (tokenIsIdentifier(this.type)) {
|
|
2633
|
+
const source = this.parseIdent(false);
|
|
2634
|
+
source.metadata ??= { path: [] };
|
|
2635
|
+
import_node.source = source;
|
|
2636
|
+
} else {
|
|
2637
|
+
this.unexpected();
|
|
2638
|
+
}
|
|
2639
|
+
}
|
|
2640
|
+
parser.parseMaybeImportAttributes(node);
|
|
2641
|
+
this.semicolon();
|
|
2642
|
+
this.finishNode(node, 'ImportDeclaration');
|
|
2643
|
+
parser.importOrExportOuterKind = 'value';
|
|
2644
|
+
return import_node;
|
|
2645
|
+
}
|
|
2646
|
+
|
|
2604
2647
|
/**
|
|
2605
2648
|
* @type {Parse.Parser['parseStatement']}
|
|
2606
2649
|
*/
|
|
@@ -2616,11 +2659,23 @@ export function TSRXPlugin(config) {
|
|
|
2616
2659
|
const node = this.jsx_parseExpressionContainer();
|
|
2617
2660
|
// Keep JSXEmptyExpression as-is (don't convert to TSRXExpression/Text/Html)
|
|
2618
2661
|
if (node.expression.type !== 'JSXEmptyExpression') {
|
|
2619
|
-
/** @type {AST.TSRXExpression | AST.Html | AST.TextNode} */ (
|
|
2662
|
+
/** @type {AST.TSRXExpression | AST.Html | AST.TextNode | AST.Style} */ (
|
|
2620
2663
|
/** @type {unknown} */ (node)
|
|
2621
|
-
).type = node.html
|
|
2664
|
+
).type = node.html
|
|
2665
|
+
? 'Html'
|
|
2666
|
+
: node.text
|
|
2667
|
+
? 'Text'
|
|
2668
|
+
: node.style
|
|
2669
|
+
? 'Style'
|
|
2670
|
+
: 'TSRXExpression';
|
|
2671
|
+
if (node.style) {
|
|
2672
|
+
/** @type {AST.Style} */ (/** @type {unknown} */ (node)).value =
|
|
2673
|
+
/** @type {AST.Literal} */ (node.expression);
|
|
2674
|
+
delete (/** @type {any} */ (node).expression);
|
|
2675
|
+
}
|
|
2622
2676
|
delete node.html;
|
|
2623
2677
|
delete node.text;
|
|
2678
|
+
delete node.style;
|
|
2624
2679
|
}
|
|
2625
2680
|
|
|
2626
2681
|
return /** @type {ESTreeJSX.JSXEmptyExpression | AST.TSRXExpression | AST.Html | AST.TextNode | ESTreeJSX.JSXExpressionContainer} */ (
|
|
@@ -2628,18 +2683,6 @@ export function TSRXPlugin(config) {
|
|
|
2628
2683
|
);
|
|
2629
2684
|
}
|
|
2630
2685
|
|
|
2631
|
-
if (this.value === '#server') {
|
|
2632
|
-
// Peek ahead to see if this is a server block (#server { ... }) vs
|
|
2633
|
-
// a server identifier expression (#server.fn(), #server.fn().then())
|
|
2634
|
-
let peek_pos = this.end;
|
|
2635
|
-
while (peek_pos < this.input.length && /\s/.test(this.input[peek_pos])) peek_pos++;
|
|
2636
|
-
if (peek_pos < this.input.length && this.input.charCodeAt(peek_pos) === 123) {
|
|
2637
|
-
// Next non-whitespace character is '{' — parse as server block
|
|
2638
|
-
return this.parseServerBlock();
|
|
2639
|
-
}
|
|
2640
|
-
// Otherwise fall through to parse as expression statement (e.g., #server.fn().then(...))
|
|
2641
|
-
}
|
|
2642
|
-
|
|
2643
2686
|
if (this.value === 'component') {
|
|
2644
2687
|
this.awaitPos = 0;
|
|
2645
2688
|
return this.parseComponent({ requireName: true, declareName: true });
|
package/src/scope.js
CHANGED
|
@@ -127,10 +127,18 @@ export function create_scopes(ast, root, parent, error_options) {
|
|
|
127
127
|
next({ scope });
|
|
128
128
|
},
|
|
129
129
|
|
|
130
|
-
|
|
130
|
+
TSModuleDeclaration(node, { state, next }) {
|
|
131
|
+
const is_submodule = node.metadata?.module_keyword === 'module';
|
|
132
|
+
if (is_submodule && node.id?.type === 'Identifier') {
|
|
133
|
+
state.scope.declare(node.id, 'normal', 'module', node);
|
|
134
|
+
}
|
|
135
|
+
|
|
131
136
|
const scope = state.scope.child();
|
|
132
|
-
scope.server_block =
|
|
137
|
+
scope.server_block = is_submodule;
|
|
133
138
|
scopes.set(node, scope);
|
|
139
|
+
if (node.body) {
|
|
140
|
+
scopes.set(node.body, scope);
|
|
141
|
+
}
|
|
134
142
|
|
|
135
143
|
next({ scope });
|
|
136
144
|
},
|
|
@@ -296,7 +304,7 @@ export class Scope {
|
|
|
296
304
|
tracing = null;
|
|
297
305
|
|
|
298
306
|
/**
|
|
299
|
-
* Is this scope a
|
|
307
|
+
* Is this scope a submodule scope
|
|
300
308
|
* @type {ScopeInterface['server_block']}
|
|
301
309
|
*/
|
|
302
310
|
server_block = false;
|
|
@@ -325,7 +333,7 @@ export class Scope {
|
|
|
325
333
|
return this.parent.declare(node, kind, declaration_kind);
|
|
326
334
|
}
|
|
327
335
|
|
|
328
|
-
if (declaration_kind === 'import' && !this.parent.server_block) {
|
|
336
|
+
if (declaration_kind === 'import' && !this.server_block && !this.parent.server_block) {
|
|
329
337
|
return this.parent.declare(node, kind, declaration_kind, initial);
|
|
330
338
|
}
|
|
331
339
|
}
|
|
@@ -186,7 +186,37 @@ export function tsx_with_ts_locations() {
|
|
|
186
186
|
context.visit(body);
|
|
187
187
|
}
|
|
188
188
|
},
|
|
189
|
+
|
|
190
|
+
// esrap's JSXOpeningElement printer doesn't emit `typeArguments`, so generic
|
|
191
|
+
// component tags like `<RenderProp<User>>` lose the `<User>` in the output.
|
|
192
|
+
JSXOpeningElement: (node, context) => {
|
|
193
|
+
context.write('<');
|
|
194
|
+
context.visit(node.name);
|
|
195
|
+
if (node.typeArguments) {
|
|
196
|
+
context.visit(node.typeArguments);
|
|
197
|
+
}
|
|
198
|
+
for (const attribute of node.attributes) {
|
|
199
|
+
context.write(' ');
|
|
200
|
+
context.visit(attribute);
|
|
201
|
+
}
|
|
202
|
+
if (node.selfClosing) {
|
|
203
|
+
context.write(' /');
|
|
204
|
+
}
|
|
205
|
+
context.write('>');
|
|
206
|
+
},
|
|
207
|
+
TSModuleDeclaration: (node, context) => {
|
|
208
|
+
context.write(node.metadata?.module_keyword ?? 'module');
|
|
209
|
+
context.write(' ');
|
|
210
|
+
context.visit(node.id);
|
|
211
|
+
context.visit(node.body);
|
|
212
|
+
},
|
|
189
213
|
};
|
|
214
|
+
|
|
215
|
+
// Be careful when duplicating visitors that are already defined
|
|
216
|
+
// above in the `wrappers`
|
|
217
|
+
// if there is already a visitor but you still need a mapping
|
|
218
|
+
// on the whole node, only then duplicate it here
|
|
219
|
+
// e.g. JSXOpeningElement is such a case
|
|
190
220
|
for (const type of [
|
|
191
221
|
// JS nodes whose esrap printer emits no location marker, causing
|
|
192
222
|
// segments.js get_mapping_from_node() to throw when it asks for the
|
|
@@ -214,7 +244,9 @@ export function tsx_with_ts_locations() {
|
|
|
214
244
|
'TSTypeParameterDeclaration',
|
|
215
245
|
'TSTypeParameter',
|
|
216
246
|
]) {
|
|
217
|
-
|
|
247
|
+
const visitor = wrappers[type];
|
|
248
|
+
|
|
249
|
+
wrappers[type] = (node, context) => wrap_with_locations(node, context, visitor ?? base[type]);
|
|
218
250
|
}
|
|
219
251
|
|
|
220
252
|
return { ...base, ...wrappers };
|
|
@@ -254,14 +254,13 @@ export function createJsxTransform(platform) {
|
|
|
254
254
|
return /** @type {any} */ (to_jsx_expression_container(inner.expression, inner));
|
|
255
255
|
},
|
|
256
256
|
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
}
|
|
264
|
-
return next();
|
|
257
|
+
Style(node, { state, path }) {
|
|
258
|
+
validate_style_directive(node, state, path);
|
|
259
|
+
const class_name = typeof node.value.value === 'string' ? node.value.value : '';
|
|
260
|
+
const value = state.current_css_hash
|
|
261
|
+
? `${state.current_css_hash} ${class_name}`
|
|
262
|
+
: class_name;
|
|
263
|
+
return /** @type {any} */ (b.literal(value, node));
|
|
265
264
|
},
|
|
266
265
|
|
|
267
266
|
// Default .metadata on every function-like node so downstream consumers
|
|
@@ -2209,7 +2208,12 @@ function to_jsx_element(node, transform_context, raw_children = node.children ||
|
|
|
2209
2208
|
(/** @type {any} */ attribute) => attribute?.metadata?.has_unmappable_value,
|
|
2210
2209
|
);
|
|
2211
2210
|
|
|
2212
|
-
const opening_element_node = b.jsx_opening_element(
|
|
2211
|
+
const opening_element_node = b.jsx_opening_element(
|
|
2212
|
+
name,
|
|
2213
|
+
attributes,
|
|
2214
|
+
selfClosing,
|
|
2215
|
+
node.openingElement?.typeArguments,
|
|
2216
|
+
);
|
|
2213
2217
|
const openingElement = has_unmappable_attribute
|
|
2214
2218
|
? opening_element_node
|
|
2215
2219
|
: set_loc(opening_element_node, node.openingElement || node);
|
|
@@ -2766,6 +2770,108 @@ function get_body_source_node(body_nodes) {
|
|
|
2766
2770
|
return first;
|
|
2767
2771
|
}
|
|
2768
2772
|
|
|
2773
|
+
/**
|
|
2774
|
+
* @param {any} node
|
|
2775
|
+
* @param {TransformContext} transform_context
|
|
2776
|
+
* @param {any[]} path
|
|
2777
|
+
*/
|
|
2778
|
+
function validate_style_directive(node, transform_context, path) {
|
|
2779
|
+
const { attribute, element } = get_style_attribute_context(node, path);
|
|
2780
|
+
|
|
2781
|
+
if (!attribute) {
|
|
2782
|
+
error(
|
|
2783
|
+
'`{style "class_name"}` can only be used as an element attribute value.',
|
|
2784
|
+
transform_context.filename,
|
|
2785
|
+
node,
|
|
2786
|
+
transform_context.errors,
|
|
2787
|
+
transform_context.comments,
|
|
2788
|
+
);
|
|
2789
|
+
}
|
|
2790
|
+
|
|
2791
|
+
if (element && is_dom_style_target(element)) {
|
|
2792
|
+
error(
|
|
2793
|
+
'`{style "class_name"}` cannot be used directly on DOM elements. Pass the class to a child component instead.',
|
|
2794
|
+
transform_context.filename,
|
|
2795
|
+
node,
|
|
2796
|
+
transform_context.errors,
|
|
2797
|
+
transform_context.comments,
|
|
2798
|
+
);
|
|
2799
|
+
}
|
|
2800
|
+
|
|
2801
|
+
if (!transform_context.current_css_hash) {
|
|
2802
|
+
error(
|
|
2803
|
+
'`{style "class_name"}` requires a <style> block in the current component.',
|
|
2804
|
+
transform_context.filename,
|
|
2805
|
+
node,
|
|
2806
|
+
transform_context.errors,
|
|
2807
|
+
transform_context.comments,
|
|
2808
|
+
);
|
|
2809
|
+
}
|
|
2810
|
+
}
|
|
2811
|
+
|
|
2812
|
+
/**
|
|
2813
|
+
* @param {any} node
|
|
2814
|
+
* @param {any[]} path
|
|
2815
|
+
* @returns {{ attribute: any, element: any }}
|
|
2816
|
+
*/
|
|
2817
|
+
function get_style_attribute_context(node, path) {
|
|
2818
|
+
const parent = path.at(-1);
|
|
2819
|
+
const attribute =
|
|
2820
|
+
parent?.type === 'Attribute' && parent.value === node
|
|
2821
|
+
? parent
|
|
2822
|
+
: path
|
|
2823
|
+
.findLast((ancestor) => ancestor?.type === 'Element')
|
|
2824
|
+
?.attributes?.find(
|
|
2825
|
+
(/** @type {any} */ attr) =>
|
|
2826
|
+
attr?.type === 'Attribute' &&
|
|
2827
|
+
(attr.value === node || node_contains(attr.value, node)),
|
|
2828
|
+
);
|
|
2829
|
+
const element = path.findLast(
|
|
2830
|
+
(ancestor) =>
|
|
2831
|
+
ancestor?.type === 'Element' &&
|
|
2832
|
+
(!attribute || ancestor.attributes?.some((/** @type {any} */ attr) => attr === attribute)),
|
|
2833
|
+
);
|
|
2834
|
+
|
|
2835
|
+
return { attribute: attribute ?? null, element: element ?? null };
|
|
2836
|
+
}
|
|
2837
|
+
|
|
2838
|
+
/**
|
|
2839
|
+
* @param {any} root
|
|
2840
|
+
* @param {any} target
|
|
2841
|
+
* @returns {boolean}
|
|
2842
|
+
*/
|
|
2843
|
+
function node_contains(root, target) {
|
|
2844
|
+
if (!root || typeof root !== 'object') {
|
|
2845
|
+
return false;
|
|
2846
|
+
}
|
|
2847
|
+
if (root === target) {
|
|
2848
|
+
return true;
|
|
2849
|
+
}
|
|
2850
|
+
if (Array.isArray(root)) {
|
|
2851
|
+
return root.some((child) => node_contains(child, target));
|
|
2852
|
+
}
|
|
2853
|
+
for (const key of Object.keys(root)) {
|
|
2854
|
+
if (key === 'loc' || key === 'start' || key === 'end' || key === 'metadata') {
|
|
2855
|
+
continue;
|
|
2856
|
+
}
|
|
2857
|
+
if (node_contains(root[key], target)) {
|
|
2858
|
+
return true;
|
|
2859
|
+
}
|
|
2860
|
+
}
|
|
2861
|
+
return false;
|
|
2862
|
+
}
|
|
2863
|
+
|
|
2864
|
+
/**
|
|
2865
|
+
* @param {any} element
|
|
2866
|
+
* @returns {boolean}
|
|
2867
|
+
*/
|
|
2868
|
+
function is_dom_style_target(element) {
|
|
2869
|
+
if (!element?.id || is_dynamic_element_id(element.id)) {
|
|
2870
|
+
return false;
|
|
2871
|
+
}
|
|
2872
|
+
return element.id.type === 'Identifier' && /^[a-z]/.test(element.id.name);
|
|
2873
|
+
}
|
|
2874
|
+
|
|
2769
2875
|
/**
|
|
2770
2876
|
* @param {any} node
|
|
2771
2877
|
* @param {TransformContext} transform_context
|
|
@@ -380,6 +380,37 @@ export function convert_source_map_to_mappings(
|
|
|
380
380
|
css_element_info,
|
|
381
381
|
});
|
|
382
382
|
|
|
383
|
+
/** @type {Map<string, number>} */
|
|
384
|
+
const generated_position_indexes = new Map();
|
|
385
|
+
|
|
386
|
+
/**
|
|
387
|
+
* When a transform expands one source identifier into multiple generated
|
|
388
|
+
* identifiers (e.g. `import { foo } from server` -> `const foo =
|
|
389
|
+
* _$_server_$_.foo`), esrap records multiple generated positions for the
|
|
390
|
+
* same source location. Keep token mappings in generated-order by consuming
|
|
391
|
+
* the next matching generated token instead of always using the first one.
|
|
392
|
+
* @param {Token} token
|
|
393
|
+
* @returns {{ line: number; column: number }}
|
|
394
|
+
*/
|
|
395
|
+
function get_generated_position_for_token(token) {
|
|
396
|
+
const key = `${token.loc.start.line}:${token.loc.start.column}`;
|
|
397
|
+
const positions = src_to_gen_map.get(key);
|
|
398
|
+
if (!positions || positions.length === 0) {
|
|
399
|
+
throw new Error(`No source map entry for position "${key}"`);
|
|
400
|
+
}
|
|
401
|
+
|
|
402
|
+
const matching_positions = positions.filter((position) => {
|
|
403
|
+
const offset = loc_to_offset(position.line, position.column, gen_line_offsets);
|
|
404
|
+
return generated_code.startsWith(token.generated, offset);
|
|
405
|
+
});
|
|
406
|
+
const candidates = matching_positions.length > 0 ? matching_positions : positions;
|
|
407
|
+
const index_key = `${key}:${token.generated}`;
|
|
408
|
+
const index = generated_position_indexes.get(index_key) ?? 0;
|
|
409
|
+
generated_position_indexes.set(index_key, index + 1);
|
|
410
|
+
|
|
411
|
+
return candidates[Math.min(index, candidates.length - 1)];
|
|
412
|
+
}
|
|
413
|
+
|
|
383
414
|
/**
|
|
384
415
|
* Needed for a mapping that includes the computed brackets for diagnostics
|
|
385
416
|
* @param {AST.MethodDefinition | AST.Property} node
|
|
@@ -653,8 +684,11 @@ export function convert_source_map_to_mappings(
|
|
|
653
684
|
// Nothing to visit (just source string)
|
|
654
685
|
return;
|
|
655
686
|
} else if (node.type === 'JSXOpeningElement') {
|
|
656
|
-
// Visit name and attributes in source order
|
|
687
|
+
// Visit name, type arguments, and attributes in source order
|
|
657
688
|
visit(node.name);
|
|
689
|
+
if (node.typeArguments) {
|
|
690
|
+
visit(node.typeArguments);
|
|
691
|
+
}
|
|
658
692
|
for (const attr of node.attributes) {
|
|
659
693
|
visit(attr);
|
|
660
694
|
}
|
|
@@ -2179,11 +2213,7 @@ export function convert_source_map_to_mappings(
|
|
|
2179
2213
|
const gen_length = gen_text.length;
|
|
2180
2214
|
let gen_line_col;
|
|
2181
2215
|
try {
|
|
2182
|
-
gen_line_col =
|
|
2183
|
-
token.loc.start.line,
|
|
2184
|
-
token.loc.start.column,
|
|
2185
|
-
src_to_gen_map,
|
|
2186
|
-
);
|
|
2216
|
+
gen_line_col = get_generated_position_for_token(token);
|
|
2187
2217
|
} catch {
|
|
2188
2218
|
continue;
|
|
2189
2219
|
}
|
package/src/utils/builders.js
CHANGED
|
@@ -1107,15 +1107,23 @@ export function jsx_attribute(name, value = null, shorthand = false, loc_info) {
|
|
|
1107
1107
|
* @param {ESTreeJSX.JSXOpeningElement['name']} name
|
|
1108
1108
|
* @param {ESTreeJSX.JSXOpeningElement['attributes']} [attributes]
|
|
1109
1109
|
* @param {boolean} [self_closing]
|
|
1110
|
+
* @param {ESTreeJSX.JSXOpeningElement['typeArguments']} [type_arguments]
|
|
1110
1111
|
* @param {AST.NodeWithLocation} [loc_info]
|
|
1111
1112
|
* @returns {ESTreeJSX.JSXOpeningElement}
|
|
1112
1113
|
*/
|
|
1113
|
-
export function jsx_opening_element(
|
|
1114
|
+
export function jsx_opening_element(
|
|
1115
|
+
name,
|
|
1116
|
+
attributes = [],
|
|
1117
|
+
self_closing = false,
|
|
1118
|
+
type_arguments = undefined,
|
|
1119
|
+
loc_info,
|
|
1120
|
+
) {
|
|
1114
1121
|
const node = /** @type {ESTreeJSX.JSXOpeningElement} */ ({
|
|
1115
1122
|
type: 'JSXOpeningElement',
|
|
1116
1123
|
name,
|
|
1117
1124
|
attributes,
|
|
1118
1125
|
selfClosing: self_closing,
|
|
1126
|
+
typeArguments: type_arguments,
|
|
1119
1127
|
metadata: { path: [] },
|
|
1120
1128
|
});
|
|
1121
1129
|
|
package/types/index.d.ts
CHANGED
|
@@ -64,8 +64,9 @@ interface BaseNodeMetaData {
|
|
|
64
64
|
scoped?: boolean;
|
|
65
65
|
path: AST.Node[];
|
|
66
66
|
has_template?: boolean;
|
|
67
|
-
source_name?: string
|
|
67
|
+
source_name?: string;
|
|
68
68
|
source_length?: number;
|
|
69
|
+
module_keyword?: 'module' | 'namespace';
|
|
69
70
|
is_capitalized?: boolean;
|
|
70
71
|
commentContainerId?: number;
|
|
71
72
|
parenthesized?: boolean;
|
|
@@ -206,12 +207,9 @@ declare module 'estree' {
|
|
|
206
207
|
TsxCompat: TsxCompat;
|
|
207
208
|
TSRXExpression: TSRXExpression;
|
|
208
209
|
Html: Html;
|
|
210
|
+
Style: Style;
|
|
209
211
|
Element: Element;
|
|
210
212
|
Text: TextNode;
|
|
211
|
-
ServerBlock: ServerBlock;
|
|
212
|
-
ServerBlockStatement: ServerBlockStatement;
|
|
213
|
-
ServerIdentifier: ServerIdentifier;
|
|
214
|
-
StyleIdentifier: StyleIdentifier;
|
|
215
213
|
Attribute: Attribute;
|
|
216
214
|
RefAttribute: RefAttribute;
|
|
217
215
|
SpreadAttribute: SpreadAttribute;
|
|
@@ -220,8 +218,7 @@ declare module 'estree' {
|
|
|
220
218
|
}
|
|
221
219
|
|
|
222
220
|
interface ExpressionMap {
|
|
223
|
-
|
|
224
|
-
ServerIdentifier: ServerIdentifier;
|
|
221
|
+
Style: Style;
|
|
225
222
|
Text: TextNode;
|
|
226
223
|
JSXEmptyExpression: ESTreeJSX.JSXEmptyExpression;
|
|
227
224
|
ParenthesizedExpression: ParenthesizedExpression;
|
|
@@ -268,14 +265,6 @@ declare module 'estree' {
|
|
|
268
265
|
key?: AST.Expression | null;
|
|
269
266
|
}
|
|
270
267
|
|
|
271
|
-
interface ServerIdentifier extends AST.BaseExpression {
|
|
272
|
-
type: 'ServerIdentifier';
|
|
273
|
-
}
|
|
274
|
-
|
|
275
|
-
interface StyleIdentifier extends AST.BaseExpression {
|
|
276
|
-
type: 'StyleIdentifier';
|
|
277
|
-
}
|
|
278
|
-
|
|
279
268
|
interface ImportDeclaration {
|
|
280
269
|
importKind: TSESTree.ImportDeclaration['importKind'];
|
|
281
270
|
}
|
|
@@ -338,7 +327,6 @@ declare module 'estree' {
|
|
|
338
327
|
metadata: BaseNodeMetaData & {
|
|
339
328
|
topScopedClasses?: TopScopedClasses;
|
|
340
329
|
styleClasses?: StyleClasses;
|
|
341
|
-
styleIdentifierPresent?: boolean;
|
|
342
330
|
};
|
|
343
331
|
default: boolean;
|
|
344
332
|
typeParameters?: AST.TSTypeParameterDeclaration;
|
|
@@ -370,6 +358,12 @@ declare module 'estree' {
|
|
|
370
358
|
expression: AST.Expression;
|
|
371
359
|
}
|
|
372
360
|
|
|
361
|
+
interface Style extends AST.BaseExpression {
|
|
362
|
+
type: 'Style';
|
|
363
|
+
value: AST.Literal;
|
|
364
|
+
loc?: AST.SourceLocation;
|
|
365
|
+
}
|
|
366
|
+
|
|
373
367
|
export interface TSRXExpression extends AST.BaseExpression {
|
|
374
368
|
type: 'TSRXExpression';
|
|
375
369
|
expression: AST.Expression;
|
|
@@ -416,18 +410,6 @@ declare module 'estree' {
|
|
|
416
410
|
loc?: AST.SourceLocation;
|
|
417
411
|
}
|
|
418
412
|
|
|
419
|
-
interface ServerBlockStatement extends Omit<BlockStatement, 'body'> {
|
|
420
|
-
body: (AST.Statement | AST.ExportNamedDeclaration)[];
|
|
421
|
-
}
|
|
422
|
-
|
|
423
|
-
interface ServerBlock extends AST.BaseNode {
|
|
424
|
-
type: 'ServerBlock';
|
|
425
|
-
body: ServerBlockStatement;
|
|
426
|
-
metadata: BaseNodeMetaData & {
|
|
427
|
-
exports: Set<string>;
|
|
428
|
-
};
|
|
429
|
-
}
|
|
430
|
-
|
|
431
413
|
interface ScriptContent extends Omit<AST.Element, 'type'> {
|
|
432
414
|
type: 'ScriptContent';
|
|
433
415
|
content: string;
|
|
@@ -694,6 +676,7 @@ declare module 'estree-jsx' {
|
|
|
694
676
|
interface JSXExpressionContainer {
|
|
695
677
|
html?: boolean;
|
|
696
678
|
text?: boolean;
|
|
679
|
+
style?: boolean;
|
|
697
680
|
}
|
|
698
681
|
|
|
699
682
|
interface JSXMemberExpression {
|
|
@@ -977,6 +960,9 @@ declare module 'estree' {
|
|
|
977
960
|
> {
|
|
978
961
|
body: TSModuleBlock;
|
|
979
962
|
id: AST.Identifier;
|
|
963
|
+
metadata: BaseNodeMetaData & {
|
|
964
|
+
exports?: Set<string>;
|
|
965
|
+
};
|
|
980
966
|
}
|
|
981
967
|
interface TSNamedTupleMember extends Omit<
|
|
982
968
|
AcornTSNode<TSESTree.TSNamedTupleMember>,
|
|
@@ -1184,7 +1170,9 @@ export interface AnalysisResult {
|
|
|
1184
1170
|
scope: ScopeInterface;
|
|
1185
1171
|
component_metadata: Array<{ id: string }>;
|
|
1186
1172
|
metadata: {
|
|
1187
|
-
|
|
1173
|
+
serverImportsPresent: boolean;
|
|
1174
|
+
serverImportDeclarations: AST.ImportDeclaration[];
|
|
1175
|
+
serverModule: AST.TSModuleDeclaration | null;
|
|
1188
1176
|
};
|
|
1189
1177
|
errors: CompileError[];
|
|
1190
1178
|
comments: AST.CommentWithLocation[];
|
|
@@ -1209,6 +1197,7 @@ export type DeclarationKind =
|
|
|
1209
1197
|
| 'rest_param'
|
|
1210
1198
|
| 'component'
|
|
1211
1199
|
| 'import'
|
|
1200
|
+
| 'module'
|
|
1212
1201
|
| 'using'
|
|
1213
1202
|
| 'await using';
|
|
1214
1203
|
|
|
@@ -1239,7 +1228,8 @@ export interface Binding {
|
|
|
1239
1228
|
| AST.Expression
|
|
1240
1229
|
| AST.FunctionDeclaration
|
|
1241
1230
|
| AST.ClassDeclaration
|
|
1242
|
-
| AST.ImportDeclaration
|
|
1231
|
+
| AST.ImportDeclaration
|
|
1232
|
+
| AST.TSModuleDeclaration;
|
|
1243
1233
|
/** Whether this binding has been reassigned */
|
|
1244
1234
|
reassigned: boolean;
|
|
1245
1235
|
/** Whether this binding has been mutated (property access) */
|
|
@@ -1331,7 +1321,8 @@ export interface ScopeInterface {
|
|
|
1331
1321
|
| AST.Expression
|
|
1332
1322
|
| AST.FunctionDeclaration
|
|
1333
1323
|
| AST.ClassDeclaration
|
|
1334
|
-
| AST.ImportDeclaration
|
|
1324
|
+
| AST.ImportDeclaration
|
|
1325
|
+
| AST.TSModuleDeclaration,
|
|
1335
1326
|
): Binding;
|
|
1336
1327
|
/** Get binding by name */
|
|
1337
1328
|
get(name: string): Binding | null;
|
|
@@ -1357,8 +1348,7 @@ export interface BaseState {
|
|
|
1357
1348
|
/** For utils */
|
|
1358
1349
|
scope: ScopeInterface;
|
|
1359
1350
|
scopes: Map<AST.Node | AST.Node[], ScopeInterface>;
|
|
1360
|
-
|
|
1361
|
-
ancestor_server_block: AST.ServerBlock | undefined;
|
|
1351
|
+
ancestor_server_block: AST.TSModuleDeclaration | undefined;
|
|
1362
1352
|
inside_head?: boolean;
|
|
1363
1353
|
keep_component_style?: boolean;
|
|
1364
1354
|
|
package/types/parse.d.ts
CHANGED
|
@@ -930,7 +930,7 @@ export namespace Parse {
|
|
|
930
930
|
refDestructuringErrors?: DestructuringErrors,
|
|
931
931
|
forInit?: ForInit,
|
|
932
932
|
forNew?: boolean,
|
|
933
|
-
): AST.
|
|
933
|
+
): AST.Component | AST.Identifier | AST.Literal;
|
|
934
934
|
|
|
935
935
|
/** Default handler for parseExprAtom when no other case matches */
|
|
936
936
|
parseExprAtomDefault(): AST.Expression;
|
|
@@ -1172,8 +1172,6 @@ export namespace Parse {
|
|
|
1172
1172
|
*/
|
|
1173
1173
|
parseTopLevel(node: AST.Program): AST.Program;
|
|
1174
1174
|
|
|
1175
|
-
parseServerBlock(): AST.ServerBlock;
|
|
1176
|
-
|
|
1177
1175
|
parseElement(): AST.Element | AST.Tsx | AST.TsxCompat;
|
|
1178
1176
|
|
|
1179
1177
|
parseDoubleQuotedTextChild(): AST.TextNode;
|
|
@@ -1210,7 +1208,6 @@ export namespace Parse {
|
|
|
1210
1208
|
| AST.TextNode
|
|
1211
1209
|
| ESTreeJSX.JSXEmptyExpression
|
|
1212
1210
|
| ESTreeJSX.JSXExpressionContainer
|
|
1213
|
-
| AST.ServerBlock
|
|
1214
1211
|
| AST.Component
|
|
1215
1212
|
| AST.ExpressionStatement
|
|
1216
1213
|
| ReturnType<Parser['parseElement']>
|
|
@@ -1543,7 +1540,7 @@ export namespace Parse {
|
|
|
1543
1540
|
/**
|
|
1544
1541
|
* Check if a local export refers to a defined variable.
|
|
1545
1542
|
* Acorn's default implementation only checks the top-level module scope,
|
|
1546
|
-
* but Ripple overrides this to check all scopes (for
|
|
1543
|
+
* but Ripple overrides this to check all scopes (for submodules).
|
|
1547
1544
|
* @param id The identifier being exported
|
|
1548
1545
|
*/
|
|
1549
1546
|
checkLocalExport(id: AST.Identifier): void;
|