Skip to main content

docx_text_formatting/
docx_text_formatting.rs

1//! Word character- and paragraph-level formatting: everything you can put
2//! on a run of text (bold/italic/underline/strike, colors, highlight,
3//! superscript/subscript, small caps, character spacing) and on a
4//! paragraph itself (alignment, tab stops). One page per feature group.
5//!
6//! Run with: `cargo run -p office-toolkit --example docx_text_formatting`
7
8use std::path::{Path, PathBuf};
9
10use office_toolkit::SaveToFile;
11use office_toolkit::prelude::*;
12use office_toolkit::word::{
13    Alignment, Highlight, Run, TabLeader, TabStop, TabStopAlignment, UnderlineStyle, VerticalAlign,
14};
15
16fn main() -> office_toolkit::Result<()> {
17    let path = output_path("docx_text_formatting.docx");
18
19    let document = Document::new()
20        .with_paragraph(heading("Docx text formatting — bold, italic, underline, strike", false))
21        .with_paragraph(Paragraph::new().with_run(Run::new("Bold text.").with_bold(true)))
22        .with_paragraph(Paragraph::new().with_run(Run::new("Italic text.").with_italic(true)))
23        .with_paragraph(Paragraph::new().with_run(Run::new("Single underline.").with_underline(UnderlineStyle::Single)))
24        .with_paragraph(Paragraph::new().with_run(Run::new("Wavy underline.").with_underline(UnderlineStyle::Wave)))
25        .with_paragraph(Paragraph::new().with_run(Run::new("Strikethrough text.").with_strike(true)))
26        .with_paragraph(heading("Colors and highlight", true))
27        .with_paragraph(Paragraph::new().with_run(Run::new("Red text on the default background.").with_color("FF0000")))
28        .with_paragraph(Paragraph::new().with_run(Run::new("Text highlighted in yellow.").with_highlight(Highlight::Yellow)))
29        .with_paragraph(
30            Paragraph::new()
31                .with_run(Run::new("Larger, custom font.").with_font_size(32).with_font_family("Georgia")),
32        )
33        .with_paragraph(heading("Superscript and subscript", true))
34        .with_paragraph(
35            Paragraph::new()
36                .with_run(Run::new("Water is H"))
37                .with_run(Run::new("2").with_vertical_align(VerticalAlign::Subscript))
38                .with_run(Run::new("O.")),
39        )
40        .with_paragraph(
41            Paragraph::new()
42                .with_run(Run::new("Squared: x"))
43                .with_run(Run::new("2").with_vertical_align(VerticalAlign::Superscript))
44                .with_run(Run::new(".")),
45        )
46        .with_paragraph(heading("Small caps, all caps, character spacing", true))
47        .with_paragraph(Paragraph::new().with_run(Run::new("rendered in small caps").with_small_caps(true)))
48        .with_paragraph(Paragraph::new().with_run(Run::new("rendered in all caps").with_all_caps(true)))
49        .with_paragraph(Paragraph::new().with_run(Run::new("Widely spaced letters.").with_character_spacing(120)))
50        .with_paragraph(heading("Paragraph alignment", true))
51        .with_paragraph(Paragraph::with_text("Left-aligned (the default).").with_alignment(Alignment::Left))
52        .with_paragraph(Paragraph::with_text("Centered.").with_alignment(Alignment::Center))
53        .with_paragraph(Paragraph::with_text("Right-aligned.").with_alignment(Alignment::Right))
54        .with_paragraph(
55            Paragraph::with_text(
56                "Justified: this line is long enough for Word to stretch the spacing between words so both edges line up.",
57            )
58            .with_alignment(Alignment::Justify),
59        )
60        .with_paragraph(heading("Tab stops", true))
61        .with_paragraph(
62            Paragraph::new()
63                .with_tab(TabStop::new(1_440).with_alignment(TabStopAlignment::Center))
64                .with_tab(TabStop::new(2_880).with_alignment(TabStopAlignment::Right).with_leader(TabLeader::Dot))
65                .with_run(Run::new("Left\tCentered\tRight, dot leader")),
66        );
67
68    document.save_to_file(&path)?;
69    println!("Wrote {}", path.display());
70    Ok(())
71}
72
73/// A bold section heading, optionally starting a new page — used to give
74/// each feature group its own page in the rendered document.
75fn heading(text: &str, new_page: bool) -> Paragraph {
76    Paragraph::new()
77        .with_run(Run::new(text).with_bold(true).with_font_size(28))
78        .with_page_break_before(new_page)
79}
80
81/// Every example in this directory writes its output under
82/// `tests-data/output/`, resolved relative to this crate's own manifest so
83/// it works no matter what directory `cargo run` was invoked from.
84fn output_path(filename: &str) -> PathBuf {
85    Path::new(env!("CARGO_MANIFEST_DIR"))
86        .join("../../tests-data/output")
87        .join(filename)
88}