typst_library/text/
case.rs

1use crate::foundations::{cast, func, Cast, Content, Str};
2use crate::text::TextElem;
3
4/// Converts a string or content to lowercase.
5///
6/// # Example
7/// ```example
8/// #lower("ABC") \
9/// #lower[*My Text*] \
10/// #lower[already low]
11/// ```
12#[func(title = "Lowercase")]
13pub fn lower(
14    /// The text to convert to lowercase.
15    text: Caseable,
16) -> Caseable {
17    case(text, Case::Lower)
18}
19
20/// Converts a string or content to uppercase.
21///
22/// # Example
23/// ```example
24/// #upper("abc") \
25/// #upper[*my text*] \
26/// #upper[ALREADY HIGH]
27/// ```
28#[func(title = "Uppercase")]
29pub fn upper(
30    /// The text to convert to uppercase.
31    text: Caseable,
32) -> Caseable {
33    case(text, Case::Upper)
34}
35
36/// Change the case of text.
37fn case(text: Caseable, case: Case) -> Caseable {
38    match text {
39        Caseable::Str(v) => Caseable::Str(case.apply(&v).into()),
40        Caseable::Content(v) => {
41            Caseable::Content(v.styled(TextElem::set_case(Some(case))))
42        }
43    }
44}
45
46/// A value whose case can be changed.
47pub enum Caseable {
48    Str(Str),
49    Content(Content),
50}
51
52cast! {
53    Caseable,
54    self => match self {
55        Self::Str(v) => v.into_value(),
56        Self::Content(v) => v.into_value(),
57    },
58    v: Str => Self::Str(v),
59    v: Content => Self::Content(v),
60}
61
62/// A case transformation on text.
63#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash, Cast)]
64pub enum Case {
65    /// Everything is lowercased.
66    Lower,
67    /// Everything is uppercased.
68    Upper,
69}
70
71impl Case {
72    /// Apply the case to a string.
73    pub fn apply(self, text: &str) -> String {
74        match self {
75            Self::Lower => text.to_lowercase(),
76            Self::Upper => text.to_uppercase(),
77        }
78    }
79}