Skip to main content

stylex_transform/shared/transformers/
stylex_create.rs

1use std::{collections::VecDeque, rc::Rc};
2
3use indexmap::{IndexMap, IndexSet};
4use stylex_macros::stylex_panic;
5
6use crate::shared::enums::data_structures::evaluate_result_value::EvaluateResultValue;
7use crate::shared::enums::data_structures::flat_compiled_styles_value::FlatCompiledStylesValue;
8use crate::shared::structures::functions::FunctionMap;
9use crate::shared::structures::pre_rule::{CompiledResult, ComputedStyle, PreRule, PreRules};
10use crate::shared::structures::state::EvaluationState;
11use crate::shared::structures::state_manager::StateManager;
12use crate::shared::structures::types::{
13  ClassPathsInNamespace, ClassPathsMap, FlatCompiledStyles, InjectableStylesMap, StylesObjectMap,
14};
15use crate::shared::utils::ast::convertors::convert_expr_to_str;
16use crate::shared::utils::common::create_short_hash;
17use crate::shared::utils::core::flatten_raw_style_object::flatten_raw_style_object;
18use crate::shared::utils::validators::validate_namespace;
19use stylex_constants::constants::common::COMPILED_KEY;
20use stylex_constants::constants::messages::{EXPRESSION_IS_NOT_A_STRING, VALUES_MUST_BE_OBJECT};
21use stylex_types::enums::data_structures::injectable_style::InjectableStyleKind;
22
23pub(crate) fn stylex_create_set(
24  namespaces: &EvaluateResultValue,
25  state: &mut EvaluationState,
26  traversal_state: &mut StateManager,
27  functions: &FunctionMap,
28) -> (StylesObjectMap, InjectableStylesMap, ClassPathsMap) {
29  let mut resolved_namespaces = IndexMap::new();
30  let mut injected_styles_map = IndexMap::new();
31  let mut namespace_to_class_paths = IndexMap::new();
32
33  for (namespace_name, namespace) in match namespaces.as_map() {
34    Some(map) => map,
35    None => stylex_panic!("{}", VALUES_MUST_BE_OBJECT),
36  } {
37    validate_namespace(namespace, &[], traversal_state);
38
39    let mut class_paths_in_namespace: ClassPathsInNamespace = IndexMap::new();
40
41    let mut seen_properties = IndexSet::<String>::new();
42
43    let mut flattened_namespace =
44      flatten_raw_style_object(namespace, state, traversal_state, functions)
45        .into_iter()
46        .rev()
47        .fold(VecDeque::new(), |mut arr, curr| {
48          if !seen_properties.contains(&curr.0) {
49            seen_properties.insert(curr.0.clone());
50            arr.push_front(curr);
51          }
52          arr
53        });
54
55    let compiled_namespace_tuples = flattened_namespace
56      .iter_mut()
57      .map(|(key, value)| {
58        let key = if traversal_state.options.enable_minified_keys && !key.starts_with("--") {
59          let hashed_key = create_short_hash(&format!("<>{}", key));
60          if traversal_state.options.debug {
61            format!("{}-k{}", key, hashed_key)
62          } else {
63            format!("k{}", hashed_key)
64          }
65        } else {
66          key.clone()
67        };
68
69        let compiled_value = match value {
70          PreRules::PreRuleSet(rule_set) => rule_set.compiled(traversal_state),
71          PreRules::StylesPreRule(styles_pre_rule) => styles_pre_rule.compiled(traversal_state),
72          PreRules::NullPreRule(rule_set) => rule_set.compiled(traversal_state),
73        };
74        (key, compiled_value)
75      })
76      .collect::<Vec<(String, CompiledResult)>>();
77
78    let mut namespace_obj: FlatCompiledStyles = IndexMap::new();
79
80    for (key, value) in compiled_namespace_tuples {
81      match value {
82        CompiledResult::ComputedStyles(class_name_tuples) => {
83          let mut unique_class_names = IndexSet::new();
84
85          for ComputedStyle(class_name, _, classes_to_original_path) in class_name_tuples.iter() {
86            unique_class_names.insert(class_name.as_str());
87            class_paths_in_namespace.extend(classes_to_original_path.clone());
88          }
89
90          let class_name = unique_class_names
91            .iter()
92            .cloned()
93            .collect::<Vec<&str>>()
94            .join(" ");
95
96          namespace_obj.insert(
97            key.clone(),
98            if !class_name.is_empty() {
99              Rc::new(FlatCompiledStylesValue::String(class_name.clone()))
100            } else {
101              Rc::new(FlatCompiledStylesValue::Null)
102            },
103          );
104
105          for ComputedStyle(class_name, injectable_styles, _) in class_name_tuples.iter() {
106            injected_styles_map
107              .entry(class_name.clone())
108              .or_insert_with(|| Rc::new(InjectableStyleKind::Regular(injectable_styles.clone())));
109          }
110        },
111        _ => {
112          namespace_obj.insert(key.clone(), Rc::new(FlatCompiledStylesValue::Null));
113        },
114      }
115    }
116
117    let resolved_namespace_name =
118      match convert_expr_to_str(namespace_name, traversal_state, functions) {
119        Some(s) => s,
120        None => stylex_panic!("{}", EXPRESSION_IS_NOT_A_STRING),
121      };
122
123    namespace_obj.insert(
124      COMPILED_KEY.to_owned(),
125      Rc::new(FlatCompiledStylesValue::Bool(true)),
126    );
127
128    resolved_namespaces.insert(resolved_namespace_name.clone(), Rc::new(namespace_obj));
129
130    namespace_to_class_paths.insert(resolved_namespace_name, Rc::new(class_paths_in_namespace));
131  }
132
133  (
134    resolved_namespaces,
135    injected_styles_map,
136    namespace_to_class_paths,
137  )
138}