From 2a94921e88da529086c171552aa59ad8dde71815 Mon Sep 17 00:00:00 2001
From: shen <>
Date: Sun, 24 May 2026 15:36:01 +0800
Subject: [PATCH] feat(wxread): align pagination, rendering, and docs
---
.planning/ARCHITECTURE-CONTEXT.md | 115 +
.planning/PROJECT.md | 6 +-
.planning/REQUIREMENTS-v1.1-WXRead-next.md | 2 +-
.planning/REQUIREMENTS.md | 2 +-
.planning/ROADMAP.md | 2 +-
.planning/milestones/v1.0-REQUIREMENTS.md | 2 +-
.../06-01-SUMMARY.md | 19 +
.../06-02-SUMMARY.md | 19 +
.../06-03-SUMMARY.md | 21 +
.planning/phases/07-wxread/07-PATTERNS.md | 2 +-
.../08-01-PLAN.md | 307 +-
.../08-01-SUMMARY.md | 53 +
.../08-02-PLAN.md | 512 ++--
.../08-02-SUMMARY.md | 51 +
.../08-03-PLAN.md | 380 ++-
.../08-03-SUMMARY.md | 45 +
.../08-CONTEXT.md | 180 +-
.../08-PATTERNS.md | 459 +++
.../08-RESEARCH.md | 26 +-
.../08-UAT.md | 63 +
.../08-VALIDATION.md | 94 +-
.xcodebuildmcp/config.yaml | 13 +
AGENTS.md | 3 +
Doc/ARCHITECTURE.md | 19 +-
Doc/EPUBTextRendering_功能实现逻辑.md | 75 +-
Doc/EPUBUI_功能实现逻辑.md | 10 +-
Doc/EPUB_MAINTENANCE.md | 2 +
.../ReflowableEPUB_WXReadRenderer_Design.md | 6 +-
Doc/RDReaderView_功能实现逻辑.md | 5 +-
Doc/WXRead/analysis/01_核心架构与数据流图.md | 11 +-
Doc/WXRead/analysis/02_符号恢复与核心算法.md | 8 +-
.../analysis/03_数据结构与API协议定义.md | 13 +-
Doc/WXRead/analysis/CSS_JS资源分析.md | 20 +-
.../analysis/DTCoreText自定义修改分析.md | 2 +-
Doc/WXRead/analysis/EPUB渲染管线详解.md | 2 +-
Doc/WXRead/decompiled-doc.md | 334 +++
.../DTHTMLAttributedStringBuilder.h | 2 +-
Doc/WXRead/decompiled/DTHTMLElement.h | 2 +-
Doc/WXRead/decompiled/WRBookmark.h | 2 +-
Doc/WXRead/decompiled/WRBookmark.m | 2 +-
Doc/WXRead/decompiled/WRChapterData.h | 2 +-
Doc/WXRead/decompiled/WRChapterData.m | 2 +-
Doc/WXRead/decompiled/WRChapterPageCount.h | 2 +-
Doc/WXRead/decompiled/WRChapterPageCount.m | 2 +-
Doc/WXRead/decompiled/WREpubParser.h | 2 +-
Doc/WXRead/decompiled/WREpubParser.m | 2 +-
.../decompiled/WREpubPositionConverter.h | 2 +-
.../decompiled/WREpubPositionConverter.m | 2 +-
Doc/WXRead/decompiled/WREpubTypesetter.h | 2 +-
Doc/WXRead/decompiled/WREpubTypesetter.m | 2 +-
Doc/WXRead/decompiled/WRPageHighlight.h | 2 +-
Doc/WXRead/decompiled/WRPageHighlight.m | 2 +-
Doc/WXRead/decompiled/WRPageMark.h | 2 +-
Doc/WXRead/decompiled/WRPageMark.m | 2 +-
Doc/WXRead/decompiled/WRPageUnderline.h | 2 +-
Doc/WXRead/decompiled/WRPageUnderline.m | 2 +-
Doc/WXRead/decompiled/WRPageView.h | 2 +-
Doc/WXRead/decompiled/WRPageView.m | 2 +-
Doc/WXRead/decompiled/WRPageViewController.h | 2 +-
Doc/WXRead/decompiled/WRPageViewController.m | 2 +-
Doc/WXRead/decompiled/WRPreloadBookManager.h | 2 +-
Doc/WXRead/decompiled/WRPreloadBookManager.m | 2 +-
.../decompiled/WRReaderPencilNoteManager.h | 2 +-
.../decompiled/WRReaderPencilNoteManager.m | 2 +-
.../decompiled/WRReaderViewController.h | 2 +-
.../decompiled/WRReaderViewController.m | 2 +-
.../objc_metadata/all_method_signatures.txt | 439 ---
Doc/WXRead/objc_metadata/epub_class_names.txt | 320 --
.../objc_metadata/epub_core_classes.txt | 798 -----
Doc/WXRead/resources-doc.md | 181 ++
Doc/WXRead/resources/js/HtmlGenerator.js | 26 -
Doc/WXRead/resources/js/InnerMP.js | 26 -
Doc/WXRead/resources/js/MediaPlatform.js | 125 -
Doc/WXRead/resources/js/mpForArticle.js | 349 ---
Doc/WXRead/resources/js/mp_interceptor.js | 74 -
.../js/tencent-news-weread-custom.js | 16 -
Doc/WXRead/微信读书EPUB阅读器实现架构.md | 14 +-
Doc/WXRead剩余问题修复计划.md | 329 +--
Doc/index.md | 13 +-
Doc/架构对比分析_WXRead_vs_ReadViewSDK.md | 335 ++-
.../Pods/Pods.xcodeproj/project.pbxproj | 2574 +++++++++--------
.../UserInterfaceState.xcuserstate | Bin 50620 -> 64568 bytes
.../xcdebugger/Breakpoints_v2.xcbkptlist | 36 +
.../ReadViewDemo/ViewController.swift | 113 +-
.../EPUBCore/RDEPUBReadingModels.swift | 5 +-
.../EPUBCore/RDEPUBResourceResolver.swift | 3 +-
.../EPUBCore/RDEPUBSearchModels.swift | 5 +-
.../EPUBCore/RDEPUBTextAnchor.swift | 68 +
.../EPUBCore/RDEPUBTextIndexTable.swift | 249 ++
.../EPUBTextRendering/RDEPUBChapterData.swift | 148 +
.../RDEPUBTextBookBuilder.swift | 164 +-
.../RDEPUBTextLayouter.swift | 203 +-
.../RDEPUBTextRenderer.swift | 1 +
.../RDEPUBTextRendererSupport.swift | 12 +
.../RDEPUBTextSearchEngine.swift | 4 +-
.../RDEPUBPageInteractionController.swift | 212 ++
.../EPUBUI/RDEPUBPageLayoutSnapshot.swift | 146 +
.../EPUBUI/RDEPUBReaderController.swift | 135 +-
.../EPUBUI/RDEPUBSelectionOverlayView.swift | 72 +-
.../EPUBUI/RDEPUBTextContentView.swift | 271 +-
Sources/RDReaderView/RDReaderView.swift | 268 +-
.../RDReaderView/RDURLReaderController.swift | 60 +
Sources/RDReaderView/Resources/epub-bridge.js | 10 +-
103 files changed, 6124 insertions(+), 4623 deletions(-)
create mode 100644 .planning/ARCHITECTURE-CONTEXT.md
create mode 100644 .planning/phases/06-page-geometry-and-interaction-hit-layer/06-01-SUMMARY.md
create mode 100644 .planning/phases/06-page-geometry-and-interaction-hit-layer/06-02-SUMMARY.md
create mode 100644 .planning/phases/06-page-geometry-and-interaction-hit-layer/06-03-SUMMARY.md
create mode 100644 .planning/phases/08-pagination-quality-cache-performance/08-01-SUMMARY.md
create mode 100644 .planning/phases/08-pagination-quality-cache-performance/08-02-SUMMARY.md
create mode 100644 .planning/phases/08-pagination-quality-cache-performance/08-03-SUMMARY.md
create mode 100644 .planning/phases/08-pagination-quality-cache-performance/08-PATTERNS.md
create mode 100644 .planning/phases/08-pagination-quality-cache-performance/08-UAT.md
create mode 100644 .xcodebuildmcp/config.yaml
create mode 100644 AGENTS.md
create mode 100644 Doc/WXRead/decompiled-doc.md
delete mode 100644 Doc/WXRead/objc_metadata/all_method_signatures.txt
delete mode 100644 Doc/WXRead/objc_metadata/epub_class_names.txt
delete mode 100644 Doc/WXRead/objc_metadata/epub_core_classes.txt
create mode 100644 Doc/WXRead/resources-doc.md
delete mode 100644 Doc/WXRead/resources/js/HtmlGenerator.js
delete mode 100644 Doc/WXRead/resources/js/InnerMP.js
delete mode 100644 Doc/WXRead/resources/js/MediaPlatform.js
delete mode 100644 Doc/WXRead/resources/js/mpForArticle.js
delete mode 100644 Doc/WXRead/resources/js/mp_interceptor.js
delete mode 100644 Doc/WXRead/resources/js/tencent-news-weread-custom.js
create mode 100644 ReadViewDemo/ReadViewDemo.xcworkspace/xcuserdata/shen.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist
create mode 100644 Sources/RDReaderView/EPUBCore/RDEPUBTextAnchor.swift
create mode 100644 Sources/RDReaderView/EPUBCore/RDEPUBTextIndexTable.swift
create mode 100644 Sources/RDReaderView/EPUBTextRendering/RDEPUBChapterData.swift
create mode 100644 Sources/RDReaderView/EPUBUI/RDEPUBPageInteractionController.swift
create mode 100644 Sources/RDReaderView/EPUBUI/RDEPUBPageLayoutSnapshot.swift
diff --git a/.planning/ARCHITECTURE-CONTEXT.md b/.planning/ARCHITECTURE-CONTEXT.md
new file mode 100644
index 0000000..291d1ef
--- /dev/null
+++ b/.planning/ARCHITECTURE-CONTEXT.md
@@ -0,0 +1,115 @@
+# 架构分析:WXRead 参考 vs ReadViewSDK 当前
+
+**分析日期:** 2026-05-23
+**分析基础:** `Doc/WXRead/decompiled-doc.md`、`Doc/WXRead/resources-doc.md`、`Doc/WXRead/读书EPUB阅读器实现架构.md`
+**状态:** Decisions captured
+
+---
+
+
+## 分析范围
+
+对比读书 (WeRead v10.0.3) 逆向架构与当前 ReadViewSDK 项目的结构性差距,聚焦四大方向:分页引擎集成、CSS 处理、渲染架构、字体系统。
+
+读书 EPUB 渲染的核心架构特征:
+- Path A (EPUB): 纯 CoreText 渲染 — `WRPageView.drawRect:` → `CTFrameDraw`,不用 UITextView/UILabel
+- 4 级语义断页:`WRCoreTextLayouter` + `WRCoreTextLayoutFrame` (语义边界 > 附件边界 > 块边界 > 帧限制)
+- 5 层 CSS 级联:`default.css < replace.css < dark.css < EPUB 内嵌 < 用户设置`
+- 字符级位置精度:`WREpubPositionConverter` (fileIndex, row, column) ↔ 全局字符偏移
+- 标注直接在 CTFrame 层叠加绘制,搜索高亮同理
+
+
+
+
+## 已决事项
+
+### Area 1: 分页引擎集成(P0)
+
+| 决策 | 说明 |
+|------|------|
+| 将 `RDEPUBTextLayouter` 集成到 `RDEPUBTextBookBuilder` | 内部调用 `rd_paginatedFrames(size:)` 替代旧的 `ss_pageRanges(size:)`,外部 API 不变 |
+| 分页元数据暴露到 `RDEPUBTextPage` | 新增 `metadata: RDEPUBTextPageMetadata` 字段(含 breakReason/blockKinds/semanticHints),对外暴露分页质量数据 |
+| `RDEPUBTextChapterPaginationDiagnostic` 增强 | 透传 RDEPUBTextLayoutFrame 的诊断信息 |
+| 分页缓存 | 按 `bookID + fontSize + lineHeightMultiple + contentInsets` 生成缓存 key,缓存完整 `RDEPUBTextBook` 到磁盘 |
+
+### Area 2: CSS `` 外部样式表处理(P0)
+
+| 决策 | 说明 |
+|------|------|
+| 预处理内联 CSS | 渲染前扫描 HTML 中 `` 标签,从 EPUB 解压目录读取 CSS 内容,注入 `";
- result = result.replace("", insertStyle);
- result = result.replace("