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}