docs/solutions/ui-bugs/2026-04-02-blockquote-autoformat-must-wrap-nested-quotes.md
The app's > autoformat rule still used the generic block autoformat path for blockquote.
That path assumes the target is a retaggable block. After blockquote became a container element, the rule still worked at the root through normalization, but it failed inside an existing quote where nested wrapping was required.
/blocks/editor-ai, typing > at the start of a paragraph inside a blockquote left > as plain text.> still produced a blockquote, so the regression only showed up once a quote already existed.blockquote > blockquote > pblockquote > p with text > hellopackages/autoformat. The package-level block transform behaved exactly as designed for flat block types.type: KEYS.blockquote alone. That goes through setNodes, which is the wrong operation for a wrapper element.toggleBlock(..., { wrap: true }) for this seam. Inside an existing quote, toggle semantics can unwrap instead of nesting.Make the app rule explicit about blockquote being a wrapper:
allowSameTypeAbove: true so the rule can fire while already inside a quoteeditor.tf.wrapNodes({ type: KEYS.blockquote, children: [] })> and nested > inside an existing quoteThe fixed rule became:
{
allowSameTypeAbove: true,
format: (editor) => {
editor.tf.wrapNodes({ children: [], type: KEYS.blockquote });
},
match: '> ',
mode: 'block',
type: KEYS.blockquote,
}
Nested quotes require one blockquote to wrap another block, not one block to change its type field.
wrapNodes(...) preserves that container relationship directly. allowSameTypeAbove: true removes the guard that previously blocked the rule the moment the cursor was already inside a quote.
#4898