# [recycle] Rust Block Editor Model v0

> 更新时间：2026-04-18
>
> 关联文档：
> - `/mnt/Data1T/mnote/design/old/05-editor-mainline/process/ai-first-rust-block-editor-baseline-v1.md`
> - `/mnt/Data1T/mnote/design/old/05-editor-mainline/process/rust-block-editor-phase0-baseline-v1.md`
> - `/mnt/Data1T/mnote/design/05-editor-mainline/reference-code/edita/edita-core/src/lib.rs`
> - `/mnt/Data1T/mnote/design/05-editor-mainline/reference-code/blocks/src/document.rs`
> - `/mnt/Data1T/mnote/rust/crates/core-protocol/src/editor/model.rs`

## 1. 目的

本文冻结 `task-053` 的第一阶段 Rust block editor 模型口径。

目标不是一次定义最终全文档系统，而是先确定：

- 首批 Rust block type
- `BlockProps` 的最小字段面
- `reference token` 的表示方式
- `content_node` 的载荷格式
- 哪些内容明确退出对 BlockNote JSON 的长期依赖

## 2. 第一阶段 block type

第一阶段固定以下块类型进入 canonical model：

- `paragraph`
- `heading`
- `bullet_list_item`
- `numbered_list_item`
- `quote`
- `todo`
- `code_block`
- `page_reference`
- `block_reference`

补充说明：

- `paragraph` 是默认文本块。
- `heading` 是标题块，级别收敛到 `BlockProps.heading_level`。
- `bullet_list_item` 与 `numbered_list_item` 先保留为列表项，而不是先做复杂 list container。
- `todo` 用来承接当前 `advancedTodo` 的第一阶段简化版。
- `page_reference` 与 `block_reference` 先作为稳定引用块进入模型。

下面这些不进入第一阶段 canonical model，只保留 placeholder 或 compat：

- `media`
- `progressMeter`
- `mindmap`
- `onlineTable`

## 3. `BlockProps`

第一阶段 `BlockProps` 固定为轻量可扩展对象。

核心字段：

- `indent`
- `heading_level`
- `checked`
- `collapsed`
- `language`
- `reference_target_id`
- `reference_label`
- `reference_token_strategy`
- `extra`

固定口径：

- `indent` 表示有限缩进层级，不承诺长期树协议。
- `heading_level` 只对 `heading` 生效。
- `checked` 只对 `todo` 生效。
- `collapsed` 只对 `heading` 生效，用于折叠标题。
- `language` 只对 `code_block` 生效。
- `reference_target_id` 与 `reference_label` 服务 `page_reference` / `block_reference`。
- `extra` 只用于迁移期兼容字段，不能成为长期语义事实源。

## 4. `reference token` 策略

第一阶段引用 token 固定区分两类：

- `page_reference`
- `block_reference`

第一阶段 token strategy 固定支持三种：

- `double_bracket`
- `double_paren`
- `inline_chip`

对应语义：

- `double_bracket` 对应 `[[page]]`
- `double_paren` 对应 `((block))`
- `inline_chip` 只用于 UI 渲染或迁移期兼容，不作为长期文本事实源

引用 token 最小字段：

- `kind`
- `strategy`
- `target_id`
- `label`
- `raw_token`

## 5. `content_node` 载荷格式

第一阶段 `content_node` 是 block 内内容的最小结构单元。

固定 payload 类型：

- `text`
- `hard_break`
- `reference_token`

### 5.1 `text`

`text` 节点字段：

- `text`
- `marks`

`marks` 第一阶段只支持：

- `bold`
- `italic`
- `underline`
- `strike`
- `code`

### 5.2 `hard_break`

`hard_break` 用于显式换行，不引入复杂段内结构树。

### 5.3 `reference_token`

`reference_token` 节点直接挂稳定 token 对象，而不是把引用仅留在原始文本里。

## 6. 块对象与文档对象

第一阶段 canonical block 结构固定为：

- `block_id`
- `block_type`
- `props`
- `content_nodes`
- `child_block_ids`

第一阶段 canonical document 结构固定为：

- `document_id`
- `root_block_ids`
- `blocks`

设计原则：

- `blocks` 先按稳定数组序列输出，便于命令执行和导入导出。
- `child_block_ids` 先表达父子关系，不强求复杂树索引结构。
- `content_nodes` 替代对 BlockNote inline JSON 的长期依赖。

## 7. 与 BlockNote JSON 的边界

第一阶段固定口径：

- BlockNote JSON 只作为迁移期外部格式
- Rust editor model 才是长期事实层
- `BlockProps`、`content_node`、`reference token` 必须能独立表达核心语义

换句话说：

- 可以保留 `BlockNote JSON -> Rust model` 适配器
- 不能继续把 BlockNote JSON 当作长期 canonical schema

## 8. 第一阶段不解决的事

下面这些明确不在 `task-053` 解决：

- 多人协作状态
- 复杂 mark 树
- 富媒体完整属性系统
- `mindmap` / `onlineTable` 的完整内嵌编辑语义
- 完整批量选择与多块复制粘贴

## 9. 结论

`task-053` 的固定口径是：

- 用首批 `paragraph`、`heading`、`bullet_list_item`、`todo`、`page_reference`、`block_reference` 等块型建立 Rust canonical model
- 用 `BlockProps` 收拢最小块属性
- 用 `reference token` 固定 `[[page]]` / `((block))` 的稳定表示
- 用 `content_node` 承接块内文本与引用
- 从这一阶段开始退出对 BlockNote JSON 的长期依赖
