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("", insertJs); - return result; -} - -generator.generateHtmlForMPReview = function (content,js, css) { - var result = generator.generateHtml(content,js,css) - var modifiedCopyRight = "