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(
598 default,
599 deserialize_with = "crate::transport::deserialize_optional_text",
600 skip_serializing_if = "Option::is_none"
601 )]
602 pub src: Option<String>,
603 #[serde(skip_serializing_if = "Option::is_none")]
604 pub alt: Option<String>,
605 #[serde(skip_serializing_if = "Option::is_none")]
606 pub width_px: Option<f64>,
607 #[serde(skip_serializing_if = "Option::is_none")]
608 pub height_px: Option<f64>,
609 #[serde(skip_serializing_if = "Option::is_none")]
610 pub part_name: Option<String>,
611 #[serde(skip_serializing_if = "Option::is_none")]
612 pub content_type: Option<String>,
613 #[serde(
614 default,
615 deserialize_with = "crate::transport::deserialize_image_data",
616 skip_serializing_if = "Option::is_none"
617 )]
618 pub data: Option<Vec<u8>>,
619 #[serde(skip_serializing_if = "Option::is_none")]
620 pub source_xml: Option<String>,
621 #[serde(skip_serializing_if = "Option::is_none")]
622 pub crop: Option<ImageCrop>,
623 #[serde(skip_serializing_if = "Option::is_none")]
624 pub css_filter: Option<String>,
625 #[serde(skip_serializing_if = "Option::is_none")]
626 pub css_opacity: Option<f64>,
627 #[serde(skip_serializing_if = "Option::is_none")]
628 pub floating: Option<ImageFloating>,
629 #[serde(skip_serializing_if = "Option::is_none")]
630 pub synthetic_text_box: Option<bool>,
631 #[serde(skip_serializing_if = "Option::is_none")]
632 pub text_box_text: Option<String>,
633}
634
635#[derive(Clone, Copy, Debug, PartialEq, Eq, Serialize, Deserialize)]
637pub enum ImageRunNodeType {
638 #[serde(rename = "image")]
639 Image,
640}
641
642#[derive(Clone, Copy, Debug, PartialEq, Eq, Serialize, Deserialize)]
644#[serde(rename_all = "camelCase")]
645pub enum FormFieldType {
646 #[serde(rename = "checkbox")]
647 Checkbox,
648 #[serde(rename = "text")]
649 Text,
650 #[serde(rename = "date")]
651 Date,
652 #[serde(rename = "dropdown")]
653 Dropdown,
654}
655
656#[derive(Clone, Copy, Debug, PartialEq, Eq, Serialize, Deserialize)]
658pub enum FormFieldSourceKind {
659 #[serde(rename = "sdt")]
660 Sdt,
661 #[serde(rename = "legacy")]
662 Legacy,
663}
664
665#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
667#[serde(rename_all = "camelCase")]
668pub struct FormFieldOption {
669 pub display_text: String,
670 #[serde(skip_serializing_if = "Option::is_none")]
671 pub value: Option<String>,
672}
673
674#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
676#[serde(rename_all = "camelCase")]
677pub struct FormFieldTextWidgetSettings {
678 #[serde(skip_serializing_if = "Option::is_none")]
679 pub input_type: Option<String>,
680 #[serde(skip_serializing_if = "Option::is_none")]
681 pub default_text: Option<String>,
682 #[serde(skip_serializing_if = "Option::is_none")]
683 pub max_length: Option<i64>,
684 #[serde(skip_serializing_if = "Option::is_none")]
685 pub text_format: Option<String>,
686}
687
688#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
690#[serde(rename_all = "camelCase")]
691pub struct FormFieldCheckboxWidgetSettings {
692 #[serde(skip_serializing_if = "Option::is_none")]
693 pub default_checked: Option<bool>,
694 #[serde(skip_serializing_if = "Option::is_none")]
695 pub size_mode: Option<FormFieldCheckboxSizeMode>,
696 #[serde(skip_serializing_if = "Option::is_none")]
697 pub size_pt: Option<f64>,
698}
699
700#[derive(Clone, Copy, Debug, PartialEq, Eq, Serialize, Deserialize)]
702pub enum FormFieldCheckboxSizeMode {
703 #[serde(rename = "auto")]
704 Auto,
705 #[serde(rename = "exact")]
706 Exact,
707}
708
709#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
711#[serde(rename_all = "camelCase")]
712pub struct FormFieldDropdownWidgetSettings {
713 #[serde(skip_serializing_if = "Option::is_none")]
714 pub default_value: Option<String>,
715}
716
717#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
719#[serde(rename_all = "camelCase")]
720pub struct FormFieldWidgetSettings {
721 #[serde(skip_serializing_if = "Option::is_none")]
722 pub name: Option<String>,
723 #[serde(skip_serializing_if = "Option::is_none")]
724 pub enabled: Option<bool>,
725 #[serde(skip_serializing_if = "Option::is_none")]
726 pub calc_on_exit: Option<bool>,
727 #[serde(skip_serializing_if = "Option::is_none")]
728 pub text: Option<FormFieldTextWidgetSettings>,
729 #[serde(skip_serializing_if = "Option::is_none")]
730 pub checkbox: Option<FormFieldCheckboxWidgetSettings>,
731 #[serde(skip_serializing_if = "Option::is_none")]
732 pub dropdown: Option<FormFieldDropdownWidgetSettings>,
733}
734
735#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
736#[serde(rename_all = "camelCase")]
737pub struct FormFieldSourcePreview {
738 pub relationship_id: String,
739 pub shape_id: String,
740 pub checked: bool,
741 pub image: Box<ImageRunNode>,
742}
743
744#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
746#[serde(rename_all = "camelCase")]
747pub struct FormFieldRunNode {
748 #[serde(default = "default_form_field_run_type", rename = "type")]
749 pub r#type: FormFieldRunNodeType,
750 pub field_type: FormFieldType,
751 #[serde(skip_serializing_if = "Option::is_none")]
752 pub source_kind: Option<FormFieldSourceKind>,
753 #[serde(skip_serializing_if = "Option::is_none")]
754 pub id: Option<i64>,
755 #[serde(skip_serializing_if = "Option::is_none")]
756 pub tag: Option<String>,
757 #[serde(skip_serializing_if = "Option::is_none")]
758 pub title: Option<String>,
759 #[serde(skip_serializing_if = "Option::is_none")]
760 pub placeholder: Option<String>,
761 #[serde(skip_serializing_if = "Option::is_none")]
762 pub checked: Option<bool>,
763 #[serde(skip_serializing_if = "Option::is_none")]
764 pub value: Option<String>,
765 #[serde(skip_serializing_if = "Option::is_none")]
766 pub options: Option<Vec<FormFieldOption>>,
767 #[serde(skip_serializing_if = "Option::is_none")]
768 pub widget: Option<FormFieldWidgetSettings>,
769 #[serde(skip_serializing_if = "Option::is_none")]
770 pub checked_symbol: Option<String>,
771 #[serde(skip_serializing_if = "Option::is_none")]
772 pub unchecked_symbol: Option<String>,
773 #[serde(skip_serializing_if = "Option::is_none")]
774 pub style: Option<SharedTextStyle>,
775 #[serde(skip_serializing_if = "Option::is_none")]
776 pub link: Option<String>,
777 #[serde(skip_serializing_if = "Option::is_none")]
778 pub source_xml: Option<String>,
779 #[serde(default, skip_serializing_if = "Option::is_none")]
780 pub source_preview: Option<Box<FormFieldSourcePreview>>,
781}
782
783#[derive(Clone, Copy, Debug, PartialEq, Eq, Serialize, Deserialize)]
785pub enum FormFieldRunNodeType {
786 #[serde(rename = "form-field")]
787 FormField,
788}
789
790#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
792#[serde(untagged)]
793pub enum ParagraphChildNode {
794 Text(TextRunNode),
795 Image(Box<ImageRunNode>),
796 FormField(Box<FormFieldRunNode>),
797}
798
799#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
801#[serde(rename_all = "camelCase")]
802pub struct ParagraphNumbering {
803 pub num_id: i64,
804 pub ilvl: i64,
805}
806
807#[derive(Clone, Copy, Debug, PartialEq, Eq, Serialize, Deserialize)]
809pub enum ParagraphLineRule {
810 #[serde(rename = "auto")]
811 Auto,
812 #[serde(rename = "exact")]
813 Exact,
814 #[serde(rename = "atLeast")]
815 AtLeast,
816}
817
818#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
820#[serde(rename_all = "camelCase")]
821pub struct ParagraphSpacing {
822 #[serde(skip_serializing_if = "Option::is_none")]
823 pub before_twips: Option<i64>,
824 #[serde(skip_serializing_if = "Option::is_none")]
825 pub after_twips: Option<i64>,
826 #[serde(skip_serializing_if = "Option::is_none")]
827 pub before_auto_spacing: Option<bool>,
828 #[serde(skip_serializing_if = "Option::is_none")]
829 pub after_auto_spacing: Option<bool>,
830 #[serde(skip_serializing_if = "Option::is_none")]
831 pub line_twips: Option<i64>,
832 #[serde(skip_serializing_if = "Option::is_none")]
833 pub line_rule: Option<ParagraphLineRule>,
834}
835
836#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
838#[serde(rename_all = "camelCase")]
839pub struct ParagraphIndent {
840 #[serde(skip_serializing_if = "Option::is_none")]
841 pub left_twips: Option<i64>,
842 #[serde(skip_serializing_if = "Option::is_none")]
843 pub right_twips: Option<i64>,
844 #[serde(skip_serializing_if = "Option::is_none")]
845 pub first_line_twips: Option<i64>,
846 #[serde(skip_serializing_if = "Option::is_none")]
847 pub hanging_twips: Option<i64>,
848}
849
850#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
852#[serde(rename_all = "camelCase")]
853pub struct ParagraphBorderStyle {
854 #[serde(rename = "type")]
855 pub border_type: String,
856 #[serde(skip_serializing_if = "Option::is_none")]
857 pub color: Option<String>,
858 #[serde(skip_serializing_if = "Option::is_none")]
859 pub size_eighth_pt: Option<f64>,
860 #[serde(skip_serializing_if = "Option::is_none")]
861 pub space_pt: Option<f64>,
862 #[serde(skip_serializing_if = "Option::is_none")]
863 pub frame: Option<bool>,
864 #[serde(skip_serializing_if = "Option::is_none")]
865 pub shadow: Option<bool>,
866}
867
868#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
870#[serde(rename_all = "camelCase")]
871pub struct ParagraphBorderSet {
872 #[serde(skip_serializing_if = "Option::is_none")]
873 pub top: Option<ParagraphBorderStyle>,
874 #[serde(skip_serializing_if = "Option::is_none")]
875 pub right: Option<ParagraphBorderStyle>,
876 #[serde(skip_serializing_if = "Option::is_none")]
877 pub bottom: Option<ParagraphBorderStyle>,
878 #[serde(skip_serializing_if = "Option::is_none")]
879 pub left: Option<ParagraphBorderStyle>,
880 #[serde(skip_serializing_if = "Option::is_none")]
881 pub between: Option<ParagraphBorderStyle>,
882 #[serde(skip_serializing_if = "Option::is_none")]
883 pub bar: Option<ParagraphBorderStyle>,
884}
885
886#[derive(Clone, Copy, Debug, PartialEq, Eq, Serialize, Deserialize)]
888#[serde(rename_all = "camelCase")]
889pub enum ParagraphTabStopAlignment {
890 Clear,
891 Left,
892 Center,
893 Right,
894 Decimal,
895 Bar,
896}
897
898#[derive(Clone, Copy, Debug, PartialEq, Eq, Serialize, Deserialize)]
900pub enum ParagraphTabStopLeader {
901 #[serde(rename = "none")]
902 LeaderNone,
903 #[serde(rename = "dot")]
904 Dot,
905 #[serde(rename = "hyphen")]
906 Hyphen,
907 #[serde(rename = "underscore")]
908 Underscore,
909 #[serde(rename = "middleDot")]
910 MiddleDot,
911}
912
913#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
915#[serde(rename_all = "camelCase")]
916pub struct ParagraphTabStop {
917 #[serde(skip_serializing_if = "Option::is_none")]
918 pub alignment: Option<ParagraphTabStopAlignment>,
919 #[serde(skip_serializing_if = "Option::is_none")]
920 pub leader: Option<ParagraphTabStopLeader>,
921 #[serde(skip_serializing_if = "Option::is_none")]
922 pub position_twips: Option<i64>,
923}
924
925#[derive(Clone, Copy, Debug, PartialEq, Eq, Serialize, Deserialize)]
927pub enum ParagraphDropCapType {
928 #[serde(rename = "drop")]
929 Drop,
930 #[serde(rename = "margin")]
931 Margin,
932}
933
934#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
936#[serde(rename_all = "camelCase")]
937pub struct ParagraphDropCap {
938 #[serde(rename = "type")]
939 pub drop_cap_type: ParagraphDropCapType,
940 #[serde(skip_serializing_if = "Option::is_none")]
941 pub lines: Option<i64>,
942 #[serde(skip_serializing_if = "Option::is_none")]
943 pub wrap: Option<String>,
944 #[serde(skip_serializing_if = "Option::is_none")]
945 pub horizontal_anchor: Option<String>,
946 #[serde(skip_serializing_if = "Option::is_none")]
947 pub vertical_anchor: Option<String>,
948 #[serde(skip_serializing_if = "Option::is_none")]
949 pub x_twips: Option<i64>,
950 #[serde(skip_serializing_if = "Option::is_none")]
951 pub y_twips: Option<i64>,
952 #[serde(skip_serializing_if = "Option::is_none")]
953 pub horizontal_space_twips: Option<i64>,
954 #[serde(skip_serializing_if = "Option::is_none")]
955 pub vertical_space_twips: Option<i64>,
956}
957
958#[derive(Clone, Copy, Debug, PartialEq, Eq, Serialize, Deserialize)]
959#[serde(rename_all = "camelCase")]
960pub enum ParagraphTextAlignment {
961 Auto,
962 Top,
963 Center,
964 Baseline,
965 Bottom,
966}
967
968#[derive(Clone, Debug, Default, PartialEq, Serialize, Deserialize)]
970#[serde(rename_all = "camelCase")]
971pub struct ParagraphStyle {
972 #[serde(skip_serializing_if = "Option::is_none")]
973 pub source_before_auto_spacing: Option<bool>,
974 #[serde(skip_serializing_if = "Option::is_none")]
975 pub source_after_auto_spacing: Option<bool>,
976 #[serde(skip_serializing_if = "Option::is_none")]
977 pub align: Option<ParagraphAlignment>,
978 #[serde(skip_serializing_if = "Option::is_none")]
979 pub snap_to_grid: Option<bool>,
980 #[serde(skip_serializing_if = "Option::is_none")]
981 pub source_snap_to_grid: Option<bool>,
982 #[serde(skip_serializing_if = "Option::is_none")]
983 pub source_has_snap_to_grid: Option<bool>,
984 #[serde(skip_serializing_if = "Option::is_none")]
985 pub source_inherited_snap_to_grid: Option<bool>,
986 #[serde(skip_serializing_if = "Option::is_none")]
987 pub source_table_snap_to_grid: Option<bool>,
988 #[serde(skip_serializing_if = "Option::is_none")]
989 pub text_alignment: Option<ParagraphTextAlignment>,
990 #[serde(skip_serializing_if = "Option::is_none")]
991 pub source_text_alignment: Option<ParagraphTextAlignment>,
992 #[serde(skip_serializing_if = "Option::is_none")]
993 pub source_has_text_alignment: Option<bool>,
994 #[serde(skip_serializing_if = "Option::is_none")]
995 pub source_inherited_text_alignment: Option<ParagraphTextAlignment>,
996 #[serde(skip_serializing_if = "Option::is_none")]
997 pub source_table_text_alignment: Option<ParagraphTextAlignment>,
998 #[serde(skip_serializing_if = "Option::is_none")]
999 pub heading_level: Option<HeadingLevel>,
1000 #[serde(skip_serializing_if = "Option::is_none")]
1001 pub style_id: Option<String>,
1002 #[serde(skip_serializing_if = "Option::is_none")]
1003 pub style_name: Option<String>,
1004 #[serde(skip_serializing_if = "Option::is_none")]
1005 pub numbering: Option<ParagraphNumbering>,
1006 #[serde(skip_serializing_if = "Option::is_none")]
1007 pub spacing: Option<ParagraphSpacing>,
1008 #[serde(skip_serializing_if = "Option::is_none")]
1009 pub indent: Option<ParagraphIndent>,
1010 #[serde(skip_serializing_if = "Option::is_none")]
1011 pub background_color: Option<String>,
1012 #[serde(skip_serializing_if = "Option::is_none")]
1013 pub borders: Option<ParagraphBorderSet>,
1014 #[serde(skip_serializing_if = "Option::is_none")]
1015 pub tab_stops: Option<Vec<ParagraphTabStop>>,
1016 #[serde(skip_serializing_if = "Option::is_none")]
1017 pub contextual_spacing: Option<bool>,
1018 #[serde(skip_serializing_if = "Option::is_none")]
1019 pub keep_next: Option<bool>,
1020 #[serde(skip_serializing_if = "Option::is_none")]
1021 pub keep_lines: Option<bool>,
1022 #[serde(skip_serializing_if = "Option::is_none")]
1023 pub widow_control: Option<bool>,
1024 #[serde(skip_serializing_if = "Option::is_none")]
1025 pub page_break_before: Option<bool>,
1026 #[serde(skip_serializing_if = "Option::is_none")]
1027 pub drop_cap: Option<ParagraphDropCap>,
1028}
1029
1030#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
1032#[serde(rename_all = "camelCase")]
1033pub struct ParagraphSourceTextPatchRun {
1034 #[serde(skip_serializing_if = "Option::is_none")]
1035 pub style: Option<SharedTextStyle>,
1036 #[serde(skip_serializing_if = "Option::is_none")]
1037 pub link: Option<String>,
1038 #[serde(skip_serializing_if = "Option::is_none")]
1039 pub note_reference: Option<NoteReference>,
1040}
1041
1042#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
1043#[serde(rename_all = "camelCase")]
1044pub struct ParagraphSourceTextPatch {
1045 pub runs: Vec<ParagraphSourceTextPatchRun>,
1046}
1047
1048#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
1050#[serde(rename_all = "camelCase")]
1051pub struct ParagraphMarkFormattingSource {
1052 #[serde(skip_serializing_if = "Option::is_none")]
1053 pub default_style: Option<SharedTextStyle>,
1054 #[serde(skip_serializing_if = "Option::is_none")]
1055 pub character_style: Option<SharedTextStyle>,
1056 #[serde(skip_serializing_if = "Option::is_none")]
1057 pub direct_style: Option<SharedTextStyle>,
1058}
1059
1060#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
1062#[serde(rename_all = "camelCase")]
1063pub struct ParagraphNode {
1064 #[serde(default, skip_serializing_if = "Option::is_none")]
1065 pub review_content: Option<Vec<crate::revisions::ReviewContent>>,
1066 #[serde(default, skip_serializing_if = "Option::is_none")]
1067 pub block_id: Option<String>,
1068 #[serde(default = "default_paragraph_node_type", rename = "type")]
1069 pub r#type: ParagraphNodeType,
1070 pub children: Vec<ParagraphChildNode>,
1071 #[serde(skip_serializing_if = "Option::is_none")]
1072 pub style: Option<SharedParagraphStyle>,
1073 #[serde(skip_serializing_if = "Option::is_none")]
1074 pub paragraph_mark_style: Option<SharedTextStyle>,
1075 #[serde(skip_serializing_if = "Option::is_none")]
1076 pub source_paragraph_mark_style: Option<SharedTextStyle>,
1077 #[serde(skip_serializing_if = "Option::is_none")]
1078 pub source_paragraph_mark_formatting: Option<ParagraphMarkFormattingSource>,
1079 #[serde(skip_serializing_if = "Option::is_none")]
1080 pub source_paragraph_mark_properties_xml: Option<String>,
1081 #[serde(skip_serializing_if = "Option::is_none")]
1082 pub paragraph_mark_deleted: Option<bool>,
1083 #[serde(skip_serializing_if = "Option::is_none")]
1084 pub source_xml: Option<String>,
1085 #[serde(skip_serializing_if = "Option::is_none")]
1086 pub source_text_patch: Option<ParagraphSourceTextPatch>,
1087 #[serde(skip_serializing_if = "Option::is_none")]
1090 pub source_run_provenance: Option<ParagraphSourceTextPatch>,
1091}
1092
1093#[derive(Clone, Copy, Debug, PartialEq, Eq, Serialize, Deserialize)]
1095pub enum ParagraphNodeType {
1096 #[serde(rename = "paragraph")]
1097 Paragraph,
1098}
1099
1100#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
1102#[serde(rename_all = "camelCase")]
1103pub struct TableBoxSpacing {
1104 #[serde(skip_serializing_if = "Option::is_none")]
1105 pub top_twips: Option<i64>,
1106 #[serde(skip_serializing_if = "Option::is_none")]
1107 pub right_twips: Option<i64>,
1108 #[serde(skip_serializing_if = "Option::is_none")]
1109 pub bottom_twips: Option<i64>,
1110 #[serde(skip_serializing_if = "Option::is_none")]
1111 pub left_twips: Option<i64>,
1112}
1113
1114#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
1116#[serde(rename_all = "camelCase")]
1117pub struct TableBorderStyle {
1118 #[serde(rename = "type")]
1119 pub border_type: String,
1120 #[serde(skip_serializing_if = "Option::is_none")]
1121 pub color: Option<String>,
1122 #[serde(skip_serializing_if = "Option::is_none")]
1123 pub size_eighth_pt: Option<f64>,
1124}
1125
1126#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
1128#[serde(rename_all = "camelCase")]
1129pub struct TableBorderSet {
1130 #[serde(skip_serializing_if = "Option::is_none")]
1131 pub top: Option<TableBorderStyle>,
1132 #[serde(skip_serializing_if = "Option::is_none")]
1133 pub right: Option<TableBorderStyle>,
1134 #[serde(skip_serializing_if = "Option::is_none")]
1135 pub bottom: Option<TableBorderStyle>,
1136 #[serde(skip_serializing_if = "Option::is_none")]
1137 pub left: Option<TableBorderStyle>,
1138 #[serde(skip_serializing_if = "Option::is_none")]
1139 pub inside_h: Option<TableBorderStyle>,
1140 #[serde(skip_serializing_if = "Option::is_none")]
1141 pub inside_v: Option<TableBorderStyle>,
1142 #[serde(skip_serializing_if = "Option::is_none")]
1143 pub tl2br: Option<TableBorderStyle>,
1144 #[serde(skip_serializing_if = "Option::is_none")]
1145 pub tr2bl: Option<TableBorderStyle>,
1146}
1147
1148#[derive(Clone, Copy, Debug, PartialEq, Eq, Serialize, Deserialize)]
1150#[serde(rename_all = "camelCase")]
1151pub enum TableCellVerticalAlign {
1152 Top,
1153 Center,
1154 Bottom,
1155}
1156
1157#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
1159#[serde(tag = "type", rename_all = "camelCase")]
1160pub enum TablePreferredWidth {
1161 Dxa { value: f64 },
1162 Pct { value: f64 },
1163 Auto,
1164 Nil,
1165}
1166
1167#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
1169#[serde(rename_all = "camelCase")]
1170pub struct TableWidthSource {
1171 #[serde(skip_serializing_if = "Option::is_none")]
1172 pub preferred_width: Option<TablePreferredWidth>,
1173 #[serde(skip_serializing_if = "Option::is_none")]
1174 pub width_twips: Option<i64>,
1175 #[serde(skip_serializing_if = "Option::is_none")]
1176 pub inherited_preferred_width: Option<TablePreferredWidth>,
1177}
1178
1179#[derive(Clone, Copy, Debug, PartialEq, Eq, Serialize, Deserialize)]
1180#[serde(rename_all = "camelCase")]
1181pub enum TableAlignment {
1182 Left,
1183 Center,
1184 Right,
1185}
1186
1187#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
1189#[serde(rename_all = "camelCase")]
1190pub struct TableCellStyle {
1191 #[serde(skip_serializing_if = "Option::is_none")]
1192 pub background_color: Option<String>,
1193 #[serde(skip_serializing_if = "Option::is_none")]
1194 pub grid_span: Option<i64>,
1195 #[serde(skip_serializing_if = "Option::is_none")]
1196 pub row_span: Option<i64>,
1197 #[serde(skip_serializing_if = "Option::is_none")]
1198 pub v_merge_continuation: Option<bool>,
1199 #[serde(skip_serializing_if = "Option::is_none")]
1200 pub width_twips: Option<i64>,
1201 #[serde(skip_serializing_if = "Option::is_none")]
1202 pub preferred_width: Option<TablePreferredWidth>,
1203 #[serde(skip_serializing_if = "Option::is_none")]
1204 pub source_width: Option<TableWidthSource>,
1205 #[serde(skip_serializing_if = "Option::is_none")]
1206 pub margin_twips: Option<TableBoxSpacing>,
1207 #[serde(skip_serializing_if = "Option::is_none")]
1208 pub vertical_align: Option<TableCellVerticalAlign>,
1209 #[serde(skip_serializing_if = "Option::is_none")]
1210 pub text_direction: Option<String>,
1211 #[serde(skip_serializing_if = "Option::is_none")]
1212 pub source_text_direction: Option<String>,
1213 #[serde(skip_serializing_if = "Option::is_none")]
1214 pub no_wrap: Option<bool>,
1215 #[serde(skip_serializing_if = "Option::is_none")]
1216 pub source_no_wrap: Option<bool>,
1217 #[serde(skip_serializing_if = "Option::is_none")]
1218 pub borders: Option<TableBorderSet>,
1219}
1220
1221#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
1223#[serde(untagged)]
1224pub enum TableCellContentNode {
1225 Paragraph(ParagraphNode),
1226 Table(Box<TableNode>),
1227}
1228
1229#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
1231#[serde(rename_all = "camelCase")]
1232pub struct TableCellNode {
1233 #[serde(default = "default_table_cell_node_type", rename = "type")]
1234 pub r#type: TableCellNodeType,
1235 pub nodes: Vec<TableCellContentNode>,
1236 #[serde(skip_serializing_if = "Option::is_none")]
1237 pub style: Option<TableCellStyle>,
1238}
1239
1240#[derive(Clone, Copy, Debug, PartialEq, Eq, Serialize, Deserialize)]
1242pub enum TableCellNodeType {
1243 #[serde(rename = "table-cell")]
1244 TableCell,
1245}
1246
1247#[derive(Clone, Copy, Debug, PartialEq, Eq, Serialize, Deserialize)]
1249pub enum TableRowHeightRule {
1250 #[serde(rename = "auto")]
1251 Auto,
1252 #[serde(rename = "atLeast")]
1253 AtLeast,
1254 #[serde(rename = "exact")]
1255 Exact,
1256}
1257
1258#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
1260#[serde(rename_all = "camelCase")]
1261pub struct TableRowGeometrySource {
1262 #[serde(skip_serializing_if = "Option::is_none")]
1263 pub grid_before: Option<i64>,
1264 #[serde(skip_serializing_if = "Option::is_none")]
1265 pub grid_after: Option<i64>,
1266 #[serde(skip_serializing_if = "Option::is_none")]
1267 pub width_before: Option<TablePreferredWidth>,
1268 #[serde(skip_serializing_if = "Option::is_none")]
1269 pub width_after: Option<TablePreferredWidth>,
1270}
1271
1272#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
1274#[serde(rename_all = "camelCase")]
1275pub struct TableRowStyle {
1276 #[serde(skip_serializing_if = "Option::is_none")]
1277 pub grid_before: Option<i64>,
1278 #[serde(skip_serializing_if = "Option::is_none")]
1279 pub grid_after: Option<i64>,
1280 #[serde(skip_serializing_if = "Option::is_none")]
1281 pub width_before: Option<TablePreferredWidth>,
1282 #[serde(skip_serializing_if = "Option::is_none")]
1283 pub width_after: Option<TablePreferredWidth>,
1284 #[serde(skip_serializing_if = "Option::is_none")]
1285 pub source_row_geometry: Option<TableRowGeometrySource>,
1286 #[serde(skip_serializing_if = "Option::is_none")]
1287 pub background_color: Option<String>,
1288 #[serde(skip_serializing_if = "Option::is_none")]
1289 pub height_twips: Option<i64>,
1290 #[serde(skip_serializing_if = "Option::is_none")]
1291 pub height_rule: Option<TableRowHeightRule>,
1292 #[serde(skip_serializing_if = "Option::is_none")]
1293 pub cant_split: Option<bool>,
1294 #[serde(skip_serializing_if = "Option::is_none")]
1295 pub is_header: Option<bool>,
1296}
1297
1298#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
1300#[serde(rename_all = "camelCase")]
1301pub struct TableRowNode {
1302 #[serde(default = "default_table_row_node_type", rename = "type")]
1303 pub r#type: TableRowNodeType,
1304 pub cells: Vec<TableCellNode>,
1305 #[serde(skip_serializing_if = "Option::is_none")]
1306 pub style: Option<TableRowStyle>,
1307}
1308
1309#[derive(Clone, Copy, Debug, PartialEq, Eq, Serialize, Deserialize)]
1311pub enum TableRowNodeType {
1312 #[serde(rename = "table-row")]
1313 TableRow,
1314}
1315
1316#[derive(Clone, Copy, Debug, PartialEq, Eq, Serialize, Deserialize)]
1318pub enum TableLayout {
1319 #[serde(rename = "fixed")]
1320 Fixed,
1321 #[serde(rename = "autofit")]
1322 Autofit,
1323}
1324
1325#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
1327#[serde(rename_all = "camelCase")]
1328pub struct TableFloating {
1329 #[serde(skip_serializing_if = "Option::is_none")]
1330 pub x_twips: Option<i64>,
1331 #[serde(skip_serializing_if = "Option::is_none")]
1332 pub y_twips: Option<i64>,
1333 #[serde(skip_serializing_if = "Option::is_none")]
1334 pub left_from_text_twips: Option<i64>,
1335 #[serde(skip_serializing_if = "Option::is_none")]
1336 pub right_from_text_twips: Option<i64>,
1337 #[serde(skip_serializing_if = "Option::is_none")]
1338 pub top_from_text_twips: Option<i64>,
1339 #[serde(skip_serializing_if = "Option::is_none")]
1340 pub bottom_from_text_twips: Option<i64>,
1341 #[serde(skip_serializing_if = "Option::is_none")]
1342 pub horizontal_anchor: Option<String>,
1343 #[serde(skip_serializing_if = "Option::is_none")]
1344 pub vertical_anchor: Option<String>,
1345 #[serde(skip_serializing_if = "Option::is_none")]
1346 pub horizontal_align: Option<ImageHorizontalAlign>,
1347 #[serde(skip_serializing_if = "Option::is_none")]
1348 pub vertical_align: Option<ImageVerticalAlign>,
1349}
1350
1351#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
1353#[serde(rename_all = "camelCase")]
1354pub struct TableStyle {
1355 #[serde(skip_serializing_if = "Option::is_none")]
1356 pub style_id: Option<String>,
1357 #[serde(skip_serializing_if = "Option::is_none")]
1358 pub source_style_id: Option<String>,
1359 #[serde(skip_serializing_if = "Option::is_none")]
1360 pub width_twips: Option<i64>,
1361 #[serde(skip_serializing_if = "Option::is_none")]
1362 pub preferred_width: Option<TablePreferredWidth>,
1363 #[serde(skip_serializing_if = "Option::is_none")]
1364 pub source_width: Option<TableWidthSource>,
1365 #[serde(skip_serializing_if = "Option::is_none")]
1366 pub alignment: Option<TableAlignment>,
1367 #[serde(skip_serializing_if = "Option::is_none")]
1368 pub source_alignment: Option<TableAlignment>,
1369 #[serde(skip_serializing_if = "Option::is_none")]
1370 pub source_inherited_alignment: Option<TableAlignment>,
1371 #[serde(skip_serializing_if = "Option::is_none")]
1372 pub bidi_visual: Option<bool>,
1373 #[serde(skip_serializing_if = "Option::is_none")]
1374 pub source_bidi_visual: Option<bool>,
1375 #[serde(skip_serializing_if = "Option::is_none")]
1376 pub source_inherited_bidi_visual: Option<bool>,
1377 #[serde(skip_serializing_if = "Option::is_none")]
1378 pub indent_twips: Option<i64>,
1379 #[serde(skip_serializing_if = "Option::is_none")]
1380 pub layout: Option<TableLayout>,
1381 #[serde(skip_serializing_if = "Option::is_none")]
1382 pub cell_spacing_twips: Option<i64>,
1383 #[serde(skip_serializing_if = "Option::is_none")]
1384 pub cell_margin_twips: Option<TableBoxSpacing>,
1385 #[serde(skip_serializing_if = "Option::is_none")]
1386 pub column_widths_twips: Option<Vec<i64>>,
1387 #[serde(skip_serializing_if = "Option::is_none")]
1390 pub collapsed_grid_columns: Option<Vec<usize>>,
1391 #[serde(skip_serializing_if = "Option::is_none")]
1392 pub borders: Option<TableBorderSet>,
1393 #[serde(skip_serializing_if = "Option::is_none")]
1394 pub floating: Option<TableFloating>,
1395}
1396
1397#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
1399#[serde(rename_all = "camelCase")]
1400pub struct TableSourceTextPatch {
1401 pub source_paragraph_xml: String,
1402 pub paragraph: ParagraphNode,
1403}
1404
1405#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
1407#[serde(rename_all = "camelCase")]
1408pub struct TableNode {
1409 #[serde(default, skip_serializing_if = "Option::is_none")]
1410 pub review_rows: Option<Vec<crate::revisions::ReviewRow>>,
1411 #[serde(default, skip_serializing_if = "Option::is_none")]
1412 pub block_id: Option<String>,
1413 #[serde(default = "default_table_node_type", rename = "type")]
1414 pub r#type: TableNodeType,
1415 pub rows: Vec<TableRowNode>,
1416 #[serde(skip_serializing_if = "Option::is_none")]
1417 pub style: Option<TableStyle>,
1418 #[serde(skip_serializing_if = "Option::is_none")]
1419 pub source_xml: Option<String>,
1420 #[serde(skip_serializing_if = "Option::is_none")]
1421 pub source_text_patches: Option<Vec<TableSourceTextPatch>>,
1422}
1423
1424#[derive(Clone, Copy, Debug, PartialEq, Eq, Serialize, Deserialize)]
1426pub enum TableNodeType {
1427 #[serde(rename = "table")]
1428 Table,
1429}
1430
1431#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
1433#[serde(untagged)]
1434pub enum DocNode {
1435 Paragraph(ParagraphNode),
1436 Table(TableNode),
1437}
1438
1439#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
1441#[serde(rename_all = "camelCase")]
1442pub struct HeaderSection {
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 FooterSection {
1453 pub part_name: String,
1454 #[serde(skip_serializing_if = "Option::is_none")]
1455 pub reference_type: Option<String>,
1456 pub nodes: Vec<DocNode>,
1457}
1458
1459#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
1461#[serde(rename_all = "camelCase")]
1462pub struct DocumentSection {
1463 pub start_node_index: i64,
1464 #[serde(skip_serializing_if = "Option::is_none")]
1465 pub section_properties_xml: Option<String>,
1466 pub header_sections: Vec<HeaderSection>,
1467 pub footer_sections: Vec<FooterSection>,
1468}
1469
1470#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
1472#[serde(rename_all = "camelCase")]
1473pub struct ParagraphStyleDefinition {
1474 pub id: String,
1475 pub name: String,
1476 #[serde(skip_serializing_if = "Option::is_none")]
1477 pub based_on_id: Option<String>,
1478 #[serde(skip_serializing_if = "Option::is_none")]
1479 pub next_style_id: Option<String>,
1480 #[serde(skip_serializing_if = "Option::is_none")]
1481 pub align: Option<ParagraphAlignment>,
1482 #[serde(skip_serializing_if = "Option::is_none")]
1483 pub snap_to_grid: Option<bool>,
1484 #[serde(skip_serializing_if = "Option::is_none")]
1485 pub source_has_snap_to_grid: Option<bool>,
1486 #[serde(skip_serializing_if = "Option::is_none")]
1487 pub text_alignment: Option<ParagraphTextAlignment>,
1488 #[serde(skip_serializing_if = "Option::is_none")]
1489 pub source_has_text_alignment: Option<bool>,
1490 #[serde(skip_serializing_if = "Option::is_none")]
1491 pub heading_level: Option<HeadingLevel>,
1492 #[serde(skip_serializing_if = "Option::is_none")]
1493 pub numbering: Option<ParagraphNumbering>,
1494 #[serde(skip_serializing_if = "Option::is_none")]
1495 pub spacing: Option<ParagraphSpacing>,
1496 #[serde(skip_serializing_if = "Option::is_none")]
1497 pub indent: Option<ParagraphIndent>,
1498 #[serde(skip_serializing_if = "Option::is_none")]
1499 pub background_color: Option<String>,
1500 #[serde(skip_serializing_if = "Option::is_none")]
1501 pub borders: Option<ParagraphBorderSet>,
1502 #[serde(skip_serializing_if = "Option::is_none")]
1503 pub tab_stops: Option<Vec<ParagraphTabStop>>,
1504 #[serde(skip_serializing_if = "Option::is_none")]
1505 pub contextual_spacing: Option<bool>,
1506 #[serde(skip_serializing_if = "Option::is_none")]
1507 pub keep_next: Option<bool>,
1508 #[serde(skip_serializing_if = "Option::is_none")]
1509 pub keep_lines: Option<bool>,
1510 #[serde(skip_serializing_if = "Option::is_none")]
1511 pub widow_control: Option<bool>,
1512 #[serde(skip_serializing_if = "Option::is_none")]
1513 pub page_break_before: Option<bool>,
1514 #[serde(skip_serializing_if = "Option::is_none")]
1515 pub run_style: Option<TextStyle>,
1516 #[serde(skip_serializing_if = "Option::is_none")]
1517 pub ui_priority: Option<i64>,
1518 #[serde(skip_serializing_if = "Option::is_none")]
1519 pub is_default: Option<bool>,
1520 #[serde(skip_serializing_if = "Option::is_none")]
1521 pub is_primary: Option<bool>,
1522}
1523
1524#[derive(Clone, Copy, Debug, PartialEq, Eq, Serialize, Deserialize)]
1526pub enum NumberingLevelSuffix {
1527 #[serde(rename = "tab")]
1528 Tab,
1529 #[serde(rename = "space")]
1530 Space,
1531 #[serde(rename = "nothing")]
1532 Nothing,
1533}
1534
1535#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
1537#[serde(rename_all = "camelCase")]
1538pub struct NumberingLevelDefinition {
1539 pub ilvl: i64,
1540 #[serde(skip_serializing_if = "Option::is_none")]
1541 pub start: Option<i64>,
1542 #[serde(skip_serializing_if = "Option::is_none")]
1543 pub format: Option<String>,
1544 #[serde(skip_serializing_if = "Option::is_none")]
1545 pub text: Option<String>,
1546 #[serde(skip_serializing_if = "Option::is_none")]
1547 pub suffix: Option<NumberingLevelSuffix>,
1548 #[serde(skip_serializing_if = "Option::is_none")]
1552 pub lvl_restart: Option<i64>,
1553 #[serde(skip_serializing_if = "Option::is_none")]
1556 pub is_lgl: Option<bool>,
1557 #[serde(skip_serializing_if = "Option::is_none")]
1558 pub indent: Option<ParagraphIndent>,
1559 #[serde(skip_serializing_if = "Option::is_none")]
1560 pub run_style: Option<TextStyle>,
1561 #[serde(skip_serializing_if = "Option::is_none")]
1562 pub bullet_font_family: Option<String>,
1563 #[serde(skip_serializing_if = "Option::is_none")]
1564 pub bullet_color: Option<String>,
1565 #[serde(skip_serializing_if = "Option::is_none")]
1566 pub picture_bullet_id: Option<i64>,
1567 #[serde(skip_serializing_if = "Option::is_none")]
1568 pub picture_bullet: Option<NumberingPictureBulletDefinition>,
1569}
1570
1571#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
1573#[serde(rename_all = "camelCase")]
1574pub struct NumberingAbstractDefinition {
1575 pub abstract_num_id: i64,
1576 pub levels: Vec<NumberingLevelDefinition>,
1577}
1578
1579#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
1581#[serde(rename_all = "camelCase")]
1582pub struct NumberingInstanceDefinition {
1583 pub num_id: i64,
1584 pub abstract_num_id: i64,
1585 #[serde(skip_serializing_if = "Option::is_none")]
1586 pub level_start_overrides: Option<HashMap<String, i64>>,
1587 #[serde(skip_serializing_if = "Option::is_none")]
1588 pub level_overrides: Option<Vec<NumberingLevelDefinition>>,
1589}
1590
1591#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
1593#[serde(rename_all = "camelCase")]
1594pub struct NumberingDefinitionSet {
1595 pub abstracts: Vec<NumberingAbstractDefinition>,
1596 pub instances: Vec<NumberingInstanceDefinition>,
1597}
1598
1599#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
1601#[serde(rename_all = "camelCase")]
1602pub struct NumberingPictureBulletDefinition {
1603 pub num_pic_bullet_id: i64,
1604 #[serde(
1605 default,
1606 deserialize_with = "crate::transport::deserialize_optional_text",
1607 skip_serializing_if = "Option::is_none"
1608 )]
1609 pub src: Option<String>,
1610 #[serde(skip_serializing_if = "Option::is_none")]
1611 pub width_px: Option<f64>,
1612 #[serde(skip_serializing_if = "Option::is_none")]
1613 pub height_px: Option<f64>,
1614 #[serde(skip_serializing_if = "Option::is_none")]
1615 pub part_name: Option<String>,
1616 #[serde(skip_serializing_if = "Option::is_none")]
1617 pub content_type: Option<String>,
1618}
1619
1620#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
1622#[serde(rename_all = "camelCase")]
1623pub struct DocumentNoteDefinition {
1624 pub id: i64,
1625 pub text: String,
1626 #[serde(skip_serializing_if = "Option::is_none")]
1627 pub nodes: Option<Vec<DocNode>>,
1628}
1629
1630#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
1632#[serde(rename_all = "camelCase")]
1633pub struct DocumentCommentDefinition {
1634 #[serde(default, skip_serializing_if = "Option::is_none")]
1635 pub nodes: Option<Vec<DocNode>>,
1636 pub id: i64,
1637 #[serde(skip_serializing_if = "Option::is_none")]
1638 pub author: Option<String>,
1639 #[serde(skip_serializing_if = "Option::is_none")]
1640 pub initials: Option<String>,
1641 #[serde(skip_serializing_if = "Option::is_none")]
1642 pub date: Option<String>,
1643 pub text: String,
1644 #[serde(skip_serializing_if = "Option::is_none")]
1645 pub parent_id: Option<i64>,
1646 #[serde(skip_serializing_if = "Option::is_none")]
1647 pub resolved: Option<bool>,
1648 #[serde(skip_serializing_if = "Option::is_none")]
1649 pub source_xml: Option<String>,
1650 #[serde(skip_serializing_if = "Option::is_none")]
1651 pub extended_paragraph_id: Option<String>,
1652 #[serde(skip_serializing_if = "Option::is_none")]
1653 pub source_resolved: Option<bool>,
1654 #[serde(skip_serializing_if = "Option::is_none")]
1655 pub resolution_dirty: Option<bool>,
1656 #[serde(skip_serializing_if = "Option::is_none")]
1657 pub is_new: Option<bool>,
1658}
1659
1660#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
1662#[serde(rename_all = "camelCase")]
1663pub struct DocumentCompatibilitySettings {
1664 #[serde(skip_serializing_if = "Option::is_none")]
1665 pub adjust_line_height_in_table: Option<bool>,
1666 #[serde(skip_serializing_if = "Option::is_none")]
1667 pub no_leading: Option<bool>,
1668 #[serde(
1669 rename = "suppressTopSpacingWP",
1670 skip_serializing_if = "Option::is_none"
1671 )]
1672 pub suppress_top_spacing_wp: Option<bool>,
1673 #[serde(
1674 rename = "truncateFontHeightsLikeWP6",
1675 skip_serializing_if = "Option::is_none"
1676 )]
1677 pub truncate_font_heights_like_wp6: Option<bool>,
1678 #[serde(skip_serializing_if = "Option::is_none")]
1679 pub no_extra_line_spacing: Option<bool>,
1680 #[serde(rename = "spaceForUL", skip_serializing_if = "Option::is_none")]
1681 pub space_for_ul: Option<bool>,
1682 #[serde(skip_serializing_if = "Option::is_none")]
1683 pub suppress_bottom_spacing: Option<bool>,
1684 #[serde(skip_serializing_if = "Option::is_none")]
1685 pub compatibility_mode: Option<i64>,
1686 #[serde(
1687 rename = "enableOpenTypeFeatures",
1688 skip_serializing_if = "Option::is_none"
1689 )]
1690 pub enable_open_type_features: Option<bool>,
1691 #[serde(skip_serializing_if = "Option::is_none")]
1692 pub suppress_spacing_before_after_page_break: Option<bool>,
1693 #[serde(skip_serializing_if = "Option::is_none")]
1694 pub use_printer_metrics: Option<bool>,
1695 #[serde(skip_serializing_if = "Option::is_none")]
1696 pub use_fixed_html_paragraph_spacing: Option<bool>,
1697 #[serde(skip_serializing_if = "Option::is_none")]
1698 pub do_not_break_wrapped_tables: Option<bool>,
1699 #[serde(skip_serializing_if = "Option::is_none")]
1700 pub do_not_break_constrained_forced_table: Option<bool>,
1701 #[serde(skip_serializing_if = "Option::is_none")]
1702 pub even_and_odd_headers: Option<bool>,
1703}
1704
1705#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
1707#[serde(rename_all = "camelCase")]
1708pub struct DocModelMetadata {
1709 #[serde(default, skip_serializing_if = "Option::is_none")]
1710 pub document_id: Option<String>,
1711 #[serde(default, skip_serializing_if = "Option::is_none")]
1712 pub source_part_names: Option<std::collections::BTreeMap<String, String>>,
1713 pub source_parts: i64,
1714 pub warnings: Vec<String>,
1715 #[serde(skip_serializing_if = "Option::is_none")]
1716 pub document_page_count: Option<i64>,
1717 #[serde(skip_serializing_if = "Option::is_none")]
1718 pub document_open_tag: Option<String>,
1719 #[serde(skip_serializing_if = "Option::is_none")]
1720 pub document_background_color: Option<String>,
1721 #[serde(skip_serializing_if = "Option::is_none")]
1722 pub section_properties_xml: Option<String>,
1723 #[serde(skip_serializing_if = "Option::is_none")]
1724 pub sections: Option<Vec<DocumentSection>>,
1725 pub header_sections: Vec<HeaderSection>,
1726 pub footer_sections: Vec<FooterSection>,
1727 pub paragraph_styles: Vec<ParagraphStyleDefinition>,
1728 #[serde(skip_serializing_if = "Option::is_none")]
1729 pub default_paragraph_style_id: Option<String>,
1730 #[serde(skip_serializing_if = "Option::is_none")]
1731 pub default_tab_stop_twips: Option<i64>,
1732 #[serde(skip_serializing_if = "Option::is_none")]
1733 pub document_settings_imported: Option<bool>,
1734 #[serde(skip_serializing_if = "Option::is_none")]
1735 pub line_spacing_compatibility_imported: Option<bool>,
1736 #[serde(skip_serializing_if = "Option::is_none")]
1737 pub numbering_definitions: Option<NumberingDefinitionSet>,
1738 #[serde(skip_serializing_if = "Option::is_none")]
1739 pub compatibility: Option<DocumentCompatibilitySettings>,
1740 #[serde(skip_serializing_if = "Option::is_none")]
1741 pub footnotes: Option<Vec<DocumentNoteDefinition>>,
1742 #[serde(skip_serializing_if = "Option::is_none")]
1743 pub endnotes: Option<Vec<DocumentNoteDefinition>>,
1744 #[serde(skip_serializing_if = "Option::is_none")]
1745 pub comments: Option<Vec<DocumentCommentDefinition>>,
1746}
1747
1748#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
1750#[serde(rename_all = "camelCase")]
1751pub struct DocModel {
1752 pub nodes: Vec<DocNode>,
1753 pub metadata: DocModelMetadata,
1754}
1755
1756#[cfg(test)]
1757mod deserialize_tests {
1758 use super::{DocModel, DocNode, HeadingLevel, ParagraphAlignment};
1759
1760 #[test]
1761 fn deserializes_minimal_js_doc_model() {
1762 let json = r#"{"nodes":[{"type":"paragraph","children":[{"type":"text","text":"Hi"}]}],"metadata":{"sourceParts":1,"warnings":[],"headerSections":[],"footerSections":[],"paragraphStyles":[]}}"#;
1763 let model: DocModel = serde_json::from_str(json).expect("should deserialize");
1764 assert_eq!(model.nodes.len(), 1);
1765 }
1766
1767 #[test]
1768 fn deserializes_heading_level_two() {
1769 let json = r#"{"type":"paragraph","style":{"headingLevel":2},"children":[{"type":"text","text":"Added"}]}"#;
1770 let node: DocNode = serde_json::from_str(json).expect("heading level 2");
1771 let DocNode::Paragraph(paragraph) = node else {
1772 panic!("expected paragraph");
1773 };
1774 assert_eq!(
1775 paragraph.style.and_then(|style| style.heading_level),
1776 Some(HeadingLevel::Two)
1777 );
1778 }
1779
1780 #[test]
1781 fn deserializes_align_center() {
1782 let json = r#"{"type":"paragraph","style":{"align":"center"},"children":[{"type":"text","text":"Added"}]}"#;
1783 let node: DocNode = serde_json::from_str(json).expect("align center");
1784 let DocNode::Paragraph(paragraph) = node else {
1785 panic!("expected paragraph");
1786 };
1787 assert_eq!(
1788 paragraph.style.and_then(|style| style.align),
1789 Some(ParagraphAlignment::Center)
1790 );
1791 }
1792}
1793
1794#[derive(Clone, Default, Debug, PartialEq, Serialize, Deserialize)]
1796#[serde(transparent)]
1797pub struct SharedParagraphStyle(std::sync::Arc<ParagraphStyle>);
1798
1799impl SharedParagraphStyle {
1800 pub fn into_owned(self) -> ParagraphStyle {
1801 std::sync::Arc::unwrap_or_clone(self.0)
1802 }
1803}
1804
1805impl From<ParagraphStyle> for SharedParagraphStyle {
1806 fn from(style: ParagraphStyle) -> Self {
1807 Self(std::sync::Arc::new(style))
1808 }
1809}
1810
1811impl std::ops::Deref for SharedParagraphStyle {
1812 type Target = ParagraphStyle;
1813
1814 fn deref(&self) -> &ParagraphStyle {
1815 &self.0
1816 }
1817}
1818
1819impl std::ops::DerefMut for SharedParagraphStyle {
1820 fn deref_mut(&mut self) -> &mut ParagraphStyle {
1821 std::sync::Arc::make_mut(&mut self.0)
1822 }
1823}