use crate::entities::Alignment;
use serde::{Deserialize, Serialize};
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct DocxHeadingStyle {
pub size_half_points: Option<usize>,
pub bold: bool,
pub italic: bool,
pub alignment: Option<Alignment>,
pub space_before_twips: Option<i32>,
pub space_after_twips: Option<i32>,
pub keep_with_next: bool,
pub page_break_before: bool,
}
impl Default for DocxHeadingStyle {
fn default() -> Self {
Self {
size_half_points: None,
bold: true,
italic: false,
alignment: None,
space_before_twips: None,
space_after_twips: None,
keep_with_next: true,
page_break_before: false,
}
}
}
impl DocxHeadingStyle {
pub fn default_ramp(body_half_points: usize) -> Vec<Self> {
const RAMP: [(f32, f32, f32); 6] = [
(1.80, 24.0, 12.0),
(1.50, 18.0, 9.0),
(1.25, 14.0, 7.0),
(1.10, 12.0, 6.0),
(1.00, 12.0, 6.0),
(1.00, 12.0, 6.0),
];
RAMP.iter()
.enumerate()
.map(|(i, &(scale, before_pt, after_pt))| Self {
size_half_points: Some(((body_half_points as f32 * scale).round() as usize).max(2)),
bold: true,
italic: i == 5,
alignment: None,
space_before_twips: Some((before_pt * 20.0) as i32),
space_after_twips: Some((after_pt * 20.0) as i32),
keep_with_next: true,
page_break_before: false,
})
.collect()
}
}
#[derive(Debug, Clone, PartialEq, Default, Serialize, Deserialize)]
pub struct DocxExportOptions {
pub page_width_twips: Option<u32>,
pub page_height_twips: Option<u32>,
pub margin_top_twips: Option<i32>,
pub margin_bottom_twips: Option<i32>,
pub margin_left_twips: Option<i32>,
pub margin_right_twips: Option<i32>,
pub font_family: Option<String>,
pub font_half_points: Option<usize>,
pub line_spacing_twips: Option<i32>,
pub first_line_indent_twips: Option<i32>,
pub paragraph_spacing_after_twips: Option<i32>,
pub justify: bool,
pub page_numbers: bool,
pub running_header: Option<String>,
#[serde(default)]
pub heading_styles: Vec<DocxHeadingStyle>,
#[serde(default)]
pub images: super::image_options::ExportImages,
}
impl DocxExportOptions {
pub fn plain() -> Self {
Self::default()
}
pub fn resolved_heading_styles(&self) -> Vec<DocxHeadingStyle> {
if self.heading_styles.is_empty() {
DocxHeadingStyle::default_ramp(self.font_half_points.unwrap_or(24))
} else {
self.heading_styles.clone()
}
}
}