Skip to content

feat(reader): search and the table of contents through the page - #64

Merged
usamaiqb merged 1 commit into
mainfrom
feat/document-search-and-outline
Oct 24, 2026
Merged

usamaiqb merged 1 commit into
mainfrom
feat/document-search-and-outline

Conversation

@usamaiqb

Copy link
Copy Markdown
Owner

Both worked before the WebView swap and neither survived it: they index a rendering, and the rendering moved into the page. The controls were hidden rather than left to report nothing. They are back, driven by the renderer that already ships find and an outline -- this is wiring, not a rewrite.

__mdrPage gains runFind, stepFind, closeFind and revealSlug, and the page forwards three reports out through __mdrHost: the outline, the heading being read, and the match count. openFind is deliberately absent -- it re-runs whatever query the page last had, and the app is the one holding the query.

Search runs on whichever surface is drawing, and the two are not alike. The page owns its match set, since matches are DOM ranges over a rendering only it has, so a query goes in and an index comes back as an event; raw mode keeps the span pass over text held out here. That fork is decided in one place, usesPageFind, off the same predicate the reader uses to pick a surface -- and a test asserts the two agree across the whole input space, because a disagreement is a search running against a surface that is not there.

Requests reach the page over a buffered channel rather than as state. "Next match" has no value to hold, and every toggle into raw mode and back destroys the WebView, so a request in flight has to survive that instead of being lost or replayed at every page that follows.

The outline came off the format layer entirely. A heading's position is a fact about the rendering, so DocumentFormat.headings, the ATX parser and the heading math in ScrollAnchor and ReaderContentView are deleted, and HeadingItem moves beside the WebView host carrying a slug rather than a character offset. The detekt baseline loses three entries and gains none.

Two fixes fall out of it. A search with no usable renderer reported matches and highlighted nothing, because the fallback drew the unmarked source; it shares raw mode's branch now, which is the branch the highlighting is written to. And the shared stylesheet is re-vendored: the ::highlight(mr-find-*) rules were in the desktop chrome stylesheet this host deliberately never loads, so find painted on desktop and was invisible here.

Both worked before the WebView swap and neither survived it: they index a
rendering, and the rendering moved into the page. The controls were hidden
rather than left to report nothing. They are back, driven by the renderer
that already ships find and an outline -- this is wiring, not a rewrite.

`__mdrPage` gains `runFind`, `stepFind`, `closeFind` and `revealSlug`, and
the page forwards three reports out through `__mdrHost`: the outline, the
heading being read, and the match count. `openFind` is deliberately absent
-- it re-runs whatever query the page last had, and the app is the one
holding the query.

Search runs on whichever surface is drawing, and the two are not alike.
The page owns its match set, since matches are DOM ranges over a rendering
only it has, so a query goes in and an index comes back as an event; raw
mode keeps the span pass over text held out here. That fork is decided in
one place, `usesPageFind`, off the same predicate the reader uses to pick a
surface -- and a test asserts the two agree across the whole input space,
because a disagreement is a search running against a surface that is not
there.

Requests reach the page over a buffered channel rather than as state.
"Next match" has no value to hold, and every toggle into raw mode and back
destroys the WebView, so a request in flight has to survive that instead
of being lost or replayed at every page that follows.

The outline came off the format layer entirely. A heading's position is a
fact about the rendering, so `DocumentFormat.headings`, the ATX parser and
the heading math in `ScrollAnchor` and `ReaderContentView` are deleted, and
`HeadingItem` moves beside the WebView host carrying a slug rather than a
character offset. The detekt baseline loses three entries and gains none.

Two fixes fall out of it. A search with no usable renderer reported
matches and highlighted nothing, because the fallback drew the unmarked
source; it shares raw mode's branch now, which is the branch the
highlighting is written to. And the shared stylesheet is re-vendored: the
`::highlight(mr-find-*)` rules were in the desktop chrome stylesheet this
host deliberately never loads, so find painted on desktop and was
invisible here.
@usamaiqb usamaiqb self-assigned this Oct 24, 2026
@usamaiqb
usamaiqb merged commit ec80a41 into main Oct 24, 2026
3 checks passed
@usamaiqb
usamaiqb deleted the feat/document-search-and-outline branch October 24, 2026 17:59
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant