Skip to main content

extend_docx/parse/
context.rs

1use std::cell::RefCell;
2use std::collections::HashMap;
3
4use crate::model::{
5    ParagraphSpacing, ParagraphStyle, ParagraphStyleDefinition, TableAlignment, TableBorderSet,
6    TableBoxSpacing, TableFloating, TableLayout, TablePreferredWidth, TextStyle,
7};
8use crate::package::OoxmlPart;
9
10/// Mirrors TypeScript `ContentTypeLookup`.
11#[derive(Clone, Debug, Default, PartialEq, Eq)]
12pub struct ContentTypeLookup {
13    pub default_by_extension: HashMap<String, String>,
14    pub override_by_part_name: HashMap<String, String>,
15}
16
17/// Mirrors TypeScript `ThemeFontMap`.
18#[derive(Clone, Debug, Default, PartialEq, Eq)]
19pub struct ThemeFontMap {
20    pub major_latin: Option<String>,
21    pub minor_latin: Option<String>,
22    pub major_east_asia: Option<String>,
23    pub minor_east_asia: Option<String>,
24    pub major_complex_script: Option<String>,
25    pub minor_complex_script: Option<String>,
26}
27
28/// Mirrors TypeScript `ThemeColorMap`.
29pub type ThemeColorMap = HashMap<String, String>;
30
31/// Mirrors TypeScript `TableConditionalStyleType`.
32#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
33pub enum TableConditionalStyleType {
34    WholeTable,
35    FirstRow,
36    LastRow,
37    FirstCol,
38    LastCol,
39    Band1Horz,
40    Band2Horz,
41    Band1Vert,
42    Band2Vert,
43    NwCell,
44    NeCell,
45    SwCell,
46    SeCell,
47}
48
49impl TableConditionalStyleType {
50    pub const ALL: [TableConditionalStyleType; 13] = [
51        TableConditionalStyleType::WholeTable,
52        TableConditionalStyleType::FirstRow,
53        TableConditionalStyleType::LastRow,
54        TableConditionalStyleType::FirstCol,
55        TableConditionalStyleType::LastCol,
56        TableConditionalStyleType::Band1Horz,
57        TableConditionalStyleType::Band2Horz,
58        TableConditionalStyleType::Band1Vert,
59        TableConditionalStyleType::Band2Vert,
60        TableConditionalStyleType::NwCell,
61        TableConditionalStyleType::NeCell,
62        TableConditionalStyleType::SwCell,
63        TableConditionalStyleType::SeCell,
64    ];
65}
66
67/// Mirrors TypeScript `ParsedTableLook`.
68#[derive(Clone, Debug, PartialEq)]
69pub struct ParsedTableLook {
70    pub first_row: bool,
71    pub last_row: bool,
72    pub first_col: bool,
73    pub last_col: bool,
74    pub no_h_band: bool,
75    pub no_v_band: bool,
76    pub row_band_size: i64,
77    pub col_band_size: i64,
78}
79
80/// Mirrors TypeScript `ParsedTableProperties`.
81#[derive(Clone, Debug, Default, PartialEq)]
82pub struct ParsedTableProperties {
83    pub width_twips: Option<i64>,
84    pub preferred_width: Option<TablePreferredWidth>,
85    pub alignment: Option<TableAlignment>,
86    pub bidi_visual: Option<bool>,
87    pub indent_twips: Option<i64>,
88    pub layout: Option<TableLayout>,
89    pub cell_spacing_twips: Option<i64>,
90    pub cell_margin_twips: Option<TableBoxSpacing>,
91    pub floating: Option<TableFloating>,
92}
93
94/// Mirrors TypeScript `ParsedTableStyleCondition`.
95#[derive(Clone, Debug, Default, PartialEq)]
96pub struct ParsedTableStyleCondition {
97    pub row_background_color: Option<String>,
98    pub cell_background_color: Option<String>,
99    pub cell_preferred_width: Option<TablePreferredWidth>,
100    pub paragraph_align: Option<crate::model::ParagraphAlignment>,
101    pub paragraph_snap_to_grid: Option<bool>,
102    pub paragraph_text_alignment: Option<crate::model::ParagraphTextAlignment>,
103    pub run_style: Option<TextStyle>,
104    pub table_borders: Option<TableBorderSet>,
105    pub cell_borders: Option<TableBorderSet>,
106    pub table_properties: Option<ParsedTableProperties>,
107    pub table_look: Option<ParsedTableLook>,
108}
109
110/// Mirrors TypeScript `ParsedTableStyleDefinition`.
111#[derive(Clone, Debug, PartialEq)]
112pub struct ParsedTableStyleDefinition {
113    pub id: String,
114    pub based_on_id: Option<String>,
115    pub name: String,
116    pub conditions: HashMap<TableConditionalStyleType, ParsedTableStyleCondition>,
117    pub floating: Option<TableFloating>,
118    pub properties: Option<ParsedTableProperties>,
119    pub has_row_cell_spacing: bool,
120}
121
122/// Mirrors TypeScript `ParsedStyleSheet`.
123#[derive(Clone, Debug, PartialEq)]
124pub struct ParsedStyleSheet {
125    pub paragraph_styles: Vec<ParagraphStyleDefinition>,
126    pub paragraph_style_by_id: HashMap<String, ParagraphStyleDefinition>,
127    pub run_style_by_id: HashMap<String, TextStyle>,
128    pub table_style_by_id: HashMap<String, ParsedTableStyleDefinition>,
129    pub default_table_style_id: Option<String>,
130    /// Table styles' own `w:pPr` spacing (basedOn-resolved). ECMA-376 layers
131    /// table-style paragraph properties between document defaults and
132    /// paragraph styles for every paragraph inside a styled table.
133    pub table_paragraph_spacing_by_style_id: HashMap<String, ParagraphSpacing>,
134    pub doc_default_paragraph_spacing: Option<ParagraphSpacing>,
135    pub default_paragraph_style: Option<ParagraphStyle>,
136    pub default_paragraph_text_alignment: Option<crate::model::ParagraphTextAlignment>,
137    pub default_paragraph_style_id: Option<String>,
138    pub default_run_style: Option<TextStyle>,
139    pub theme_fonts: ThemeFontMap,
140    pub theme_colors: ThemeColorMap,
141}
142
143impl ParsedStyleSheet {
144    pub fn empty() -> Self {
145        empty_style_sheet()
146    }
147}
148
149/// Mirrors TypeScript `EMPTY_STYLE_SHEET`.
150pub fn empty_style_sheet() -> ParsedStyleSheet {
151    ParsedStyleSheet {
152        paragraph_styles: Vec::new(),
153        paragraph_style_by_id: HashMap::new(),
154        run_style_by_id: HashMap::new(),
155        table_style_by_id: HashMap::new(),
156        default_table_style_id: None,
157        table_paragraph_spacing_by_style_id: HashMap::new(),
158        doc_default_paragraph_spacing: None,
159        default_paragraph_style: None,
160        default_paragraph_text_alignment: None,
161        default_paragraph_style_id: None,
162        default_run_style: None,
163        theme_fonts: ThemeFontMap::default(),
164        theme_colors: ThemeColorMap::new(),
165    }
166}
167
168pub fn default_table_look() -> ParsedTableLook {
169    ParsedTableLook {
170        first_row: false,
171        last_row: false,
172        first_col: false,
173        last_col: false,
174        no_h_band: true,
175        no_v_band: true,
176        row_band_size: 1,
177        col_band_size: 1,
178    }
179}
180
181/// Mirrors TypeScript `ParseContext`.
182pub struct ParseContext<'a, S = ParsedStyleSheet> {
183    pub relationships: HashMap<String, String>,
184    pub content_types: ContentTypeLookup,
185    pub parts: &'a HashMap<String, OoxmlPart>,
186    pub binary_assets: &'a HashMap<String, Vec<u8>>,
187    pub style_sheet: S,
188    pub warnings: RefCell<Vec<String>>,
189}
190
191impl<'a, S: std::borrow::Borrow<ParsedStyleSheet>> ParseContext<'a, S> {
192    pub fn styles(&self) -> &ParsedStyleSheet {
193        self.style_sheet.borrow()
194    }
195
196    pub fn push_warning(&self, message: impl Into<String>) {
197        self.warnings.borrow_mut().push(message.into());
198    }
199}