Description
Initial checklist
- I read the support docs
- I read the contributing guide
- I agree to follow the code of conduct
- I searched issues and couldn’t find anything (or linked relevant results below)
Problem
It could be useful to have a special type for fragments.
A fragment
node type could help some plugins which need to preserve some isolated data for itself or replace a node with an array of nodes. Imagine a component for this case, that results in multiple nodes and has no single 'root' element. The idea is similar to JSX's fragment.
The plugins I bear in mind:
-
include
— another file is imported but it has multiple nodes. It can be done with asplice()
like below:parent.children.splice(index, 1, ...loadedRoot.children)
but having a
fragment
node enables storing additional information (original properties, actual file location etc) in the node for possible future use. -
components
There is no limitation for number of children for the
<template>
element, i.e. a web component could yield multiple children instead itself. If a component gets replaced (like inrehype-componets
plugin), it might be useful to preserve old data for other plugins that work on data based on that plugin.
Solution
Having a following interface could be useful.
interface Fragment <: Parent {
type: "fragment"
}
Alternatives
With rehype, nested root
nodes effectively work as fragments. This was tested running the following example:
const tree = {
type: 'root',
children: [
{ type: 'text', value: 'outside nested root\n' },
{
type: 'element',
tagName: 'div',
children: [
{
type: 'root',
children: [{
type: 'element',
tagName: 'span',
children: [{ type: 'text', value: 'inside nested root' }],
}]}
]
}
],
}
const file = await rehype()
.data('settings', { fragment: true })
.stringify(tree)
console.log(String(file))
This code does not throw and yields the following HTML:
outside nested root
<div><span>inside nested root</span></div>
The proposal is actually made for a sanity in specific cases. I understand that this is not a part of HTML and is rather a common practice in frameworks like React, Vue etc. and could be rejected as well as #20. However, as it could be useful for some plugins and does not require a lot of effort in the implementation, I am bringing this to your consideration.