Skip to content

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.document (ProseMirror) or editor-change payload (detail.doc)
Core Editor instance editor.getDoc()

Use the JSON snapshot from editor-change to derive heading data. For click-to-jump behavior, pair the heading positions with the stable position helpers exposed on the web component (editor.positions) or core editor APIs.

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(doc, container) {
  const outline = collectOutline(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);
  });
}
editor.addEventListener('editor-change', (event) => {
  renderOutline(event.detail.doc, outlineContainer);
});

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 renderOutline after calling editor.configureFeatures(...).

Position helpers

Use the positions API to map document offsets to screen coordinates (coordsAtPos) and to resolve positional context (resolve). See Web Components Basics for the full position API surface.