typst_library/text/
case.rs

1use crate::foundations::{Cast, Content, Str, cast, func};
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) => Caseable::Content(v.set(TextElem::case, Some(case))),
41    }
42}
43
44/// A value whose case can be changed.
45pub enum Caseable {
46    Str(Str),
47    Content(Content),
48}
49
50cast! {
51    Caseable,
52    self => match self {
53        Self::Str(v) => v.into_value(),
54        Self::Content(v) => v.into_value(),
55    },
56    v: Str => Self::Str(v),
57    v: Content => Self::Content(v),
58}
59
60/// A case transformation on text.
61#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash, Cast)]
62pub enum Case {
63    /// Everything is lowercased.
64    Lower,
65    /// Everything is uppercased.
66    Upper,
67}
68
69impl Case {
70    /// Apply the case to a string.
71    pub fn apply(self, text: &str) -> String {
72        match self {
73            Self::Lower => text.to_lowercase(),
74            Self::Upper => text.to_uppercase(),
75        }
76    }
77}