encre_css/plugins/layout/container/
mod.rs

1#![doc = include_str!("README.md")]
2#![doc(alias = "layout")]
3use crate::{config::BUILTIN_SCREENS, prelude::build_plugin::*};
4
5use std::{borrow::Cow, cmp::Ordering};
6
7#[derive(Debug)]
8pub(crate) struct PluginDefinition;
9
10impl Plugin for PluginDefinition {
11    fn needs_wrapping(&self) -> bool {
12        false
13    }
14
15    fn can_handle(&self, context: ContextCanHandle) -> bool {
16        matches!(context.modifier, Modifier::Builtin { value: "", .. })
17    }
18
19    fn handle(&self, context: &mut ContextHandle) {
20        if let Modifier::Builtin { .. } = context.modifier {
21            generate_wrapper(context, |context| {
22                context.buffer.line("width: 100%;");
23            });
24
25            context.buffer.raw("\n\n");
26
27            let mut first_child = true;
28
29            generate_at_rules(context, |context| {
30                let mut screens = context
31                    .config
32                    .theme
33                    .screens
34                    .iter()
35                    .map(|(a, b)| (a.clone(), b.clone()))
36                    .chain(
37                        BUILTIN_SCREENS
38                            .iter()
39                            .map(|(a, b)| (Cow::from(*a), Cow::from(*b))),
40                    )
41                    .collect::<Vec<(Cow<str>, Cow<str>)>>();
42
43                // Deduplicate screens
44                screens.sort_by(|a, b| a.0.cmp(&b.0));
45                screens.dedup_by(|a, b| a.0.eq(&b.0));
46
47                // Emulate Tailwind sorting (based on the JS `parseInt` function)
48                screens.sort_by(|a, b| {
49                    let a = if let Some(first_char_a) = a.1.chars().position(char::is_alphabetic) {
50                        a.1[..first_char_a].parse::<usize>().ok()
51                    } else {
52                        a.1.parse::<usize>().ok()
53                    };
54
55                    let b = if let Some(first_char_b) = b.1.chars().position(char::is_alphabetic) {
56                        b.1[..first_char_b].parse::<usize>().ok()
57                    } else {
58                        b.1.parse::<usize>().ok()
59                    };
60
61                    if let Some(a) = a {
62                        if let Some(b) = b {
63                            a.cmp(&b)
64                        } else {
65                            Ordering::Less
66                        }
67                    } else {
68                        Ordering::Greater
69                    }
70                });
71
72                for (_, screen) in &screens {
73                    if first_child {
74                        first_child = false;
75                    } else if context.buffer.is_unindented() {
76                        context.buffer.raw("\n\n");
77                    } else {
78                        context.buffer.raw("\n");
79                    }
80
81                    context
82                        .buffer
83                        .line(format_args!("@media (width >= {screen}) {{"));
84                    context.buffer.indent();
85
86                    generate_class(
87                        context,
88                        |context| {
89                            context.buffer.line(format_args!("max-width: {screen};"));
90                        },
91                        "",
92                    );
93
94                    context.buffer.unindent();
95                    if context.buffer.is_unindented() {
96                        context.buffer.raw("}");
97                    } else {
98                        context.buffer.line("}");
99                    }
100                }
101
102                // After rule
103                while !context.buffer.is_unindented() {
104                    context.buffer.unindent();
105
106                    if context.buffer.is_unindented() {
107                        context.buffer.raw("}");
108                    } else {
109                        context.buffer.line("}");
110                    }
111                }
112            });
113        }
114    }
115}