docs/solutions/logic-errors/2026-03-27-code-block-format-must-rebuild-code-lines.md
formatCodeBlock formatted valid JSON, but syntax highlighting broke immediately afterward.
The bug showed up most clearly when formatting one-line JSON into multi-line JSON from the code-block toolbar.
formatCodeBlock wrote the formatted string back with insertText(..., { at: element }).
That kept the code block as a single code_line node containing embedded \n characters instead of rebuilding separate code_line elements. The syntax highlighter maps decorations by code-line element, so once the formatter collapsed multiple visual lines into one structural line, only the first line had a node that decorations could target. The formatter also did not trigger editor.api.redecorate(), so React could keep rendering the stale decoration pass until another change forced a refresh.
Route formatted code through a shared code-block content transform that replaces the block children with real code_line nodes, then triggers a redecorate pass.
export const setCodeBlockContent = (
editor: SlateEditor,
{ code, element }: { code: string; element: TCodeBlockElement }
) => {
editor.tf.replaceNodes(
code.split('\n').map((line) => ({
children: [{ text: line }],
type: editor.getType(KEYS.codeLine),
})),
{ at: element, children: true }
);
editor.api.redecorate();
};
These checks passed:
bun test packages/code-block/src/lib
pnpm install
pnpm turbo build --filter=./packages/code-block
pnpm turbo typecheck --filter=./packages/code-block
pnpm lint:fix
When a formatter can introduce line breaks, do not treat the result as plain text insertion. Rebuild the editor structure that downstream plugins depend on.
For code-block regressions, add one formatter test that asserts both:
code_line nodes