77 lines
3.3 KiB
Markdown
77 lines
3.3 KiB
Markdown
# 7-27 [done][bug] 在线 markdown_edit full_content 会保留旧普通块
|
||||
|
|
|
|||
|
|
> 发现时间:2026-05-18
|
|||
|
|
>
|
|||
|
|
> 状态:`[done]`
|
|||
|
|
>
|
|||
|
|
> 关联主线:`07-ai`
|
|||
|
|
>
|
|||
|
|
> 关联设计:`design/07-ai/process/7-27-online-markdown-writeback-final-content-truth-v2.md`
|
|||
|
|
|
|||
|
|
## 1. 问题定义
|
|||
|
|
|
|||
|
|
`mnote.doc.markdown_edit` 的在线 Convex 文档路径已经切到 final markdown -> block content 直接写回,但 `full_content` 模式下,最终 markdown 通常不包含任何 `<!-- block:... -->` 原始块注释。
|
|||
|
|
|
|||
|
|
当前 `build_page_content()` 会把所有未处理的原始块追加到写回结果尾部,导致全文替换不是“替换全文”,而是:
|
|||
|
|
|
|||
|
|
```text
|
|||
|
|
新全文块...
|
|||
|
|
旧 heading / paragraph / todo 块...
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
## 2. 影响
|
|||
|
|
|
|||
|
|
- AI 执行全文改写、重写大纲、把页面替换为整理后的内容时,会保留旧正文残留。
|
|||
|
|
- Page Aggregate / `mnote.doc.fetch` 回读会看到新旧内容混在一起。
|
|||
|
|
- 7-27 的“最终 markdown 是唯一写回真源”合同被破坏。
|
|||
|
|
|
|||
|
|
## 3. 根因
|
|||
|
|
|
|||
|
|
`parse_final_markdown_to_blocks()` 对无注释的 final markdown 行会生成 `is_new=true` 块,这是正确的。
|
|||
|
|
|
|||
|
|
问题在 `build_page_content()` 的末尾:
|
|||
|
|
|
|||
|
|
```rust
|
|||
|
|
for original in &original_blocks {
|
|||
|
|
if let Some(id) = block_id_of(original) {
|
|||
|
|
if !processed_ids.contains(&id) {
|
|||
|
|
result.push(original.clone());
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
该逻辑没有区分:
|
|||
|
|
|
|||
|
|
- 部分 search/replace 丢掉某个块注释:应保守保留缺失旧块,避免误删。
|
|||
|
|
- `full_content` / 全文替换没有任何原始块 ID:应只保留复杂块,普通旧文本块应被替换掉。
|
|||
|
|
|
|||
|
|
## 4. 修复
|
|||
|
|
|
|||
|
|
- [doc.rs](/mnt/Data1T/mnote/rust/crates/mnote-web/src/hermes_tools/doc.rs:727) 给 `build_page_content()` 增加策略:
|
|||
|
|
- 若 parsed 中至少引用了一个原始 block id,则保留未处理原始块,维持安全降级。
|
|||
|
|
- 若 parsed 中没有任何原始 block id,则视为全文重建,只保留复杂块,不保留普通旧文本块。
|
|||
|
|
- [doc.rs](/mnt/Data1T/mnote/rust/crates/mnote-web/src/hermes_tools/doc.rs:799) 增加 `is_complex_markdown_original_block()`,用于 full_content 重建时保留 resource / mindmap / table / image / attachment / 非 editable / unsupported / 带 children 的复杂块。
|
|||
|
|
- [doc.rs](/mnt/Data1T/mnote/rust/crates/mnote-web/src/hermes_tools/doc.rs:1059) 增加单元测试:
|
|||
|
|
- `full_content` 无原始 ID 时不保留旧 heading / paragraph。
|
|||
|
|
- 原始 resource 复杂块仍保留。
|
|||
|
|
- 部分块注释丢失时仍保留缺失旧块。
|
|||
|
|
|
|||
|
|
## 5. 验证
|
|||
|
|
|
|||
|
|
```bash
|
|||
|
|
cargo test --manifest-path rust/Cargo.toml -p mnote-web build_page_content -- --nocapture
|
|||
|
|
cargo test --manifest-path rust/Cargo.toml -p mnote-web hermes_tools_markdown_edit_online_full_content_rejects_unsafe_block_mapping -- --nocapture
|
|||
|
|
cargo test --manifest-path rust/Cargo.toml -p mnote-web hermes_tools_markdown_edit -- --nocapture
|
|||
|
|
cargo fmt --manifest-path rust/Cargo.toml --all -- --check
|
|||
|
|
git diff --check -- rust/crates/mnote-web/src/hermes_tools/doc.rs bugs/07-ai/done/7-27-markdown-edit-full-content-retains-old-blocks-v1.md
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
结果:
|
|||
|
|
|
|||
|
|
- `build_page_content` 相关测试:`2 passed`。
|
|||
|
|
- `hermes_tools_markdown_edit_online_full_content_rejects_unsafe_block_mapping`:`1 passed`。
|
|||
|
|
- `hermes_tools_markdown_edit` 相关测试:`6 passed`。
|
|||
|
|
- Rust workspace format check 通过。
|
|||
|
|
- 相关路径 diff check 通过。
|