Problem
We need mixed grouping at the root level.
Solution
After researching the codebase, I believe only 2 options are worth looking at.
Empty block type
PM: empty block is registered as a new block type, in the existing block group, same as paragraph/heading. Its containing blockNode uses its optional blockChildren to hold the grouped children with the desired childrenType.
doc
└── blockChildren (Group)
├── blockNode → paragraph
├── blockNode → empty // renders nothing
│ blockChildren (Unordered)
│ ├── blockNode → paragraph
│ └── blockNode → paragraph
└── blockNode → paragraph
Backend: add HMBlockEmpty (or any name) to HMBlockKnownSchema
{
type: 'Empty',
id: string,
attributes: {
childrenType: HMBlockChildrenType,
columnCount?: number,
}
}
Every existing block type already carries childrenType/columnCount for its children. Empty is just a new block type with no rendering of its own.
Pros:
Backend to editor mapping is one to one.
Extra blocks only when needed. Simple docs have zero extra structure.
PM root shape is unchanged.
Cons:
Introduces an invisible block type. Code that iterates or filters by block type needs to remember to exclude Empty.
New root node type
PM: replace root blockChildren with a new node that contains blockChildren+. Each blockChildren has its own listType/columnCount.
doc
└── docRoot
├── blockChildren (Group)
│ └── blockNode → paragraph
├── blockChildren (Unordered)
│ ├── blockNode → paragraph
│ └── blockNode → paragraph
└── blockChildren (Group)
└── blockNode → paragraph
Backend: same HMBlockEmpty block type as Option A. The editor's shape doesn't map 1:1 to the backend tree, needs custom conversion.
Editor to HM block: each blockChildren under docRoot becomes either:
an array of top level HMBlockNodes (when listType === 'Group')
one HMBlockEmpty HMBlockNode with attributes.childrenType set, its blockNodes as .children.
HM to editor block: iterate the root HMBlockNode[]. Non Empty blocks become blockChildren with listType="Group". Each Empty block becomes blockChildren with the corresponding listType.
Pros:
Editor blockChildren gains a unified meaning: "always a grouping container." Root and nested behave the same. No special case for root listType.
No invisible block type. Menus, type-based filters, and serializers don't need to know about a hidden wrapper.
Cons:
Conversion layer needs new handling. Non-trivial and needs round-trip tests.
Conclusion
Both are roughly the same amount of code and produce the same backend structure. I don't believe 2nd is much easier to maintain in the editor, so I'd lean towards an empty block type.
Do you like what you are reading? Subscribe to receive updates.
Unsubscribe anytime