@@ -16,6 +16,7 @@ import type {
16
16
ObjectExpression ,
17
17
Program ,
18
18
SpreadElement ,
19
+ TemplateElement ,
19
20
} from 'estree'
20
21
import type { JSXClosingElement , JSXElement , JSXFragment } from 'estree-jsx'
21
22
import type { BlockContent , PhrasingContent } from 'mdast'
@@ -111,8 +112,9 @@ export const getRemarkProcessor = async (
111
112
112
113
if ( result ) {
113
114
/* istanbul ignore next */
114
- const { plugins = [ ] , settings } = ( result . config ||
115
- { } ) as Partial < RemarkConfig >
115
+ const { plugins = [ ] , settings } =
116
+ // type-coverage:ignore-next-line -- cosmiconfig's typings issue
117
+ ( result . config || { } ) as Partial < RemarkConfig >
116
118
117
119
// disable this rule automatically since we already have a parser option `extensions`
118
120
// only disable this plugin if there are at least one plugin enabled
@@ -292,44 +294,51 @@ runAsWorker(
292
294
293
295
processed . add ( node )
294
296
295
- const children =
296
- 'children' in node
297
+ function handleChildren ( node : BlockContent | PhrasingContent ) {
298
+ return 'children' in node
297
299
? ( node . children as Array < BlockContent | PhrasingContent > ) . reduce <
298
300
JSXElement [ 'children' ]
299
301
> ( ( acc , child ) => {
300
302
processed . add ( child )
301
303
302
- if ( ! child . data || 'estree' in child . data || ! child . data ) {
303
- return acc
304
- }
304
+ if ( child . data && 'estree' in child . data && child . data . estree ) {
305
+ const estree = child . data . estree as Program
305
306
306
- const estree = ( child . data . estree || {
307
- body : [ ] ,
308
- comments : [ ] ,
309
- } ) as Program
307
+ assert ( estree . body . length <= 1 )
310
308
311
- assert ( estree . body . length <= 1 )
309
+ const expStat = estree . body [ 0 ] as ExpressionStatement
312
310
313
- const expStat = estree . body [ 0 ] as
314
- | ExpressionStatement
315
- | undefined
311
+ if ( expStat ) {
312
+ const expression =
313
+ expStat . expression as BaseExpression as JSXElement [ 'children' ] [ number ]
314
+ acc . push ( expression )
315
+ }
316
316
317
- if ( expStat ) {
318
- const expression =
319
- expStat . expression as BaseExpression as JSXElement [ 'children' ] [ number ]
320
- acc . push ( expression )
317
+ comments . push ( ...estree . comments )
318
+ } else {
319
+ const expression = handleNode (
320
+ child ,
321
+ ) as JSXElement [ 'children' ] [ number ]
322
+ if ( expression ) {
323
+ acc . push ( expression )
324
+ }
321
325
}
322
326
323
- comments . push ( ...estree . comments )
324
-
325
327
return acc
326
328
} , [ ] )
327
329
: [ ]
330
+ }
331
+
332
+ function handleNode ( node : BlockContent | PhrasingContent ) {
333
+ if (
334
+ node . type !== 'mdxJsxTextElement' &&
335
+ node . type !== 'mdxJsxFlowElement'
336
+ ) {
337
+ return
338
+ }
339
+
340
+ const children = handleChildren ( node )
328
341
329
- if (
330
- node . type === 'mdxJsxTextElement' ||
331
- node . type === 'mdxJsxFlowElement'
332
- ) {
333
342
const nodePos = node . position
334
343
335
344
const nodeStart = nodePos . start . offset
@@ -546,15 +555,20 @@ runAsWorker(
546
555
expression = jsxFrg
547
556
}
548
557
558
+ return expression
559
+ }
560
+
561
+ const expression = handleNode ( node ) as Expression
562
+
563
+ if ( expression ) {
549
564
body . push ( {
550
- ...normalizePosition ( nodePos ) ,
565
+ ...normalizePosition ( node . position ) ,
551
566
type : 'ExpressionStatement' ,
552
- expression : expression as Expression ,
567
+ expression : handleNode ( node ) as Expression ,
553
568
} )
554
- return
555
569
}
556
570
557
- const estree = ( node . data . estree || {
571
+ const estree = ( node . data ? .estree || {
558
572
body : [ ] ,
559
573
comments : [ ] ,
560
574
} ) as Program
@@ -564,6 +578,46 @@ runAsWorker(
564
578
} )
565
579
}
566
580
581
+ const { visit : visitEstree } = await loadEsmModule <
582
+ typeof import ( 'estree-util-visit' )
583
+ > ( 'estree-util-visit' )
584
+
585
+ visitEstree (
586
+ {
587
+ type : 'Program' ,
588
+ sourceType : 'module' ,
589
+ body,
590
+ } ,
591
+ node => {
592
+ if ( node . type !== 'TemplateElement' ) {
593
+ return
594
+ }
595
+
596
+ /**
597
+ * Copied from @see https://github.com/eslint/espree/blob/main/lib/espree.js#L206-L220
598
+ */
599
+ const templateElement = node as TemplateElement
600
+
601
+ const startOffset = - 1
602
+ const endOffset = templateElement . tail ? 1 : 2
603
+
604
+ // @ts -expect-error - unavailable for typing from estree
605
+ templateElement . start += startOffset
606
+ // @ts -expect-error - unavailable for typing from estree
607
+ templateElement . end += endOffset
608
+
609
+ if ( templateElement . range ) {
610
+ templateElement . range [ 0 ] += startOffset
611
+ templateElement . range [ 1 ] += endOffset
612
+ }
613
+
614
+ if ( templateElement . loc ) {
615
+ templateElement . loc . start . column += startOffset
616
+ templateElement . loc . end . column += endOffset
617
+ }
618
+ } ,
619
+ )
620
+
567
621
for ( const token of restoreTokens ( text , root , sharedTokens , tt , visit ) ) {
568
622
tokenTranslator . onToken ( token , {
569
623
ecmaVersion : 'latest' ,
0 commit comments