Skip to content

Commit 7a61aed

Browse files
authored
feat: use xdmEsBuild for all compiling (#45)
Co-authored-by: Gaël Haméon <[email protected]> BREAKING CHANGE: `xdmOptions` now only accepts a single argument of `options`.
1 parent 4664b61 commit 7a61aed

File tree

5 files changed

+84
-71
lines changed

5 files changed

+84
-71
lines changed

README.md

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -290,13 +290,13 @@ database. If your MDX doesn't reference other files (or only imports things from
290290

291291
#### xdmOptions
292292

293-
This allows you to modify the built-in xdm configuration (passed to
294-
xdm.compile). This can be helpful for specifying your own
293+
This allows you to modify the built-in xdm configuration (passed to the xdm
294+
esbuild plugin). This can be helpful for specifying your own
295295
remarkPlugins/rehypePlugins.
296296

297297
```ts
298298
bundleMDX(mdxString, {
299-
xdmOptions(input, options) {
299+
xdmOptions(options) {
300300
// this is the recommended way to add custom remark/rehype plugins:
301301
// The syntax might look weird, but it protects you in case we add/remove
302302
// plugins in the future.

package.json

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -43,22 +43,23 @@
4343
"@babel/runtime": "^7.14.0",
4444
"@esbuild-plugins/node-resolve": "^0.1.4",
4545
"@fal-works/esbuild-plugin-global-externals": "^2.1.1",
46-
"esbuild": "^0.11.16",
46+
"esbuild": "^0.11.20",
4747
"gray-matter": "^4.0.3",
4848
"jsdom": "^16.5.3",
4949
"remark-frontmatter": "^3.0.0",
5050
"remark-mdx-frontmatter": "^1.0.1",
5151
"uvu": "^0.5.1",
52-
"xdm": "^1.9.0"
52+
"xdm": "^1.11.0"
5353
},
5454
"devDependencies": {
5555
"@testing-library/react": "^11.2.6",
5656
"@types/jsdom": "^16.2.10",
57-
"@types/react": "^17.0.4",
57+
"@types/react": "^17.0.5",
5858
"@types/react-dom": "^17.0.3",
5959
"cross-env": "^7.0.3",
6060
"kcd-scripts": "^10.0.0",
6161
"left-pad": "^1.3.0",
62+
"mdx-test-data": "^1.0.1",
6263
"react": "^17.0.2",
6364
"react-dom": "^17.0.2",
6465
"remark-mdx-images": "^1.0.2",

src/__tests__/index.js

Lines changed: 26 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -149,7 +149,7 @@ import Demo from './demo'
149149
assert.equal(
150150
error.message,
151151
`Build failed with 1 error:
152-
__mdx_bundler_fake_dir__/_mdx_bundler_entry_point.mdx:2:17: error: Could not resolve "./demo"`,
152+
__mdx_bundler_fake_dir__/_mdx_bundler_entry_point.mdx:3:17: error: Could not resolve "./demo"`,
153153
)
154154
})
155155

@@ -189,7 +189,7 @@ import Demo from './demo.blah'
189189
assert.equal(
190190
error.message,
191191
`Build failed with 1 error:
192-
__mdx_bundler_fake_dir__/_mdx_bundler_entry_point.mdx:2:17: error: [plugin: JavaScript plugins] Invalid loader: "blah" (valid: js, jsx, ts, tsx, css, json, text, base64, dataurl, file, binary)`,
192+
__mdx_bundler_fake_dir__/_mdx_bundler_entry_point.mdx:3:17: error: [plugin: JavaScript plugins] Invalid loader: "blah" (valid: js, jsx, ts, tsx, css, json, text, base64, dataurl, file, binary)`,
193193
)
194194
})
195195

@@ -303,7 +303,7 @@ import {Sample} from './other/sample-component'
303303

304304
const {code} = await bundleMDX(mdxSource, {
305305
cwd: process.cwd(),
306-
xdmOptions: (vFile, options) => {
306+
xdmOptions: options => {
307307
options.remarkPlugins = [remarkMdxImages]
308308

309309
return options
@@ -341,7 +341,7 @@ test('should output assets', async () => {
341341

342342
const {code} = await bundleMDX(mdxSource, {
343343
cwd: process.cwd(),
344-
xdmOptions: (vFile, options) => {
344+
xdmOptions: options => {
345345
options.remarkPlugins = [remarkMdxImages]
346346

347347
return options
@@ -367,7 +367,7 @@ test('should output assets', async () => {
367367

368368
const error = /** @type Error */ (await bundleMDX(mdxSource, {
369369
cwd: process.cwd(),
370-
xdmOptions: (vFile, options) => {
370+
xdmOptions: options => {
371371
options.remarkPlugins = [remarkMdxImages]
372372

373373
return options
@@ -390,4 +390,25 @@ test('should output assets', async () => {
390390
)
391391
})
392392

393+
test('should support mdx from node_modules', async () => {
394+
const mdxSource = `
395+
import MdxData from 'mdx-test-data'
396+
397+
Local Content
398+
399+
<MdxData />
400+
`.trim()
401+
402+
const {code} = await bundleMDX(mdxSource, {})
403+
404+
const Component = getMDXComponent(code)
405+
406+
const {container} = render(React.createElement(Component))
407+
408+
assert.match(
409+
container.innerHTML,
410+
'Mdx file published as an npm package, for testing purposes.',
411+
)
412+
})
413+
393414
test.run()

src/index.js

Lines changed: 48 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ async function bundleMDX(
2121
mdxSource,
2222
{
2323
files = {},
24-
xdmOptions = (vfileCompatible, options) => options,
24+
xdmOptions = options => options,
2525
esbuildOptions = options => options,
2626
globals = {},
2727
cwd = path.join(process.cwd(), `__mdx_bundler_fake_dir__`),
@@ -35,8 +35,7 @@ async function bundleMDX(
3535

3636
// xdm is a native ESM, and we're running in a CJS context. This is the
3737
// only way to import ESM within CJS
38-
const [{compile: compileMDX}, {default: xdmESBuild}] = await Promise.all([
39-
await import('xdm'),
38+
const [{default: xdmESBuild}] = await Promise.all([
4039
await import('xdm/esbuild.js'),
4140
])
4241
// extract the frontmatter
@@ -56,18 +55,33 @@ async function bundleMDX(
5655
name: 'inMemory',
5756
setup(build) {
5857
build.onResolve({filter: /.*/}, ({path: filePath, importer}) => {
59-
if (filePath === entryPath)
60-
return {path: filePath, pluginData: {inMemory: true}}
58+
if (filePath === entryPath) {
59+
return {
60+
path: filePath,
61+
pluginData: {inMemory: true, contents: absoluteFiles[filePath]},
62+
}
63+
}
6164

6265
const modulePath = path.resolve(path.dirname(importer), filePath)
6366

64-
if (modulePath in absoluteFiles)
65-
return {path: modulePath, pluginData: {inMemory: true}}
67+
if (modulePath in absoluteFiles) {
68+
return {
69+
path: modulePath,
70+
pluginData: {inMemory: true, contents: absoluteFiles[modulePath]},
71+
}
72+
}
6673

6774
for (const ext of ['.js', '.ts', '.jsx', '.tsx', '.json', '.mdx']) {
6875
const fullModulePath = `${modulePath}${ext}`
69-
if (fullModulePath in absoluteFiles)
70-
return {path: fullModulePath, pluginData: {inMemory: true}}
76+
if (fullModulePath in absoluteFiles) {
77+
return {
78+
path: fullModulePath,
79+
pluginData: {
80+
inMemory: true,
81+
contents: absoluteFiles[fullModulePath],
82+
},
83+
}
84+
}
7185
}
7286

7387
// Return an empty object so that esbuild will handle resolving the file itself.
@@ -77,50 +91,30 @@ async function bundleMDX(
7791
build.onLoad({filter: /.*/}, async ({path: filePath, pluginData}) => {
7892
if (pluginData === undefined || !pluginData.inMemory) {
7993
// Return an empty object so that esbuild will load & parse the file contents itself.
80-
return {}
94+
return null
8195
}
8296

8397
// the || .js allows people to exclude a file extension
8498
const fileType = (path.extname(filePath) || '.jsx').slice(1)
8599
const contents = absoluteFiles[filePath]
86100

87-
switch (fileType) {
88-
case 'mdx': {
89-
/** @type import('xdm/lib/compile').VFileCompatible */
90-
const vFileCompatible = {
91-
path: filePath,
92-
contents,
93-
}
94-
const vfile = await compileMDX(
95-
vFileCompatible,
96-
xdmOptions(vFileCompatible, {
97-
jsx: true,
98-
remarkPlugins: [
99-
remarkFrontmatter,
100-
[remarkMdxFrontmatter, {name: 'frontmatter'}],
101-
],
102-
}),
103-
)
104-
return {contents: vfile.toString(), loader: 'jsx'}
105-
}
106-
default: {
107-
/** @type import('esbuild').Loader */
108-
let loader
109-
110-
if (
111-
build.initialOptions.loader &&
112-
build.initialOptions.loader[`.${fileType}`]
113-
) {
114-
loader = build.initialOptions.loader[`.${fileType}`]
115-
} else {
116-
loader = /** @type import('esbuild').Loader */ (fileType)
117-
}
101+
if (fileType === 'mdx') return null
118102

119-
return {
120-
contents,
121-
loader,
122-
}
123-
}
103+
/** @type import('esbuild').Loader */
104+
let loader
105+
106+
if (
107+
build.initialOptions.loader &&
108+
build.initialOptions.loader[`.${fileType}`]
109+
) {
110+
loader = build.initialOptions.loader[`.${fileType}`]
111+
} else {
112+
loader = /** @type import('esbuild').Loader */ (fileType)
113+
}
114+
115+
return {
116+
contents,
117+
loader,
124118
}
125119
})
126120
},
@@ -147,14 +141,14 @@ async function bundleMDX(
147141
// eslint-disable-next-line babel/new-cap
148142
NodeResolvePlugin({extensions: ['.js', '.ts', '.jsx', '.tsx']}),
149143
inMemoryPlugin,
150-
// NOTE: the only time the xdm esbuild plugin will be used
151-
// is if it's not processed by our inMemory plugin which will
152-
// only happen for mdx files imported from node_modules.
153-
// This is an edge case, but it's easy enough to support so we do.
154-
// If someone wants to customize *this* particular xdm compilation,
155-
// they'll need to use the esbuildOptions function to swap this
156-
// for their own configured version of this plugin.
157-
xdmESBuild(),
144+
xdmESBuild(
145+
xdmOptions({
146+
remarkPlugins: [
147+
remarkFrontmatter,
148+
[remarkMdxFrontmatter, {name: 'frontmatter'}],
149+
],
150+
}),
151+
),
158152
],
159153
bundle: true,
160154
format: 'iife',

src/types.d.ts

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66

77
import type {Plugin, BuildOptions, Loader} from 'esbuild'
88
import type {ModuleInfo} from '@fal-works/esbuild-plugin-global-externals'
9-
import type {VFileCompatible, CompileOptions} from 'xdm/lib/compile'
9+
import type {CoreProcessorOptions} from 'xdm/lib/compile'
1010

1111
type ESBuildOptions = BuildOptions
1212

@@ -45,7 +45,7 @@ type BundleMDXOptions = {
4545
* @example
4646
* ```
4747
* bundleMDX(mdxString, {
48-
* xdmOptions(input, options) {
48+
* xdmOptions(options) {
4949
* // this is the recommended way to add custom remark/rehype plugins:
5050
* // The syntax might look weird, but it protects you in case we add/remove
5151
* // plugins in the future.
@@ -57,10 +57,7 @@ type BundleMDXOptions = {
5757
* })
5858
* ```
5959
*/
60-
xdmOptions?: (
61-
vfileCompatible: VFileCompatible,
62-
options: CompileOptions,
63-
) => CompileOptions
60+
xdmOptions?: (options: CoreProcessorOptions) => CoreProcessorOptions
6461
/**
6562
* This allows you to modify the built-in esbuild configuration. This can be
6663
* especially helpful for specifying the compilation target.

0 commit comments

Comments
 (0)