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 ext(&self) -> Option<&serde_json::Map<String, serde_json::Value>> {
82 self.payload.ext()
83 }
84
85 pub fn payload(&self) -> &Payload {
86 &self.payload
87 }
88
89 pub fn payload_mut(&mut self) -> &mut Payload {
90 &mut self.payload
91 }
92
93 pub fn body(&self) -> &str {
94 &self.body
95 }
96
97 pub(crate) fn overwrite_body(&mut self, body: String) {
98 self.body = body;
99 }
100}
101
102#[derive(Debug, Clone, Serialize, Deserialize)]
105#[serde(into = "StoredDocument", try_from = "StoredDocument")]
106pub struct Document {
107 main: Card,
108 cards: Vec<Card>,
109 warnings: Vec<Diagnostic>,
110}
111
112impl PartialEq for Document {
115 fn eq(&self, other: &Self) -> bool {
116 self.main == other.main && self.cards == other.cards
117 }
118}
119
120impl Document {
121 pub fn from_main_and_cards(main: Card, cards: Vec<Card>, warnings: Vec<Diagnostic>) -> Self {
124 debug_assert!(main.quill().is_some(), "main card must carry `$quill`");
125 debug_assert!(
126 cards.iter().all(|c| c.quill().is_none()),
127 "composable cards must not carry `$quill`"
128 );
129 Self {
130 main,
131 cards,
132 warnings,
133 }
134 }
135
136 pub fn from_markdown(markdown: &str) -> Result<Self, ParseError> {
137 assemble::decompose(markdown)
138 }
139
140 pub fn from_markdown_with_warnings(markdown: &str) -> Result<ParseOutput, ParseError> {
141 assemble::decompose_with_warnings(markdown)
142 .map(|(document, warnings)| ParseOutput { document, warnings })
143 }
144
145 pub fn main(&self) -> &Card {
146 &self.main
147 }
148
149 pub fn main_mut(&mut self) -> &mut Card {
150 &mut self.main
151 }
152
153 pub fn quill_reference(&self) -> QuillReference {
155 self.main
156 .quill()
157 .cloned()
158 .expect("root block's $quill is validated at parse time")
159 }
160
161 pub fn cards(&self) -> &[Card] {
162 &self.cards
163 }
164
165 pub fn cards_mut(&mut self) -> &mut [Card] {
166 &mut self.cards
167 }
168
169 pub fn warnings(&self) -> &[Diagnostic] {
171 &self.warnings
172 }
173
174 pub(crate) fn cards_vec_mut(&mut self) -> &mut Vec<Card> {
175 &mut self.cards
176 }
177
178 pub fn to_plate_json(&self) -> serde_json::Value {
195 let mut map = serde_json::Map::new();
196
197 map.insert(
198 "$quill".to_string(),
199 serde_json::Value::String(self.quill_reference().to_string()),
200 );
201
202 map.insert(
203 "$body".to_string(),
204 serde_json::Value::String(self.main.body.clone()),
205 );
206
207 let cards_array: Vec<serde_json::Value> = self
208 .cards
209 .iter()
210 .map(|card| {
211 let mut card_map = serde_json::Map::new();
212 card_map.insert(
213 "$kind".to_string(),
214 serde_json::Value::String(card.kind().unwrap_or("").to_string()),
215 );
216 card_map.insert(
217 "$body".to_string(),
218 serde_json::Value::String(card.body.clone()),
219 );
220 for (key, value) in card.payload.iter() {
221 card_map.insert(key.clone(), value.as_json().clone());
222 }
223 serde_json::Value::Object(card_map)
224 })
225 .collect();
226
227 map.insert("$cards".to_string(), serde_json::Value::Array(cards_array));
228
229 for (key, value) in self.main.payload.iter() {
230 map.insert(key.clone(), value.as_json().clone());
231 }
232
233 serde_json::Value::Object(map)
234 }
235}