Repository: mdx-js/mdx-analyzer (js)

Issue:
vscode-mdx@1.8.14 mess with mdx file
### Initial checklist

- [x] I read the [support docs](https://mdxjs.com/community/support/)
- [x] I read the [contributing guide](https://mdxjs.com/community/contribute/)
- [x] I agree to follow the [code of conduct](https://github.com/mdx-js/.github/blob/main/code-of-conduct.md)
- [x] I searched [issues](https://github.com/search?q=user%3Amdx-js&type=issues) and [discussions](https://github.com/orgs/mdx-js/discussions) and couldn’t find anything (or linked relevant results below)

### Affected package

 vscode-mdx@1.8.14

### Steps to reproduce

1. install [vscode-mdx@1.8.14](https://github.com/mdx-js/mdx-analyzer/releases/tag/vscode-mdx%401.8.14)
2. using vscode modify .mdx file
3. using vscode the file.

my vscode settings
```
"[mdx]": {
    "files.trimTrailingWhitespace": false,
    "editor.rulers": [100],
    "editor.wordWrap": "wordWrapColumn",
    "editor.wordWrapColumn": 100
  },
  "mdx.validate.ignoreLinks": ["/help/**", "/other/**", "/releases/**", "/troubleshooting/**"],
  "mdx.server.enable": true,
```

### Actual behavior

I am using [vscode-mdx@1.8.14](https://github.com/mdx-js/mdx-analyzer/releases/tag/vscode-mdx%401.8.14) in vscode in an Astro project
today after vscode-mdx updated to version 1.8.14 on every save of the file it removes the top lines

```mdx
---
title: Download
---

import Download from '@components/Download.astro'
import { devBuild, releases } from '@utils/getDownloadsInfoSync.mjs'
```

reverting back to version 1.8.13 solved the issue

### Expected behavior

saving file in vscode should not remove content from the file 

### Runtime

node@23.11.0

### Package manager

pnpm@10.9.0

### Operating system

Windows 11

### Build and bundle tools

_No response_

Pull request:
Fix organizing imports
### Initial checklist

* [x] I read the support docs <!-- https://mdxjs.com/community/support/ -->
* [x] I read the contributing guide <!-- https://mdxjs.com/community/contribute/ -->
* [x] I agree to follow the code of conduct <!-- https://github.com/mdx-js/.github/blob/main/code-of-conduct.md -->
* [x] I searched issues and discussions and couldn’t find anything or linked relevant results below <!-- https://github.com/search?q=user%3Amdx-js&type=issues and https://github.com/orgs/mdx-js/discussions -->
* [x] I made sure the docs are up to date
* [x] I included tests (or that’s not needed)

### Description of changes

The organize imports command broke documents where imports are present. This was a regression caused by the logic to support auto imports.

Closes #502


<!--do not edit: pr-->


Patch:
diff --git a/.changeset/silly-loops-wait.md b/.changeset/silly-loops-wait.md
new file mode 100644
index 0000000..aa094ff
--- /dev/null
+++ b/.changeset/silly-loops-wait.md
@@ -0,0 +1,8 @@
+---
+'@mdx-js/language-service': patch
+'@mdx-js/language-server': patch
+'@mdx-js/typescript-plugin': patch
+'vscode-mdx': patch
+---
+
+Fix organizing imports
diff --git a/fixtures/node16/organize-imports.mdx b/fixtures/node16/organize-imports.mdx
new file mode 100644
index 0000000..1866972
--- /dev/null
+++ b/fixtures/node16/organize-imports.mdx
@@ -0,0 +1,16 @@
+---
+frontmatter: yaml
+---
+
+import { useState } from 'react'
+import { compile } from '@mdx-js/mdx'
+import { unified } from 'unified'
+import { createRoot } from 'react-dom/client'
+
+Paragraph text.
+
+export function whatever() {
+  compile;
+  useState;
+  createRoot;
+}
diff --git a/package.json b/package.json
index db6538f..fe0b412 100644
--- a/package.json
+++ b/package.json
@@ -56,6 +56,7 @@
       "complexity": "off",
       "max-lines": "off",
       "max-params": "off",
+      "no-labels": "off",
       "@typescript-eslint/consistent-type-definitions": "off",
       "@typescript-eslint/naming-convention": "off",
       "unicorn/prevent-abbreviations": "off"
diff --git a/packages/language-service/lib/virtual-code.js b/packages/language-service/lib/virtual-code.js
index 673fe8a..b8244a0 100644
--- a/packages/language-service/lib/virtual-code.js
+++ b/packages/language-service/lib/virtual-code.js
@@ -24,12 +24,8 @@ import {isInjectableComponent, isInjectableEstree} from './jsx-utils.js'
  * @param {string} jsxImportSource
  *   The string to use for the JSX import source tag.
  */
-const jsPrefix = (
-  tsCheck,
-  jsxImportSource
-) => `${tsCheck ? '// @ts-check\n' : ''}/* @jsxRuntime automatic
+const jsPrefix = (tsCheck, jsxImportSource) => `/* @jsxRuntime automatic
 @jsxImportSource ${jsxImportSource} */
-import '${jsxImportSource}/jsx-runtime'
 `
 
 /**
@@ -216,86 +212,6 @@ function getPropsName(node) {
   return 'props'
 }
 
-/**
- * Process exports of an MDX ESM node.
- *
- * @param {string} mdx
- *   The full MDX code to process.
- * @param {MdxjsEsm} node
- *   The MDX ESM node to process.
- * @param {CodeMapping} mapping
- *   The Volar mapping to add offsets to.
- * @param {string} esm
- *   The virtual ESM code up to the point this function was called.
- * @returns {string}
- *   The updated virtual ESM code.
- */
-function processExports(mdx, node, mapping, esm) {
-  const start = node.position?.start?.offset
-  const end = node.position?.end?.offset
-
-  if (start === undefined || end === undefined) {
-    return esm
-  }
-
-  const body = node.data?.estree?.body
-
-  if (!body?.length) {
-    return addOffset(mapping, mdx, esm, start, end, true)
-  }
-
-  for (const child of body) {
-    if (child.type === 'ExportDefaultDeclaration') {
-      const propsName = getPropsName(child)
-      if (propsName) {
-        esm += layoutJsDoc(propsName)
-      }
-
-      esm = addOffset(
-        mapping,
-        mdx,
-        esm + '\nconst MDXLayout = ',
-        child.declaration.start,
-        child.end,
-        true
-      )
-      continue
-    }
-
-    if (child.type === 'ExportNamedDeclaration' && child.source) {
-      const {specifiers} = child
-      for (let index = 0; index < specifiers.length; index++) {
-        const specifier = specifiers[index]
-        if (
-          specifier.local.type === 'Identifier'
-            ? specifier.local.name === 'default'
-            : specifier.local.value === 'default'
-        ) {
-          esm = addOffset(mapping, mdx, esm, start, specifier.start)
-          const nextPosition =
-            index === specifiers.length - 1
-              ? specifier.end
-              : mdx.indexOf(',', specifier.end) + 1
-          return (
-            addOffset(mapping, mdx, esm, nextPosition, end, true) +
-            '\nimport {' +
-            (specifier.exported.type === 'Identifier'
-              ? specifier.exported.name
-              : JSON.stringify(specifier.exported.value)) +
-            ' as MDXLayout} from ' +
-            JSON.stringify(child.source.value) +
-            '\n'
-          )
-        }
-      }
-    }
-
-    esm = addOffset(mapping, mdx, esm, child.start, child.end, true)
-  }
-
-  return esm + '\n'
-}
-
 /**
  * Pad the generated offsets of a Volar code mapping.
  *
@@ -327,6 +243,7 @@ function getEmbeddedCodes(
   jsxImportSource
 ) {
   let hasAwait = false
+  let hasImports = false
   let esm = jsPrefix(checkMdx, jsxImportSource)
   let jsx = ''
   let jsxVariables = ''
@@ -345,9 +262,9 @@ function getEmbeddedCodes(
   const esmMapping = {
     // The empty mapping makes sure there’s always a valid mapping to insert
     // auto-imports.
-    sourceOffsets: [0],
-    generatedOffsets: [esm.length],
-    lengths: [0],
+    sourceOffsets: [],
+    generatedOffsets: [],
+    lengths: [],
     data: {
       completion: true,
       format: true,
@@ -493,6 +410,83 @@ function getEmbeddedCodes(
     updateMarkdownFromOffsets(startOffset, endOffset)
   }
 
+  /**
+   * Process exports of an MDX ESM node.
+   *
+   * @param {MdxjsEsm} node
+   *   The MDX ESM node to process.
+   * @returns {undefined}
+   */
+  function processExports(node) {
+    const start = node.position?.start?.offset
+    const end = node.position?.end?.offset
+
+    if (start === undefined || end === undefined) {
+      return
+    }
+
+    const body = node.data?.estree?.body
+
+    if (!body?.length) {
+      esm = addOffset(esmMapping, mdx, esm, start, end, true)
+      return
+    }
+
+    bodyLoop: for (const child of body) {
+      if (child.type === 'ExportDefaultDeclaration') {
+        const propsName = getPropsName(child)
+        if (propsName) {
+          esm += layoutJsDoc(propsName)
+        }
+
+        esm = addOffset(
+          esmMapping,
+          mdx,
+          esm + '\nconst MDXLayout = ',
+          child.declaration.start,
+          child.end,
+          true
+        )
+        continue
+      }
+
+      if (child.type === 'ExportNamedDeclaration' && child.source) {
+        const {specifiers} = child
+        for (let index = 0; index < specifiers.length; index++) {
+          const specifier = specifiers[index]
+          if (
+            specifier.local.type === 'Identifier'
+              ? specifier.local.name === 'default'
+              : specifier.local.value === 'default'
+          ) {
+            esm = addOffset(esmMapping, mdx, esm, start, specifier.start)
+            const nextPosition =
+              index === specifiers.length - 1
+                ? specifier.end
+                : mdx.indexOf(',', specifier.end) + 1
+            esm =
+              addOffset(esmMapping, mdx, esm, nextPosition, end, true) +
+              '\nimport {' +
+              (specifier.exported.type === 'Identifier'
+                ? specifier.exported.name
+                : JSON.stringify(specifier.exported.value)) +
+              ' as MDXLayout} from ' +
+              JSON.stringify(child.source.value)
+            continue bodyLoop
+          }
+        }
+      }
+
+      if (child.type === 'ImportDeclaration') {
+        hasImports = true
+      }
+
+      esm = addOffset(esmMapping, mdx, esm, child.start, child.end, true)
+    }
+
+    esm += '\n'
+  }
+
   /**
    * @param {Program} program
    * @param {number} lastIndex
@@ -663,7 +657,7 @@ function getEmbeddedCodes(
 
         case 'mdxjsEsm': {
           updateMarkdownFromNode(node)
-          esm = processExports(mdx, node, esmMapping, esm)
+          processExports(node)
           break
         }
 
@@ -808,6 +802,26 @@ function getEmbeddedCodes(
     esm += '\n' + plugin.finalize() + '\n'
   }
 
+  let prefix = ''
+  if (checkMdx) {
+    prefix += '// @ts-check\n'
+  }
+
+  if (!hasImports) {
+    prefix += `import '${jsxImportSource}/jsx-runtime'\n`
+  }
+
+  if (prefix) {
+    padOffsets(esmMapping, prefix.length)
+    esm = prefix + esm
+  }
+
+  if (!hasImports) {
+    esmMapping.sourceOffsets.unshift(0)
+    esmMapping.generatedOffsets.unshift(prefix.length)
+    esmMapping.lengths.unshift(0)
+  }
+
   updateMarkdownFromOffsets(mdx.length, mdx.length)
   esm += componentStart(hasAwait, programScope)
 


Test patch:
diff --git a/packages/language-server/test/code-action.test.js b/packages/language-server/test/code-action.test.js
new file mode 100644
index 0000000..d1de439
--- /dev/null
+++ b/packages/language-server/test/code-action.test.js
@@ -0,0 +1,97 @@
+/**
+ * @import {LanguageServerHandle} from '@volar/test-utils'
+ */
+import assert from 'node:assert/strict'
+import {afterEach, beforeEach, test} from 'node:test'
+import {CodeAction, CodeActionTriggerKind} from '@volar/language-server'
+import {createServer, fixturePath, fixtureUri, tsdk} from './utils.js'
+
+/** @type {LanguageServerHandle} */
+let serverHandle
+
+beforeEach(async () => {
+  serverHandle = createServer()
+  await serverHandle.initialize(fixtureUri('node16'), {
+    typescript: {enabled: true, tsdk}
+  })
+})
+
+afterEach(() => {
+  serverHandle.connection.dispose()
+})
+
+test('organize imports', async () => {
+  const {uri} = await serverHandle.openTextDocument(
+    fixturePath('node16/organize-imports.mdx'),
+    'mdx'
+  )
+
+  const codeActions = await serverHandle.sendCodeActionsRequest(
+    uri,
+    {
+      start: {line: 6, character: 0},
+      end: {line: 6, character: 0}
+    },
+    {
+      diagnostics: [],
+      only: ['source.organizeImports'],
+      triggerKind: CodeActionTriggerKind.Invoked
+    }
+  )
+
+  assert.ok(codeActions)
+  const codeAction = codeActions
+    .filter((c) => CodeAction.is(c))
+    .find((c) => c.kind === 'source.organizeImports')
+  delete codeAction?.data
+
+  assert.deepEqual(codeAction, {
+    diagnostics: [],
+    edit: {
+      documentChanges: [
+        {
+          edits: [
+            {
+              newText:
+                "import { compile } from '@mdx-js/mdx';\n" +
+                "import { useState } from 'react';\n" +
+                "import { createRoot } from 'react-dom/client';\n" +
+                "import { unified } from 'unified';\n",
+              range: {
+                end: {character: 0, line: 5},
+                start: {character: 0, line: 4}
+              }
+            },
+            {
+              newText: '',
+              range: {
+                end: {character: 0, line: 6},
+                start: {character: 0, line: 5}
+              }
+            },
+            {
+              newText: '',
+              range: {
+                end: {character: 0, line: 7},
+                start: {character: 0, line: 6}
+              }
+            },
+            {
+              newText: '',
+              range: {
+                end: {character: 0, line: 8},
+                start: {character: 0, line: 7}
+              }
+            }
+          ],
+          textDocument: {
+            uri: fixtureUri('node16/organize-imports.mdx'),
+            version: null
+          }
+        }
+      ]
+    },
+    kind: 'source.organizeImports',
+    title: 'Organize Imports'
+  })
+})
diff --git a/packages/language-service/test/language-plugin.js b/packages/language-service/test/language-plugin.js
index 380ad8c..14a3d1a 100644
--- a/packages/language-service/test/language-plugin.js
+++ b/packages/language-service/test/language-plugin.js
@@ -46,7 +46,7 @@ test('create virtual code w/ mdxjsEsm', () => {
       mappings: [
         {
           sourceOffsets: [0],
-          generatedOffsets: [78],
+          generatedOffsets: [51],
           lengths: [35],
           data: {
             completion: true,
@@ -61,7 +61,6 @@ test('create virtual code w/ mdxjsEsm', () => {
       snapshot: snapshotFromLines(
         '/* @jsxRuntime automatic',
         '@jsxImportSource react */',
-        "import 'react/jsx-runtime'",
         'import {Planet} from "./Planet.js"',
         '',
         '',
@@ -165,7 +164,7 @@ test('create virtual code w/ mdxjsEsm and CRLF', () => {
       mappings: [
         {
           sourceOffsets: [0],
-          generatedOffsets: [78],
+          generatedOffsets: [51],
           lengths: [36],
           data: {
             completion: true,
@@ -180,7 +179,6 @@ test('create virtual code w/ mdxjsEsm and CRLF', () => {
       snapshot: snapshotFromLines(
         '/* @jsxRuntime automatic',
         '@jsxImportSource react */',
-        "import 'react/jsx-runtime'",
         'import {Planet} from "./Planet.js"\r',
         '',
         '',
@@ -283,9 +281,9 @@ test('create virtual code w/o MDX layout in case of named re-export', () => {
       languageId: 'javascriptreact',
       mappings: [
         {
-          sourceOffsets: [0],
-          generatedOffsets: [78],
-          lengths: [34],
+          sourceOffsets: [0, 0],
+          generatedOffsets: [27, 78],
+          lengths: [0, 34],
           data: {
             completion: true,
             format: true,
@@ -297,9 +295,9 @@ test('create virtual code w/o MDX layout in case of named re-export', () => {
         }
       ],
       snapshot: snapshotFromLines(
+        "import 'react/jsx-runtime'",
         '/* @jsxRuntime automatic',
         '@jsxImportSource react */',
-        "import 'react/jsx-runtime'",
         'export {named} from "./Layout.js"',
         '',
         '',
@@ -400,9 +398,9 @@ test('create virtual code w/ MDX layout in case of default re-export', () => {
       languageId: 'javascriptreact',
       mappings: [
         {
-          sourceOffsets: [0, 15],
-          generatedOffsets: [78, 86],
-          lengths: [8, 21],
+          sourceOffsets: [0, 0, 15],
+          generatedOffsets: [27, 78, 86],
+          lengths: [0, 8, 21],
           data: {
             completion: true,
             format: true,
@@ -414,9 +412,9 @@ test('create virtual code w/ MDX layout in case of default re-export', () => {
         }
       ],
       snapshot: snapshotFromLines(
+        "import 'react/jsx-runtime'",
         '/* @jsxRuntime automatic',
         '@jsxImportSource react */',
-        "import 'react/jsx-runtime'",
         'export {} from "./Layout.js"',
         '',
         'import {default as MDXLayout} from "./Layout.js"',
@@ -521,9 +519,9 @@ test('create virtual code w/ MDX layout in case of named and default re-export',
       languageId: 'javascriptreact',
       mappings: [
         {
-          sourceOffsets: [0, 22],
-          generatedOffsets: [78, 93],
-          lengths: [15, 21],
+          sourceOffsets: [0, 0, 22],
+          generatedOffsets: [27, 78, 93],
+          lengths: [0, 15, 21],
           data: {
             completion: true,
             format: true,
@@ -535,9 +533,9 @@ test('create virtual code w/ MDX layout in case of named and default re-export',
         }
       ],
       snapshot: snapshotFromLines(
+        "import 'react/jsx-runtime'",
         '/* @jsxRuntime automatic',
         '@jsxImportSource react */',
-        "import 'react/jsx-runtime'",
         'export {named, } from "./Layout.js"',
         '',
         'import {default as MDXLayout} from "./Layout.js"',
@@ -642,9 +640,9 @@ test('create virtual code w/ MDX layout in case of default and named re-export',
       languageId: 'javascriptreact',
       mappings: [
         {
-          sourceOffsets: [0, 16],
-          generatedOffsets: [78, 86],
-          lengths: [8, 27],
+          sourceOffsets: [0, 0, 16],
+          generatedOffsets: [27, 78, 86],
+          lengths: [0, 8, 27],
           data: {
             completion: true,
             format: true,
@@ -656,9 +654,9 @@ test('create virtual code w/ MDX layout in case of default and named re-export',
         }
       ],
       snapshot: snapshotFromLines(
+        "import 'react/jsx-runtime'",
         '/* @jsxRuntime automatic',
         '@jsxImportSource react */',
-        "import 'react/jsx-runtime'",
         'export { named} from "./Layout.js"',
         '',
         'import {default as MDXLayout} from "./Layout.js"',
@@ -761,7 +759,7 @@ test('create virtual code w/ MDX layout in case of a default exported arrow func
       mappings: [
         {
           sourceOffsets: [0, 15],
-          generatedOffsets: [78, 748],
+          generatedOffsets: [27, 748],
           lengths: [0, 9],
           data: {
             completion: true,
@@ -774,9 +772,9 @@ test('create virtual code w/ MDX layout in case of a default exported arrow func
         }
       ],
       snapshot: snapshotFromLines(
+        "import 'react/jsx-runtime'",
         '/* @jsxRuntime automatic',
         '@jsxImportSource react */',
-        "import 'react/jsx-runtime'",
         '',
         '/** @typedef {MDXContentProps & { children: JSX.Element }} MDXLayoutProps */',
         '',
@@ -895,7 +893,7 @@ test('create virtual code w/ MDX layout in case of a default exported function d
       mappings: [
         {
           sourceOffsets: [0, 15],
-          generatedOffsets: [78, 748],
+          generatedOffsets: [27, 748],
           lengths: [0, 24],
           data: {
             completion: true,
@@ -908,9 +906,9 @@ test('create virtual code w/ MDX layout in case of a default exported function d
         }
       ],
       snapshot: snapshotFromLines(
+        "import 'react/jsx-runtime'",
         '/* @jsxRuntime automatic',
         '@jsxImportSource react */',
-        "import 'react/jsx-runtime'",
         '',
         '/** @typedef {MDXContentProps & { children: JSX.Element }} MDXLayoutProps */',
         '',
@@ -1028,7 +1026,7 @@ test('create virtual code w/ MDX layout in case of a default exported constant',
       mappings: [
         {
           sourceOffsets: [0, 15],
-          generatedOffsets: [78, 97],
+          generatedOffsets: [27, 97],
           lengths: [0, 7],
           data: {
             completion: true,
@@ -1041,9 +1039,9 @@ test('create virtual code w/ MDX layout in case of a default exported constant',
         }
       ],
       snapshot: snapshotFromLines(
+        "import 'react/jsx-runtime'",
         '/* @jsxRuntime automatic',
         '@jsxImportSource react */',
-        "import 'react/jsx-runtime'",
         '',
         'const MDXLayout = "main"',
         '',
@@ -1149,7 +1147,7 @@ test('create virtual code w/ MDX layout and matching argument name', () => {
       mappings: [
         {
           sourceOffsets: [0, 15],
-          generatedOffsets: [78, 753],
+          generatedOffsets: [27, 753],
           lengths: [0, 34],
           data: {
             completion: true,
@@ -1162,9 +1160,9 @@ test('create virtual code w/ MDX layout and matching argument name', () => {
         }
       ],
       snapshot: snapshotFromLines(
+        "import 'react/jsx-runtime'",
         '/* @jsxRuntime automatic',
         '@jsxImportSource react */',
-        "import 'react/jsx-runtime'",
         '',
         '/** @typedef {MDXContentProps & { children: JSX.Element }} MDXLayoutProps */',
         '',
@@ -1286,7 +1284,7 @@ test('create virtual code w/ MDX layout in case of a default export followed by
       mappings: [
         {
           sourceOffsets: [0, 15],
-          generatedOffsets: [78, 748],
+          generatedOffsets: [27, 748],
           lengths: [0, 51],
           data: {
             completion: true,
@@ -1299,9 +1297,9 @@ test('create virtual code w/ MDX layout in case of a default export followed by
         }
       ],
       snapshot: snapshotFromLines(
+        "import 'react/jsx-runtime'",
         '/* @jsxRuntime automatic',
         '@jsxImportSource react */',
-        "import 'react/jsx-runtime'",
         '',
         '/** @typedef {MDXContentProps & { children: JSX.Element }} MDXLayoutProps */',
         '',
@@ -1425,9 +1423,9 @@ test('create virtual code w/ MDX layout in case of a default export preceded by
       languageId: 'javascriptreact',
       mappings: [
         {
-          sourceOffsets: [0, 42],
-          generatedOffsets: [78, 775],
-          lengths: [27, 24],
+          sourceOffsets: [0, 0, 42],
+          generatedOffsets: [27, 78, 775],
+          lengths: [0, 27, 24],
           data: {
             completion: true,
             format: true,
@@ -1439,9 +1437,9 @@ test('create virtual code w/ MDX layout in case of a default export preceded by
         }
       ],
       snapshot: snapshotFromLines(
+        "import 'react/jsx-runtime'",
         '/* @jsxRuntime automatic',
         '@jsxImportSource react */',
-        "import 'react/jsx-runtime'",
         'export function named() {}',
         '',
         '/** @typedef {MDXContentProps & { children: JSX.Element }} MDXLayoutProps */',
@@ -1562,7 +1560,7 @@ test('create virtual code w/ mdxFlowExpression', () => {
       mappings: [
         {
           sourceOffsets: [0],
-          generatedOffsets: [78],
+          generatedOffsets: [27],
           lengths: [0],
           data: {
             completion: true,
@@ -1588,9 +1586,9 @@ test('create virtual code w/ mdxFlowExpression', () => {
         }
       ],
       snapshot: snapshotFromLines(
+        "import 'react/jsx-runtime'",
         '/* @jsxRuntime automatic',
         '@jsxImportSource react */',
-        "import 'react/jsx-runtime'",
         '',
         '/**',
         ' * @internal',
@@ -1691,7 +1689,7 @@ test('create virtual code w/ empty mdxFlowExpression', () => {
       mappings: [
         {
           sourceOffsets: [0],
-          generatedOffsets: [78],
+          generatedOffsets: [27],
           lengths: [0],
           data: {
             completion: true,
@@ -1717,9 +1715,9 @@ test('create virtual code w/ empty mdxFlowExpression', () => {
         }
       ],
       snapshot: snapshotFromLines(
+        "import 'react/jsx-runtime'",
         '/* @jsxRuntime automatic',
         '@jsxImportSource react */',
-        "import 'react/jsx-runtime'",
         '',
         '',
         '/**',
@@ -1833,9 +1831,9 @@ test('create virtual code w/ prefixed JSX expressions for mdxFlowExpression', ()
       languageId: 'javascriptreact',
       mappings: [
         {
-          sourceOffsets: [0],
-          generatedOffsets: [78],
-          lengths: [27],
+          sourceOffsets: [0, 0],
+          generatedOffsets: [27, 78],
+          lengths: [0, 27],
           data: {
             completion: true,
             format: true,
@@ -1882,9 +1880,9 @@ test('create virtual code w/ prefixed JSX expressions for mdxFlowExpression', ()
         }
       ],
       snapshot: snapshotFromLines(
+        "import 'react/jsx-runtime'",
         '/* @jsxRuntime automatic',
         '@jsxImportSource react */',
-        "import 'react/jsx-runtime'",
         'export function Local() {}',
         '',
         '',
@@ -2030,9 +2028,9 @@ test('create virtual code w/ prefixed JSX expressions in attributes', () => {
       languageId: 'javascriptreact',
       mappings: [
         {
-          sourceOffsets: [0],
-          generatedOffsets: [78],
-          lengths: [27],
+          sourceOffsets: [0, 0],
+          generatedOffsets: [27, 78],
+          lengths: [0, 27],
           data: {
             completion: true,
             format: true,
@@ -2070,9 +2068,9 @@ test('create virtual code w/ prefixed JSX expressions in attributes', () => {
         }
       ],
       snapshot: snapshotFromLines(
+        "import 'react/jsx-runtime'",
         '/* @jsxRuntime automatic',
         '@jsxImportSource react */',
-        "import 'react/jsx-runtime'",
         'export function Local() {}',
         '',
         '',
@@ -2212,9 +2210,9 @@ test('create virtual code w/ mdxJsxFlowElement w/ children', () => {
       languageId: 'javascriptreact',
       mappings: [
         {
-          sourceOffsets: [0],
-          generatedOffsets: [78],
-          lengths: [27],
+          sourceOffsets: [0, 0],
+          generatedOffsets: [27, 78],
+          lengths: [0, 27],
           data: {
             completion: true,
             format: true,
@@ -2252,9 +2250,9 @@ test('create virtual code w/ mdxJsxFlowElement w/ children', () => {
         }
       ],
       snapshot: snapshotFromLines(
+        "import 'react/jsx-runtime'",
         '/* @jsxRuntime automatic',
         '@jsxImportSource react */',
-        "import 'react/jsx-runtime'",
         'export function Local() {}',
         '',
         '',
@@ -2394,7 +2392,7 @@ test('create virtual code w/ mdxJsxFlowElement w/ blockquote child', () => {
       mappings: [
         {
           sourceOffsets: [0],
-          generatedOffsets: [78],
+          generatedOffsets: [27],
           lengths: [0],
           data: {
             completion: true,
@@ -2420,9 +2418,9 @@ test('create virtual code w/ mdxJsxFlowElement w/ blockquote child', () => {
         }
       ],
       snapshot: snapshotFromLines(
+        "import 'react/jsx-runtime'",
         '/* @jsxRuntime automatic',
         '@jsxImportSource react */',
-        "import 'react/jsx-runtime'",
         '',
         '/**',
         ' * @internal',
@@ -2537,9 +2535,9 @@ test('create virtual code w/ mdxJsxFlowElement w/o children', () => {
       languageId: 'javascriptreact',
       mappings: [
         {
-          sourceOffsets: [0],
-          generatedOffsets: [78],
-          lengths: [27],
+          sourceOffsets: [0, 0],
+          generatedOffsets: [27, 78],
+          lengths: [0, 27],
           data: {
             completion: true,
             format: true,
@@ -2577,9 +2575,9 @@ test('create virtual code w/ mdxJsxFlowElement w/o children', () => {
         }
       ],
       snapshot: snapshotFromLines(
+        "import 'react/jsx-runtime'",
         '/* @jsxRuntime automatic',
         '@jsxImportSource react */',
-        "import 'react/jsx-runtime'",
         'export function Local() {}',
         '',
         '',
@@ -2694,9 +2692,9 @@ test('create virtual code w/ mdxJsxTextElement', () => {
       languageId: 'javascriptreact',
       mappings: [
         {
-          sourceOffsets: [0],
-          generatedOffsets: [78],
-          lengths: [27],
+          sourceOffsets: [0, 0],
+          generatedOffsets: [27, 78],
+          lengths: [0, 27],
           data: {
             completion: true,
             format: true,
@@ -2734,9 +2732,9 @@ test('create virtual code w/ mdxJsxTextElement', () => {
         }
       ],
       snapshot: snapshotFromLines(
+        "import 'react/jsx-runtime'",
         '/* @jsxRuntime automatic',
         '@jsxImportSource react */',
-        "import 'react/jsx-runtime'",
         'export function Local() {}',
         '',
         '',
@@ -2856,7 +2854,7 @@ test('create virtual code w/ mdxTextExpression', () => {
       languageId: 'javascriptreact',
       mappings: [
         {
-          generatedOffsets: [78],
+          generatedOffsets: [27],
           lengths: [0],
           sourceOffsets: [0],
           data: {
@@ -2883,9 +2881,9 @@ test('create virtual code w/ mdxTextExpression', () => {
         }
       ],
       snapshot: snapshotFromLines(
+        "import 'react/jsx-runtime'",
         '/* @jsxRuntime automatic',
         '@jsxImportSource react */',
-        "import 'react/jsx-runtime'",
         '',
         '/**',
         ' * @internal',
@@ -2992,7 +2990,7 @@ test('create virtual code w/ async mdxTextExpression', () => {
       languageId: 'javascriptreact',
       mappings: [
         {
-          generatedOffsets: [78],
+          generatedOffsets: [27],
           sourceOffsets: [0],
           lengths: [0],
           data: {
@@ -3019,9 +3017,9 @@ test('create virtual code w/ async mdxTextExpression', () => {
         }
       ],
       snapshot: snapshotFromLines(
+        "import 'react/jsx-runtime'",
         '/* @jsxRuntime automatic',
         '@jsxImportSource react */',
-        "import 'react/jsx-runtime'",
         '',
         '/**',
         ' * @internal',
@@ -3142,9 +3140,9 @@ test('ignore async functions in props or expressions', () => {
       languageId: 'javascriptreact',
       mappings: [
         {
-          generatedOffsets: [78, 144, 220],
-          sourceOffsets: [0, 66, 142],
-          lengths: [65, 75, 62],
+          generatedOffsets: [27, 78, 144, 220],
+          sourceOffsets: [0, 0, 66, 142],
+          lengths: [0, 65, 75, 62],
           data: {
             completion: true,
             format: true,
@@ -3169,9 +3167,9 @@ test('ignore async functions in props or expressions', () => {
         }
       ],
       snapshot: snapshotFromLines(
+        "import 'react/jsx-runtime'",
         '/* @jsxRuntime automatic',
         '@jsxImportSource react */',
-        "import 'react/jsx-runtime'",
         'export const arrow = async () => {',
         '  await Promise.resolve(42)',
         '}',
@@ -3312,7 +3310,7 @@ test('support locally scoped components', () => {
             structure: true,
             verification: true
           },
-          generatedOffsets: [78],
+          generatedOffsets: [27],
           lengths: [0],
           sourceOffsets: [0]
         },
@@ -3331,9 +3329,9 @@ test('support locally scoped components', () => {
         }
       ],
       snapshot: snapshotFromLines(
+        "import 'react/jsx-runtime'",
         '/* @jsxRuntime automatic',
         '@jsxImportSource react */',
-        "import 'react/jsx-runtime'",
         '',
         '/**',
         ' * @internal',
@@ -3447,15 +3445,15 @@ test('create virtual code w/ dedented markdown content', () => {
             structure: true,
             verification: true
           },
-          generatedOffsets: [78],
+          generatedOffsets: [27],
           lengths: [0],
           sourceOffsets: [0]
         }
       ],
       snapshot: snapshotFromLines(
+        "import 'react/jsx-runtime'",
         '/* @jsxRuntime automatic',
         '@jsxImportSource react */',
-        "import 'react/jsx-runtime'",
         '',
         '/**',
         ' * @internal',
@@ -3565,7 +3563,6 @@ test('create virtual code w/ syntax error', () => {
       snapshot: snapshotFromLines(
         '/* @jsxRuntime automatic',
         '@jsxImportSource react */',
-        "import 'react/jsx-runtime'",
         '',
         '/**',
         ' * @internal',
@@ -3658,15 +3655,15 @@ test('create virtual code w/ yaml frontmatter', () => {
             structure: true,
             verification: true
           },
-          generatedOffsets: [78],
+          generatedOffsets: [27],
           lengths: [0],
           sourceOffsets: [0]
         }
       ],
       snapshot: snapshotFromLines(
+        "import 'react/jsx-runtime'",
         '/* @jsxRuntime automatic',
         '@jsxImportSource react */',
-        "import 'react/jsx-runtime'",
         '',
         '/**',
         ' * @internal',
@@ -3802,15 +3799,15 @@ test('update virtual code', () => {
             structure: true,
             verification: true
           },
-          generatedOffsets: [78],
+          generatedOffsets: [27],
           lengths: [0],
           sourceOffsets: [0]
         }
       ],
       snapshot: snapshotFromLines(
+        "import 'react/jsx-runtime'",
         '/* @jsxRuntime automatic',
         '@jsxImportSource react */',
-        "import 'react/jsx-runtime'",
         '',
         '/**',
         ' * @internal',
@@ -3960,16 +3957,16 @@ test('support checkMdx', () => {
             structure: true,
             verification: true
           },
-          generatedOffsets: [91],
+          generatedOffsets: [40],
           lengths: [0],
           sourceOffsets: [0]
         }
       ],
       snapshot: snapshotFromLines(
         '// @ts-check',
+        "import 'react/jsx-runtime'",
         '/* @jsxRuntime automatic',
         '@jsxImportSource react */',
-        "import 'react/jsx-runtime'",
         '',
         '/**',
         ' * @internal',
@@ -4076,15 +4073,15 @@ test('support custom jsxImportSource', () => {
             structure: true,
             verification: true
           },
-          generatedOffsets: [80],
+          generatedOffsets: [28],
           lengths: [0],
           sourceOffsets: [0]
         }
       ],
       snapshot: snapshotFromLines(
+        "import 'preact/jsx-runtime'",
         '/* @jsxRuntime automatic',
         '@jsxImportSource preact */',
-        "import 'preact/jsx-runtime'",
         '',
         '/**',
         ' * @internal',
@@ -4195,15 +4192,15 @@ test('recma-export-filepath', () => {
             structure: true,
             verification: true
           },
-          generatedOffsets: [78],
+          generatedOffsets: [27],
           lengths: [0],
           sourceOffsets: [0]
         }
       ],
       snapshot: snapshotFromLines(
+        "import 'react/jsx-runtime'",
         '/* @jsxRuntime automatic',
         '@jsxImportSource react */',
-        "import 'react/jsx-runtime'",
         '',
         '/** Generated by [recma-export-filepath](https://github.com/remcohaszing/recma-export-filepath) */',
         "export const filepath = /** @type {string} */ ('')",
@@ -4317,15 +4314,15 @@ test('recma-export-filepath custom name', () => {
             structure: true,
             verification: true
           },
-          generatedOffsets: [78],
+          generatedOffsets: [27],
           lengths: [0],
           sourceOffsets: [0]
         }
       ],
       snapshot: snapshotFromLines(
+        "import 'react/jsx-runtime'",
         '/* @jsxRuntime automatic',
         '@jsxImportSource react */',
-        "import 'react/jsx-runtime'",
         '',
         '/** Generated by [recma-export-filepath](https://github.com/remcohaszing/recma-export-filepath) */',
         "export const custom = /** @type {string} */ ('')",
@@ -4439,15 +4436,15 @@ test('remark-mdx-frontmatter', () => {
             structure: true,
             verification: true
           },
-          generatedOffsets: [78],
+          generatedOffsets: [27],
           lengths: [0],
           sourceOffsets: [0]
         }
       ],
       snapshot: snapshotFromLines(
+        "import 'react/jsx-runtime'",
         '/* @jsxRuntime automatic',
         '@jsxImportSource react */',
-        "import 'react/jsx-runtime'",
         '',
         '/** Generated by [remark-mdx-frontmatter](https://github.com/remcohaszing/remark-mdx-frontmatter) */',
         'export const frontmatter = /** @type {undefined} */ (undefined)',
@@ -4561,15 +4558,15 @@ test('remark-mdx-frontmatter custom name', () => {
             structure: true,
             verification: true
           },
-          generatedOffsets: [78],
+          generatedOffsets: [27],
           lengths: [0],
           sourceOffsets: [0]
         }
       ],
       snapshot: snapshotFromLines(
+        "import 'react/jsx-runtime'",
         '/* @jsxRuntime automatic',
         '@jsxImportSource react */',
-        "import 'react/jsx-runtime'",
         '',
         '/** Generated by [remark-mdx-frontmatter](https://github.com/remcohaszing/remark-mdx-frontmatter) */',
         'export const custom = /** @type {undefined} */ (undefined)',
@@ -4683,15 +4680,15 @@ test('remark-mdx-frontmatter yaml', () => {
             structure: true,
             verification: true
           },
-          generatedOffsets: [78],
+          generatedOffsets: [27],
           lengths: [0],
           sourceOffsets: [0]
         }
       ],
       snapshot: snapshotFromLines(
+        "import 'react/jsx-runtime'",
         '/* @jsxRuntime automatic',
         '@jsxImportSource react */',
-        "import 'react/jsx-runtime'",
         '',
         '/** Generated by [remark-mdx-frontmatter](https://github.com/remcohaszing/remark-mdx-frontmatter) */',
         'export const frontmatter = /** @type {any} */ (undefined)',
@@ -4825,15 +4822,15 @@ test('remark-mdx-frontmatter toml', () => {
             structure: true,
             verification: true
           },
-          generatedOffsets: [78],
+          generatedOffsets: [27],
           lengths: [0],
           sourceOffsets: [0]
         }
       ],
       snapshot: snapshotFromLines(
+        "import 'react/jsx-runtime'",
         '/* @jsxRuntime automatic',
         '@jsxImportSource react */',
-        "import 'react/jsx-runtime'",
         '',
         '/** Generated by [remark-mdx-frontmatter](https://github.com/remcohaszing/remark-mdx-frontmatter) */',
         'export const frontmatter = /** @type {any} */ (undefined)',
@@ -4967,15 +4964,15 @@ test('rehype-mdx-title', () => {
             structure: true,
             verification: true
           },
-          generatedOffsets: [78],
+          generatedOffsets: [27],
           lengths: [0],
           sourceOffsets: [0]
         }
       ],
       snapshot: snapshotFromLines(
+        "import 'react/jsx-runtime'",
         '/* @jsxRuntime automatic',
         '@jsxImportSource react */',
-        "import 'react/jsx-runtime'",
         '',
         '/** Generated by [rehype-mdx-title](https://github.com/remcohaszing/rehype-mdx-title) */',
         "export const title = /** @type {string | undefined} */ ('')",
@@ -5089,15 +5086,15 @@ test('rehype-mdx-title custom name', () => {
             structure: true,
             verification: true
           },
-          generatedOffsets: [78],
+          generatedOffsets: [27],
           lengths: [0],
           sourceOffsets: [0]
         }
       ],
       snapshot: snapshotFromLines(
+        "import 'react/jsx-runtime'",
         '/* @jsxRuntime automatic',
         '@jsxImportSource react */',
-        "import 'react/jsx-runtime'",
         '',
         '/** Generated by [rehype-mdx-title](https://github.com/remcohaszing/rehype-mdx-title) */',
         "export const custom = /** @type {string | undefined} */ ('')",
@@ -5211,15 +5208,15 @@ test('rehype-mdx-title matching rank', () => {
             structure: true,
             verification: true
           },
-          generatedOffsets: [78],
+          generatedOffsets: [27],
           lengths: [0],
           sourceOffsets: [0]
         }
       ],
       snapshot: snapshotFromLines(
+        "import 'react/jsx-runtime'",
         '/* @jsxRuntime automatic',
         '@jsxImportSource react */',
-        "import 'react/jsx-runtime'",
         '',
         '/** Generated by [rehype-mdx-title](https://github.com/remcohaszing/rehype-mdx-title) */',
         "export const title = /** @type {string} */ ('')",