fix(reader): include OCR text layers in pdf-pages bookmark excerpts
opencode
1721a47
The bookmark excerpt branch returned an empty string for the pdf-pages mode
before reading the page shell. Image-page PDFs with an OCR text layer already
populate _bookmarkTextItems, so their bookmark preview was blank. Treat
pdf-pages like pdf, while still returning empty when a page has no OCR text.
fix(tts): hand off at sentence ends too; ramp clips by 1.45x of the previous clip
fix(reader): rename the speech title helper to satisfy the state guard
opencode
c368c6d
reader-speech.mjs declared a module-level 'title' helper. The architecture
contract forbids top-level title state in the composed Reader source, so the
helper is now readerSpeechTitle. Behavior is unchanged.
Any reader-initiated scroll (wheel/touch/scroll keys/pointer navigation) stops auto-follow until 回到播放位置 or a new start, so sentences no longer pull the page back. After 回到播放位置 the button reads 回到原位置 until the playing sentence leaves the view. 听书 starts at the first line in view (loading that page/section first). The button appears only once text is found near the reading position (scanned PDFs, comics). Closing a Reader that is reading keeps it hidden with a small player (返回阅读/暂停/停止); reopening the same book reuses it, opening another book releases it. The shared player keeps list numbers (1. / (3).) with their item.
Yesterday
fix(reader): do not pull the reader back after scrolling away from speech
Auto-follow is now decided by the reader's own settled scrolling: once the sentence being read is scrolled out of view, sentence changes no longer scroll back; following resumes via 回到播放位置 or by scrolling back to it. Wheel/touch/key input overrides one of our smooth scrolls in progress. Follow and 回到播放位置 scroll the sentence itself instead of its parent block (a TXT block holds 32 KiB, so the old scroll landed far from the sentence). Adds a regression test.
fix(reader): highlight and follow speech on unrendered PDF pages
When the clip being read is on a page or section that is not rendered yet, the adapter navigates there, waits for its text layer and the clip is highlighted once. Auto-follow no longer turns itself off after its own smooth scroll, and HTML frame offsets are included. Adds a sparse 30-page PDF regression test. Previously: playback starts once one batch plus its planning context (1,800 chars) is loaded instead of the full 2,400-char lookahead; slow searches through pages without text show page progress; stop cancels a pending text load. PDF pages already rendered use their text layer.
fix(reader): start reading sooner on sparse/scanned PDFs
Playback starts once one batch plus its planning context (1,800 chars) is loaded instead of the full 2,400-char lookahead; slow searches through pages without text show page progress; stop cancels a pending text load. PDF pages already rendered use their text layer.
feat(reader): native reading for every text-bearing Reader format
Adds the shared tts-client.js player (Hitokoto CPU TTS) to the Reader. reader-speech.mjs supplies a growing-text adapter per format: TXT/Markdown/HTML rendered text, Foliate EPUB/MOBI/FB2 sections, chapter bundles, native PDF text layers and pdf-pages/v3 OCR text layers. Highlights use the CSS Custom Highlight API in the owning realm; DOM text is never modified. Images/media/pages without text get no button. CSP adds the Hitokoto origin to connect-src and Hitokoto plus blob: to media-src. Inventory, components and release gate list the new files on both sites.
fix(search): multi-token AND across tokenizer boundaries, exact term splitting
vomebook
ba5a2f5
Ordinary multi-token queries now union each term's jieba/fuzzy postings with
a literal substring scan before intersecting, so matches that cross a jieba
token boundary are retained. Exact mode splits on whitespace and matches each
term independently; punctuation-bearing terms stay literal, preserving the
documented "手。机" and wildcard behaviour.
The bootstrap payload now reports the same string generation as search and
initial payloads, GET search routes return 405, unknown API paths return a
JSON 404, and the SVG manifest icon declares sizes "any".
Bump HF search semantics to v4 so cached orders and snapshots are invalidated.