use serde::{Deserialize, Serialize}; use serde_json::Value; #[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)] #[serde(rename_all = "PascalCase")] pub enum PageAggregateSource { KernelProjection, CompatMetaContentJoin, Fixture, } #[derive(Debug, Clone, Serialize, Deserialize, PartialEq)] #[serde(rename_all = "camelCase")] pub struct PageAggregateProjection { pub schema: String, pub projection_version: u32, pub source: PageAggregateSource, pub page_id: String, #[serde(skip_serializing_if = "Option::is_none")] pub parent_id: Option, pub title: String, #[serde(default)] pub path: Vec, #[serde(default)] pub sidebar_tree_membership: Vec, #[serde(skip_serializing_if = "Option::is_none")] pub body_ref: Option, pub layout_options: Value, #[serde(skip_serializing_if = "Option::is_none")] pub updated_at: Option, pub identity: PageIdentity, pub head: PageHead, pub layout: PageLayout, pub body: PageBody, pub tree: PageTree, pub stats: PageStats, } impl PageAggregateProjection { pub const SCHEMA: &'static str = "mnote.page_aggregate.v1"; pub const VERSION: u32 = 1; pub fn source_label(&self) -> &'static str { match self.source { PageAggregateSource::KernelProjection => "rust-kernel", PageAggregateSource::CompatMetaContentJoin => "compat-join", PageAggregateSource::Fixture => "fixture", } } } #[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)] #[serde(rename_all = "camelCase")] pub struct PageIdentity { pub document_id: String, pub workspace_id: String, } #[derive(Debug, Clone, Serialize, Deserialize, PartialEq)] #[serde(rename_all = "camelCase")] pub struct PageHead { pub title: String, pub updated_at: Value, pub permissions: PagePermissions, } #[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)] #[serde(rename_all = "camelCase")] pub struct PagePermissions { pub read_only: bool, pub disable_download: bool, pub disable_copy: bool, } #[derive(Debug, Clone, Serialize, Deserialize, PartialEq)] #[serde(rename_all = "camelCase")] pub struct PageLayout { pub page_options: PageOptions, } #[derive(Debug, Clone, Serialize, Deserialize, PartialEq)] #[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, } impl Default for PageOptions { fn default() -> Self { Self { wide_layout: false, small_text: false, layout_density: "normal".into(), show_heading_numbers: false, show_toc: false, show_structure: false, protect_editing: false, show_word_count: true, collapse_backlinks: false, page_font: "default".into(), hide_child_pages: false, show_block_ref_count: false, embed_default_block_id: Value::Null, } } } #[cfg(test)] mod tests { use super::PageOptions; #[test] fn page_options_default_disables_heading_numbers() { assert!(!PageOptions::default().show_heading_numbers); } } #[derive(Debug, Clone, Serialize, Deserialize, PartialEq)] #[serde(rename_all = "camelCase")] pub struct PageBody { pub content: Value, pub revision: Value, pub conflict_detection_key: Value, } #[derive(Debug, Clone, Serialize, Deserialize, PartialEq)] #[serde(rename_all = "camelCase")] pub struct PageTree { pub page_subtree: Value, } #[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, Default)] #[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, }