feat: cut over rust web main shell

This commit is contained in:
lix-2026
2026-04-29 12:24:44 +08:00
parent 7965c6c107
commit 048fe28a4d
97 changed files with 9396 additions and 1263 deletions
+136
View File
@@ -0,0 +1,136 @@
//! 类型安全的 Page Aggregate 结构体,替代 serde_json::Value 的临时实现。
//!
//! 参考契约文档: design/05-editor-mainline/done/5-5-1-page-aggregate-contract-v1.md
pub mod builder;
use serde::Serialize;
use serde_json::Value;
/// Page Aggregate 根结构
///
/// 对应 JSON 契约:
/// ```json
/// {
/// "schema": "mnote.page_aggregate.v1",
/// "identity": { ... },
/// "head": { ... },
/// "layout": { ... },
/// "body": { ... },
/// "tree": { ... },
/// "stats": { ... }
/// }
/// ```
#[derive(Debug, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct PageAggregate {
pub schema: String,
pub identity: PageIdentity,
pub head: PageHead,
pub layout: PageLayout,
pub body: PageBody,
pub tree: PageTree,
pub stats: PageStats,
}
impl PageAggregate {
/// 创建一个新的 builder 用于构建 PageAggregate。
pub fn builder() -> builder::PageAggregateBuilder {
builder::PageAggregateBuilder::new()
}
/// 序列化为 `serde_json::Value`,输出与当前 `build_page_aggregate_snapshot` 完全一致的 JSON。
///
/// 使用 `#[serde(rename_all = "camelCase")]` 确保字段名与前端契约一致。
pub fn to_json_value(&self) -> Value {
serde_json::to_value(self).expect("PageAggregate 序列化不应失败")
}
/// 获取页面标题(`head.title`)的便捷方法。
pub fn head_title(&self) -> &str {
&self.head.title
}
}
/// 页面身份标识。
///
/// 标识这份页面聚合属于哪一个 page aggregate。
#[derive(Debug, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct PageIdentity {
pub document_id: String,
pub workspace_id: String,
}
/// 页面头部正式真相。
///
/// 承载页面头部的 title、updatedAt 及权限信息。
#[derive(Debug, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct PageHead {
pub title: String,
pub updated_at: Value,
pub permissions: PagePermissions,
}
/// 页面权限。
#[derive(Debug, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct PagePermissions {
pub read_only: bool,
pub disable_download: bool,
pub disable_copy: bool,
}
/// 页面布局。
#[derive(Debug, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct PageLayout {
pub page_options: PageOptions,
}
/// 页面选项 / 编辑器运行时设置。
#[derive(Debug, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct PageOptions {
pub wide_layout: bool,
pub small_text: bool,
pub layout_density: String,
pub show_heading_numbers: bool,
pub show_toc: bool,
pub show_structure: bool,
pub protect_editing: bool,
pub show_word_count: bool,
pub collapse_backlinks: bool,
pub page_font: String,
pub hide_child_pages: bool,
pub show_block_ref_count: bool,
pub embed_default_block_id: Value,
}
/// 页面正文内容与保存元数据。
#[derive(Debug, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct PageBody {
pub content: Value,
pub revision: Value,
pub conflict_detection_key: Value,
}
/// 当前页面对应的子树投影。
#[derive(Debug, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct PageTree {
pub page_subtree: Value,
}
/// 页面统计附属投影。
#[derive(Debug, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct PageStats {
pub word_count: u64,
pub character_count: u64,
pub block_count: u64,
pub todo_total: u64,
pub todo_done: u64,
}