Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add passNode option to pass props.node #22

Merged
merged 5 commits into from Jul 24, 2020
Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
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`

Expose HAST Node objects to `node` prop of react components
wooorm marked this conversation as resolved.
Show resolved Hide resolved
(`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
ChristianMurphy marked this conversation as resolved.
Show resolved Hide resolved
}

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