Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

xdm

Package Overview
Dependencies
Maintainers
1
Versions
37
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

xdm - npm Package Compare versions

Comparing version 1.1.0 to 1.2.0

esbuild.d.ts

98

lib/core.d.ts

@@ -11,7 +11,7 @@ /**

* @typedef BaseProcessorOptions
* @property {boolean} [jsx]
* @property {PluggableList} [recmaPlugins]
* @property {PluggableList} [remarkPlugins]
* @property {PluggableList} [rehypePlugins]
* @property {boolean} [_contain]
* @property {boolean} [jsx=false] Whether to keep JSX
* @property {PluggableList} [recmaPlugins] List of recma (esast, JavaScript) plugins
* @property {PluggableList} [remarkPlugins] List of remark (mdast, markdown) plugins
* @property {PluggableList} [rehypePlugins] List of rehype (hast, HTML) plugins
* @property {boolean} [_contain=false] Semihidden option
*

@@ -21,4 +21,5 @@ * @typedef {Omit<RecmaDocumentOptions & RecmaStringifyOptions & RecmaJsxRewriteOptions & BaseProcessorOptions, "contain"> } ProcessorOptions

/**
* Compile MDX to JS.
*
* @param {VFileCompatible} file
* @param {VFileCompatible} file MDX document to parse (`string`, `Buffer`, `vfile`, anything that can be given to `vfile`)
* @param {ProcessorOptions} [options]

@@ -29,4 +30,5 @@ * @return {Promise<VFile>}

/**
* Synchronously compile MDX to JS.
*
* @param {VFileCompatible} file
* @param {VFileCompatible} file MDX document to parse (`string`, `Buffer`, `vfile`, anything that can be given to `vfile`)
* @param {ProcessorOptions} [options]

@@ -41,37 +43,115 @@ * @return {VFile}

export type RecmaDocumentOptions = {
contain: boolean;
/**
* Semihidden option which here results in failing on imports and adding a top-level return statement instead of an export.
*/
contain?: boolean;
/**
* Pragma for JSX (used in classic runtime)
*/
pragma?: string;
/**
* Pragma for JSX fragments (used in classic runtime)
*/
pragmaFrag?: string;
/**
* Where to import the identifier of `pragma` from (used in classic runtime)
*/
pragmaImportSource?: string;
/**
* Place to import automatic JSX runtimes from (used in automatic runtime)
*/
jsxImportSource?: string;
/**
* JSX runtime to use
*/
jsxRuntime?: "automatic" | "classic";
};
export type RecmaStringifyOptions = {
/**
* Generate a source map by passing a `SourceMapGenerator` from `source-map` in
*/
SourceMapGenerator?: typeof import("source-map").SourceMapGenerator;
};
export type RecmaJsxRewriteOptions = {
/**
* Semihidden option which here results in getting `useMDXComponents` from `arguments[0]` instead of importing it
*/
contain?: boolean;
/**
* Place to import a provider from
*/
providerImportSource?: string;
contain?: boolean;
};
export type BaseProcessorOptions = {
/**
* Whether to keep JSX
*/
jsx?: boolean;
/**
* List of recma (esast, JavaScript) plugins
*/
recmaPlugins?: unified.PluggableList<unified.Settings>;
/**
* List of remark (mdast, markdown) plugins
*/
remarkPlugins?: unified.PluggableList<unified.Settings>;
/**
* List of rehype (hast, HTML) plugins
*/
rehypePlugins?: unified.PluggableList<unified.Settings>;
/**
* Semihidden option
*/
_contain?: boolean;
};
export type ProcessorOptions = {
/**
* Pragma for JSX (used in classic runtime)
*/
pragma?: string;
/**
* Pragma for JSX fragments (used in classic runtime)
*/
pragmaFrag?: string;
/**
* Where to import the identifier of `pragma` from (used in classic runtime)
*/
pragmaImportSource?: string;
/**
* Place to import automatic JSX runtimes from (used in automatic runtime)
*/
jsxImportSource?: string;
/**
* JSX runtime to use
*/
jsxRuntime?: "automatic" | "classic";
/**
* Place to import a provider from
*/
providerImportSource?: string;
/**
* Generate a source map by passing a `SourceMapGenerator` from `source-map` in
*/
SourceMapGenerator?: typeof import("source-map").SourceMapGenerator;
/**
* Whether to keep JSX
*/
jsx?: boolean;
/**
* List of recma (esast, JavaScript) plugins
*/
recmaPlugins?: unified.PluggableList<unified.Settings>;
/**
* List of remark (mdast, markdown) plugins
*/
remarkPlugins?: unified.PluggableList<unified.Settings>;
/**
* List of rehype (hast, HTML) plugins
*/
rehypePlugins?: unified.PluggableList<unified.Settings>;
/**
* Semihidden option
*/
_contain?: boolean;
};
import unified from "unified/types/ts3.4/";

25

lib/core.js

@@ -22,7 +22,7 @@ import unified from 'unified'

* @typedef BaseProcessorOptions
* @property {boolean} [jsx]
* @property {PluggableList} [recmaPlugins]
* @property {PluggableList} [remarkPlugins]
* @property {PluggableList} [rehypePlugins]
* @property {boolean} [_contain]
* @property {boolean} [jsx=false] Whether to keep JSX
* @property {PluggableList} [recmaPlugins] List of recma (esast, JavaScript) plugins
* @property {PluggableList} [remarkPlugins] List of remark (mdast, markdown) plugins
* @property {PluggableList} [rehypePlugins] List of rehype (hast, HTML) plugins
* @property {boolean} [_contain=false] Semihidden option
*

@@ -33,4 +33,5 @@ * @typedef {Omit<RecmaDocumentOptions & RecmaStringifyOptions & RecmaJsxRewriteOptions & BaseProcessorOptions, "contain"> } ProcessorOptions

/**
* Compile MDX to JS.
*
* @param {VFileCompatible} file
* @param {VFileCompatible} file MDX document to parse (`string`, `Buffer`, `vfile`, anything that can be given to `vfile`)
* @param {ProcessorOptions} [options]

@@ -44,4 +45,5 @@ * @return {Promise<VFile>}

/**
* Synchronously compile MDX to JS.
*
* @param {VFileCompatible} file
* @param {VFileCompatible} file MDX document to parse (`string`, `Buffer`, `vfile`, anything that can be given to `vfile`)
* @param {ProcessorOptions} [options]

@@ -55,3 +57,8 @@ * @return {VFile}

/**
* Pipeline to:
*
* 1. Parse MDX (serialized markdown with embedded JSX, ESM, and expressions)
* 2. Transform through remark (mdast), rehype (hast), and recma (esast)
* 3. Serialize as JavaScript
*
* @param {ProcessorOptions} [options]

@@ -92,5 +99,5 @@ * @return {Processor}

.use(recmaDocument, {...otherOptions, contain})
// @ts-ignore recma transformer uses an estree node rather than a unist node
// @ts-ignore recma transformer uses an esast node rather than a unist node
.use(recmaJsxRewrite, {providerImportSource, contain})
// @ts-ignore recma transformer uses an estree node rather than a unist node
// @ts-ignore recma transformer uses an esast node rather than a unist node
.use(jsx ? undefined : recmaJsxBuild, {contain})

@@ -97,0 +104,0 @@ // @ts-ignore recma compiler is seen as a transformer

@@ -6,6 +6,6 @@ /**

* @typedef RunnerOptions
* @property {*} [Fragment]
* @property {*} [jsx]
* @property {*} [jsxs]
* @property {*} [useMDXComponents]
* @property {*} Fragment Symbol to use for fragments
* @property {*} jsx Function to generate an element with static children
* @property {*} jsxs Function to generate an element with dynamic children
* @property {*} [useMDXComponents] Function to get `MDXComponents` from context
*

@@ -20,32 +20,70 @@ * @typedef {Omit<BaseProcessorOptions, "jsx" | "_contain"> } ProcessorOptions

/**
* Evaluate MDX.
*
* @param {VFileCompatible} file
* @param {ProcessorAndRunnerOptions} [options]
* @param {VFileCompatible} file MDX document to parse (`string`, `Buffer`, `vfile`, anything that can be given to `vfile`)
* @param {ProcessorAndRunnerOptions} options
* @return {Promise<ExportMap>}
*/
export function evaluate(file: VFileCompatible, options?: ProcessorAndRunnerOptions): Promise<ExportMap>;
export function evaluate(file: VFileCompatible, options: ProcessorAndRunnerOptions): Promise<ExportMap>;
/**
* Synchronously evaluate MDX.
*
* @param {VFileCompatible} file
* @param {ProcessorAndRunnerOptions} [options]
* @param {VFileCompatible} file MDX document to parse (`string`, `Buffer`, `vfile`, anything that can be given to `vfile`)
* @param {ProcessorAndRunnerOptions} options
* @return {ExportMap}
*/
export function evaluateSync(file: VFileCompatible, options?: ProcessorAndRunnerOptions): ExportMap;
export function evaluateSync(file: VFileCompatible, options: ProcessorAndRunnerOptions): ExportMap;
export type VFileCompatible = string | import("vfile").VFile | import("vfile").VFileOptions | Uint8Array;
export type BaseProcessorOptions = {
/**
* Whether to keep JSX
*/
jsx?: boolean;
/**
* List of recma (esast, JavaScript) plugins
*/
recmaPlugins?: import("unified/types/ts3.4/").PluggableList<import("unified/types/ts3.4/").Settings>;
/**
* List of remark (mdast, markdown) plugins
*/
remarkPlugins?: import("unified/types/ts3.4/").PluggableList<import("unified/types/ts3.4/").Settings>;
/**
* List of rehype (hast, HTML) plugins
*/
rehypePlugins?: import("unified/types/ts3.4/").PluggableList<import("unified/types/ts3.4/").Settings>;
/**
* Semihidden option
*/
_contain?: boolean;
};
export type RunnerOptions = {
Fragment?: any;
jsx?: any;
jsxs?: any;
/**
* Symbol to use for fragments
*/
Fragment: any;
/**
* Function to generate an element with static children
*/
jsx: any;
/**
* Function to generate an element with dynamic children
*/
jsxs: any;
/**
* Function to get `MDXComponents` from context
*/
useMDXComponents?: any;
};
export type ProcessorOptions = {
/**
* List of recma (esast, JavaScript) plugins
*/
recmaPlugins?: import("unified/types/ts3.4/").PluggableList<import("unified/types/ts3.4/").Settings>;
/**
* List of remark (mdast, markdown) plugins
*/
remarkPlugins?: import("unified/types/ts3.4/").PluggableList<import("unified/types/ts3.4/").Settings>;
/**
* List of rehype (hast, HTML) plugins
*/
rehypePlugins?: import("unified/types/ts3.4/").PluggableList<import("unified/types/ts3.4/").Settings>;

@@ -52,0 +90,0 @@ };

@@ -8,6 +8,6 @@ import {compile, compileSync} from './core.js'

* @typedef RunnerOptions
* @property {*} [Fragment]
* @property {*} [jsx]
* @property {*} [jsxs]
* @property {*} [useMDXComponents]
* @property {*} Fragment Symbol to use for fragments
* @property {*} jsx Function to generate an element with static children
* @property {*} jsxs Function to generate an element with dynamic children
* @property {*} [useMDXComponents] Function to get `MDXComponents` from context
*

@@ -23,5 +23,6 @@ * @typedef {Omit<BaseProcessorOptions, "jsx" | "_contain"> } ProcessorOptions

/**
* Evaluate MDX.
*
* @param {VFileCompatible} file
* @param {ProcessorAndRunnerOptions} [options]
* @param {VFileCompatible} file MDX document to parse (`string`, `Buffer`, `vfile`, anything that can be given to `vfile`)
* @param {ProcessorAndRunnerOptions} options
* @return {Promise<ExportMap>}

@@ -38,5 +39,6 @@ */

/**
* Synchronously evaluate MDX.
*
* @param {VFileCompatible} file
* @param {ProcessorAndRunnerOptions} [options]
* @param {VFileCompatible} file MDX document to parse (`string`, `Buffer`, `vfile`, anything that can be given to `vfile`)
* @param {ProcessorAndRunnerOptions} options
* @return {ExportMap}

@@ -50,7 +52,7 @@ */

/**
* Split processor/compiler options from runner options
* Split processor/compiler options from runner options.
*
* @param {ProcessorAndRunnerOptions} [options]
* @param {ProcessorAndRunnerOptions} options
*/
function split(options = {}) {
function split(options) {
var {

@@ -64,3 +66,3 @@ Fragment,

useMDXComponents
} = options
} = options || {}

@@ -67,0 +69,0 @@ if (!Fragment) throw new Error('Expected `Fragment` given to `evaluate`')

/**
* @typedef RecmaDocumentOptions
* @property {boolean} contain
* @property {string} [pragma]
* @property {string} [pragmaFrag]
* @property {string} [pragmaImportSource]
* @property {string} [jsxImportSource]
* @property {'automatic' | 'classic'} [jsxRuntime]
* @property {boolean} [contain] Semihidden option which here results in failing on imports and adding a top-level return statement instead of an export.
* @property {string} [pragma='React.createElement'] Pragma for JSX (used in classic runtime)
* @property {string} [pragmaFrag='React.Fragment'] Pragma for JSX fragments (used in classic runtime)
* @property {string} [pragmaImportSource='react'] Where to import the identifier of `pragma` from (used in classic runtime)
* @property {string} [jsxImportSource='react'] Place to import automatic JSX runtimes from (used in automatic runtime)
* @property {'automatic' | 'classic'} [jsxRuntime='automatic'] JSX runtime to use
*/
/**
* A plugin to wrap the estree in `MDXContent`.
*
* @param {RecmaDocumentOptions} [options]

@@ -16,8 +17,26 @@ */

export type RecmaDocumentOptions = {
contain: boolean;
/**
* Semihidden option which here results in failing on imports and adding a top-level return statement instead of an export.
*/
contain?: boolean;
/**
* Pragma for JSX (used in classic runtime)
*/
pragma?: string;
/**
* Pragma for JSX fragments (used in classic runtime)
*/
pragmaFrag?: string;
/**
* Where to import the identifier of `pragma` from (used in classic runtime)
*/
pragmaImportSource?: string;
/**
* Place to import automatic JSX runtimes from (used in automatic runtime)
*/
jsxImportSource?: string;
/**
* JSX runtime to use
*/
jsxRuntime?: 'automatic' | 'classic';
};

@@ -8,8 +8,8 @@ import u from 'unist-builder'

* @typedef RecmaDocumentOptions
* @property {boolean} contain
* @property {string} [pragma]
* @property {string} [pragmaFrag]
* @property {string} [pragmaImportSource]
* @property {string} [jsxImportSource]
* @property {'automatic' | 'classic'} [jsxRuntime]
* @property {boolean} [contain] Semihidden option which here results in failing on imports and adding a top-level return statement instead of an export.
* @property {string} [pragma='React.createElement'] Pragma for JSX (used in classic runtime)
* @property {string} [pragmaFrag='React.Fragment'] Pragma for JSX fragments (used in classic runtime)
* @property {string} [pragmaImportSource='react'] Where to import the identifier of `pragma` from (used in classic runtime)
* @property {string} [jsxImportSource='react'] Place to import automatic JSX runtimes from (used in automatic runtime)
* @property {'automatic' | 'classic'} [jsxRuntime='automatic'] JSX runtime to use
*/

@@ -19,2 +19,3 @@

* A plugin to wrap the estree in `MDXContent`.
*
* @param {RecmaDocumentOptions} [options]

@@ -21,0 +22,0 @@ */

@@ -5,3 +5,3 @@ /**

* @typedef RecmaJsxBuildOptions
* @property {boolean} [contain]
* @property {boolean} [contain] Semihidden option which here results in getting the automatic runtime from `arguments[0]` instead of importing it
*/

@@ -17,3 +17,6 @@ /**

export type RecmaJsxBuildOptions = {
/**
* Semihidden option which here results in getting the automatic runtime from `arguments[0]` instead of importing it
*/
contain?: boolean;
};

@@ -8,3 +8,3 @@ import build from 'estree-util-build-jsx'

* @typedef RecmaJsxBuildOptions
* @property {boolean} [contain]
* @property {boolean} [contain] Semihidden option which here results in getting the automatic runtime from `arguments[0]` instead of importing it
*/

@@ -22,3 +22,2 @@

/**
*
* @param {Program} tree

@@ -31,3 +30,9 @@ */

// `jsx`, `jsxs`, and `Fragment` from `arguments[0]` instead.
if (contain && tree.body[0] && tree.body[0].type === 'ImportDeclaration') {
if (
contain &&
tree.body[0] &&
tree.body[0].type === 'ImportDeclaration' &&
typeof tree.body[0].source.value === 'string' &&
/\/jsx-runtime$/.test(tree.body[0].source.value)
) {
// @ts-ignore assume this is not missing properties

@@ -34,0 +39,0 @@ tree.body[0] = u('VariableDeclaration', {

@@ -5,4 +5,4 @@ /**

* @typedef RecmaJsxRewriteOptions
* @property {string} [providerImportSource]
* @property {boolean} [contain]
* @property {boolean} [contain] Semihidden option which here results in getting `useMDXComponents` from `arguments[0]` instead of importing it
* @property {string} [providerImportSource] Place to import a provider from
*/

@@ -21,4 +21,10 @@ /**

export type RecmaJsxRewriteOptions = {
/**
* Semihidden option which here results in getting `useMDXComponents` from `arguments[0]` instead of importing it
*/
contain?: boolean;
/**
* Place to import a provider from
*/
providerImportSource?: string;
contain?: boolean;
};

@@ -10,4 +10,4 @@ import isIdentifierName from 'estree-util-is-identifier-name'

* @typedef RecmaJsxRewriteOptions
* @property {string} [providerImportSource]
* @property {boolean} [contain]
* @property {boolean} [contain] Semihidden option which here results in getting `useMDXComponents` from `arguments[0]` instead of importing it
* @property {string} [providerImportSource] Place to import a provider from
*/

@@ -28,3 +28,2 @@

/**
*
* @param {Program} tree

@@ -31,0 +30,0 @@ */

@@ -7,6 +7,7 @@ /**

* @typedef RecmaStringifyOptions
* @property {SourceMapGenerator} [SourceMapGenerator]
* @property {SourceMapGenerator} [SourceMapGenerator] Generate a source map by passing a `SourceMapGenerator` from `source-map` in
*/
/**
* A small wrapper around `astring` to add support for serializing JSX.
* A plugin that adds an esast compiler: a small wrapper around `astring` to add
* support for serializing JSX.
*

@@ -23,6 +24,7 @@ * @param {RecmaStringifyOptions} [options]

* @typedef RecmaStringifyOptions
* @property {SourceMapGenerator} [SourceMapGenerator]
* @property {SourceMapGenerator} [SourceMapGenerator] Generate a source map by passing a `SourceMapGenerator` from `source-map` in
*/
/**
* A small wrapper around `astring` to add support for serializing JSX.
* A plugin that adds an esast compiler: a small wrapper around `astring` to add
* support for serializing JSX.
*

@@ -38,3 +40,6 @@ * @param {RecmaStringifyOptions} [options]

export type RecmaStringifyOptions = {
/**
* Generate a source map by passing a `SourceMapGenerator` from `source-map` in
*/
SourceMapGenerator?: SourceMapGenerator;
};

@@ -11,7 +11,8 @@ // @ts-ignore baseGenerator is not yet exported by astring typings

* @typedef RecmaStringifyOptions
* @property {SourceMapGenerator} [SourceMapGenerator]
* @property {SourceMapGenerator} [SourceMapGenerator] Generate a source map by passing a `SourceMapGenerator` from `source-map` in
*/
/**
* A small wrapper around `astring` to add support for serializing JSX.
* A plugin that adds an esast compiler: a small wrapper around `astring` to add
* support for serializing JSX.
*

@@ -26,3 +27,2 @@ * @param {RecmaStringifyOptions} [options]

/**
*
* @param {Program} tree

@@ -194,3 +194,3 @@ * @param {VFile} file

function JSXText(node, state) {
// `raw` is currently always be set, but could be missing if something injects
// `raw` is currently always set, but could be missing if something injects
// a `JSXText` into the tree.

@@ -197,0 +197,0 @@ // Preferring `raw` over `value` means character references are kept as-is.

@@ -12,3 +12,2 @@ /**

/**
*
* @param {Node} tree

@@ -15,0 +14,0 @@ * @return {void}

@@ -17,3 +17,2 @@ import visit from 'unist-util-visit'

/**
*
* @param {Node} tree

@@ -20,0 +19,0 @@ * @return {void}

@@ -6,2 +6,3 @@ /**

* `file.map` is defined when a `SourceMapGenerator` is passed in options.
*
* @param {string} value

@@ -8,0 +9,0 @@ * @param {*} callback

@@ -9,2 +9,3 @@ import {getOptions} from 'loader-utils'

* `file.map` is defined when a `SourceMapGenerator` is passed in options.
*
* @param {string} value

@@ -11,0 +12,0 @@ * @param {*} callback

{
"name": "xdm",
"version": "1.1.0",
"version": "1.2.0",
"description": "an MDX compiler",

@@ -25,4 +25,7 @@ "license": "MIT",

"types": "./index.d.ts",
"sideEffects": false,
"files": [
"lib/",
"esbuild.js",
"esbuild.d.ts",
"index.js",

@@ -66,3 +69,3 @@ "index.d.ts",

"c8": "^7.0.0",
"convert-source-map": "^1.0.0",
"esbuild": "^0.8.0",
"eslint-plugin-es": "^4.0.0",

@@ -154,2 +157,18 @@ "eslint-plugin-security": "^1.0.0",

}
},
{
"files": [
"lib/esbuild.js"
],
"rules": {
"eqeqeq": [
"error",
"always",
{
"null": "ignore"
}
],
"no-eq-null": "off",
"security/detect-non-literal-fs-filename": "off"
}
}

@@ -156,0 +175,0 @@ ]

@@ -16,3 +16,3 @@ # xdm

maps, ESM only, defaulting to an automatic JSX runtime, no Babel, smallish
browser size, more docs).
browser size, more docs, esbuild plugin).

@@ -73,2 +73,3 @@ ## Install

* [Differences from `@mdx-js/mdx`](#differences-from-mdx-jsmdx)
* [Architecture](#architecture)
* [Security](#security)

@@ -113,4 +114,4 @@ * [Related](#related)

See [§ MDX syntax][mdx-syntax] on how the format works.
See [§ Integrations][integrations] on how to use **xdm** with webpack, Rollup,
Babel, etc.
See [§ Integrations][integrations] on how to use **xdm** with Babel, esbuild,
Rollup, webpack, etc.

@@ -206,2 +207,5 @@ Say we have an MDX document, `example.mdx`:

`xdm/esbuild.js` exports a function that returns an esbuild plugin as the
default export.
### `compile(file, options?)`

@@ -424,3 +428,3 @@

Place to import automatic JSX runtimes from (`string?`, default: `react`).
Place to import automatic JSX runtimes from (`string?`, default: `'react'`).
When in the `automatic` runtime, this is used to define an import for

@@ -546,3 +550,3 @@ `_Fragment`, `_jsx`, and `_jsxs`.

To get the full power of MDX it’s suggested to use `compile`, write to a file,
and then run with Node or bundle with webpack/Rollup.
and then run with Node or bundle with esbuild/Rollup/webpack.
But if you trust your content and know that it doesn’t contain imports,

@@ -891,34 +895,17 @@ `evaluate` can work.

#### Webpack
#### esbuild
Install `xdm` and use `xdm/webpack.cjs`.
Add something along these lines to your `webpack.config.js`:
Install `xdm` and use `xdm/esbuild.js`.
Add something along these lines to your `build` call:
```js
module.exports = {
module: {
// …
rules: [
// …
{test: /\.mdx$/, use: [{loader: 'xdm/webpack.cjs', options: {}}]}
]
}
}
```
import xdm from 'xdm/esbuild.js'
import esbuild from 'esbuild'
Source maps are supported when [`SourceMapGenerator`][sm] is passed in.
If you use modern JavaScript features you might want to use Babel through
[`babel-loader`](https://webpack.js.org/loaders/babel-loader/) to compile to
code that works:
```js
// …
use: [
// Note that Webpack runs right-to-left: `xdm` is used first, then
// `babel-loader`.
{loader: 'babel-loader', options: {}},
{loader: 'xdm/webpack.cjs', options: {}}
]
// …
await esbuild.build({
entryPoints: ['index.mdx'],
outfile: 'output.js',
format: 'esm',
plugins: [xdm({/* Options… */})]
})
```

@@ -980,2 +967,36 @@

#### Webpack
Install `xdm` and use `xdm/webpack.cjs`.
Add something along these lines to your `webpack.config.js`:
```js
module.exports = {
module: {
// …
rules: [
// …
{test: /\.mdx$/, use: [{loader: 'xdm/webpack.cjs', options: {}}]}
]
}
}
```
Source maps are supported when [`SourceMapGenerator`][sm] is passed in.
If you use modern JavaScript features you might want to use Babel through
[`babel-loader`](https://webpack.js.org/loaders/babel-loader/) to compile to
code that works:
```js
// …
use: [
// Note that Webpack runs right-to-left: `xdm` is used first, then
// `babel-loader`.
{loader: 'babel-loader', options: {}},
{loader: 'xdm/webpack.cjs', options: {}}
]
// …
```
### Build systems

@@ -1449,2 +1470,86 @@

#### Syntax highlighting with the `meta` field
Markdown supports a meta string for code:
````markdown
```js filename="index.js"
console.log(1)
```
````
This is a *hidden* part of markdown: it’s normally not rendered.
But as the above example shows, it’s a useful place to put some extra fields.
**xdm** doesn’t know whether you’re handling code as a component or what the
format of that meta string is, so it defaults to how markdown handles it: `meta`
is ignored.
But it’s possible to pass that string as a prop by writing a rehype plugin:
```js
function rehypeMetaAsAttribute() {
return transform
}
function transform(tree) {
visit(tree, 'element', onelement)
}
function onelement(node) {
if (node.tagName === 'code' && node.data && node.data.meta) {
node.properties.meta = node.data.meta
}
}
```
This would yields the following JSX:
```jsx
<pre>
<code class="language-js" meta='filename="index.js"'>
console.log(1)
</code>
</pre>
```
Note that the `meta` attribute is not valid HTML, so make sure to handle `code`
with a component.
The meta string in this example looks a lot like HTML attributes.
What if we wanted to parse that string and add each “attribute” as a prop?
Using the same rehype plugin as above, but with a different `onelement`
function, that can be achieved:
```js
var re = /\b([-\w]+)(?:=(?:"([^"]*)"|'([^']*)'|([^"'\s]+)))?/g
// …
function onelement(node) {
var match
if (node.tagName === 'code' && node.data && node.data.meta) {
re.lastIndex = 0 // Reset regex.
while ((match = re.exec(node.data.meta))) {
node.properties[match[1]] = match[2] || match[3] || match[4] || ''
}
}
}
```
This would yields the following JSX:
```jsx
<pre>
<code class="language-js" filename="index.js">
console.log(1)
</code>
</pre>
```
Note that the these added attributes are not valid HTML, so make sure to handle
`code` with a component.
### Math

@@ -1749,2 +1854,74 @@

## Architecture
To understand what this project does, it’s very important to first understand
what unified does: please read through the
[`unifiedjs/unified`](https://github.com/unifiedjs/unified) readme (the part
until you hit the API section is required reading).
**xdm** is a unified pipeline — wrapped so that most folks don’t need to know
about unified: [`core.js#L76-L101`](https://github.com/wooorm/xdm/blob/e4c2340b41d3354617aa42350306fd35cb57967d/lib/core.js#L76-L101).
The processor goes through these steps:
1. Parse MDX (serialized markdown with embedded JSX, ESM, and expressions)
to mdast (markdown syntax tree)
2. Transform through remark (markdown ecosystem)
3. Transform mdast to hast (HTML syntax tree)
4. Transform through rehype (HTML ecosystem)
5. Transform hast to esast (JS syntax tree)
6. Do the work needed to get a component
7. Serialize esast as JavaScript
The *input* is MDX (serialized markdown with embedded JSX, ESM, and
expressions).
The markdown is parsed with [`micromark`][micromark] and the embedded JS with
one of its extensions
[`micromark-extension-mdxjs`](https://github.com/micromark/micromark-extension-mdxjs)
(which in turn uses [acorn][]).
Then [`mdast-util-from-markdown`](https://github.com/syntax-tree/mdast-util-from-markdown)
and its extension
[`mdast-util-mdx`](https://github.com/syntax-tree/mdast-util-mdx) are used to
turn the results from the parser into a syntax tree:
[mdast](https://github.com/syntax-tree/mdast).
Markdown is closest to the source format.
This is where [remark plugins][remark-plugins] come in.
Typically, there shouldn’t be much going on here.
But perhaps you want to support GFM (tables and such) or frontmatter?
Then you can add a plugin here: `remark-gfm` or `remark-frontmatter`,
respectively.
After markdown, we go to [hast](https://github.com/syntax-tree/hast) (HTML).
This transormation is done by
[`mdast-util-to-hast`](https://github.com/syntax-tree/mdast-util-to-hast).
Wait, why, what does HTML have to do with it?
Part of the reason is that we care about HTML semantics: we want to know that
something is an `<a>`, not whether it’s a link with a resource (`[text](url)`)
or a reference to a defined link definition (`[text][id]\n\n[id]: url`).
So an HTML AST is *closer* to where we want to go.
Another reason is that there are many things folks need when they go MDX -> JS,
markdown -> HTML, or even folks who only process their HTML -> HTML: use cases
other than xdm.
By having a single AST in these cases and writing a plugin that works on that
AST, that plugin can supports *all* these use cases (for example,
[`rehype-highlight`](https://github.com/rehypejs/rehype-highlight)
for syntax highlighting or
[`rehype-katex`](https://github.com/remarkjs/remark-math/tree/main/packages/rehype-katex)
for math).
So, this is where [rehype plugins][rehype-plugins] come in: most of the plugins,
probably.
Then we go to JavaScript: esast (JS; an AST which is compatible with estree but
looks a bit more like other unist ASTs).
This transformation is done by
[`hast-util-to-estree`](https://github.com/syntax-tree/hast-util-to-estree).
This is a new ecosystem that does not have utilities or plugins yet.
But it’s where **xdm** does its thing: where it adds imports/exports, where it
compiles JSX away into `_jsx()` calls, and where it does the other cool things
that it provides.
Finally, The output is serialized JavaScript.
That final step is done by [astring](https://github.com/davidbonnet/astring), a
small and fast JS generator.
## Security

@@ -1768,5 +1945,5 @@

* [`micromark`](https://github.com/micromark/micromark)
* [`micromark`][micromark]
— Handles parsing of markdown (CommonMark)
* [`acorn`](https://github.com/acornjs/acorn)
* [`acorn`][acorn]
— Handles parsing of JS (ECMAScript)

@@ -1847,1 +2024,5 @@ * [`unifiedjs.com`](https://unifiedjs.com)

[caveats]: #caveats
[micromark]: https://github.com/micromark/micromark
[acorn]: https://github.com/acornjs/acorn
SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc