@@ -16,6 +16,7 @@ import type {
1616 ObjectExpression ,
1717 Program ,
1818 SpreadElement ,
19+ TemplateElement ,
1920} from 'estree'
2021import type { JSXClosingElement , JSXElement , JSXFragment } from 'estree-jsx'
2122import type { BlockContent , PhrasingContent } from 'mdast'
@@ -111,8 +112,9 @@ export const getRemarkProcessor = async (
111112
112113 if ( result ) {
113114 /* 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 >
116118
117119 // disable this rule automatically since we already have a parser option `extensions`
118120 // only disable this plugin if there are at least one plugin enabled
@@ -292,44 +294,51 @@ runAsWorker(
292294
293295 processed . add ( node )
294296
295- const children =
296- 'children' in node
297+ function handleChildren ( node : BlockContent | PhrasingContent ) {
298+ return 'children' in node
297299 ? ( node . children as Array < BlockContent | PhrasingContent > ) . reduce <
298300 JSXElement [ 'children' ]
299301 > ( ( acc , child ) => {
300302 processed . add ( child )
301303
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
305306
306- const estree = ( child . data . estree || {
307- body : [ ] ,
308- comments : [ ] ,
309- } ) as Program
307+ assert ( estree . body . length <= 1 )
310308
311- assert ( estree . body . length <= 1 )
309+ const expStat = estree . body [ 0 ] as ExpressionStatement
312310
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+ }
316316
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+ }
321325 }
322326
323- comments . push ( ...estree . comments )
324-
325327 return acc
326328 } , [ ] )
327329 : [ ]
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 )
328341
329- if (
330- node . type === 'mdxJsxTextElement' ||
331- node . type === 'mdxJsxFlowElement'
332- ) {
333342 const nodePos = node . position
334343
335344 const nodeStart = nodePos . start . offset
@@ -546,15 +555,20 @@ runAsWorker(
546555 expression = jsxFrg
547556 }
548557
558+ return expression
559+ }
560+
561+ const expression = handleNode ( node ) as Expression
562+
563+ if ( expression ) {
549564 body . push ( {
550- ...normalizePosition ( nodePos ) ,
565+ ...normalizePosition ( node . position ) ,
551566 type : 'ExpressionStatement' ,
552- expression : expression as Expression ,
567+ expression : handleNode ( node ) as Expression ,
553568 } )
554- return
555569 }
556570
557- const estree = ( node . data . estree || {
571+ const estree = ( node . data ? .estree || {
558572 body : [ ] ,
559573 comments : [ ] ,
560574 } ) as Program
@@ -564,6 +578,46 @@ runAsWorker(
564578 } )
565579 }
566580
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+
567621 for ( const token of restoreTokens ( text , root , sharedTokens , tt , visit ) ) {
568622 tokenTranslator . onToken ( token , {
569623 ecmaVersion : 'latest' ,
0 commit comments