Skip to content

feat(toc): add headings extraction, scroll-to-range, and per-editor TOC integration#89

Open
sospartan wants to merge 1 commit into
nodes-app:mainfrom
sospartan:feature/toc-headings-extraction
Open

feat(toc): add headings extraction, scroll-to-range, and per-editor TOC integration#89
sospartan wants to merge 1 commit into
nodes-app:mainfrom
sospartan:feature/toc-headings-extraction

Conversation

@sospartan

Copy link
Copy Markdown
Contributor

Summary

Adds public heading-extraction and scroll-to-heading APIs so an embedder can build an outline / TOC panel alongside the editor.

Problem

The engine rendered headings, but there was no public way to:

  1. Enumerate the headings in a document with level, title, and source range.
  2. Receive updates when headings changed after edits.
  3. Programmatically scroll the editor to a heading's source range.

This made it impossible to build a navigation / TOC sidebar without re-parsing the Markdown outside the engine.

Solution

  • DocumentHeading — public struct describing one heading (level, title, range in source coordinates).
  • HeadingExtractor — AST-based collector for ATX headings; excludes headings inside code blocks and strips inline markup from the title text.
  • NativeTextViewWrapper.onHeadingsDidChange — closure callback that fires after text changes with the current heading list (deduplicated).
  • ScrollHandler — per-editor NSObject bridge that the embedder owns and the engine fills in makeNSView, so the embedder can request scrolls directly.
  • scrollRangeIntoView(_:in:) — shared TextKit 2 layout-fragment scroll helper used by both TOC reveal and existing find-match reveal.
  • HeadingsBusTests — unit tests covering heading extraction, code-block exclusion, and title-stripping.

…OC integration

- DocumentHeading: public struct (level, title, source-coordinate range)
- HeadingExtractor: AST-based ATX heading collection (excludes code blocks,
  strips inline markup from title text)
- NativeTextViewWrapper.onHeadingsDidChange: closure callback for embedder
  TOC panels, called after text changes (deduplicated)
- ScrollHandler: per-editor NSObject bridge; embedder passes to wrapper,
  engine fills handler in makeNSView for direct scroll invocation
- scrollRangeIntoView(_:in:): shared TextKit-2 layout-fragment scroll
  helper (also used by find-match reveal)
- HeadingsBusTests: 4 unit tests for heading extraction
@sospartan sospartan marked this pull request as ready for review July 11, 2026 00:40
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant