@@ -24,12 +24,8 @@ import {isInjectableComponent, isInjectableEstree} from './jsx-utils.js'
2424 * @param {string } jsxImportSource
2525 * The string to use for the JSX import source tag.
2626 */
27- const jsPrefix = (
28- tsCheck ,
29- jsxImportSource
30- ) => `${ tsCheck ? '// @ts-check\n' : '' } /* @jsxRuntime automatic
27+ const jsPrefix = ( tsCheck , jsxImportSource ) => `/* @jsxRuntime automatic
3128@jsxImportSource ${ jsxImportSource } */
32- import '${ jsxImportSource } /jsx-runtime'
3329`
3430
3531/**
@@ -216,86 +212,6 @@ function getPropsName(node) {
216212 return 'props'
217213}
218214
219- /**
220- * Process exports of an MDX ESM node.
221- *
222- * @param {string } mdx
223- * The full MDX code to process.
224- * @param {MdxjsEsm } node
225- * The MDX ESM node to process.
226- * @param {CodeMapping } mapping
227- * The Volar mapping to add offsets to.
228- * @param {string } esm
229- * The virtual ESM code up to the point this function was called.
230- * @returns {string }
231- * The updated virtual ESM code.
232- */
233- function processExports ( mdx , node , mapping , esm ) {
234- const start = node . position ?. start ?. offset
235- const end = node . position ?. end ?. offset
236-
237- if ( start === undefined || end === undefined ) {
238- return esm
239- }
240-
241- const body = node . data ?. estree ?. body
242-
243- if ( ! body ?. length ) {
244- return addOffset ( mapping , mdx , esm , start , end , true )
245- }
246-
247- for ( const child of body ) {
248- if ( child . type === 'ExportDefaultDeclaration' ) {
249- const propsName = getPropsName ( child )
250- if ( propsName ) {
251- esm += layoutJsDoc ( propsName )
252- }
253-
254- esm = addOffset (
255- mapping ,
256- mdx ,
257- esm + '\nconst MDXLayout = ' ,
258- child . declaration . start ,
259- child . end ,
260- true
261- )
262- continue
263- }
264-
265- if ( child . type === 'ExportNamedDeclaration' && child . source ) {
266- const { specifiers} = child
267- for ( let index = 0 ; index < specifiers . length ; index ++ ) {
268- const specifier = specifiers [ index ]
269- if (
270- specifier . local . type === 'Identifier'
271- ? specifier . local . name === 'default'
272- : specifier . local . value === 'default'
273- ) {
274- esm = addOffset ( mapping , mdx , esm , start , specifier . start )
275- const nextPosition =
276- index === specifiers . length - 1
277- ? specifier . end
278- : mdx . indexOf ( ',' , specifier . end ) + 1
279- return (
280- addOffset ( mapping , mdx , esm , nextPosition , end , true ) +
281- '\nimport {' +
282- ( specifier . exported . type === 'Identifier'
283- ? specifier . exported . name
284- : JSON . stringify ( specifier . exported . value ) ) +
285- ' as MDXLayout} from ' +
286- JSON . stringify ( child . source . value ) +
287- '\n'
288- )
289- }
290- }
291- }
292-
293- esm = addOffset ( mapping , mdx , esm , child . start , child . end , true )
294- }
295-
296- return esm + '\n'
297- }
298-
299215/**
300216 * Pad the generated offsets of a Volar code mapping.
301217 *
@@ -327,6 +243,7 @@ function getEmbeddedCodes(
327243 jsxImportSource
328244) {
329245 let hasAwait = false
246+ let hasImports = false
330247 let esm = jsPrefix ( checkMdx , jsxImportSource )
331248 let jsx = ''
332249 let jsxVariables = ''
@@ -345,9 +262,9 @@ function getEmbeddedCodes(
345262 const esmMapping = {
346263 // The empty mapping makes sure there’s always a valid mapping to insert
347264 // auto-imports.
348- sourceOffsets : [ 0 ] ,
349- generatedOffsets : [ esm . length ] ,
350- lengths : [ 0 ] ,
265+ sourceOffsets : [ ] ,
266+ generatedOffsets : [ ] ,
267+ lengths : [ ] ,
351268 data : {
352269 completion : true ,
353270 format : true ,
@@ -493,6 +410,83 @@ function getEmbeddedCodes(
493410 updateMarkdownFromOffsets ( startOffset , endOffset )
494411 }
495412
413+ /**
414+ * Process exports of an MDX ESM node.
415+ *
416+ * @param {MdxjsEsm } node
417+ * The MDX ESM node to process.
418+ * @returns {undefined }
419+ */
420+ function processExports ( node ) {
421+ const start = node . position ?. start ?. offset
422+ const end = node . position ?. end ?. offset
423+
424+ if ( start === undefined || end === undefined ) {
425+ return
426+ }
427+
428+ const body = node . data ?. estree ?. body
429+
430+ if ( ! body ?. length ) {
431+ esm = addOffset ( esmMapping , mdx , esm , start , end , true )
432+ return
433+ }
434+
435+ bodyLoop: for ( const child of body ) {
436+ if ( child . type === 'ExportDefaultDeclaration' ) {
437+ const propsName = getPropsName ( child )
438+ if ( propsName ) {
439+ esm += layoutJsDoc ( propsName )
440+ }
441+
442+ esm = addOffset (
443+ esmMapping ,
444+ mdx ,
445+ esm + '\nconst MDXLayout = ' ,
446+ child . declaration . start ,
447+ child . end ,
448+ true
449+ )
450+ continue
451+ }
452+
453+ if ( child . type === 'ExportNamedDeclaration' && child . source ) {
454+ const { specifiers} = child
455+ for ( let index = 0 ; index < specifiers . length ; index ++ ) {
456+ const specifier = specifiers [ index ]
457+ if (
458+ specifier . local . type === 'Identifier'
459+ ? specifier . local . name === 'default'
460+ : specifier . local . value === 'default'
461+ ) {
462+ esm = addOffset ( esmMapping , mdx , esm , start , specifier . start )
463+ const nextPosition =
464+ index === specifiers . length - 1
465+ ? specifier . end
466+ : mdx . indexOf ( ',' , specifier . end ) + 1
467+ esm =
468+ addOffset ( esmMapping , mdx , esm , nextPosition , end , true ) +
469+ '\nimport {' +
470+ ( specifier . exported . type === 'Identifier'
471+ ? specifier . exported . name
472+ : JSON . stringify ( specifier . exported . value ) ) +
473+ ' as MDXLayout} from ' +
474+ JSON . stringify ( child . source . value )
475+ continue bodyLoop
476+ }
477+ }
478+ }
479+
480+ if ( child . type === 'ImportDeclaration' ) {
481+ hasImports = true
482+ }
483+
484+ esm = addOffset ( esmMapping , mdx , esm , child . start , child . end , true )
485+ }
486+
487+ esm += '\n'
488+ }
489+
496490 /**
497491 * @param {Program } program
498492 * @param {number } lastIndex
@@ -663,7 +657,7 @@ function getEmbeddedCodes(
663657
664658 case 'mdxjsEsm' : {
665659 updateMarkdownFromNode ( node )
666- esm = processExports ( mdx , node , esmMapping , esm )
660+ processExports ( node )
667661 break
668662 }
669663
@@ -808,6 +802,26 @@ function getEmbeddedCodes(
808802 esm += '\n' + plugin . finalize ( ) + '\n'
809803 }
810804
805+ let prefix = ''
806+ if ( checkMdx ) {
807+ prefix += '// @ts-check\n'
808+ }
809+
810+ if ( ! hasImports ) {
811+ prefix += `import '${ jsxImportSource } /jsx-runtime'\n`
812+ }
813+
814+ if ( prefix ) {
815+ padOffsets ( esmMapping , prefix . length )
816+ esm = prefix + esm
817+ }
818+
819+ if ( ! hasImports ) {
820+ esmMapping . sourceOffsets . unshift ( 0 )
821+ esmMapping . generatedOffsets . unshift ( prefix . length )
822+ esmMapping . lengths . unshift ( 0 )
823+ }
824+
811825 updateMarkdownFromOffsets ( mdx . length , mdx . length )
812826 esm += componentStart ( hasAwait , programScope )
813827
0 commit comments