sauron_core/html/
units.rs

1//! provides function and macro for html units such as px, %, em, etc.
2
3use crate::vdom::Value;
4pub use fns::{rgb, rgba, rotate};
5
6mod fns;
7
8#[inline]
9fn unit(unit_name: &str, v: impl Into<Value>) -> String {
10    let value: Value = v.into();
11    match value {
12        Value::Vec(values) => values
13            .into_iter()
14            .map(|v| format!("{}{}", Into::<Value>::into(v), unit_name))
15            .collect::<Vec<_>>()
16            .join(" "),
17        _ => {
18            format!("{}{}", value, unit_name)
19        }
20    }
21}
22
23macro_rules! declare_units{
24    (  $(
25            $(#[$attr:meta])*
26            $name:ident;
27        )*
28    ) => {
29        $(
30            $(#[$attr])*
31            ///
32            /// [MDN reference](https://developer.mozilla.org/en-US/docs/Learn/CSS/Building_blocks/Values_and_units)
33            pub fn $name(v: impl Into<Value>) -> String {
34                unit(stringify!($name), v)
35            }
36        )*
37    };
38    (
39        $(
40            $(#[$attr:meta])*
41            $name:ident => $unit:tt;
42         )*
43    ) => {
44        $(
45            $(#[$attr])*
46            ///
47            /// [MDN reference](https://developer.mozilla.org/en-US/docs/Learn/CSS/Building_blocks/Values_and_units)
48            pub fn $name(v: impl Into<Value>) -> String {
49                  unit($unit, v)
50            }
51        )*
52    }
53}
54
55declare_units! {
56
57    /// pixels (1px = 1/96th of 1in)
58    ///
59    /// a helper function which append `px` into a value
60    ///
61    /// Example:
62    /// ```rust
63    /// use sauron::html::units::*;
64    ///
65    /// assert_eq!("10px", px(10));
66    /// ```
67    px;
68    /// 1q is equivalent to 1/40th of 1cm.
69    ///
70    /// Example:
71    /// ```rust
72    /// use sauron::html::units::*;
73    ///
74    /// assert_eq!("10q", q(10));
75    /// ```
76    q;
77    /// milimeters
78    ///
79    /// Example:
80    /// ```rust
81    /// use sauron::html::units::*;
82    ///
83    /// assert_eq!("10mm", mm(10));
84    /// ```
85    mm;
86    /// centimeters
87    ///
88    /// Example:
89    /// ```rust
90    /// use sauron::html::units::*;
91    ///
92    /// assert_eq!("10cm", cm(10));
93    /// ```
94    cm;
95    /// points (1pt = 1/72 of 1in)
96    ///
97    /// Example:
98    /// ```rust
99    /// use sauron::html::units::*;
100    ///
101    /// assert_eq!("10pt", pt(10));
102    /// ```
103    pt;
104    /// picas (1pc = 12 pt)
105    ///
106    /// Example:
107    /// ```rust
108    /// use sauron::html::units::*;
109    ///
110    /// assert_eq!("10pc", pc(10));
111    /// ```
112    pc;
113    /// Relative to the font-size of the element (2em means 2 times the size of the current font)
114    ///
115    /// Example:
116    /// ```rust
117    /// use sauron::html::units::*;
118    ///
119    /// assert_eq!("10em", em(10));
120    /// ```
121    em;
122    /// Relative to the x-height of the current font (rarely used)
123    ///
124    /// Example:
125    /// ```rust
126    /// use sauron::html::units::*;
127    ///
128    /// assert_eq!("10ex", ex(10));
129    /// ```
130    ex;
131    /// Relative to the width of the "0" (zero)
132    ///
133    /// Example:
134    /// ```rust
135    /// use sauron::html::units::*;
136    ///
137    /// assert_eq!("10ch", ch(10));
138    /// ```
139    ch;
140    /// Relative to font-size of the root element
141    ///
142    /// Example:
143    /// ```rust
144    /// use sauron::html::units::*;
145    ///
146    /// assert_eq!("10rem", rem(10));
147    /// ```
148    rem;
149    /// Relative to 1% of the width of the viewport*
150    ///
151    /// Example:
152    /// ```rust
153    /// use sauron::html::units::*;
154    ///
155    /// assert_eq!("10vw", vw(10));
156    /// ```
157    vw;
158    /// Relative to 1% of the height of the viewport*
159    ///
160    /// Example:
161    /// ```rust
162    /// use sauron::html::units::*;
163    ///
164    /// assert_eq!("10vh", vh(10));
165    /// ```
166    vh;
167}
168
169declare_units! {
170    /// inches (1in = 96px = 2.54cm)
171    /// Example:
172    /// ```rust
173    /// use sauron::html::units::*;
174    ///
175    /// assert_eq!("10in", r#in(10))
176    /// ```
177    r#in => "in";
178    /// percentage
179    /// Example:
180    /// ```rust
181    /// use sauron::html::units::*;
182    ///
183    /// assert_eq!("10%", percent(10))
184    /// ```
185    percent => "%";
186}
187
188// angle units
189declare_units! {
190    /// Represent an angle in degrees
191    /// https://developer.mozilla.org/en-US/docs/Web/CSS/angle
192    deg;
193    /// Represent an angle in radians
194    /// https://developer.mozilla.org/en-US/docs/Web/CSS/angle
195    rad;
196    /// Represents an angle in gradians
197    /// https://developer.mozilla.org/en-US/docs/Web/CSS/angle
198    grad;
199    /// Represents an angle in a number of turns. One full circle is 1turn.
200    /// https://developer.mozilla.org/en-US/docs/Web/CSS/angle
201    turn;
202}
203
204// time units
205declare_units! {
206   /// Represents a time in seconds.
207   /// https://developer.mozilla.org/en-US/docs/Web/CSS/time
208   s;
209   /// Represents a time in milliseconds.
210   /// https://developer.mozilla.org/en-US/docs/Web/CSS/time
211   ms;
212}
213
214#[cfg(test)]
215mod tests {
216    use super::*;
217
218    #[test]
219    fn test_units() {
220        assert_eq!(px(1), "1px");
221        assert_eq!(mm(1), "1mm");
222        assert_eq!(cm(2), "2cm");
223        assert_eq!(pt(5), "5pt");
224        assert_eq!(pc(5), "5pc");
225        assert_eq!(r#in(2.5), "2.5in");
226        assert_eq!(ch(1), "1ch");
227    }
228}