{"_id":"@eduardo-exists/mdx-bundler","_rev":"3-311305c8cf77c0018e1544c798d1fe8d","name":"@eduardo-exists/mdx-bundler","dist-tags":{"latest":"1.0.0"},"versions":{"0.0.0-semantically-released":{"name":"@eduardo-exists/mdx-bundler","version":"0.0.0-semantically-released","description":"Compile and bundle your MDX files and their dependencies. FAST.","main":"dist/index.js","types":"dist/index.d.ts","type":"module","keywords":["mdx","bundler","mdx-bundler","esbuild","xdm"],"author":{"name":"Kent C. Dodds","email":"me@kentcdodds.com","url":"https://kentcdodds.com"},"license":"MIT","engines":{"node":">=12","npm":">=6"},"repository":{"type":"git","url":"git+https://github.com/eduardo-exists/mdx-bundler.git"},"bugs":{"url":"https://github.com/kentcdodds/mdx-bundler/issues"},"homepage":"https://github.com/kentcdodds/mdx-bundler#readme","scripts":{"build":"kcd-scripts build","postbuild":"node ./other/cjs-ify.js","lint":"kcd-scripts lint","setup":"npm install && npm run validate -s","test":"c8 -r text -r lcov uvu -i setup-tests.js src/__tests__","typecheck":"kcd-scripts typecheck","validate":"kcd-scripts validate"},"dependencies":{"@babel/runtime":"^7.15.4","@eduardo-exists/xdm":"^3.2.2","@esbuild-plugins/node-resolve":"^0.1.4","@fal-works/esbuild-plugin-global-externals":"^2.1.2","gray-matter":"^4.0.3","remark-frontmatter":"^4.0.1","remark-mdx-frontmatter":"^1.0.1","uuid":"^8.3.2"},"peerDependencies":{"esbuild":"0.11.x || 0.12.x || 0.13.x"},"devDependencies":{"@testing-library/react":"^12.1.2","@types/jsdom":"^16.2.13","@types/mdx":"^2.0.1","@types/react":"^17.0.34","@types/react-dom":"^17.0.11","@types/uuid":"^8.3.1","c8":"^7.10.0","cross-env":"^7.0.3","esbuild":"^0.13.12","jsdom":"^18.0.1","kcd-scripts":"^11.2.2","left-pad":"^1.3.0","mdx-test-data":"^1.0.1","react":"^17.0.2","react-dom":"^17.0.2","remark-mdx-images":"^1.0.3","typescript":"^4.4.3","uvu":"^0.5.2"},"eslintConfig":{"extends":"./node_modules/kcd-scripts/eslint.js","rules":{"import/extensions":"off","@typescript-eslint/no-unsafe-assignment":"off","max-lines-per-function":"off"}},"eslintIgnore":["node_modules","coverage","dist","*.d.ts"],"gitHead":"aedd58629ebad35d39bf5f37ab11a4aba2b763e8","_id":"@eduardo-exists/mdx-bundler@0.0.0-semantically-released","_nodeVersion":"14.17.5","_npmVersion":"7.21.0","dist":{"integrity":"sha512-f3JgX5w2jirpiRUuocr86dRG1+HYwn4LR3gV0ocN+NcVsgnuttAWSdwnzYENG/gdqkpzr+uIZW3SHGdgksQ2UQ==","shasum":"4387640bb80b720b40a2d926c237db8574b8142d","tarball":"https://registry.npmjs.org/@eduardo-exists/mdx-bundler/-/mdx-bundler-0.0.0-semantically-released.tgz","fileCount":6,"unpackedSize":32216,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQDqCoVgvtlfMZbRIuk8po7xySRseIstdQ5df7zWZYfDyAIhAKVmEUxLSsBseiKQalB6FkBSPgfcCPfpDisF8BwG/OLu"}]},"_npmUser":{"name":"eduardo-exists","email":"me@eduardo.wtf"},"directories":{},"maintainers":[{"name":"eduardo-exists","email":"me@eduardo.wtf"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/mdx-bundler_0.0.0-semantically-released_1636638619580_0.2997325579918284"},"_hasShrinkwrap":false},"1.0.0":{"name":"@eduardo-exists/mdx-bundler","version":"1.0.0","description":"Compile and bundle your MDX files and their dependencies. FAST.","main":"dist/index.js","types":"dist/index.d.ts","type":"module","keywords":["mdx","bundler","mdx-bundler","esbuild","xdm"],"author":{"name":"Kent C. Dodds","email":"me@kentcdodds.com","url":"https://kentcdodds.com"},"license":"MIT","engines":{"node":">=12","npm":">=6"},"repository":{"type":"git","url":"git+https://github.com/eduardo-exists/mdx-bundler.git"},"bugs":{"url":"https://github.com/kentcdodds/mdx-bundler/issues"},"homepage":"https://github.com/kentcdodds/mdx-bundler#readme","scripts":{"prepack":"npm run build","build":"kcd-scripts build","postbuild":"node ./other/cjs-ify.js","lint":"kcd-scripts lint","setup":"npm install && npm run validate -s","test":"c8 -r text -r lcov uvu -i setup-tests.js src/__tests__","typecheck":"kcd-scripts typecheck","validate":"kcd-scripts validate"},"dependencies":{"@babel/runtime":"^7.15.4","@eduardo-exists/xdm":"^3.2.2","@esbuild-plugins/node-resolve":"^0.1.4","@fal-works/esbuild-plugin-global-externals":"^2.1.2","gray-matter":"^4.0.3","remark-frontmatter":"^4.0.1","remark-mdx-frontmatter":"^1.0.1","uuid":"^8.3.2"},"peerDependencies":{"esbuild":"0.11.x || 0.12.x || 0.13.x"},"devDependencies":{"@testing-library/react":"^12.1.2","@types/jsdom":"^16.2.13","@types/mdx":"^2.0.1","@types/react":"^17.0.34","@types/react-dom":"^17.0.11","@types/uuid":"^8.3.1","c8":"^7.10.0","cross-env":"^7.0.3","esbuild":"^0.13.12","jsdom":"^18.0.1","kcd-scripts":"^11.2.2","left-pad":"^1.3.0","mdx-test-data":"^1.0.1","react":"^17.0.2","react-dom":"^17.0.2","remark-mdx-images":"^1.0.3","typescript":"^4.4.3","uvu":"^0.5.2"},"eslintConfig":{"extends":"./node_modules/kcd-scripts/eslint.js","rules":{"import/extensions":"off","@typescript-eslint/no-unsafe-assignment":"off","max-lines-per-function":"off"}},"eslintIgnore":["node_modules","coverage","dist","*.d.ts"],"gitHead":"aedd58629ebad35d39bf5f37ab11a4aba2b763e8","_id":"@eduardo-exists/mdx-bundler@1.0.0","_nodeVersion":"14.17.5","_npmVersion":"7.21.0","dist":{"integrity":"sha512-4SyPxCDu99pdhzIFRVKFjZDoVYBKqvtWiQAkRctub3JZLO+elUNgIAjEt+eO8ueLO5PD+Wj9CoEFMx5aQKGPvw==","shasum":"13942e71a84b78243cfc9b459745b05b396cb98e","tarball":"https://registry.npmjs.org/@eduardo-exists/mdx-bundler/-/mdx-bundler-1.0.0.tgz","fileCount":14,"unpackedSize":50985,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJh2FaSCRA9TVsSAnZWagAArDYP/RrOwRjjX5e+nosTnk2M\nJNQZa2/8Qww0Qm1GtCzdm6e8tUjUawnZ1HH+Z6Yysx2Cy2lSEii0Jo9RGDj3\nl+MUTpSVkLanRfPKkRcapLYJs7jC4bAipoT+6bFBdbArCxiDGieEpUI98r+g\nzpin9Lm31RyzKl+7aBckd4mvG3ykhLDv/cTWFigXiidj2vi5V+b7NfALA7va\nZBXu6kSY2t6mcfmmsRtmIDuJ6lCVyJ3fUYQciQkWohOGZK375q4YHPbdO55H\nsWs/eQKgbnLH+EEmX7rmyjgmV80/kAu2bJwX2IhTBNNVGlmUMFKAc3mIzred\nvuuceDZ5CwXOHfs1V5jyVruptv8n/xG0mr6ddjxB7X54bWB70ZsBYgU12NDg\nw+I6prsukCQVTewoNN3wDFSH7I0NDCnERoZb1WRQR1E7GBrh2I11U5PMbUN1\nkTHqYvP0ztFPQqO0vPPvJYOCPSr3b/XVbHVOVKYHwjZrNMw6wV11lMdj2u66\nh78oaDCUZRmXJ8ax4PV72s9Mo1cc2KQHaoJJN2J7w4PGEZhirEl0diPzWvdE\n7qO+JvvUPP3gGN7ROmUFKNR1h7qEIC8reMMlX0bg+TVPfInPGcdit1fmqnPx\nMYsxUkWef1o11tIsnMghBXeaMq5T+Cu+N/CLaokvwgQpj/2XtK3hkuzE81Ig\nLImx\r\n=gsdb\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQDJnOZjoMTGKlEOrxnL7viWUyEkIJJPTzfaxpj6xZlDRgIhAMAORz0KV3RhlP22T7HxW2GVC/kpcklm7DuMe8dhaiD2"}]},"_npmUser":{"name":"eduardo-exists","email":"me@eduardo.wtf"},"directories":{},"maintainers":[{"name":"eduardo-exists","email":"me@eduardo.wtf"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/mdx-bundler_1.0.0_1636639017031_0.5507380096416354"},"_hasShrinkwrap":false}},"time":{"created":"2021-11-11T13:50:19.524Z","0.0.0-semantically-released":"2021-11-11T13:50:19.720Z","modified":"2022-04-05T06:43:47.016Z","1.0.0":"2021-11-11T13:56:57.165Z"},"maintainers":[{"name":"eduardo-exists","email":"me@eduardo.wtf"}],"description":"Compile and bundle your MDX files and their dependencies. FAST.","homepage":"https://github.com/kentcdodds/mdx-bundler#readme","keywords":["mdx","bundler","mdx-bundler","esbuild","xdm"],"repository":{"type":"git","url":"git+https://github.com/eduardo-exists/mdx-bundler.git"},"author":{"name":"Kent C. Dodds","email":"me@kentcdodds.com","url":"https://kentcdodds.com"},"bugs":{"url":"https://github.com/kentcdodds/mdx-bundler/issues"},"license":"MIT","readme":"<div align=\"center\">\n<h1>mdx-bundler 🦤</h1>\n\n<p>Compile and bundle your MDX files and their dependencies. FAST.</p>\n</div>\n\n---\n\n<!-- prettier-ignore-start -->\n[![Build Status][build-badge]][build]\n[![Code Coverage][coverage-badge]][coverage]\n[![version][version-badge]][package]\n[![downloads][downloads-badge]][npmtrends]\n[![MIT License][license-badge]][license]\n[![All Contributors][all-contributors-badge]](#contributors-)\n[![PRs Welcome][prs-badge]][prs]\n[![Code of Conduct][coc-badge]][coc]\n<!-- prettier-ignore-end -->\n\n## The problem\n\nYou have a string of MDX and various TS/JS files that it uses and you want to\nget a bundled version of these files to eval in the browser.\n\n## This solution\n\nThis is an async function that will compile and bundle your MDX files and their\ndependencies. It uses [esbuild](https://esbuild.github.io/), so it's VERY fast\nand supports TypeScript files (for the dependencies of your MDX files). It also\nuses [xdm](https://github.com/wooorm/xdm) which is a more modern and powerful\nMDX compiler with fewer bugs and more features (and no extra runtime\nrequirements).\n\nYour source files could be local, in a remote github repo, in a CMS, or wherever\nelse and it doesn't matter. All `mdx-bundler` cares about is that you pass it\nall the files and source code necessary and it will take care of bundling\neverything for you.\n\n### FAQ:\n\n<details>\n  <summary>\n    <strong>\n      \"What's so cool about MDX?\"\n    </strong>\n  </summary>\n\n[MDX](https://mdxjs.com/) enables you to combine terse markdown syntax for your\ncontent with the power of React components. For content-heavy sites, writing the\ncontent with straight-up HTML can be annoyingly verbose. Often people solve this\nusing a WSYWIG editor, but too often those fall short in mapping the writer's\nintent to HTML. Many people prefer using markdown to express their content\nsource and have that parsed into HTML to be rendered.\n\nThe problem with using Markdown for your content is if you want to have some\ninteractivity embedded into your content, you're pretty limited. You either need\nto insert an element that JavaScript targets (which is annoyingly indirect), or\nyou can use an `iframe` or something.\n\nAs previously stated, [MDX](https://mdxjs.com/) enables you to combine terse\nmarkdown syntax for your content with the power of React components. So you can\nimport a React component and render it within the markdown itself. It's the best\nof both worlds.\n\n</details>\n\n<details>\n  <summary>\n    <strong>\n      \"How is this different from <a href=\"https://github.com/hashicorp/next-mdx-remote\"><code>next-mdx-remote</code></a>?\"\n    </strong>\n  </summary>\n\n`mdx-bundler` actually bundles dependencies of your MDX files. For example, this\nwon't work with `next-mdx-remote`, but it will with `mdx-bundler`:\n\n```md\n---\ntitle: Example Post\npublished: 2021-02-13\ndescription: This is some description\n---\n\n# Wahoo\n\nimport Demo from './demo'\n\nHere's a **neat** demo:\n\n<Demo />\n```\n\n`next-mdx-remote` chokes on that import because it's not a bundler, it's just a\ncompiler. `mdx-bundler` is an MDX compiler and bundler. That's the difference.\n\n</details>\n\n<details>\n  <summary>\n    <strong>\n      \"How is this different from the mdx plugins for webpack or rollup?\"\n    </strong>\n  </summary>\n\nThose tools are intended to be run \"at build time\" and then you deploy the built\nversion of your files. This means if you have some content in MDX and want to\nmake a typo change, you have to rebuild and redeploy the whole site. This also\nmeans that every MDX page you add to your site will increase your build-times,\nso it doesn't scale all that well.\n\n`mdx-bundler` can definitely be used at build-time, but it's more powerfully\nused as a runtime bundler. A common use case is to have a route for your MDX\ncontent and when that request comes in, you load the MDX content and hand that\noff to `mdx-bundler` for bundling. This means that `mdx-bundler` is infinitely\nscalable. Your build won't be any longer regardless of how much MDX content you\nhave. Also, `mdx-bundler` is quite fast, but to make this on-demand bundling\neven faster, you can use appropriate cache headers to avoid unnecessary\nre-bundling.\n\nWebpack/rollup/etc also require that all your MDX files are on the local\nfilesystem to work. If you want to store your MDX content in a separate repo or\nCMS, you're kinda out of luck or have to do some build-time gymnastics to get\nthe files in place for the build.\n\nWith `mdx-bundler`, it doesn't matter where your MDX content comes from, you can\nbundle files from anywhere, you're just responsible for getting the content into\nmemory and then you hand that off to `mdx-bundler` for bundling.\n\n</details>\n\n<details>\n  <summary>\n    <strong>\n      \"Does this work with Remix/Gatsby/Next/CRA/etc?\"\n    </strong>\n  </summary>\n\nTotally. It works with any of those tools. Depending on whether your\nmeta-framework supports server-side rendering, you'll implement it differently.\nYou might decide to go with a built-time approach (for Gatsby/CRA), but as\nmentioned, the true power of `mdx-bundler` comes in the form of on-demand\nbundling. So it's best suited for SSR frameworks like Remix/Next.\n\n</details>\n\n<details>\n  <summary>\n    <strong>\n      \"Why the dodo bird emoji? 🦤\"\n    </strong>\n  </summary>\n\nWhy not?\n\n</details>\n\n<details>\n  <summary>\n    <strong>\n      \"Why does this use XDM instead of @mdx-js?\"\n    </strong>\n  </summary>\n\nIt has more features, fewer bugs, and no runtime!\n\n</details>\n\n<details>\n  <summary>\n    <strong>\n      \"Why is esbuild a peer dependancy?\"\n    </strong>\n  </summary>\n\nesbuild provides a service written in GO that it interacts with. Only one\ninstance of this service can run at a time and it must have an identical version\nto the npm package. If it was a hard dependency you would only be able to use\nthe esbuild version mdx-bundler uses.\n\n</details>\n\n## Table of Contents\n\n<!-- START doctoc generated TOC please keep comment here to allow auto update -->\n<!-- DON'T EDIT THIS SECTION, INSTEAD RE-RUN doctoc TO UPDATE -->\n\n- [Installation](#installation)\n- [Usage](#usage)\n  - [Options](#options)\n  - [Component Substitution](#component-substitution)\n  - [Frontmatter and const](#frontmatter-and-const)\n  - [Accessing named exports](#accessing-named-exports)\n  - [Image Bundling](#image-bundling)\n  - [bundleMDXFile](#bundlemdxfile)\n  - [Known Issues](#known-issues)\n- [Inspiration](#inspiration)\n- [Other Solutions](#other-solutions)\n- [Issues](#issues)\n  - [🐛 Bugs](#-bugs)\n  - [💡 Feature Requests](#-feature-requests)\n- [Contributors ✨](#contributors-)\n- [LICENSE](#license)\n\n<!-- END doctoc generated TOC please keep comment here to allow auto update -->\n\n## Installation\n\nThis module is distributed via [npm][npm] which is bundled with [node][node] and\nshould be installed as one of your project's `dependencies`:\n\n```\nnpm install --save mdx-bundler esbuild\n```\n\nOne of mdx-bundler's dependancies requires a working [node-gyp][node-gyp] setup\nto be able to install correctly.\n\n## Usage\n\n```typescript\nimport {bundleMDX} from 'mdx-bundler'\n\nconst mdxSource = `\n---\ntitle: Example Post\npublished: 2021-02-13\ndescription: This is some description\n---\n\n# Wahoo\n\nimport Demo from './demo'\n\nHere's a **neat** demo:\n\n<Demo />\n`.trim()\n\nconst result = await bundleMDX(mdxSource, {\n  files: {\n    './demo.tsx': `\nimport * as React from 'react'\n\nfunction Demo() {\n  return <div>Neat demo!</div>\n}\n\nexport default Demo\n    `,\n  },\n})\n\nconst {code, frontmatter} = result\n```\n\nFrom there, you send the `code` to your client, and then:\n\n```jsx\nimport * as React from 'react'\nimport {getMDXComponent} from 'mdx-bundler/client'\n\nfunction Post({code, frontmatter}) {\n  // it's generally a good idea to memoize this function call to\n  // avoid re-creating the component every render.\n  const Component = React.useMemo(() => getMDXComponent(code), [code])\n  return (\n    <>\n      <header>\n        <h1>{frontmatter.title}</h1>\n        <p>{frontmatter.description}</p>\n      </header>\n      <main>\n        <Component />\n      </main>\n    </>\n  )\n}\n```\n\nUltimately, this gets rendered (basically):\n\n```html\n<header>\n  <h1>This is the title</h1>\n  <p>This is some description</p>\n</header>\n<main>\n  <div>\n    <h1>Wahoo</h1>\n\n    <p>Here's a <strong>neat</strong> demo:</p>\n\n    <div>Neat demo!</div>\n  </div>\n</main>\n```\n\n### Options\n\n#### files\n\nThe `files` config is an object of all the files you're bundling. The key is the\npath to the file (relative to the MDX source) and the value is the string of the\nfile source code. You could get these from the filesystem or from a remote\ndatabase. If your MDX doesn't reference other files (or only imports things from\n`node_modules`), then you can omit this entirely.\n\n#### xdmOptions\n\nThis allows you to modify the built-in xdm configuration (passed to the xdm\nesbuild plugin). This can be helpful for specifying your own\nremarkPlugins/rehypePlugins.\n\n```ts\nbundleMDX(mdxString, {\n  xdmOptions(options) {\n    // this is the recommended way to add custom remark/rehype plugins:\n    // The syntax might look weird, but it protects you in case we add/remove\n    // plugins in the future.\n    options.remarkPlugins = [...(options.remarkPlugins ?? []), myRemarkPlugin]\n    options.rehypePlugins = [...(options.rehypePlugins ?? []), myRehypePlugin]\n\n    return options\n  },\n})\n```\n\n#### esbuildOptions\n\nYou can customize any of esbuild options with the option `esbuildOptions`. This\ntakes a function which is passed the default esbuild options and expects an\noptions object to be returned.\n\n```typescript\nbundleMDX(mdxSource, {\n  esbuildOptions(options) {\n    options.minify = false\n    options.target = [\n      'es2020',\n      'chrome58',\n      'firefox57',\n      'safari11',\n      'edge16',\n      'node12',\n    ]\n\n    return options\n  },\n})\n```\n\nMore information on the available options can be found in the\n[esbuild documentation](https://esbuild.github.io/api/#build-api).\n\nIt's recommended to use this feature to configure the `target` to your desired\noutput, otherwise, esbuild defaults to `esnext` which is to say that it doesn't\ncompile any standardized features so it's possible users of older browsers will\nexperience errors.\n\n#### globals\n\nThis tells esbuild that a given module is externally available. For example, if\nyour MDX file uses the d3 library and you're already using the d3 library in\nyour app then you'll end up shipping `d3` to the user twice (once for your app\nand once for this MDX component). This is wasteful and you'd be better off just\ntelling esbuild to _not_ bundle `d3` and you can pass it to the component\nyourself when you call `getMDXComponent`.\n\nGlobal external configuration options: https://www.npmjs.com/package/@fal-works/esbuild-plugin-global-externals\n\nHere's an example:\n\n```tsx\n// server-side or build-time code that runs in Node:\nimport {bundleMDX} from 'mdx-bundler'\n\nconst mdxSource = `\n# This is the title\n\nimport leftPad from 'left-pad'\n\n<div>{leftPad(\"Neat demo!\", 12, '!')}</div>\n`.trim()\n\nconst result = await bundleMDX(mdxSource, {\n  // NOTE: this is *only* necessary if you want to share deps between your MDX\n  // file bundle and the host app. Otherwise, all deps will just be bundled.\n  // So it'll work either way, this is just an optimization to avoid sending\n  // multiple copies of the same library to your users.\n  globals: {'left-pad': 'myLeftPad'},\n})\n```\n\n```tsx\n// server-rendered and/or client-side code that can run in the browser or Node:\nimport * as React from 'react'\nimport leftPad from 'left-pad'\nimport {getMDXComponent} from 'mdx-bundler/client'\n\nfunction MDXPage({code}: {code: string}) {\n  const Component = React.useMemo(\n    () => getMDXComponent(result.code, {myLeftPad: leftPad}),\n    [result.code, leftPad],\n  )\n  return (\n    <main>\n      <Component />\n    </main>\n  )\n}\n```\n\n#### cwd\n\nSetting `cwd` (_current working directory_) to a directory will allow esbuild to\nresolve imports. This directory could be the directory the mdx content was read\nfrom or a directory that off-disk mdx should be _run_ in.\n\n_content/pages/demo.tsx_\n\n```typescript\nimport * as React from 'react'\n\nfunction Demo() {\n  return <div>Neat demo!</div>\n}\n\nexport default Demo\n```\n\n_src/build.ts_\n\n```typescript\nimport {bundleMDX} from 'mdx-bundler'\n\nconst mdxSource = `\n---\ntitle: Example Post\npublished: 2021-02-13\ndescription: This is some description\n---\n\n# Wahoo\n\nimport Demo from './demo'\n\nHere's a **neat** demo:\n\n<Demo />\n`.trim()\n\nconst result = await bundleMDX(mdxSource, {\n  cwd: '/users/you/site/_content/pages',\n})\n\nconst {code, frontmatter} = result\n```\n\n#### grayMatterOptions\n\nThis allows you to configure the\n[gray-matter options](https://github.com/jonschlinkert/gray-matter#options).\n\nYour function is passed the current gray-matter configuration for you to modify.\nReturn your modified configuration object for gray matter.\n\n```js\nbundleMDX(mdxString, {\n  grayMatterOptions: options => {\n    options.excerpt = true\n\n    return options\n  },\n})\n```\n\n### Returns\n\n`bundleMDX` returns a promise for an object with the following properties.\n\n- `code` - The bundle of your mdx as a `string`.\n- `frontmatter` - The frontmatter `object` from gray-matter.\n- `matter` - The whole\n  [object returned by gray-matter](https://github.com/jonschlinkert/gray-matter#returned-object)\n\n### Component Substitution\n\nMDX Bundler passes on\n[XDM's ability to substitute components](https://github.com/wooorm/xdm#mdx-content)\nthrough the `components` prop on the component returned by `getMDXComponent`.\n\nHere's an example that removes _p_ tags from around images.\n\n```tsx\nimport * as React from 'react'\nimport {getMDXComponent} from 'mdx-bundler/client'\n\nconst Paragraph: React.FC = props => {\n  if (typeof props.children !== 'string' && props.children.type === 'img') {\n    return <>{props.children}</>\n  }\n\n  return <p {...props} />\n}\n\nfunction MDXPage({code}: {code: string}) {\n  const Component = React.useMemo(() => getMDXComponent(code), [code])\n\n  return (\n    <main>\n      <Component components={{p: Paragraph}} />\n    </main>\n  )\n}\n```\n\n### Frontmatter and const\n\nYou can reference frontmatter meta or consts in the mdx content.\n\n```mdx\n---\ntitle: Example Post\n---\n\nexport const exampleImage = 'https://example.com/image.jpg'\n\n# {frontmatter.title}\n\n<img src={exampleImage} alt=\"Image alt text\" />\n```\n\n### Accessing named exports\n\nYou can use `getMDXExport` instead of `getMDXComponent` to treat the mdx file as a module instead of just a component.\nIt takes the same arguments that `getMDXComponent` does.\n\n```mdx\n---\ntitle: Example Post\n---\n\nexport const toc = [\n  { depth: 1, value: 'The title' }\n]\n\n# The title\n```\n\n```js\nimport * as React from 'react'\nimport {getMDXExport} from 'mdx-bundler/client'\n\nfunction MDXPage({code}: {code: string}) {\n  const mdxExport = getMDXExport(code)\n  console.log(mdxExport.toc) // [ { depth: 1, value: 'The title' } ]\n\n  const Component = React.useMemo(() => mdxExport.default, [code])\n\n  return <Component />\n}\n```\n### Image Bundling\n\nWith the [cwd](#cwd) and the remark plugin\n[remark-mdx-images](https://www.npmjs.com/package/remark-mdx-images) you can\nbundle images in your mdx!\n\nThere are two loaders in esbuild that can be used here. The easiest is `dataurl`\nwhich outputs the images as inline data urls in the returned code.\n\n```js\nimport {remarkMdxImages} from 'remark-mdx-images'\n\nconst {code} = await bundleMDX(mdxSource, {\n  cwd: '/users/you/site/_content/pages',\n  xdmOptions: options => {\n    options.remarkPlugins = [...(options.remarkPlugins ?? []), remarkMdxImages]\n\n    return options\n  },\n  esbuildOptions: options => {\n    options.loader = {\n      ...options.loader,\n      '.png': 'dataurl',\n    }\n\n    return options\n  },\n})\n```\n\nThe `file` loader requires a little more configuration to get working. With the\n`file` loader your images are copied to the output directory so esbuild needs to\nbe set to write files and needs to know where to put them plus the url of the\nfolder to be used in image sources.\n\n> Each call to `bundleMDX` is isloated from the others. If you set the directory\n> the same for everything `bundleMDX` will overwrite images without warning. As\n> a result each _bundle_ needs its own output directory.\n\n```js\n// For the file `_content/pages/about.mdx`\n\nconst {code} = await bundleMDX(mdxSource, {\n  cwd: '/users/you/site/_content/pages',\n  xdmOptions: options => {\n    options.remarkPlugins = [...(options.remarkPlugins ?? []), remarkMdxImages]\n\n    return options\n  },\n  esbuildOptions: options => {\n    // Set the `outdir` to a public location for this bundle.\n    options.outdir = '/users/you/site/public/img/about'\n    options.loader = {\n      ...options.loader,\n      // Tell esbuild to use the `file` loader for pngs\n      '.png': 'file',\n    }\n    // Set the public path to /img/about\n    options.publicPath = '/img/about'\n\n    // Set write to true so that esbuild will output the files.\n    options.write = true\n\n    return options\n  },\n})\n```\n\n### bundleMDXFile\n\nIf your MDX file is on your disk you can save some time and code by having\n`esbuild` read the file for you. To do this mdx-bundler provides the function\n`bundleMDXFile` which works the same as `bundleMDX` except it's first option is\nthe path to the mdx file instead of the mdx source.\n\n```js\nimport {bundleMDXFile} from 'mdx-bundler'\n\nconst {code, frontmatter} = await bundleMDXFile(\n  '/users/you/site/content/file.mdx',\n)\n```\n\n`cwd` will be automatically set to the `dirname` of the given file path, you can\nstill override this. All other options work the same as they do for `bundleMDX`.\n\n### Known Issues\n\n#### Cloudflare Workers\n\nWe'd _love_ for this to work in cloudflare workers. Unfortunately cloudflares\nhave two limitations that prevent `mdx-bundler` from working in that\nenvironment:\n\n1. Workers can't run binaries. `bundleMDX` uses `esbuild` (a binary) to bundle\n   your MDX code.\n2. Workers can't run `eval` or similar. `getMDXComponent` evaluates the bundled\n   code using `new Function`.\n\nOne workaround to this is to put your mdx-bundler related code in a different\nenvironment and call that environment from within the Cloudflare worker. IMO,\nthis defeats the purpose of using Cloudflare workers. Another potential\nworkaround is to use WASM from within the worker. There is\n[`esbuild-wasm`](https://esbuild.github.io/getting-started/#install-the-wasm-version)\nbut there are some issues with that package explained at that link. Then there's\n[`wasm-jseval`](https://github.com/maple3142/wasm-jseval), but I couldn't get\nthat to run code that was output from `mdx-bundler` without error.\n\nIf someone would like to dig into this, that would be stellar, but unfortunately\nit's unlikely I'll ever work on it.\n\n#### Next.JS esbuild ENOENT\n\nesbuild relies on `__dirname` to work out where is executable is, Next.JS and\nWebpack can sometimes break this and esbuild needs to be told manually where to\nlook.\n\nAdding the following code before your `bundleMDX` will point esbuild directly at\nthe correct executable for your platform.\n\n```js\nimport path from 'path'\n\nif (process.platform === 'win32') {\n  process.env.ESBUILD_BINARY_PATH = path.join(\n    process.cwd(),\n    'node_modules',\n    'esbuild',\n    'esbuild.exe',\n  )\n} else {\n  process.env.ESBUILD_BINARY_PATH = path.join(\n    process.cwd(),\n    'node_modules',\n    'esbuild',\n    'bin',\n    'esbuild',\n  )\n}\n```\n\nMore information on this issue can be found\n[in this article](https://www.arcath.net/2021/03/mdx-bundler#esbuild-executable).\n\n## Inspiration\n\nAs I was rewriting [kentcdodds.com](https://kentcdodds.com) to\n[remix](https://remix.run), I decided I wanted to keep my blog posts as MDX, but\nI didn't want to have to compile them all at build time or be required to\nredeploy every time I fix a typo. So I made this which allows my server to\ncompile on demand.\n\n## Other Solutions\n\nThere's [next-mdx-remote](https://github.com/hashicorp/next-mdx-remote) but it's\nmore of an mdx-compiler than a bundler (can't bundle your mdx for dependencies).\nAlso it's focused on Next.js whereas this is meta-framework agnostic.\n\n## Issues\n\n_Looking to contribute? Look for the [Good First Issue][good-first-issue]\nlabel._\n\n### 🐛 Bugs\n\nPlease file an issue for bugs, missing documentation, or unexpected behavior.\n\n[**See Bugs**][bugs]\n\n### 💡 Feature Requests\n\nPlease file an issue to suggest new features. Vote on feature requests by adding\na 👍. This helps maintainers prioritize what to work on.\n\n[**See Feature Requests**][requests]\n\n## Contributors ✨\n\nThanks goes to these people ([emoji key][emojis]):\n\n<!-- ALL-CONTRIBUTORS-LIST:START - Do not remove or modify this section -->\n<!-- prettier-ignore-start -->\n<!-- markdownlint-disable -->\n<table>\n  <tr>\n    <td align=\"center\"><a href=\"https://kentcdodds.com\"><img src=\"https://avatars.githubusercontent.com/u/1500684?v=3?s=100\" width=\"100px;\" alt=\"\"/><br /><sub><b>Kent C. Dodds</b></sub></a><br /><a href=\"https://github.com/kentcdodds/mdx-bundler/commits?author=kentcdodds\" title=\"Code\">💻</a> <a href=\"https://github.com/kentcdodds/mdx-bundler/commits?author=kentcdodds\" title=\"Documentation\">📖</a> <a href=\"#infra-kentcdodds\" title=\"Infrastructure (Hosting, Build-Tools, etc)\">🚇</a> <a href=\"https://github.com/kentcdodds/mdx-bundler/commits?author=kentcdodds\" title=\"Tests\">⚠️</a></td>\n    <td align=\"center\"><a href=\"https://github.com/benwis\"><img src=\"https://avatars.githubusercontent.com/u/6953353?v=4?s=100\" width=\"100px;\" alt=\"\"/><br /><sub><b>benwis</b></sub></a><br /><a href=\"https://github.com/kentcdodds/mdx-bundler/issues?q=author%3Abenwis\" title=\"Bug reports\">🐛</a> <a href=\"https://github.com/kentcdodds/mdx-bundler/pulls?q=is%3Apr+reviewed-by%3Abenwis\" title=\"Reviewed Pull Requests\">👀</a></td>\n    <td align=\"center\"><a href=\"https://www.arcath.net\"><img src=\"https://avatars.githubusercontent.com/u/19609?v=4?s=100\" width=\"100px;\" alt=\"\"/><br /><sub><b>Adam Laycock</b></sub></a><br /><a href=\"https://github.com/kentcdodds/mdx-bundler/commits?author=Arcath\" title=\"Code\">💻</a> <a href=\"https://github.com/kentcdodds/mdx-bundler/commits?author=Arcath\" title=\"Tests\">⚠️</a> <a href=\"#ideas-Arcath\" title=\"Ideas, Planning, & Feedback\">🤔</a> <a href=\"https://github.com/kentcdodds/mdx-bundler/pulls?q=is%3Apr+reviewed-by%3AArcath\" title=\"Reviewed Pull Requests\">👀</a> <a href=\"https://github.com/kentcdodds/mdx-bundler/commits?author=Arcath\" title=\"Documentation\">📖</a></td>\n    <td align=\"center\"><a href=\"http://wooorm.com\"><img src=\"https://avatars.githubusercontent.com/u/944406?v=4?s=100\" width=\"100px;\" alt=\"\"/><br /><sub><b>Titus</b></sub></a><br /><a href=\"#ideas-wooorm\" title=\"Ideas, Planning, & Feedback\">🤔</a> <a href=\"https://github.com/kentcdodds/mdx-bundler/pulls?q=is%3Apr+reviewed-by%3Awooorm\" title=\"Reviewed Pull Requests\">👀</a> <a href=\"https://github.com/kentcdodds/mdx-bundler/commits?author=wooorm\" title=\"Code\">💻</a></td>\n    <td align=\"center\"><a href=\"https://github.com/ChristianMurphy\"><img src=\"https://avatars.githubusercontent.com/u/3107513?v=4?s=100\" width=\"100px;\" alt=\"\"/><br /><sub><b>Christian Murphy</b></sub></a><br /><a href=\"#ideas-ChristianMurphy\" title=\"Ideas, Planning, & Feedback\">🤔</a></td>\n    <td align=\"center\"><a href=\"https://ped.ro\"><img src=\"https://avatars.githubusercontent.com/u/372831?v=4?s=100\" width=\"100px;\" alt=\"\"/><br /><sub><b>Pedro Duarte</b></sub></a><br /><a href=\"https://github.com/kentcdodds/mdx-bundler/commits?author=peduarte\" title=\"Documentation\">📖</a></td>\n    <td align=\"center\"><a href=\"https://keybase.io/erikras\"><img src=\"https://avatars.githubusercontent.com/u/4396759?v=4?s=100\" width=\"100px;\" alt=\"\"/><br /><sub><b>Erik Rasmussen</b></sub></a><br /><a href=\"https://github.com/kentcdodds/mdx-bundler/commits?author=erikras\" title=\"Documentation\">📖</a></td>\n  </tr>\n  <tr>\n    <td align=\"center\"><a href=\"https://github.com/ozyxdev\"><img src=\"https://avatars.githubusercontent.com/u/83309085?v=4?s=100\" width=\"100px;\" alt=\"\"/><br /><sub><b>Omar Syx</b></sub></a><br /><a href=\"https://github.com/kentcdodds/mdx-bundler/issues?q=author%3Aozyxdev\" title=\"Bug reports\">🐛</a></td>\n    <td align=\"center\"><a href=\"https://github.com/gaelhameon\"><img src=\"https://avatars.githubusercontent.com/u/17253950?v=4?s=100\" width=\"100px;\" alt=\"\"/><br /><sub><b>Gaël Haméon</b></sub></a><br /><a href=\"https://github.com/kentcdodds/mdx-bundler/commits?author=gaelhameon\" title=\"Documentation\">📖</a></td>\n    <td align=\"center\"><a href=\"https://github.com/loiacon\"><img src=\"https://avatars.githubusercontent.com/u/32134586?v=4?s=100\" width=\"100px;\" alt=\"\"/><br /><sub><b>Gabriel Loiácono</b></sub></a><br /><a href=\"https://github.com/kentcdodds/mdx-bundler/commits?author=loiacon\" title=\"Code\">💻</a> <a href=\"https://github.com/kentcdodds/mdx-bundler/commits?author=loiacon\" title=\"Tests\">⚠️</a></td>\n    <td align=\"center\"><a href=\"https://skovy.dev\"><img src=\"https://avatars.githubusercontent.com/u/5247455?v=4?s=100\" width=\"100px;\" alt=\"\"/><br /><sub><b>Spencer Miskoviak</b></sub></a><br /><a href=\"https://github.com/kentcdodds/mdx-bundler/commits?author=skovy\" title=\"Documentation\">📖</a></td>\n    <td align=\"center\"><a href=\"https://caspertheghost.me\"><img src=\"https://avatars.githubusercontent.com/u/53900565?v=4?s=100\" width=\"100px;\" alt=\"\"/><br /><sub><b>Casper</b></sub></a><br /><a href=\"https://github.com/kentcdodds/mdx-bundler/commits?author=Dev-CasperTheGhost\" title=\"Code\">💻</a></td>\n    <td align=\"center\"><a href=\"http://a7sc11u.dev\"><img src=\"https://avatars.githubusercontent.com/u/803868?v=4?s=100\" width=\"100px;\" alt=\"\"/><br /><sub><b>Apostolos Christodoulou</b></sub></a><br /><a href=\"https://github.com/kentcdodds/mdx-bundler/commits?author=a7sc11u\" title=\"Documentation\">📖</a></td>\n    <td align=\"center\"><a href=\"https://github.com/yordis\"><img src=\"https://avatars.githubusercontent.com/u/4237280?v=4?s=100\" width=\"100px;\" alt=\"\"/><br /><sub><b>Yordis Prieto</b></sub></a><br /><a href=\"https://github.com/kentcdodds/mdx-bundler/commits?author=yordis\" title=\"Code\">💻</a></td>\n  </tr>\n  <tr>\n    <td align=\"center\"><a href=\"https://github.com/xoumi\"><img src=\"https://avatars.githubusercontent.com/u/24864287?v=4?s=100\" width=\"100px;\" alt=\"\"/><br /><sub><b>xoumi</b></sub></a><br /><a href=\"https://github.com/kentcdodds/mdx-bundler/commits?author=xoumi\" title=\"Code\">💻</a></td>\n  </tr>\n</table>\n\n<!-- markdownlint-restore -->\n<!-- prettier-ignore-end -->\n\n<!-- ALL-CONTRIBUTORS-LIST:END -->\n\nThis project follows the [all-contributors][all-contributors] specification.\nContributions of any kind welcome!\n\n## LICENSE\n\nMIT\n\n<!-- prettier-ignore-start -->\n[npm]: https://www.npmjs.com\n[node]: https://nodejs.org\n[build-badge]: https://img.shields.io/github/workflow/status/kentcdodds/mdx-bundler/validate?logo=github&style=flat-square\n[build]: https://github.com/kentcdodds/mdx-bundler/actions?query=workflow%3Avalidate\n[coverage-badge]: https://img.shields.io/codecov/c/github/kentcdodds/mdx-bundler.svg?style=flat-square\n[coverage]: https://codecov.io/github/kentcdodds/mdx-bundler\n[version-badge]: https://img.shields.io/npm/v/mdx-bundler.svg?style=flat-square\n[package]: https://www.npmjs.com/package/mdx-bundler\n[downloads-badge]: https://img.shields.io/npm/dm/mdx-bundler.svg?style=flat-square\n[npmtrends]: https://www.npmtrends.com/mdx-bundler\n[license-badge]: https://img.shields.io/npm/l/mdx-bundler.svg?style=flat-square\n[license]: https://github.com/kentcdodds/mdx-bundler/blob/main/LICENSE\n[prs-badge]: https://img.shields.io/badge/PRs-welcome-brightgreen.svg?style=flat-square\n[prs]: https://makeapullrequest.com\n[coc-badge]: https://img.shields.io/badge/code%20of-conduct-ff69b4.svg?style=flat-square\n[coc]: https://github.com/kentcdodds/mdx-bundler/blob/main/CODE_OF_CONDUCT.md\n[emojis]: https://github.com/all-contributors/all-contributors#emoji-key\n[all-contributors]: https://github.com/all-contributors/all-contributors\n[all-contributors-badge]: https://img.shields.io/github/all-contributors/kentcdodds/mdx-bundler?color=orange&style=flat-square\n[bugs]: https://github.com/kentcdodds/mdx-bundler/issues?utf8=%E2%9C%93&q=is%3Aissue+is%3Aopen+sort%3Acreated-desc+label%3Abug\n[requests]: https://github.com/kentcdodds/mdx-bundler/issues?utf8=%E2%9C%93&q=is%3Aissue+is%3Aopen+sort%3Areactions-%2B1-desc+label%3Aenhancement\n[good-first-issue]: https://github.com/kentcdodds/mdx-bundler/issues?utf8=%E2%9C%93&q=is%3Aissue+is%3Aopen+sort%3Areactions-%2B1-desc+label%3Aenhancement+label%3A%22good+first+issue%22\n[node-gyp]: https://github.com/nodejs/node-gyp#installation\n<!-- prettier-ignore-end -->\n","readmeFilename":"README.md"}