1use hard_xml::{XmlRead, XmlWrite};
2use std::borrow::Cow;
3
4use crate::{
5 __define_enum, __define_struct, __define_struct_vec, __setter, __xml_test_suites,
6 formatting::{Borders, Indent, Justification, NumberingProperty, Spacing, WidowControl},
7};
8
9#[derive(Debug, Default, XmlRead, XmlWrite, Clone)]
20#[cfg_attr(test, derive(PartialEq))]
21#[xml(tag = "w:pPr")]
22pub struct ParagraphProperty<'a> {
23 #[xml(child = "w:pStyle")]
25 pub style_id: Option<ParagraphStyleId<'a>>,
26 #[xml(child = "w:keepNext")]
28 pub keep_next: Option<KeepNext>,
29 #[xml(child = "w:keepLines")]
31 pub keep_lines: Option<KeepLines>,
32 #[xml(child = "w:pageBreakBefore")]
34 pub page_break_before: Option<PageBreakBefore>,
35 #[xml(child = "w:widowControl")]
41 pub widow_control: Option<WidowControl>,
42 #[xml(child = "w:numPr")]
44 pub numbering: Option<NumberingProperty<'a>>,
45 #[xml(child = "w:suppressLineNumbers")]
47 pub suppress_line_numbers: Option<SuppressLineNumbers>,
48 #[xml(child = "w:pBdr")]
50 pub border: Option<Borders<'a>>,
51 #[xml(child = "w:shd")]
53 pub shading: Option<super::Shading<'a>>,
54 #[xml(child = "w:tabs")]
56 pub tabs: Option<CustomTabStopSet>,
57 #[xml(child = "w:suppressAutoHyphens")]
59 pub suppress_auto_hyphens: Option<SuppressAutoHyphens>,
60 #[xml(child = "w:kinsoku")]
62 pub kinsoku: Option<Kinsoku>,
63 #[xml(child = "w:wordWrap")]
65 pub word_wrap: Option<WordWrap>,
66 #[xml(child = "w:overflowPunct")]
68 pub overflow_punct: Option<OverflowPunct>,
69 #[xml(child = "w:topLinePunct")]
71 pub top_line_punct: Option<TopLinePunct>,
72 #[xml(child = "w:autoSpaceDE")]
74 pub auto_space_de: Option<AutoSpaceDE>,
75 #[xml(child = "w:autoSpaceDN")]
77 pub auto_space_dn: Option<AutoSpaceDN>,
78 #[xml(child = "w:bidi")]
80 pub bidi: Option<Bidi>,
81 #[xml(child = "w:adjustRightInd")]
83 pub adjust_right_ind: Option<AdjustRightInd>,
84 #[xml(child = "w:snapToGrid")]
86 pub snap_to_grid: Option<SnapToGrid>,
87 #[xml(child = "w:spacing")]
89 pub spacing: Option<Spacing>,
90 #[xml(child = "w:ind")]
92 pub indent: Option<Indent>,
93 #[xml(child = "w:contextualSpacing")]
95 pub contextual_spacing: Option<ContextualSpacing>,
96 #[xml(child = "w:mirrorIndents")]
98 pub mirror_indents: Option<MirrorIndents>,
99 #[xml(child = "w:suppressOverlap")]
101 pub suppress_overlap: Option<SuppressOverlap>,
102 #[xml(child = "w:jc")]
104 pub justification: Option<Justification>,
105 #[xml(child = "w:textDirection")]
107 pub text_direction: Option<super::TextDirection>,
108 #[xml(child = "w:textAlignment")]
110 pub text_alignment: Option<super::TextAlignment>,
111 #[xml(child = "w:textboxTightWrap")]
113 pub textbox_tight_wrap: Option<super::TextboxTightWrap>,
114 #[xml(child = "w:outlineLvl")]
116 pub outline_lvl: Option<OutlineLvl>,
117 #[xml(child = "w:divId")]
119 pub div_id: Option<DivId>,
120 #[xml(child = "w:cnfStyle")]
122 pub cnf_style: Option<CnfStyle<'a>>,
123 #[xml(child = "w:rPr")]
124 pub r_pr: Vec<super::CharacterProperty<'a>>,
125 #[xml(child = "w:sectPr")]
126 pub section_property: Option<SectionProperty<'a>>,
127 #[xml(child = "w:pPrChange")]
128 pub p_pr_change: Option<RevisionParagraphProperty<'a>>,
129}
130
131impl<'a> ParagraphProperty<'a> {
132 __setter!(style_id: Option<ParagraphStyleId<'a>>);
133 __setter!(justification: Option<Justification>);
134 __setter!(border: Option<Borders<'a>>);
135 __setter!(numbering: Option<NumberingProperty<'a>>);
136 __setter!(spacing: Option<Spacing>);
137 __setter!(indent: Option<Indent>);
138}
139
140#[derive(Debug, Default, XmlRead, XmlWrite, Clone)]
141#[cfg_attr(test, derive(PartialEq))]
142#[xml(tag = "w:pStyle")]
143pub struct ParagraphStyleId<'a> {
144 #[xml(attr = "w:val")]
145 pub value: Cow<'a, str>,
146}
147
148impl<'a, T: Into<Cow<'a, str>>> From<T> for ParagraphStyleId<'a> {
149 fn from(val: T) -> Self {
150 ParagraphStyleId { value: val.into() }
151 }
152}
153
154#[derive(Debug, Default, XmlRead, XmlWrite, Clone)]
155#[cfg_attr(test, derive(PartialEq))]
156#[xml(tag = "w:keepNext")]
157pub struct KeepNext {
158 #[xml(attr = "w:val")]
159 pub value: Option<bool>,
160}
161
162#[derive(Debug, Default, XmlRead, XmlWrite, Clone)]
163#[cfg_attr(test, derive(PartialEq))]
164#[xml(tag = "w:keepLines")]
165pub struct KeepLines {
166 #[xml(attr = "w:val")]
167 pub value: Option<bool>,
168}
169
170#[derive(Debug, Default, XmlRead, XmlWrite, Clone)]
171#[cfg_attr(test, derive(PartialEq))]
172#[xml(tag = "w:pageBreakBefore")]
173pub struct PageBreakBefore {
174 #[xml(attr = "w:val")]
175 pub value: Option<bool>,
176}
177
178#[derive(Debug, Default, XmlRead, XmlWrite, Clone)]
179#[cfg_attr(test, derive(PartialEq))]
180#[xml(tag = "w:suppressLineNumbers")]
181pub struct SuppressLineNumbers {
182 #[xml(attr = "w:val")]
183 pub value: Option<bool>,
184}
185
186#[derive(Debug, Default, XmlRead, XmlWrite, Clone)]
187#[cfg_attr(test, derive(PartialEq))]
188#[xml(tag = "w:suppressAutoHyphens")]
189pub struct SuppressAutoHyphens {
190 #[xml(attr = "w:val")]
191 pub value: Option<bool>,
192}
193
194#[derive(Debug, Default, XmlRead, XmlWrite, Clone)]
195#[cfg_attr(test, derive(PartialEq))]
196#[xml(tag = "w:kinsoku")]
197pub struct Kinsoku {
198 #[xml(attr = "w:val")]
199 pub value: Option<bool>,
200}
201
202#[derive(Debug, Default, XmlRead, XmlWrite, Clone)]
203#[cfg_attr(test, derive(PartialEq))]
204#[xml(tag = "w:wordWrap")]
205pub struct WordWrap {
206 #[xml(attr = "w:val")]
207 pub value: Option<bool>,
208}
209
210#[derive(Debug, Default, XmlRead, XmlWrite, Clone)]
211#[cfg_attr(test, derive(PartialEq))]
212#[xml(tag = "w:overflowPunct")]
213pub struct OverflowPunct {
214 #[xml(attr = "w:val")]
215 pub value: Option<bool>,
216}
217
218#[derive(Debug, Default, XmlRead, XmlWrite, Clone)]
219#[cfg_attr(test, derive(PartialEq))]
220#[xml(tag = "w:topLinePunct")]
221pub struct TopLinePunct {
222 #[xml(attr = "w:val")]
223 pub value: Option<bool>,
224}
225
226#[derive(Debug, Default, XmlRead, XmlWrite, Clone)]
227#[cfg_attr(test, derive(PartialEq))]
228#[xml(tag = "w:autoSpaceDE")]
229pub struct AutoSpaceDE {
230 #[xml(attr = "w:val")]
231 pub value: Option<bool>,
232}
233
234#[derive(Debug, Default, XmlRead, XmlWrite, Clone)]
235#[cfg_attr(test, derive(PartialEq))]
236#[xml(tag = "w:autoSpaceDN")]
237pub struct AutoSpaceDN {
238 #[xml(attr = "w:val")]
239 pub value: Option<bool>,
240}
241
242#[derive(Debug, Default, XmlRead, XmlWrite, Clone)]
243#[cfg_attr(test, derive(PartialEq))]
244#[xml(tag = "w:bidi")]
245pub struct Bidi {
246 #[xml(attr = "w:val")]
247 pub value: Option<bool>,
248}
249
250#[derive(Debug, Default, XmlRead, XmlWrite, Clone)]
251#[cfg_attr(test, derive(PartialEq))]
252#[xml(tag = "w:adjustRightInd")]
253pub struct AdjustRightInd {
254 #[xml(attr = "w:val")]
255 pub value: Option<bool>,
256}
257
258#[derive(Debug, Default, XmlRead, XmlWrite, Clone)]
259#[cfg_attr(test, derive(PartialEq))]
260#[xml(tag = "w:snapToGrid")]
261pub struct SnapToGrid {
262 #[xml(attr = "w:val")]
263 pub value: Option<bool>,
264}
265
266#[derive(Debug, Default, XmlRead, XmlWrite, Clone)]
267#[cfg_attr(test, derive(PartialEq))]
268#[xml(tag = "w:contextualSpacing")]
269pub struct ContextualSpacing {
270 #[xml(attr = "w:val")]
271 pub value: Option<bool>,
272}
273
274#[derive(Debug, Default, XmlRead, XmlWrite, Clone)]
275#[cfg_attr(test, derive(PartialEq))]
276#[xml(tag = "w:mirrorIndents")]
277pub struct MirrorIndents {
278 #[xml(attr = "w:val")]
279 pub value: Option<bool>,
280}
281
282#[derive(Debug, Default, XmlRead, XmlWrite, Clone)]
283#[cfg_attr(test, derive(PartialEq))]
284#[xml(tag = "w:suppressOverlap")]
285pub struct SuppressOverlap {
286 #[xml(attr = "w:val")]
287 pub value: Option<bool>,
288}
289
290#[derive(Debug, Default, XmlRead, XmlWrite, Clone)]
291#[cfg_attr(test, derive(PartialEq))]
292#[xml(tag = "w:outlineLvl")]
293pub struct OutlineLvl {
294 #[xml(attr = "w:val")]
295 pub value: isize,
296}
297
298#[derive(Debug, Default, XmlRead, XmlWrite, Clone)]
299#[cfg_attr(test, derive(PartialEq))]
300#[xml(tag = "w:divId")]
301pub struct DivId {
302 #[xml(attr = "w:val")]
303 pub value: isize,
304}
305
306#[derive(Debug, Default, XmlRead, XmlWrite, Clone)]
307#[cfg_attr(test, derive(PartialEq))]
308#[xml(tag = "w:cnfStyle")]
309pub struct CnfStyle<'a> {
310 #[xml(attr = "w:val")]
311 pub value: Cow<'a, str>,
312}
313
314#[derive(Debug, Default, XmlRead, XmlWrite, Clone)]
315#[cfg_attr(test, derive(PartialEq))]
316#[xml(tag = "w:pPrChange")]
317pub struct RevisionParagraphProperty<'a> {
318 #[xml(attr = "w:id")]
319 pub id: isize,
320 #[xml(attr = "w:author")]
321 pub author: Cow<'a, str>,
322 #[xml(attr = "w:date")]
323 pub date: Option<Cow<'a, str>>,
324
325 #[xml(child = "w:pPr")]
326 pub previous_property: Option<PreviousParagraphProperty<'a>>,
327}
328
329#[derive(Debug, Default, XmlRead, XmlWrite, Clone)]
330#[cfg_attr(test, derive(PartialEq))]
331#[xml(tag = "w:pPr")]
332pub struct PreviousParagraphProperty<'a> {
333 #[xml(child = "w:pStyle")]
335 pub style_id: Option<ParagraphStyleId<'a>>,
336 #[xml(child = "w:keepNext")]
338 pub keep_next: Option<KeepNext>,
339 #[xml(child = "w:keepLines")]
341 pub keep_lines: Option<KeepLines>,
342 #[xml(child = "w:pageBreakBefore")]
344 pub page_break_before: Option<PageBreakBefore>,
345 #[xml(child = "w:widowControl")]
351 pub widow_control: Option<WidowControl>,
352 #[xml(child = "w:numPr")]
354 pub numbering: Option<NumberingProperty<'a>>,
355 #[xml(child = "w:suppressLineNumbers")]
357 pub suppress_line_numbers: Option<SuppressLineNumbers>,
358 #[xml(child = "w:pBdr")]
360 pub border: Option<Borders<'a>>,
361 #[xml(child = "w:shd")]
363 pub shading: Option<super::Shading<'a>>,
364 #[xml(child = "w:tabs")]
366 pub tabs: Option<CustomTabStopSet>,
367 #[xml(child = "w:suppressAutoHyphens")]
369 pub suppress_auto_hyphens: Option<SuppressAutoHyphens>,
370 #[xml(child = "w:kinsoku")]
372 pub kinsoku: Option<Kinsoku>,
373 #[xml(child = "w:wordWrap")]
375 pub word_wrap: Option<WordWrap>,
376 #[xml(child = "w:overflowPunct")]
378 pub overflow_punct: Option<OverflowPunct>,
379 #[xml(child = "w:topLinePunct")]
381 pub top_line_punct: Option<TopLinePunct>,
382 #[xml(child = "w:autoSpaceDE")]
384 pub auto_space_de: Option<AutoSpaceDE>,
385 #[xml(child = "w:autoSpaceDN")]
387 pub auto_space_dn: Option<AutoSpaceDN>,
388 #[xml(child = "w:bidi")]
390 pub bidi: Option<Bidi>,
391 #[xml(child = "w:adjustRightInd")]
393 pub adjust_right_ind: Option<AdjustRightInd>,
394 #[xml(child = "w:snapToGrid")]
396 pub snap_to_grid: Option<SnapToGrid>,
397 #[xml(child = "w:spacing")]
399 pub spacing: Option<Spacing>,
400 #[xml(child = "w:ind")]
402 pub indent: Option<Indent>,
403 #[xml(child = "w:contextualSpacing")]
405 pub contextual_spacing: Option<ContextualSpacing>,
406 #[xml(child = "w:mirrorIndents")]
408 pub mirror_indents: Option<MirrorIndents>,
409 #[xml(child = "w:suppressOverlap")]
411 pub suppress_overlap: Option<SuppressOverlap>,
412 #[xml(child = "w:jc")]
414 pub justification: Option<Justification>,
415 #[xml(child = "w:textDirection")]
417 pub text_direction: Option<super::TextDirection>,
418 #[xml(child = "w:textAlignment")]
420 pub text_alignment: Option<super::TextAlignment>,
421 #[xml(child = "w:textboxTightWrap")]
423 pub textbox_tight_wrap: Option<super::TextboxTightWrap>,
424 #[xml(child = "w:outlineLvl")]
426 pub outline_lvl: Option<OutlineLvl>,
427 #[xml(child = "w:divId")]
429 pub div_id: Option<DivId>,
430 #[xml(child = "w:cnfStyle")]
432 pub cnf_style: Option<CnfStyle<'a>>,
433}
434
435__define_enum! {
436 TabStopType {
437 Clear = "clear", Left = "left", Center = "center", Right = "right", Decimal = "decimal", Bar = "bar", Num = "num", }
445}
446
447__define_enum! {
448 TabLeaderCharacter {
449 None = "none", Dot = "dot", Hyphen = "hyphen", Underscore = "underscore", Heavy = "heavy", MiddleDot = "middleDot", }
456}
457
458__define_struct! {
459 ("w:tab", CustomTabStop) {
460 "w:val", tab_stop_type, TabStopType
461 "w:leader", leader, TabLeaderCharacter
462 "w:pos", pos, isize
463 }
464}
465
466__define_struct_vec! {
467 ("w:tabs", CustomTabStopSet, CustomTabStopSetChoice) {} {
468 "w:tab", CustomTabStop
469 }
470}
471
472#[cfg(test)]
473use crate::formatting::JustificationVal;
474
475use super::SectionProperty;
476
477__xml_test_suites!(
478 ParagraphProperty,
479 ParagraphProperty::default(),
480 r#"<w:pPr/>"#,
481 ParagraphProperty::default().style_id("id"),
482 r#"<w:pPr><w:pStyle w:val="id"/></w:pPr>"#,
483 ParagraphProperty::default().justification(JustificationVal::Start),
484 r#"<w:pPr><w:jc w:val="start"/></w:pPr>"#,
485 ParagraphProperty::default().border(Borders::default()),
486 r#"<w:pPr><w:pBdr/></w:pPr>"#,
487 ParagraphProperty::default().numbering(NumberingProperty::default()),
488 r#"<w:pPr><w:numPr/></w:pPr>"#,
489);