@tsrx/core 0.1.56 → 0.1.58
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 +3 -3
- package/src/plugin.js +47 -44
- package/src/transform/jsx/helpers.js +9 -0
- package/types/parse.d.ts +6 -0
package/package.json
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
"description": "Core compiler infrastructure for TSRX syntax",
|
|
4
4
|
"license": "MIT",
|
|
5
5
|
"author": "Dominic Gannaway",
|
|
6
|
-
"version": "0.1.
|
|
6
|
+
"version": "0.1.58",
|
|
7
7
|
"type": "module",
|
|
8
8
|
"repository": {
|
|
9
9
|
"type": "git",
|
|
@@ -71,11 +71,11 @@
|
|
|
71
71
|
"dependencies": {
|
|
72
72
|
"@jridgewell/sourcemap-codec": "^1.5.5",
|
|
73
73
|
"@noble/hashes": "^2.2.0",
|
|
74
|
-
"@sveltejs/acorn-typescript": "^1.0.
|
|
74
|
+
"@sveltejs/acorn-typescript": "^1.0.13",
|
|
75
75
|
"@types/estree-jsx": "^1.0.5",
|
|
76
76
|
"@types/estree": "^1.0.8",
|
|
77
77
|
"acorn": "^8.17.0",
|
|
78
|
-
"esrap": "^2.3.
|
|
78
|
+
"esrap": "^2.3.2",
|
|
79
79
|
"is-reference": "^3.0.3",
|
|
80
80
|
"magic-string": "^0.30.18",
|
|
81
81
|
"zimmerframe": "^1.1.2"
|
package/src/plugin.js
CHANGED
|
@@ -108,6 +108,28 @@ function get_argument_clash_reported_names(check_clashes) {
|
|
|
108
108
|
return reported_names;
|
|
109
109
|
}
|
|
110
110
|
|
|
111
|
+
/**
|
|
112
|
+
* A `<` opens a tag only when the character after it can begin one: `/` for a
|
|
113
|
+
* closing tag, `>` for a fragment, `{` for a dynamic tag, or an element or
|
|
114
|
+
* component name start. Any other character, or end of input, leaves the `<`
|
|
115
|
+
* as literal text.
|
|
116
|
+
* @param {string} input
|
|
117
|
+
* @param {number} index Index of the `<`.
|
|
118
|
+
*/
|
|
119
|
+
function can_start_tag_after_lt(input, index) {
|
|
120
|
+
const next = index + 1 < input.length ? input.charCodeAt(index + 1) : -1;
|
|
121
|
+
return (
|
|
122
|
+
next === CharCode.slash ||
|
|
123
|
+
next === CharCode.greaterThan ||
|
|
124
|
+
next === CharCode.openBrace ||
|
|
125
|
+
next === CharCode.at ||
|
|
126
|
+
next === CharCode.dollar ||
|
|
127
|
+
next === CharCode.underscore ||
|
|
128
|
+
(next >= CharCode.uppercaseA && next <= CharCode.uppercaseZ) ||
|
|
129
|
+
(next >= CharCode.lowercaseA && next <= CharCode.lowercaseZ)
|
|
130
|
+
);
|
|
131
|
+
}
|
|
132
|
+
|
|
111
133
|
/**
|
|
112
134
|
* @param {string} input
|
|
113
135
|
* @param {number} i
|
|
@@ -623,7 +645,7 @@ export function TSRXPlugin(config) {
|
|
|
623
645
|
}
|
|
624
646
|
const ch = this.input.charCodeAt(index);
|
|
625
647
|
if (
|
|
626
|
-
ch === CharCode.lessThan ||
|
|
648
|
+
(ch === CharCode.lessThan && can_start_tag_after_lt(this.input, index)) ||
|
|
627
649
|
ch === CharCode.openBrace ||
|
|
628
650
|
ch === CharCode.closeBrace ||
|
|
629
651
|
this.#isCodeBlockStart(index) ||
|
|
@@ -1146,7 +1168,7 @@ export function TSRXPlugin(config) {
|
|
|
1146
1168
|
while (index < this.input.length) {
|
|
1147
1169
|
const ch = this.input.charCodeAt(index);
|
|
1148
1170
|
if (
|
|
1149
|
-
ch === CharCode.lessThan ||
|
|
1171
|
+
(ch === CharCode.lessThan && can_start_tag_after_lt(this.input, index)) ||
|
|
1150
1172
|
ch === CharCode.openBrace ||
|
|
1151
1173
|
ch === CharCode.closeBrace ||
|
|
1152
1174
|
this.#isJSXControlFlowDirectiveAt(index) ||
|
|
@@ -1247,16 +1269,8 @@ export function TSRXPlugin(config) {
|
|
|
1247
1269
|
const index = skip_whitespace_from(this.input, this.start);
|
|
1248
1270
|
const ch = this.input.charCodeAt(index);
|
|
1249
1271
|
if (ch === CharCode.lessThan) {
|
|
1250
|
-
|
|
1251
|
-
|
|
1252
|
-
const tagLike =
|
|
1253
|
-
next === CharCode.greaterThan ||
|
|
1254
|
-
next === CharCode.openBrace ||
|
|
1255
|
-
next === CharCode.at ||
|
|
1256
|
-
next === CharCode.dollar ||
|
|
1257
|
-
next === CharCode.underscore ||
|
|
1258
|
-
(next >= CharCode.uppercaseA && next <= CharCode.uppercaseZ) ||
|
|
1259
|
-
(next >= CharCode.lowercaseA && next <= CharCode.lowercaseZ);
|
|
1272
|
+
if (this.input.charCodeAt(index + 1) === CharCode.slash) return false;
|
|
1273
|
+
const tagLike = can_start_tag_after_lt(this.input, index);
|
|
1260
1274
|
const previous = this.#previousNonSpaceTabIndex(index);
|
|
1261
1275
|
const afterSemicolon =
|
|
1262
1276
|
previous >= 0 && this.input.charCodeAt(previous) === CharCode.semicolon;
|
|
@@ -2895,7 +2909,7 @@ export function TSRXPlugin(config) {
|
|
|
2895
2909
|
this.#suppressTemplateRawTextToken = false;
|
|
2896
2910
|
const context = this.curContext();
|
|
2897
2911
|
if (
|
|
2898
|
-
code !== CharCode.lessThan &&
|
|
2912
|
+
(code !== CharCode.lessThan || !can_start_tag_after_lt(this.input, this.pos)) &&
|
|
2899
2913
|
code !== CharCode.greaterThan &&
|
|
2900
2914
|
code !== CharCode.openBrace &&
|
|
2901
2915
|
code !== CharCode.closeBrace &&
|
|
@@ -2933,17 +2947,7 @@ export function TSRXPlugin(config) {
|
|
|
2933
2947
|
return super.readToken(code);
|
|
2934
2948
|
}
|
|
2935
2949
|
if (code === CharCode.lessThan) {
|
|
2936
|
-
|
|
2937
|
-
const isTagLikeAfterLt =
|
|
2938
|
-
next === CharCode.slash ||
|
|
2939
|
-
next === CharCode.greaterThan ||
|
|
2940
|
-
next === CharCode.openBrace ||
|
|
2941
|
-
next === CharCode.at ||
|
|
2942
|
-
next === CharCode.dollar ||
|
|
2943
|
-
next === CharCode.underscore ||
|
|
2944
|
-
(next >= CharCode.uppercaseA && next <= CharCode.uppercaseZ) ||
|
|
2945
|
-
(next >= CharCode.lowercaseA && next <= CharCode.lowercaseZ);
|
|
2946
|
-
if (this.exprAllowed && isTagLikeAfterLt) {
|
|
2950
|
+
if (this.exprAllowed && can_start_tag_after_lt(this.input, this.pos)) {
|
|
2947
2951
|
++this.pos;
|
|
2948
2952
|
return this.finishToken(tstt.jsxTagStart);
|
|
2949
2953
|
}
|
|
@@ -3058,21 +3062,7 @@ export function TSRXPlugin(config) {
|
|
|
3058
3062
|
// <Something>...</Something>\n\n<Child />
|
|
3059
3063
|
// <head><style>...</style></head>
|
|
3060
3064
|
// We only do this when '<' is in a tag-like position.
|
|
3061
|
-
const
|
|
3062
|
-
nextChar === CharCode.space ||
|
|
3063
|
-
nextChar === CharCode.tab ||
|
|
3064
|
-
nextChar === CharCode.lineFeed ||
|
|
3065
|
-
nextChar === CharCode.carriageReturn;
|
|
3066
|
-
const isTagLikeAfterLt =
|
|
3067
|
-
!isWhitespaceAfterLt &&
|
|
3068
|
-
(nextChar === CharCode.slash ||
|
|
3069
|
-
nextChar === CharCode.greaterThan ||
|
|
3070
|
-
nextChar === CharCode.openBrace ||
|
|
3071
|
-
nextChar === CharCode.at ||
|
|
3072
|
-
nextChar === CharCode.dollar ||
|
|
3073
|
-
nextChar === CharCode.underscore ||
|
|
3074
|
-
(nextChar >= CharCode.uppercaseA && nextChar <= CharCode.uppercaseZ) ||
|
|
3075
|
-
(nextChar >= CharCode.lowercaseA && nextChar <= CharCode.lowercaseZ));
|
|
3065
|
+
const isTagLikeAfterLt = can_start_tag_after_lt(this.input, this.pos);
|
|
3076
3066
|
const prevAllowsTagStart =
|
|
3077
3067
|
prevNonWhitespaceChar === null ||
|
|
3078
3068
|
prevNonWhitespaceChar === CharCode.lineFeed || // '\n'
|
|
@@ -3099,7 +3089,7 @@ export function TSRXPlugin(config) {
|
|
|
3099
3089
|
prevNonWhitespaceChar === CharCode.openBrace ||
|
|
3100
3090
|
prevNonWhitespaceChar === CharCode.greaterThan
|
|
3101
3091
|
) {
|
|
3102
|
-
if (
|
|
3092
|
+
if (isTagLikeAfterLt) {
|
|
3103
3093
|
++this.pos;
|
|
3104
3094
|
return this.finishToken(tstt.jsxTagStart);
|
|
3105
3095
|
}
|
|
@@ -4136,6 +4126,16 @@ export function TSRXPlugin(config) {
|
|
|
4136
4126
|
|
|
4137
4127
|
case CharCode.lessThan:
|
|
4138
4128
|
case CharCode.openBrace:
|
|
4129
|
+
// This path reads the children of an element nested in a `{ … }`
|
|
4130
|
+
// expression container, where the raw-text intercept in `readToken`
|
|
4131
|
+
// is off, so the literal-`<` rule has to be applied here too. Keep
|
|
4132
|
+
// scanning rather than finishing the token: the `<` belongs to the
|
|
4133
|
+
// text run, and finishing here would emit an empty text token when
|
|
4134
|
+
// it is the run's first character.
|
|
4135
|
+
if (ch === CharCode.lessThan && !can_start_tag_after_lt(this.input, this.pos)) {
|
|
4136
|
+
++this.pos;
|
|
4137
|
+
break;
|
|
4138
|
+
}
|
|
4139
4139
|
if (out || this.pos > chunkStart) {
|
|
4140
4140
|
return this.finishToken(tstt.jsxText, out + this.input.slice(chunkStart, this.pos));
|
|
4141
4141
|
}
|
|
@@ -4629,10 +4629,13 @@ export function TSRXPlugin(config) {
|
|
|
4629
4629
|
} else if (this.type === tstt.jsxText) {
|
|
4630
4630
|
// A nested element with its own body can leak a JSX expression context,
|
|
4631
4631
|
// so the whitespace after its closing tag is mis-tokenized as a stale
|
|
4632
|
-
// text token whose start was advanced onto the following `<`.
|
|
4633
|
-
//
|
|
4634
|
-
// tag instead of emitting an empty node.
|
|
4635
|
-
if (
|
|
4632
|
+
// text token whose start was advanced onto the following `<`. Text never
|
|
4633
|
+
// starts at a `<` that can open a tag, so drop the leaked context and
|
|
4634
|
+
// re-read the tag instead of emitting an empty node.
|
|
4635
|
+
if (
|
|
4636
|
+
this.input.charCodeAt(this.start) === CharCode.lessThan &&
|
|
4637
|
+
can_start_tag_after_lt(this.input, this.start)
|
|
4638
|
+
) {
|
|
4636
4639
|
if (this.#jsxExpressionContainerDepth > 0) {
|
|
4637
4640
|
// Inside a `{ … }` container the whole-stack counts below are
|
|
4638
4641
|
// blind: the enclosing template's `tc_expr` contexts sit on the
|
|
@@ -152,6 +152,15 @@ export function tsx_with_ts_locations(boundary_tokens = false, comments = undefi
|
|
|
152
152
|
context.visit(value.body);
|
|
153
153
|
},
|
|
154
154
|
|
|
155
|
+
// TSRX text may contain a literal `<` — one that cannot start a tag
|
|
156
|
+
// (`<span><3</span>`) or a raw-text `<script>` body — but the printed TSX
|
|
157
|
+
// is re-parsed by a JSX toolchain (esbuild, Babel, SWC), and JSX forbids
|
|
158
|
+
// a bare `<` in text. Emit it as `<`, which those parsers decode back
|
|
159
|
+
// to the same string.
|
|
160
|
+
JSXText: (node, context) => {
|
|
161
|
+
context.write(node.value.replace(/</g, '<'), node);
|
|
162
|
+
},
|
|
163
|
+
|
|
155
164
|
// esrap's JSXOpeningElement printer doesn't emit `typeArguments`, so generic
|
|
156
165
|
// component tags like `<RenderProp<User>>` lose the `<User>` in the output.
|
|
157
166
|
JSXOpeningElement: (node, context) => {
|
package/types/parse.d.ts
CHANGED
|
@@ -679,6 +679,12 @@ export namespace Parse {
|
|
|
679
679
|
*/
|
|
680
680
|
getTokenFromCodeInType(code: number): void;
|
|
681
681
|
|
|
682
|
+
/**
|
|
683
|
+
* Get the current tokenizer state used by lookahead parsing.
|
|
684
|
+
* Added by @sveltejs/acorn-typescript.
|
|
685
|
+
*/
|
|
686
|
+
getCurLookaheadState(): LookaheadState;
|
|
687
|
+
|
|
682
688
|
/**
|
|
683
689
|
* Get current position as Position object
|
|
684
690
|
* @returns { line: number, column: number, index: number }
|