quillmark_core/document/
mod.rs1use serde::{Deserialize, Serialize};
20
21use crate::error::ParseError;
22use crate::version::QuillReference;
23use crate::Diagnostic;
24
25pub mod assemble;
26pub mod dto;
27pub mod edit;
28pub mod emit;
29pub mod fences;
30pub mod limits;
31pub mod meta;
32pub mod payload;
33pub mod prescan;
34
35pub use dto::{peek_schema_version, StorageError, StoredDocument, SCHEMA_V0_81_0, SCHEMA_V0_82_0};
36pub use edit::EditError;
37pub use meta::{is_valid_kind_name, validate_composable_kind, CardKindError};
38pub use payload::{Payload, PayloadItem};
39
40#[cfg(test)]
41mod tests;
42
43#[derive(Debug)]
45pub struct ParseOutput {
46 pub document: Document,
47 pub warnings: Vec<Diagnostic>,
48}
49
50#[derive(Debug, Clone, PartialEq)]
53pub struct Card {
54 payload: Payload,
55 body: String,
56}
57
58impl Card {
59 pub fn from_parts(payload: Payload, body: String) -> Self {
62 Self { payload, body }
63 }
64
65 pub fn quill(&self) -> Option<&QuillReference> {
66 self.payload.quill()
67 }
68
69 pub fn kind(&self) -> Option<&str> {
70 self.payload.kind()
71 }
72
73 pub fn id(&self) -> Option<&str> {
74 self.payload.id()
75 }
76
77 pub fn payload(&self) -> &Payload {
78 &self.payload
79 }
80
81 pub fn payload_mut(&mut self) -> &mut Payload {
82 &mut self.payload
83 }
84
85 pub fn body(&self) -> &str {
86 &self.body
87 }
88
89 pub(crate) fn overwrite_body(&mut self, body: String) {
90 self.body = body;
91 }
92}
93
94#[derive(Debug, Clone, Serialize, Deserialize)]
97#[serde(into = "StoredDocument", try_from = "StoredDocument")]
98pub struct Document {
99 main: Card,
100 cards: Vec<Card>,
101 warnings: Vec<Diagnostic>,
102}
103
104impl PartialEq for Document {
107 fn eq(&self, other: &Self) -> bool {
108 self.main == other.main && self.cards == other.cards
109 }
110}
111
112impl Document {
113 pub fn from_main_and_cards(main: Card, cards: Vec<Card>, warnings: Vec<Diagnostic>) -> Self {
116 debug_assert!(main.quill().is_some(), "main card must carry `$quill`");
117 debug_assert!(
118 cards.iter().all(|c| c.quill().is_none()),
119 "composable cards must not carry `$quill`"
120 );
121 Self {
122 main,
123 cards,
124 warnings,
125 }
126 }
127
128 pub fn from_markdown(markdown: &str) -> Result<Self, ParseError> {
129 assemble::decompose(markdown)
130 }
131
132 pub fn from_markdown_with_warnings(markdown: &str) -> Result<ParseOutput, ParseError> {
133 assemble::decompose_with_warnings(markdown)
134 .map(|(document, warnings)| ParseOutput { document, warnings })
135 }
136
137 pub fn main(&self) -> &Card {
138 &self.main
139 }
140
141 pub fn main_mut(&mut self) -> &mut Card {
142 &mut self.main
143 }
144
145 pub fn quill_reference(&self) -> QuillReference {
147 self.main
148 .quill()
149 .cloned()
150 .expect("root block's $quill is validated at parse time")
151 }
152
153 pub fn cards(&self) -> &[Card] {
154 &self.cards
155 }
156
157 pub fn cards_mut(&mut self) -> &mut [Card] {
158 &mut self.cards
159 }
160
161 pub fn warnings(&self) -> &[Diagnostic] {
163 &self.warnings
164 }
165
166 pub(crate) fn cards_vec_mut(&mut self) -> &mut Vec<Card> {
167 &mut self.cards
168 }
169
170 pub fn to_plate_json(&self) -> serde_json::Value {
181 let mut map = serde_json::Map::new();
182
183 map.insert(
184 "QUILL".to_string(),
185 serde_json::Value::String(self.quill_reference().to_string()),
186 );
187
188 for (key, value) in self.main.payload.iter() {
189 map.insert(key.clone(), value.as_json().clone());
190 }
191
192 map.insert(
193 "BODY".to_string(),
194 serde_json::Value::String(self.main.body.clone()),
195 );
196
197 let cards_array: Vec<serde_json::Value> = self
198 .cards
199 .iter()
200 .map(|card| {
201 let mut card_map = serde_json::Map::new();
202 card_map.insert(
203 "CARD".to_string(),
204 serde_json::Value::String(card.kind().unwrap_or("").to_string()),
205 );
206 for (key, value) in card.payload.iter() {
207 card_map.insert(key.clone(), value.as_json().clone());
208 }
209 card_map.insert(
210 "BODY".to_string(),
211 serde_json::Value::String(card.body.clone()),
212 );
213 serde_json::Value::Object(card_map)
214 })
215 .collect();
216
217 map.insert("CARDS".to_string(), serde_json::Value::Array(cards_array));
218
219 serde_json::Value::Object(map)
220 }
221}