sofie_engine/
components.rs1use std::collections::BTreeMap;
2
3use crate::catalog::Kind;
4use crate::error::TemplateError;
5
6#[derive(Clone, Debug, Default)]
9pub struct Components {
10 by_name: BTreeMap<String, String>,
11}
12
13impl Components {
14 pub fn add(&mut self, name: &str, source: String) -> Result<(), TemplateError> {
16 let refused = |message: String| TemplateError::unlocated(name, message);
17 if !is_component_name(name) {
18 return Err(refused(format!(
19 "`{name}` is no component name: name `web/<Name>.html` in PascalCase, such as \
20 `OrderCard`"
21 )));
22 }
23 if Kind::named(name).is_some() {
24 return Err(refused(format!(
25 "`{name}` is a component the catalog ships; name the template otherwise"
26 )));
27 }
28 if self.by_name.insert(name.to_owned(), source).is_some() {
29 return Err(refused(format!(
30 "component `{name}` is added twice; one `web/{name}.html` per app"
31 )));
32 }
33 Ok(())
34 }
35
36 pub(crate) fn source(&self, name: &str) -> Option<&str> {
37 self.by_name.get(name).map(String::as_str)
38 }
39}
40
41fn is_component_name(name: &str) -> bool {
42 name.starts_with(|first: char| first.is_ascii_uppercase())
43 && name.bytes().all(|byte| byte.is_ascii_alphanumeric())
44}