encre_css/plugins/typography/
mod.rs

1//! Typography utilities
2pub mod content;
3pub mod font_family;
4pub mod font_size;
5pub mod font_smoothing;
6pub mod font_style;
7pub mod font_variant_numeric;
8pub mod font_weight;
9pub mod letter_spacing;
10pub mod line_clamp;
11pub mod line_height;
12pub mod list_style_position;
13pub mod list_style_type;
14pub mod text_align;
15pub mod text_color;
16pub mod text_decoration;
17pub mod text_decoration_color;
18pub mod text_decoration_style;
19pub mod text_decoration_thickness;
20pub mod text_indent;
21pub mod text_overflow;
22pub mod text_transform;
23pub mod text_underline_offset;
24pub mod vertical_align;
25pub mod whitespace;
26pub mod text_wrap;
27pub mod word_break;
28
29#[cfg(test)]
30mod tests {
31    use crate::{generate, utils::testing::base_config};
32
33    use pretty_assertions::assert_eq;
34
35    #[test]
36    fn content() {
37        assert_eq!(
38            generate(["before:content-none"], &base_config()),
39            r".before\:content-none::before {
40  --en-content: none;
41  content: var(--en-content);
42}"
43        );
44        assert_eq!(
45            generate(["before:content-['1234_some_words']"], &base_config()),
46            r".before\:content-\[\'1234_some_words\'\]::before {
47  --en-content: '1234 some words';
48  content: var(--en-content);
49}"
50        );
51        assert_eq!(
52            generate(["before:content-[&#39;:-><-:&#39;]"], &base_config()),
53            r".before\:content-\[\'\:-\>\<-\:\'\]::before {
54  --en-content: ':-><-:';
55  content: var(--en-content);
56}"
57        );
58        assert_eq!(
59            generate(["before:content-[&#39;&#91;inside&#93;&#39;]"], &base_config()),
60            r".before\:content-\[\'\[inside\]\'\]::before {
61  --en-content: '[inside]';
62  content: var(--en-content);
63}"
64        );
65    }
66
67    #[test]
68    fn font_family() {
69        assert_eq!(
70            generate(["font-mono"], &base_config()),
71            r#".font-mono {
72  font-family: Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace;
73}"#
74        );
75        assert_eq!(
76            generate(["font-[&#39;Open_Sans&#39;,Roboto,sans-serif]"], &base_config()),
77            r".font-\[\'Open_Sans\'\,Roboto\,sans-serif\] {
78  font-family: 'Open Sans',Roboto,sans-serif;
79}"
80        );
81        assert_eq!(
82            generate(["font-[\u{fb17}\u{fb17}]"], &base_config()),
83            ".font-\\[\u{fb17}\u{fb17}\\] {
84  font-family: \u{fb17}\u{fb17};
85}"
86        );
87    }
88
89    #[test]
90    #[allow(clippy::too_many_lines)]
91    fn font_size() {
92        assert_eq!(
93            generate(["text-xs"], &base_config()),
94            ".text-xs {
95  font-size: 0.75rem;
96  line-height: 1rem;
97}"
98        );
99        assert_eq!(
100            generate(["text-sm"], &base_config()),
101            ".text-sm {
102  font-size: 0.875rem;
103  line-height: 1.25rem;
104}"
105        );
106        assert_eq!(
107            generate(["text-base"], &base_config()),
108            ".text-base {
109  font-size: 1rem;
110  line-height: 1.5rem;
111}"
112        );
113        assert_eq!(
114            generate(["text-lg"], &base_config()),
115            ".text-lg {
116  font-size: 1.125rem;
117  line-height: 1.75rem;
118}"
119        );
120        assert_eq!(
121            generate(["text-xl"], &base_config()),
122            ".text-xl {
123  font-size: 1.25rem;
124  line-height: 1.75rem;
125}"
126        );
127        assert_eq!(
128            generate(["text-2xl"], &base_config()),
129            ".text-2xl {
130  font-size: 1.5rem;
131  line-height: 2rem;
132}"
133        );
134        assert_eq!(
135            generate(["text-3xl"], &base_config()),
136            ".text-3xl {
137  font-size: 1.875rem;
138  line-height: 2.25rem;
139}"
140        );
141        assert_eq!(
142            generate(["text-4xl"], &base_config()),
143            ".text-4xl {
144  font-size: 2.25rem;
145  line-height: 2.5rem;
146}"
147        );
148        assert_eq!(
149            generate(["text-5xl"], &base_config()),
150            ".text-5xl {
151  font-size: 3rem;
152  line-height: 1;
153}"
154        );
155        assert_eq!(
156            generate(["text-6xl"], &base_config()),
157            ".text-6xl {
158  font-size: 3.75rem;
159  line-height: 1;
160}"
161        );
162        assert_eq!(
163            generate(["text-7xl"], &base_config()),
164            ".text-7xl {
165  font-size: 4.5rem;
166  line-height: 1;
167}"
168        );
169        assert_eq!(
170            generate(["text-8xl"], &base_config()),
171            ".text-8xl {
172  font-size: 6rem;
173  line-height: 1;
174}"
175        );
176        assert_eq!(
177            generate(["text-9xl"], &base_config()),
178            ".text-9xl {
179  font-size: 8rem;
180  line-height: 1;
181}"
182        );
183        assert_eq!(
184            generate(["text-[18px]"], &base_config()),
185            r".text-\[18px\] {
186  font-size: 18px;
187}"
188        );
189        assert_eq!(
190            generate(["text-[10%]"], &base_config()),
191            r".text-\[10\%\] {
192  font-size: 10%;
193}"
194        );
195        assert_eq!(
196            generate(["text-[x-large]"], &base_config()),
197            r".text-\[x-large\] {
198  font-size: x-large;
199}"
200        );
201        assert_eq!(
202            generate(["text-[smaller]"], &base_config()),
203            r".text-\[smaller\] {
204  font-size: smaller;
205}"
206        );
207    }
208
209    #[test]
210    fn font_smoothing() {
211        assert_eq!(
212            generate(["antialised"], &base_config()),
213            ".antialised {
214  -webkit-font-smoothing: antialiased;
215  -moz-osx-font-smoothing: grayscale;
216}"
217        );
218        assert_eq!(
219            generate(["subpixel-antialised"], &base_config()),
220            ".subpixel-antialised {
221  -webkit-font-smoothing: auto;
222  -moz-osx-font-smoothing: auto;
223}"
224        );
225    }
226
227    #[test]
228    fn font_style() {
229        assert_eq!(
230            generate(["italic"], &base_config()),
231            ".italic {
232  font-style: italic;
233}"
234        );
235        assert_eq!(
236            generate(["not-italic"], &base_config()),
237            ".not-italic {
238  font-style: normal;
239}"
240        );
241    }
242
243    #[test]
244    fn font_variant_numeric() {
245        assert_eq!(
246            generate(["normal-nums"], &base_config()),
247            ".normal-nums {
248  font-variant-numeric: normal;
249}"
250        );
251        assert_eq!(
252            generate(["ordinal"], &base_config()),
253            ".ordinal {
254  --en-ordinal: ordinal;
255  font-variant-numeric: var(--en-ordinal) var(--en-slashed-zero) var(--en-numeric-figure) var(--en-numeric-spacing) var(--en-numeric-fraction);
256}"
257        );
258        assert_eq!(
259            generate(["slashed-zero"], &base_config()),
260            ".slashed-zero {
261  --en-slashed-zero: slashed-zero;
262  font-variant-numeric: var(--en-ordinal) var(--en-slashed-zero) var(--en-numeric-figure) var(--en-numeric-spacing) var(--en-numeric-fraction);
263}"
264        );
265        assert_eq!(
266            generate(["lining-nums"], &base_config()),
267            ".lining-nums {
268  --en-numeric-figure: lining-nums;
269  font-variant-numeric: var(--en-ordinal) var(--en-slashed-zero) var(--en-numeric-figure) var(--en-numeric-spacing) var(--en-numeric-fraction);
270}"
271        );
272        assert_eq!(
273            generate(["oldstyle-nums"], &base_config()),
274            ".oldstyle-nums {
275  --en-numeric-figure: oldstyle-nums;
276  font-variant-numeric: var(--en-ordinal) var(--en-slashed-zero) var(--en-numeric-figure) var(--en-numeric-spacing) var(--en-numeric-fraction);
277}"
278        );
279        assert_eq!(
280            generate(["proportional-nums"], &base_config()),
281            ".proportional-nums {
282  --en-numeric-spacing: proportional-nums;
283  font-variant-numeric: var(--en-ordinal) var(--en-slashed-zero) var(--en-numeric-figure) var(--en-numeric-spacing) var(--en-numeric-fraction);
284}"
285        );
286        assert_eq!(
287            generate(["tabular-nums"], &base_config()),
288            ".tabular-nums {
289  --en-numeric-spacing: tabular-nums;
290  font-variant-numeric: var(--en-ordinal) var(--en-slashed-zero) var(--en-numeric-figure) var(--en-numeric-spacing) var(--en-numeric-fraction);
291}"
292        );
293        assert_eq!(
294            generate(["diagonal-fractions"], &base_config()),
295            ".diagonal-fractions {
296  --en-numeric-fraction: diagonal-fractions;
297  font-variant-numeric: var(--en-ordinal) var(--en-slashed-zero) var(--en-numeric-figure) var(--en-numeric-spacing) var(--en-numeric-fraction);
298}"
299        );
300        assert_eq!(
301            generate(["stacked-fractions"], &base_config()),
302            ".stacked-fractions {
303  --en-numeric-fraction: stacked-fractions;
304  font-variant-numeric: var(--en-ordinal) var(--en-slashed-zero) var(--en-numeric-figure) var(--en-numeric-spacing) var(--en-numeric-fraction);
305}"
306        );
307    }
308
309    #[test]
310    fn font_weight() {
311        assert_eq!(
312            generate(["font-thin"], &base_config()),
313            ".font-thin {
314  font-weight: 100;
315}"
316        );
317        assert_eq!(
318            generate(["font-extralight"], &base_config()),
319            ".font-extralight {
320  font-weight: 200;
321}"
322        );
323        assert_eq!(
324            generate(["font-light"], &base_config()),
325            ".font-light {
326  font-weight: 300;
327}"
328        );
329        assert_eq!(
330            generate(["font-normal"], &base_config()),
331            ".font-normal {
332  font-weight: 400;
333}"
334        );
335        assert_eq!(
336            generate(["font-medium"], &base_config()),
337            ".font-medium {
338  font-weight: 500;
339}"
340        );
341        assert_eq!(
342            generate(["font-semibold"], &base_config()),
343            ".font-semibold {
344  font-weight: 600;
345}"
346        );
347        assert_eq!(
348            generate(["font-bold"], &base_config()),
349            ".font-bold {
350  font-weight: 700;
351}"
352        );
353        assert_eq!(
354            generate(["font-extrabold"], &base_config()),
355            ".font-extrabold {
356  font-weight: 800;
357}"
358        );
359        assert_eq!(
360            generate(["font-black"], &base_config()),
361            ".font-black {
362  font-weight: 900;
363}"
364        );
365        assert_eq!(
366            generate(["font-[50]"], &base_config()),
367            r".font-\[50\] {
368  font-weight: 50;
369}"
370        );
371    }
372
373    #[test]
374    fn letter_spacing() {
375        assert_eq!(
376            generate(["tracking-tighter"], &base_config()),
377            ".tracking-tighter {
378  letter-spacing: -0.05em;
379}"
380        );
381        assert_eq!(
382            generate(["tracking-tight"], &base_config()),
383            ".tracking-tight {
384  letter-spacing: -0.025em;
385}"
386        );
387        assert_eq!(
388            generate(["tracking-normal"], &base_config()),
389            ".tracking-normal {
390  letter-spacing: 0;
391}"
392        );
393        assert_eq!(
394            generate(["tracking-wide"], &base_config()),
395            ".tracking-wide {
396  letter-spacing: 0.025em;
397}"
398        );
399        assert_eq!(
400            generate(["tracking-wider"], &base_config()),
401            ".tracking-wider {
402  letter-spacing: 0.05em;
403}"
404        );
405        assert_eq!(
406            generate(["tracking-widest"], &base_config()),
407            ".tracking-widest {
408  letter-spacing: 0.1em;
409}"
410        );
411        assert_eq!(
412            generate(["tracking-[10px]"], &base_config()),
413            r".tracking-\[10px\] {
414  letter-spacing: 10px;
415}"
416        );
417    }
418
419    #[test]
420    fn line_clamp() {
421        assert_eq!(
422            generate(["line-clamp-none"], &base_config()),
423            ".line-clamp-none {
424  -webkit-line-clamp: unset;
425}"
426        );
427        assert_eq!(
428            generate(["line-clamp-12"], &base_config()),
429            ".line-clamp-12 {
430  overflow: hidden;
431  display: -webkit-box;
432  -webkit-box-orient: vertical;
433  -webkit-line-clamp: 12;
434}"
435        );
436    }
437
438    #[test]
439    fn line_height() {
440        assert_eq!(
441            generate(["leading-none"], &base_config()),
442            ".leading-none {
443  line-height: 1;
444}"
445        );
446        assert_eq!(
447            generate(["leading-tight"], &base_config()),
448            ".leading-tight {
449  line-height: 1.25;
450}"
451        );
452        assert_eq!(
453            generate(["leading-snug"], &base_config()),
454            ".leading-snug {
455  line-height: 1.375;
456}"
457        );
458        assert_eq!(
459            generate(["leading-normal"], &base_config()),
460            ".leading-normal {
461  line-height: 1.5;
462}"
463        );
464        assert_eq!(
465            generate(["leading-relaxed"], &base_config()),
466            ".leading-relaxed {
467  line-height: 1.625;
468}"
469        );
470        assert_eq!(
471            generate(["leading-loose"], &base_config()),
472            ".leading-loose {
473  line-height: 2;
474}"
475        );
476        assert_eq!(
477            generate(["leading-4"], &base_config()),
478            ".leading-4 {
479  line-height: 1rem;
480}"
481        );
482        assert_eq!(
483            generate(["-leading-4"], &base_config()),
484            ".-leading-4 {
485  line-height: -1rem;
486}"
487        );
488        assert_eq!(
489            generate(["leading-1/2"], &base_config()),
490            r".leading-1\/2 {
491  line-height: 50%;
492}"
493        );
494        assert_eq!(
495            generate(["leading-[8]"], &base_config()),
496            r".leading-\[8\] {
497  line-height: 8;
498}"
499        );
500        assert_eq!(
501            generate(["leading-[16px]"], &base_config()),
502            r".leading-\[16px\] {
503  line-height: 16px;
504}"
505        );
506        assert_eq!(
507            generate(["leading-[22%]"], &base_config()),
508            r".leading-\[22\%\] {
509  line-height: 22%;
510}"
511        );
512    }
513
514    #[test]
515    fn list_style_position() {
516        assert_eq!(
517            generate(["list-inside"], &base_config()),
518            ".list-inside {
519  list-style-position: inside;
520}"
521        );
522        assert_eq!(
523            generate(["list-outside"], &base_config()),
524            ".list-outside {
525  list-style-position: outside;
526}"
527        );
528    }
529
530    #[test]
531    fn list_style_type() {
532        assert_eq!(
533            generate(["list-disc"], &base_config()),
534            ".list-disc {
535  list-style-type: disc;
536}"
537        );
538        assert_eq!(
539            generate(["list-decimal"], &base_config()),
540            ".list-decimal {
541  list-style-type: decimal;
542}"
543        );
544        assert_eq!(
545            generate(["list-none"], &base_config()),
546            ".list-none {
547  list-style-type: none;
548}"
549        );
550        assert_eq!(
551            generate(["list-[greek]"], &base_config()),
552            r".list-\[greek\] {
553  list-style-type: greek;
554}"
555        );
556    }
557
558    #[test]
559    fn text_align() {
560        assert_eq!(
561            generate(["text-center"], &base_config()),
562            ".text-center {
563  text-align: center;
564}"
565        );
566        assert_eq!(
567            generate(["text-justify"], &base_config()),
568            ".text-justify {
569  text-align: justify;
570}"
571        );
572    }
573
574    #[test]
575    fn text_color() {
576        assert_eq!(
577            generate(["text-red-400"], &base_config()),
578            ".text-red-400 {
579  color: oklch(70.4% .191 22.216);
580}"
581        );
582        assert_eq!(
583            generate(["text-[rgb(12,12,12)]"], &base_config()),
584            r".text-\[rgb\(12\,12\,12\)\] {
585  color: rgb(12,12,12);
586}"
587        );
588        assert_eq!(
589            generate(["text-[purple]"], &base_config()),
590            r".text-\[purple\] {
591  color: purple;
592}"
593        );
594    }
595
596    #[test]
597    fn text_decoration() {
598        assert_eq!(
599            generate(["underline"], &base_config()),
600            ".underline {
601  -webkit-text-decoration-line: underline;
602  text-decoration-line: underline;
603}"
604        );
605        assert_eq!(
606            generate(["no-underline"], &base_config()),
607            ".no-underline {
608  -webkit-text-decoration-line: none;
609  text-decoration-line: none;
610}"
611        );
612    }
613
614    #[test]
615    fn text_decoration_color() {
616        assert_eq!(
617            generate(["decoration-red-400"], &base_config()),
618            ".decoration-red-400 {
619  -webkit-text-decoration-color: oklch(70.4% .191 22.216);
620  text-decoration-color: oklch(70.4% .191 22.216);
621}"
622        );
623        assert_eq!(
624            generate(["decoration-[rgb(12,12,12)]"], &base_config()),
625            r".decoration-\[rgb\(12\,12\,12\)\] {
626  -webkit-text-decoration-color: rgb(12,12,12);
627  text-decoration-color: rgb(12,12,12);
628}"
629        );
630        assert_eq!(
631            generate(["decoration-[purple]"], &base_config()),
632            r".decoration-\[purple\] {
633  -webkit-text-decoration-color: purple;
634  text-decoration-color: purple;
635}"
636        );
637    }
638
639    #[test]
640    fn text_decoration_style() {
641        assert_eq!(
642            generate(["decoration-wavy"], &base_config()),
643            ".decoration-wavy {
644  text-decoration-style: wavy;
645}"
646        );
647    }
648
649    #[test]
650    fn text_decoration_thickness() {
651        assert_eq!(
652            generate(["decoration-auto"], &base_config()),
653            ".decoration-auto {
654  text-decoration-thickness: auto;
655}"
656        );
657        assert_eq!(
658            generate(["decoration-from-font"], &base_config()),
659            ".decoration-from-font {
660  text-decoration-thickness: from-font;
661}"
662        );
663        assert_eq!(
664            generate(["decoration-12"], &base_config()),
665            ".decoration-12 {
666  text-decoration-thickness: 12px;
667}"
668        );
669        assert_eq!(
670            generate(["decoration-[4.2rem]"], &base_config()),
671            r".decoration-\[4\.2rem\] {
672  text-decoration-thickness: 4.2rem;
673}"
674        );
675        assert_eq!(
676            generate(["decoration-[2%]"], &base_config()),
677            r".decoration-\[2\%\] {
678  text-decoration-thickness: 2%;
679}"
680        );
681    }
682
683    #[test]
684    fn text_indent() {
685        assert_eq!(
686            generate(["indent-2"], &base_config()),
687            ".indent-2 {
688  text-indent: 0.5rem;
689}"
690        );
691        assert_eq!(
692            generate(["-indent-2"], &base_config()),
693            ".-indent-2 {
694  text-indent: -0.5rem;
695}"
696        );
697        assert_eq!(
698            generate(["indent-[20px]"], &base_config()),
699            r".indent-\[20px\] {
700  text-indent: 20px;
701}"
702        );
703    }
704
705    #[test]
706    fn text_overflow() {
707        assert_eq!(
708            generate(["truncate"], &base_config()),
709            ".truncate {
710  overflow: hidden;
711  text-overflow: ellipsis;
712  white-space: nowrap;
713}"
714        );
715        assert_eq!(
716            generate(["text-ellipsis"], &base_config()),
717            ".text-ellipsis {
718  text-overflow: ellipsis;
719}"
720        );
721        assert_eq!(
722            generate(["text-clip"], &base_config()),
723            ".text-clip {
724  text-overflow: clip;
725}"
726        );
727    }
728
729    #[test]
730    fn text_transform() {
731        assert_eq!(
732            generate(["normal-case"], &base_config()),
733            ".normal-case {
734  text-transform: none;
735}"
736        );
737        assert_eq!(
738            generate(["uppercase"], &base_config()),
739            ".uppercase {
740  text-transform: uppercase;
741}"
742        );
743    }
744
745    #[test]
746    fn text_underline_offset() {
747        assert_eq!(
748            generate(["underline-offset-auto"], &base_config()),
749            ".underline-offset-auto {
750  text-underline-offset: auto;
751}"
752        );
753        assert_eq!(
754            generate(["underline-offset-12"], &base_config()),
755            ".underline-offset-12 {
756  text-underline-offset: 12px;
757}"
758        );
759        assert_eq!(
760            generate(["underline-offset-[2rem]"], &base_config()),
761            r".underline-offset-\[2rem\] {
762  text-underline-offset: 2rem;
763}"
764        );
765        assert_eq!(
766            generate(["underline-offset-[10%]"], &base_config()),
767            r".underline-offset-\[10\%\] {
768  text-underline-offset: 10%;
769}"
770        );
771    }
772
773    #[test]
774    fn vertical_align() {
775        assert_eq!(
776            generate(["align-sub"], &base_config()),
777            ".align-sub {
778  vertical-align: sub;
779}"
780        );
781        assert_eq!(
782            generate(["align-text-top"], &base_config()),
783            ".align-text-top {
784  vertical-align: text-top;
785}"
786        );
787    }
788
789    #[test]
790    fn whitespace() {
791        assert_eq!(
792            generate(["whitespace-normal"], &base_config()),
793            ".whitespace-normal {
794  white-space: normal;
795}"
796        );
797        assert_eq!(
798            generate(["whitespace-pre-wrap"], &base_config()),
799            ".whitespace-pre-wrap {
800  white-space: pre-wrap;
801}"
802        );
803    }
804
805    #[test]
806    fn text_wrap() {
807        assert_eq!(
808            generate(["text-wrap"], &base_config()),
809            ".text-wrap {
810  text-wrap: wrap;
811}"
812        );
813        assert_eq!(
814            generate(["text-pretty"], &base_config()),
815            ".text-pretty {
816  text-wrap: pretty;
817}"
818        );
819    }
820
821    #[test]
822    fn word_break() {
823        assert_eq!(
824            generate(["break-normal"], &base_config()),
825            ".break-normal {
826  overflow-wrap: normal;
827  word-break: normal;
828}"
829        );
830        assert_eq!(
831            generate(["break-keep"], &base_config()),
832            ".break-keep {
833  word-break: keep-all;
834}"
835        );
836    }
837}