ReadViewSDK/.planning/phases/01-current-engine-boundaries/01-refactor-entry-strategy.md

10 KiB
Raw Blame History

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:) 已经承担最小可用分页
  • RDEPUBTextContentViewRDReaderView 已经承担原生页面展示

因此,新增第二套原生引擎只会制造双轨维护问题:

  • 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适合做 <link> CSS 内联或章节级规范化。
统一 stylesheet 生成器 新建 Sources/RDReaderView/EPUBTextRendering/RDEPUBWXReadStyleSheetBuilder.swift Phase 2 避免把 layered CSS 逻辑塞进 renderer使样式层可测试、可替换、可调试。
页面级 attributed string 元数据 Sources/RDReaderView/EPUBTextRendering/RDEPUBTextBookBuilder.swiftRDEPUBTextChapterRDEPUBTextPage 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 所依赖的页内容语义

建议执行顺序如下:

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 再升级 RDEPUBTextPaginationSupportRDEPUBTextBookBuilder 与 page model 的页面语义Phase 4 才处理 reader capability 链路的兼容回接。整个过程中,WKWebView 边界和 RDReaderView 容器契约都保持不变。