---
phase: 03-page-metadata-pagination
plan: 02
type: execute
wave: 2
depends_on:
- "03-01"
files_modified:
- Sources/RDReaderView/EPUBTextRendering/RDEPUBTextPaginationSupport.swift
- Sources/RDReaderView/EPUBTextRendering/RDEPUBTextBookBuilder.swift
- Sources/RDReaderView/EPUBTextRendering/RDEPUBTextLayouter.swift
- Sources/RDReaderView/EPUBTextRendering/RDEPUBTextLayoutFrame.swift
autonomous: true
requirements:
- REND-03
- REND-04
user_setup: []
must_haves:
truths:
- pagination is no longer implemented as only `CTFrameGetVisibleStringRange` range slicing.
- layouter/layout-frame responsibilities live inside `EPUBTextRendering`, not in reader UI classes.
- stronger page edges still resolve to stable `RDEPUBTextPage` offsets and chapter continuity.
artifacts:
- .planning/phases/03-page-metadata-pagination/03-02-SUMMARY.md
key_links:
- `RDEPUBTextPaginationSupport` remains the entry point for native pagination work.
- `RDEPUBTextBookBuilder` still assembles final pages and chapters.
---
在旧引擎基础上重构分页器,引入内部 layouter / layout-frame 语义,并把纯 visible-range slicing 升级为更强的页面边界控制。
Purpose: 让 native paginator 能表达 block / image / attachment 的页面边界语义,同时不破坏现有 page model 与 chapter offset continuity。
Output: stronger paginator implementation, internal layouter/frame types, and book-builder wiring onto the new pagination path.
@$HOME/.codex/get-shit-done/workflows/execute-plan.md
@$HOME/.codex/get-shit-done/templates/summary.md
@.planning/ROADMAP.md
@.planning/STATE.md
@.planning/REQUIREMENTS.md
@.planning/phases/01-current-engine-boundaries/01-refactor-entry-strategy.md
@.planning/phases/03-page-metadata-pagination/03-RESEARCH.md
@.planning/phases/03-page-metadata-pagination/03-PATTERNS.md
@.planning/phases/03-page-metadata-pagination/03-01-PLAN.md
@Sources/RDReaderView/EPUBTextRendering/RDEPUBTextPaginationSupport.swift
@Sources/RDReaderView/EPUBTextRendering/RDEPUBTextBookBuilder.swift
@Sources/RDReaderView/EPUBCore/RDEPUBReadingSession.swift
@Sources/RDReaderView/EPUBUI/RDEPUBTextContentView.swift
Task 1: 引入 layouter / layout-frame 语义并升级分页入口
Sources/RDReaderView/EPUBTextRendering/RDEPUBTextPaginationSupport.swift, Sources/RDReaderView/EPUBTextRendering/RDEPUBTextLayouter.swift, Sources/RDReaderView/EPUBTextRendering/RDEPUBTextLayoutFrame.swift
Sources/RDReaderView/EPUBTextRendering/RDEPUBTextPaginationSupport.swift, Sources/RDReaderView/EPUBTextRendering/RDEPUBTextBookBuilder.swift, .planning/phases/01-current-engine-boundaries/01-refactor-entry-strategy.md
把当前 `ss_pageRanges(size:)` 的纯 range slicing 入口升级成内部 layouter / layout-frame 驱动的分页路径;新路径至少要能表达 page break reason、block boundary avoidance、image/attachment boundary handling 这三类语义。新增类型应放在 `EPUBTextRendering` 内部,例如 `RDEPUBTextLayouter` / `RDEPUBTextLayoutFrame`,并由 `RDEPUBTextPaginationSupport` 调用,而不是把复杂分页逻辑堆到 UI controller 里。
- `Sources/RDReaderView/EPUBTextRendering` contains layouter/frame types or equivalent internal pagination structures
- paginator code contains semantics beyond plain `CTFrameGetVisibleStringRange` slicing
- source tree does not move pagination logic into `RDEPUBReaderController` or `RDEPUBTextContentView`
rg -n "Layouter|LayoutFrame|pageBreak|attachment|avoid|CTFrameGetVisibleStringRange|CTTypesetter" Sources/RDReaderView/EPUBTextRendering
native pagination now has a real internal layout vocabulary rather than one visible-range helper.
Task 2: 把更强分页结果接回 `RDEPUBTextBookBuilder` 与现有页模型
Sources/RDReaderView/EPUBTextRendering/RDEPUBTextBookBuilder.swift
Sources/RDReaderView/EPUBTextRendering/RDEPUBTextBookBuilder.swift, Sources/RDReaderView/EPUBCore/RDEPUBReadingSession.swift, Sources/RDReaderView/EPUBTextRendering/RDEPUBTextSearchEngine.swift, Sources/RDReaderView/EPUBUI/RDEPUBTextContentView.swift
让 `RDEPUBTextBookBuilder` 消费新分页结果并把 page-level metadata 落到 `RDEPUBTextPage` / `RDEPUBTextChapter` 上,同时保持 `pageStartOffset` / `pageEndOffset`、chapter order、fragmentOffsets 和 search/highlight overlap 逻辑不变。需要时可以在 builder 内转换 layouter output,但最终输出仍必须是当前 `RDEPUBTextBook` 契约,而不是新的 UI-only page list。
- `RDEPUBTextBookBuilder` constructs pages from the upgraded pagination output rather than raw `ss_pageRanges(size:)` only
- page model assembly still emits `RDEPUBTextBook(chapters:pages:)`
- search/highlight/navigation dependent fields remain present in the built pages
rg -n "RDEPUBTextBook\\(|pageStartOffset|pageEndOffset|fragmentOffsets|metadata|layout" Sources/RDReaderView/EPUBTextRendering/RDEPUBTextBookBuilder.swift
the richer paginator is wired back into the existing native book contract and remains consumable by later reader phases.
Before declaring plan complete:
- [ ] `test -f Sources/RDReaderView/EPUBTextRendering/RDEPUBTextPaginationSupport.swift`
- [ ] `rg -n "Layouter|LayoutFrame|pageBreak|attachment|avoid" Sources/RDReaderView/EPUBTextRendering`
- [ ] `rg -n "RDEPUBTextBook\\(|pageStartOffset|pageEndOffset|fragmentOffsets" Sources/RDReaderView/EPUBTextRendering/RDEPUBTextBookBuilder.swift`
- All tasks completed
- All verification checks pass
- paginator semantics are meaningfully stronger than pure visible-range slicing
- output still flows through the existing native text book/page model