1use hard_xml::{XmlRead, XmlWrite};
2use std::borrow::Cow;
3
4use crate::{
5 __setter, __string_enum, __xml_test_suites,
6 formatting::{Bold, Color, Dstrike, Fonts, Italics, Lang, Outline, Size, Strike, Underline},
7};
8
9use super::{BoldComplex, Caps, Highlight, ItalicsComplex, Position, SmallCaps, VertAlign};
10
11#[derive(Debug, Default, XmlRead, XmlWrite, Clone)]
31#[cfg_attr(test, derive(PartialEq))]
32#[xml(tag = "w:rPr")]
33pub struct CharacterProperty<'a> {
34 #[xml(child = "w:rStyle")]
36 pub style_id: Option<CharacterStyleId<'a>>,
37 #[xml(child = "w:rFonts")]
39 pub fonts: Option<Fonts>,
40 #[xml(child = "w:b")]
42 pub bold: Option<Bold>,
43 #[xml(child = "w:bCs")]
44 pub bold_complex: Option<BoldComplex>,
45 #[xml(child = "w:i")]
47 pub italics: Option<Italics>,
48 #[xml(child = "w:iCs")]
50 pub italics_complex: Option<ItalicsComplex>,
51 #[xml(child = "w:caps")]
53 pub caps: Option<Caps>,
54 #[xml(child = "w:smallCaps")]
56 pub small_caps: Option<SmallCaps>,
57 #[xml(child = "w:strike")]
59 pub strike: Option<Strike>,
60 #[xml(child = "w:dstrike")]
62 pub dstrike: Option<Dstrike>,
63 #[xml(child = "w:outline")]
65 pub outline: Option<Outline>,
66 #[xml(child = "w:shadow")]
68 pub shadow: Option<Shadow>,
69 #[xml(child = "w:emboss")]
71 pub emboss: Option<Emboss>,
72 #[xml(child = "w:imprint")]
74 pub imprint: Option<Imprint>,
75 #[xml(child = "w:noProof")]
77 pub no_proof: Option<NoProof>,
78 #[xml(child = "w:snapToGrid")]
80 pub snap_to_grid: Option<super::SnapToGrid>,
81 #[xml(child = "w:vanish")]
83 pub vanish: Option<Vanish>,
84 #[xml(child = "w:webHidden")]
86 pub web_hidden: Option<WebHidden>,
87 #[xml(child = "w:color")]
89 pub color: Option<Color<'a>>,
90 #[xml(child = "w:spacing")]
92 pub spacing: Option<TextSpacing>,
93 #[xml(child = "w:w")]
95 pub scale: Option<Scale>,
96 #[xml(child = "w:kern")]
98 pub kern: Option<Kern>,
99 #[xml(child = "w:position")]
101 pub position: Option<Position>,
102 #[xml(child = "w:sz")]
104 pub size: Option<Size>,
105 #[xml(child = "w:szCs")]
107 pub size_complex: Option<SizeComplex>,
108 #[xml(child = "w:highlight")]
110 pub highlight: Option<Highlight>,
111 #[xml(child = "w:u")]
113 pub underline: Option<Underline<'a>>,
114 #[xml(child = "w:effect")]
116 pub effect: Option<Effect>,
117 #[xml(child = "w:bdr")]
119 pub border: Option<TextBorder<'a>>,
120 #[xml(child = "w:shd")]
122 pub shading: Option<Shading<'a>>,
123 #[xml(child = "w:fitText")]
125 pub fit_text: Option<FitText>,
126 #[xml(child = "w:vertAlign")]
128 pub vertical_align: Option<VertAlign>,
129 #[xml(child = "w:rtl")]
131 pub rtl: Option<RightToLeftText>,
132 #[xml(child = "w:cs")]
134 pub complex_script: Option<ComplexScript>,
135 #[xml(child = "w:em")]
137 pub emphasis: Option<Emphasis>,
138 #[xml(child = "w:lang")]
140 pub lang: Option<Lang<'a>>,
141 #[xml(child = "w:eastAsianLayout")]
143 pub east_asian_layout: Option<EastAsianLayout>,
144 #[xml(child = "w:specVanish")]
146 pub spec_vanish: Option<SpecVanish>,
147 #[xml(child = "w:oMath")]
149 pub o_math: Option<OMath>,
150}
151
152impl<'a> CharacterProperty<'a> {
153 __setter!(style_id: Option<CharacterStyleId<'a>>);
154 __setter!(color: Option<Color<'a>>);
155 __setter!(bold: Option<Bold>);
156 __setter!(dstrike: Option<Dstrike>);
157 __setter!(italics: Option<Italics>);
158 __setter!(outline: Option<Outline>);
159 __setter!(strike: Option<Strike>);
160 __setter!(size: Option<Size>);
161 __setter!(underline: Option<Underline<'a>>);
162 __setter!(fonts: Option<Fonts>);
163}
164
165#[derive(Debug, XmlRead, XmlWrite, Clone)]
166#[cfg_attr(test, derive(PartialEq))]
167#[xml(tag = "w:rStyle")]
168pub struct CharacterStyleId<'a> {
169 #[xml(attr = "w:val")]
170 pub value: Cow<'a, str>,
171}
172
173impl<'a, T: Into<Cow<'a, str>>> From<T> for CharacterStyleId<'a> {
174 fn from(val: T) -> Self {
175 CharacterStyleId { value: val.into() }
176 }
177}
178
179#[derive(Debug, Default, XmlRead, XmlWrite, Clone)]
180#[cfg_attr(test, derive(PartialEq))]
181#[xml(tag = "w:shadow")]
182pub struct Shadow {
183 #[xml(attr = "w:val")]
184 pub value: Option<bool>,
185}
186
187#[derive(Debug, Default, XmlRead, XmlWrite, Clone)]
188#[cfg_attr(test, derive(PartialEq))]
189#[xml(tag = "w:emboss")]
190pub struct Emboss {
191 #[xml(attr = "w:val")]
192 pub value: Option<bool>,
193}
194
195#[derive(Debug, Default, XmlRead, XmlWrite, Clone)]
196#[cfg_attr(test, derive(PartialEq))]
197#[xml(tag = "w:imprint")]
198pub struct Imprint {
199 #[xml(attr = "w:val")]
200 pub value: Option<bool>,
201}
202
203#[derive(Debug, Default, XmlRead, XmlWrite, Clone)]
204#[cfg_attr(test, derive(PartialEq))]
205#[xml(tag = "w:noProof")]
206pub struct NoProof {
207 #[xml(attr = "w:val")]
208 pub value: Option<bool>,
209}
210
211#[derive(Debug, Default, XmlRead, XmlWrite, Clone)]
220#[cfg_attr(test, derive(PartialEq))]
221#[xml(tag = "w:vanish")]
222pub struct Vanish {
223 #[xml(attr = "w:val")]
224 pub value: Option<bool>,
225}
226
227#[derive(Debug, Default, XmlRead, XmlWrite, Clone)]
228#[cfg_attr(test, derive(PartialEq))]
229#[xml(tag = "w:webHidden")]
230pub struct WebHidden {
231 #[xml(attr = "w:val")]
232 pub value: Option<bool>,
233}
234
235#[derive(Debug, Default, XmlRead, XmlWrite, Clone)]
236#[cfg_attr(test, derive(PartialEq))]
237#[xml(tag = "w:rtl")]
238pub struct RightToLeftText {
239 #[xml(attr = "w:val")]
240 pub value: Option<bool>,
241}
242
243#[derive(Debug, Default, XmlRead, XmlWrite, Clone)]
244#[cfg_attr(test, derive(PartialEq))]
245#[xml(tag = "w:cs")]
246pub struct ComplexScript {
247 #[xml(attr = "w:val")]
248 pub value: Option<bool>,
249}
250
251#[derive(Debug, Default, XmlRead, XmlWrite, Clone)]
252#[cfg_attr(test, derive(PartialEq))]
253#[xml(tag = "w:specVanish")]
254pub struct SpecVanish {
255 #[xml(attr = "w:val")]
256 pub value: Option<bool>,
257}
258
259#[derive(Debug, Default, XmlRead, XmlWrite, Clone)]
260#[cfg_attr(test, derive(PartialEq))]
261#[xml(tag = "w:oMath")]
262pub struct OMath {
263 #[xml(attr = "w:val")]
264 pub value: Option<bool>,
265}
266
267#[derive(Debug, Default, XmlRead, XmlWrite, Clone)]
269#[cfg_attr(test, derive(PartialEq))]
270#[xml(tag = "w:spacing")]
271pub struct TextSpacing {
272 #[xml(attr = "w:val")]
273 pub value: Option<isize>,
274}
275
276#[derive(Debug, Default, XmlRead, XmlWrite, Clone)]
278#[cfg_attr(test, derive(PartialEq))]
279#[xml(tag = "w:w")]
280pub struct Scale {
281 #[xml(attr = "w:val")]
282 pub value: Option<u16>,
283}
284
285#[derive(Debug, Default, XmlRead, XmlWrite, Clone)]
287#[cfg_attr(test, derive(PartialEq))]
288#[xml(tag = "w:szCs")]
289pub struct SizeComplex {
290 #[xml(attr = "w:val")]
291 pub value: Option<isize>,
292}
293
294#[derive(Debug, Default, XmlRead, XmlWrite, Clone)]
296#[cfg_attr(test, derive(PartialEq))]
297#[xml(tag = "w:kern")]
298pub struct Kern {
299 #[xml(attr = "w:val")]
300 pub value: Option<isize>,
301}
302
303#[derive(Debug, Default, XmlRead, XmlWrite, Clone)]
304#[cfg_attr(test, derive(PartialEq))]
305#[xml(tag = "w:effect")]
306pub struct Effect {
307 #[xml(attr = "w:val")]
308 pub value: Option<EffectType>,
309}
310
311#[derive(Debug, Clone, Default)]
312#[cfg_attr(test, derive(PartialEq))]
313pub enum EffectType {
314 BlinkBackground, Lights, AntsBlack, AntsRed, Shimmer, Sparkle, #[default]
321 None, }
323
324__string_enum! {
325 EffectType {
326 BlinkBackground = "blinkBackground",
327 Lights = "lights",
328 AntsBlack = "antsBlack",
329 AntsRed = "antsRed",
330 Shimmer = "shimmer",
331 Sparkle = "sparkle",
332 None = "none",
333 }
334}
335
336#[derive(Debug, Default, XmlRead, XmlWrite, Clone)]
337#[cfg_attr(test, derive(PartialEq))]
338#[xml(tag = "w:eastAsianLayout")]
339pub struct EastAsianLayout {
340 #[xml(attr = "w:id")]
341 pub id: Option<isize>,
342 #[xml(attr = "w:combine")]
343 pub combine: Option<bool>,
344 #[xml(attr = "w:combineBrackets")]
345 pub combine_brackets: Option<CombineBracketsType>,
346 #[xml(attr = "w:vert")]
347 pub vert: Option<bool>,
348 #[xml(attr = "w:vertCompress")]
349 pub vert_compress: Option<bool>,
350}
351
352#[derive(Debug, Clone, Default)]
353#[cfg_attr(test, derive(PartialEq))]
354pub enum CombineBracketsType {
355 #[default]
356 None, Round, Square, Angle, Curly, }
362
363__string_enum! {
364 CombineBracketsType {
365 None = "none",
366 Round = "round",
367 Square = "square",
368 Angle = "angle",
369 Curly = "curly",
370 }
371}
372
373#[derive(Debug, Default, XmlRead, XmlWrite, Clone)]
374#[cfg_attr(test, derive(PartialEq))]
375#[xml(tag = "w:fitText")]
376pub struct FitText {
377 #[xml(attr = "w:val")]
379 pub value: Option<isize>,
380 #[xml(attr = "w:id")]
381 pub id: Option<isize>,
382}
383
384#[derive(Debug, Default, XmlRead, XmlWrite, Clone)]
385#[cfg_attr(test, derive(PartialEq))]
386#[xml(tag = "w:bdr")]
387pub struct TextBorder<'a> {
388 #[xml(attr = "w:val")]
389 pub style: super::BorderStyle,
390 #[xml(attr = "w:color")]
391 pub color: Option<Cow<'a, str>>,
392 #[xml(attr = "w:themeColor")]
393 pub theme_color: Option<ThemeColor>,
394 #[xml(attr = "w:themeTint")]
395 pub theme_tint: Option<Cow<'a, str>>,
396 #[xml(attr = "w:themeShade")]
397 pub theme_shade: Option<Cow<'a, str>>,
398 #[xml(attr = "w:sz")]
399 pub size: Option<isize>, #[xml(attr = "w:space")]
401 pub space: Option<isize>,
402 #[xml(attr = "w:shadow")]
403 pub shadow: Option<bool>,
404 #[xml(attr = "w:frame")]
405 pub frame: Option<bool>,
406}
407
408#[derive(Debug, Clone, Default)]
409#[cfg_attr(test, derive(PartialEq))]
410pub enum ThemeColor {
411 #[default]
412 Dark1, Light1, Dark2, Light2, Accent1, Accent2, Accent3, Accent4, Accent5, Accent6, Hyperlink, FollowedHyperlink, None, Background1, Text1, Background2, Text2, }
430
431__string_enum! {
432 ThemeColor {
433 Dark1 = "dark1",
434 Light1 = "light1",
435 Dark2 = "dark2",
436 Light2 = "light2",
437 Accent1 = "accent1",
438 Accent2 = "accent2",
439 Accent3 = "accent3",
440 Accent4 = "accent4",
441 Accent5 = "accent5",
442 Accent6 = "accent6",
443 Hyperlink = "hyperlink",
444 FollowedHyperlink = "followedHyperlink",
445 None = "none",
446 Background1 = "background1",
447 Text1 = "text1",
448 Background2 = "background2",
449 Text2 = "text2",
450 }
451}
452
453#[derive(Debug, Default, XmlRead, XmlWrite, Clone)]
454#[cfg_attr(test, derive(PartialEq))]
455#[xml(tag = "w:shd")]
456pub struct Shading<'a> {
457 #[xml(attr = "w:val")]
458 pub style: Option<ShadingStyle>,
459 #[xml(attr = "w:color")]
460 pub color: Option<Cow<'a, str>>,
461 #[xml(attr = "w:themeColor")]
462 pub theme_color: Option<ThemeColor>,
463 #[xml(attr = "w:themeTint")]
464 pub theme_tint: Option<Cow<'a, str>>,
465 #[xml(attr = "w:themeShade")]
466 pub theme_shade: Option<Cow<'a, str>>,
467 #[xml(attr = "w:fill")]
468 pub fill: Option<Cow<'a, str>>,
469 #[xml(attr = "w:themeFill")]
470 pub theme_fill: Option<ThemeColor>,
471 #[xml(attr = "w:themeFillTint")]
472 pub theme_fill_tint: Option<Cow<'a, str>>,
473 #[xml(attr = "w:themeFillShade")]
474 pub theme_fill_shade: Option<Cow<'a, str>>,
475}
476
477#[derive(Debug, Default, XmlRead, XmlWrite, Clone)]
478#[cfg_attr(test, derive(PartialEq))]
479#[xml(tag = "w:em")]
480pub struct Emphasis {
481 #[xml(attr = "w:val")]
482 pub value: Option<EmphasisType>,
483}
484
485#[derive(Debug, Default, Clone)]
486#[cfg_attr(test, derive(PartialEq))]
487pub enum ShadingStyle {
488 #[default]
489 Nil, Clear, Solid, HorzStripe, VertStripe, ReverseDiagStripe, DiagStripe, HorzCross, DiagCross, ThinHorzStripe, ThinVertStripe, ThinReverseDiagStripe, ThinDiagStripe, ThinHorzCross, ThinDiagCross, Pct5, Pct10, Pct12, Pct15, Pct20, Pct25, Pct30, Pct35, Pct37, Pct40, Pct45, Pct50, Pct55, Pct60, Pct62, Pct65, Pct70, Pct75, Pct80, Pct85, Pct87, Pct90, Pct95, }
528
529__string_enum! {
530 ShadingStyle {
531 Nil = "nil",
532 Clear = "clear",
533 Solid = "solid",
534 HorzStripe = "horzStripe",
535 VertStripe = "vertStripe",
536 ReverseDiagStripe = "reverseDiagStripe",
537 DiagStripe = "diagStripe",
538 HorzCross = "horzCross",
539 DiagCross = "diagCross",
540 ThinHorzStripe = "thinHorzStripe",
541 ThinVertStripe = "thinVertStripe",
542 ThinReverseDiagStripe = "thinReverseDiagStripe",
543 ThinDiagStripe = "thinDiagStripe",
544 ThinHorzCross = "thinHorzCross",
545 ThinDiagCross = "thinDiagCross",
546 Pct5 = "pct5",
547 Pct10 = "pct10",
548 Pct12 = "pct12",
549 Pct15 = "pct15",
550 Pct20 = "pct20",
551 Pct25 = "pct25",
552 Pct30 = "pct30",
553 Pct35 = "pct35",
554 Pct37 = "pct37",
555 Pct40 = "pct40",
556 Pct45 = "pct45",
557 Pct50 = "pct50",
558 Pct55 = "pct55",
559 Pct60 = "pct60",
560 Pct62 = "pct62",
561 Pct65 = "pct65",
562 Pct70 = "pct70",
563 Pct75 = "pct75",
564 Pct80 = "pct80",
565 Pct85 = "pct85",
566 Pct87 = "pct87",
567 Pct90 = "pct90",
568 Pct95 = "pct95",
569 }
570}
571
572#[derive(Debug, Default, Clone)]
573#[cfg_attr(test, derive(PartialEq))]
574pub enum EmphasisType {
575 #[default]
576 None, Dot, Comma, Circle, UnderDot, }
582
583__string_enum! {
584 EmphasisType {
585 None = "none",
586 Dot = "dot",
587 Comma = "comma",
588 Circle = "circle",
589 UnderDot = "underdot",
590 }
591}
592
593__xml_test_suites!(
594 CharacterProperty,
595 CharacterProperty::default(),
596 r#"<w:rPr/>"#,
597 CharacterProperty::default().style_id("id"),
598 r#"<w:rPr><w:rStyle w:val="id"/></w:rPr>"#,
599 CharacterProperty::default().color("00ff00"),
600 r#"<w:rPr><w:color w:val="00ff00"/></w:rPr>"#,
601 CharacterProperty::default().size(42isize),
602 r#"<w:rPr><w:sz w:val="42"/></w:rPr>"#,
603 CharacterProperty::default().bold(true),
604 r#"<w:rPr><w:b w:val="true"/></w:rPr>"#,
605 CharacterProperty::default().italics(false),
606 r#"<w:rPr><w:i w:val="false"/></w:rPr>"#,
607 CharacterProperty::default().outline(true),
608 r#"<w:rPr><w:outline w:val="true"/></w:rPr>"#,
609 CharacterProperty::default().strike(false),
610 r#"<w:rPr><w:strike w:val="false"/></w:rPr>"#,
611 CharacterProperty::default().dstrike(true),
612 r#"<w:rPr><w:dstrike w:val="true"/></w:rPr>"#,
613 CharacterProperty::default().underline(Underline::default()),
614 r#"<w:rPr><w:u/></w:rPr>"#,
615 CharacterProperty::default().fonts(Fonts::default().east_asia("宋体")),
616 r#"<w:rPr><w:rFonts w:eastAsia="宋体"/></w:rPr>"#,
617);