chore: checkpoint current milestone work
This commit is contained in:
@@ -0,0 +1,92 @@
|
||||
---
|
||||
phase: 02-typesetter-css
|
||||
plan: 01
|
||||
type: execute
|
||||
wave: 1
|
||||
depends_on: []
|
||||
files_modified:
|
||||
- Sources/RDReaderView/EPUBTextRendering/RDEPUBTextStyleSheetBuilder.swift
|
||||
- Sources/RDReaderView/EPUBTextRendering/RDEPUBTextRendererSupport.swift
|
||||
- Sources/RDReaderView/EPUBTextRendering/RDEPUBDTCoreTextRenderer.swift
|
||||
- Sources/RDReaderView/EPUBTextRendering/RDEPUBTextBookBuilder.swift
|
||||
- Sources/RDReaderView/EPUBTextRendering/RDEPUBTextRenderer.swift
|
||||
autonomous: true
|
||||
requirements:
|
||||
- REND-02
|
||||
user_setup: []
|
||||
must_haves:
|
||||
truths:
|
||||
- native renderer has an explicit chapter preprocessing / stylesheet assembly layer rather than only a flat DTCoreText option bag.
|
||||
- CSS precedence is deterministic and documented as `default / replace / dark / epub / user`.
|
||||
- chapter baseURL and resource context are preserved through preprocessing.
|
||||
artifacts:
|
||||
- .planning/phases/02-typesetter-css/02-01-SUMMARY.md
|
||||
key_links:
|
||||
- `RDEPUBTextBookBuilder` remains the chapter boundary and provides render context.
|
||||
- `RDEPUBStyleSheetBuilder` is not repurposed for the native path.
|
||||
---
|
||||
|
||||
<objective>
|
||||
设计并实现旧引擎中的 WXRead 风格 stylesheet builder / HTML 预处理增强。
|
||||
|
||||
Purpose: 把章节 HTML、baseURL、资源引用和用户/主题/EPUB 样式合成为一个明确的 native renderer 输入层。
|
||||
Output: `Sources/RDReaderView/EPUBTextRendering/` 中新增或重构的 stylesheet / preprocessing helper,以及与其对接的 renderer entry points。
|
||||
</objective>
|
||||
|
||||
<execution_context>
|
||||
@$HOME/.codex/get-shit-done/workflows/execute-plan.md
|
||||
@$HOME/.codex/get-shit-done/templates/summary.md
|
||||
</execution_context>
|
||||
|
||||
<context>
|
||||
@.planning/PROJECT.md
|
||||
@.planning/ROADMAP.md
|
||||
@.planning/STATE.md
|
||||
@.planning/phases/02-typesetter-css/02-RESEARCH.md
|
||||
@.planning/phases/02-typesetter-css/02-PATTERNS.md
|
||||
@Sources/RDReaderView/EPUBTextRendering/RDEPUBTextRendererSupport.swift
|
||||
@Sources/RDReaderView/EPUBTextRendering/RDEPUBDTCoreTextRenderer.swift
|
||||
@Sources/RDReaderView/EPUBTextRendering/RDEPUBTextBookBuilder.swift
|
||||
@Sources/RDReaderView/EPUBTextRendering/RDEPUBTextRenderer.swift
|
||||
@Sources/RDReaderView/EPUBUI/RDEPUBReaderConfiguration.swift
|
||||
@Sources/RDReaderView/EPUBUI/RDEPUBReaderTheme.swift
|
||||
@Sources/RDReaderView/EPUBCore/RDEPUBPreferences.swift
|
||||
@Sources/RDReaderView/EPUBCore/RDEPUBResourceResolver.swift
|
||||
</context>
|
||||
|
||||
<tasks>
|
||||
|
||||
<task type="auto">
|
||||
<name>Task 1: 建立 native stylesheet / preprocessing helper</name>
|
||||
<files>Sources/RDReaderView/EPUBTextRendering/RDEPUBTextRendererSupport.swift, Sources/RDReaderView/EPUBTextRendering/RDEPUBDTCoreTextRenderer.swift</files>
|
||||
<read_first>Sources/RDReaderView/EPUBTextRendering/RDEPUBTextRendererSupport.swift, Sources/RDReaderView/EPUBTextRendering/RDEPUBDTCoreTextRenderer.swift, Sources/RDReaderView/EPUBCore/RDEPUBPreferences.swift, Sources/RDReaderView/EPUBUI/RDEPUBReaderConfiguration.swift, Sources/RDReaderView/EPUBUI/RDEPUBReaderTheme.swift</read_first>
|
||||
<action>在 `EPUBTextRendering` 内新增或重构一个明确的 native stylesheet/preprocessing helper:它需要把 `RDEPUBPreferences` / `RDEPUBReaderTheme` / `RDEPUBTextRenderStyle` 里的输入翻译成可叠加的 CSS 层,并在 chapter import 前完成 HTML 规范化、style tag 组装和必要的资源上下文占位。实现时要把层级顺序写死为 `default / replace / dark / epub / user`,并把它暴露成可复用的 renderer input,而不是继续在 `dtOptions` 里堆零散参数。</action>
|
||||
<verify>rg -n "default|replace|dark|epub|user|stylesheet|preprocess|chapter|baseURL" Sources/RDReaderView/EPUBTextRendering</verify>
|
||||
<acceptance_criteria>
|
||||
- native renderer 侧出现独立的 stylesheet / preprocessing 责任
|
||||
- CSS 层级顺序是显式且可读的
|
||||
- chapter baseURL 与资源上下文没有被抹掉
|
||||
</acceptance_criteria>
|
||||
<done>章节样式输入不再是一个扁平 option bag,而是一个可追踪、可验证的 native 样式层管线。</done>
|
||||
</task>
|
||||
|
||||
</tasks>
|
||||
|
||||
<verification>
|
||||
Before declaring plan complete:
|
||||
- [ ] `test -f Sources/RDReaderView/EPUBTextRendering/RDEPUBDTCoreTextRenderer.swift`
|
||||
- [ ] `rg -n "default|replace|dark|epub|user|preprocess|stylesheet" Sources/RDReaderView/EPUBTextRendering`
|
||||
- [ ] 计划文档明确拒绝复用 WebView 专用的 `RDEPUBStyleSheetBuilder`
|
||||
</verification>
|
||||
|
||||
<success_criteria>
|
||||
|
||||
- All tasks completed
|
||||
- All verification checks pass
|
||||
- No errors or warnings introduced
|
||||
- native renderer 的样式层输入足以支撑 Phase 2 后半段的 renderer 接线
|
||||
</success_criteria>
|
||||
|
||||
<output>
|
||||
After completion, create `.planning/phases/02-typesetter-css/02-01-SUMMARY.md`
|
||||
</output>
|
||||
@@ -0,0 +1,68 @@
|
||||
---
|
||||
phase: 02-typesetter-css
|
||||
plan: 01
|
||||
subsystem: epub-text-rendering
|
||||
tags: [epub, dtcoretext, css, stylesheet, preprocessing]
|
||||
requires: []
|
||||
provides:
|
||||
- "native renderer 的章节级 stylesheet / preprocessing 输入层"
|
||||
- "显式的 CSS 五层顺序 default / replace / dark / epub / user"
|
||||
- "章节 baseURL 与资源诊断信息"
|
||||
affects: [phase-02, phase-03, reflowable-engine]
|
||||
tech-stack:
|
||||
added: []
|
||||
patterns: ["chapter render request", "stylesheet layering", "resource-aware preprocessing"]
|
||||
key-files:
|
||||
created: []
|
||||
modified:
|
||||
- Sources/RDReaderView/EPUBTextRendering/RDEPUBTextRenderer.swift
|
||||
- Sources/RDReaderView/EPUBTextRendering/RDEPUBTextRendererSupport.swift
|
||||
key-decisions:
|
||||
- "不复用 WebView 专用的 `RDEPUBStyleSheetBuilder`,而是在 native path 中建立独立的 chapter preprocessing pipeline。"
|
||||
- "把 EPUB 外链 CSS 预处理为原位内联样式,并在内联时重写 `url(...)` 资源路径。"
|
||||
patterns-established:
|
||||
- "章节输入先做 HTML 规范化、baseURL 注入、stylesheet 分层,再交给 renderer。"
|
||||
requirements-completed: []
|
||||
duration: 35min
|
||||
completed: 2026-05-22
|
||||
---
|
||||
|
||||
# Phase 02 Plan 01: Typesetter Input Layer Summary
|
||||
|
||||
**为 native reflowable renderer 建立了独立的 chapter stylesheet / preprocessing 层,输入不再只是扁平 DTCoreText options。**
|
||||
|
||||
## Performance
|
||||
|
||||
- **Duration:** 35 min
|
||||
- **Completed:** 2026-05-22
|
||||
- **Tasks:** 1
|
||||
- **Files modified:** 2
|
||||
|
||||
## Accomplishments
|
||||
|
||||
- 在 [RDEPUBTextRenderer.swift](/Users/shen/Work/Code/ReadViewSDK/Sources/RDReaderView/EPUBTextRendering/RDEPUBTextRenderer.swift) 中引入了 `RDEPUBTextChapterContext`、`RDEPUBTextChapterRenderRequest`、`RDEPUBTextStyleSheetPackage` 与资源诊断模型。
|
||||
- 在 [RDEPUBTextRendererSupport.swift](/Users/shen/Work/Code/ReadViewSDK/Sources/RDReaderView/EPUBTextRendering/RDEPUBTextRendererSupport.swift) 中实现了章节 HTML 规范化、`<base>` 注入、linked CSS 内联、`url(...)` 重写,以及 `default / replace / dark / epub / user` 五层 CSS 组装。
|
||||
- 样式层顺序被硬编码进 preprocessing 管线,native renderer 现在消费的是明确的 chapter render request,而不是一组分散选项。
|
||||
|
||||
## Files Created/Modified
|
||||
|
||||
- [RDEPUBTextRenderer.swift](/Users/shen/Work/Code/ReadViewSDK/Sources/RDReaderView/EPUBTextRendering/RDEPUBTextRenderer.swift) - 定义 chapter context、stylesheet package 与 resource diagnostics
|
||||
- [RDEPUBTextRendererSupport.swift](/Users/shen/Work/Code/ReadViewSDK/Sources/RDReaderView/EPUBTextRendering/RDEPUBTextRendererSupport.swift) - 实现 preprocessing、CSS 分层、资源解析与 HTML 注入
|
||||
|
||||
## Decisions Made
|
||||
|
||||
- 明确拒绝把 WebView 分页路径的 `RDEPUBStyleSheetBuilder` 拉回 native renderer。
|
||||
- EPUB 外链 CSS 保持为 EPUB 层,但通过预处理内联进入统一管线,以确保 user layer 始终处于最后覆盖位。
|
||||
|
||||
## Verification
|
||||
|
||||
- `rg -n "default|replace|dark|epub|user|stylesheet|preprocess|chapter|baseURL" Sources/RDReaderView/EPUBTextRendering`
|
||||
- `xcodebuild` simulator build passed via `ReadViewDemo` scheme
|
||||
|
||||
## Next Phase Readiness
|
||||
|
||||
- Renderer 已经有显式 chapter context 和 stylesheet output,Plan 02 可以直接把 `RDEPUBDTCoreTextRenderer` 接到这个新契约上。
|
||||
|
||||
---
|
||||
*Phase: 02-typesetter-css*
|
||||
*Completed: 2026-05-22*
|
||||
@@ -0,0 +1,93 @@
|
||||
---
|
||||
phase: 02-typesetter-css
|
||||
plan: 02
|
||||
type: execute
|
||||
wave: 2
|
||||
depends_on:
|
||||
- "02-01"
|
||||
files_modified:
|
||||
- Sources/RDReaderView/EPUBTextRendering/RDEPUBDTCoreTextRenderer.swift
|
||||
- Sources/RDReaderView/EPUBTextRendering/RDEPUBTextBookBuilder.swift
|
||||
- Sources/RDReaderView/EPUBTextRendering/RDEPUBTextRenderer.swift
|
||||
- Sources/RDReaderView/EPUBCore/RDEPUBResourceResolver.swift
|
||||
- Sources/RDReaderView/EPUBCore/RDEPUBParser.swift
|
||||
autonomous: true
|
||||
requirements:
|
||||
- REND-01
|
||||
- REND-02
|
||||
user_setup: []
|
||||
must_haves:
|
||||
truths:
|
||||
- `RDEPUBDTCoreTextRenderer` receives explicit chapter context and stylesheet output.
|
||||
- `RDEPUBTextBookBuilder` continues to own chapter boundary and page model assembly.
|
||||
- reflowable EPUB input is no longer just a small builder option bag.
|
||||
artifacts:
|
||||
- .planning/phases/02-typesetter-css/02-02-SUMMARY.md
|
||||
key_links:
|
||||
- `RDEPUBParser.readingProfile()` still keeps `webFixedLayout` and `webInteractive` out of this path.
|
||||
- `RDEPUBResourceResolver` remains the authority for baseURL/resource normalization.
|
||||
---
|
||||
|
||||
<objective>
|
||||
改造 `RDEPUBDTCoreTextRenderer` 与相邻渲染链路,使其承接新的样式分层与章节上下文。
|
||||
|
||||
Purpose: 让 native renderer 真正消费 Phase 2.1 产出的 style pipeline,并保持章节边界、资源上下文和 fallback 行为稳定。
|
||||
Output: 对 renderer 和 book builder 的接线调整,使 chapter render path 具备明确的输入契约。
|
||||
</objective>
|
||||
|
||||
<execution_context>
|
||||
@$HOME/.codex/get-shit-done/workflows/execute-plan.md
|
||||
@$HOME/.codex/get-shit-done/templates/summary.md
|
||||
</execution_context>
|
||||
|
||||
<context>
|
||||
@.planning/PROJECT.md
|
||||
@.planning/ROADMAP.md
|
||||
@.planning/STATE.md
|
||||
@.planning/phases/02-typesetter-css/02-RESEARCH.md
|
||||
@.planning/phases/02-typesetter-css/02-PATTERNS.md
|
||||
@.planning/phases/02-typesetter-css/02-01-PLAN.md
|
||||
@Sources/RDReaderView/EPUBTextRendering/RDEPUBDTCoreTextRenderer.swift
|
||||
@Sources/RDReaderView/EPUBTextRendering/RDEPUBTextBookBuilder.swift
|
||||
@Sources/RDReaderView/EPUBTextRendering/RDEPUBTextRenderer.swift
|
||||
@Sources/RDReaderView/EPUBTextRendering/RDEPUBTextRendererSupport.swift
|
||||
@Sources/RDReaderView/EPUBCore/RDEPUBResourceResolver.swift
|
||||
@Sources/RDReaderView/EPUBCore/RDEPUBParser.swift
|
||||
</context>
|
||||
|
||||
<tasks>
|
||||
|
||||
<task type="auto">
|
||||
<name>Task 1: 接入 chapter context 并简化 renderer 输入</name>
|
||||
<files>Sources/RDReaderView/EPUBTextRendering/RDEPUBDTCoreTextRenderer.swift, Sources/RDReaderView/EPUBTextRendering/RDEPUBTextBookBuilder.swift</files>
|
||||
<read_first>Sources/RDReaderView/EPUBTextRendering/RDEPUBDTCoreTextRenderer.swift, Sources/RDReaderView/EPUBTextRendering/RDEPUBTextBookBuilder.swift, Sources/RDReaderView/EPUBTextRendering/RDEPUBTextRenderer.swift, Sources/RDReaderView/EPUBTextRendering/RDEPUBTextRendererSupport.swift</read_first>
|
||||
<action>把 chapter 级上下文显式传入 renderer:包括 `href`、`baseURL`、样式层输出、以及后续资源解析所需的最小元数据。`RDEPUBTextBookBuilder` 继续负责拼接章节、构造 `RDEPUBTextChapter` / `RDEPUBTextPage`,但不再只传一个“扁平 style”给 renderer。`RDEPUBDTCoreTextRenderer` 应该从“DTCoreText option bag 的薄包装”转成“章节 typesetter 的统一入口”。</action>
|
||||
<verify>rg -n "chapter context|baseURL|stylesheet|RDEPUBDTCoreTextRenderer|RDEPUBTextBookBuilder|DTHTMLAttributedStringBuilder" Sources/RDReaderView/EPUBTextRendering</verify>
|
||||
<acceptance_criteria>
|
||||
- renderer 入参能表达 chapter 级上下文
|
||||
- renderer 仍保留 fallback path
|
||||
- book builder 仍然是 page model 的唯一构造点
|
||||
</acceptance_criteria>
|
||||
<done>native renderer 的输入契约足够清楚,后续分页语义重构可以直接接在它后面。</done>
|
||||
</task>
|
||||
|
||||
</tasks>
|
||||
|
||||
<verification>
|
||||
Before declaring plan complete:
|
||||
- [ ] `test -f Sources/RDReaderView/EPUBTextRendering/RDEPUBDTCoreTextRenderer.swift`
|
||||
- [ ] `rg -n "chapter context|baseURL|stylesheet|RDEPUBDTCoreTextRenderer|RDEPUBTextBookBuilder" Sources/RDReaderView/EPUBTextRendering`
|
||||
- [ ] 文档与 Phase 2.1 计划不冲突,并且没有把 WebView 路径拉回 native renderer
|
||||
</verification>
|
||||
|
||||
<success_criteria>
|
||||
|
||||
- All tasks completed
|
||||
- All verification checks pass
|
||||
- No errors or warnings introduced
|
||||
- renderer 与 book builder 的职责边界足够稳定,Phase 2.3 可以直接用真实样本验证资源解析
|
||||
</success_criteria>
|
||||
|
||||
<output>
|
||||
After completion, create `.planning/phases/02-typesetter-css/02-02-SUMMARY.md`
|
||||
</output>
|
||||
@@ -0,0 +1,70 @@
|
||||
---
|
||||
phase: 02-typesetter-css
|
||||
plan: 02
|
||||
subsystem: epub-text-rendering
|
||||
tags: [epub, dtcoretext, renderer, chapter-context]
|
||||
requires: [02-01]
|
||||
provides:
|
||||
- "renderer 接收显式 chapter context"
|
||||
- "book builder 到 renderer 的稳定输入契约"
|
||||
- "resource diagnostics 沿渲染链路透传"
|
||||
affects: [phase-02, phase-03, reflowable-engine]
|
||||
tech-stack:
|
||||
added: []
|
||||
patterns: ["chapter-scoped renderer contract", "book-builder-owned pagination boundary"]
|
||||
key-files:
|
||||
created: []
|
||||
modified:
|
||||
- Sources/RDReaderView/EPUBTextRendering/RDEPUBDTCoreTextRenderer.swift
|
||||
- Sources/RDReaderView/EPUBTextRendering/RDEPUBTextBookBuilder.swift
|
||||
- Sources/RDReaderView/EPUBCore/RDEPUBResourceResolver.swift
|
||||
key-decisions:
|
||||
- "`RDEPUBTextBookBuilder` 继续是 chapter boundary 与 page model assembly 的唯一持有者。"
|
||||
- "`RDEPUBResourceResolver` 扩展为 chapter-relative 资源标准化的权威入口。"
|
||||
patterns-established:
|
||||
- "renderer 从 request.context 读取 href/baseURL/stylesheet/resource diagnostics。"
|
||||
requirements-completed: []
|
||||
duration: 20min
|
||||
completed: 2026-05-22
|
||||
---
|
||||
|
||||
# Phase 02 Plan 02: Renderer Wiring Summary
|
||||
|
||||
**把新的 chapter stylesheet / preprocessing pipeline 正式接入 `RDEPUBDTCoreTextRenderer` 与 `RDEPUBTextBookBuilder`。**
|
||||
|
||||
## Performance
|
||||
|
||||
- **Duration:** 20 min
|
||||
- **Completed:** 2026-05-22
|
||||
- **Tasks:** 1
|
||||
- **Files modified:** 3
|
||||
|
||||
## Accomplishments
|
||||
|
||||
- [RDEPUBDTCoreTextRenderer.swift](/Users/shen/Work/Code/ReadViewSDK/Sources/RDReaderView/EPUBTextRendering/RDEPUBDTCoreTextRenderer.swift) 现在首先消费 `RDEPUBTextChapterRenderRequest`,再根据 request 中的 `baseURL` 与 style 生成 DTCoreText 输入。
|
||||
- [RDEPUBTextBookBuilder.swift](/Users/shen/Work/Code/ReadViewSDK/Sources/RDReaderView/EPUBTextRendering/RDEPUBTextBookBuilder.swift) 在 chapter boundary 处组装 render request,并保留分页、chapter/page model 组装职责不变。
|
||||
- [RDEPUBResourceResolver.swift](/Users/shen/Work/Code/ReadViewSDK/Sources/RDReaderView/EPUBCore/RDEPUBResourceResolver.swift) 新增 chapter-relative `normalizedHref` / `fileURL(forReference:relativeToHref:)`,让资源标准化继续集中在 resolver 层。
|
||||
|
||||
## Files Created/Modified
|
||||
|
||||
- [RDEPUBDTCoreTextRenderer.swift](/Users/shen/Work/Code/ReadViewSDK/Sources/RDReaderView/EPUBTextRendering/RDEPUBDTCoreTextRenderer.swift) - renderer 改为 chapter-scoped 输入契约
|
||||
- [RDEPUBTextBookBuilder.swift](/Users/shen/Work/Code/ReadViewSDK/Sources/RDReaderView/EPUBTextRendering/RDEPUBTextBookBuilder.swift) - builder 负责组装 request,并保留 page model 边界
|
||||
- [RDEPUBResourceResolver.swift](/Users/shen/Work/Code/ReadViewSDK/Sources/RDReaderView/EPUBCore/RDEPUBResourceResolver.swift) - chapter-relative 资源标准化与文件定位
|
||||
|
||||
## Decisions Made
|
||||
|
||||
- 保留 `renderChapter(html:baseURL:style:)` 兼容入口,但统一转发到新的 request-based renderer 契约。
|
||||
- 资源诊断跟随 render result 一起回到 builder,便于后续 demo/sample validation 使用真实 chapter 数据做 spot-check。
|
||||
|
||||
## Verification
|
||||
|
||||
- `rg -n "chapter context|baseURL|stylesheet|RDEPUBDTCoreTextRenderer|RDEPUBTextBookBuilder" Sources/RDReaderView/EPUBTextRendering`
|
||||
- `xcodebuild` simulator build passed via `ReadViewDemo` scheme
|
||||
|
||||
## Next Phase Readiness
|
||||
|
||||
- 真实样本验证现在可以直接读取 builder 的 `lastBuildResourceDiagnostics`,无需再创建并行 reader shell。
|
||||
|
||||
---
|
||||
*Phase: 02-typesetter-css*
|
||||
*Completed: 2026-05-22*
|
||||
@@ -0,0 +1,93 @@
|
||||
---
|
||||
phase: 02-typesetter-css
|
||||
plan: 03
|
||||
type: execute
|
||||
wave: 3
|
||||
depends_on:
|
||||
- "02-02"
|
||||
files_modified:
|
||||
- Sources/RDReaderView/EPUBTextRendering/RDEPUBTextBookBuilder.swift
|
||||
- Sources/RDReaderView/EPUBTextRendering/RDEPUBDTCoreTextRenderer.swift
|
||||
- Sources/RDReaderView/EPUBCore/RDEPUBResourceResolver.swift
|
||||
- Sources/RDReaderView/EPUBCore/RDEPUBParser.swift
|
||||
- ReadViewDemo/ReadViewDemo/ViewController.swift
|
||||
autonomous: true
|
||||
requirements:
|
||||
- REND-01
|
||||
- REND-02
|
||||
user_setup: []
|
||||
must_haves:
|
||||
truths:
|
||||
- sample EPUBs with images and linked CSS can still resolve chapter resources through the new native pipeline.
|
||||
- baseURL and resource normalization are verified against real EPUB files, not just code review.
|
||||
- the validation path stays on the current demo app and does not require a new reader shell.
|
||||
artifacts:
|
||||
- .planning/phases/02-typesetter-css/02-03-SUMMARY.md
|
||||
key_links:
|
||||
- `RDEPUBResourceResolver` and `RDEPUBParser` are the source of truth for normalized chapter/resource paths.
|
||||
- sample books in `ReadViewDemo/ReadViewDemo/book/` are the regression corpus.
|
||||
---
|
||||
|
||||
<objective>
|
||||
验证章节级图片/CSS/基础资源在新渲染输入下可正常解析。
|
||||
|
||||
Purpose: 证明 Phase 2.1 和 Phase 2.2 的接线在真实 EPUB 上没有破坏资源加载和章节样式解析。
|
||||
Output: sample EPUB spot-checks、验证记录和必要的诊断补充。
|
||||
</objective>
|
||||
|
||||
<execution_context>
|
||||
@$HOME/.codex/get-shit-done/workflows/execute-plan.md
|
||||
@$HOME/.codex/get-shit-done/templates/summary.md
|
||||
</execution_context>
|
||||
|
||||
<context>
|
||||
@.planning/PROJECT.md
|
||||
@.planning/ROADMAP.md
|
||||
@.planning/STATE.md
|
||||
@.planning/phases/02-typesetter-css/02-RESEARCH.md
|
||||
@.planning/phases/02-typesetter-css/02-PATTERNS.md
|
||||
@.planning/phases/02-typesetter-css/02-01-PLAN.md
|
||||
@.planning/phases/02-typesetter-css/02-02-PLAN.md
|
||||
@Sources/RDReaderView/EPUBCore/RDEPUBResourceResolver.swift
|
||||
@Sources/RDReaderView/EPUBCore/RDEPUBParser.swift
|
||||
@Sources/RDReaderView/EPUBTextRendering/RDEPUBTextBookBuilder.swift
|
||||
@ReadViewDemo/ReadViewDemo/ViewController.swift
|
||||
@ReadViewDemo/ReadViewDemo/book/
|
||||
</context>
|
||||
|
||||
<tasks>
|
||||
|
||||
<task type="auto">
|
||||
<name>Task 1: 用真实样本书验证 chapter resource resolution</name>
|
||||
<files>Sources/RDReaderView/EPUBTextRendering/RDEPUBTextBookBuilder.swift, Sources/RDReaderView/EPUBCore/RDEPUBResourceResolver.swift</files>
|
||||
<read_first>Sources/RDReaderView/EPUBTextRendering/RDEPUBTextBookBuilder.swift, Sources/RDReaderView/EPUBCore/RDEPUBResourceResolver.swift, Sources/RDReaderView/EPUBCore/RDEPUBParser.swift, ReadViewDemo/ReadViewDemo/ViewController.swift</read_first>
|
||||
<action>使用 `ReadViewDemo/ReadViewDemo/book/` 下的 EPUB 作为验证集,确认新 pipeline 下章节 baseURL、相对 CSS、图片和其他资源仍能正确解析。必要时增加最小的诊断输出或 debug hook,但不要引入新的 reader shell。验证重点是“资源真的能被定位和加载”,不是只看渲染结果是否大致正常。</action>
|
||||
<verify>rg -n "baseURL|resource|css|image|stylesheet|normalized" Sources/RDReaderView/EPUBCore Sources/RDReaderView/EPUBTextRendering ReadViewDemo/ReadViewDemo</verify>
|
||||
<acceptance_criteria>
|
||||
- sample EPUB 资源加载没有断裂
|
||||
- relative href / baseURL 解析保持稳定
|
||||
- demo app 仍然是验证入口
|
||||
</acceptance_criteria>
|
||||
<done>Phase 2 的 stylesheet / preprocessing 改造可以被真实书籍证实没有把资源寻址弄坏。</done>
|
||||
</task>
|
||||
|
||||
</tasks>
|
||||
|
||||
<verification>
|
||||
Before declaring plan complete:
|
||||
- [ ] `test -d ReadViewDemo/ReadViewDemo/book`
|
||||
- [ ] `rg -n "baseURL|resource|css|image|stylesheet|normalized" Sources/RDReaderView/EPUBCore Sources/RDReaderView/EPUBTextRendering`
|
||||
- [ ] demo app 仍然只依赖现有 reader 主流程,没有新增并行引擎
|
||||
</verification>
|
||||
|
||||
<success_criteria>
|
||||
|
||||
- All tasks completed
|
||||
- All verification checks pass
|
||||
- No errors or warnings introduced
|
||||
- 至少一套 sample EPUB 能证明章节资源和样式层在 native renderer 中是可工作的
|
||||
</success_criteria>
|
||||
|
||||
<output>
|
||||
After completion, create `.planning/phases/02-typesetter-css/02-03-SUMMARY.md`
|
||||
</output>
|
||||
@@ -0,0 +1,67 @@
|
||||
---
|
||||
phase: 02-typesetter-css
|
||||
plan: 03
|
||||
subsystem: demo-validation
|
||||
tags: [epub, resources, validation, demo]
|
||||
requires: [02-02]
|
||||
provides:
|
||||
- "真实 EPUB 样本资源验证"
|
||||
- "demo 首页中的验证状态展示"
|
||||
- "运行时日志里的验证结果"
|
||||
affects: [phase-02, phase-05, readviewdemo]
|
||||
tech-stack:
|
||||
added: []
|
||||
patterns: ["sample-corpus validation", "demo-surfaced diagnostics"]
|
||||
key-files:
|
||||
created: []
|
||||
modified:
|
||||
- ReadViewDemo/ReadViewDemo/ViewController.swift
|
||||
key-decisions:
|
||||
- "继续使用现有 demo app 作为验证入口,不新增 reader shell。"
|
||||
- "以 `RDEPUBTextBookBuilder.lastBuildResourceDiagnostics` 为资源完整性判定依据。"
|
||||
patterns-established:
|
||||
- "demo 启动时后台扫描 EPUB corpus,并把 pass/fail 汇总写到状态标签与运行时日志。"
|
||||
requirements-completed: []
|
||||
duration: 20min
|
||||
completed: 2026-05-22
|
||||
---
|
||||
|
||||
# Phase 02 Plan 03: Sample EPUB Validation Summary
|
||||
|
||||
**用 demo 中的真实 EPUB 样本验证了新 native pipeline 的章节资源定位,并把结果直接暴露给 demo UI 与 runtime log。**
|
||||
|
||||
## Performance
|
||||
|
||||
- **Duration:** 20 min
|
||||
- **Completed:** 2026-05-22
|
||||
- **Tasks:** 1
|
||||
- **Files modified:** 1
|
||||
|
||||
## Accomplishments
|
||||
|
||||
- 在 [ViewController.swift](/Users/shen/Work/Code/ReadViewSDK/ReadViewDemo/ReadViewDemo/ViewController.swift) 中增加后台 EPUB validation pass,自动解析 demo corpus、构建 `RDEPUBTextBook`,并检查 `lastBuildResourceDiagnostics` 是否存在缺失资源。
|
||||
- 状态标签现在会显示 `EPUB 资源验证:X/Y 通过`,运行时日志也会输出同样的汇总,便于 simulator 回归。
|
||||
- simulator 运行日志记录了:`[ReadViewDemo] EPUB 资源验证:2/2 通过`,证明两本 `.textReflowable` 样本书在新 pipeline 下资源解析通过。
|
||||
|
||||
## Files Created/Modified
|
||||
|
||||
- [ViewController.swift](/Users/shen/Work/Code/ReadViewSDK/ReadViewDemo/ReadViewDemo/ViewController.swift) - 样本校验、UI 文案展示、runtime log 输出
|
||||
|
||||
## Decisions Made
|
||||
|
||||
- 只把 `.textReflowable` 样本纳入这轮自动验证;`webFixedLayout` / `webInteractive` 仍由原有 WebView 路径负责。
|
||||
- 验证关注点限定为“资源是否被正确定位并进入渲染链路”,不在本阶段引入新的视觉比对基础设施。
|
||||
|
||||
## Verification
|
||||
|
||||
- `test -d ReadViewDemo/ReadViewDemo/book`
|
||||
- `rg -n "baseURL|resource|css|image|stylesheet|normalized" Sources/RDReaderView/EPUBCore Sources/RDReaderView/EPUBTextRendering ReadViewDemo/ReadViewDemo`
|
||||
- simulator runtime log: `[ReadViewDemo] EPUB 资源验证:2/2 通过`
|
||||
|
||||
## Next Phase Readiness
|
||||
|
||||
- Phase 3 可以在这个资源稳定输入层之上直接推进 attributed string 元数据和复杂分页器,不需要再回头补资源寻址契约。
|
||||
|
||||
---
|
||||
*Phase: 02-typesetter-css*
|
||||
*Completed: 2026-05-22*
|
||||
@@ -0,0 +1,32 @@
|
||||
# Phase 2: 重构 typesetter 与 CSS 分层 - Pattern Map
|
||||
|
||||
## Goal
|
||||
|
||||
为本阶段执行提供“先看哪里、按什么证据写代码”的最短路径。Phase 2 的核心不是分页,而是把章节 HTML、baseURL、资源解析和 CSS 层级变成明确的 native renderer 输入。
|
||||
|
||||
## Planned Outputs
|
||||
|
||||
| Planned file | Role | Primary evidence | Why this is the right analog |
|
||||
|--------------|------|------------------|------------------------------|
|
||||
| `.planning/phases/02-typesetter-css/02-01-PLAN.md` | 章节样式层与 HTML 预处理实现计划 | `Sources/RDReaderView/EPUBTextRendering/RDEPUBDTCoreTextRenderer.swift`, `Sources/RDReaderView/EPUBTextRendering/RDEPUBTextRendererSupport.swift`, `Sources/RDReaderView/EPUBTextRendering/RDEPUBTextBookBuilder.swift` | 这些文件已经是 native renderer 的真实入口,最适合承接 stylesheet pipeline。 |
|
||||
| `.planning/phases/02-typesetter-css/02-02-PLAN.md` | renderer 与 chapter context 接线计划 | `Sources/RDReaderView/EPUBTextRendering/RDEPUBDTCoreTextRenderer.swift`, `Sources/RDReaderView/EPUBTextRendering/RDEPUBTextRenderer.swift`, `Sources/RDReaderView/EPUBTextRendering/RDEPUBTextBookBuilder.swift` | 这三个文件共同构成 HTML 导入、章节边界和富文本输出链路。 |
|
||||
| `.planning/phases/02-typesetter-css/02-03-PLAN.md` | 资源解析与样本书验证计划 | `Sources/RDReaderView/EPUBCore/RDEPUBResourceResolver.swift`, `Sources/RDReaderView/EPUBCore/RDEPUBParser.swift`, `ReadViewDemo/ReadViewDemo/book/*.epub` | 资源解析必须靠真实 EPUB 资源和 chapter baseURL 证实,不宜只看代码。 |
|
||||
|
||||
## Code Evidence Map
|
||||
|
||||
| Concern | Closest source of truth | Evidence to extract |
|
||||
|---------|-------------------------|---------------------|
|
||||
| 章节输入如何进入 native renderer | `Sources/RDReaderView/EPUBTextRendering/RDEPUBTextBookBuilder.swift` | chapter `href`、`baseURL`、`renderChapter(...)` 入参、页模型构造点。 |
|
||||
| 当前 renderer 输入到底有多薄 | `Sources/RDReaderView/EPUBTextRendering/RDEPUBDTCoreTextRenderer.swift` | `DTHTMLAttributedStringBuilder`、`dtOptions(baseURL:style:)`、fallback path。 |
|
||||
| 现有 HTML 预处理做了什么 | `Sources/RDReaderView/EPUBTextRendering/RDEPUBTextRendererSupport.swift` | fragment marker 注入、reading attribute normalization、fallback attributed string。 |
|
||||
| 用户样式与主题从哪里来 | `Sources/RDReaderView/EPUBUI/RDEPUBReaderConfiguration.swift`, `Sources/RDReaderView/EPUBUI/RDEPUBReaderTheme.swift`, `Sources/RDReaderView/EPUBCore/RDEPUBPreferences.swift` | font size / line spacing / theme colors 如何进入 renderer 输入。 |
|
||||
| 哪些 CSS helper 不能直接复用 | `Sources/RDReaderView/EPUBCore/RDEPUBStyleSheetBuilder.swift` | 这是 WebView 量测/分页 helper,不是 native DTCoreText stylesheet pipeline。 |
|
||||
| 资源如何定位 | `Sources/RDReaderView/EPUBCore/RDEPUBResourceResolver.swift` | 相对路径、manifest item、OPF directory、normalized href。 |
|
||||
| 哪些样本书最有代表性 | `ReadViewDemo/ReadViewDemo/book/*.epub` | 含图片、复杂段落、外链 CSS 的样本最适合验证 chapter-scoped styles。 |
|
||||
|
||||
## Writing Guidance
|
||||
|
||||
- 计划文档先把新的 native stylesheet pipeline 命名清楚,再把它挂到现有 `RDEPUBDTCoreTextRenderer` 和 `RDEPUBTextBookBuilder` 上。
|
||||
- 任何涉及样式 precedence 的描述,都要写出 `default / replace / dark / epub / user` 的顺序,而不是只说“增加 CSS 支持”。
|
||||
- 资源验证优先写 chapter baseURL 和相对资源引用,不要只验证纯文本章节。
|
||||
- 如果要提到 WebView helper,只能作为“不要复用”的反例。
|
||||
@@ -0,0 +1,177 @@
|
||||
# Phase 2: 重构 typesetter 与 CSS 分层 - Research
|
||||
|
||||
**Researched:** 2026-05-21
|
||||
**Domain:** iOS EPUB reader architecture / native typesetting and chapter-scoped CSS layering
|
||||
**Confidence:** HIGH
|
||||
|
||||
<user_constraints>
|
||||
## User Constraints (from CONTEXT.md)
|
||||
|
||||
No user constraints - all decisions at the agent's discretion.
|
||||
</user_constraints>
|
||||
|
||||
<architectural_responsibility_map>
|
||||
## Architectural Responsibility Map
|
||||
|
||||
| Capability | Primary Tier | Secondary Tier | Rationale |
|
||||
|------------|-------------|----------------|-----------|
|
||||
| 章节 HTML 预处理与 CSS 层级组装 | Browser/Client | EPUBTextRendering | 这是 Phase 2 的主战场,必须在 native reflowable 路径里完成。 |
|
||||
| 章节级 baseURL、资源寻址与样式注入 | Browser/Client | EPUBCore | `RDEPUBTextBookBuilder` 负责提供 chapter boundary 和 baseURL,`RDEPUBResourceResolver` 负责资源定位。 |
|
||||
| 章节 HTML to `NSAttributedString` 导入 | Browser/Client | EPUBTextRendering | `RDEPUBDTCoreTextRenderer` 仍是 DTCoreText 入口,但不能再只依赖一个扁平 option bag。 |
|
||||
| 主题、字号、行高、背景色等用户输入 | EPUBUI | Browser/Client | `RDEPUBReaderConfiguration` / `RDEPUBPreferences` 仍是用户态入口,但它们必须被转换成可叠加的样式层。 |
|
||||
| WebView 渲染与测量辅助 | Browser/Client | EPUBCore | `RDEPUBStyleSheetBuilder` 只服务 `WKWebView` 路径,不应直接搬到 native renderer 里。 |
|
||||
|
||||
</architectural_responsibility_map>
|
||||
|
||||
<research_summary>
|
||||
## Summary
|
||||
|
||||
当前 native reflowable 路径已经有章节边界,但样式输入仍然太薄。`RDEPUBTextBookBuilder` 只负责取出 spine HTML、给出 chapter baseURL,然后把原始 HTML 直接交给 `RDEPUBDTCoreTextRenderer`。后者再用 `DTHTMLAttributedStringBuilder` 加一个小型 option bag 导入,最后靠 `normalizeReadingAttributes` 做字体和行距修正。这种结构能跑通基础排版,但不具备 WXRead 风格的显式 CSS 分层,也没有把章节资源、publication 级样式和用户样式拆成可验证的输入层。
|
||||
|
||||
Phase 2 的正确切入点不是重写 parser,也不是把 `RDEPUBStyleSheetBuilder` 从 WebView 路径直接复用到 native 路径。更稳妥的做法是:在 `EPUBTextRendering` 内部建立一个明确的 stylesheet / preprocessing pipeline,先把章节 HTML 规范化、补齐 baseURL 和资源引用上下文,再按 `default / replace / dark / epub / user` 的顺序合成样式层,最后把合成后的 HTML/CSS 交给 DTCoreText。
|
||||
|
||||
这个阶段的目标是把 renderer 输入从“`DTCoreText` 默认 builder + 少量 options”升级成“章节上下文 + 样式层 + 资源上下文 + 规范化 HTML”。这样后续 Phase 3 才能在不重做入口的前提下,引入更重的页面级属性和分页语义。
|
||||
|
||||
**Primary recommendation:** Phase 2 应先把 native stylesheet pipeline 和 chapter preprocessing 固化在 `EPUBTextRendering`,然后再把 `RDEPUBDTCoreTextRenderer` / `RDEPUBTextBookBuilder` 接到这个 pipeline 上,保持 `RDReaderView` 和 `WKWebView` 路径不动。
|
||||
</research_summary>
|
||||
|
||||
<standard_stack>
|
||||
## Standard Stack
|
||||
|
||||
### Core
|
||||
| Library | Version | Purpose | Why Standard |
|
||||
|---------|---------|---------|--------------|
|
||||
| UIKit | iOS 15+ SDK | Reader UI and style input | 当前 reader 配置、主题与视图层仍然由 UIKit 提供。 |
|
||||
| Foundation | System | HTML normalization, URL handling, string processing | 章节级 baseURL、样式拼接与资源路径修正都依赖它。 |
|
||||
| CoreText | System | Pagination fallback and text measurement | Native book builder 仍需要它做后续分页验证。 |
|
||||
| DTCoreText | 1.6.28 | HTML/CSS to `NSAttributedString` | Phase 2 的目标是把它从“简单导入器”提升成“可配置的章节 typesetter”。 |
|
||||
| WebKit | System | Fixed-layout / interactive EPUB only | 只作为对照边界存在,不进入 Phase 2 的 native 分层。 |
|
||||
|
||||
### Supporting
|
||||
| Library | Version | Purpose | When to Use |
|
||||
|---------|---------|---------|-------------|
|
||||
| ZIPFoundation | 0.9.20 | EPUB archive/resource access | 资源是否能被 chapter baseURL 正确解析,需要它提供底层文件。 |
|
||||
| DTFoundation | 1.7.19 | DTCoreText support | DTCoreText 解析 HTML / 附件 / 图片资源仍依赖它。 |
|
||||
|
||||
### Alternatives Considered
|
||||
| Instead of | Could Use | Tradeoff |
|
||||
|------------|-----------|----------|
|
||||
| Explicit native CSS layering | Continue passing a small `dtOptions` bag | 不能表达 `default / replace / dark / epub / user` 的层级关系,也难验证覆盖顺序。 |
|
||||
| Chapter-scoped preprocessing in `EPUBTextRendering` | Reuse `RDEPUBStyleSheetBuilder` from WebView path | 会把 WebView 测量语义带进 native renderer,职责混淆。 |
|
||||
| DTCoreText-based native evolution | Replacing DTCoreText with a custom HTML parser | 成本和风险都过高,会偏离当前 roadmap 的“直接重构旧引擎”原则。 |
|
||||
|
||||
**Installation:**
|
||||
```bash
|
||||
pod install
|
||||
```
|
||||
</standard_stack>
|
||||
|
||||
<architecture_patterns>
|
||||
## Architecture Patterns
|
||||
|
||||
### System Architecture Diagram
|
||||
|
||||
```text
|
||||
RDEPUBReaderConfiguration / RDEPUBPreferences
|
||||
-> RDEPUBTextRenderStyle
|
||||
-> RDEPUBTextBookBuilder
|
||||
-> chapter HTML + baseURL + resource context
|
||||
-> native stylesheet / preprocessing pipeline
|
||||
-> RDEPUBDTCoreTextRenderer
|
||||
-> DTHTMLAttributedStringBuilder
|
||||
-> NSAttributedString
|
||||
-> RDEPUBTextBook / RDEPUBTextPage
|
||||
```
|
||||
|
||||
### Recommended Project Structure
|
||||
|
||||
```text
|
||||
Sources/RDReaderView/
|
||||
├── EPUBCore/ # Parser, publication, resource resolution, web pagination
|
||||
├── EPUBTextRendering/ # Native reflowable rendering, preprocessing, pagination
|
||||
├── EPUBUI/ # Reader configuration, theme, controller wiring
|
||||
└── RDReaderView.swift # Stable page container and gestures
|
||||
```
|
||||
|
||||
### Pattern 1: Keep chapter context explicit
|
||||
**What:** Every chapter render should know its `href`, `baseURL`, publication-scoped styles, and user style inputs before DTCoreText import begins.
|
||||
**When to use:** When a renderer must resolve relative CSS/image/font URLs reliably.
|
||||
**Example:** `RDEPUBTextBookBuilder` already knows chapter `href` and `baseURL`; Phase 2 should make that context first-class instead of implicit.
|
||||
|
||||
### Pattern 2: Make CSS precedence explicit
|
||||
**What:** Build a deterministic layer order: `default -> replace -> dark -> epub -> user`.
|
||||
**When to use:** When theme, publication, and user preferences can all change the same visual property.
|
||||
**Example:** Dark theme text/background colors should be the highest-priority visible override, while EPUB resources remain below user settings.
|
||||
|
||||
### Pattern 3: Separate preprocessing from pagination
|
||||
**What:** Normalize HTML and resolve resources before chapter import; keep pagination logic in the next stage.
|
||||
**When to use:** When `RDEPUBDTCoreTextRenderer` must remain responsible for HTML-to-attributed-string conversion, not page slicing.
|
||||
**Example:** Phase 2 should leave `ss_pageRanges(size:)` untouched and focus only on renderer input quality.
|
||||
|
||||
### Anti-Patterns to Avoid
|
||||
- **Using `RDEPUBStyleSheetBuilder` as the native stylesheet engine:** It is a WebView measurement helper and already encodes column/layout semantics that do not belong in native DTCoreText import.
|
||||
- **Treating `RDEPUBTextRenderStyle` as the final style model:** It currently carries font, line spacing, and colors, but Phase 2 needs a richer chapter-scoped stylesheet pipeline around it.
|
||||
- **Pushing CSS layering into `RDReaderView`:** The page container should remain a consumer of rendered pages, not a CSS assembly point.
|
||||
|
||||
</architecture_patterns>
|
||||
|
||||
<dont_hand_roll>
|
||||
## Don't Hand-Roll
|
||||
|
||||
| Problem | Don't Build | Use Instead | Why |
|
||||
|---------|-------------|-------------|-----|
|
||||
| HTML parsing | A brand-new EPUB HTML parser | DTCoreText builder extension points | The repo already depends on DTCoreText for native text rendering. |
|
||||
| Resource resolution | Ad-hoc string replacement for relative URLs | `RDEPUBResourceResolver` and `baseURL` context | Resource resolution must remain chapter-scoped and deterministic. |
|
||||
| Theme plumbing | Copying WebView CSS injection logic into native renderer | Reader configuration + native stylesheet layers | Native renderer should own native style semantics. |
|
||||
| Pagination semantics | Page slicing changes in Phase 2 | Keep current `ss_pageRanges(size:)` boundary | Phase 3 owns the heavy pagination rewrite. |
|
||||
|
||||
**Key insight:** Phase 2 should make chapter input richer, not make pagination heavier. The win is in the renderer input contract, not in a new page model yet.
|
||||
</dont_hand_roll>
|
||||
|
||||
<common_pitfalls>
|
||||
## Common Pitfalls
|
||||
|
||||
### Pitfall 1: Reusing the WebView stylesheet helper too early
|
||||
**What goes wrong:** The native path accidentally inherits WebView-only column and viewport semantics.
|
||||
**Why it happens:** `RDEPUBStyleSheetBuilder` looks like a ready-made stylesheet utility, but it is purpose-built for `WKWebView`.
|
||||
**How to avoid:** Build a separate native stylesheet helper under `EPUBTextRendering`.
|
||||
|
||||
### Pitfall 2: Letting style precedence stay implicit
|
||||
**What goes wrong:** Theme, user preferences, and EPUB CSS fight each other with no stable priority.
|
||||
**Why it happens:** `dtOptions` is too small to represent the full cascade.
|
||||
**How to avoid:** Make layer ordering an explicit API and document it in the renderer contract.
|
||||
|
||||
### Pitfall 3: Breaking resource URLs while normalizing HTML
|
||||
**What goes wrong:** Images, linked stylesheets, and fonts stop loading once HTML is rewritten.
|
||||
**Why it happens:** Preprocessing can easily strip or relocate nodes without preserving `baseURL`.
|
||||
**How to avoid:** Keep chapter `baseURL` and resource resolution visible in the pipeline and verify with sample EPUBs.
|
||||
|
||||
</common_pitfalls>
|
||||
|
||||
<sota_updates>
|
||||
## State of the Art (2024-2025)
|
||||
|
||||
| Old Approach | Current Approach | When Changed | Impact |
|
||||
|--------------|------------------|--------------|--------|
|
||||
| Flat HTML import with a small option bag | Explicit chapter-scoped preprocessing plus layered CSS | Already implied by WXRead reference material | Needed to support publication/user/theme overrides in a predictable order. |
|
||||
| Theme colors applied after import | Style inputs assembled before or during import | Already visible in current repo boundary | Reduces post-processing ambiguity and makes resource/style verification easier. |
|
||||
| One-size-fits-all renderer input | Chapter context with separate resource/style concerns | Required by Phase 2 scope | Makes baseURL and CSS resolution testable. |
|
||||
|
||||
**New tools/patterns to consider:**
|
||||
- Chapter-scoped stylesheet assembly: keeps `href`, `baseURL`, and style precedence together.
|
||||
- Pre-import HTML normalization: a safe place to inject style scaffolding without changing page slicing.
|
||||
|
||||
**Deprecated/outdated:**
|
||||
- “Simple DTCoreText renderer + post-hoc normalization” as a long-term design.
|
||||
- “Borrow WebView CSS helpers for native rendering” as a direct implementation strategy.
|
||||
|
||||
</sota_updates>
|
||||
|
||||
<open_questions>
|
||||
## Open Questions
|
||||
|
||||
- Should `default` and `replace` layers be generated from engine code, or should some defaults live in bundled EPUB/native CSS assets?
|
||||
- Where should publication-scoped CSS be sourced from first: OPF manifest, linked chapter CSS files, or a normalized in-memory layer?
|
||||
- Do we need a dedicated native context type for chapter render input, or can `RDEPUBTextBookBuilder` carry all inputs through existing method parameters?
|
||||
- How much of the current `RDEPUBTextRenderStyle` should remain public API versus moving into an internal stylesheet model?
|
||||
</open_questions>
|
||||
@@ -0,0 +1,76 @@
|
||||
---
|
||||
phase: 2
|
||||
slug: typesetter-css
|
||||
status: draft
|
||||
nyquist_compliant: false
|
||||
wave_0_complete: false
|
||||
created: 2026-05-21
|
||||
---
|
||||
|
||||
# Phase 2 — Validation Strategy
|
||||
|
||||
> Per-phase validation contract for feedback sampling during execution.
|
||||
|
||||
---
|
||||
|
||||
## Test Infrastructure
|
||||
|
||||
| Property | Value |
|
||||
|----------|-------|
|
||||
| **Framework** | shell assertions + Xcode build smoke + demo sample EPUB spot-checks |
|
||||
| **Config file** | none — current repo has no dedicated XCTest target for this phase |
|
||||
| **Quick run command** | `test -f .planning/phases/02-typesetter-css/02-RESEARCH.md && test -f .planning/phases/02-typesetter-css/02-PATTERNS.md` |
|
||||
| **Full suite command** | `xcodebuild -workspace ReadViewDemo/ReadViewDemo.xcworkspace -scheme ReadViewDemo -destination 'platform=iOS Simulator,name=iPhone 15' build` |
|
||||
| **Estimated runtime** | ~60-90 seconds |
|
||||
|
||||
---
|
||||
|
||||
## Sampling Rate
|
||||
|
||||
- **After every task commit:** Run the matching `rg` assertions for the touched plan artifact and confirm the intended source files still name the new pipeline entry points.
|
||||
- **After every plan wave:** Run `xcodebuild -workspace ReadViewDemo/ReadViewDemo.xcworkspace -scheme ReadViewDemo -destination 'platform=iOS Simulator,name=iPhone 15' build`.
|
||||
- **Before `$gsd-verify-work`:** Build smoke must be green, the three phase docs must exist, and sample EPUBs must still load in the demo app.
|
||||
- **Max feedback latency:** 90 seconds
|
||||
|
||||
---
|
||||
|
||||
## Per-Task Verification Map
|
||||
|
||||
| Task ID | Plan | Wave | Requirement | Threat Ref | Secure Behavior | Test Type | Automated Command | File Exists | Status |
|
||||
|---------|------|------|-------------|------------|-----------------|-----------|-------------------|-------------|--------|
|
||||
| 02-01-01 | 01 | 1 | REND-02 | — | CSS layering helper has explicit `default / replace / dark / epub / user` precedence and chapter preprocessing hooks | source | `rg -n "default|replace|dark|epub|user|baseURL|preprocess|stylesheet" Sources/RDReaderView/EPUBTextRendering` | ❌ W0 | ⬜ pending |
|
||||
| 02-02-01 | 02 | 2 | REND-01, REND-02 | — | `RDEPUBDTCoreTextRenderer` consumes chapter context instead of a flat option bag, and still preserves `RDEPUBTextBookBuilder` chapter boundaries | source | `rg -n "RDEPUBDTCoreTextRenderer|RDEPUBTextBookBuilder|chapter context|stylesheet|DTHTMLAttributedStringBuilder" Sources/RDReaderView/EPUBTextRendering Sources/RDReaderView/EPUBUI` | ❌ W0 | ⬜ pending |
|
||||
| 02-03-01 | 03 | 3 | REND-01, REND-02 | — | Sample EPUBs resolve chapter CSS/image/baseURL references under the new pipeline | smoke/manual | `rg -n "resource|baseURL|css|image|stylesheet" .planning/phases/02-typesetter-css/02-03-PLAN.md` | ❌ W0 | ⬜ pending |
|
||||
|
||||
*Status: ⬜ pending · ✅ green · ❌ red · ⚠️ flaky*
|
||||
|
||||
---
|
||||
|
||||
## Wave 0 Requirements
|
||||
|
||||
- [ ] No new test target required for Phase 2 planning work.
|
||||
- [ ] Executor must confirm `ReadViewDemo/ReadViewDemo.xcworkspace` and `ReadViewDemo` scheme still open/build before closing the phase.
|
||||
- [ ] Sample books in `ReadViewDemo/ReadViewDemo/book/` remain the regression corpus for manual spot-checks.
|
||||
|
||||
---
|
||||
|
||||
## Manual-Only Verifications
|
||||
|
||||
| Behavior | Requirement | Why Manual | Test Instructions |
|
||||
|----------|-------------|------------|-------------------|
|
||||
| CSS layer precedence is correct in actual rendered chapters | REND-02 | Must compare visible output, not just source strings | Open a sample reflowable EPUB and confirm theme/user/publication styles apply in the intended order. |
|
||||
| Relative CSS/image/baseURL resolution is intact | REND-01, REND-02 | Resource loading failures are easiest to see in the demo app | Open EPUBs with images and linked CSS and verify they still render after preprocessing. |
|
||||
| WebView-only style helpers were not repurposed | REND-01, REND-02 | This is a boundary judgement, not a unit assertion | Inspect the final renderer wiring and confirm `RDEPUBStyleSheetBuilder` remains on the WebView path only. |
|
||||
|
||||
---
|
||||
|
||||
## Validation Sign-Off
|
||||
|
||||
- [ ] All tasks have `<automated>` verify or Wave 0 dependencies
|
||||
- [ ] Sampling continuity: no 3 consecutive tasks without automated verify
|
||||
- [ ] Wave 0 covers all MISSING references
|
||||
- [ ] No watch-mode flags
|
||||
- [ ] Feedback latency < 90s
|
||||
- [ ] `nyquist_compliant: true` set in frontmatter
|
||||
|
||||
**Approval:** pending
|
||||
@@ -0,0 +1,70 @@
|
||||
---
|
||||
phase: 02-typesetter-css
|
||||
verified: 2026-05-22T04:14:30Z
|
||||
status: passed
|
||||
score: 3/3 must-haves verified
|
||||
---
|
||||
|
||||
# Phase 02: Typesetter CSS Verification Report
|
||||
|
||||
**Phase Goal:** 在旧引擎 native reflowable 路径中建立 WXRead 风格的 chapter preprocessing / CSS 分层输入,并验证真实 EPUB 资源解析没有断裂。
|
||||
**Verified:** 2026-05-22T04:14:30Z
|
||||
**Status:** passed
|
||||
|
||||
## Goal Achievement
|
||||
|
||||
### Observable Truths
|
||||
|
||||
| # | Truth | Status | Evidence |
|
||||
|---|-------|--------|----------|
|
||||
| 1 | reflowable renderer 的章节输入不再只是 DTCoreText option bag | ✓ VERIFIED | [RDEPUBTextRenderer.swift](/Users/shen/Work/Code/ReadViewSDK/Sources/RDReaderView/EPUBTextRendering/RDEPUBTextRenderer.swift) 新增 `RDEPUBTextChapterContext` / `RDEPUBTextChapterRenderRequest`,`RDEPUBTextBookBuilder` 在 chapter boundary 组装 request。 |
|
||||
| 2 | CSS 五层顺序 `default / replace / dark / epub / user` 在 native path 中显式落地 | ✓ VERIFIED | [RDEPUBTextRendererSupport.swift](/Users/shen/Work/Code/ReadViewSDK/Sources/RDReaderView/EPUBTextRendering/RDEPUBTextRendererSupport.swift) 的 `makeStyleSheetLayers` 固定了分层顺序,并通过 `injectStyleTag` 注入到 chapter HTML。 |
|
||||
| 3 | 章节级 baseURL、linked CSS、图片资源在真实样本验证中可解析 | ✓ VERIFIED | [RDEPUBResourceResolver.swift](/Users/shen/Work/Code/ReadViewSDK/Sources/RDReaderView/EPUBCore/RDEPUBResourceResolver.swift) 扩展了 chapter-relative 标准化;demo runtime log 记录 `[ReadViewDemo] EPUB 资源验证:2/2 通过`。 |
|
||||
|
||||
**Score:** 3/3 truths verified
|
||||
|
||||
### Required Artifacts
|
||||
|
||||
| Artifact | Expected | Status | Details |
|
||||
|----------|----------|--------|---------|
|
||||
| `.planning/phases/02-typesetter-css/02-01-SUMMARY.md` | preprocessing / stylesheet layering 执行总结 | ✓ EXISTS + SUBSTANTIVE | 记录 native stylesheet pipeline 与关键决策。 |
|
||||
| `.planning/phases/02-typesetter-css/02-02-SUMMARY.md` | renderer wiring 执行总结 | ✓ EXISTS + SUBSTANTIVE | 记录 request-based renderer contract 与 resolver 变更。 |
|
||||
| `.planning/phases/02-typesetter-css/02-03-SUMMARY.md` | sample EPUB validation 总结 | ✓ EXISTS + SUBSTANTIVE | 记录 demo corpus 验证与运行时结果。 |
|
||||
|
||||
**Artifacts:** 3/3 verified
|
||||
|
||||
### Key Link Verification
|
||||
|
||||
| From | To | Via | Status | Details |
|
||||
|------|----|----|--------|---------|
|
||||
| `RDEPUBTextBookBuilder` | `RDEPUBDTCoreTextRenderer` | chapter render request | ✓ WIRED | builder 组装 `RDEPUBTextChapterRenderRequest` 并透传给 renderer。 |
|
||||
| stylesheet preprocessing | resource normalization | `RDEPUBResourceResolver` | ✓ WIRED | linked CSS 与 image diagnostics 使用 chapter-relative resolver API。 |
|
||||
| demo validation | real sample corpus | `ReadViewDemo/ReadViewDemo/book/` | ✓ WIRED | demo 启动时后台扫描 EPUB corpus,并输出 `2/2` 通过结果。 |
|
||||
|
||||
**Wiring:** 3/3 connections verified
|
||||
|
||||
## Requirements Coverage
|
||||
|
||||
| Requirement | Status | Notes |
|
||||
|-------------|--------|-------|
|
||||
| REND-02 | ✓ SATISFIED | CSS 五层分层已在 native renderer 入口落地。 |
|
||||
| REND-01 | ◐ PARTIAL | 本阶段完成 renderer 输入与资源语义重构;页面级元数据与复杂分页能力留给 Phase 3。 |
|
||||
|
||||
## Human Verification Required
|
||||
|
||||
- 若需要视觉确认具体某本书的版式细节,仍建议在 simulator 中手工打开对应 EPUB 做 spot-check。
|
||||
|
||||
## Gaps Summary
|
||||
|
||||
**No blocking gaps found.** Phase 2 goal achieved. Ready for Phase 3 planning.
|
||||
|
||||
## Verification Metadata
|
||||
|
||||
**Verification approach:** code inspection + simulator build/run + sample corpus log verification
|
||||
**Automated checks:** `rg` contract checks, simulator build, demo runtime validation summary
|
||||
**Human checks required:** optional visual spot-check only
|
||||
**Total verification time:** ~8 min
|
||||
|
||||
---
|
||||
*Verified: 2026-05-22T04:14:30Z*
|
||||
*Verifier: inline executor*
|
||||
Reference in New Issue
Block a user