Skip to content

Commit

Permalink
esbuild: remove allowDangerousRemoteMdx option
Browse files Browse the repository at this point in the history
  • Loading branch information
wooorm committed Oct 23, 2023
1 parent e12f307 commit 0d1558a
Show file tree
Hide file tree
Showing 10 changed files with 8 additions and 299 deletions.
1 change: 0 additions & 1 deletion docs/docs/getting-started.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -237,7 +237,6 @@ long.

We support [esbuild](https://esbuild.github.io).
Install and configure the esbuild plugin [`@mdx-js/esbuild`][mdx-esbuild].
This plugin has an additional option `allowDangerousRemoteMdx`.
[Configure your JSX runtime][jsx] depending on which one you use (React, Preact,
Vue, etc.).

Expand Down
20 changes: 0 additions & 20 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

120 changes: 6 additions & 114 deletions packages/esbuild/lib/index.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/**
* @typedef {import('@mdx-js/mdx').ProcessorOptions} ProcessorOptions
* @typedef {import('@mdx-js/mdx').CompileOptions} CompileOptions
* @typedef {import('esbuild').Message} Message
* @typedef {import('esbuild').OnLoadArgs} OnLoadArgs
* @typedef {import('esbuild').OnLoadResult} OnLoadResult
Expand All @@ -10,15 +10,6 @@
*/

/**
* @typedef EsbuildOptions
* Extra options.
* @property {boolean | null | undefined} [allowDangerousRemoteMdx=false]
* Whether to allow importing from `http:` and `https:` URLs (`boolean`,
* default: `false`).
*
* When passing `allowDangerousRemoteMdx`, MD(X) *and* JS files can be
* imported from `http:` and `https:` urls.
*
* @typedef {Omit<OnLoadArgs, 'pluginData'> & LoadDataFields} LoadData
* Data passed to `onload`.
*
Expand All @@ -27,22 +18,10 @@
* @property {PluginData | null | undefined} [pluginData]
* Plugin data.
*
* @typedef {EsbuildOptions & ProcessorOptions} Options
* @typedef {CompileOptions} Options
* Configuration.
*
* Options are the same as `compile` from `@mdx-js/mdx` with the addition
* of `allowDangerousRemoteMdx`.
*
* ###### Notes
*
* > ⚠️ **Security**: `allowDangerousRemoteMdx` (intentionally) enabled remote
* > code execution.
* > Make sure you trust your code!
* > See [§ Security][security] for more
* > info.
*
* > 💡 **Experiment**: `allowDangerousRemoteMdx` is an experimental feature
* > that might not work well and might change in minor releases.
* Options are the same as `compile` from `@mdx-js/mdx`.
*
* @typedef PluginData
* Extra data passed.
Expand All @@ -62,20 +41,14 @@
import assert from 'node:assert'
import fs from 'node:fs/promises'
import path from 'node:path'
import process from 'node:process'
import {createFormatAwareProcessors} from '@mdx-js/mdx/internal-create-format-aware-processors'
import {extnamesToRegex} from '@mdx-js/mdx/internal-extnames-to-regex'
import {fetch} from 'undici'
import {VFile} from 'vfile'
import {VFileMessage} from 'vfile-message'

const eol = /\r\n|\r|\n|\u2028|\u2029/g

/** @type {Map<string, string>} */
const cache = new Map()
const name = '@mdx-js/esbuild'
const p = process
const remoteNamespace = name + '-remote'

/**
* Create an esbuild plugin to compile MDX to JS.
Expand All @@ -92,8 +65,7 @@ const remoteNamespace = name + '-remote'
* Plugin.
*/
export function esbuild(options) {
const {allowDangerousRemoteMdx, ...rest} = options || {}
const {extnames, process} = createFormatAwareProcessors(rest)
const {extnames, process} = createFormatAwareProcessors(options || {})

return {name, setup}

Expand All @@ -104,85 +76,7 @@ export function esbuild(options) {
* Nothing.
*/
function setup(build) {
const filter = extnamesToRegex(extnames)
const filterHttp = new RegExp('^https?:\\/{2}.+' + filter.source)
const http = /^https?:\/{2}/
const filterHttpOrRelative = /^(https?:\/{2}|.{1,2}\/).*/

if (allowDangerousRemoteMdx) {
// Intercept import paths starting with "http:" and "https:" so
// esbuild doesn't attempt to map them to a file system location.
// Tag them with the "http-url" namespace to associate them with
// this plugin.
build.onResolve(
{filter: filterHttp, namespace: 'file'},
resolveRemoteInLocal
)

build.onResolve(
{filter: filterHttpOrRelative, namespace: remoteNamespace},
resolveInRemote
)
}

build.onLoad({filter: /.*/, namespace: remoteNamespace}, onloadremote)
build.onLoad({filter}, onload)

/** @param {OnResolveArgs} args */
function resolveRemoteInLocal(args) {
return {namespace: remoteNamespace, path: args.path}
}

// Intercept all import paths inside downloaded files and resolve them against
// the original URL. All of these
// files will be in the "http-url" namespace. Make sure to keep
// the newly resolved URL in the "http-url" namespace so imports
// inside it will also be resolved as URLs recursively.
/** @param {OnResolveArgs} args */
function resolveInRemote(args) {
return {
namespace: remoteNamespace,
path: String(new URL(args.path, args.importer))
}
}

/**
* @param {OnLoadArgs} data
* Data.
* @returns {Promise<OnLoadResult>}
* Result.
*/
async function onloadremote(data) {
const href = data.path
console.log('%s: downloading `%s`', remoteNamespace, href)

/** @type {string} */
let contents

const cachedContents = cache.get(href)
if (cachedContents) {
contents = cachedContents
} else {
const response = await fetch(href)
contents = await response.text()
cache.set(href, contents)
}

if (filter.test(href)) {
// Clean search and hash from URL.
const url = new URL(href)
url.hash = ''
url.search = ''
return onload({
namespace: 'file',
path: url.href,
pluginData: {contents},
suffix: ''
})
}

return {contents, loader: 'js', resolveDir: p.cwd()}
}
build.onLoad({filter: extnamesToRegex(extnames)}, onload)

/**
* @param {LoadData} data
Expand Down Expand Up @@ -240,9 +134,7 @@ export function esbuild(options) {
return {
contents: value || '',
errors,
resolveDir: http.test(file.path)
? p.cwd()
: path.resolve(file.cwd, file.dirname),
resolveDir: path.resolve(file.cwd, file.dirname),
warnings
}
}
Expand Down
1 change: 0 additions & 1 deletion packages/esbuild/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,6 @@
"dependencies": {
"@mdx-js/mdx": "^2.0.0",
"@types/unist": "^3.0.0",
"undici": "^5.0.0",
"vfile": "^6.0.0",
"vfile-message": "^4.0.0"
},
Expand Down
59 changes: 1 addition & 58 deletions packages/esbuild/readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -97,64 +97,7 @@ ESBuild plugin ([`Plugin`][esbuild-plugin] from `esbuild`).

Configuration (TypeScript type).

Options are the same as [`CompileOptions` from `@mdx-js/mdx`][compile-options]
with the addition of `allowDangerousRemoteMdx`:

###### Fields

* `allowDangerousRemoteMdx` (`boolean`, default: `false`)
— whether to allow importing from `http:` and `https:` URLs;
when passing `allowDangerousRemoteMdx`, MD(X) *and* JS files can be imported
from `http:` and `https:` urls;

###### Notes

> ⚠️ **Security**: `allowDangerousRemoteMdx` (intentionally) enabled remote
> code execution.
> Make sure you trust your code!
> See [§ Security][security] for more
> info.
> 💡 **Experiment**: `allowDangerousRemoteMdx` is an experimental feature that
> might not work well and might change in minor releases.
## Examples

### Use `allowDangerousRemoteMdx`

Take this `index.mdx` file:

```mdx
import Readme from 'https://raw.githubusercontent.com/mdx-js/mdx/main/readme.md'

Here’s the readme:

<Readme />
```

…and a module `build.js`:

```tsx
import mdx from '@mdx-js/esbuild'
import esbuild from 'esbuild'

await esbuild.build({
entryPoints: ['index.mdx'],
format: 'esm',
outfile: 'output.js',
plugins: [mdx({allowDangerousRemoteMdx: true, /* Other options… */})]
})
```

…then running that (`node build.js`) and evaluating `output.js` (depends on how
you evaluate React or another framework) would give:

```tsx
<p>Here’s the readme:</p>
<h1>MDX: Markdown for the component era 🚀</h1>
{/**/}
<p><a href="https://github.com/mdx-js/mdx/blob/main/license">MIT</a> © …</p>
```
Options are the same as [`CompileOptions` from `@mdx-js/mdx`][compile-options].

## Types

Expand Down
23 changes: 0 additions & 23 deletions packages/esbuild/test/files/components.js

This file was deleted.

1 change: 0 additions & 1 deletion packages/esbuild/test/files/md-file.md

This file was deleted.

8 changes: 0 additions & 8 deletions packages/esbuild/test/files/mdx-file-importing-markdown.mdx

This file was deleted.

Loading

1 comment on commit 0d1558a

@vercel
Copy link

@vercel vercel bot commented on 0d1558a Oct 23, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Successfully deployed to the following URLs:

mdx – ./

mdxjs.com
mdx-mdx.vercel.app
v2.mdxjs.com
mdx-git-main-mdx.vercel.app

Please sign in to comment.