# Phase 1 Strategy: Direct Refactor Entry Points for the Existing Reflowable Engine **Phase:** 01-current-engine-boundaries **Date:** 2026-05-21 **Purpose:** 把“旧引擎直接演进”的切入点、顺序和硬边界固定下来,供 Phase 2/3 实施使用。 ## 1. Strategy in One Sentence 后续实现应保留现有 `RDURLReaderController -> RDEPUBReaderController -> RDReaderView` 外层契约不变,把升级集中在 `EPUBTextRendering` 内部:先增强 typesetter / CSS 分层,再增强页面级属性与分页语义,最后回接并验证 reader 兼容能力。 ## 2. Why the Strategy Is “Direct Evolution,” Not “Parallel Engine” 根据当前源码审计,native `.textReflowable` 主路径已经具备以下骨架: - `RDEPUBParser.readingProfile()` 已经把普通 reflowable EPUB 分到 `.textReflowable` - `RDEPUBReaderController.paginatePublication()` 已经把 `.textReflowable` 接到 `RDEPUBTextBookBuilder` - `RDEPUBDTCoreTextRenderer` 已经承担章节 HTML -> `NSAttributedString` - `RDEPUBTextPaginationSupport.ss_pageRanges(size:)` 已经承担最小可用分页 - `RDEPUBTextContentView` 与 `RDReaderView` 已经承担原生页面展示 因此,新增第二套原生引擎只会制造双轨维护问题: - duplicate reader integration - duplicate location/highlight/search transport - duplicate pagination data model - duplicate regression matrix 正确策略是:**沿着现有 native text 路径升级内部能力,而不是复制一条新路径。** ## 3. Target Capability Map: WXRead -> Current Touchpoints 下表把 WXRead 目标能力映射到当前仓库中真正应该改动的触点。 | WXRead-style capability | Current touchpoint | Target phase | Why this file is the right entry point | |-------------------------|-------------------|--------------|----------------------------------------| | 五层 CSS 级联(default / replace / dark / epub / user) | `Sources/RDReaderView/EPUBTextRendering/RDEPUBDTCoreTextRenderer.swift` | Phase 2 | 当前 renderer 已拥有 HTML、baseURL、style 三要素,是升级 stylesheet pipeline 的最直接入口。 | | HTML 预处理与资源引用兜底 | `Sources/RDReaderView/EPUBTextRendering/RDEPUBTextBookBuilder.swift` 或新建 `RDEPUBWXReadHTMLPreprocessor.swift` | Phase 2 | builder 已掌握章节原始 HTML 与章节 baseURL,适合做 `` CSS 内联或章节级规范化。 | | 统一 stylesheet 生成器 | 新建 `Sources/RDReaderView/EPUBTextRendering/RDEPUBWXReadStyleSheetBuilder.swift` | Phase 2 | 避免把 layered CSS 逻辑塞进 renderer,使样式层可测试、可替换、可调试。 | | 页面级 attributed string 元数据 | `Sources/RDReaderView/EPUBTextRendering/RDEPUBTextBookBuilder.swift`、`RDEPUBTextChapter`、`RDEPUBTextPage` | Phase 3 | 当前 page model 只有范围和 offset,后续页面语义需要在这里承接。 | | 更强分页语义(块级避免断页、图片/附件边界) | `Sources/RDReaderView/EPUBTextRendering/RDEPUBTextPaginationSupport.swift` | Phase 3 | 当前 `ss_pageRanges(size:)` 是唯一分页核心,增强必须从这里开始。 | | Layout frame / layouter 责任分离 | 新建 `EPUBTextRendering` 内部 layouter/frame 类型 | Phase 3 | 不应把复杂页面布局逻辑继续堆在 `RDEPUBReaderController` 或 content view。 | | Reader 兼容性回接(位置、高亮、搜索、重分页) | `Sources/RDReaderView/EPUBUI/RDEPUBReaderController.swift` | Phase 4 | 这是现有 reader state 的唯一编排点,适合接回而不是承担新排版实现。 | ## 4. Phase 2 Entry Strategy: Upgrade Typesetter First Phase 2 的目标不是“立刻实现 WXRead 全量布局器”,而是把渲染输入从“简单 DTCoreText options”升级为“WXRead 风格 typesetter”。 ### 4.1 Primary code touchpoints 优先改动: - `Sources/RDReaderView/EPUBTextRendering/RDEPUBDTCoreTextRenderer.swift` - `Sources/RDReaderView/EPUBTextRendering/RDEPUBTextBookBuilder.swift` - 新建 `Sources/RDReaderView/EPUBTextRendering/RDEPUBWXReadStyleSheetBuilder.swift` ### 4.2 Concrete target state Phase 2 应把当前 renderer 升级到以下状态: 1. 合成 layered CSS - SDK default CSS - SDK replace/enhancement CSS - dark theme override - EPUB embedded CSS - user CSS from `RDEPUBTextRenderStyle` 2. 使用章节目录 `baseURL` - 保留当前 baseURL 计算方式 - 确保图片与章节级 CSS 相对路径继续可解析 3. 维持 fragment marker / fragment offset 体系 - 不能破坏 `injectFragmentMarkers` - 不能破坏 `extractFragmentOffsets` 4. 不改 reader integration surface - `RDEPUBTextBookBuilder.build(...)` 的高层职责保持不变 - `RDEPUBReaderController.paginatePublication()` 的分支结构保持不变 ### 4.3 Why Phase 2 should stop there 如果在 Phase 2 就同时引入: - 全新分页器 - 大量新 page model - reader compatibility 回接修复 就会把“渲染输入提升”与“分页语义重构”混为一体,定位回归原因会非常困难。Phase 2 应该先把章节渲染输入变得更接近 WXRead,再观察真实样本书暴露的分页问题。 ## 5. Phase 3 Entry Strategy: Upgrade Pagination Semantics Phase 3 才是“把 pageRanges 模式升级为更强页面语义”的阶段。 ### 5.1 Primary code touchpoints 优先改动: - `Sources/RDReaderView/EPUBTextRendering/RDEPUBTextPaginationSupport.swift` - `Sources/RDReaderView/EPUBTextRendering/RDEPUBTextBookBuilder.swift` - `RDEPUBTextPage` - `RDEPUBTextChapter` - 必要时新建内部 layouter/layout-frame 类型 ### 5.2 Concrete target state Phase 3 应逐步实现: 1. 当前 range-only page model -> richer page metadata - block boundaries - image/attachment semantics - page-level layout markers - future page background or page-style metadata hooks 2. 当前 visible-range slicing -> stronger pagination semantics - avoid page break inside for large blocks - image and attachment boundary handling - better page edge control than pure `CTFrameGetVisibleStringRange` 3. 保留 offset continuity - `pageStartOffset` - `pageEndOffset` - chapter-level text continuity - fragment offset compatibility ### 5.3 What not to do in Phase 3 不要把分页器升级等同于: - 改写 `RDReaderView` - 改写 fixed/interactive 渲染链路 - 绕开 `RDEPUBTextBook` 直接输出新的 UI 专用模型 Phase 3 的正确做法是:让更强的分页语义仍然最终落到现有 book/chapter/page 契约上,必要时是“扩展”这些模型,而不是抛弃它们。 ## 6. Compatibility Surface That Must Be Preserved 以下能力必须视为后续 phase 的硬约束: ### 6.1 `WKWebView` retention boundary 保留不动: - `webFixedLayout` - `webInteractive` - `RDEPUBWebView+FixedLayout.swift` - `RDEPUBWebView+Reflowable.swift` - `RDEPUBPaginator.swift` 所属的 WebView 测量职责 原因: - Fixed layout 依赖 spread HTML 表示 - interactive EPUB 依赖 JS/bridge/iframe/form/multimedia 支持 - 它们不属于 native reflowable 的目标问题域 ### 6.2 Stable reader container `RDReaderView` 与现有翻页模式保持不变: - page curl - horizontal scroll - vertical scroll - page direction - dual-page / cover page behavior - orientation-driven container refresh 原因: - 它是 native text 与 web content 的共同外壳 - 改它会同时扩大 regression surface ### 6.3 Reader capability continuity 以下链路必须继续通过现有 `RDEPUBReaderController` 契约工作: - 阅读位置恢复 - `RDEPUBLocation` 映射 - 高亮 / 选区 - 搜索结果定位 - 字号/行高/主题切换后的重分页 这要求后续 phase 继续维护: - `fragmentOffsets` - `pageStartOffset` - `pageEndOffset` - `RDEPUBTextOffsetRangeInfo` - `RDEPUBTextContentView` 所依赖的页内容语义 ## 7. Recommended Implementation Sequence 建议执行顺序如下: ### Step 1: Strengthen renderer / typesetter 目标: - layered CSS - HTML preprocessing - stable resource resolution - normalized style injection 原因: - 先把“输入质量”提升,才能判断现有分页问题到底是样式输入问题还是分页算法问题 ### Step 2: Strengthen pagination semantics 目标: - richer page metadata - avoid-break logic - attachment-aware page boundaries 原因: - 在更稳定的 attributed string 输入上做分页升级,结果更可解释 ### Step 3: Reconnect and validate reader capability chain 目标: - 位置映射 - highlight/search - repagination after settings change 原因: - 这一步应基于已经稳定的 renderer + page model,而不是把所有问题都混在一起排查 ## 8. File-Level Recommendations for Next Phases ### 8.1 Files Phase 2 should read first - `Sources/RDReaderView/EPUBTextRendering/RDEPUBDTCoreTextRenderer.swift` - `Sources/RDReaderView/EPUBTextRendering/RDEPUBTextBookBuilder.swift` - `Doc/WXRead/analysis/EPUB渲染管线详解.md` - `Doc/WXRead/analysis/DTCoreText自定义修改分析.md` - `.planning/phases/01-current-engine-boundaries/01-reflowable-audit.md` ### 8.2 Files Phase 3 should read first - `Sources/RDReaderView/EPUBTextRendering/RDEPUBTextPaginationSupport.swift` - `Sources/RDReaderView/EPUBTextRendering/RDEPUBTextBookBuilder.swift` - `Sources/RDReaderView/EPUBUI/RDEPUBTextContentView.swift` - `.planning/phases/01-current-engine-boundaries/01-reflowable-audit.md` - `Doc/WXRead/analysis/02_符号恢复与核心算法.md` ### 8.3 Files Phase 4 should read first - `Sources/RDReaderView/EPUBUI/RDEPUBReaderController.swift` - `Sources/RDReaderView/EPUBUI/RDEPUBTextContentView.swift` - `Sources/RDReaderView/RDReaderView.swift` - Any Phase 2/3 summaries produced from the pagination work ## 9. Non-Goals and Refusal Rules 后续 phase 默认拒绝以下方向,除非 roadmap 被显式修改: 1. 把 Fixed Layout EPUB 改成 native renderer 2. 把 interactive EPUB 改成 native renderer 3. 新建并长期维护第二套 reflowable 原生引擎 4. 修改 `RDReaderView` 的外部容器契约 5. 在还没完成 Phase 2 renderer 升级前,就全面重写 reader integration ## 10. Final Strategy Decision 最终策略决议如下: > Phase 2 先把 `RDEPUBDTCoreTextRenderer` 从“简单 DTCoreText options”升级成“WXRead 风格 typesetter + layered CSS pipeline”;Phase 3 再升级 `RDEPUBTextPaginationSupport`、`RDEPUBTextBookBuilder` 与 page model 的页面语义;Phase 4 才处理 reader capability 链路的兼容回接。整个过程中,`WKWebView` 边界和 `RDReaderView` 容器契约都保持不变。