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}
364
365#[derive(Clone, Copy, Debug, PartialEq, Eq, Serialize, Deserialize)]
367pub enum TextRunNodeType {
368 #[serde(rename = "text")]
369 Text,
370}
371
372#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
374#[serde(rename_all = "camelCase")]
375pub struct ImageCrop {
376 #[serde(skip_serializing_if = "Option::is_none")]
377 pub left_fraction: Option<f64>,
378 #[serde(skip_serializing_if = "Option::is_none")]
379 pub top_fraction: Option<f64>,
380 #[serde(skip_serializing_if = "Option::is_none")]
381 pub right_fraction: Option<f64>,
382 #[serde(skip_serializing_if = "Option::is_none")]
383 pub bottom_fraction: Option<f64>,
384}
385
386#[derive(Clone, Copy, Debug, PartialEq, Eq, Serialize, Deserialize)]
388#[serde(rename_all = "camelCase")]
389pub enum ImageHorizontalAlign {
390 Left,
391 Center,
392 Right,
393 Inside,
394 Outside,
395}
396
397#[derive(Clone, Copy, Debug, PartialEq, Eq, Serialize, Deserialize)]
399#[serde(rename_all = "camelCase")]
400pub enum ImageVerticalAlign {
401 Top,
402 Center,
403 Bottom,
404 Inside,
405 Outside,
406}
407
408#[derive(Clone, Copy, Debug, PartialEq, Eq, Serialize, Deserialize)]
410#[serde(rename_all = "camelCase")]
411pub enum ImageWrapType {
412 #[serde(rename = "none")]
413 WrapNone,
414 #[serde(rename = "square")]
415 Square,
416 #[serde(rename = "tight")]
417 Tight,
418 #[serde(rename = "through")]
419 Through,
420 #[serde(rename = "topAndBottom")]
421 TopAndBottom,
422}
423
424#[derive(Clone, Copy, Debug, PartialEq, Eq, Serialize, Deserialize)]
426#[serde(rename_all = "camelCase")]
427pub enum ImageWrapText {
428 #[serde(rename = "bothSides")]
429 BothSides,
430 #[serde(rename = "left")]
431 Left,
432 #[serde(rename = "right")]
433 Right,
434 #[serde(rename = "largest")]
435 Largest,
436}
437
438#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
440#[serde(rename_all = "camelCase")]
441pub struct ImageFloating {
442 #[serde(skip_serializing_if = "Option::is_none")]
443 pub x_px: Option<f64>,
444 #[serde(skip_serializing_if = "Option::is_none")]
445 pub y_px: Option<f64>,
446 #[serde(skip_serializing_if = "Option::is_none")]
447 pub horizontal_align: Option<ImageHorizontalAlign>,
448 #[serde(skip_serializing_if = "Option::is_none")]
449 pub vertical_align: Option<ImageVerticalAlign>,
450 #[serde(skip_serializing_if = "Option::is_none")]
451 pub horizontal_relative_to: Option<String>,
452 #[serde(skip_serializing_if = "Option::is_none")]
453 pub vertical_relative_to: Option<String>,
454 #[serde(skip_serializing_if = "Option::is_none")]
455 pub dist_l_px: Option<f64>,
456 #[serde(skip_serializing_if = "Option::is_none")]
457 pub dist_r_px: Option<f64>,
458 #[serde(skip_serializing_if = "Option::is_none")]
459 pub dist_t_px: Option<f64>,
460 #[serde(skip_serializing_if = "Option::is_none")]
461 pub dist_b_px: Option<f64>,
462 #[serde(skip_serializing_if = "Option::is_none")]
463 pub wrap_type: Option<ImageWrapType>,
464 #[serde(skip_serializing_if = "Option::is_none")]
465 pub wrap_text: Option<ImageWrapText>,
466 #[serde(skip_serializing_if = "Option::is_none")]
467 pub behind_document: Option<bool>,
468 #[serde(skip_serializing_if = "Option::is_none")]
469 pub z_index: Option<i64>,
470}
471
472#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
473#[serde(rename_all = "camelCase")]
474pub struct ImagePaintBounds {
475 pub x_px: f64,
476 pub y_px: f64,
477 pub width_px: f64,
478 pub height_px: f64,
479 pub layout_width_px: f64,
480 pub layout_height_px: f64,
481}
482
483#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
484#[serde(rename_all = "camelCase")]
485pub struct ImagePropertyAttribute {
486 pub name: String,
487 pub value: String,
488}
489
490#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
492#[serde(rename_all = "camelCase")]
493pub struct ImagePropertyNode {
494 pub name: String,
495 #[serde(default, skip_serializing_if = "Vec::is_empty")]
496 pub attributes: Vec<ImagePropertyAttribute>,
497 #[serde(default, skip_serializing_if = "Vec::is_empty")]
498 pub children: Vec<ImagePropertyNode>,
499 #[serde(default, skip_serializing_if = "Option::is_none")]
500 pub text: Option<String>,
501}
502
503#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
504#[serde(rename_all = "camelCase")]
505pub struct ImageAssetReference {
506 pub element: String,
507 pub kind: String,
508 #[serde(skip_serializing_if = "Option::is_none")]
509 pub relationship_id: Option<String>,
510 #[serde(skip_serializing_if = "Option::is_none")]
511 pub target: Option<String>,
512 pub embedded_asset_available: bool,
513}
514
515#[derive(Clone, Debug, Default, PartialEq, Serialize, Deserialize)]
516#[serde(rename_all = "camelCase")]
517pub struct ImageTransform {
518 #[serde(skip_serializing_if = "Option::is_none")]
519 pub rotation_degrees: Option<f64>,
520 #[serde(skip_serializing_if = "Option::is_none")]
521 pub flip_horizontal: Option<bool>,
522 #[serde(skip_serializing_if = "Option::is_none")]
523 pub flip_vertical: Option<bool>,
524 #[serde(skip_serializing_if = "Option::is_none")]
525 pub offset_x_emu: Option<f64>,
526 #[serde(skip_serializing_if = "Option::is_none")]
527 pub offset_y_emu: Option<f64>,
528 #[serde(skip_serializing_if = "Option::is_none")]
529 pub width_emu: Option<f64>,
530 #[serde(skip_serializing_if = "Option::is_none")]
531 pub height_emu: Option<f64>,
532}
533
534#[derive(Clone, Debug, Default, PartialEq, Serialize, Deserialize)]
535#[serde(rename_all = "camelCase")]
536pub struct ImageTile {
537 #[serde(skip_serializing_if = "Option::is_none")]
538 pub offset_x_emu: Option<f64>,
539 #[serde(skip_serializing_if = "Option::is_none")]
540 pub offset_y_emu: Option<f64>,
541 #[serde(skip_serializing_if = "Option::is_none")]
542 pub scale_x: Option<f64>,
543 #[serde(skip_serializing_if = "Option::is_none")]
544 pub scale_y: Option<f64>,
545 #[serde(skip_serializing_if = "Option::is_none")]
546 pub alignment: Option<String>,
547 #[serde(skip_serializing_if = "Option::is_none")]
548 pub flip: Option<String>,
549}
550
551#[derive(Clone, Debug, Default, PartialEq, Serialize, Deserialize)]
553#[serde(rename_all = "camelCase")]
554pub struct ImagePresentation {
555 #[serde(default, skip_serializing_if = "std::ops::Not::not")]
556 pub transform_applied: bool,
557 #[serde(default, skip_serializing_if = "Vec::is_empty")]
558 pub assets: Vec<ImageAssetReference>,
559 #[serde(skip_serializing_if = "Option::is_none")]
560 pub transform: Option<ImageTransform>,
561 #[serde(skip_serializing_if = "Option::is_none")]
562 pub source_rectangle: Option<ImageCrop>,
563 #[serde(skip_serializing_if = "Option::is_none")]
564 pub fill_rectangle: Option<ImageCrop>,
565 #[serde(skip_serializing_if = "Option::is_none")]
566 pub tile: Option<ImageTile>,
567 #[serde(default, skip_serializing_if = "Vec::is_empty")]
568 pub properties: Vec<ImagePropertyNode>,
569}
570
571#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
573#[serde(rename_all = "camelCase")]
574pub struct ImageRunNode {
575 #[serde(default, rename = "model3d", skip_serializing_if = "Option::is_none")]
576 pub model_3d: Option<Box<rust_office_art::model3d::Model3D>>,
577 #[serde(default, skip_serializing_if = "Option::is_none")]
578 pub presentation: Option<Box<ImagePresentation>>,
579 #[serde(default, skip_serializing_if = "Option::is_none")]
580 pub chart_part_name: Option<String>,
581 #[serde(default, skip_serializing_if = "Option::is_none")]
582 pub chart_data: Option<Box<crate::ChartData>>,
583 #[serde(default, skip_serializing_if = "Option::is_none")]
584 pub paint_bounds: Option<Box<ImagePaintBounds>>,
585 #[serde(default, skip_serializing_if = "Option::is_none")]
586 pub math_ml: Option<String>,
587 #[serde(default, skip_serializing_if = "Option::is_none")]
588 pub content_nodes: Option<Vec<DocNode>>,
589 #[serde(default, skip_serializing_if = "Option::is_none")]
590 pub semantic_kind: Option<String>,
591 #[serde(default, skip_serializing_if = "Option::is_none")]
592 pub block_id: Option<String>,
593 #[serde(default = "default_image_run_type", rename = "type")]
594 pub r#type: ImageRunNodeType,
595 #[serde(skip_serializing_if = "Option::is_none")]
596 pub src: Option<String>,
597 #[serde(skip_serializing_if = "Option::is_none")]
598 pub alt: Option<String>,
599 #[serde(skip_serializing_if = "Option::is_none")]
600 pub width_px: Option<f64>,
601 #[serde(skip_serializing_if = "Option::is_none")]
602 pub height_px: Option<f64>,
603 #[serde(skip_serializing_if = "Option::is_none")]
604 pub part_name: Option<String>,
605 #[serde(skip_serializing_if = "Option::is_none")]
606 pub content_type: Option<String>,
607 #[serde(default, skip_serializing_if = "Option::is_none")]
608 pub data: Option<Vec<u8>>,
609 #[serde(skip_serializing_if = "Option::is_none")]
610 pub source_xml: Option<String>,
611 #[serde(skip_serializing_if = "Option::is_none")]
612 pub crop: Option<ImageCrop>,
613 #[serde(skip_serializing_if = "Option::is_none")]
614 pub css_filter: Option<String>,
615 #[serde(skip_serializing_if = "Option::is_none")]
616 pub css_opacity: Option<f64>,
617 #[serde(skip_serializing_if = "Option::is_none")]
618 pub floating: Option<ImageFloating>,
619 #[serde(skip_serializing_if = "Option::is_none")]
620 pub synthetic_text_box: Option<bool>,
621 #[serde(skip_serializing_if = "Option::is_none")]
622 pub text_box_text: Option<String>,
623}
624
625#[derive(Clone, Copy, Debug, PartialEq, Eq, Serialize, Deserialize)]
627pub enum ImageRunNodeType {
628 #[serde(rename = "image")]
629 Image,
630}
631
632#[derive(Clone, Copy, Debug, PartialEq, Eq, Serialize, Deserialize)]
634#[serde(rename_all = "camelCase")]
635pub enum FormFieldType {
636 #[serde(rename = "checkbox")]
637 Checkbox,
638 #[serde(rename = "text")]
639 Text,
640 #[serde(rename = "date")]
641 Date,
642 #[serde(rename = "dropdown")]
643 Dropdown,
644}
645
646#[derive(Clone, Copy, Debug, PartialEq, Eq, Serialize, Deserialize)]
648pub enum FormFieldSourceKind {
649 #[serde(rename = "sdt")]
650 Sdt,
651 #[serde(rename = "legacy")]
652 Legacy,
653}
654
655#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
657#[serde(rename_all = "camelCase")]
658pub struct FormFieldOption {
659 pub display_text: String,
660 #[serde(skip_serializing_if = "Option::is_none")]
661 pub value: Option<String>,
662}
663
664#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
666#[serde(rename_all = "camelCase")]
667pub struct FormFieldTextWidgetSettings {
668 #[serde(skip_serializing_if = "Option::is_none")]
669 pub input_type: Option<String>,
670 #[serde(skip_serializing_if = "Option::is_none")]
671 pub default_text: Option<String>,
672 #[serde(skip_serializing_if = "Option::is_none")]
673 pub max_length: Option<i64>,
674 #[serde(skip_serializing_if = "Option::is_none")]
675 pub text_format: Option<String>,
676}
677
678#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
680#[serde(rename_all = "camelCase")]
681pub struct FormFieldCheckboxWidgetSettings {
682 #[serde(skip_serializing_if = "Option::is_none")]
683 pub default_checked: Option<bool>,
684 #[serde(skip_serializing_if = "Option::is_none")]
685 pub size_mode: Option<FormFieldCheckboxSizeMode>,
686 #[serde(skip_serializing_if = "Option::is_none")]
687 pub size_pt: Option<f64>,
688}
689
690#[derive(Clone, Copy, Debug, PartialEq, Eq, Serialize, Deserialize)]
692pub enum FormFieldCheckboxSizeMode {
693 #[serde(rename = "auto")]
694 Auto,
695 #[serde(rename = "exact")]
696 Exact,
697}
698
699#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
701#[serde(rename_all = "camelCase")]
702pub struct FormFieldDropdownWidgetSettings {
703 #[serde(skip_serializing_if = "Option::is_none")]
704 pub default_value: Option<String>,
705}
706
707#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
709#[serde(rename_all = "camelCase")]
710pub struct FormFieldWidgetSettings {
711 #[serde(skip_serializing_if = "Option::is_none")]
712 pub name: Option<String>,
713 #[serde(skip_serializing_if = "Option::is_none")]
714 pub enabled: Option<bool>,
715 #[serde(skip_serializing_if = "Option::is_none")]
716 pub calc_on_exit: Option<bool>,
717 #[serde(skip_serializing_if = "Option::is_none")]
718 pub text: Option<FormFieldTextWidgetSettings>,
719 #[serde(skip_serializing_if = "Option::is_none")]
720 pub checkbox: Option<FormFieldCheckboxWidgetSettings>,
721 #[serde(skip_serializing_if = "Option::is_none")]
722 pub dropdown: Option<FormFieldDropdownWidgetSettings>,
723}
724
725#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
726#[serde(rename_all = "camelCase")]
727pub struct FormFieldSourcePreview {
728 pub relationship_id: String,
729 pub shape_id: String,
730 pub checked: bool,
731 pub image: Box<ImageRunNode>,
732}
733
734#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
736#[serde(rename_all = "camelCase")]
737pub struct FormFieldRunNode {
738 #[serde(default = "default_form_field_run_type", rename = "type")]
739 pub r#type: FormFieldRunNodeType,
740 pub field_type: FormFieldType,
741 #[serde(skip_serializing_if = "Option::is_none")]
742 pub source_kind: Option<FormFieldSourceKind>,
743 #[serde(skip_serializing_if = "Option::is_none")]
744 pub id: Option<i64>,
745 #[serde(skip_serializing_if = "Option::is_none")]
746 pub tag: Option<String>,
747 #[serde(skip_serializing_if = "Option::is_none")]
748 pub title: Option<String>,
749 #[serde(skip_serializing_if = "Option::is_none")]
750 pub placeholder: Option<String>,
751 #[serde(skip_serializing_if = "Option::is_none")]
752 pub checked: Option<bool>,
753 #[serde(skip_serializing_if = "Option::is_none")]
754 pub value: Option<String>,
755 #[serde(skip_serializing_if = "Option::is_none")]
756 pub options: Option<Vec<FormFieldOption>>,
757 #[serde(skip_serializing_if = "Option::is_none")]
758 pub widget: Option<FormFieldWidgetSettings>,
759 #[serde(skip_serializing_if = "Option::is_none")]
760 pub checked_symbol: Option<String>,
761 #[serde(skip_serializing_if = "Option::is_none")]
762 pub unchecked_symbol: Option<String>,
763 #[serde(skip_serializing_if = "Option::is_none")]
764 pub style: Option<SharedTextStyle>,
765 #[serde(skip_serializing_if = "Option::is_none")]
766 pub link: Option<String>,
767 #[serde(skip_serializing_if = "Option::is_none")]
768 pub source_xml: Option<String>,
769 #[serde(default, skip_serializing_if = "Option::is_none")]
770 pub source_preview: Option<Box<FormFieldSourcePreview>>,
771}
772
773#[derive(Clone, Copy, Debug, PartialEq, Eq, Serialize, Deserialize)]
775pub enum FormFieldRunNodeType {
776 #[serde(rename = "form-field")]
777 FormField,
778}
779
780#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
782#[serde(untagged)]
783pub enum ParagraphChildNode {
784 Text(TextRunNode),
785 Image(Box<ImageRunNode>),
786 FormField(Box<FormFieldRunNode>),
787}
788
789#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
791#[serde(rename_all = "camelCase")]
792pub struct ParagraphNumbering {
793 pub num_id: i64,
794 pub ilvl: i64,
795}
796
797#[derive(Clone, Copy, Debug, PartialEq, Eq, Serialize, Deserialize)]
799pub enum ParagraphLineRule {
800 #[serde(rename = "auto")]
801 Auto,
802 #[serde(rename = "exact")]
803 Exact,
804 #[serde(rename = "atLeast")]
805 AtLeast,
806}
807
808#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
810#[serde(rename_all = "camelCase")]
811pub struct ParagraphSpacing {
812 #[serde(skip_serializing_if = "Option::is_none")]
813 pub before_twips: Option<i64>,
814 #[serde(skip_serializing_if = "Option::is_none")]
815 pub after_twips: Option<i64>,
816 #[serde(skip_serializing_if = "Option::is_none")]
817 pub before_auto_spacing: Option<bool>,
818 #[serde(skip_serializing_if = "Option::is_none")]
819 pub after_auto_spacing: Option<bool>,
820 #[serde(skip_serializing_if = "Option::is_none")]
821 pub line_twips: Option<i64>,
822 #[serde(skip_serializing_if = "Option::is_none")]
823 pub line_rule: Option<ParagraphLineRule>,
824}
825
826#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
828#[serde(rename_all = "camelCase")]
829pub struct ParagraphIndent {
830 #[serde(skip_serializing_if = "Option::is_none")]
831 pub left_twips: Option<i64>,
832 #[serde(skip_serializing_if = "Option::is_none")]
833 pub right_twips: Option<i64>,
834 #[serde(skip_serializing_if = "Option::is_none")]
835 pub first_line_twips: Option<i64>,
836 #[serde(skip_serializing_if = "Option::is_none")]
837 pub hanging_twips: Option<i64>,
838}
839
840#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
842#[serde(rename_all = "camelCase")]
843pub struct ParagraphBorderStyle {
844 #[serde(rename = "type")]
845 pub border_type: String,
846 #[serde(skip_serializing_if = "Option::is_none")]
847 pub color: Option<String>,
848 #[serde(skip_serializing_if = "Option::is_none")]
849 pub size_eighth_pt: Option<f64>,
850 #[serde(skip_serializing_if = "Option::is_none")]
851 pub space_pt: Option<f64>,
852 #[serde(skip_serializing_if = "Option::is_none")]
853 pub frame: Option<bool>,
854 #[serde(skip_serializing_if = "Option::is_none")]
855 pub shadow: Option<bool>,
856}
857
858#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
860#[serde(rename_all = "camelCase")]
861pub struct ParagraphBorderSet {
862 #[serde(skip_serializing_if = "Option::is_none")]
863 pub top: Option<ParagraphBorderStyle>,
864 #[serde(skip_serializing_if = "Option::is_none")]
865 pub right: Option<ParagraphBorderStyle>,
866 #[serde(skip_serializing_if = "Option::is_none")]
867 pub bottom: Option<ParagraphBorderStyle>,
868 #[serde(skip_serializing_if = "Option::is_none")]
869 pub left: Option<ParagraphBorderStyle>,
870 #[serde(skip_serializing_if = "Option::is_none")]
871 pub between: Option<ParagraphBorderStyle>,
872 #[serde(skip_serializing_if = "Option::is_none")]
873 pub bar: Option<ParagraphBorderStyle>,
874}
875
876#[derive(Clone, Copy, Debug, PartialEq, Eq, Serialize, Deserialize)]
878#[serde(rename_all = "camelCase")]
879pub enum ParagraphTabStopAlignment {
880 Clear,
881 Left,
882 Center,
883 Right,
884 Decimal,
885 Bar,
886}
887
888#[derive(Clone, Copy, Debug, PartialEq, Eq, Serialize, Deserialize)]
890pub enum ParagraphTabStopLeader {
891 #[serde(rename = "none")]
892 LeaderNone,
893 #[serde(rename = "dot")]
894 Dot,
895 #[serde(rename = "hyphen")]
896 Hyphen,
897 #[serde(rename = "underscore")]
898 Underscore,
899 #[serde(rename = "middleDot")]
900 MiddleDot,
901}
902
903#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
905#[serde(rename_all = "camelCase")]
906pub struct ParagraphTabStop {
907 #[serde(skip_serializing_if = "Option::is_none")]
908 pub alignment: Option<ParagraphTabStopAlignment>,
909 #[serde(skip_serializing_if = "Option::is_none")]
910 pub leader: Option<ParagraphTabStopLeader>,
911 #[serde(skip_serializing_if = "Option::is_none")]
912 pub position_twips: Option<i64>,
913}
914
915#[derive(Clone, Copy, Debug, PartialEq, Eq, Serialize, Deserialize)]
917pub enum ParagraphDropCapType {
918 #[serde(rename = "drop")]
919 Drop,
920 #[serde(rename = "margin")]
921 Margin,
922}
923
924#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
926#[serde(rename_all = "camelCase")]
927pub struct ParagraphDropCap {
928 #[serde(rename = "type")]
929 pub drop_cap_type: ParagraphDropCapType,
930 #[serde(skip_serializing_if = "Option::is_none")]
931 pub lines: Option<i64>,
932 #[serde(skip_serializing_if = "Option::is_none")]
933 pub wrap: Option<String>,
934 #[serde(skip_serializing_if = "Option::is_none")]
935 pub horizontal_anchor: Option<String>,
936 #[serde(skip_serializing_if = "Option::is_none")]
937 pub vertical_anchor: Option<String>,
938 #[serde(skip_serializing_if = "Option::is_none")]
939 pub x_twips: Option<i64>,
940 #[serde(skip_serializing_if = "Option::is_none")]
941 pub y_twips: Option<i64>,
942 #[serde(skip_serializing_if = "Option::is_none")]
943 pub horizontal_space_twips: Option<i64>,
944 #[serde(skip_serializing_if = "Option::is_none")]
945 pub vertical_space_twips: Option<i64>,
946}
947
948#[derive(Clone, Copy, Debug, PartialEq, Eq, Serialize, Deserialize)]
949#[serde(rename_all = "camelCase")]
950pub enum ParagraphTextAlignment {
951 Auto,
952 Top,
953 Center,
954 Baseline,
955 Bottom,
956}
957
958#[derive(Clone, Debug, Default, PartialEq, Serialize, Deserialize)]
960#[serde(rename_all = "camelCase")]
961pub struct ParagraphStyle {
962 #[serde(skip_serializing_if = "Option::is_none")]
963 pub source_before_auto_spacing: Option<bool>,
964 #[serde(skip_serializing_if = "Option::is_none")]
965 pub source_after_auto_spacing: Option<bool>,
966 #[serde(skip_serializing_if = "Option::is_none")]
967 pub align: Option<ParagraphAlignment>,
968 #[serde(skip_serializing_if = "Option::is_none")]
969 pub snap_to_grid: Option<bool>,
970 #[serde(skip_serializing_if = "Option::is_none")]
971 pub source_snap_to_grid: Option<bool>,
972 #[serde(skip_serializing_if = "Option::is_none")]
973 pub source_has_snap_to_grid: Option<bool>,
974 #[serde(skip_serializing_if = "Option::is_none")]
975 pub source_inherited_snap_to_grid: Option<bool>,
976 #[serde(skip_serializing_if = "Option::is_none")]
977 pub source_table_snap_to_grid: Option<bool>,
978 #[serde(skip_serializing_if = "Option::is_none")]
979 pub text_alignment: Option<ParagraphTextAlignment>,
980 #[serde(skip_serializing_if = "Option::is_none")]
981 pub source_text_alignment: Option<ParagraphTextAlignment>,
982 #[serde(skip_serializing_if = "Option::is_none")]
983 pub source_has_text_alignment: Option<bool>,
984 #[serde(skip_serializing_if = "Option::is_none")]
985 pub source_inherited_text_alignment: Option<ParagraphTextAlignment>,
986 #[serde(skip_serializing_if = "Option::is_none")]
987 pub source_table_text_alignment: Option<ParagraphTextAlignment>,
988 #[serde(skip_serializing_if = "Option::is_none")]
989 pub heading_level: Option<HeadingLevel>,
990 #[serde(skip_serializing_if = "Option::is_none")]
991 pub style_id: Option<String>,
992 #[serde(skip_serializing_if = "Option::is_none")]
993 pub style_name: Option<String>,
994 #[serde(skip_serializing_if = "Option::is_none")]
995 pub numbering: Option<ParagraphNumbering>,
996 #[serde(skip_serializing_if = "Option::is_none")]
997 pub spacing: Option<ParagraphSpacing>,
998 #[serde(skip_serializing_if = "Option::is_none")]
999 pub indent: Option<ParagraphIndent>,
1000 #[serde(skip_serializing_if = "Option::is_none")]
1001 pub background_color: Option<String>,
1002 #[serde(skip_serializing_if = "Option::is_none")]
1003 pub borders: Option<ParagraphBorderSet>,
1004 #[serde(skip_serializing_if = "Option::is_none")]
1005 pub tab_stops: Option<Vec<ParagraphTabStop>>,
1006 #[serde(skip_serializing_if = "Option::is_none")]
1007 pub contextual_spacing: Option<bool>,
1008 #[serde(skip_serializing_if = "Option::is_none")]
1009 pub keep_next: Option<bool>,
1010 #[serde(skip_serializing_if = "Option::is_none")]
1011 pub keep_lines: Option<bool>,
1012 #[serde(skip_serializing_if = "Option::is_none")]
1013 pub widow_control: Option<bool>,
1014 #[serde(skip_serializing_if = "Option::is_none")]
1015 pub page_break_before: Option<bool>,
1016 #[serde(skip_serializing_if = "Option::is_none")]
1017 pub drop_cap: Option<ParagraphDropCap>,
1018}
1019
1020#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
1022#[serde(rename_all = "camelCase")]
1023pub struct ParagraphSourceTextPatchRun {
1024 #[serde(skip_serializing_if = "Option::is_none")]
1025 pub style: Option<SharedTextStyle>,
1026 #[serde(skip_serializing_if = "Option::is_none")]
1027 pub link: Option<String>,
1028 #[serde(skip_serializing_if = "Option::is_none")]
1029 pub note_reference: Option<NoteReference>,
1030}
1031
1032#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
1033#[serde(rename_all = "camelCase")]
1034pub struct ParagraphSourceTextPatch {
1035 pub runs: Vec<ParagraphSourceTextPatchRun>,
1036}
1037
1038#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
1040#[serde(rename_all = "camelCase")]
1041pub struct ParagraphMarkFormattingSource {
1042 #[serde(skip_serializing_if = "Option::is_none")]
1043 pub default_style: Option<SharedTextStyle>,
1044 #[serde(skip_serializing_if = "Option::is_none")]
1045 pub character_style: Option<SharedTextStyle>,
1046 #[serde(skip_serializing_if = "Option::is_none")]
1047 pub direct_style: Option<SharedTextStyle>,
1048}
1049
1050#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
1052#[serde(rename_all = "camelCase")]
1053pub struct ParagraphNode {
1054 #[serde(default, skip_serializing_if = "Option::is_none")]
1055 pub review_content: Option<Vec<crate::revisions::ReviewContent>>,
1056 #[serde(default, skip_serializing_if = "Option::is_none")]
1057 pub block_id: Option<String>,
1058 #[serde(default = "default_paragraph_node_type", rename = "type")]
1059 pub r#type: ParagraphNodeType,
1060 pub children: Vec<ParagraphChildNode>,
1061 #[serde(skip_serializing_if = "Option::is_none")]
1062 pub style: Option<SharedParagraphStyle>,
1063 #[serde(skip_serializing_if = "Option::is_none")]
1064 pub paragraph_mark_style: Option<SharedTextStyle>,
1065 #[serde(skip_serializing_if = "Option::is_none")]
1066 pub source_paragraph_mark_style: Option<SharedTextStyle>,
1067 #[serde(skip_serializing_if = "Option::is_none")]
1068 pub source_paragraph_mark_formatting: Option<ParagraphMarkFormattingSource>,
1069 #[serde(skip_serializing_if = "Option::is_none")]
1070 pub source_paragraph_mark_properties_xml: Option<String>,
1071 #[serde(skip_serializing_if = "Option::is_none")]
1072 pub paragraph_mark_deleted: Option<bool>,
1073 #[serde(skip_serializing_if = "Option::is_none")]
1074 pub source_xml: Option<String>,
1075 #[serde(skip_serializing_if = "Option::is_none")]
1076 pub source_text_patch: Option<ParagraphSourceTextPatch>,
1077 #[serde(skip_serializing_if = "Option::is_none")]
1080 pub source_run_provenance: Option<ParagraphSourceTextPatch>,
1081}
1082
1083#[derive(Clone, Copy, Debug, PartialEq, Eq, Serialize, Deserialize)]
1085pub enum ParagraphNodeType {
1086 #[serde(rename = "paragraph")]
1087 Paragraph,
1088}
1089
1090#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
1092#[serde(rename_all = "camelCase")]
1093pub struct TableBoxSpacing {
1094 #[serde(skip_serializing_if = "Option::is_none")]
1095 pub top_twips: Option<i64>,
1096 #[serde(skip_serializing_if = "Option::is_none")]
1097 pub right_twips: Option<i64>,
1098 #[serde(skip_serializing_if = "Option::is_none")]
1099 pub bottom_twips: Option<i64>,
1100 #[serde(skip_serializing_if = "Option::is_none")]
1101 pub left_twips: Option<i64>,
1102}
1103
1104#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
1106#[serde(rename_all = "camelCase")]
1107pub struct TableBorderStyle {
1108 #[serde(rename = "type")]
1109 pub border_type: String,
1110 #[serde(skip_serializing_if = "Option::is_none")]
1111 pub color: Option<String>,
1112 #[serde(skip_serializing_if = "Option::is_none")]
1113 pub size_eighth_pt: Option<f64>,
1114}
1115
1116#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
1118#[serde(rename_all = "camelCase")]
1119pub struct TableBorderSet {
1120 #[serde(skip_serializing_if = "Option::is_none")]
1121 pub top: Option<TableBorderStyle>,
1122 #[serde(skip_serializing_if = "Option::is_none")]
1123 pub right: Option<TableBorderStyle>,
1124 #[serde(skip_serializing_if = "Option::is_none")]
1125 pub bottom: Option<TableBorderStyle>,
1126 #[serde(skip_serializing_if = "Option::is_none")]
1127 pub left: Option<TableBorderStyle>,
1128 #[serde(skip_serializing_if = "Option::is_none")]
1129 pub inside_h: Option<TableBorderStyle>,
1130 #[serde(skip_serializing_if = "Option::is_none")]
1131 pub inside_v: Option<TableBorderStyle>,
1132 #[serde(skip_serializing_if = "Option::is_none")]
1133 pub tl2br: Option<TableBorderStyle>,
1134 #[serde(skip_serializing_if = "Option::is_none")]
1135 pub tr2bl: Option<TableBorderStyle>,
1136}
1137
1138#[derive(Clone, Copy, Debug, PartialEq, Eq, Serialize, Deserialize)]
1140#[serde(rename_all = "camelCase")]
1141pub enum TableCellVerticalAlign {
1142 Top,
1143 Center,
1144 Bottom,
1145}
1146
1147#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
1149#[serde(tag = "type", rename_all = "camelCase")]
1150pub enum TablePreferredWidth {
1151 Dxa { value: f64 },
1152 Pct { value: f64 },
1153 Auto,
1154 Nil,
1155}
1156
1157#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
1159#[serde(rename_all = "camelCase")]
1160pub struct TableWidthSource {
1161 #[serde(skip_serializing_if = "Option::is_none")]
1162 pub preferred_width: Option<TablePreferredWidth>,
1163 #[serde(skip_serializing_if = "Option::is_none")]
1164 pub width_twips: Option<i64>,
1165 #[serde(skip_serializing_if = "Option::is_none")]
1166 pub inherited_preferred_width: Option<TablePreferredWidth>,
1167}
1168
1169#[derive(Clone, Copy, Debug, PartialEq, Eq, Serialize, Deserialize)]
1170#[serde(rename_all = "camelCase")]
1171pub enum TableAlignment {
1172 Left,
1173 Center,
1174 Right,
1175}
1176
1177#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
1179#[serde(rename_all = "camelCase")]
1180pub struct TableCellStyle {
1181 #[serde(skip_serializing_if = "Option::is_none")]
1182 pub background_color: Option<String>,
1183 #[serde(skip_serializing_if = "Option::is_none")]
1184 pub grid_span: Option<i64>,
1185 #[serde(skip_serializing_if = "Option::is_none")]
1186 pub row_span: Option<i64>,
1187 #[serde(skip_serializing_if = "Option::is_none")]
1188 pub v_merge_continuation: Option<bool>,
1189 #[serde(skip_serializing_if = "Option::is_none")]
1190 pub width_twips: Option<i64>,
1191 #[serde(skip_serializing_if = "Option::is_none")]
1192 pub preferred_width: Option<TablePreferredWidth>,
1193 #[serde(skip_serializing_if = "Option::is_none")]
1194 pub source_width: Option<TableWidthSource>,
1195 #[serde(skip_serializing_if = "Option::is_none")]
1196 pub margin_twips: Option<TableBoxSpacing>,
1197 #[serde(skip_serializing_if = "Option::is_none")]
1198 pub vertical_align: Option<TableCellVerticalAlign>,
1199 #[serde(skip_serializing_if = "Option::is_none")]
1200 pub text_direction: Option<String>,
1201 #[serde(skip_serializing_if = "Option::is_none")]
1202 pub source_text_direction: Option<String>,
1203 #[serde(skip_serializing_if = "Option::is_none")]
1204 pub no_wrap: Option<bool>,
1205 #[serde(skip_serializing_if = "Option::is_none")]
1206 pub source_no_wrap: Option<bool>,
1207 #[serde(skip_serializing_if = "Option::is_none")]
1208 pub borders: Option<TableBorderSet>,
1209}
1210
1211#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
1213#[serde(untagged)]
1214pub enum TableCellContentNode {
1215 Paragraph(ParagraphNode),
1216 Table(Box<TableNode>),
1217}
1218
1219#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
1221#[serde(rename_all = "camelCase")]
1222pub struct TableCellNode {
1223 #[serde(default = "default_table_cell_node_type", rename = "type")]
1224 pub r#type: TableCellNodeType,
1225 pub nodes: Vec<TableCellContentNode>,
1226 #[serde(skip_serializing_if = "Option::is_none")]
1227 pub style: Option<TableCellStyle>,
1228}
1229
1230#[derive(Clone, Copy, Debug, PartialEq, Eq, Serialize, Deserialize)]
1232pub enum TableCellNodeType {
1233 #[serde(rename = "table-cell")]
1234 TableCell,
1235}
1236
1237#[derive(Clone, Copy, Debug, PartialEq, Eq, Serialize, Deserialize)]
1239pub enum TableRowHeightRule {
1240 #[serde(rename = "auto")]
1241 Auto,
1242 #[serde(rename = "atLeast")]
1243 AtLeast,
1244 #[serde(rename = "exact")]
1245 Exact,
1246}
1247
1248#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
1250#[serde(rename_all = "camelCase")]
1251pub struct TableRowGeometrySource {
1252 #[serde(skip_serializing_if = "Option::is_none")]
1253 pub grid_before: Option<i64>,
1254 #[serde(skip_serializing_if = "Option::is_none")]
1255 pub grid_after: Option<i64>,
1256 #[serde(skip_serializing_if = "Option::is_none")]
1257 pub width_before: Option<TablePreferredWidth>,
1258 #[serde(skip_serializing_if = "Option::is_none")]
1259 pub width_after: Option<TablePreferredWidth>,
1260}
1261
1262#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
1264#[serde(rename_all = "camelCase")]
1265pub struct TableRowStyle {
1266 #[serde(skip_serializing_if = "Option::is_none")]
1267 pub grid_before: Option<i64>,
1268 #[serde(skip_serializing_if = "Option::is_none")]
1269 pub grid_after: Option<i64>,
1270 #[serde(skip_serializing_if = "Option::is_none")]
1271 pub width_before: Option<TablePreferredWidth>,
1272 #[serde(skip_serializing_if = "Option::is_none")]
1273 pub width_after: Option<TablePreferredWidth>,
1274 #[serde(skip_serializing_if = "Option::is_none")]
1275 pub source_row_geometry: Option<TableRowGeometrySource>,
1276 #[serde(skip_serializing_if = "Option::is_none")]
1277 pub background_color: Option<String>,
1278 #[serde(skip_serializing_if = "Option::is_none")]
1279 pub height_twips: Option<i64>,
1280 #[serde(skip_serializing_if = "Option::is_none")]
1281 pub height_rule: Option<TableRowHeightRule>,
1282 #[serde(skip_serializing_if = "Option::is_none")]
1283 pub cant_split: Option<bool>,
1284 #[serde(skip_serializing_if = "Option::is_none")]
1285 pub is_header: Option<bool>,
1286}
1287
1288#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
1290#[serde(rename_all = "camelCase")]
1291pub struct TableRowNode {
1292 #[serde(default = "default_table_row_node_type", rename = "type")]
1293 pub r#type: TableRowNodeType,
1294 pub cells: Vec<TableCellNode>,
1295 #[serde(skip_serializing_if = "Option::is_none")]
1296 pub style: Option<TableRowStyle>,
1297}
1298
1299#[derive(Clone, Copy, Debug, PartialEq, Eq, Serialize, Deserialize)]
1301pub enum TableRowNodeType {
1302 #[serde(rename = "table-row")]
1303 TableRow,
1304}
1305
1306#[derive(Clone, Copy, Debug, PartialEq, Eq, Serialize, Deserialize)]
1308pub enum TableLayout {
1309 #[serde(rename = "fixed")]
1310 Fixed,
1311 #[serde(rename = "autofit")]
1312 Autofit,
1313}
1314
1315#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
1317#[serde(rename_all = "camelCase")]
1318pub struct TableFloating {
1319 #[serde(skip_serializing_if = "Option::is_none")]
1320 pub x_twips: Option<i64>,
1321 #[serde(skip_serializing_if = "Option::is_none")]
1322 pub y_twips: Option<i64>,
1323 #[serde(skip_serializing_if = "Option::is_none")]
1324 pub left_from_text_twips: Option<i64>,
1325 #[serde(skip_serializing_if = "Option::is_none")]
1326 pub right_from_text_twips: Option<i64>,
1327 #[serde(skip_serializing_if = "Option::is_none")]
1328 pub top_from_text_twips: Option<i64>,
1329 #[serde(skip_serializing_if = "Option::is_none")]
1330 pub bottom_from_text_twips: Option<i64>,
1331 #[serde(skip_serializing_if = "Option::is_none")]
1332 pub horizontal_anchor: Option<String>,
1333 #[serde(skip_serializing_if = "Option::is_none")]
1334 pub vertical_anchor: Option<String>,
1335 #[serde(skip_serializing_if = "Option::is_none")]
1336 pub horizontal_align: Option<ImageHorizontalAlign>,
1337 #[serde(skip_serializing_if = "Option::is_none")]
1338 pub vertical_align: Option<ImageVerticalAlign>,
1339}
1340
1341#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
1343#[serde(rename_all = "camelCase")]
1344pub struct TableStyle {
1345 #[serde(skip_serializing_if = "Option::is_none")]
1346 pub style_id: Option<String>,
1347 #[serde(skip_serializing_if = "Option::is_none")]
1348 pub source_style_id: Option<String>,
1349 #[serde(skip_serializing_if = "Option::is_none")]
1350 pub width_twips: Option<i64>,
1351 #[serde(skip_serializing_if = "Option::is_none")]
1352 pub preferred_width: Option<TablePreferredWidth>,
1353 #[serde(skip_serializing_if = "Option::is_none")]
1354 pub source_width: Option<TableWidthSource>,
1355 #[serde(skip_serializing_if = "Option::is_none")]
1356 pub alignment: Option<TableAlignment>,
1357 #[serde(skip_serializing_if = "Option::is_none")]
1358 pub source_alignment: Option<TableAlignment>,
1359 #[serde(skip_serializing_if = "Option::is_none")]
1360 pub source_inherited_alignment: Option<TableAlignment>,
1361 #[serde(skip_serializing_if = "Option::is_none")]
1362 pub bidi_visual: Option<bool>,
1363 #[serde(skip_serializing_if = "Option::is_none")]
1364 pub source_bidi_visual: Option<bool>,
1365 #[serde(skip_serializing_if = "Option::is_none")]
1366 pub source_inherited_bidi_visual: Option<bool>,
1367 #[serde(skip_serializing_if = "Option::is_none")]
1368 pub indent_twips: Option<i64>,
1369 #[serde(skip_serializing_if = "Option::is_none")]
1370 pub layout: Option<TableLayout>,
1371 #[serde(skip_serializing_if = "Option::is_none")]
1372 pub cell_spacing_twips: Option<i64>,
1373 #[serde(skip_serializing_if = "Option::is_none")]
1374 pub cell_margin_twips: Option<TableBoxSpacing>,
1375 #[serde(skip_serializing_if = "Option::is_none")]
1376 pub column_widths_twips: Option<Vec<i64>>,
1377 #[serde(skip_serializing_if = "Option::is_none")]
1380 pub collapsed_grid_columns: Option<Vec<usize>>,
1381 #[serde(skip_serializing_if = "Option::is_none")]
1382 pub borders: Option<TableBorderSet>,
1383 #[serde(skip_serializing_if = "Option::is_none")]
1384 pub floating: Option<TableFloating>,
1385}
1386
1387#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
1389#[serde(rename_all = "camelCase")]
1390pub struct TableSourceTextPatch {
1391 pub source_paragraph_xml: String,
1392 pub paragraph: ParagraphNode,
1393}
1394
1395#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
1397#[serde(rename_all = "camelCase")]
1398pub struct TableNode {
1399 #[serde(default, skip_serializing_if = "Option::is_none")]
1400 pub review_rows: Option<Vec<crate::revisions::ReviewRow>>,
1401 #[serde(default, skip_serializing_if = "Option::is_none")]
1402 pub block_id: Option<String>,
1403 #[serde(default = "default_table_node_type", rename = "type")]
1404 pub r#type: TableNodeType,
1405 pub rows: Vec<TableRowNode>,
1406 #[serde(skip_serializing_if = "Option::is_none")]
1407 pub style: Option<TableStyle>,
1408 #[serde(skip_serializing_if = "Option::is_none")]
1409 pub source_xml: Option<String>,
1410 #[serde(skip_serializing_if = "Option::is_none")]
1411 pub source_text_patches: Option<Vec<TableSourceTextPatch>>,
1412}
1413
1414#[derive(Clone, Copy, Debug, PartialEq, Eq, Serialize, Deserialize)]
1416pub enum TableNodeType {
1417 #[serde(rename = "table")]
1418 Table,
1419}
1420
1421#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
1423#[serde(untagged)]
1424pub enum DocNode {
1425 Paragraph(ParagraphNode),
1426 Table(TableNode),
1427}
1428
1429#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
1431#[serde(rename_all = "camelCase")]
1432pub struct HeaderSection {
1433 pub part_name: String,
1434 #[serde(skip_serializing_if = "Option::is_none")]
1435 pub reference_type: Option<String>,
1436 pub nodes: Vec<DocNode>,
1437}
1438
1439#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
1441#[serde(rename_all = "camelCase")]
1442pub struct FooterSection {
1443 pub part_name: String,
1444 #[serde(skip_serializing_if = "Option::is_none")]
1445 pub reference_type: Option<String>,
1446 pub nodes: Vec<DocNode>,
1447}
1448
1449#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
1451#[serde(rename_all = "camelCase")]
1452pub struct DocumentSection {
1453 pub start_node_index: i64,
1454 #[serde(skip_serializing_if = "Option::is_none")]
1455 pub section_properties_xml: Option<String>,
1456 pub header_sections: Vec<HeaderSection>,
1457 pub footer_sections: Vec<FooterSection>,
1458}
1459
1460#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
1462#[serde(rename_all = "camelCase")]
1463pub struct ParagraphStyleDefinition {
1464 pub id: String,
1465 pub name: String,
1466 #[serde(skip_serializing_if = "Option::is_none")]
1467 pub based_on_id: Option<String>,
1468 #[serde(skip_serializing_if = "Option::is_none")]
1469 pub next_style_id: Option<String>,
1470 #[serde(skip_serializing_if = "Option::is_none")]
1471 pub align: Option<ParagraphAlignment>,
1472 #[serde(skip_serializing_if = "Option::is_none")]
1473 pub snap_to_grid: Option<bool>,
1474 #[serde(skip_serializing_if = "Option::is_none")]
1475 pub source_has_snap_to_grid: Option<bool>,
1476 #[serde(skip_serializing_if = "Option::is_none")]
1477 pub text_alignment: Option<ParagraphTextAlignment>,
1478 #[serde(skip_serializing_if = "Option::is_none")]
1479 pub source_has_text_alignment: Option<bool>,
1480 #[serde(skip_serializing_if = "Option::is_none")]
1481 pub heading_level: Option<HeadingLevel>,
1482 #[serde(skip_serializing_if = "Option::is_none")]
1483 pub numbering: Option<ParagraphNumbering>,
1484 #[serde(skip_serializing_if = "Option::is_none")]
1485 pub spacing: Option<ParagraphSpacing>,
1486 #[serde(skip_serializing_if = "Option::is_none")]
1487 pub indent: Option<ParagraphIndent>,
1488 #[serde(skip_serializing_if = "Option::is_none")]
1489 pub background_color: Option<String>,
1490 #[serde(skip_serializing_if = "Option::is_none")]
1491 pub borders: Option<ParagraphBorderSet>,
1492 #[serde(skip_serializing_if = "Option::is_none")]
1493 pub tab_stops: Option<Vec<ParagraphTabStop>>,
1494 #[serde(skip_serializing_if = "Option::is_none")]
1495 pub contextual_spacing: Option<bool>,
1496 #[serde(skip_serializing_if = "Option::is_none")]
1497 pub keep_next: Option<bool>,
1498 #[serde(skip_serializing_if = "Option::is_none")]
1499 pub keep_lines: Option<bool>,
1500 #[serde(skip_serializing_if = "Option::is_none")]
1501 pub widow_control: Option<bool>,
1502 #[serde(skip_serializing_if = "Option::is_none")]
1503 pub page_break_before: Option<bool>,
1504 #[serde(skip_serializing_if = "Option::is_none")]
1505 pub run_style: Option<TextStyle>,
1506 #[serde(skip_serializing_if = "Option::is_none")]
1507 pub ui_priority: Option<i64>,
1508 #[serde(skip_serializing_if = "Option::is_none")]
1509 pub is_default: Option<bool>,
1510 #[serde(skip_serializing_if = "Option::is_none")]
1511 pub is_primary: Option<bool>,
1512}
1513
1514#[derive(Clone, Copy, Debug, PartialEq, Eq, Serialize, Deserialize)]
1516pub enum NumberingLevelSuffix {
1517 #[serde(rename = "tab")]
1518 Tab,
1519 #[serde(rename = "space")]
1520 Space,
1521 #[serde(rename = "nothing")]
1522 Nothing,
1523}
1524
1525#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
1527#[serde(rename_all = "camelCase")]
1528pub struct NumberingLevelDefinition {
1529 pub ilvl: i64,
1530 #[serde(skip_serializing_if = "Option::is_none")]
1531 pub start: Option<i64>,
1532 #[serde(skip_serializing_if = "Option::is_none")]
1533 pub format: Option<String>,
1534 #[serde(skip_serializing_if = "Option::is_none")]
1535 pub text: Option<String>,
1536 #[serde(skip_serializing_if = "Option::is_none")]
1537 pub suffix: Option<NumberingLevelSuffix>,
1538 #[serde(skip_serializing_if = "Option::is_none")]
1542 pub lvl_restart: Option<i64>,
1543 #[serde(skip_serializing_if = "Option::is_none")]
1546 pub is_lgl: Option<bool>,
1547 #[serde(skip_serializing_if = "Option::is_none")]
1548 pub indent: Option<ParagraphIndent>,
1549 #[serde(skip_serializing_if = "Option::is_none")]
1550 pub run_style: Option<TextStyle>,
1551 #[serde(skip_serializing_if = "Option::is_none")]
1552 pub bullet_font_family: Option<String>,
1553 #[serde(skip_serializing_if = "Option::is_none")]
1554 pub bullet_color: Option<String>,
1555 #[serde(skip_serializing_if = "Option::is_none")]
1556 pub picture_bullet_id: Option<i64>,
1557 #[serde(skip_serializing_if = "Option::is_none")]
1558 pub picture_bullet: Option<NumberingPictureBulletDefinition>,
1559}
1560
1561#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
1563#[serde(rename_all = "camelCase")]
1564pub struct NumberingAbstractDefinition {
1565 pub abstract_num_id: i64,
1566 pub levels: Vec<NumberingLevelDefinition>,
1567}
1568
1569#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
1571#[serde(rename_all = "camelCase")]
1572pub struct NumberingInstanceDefinition {
1573 pub num_id: i64,
1574 pub abstract_num_id: i64,
1575 #[serde(skip_serializing_if = "Option::is_none")]
1576 pub level_start_overrides: Option<HashMap<String, i64>>,
1577 #[serde(skip_serializing_if = "Option::is_none")]
1578 pub level_overrides: Option<Vec<NumberingLevelDefinition>>,
1579}
1580
1581#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
1583#[serde(rename_all = "camelCase")]
1584pub struct NumberingDefinitionSet {
1585 pub abstracts: Vec<NumberingAbstractDefinition>,
1586 pub instances: Vec<NumberingInstanceDefinition>,
1587}
1588
1589#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
1591#[serde(rename_all = "camelCase")]
1592pub struct NumberingPictureBulletDefinition {
1593 pub num_pic_bullet_id: i64,
1594 #[serde(skip_serializing_if = "Option::is_none")]
1595 pub src: Option<String>,
1596 #[serde(skip_serializing_if = "Option::is_none")]
1597 pub width_px: Option<f64>,
1598 #[serde(skip_serializing_if = "Option::is_none")]
1599 pub height_px: Option<f64>,
1600 #[serde(skip_serializing_if = "Option::is_none")]
1601 pub part_name: Option<String>,
1602 #[serde(skip_serializing_if = "Option::is_none")]
1603 pub content_type: Option<String>,
1604}
1605
1606#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
1608#[serde(rename_all = "camelCase")]
1609pub struct DocumentNoteDefinition {
1610 pub id: i64,
1611 pub text: String,
1612 #[serde(skip_serializing_if = "Option::is_none")]
1613 pub nodes: Option<Vec<DocNode>>,
1614}
1615
1616#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
1618#[serde(rename_all = "camelCase")]
1619pub struct DocumentCommentDefinition {
1620 #[serde(default, skip_serializing_if = "Option::is_none")]
1621 pub nodes: Option<Vec<DocNode>>,
1622 pub id: i64,
1623 #[serde(skip_serializing_if = "Option::is_none")]
1624 pub author: Option<String>,
1625 #[serde(skip_serializing_if = "Option::is_none")]
1626 pub initials: Option<String>,
1627 #[serde(skip_serializing_if = "Option::is_none")]
1628 pub date: Option<String>,
1629 pub text: String,
1630 #[serde(skip_serializing_if = "Option::is_none")]
1631 pub parent_id: Option<i64>,
1632 #[serde(skip_serializing_if = "Option::is_none")]
1633 pub resolved: Option<bool>,
1634 #[serde(skip_serializing_if = "Option::is_none")]
1635 pub source_xml: Option<String>,
1636 #[serde(skip_serializing_if = "Option::is_none")]
1637 pub extended_paragraph_id: Option<String>,
1638 #[serde(skip_serializing_if = "Option::is_none")]
1639 pub source_resolved: Option<bool>,
1640 #[serde(skip_serializing_if = "Option::is_none")]
1641 pub resolution_dirty: Option<bool>,
1642 #[serde(skip_serializing_if = "Option::is_none")]
1643 pub is_new: Option<bool>,
1644}
1645
1646#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
1648#[serde(rename_all = "camelCase")]
1649pub struct DocumentCompatibilitySettings {
1650 #[serde(skip_serializing_if = "Option::is_none")]
1651 pub adjust_line_height_in_table: Option<bool>,
1652 #[serde(skip_serializing_if = "Option::is_none")]
1653 pub no_leading: Option<bool>,
1654 #[serde(
1655 rename = "suppressTopSpacingWP",
1656 skip_serializing_if = "Option::is_none"
1657 )]
1658 pub suppress_top_spacing_wp: Option<bool>,
1659 #[serde(
1660 rename = "truncateFontHeightsLikeWP6",
1661 skip_serializing_if = "Option::is_none"
1662 )]
1663 pub truncate_font_heights_like_wp6: Option<bool>,
1664 #[serde(skip_serializing_if = "Option::is_none")]
1665 pub no_extra_line_spacing: Option<bool>,
1666 #[serde(rename = "spaceForUL", skip_serializing_if = "Option::is_none")]
1667 pub space_for_ul: Option<bool>,
1668 #[serde(skip_serializing_if = "Option::is_none")]
1669 pub suppress_bottom_spacing: Option<bool>,
1670 #[serde(skip_serializing_if = "Option::is_none")]
1671 pub compatibility_mode: Option<i64>,
1672 #[serde(
1673 rename = "enableOpenTypeFeatures",
1674 skip_serializing_if = "Option::is_none"
1675 )]
1676 pub enable_open_type_features: Option<bool>,
1677 #[serde(skip_serializing_if = "Option::is_none")]
1678 pub suppress_spacing_before_after_page_break: Option<bool>,
1679 #[serde(skip_serializing_if = "Option::is_none")]
1680 pub use_printer_metrics: Option<bool>,
1681 #[serde(skip_serializing_if = "Option::is_none")]
1682 pub use_fixed_html_paragraph_spacing: Option<bool>,
1683 #[serde(skip_serializing_if = "Option::is_none")]
1684 pub do_not_break_wrapped_tables: Option<bool>,
1685 #[serde(skip_serializing_if = "Option::is_none")]
1686 pub do_not_break_constrained_forced_table: Option<bool>,
1687 #[serde(skip_serializing_if = "Option::is_none")]
1688 pub even_and_odd_headers: Option<bool>,
1689}
1690
1691#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
1693#[serde(rename_all = "camelCase")]
1694pub struct DocModelMetadata {
1695 #[serde(default, skip_serializing_if = "Option::is_none")]
1696 pub document_id: Option<String>,
1697 #[serde(default, skip_serializing_if = "Option::is_none")]
1698 pub source_part_names: Option<std::collections::BTreeMap<String, String>>,
1699 pub source_parts: i64,
1700 pub warnings: Vec<String>,
1701 #[serde(skip_serializing_if = "Option::is_none")]
1702 pub document_page_count: Option<i64>,
1703 #[serde(skip_serializing_if = "Option::is_none")]
1704 pub document_open_tag: Option<String>,
1705 #[serde(skip_serializing_if = "Option::is_none")]
1706 pub document_background_color: Option<String>,
1707 #[serde(skip_serializing_if = "Option::is_none")]
1708 pub section_properties_xml: Option<String>,
1709 #[serde(skip_serializing_if = "Option::is_none")]
1710 pub sections: Option<Vec<DocumentSection>>,
1711 pub header_sections: Vec<HeaderSection>,
1712 pub footer_sections: Vec<FooterSection>,
1713 pub paragraph_styles: Vec<ParagraphStyleDefinition>,
1714 #[serde(skip_serializing_if = "Option::is_none")]
1715 pub default_paragraph_style_id: Option<String>,
1716 #[serde(skip_serializing_if = "Option::is_none")]
1717 pub default_tab_stop_twips: Option<i64>,
1718 #[serde(skip_serializing_if = "Option::is_none")]
1719 pub document_settings_imported: Option<bool>,
1720 #[serde(skip_serializing_if = "Option::is_none")]
1721 pub line_spacing_compatibility_imported: Option<bool>,
1722 #[serde(skip_serializing_if = "Option::is_none")]
1723 pub numbering_definitions: Option<NumberingDefinitionSet>,
1724 #[serde(skip_serializing_if = "Option::is_none")]
1725 pub compatibility: Option<DocumentCompatibilitySettings>,
1726 #[serde(skip_serializing_if = "Option::is_none")]
1727 pub footnotes: Option<Vec<DocumentNoteDefinition>>,
1728 #[serde(skip_serializing_if = "Option::is_none")]
1729 pub endnotes: Option<Vec<DocumentNoteDefinition>>,
1730 #[serde(skip_serializing_if = "Option::is_none")]
1731 pub comments: Option<Vec<DocumentCommentDefinition>>,
1732}
1733
1734#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
1736#[serde(rename_all = "camelCase")]
1737pub struct DocModel {
1738 pub nodes: Vec<DocNode>,
1739 pub metadata: DocModelMetadata,
1740}
1741
1742#[cfg(test)]
1743mod deserialize_tests {
1744 use super::{DocModel, DocNode, HeadingLevel, ParagraphAlignment};
1745
1746 #[test]
1747 fn deserializes_minimal_js_doc_model() {
1748 let json = r#"{"nodes":[{"type":"paragraph","children":[{"type":"text","text":"Hi"}]}],"metadata":{"sourceParts":1,"warnings":[],"headerSections":[],"footerSections":[],"paragraphStyles":[]}}"#;
1749 let model: DocModel = serde_json::from_str(json).expect("should deserialize");
1750 assert_eq!(model.nodes.len(), 1);
1751 }
1752
1753 #[test]
1754 fn deserializes_heading_level_two() {
1755 let json = r#"{"type":"paragraph","style":{"headingLevel":2},"children":[{"type":"text","text":"Added"}]}"#;
1756 let node: DocNode = serde_json::from_str(json).expect("heading level 2");
1757 let DocNode::Paragraph(paragraph) = node else {
1758 panic!("expected paragraph");
1759 };
1760 assert_eq!(
1761 paragraph.style.and_then(|style| style.heading_level),
1762 Some(HeadingLevel::Two)
1763 );
1764 }
1765
1766 #[test]
1767 fn deserializes_align_center() {
1768 let json = r#"{"type":"paragraph","style":{"align":"center"},"children":[{"type":"text","text":"Added"}]}"#;
1769 let node: DocNode = serde_json::from_str(json).expect("align center");
1770 let DocNode::Paragraph(paragraph) = node else {
1771 panic!("expected paragraph");
1772 };
1773 assert_eq!(
1774 paragraph.style.and_then(|style| style.align),
1775 Some(ParagraphAlignment::Center)
1776 );
1777 }
1778}
1779
1780#[derive(Clone, Default, Debug, PartialEq, Serialize, Deserialize)]
1782#[serde(transparent)]
1783pub struct SharedParagraphStyle(std::sync::Arc<ParagraphStyle>);
1784
1785impl SharedParagraphStyle {
1786 pub fn into_owned(self) -> ParagraphStyle {
1787 std::sync::Arc::unwrap_or_clone(self.0)
1788 }
1789}
1790
1791impl From<ParagraphStyle> for SharedParagraphStyle {
1792 fn from(style: ParagraphStyle) -> Self {
1793 Self(std::sync::Arc::new(style))
1794 }
1795}
1796
1797impl std::ops::Deref for SharedParagraphStyle {
1798 type Target = ParagraphStyle;
1799
1800 fn deref(&self) -> &ParagraphStyle {
1801 &self.0
1802 }
1803}
1804
1805impl std::ops::DerefMut for SharedParagraphStyle {
1806 fn deref_mut(&mut self) -> &mut ParagraphStyle {
1807 std::sync::Arc::make_mut(&mut self.0)
1808 }
1809}