Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
Add passNode option to pass props.node
Related to: syntax-tree/hast-to-hyperscript#23.
Closes GH-19.
Closes GH-22.

Reviewed-by: Christian Murphy <christian.murphy.42@gmail.com>
Reviewed-by: Titus Wormer <tituswormer@gmail.com>
  • Loading branch information
Rokt33r committed Jul 24, 2020
1 parent 310b133 commit 985b705
Show file tree
Hide file tree
Showing 5 changed files with 62 additions and 2 deletions.
10 changes: 9 additions & 1 deletion index.js
Expand Up @@ -13,6 +13,7 @@ function rehypeReact(options) {
var createElement = settings.createElement
var Fragment = settings.Fragment
var components = settings.components || {}
var passNode = settings.passNode

this.Compiler = compiler

Expand All @@ -38,7 +39,14 @@ function rehypeReact(options) {

// Wrap `createElement` to pass components in.
function h(name, props, children) {
var component = has.call(components, name) ? components[name] : name
var component = name
if (has.call(components, name)) {
component = components[name]
if (passNode) {
props.node = this
}
}

return createElement(component, props, children)
}
}
5 changes: 5 additions & 0 deletions readme.md
Expand Up @@ -134,6 +134,11 @@ instead of `<p>`, so something like this:

React key prefix (`string`, default: `'h-'`).

###### `options.passNode`

Pass the original hast node as `props.node` to custom React components
(`boolean`, default: `false`).

## Security

Use of `rehype-react` can open you up to a [cross-site scripting (XSS)][xss]
Expand Down
21 changes: 21 additions & 0 deletions test.js
Expand Up @@ -141,5 +141,26 @@ test('React ' + React.version, function (t) {
'should transform an element with align property'
)

const headingNode = h('h1')
const Heading1 = function (props) {
return React.createElement('h1', props)
}
t.deepEqual(
unified()
.use(rehype2react, {
createElement: React.createElement,
passNode: true,
components: {
h1: Heading1
}
})
.stringify(u('root', [headingNode, h('p')])),
React.createElement('div', {}, [
React.createElement(Heading1, {key: 'h-2', node: headingNode}, undefined),
React.createElement('p', {key: 'h-3'}, undefined)
]),
'should expose node from node prop'
)

t.end()
})
15 changes: 14 additions & 1 deletion types/index.d.ts
Expand Up @@ -2,11 +2,17 @@

import {Transformer} from 'unified'
import {Prefix, CreateElementLike} from 'hast-to-hyperscript'
import {Node} from 'unist'

declare namespace rehypeReact {
type FragmentLike<T> = (props: any) => T | null

type ComponentLike<T> = (props: {[prop: string]: unknown}) => T | null
interface ComponentProps {
[prop: string]: unknown
node?: Node
}

type ComponentLike<T> = (props: ComponentProps) => T | null

interface Options<H extends CreateElementLike> {
/**
Expand Down Expand Up @@ -34,6 +40,13 @@ declare namespace rehypeReact {
* @defaultValue 'h-'
*/
prefix?: Prefix

/**
* Expose HAST Node objects to `node` prop of react components
*
* @defaultValue false
*/
passNode?: boolean
}
}

Expand Down
13 changes: 13 additions & 0 deletions types/rehype-react-test.tsx
Expand Up @@ -43,6 +43,19 @@ unified().use(rehypeToReact, {
}
})

unified().use(rehypeToReact, {
createElement: React.createElement,
passNode: true
})

unified().use(rehypeToReact, {
createElement: React.createElement,
passNode: true,
components: {
a: (props: rehypeToReact.ComponentProps) => <a>{props.node}</a>
}
})

// Mismatch between framework of createElement and components or Fragment should fail
unified().use(rehypeToReact, {
createElement: virtualDomCreateElement,
Expand Down

0 comments on commit 985b705

Please sign in to comment.