1use std::collections::HashMap;
2
3use serde::{Deserialize, Serialize};
4
5fn default_text_run_type() -> TextRunNodeType {
6 TextRunNodeType::Text
7}
8
9fn default_image_run_type() -> ImageRunNodeType {
10 ImageRunNodeType::Image
11}
12
13fn default_form_field_run_type() -> FormFieldRunNodeType {
14 FormFieldRunNodeType::FormField
15}
16
17fn default_paragraph_node_type() -> ParagraphNodeType {
18 ParagraphNodeType::Paragraph
19}
20
21fn default_table_cell_node_type() -> TableCellNodeType {
22 TableCellNodeType::TableCell
23}
24
25fn default_table_row_node_type() -> TableRowNodeType {
26 TableRowNodeType::TableRow
27}
28
29fn default_table_node_type() -> TableNodeType {
30 TableNodeType::Table
31}
32
33#[derive(Clone, Copy, Debug, PartialEq, Eq, Serialize, Deserialize)]
35#[serde(rename_all = "camelCase")]
36pub enum ParagraphAlignment {
37 Left,
38 Center,
39 Right,
40 Justify,
41}
42
43#[derive(Clone, Copy, Debug, PartialEq, Eq, Serialize)]
45#[serde(into = "i64")]
46pub enum HeadingLevel {
47 One = 1,
48 Two = 2,
49 Three = 3,
50 Four = 4,
51 Five = 5,
52 Six = 6,
53 Seven = 7,
54 Eight = 8,
55 Nine = 9,
56}
57
58impl<'de> Deserialize<'de> for HeadingLevel {
59 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
60 where
61 D: serde::Deserializer<'de>,
62 {
63 let value = i64::deserialize(deserializer)?;
64 match value {
65 1 => Ok(HeadingLevel::One),
66 2 => Ok(HeadingLevel::Two),
67 3 => Ok(HeadingLevel::Three),
68 4 => Ok(HeadingLevel::Four),
69 5 => Ok(HeadingLevel::Five),
70 6 => Ok(HeadingLevel::Six),
71 7 => Ok(HeadingLevel::Seven),
72 8 => Ok(HeadingLevel::Eight),
73 9 => Ok(HeadingLevel::Nine),
74 _ => Err(serde::de::Error::custom(format!(
75 "invalid heading level {value}"
76 ))),
77 }
78 }
79}
80
81impl From<HeadingLevel> for i64 {
82 fn from(value: HeadingLevel) -> Self {
83 value as i64
84 }
85}
86
87#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
89#[serde(rename_all = "camelCase")]
90pub struct TextRunBorderStyle {
91 #[serde(rename = "type")]
92 pub border_type: String,
93 #[serde(skip_serializing_if = "Option::is_none")]
94 pub color: Option<String>,
95 #[serde(skip_serializing_if = "Option::is_none")]
96 pub size_eighth_pt: Option<f64>,
97 #[serde(skip_serializing_if = "Option::is_none")]
98 pub space_pt: Option<f64>,
99 #[serde(skip_serializing_if = "Option::is_none")]
100 pub frame: Option<bool>,
101 #[serde(skip_serializing_if = "Option::is_none")]
102 pub shadow: Option<bool>,
103}
104
105#[derive(Clone, Copy, Debug, PartialEq, Eq, Serialize, Deserialize)]
107#[serde(rename_all = "camelCase")]
108pub enum VerticalAlign {
109 #[serde(rename = "superscript")]
110 Superscript,
111 #[serde(rename = "subscript")]
112 Subscript,
113}
114
115#[derive(Clone, Copy, Debug, PartialEq, Eq, Serialize, Deserialize)]
116#[serde(rename_all = "camelCase")]
117pub enum TextLigatures {
118 None,
119 Standard,
120 Contextual,
121 Historical,
122 Discretional,
123 StandardContextual,
124 StandardHistorical,
125 ContextualHistorical,
126 StandardDiscretional,
127 ContextualDiscretional,
128 HistoricalDiscretional,
129 StandardContextualHistorical,
130 StandardContextualDiscretional,
131 StandardHistoricalDiscretional,
132 ContextualHistoricalDiscretional,
133 All,
134}
135
136impl TextLigatures {
137 pub fn from_xml_value(value: &str) -> Option<Self> {
138 match value {
139 "none" => Some(Self::None),
140 "standard" => Some(Self::Standard),
141 "contextual" => Some(Self::Contextual),
142 "historical" => Some(Self::Historical),
143 "discretional" => Some(Self::Discretional),
144 "standardContextual" => Some(Self::StandardContextual),
145 "standardHistorical" => Some(Self::StandardHistorical),
146 "contextualHistorical" => Some(Self::ContextualHistorical),
147 "standardDiscretional" => Some(Self::StandardDiscretional),
148 "contextualDiscretional" => Some(Self::ContextualDiscretional),
149 "historicalDiscretional" => Some(Self::HistoricalDiscretional),
150 "standardContextualHistorical" => Some(Self::StandardContextualHistorical),
151 "standardContextualDiscretional" => Some(Self::StandardContextualDiscretional),
152 "standardHistoricalDiscretional" => Some(Self::StandardHistoricalDiscretional),
153 "contextualHistoricalDiscretional" => Some(Self::ContextualHistoricalDiscretional),
154 "all" => Some(Self::All),
155 _ => None,
156 }
157 }
158
159 pub fn xml_value(self) -> &'static str {
160 match self {
161 Self::None => "none",
162 Self::Standard => "standard",
163 Self::Contextual => "contextual",
164 Self::Historical => "historical",
165 Self::Discretional => "discretional",
166 Self::StandardContextual => "standardContextual",
167 Self::StandardHistorical => "standardHistorical",
168 Self::ContextualHistorical => "contextualHistorical",
169 Self::StandardDiscretional => "standardDiscretional",
170 Self::ContextualDiscretional => "contextualDiscretional",
171 Self::HistoricalDiscretional => "historicalDiscretional",
172 Self::StandardContextualHistorical => "standardContextualHistorical",
173 Self::StandardContextualDiscretional => "standardContextualDiscretional",
174 Self::StandardHistoricalDiscretional => "standardHistoricalDiscretional",
175 Self::ContextualHistoricalDiscretional => "contextualHistoricalDiscretional",
176 Self::All => "all",
177 }
178 }
179}
180
181#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
183#[serde(rename_all = "camelCase")]
184pub struct TextStyle {
185 #[serde(skip_serializing_if = "Option::is_none")]
186 pub text_shadow: Option<TextShadow>,
187 #[serde(skip_serializing_if = "Option::is_none")]
188 pub text_outline: Option<TextOutline>,
189 #[serde(skip_serializing_if = "Option::is_none")]
190 pub bold: Option<bool>,
191 #[serde(skip_serializing_if = "Option::is_none")]
192 pub italic: Option<bool>,
193 #[serde(skip_serializing_if = "Option::is_none")]
194 pub underline: Option<bool>,
195 #[serde(skip_serializing_if = "Option::is_none")]
196 pub strike: Option<bool>,
197 #[serde(skip_serializing_if = "Option::is_none")]
198 pub all_caps: Option<bool>,
199 #[serde(skip_serializing_if = "Option::is_none")]
200 pub small_caps: Option<bool>,
201 #[serde(skip_serializing_if = "Option::is_none")]
202 pub color: Option<String>,
203 #[serde(skip_serializing_if = "Option::is_none")]
204 pub highlight: Option<String>,
205 #[serde(skip_serializing_if = "Option::is_none")]
206 pub background_color: Option<String>,
207 #[serde(skip_serializing_if = "Option::is_none")]
208 pub font_size_pt: Option<f64>,
209 #[serde(skip_serializing_if = "Option::is_none")]
210 pub font_size_cs_pt: Option<f64>,
211 #[serde(skip_serializing_if = "Option::is_none")]
212 pub font_family: Option<String>,
213 #[serde(skip_serializing_if = "Option::is_none")]
216 pub source_font_family: Option<String>,
217 #[serde(skip_serializing_if = "Option::is_none")]
220 pub font_family_ascii: Option<String>,
221 #[serde(skip_serializing_if = "Option::is_none")]
222 pub font_family_h_ansi: Option<String>,
223 #[serde(skip_serializing_if = "Option::is_none")]
224 pub font_family_east_asia: Option<String>,
225 #[serde(skip_serializing_if = "Option::is_none")]
226 pub font_family_cs: Option<String>,
227 #[serde(skip_serializing_if = "Option::is_none")]
228 pub font_theme_ascii: Option<String>,
229 #[serde(skip_serializing_if = "Option::is_none")]
230 pub font_theme_h_ansi: Option<String>,
231 #[serde(skip_serializing_if = "Option::is_none")]
232 pub font_theme_east_asia: Option<String>,
233 #[serde(skip_serializing_if = "Option::is_none")]
234 pub font_theme_cs: Option<String>,
235 #[serde(skip_serializing_if = "Option::is_none")]
236 pub resolved_font_family_ascii: Option<String>,
237 #[serde(skip_serializing_if = "Option::is_none")]
238 pub resolved_font_family_h_ansi: Option<String>,
239 #[serde(skip_serializing_if = "Option::is_none")]
240 pub resolved_font_family_east_asia: Option<String>,
241 #[serde(skip_serializing_if = "Option::is_none")]
242 pub resolved_font_family_cs: Option<String>,
243 #[serde(skip_serializing_if = "Option::is_none")]
244 pub font_hint: Option<String>,
245 #[serde(skip_serializing_if = "Option::is_none")]
248 pub language: Option<String>,
249 #[serde(skip_serializing_if = "Option::is_none")]
250 pub language_east_asia: Option<String>,
251 #[serde(skip_serializing_if = "Option::is_none")]
252 pub language_bidi: Option<String>,
253 #[serde(skip_serializing_if = "Option::is_none")]
254 pub right_to_left: Option<bool>,
255 #[serde(skip_serializing_if = "Option::is_none")]
256 pub complex_script: Option<bool>,
257 #[serde(skip_serializing_if = "Option::is_none")]
258 pub character_spacing_twips: Option<i64>,
259 #[serde(skip_serializing_if = "Option::is_none")]
260 pub character_scale_percent: Option<u16>,
261 #[serde(skip_serializing_if = "Option::is_none")]
262 pub source_character_scale: Option<String>,
263 #[serde(skip_serializing_if = "Option::is_none")]
264 pub kerning_min_font_size_pt: Option<f64>,
265 #[serde(skip_serializing_if = "Option::is_none")]
266 pub ligatures: Option<TextLigatures>,
267 #[serde(skip_serializing_if = "Option::is_none")]
268 pub contextual_alternates: Option<bool>,
269 #[serde(skip_serializing_if = "Option::is_none")]
270 pub vertical_align: Option<VerticalAlign>,
271 #[serde(skip_serializing_if = "Option::is_none")]
272 pub run_border: Option<TextRunBorderStyle>,
273}
274
275#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
276#[serde(rename_all = "camelCase")]
277pub struct TextShadow {
278 pub color: String,
279 pub opacity: f64,
280 pub offset_x_px: f64,
281 pub offset_y_px: f64,
282 pub blur_radius_px: f64,
283 #[serde(skip_serializing_if = "Option::is_none")]
284 pub source_xml: Option<String>,
285 #[serde(skip_serializing_if = "Option::is_none")]
286 pub source_color: Option<String>,
287}
288
289#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
290#[serde(rename_all = "camelCase")]
291pub struct TextOutline {
292 pub color: String,
293 pub opacity: f64,
294 pub width_px: f64,
295 pub line_join: String,
296 #[serde(skip_serializing_if = "Option::is_none")]
297 pub source_xml: Option<String>,
298 #[serde(skip_serializing_if = "Option::is_none")]
299 pub source_color: Option<String>,
300}
301
302#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
304#[serde(transparent)]
305pub struct SharedTextStyle(std::sync::Arc<TextStyle>);
306
307impl SharedTextStyle {
308 pub fn into_owned(self) -> TextStyle {
309 std::sync::Arc::unwrap_or_clone(self.0)
310 }
311}
312
313impl From<TextStyle> for SharedTextStyle {
314 fn from(style: TextStyle) -> Self {
315 Self(std::sync::Arc::new(style))
316 }
317}
318
319impl std::ops::Deref for SharedTextStyle {
320 type Target = TextStyle;
321
322 fn deref(&self) -> &TextStyle {
323 &self.0
324 }
325}
326
327impl std::ops::DerefMut for SharedTextStyle {
328 fn deref_mut(&mut self) -> &mut TextStyle {
329 std::sync::Arc::make_mut(&mut self.0)
330 }
331}
332
333#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
335#[serde(rename_all = "camelCase")]
336pub struct NoteReference {
337 pub kind: NoteReferenceKind,
338 pub id: i64,
339}
340
341#[derive(Clone, Copy, Debug, PartialEq, Eq, Serialize, Deserialize)]
343pub enum NoteReferenceKind {
344 #[serde(rename = "footnote")]
345 Footnote,
346 #[serde(rename = "endnote")]
347 Endnote,
348}
349
350#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
352#[serde(rename_all = "camelCase")]
353pub struct TextRunNode {
354 #[serde(default = "default_text_run_type", rename = "type")]
355 pub r#type: TextRunNodeType,
356 pub text: String,
357 #[serde(skip_serializing_if = "Option::is_none")]
358 pub style: Option<SharedTextStyle>,
359 #[serde(skip_serializing_if = "Option::is_none")]
360 pub link: Option<String>,
361 #[serde(skip_serializing_if = "Option::is_none")]
362 pub note_reference: Option<NoteReference>,
363 #[serde(skip_serializing_if = "Option::is_none")]
364 pub field_instruction: Option<String>,
365}
366
367#[derive(Clone, Copy, Debug, PartialEq, Eq, Serialize, Deserialize)]
369pub enum TextRunNodeType {
370 #[serde(rename = "text")]
371 Text,
372}
373
374#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
376#[serde(rename_all = "camelCase")]
377pub struct ImageCrop {
378 #[serde(skip_serializing_if = "Option::is_none")]
379 pub left_fraction: Option<f64>,
380 #[serde(skip_serializing_if = "Option::is_none")]
381 pub top_fraction: Option<f64>,
382 #[serde(skip_serializing_if = "Option::is_none")]
383 pub right_fraction: Option<f64>,
384 #[serde(skip_serializing_if = "Option::is_none")]
385 pub bottom_fraction: Option<f64>,
386}
387
388#[derive(Clone, Copy, Debug, PartialEq, Eq, Serialize, Deserialize)]
390#[serde(rename_all = "camelCase")]
391pub enum ImageHorizontalAlign {
392 Left,
393 Center,
394 Right,
395 Inside,
396 Outside,
397}
398
399#[derive(Clone, Copy, Debug, PartialEq, Eq, Serialize, Deserialize)]
401#[serde(rename_all = "camelCase")]
402pub enum ImageVerticalAlign {
403 Top,
404 Center,
405 Bottom,
406 Inside,
407 Outside,
408}
409
410#[derive(Clone, Copy, Debug, PartialEq, Eq, Serialize, Deserialize)]
412#[serde(rename_all = "camelCase")]
413pub enum ImageWrapType {
414 #[serde(rename = "none")]
415 WrapNone,
416 #[serde(rename = "square")]
417 Square,
418 #[serde(rename = "tight")]
419 Tight,
420 #[serde(rename = "through")]
421 Through,
422 #[serde(rename = "topAndBottom")]
423 TopAndBottom,
424}
425
426#[derive(Clone, Copy, Debug, PartialEq, Eq, Serialize, Deserialize)]
428#[serde(rename_all = "camelCase")]
429pub enum ImageWrapText {
430 #[serde(rename = "bothSides")]
431 BothSides,
432 #[serde(rename = "left")]
433 Left,
434 #[serde(rename = "right")]
435 Right,
436 #[serde(rename = "largest")]
437 Largest,
438}
439
440#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
442#[serde(rename_all = "camelCase")]
443pub struct ImageFloating {
444 #[serde(skip_serializing_if = "Option::is_none")]
445 pub x_px: Option<f64>,
446 #[serde(skip_serializing_if = "Option::is_none")]
447 pub y_px: Option<f64>,
448 #[serde(skip_serializing_if = "Option::is_none")]
449 pub horizontal_align: Option<ImageHorizontalAlign>,
450 #[serde(skip_serializing_if = "Option::is_none")]
451 pub vertical_align: Option<ImageVerticalAlign>,
452 #[serde(skip_serializing_if = "Option::is_none")]
453 pub horizontal_relative_to: Option<String>,
454 #[serde(skip_serializing_if = "Option::is_none")]
455 pub vertical_relative_to: Option<String>,
456 #[serde(skip_serializing_if = "Option::is_none")]
457 pub dist_l_px: Option<f64>,
458 #[serde(skip_serializing_if = "Option::is_none")]
459 pub dist_r_px: Option<f64>,
460 #[serde(skip_serializing_if = "Option::is_none")]
461 pub dist_t_px: Option<f64>,
462 #[serde(skip_serializing_if = "Option::is_none")]
463 pub dist_b_px: Option<f64>,
464 #[serde(skip_serializing_if = "Option::is_none")]
465 pub wrap_type: Option<ImageWrapType>,
466 #[serde(skip_serializing_if = "Option::is_none")]
467 pub wrap_text: Option<ImageWrapText>,
468 #[serde(skip_serializing_if = "Option::is_none")]
469 pub behind_document: Option<bool>,
470 #[serde(skip_serializing_if = "Option::is_none")]
471 pub z_index: Option<i64>,
472}
473
474#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
475#[serde(rename_all = "camelCase")]
476pub struct ImagePaintBounds {
477 pub x_px: f64,
478 pub y_px: f64,
479 pub width_px: f64,
480 pub height_px: f64,
481 pub layout_width_px: f64,
482 pub layout_height_px: f64,
483}
484
485#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
486#[serde(rename_all = "camelCase")]
487pub struct ImagePropertyAttribute {
488 pub name: String,
489 pub value: String,
490}
491
492#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
494#[serde(rename_all = "camelCase")]
495pub struct ImagePropertyNode {
496 pub name: String,
497 #[serde(default, skip_serializing_if = "Vec::is_empty")]
498 pub attributes: Vec<ImagePropertyAttribute>,
499 #[serde(default, skip_serializing_if = "Vec::is_empty")]
500 pub children: Vec<ImagePropertyNode>,
501 #[serde(default, skip_serializing_if = "Option::is_none")]
502 pub text: Option<String>,
503}
504
505#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
506#[serde(rename_all = "camelCase")]
507pub struct ImageAssetReference {
508 pub element: String,
509 pub kind: String,
510 #[serde(skip_serializing_if = "Option::is_none")]
511 pub relationship_id: Option<String>,
512 #[serde(skip_serializing_if = "Option::is_none")]
513 pub target: Option<String>,
514 pub embedded_asset_available: bool,
515}
516
517#[derive(Clone, Debug, Default, PartialEq, Serialize, Deserialize)]
518#[serde(rename_all = "camelCase")]
519pub struct ImageTransform {
520 #[serde(skip_serializing_if = "Option::is_none")]
521 pub rotation_degrees: Option<f64>,
522 #[serde(skip_serializing_if = "Option::is_none")]
523 pub flip_horizontal: Option<bool>,
524 #[serde(skip_serializing_if = "Option::is_none")]
525 pub flip_vertical: Option<bool>,
526 #[serde(skip_serializing_if = "Option::is_none")]
527 pub offset_x_emu: Option<f64>,
528 #[serde(skip_serializing_if = "Option::is_none")]
529 pub offset_y_emu: Option<f64>,
530 #[serde(skip_serializing_if = "Option::is_none")]
531 pub width_emu: Option<f64>,
532 #[serde(skip_serializing_if = "Option::is_none")]
533 pub height_emu: Option<f64>,
534}
535
536#[derive(Clone, Debug, Default, PartialEq, Serialize, Deserialize)]
537#[serde(rename_all = "camelCase")]
538pub struct ImageTile {
539 #[serde(skip_serializing_if = "Option::is_none")]
540 pub offset_x_emu: Option<f64>,
541 #[serde(skip_serializing_if = "Option::is_none")]
542 pub offset_y_emu: Option<f64>,
543 #[serde(skip_serializing_if = "Option::is_none")]
544 pub scale_x: Option<f64>,
545 #[serde(skip_serializing_if = "Option::is_none")]
546 pub scale_y: Option<f64>,
547 #[serde(skip_serializing_if = "Option::is_none")]
548 pub alignment: Option<String>,
549 #[serde(skip_serializing_if = "Option::is_none")]
550 pub flip: Option<String>,
551}
552
553#[derive(Clone, Debug, Default, PartialEq, Serialize, Deserialize)]
555#[serde(rename_all = "camelCase")]
556pub struct ImagePresentation {
557 #[serde(default, skip_serializing_if = "std::ops::Not::not")]
558 pub transform_applied: bool,
559 #[serde(default, skip_serializing_if = "Vec::is_empty")]
560 pub assets: Vec<ImageAssetReference>,
561 #[serde(skip_serializing_if = "Option::is_none")]
562 pub transform: Option<ImageTransform>,
563 #[serde(skip_serializing_if = "Option::is_none")]
564 pub source_rectangle: Option<ImageCrop>,
565 #[serde(skip_serializing_if = "Option::is_none")]
566 pub fill_rectangle: Option<ImageCrop>,
567 #[serde(skip_serializing_if = "Option::is_none")]
568 pub tile: Option<ImageTile>,
569 #[serde(default, skip_serializing_if = "Vec::is_empty")]
570 pub properties: Vec<ImagePropertyNode>,
571}
572
573#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
575#[serde(rename_all = "camelCase")]
576pub struct ImageRunNode {
577 #[serde(default, rename = "model3d", skip_serializing_if = "Option::is_none")]
578 pub model_3d: Option<Box<rust_office_art::model3d::Model3D>>,
579 #[serde(default, skip_serializing_if = "Option::is_none")]
580 pub presentation: Option<Box<ImagePresentation>>,
581 #[serde(default, skip_serializing_if = "Option::is_none")]
582 pub chart_part_name: Option<String>,
583 #[serde(default, skip_serializing_if = "Option::is_none")]
584 pub chart_data: Option<Box<crate::ChartData>>,
585 #[serde(default, skip_serializing_if = "Option::is_none")]
586 pub paint_bounds: Option<Box<ImagePaintBounds>>,
587 #[serde(default, skip_serializing_if = "Option::is_none")]
588 pub math_ml: Option<String>,
589 #[serde(default, skip_serializing_if = "Option::is_none")]
590 pub content_nodes: Option<Vec<DocNode>>,
591 #[serde(default, skip_serializing_if = "Option::is_none")]
592 pub semantic_kind: Option<String>,
593 #[serde(default, skip_serializing_if = "Option::is_none")]
594 pub block_id: Option<String>,
595 #[serde(default = "default_image_run_type", rename = "type")]
596 pub r#type: ImageRunNodeType,
597 #[serde(skip_serializing_if = "Option::is_none")]
598 pub src: Option<String>,
599 #[serde(skip_serializing_if = "Option::is_none")]
600 pub alt: Option<String>,
601 #[serde(skip_serializing_if = "Option::is_none")]
602 pub width_px: Option<f64>,
603 #[serde(skip_serializing_if = "Option::is_none")]
604 pub height_px: Option<f64>,
605 #[serde(skip_serializing_if = "Option::is_none")]
606 pub part_name: Option<String>,
607 #[serde(skip_serializing_if = "Option::is_none")]
608 pub content_type: Option<String>,
609 #[serde(default, skip_serializing_if = "Option::is_none")]
610 pub data: Option<Vec<u8>>,
611 #[serde(skip_serializing_if = "Option::is_none")]
612 pub source_xml: Option<String>,
613 #[serde(skip_serializing_if = "Option::is_none")]
614 pub crop: Option<ImageCrop>,
615 #[serde(skip_serializing_if = "Option::is_none")]
616 pub css_filter: Option<String>,
617 #[serde(skip_serializing_if = "Option::is_none")]
618 pub css_opacity: Option<f64>,
619 #[serde(skip_serializing_if = "Option::is_none")]
620 pub floating: Option<ImageFloating>,
621 #[serde(skip_serializing_if = "Option::is_none")]
622 pub synthetic_text_box: Option<bool>,
623 #[serde(skip_serializing_if = "Option::is_none")]
624 pub text_box_text: Option<String>,
625}
626
627#[derive(Clone, Copy, Debug, PartialEq, Eq, Serialize, Deserialize)]
629pub enum ImageRunNodeType {
630 #[serde(rename = "image")]
631 Image,
632}
633
634#[derive(Clone, Copy, Debug, PartialEq, Eq, Serialize, Deserialize)]
636#[serde(rename_all = "camelCase")]
637pub enum FormFieldType {
638 #[serde(rename = "checkbox")]
639 Checkbox,
640 #[serde(rename = "text")]
641 Text,
642 #[serde(rename = "date")]
643 Date,
644 #[serde(rename = "dropdown")]
645 Dropdown,
646}
647
648#[derive(Clone, Copy, Debug, PartialEq, Eq, Serialize, Deserialize)]
650pub enum FormFieldSourceKind {
651 #[serde(rename = "sdt")]
652 Sdt,
653 #[serde(rename = "legacy")]
654 Legacy,
655}
656
657#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
659#[serde(rename_all = "camelCase")]
660pub struct FormFieldOption {
661 pub display_text: String,
662 #[serde(skip_serializing_if = "Option::is_none")]
663 pub value: Option<String>,
664}
665
666#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
668#[serde(rename_all = "camelCase")]
669pub struct FormFieldTextWidgetSettings {
670 #[serde(skip_serializing_if = "Option::is_none")]
671 pub input_type: Option<String>,
672 #[serde(skip_serializing_if = "Option::is_none")]
673 pub default_text: Option<String>,
674 #[serde(skip_serializing_if = "Option::is_none")]
675 pub max_length: Option<i64>,
676 #[serde(skip_serializing_if = "Option::is_none")]
677 pub text_format: Option<String>,
678}
679
680#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
682#[serde(rename_all = "camelCase")]
683pub struct FormFieldCheckboxWidgetSettings {
684 #[serde(skip_serializing_if = "Option::is_none")]
685 pub default_checked: Option<bool>,
686 #[serde(skip_serializing_if = "Option::is_none")]
687 pub size_mode: Option<FormFieldCheckboxSizeMode>,
688 #[serde(skip_serializing_if = "Option::is_none")]
689 pub size_pt: Option<f64>,
690}
691
692#[derive(Clone, Copy, Debug, PartialEq, Eq, Serialize, Deserialize)]
694pub enum FormFieldCheckboxSizeMode {
695 #[serde(rename = "auto")]
696 Auto,
697 #[serde(rename = "exact")]
698 Exact,
699}
700
701#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
703#[serde(rename_all = "camelCase")]
704pub struct FormFieldDropdownWidgetSettings {
705 #[serde(skip_serializing_if = "Option::is_none")]
706 pub default_value: Option<String>,
707}
708
709#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
711#[serde(rename_all = "camelCase")]
712pub struct FormFieldWidgetSettings {
713 #[serde(skip_serializing_if = "Option::is_none")]
714 pub name: Option<String>,
715 #[serde(skip_serializing_if = "Option::is_none")]
716 pub enabled: Option<bool>,
717 #[serde(skip_serializing_if = "Option::is_none")]
718 pub calc_on_exit: Option<bool>,
719 #[serde(skip_serializing_if = "Option::is_none")]
720 pub text: Option<FormFieldTextWidgetSettings>,
721 #[serde(skip_serializing_if = "Option::is_none")]
722 pub checkbox: Option<FormFieldCheckboxWidgetSettings>,
723 #[serde(skip_serializing_if = "Option::is_none")]
724 pub dropdown: Option<FormFieldDropdownWidgetSettings>,
725}
726
727#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
728#[serde(rename_all = "camelCase")]
729pub struct FormFieldSourcePreview {
730 pub relationship_id: String,
731 pub shape_id: String,
732 pub checked: bool,
733 pub image: Box<ImageRunNode>,
734}
735
736#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
738#[serde(rename_all = "camelCase")]
739pub struct FormFieldRunNode {
740 #[serde(default = "default_form_field_run_type", rename = "type")]
741 pub r#type: FormFieldRunNodeType,
742 pub field_type: FormFieldType,
743 #[serde(skip_serializing_if = "Option::is_none")]
744 pub source_kind: Option<FormFieldSourceKind>,
745 #[serde(skip_serializing_if = "Option::is_none")]
746 pub id: Option<i64>,
747 #[serde(skip_serializing_if = "Option::is_none")]
748 pub tag: Option<String>,
749 #[serde(skip_serializing_if = "Option::is_none")]
750 pub title: Option<String>,
751 #[serde(skip_serializing_if = "Option::is_none")]
752 pub placeholder: Option<String>,
753 #[serde(skip_serializing_if = "Option::is_none")]
754 pub checked: Option<bool>,
755 #[serde(skip_serializing_if = "Option::is_none")]
756 pub value: Option<String>,
757 #[serde(skip_serializing_if = "Option::is_none")]
758 pub options: Option<Vec<FormFieldOption>>,
759 #[serde(skip_serializing_if = "Option::is_none")]
760 pub widget: Option<FormFieldWidgetSettings>,
761 #[serde(skip_serializing_if = "Option::is_none")]
762 pub checked_symbol: Option<String>,
763 #[serde(skip_serializing_if = "Option::is_none")]
764 pub unchecked_symbol: Option<String>,
765 #[serde(skip_serializing_if = "Option::is_none")]
766 pub style: Option<SharedTextStyle>,
767 #[serde(skip_serializing_if = "Option::is_none")]
768 pub link: Option<String>,
769 #[serde(skip_serializing_if = "Option::is_none")]
770 pub source_xml: Option<String>,
771 #[serde(default, skip_serializing_if = "Option::is_none")]
772 pub source_preview: Option<Box<FormFieldSourcePreview>>,
773}
774
775#[derive(Clone, Copy, Debug, PartialEq, Eq, Serialize, Deserialize)]
777pub enum FormFieldRunNodeType {
778 #[serde(rename = "form-field")]
779 FormField,
780}
781
782#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
784#[serde(untagged)]
785pub enum ParagraphChildNode {
786 Text(TextRunNode),
787 Image(Box<ImageRunNode>),
788 FormField(Box<FormFieldRunNode>),
789}
790
791#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
793#[serde(rename_all = "camelCase")]
794pub struct ParagraphNumbering {
795 pub num_id: i64,
796 pub ilvl: i64,
797}
798
799#[derive(Clone, Copy, Debug, PartialEq, Eq, Serialize, Deserialize)]
801pub enum ParagraphLineRule {
802 #[serde(rename = "auto")]
803 Auto,
804 #[serde(rename = "exact")]
805 Exact,
806 #[serde(rename = "atLeast")]
807 AtLeast,
808}
809
810#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
812#[serde(rename_all = "camelCase")]
813pub struct ParagraphSpacing {
814 #[serde(skip_serializing_if = "Option::is_none")]
815 pub before_twips: Option<i64>,
816 #[serde(skip_serializing_if = "Option::is_none")]
817 pub after_twips: Option<i64>,
818 #[serde(skip_serializing_if = "Option::is_none")]
819 pub before_auto_spacing: Option<bool>,
820 #[serde(skip_serializing_if = "Option::is_none")]
821 pub after_auto_spacing: Option<bool>,
822 #[serde(skip_serializing_if = "Option::is_none")]
823 pub line_twips: Option<i64>,
824 #[serde(skip_serializing_if = "Option::is_none")]
825 pub line_rule: Option<ParagraphLineRule>,
826}
827
828#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
830#[serde(rename_all = "camelCase")]
831pub struct ParagraphIndent {
832 #[serde(skip_serializing_if = "Option::is_none")]
833 pub left_twips: Option<i64>,
834 #[serde(skip_serializing_if = "Option::is_none")]
835 pub right_twips: Option<i64>,
836 #[serde(skip_serializing_if = "Option::is_none")]
837 pub first_line_twips: Option<i64>,
838 #[serde(skip_serializing_if = "Option::is_none")]
839 pub hanging_twips: Option<i64>,
840}
841
842#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
844#[serde(rename_all = "camelCase")]
845pub struct ParagraphBorderStyle {
846 #[serde(rename = "type")]
847 pub border_type: String,
848 #[serde(skip_serializing_if = "Option::is_none")]
849 pub color: Option<String>,
850 #[serde(skip_serializing_if = "Option::is_none")]
851 pub size_eighth_pt: Option<f64>,
852 #[serde(skip_serializing_if = "Option::is_none")]
853 pub space_pt: Option<f64>,
854 #[serde(skip_serializing_if = "Option::is_none")]
855 pub frame: Option<bool>,
856 #[serde(skip_serializing_if = "Option::is_none")]
857 pub shadow: Option<bool>,
858}
859
860#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
862#[serde(rename_all = "camelCase")]
863pub struct ParagraphBorderSet {
864 #[serde(skip_serializing_if = "Option::is_none")]
865 pub top: Option<ParagraphBorderStyle>,
866 #[serde(skip_serializing_if = "Option::is_none")]
867 pub right: Option<ParagraphBorderStyle>,
868 #[serde(skip_serializing_if = "Option::is_none")]
869 pub bottom: Option<ParagraphBorderStyle>,
870 #[serde(skip_serializing_if = "Option::is_none")]
871 pub left: Option<ParagraphBorderStyle>,
872 #[serde(skip_serializing_if = "Option::is_none")]
873 pub between: Option<ParagraphBorderStyle>,
874 #[serde(skip_serializing_if = "Option::is_none")]
875 pub bar: Option<ParagraphBorderStyle>,
876}
877
878#[derive(Clone, Copy, Debug, PartialEq, Eq, Serialize, Deserialize)]
880#[serde(rename_all = "camelCase")]
881pub enum ParagraphTabStopAlignment {
882 Clear,
883 Left,
884 Center,
885 Right,
886 Decimal,
887 Bar,
888}
889
890#[derive(Clone, Copy, Debug, PartialEq, Eq, Serialize, Deserialize)]
892pub enum ParagraphTabStopLeader {
893 #[serde(rename = "none")]
894 LeaderNone,
895 #[serde(rename = "dot")]
896 Dot,
897 #[serde(rename = "hyphen")]
898 Hyphen,
899 #[serde(rename = "underscore")]
900 Underscore,
901 #[serde(rename = "middleDot")]
902 MiddleDot,
903}
904
905#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
907#[serde(rename_all = "camelCase")]
908pub struct ParagraphTabStop {
909 #[serde(skip_serializing_if = "Option::is_none")]
910 pub alignment: Option<ParagraphTabStopAlignment>,
911 #[serde(skip_serializing_if = "Option::is_none")]
912 pub leader: Option<ParagraphTabStopLeader>,
913 #[serde(skip_serializing_if = "Option::is_none")]
914 pub position_twips: Option<i64>,
915}
916
917#[derive(Clone, Copy, Debug, PartialEq, Eq, Serialize, Deserialize)]
919pub enum ParagraphDropCapType {
920 #[serde(rename = "drop")]
921 Drop,
922 #[serde(rename = "margin")]
923 Margin,
924}
925
926#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
928#[serde(rename_all = "camelCase")]
929pub struct ParagraphDropCap {
930 #[serde(rename = "type")]
931 pub drop_cap_type: ParagraphDropCapType,
932 #[serde(skip_serializing_if = "Option::is_none")]
933 pub lines: Option<i64>,
934 #[serde(skip_serializing_if = "Option::is_none")]
935 pub wrap: Option<String>,
936 #[serde(skip_serializing_if = "Option::is_none")]
937 pub horizontal_anchor: Option<String>,
938 #[serde(skip_serializing_if = "Option::is_none")]
939 pub vertical_anchor: Option<String>,
940 #[serde(skip_serializing_if = "Option::is_none")]
941 pub x_twips: Option<i64>,
942 #[serde(skip_serializing_if = "Option::is_none")]
943 pub y_twips: Option<i64>,
944 #[serde(skip_serializing_if = "Option::is_none")]
945 pub horizontal_space_twips: Option<i64>,
946 #[serde(skip_serializing_if = "Option::is_none")]
947 pub vertical_space_twips: Option<i64>,
948}
949
950#[derive(Clone, Copy, Debug, PartialEq, Eq, Serialize, Deserialize)]
951#[serde(rename_all = "camelCase")]
952pub enum ParagraphTextAlignment {
953 Auto,
954 Top,
955 Center,
956 Baseline,
957 Bottom,
958}
959
960#[derive(Clone, Debug, Default, PartialEq, Serialize, Deserialize)]
962#[serde(rename_all = "camelCase")]
963pub struct ParagraphStyle {
964 #[serde(skip_serializing_if = "Option::is_none")]
965 pub source_before_auto_spacing: Option<bool>,
966 #[serde(skip_serializing_if = "Option::is_none")]
967 pub source_after_auto_spacing: Option<bool>,
968 #[serde(skip_serializing_if = "Option::is_none")]
969 pub align: Option<ParagraphAlignment>,
970 #[serde(skip_serializing_if = "Option::is_none")]
971 pub snap_to_grid: Option<bool>,
972 #[serde(skip_serializing_if = "Option::is_none")]
973 pub source_snap_to_grid: Option<bool>,
974 #[serde(skip_serializing_if = "Option::is_none")]
975 pub source_has_snap_to_grid: Option<bool>,
976 #[serde(skip_serializing_if = "Option::is_none")]
977 pub source_inherited_snap_to_grid: Option<bool>,
978 #[serde(skip_serializing_if = "Option::is_none")]
979 pub source_table_snap_to_grid: Option<bool>,
980 #[serde(skip_serializing_if = "Option::is_none")]
981 pub text_alignment: Option<ParagraphTextAlignment>,
982 #[serde(skip_serializing_if = "Option::is_none")]
983 pub source_text_alignment: Option<ParagraphTextAlignment>,
984 #[serde(skip_serializing_if = "Option::is_none")]
985 pub source_has_text_alignment: Option<bool>,
986 #[serde(skip_serializing_if = "Option::is_none")]
987 pub source_inherited_text_alignment: Option<ParagraphTextAlignment>,
988 #[serde(skip_serializing_if = "Option::is_none")]
989 pub source_table_text_alignment: Option<ParagraphTextAlignment>,
990 #[serde(skip_serializing_if = "Option::is_none")]
991 pub heading_level: Option<HeadingLevel>,
992 #[serde(skip_serializing_if = "Option::is_none")]
993 pub style_id: Option<String>,
994 #[serde(skip_serializing_if = "Option::is_none")]
995 pub style_name: Option<String>,
996 #[serde(skip_serializing_if = "Option::is_none")]
997 pub numbering: Option<ParagraphNumbering>,
998 #[serde(skip_serializing_if = "Option::is_none")]
999 pub spacing: Option<ParagraphSpacing>,
1000 #[serde(skip_serializing_if = "Option::is_none")]
1001 pub indent: Option<ParagraphIndent>,
1002 #[serde(skip_serializing_if = "Option::is_none")]
1003 pub background_color: Option<String>,
1004 #[serde(skip_serializing_if = "Option::is_none")]
1005 pub borders: Option<ParagraphBorderSet>,
1006 #[serde(skip_serializing_if = "Option::is_none")]
1007 pub tab_stops: Option<Vec<ParagraphTabStop>>,
1008 #[serde(skip_serializing_if = "Option::is_none")]
1009 pub contextual_spacing: Option<bool>,
1010 #[serde(skip_serializing_if = "Option::is_none")]
1011 pub keep_next: Option<bool>,
1012 #[serde(skip_serializing_if = "Option::is_none")]
1013 pub keep_lines: Option<bool>,
1014 #[serde(skip_serializing_if = "Option::is_none")]
1015 pub widow_control: Option<bool>,
1016 #[serde(skip_serializing_if = "Option::is_none")]
1017 pub page_break_before: Option<bool>,
1018 #[serde(skip_serializing_if = "Option::is_none")]
1019 pub drop_cap: Option<ParagraphDropCap>,
1020}
1021
1022#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
1024#[serde(rename_all = "camelCase")]
1025pub struct ParagraphSourceTextPatchRun {
1026 #[serde(skip_serializing_if = "Option::is_none")]
1027 pub style: Option<SharedTextStyle>,
1028 #[serde(skip_serializing_if = "Option::is_none")]
1029 pub link: Option<String>,
1030 #[serde(skip_serializing_if = "Option::is_none")]
1031 pub note_reference: Option<NoteReference>,
1032}
1033
1034#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
1035#[serde(rename_all = "camelCase")]
1036pub struct ParagraphSourceTextPatch {
1037 pub runs: Vec<ParagraphSourceTextPatchRun>,
1038}
1039
1040#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
1042#[serde(rename_all = "camelCase")]
1043pub struct ParagraphMarkFormattingSource {
1044 #[serde(skip_serializing_if = "Option::is_none")]
1045 pub default_style: Option<SharedTextStyle>,
1046 #[serde(skip_serializing_if = "Option::is_none")]
1047 pub character_style: Option<SharedTextStyle>,
1048 #[serde(skip_serializing_if = "Option::is_none")]
1049 pub direct_style: Option<SharedTextStyle>,
1050}
1051
1052#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
1054#[serde(rename_all = "camelCase")]
1055pub struct ParagraphNode {
1056 #[serde(default, skip_serializing_if = "Option::is_none")]
1057 pub review_content: Option<Vec<crate::revisions::ReviewContent>>,
1058 #[serde(default, skip_serializing_if = "Option::is_none")]
1059 pub block_id: Option<String>,
1060 #[serde(default = "default_paragraph_node_type", rename = "type")]
1061 pub r#type: ParagraphNodeType,
1062 pub children: Vec<ParagraphChildNode>,
1063 #[serde(skip_serializing_if = "Option::is_none")]
1064 pub style: Option<SharedParagraphStyle>,
1065 #[serde(skip_serializing_if = "Option::is_none")]
1066 pub paragraph_mark_style: Option<SharedTextStyle>,
1067 #[serde(skip_serializing_if = "Option::is_none")]
1068 pub source_paragraph_mark_style: Option<SharedTextStyle>,
1069 #[serde(skip_serializing_if = "Option::is_none")]
1070 pub source_paragraph_mark_formatting: Option<ParagraphMarkFormattingSource>,
1071 #[serde(skip_serializing_if = "Option::is_none")]
1072 pub source_paragraph_mark_properties_xml: Option<String>,
1073 #[serde(skip_serializing_if = "Option::is_none")]
1074 pub paragraph_mark_deleted: Option<bool>,
1075 #[serde(skip_serializing_if = "Option::is_none")]
1076 pub source_xml: Option<String>,
1077 #[serde(skip_serializing_if = "Option::is_none")]
1078 pub source_text_patch: Option<ParagraphSourceTextPatch>,
1079 #[serde(skip_serializing_if = "Option::is_none")]
1082 pub source_run_provenance: Option<ParagraphSourceTextPatch>,
1083}
1084
1085#[derive(Clone, Copy, Debug, PartialEq, Eq, Serialize, Deserialize)]
1087pub enum ParagraphNodeType {
1088 #[serde(rename = "paragraph")]
1089 Paragraph,
1090}
1091
1092#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
1094#[serde(rename_all = "camelCase")]
1095pub struct TableBoxSpacing {
1096 #[serde(skip_serializing_if = "Option::is_none")]
1097 pub top_twips: Option<i64>,
1098 #[serde(skip_serializing_if = "Option::is_none")]
1099 pub right_twips: Option<i64>,
1100 #[serde(skip_serializing_if = "Option::is_none")]
1101 pub bottom_twips: Option<i64>,
1102 #[serde(skip_serializing_if = "Option::is_none")]
1103 pub left_twips: Option<i64>,
1104}
1105
1106#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
1108#[serde(rename_all = "camelCase")]
1109pub struct TableBorderStyle {
1110 #[serde(rename = "type")]
1111 pub border_type: String,
1112 #[serde(skip_serializing_if = "Option::is_none")]
1113 pub color: Option<String>,
1114 #[serde(skip_serializing_if = "Option::is_none")]
1115 pub size_eighth_pt: Option<f64>,
1116}
1117
1118#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
1120#[serde(rename_all = "camelCase")]
1121pub struct TableBorderSet {
1122 #[serde(skip_serializing_if = "Option::is_none")]
1123 pub top: Option<TableBorderStyle>,
1124 #[serde(skip_serializing_if = "Option::is_none")]
1125 pub right: Option<TableBorderStyle>,
1126 #[serde(skip_serializing_if = "Option::is_none")]
1127 pub bottom: Option<TableBorderStyle>,
1128 #[serde(skip_serializing_if = "Option::is_none")]
1129 pub left: Option<TableBorderStyle>,
1130 #[serde(skip_serializing_if = "Option::is_none")]
1131 pub inside_h: Option<TableBorderStyle>,
1132 #[serde(skip_serializing_if = "Option::is_none")]
1133 pub inside_v: Option<TableBorderStyle>,
1134 #[serde(skip_serializing_if = "Option::is_none")]
1135 pub tl2br: Option<TableBorderStyle>,
1136 #[serde(skip_serializing_if = "Option::is_none")]
1137 pub tr2bl: Option<TableBorderStyle>,
1138}
1139
1140#[derive(Clone, Copy, Debug, PartialEq, Eq, Serialize, Deserialize)]
1142#[serde(rename_all = "camelCase")]
1143pub enum TableCellVerticalAlign {
1144 Top,
1145 Center,
1146 Bottom,
1147}
1148
1149#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
1151#[serde(tag = "type", rename_all = "camelCase")]
1152pub enum TablePreferredWidth {
1153 Dxa { value: f64 },
1154 Pct { value: f64 },
1155 Auto,
1156 Nil,
1157}
1158
1159#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
1161#[serde(rename_all = "camelCase")]
1162pub struct TableWidthSource {
1163 #[serde(skip_serializing_if = "Option::is_none")]
1164 pub preferred_width: Option<TablePreferredWidth>,
1165 #[serde(skip_serializing_if = "Option::is_none")]
1166 pub width_twips: Option<i64>,
1167 #[serde(skip_serializing_if = "Option::is_none")]
1168 pub inherited_preferred_width: Option<TablePreferredWidth>,
1169}
1170
1171#[derive(Clone, Copy, Debug, PartialEq, Eq, Serialize, Deserialize)]
1172#[serde(rename_all = "camelCase")]
1173pub enum TableAlignment {
1174 Left,
1175 Center,
1176 Right,
1177}
1178
1179#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
1181#[serde(rename_all = "camelCase")]
1182pub struct TableCellStyle {
1183 #[serde(skip_serializing_if = "Option::is_none")]
1184 pub background_color: Option<String>,
1185 #[serde(skip_serializing_if = "Option::is_none")]
1186 pub grid_span: Option<i64>,
1187 #[serde(skip_serializing_if = "Option::is_none")]
1188 pub row_span: Option<i64>,
1189 #[serde(skip_serializing_if = "Option::is_none")]
1190 pub v_merge_continuation: Option<bool>,
1191 #[serde(skip_serializing_if = "Option::is_none")]
1192 pub width_twips: Option<i64>,
1193 #[serde(skip_serializing_if = "Option::is_none")]
1194 pub preferred_width: Option<TablePreferredWidth>,
1195 #[serde(skip_serializing_if = "Option::is_none")]
1196 pub source_width: Option<TableWidthSource>,
1197 #[serde(skip_serializing_if = "Option::is_none")]
1198 pub margin_twips: Option<TableBoxSpacing>,
1199 #[serde(skip_serializing_if = "Option::is_none")]
1200 pub vertical_align: Option<TableCellVerticalAlign>,
1201 #[serde(skip_serializing_if = "Option::is_none")]
1202 pub text_direction: Option<String>,
1203 #[serde(skip_serializing_if = "Option::is_none")]
1204 pub source_text_direction: Option<String>,
1205 #[serde(skip_serializing_if = "Option::is_none")]
1206 pub no_wrap: Option<bool>,
1207 #[serde(skip_serializing_if = "Option::is_none")]
1208 pub source_no_wrap: Option<bool>,
1209 #[serde(skip_serializing_if = "Option::is_none")]
1210 pub borders: Option<TableBorderSet>,
1211}
1212
1213#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
1215#[serde(untagged)]
1216pub enum TableCellContentNode {
1217 Paragraph(ParagraphNode),
1218 Table(Box<TableNode>),
1219}
1220
1221#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
1223#[serde(rename_all = "camelCase")]
1224pub struct TableCellNode {
1225 #[serde(default = "default_table_cell_node_type", rename = "type")]
1226 pub r#type: TableCellNodeType,
1227 pub nodes: Vec<TableCellContentNode>,
1228 #[serde(skip_serializing_if = "Option::is_none")]
1229 pub style: Option<TableCellStyle>,
1230}
1231
1232#[derive(Clone, Copy, Debug, PartialEq, Eq, Serialize, Deserialize)]
1234pub enum TableCellNodeType {
1235 #[serde(rename = "table-cell")]
1236 TableCell,
1237}
1238
1239#[derive(Clone, Copy, Debug, PartialEq, Eq, Serialize, Deserialize)]
1241pub enum TableRowHeightRule {
1242 #[serde(rename = "auto")]
1243 Auto,
1244 #[serde(rename = "atLeast")]
1245 AtLeast,
1246 #[serde(rename = "exact")]
1247 Exact,
1248}
1249
1250#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
1252#[serde(rename_all = "camelCase")]
1253pub struct TableRowGeometrySource {
1254 #[serde(skip_serializing_if = "Option::is_none")]
1255 pub grid_before: Option<i64>,
1256 #[serde(skip_serializing_if = "Option::is_none")]
1257 pub grid_after: Option<i64>,
1258 #[serde(skip_serializing_if = "Option::is_none")]
1259 pub width_before: Option<TablePreferredWidth>,
1260 #[serde(skip_serializing_if = "Option::is_none")]
1261 pub width_after: Option<TablePreferredWidth>,
1262}
1263
1264#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
1266#[serde(rename_all = "camelCase")]
1267pub struct TableRowStyle {
1268 #[serde(skip_serializing_if = "Option::is_none")]
1269 pub grid_before: Option<i64>,
1270 #[serde(skip_serializing_if = "Option::is_none")]
1271 pub grid_after: Option<i64>,
1272 #[serde(skip_serializing_if = "Option::is_none")]
1273 pub width_before: Option<TablePreferredWidth>,
1274 #[serde(skip_serializing_if = "Option::is_none")]
1275 pub width_after: Option<TablePreferredWidth>,
1276 #[serde(skip_serializing_if = "Option::is_none")]
1277 pub source_row_geometry: Option<TableRowGeometrySource>,
1278 #[serde(skip_serializing_if = "Option::is_none")]
1279 pub background_color: Option<String>,
1280 #[serde(skip_serializing_if = "Option::is_none")]
1281 pub height_twips: Option<i64>,
1282 #[serde(skip_serializing_if = "Option::is_none")]
1283 pub height_rule: Option<TableRowHeightRule>,
1284 #[serde(skip_serializing_if = "Option::is_none")]
1285 pub cant_split: Option<bool>,
1286 #[serde(skip_serializing_if = "Option::is_none")]
1287 pub is_header: Option<bool>,
1288}
1289
1290#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
1292#[serde(rename_all = "camelCase")]
1293pub struct TableRowNode {
1294 #[serde(default = "default_table_row_node_type", rename = "type")]
1295 pub r#type: TableRowNodeType,
1296 pub cells: Vec<TableCellNode>,
1297 #[serde(skip_serializing_if = "Option::is_none")]
1298 pub style: Option<TableRowStyle>,
1299}
1300
1301#[derive(Clone, Copy, Debug, PartialEq, Eq, Serialize, Deserialize)]
1303pub enum TableRowNodeType {
1304 #[serde(rename = "table-row")]
1305 TableRow,
1306}
1307
1308#[derive(Clone, Copy, Debug, PartialEq, Eq, Serialize, Deserialize)]
1310pub enum TableLayout {
1311 #[serde(rename = "fixed")]
1312 Fixed,
1313 #[serde(rename = "autofit")]
1314 Autofit,
1315}
1316
1317#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
1319#[serde(rename_all = "camelCase")]
1320pub struct TableFloating {
1321 #[serde(skip_serializing_if = "Option::is_none")]
1322 pub x_twips: Option<i64>,
1323 #[serde(skip_serializing_if = "Option::is_none")]
1324 pub y_twips: Option<i64>,
1325 #[serde(skip_serializing_if = "Option::is_none")]
1326 pub left_from_text_twips: Option<i64>,
1327 #[serde(skip_serializing_if = "Option::is_none")]
1328 pub right_from_text_twips: Option<i64>,
1329 #[serde(skip_serializing_if = "Option::is_none")]
1330 pub top_from_text_twips: Option<i64>,
1331 #[serde(skip_serializing_if = "Option::is_none")]
1332 pub bottom_from_text_twips: Option<i64>,
1333 #[serde(skip_serializing_if = "Option::is_none")]
1334 pub horizontal_anchor: Option<String>,
1335 #[serde(skip_serializing_if = "Option::is_none")]
1336 pub vertical_anchor: Option<String>,
1337 #[serde(skip_serializing_if = "Option::is_none")]
1338 pub horizontal_align: Option<ImageHorizontalAlign>,
1339 #[serde(skip_serializing_if = "Option::is_none")]
1340 pub vertical_align: Option<ImageVerticalAlign>,
1341}
1342
1343#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
1345#[serde(rename_all = "camelCase")]
1346pub struct TableStyle {
1347 #[serde(skip_serializing_if = "Option::is_none")]
1348 pub style_id: Option<String>,
1349 #[serde(skip_serializing_if = "Option::is_none")]
1350 pub source_style_id: Option<String>,
1351 #[serde(skip_serializing_if = "Option::is_none")]
1352 pub width_twips: Option<i64>,
1353 #[serde(skip_serializing_if = "Option::is_none")]
1354 pub preferred_width: Option<TablePreferredWidth>,
1355 #[serde(skip_serializing_if = "Option::is_none")]
1356 pub source_width: Option<TableWidthSource>,
1357 #[serde(skip_serializing_if = "Option::is_none")]
1358 pub alignment: Option<TableAlignment>,
1359 #[serde(skip_serializing_if = "Option::is_none")]
1360 pub source_alignment: Option<TableAlignment>,
1361 #[serde(skip_serializing_if = "Option::is_none")]
1362 pub source_inherited_alignment: Option<TableAlignment>,
1363 #[serde(skip_serializing_if = "Option::is_none")]
1364 pub bidi_visual: Option<bool>,
1365 #[serde(skip_serializing_if = "Option::is_none")]
1366 pub source_bidi_visual: Option<bool>,
1367 #[serde(skip_serializing_if = "Option::is_none")]
1368 pub source_inherited_bidi_visual: Option<bool>,
1369 #[serde(skip_serializing_if = "Option::is_none")]
1370 pub indent_twips: Option<i64>,
1371 #[serde(skip_serializing_if = "Option::is_none")]
1372 pub layout: Option<TableLayout>,
1373 #[serde(skip_serializing_if = "Option::is_none")]
1374 pub cell_spacing_twips: Option<i64>,
1375 #[serde(skip_serializing_if = "Option::is_none")]
1376 pub cell_margin_twips: Option<TableBoxSpacing>,
1377 #[serde(skip_serializing_if = "Option::is_none")]
1378 pub column_widths_twips: Option<Vec<i64>>,
1379 #[serde(skip_serializing_if = "Option::is_none")]
1382 pub collapsed_grid_columns: Option<Vec<usize>>,
1383 #[serde(skip_serializing_if = "Option::is_none")]
1384 pub borders: Option<TableBorderSet>,
1385 #[serde(skip_serializing_if = "Option::is_none")]
1386 pub floating: Option<TableFloating>,
1387}
1388
1389#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
1391#[serde(rename_all = "camelCase")]
1392pub struct TableSourceTextPatch {
1393 pub source_paragraph_xml: String,
1394 pub paragraph: ParagraphNode,
1395}
1396
1397#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
1399#[serde(rename_all = "camelCase")]
1400pub struct TableNode {
1401 #[serde(default, skip_serializing_if = "Option::is_none")]
1402 pub review_rows: Option<Vec<crate::revisions::ReviewRow>>,
1403 #[serde(default, skip_serializing_if = "Option::is_none")]
1404 pub block_id: Option<String>,
1405 #[serde(default = "default_table_node_type", rename = "type")]
1406 pub r#type: TableNodeType,
1407 pub rows: Vec<TableRowNode>,
1408 #[serde(skip_serializing_if = "Option::is_none")]
1409 pub style: Option<TableStyle>,
1410 #[serde(skip_serializing_if = "Option::is_none")]
1411 pub source_xml: Option<String>,
1412 #[serde(skip_serializing_if = "Option::is_none")]
1413 pub source_text_patches: Option<Vec<TableSourceTextPatch>>,
1414}
1415
1416#[derive(Clone, Copy, Debug, PartialEq, Eq, Serialize, Deserialize)]
1418pub enum TableNodeType {
1419 #[serde(rename = "table")]
1420 Table,
1421}
1422
1423#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
1425#[serde(untagged)]
1426pub enum DocNode {
1427 Paragraph(ParagraphNode),
1428 Table(TableNode),
1429}
1430
1431#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
1433#[serde(rename_all = "camelCase")]
1434pub struct HeaderSection {
1435 pub part_name: String,
1436 #[serde(skip_serializing_if = "Option::is_none")]
1437 pub reference_type: Option<String>,
1438 pub nodes: Vec<DocNode>,
1439}
1440
1441#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
1443#[serde(rename_all = "camelCase")]
1444pub struct FooterSection {
1445 pub part_name: String,
1446 #[serde(skip_serializing_if = "Option::is_none")]
1447 pub reference_type: Option<String>,
1448 pub nodes: Vec<DocNode>,
1449}
1450
1451#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
1453#[serde(rename_all = "camelCase")]
1454pub struct DocumentSection {
1455 pub start_node_index: i64,
1456 #[serde(skip_serializing_if = "Option::is_none")]
1457 pub section_properties_xml: Option<String>,
1458 pub header_sections: Vec<HeaderSection>,
1459 pub footer_sections: Vec<FooterSection>,
1460}
1461
1462#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
1464#[serde(rename_all = "camelCase")]
1465pub struct ParagraphStyleDefinition {
1466 pub id: String,
1467 pub name: String,
1468 #[serde(skip_serializing_if = "Option::is_none")]
1469 pub based_on_id: Option<String>,
1470 #[serde(skip_serializing_if = "Option::is_none")]
1471 pub next_style_id: Option<String>,
1472 #[serde(skip_serializing_if = "Option::is_none")]
1473 pub align: Option<ParagraphAlignment>,
1474 #[serde(skip_serializing_if = "Option::is_none")]
1475 pub snap_to_grid: Option<bool>,
1476 #[serde(skip_serializing_if = "Option::is_none")]
1477 pub source_has_snap_to_grid: Option<bool>,
1478 #[serde(skip_serializing_if = "Option::is_none")]
1479 pub text_alignment: Option<ParagraphTextAlignment>,
1480 #[serde(skip_serializing_if = "Option::is_none")]
1481 pub source_has_text_alignment: Option<bool>,
1482 #[serde(skip_serializing_if = "Option::is_none")]
1483 pub heading_level: Option<HeadingLevel>,
1484 #[serde(skip_serializing_if = "Option::is_none")]
1485 pub numbering: Option<ParagraphNumbering>,
1486 #[serde(skip_serializing_if = "Option::is_none")]
1487 pub spacing: Option<ParagraphSpacing>,
1488 #[serde(skip_serializing_if = "Option::is_none")]
1489 pub indent: Option<ParagraphIndent>,
1490 #[serde(skip_serializing_if = "Option::is_none")]
1491 pub background_color: Option<String>,
1492 #[serde(skip_serializing_if = "Option::is_none")]
1493 pub borders: Option<ParagraphBorderSet>,
1494 #[serde(skip_serializing_if = "Option::is_none")]
1495 pub tab_stops: Option<Vec<ParagraphTabStop>>,
1496 #[serde(skip_serializing_if = "Option::is_none")]
1497 pub contextual_spacing: Option<bool>,
1498 #[serde(skip_serializing_if = "Option::is_none")]
1499 pub keep_next: Option<bool>,
1500 #[serde(skip_serializing_if = "Option::is_none")]
1501 pub keep_lines: Option<bool>,
1502 #[serde(skip_serializing_if = "Option::is_none")]
1503 pub widow_control: Option<bool>,
1504 #[serde(skip_serializing_if = "Option::is_none")]
1505 pub page_break_before: Option<bool>,
1506 #[serde(skip_serializing_if = "Option::is_none")]
1507 pub run_style: Option<TextStyle>,
1508 #[serde(skip_serializing_if = "Option::is_none")]
1509 pub ui_priority: Option<i64>,
1510 #[serde(skip_serializing_if = "Option::is_none")]
1511 pub is_default: Option<bool>,
1512 #[serde(skip_serializing_if = "Option::is_none")]
1513 pub is_primary: Option<bool>,
1514}
1515
1516#[derive(Clone, Copy, Debug, PartialEq, Eq, Serialize, Deserialize)]
1518pub enum NumberingLevelSuffix {
1519 #[serde(rename = "tab")]
1520 Tab,
1521 #[serde(rename = "space")]
1522 Space,
1523 #[serde(rename = "nothing")]
1524 Nothing,
1525}
1526
1527#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
1529#[serde(rename_all = "camelCase")]
1530pub struct NumberingLevelDefinition {
1531 pub ilvl: i64,
1532 #[serde(skip_serializing_if = "Option::is_none")]
1533 pub start: Option<i64>,
1534 #[serde(skip_serializing_if = "Option::is_none")]
1535 pub format: Option<String>,
1536 #[serde(skip_serializing_if = "Option::is_none")]
1537 pub text: Option<String>,
1538 #[serde(skip_serializing_if = "Option::is_none")]
1539 pub suffix: Option<NumberingLevelSuffix>,
1540 #[serde(skip_serializing_if = "Option::is_none")]
1544 pub lvl_restart: Option<i64>,
1545 #[serde(skip_serializing_if = "Option::is_none")]
1548 pub is_lgl: Option<bool>,
1549 #[serde(skip_serializing_if = "Option::is_none")]
1550 pub indent: Option<ParagraphIndent>,
1551 #[serde(skip_serializing_if = "Option::is_none")]
1552 pub run_style: Option<TextStyle>,
1553 #[serde(skip_serializing_if = "Option::is_none")]
1554 pub bullet_font_family: Option<String>,
1555 #[serde(skip_serializing_if = "Option::is_none")]
1556 pub bullet_color: Option<String>,
1557 #[serde(skip_serializing_if = "Option::is_none")]
1558 pub picture_bullet_id: Option<i64>,
1559 #[serde(skip_serializing_if = "Option::is_none")]
1560 pub picture_bullet: Option<NumberingPictureBulletDefinition>,
1561}
1562
1563#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
1565#[serde(rename_all = "camelCase")]
1566pub struct NumberingAbstractDefinition {
1567 pub abstract_num_id: i64,
1568 pub levels: Vec<NumberingLevelDefinition>,
1569}
1570
1571#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
1573#[serde(rename_all = "camelCase")]
1574pub struct NumberingInstanceDefinition {
1575 pub num_id: i64,
1576 pub abstract_num_id: i64,
1577 #[serde(skip_serializing_if = "Option::is_none")]
1578 pub level_start_overrides: Option<HashMap<String, i64>>,
1579 #[serde(skip_serializing_if = "Option::is_none")]
1580 pub level_overrides: Option<Vec<NumberingLevelDefinition>>,
1581}
1582
1583#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
1585#[serde(rename_all = "camelCase")]
1586pub struct NumberingDefinitionSet {
1587 pub abstracts: Vec<NumberingAbstractDefinition>,
1588 pub instances: Vec<NumberingInstanceDefinition>,
1589}
1590
1591#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
1593#[serde(rename_all = "camelCase")]
1594pub struct NumberingPictureBulletDefinition {
1595 pub num_pic_bullet_id: i64,
1596 #[serde(skip_serializing_if = "Option::is_none")]
1597 pub src: Option<String>,
1598 #[serde(skip_serializing_if = "Option::is_none")]
1599 pub width_px: Option<f64>,
1600 #[serde(skip_serializing_if = "Option::is_none")]
1601 pub height_px: Option<f64>,
1602 #[serde(skip_serializing_if = "Option::is_none")]
1603 pub part_name: Option<String>,
1604 #[serde(skip_serializing_if = "Option::is_none")]
1605 pub content_type: Option<String>,
1606}
1607
1608#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
1610#[serde(rename_all = "camelCase")]
1611pub struct DocumentNoteDefinition {
1612 pub id: i64,
1613 pub text: String,
1614 #[serde(skip_serializing_if = "Option::is_none")]
1615 pub nodes: Option<Vec<DocNode>>,
1616}
1617
1618#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
1620#[serde(rename_all = "camelCase")]
1621pub struct DocumentCommentDefinition {
1622 #[serde(default, skip_serializing_if = "Option::is_none")]
1623 pub nodes: Option<Vec<DocNode>>,
1624 pub id: i64,
1625 #[serde(skip_serializing_if = "Option::is_none")]
1626 pub author: Option<String>,
1627 #[serde(skip_serializing_if = "Option::is_none")]
1628 pub initials: Option<String>,
1629 #[serde(skip_serializing_if = "Option::is_none")]
1630 pub date: Option<String>,
1631 pub text: String,
1632 #[serde(skip_serializing_if = "Option::is_none")]
1633 pub parent_id: Option<i64>,
1634 #[serde(skip_serializing_if = "Option::is_none")]
1635 pub resolved: Option<bool>,
1636 #[serde(skip_serializing_if = "Option::is_none")]
1637 pub source_xml: Option<String>,
1638 #[serde(skip_serializing_if = "Option::is_none")]
1639 pub extended_paragraph_id: Option<String>,
1640 #[serde(skip_serializing_if = "Option::is_none")]
1641 pub source_resolved: Option<bool>,
1642 #[serde(skip_serializing_if = "Option::is_none")]
1643 pub resolution_dirty: Option<bool>,
1644 #[serde(skip_serializing_if = "Option::is_none")]
1645 pub is_new: Option<bool>,
1646}
1647
1648#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
1650#[serde(rename_all = "camelCase")]
1651pub struct DocumentCompatibilitySettings {
1652 #[serde(skip_serializing_if = "Option::is_none")]
1653 pub adjust_line_height_in_table: Option<bool>,
1654 #[serde(skip_serializing_if = "Option::is_none")]
1655 pub no_leading: Option<bool>,
1656 #[serde(
1657 rename = "suppressTopSpacingWP",
1658 skip_serializing_if = "Option::is_none"
1659 )]
1660 pub suppress_top_spacing_wp: Option<bool>,
1661 #[serde(
1662 rename = "truncateFontHeightsLikeWP6",
1663 skip_serializing_if = "Option::is_none"
1664 )]
1665 pub truncate_font_heights_like_wp6: Option<bool>,
1666 #[serde(skip_serializing_if = "Option::is_none")]
1667 pub no_extra_line_spacing: Option<bool>,
1668 #[serde(rename = "spaceForUL", skip_serializing_if = "Option::is_none")]
1669 pub space_for_ul: Option<bool>,
1670 #[serde(skip_serializing_if = "Option::is_none")]
1671 pub suppress_bottom_spacing: Option<bool>,
1672 #[serde(skip_serializing_if = "Option::is_none")]
1673 pub compatibility_mode: Option<i64>,
1674 #[serde(
1675 rename = "enableOpenTypeFeatures",
1676 skip_serializing_if = "Option::is_none"
1677 )]
1678 pub enable_open_type_features: Option<bool>,
1679 #[serde(skip_serializing_if = "Option::is_none")]
1680 pub suppress_spacing_before_after_page_break: Option<bool>,
1681 #[serde(skip_serializing_if = "Option::is_none")]
1682 pub use_printer_metrics: Option<bool>,
1683 #[serde(skip_serializing_if = "Option::is_none")]
1684 pub use_fixed_html_paragraph_spacing: Option<bool>,
1685 #[serde(skip_serializing_if = "Option::is_none")]
1686 pub do_not_break_wrapped_tables: Option<bool>,
1687 #[serde(skip_serializing_if = "Option::is_none")]
1688 pub do_not_break_constrained_forced_table: Option<bool>,
1689 #[serde(skip_serializing_if = "Option::is_none")]
1690 pub even_and_odd_headers: Option<bool>,
1691}
1692
1693#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
1695#[serde(rename_all = "camelCase")]
1696pub struct DocModelMetadata {
1697 #[serde(default, skip_serializing_if = "Option::is_none")]
1698 pub document_id: Option<String>,
1699 #[serde(default, skip_serializing_if = "Option::is_none")]
1700 pub source_part_names: Option<std::collections::BTreeMap<String, String>>,
1701 pub source_parts: i64,
1702 pub warnings: Vec<String>,
1703 #[serde(skip_serializing_if = "Option::is_none")]
1704 pub document_page_count: Option<i64>,
1705 #[serde(skip_serializing_if = "Option::is_none")]
1706 pub document_open_tag: Option<String>,
1707 #[serde(skip_serializing_if = "Option::is_none")]
1708 pub document_background_color: Option<String>,
1709 #[serde(skip_serializing_if = "Option::is_none")]
1710 pub section_properties_xml: Option<String>,
1711 #[serde(skip_serializing_if = "Option::is_none")]
1712 pub sections: Option<Vec<DocumentSection>>,
1713 pub header_sections: Vec<HeaderSection>,
1714 pub footer_sections: Vec<FooterSection>,
1715 pub paragraph_styles: Vec<ParagraphStyleDefinition>,
1716 #[serde(skip_serializing_if = "Option::is_none")]
1717 pub default_paragraph_style_id: Option<String>,
1718 #[serde(skip_serializing_if = "Option::is_none")]
1719 pub default_tab_stop_twips: Option<i64>,
1720 #[serde(skip_serializing_if = "Option::is_none")]
1721 pub document_settings_imported: Option<bool>,
1722 #[serde(skip_serializing_if = "Option::is_none")]
1723 pub line_spacing_compatibility_imported: Option<bool>,
1724 #[serde(skip_serializing_if = "Option::is_none")]
1725 pub numbering_definitions: Option<NumberingDefinitionSet>,
1726 #[serde(skip_serializing_if = "Option::is_none")]
1727 pub compatibility: Option<DocumentCompatibilitySettings>,
1728 #[serde(skip_serializing_if = "Option::is_none")]
1729 pub footnotes: Option<Vec<DocumentNoteDefinition>>,
1730 #[serde(skip_serializing_if = "Option::is_none")]
1731 pub endnotes: Option<Vec<DocumentNoteDefinition>>,
1732 #[serde(skip_serializing_if = "Option::is_none")]
1733 pub comments: Option<Vec<DocumentCommentDefinition>>,
1734}
1735
1736#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
1738#[serde(rename_all = "camelCase")]
1739pub struct DocModel {
1740 pub nodes: Vec<DocNode>,
1741 pub metadata: DocModelMetadata,
1742}
1743
1744#[cfg(test)]
1745mod deserialize_tests {
1746 use super::{DocModel, DocNode, HeadingLevel, ParagraphAlignment};
1747
1748 #[test]
1749 fn deserializes_minimal_js_doc_model() {
1750 let json = r#"{"nodes":[{"type":"paragraph","children":[{"type":"text","text":"Hi"}]}],"metadata":{"sourceParts":1,"warnings":[],"headerSections":[],"footerSections":[],"paragraphStyles":[]}}"#;
1751 let model: DocModel = serde_json::from_str(json).expect("should deserialize");
1752 assert_eq!(model.nodes.len(), 1);
1753 }
1754
1755 #[test]
1756 fn deserializes_heading_level_two() {
1757 let json = r#"{"type":"paragraph","style":{"headingLevel":2},"children":[{"type":"text","text":"Added"}]}"#;
1758 let node: DocNode = serde_json::from_str(json).expect("heading level 2");
1759 let DocNode::Paragraph(paragraph) = node else {
1760 panic!("expected paragraph");
1761 };
1762 assert_eq!(
1763 paragraph.style.and_then(|style| style.heading_level),
1764 Some(HeadingLevel::Two)
1765 );
1766 }
1767
1768 #[test]
1769 fn deserializes_align_center() {
1770 let json = r#"{"type":"paragraph","style":{"align":"center"},"children":[{"type":"text","text":"Added"}]}"#;
1771 let node: DocNode = serde_json::from_str(json).expect("align center");
1772 let DocNode::Paragraph(paragraph) = node else {
1773 panic!("expected paragraph");
1774 };
1775 assert_eq!(
1776 paragraph.style.and_then(|style| style.align),
1777 Some(ParagraphAlignment::Center)
1778 );
1779 }
1780}
1781
1782#[derive(Clone, Default, Debug, PartialEq, Serialize, Deserialize)]
1784#[serde(transparent)]
1785pub struct SharedParagraphStyle(std::sync::Arc<ParagraphStyle>);
1786
1787impl SharedParagraphStyle {
1788 pub fn into_owned(self) -> ParagraphStyle {
1789 std::sync::Arc::unwrap_or_clone(self.0)
1790 }
1791}
1792
1793impl From<ParagraphStyle> for SharedParagraphStyle {
1794 fn from(style: ParagraphStyle) -> Self {
1795 Self(std::sync::Arc::new(style))
1796 }
1797}
1798
1799impl std::ops::Deref for SharedParagraphStyle {
1800 type Target = ParagraphStyle;
1801
1802 fn deref(&self) -> &ParagraphStyle {
1803 &self.0
1804 }
1805}
1806
1807impl std::ops::DerefMut for SharedParagraphStyle {
1808 fn deref_mut(&mut self) -> &mut ParagraphStyle {
1809 std::sync::Arc::make_mut(&mut self.0)
1810 }
1811}