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