lewp/css/
register.rs

1use {
2    super::{Component, Entireness, ProcessedComponent},
3    crate::{
4        fh::{ComponentInformation, ComponentType, FileHierarchy, Level},
5        LewpError,
6    },
7    std::{collections::HashMap, rc::Rc, sync::Arc},
8};
9
10/// Options for the Register.
11pub struct RegisterOptions {}
12
13impl RegisterOptions {
14    /// Creates a new RegisterOptions instance.
15    pub fn new() -> Self {
16        Self {}
17    }
18}
19
20/// Manages the CSS of lewp components in the given file hierarchy.
21///
22/// This register can be used in multi threaded environments as a shared
23/// variable. It loads all components available in the given file hierarchy and
24/// keeps them in memory, as long as this instance is available.
25pub struct Register {
26    fh: Rc<FileHierarchy>,
27    options: RegisterOptions,
28    components: HashMap<Rc<ComponentInformation>, ProcessedComponent>,
29}
30
31impl Register {
32    /// Creates a new Register instance.
33    pub fn new(fh: FileHierarchy, options: RegisterOptions) -> Self {
34        Self {
35            fh: Rc::new(fh),
36            options,
37            components: HashMap::new(),
38        }
39    }
40
41    /// Queries the CSS of the given component using the given options.
42    pub fn query(
43        &self,
44        component_information: Rc<ComponentInformation>,
45        entity: Entireness,
46    ) -> Option<Arc<String>> {
47        let ref_css = self.components.get(&component_information)?;
48        Some(ref_css.render_critical())
49    }
50
51    /// Collects, processes and caches all available CSS in the file hierarchy.
52    pub fn load_process_components(&mut self) -> Result<(), LewpError> {
53        self.load_process_modules()?;
54        self.load_process_pages()
55    }
56
57    fn load_process_modules(&mut self) -> Result<(), LewpError> {
58        let module_ids = self
59            .fh
60            .collect_component_ids(ComponentType::Css, Level::Module)?;
61        for id in module_ids {
62            let component_information = Rc::new(ComponentInformation {
63                id: id.clone(),
64                level: Level::Module,
65                kind: ComponentType::Css,
66            });
67            let c =
68                Component::new(component_information.clone(), self.fh.clone());
69            let c = ProcessedComponent::from(&c)?;
70            self.components.insert(component_information.clone(), c);
71        }
72        Ok(())
73    }
74
75    fn load_process_pages(&mut self) -> Result<(), LewpError> {
76        let page_ids = self
77            .fh
78            .collect_component_ids(ComponentType::Css, Level::Page)?;
79        for id in page_ids {
80            let component_information = Rc::new(ComponentInformation {
81                id: id.clone(),
82                level: Level::Page,
83                kind: ComponentType::Css,
84            });
85            let c =
86                Component::new(component_information.clone(), self.fh.clone());
87            let c = ProcessedComponent::from(&c)?;
88            self.components.insert(component_information.clone(), c);
89        }
90        Ok(())
91    }
92}
93
94impl Default for Register {
95    fn default() -> Self {
96        Self::new(FileHierarchy::new(), RegisterOptions::new())
97    }
98}