Custom Document Outline¶
Use this guide to wire a table-of-contents sidebar that follows the document structure and supports click-to-jump.
When to Derive the Outline¶
| Context | Argument |
|---|---|
| Web component | editor.doc (JSON) |
Core Editor instance |
editor.getDoc() |
Position-aware helpers will be exposed through a dedicated API in a future release. Today the JSON snapshot is the supported surface for read-only outlines.
Rendering Your Own Panel¶
function collectOutline(doc) {
const headings = [];
// Derive headings from the JSON snapshot.
(doc?.content ?? []).forEach((node) => {
if (node.type === 'heading') {
headings.push({ text: node.content?.[0]?.text ?? '', level: node.attrs?.level ?? 1, position: null });
}
});
return { headings };
}
function renderOutline(editor, container) {
const outline = collectOutline(editor.doc);
container.innerHTML = '';
outline.headings.forEach((heading) => {
const item = document.createElement('li');
item.textContent = heading.text || 'Untitled section';
item.dataset.level = String(heading.level ?? 1);
container.appendChild(item);
});
}
Scrolling Into View¶
The outline handler can call commands.setSelection(position, { scroll: false }) followed by commands.scrollIntoView() and commands.focus() to keep behavior consistent with the editor’s native navigation.
const runner = editor.commands;
if (runner?.commands?.setSelection) {
const didSet = runner.commands.setSelection(position, { scroll: false });
if (didSet && runner.commands.scrollIntoView) {
runner.commands.scrollIntoView();
}
runner.commands.focus?.();
}
Re-render Triggers¶
editor-change– update the outline whenever the document structure changes.- Feature toggles – if you enable/disable heading support on the fly, re-run
renderOutlineafter callingeditor.configureFeatures(...).
Graceful degradation
With the current public API, collectDocumentOutline returns heading data without live positions. You can show the outline as read-only today and layer in click-to-jump once the position API lands.