@@ -24,12 +24,8 @@ import {isInjectableComponent, isInjectableEstree} from './jsx-utils.js'
24
24
* @param {string } jsxImportSource
25
25
* The string to use for the JSX import source tag.
26
26
*/
27
- const jsPrefix = (
28
- tsCheck ,
29
- jsxImportSource
30
- ) => `${ tsCheck ? '// @ts-check\n' : '' } /* @jsxRuntime automatic
27
+ const jsPrefix = ( tsCheck , jsxImportSource ) => `/* @jsxRuntime automatic
31
28
@jsxImportSource ${ jsxImportSource } */
32
- import '${ jsxImportSource } /jsx-runtime'
33
29
`
34
30
35
31
/**
@@ -216,86 +212,6 @@ function getPropsName(node) {
216
212
return 'props'
217
213
}
218
214
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
-
299
215
/**
300
216
* Pad the generated offsets of a Volar code mapping.
301
217
*
@@ -327,6 +243,7 @@ function getEmbeddedCodes(
327
243
jsxImportSource
328
244
) {
329
245
let hasAwait = false
246
+ let hasImports = false
330
247
let esm = jsPrefix ( checkMdx , jsxImportSource )
331
248
let jsx = ''
332
249
let jsxVariables = ''
@@ -345,9 +262,9 @@ function getEmbeddedCodes(
345
262
const esmMapping = {
346
263
// The empty mapping makes sure there’s always a valid mapping to insert
347
264
// auto-imports.
348
- sourceOffsets : [ 0 ] ,
349
- generatedOffsets : [ esm . length ] ,
350
- lengths : [ 0 ] ,
265
+ sourceOffsets : [ ] ,
266
+ generatedOffsets : [ ] ,
267
+ lengths : [ ] ,
351
268
data : {
352
269
completion : true ,
353
270
format : true ,
@@ -493,6 +410,83 @@ function getEmbeddedCodes(
493
410
updateMarkdownFromOffsets ( startOffset , endOffset )
494
411
}
495
412
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
+
496
490
/**
497
491
* @param {Program } program
498
492
* @param {number } lastIndex
@@ -663,7 +657,7 @@ function getEmbeddedCodes(
663
657
664
658
case 'mdxjsEsm' : {
665
659
updateMarkdownFromNode ( node )
666
- esm = processExports ( mdx , node , esmMapping , esm )
660
+ processExports ( node )
667
661
break
668
662
}
669
663
@@ -808,6 +802,26 @@ function getEmbeddedCodes(
808
802
esm += '\n' + plugin . finalize ( ) + '\n'
809
803
}
810
804
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
+
811
825
updateMarkdownFromOffsets ( mdx . length , mdx . length )
812
826
esm += componentStart ( hasAwait , programScope )
813
827
0 commit comments