Skip to content

Commit 3335b58

Browse files
authored
Add parsing logic for dot notation in component name (#301)
* Add parsing logic for dot notation in component name * Add unit test
1 parent 96dfb7c commit 3335b58

2 files changed

Lines changed: 34 additions & 1 deletion

File tree

source/components/JsxParser.test.tsx

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -450,6 +450,31 @@ describe('JsxParser Component', () => {
450450
const { root } = render(<JsxParser jsx="<h1>Foo</h1><hr />" renderInWrapper={false} />)
451451
expect(root.innerHTML).toEqual('<h1>Foo</h1><hr>')
452452
})
453+
454+
test('resolves nested components through dot notation', () => {
455+
const Nested = {
456+
Button: ({ children, className }) => <button className={className} type="button">{children}</button>,
457+
Div: ({ children, className }) => <div className={className}>{children}</div>,
458+
}
459+
const { node } = render(
460+
<JsxParser
461+
components={{ Nested }}
462+
jsx={`
463+
<Nested.Button className="inner">Click Me</Nested.Button>
464+
<Nested.Div className="outer"/>
465+
`}
466+
/>,
467+
)
468+
469+
const elementNodes = Array.from(node.childNodes).filter(n => n.nodeType === Node.ELEMENT_NODE)
470+
expect(elementNodes).toHaveLength(2)
471+
const [button, div] = elementNodes
472+
expect(button.nodeName).toEqual('BUTTON')
473+
expect(button.className).toEqual('inner')
474+
expect(button.textContent).toEqual('Click Me')
475+
expect(div.nodeName).toEqual('DIV')
476+
expect(div.className).toEqual('outer')
477+
})
453478
})
454479

455480
// Rewritten 'blacklisting & whitelisting' suite

source/components/JsxParser.tsx

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -373,12 +373,20 @@ export default class JsxParser extends React.Component<TProps> {
373373
}
374374

375375
let children
376-
const component = element.type === 'JSXElement'
376+
let component = element.type === 'JSXElement'
377377
? resolvePath(components, name)
378378
: Fragment
379379

380380
if (component || canHaveChildren(name)) {
381381
children = childNodes.map(node => this.#parseExpression(node, scope))
382+
if (name.includes('.')) {
383+
const nameParts = name.split('.')
384+
const componentPath = nameParts
385+
.reduce((acc: any, part) => (acc ? acc[part] : components?.[part]), null)
386+
if (componentPath) {
387+
component = componentPath
388+
}
389+
}
382390
if (!component && !canHaveWhitespace(name)) {
383391
children = children.filter(child => (
384392
typeof child !== 'string' || !/^\s*$/.test(child)

0 commit comments

Comments
 (0)