Code Block
A full code editor with syntax highlighting, language selection, line wrapping, undo/redo history, and a draggable resize handle. Built on CodeMirror 6 — a single unified editor layer with no rendering hacks. Add with /code or /snippet.
Adding a Code Block
/ on any empty paragraph, type code or snippet, press Enter.``` at the start of an empty block and press Space or Enter. The fence is removed and the block converts to a Code Block.+ on any block → scroll to Advanced → Code Block.The editor
The Code Block uses CodeMirror 6 — a single unified editor that handles syntax highlighting, cursor rendering, selection, paste, and text input in one layer. There is no dual-layer transparent textarea trick; CodeMirror's own content-editable DOM is the editor surface.
The editor mounts once on load. Theme and language changes after mount use CodeMirror's Compartment system — they hot-swap the relevant extension without destroying and recreating the editor or losing the undo history.
Keyboard behaviour
KeyboardEvent on the container, which the block editor's own keydown handler picks up and treats as a normal inter-block navigation event.Languages
23 languages are available from the dropdown in the toolbar header. Language extensions are loaded lazily — only the language you select is fetched. Switching languages hot-swaps the parser via CodeMirror's Compartment API without remounting the editor.
Available languages: plaintext, JavaScript, TypeScript, JSX, TSX, Python, Rust, Go, Java, C, C++, C#, Ruby, PHP, Swift, Kotlin, SQL, HTML, CSS, JSON, YAML, Bash, Markdown.
<Component />), select JSX or TSX for correct highlighting.Syntax highlighting
Two themes are available, selected automatically based on the document's background color:
Theme switching is reactive — if you change the document background color in the toolbar, the code block theme updates immediately via the Compartment system.
Resizing
The block has a drag handle at the bottom — five dots indicating the resize zone. Drag up to shrink, drag down to grow. Minimum height is 80px. Default height is 180px.
Unlike the previous implementation, height is now persisted to block metadata (metadata.codeBlockHeight). The block restores to its saved height on remount, page reload, and across collaborative sessions.
mousemove / mouseup listeners on window rather than the element, so dragging outside the block boundary doesn't drop the resize handle mid-drag.Content sync
The editor debounces content saves by 600ms — the block's onChange is only called 600ms after the last keystroke. This keeps the Yjs CRDT document and autosave system from being flooded with updates while typing.
External updates — from the AI panel, Yjs real-time collaboration, or version history restore — are applied to the editor via a full document replacement dispatch. The sync logic uses two refs (lastSentRef and lastExternalRef) to distinguish genuine external updates from echoes of the user's own saves, preventing cursor jumps during normal typing.
Publishing
On the published page the code block renders as a dark panel with a header bar showing the language name. The code is displayed in a <pre> tag with monospace font and horizontal scrolling enabled. Syntax highlighting is not applied on the published page — the raw code is shown with consistent dark styling.
Metadata reference
metadata.language. Defaults to plaintext. Controls which CodeMirror language extension is loaded and displayed in the toolbar dropdown.metadata.codeBlockHeight as a number (pixels). Set when the user releases the drag handle. Defaults to 180 if absent.