Socket
Socket
Sign inDemoInstall

rehype-react

Package Overview
Dependencies
Maintainers
2
Versions
26
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

rehype-react - npm Package Compare versions

Comparing version 7.2.0 to 8.0.0

43

index.d.ts
import type {Root} from 'hast'
import type {ReactElement} from 'react'
import type {Plugin} from 'unified'
import type {Options} from './lib/index.js'
export type {Components, Options} from 'hast-util-to-jsx-runtime'
/**
* Plugin to compile to React
* Turn HTML into preact, react, solid, svelte, vue, etc.
*
* ###### Result
*
* This plugin registers a compiler that returns a `JSX.Element` where
* compilers typically return `string`.
* When using `.stringify` on `unified`, the result is such a `JSX.Element`.
* When using `.process` (or `.processSync`), the result is available at
* `file.result`.
*
* ###### Frameworks
*
* There are differences between what JSX frameworks accept, such as whether
* they accept `class` or `className`, or `background-color` or
* `backgroundColor`.
*
* For hast elements transformed by this project, this is be handled through
* options:
*
* | Framework | `elementAttributeNameCase` | `stylePropertyNameCase` |
* | --------- | -------------------------- | ----------------------- |
* | Preact | `'html'` | `'dom'` |
* | React | `'react'` | `'dom'` |
* | Solid | `'html'` | `'css'` |
* | Vue | `'html'` | `'dom'` |
*
* @param options
* Configuration.
* Configuration (required).
* @returns
* Nothing.
*/
// Note: defining all react nodes as result value seems to trip TS up.
declare const rehypeReact: Plugin<[Options], Root, ReactElement<unknown>>
declare const rehypeReact: Plugin<[Options], Root, JSX.Element>
export default rehypeReact
export type {Options} from './lib/index.js'
// Register the result type.
declare module 'unified' {
interface CompileResultMap {
JsxElement: JSX.Element
}
}

@@ -0,1 +1,2 @@

// Note: types exposed from `index.d.ts`.
export {default} from './lib/index.js'

64

lib/index.d.ts

@@ -1,55 +0,13 @@

export default function rehypeReact(
this: import('unified').Processor<
void,
import('hast').Root,
import('hast').Root,
import('react').ReactElement<
unknown,
string | import('react').JSXElementConstructor<any>
>
>,
settings_0: Options
): void
export type Root = import('hast').Root
export type ReactNode = import('react').ReactNode
export type ReactElement = import('react').ReactElement<unknown>
export type CreateElementLike = (
name: any,
props: any,
...children: ReactNode[]
) => ReactNode
/**
* Base configuration (without `components`).
* Turn HTML into preact, react, solid, svelte, vue, etc.
*
* @param {Options} options
* Configuration (required).
* @returns {undefined}
* Nothing.
*/
export type SharedOptions = {
/**
* How to create elements or components.
* You should typically pass `React.createElement`.
*/
createElement: CreateElementLike
/**
* Create fragments instead of an outer `<div>` if available.
* You should typically pass `React.Fragment`.
*/
Fragment?: ((props: any) => ReactNode) | undefined
/**
* React key prefix.
*/
prefix?: string | undefined
/**
* Fix obsolete align attributes on table cells by turning them
* into inline styles.
* Keep it on when working with markdown, turn it off when working
* with markup for emails.
* The default is `true`.
*/
fixTableCellAlign?: boolean | undefined
}
/**
* Configuration.
*/
export type Options = SharedOptions &
(
| import('./complex-types').ComponentsWithNodeOptions
| import('./complex-types').ComponentsWithoutNodeOptions
)
export default function rehypeReact(options: Options): undefined;
export type Root = import('hast').Root;
export type Options = import('hast-util-to-jsx-runtime').Options;
export type Compiler = import('unified').Compiler<Root, JSX.Element>;
export type Processor = import('unified').Processor<undefined, undefined, undefined, Root, JSX.Element>;
/**
* @typedef {import('hast').Root} Root
* @typedef {import('react').ReactNode} ReactNode
* @typedef {import('react').ReactElement<unknown>} ReactElement
*
* @callback CreateElementLike
* @param {any} name
* @param {any} props
* @param {...ReactNode} children
* @returns {ReactNode}
*
* @typedef SharedOptions
* Base configuration (without `components`).
* @property {CreateElementLike} createElement
* How to create elements or components.
* You should typically pass `React.createElement`.
* @property {((props: any) => ReactNode)|undefined} [Fragment]
* Create fragments instead of an outer `<div>` if available.
* You should typically pass `React.Fragment`.
* @property {string|undefined} [prefix='h-']
* React key prefix.
* @property {boolean|undefined} [fixTableCellAlign=true]
* Fix obsolete align attributes on table cells by turning them
* into inline styles.
* Keep it on when working with markdown, turn it off when working
* with markup for emails.
* The default is `true`.
*
* @typedef {SharedOptions & (import('./complex-types').ComponentsWithNodeOptions|import('./complex-types').ComponentsWithoutNodeOptions)} Options
* Configuration.
* @typedef {import('hast-util-to-jsx-runtime').Options} Options
* @typedef {import('unified').Compiler<Root, JSX.Element>} Compiler
* @typedef {import('unified').Processor<undefined, undefined, undefined, Root, JSX.Element>} Processor
*/
import {toH} from 'hast-to-hyperscript'
// @ts-expect-error: hush.
import tableCellStyle from '@mapbox/hast-util-table-cell-style'
import {whitespace} from 'hast-util-whitespace'
import {toJsxRuntime} from 'hast-util-to-jsx-runtime'
const own = {}.hasOwnProperty
const tableElements = new Set(['table', 'thead', 'tbody', 'tfoot', 'tr'])
/**
* Compile HTML to React nodes.
* Turn HTML into preact, react, solid, svelte, vue, etc.
*
* > 👉 **Note**: this compiler returns a React node where compilers typically
* > return `string`.
* > When using `.stringify`, the result is such a React node.
* > When using `.process` (or `.processSync`), the result is available at
* > `file.result`.
*
* @this {import('unified').Processor}
* @type {import('unified').Plugin<[Options], Root, ReactElement>}
* @param {Options} options
* Configuration (required).
* @returns {undefined}
* Nothing.
*/
export default function rehypeReact(options) {
if (!options || typeof options.createElement !== 'function') {
throw new TypeError('createElement is not a function')
}
// @ts-expect-error: TypeScript doesn’t handle `this` well.
// eslint-disable-next-line unicorn/no-this-assignment
const self = /** @type {Processor} */ (this)
const createElement = options.createElement
self.compiler = compiler
const fixTableCellAlign = options.fixTableCellAlign !== false
Object.assign(this, {Compiler: compiler})
/** @type {import('unified').CompilerFunction<Root, ReactNode>} */
function compiler(node) {
/** @type {ReactNode} */
let result = toH(
// @ts-expect-error: assume `name` is a known element.
h,
fixTableCellAlign ? tableCellStyle(node) : node,
options.prefix
)
if (node.type === 'root') {
// Invert <https://github.com/syntax-tree/hast-to-hyperscript/blob/d227372/index.js#L46-L56>.
result =
result &&
typeof result === 'object' &&
'type' in result &&
'props' in result &&
result.type === 'div' &&
(node.children.length !== 1 || node.children[0].type !== 'element')
? // `children` does exist.
// type-coverage:ignore-next-line
result.props.children
: [result]
return createElement(options.Fragment || 'div', {}, result)
}
return result
/** @type {Compiler} */
function compiler(tree, file) {
return toJsxRuntime(tree, {filePath: file.path, ...options})
}
/**
* @param {keyof JSX.IntrinsicElements} name
* @param {Record<string, unknown>} props
* @param {Array<ReactNode>} [children]
* @returns {ReactNode}
*/
function h(name, props, children) {
// Currently, a warning is triggered by react for *any* white space in
// tables.
// So we remove the pretty lines for now.
// See: <https://github.com/facebook/react/pull/7081>.
// See: <https://github.com/facebook/react/pull/7515>.
// See: <https://github.com/remarkjs/remark-react/issues/64>.
// See: <https://github.com/rehypejs/rehype-react/pull/29>.
// See: <https://github.com/rehypejs/rehype-react/pull/32>.
// See: <https://github.com/rehypejs/rehype-react/pull/45>.
if (children && tableElements.has(name)) {
children = children.filter((child) => !whitespace(child))
}
if (options.components && own.call(options.components, name)) {
const component = options.components[name]
if (options.passNode && typeof component === 'function') {
// @ts-expect-error: `toH` passes the current node.
// type-coverage:ignore-next-line
props = Object.assign({node: this}, props)
}
return createElement(component, props, children)
}
return createElement(name, props, children)
}
}
{
"name": "rehype-react",
"description": "rehype plugin to transform to React",
"version": "7.2.0",
"version": "8.0.0",
"license": "MIT",
"keywords": [
"unified",
"hast",
"html",
"plugin",
"preact",
"react",
"rehype",
"rehype-plugin",
"plugin",
"html",
"hast",
"react"
"solid",
"svelte",
"unified",
"vue"
],

@@ -40,4 +44,3 @@ "repository": "rehypejs/rehype-react",

"type": "module",
"main": "index.js",
"types": "index.d.ts",
"exports": "./index.js",
"files": [

@@ -49,54 +52,40 @@ "lib/",

"dependencies": {
"@mapbox/hast-util-table-cell-style": "^0.2.0",
"@types/hast": "^2.0.0",
"hast-to-hyperscript": "^10.0.0",
"hast-util-whitespace": "^2.0.0",
"unified": "^10.0.0"
"@types/hast": "^3.0.0",
"hast-util-to-jsx-runtime": "^2.0.0",
"unified": "^11.0.0"
},
"peerDependencies": {
"@types/react": ">=17"
},
"devDependencies": {
"@types/node": "^20.0.0",
"@types/react": "^18.0.0",
"@types/react-dom": "^18.0.0",
"@types/tape": "^4.0.0",
"c8": "^7.0.0",
"hastscript": "^7.0.0",
"prettier": "^2.0.0",
"c8": "^8.0.0",
"hastscript": "^8.0.0",
"prettier": "^3.0.0",
"react": "^18.0.0",
"react-dom": "^18.0.0",
"remark": "^14.0.0",
"remark-cli": "^11.0.0",
"remark-preset-wooorm": "^9.0.0",
"rimraf": "^3.0.0",
"tape": "^5.0.0",
"type-coverage": "^2.0.0",
"typescript": "^5.0.0",
"unist-builder": "^3.0.0",
"xo": "^0.54.0"
"xo": "^0.56.0"
},
"scripts": {
"build": "rimraf \"lib/*.d.ts\" \"test.d.ts\" && tsc && type-coverage",
"format": "remark . -qfo && prettier . -w --loglevel warn && xo --fix",
"build": "tsc --build --clean && tsc --build && type-coverage",
"format": "remark . --frail --output --quiet && prettier . --log-level warn --write && xo --fix",
"prepack": "npm run build && npm run format",
"test": "npm run build && npm run format && npm run test-coverage",
"test-api": "node --conditions development test.js",
"test-coverage": "c8 --check-coverage --branches 100 --functions 100 --lines 100 --statements 100 --reporter lcov npm run test-api",
"test": "npm run build && npm run format && npm run test-coverage"
"test-coverage": "c8 --100 --check-coverage --reporter lcov npm run test-api"
},
"prettier": {
"tabWidth": 2,
"useTabs": false,
"bracketSpacing": false,
"singleQuote": true,
"bracketSpacing": false,
"semi": false,
"trailingComma": "none"
"tabWidth": 2,
"trailingComma": "none",
"useTabs": false
},
"xo": {
"prettier": true,
"": "`xo` is wrong about file extensions",
"rules": {
"n/file-extension-in-import": "off"
}
},
"remarkConfig": {
"plugins": [
"preset-wooorm"
"remark-preset-wooorm"
]

@@ -107,9 +96,22 @@ },

"detail": true,
"strict": true,
"ignoreCatch": true,
"#": "needed `any`s",
"ignoreFiles": [
"lib/index.d.ts"
]
"strict": true
},
"xo": {
"overrides": [
{
"files": [
"*.ts"
],
"rules": {
"@typescript-eslint/consistent-type-definitions": "off"
}
}
],
"prettier": true,
"#": "`xo` is wrong about file extensions",
"rules": {
"n/file-extension-in-import": "off"
}
}
}

@@ -11,3 +11,3 @@ # rehype-react

**[rehype][]** plugin to compile HTML to React nodes.
**[rehype][]** plugin to turn HTML into preact, react, solid, svelte, vue, etc.

@@ -22,2 +22,4 @@ ## Contents

* [`unified().use(rehypeReact, options)`](#unifieduserehypereact-options)
* [`Components`](#components)
* [`Options`](#options)
* [Types](#types)

@@ -33,3 +35,3 @@ * [Compatibility](#compatibility)

This package is a [unified][] ([rehype][]) plugin that compiles HTML (hast) to
React nodes (the virtual DOM that React uses).
any JSX runtime (preact, react, solid, svelte, vue, etc).

@@ -40,3 +42,3 @@ **unified** is a project that transforms content with abstract syntax trees

**hast** is the HTML AST that rehype uses.
This is a rehype plugin that adds a compiler to compile hast to React nodes.
This is a rehype plugin that adds a compiler to compile hast to a JSX runtime.

@@ -46,6 +48,6 @@ ## When should I use this?

This plugin adds a compiler for rehype, which means that it turns the final
HTML (hast) syntax tree into something else (in this case, a React node).
HTML (hast) syntax tree into something else (in this case, a `JSX.Element`).
It’s useful when you’re already using unified (whether remark or rehype) or are
open to learning about ASTs (they’re powerful!) and want to render content in
your React app.
your app.

@@ -62,4 +64,4 @@ If you’re not familiar with unified, then [`react-markdown`][react-markdown]

This package is [ESM only](https://gist.github.com/sindresorhus/a39789f98801d908bbc7ff3ecc99d99c).
In Node.js (version 12.20+, 14.14+, or 16.0+), install with [npm][]:
This package is [ESM only][esm].
In Node.js (version 16+), install with [npm][]:

@@ -73,3 +75,3 @@ ```sh

```js
import rehypeReact from 'https://esm.sh/rehype-react@7'
import rehypeReact from 'https://esm.sh/rehype-react@8'
```

@@ -81,3 +83,3 @@

<script type="module">
import rehypeReact from 'https://esm.sh/rehype-react@7?bundle'
import rehypeReact from 'https://esm.sh/rehype-react@8?bundle'
</script>

@@ -88,25 +90,37 @@ ```

Say our React app module `example.js` looks as follows:
Say our React app `example.js` looks as follows:
```js
import {createElement, Fragment, useEffect, useState} from 'react'
import {unified} from 'unified'
import {Fragment, createElement, useEffect, useState} from 'react'
import * as prod from 'react/jsx-runtime'
import rehypeParse from 'rehype-parse'
import rehypeReact from 'rehype-react'
import {unified} from 'unified'
// @ts-expect-error: the react types are missing.
const production = {Fragment: prod.Fragment, jsx: prod.jsx, jsxs: prod.jsxs}
const text = `<h2>Hello, world!</h2>
<p>Welcome to my page 👀</p>`
/**
* @param {string} text
* @returns {JSX.Element}
*/
function useProcessor(text) {
const [Content, setContent] = useState(Fragment)
const [Content, setContent] = useState(createElement(Fragment))
useEffect(() => {
unified()
.use(rehypeParse, {fragment: true})
.use(rehypeReact, {createElement, Fragment})
.process(text)
.then((file) => {
useEffect(
function () {
;(async function () {
const file = await unified()
.use(rehypeParse, {fragment: true})
.use(rehypeReact, production)
.process(text)
setContent(file.result)
})
}, [text])
})()
},
[text]
)

@@ -121,3 +135,3 @@ return Content

Assuming that runs in Next.js, Create React App (CRA), or similar, we’d get:
…running that in Next.js or similar, we’d get:

@@ -132,63 +146,88 @@ ```html

This package exports no identifiers.
The default export is `rehypeReact`.
The default export is [`rehypeReact`][api-rehype-react].
### `unified().use(rehypeReact, options)`
Compile HTML to React nodes.
Turn HTML into preact, react, solid, svelte, vue, etc.
> 👉 **Note**: this compiler returns a React node where compilers typically
> return `string`.
> When using `.stringify`, the result is such a React node.
> When using `.process` (or `.processSync`), the result is available at
> `file.result`.
###### Parameters
##### `options`
* `options` ([`Options`][api-options], required)
— configuration
Configuration (optional).
###### Returns
###### `options.createElement`
Nothing (`undefined`).
How to create elements or components (`Function`, required).
You should typically pass `React.createElement`.
###### Result
###### `options.Fragment`
This plugin registers a compiler that returns a `JSX.Element` where compilers
typically return `string`.
When using `.stringify` on `unified`, the result is such a `JSX.Element`.
When using `.process` (or `.processSync`), the result is available at
`file.result`.
Create fragments instead of an outer `<div>` if available (`symbol`).
You should typically pass `React.Fragment`.
###### Frameworks
###### `options.components`
There are differences between what JSX frameworks accept, such as whether they
accept `class` or `className`, or `background-color` or `backgroundColor`.
Override default elements (such as `<a>`, `<p>`, etc.) by passing an object
mapping tag names to components (`Record<string, Component>`, default: `{}`).
For hast elements transformed by this project, this is be handled through
options:
For example, to use `<MyLink>` components instead of `<a>`, and `<MyParagraph>`
instead of `<p>`, so something like this:
| Framework | `elementAttributeNameCase` | `stylePropertyNameCase` |
| --------- | -------------------------- | ----------------------- |
| Preact | `'html'` | `'dom'` |
| React | `'react'` | `'dom'` |
| Solid | `'html'` | `'css'` |
| Vue | `'html'` | `'dom'` |
```js
// …
.use(rehypeReact, {
createElement: React.createElement,
components: {
a: MyLink,
p: MyParagraph
}
})
// …
```
### `Components`
###### `options.prefix`
Possible components to use (TypeScript type).
React key prefix (`string`, default: `'h-'`).
See [`Components` from
`hast-util-to-jsx-runtime`](https://github.com/syntax-tree/hast-util-to-jsx-runtime#components)
for more info.
###### `options.passNode`
### `Options`
Pass the original hast node as `props.node` to custom React components
(`boolean`, default: `false`).
Configuration (TypeScript type).
###### `options.fixTableCellAlign`
###### Fields
Fix obsolete align attributes on table cells by turning them
into inline styles (`boolean`, default: `true`).
Keep it on when working with markdown, turn it off when working
with markup for emails.
* `Fragment` ([`Fragment` from
`hast-util-to-jsx-runtime`](https://github.com/syntax-tree/hast-util-to-jsx-runtime#fragment),
required)
— fragment
* `jsx` ([`Jsx` from
`hast-util-to-jsx-runtime`](https://github.com/syntax-tree/hast-util-to-jsx-runtime#jsx),
required in production)
— dynamic JSX
* `jsxs` ([`Jsx` from
`hast-util-to-jsx-runtime`](https://github.com/syntax-tree/hast-util-to-jsx-runtime#jsx),
required in production)
— static JSX
* `jsxDEV` ([`JsxDev` from
`hast-util-to-jsx-runtime`](https://github.com/syntax-tree/hast-util-to-jsx-runtime#jsxdev),
required in development)
— development JSX
* `components` ([`Partial<Components>`][api-components], optional)
— components to use
* `development` (`boolean`, default: `false`)
— whether to use `jsxDEV` when on or `jsx` and `jsxs` when off
* `elementAttributeNameCase` (`'html'` or `'react'`, default: `'react'`)
— specify casing to use for attribute names
* `passNode` (`boolean`, default: `false`)
— pass the hast element node to components
* `space` (`'html'` or `'svg'`, default: `'html'`)
— whether `tree` is in the `'html'` or `'svg'` space, when an `<svg>`
element is found in the HTML space, this package already automatically
switches to and from the SVG space when entering and exiting it
* `stylePropertyNameCase`
(`'css'` or `'dom'`, default: `'dom'`)
— specify casing to use for property names in `style` objects
* `tableCellAlignToStyle`
(`boolean`, default: `true`)
— turn obsolete `align` props on `td` and `th` into CSS `style` props

@@ -198,14 +237,19 @@ ## Types

This package is fully typed with [TypeScript][].
It exports an `Options` type, which specifies the interface of the accepted
options.
It exports the additional types [`Components`][api-components] and
[`Options`][api-options].
More advanced types are exposed from
[`hast-util-to-jsx-runtime`][hast-util-to-jsx-runtime].
## Compatibility
Projects maintained by the unified collective are compatible with all maintained
Projects maintained by the unified collective are compatible with maintained
versions of Node.js.
As of now, that is Node.js 12.20+, 14.14+, and 16.0+.
Our projects sometimes work with older versions, but this is not guaranteed.
When we cut a new major release, we drop support for unmaintained versions of
Node.
This means we try to keep the current release line, `rehype-react@^8`,
compatible with Node.js 17.
This plugin works with `rehype-parse` version 3+, `rehype` version 4+, and
`unified` version 9+, and React 16+.
`unified` version 9+, and React 18+.

@@ -258,5 +302,5 @@ ## Security

[size-badge]: https://img.shields.io/bundlephobia/minzip/rehype-react.svg
[size-badge]: https://img.shields.io/bundlejs/size/rehype-react
[size]: https://bundlephobia.com/result?p=rehype-react
[size]: https://bundlejs.com/?q=rehype-react

@@ -275,2 +319,4 @@ [sponsors-badge]: https://opencollective.com/unified/sponsors/badge.svg

[esm]: https://gist.github.com/sindresorhus/a39789f98801d908bbc7ff3ecc99d99c
[esmsh]: https://esm.sh

@@ -280,7 +326,7 @@

[contributing]: https://github.com/rehypejs/.github/blob/HEAD/contributing.md
[contributing]: https://github.com/rehypejs/.github/blob/main/contributing.md
[support]: https://github.com/rehypejs/.github/blob/HEAD/support.md
[support]: https://github.com/rehypejs/.github/blob/main/support.md
[coc]: https://github.com/rehypejs/.github/blob/HEAD/code-of-conduct.md
[coc]: https://github.com/rehypejs/.github/blob/main/code-of-conduct.md

@@ -297,2 +343,14 @@ [license]: license

[hast-util-to-jsx-runtime]: https://github.com/syntax-tree/hast-util-to-jsx-runtime
[mdx]: https://github.com/mdx-js/mdx/
[react-markdown]: https://github.com/remarkjs/react-markdown
[react-remark]: https://github.com/remarkjs/react-remark
[rehype]: https://github.com/rehypejs/rehype
[rehype-sanitize]: https://github.com/rehypejs/rehype-sanitize
[typescript]: https://www.typescriptlang.org

@@ -302,12 +360,8 @@

[rehype]: https://github.com/rehypejs/rehype
[xss]: https://en.wikipedia.org/wiki/Cross-site_scripting
[rehype-sanitize]: https://github.com/rehypejs/rehype-sanitize
[api-components]: #components
[react-markdown]: https://github.com/remarkjs/react-markdown
[api-options]: #options
[react-remark]: https://github.com/remarkjs/react-remark
[mdx]: https://github.com/mdx-js/mdx/
[api-rehype-react]: #unifieduserehypereact-options
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