@tsrx/core 0.1.4 → 0.1.7
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 +39 -6
- package/src/diagnostics.js +1 -0
- package/src/index.js +8 -2
- package/src/plugin.js +31 -1
- package/src/runtime/events.js +10 -0
- package/src/runtime/hash.js +1 -0
- package/src/runtime/html.js +3 -0
- package/src/runtime/iterable.js +110 -0
- package/src/source-map-utils.js +19 -2
- package/src/transform/jsx/ast-builders.js +120 -0
- package/src/transform/jsx/index.js +632 -1415
- package/src/transform/lazy.js +301 -205
- package/src/transform/scoping.js +9 -45
- package/src/transform/segments.js +164 -11
- package/src/utils/ast.js +13 -0
- package/src/utils/builders.js +51 -13
- package/src/utils/dom.js +158 -0
- package/src/utils.js +6 -159
- package/types/index.d.ts +1 -0
- package/types/jsx-platform.d.ts +12 -0
- package/types/runtime/events.d.ts +11 -0
- package/types/runtime/hash.d.ts +2 -0
- package/types/runtime/html.d.ts +4 -0
- package/types/runtime/iterable.d.ts +13 -0
- package/types/runtime/language-helpers.d.ts +17 -0
package/src/transform/scoping.js
CHANGED
|
@@ -6,6 +6,7 @@
|
|
|
6
6
|
*/
|
|
7
7
|
|
|
8
8
|
import { walk } from 'zimmerframe';
|
|
9
|
+
import * as b from '../utils/builders.js';
|
|
9
10
|
|
|
10
11
|
/**
|
|
11
12
|
* Mark every selector inside the stylesheet as "used" so `renderStylesheets`
|
|
@@ -183,7 +184,7 @@ export function add_hash_class(element, hash) {
|
|
|
183
184
|
if (!existing) {
|
|
184
185
|
attrs.push({
|
|
185
186
|
type: 'Attribute',
|
|
186
|
-
name:
|
|
187
|
+
name: b.id('class'),
|
|
187
188
|
value: { type: 'Literal', value: hash, raw: JSON.stringify(hash) },
|
|
188
189
|
});
|
|
189
190
|
return;
|
|
@@ -203,22 +204,7 @@ export function add_hash_class(element, hash) {
|
|
|
203
204
|
|
|
204
205
|
// Dynamic expression. Concatenate at runtime via template literal.
|
|
205
206
|
const expression = value.type === 'JSXExpressionContainer' ? value.expression : value;
|
|
206
|
-
existing.value = {
|
|
207
|
-
type: 'TemplateLiteral',
|
|
208
|
-
expressions: [expression],
|
|
209
|
-
quasis: [
|
|
210
|
-
{
|
|
211
|
-
type: 'TemplateElement',
|
|
212
|
-
value: { raw: '', cooked: '' },
|
|
213
|
-
tail: false,
|
|
214
|
-
},
|
|
215
|
-
{
|
|
216
|
-
type: 'TemplateElement',
|
|
217
|
-
value: { raw: ` ${hash}`, cooked: ` ${hash}` },
|
|
218
|
-
tail: true,
|
|
219
|
-
},
|
|
220
|
-
],
|
|
221
|
-
};
|
|
207
|
+
existing.value = b.template([b.quasi('', false), b.quasi(` ${hash}`, true)], [expression]);
|
|
222
208
|
}
|
|
223
209
|
|
|
224
210
|
/**
|
|
@@ -237,13 +223,9 @@ function add_hash_class_to_jsx_element(element, hash, jsx_class_attr_name) {
|
|
|
237
223
|
);
|
|
238
224
|
|
|
239
225
|
if (!existing) {
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
value: { type: 'Literal', value: hash, raw: JSON.stringify(hash) },
|
|
244
|
-
shorthand: false,
|
|
245
|
-
metadata: { path: [] },
|
|
246
|
-
});
|
|
226
|
+
const hash_literal = b.literal(hash);
|
|
227
|
+
/** @type {any} */ (hash_literal).raw = JSON.stringify(hash);
|
|
228
|
+
attrs.push(b.jsx_attribute(b.jsx_id(jsx_class_attr_name), hash_literal));
|
|
247
229
|
return;
|
|
248
230
|
}
|
|
249
231
|
|
|
@@ -268,25 +250,7 @@ function add_hash_class_to_jsx_element(element, hash, jsx_class_attr_name) {
|
|
|
268
250
|
}
|
|
269
251
|
|
|
270
252
|
const expression = value.type === 'JSXExpressionContainer' ? value.expression : value;
|
|
271
|
-
existing.value =
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
type: 'TemplateLiteral',
|
|
275
|
-
expressions: [expression],
|
|
276
|
-
quasis: [
|
|
277
|
-
{
|
|
278
|
-
type: 'TemplateElement',
|
|
279
|
-
value: { raw: '', cooked: '' },
|
|
280
|
-
tail: false,
|
|
281
|
-
},
|
|
282
|
-
{
|
|
283
|
-
type: 'TemplateElement',
|
|
284
|
-
value: { raw: ` ${hash}`, cooked: ` ${hash}` },
|
|
285
|
-
tail: true,
|
|
286
|
-
},
|
|
287
|
-
],
|
|
288
|
-
metadata: { path: [] },
|
|
289
|
-
},
|
|
290
|
-
metadata: { path: [] },
|
|
291
|
-
};
|
|
253
|
+
existing.value = b.jsx_expression_container(
|
|
254
|
+
b.template([b.quasi('', false), b.quasi(` ${hash}`, true)], [expression]),
|
|
255
|
+
);
|
|
292
256
|
}
|
|
@@ -10,6 +10,7 @@
|
|
|
10
10
|
VolarMappingsResult,
|
|
11
11
|
PostProcessingChanges,
|
|
12
12
|
LineOffsets,
|
|
13
|
+
CompileError,
|
|
13
14
|
} from '../../types/index';
|
|
14
15
|
@import { CodeMapping as VolarCodeMapping } from '@volar/language-core';
|
|
15
16
|
*/
|
|
@@ -343,6 +344,7 @@ function extract_classes(node, src_to_gen_map, gen_line_offsets, src_line_offset
|
|
|
343
344
|
* @param {RawSourceMap} source_map - Esrap source map for accurate position lookup
|
|
344
345
|
* @param {PostProcessingChanges } post_processing_changes - Optional post-processing changes
|
|
345
346
|
* @param {number[]} line_offsets - Pre-computed line offsets array for generated code
|
|
347
|
+
* @param {CompileError[]} [errors]
|
|
346
348
|
* @returns {Omit<VolarMappingsResult, 'errors'>}
|
|
347
349
|
*/
|
|
348
350
|
export function convert_source_map_to_mappings(
|
|
@@ -353,6 +355,7 @@ export function convert_source_map_to_mappings(
|
|
|
353
355
|
source_map,
|
|
354
356
|
post_processing_changes,
|
|
355
357
|
line_offsets,
|
|
358
|
+
errors = [],
|
|
356
359
|
) {
|
|
357
360
|
/** @type {CodeMapping[]} */
|
|
358
361
|
const mappings = [];
|
|
@@ -361,11 +364,12 @@ export function convert_source_map_to_mappings(
|
|
|
361
364
|
const src_line_offsets = build_line_offsets(source);
|
|
362
365
|
const gen_line_offsets = build_line_offsets(generated_code);
|
|
363
366
|
|
|
364
|
-
const [src_to_gen_map] = build_src_to_gen_map(
|
|
367
|
+
const [src_to_gen_map, , source_line_generated_map] = build_src_to_gen_map(
|
|
365
368
|
source_map,
|
|
366
369
|
post_processing_changes,
|
|
367
370
|
line_offsets,
|
|
368
371
|
generated_code,
|
|
372
|
+
errors.length > 0,
|
|
369
373
|
);
|
|
370
374
|
|
|
371
375
|
/** @type {Token[]} */
|
|
@@ -2250,6 +2254,15 @@ export function convert_source_map_to_mappings(
|
|
|
2250
2254
|
});
|
|
2251
2255
|
}
|
|
2252
2256
|
|
|
2257
|
+
add_diagnostic_mappings(
|
|
2258
|
+
mappings,
|
|
2259
|
+
errors,
|
|
2260
|
+
generated_code,
|
|
2261
|
+
src_to_gen_map,
|
|
2262
|
+
source_line_generated_map,
|
|
2263
|
+
gen_line_offsets,
|
|
2264
|
+
);
|
|
2265
|
+
|
|
2253
2266
|
// Sort mappings by start position, but prioritize narrower ranges that are fully contained
|
|
2254
2267
|
// within wider ones. This ensures that specific tokens (like identifiers) take precedence
|
|
2255
2268
|
// over broader ranges (like `if` consequent blocks) during language server lookups.
|
|
@@ -2351,7 +2364,7 @@ function find_component_keyword_offset(generated_code, generated_id_start) {
|
|
|
2351
2364
|
* source: string,
|
|
2352
2365
|
* generated_code: string,
|
|
2353
2366
|
* source_map: RawSourceMap,
|
|
2354
|
-
* errors?:
|
|
2367
|
+
* errors?: CompileError[],
|
|
2355
2368
|
* post_processing_changes?: PostProcessingChanges,
|
|
2356
2369
|
* line_offsets?: LineOffsets,
|
|
2357
2370
|
* }} params
|
|
@@ -2367,20 +2380,160 @@ export function create_volar_mappings_result({
|
|
|
2367
2380
|
post_processing_changes,
|
|
2368
2381
|
line_offsets,
|
|
2369
2382
|
}) {
|
|
2383
|
+
const result = convert_source_map_to_mappings(
|
|
2384
|
+
ast,
|
|
2385
|
+
ast_from_source,
|
|
2386
|
+
source,
|
|
2387
|
+
generated_code,
|
|
2388
|
+
source_map,
|
|
2389
|
+
/** @type {PostProcessingChanges} */ (post_processing_changes),
|
|
2390
|
+
line_offsets ?? build_line_offsets(generated_code),
|
|
2391
|
+
errors,
|
|
2392
|
+
);
|
|
2393
|
+
|
|
2370
2394
|
return {
|
|
2371
|
-
...
|
|
2372
|
-
ast,
|
|
2373
|
-
ast_from_source,
|
|
2374
|
-
source,
|
|
2375
|
-
generated_code,
|
|
2376
|
-
source_map,
|
|
2377
|
-
/** @type {PostProcessingChanges} */ (post_processing_changes),
|
|
2378
|
-
line_offsets ?? build_line_offsets(generated_code),
|
|
2379
|
-
),
|
|
2395
|
+
...result,
|
|
2380
2396
|
errors,
|
|
2381
2397
|
};
|
|
2382
2398
|
}
|
|
2383
2399
|
|
|
2400
|
+
/**
|
|
2401
|
+
* Parser diagnostics can point at source-only tokens that are intentionally
|
|
2402
|
+
* omitted or rewritten away in generated TSX. Add a narrow mapping so the
|
|
2403
|
+
* language-server diagnostic plugin can translate those exact source ranges.
|
|
2404
|
+
*
|
|
2405
|
+
* @param {CodeMapping[]} mappings
|
|
2406
|
+
* @param {CompileError[]} errors
|
|
2407
|
+
* @param {string} generated_code
|
|
2408
|
+
* @param {Map<string, Array<{ line: number, column: number }>>} src_to_gen_map
|
|
2409
|
+
* @param {Map<number, Array<{ column: number, position: { line: number, column: number } }>> | null} source_line_generated_map
|
|
2410
|
+
* @param {LineOffsets} gen_line_offsets
|
|
2411
|
+
*/
|
|
2412
|
+
function add_diagnostic_mappings(
|
|
2413
|
+
mappings,
|
|
2414
|
+
errors,
|
|
2415
|
+
generated_code,
|
|
2416
|
+
src_to_gen_map,
|
|
2417
|
+
source_line_generated_map,
|
|
2418
|
+
gen_line_offsets,
|
|
2419
|
+
) {
|
|
2420
|
+
if (errors.length === 0 || !source_line_generated_map) {
|
|
2421
|
+
return;
|
|
2422
|
+
}
|
|
2423
|
+
|
|
2424
|
+
/** @type {CodeMapping[]} */
|
|
2425
|
+
const diagnostic_mappings = [];
|
|
2426
|
+
|
|
2427
|
+
for (const error of errors) {
|
|
2428
|
+
const start = error.pos;
|
|
2429
|
+
if (start === undefined) continue;
|
|
2430
|
+
if (has_exact_source_map_position(error, src_to_gen_map)) continue;
|
|
2431
|
+
|
|
2432
|
+
const end = error.end && error.end > start ? error.end : start + 1;
|
|
2433
|
+
const length = end - start;
|
|
2434
|
+
const generated_start = get_nearest_generated_offset_from_source_line_map(
|
|
2435
|
+
error,
|
|
2436
|
+
source_line_generated_map,
|
|
2437
|
+
gen_line_offsets,
|
|
2438
|
+
generated_code,
|
|
2439
|
+
);
|
|
2440
|
+
if (generated_start === null) continue;
|
|
2441
|
+
|
|
2442
|
+
diagnostic_mappings.push({
|
|
2443
|
+
sourceOffsets: [start],
|
|
2444
|
+
generatedOffsets: [generated_start],
|
|
2445
|
+
lengths: [length],
|
|
2446
|
+
generatedLengths: [
|
|
2447
|
+
generated_code.length === 0
|
|
2448
|
+
? 0
|
|
2449
|
+
: Math.max(1, Math.min(length, generated_code.length - generated_start)),
|
|
2450
|
+
],
|
|
2451
|
+
data: {
|
|
2452
|
+
...mapping_data_verify_only,
|
|
2453
|
+
customData: {},
|
|
2454
|
+
},
|
|
2455
|
+
});
|
|
2456
|
+
}
|
|
2457
|
+
|
|
2458
|
+
mappings.unshift(...diagnostic_mappings);
|
|
2459
|
+
}
|
|
2460
|
+
|
|
2461
|
+
/**
|
|
2462
|
+
* @param {CompileError} error
|
|
2463
|
+
* @param {Map<string, Array<{ line: number, column: number }>>} src_to_gen_map
|
|
2464
|
+
*/
|
|
2465
|
+
function has_exact_source_map_position(error, src_to_gen_map) {
|
|
2466
|
+
const loc = error.loc?.start;
|
|
2467
|
+
return !!loc && src_to_gen_map.has(`${loc.line}:${loc.column}`);
|
|
2468
|
+
}
|
|
2469
|
+
|
|
2470
|
+
/**
|
|
2471
|
+
* @param {CompileError} error
|
|
2472
|
+
* @param {Map<number, Array<{ column: number, position: { line: number, column: number } }>>} source_line_generated_map
|
|
2473
|
+
* @param {LineOffsets} gen_line_offsets
|
|
2474
|
+
* @param {string} generated_code
|
|
2475
|
+
*/
|
|
2476
|
+
function get_nearest_generated_offset_from_source_line_map(
|
|
2477
|
+
error,
|
|
2478
|
+
source_line_generated_map,
|
|
2479
|
+
gen_line_offsets,
|
|
2480
|
+
generated_code,
|
|
2481
|
+
) {
|
|
2482
|
+
const loc = error.loc?.start;
|
|
2483
|
+
if (!loc || generated_code.length === 0) {
|
|
2484
|
+
return null;
|
|
2485
|
+
}
|
|
2486
|
+
|
|
2487
|
+
const position = get_nearest_source_line_generated_position(
|
|
2488
|
+
source_line_generated_map,
|
|
2489
|
+
loc.line,
|
|
2490
|
+
loc.column,
|
|
2491
|
+
);
|
|
2492
|
+
if (!position) {
|
|
2493
|
+
return null;
|
|
2494
|
+
}
|
|
2495
|
+
|
|
2496
|
+
const generated_offset =
|
|
2497
|
+
loc_to_offset(position.line, position.column, gen_line_offsets) +
|
|
2498
|
+
('sourceColumn' in position ? loc.column - position.sourceColumn : 0);
|
|
2499
|
+
return Math.max(0, Math.min(generated_offset, generated_code.length - 1));
|
|
2500
|
+
}
|
|
2501
|
+
|
|
2502
|
+
/**
|
|
2503
|
+
* @param {Map<number, Array<{ column: number, position: { line: number, column: number } }>>} source_line_generated_map
|
|
2504
|
+
* @param {number} line
|
|
2505
|
+
* @param {number} column
|
|
2506
|
+
* @returns {{ line: number, column: number, sourceColumn: number } | null}
|
|
2507
|
+
*/
|
|
2508
|
+
function get_nearest_source_line_generated_position(source_line_generated_map, line, column) {
|
|
2509
|
+
const line_positions = source_line_generated_map.get(line);
|
|
2510
|
+
if (!line_positions?.length) {
|
|
2511
|
+
return null;
|
|
2512
|
+
}
|
|
2513
|
+
line_positions.sort((a, b) => a.column - b.column);
|
|
2514
|
+
|
|
2515
|
+
let low = 0;
|
|
2516
|
+
let high = line_positions.length - 1;
|
|
2517
|
+
let best = -1;
|
|
2518
|
+
while (low <= high) {
|
|
2519
|
+
const mid = (low + high) >> 1;
|
|
2520
|
+
if (line_positions[mid].column <= column) {
|
|
2521
|
+
best = mid;
|
|
2522
|
+
low = mid + 1;
|
|
2523
|
+
} else {
|
|
2524
|
+
high = mid - 1;
|
|
2525
|
+
}
|
|
2526
|
+
}
|
|
2527
|
+
|
|
2528
|
+
if (best === -1) {
|
|
2529
|
+
return null;
|
|
2530
|
+
}
|
|
2531
|
+
|
|
2532
|
+
const entry = line_positions[best];
|
|
2533
|
+
const position = entry.position;
|
|
2534
|
+
return { line: position.line, column: position.column, sourceColumn: entry.column };
|
|
2535
|
+
}
|
|
2536
|
+
|
|
2384
2537
|
/**
|
|
2385
2538
|
* Remove byte-for-byte duplicate mappings. Framework compilers that extract
|
|
2386
2539
|
* shared helpers or replay JSX can emit identical mapping entries for the
|
package/src/utils/ast.js
CHANGED
|
@@ -32,6 +32,19 @@ export function is_function_node(node) {
|
|
|
32
32
|
);
|
|
33
33
|
}
|
|
34
34
|
|
|
35
|
+
/**
|
|
36
|
+
* @param {AST.Node} node
|
|
37
|
+
* @returns {boolean}
|
|
38
|
+
*/
|
|
39
|
+
export function is_function_or_component_node(node) {
|
|
40
|
+
return (
|
|
41
|
+
node.type === 'FunctionDeclaration' ||
|
|
42
|
+
node.type === 'FunctionExpression' ||
|
|
43
|
+
node.type === 'ArrowFunctionExpression' ||
|
|
44
|
+
node.type === 'Component'
|
|
45
|
+
);
|
|
46
|
+
}
|
|
47
|
+
|
|
35
48
|
/**
|
|
36
49
|
* @param {AST.Node} node
|
|
37
50
|
* @returns {boolean}
|
package/src/utils/builders.js
CHANGED
|
@@ -57,10 +57,12 @@ export function assignment_pattern(left, right) {
|
|
|
57
57
|
/**
|
|
58
58
|
* @param {Array<AST.Pattern>} params
|
|
59
59
|
* @param {AST.BlockStatement | AST.Expression} body
|
|
60
|
+
* @param {boolean} [async]
|
|
61
|
+
* @param {AST.TSTypeParameterDeclaration} [type_parameters]
|
|
60
62
|
* @param {AST.NodeWithLocation} [loc_info]
|
|
61
63
|
* @returns {AST.ArrowFunctionExpression}
|
|
62
64
|
*/
|
|
63
|
-
export function arrow(params, body, async = false, loc_info) {
|
|
65
|
+
export function arrow(params, body, async = false, type_parameters, loc_info) {
|
|
64
66
|
const node = /** @type {AST.ArrowFunctionExpression} */ ({
|
|
65
67
|
type: 'ArrowFunctionExpression',
|
|
66
68
|
params,
|
|
@@ -68,6 +70,7 @@ export function arrow(params, body, async = false, loc_info) {
|
|
|
68
70
|
expression: body.type !== 'BlockStatement',
|
|
69
71
|
generator: false,
|
|
70
72
|
async,
|
|
73
|
+
typeParameters: type_parameters,
|
|
71
74
|
metadata: { path: [] },
|
|
72
75
|
});
|
|
73
76
|
|
|
@@ -296,12 +299,16 @@ export function export_builder(
|
|
|
296
299
|
* @param {AST.Identifier} id
|
|
297
300
|
* @param {AST.Pattern[]} params
|
|
298
301
|
* @param {AST.BlockStatement} body
|
|
302
|
+
* @param {boolean} [async]
|
|
303
|
+
* @param {AST.TSTypeParameterDeclaration} [type_parameters]
|
|
304
|
+
* @param
|
|
299
305
|
* @returns {AST.FunctionDeclaration}
|
|
300
306
|
*/
|
|
301
|
-
export function function_declaration(id, params, body, async = false) {
|
|
307
|
+
export function function_declaration(id, params, body, async = false, type_parameters) {
|
|
302
308
|
return {
|
|
303
309
|
type: 'FunctionDeclaration',
|
|
304
310
|
id,
|
|
311
|
+
typeParameters: type_parameters,
|
|
305
312
|
params,
|
|
306
313
|
body,
|
|
307
314
|
generator: false,
|
|
@@ -370,11 +377,12 @@ export function init(name, value) {
|
|
|
370
377
|
|
|
371
378
|
/**
|
|
372
379
|
* @param {boolean | string | number | bigint | false | RegExp | null | undefined} value
|
|
380
|
+
* @param {string} [raw]
|
|
373
381
|
* @param {AST.NodeWithLocation} [loc_info]
|
|
374
382
|
* @returns {AST.Literal}
|
|
375
383
|
*/
|
|
376
|
-
export function literal(value, loc_info) {
|
|
377
|
-
const node = /** @type {AST.Literal} */ ({ type: 'Literal', value, metadata: { path: [] } });
|
|
384
|
+
export function literal(value, raw, loc_info) {
|
|
385
|
+
const node = /** @type {AST.Literal} */ ({ type: 'Literal', value, raw, metadata: { path: [] } });
|
|
378
386
|
|
|
379
387
|
return set_location(node, loc_info);
|
|
380
388
|
}
|
|
@@ -940,16 +948,18 @@ export function method(kind, key, params, body, computed = false, is_static = fa
|
|
|
940
948
|
* @param {AST.Pattern[]} params
|
|
941
949
|
* @param {AST.BlockStatement} body
|
|
942
950
|
* @param {boolean} async
|
|
951
|
+
* @param {AST.TSTypeParameterDeclaration} [type_parameters]
|
|
943
952
|
* @param {AST.NodeWithLocation} [loc_info]
|
|
944
953
|
* @returns {AST.FunctionExpression}
|
|
945
954
|
*/
|
|
946
|
-
function function_builder(id, params, body, async = false, loc_info) {
|
|
955
|
+
function function_builder(id, params, body, async = false, type_parameters, loc_info) {
|
|
947
956
|
/** @type {AST.FunctionExpression} */
|
|
948
957
|
const node = {
|
|
949
958
|
type: 'FunctionExpression',
|
|
950
959
|
id,
|
|
951
960
|
params,
|
|
952
961
|
body,
|
|
962
|
+
typeParameters: type_parameters,
|
|
953
963
|
generator: false,
|
|
954
964
|
async,
|
|
955
965
|
metadata: { path: [] },
|
|
@@ -990,7 +1000,7 @@ export function import_all(as, source, attributes = [], importKind = 'value') {
|
|
|
990
1000
|
}
|
|
991
1001
|
|
|
992
1002
|
/**
|
|
993
|
-
* @param {Array<[string, string, AST.ImportDeclaration['importKind']]>} parts
|
|
1003
|
+
* @param {Array<[string, string] | [string, string, AST.ImportDeclaration['importKind']]>} parts
|
|
994
1004
|
* @param {string} source
|
|
995
1005
|
* @param {Array<AST.ImportAttribute>} attributes
|
|
996
1006
|
* @param {AST.ImportDeclaration['importKind']} importKind
|
|
@@ -1001,13 +1011,41 @@ export function imports(parts, source, attributes = [], importKind = 'value') {
|
|
|
1001
1011
|
type: 'ImportDeclaration',
|
|
1002
1012
|
source: literal(source),
|
|
1003
1013
|
attributes,
|
|
1004
|
-
specifiers: parts.map((p) => (
|
|
1005
|
-
|
|
1006
|
-
|
|
1007
|
-
|
|
1008
|
-
|
|
1009
|
-
|
|
1010
|
-
|
|
1014
|
+
specifiers: parts.map((p) => import_specifier(p[0], p[1], p.length > 2 ? p[2] : 'value')),
|
|
1015
|
+
importKind,
|
|
1016
|
+
metadata: { path: [] },
|
|
1017
|
+
};
|
|
1018
|
+
}
|
|
1019
|
+
|
|
1020
|
+
/**
|
|
1021
|
+
* @param {string | AST.Identifier} imported
|
|
1022
|
+
* @param {string | AST.Identifier} [local]
|
|
1023
|
+
* @param {AST.ImportDeclaration['importKind']} [importKind]
|
|
1024
|
+
* @returns {AST.ImportSpecifier}
|
|
1025
|
+
*/
|
|
1026
|
+
export function import_specifier(imported, local = imported, importKind = 'value') {
|
|
1027
|
+
return {
|
|
1028
|
+
type: 'ImportSpecifier',
|
|
1029
|
+
imported: typeof imported === 'string' ? id(imported) : imported,
|
|
1030
|
+
local: typeof local === 'string' ? id(local) : local,
|
|
1031
|
+
importKind,
|
|
1032
|
+
metadata: { path: [] },
|
|
1033
|
+
};
|
|
1034
|
+
}
|
|
1035
|
+
|
|
1036
|
+
/**
|
|
1037
|
+
* @param {Array<AST.ImportSpecifier | AST.ImportDefaultSpecifier | AST.ImportNamespaceSpecifier>} specifiers
|
|
1038
|
+
* @param {string} source
|
|
1039
|
+
* @param {Array<AST.ImportAttribute>} [attributes]
|
|
1040
|
+
* @param {AST.ImportDeclaration['importKind']} [importKind]
|
|
1041
|
+
* @returns {AST.ImportDeclaration}
|
|
1042
|
+
*/
|
|
1043
|
+
export function import_declaration(specifiers, source, attributes = [], importKind = 'value') {
|
|
1044
|
+
return {
|
|
1045
|
+
type: 'ImportDeclaration',
|
|
1046
|
+
source: literal(source),
|
|
1047
|
+
specifiers,
|
|
1048
|
+
attributes,
|
|
1011
1049
|
importKind,
|
|
1012
1050
|
metadata: { path: [] },
|
|
1013
1051
|
};
|
package/src/utils/dom.js
ADDED
|
@@ -0,0 +1,158 @@
|
|
|
1
|
+
const VOID_ELEMENT_NAMES = [
|
|
2
|
+
'area',
|
|
3
|
+
'base',
|
|
4
|
+
'br',
|
|
5
|
+
'col',
|
|
6
|
+
'command',
|
|
7
|
+
'embed',
|
|
8
|
+
'hr',
|
|
9
|
+
'img',
|
|
10
|
+
'input',
|
|
11
|
+
'keygen',
|
|
12
|
+
'link',
|
|
13
|
+
'meta',
|
|
14
|
+
'param',
|
|
15
|
+
'source',
|
|
16
|
+
'track',
|
|
17
|
+
'wbr',
|
|
18
|
+
];
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* Returns true if name is a void element
|
|
22
|
+
* @param {string} name
|
|
23
|
+
* @returns {boolean}
|
|
24
|
+
*/
|
|
25
|
+
export function is_void_element(name) {
|
|
26
|
+
return VOID_ELEMENT_NAMES.includes(name) || name.toLowerCase() === '!doctype';
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
const RESERVED_WORDS = [
|
|
30
|
+
'arguments',
|
|
31
|
+
'await',
|
|
32
|
+
'break',
|
|
33
|
+
'case',
|
|
34
|
+
'catch',
|
|
35
|
+
'class',
|
|
36
|
+
'const',
|
|
37
|
+
'continue',
|
|
38
|
+
'debugger',
|
|
39
|
+
'default',
|
|
40
|
+
'delete',
|
|
41
|
+
'do',
|
|
42
|
+
'else',
|
|
43
|
+
'enum',
|
|
44
|
+
'eval',
|
|
45
|
+
'export',
|
|
46
|
+
'extends',
|
|
47
|
+
'false',
|
|
48
|
+
'finally',
|
|
49
|
+
'for',
|
|
50
|
+
'function',
|
|
51
|
+
'if',
|
|
52
|
+
'implements',
|
|
53
|
+
'import',
|
|
54
|
+
'in',
|
|
55
|
+
'instanceof',
|
|
56
|
+
'interface',
|
|
57
|
+
'let',
|
|
58
|
+
'new',
|
|
59
|
+
'null',
|
|
60
|
+
'package',
|
|
61
|
+
'private',
|
|
62
|
+
'protected',
|
|
63
|
+
'public',
|
|
64
|
+
'return',
|
|
65
|
+
'static',
|
|
66
|
+
'super',
|
|
67
|
+
'switch',
|
|
68
|
+
'this',
|
|
69
|
+
'throw',
|
|
70
|
+
'true',
|
|
71
|
+
'try',
|
|
72
|
+
'typeof',
|
|
73
|
+
'var',
|
|
74
|
+
'void',
|
|
75
|
+
'while',
|
|
76
|
+
'with',
|
|
77
|
+
'yield',
|
|
78
|
+
];
|
|
79
|
+
|
|
80
|
+
/**
|
|
81
|
+
* Returns true if word is a reserved JS keyword
|
|
82
|
+
* @param {string} word
|
|
83
|
+
* @returns {boolean}
|
|
84
|
+
*/
|
|
85
|
+
export function is_reserved(word) {
|
|
86
|
+
return RESERVED_WORDS.includes(word);
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
/**
|
|
90
|
+
* Attributes that are boolean, i.e. they are present or not present.
|
|
91
|
+
*/
|
|
92
|
+
const DOM_BOOLEAN_ATTRIBUTES = [
|
|
93
|
+
'allowfullscreen',
|
|
94
|
+
'async',
|
|
95
|
+
'autofocus',
|
|
96
|
+
'autoplay',
|
|
97
|
+
'checked',
|
|
98
|
+
'controls',
|
|
99
|
+
'default',
|
|
100
|
+
'disabled',
|
|
101
|
+
'formnovalidate',
|
|
102
|
+
'hidden',
|
|
103
|
+
'indeterminate',
|
|
104
|
+
'inert',
|
|
105
|
+
'ismap',
|
|
106
|
+
'loop',
|
|
107
|
+
'multiple',
|
|
108
|
+
'muted',
|
|
109
|
+
'nomodule',
|
|
110
|
+
'novalidate',
|
|
111
|
+
'open',
|
|
112
|
+
'playsinline',
|
|
113
|
+
'readonly',
|
|
114
|
+
'required',
|
|
115
|
+
'reversed',
|
|
116
|
+
'seamless',
|
|
117
|
+
'selected',
|
|
118
|
+
'webkitdirectory',
|
|
119
|
+
'defer',
|
|
120
|
+
'disablepictureinpicture',
|
|
121
|
+
'disableremoteplayback',
|
|
122
|
+
];
|
|
123
|
+
|
|
124
|
+
/**
|
|
125
|
+
* Returns true if name is a boolean DOM attribute
|
|
126
|
+
* @param {string} name
|
|
127
|
+
* @returns {boolean}
|
|
128
|
+
*/
|
|
129
|
+
export function is_boolean_attribute(name) {
|
|
130
|
+
return DOM_BOOLEAN_ATTRIBUTES.includes(name);
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
const DOM_PROPERTIES = [
|
|
134
|
+
...DOM_BOOLEAN_ATTRIBUTES,
|
|
135
|
+
'formNoValidate',
|
|
136
|
+
'isMap',
|
|
137
|
+
'noModule',
|
|
138
|
+
'playsInline',
|
|
139
|
+
'readOnly',
|
|
140
|
+
'value',
|
|
141
|
+
'volume',
|
|
142
|
+
'defaultValue',
|
|
143
|
+
'defaultChecked',
|
|
144
|
+
'srcObject',
|
|
145
|
+
'noValidate',
|
|
146
|
+
'allowFullscreen',
|
|
147
|
+
'disablePictureInPicture',
|
|
148
|
+
'disableRemotePlayback',
|
|
149
|
+
];
|
|
150
|
+
|
|
151
|
+
/**
|
|
152
|
+
* Returns true if name is a DOM property
|
|
153
|
+
* @param {string} name
|
|
154
|
+
* @returns {boolean}
|
|
155
|
+
*/
|
|
156
|
+
export function is_dom_property(name) {
|
|
157
|
+
return DOM_PROPERTIES.includes(name);
|
|
158
|
+
}
|