@tsrx/core 0.1.50 → 0.1.52
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 +10 -1
- package/src/analyze/prune.js +62 -77
- package/src/analyze/validation.js +7 -7
- package/src/parse/index.js +59 -80
- package/src/plugin.js +230 -95
- package/src/runtime/language-helpers.js +34 -25
- package/src/runtime/ref.js +57 -36
- package/src/scope.js +4 -5
- package/src/source-map-utils.js +8 -22
- package/src/transform/imports.js +8 -14
- package/src/transform/jsx/ast-builders.js +4 -1
- package/src/transform/jsx/index.js +1 -13
- package/src/transform/jsx/server-module.js +102 -96
- package/src/transform/jsx-hoist.js +4 -4
- package/src/transform/lazy.js +196 -137
- package/src/transform/scoping.js +108 -100
- package/src/transform/segments.js +24 -49
- package/src/transform/style-ref.js +92 -106
- package/src/transform/stylesheet.js +5 -21
- package/src/utils/ast.js +25 -20
- package/src/utils/builders.js +66 -2
- package/src/vite/dep-scan.js +135 -0
- package/types/index.d.ts +317 -17
- package/types/parse.d.ts +98 -13
- package/types/runtime/language-helpers.d.ts +10 -5
- package/types/runtime/ref.d.ts +63 -14
- package/types/vite/dep-scan.d.ts +26 -0
package/src/transform/scoping.js
CHANGED
|
@@ -6,11 +6,16 @@
|
|
|
6
6
|
*/
|
|
7
7
|
|
|
8
8
|
/** @import * as AST from 'estree' */
|
|
9
|
+
/** @import * as ESTreeJSX from 'estree-jsx' */
|
|
10
|
+
/** @import { Visitors } from '../../types/index' */
|
|
9
11
|
|
|
10
12
|
import { walk } from 'zimmerframe';
|
|
11
13
|
import * as b from '../utils/builders.js';
|
|
14
|
+
import { is_ast_node, is_style_element } from '../utils/ast.js';
|
|
12
15
|
import { mark_class_map_selectors } from './style-ref.js';
|
|
13
16
|
|
|
17
|
+
export { is_style_element };
|
|
18
|
+
|
|
14
19
|
/**
|
|
15
20
|
* Mark selectors inside the stylesheet as "used" so `renderStylesheets` does
|
|
16
21
|
* not comment them out.
|
|
@@ -28,36 +33,35 @@ import { mark_class_map_selectors } from './style-ref.js';
|
|
|
28
33
|
* along with their parent: they apply where the parent's class matched, and the
|
|
29
34
|
* whole rule is pruned when the parent itself is unreachable.
|
|
30
35
|
*
|
|
31
|
-
* @param {
|
|
36
|
+
* @param {AST.CSS.StyleSheet} stylesheet
|
|
32
37
|
* @param {boolean} [is_style_expression]
|
|
33
|
-
* @returns {
|
|
38
|
+
* @returns {AST.CSS.StyleSheet}
|
|
34
39
|
*/
|
|
35
40
|
export function prepare_stylesheet_for_render(stylesheet, is_style_expression = false) {
|
|
36
41
|
if (is_style_expression) {
|
|
37
42
|
mark_class_map_selectors(stylesheet);
|
|
38
43
|
}
|
|
39
|
-
walk(
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
is_unreachable_via_class_map(node, path)
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
node.metadata.
|
|
54
|
-
if (node.type === 'RelativeSelector' && !node.metadata.is_global) {
|
|
44
|
+
walk(
|
|
45
|
+
/** @type {AST.CSS.Node} */ (stylesheet),
|
|
46
|
+
null,
|
|
47
|
+
/** @type {Visitors<AST.CSS.Node, null>} */ ({
|
|
48
|
+
_(node, { next, path }) {
|
|
49
|
+
if (node.type === 'ComplexSelector') {
|
|
50
|
+
if (is_style_expression && is_unreachable_via_class_map(node, path)) {
|
|
51
|
+
// Not in the generated class map. The analyzer pre-marks global
|
|
52
|
+
// selectors as used, so reset, and leave the subtree untouched —
|
|
53
|
+
// no `scoped` marks that would splice the hash into pruned output.
|
|
54
|
+
node.metadata.used = false;
|
|
55
|
+
return;
|
|
56
|
+
}
|
|
57
|
+
node.metadata.used = true;
|
|
58
|
+
} else if (node.type === 'RelativeSelector' && !node.metadata.is_global) {
|
|
55
59
|
node.metadata.scoped = true;
|
|
56
60
|
}
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
},
|
|
60
|
-
|
|
61
|
+
return next();
|
|
62
|
+
},
|
|
63
|
+
}),
|
|
64
|
+
);
|
|
61
65
|
return stylesheet;
|
|
62
66
|
}
|
|
63
67
|
|
|
@@ -73,8 +77,8 @@ export function prepare_stylesheet_for_render(stylesheet, is_style_expression =
|
|
|
73
77
|
* is kept because its contents render unscoped as authored and cannot be
|
|
74
78
|
* pruned selector-by-selector.
|
|
75
79
|
*
|
|
76
|
-
* @param {
|
|
77
|
-
* @param {
|
|
80
|
+
* @param {AST.CSS.ComplexSelector} complex_selector
|
|
81
|
+
* @param {AST.CSS.Node[]} path
|
|
78
82
|
* @returns {boolean}
|
|
79
83
|
*/
|
|
80
84
|
function is_unreachable_via_class_map(complex_selector, path) {
|
|
@@ -82,8 +86,8 @@ function is_unreachable_via_class_map(complex_selector, path) {
|
|
|
82
86
|
if (complex_selector.metadata.rule?.metadata?.parent_rule != null) return false;
|
|
83
87
|
if (path.some((parent) => parent.type === 'ComplexSelector')) return false;
|
|
84
88
|
|
|
85
|
-
if (complex_selector.children
|
|
86
|
-
const first = complex_selector.children[0]
|
|
89
|
+
if (complex_selector.children.length === 1) {
|
|
90
|
+
const first = complex_selector.children[0].selectors[0];
|
|
87
91
|
if (first?.type === 'PseudoClassSelector' && first.name === 'global' && first.args === null) {
|
|
88
92
|
return false;
|
|
89
93
|
}
|
|
@@ -94,19 +98,15 @@ function is_unreachable_via_class_map(complex_selector, path) {
|
|
|
94
98
|
|
|
95
99
|
/**
|
|
96
100
|
* @param {AST.Node | null | undefined} node
|
|
97
|
-
* @returns {node is AST.JSXStyleElement}
|
|
98
|
-
*/
|
|
99
|
-
export function is_style_element(node) {
|
|
100
|
-
return !!node && node.type === 'JSXStyleElement';
|
|
101
|
-
}
|
|
102
|
-
|
|
103
|
-
/**
|
|
104
|
-
* @param {any} node
|
|
105
101
|
* @returns {boolean}
|
|
106
102
|
*/
|
|
107
103
|
export function is_composite_jsx_element(node) {
|
|
108
|
-
|
|
109
|
-
|
|
104
|
+
if (node?.type !== 'JSXElement') {
|
|
105
|
+
return false;
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
const name = node.openingElement?.name;
|
|
109
|
+
if (!name) {
|
|
110
110
|
return false;
|
|
111
111
|
}
|
|
112
112
|
|
|
@@ -121,11 +121,11 @@ export function is_composite_jsx_element(node) {
|
|
|
121
121
|
* Recursively walk native JSX nodes within a TSRX fragment and add the hash
|
|
122
122
|
* class name so scope-qualified selectors (e.g. `.foo.hash`) match.
|
|
123
123
|
*
|
|
124
|
-
* @param {
|
|
124
|
+
* @param {AST.Node} node
|
|
125
125
|
* @param {string} hash
|
|
126
126
|
* @param {'class' | 'className'} [jsx_class_attr_name='class']
|
|
127
127
|
* @param {boolean} [preserve_style_elements=false]
|
|
128
|
-
* @returns {
|
|
128
|
+
* @returns {AST.Node | null}
|
|
129
129
|
*/
|
|
130
130
|
export function annotate_with_hash(
|
|
131
131
|
node,
|
|
@@ -147,20 +147,17 @@ export function annotate_with_hash(
|
|
|
147
147
|
}
|
|
148
148
|
|
|
149
149
|
if (node.type === 'JSXElement') {
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
if (Array.isArray(node.children)) {
|
|
154
|
-
node.children = node.children
|
|
155
|
-
.map((/** @type {any} */ child) =>
|
|
156
|
-
annotate_with_hash(child, hash, jsx_class_attr_name, preserve_style_elements),
|
|
157
|
-
)
|
|
158
|
-
.filter(Boolean);
|
|
150
|
+
const element = /** @type {AST.TSRXJSXElement} */ (node);
|
|
151
|
+
if (!is_composite_jsx_element(element) || element.metadata?.dynamicElement) {
|
|
152
|
+
add_hash_class_to_jsx_element(element, hash, jsx_class_attr_name);
|
|
159
153
|
}
|
|
160
|
-
|
|
154
|
+
element.children = element.children
|
|
155
|
+
.map((child) => annotate_with_hash(child, hash, jsx_class_attr_name, preserve_style_elements))
|
|
156
|
+
.filter((child) => child !== null);
|
|
157
|
+
return element;
|
|
161
158
|
}
|
|
162
159
|
|
|
163
|
-
if (node
|
|
160
|
+
if (is_style_element(node)) {
|
|
164
161
|
if (preserve_style_elements) {
|
|
165
162
|
node.children = [];
|
|
166
163
|
return node;
|
|
@@ -168,18 +165,21 @@ export function annotate_with_hash(
|
|
|
168
165
|
return null;
|
|
169
166
|
}
|
|
170
167
|
|
|
171
|
-
|
|
168
|
+
const entries = /** @type {Record<string, unknown>} */ (node);
|
|
169
|
+
for (const key of Object.keys(entries)) {
|
|
172
170
|
if (key === 'loc' || key === 'start' || key === 'end' || key === 'metadata' || key === 'css') {
|
|
173
171
|
continue;
|
|
174
172
|
}
|
|
175
173
|
|
|
176
|
-
const value =
|
|
174
|
+
const value = entries[key];
|
|
177
175
|
if (Array.isArray(value)) {
|
|
178
|
-
|
|
179
|
-
|
|
176
|
+
entries[key] = value.map((child) =>
|
|
177
|
+
is_ast_node(child)
|
|
178
|
+
? annotate_with_hash(child, hash, jsx_class_attr_name, preserve_style_elements)
|
|
179
|
+
: child,
|
|
180
180
|
);
|
|
181
|
-
} else if (value
|
|
182
|
-
|
|
181
|
+
} else if (is_ast_node(value)) {
|
|
182
|
+
entries[key] = annotate_with_hash(value, hash, jsx_class_attr_name, preserve_style_elements);
|
|
183
183
|
}
|
|
184
184
|
}
|
|
185
185
|
|
|
@@ -187,7 +187,8 @@ export function annotate_with_hash(
|
|
|
187
187
|
}
|
|
188
188
|
|
|
189
189
|
/**
|
|
190
|
-
* @param {
|
|
190
|
+
* @param {{ body: AST.Node[] }} component a node whose `body` holds the
|
|
191
|
+
* component's template children
|
|
191
192
|
* @param {string} hash
|
|
192
193
|
* @param {'class' | 'className'} [jsx_class_attr_name='class']
|
|
193
194
|
* @param {boolean} [preserve_style_elements=false]
|
|
@@ -199,32 +200,53 @@ export function annotate_component_with_hash(
|
|
|
199
200
|
jsx_class_attr_name = 'class',
|
|
200
201
|
preserve_style_elements = false,
|
|
201
202
|
) {
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
.filter((
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
203
|
+
component.body = component.body
|
|
204
|
+
.filter((child) => preserve_style_elements || !is_style_element(child))
|
|
205
|
+
.map((child) => annotate_with_hash(child, hash, jsx_class_attr_name, preserve_style_elements))
|
|
206
|
+
.filter((child) => child !== null);
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
/**
|
|
210
|
+
* The element's `class`/`className` attribute, if it has a static-named one.
|
|
211
|
+
*
|
|
212
|
+
* @param {ESTreeJSX.JSXAttributeNode} attr
|
|
213
|
+
* @returns {attr is ESTreeJSX.JSXAttribute}
|
|
214
|
+
*/
|
|
215
|
+
function is_class_attribute(attr) {
|
|
216
|
+
return (
|
|
217
|
+
attr.type === 'JSXAttribute' &&
|
|
218
|
+
attr.name.type === 'JSXIdentifier' &&
|
|
219
|
+
(attr.name.name === 'class' || attr.name.name === 'className')
|
|
220
|
+
);
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
/**
|
|
224
|
+
* Merge the hash into an existing class attribute value. Returns `false` when
|
|
225
|
+
* the value is not a string literal, so the caller must wrap it instead.
|
|
226
|
+
*
|
|
227
|
+
* @param {ESTreeJSX.JSXAttribute['value'] | AST.Expression | ESTreeJSX.JSXEmptyExpression} value
|
|
228
|
+
* @param {string} hash
|
|
229
|
+
* @returns {boolean} whether the hash was merged into the literal in place
|
|
230
|
+
*/
|
|
231
|
+
function merge_hash_into_literal(value, hash) {
|
|
232
|
+
if (value?.type !== 'Literal' || typeof value.value !== 'string') return false;
|
|
233
|
+
const merged = `${value.value} ${hash}`;
|
|
234
|
+
value.value = merged;
|
|
235
|
+
value.raw = JSON.stringify(merged);
|
|
236
|
+
return true;
|
|
209
237
|
}
|
|
210
238
|
|
|
211
239
|
/**
|
|
212
240
|
* Ensure the element carries a class attribute containing the scoping hash.
|
|
213
241
|
*
|
|
214
|
-
* @param {
|
|
242
|
+
* @param {AST.TSRXJSXElement} element
|
|
215
243
|
* @param {string} hash
|
|
216
244
|
* @param {'class' | 'className'} [class_attr_name='class']
|
|
217
245
|
* @returns {void}
|
|
218
246
|
*/
|
|
219
247
|
export function add_hash_class(element, hash, class_attr_name = 'class') {
|
|
220
248
|
const attrs = element.openingElement.attributes;
|
|
221
|
-
const existing = attrs.find(
|
|
222
|
-
(/** @type {any} */ a) =>
|
|
223
|
-
a.type === 'JSXAttribute' &&
|
|
224
|
-
a.name &&
|
|
225
|
-
a.name.type === 'JSXIdentifier' &&
|
|
226
|
-
(a.name.name === 'class' || a.name.name === 'className'),
|
|
227
|
-
);
|
|
249
|
+
const existing = attrs.find(is_class_attribute);
|
|
228
250
|
|
|
229
251
|
if (!existing) {
|
|
230
252
|
attrs.push(b.jsx_attribute(b.jsx_id(class_attr_name), b.literal(hash)));
|
|
@@ -233,17 +255,12 @@ export function add_hash_class(element, hash, class_attr_name = 'class') {
|
|
|
233
255
|
|
|
234
256
|
const value =
|
|
235
257
|
existing.value?.type === 'JSXExpressionContainer' ? existing.value.expression : existing.value;
|
|
236
|
-
if (!value) {
|
|
237
|
-
existing.value =
|
|
258
|
+
if (!value || value.type === 'JSXEmptyExpression') {
|
|
259
|
+
existing.value = b.literal(hash, JSON.stringify(hash));
|
|
238
260
|
return;
|
|
239
261
|
}
|
|
240
262
|
|
|
241
|
-
if (value
|
|
242
|
-
const merged = `${value.value} ${hash}`;
|
|
243
|
-
value.value = merged;
|
|
244
|
-
value.raw = JSON.stringify(merged);
|
|
245
|
-
return;
|
|
246
|
-
}
|
|
263
|
+
if (merge_hash_into_literal(value, hash)) return;
|
|
247
264
|
|
|
248
265
|
// Dynamic expression. Concatenate at runtime via template literal.
|
|
249
266
|
existing.value = b.jsx_expression_container(
|
|
@@ -252,46 +269,37 @@ export function add_hash_class(element, hash, class_attr_name = 'class') {
|
|
|
252
269
|
}
|
|
253
270
|
|
|
254
271
|
/**
|
|
255
|
-
* @param {
|
|
272
|
+
* @param {AST.TSRXJSXElement} element
|
|
256
273
|
* @param {string} hash
|
|
257
274
|
* @param {'class' | 'className'} jsx_class_attr_name
|
|
258
275
|
* @returns {void}
|
|
259
276
|
*/
|
|
260
277
|
function add_hash_class_to_jsx_element(element, hash, jsx_class_attr_name) {
|
|
261
|
-
const attrs =
|
|
262
|
-
const existing = attrs.find(
|
|
263
|
-
(/** @type {any} */ attr) =>
|
|
264
|
-
attr?.type === 'JSXAttribute' &&
|
|
265
|
-
attr.name?.type === 'JSXIdentifier' &&
|
|
266
|
-
(attr.name.name === 'class' || attr.name.name === 'className'),
|
|
267
|
-
);
|
|
278
|
+
const attrs = (element.openingElement.attributes ??= []);
|
|
279
|
+
const existing = attrs.find(is_class_attribute);
|
|
268
280
|
|
|
269
281
|
if (!existing) {
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
element.attributes = attrs;
|
|
282
|
+
attrs.push(
|
|
283
|
+
b.jsx_attribute(b.jsx_id(jsx_class_attr_name), b.literal(hash, JSON.stringify(hash))),
|
|
284
|
+
);
|
|
274
285
|
return;
|
|
275
286
|
}
|
|
276
287
|
|
|
277
288
|
const value = existing.value;
|
|
278
289
|
if (!value) {
|
|
279
|
-
existing.value =
|
|
280
|
-
element.attributes = attrs;
|
|
290
|
+
existing.value = b.literal(hash, JSON.stringify(hash));
|
|
281
291
|
return;
|
|
282
292
|
}
|
|
283
293
|
|
|
284
|
-
if (value
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
294
|
+
if (merge_hash_into_literal(value, hash)) return;
|
|
295
|
+
|
|
296
|
+
const expression = value.type === 'JSXExpressionContainer' ? value.expression : value;
|
|
297
|
+
if (expression.type === 'JSXEmptyExpression') {
|
|
298
|
+
existing.value = b.literal(hash, JSON.stringify(hash));
|
|
289
299
|
return;
|
|
290
300
|
}
|
|
291
301
|
|
|
292
|
-
const expression = value.type === 'JSXExpressionContainer' ? value.expression : value;
|
|
293
302
|
existing.value = b.jsx_expression_container(
|
|
294
303
|
b.template([b.quasi('', false), b.quasi(` ${hash}`, true)], [expression]),
|
|
295
304
|
);
|
|
296
|
-
element.attributes = attrs;
|
|
297
305
|
}
|
|
@@ -11,45 +11,15 @@
|
|
|
11
11
|
PostProcessingChanges,
|
|
12
12
|
LineOffsets,
|
|
13
13
|
CompileError,
|
|
14
|
+
CssElementInfo,
|
|
15
|
+
CssSourceRegion,
|
|
16
|
+
MappingToken,
|
|
17
|
+
ScriptSourceRegion,
|
|
18
|
+
TokenClass,
|
|
14
19
|
} from '../../types/index';
|
|
15
20
|
@import { CodeMapping as VolarCodeMapping } from '@volar/language-core';
|
|
16
21
|
*/
|
|
17
22
|
|
|
18
|
-
/**
|
|
19
|
-
@typedef {{
|
|
20
|
-
start: number,
|
|
21
|
-
end: number,
|
|
22
|
-
content: string,
|
|
23
|
-
id: string,
|
|
24
|
-
}} CssSourceRegion;
|
|
25
|
-
@typedef {{
|
|
26
|
-
start: number,
|
|
27
|
-
end: number,
|
|
28
|
-
content: string,
|
|
29
|
-
id: string,
|
|
30
|
-
}} ScriptSourceRegion;
|
|
31
|
-
@typedef {{
|
|
32
|
-
source: string | null | undefined;
|
|
33
|
-
generated: string;
|
|
34
|
-
loc: AST.SourceLocation;
|
|
35
|
-
metadata: PluginActionOverrides;
|
|
36
|
-
generatedLoc?: AST.SourceLocation;
|
|
37
|
-
end_loc?: AST.SourceLocation;
|
|
38
|
-
sourceLength?: number;
|
|
39
|
-
mappingData?: Partial<VolarCodeMapping['data']>;
|
|
40
|
-
}} Token;
|
|
41
|
-
@typedef {{
|
|
42
|
-
name: string,
|
|
43
|
-
line: number,
|
|
44
|
-
column: number,
|
|
45
|
-
offset: number,
|
|
46
|
-
length: number,
|
|
47
|
-
sourceOffset: number,
|
|
48
|
-
}} TokenClass;
|
|
49
|
-
*/
|
|
50
|
-
|
|
51
|
-
/** @typedef {Map<string, { scopedClasses: Map<string, { start: number; end: number; selector: any }>; hash: string } | undefined>} CssElementInfo */
|
|
52
|
-
|
|
53
23
|
import { walk } from 'zimmerframe';
|
|
54
24
|
import {
|
|
55
25
|
build_src_to_gen_map,
|
|
@@ -367,7 +337,7 @@ function extract_classes(node, src_to_gen_map, gen_line_offsets, src_line_offset
|
|
|
367
337
|
/**
|
|
368
338
|
* Create Volar mappings by walking the transformed AST
|
|
369
339
|
* @param {AST.Node} ast - The transformed AST
|
|
370
|
-
* @param {AST.
|
|
340
|
+
* @param {AST.Program} ast_from_source - The original AST from source
|
|
371
341
|
* @param {string} source - Original source code
|
|
372
342
|
* @param {string} generated_code - Generated code (returned in output, not used for searching)
|
|
373
343
|
* @param {RawSourceMap} source_map - Esrap source map for accurate position lookup
|
|
@@ -401,7 +371,7 @@ export function convert_source_map_to_mappings(
|
|
|
401
371
|
errors.length > 0,
|
|
402
372
|
);
|
|
403
373
|
|
|
404
|
-
/** @type {
|
|
374
|
+
/** @type {MappingToken[]} */
|
|
405
375
|
const tokens = [];
|
|
406
376
|
/** @type {CssSourceRegion[]} */
|
|
407
377
|
const css_regions = [];
|
|
@@ -425,7 +395,7 @@ export function convert_source_map_to_mappings(
|
|
|
425
395
|
* _$_server_$_.foo`), esrap records multiple generated positions for the
|
|
426
396
|
* same source location. Keep token mappings in generated-order by consuming
|
|
427
397
|
* the next matching generated token instead of always using the first one.
|
|
428
|
-
* @param {
|
|
398
|
+
* @param {MappingToken} token
|
|
429
399
|
* @returns {{ line: number; column: number }}
|
|
430
400
|
*/
|
|
431
401
|
function get_generated_position_for_token(token) {
|
|
@@ -479,16 +449,22 @@ export function convert_source_map_to_mappings(
|
|
|
479
449
|
const mapped_comments = new Set();
|
|
480
450
|
|
|
481
451
|
/**
|
|
482
|
-
* @param {
|
|
452
|
+
* @param {AST.Node | null | undefined} node
|
|
483
453
|
* @returns {void}
|
|
484
454
|
*/
|
|
485
455
|
function add_preserved_comment_mappings(node) {
|
|
486
|
-
|
|
487
|
-
|
|
456
|
+
if (!node) return;
|
|
457
|
+
|
|
458
|
+
for (const comments of [
|
|
459
|
+
node.leadingComments,
|
|
460
|
+
node.trailingComments,
|
|
461
|
+
node.innerComments,
|
|
462
|
+
node.comments,
|
|
463
|
+
]) {
|
|
488
464
|
if (!Array.isArray(comments)) continue;
|
|
489
465
|
|
|
490
466
|
for (const comment of comments) {
|
|
491
|
-
if (!comment
|
|
467
|
+
if (!has_location(comment) || !should_preserve_comment(comment)) continue;
|
|
492
468
|
|
|
493
469
|
const comment_key = `${comment.start}:${comment.end}`;
|
|
494
470
|
if (mapped_comments.has(comment_key)) continue;
|
|
@@ -522,7 +498,7 @@ export function convert_source_map_to_mappings(
|
|
|
522
498
|
}
|
|
523
499
|
|
|
524
500
|
/**
|
|
525
|
-
* @param {
|
|
501
|
+
* @param {AST.Identifier | ESTreeJSX.JSXIdentifier} generated_node
|
|
526
502
|
* @returns {void}
|
|
527
503
|
*/
|
|
528
504
|
function add_extra_source_mapping_tokens(generated_node) {
|
|
@@ -558,7 +534,7 @@ export function convert_source_map_to_mappings(
|
|
|
558
534
|
// Only create mappings for identifiers with location info (from source)
|
|
559
535
|
// Synthesized identifiers (created by builders) don't have .loc and are skipped
|
|
560
536
|
if (node.name && node.loc) {
|
|
561
|
-
/** @type {
|
|
537
|
+
/** @type {MappingToken} */
|
|
562
538
|
let token;
|
|
563
539
|
// Check if this identifier was changed in metadata (e.g., #Map -> RippleMap)
|
|
564
540
|
// Or if it was capitalized during transformation
|
|
@@ -583,8 +559,8 @@ export function convert_source_map_to_mappings(
|
|
|
583
559
|
if (node.metadata?.source_length != null && LAZY_PARAM_IDENTIFIER_REGEX.test(node.name)) {
|
|
584
560
|
token.metadata.hover = create_lazy_param_hover_replacement(node.name);
|
|
585
561
|
}
|
|
586
|
-
if ('hover' in
|
|
587
|
-
token.metadata.hover =
|
|
562
|
+
if (node.metadata && 'hover' in node.metadata) {
|
|
563
|
+
token.metadata.hover = node.metadata.hover;
|
|
588
564
|
}
|
|
589
565
|
if (node.metadata?.disable_verification) {
|
|
590
566
|
token.mappingData = { ...mapping_data, verification: false };
|
|
@@ -624,7 +600,7 @@ export function convert_source_map_to_mappings(
|
|
|
624
600
|
} else if (node.type === 'JSXIdentifier') {
|
|
625
601
|
// JSXIdentifiers can also be capitalized (for dynamic components)
|
|
626
602
|
if (node.loc && node.name) {
|
|
627
|
-
/** @type {
|
|
603
|
+
/** @type {MappingToken} */
|
|
628
604
|
const token = {
|
|
629
605
|
source: node.metadata?.source_name ?? node.name,
|
|
630
606
|
generated: node.name,
|
|
@@ -998,8 +974,7 @@ export function convert_source_map_to_mappings(
|
|
|
998
974
|
// node-start-anchored arithmetic when tokens were not collected.
|
|
999
975
|
const keyword_bound =
|
|
1000
976
|
node_fn.id?.start ?? node_fn.params?.[0]?.start ?? node_fn.body?.start ?? node_fn.end;
|
|
1001
|
-
|
|
1002
|
-
const lexer_tokens = /** @type {any} */ (ast_from_source).tsrx_keyword_tokens ?? [];
|
|
977
|
+
const lexer_tokens = ast_from_source.tsrx_keyword_tokens ?? [];
|
|
1003
978
|
/**
|
|
1004
979
|
* @param {'async' | 'function'} keyword
|
|
1005
980
|
* @param {number} from
|