21
21
* @typedef {import('estree-jsx').ModuleDeclaration } EstreeModuleDeclaration
22
22
* @typedef {import('estree-jsx').Expression } EstreeExpression
23
23
* @typedef {import('estree-jsx').Property } EstreeProperty
24
+ * @typedef {import('estree-jsx').JSXIdentifier } JSXIdentifier
25
+ * @typedef {import('estree-jsx').JSXMemberExpression } JSXMemberExpression
24
26
*
25
27
* @typedef {EstreeJsxOpeningElement['name'] } EstreeJsxElementName
26
28
* @typedef {EstreeJsxAttribute['name'] } EstreeJsxAttributeName
@@ -69,8 +71,9 @@ import style from 'style-to-object'
69
71
import { position } from 'unist-util-position'
70
72
import { zwitch } from 'zwitch'
71
73
74
+ const toReact = /** @type {Record<string, string> } */ ( hastToReact )
75
+
72
76
const own = { } . hasOwnProperty
73
- const push = [ ] . push
74
77
75
78
/**
76
79
* @param {Node|MDXJsxAttributeValueExpression|MDXJsxAttribute|MDXJsxExpressionAttribute|MDXJsxFlowElement|MDXJsxTextElement|MDXFlowExpression|MDXTextExpression } tree
@@ -83,9 +86,12 @@ export function toEstree(tree, options = {}) {
83
86
schema : options . space === 'svg' ? svg : html ,
84
87
comments : [ ] ,
85
88
esm : [ ] ,
89
+ // @ts -expect-error: hush.
86
90
handle : zwitch ( 'type' , {
87
91
invalid,
92
+ // @ts -expect-error: hush.
88
93
unknown,
94
+ // @ts -expect-error: hush.
89
95
handlers : Object . assign (
90
96
{ } ,
91
97
{
@@ -117,7 +123,7 @@ export function toEstree(tree, options = {}) {
117
123
} )
118
124
}
119
125
120
- // @ts -ignore Types are wrong (`expression` *can* be JSX).
126
+ // @ts -expect-error Types are wrong (`expression` *can* be JSX).
121
127
body . push ( create ( tree , { type : 'ExpressionStatement' , expression : result } ) )
122
128
}
123
129
@@ -206,7 +212,7 @@ function element(node, context) {
206
212
}
207
213
208
214
prop = info . space
209
- ? hastToReact [ info . property ] || info . property
215
+ ? toReact [ info . property ] || info . property
210
216
: info . attribute
211
217
212
218
if ( Array . isArray ( value ) ) {
@@ -217,7 +223,7 @@ function element(node, context) {
217
223
218
224
if ( prop === 'style' ) {
219
225
/** @type {Object.<string, string> } */
220
- // @ts -ignore Assume `value` is then an object.
226
+ // @ts -expect-error Assume `value` is then an object.
221
227
const styleValue =
222
228
typeof value === 'string' ? parseStyle ( value , node . tagName ) : value
223
229
@@ -269,8 +275,8 @@ function element(node, context) {
269
275
shorthand : false ,
270
276
computed : false ,
271
277
key : { type : 'Literal' , value : String ( prop ) } ,
272
- // @ts -ignore No need to worry about `style` (which has a `JSXExpressionContainer`
273
- // value) because that’s a valid identifier.
278
+ // @ts -expect-error No need to worry about `style` (which has a
279
+ // `JSXExpressionContainer` value) because that’s a valid identifier.
274
280
value : attributeValue || { type : 'Literal' , value : true } ,
275
281
kind : 'init'
276
282
}
@@ -307,14 +313,14 @@ function element(node, context) {
307
313
*/
308
314
function mdxjsEsm ( node , context ) {
309
315
/** @type {EstreeProgram } */
310
- // @ts -ignore Assume program.
316
+ // @ts -expect-error Assume program.
311
317
const estree = node . data && node . data . estree
312
318
const comments = ( estree && estree . comments ) || [ ]
313
319
314
320
if ( estree ) {
315
- push . apply ( context . comments , comments )
321
+ context . comments . push ( ... comments )
316
322
attachComments ( estree , comments )
317
- push . apply ( context . esm , estree . body )
323
+ context . esm . push ( ... estree . body )
318
324
}
319
325
}
320
326
@@ -325,18 +331,19 @@ function mdxjsEsm(node, context) {
325
331
*/
326
332
function mdxExpression ( node , context ) {
327
333
/** @type {EstreeProgram } */
328
- // @ts -ignore Assume program.
334
+ // @ts -expect-error Assume program.
329
335
const estree = node . data && node . data . estree
330
- /** @type {EstreeExpression } */
336
+ /** @type {EstreeExpression|undefined } */
331
337
let expression
332
338
333
339
if ( estree ) {
334
- push . apply ( context . comments , estree . comments )
340
+ context . comments . push ( ... ( estree . comments || [ ] ) )
335
341
attachComments ( estree , estree . comments )
336
342
expression =
337
- estree . body [ 0 ] &&
338
- estree . body [ 0 ] . type === 'ExpressionStatement' &&
339
- estree . body [ 0 ] . expression
343
+ ( estree . body [ 0 ] &&
344
+ estree . body [ 0 ] . type === 'ExpressionStatement' &&
345
+ estree . body [ 0 ] . expression ) ||
346
+ undefined
340
347
}
341
348
342
349
return inherit ( node , {
@@ -384,18 +391,19 @@ function mdxJsxElement(node, context) {
384
391
// `MDXJsxAttributeValueExpression`.
385
392
else if ( typeof value === 'object' ) {
386
393
/** @type {EstreeProgram } */
387
- // @ts -ignore Assume program.
394
+ // @ts -expect-error Assume program.
388
395
const estree = value . data && value . data . estree
389
- /** @type {EstreeExpression } */
390
- let expression = null
396
+ /** @type {EstreeExpression|undefined } */
397
+ let expression
391
398
392
399
if ( estree ) {
393
- push . apply ( context . comments , estree . comments )
400
+ context . comments . push ( ... ( estree . comments || [ ] ) )
394
401
attachComments ( estree , estree . comments )
395
402
expression =
396
- estree . body [ 0 ] &&
397
- estree . body [ 0 ] . type === 'ExpressionStatement' &&
398
- estree . body [ 0 ] . expression
403
+ ( estree . body [ 0 ] &&
404
+ estree . body [ 0 ] . type === 'ExpressionStatement' &&
405
+ estree . body [ 0 ] . expression ) ||
406
+ undefined
399
407
}
400
408
401
409
attributeValue = inherit ( value , {
@@ -419,23 +427,24 @@ function mdxJsxElement(node, context) {
419
427
// MDXJsxExpressionAttribute.
420
428
else {
421
429
/** @type {EstreeProgram } */
422
- // @ts -ignore Assume program.
430
+ // @ts -expect-error Assume program.
423
431
const estree = attr . data && attr . data . estree
424
- /** @type {EstreeJsxSpreadAttribute['argument'] } */
425
- let argumentValue = null
432
+ /** @type {EstreeJsxSpreadAttribute['argument']|undefined } */
433
+ let argumentValue
426
434
427
435
if ( estree ) {
428
- push . apply ( context . comments , estree . comments )
436
+ context . comments . push ( ... ( estree . comments || [ ] ) )
429
437
attachComments ( estree , estree . comments )
430
438
argumentValue =
431
- estree . body [ 0 ] &&
432
- estree . body [ 0 ] . type === 'ExpressionStatement' &&
433
- estree . body [ 0 ] . expression &&
434
- estree . body [ 0 ] . expression . type === 'ObjectExpression' &&
435
- estree . body [ 0 ] . expression . properties &&
436
- estree . body [ 0 ] . expression . properties [ 0 ] &&
437
- estree . body [ 0 ] . expression . properties [ 0 ] . type === 'SpreadElement' &&
438
- estree . body [ 0 ] . expression . properties [ 0 ] . argument
439
+ ( estree . body [ 0 ] &&
440
+ estree . body [ 0 ] . type === 'ExpressionStatement' &&
441
+ estree . body [ 0 ] . expression &&
442
+ estree . body [ 0 ] . expression . type === 'ObjectExpression' &&
443
+ estree . body [ 0 ] . expression . properties &&
444
+ estree . body [ 0 ] . expression . properties [ 0 ] &&
445
+ estree . body [ 0 ] . expression . properties [ 0 ] . type === 'SpreadElement' &&
446
+ estree . body [ 0 ] . expression . properties [ 0 ] . argument ) ||
447
+ undefined
439
448
}
440
449
441
450
attributes . push (
@@ -486,7 +495,7 @@ function root(node, context) {
486
495
/** @type {Array.<EstreeJsxChild> } */
487
496
const cleanChildren = [ ]
488
497
let index = - 1
489
- /** @type {Array.<EstreeJsxChild> } */
498
+ /** @type {Array.<EstreeJsxChild>|undefined } */
490
499
let queue
491
500
492
501
// Remove surrounding whitespace nodes from the fragment.
@@ -498,11 +507,10 @@ function root(node, context) {
498
507
child . expression . type === 'Literal' &&
499
508
whitespace ( child . expression . value )
500
509
) {
501
- if ( queue ) {
502
- queue . push ( child )
503
- }
510
+ if ( queue ) queue . push ( child )
504
511
} else {
505
- cleanChildren . push ( ...( queue || [ ] ) , child )
512
+ if ( queue ) cleanChildren . push ( ...queue )
513
+ cleanChildren . push ( child )
506
514
queue = [ ]
507
515
}
508
516
}
@@ -517,7 +525,7 @@ function root(node, context) {
517
525
518
526
/**
519
527
* @param {Text } node
520
- * @returns {EstreeJsxExpressionContainer }
528
+ * @returns {EstreeJsxExpressionContainer|void }
521
529
*/
522
530
function text ( node ) {
523
531
const value = String ( node . value || '' )
@@ -564,7 +572,7 @@ function all(parent, context) {
564
572
*/
565
573
function inherit ( hast , esnode ) {
566
574
const left = hast . data
567
- /** @type {Object.<string, unknown> } */
575
+ /** @type {Object.<string, unknown>|undefined } */
568
576
let right
569
577
/** @type {string } */
570
578
let key
@@ -580,7 +588,7 @@ function inherit(hast, esnode) {
580
588
}
581
589
582
590
if ( right ) {
583
- // @ts -ignore `esast` extension.
591
+ // @ts -expect-error `esast` extension.
584
592
esnode . data = right
585
593
}
586
594
}
@@ -599,10 +607,14 @@ function inherit(hast, esnode) {
599
607
function create ( hast , esnode ) {
600
608
const p = position ( hast )
601
609
602
- if ( p . start . line ) {
603
- // @ts -ignore acorn-style.
610
+ if (
611
+ p . start . line &&
612
+ p . start . offset !== undefined &&
613
+ p . end . offset !== undefined
614
+ ) {
615
+ // @ts -expect-error acorn-style.
604
616
esnode . start = p . start . offset
605
- // @ts -ignore acorn-style.
617
+ // @ts -expect-error acorn-style.
606
618
esnode . end = p . end . offset
607
619
esnode . loc = {
608
620
start : { line : p . start . line , column : p . start . column - 1 } ,
@@ -628,31 +640,34 @@ const createJsxName =
628
640
* @returns {EstreeJsxElementName }
629
641
*/
630
642
function ( name , attribute ) {
631
- /** @type {EstreeJsxElementName } */
632
- let node
633
-
634
643
if ( ! attribute && name . includes ( '.' ) ) {
635
644
const parts = name . split ( '.' )
636
- node = { type : 'JSXIdentifier' , name : parts . shift ( ) }
637
- while ( parts . length > 0 ) {
645
+ let part = parts . shift ( )
646
+ /** @type {JSXIdentifier|JSXMemberExpression } */
647
+ // @ts -expect-error: hush, the first is always defined.
648
+ let node = { type : 'JSXIdentifier' , name : part }
649
+
650
+ while ( ( part = parts . shift ( ) ) ) {
638
651
node = {
639
652
type : 'JSXMemberExpression' ,
640
653
object : node ,
641
- property : { type : 'JSXIdentifier' , name : parts . shift ( ) }
654
+ property : { type : 'JSXIdentifier' , name : part }
642
655
}
643
656
}
644
- } else if ( name . includes ( ':' ) ) {
657
+
658
+ return node
659
+ }
660
+
661
+ if ( name . includes ( ':' ) ) {
645
662
const parts = name . split ( ':' )
646
- node = {
663
+ return {
647
664
type : 'JSXNamespacedName' ,
648
665
namespace : { type : 'JSXIdentifier' , name : parts [ 0 ] } ,
649
666
name : { type : 'JSXIdentifier' , name : parts [ 1 ] }
650
667
}
651
- } else {
652
- node = { type : 'JSXIdentifier' , name}
653
668
}
654
669
655
- return node
670
+ return { type : 'JSXIdentifier' , name }
656
671
}
657
672
)
658
673
0 commit comments