Skip to content

Commit 985b705

Browse files
authored
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>
1 parent 310b133 commit 985b705

File tree

5 files changed

+62
-2
lines changed

5 files changed

+62
-2
lines changed

index.js

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ function rehypeReact(options) {
1313
var createElement = settings.createElement
1414
var Fragment = settings.Fragment
1515
var components = settings.components || {}
16+
var passNode = settings.passNode
1617

1718
this.Compiler = compiler
1819

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

3940
// Wrap `createElement` to pass components in.
4041
function h(name, props, children) {
41-
var component = has.call(components, name) ? components[name] : name
42+
var component = name
43+
if (has.call(components, name)) {
44+
component = components[name]
45+
if (passNode) {
46+
props.node = this
47+
}
48+
}
49+
4250
return createElement(component, props, children)
4351
}
4452
}

readme.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -134,6 +134,11 @@ instead of `<p>`, so something like this:
134134

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

137+
###### `options.passNode`
138+
139+
Pass the original hast node as `props.node` to custom React components
140+
(`boolean`, default: `false`).
141+
137142
## Security
138143

139144
Use of `rehype-react` can open you up to a [cross-site scripting (XSS)][xss]

test.js

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -141,5 +141,26 @@ test('React ' + React.version, function (t) {
141141
'should transform an element with align property'
142142
)
143143

144+
const headingNode = h('h1')
145+
const Heading1 = function (props) {
146+
return React.createElement('h1', props)
147+
}
148+
t.deepEqual(
149+
unified()
150+
.use(rehype2react, {
151+
createElement: React.createElement,
152+
passNode: true,
153+
components: {
154+
h1: Heading1
155+
}
156+
})
157+
.stringify(u('root', [headingNode, h('p')])),
158+
React.createElement('div', {}, [
159+
React.createElement(Heading1, {key: 'h-2', node: headingNode}, undefined),
160+
React.createElement('p', {key: 'h-3'}, undefined)
161+
]),
162+
'should expose node from node prop'
163+
)
164+
144165
t.end()
145166
})

types/index.d.ts

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,17 @@
22

33
import {Transformer} from 'unified'
44
import {Prefix, CreateElementLike} from 'hast-to-hyperscript'
5+
import {Node} from 'unist'
56

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

9-
type ComponentLike<T> = (props: {[prop: string]: unknown}) => T | null
10+
interface ComponentProps {
11+
[prop: string]: unknown
12+
node?: Node
13+
}
14+
15+
type ComponentLike<T> = (props: ComponentProps) => T | null
1016

1117
interface Options<H extends CreateElementLike> {
1218
/**
@@ -34,6 +40,13 @@ declare namespace rehypeReact {
3440
* @defaultValue 'h-'
3541
*/
3642
prefix?: Prefix
43+
44+
/**
45+
* Expose HAST Node objects to `node` prop of react components
46+
*
47+
* @defaultValue false
48+
*/
49+
passNode?: boolean
3750
}
3851
}
3952

types/rehype-react-test.tsx

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,19 @@ unified().use(rehypeToReact, {
4343
}
4444
})
4545

46+
unified().use(rehypeToReact, {
47+
createElement: React.createElement,
48+
passNode: true
49+
})
50+
51+
unified().use(rehypeToReact, {
52+
createElement: React.createElement,
53+
passNode: true,
54+
components: {
55+
a: (props: rehypeToReact.ComponentProps) => <a>{props.node}</a>
56+
}
57+
})
58+
4659
// Mismatch between framework of createElement and components or Fragment should fail
4760
unified().use(rehypeToReact, {
4861
createElement: virtualDomCreateElement,

0 commit comments

Comments
 (0)