Skip to content
Permalink

Comparing changes

Choose two branches to see what’s changed or to start a new pull request. If you need to, you can also or learn more about diff comparisons.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also . Learn more about diff comparisons here.
base repository: rehypejs/rehype-react
Failed to load repositories. Confirm that selected base ref is valid, then try again.
Loading
base: 7.0.3
Choose a base ref
...
head repository: rehypejs/rehype-react
Failed to load repositories. Confirm that selected head ref is valid, then try again.
Loading
compare: 7.0.4
Choose a head ref
  • 4 commits
  • 6 files changed
  • 1 contributor

Commits on Dec 28, 2021

  1. Update dev-dependencies

    wooorm committed Dec 28, 2021

    Verified

    This commit was signed with the committer’s verified signature.
    dtolnay David Tolnay
    Copy the full SHA
    778ae38 View commit details
  2. Refactor

    wooorm committed Dec 28, 2021
    Copy the full SHA
    276884f View commit details

Commits on Jan 6, 2022

  1. Add improved docs

    Closes GH-37.
    
    Reviewed-by: Christian Murphy <christian.murphy.42@gmail.com>
    Reviewed-by: Merlijn Vos <merlijn@soverin.net>
    wooorm authored Jan 6, 2022
    Copy the full SHA
    21753da View commit details
  2. 7.0.4

    wooorm committed Jan 6, 2022
    Copy the full SHA
    41c4e83 View commit details
Showing with 134 additions and 83 deletions.
  1. +0 −1 .prettierignore
  2. +2 −1 index.d.ts
  3. +1 −3 index.js
  4. +1 −1 lib/index.js
  5. +2 −2 package.json
  6. +128 −75 readme.md
1 change: 0 additions & 1 deletion .prettierignore
Original file line number Diff line number Diff line change
@@ -1,3 +1,2 @@
coverage/
*.json
*.md
3 changes: 2 additions & 1 deletion index.d.ts
Original file line number Diff line number Diff line change
@@ -12,4 +12,5 @@ import type {Options} from './lib/index.js'
// Note: defining all react nodes as result value seems to trip TS up.
declare const rehypeReact: Plugin<[Options], Root, ReactElement<unknown>>
export default rehypeReact
export type {Options}

export {Options} from './lib/index.js'
4 changes: 1 addition & 3 deletions index.js
Original file line number Diff line number Diff line change
@@ -1,3 +1 @@
import rehypeReact from './lib/index.js'

export default rehypeReact
export {default} from './lib/index.js'
2 changes: 1 addition & 1 deletion lib/index.js
Original file line number Diff line number Diff line change
@@ -80,7 +80,7 @@ export default function rehypeReact(options) {
/**
* @param {keyof JSX.IntrinsicElements} name
* @param {Record<string, unknown>} props
* @param {unknown[]} [children]
* @param {Array<unknown>} [children]
* @returns {ReactNode}
*/
function h(name, props, children) {
4 changes: 2 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "rehype-react",
"description": "rehype plugin to transform to React",
"version": "7.0.3",
"version": "7.0.4",
"license": "MIT",
"keywords": [
"unified",
@@ -68,7 +68,7 @@
"type-coverage": "^2.0.0",
"typescript": "^4.0.0",
"unist-builder": "^3.0.0",
"xo": "^0.45.0"
"xo": "^0.47.0"
},
"scripts": {
"build": "rimraf \"lib/*.d.ts\" \"test.d.ts\" && tsc && type-coverage",
203 changes: 128 additions & 75 deletions readme.md
Original file line number Diff line number Diff line change
@@ -8,80 +8,112 @@
[![Backers][backers-badge]][collective]
[![Chat][chat-badge]][chat]

[**rehype**][rehype] plugin to transform to [**React**][react].
**[rehype][]** plugin to compile HTML to React nodes.

## Contents

* [What is this?](#what-is-this)
* [When should I use this?](#when-should-i-use-this)
* [Install](#install)
* [Use](#use)
* [API](#api)
* [`unified().use(rehypeReact, options)`](#unifieduserehypereact-options)
* [Types](#types)
* [Compatibility](#compatibility)
* [Security](#security)
* [Related](#related)
* [Contribute](#contribute)
* [License](#license)

## What is this?

This package is a [unified][] ([rehype][]) plugin that compiles HTML (hast) to
React nodes (the virtual DOM that React uses).

**unified** is a project that transforms content with abstract syntax trees
(ASTs).
**rehype** adds support for HTML to unified.
**hast** is the HTML AST that rehype uses.
This is a rehype plugin that adds a compiler to compile hast to React nodes.

## 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).
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.

If you’re not familiar with unified, then [`react-markdown`][react-markdown]
might be a better fit.
You can also use [`react-remark`][react-remark] instead, which is somewhere
between `rehype-react` and `react-markdown`, as it does more that the former and
is more modern (such as supporting hooks) than the latter, and also a good
alternative.
If you want to use JavaScript and JSX *inside* markdown files, use [MDX][].

## Install

This package is [ESM only](https://gist.github.com/sindresorhus/a39789f98801d908bbc7ff3ecc99d99c):
Node 12+ is needed to use it and it must be `import`ed instead of `require`d.

[npm][]:
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][]:

```sh
npm install rehype-react
```

In Deno with [Skypack][]:

```js
import rehypeReact from 'https://cdn.skypack.dev/rehype-react@7?dts'
```

In browsers with [Skypack][]:

```html
<script type="module">
import rehypeReact from 'https://cdn.skypack.dev/rehype-react@7?min'
</script>
```

## Use

The following example shows how to create a markdown input textarea, and
corresponding rendered HTML output.
The Markdown is processed to add a Table of Contents, highlight code blocks, and
to render GitHub mentions (and other cool GH features).
Say our React app module `example.js` looks as follows:

```js
import React from 'react'
import ReactDOM from 'react-dom'
import {createElement, Fragment, useEffect, useState} from 'react'
import {unified} from 'unified'
import remarkParse from 'remark-parse'
import remarkSlug from 'remark-slug'
import remarkToc from 'remark-toc'
import remarkGithub from 'remark-github'
import remarkRehype from 'remark-rehype'
import rehypeHighlight from 'rehype-highlight'
import rehypeParse from 'rehype-parse'
import rehypeReact from 'rehype-react'

const processor = unified()
.use(remarkParse)
.use(remarkSlug)
.use(remarkToc)
.use(remarkGithub, {repository: 'rehypejs/rehype-react'})
.use(remarkRehype)
.use(rehypeHighlight)
.use(rehypeReact, {createElement: React.createElement})

class App extends React.Component {
constructor() {
super()
this.state = {text: '# Hello\n\n## Table of Contents\n\n## @rhysd'}
this.onChange = this.onChange.bind(this)
}

onChange(ev) {
this.setState({text: ev.target.value})
}

render() {
return (
<div>
<textarea value={this.state.text} onChange={this.onChange} />
<div id="preview">{processor.processSync(this.state.text).result}</div>
</div>
)
}
const text = `<h2>Hello, world!</h2>
<p>Welcome to my page 👀</p>`

function useProcessor(text) {
const [Content, setContent] = useState(Fragment)

useEffect(() => {
unified()
.use(rehypeParse, {fragment: true})
.use(rehypeReact, {createElement, Fragment})
.process(text)
.then((file) => {
setContent(file.result)
})
}, [text])

return Content
}

ReactDOM.render(<App />, document.querySelector('#root'))
export default function App() {
return useProcessor(text)
}
```

Yields (in `id="preview"`, on first render):
Assuming that runs in Next.js, Create React App (CRA), or similar, we’d get:

```html
<div><h1 id="hello">Hello</h1>
<h2 id="table-of-contents">Table of Contents</h2>
<ul>
<li><a href="#rhysd">@rhysd</a></li>
</ul>
<h2 id="rhysd"><a href="https://github.com/rhysd"><strong>@rhysd</strong></a></h2></div>
<h2>Hello, world!</h2>
<p>Welcome to my page 👀</p>
```

## API
@@ -91,15 +123,18 @@ The default export is `rehypeReact`.

### `unified().use(rehypeReact, options)`

[**rehype**][rehype] ([hast][]) plugin to transform to [**React**][react].
Compile HTML to React nodes.

Typically, [**unified**][unified] compilers return `string`.
This compiler returns a `ReactElement` (or similar).
When using `.process` or `.processSync`, the value at `file.result` (or when
using `.stringify`, the return value), is such a custom node.
> 👉 **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`.
##### `options`

Configuration (optional).

###### `options.createElement`

How to create elements or components (`Function`, required).
@@ -112,15 +147,15 @@ You should typically pass `React.Fragment`.

###### `options.components`

Override default elements (such as `<a>`, `<p>`, etcetera) by passing an object
mapping tag names to components (`Object.<Component>`, default: `{}`).
Override default elements (such as `<a>`, `<p>`, etc.) by passing an object
mapping tag names to components (`Record<string, Component>`, default: `{}`).

For example, to use `<MyLink>` components instead of `<a>`, and `<MyParagraph>`
instead of `<p>`, so something like this:

```js
//
.use(rehype2react, {
.use(rehypeReact, {
createElement: React.createElement,
components: {
a: MyLink,
@@ -139,22 +174,38 @@ React key prefix (`string`, default: `'h-'`).
Pass the original hast node as `props.node` to custom React components
(`boolean`, default: `false`).

## Types

This package is fully typed with [TypeScript][].
It exports an `Options` type, which specifies the interface of the accepted
options.

## Compatibility

Projects maintained by the unified collective are compatible with all 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.

This plugin works with `rehype-parse` version 3+, `rehype` version 4+, and
`unified` version 9+, and React 16+.

## Security

Use of `rehype-react` can open you up to a [cross-site scripting (XSS)][xss]
attack if the tree is unsafe.
Use [`rehype-sanitize`][sanitize] to make the tree safe.
Use [`rehype-sanitize`][rehype-sanitize] to make the tree safe.

## Related

* [`remark-rehype`](https://github.com/remarkjs/remark-rehype)
— Transform Markdown ([**mdast**][mdast]) to HTML ([**hast**][hast])
* [`rehype-retext`](https://github.com/rehypejs/rehype-retext)
— Transform HTML ([**hast**][hast]) to natural language ([**nlcst**][nlcst])
— turn markdown into HTML to support rehype
* [`rehype-remark`](https://github.com/rehypejs/rehype-remark)
— Transform HTML ([**hast**][hast]) to Markdown ([**mdast**][mdast])
* [`rehype-sanitize`][sanitize]
— Sanitize HTML
— turn HTML into markdown to support remark
* [`rehype-retext`](https://github.com/rehypejs/rehype-retext)
— rehype plugin to support retext
* [`rehype-sanitize`][rehype-sanitize]
— sanitize HTML

## Contribute

@@ -201,6 +252,8 @@ abide by its terms.

[npm]: https://docs.npmjs.com/cli/install

[skypack]: https://www.skypack.dev

[health]: https://github.com/rehypejs/.github

[contributing]: https://github.com/rehypejs/.github/blob/HEAD/contributing.md
@@ -219,18 +272,18 @@ abide by its terms.

[rhysd]: https://rhysd.github.io

[typescript]: https://www.typescriptlang.org

[unified]: https://github.com/unifiedjs/unified

[rehype]: https://github.com/rehypejs/rehype

[mdast]: https://github.com/syntax-tree/mdast

[hast]: https://github.com/syntax-tree/hast
[xss]: https://en.wikipedia.org/wiki/Cross-site_scripting

[nlcst]: https://github.com/syntax-tree/nlcst
[rehype-sanitize]: https://github.com/rehypejs/rehype-sanitize

[react]: https://github.com/facebook/react
[react-markdown]: https://github.com/remarkjs/react-markdown

[xss]: https://en.wikipedia.org/wiki/Cross-site_scripting
[react-remark]: https://github.com/remarkjs/react-remark

[sanitize]: https://github.com/rehypejs/rehype-sanitize
[mdx]: https://github.com/mdx-js/mdx/