Skip to main content

stylex_transform/shared/transformers/
stylex_define_consts.rs

1use std::rc::Rc;
2
3use stylex_macros::{stylex_panic, stylex_unimplemented};
4
5use crate::shared::enums::data_structures::evaluate_result_value::EvaluateResultValue;
6use crate::shared::enums::data_structures::flat_compiled_styles_value::FlatCompiledStylesValue;
7use crate::shared::enums::data_structures::obj_map_type::ObjMapType;
8use crate::shared::structures::state_manager::StateManager;
9use crate::shared::structures::types::{FlatCompiledStyles, InjectableStylesMap};
10use crate::shared::utils::common::{create_hash, serialize_value_to_json_string};
11use crate::shared::utils::object::obj_map;
12use stylex_constants::constants::messages::{
13  EXPORT_ID_NOT_SET, INJECTABLE_STYLE_NOT_SUPPORTED, VALUES_MUST_BE_OBJECT,
14};
15use stylex_types::enums::data_structures::injectable_style::InjectableStyleKind;
16use stylex_types::structures::injectable_style::InjectableConstStyle;
17
18pub(crate) fn stylex_define_consts(
19  constants: &EvaluateResultValue,
20  state: &mut StateManager,
21) -> (FlatCompiledStyles, InjectableStylesMap) {
22  let Some(constants) = constants.as_expr().and_then(|expr| expr.as_object()) else {
23    stylex_panic!("{}", VALUES_MUST_BE_OBJECT)
24  };
25
26  let class_name_prefix = state.options.class_name_prefix.clone();
27  let debug = state.options.debug;
28  let enable_debug_class_names = state.options.enable_debug_class_names;
29  let export_id = match state.export_id.clone() {
30    Some(id) => id,
31    None => stylex_panic!("{}", EXPORT_ID_NOT_SET),
32  };
33
34  let js_output = obj_map(
35    ObjMapType::Object(constants.clone()),
36    state,
37    |item, _| -> Rc<FlatCompiledStylesValue> {
38      let result = match item.as_ref() {
39        FlatCompiledStylesValue::InjectableStyle(_) => {
40          stylex_panic!("{}", INJECTABLE_STYLE_NOT_SUPPORTED)
41        },
42        FlatCompiledStylesValue::Tuple(_key, value, _) => {
43          let serialized_value =
44            serialize_value_to_json_string(EvaluateResultValue::Expr(*value.clone()));
45
46          FlatCompiledStylesValue::String(serialized_value)
47        },
48        _ => stylex_unimplemented!(
49          "FlatCompiledStylesValue variant not supported in stylex_define_consts"
50        ),
51      };
52
53      Rc::new(result)
54    },
55  );
56
57  let injectable_types = js_output
58    .iter()
59    .filter_map(|(key, value)| {
60      if let FlatCompiledStylesValue::String(value) = value.as_ref() {
61        let var_safe_key = if key.chars().next().unwrap_or('\0') >= '0'
62          && key.chars().next().unwrap_or('\0') <= '9'
63        {
64          format!("_{}", key)
65        } else {
66          key.to_string()
67        }
68        .chars()
69        .map(|c| if c.is_alphanumeric() { c } else { '_' })
70        .collect::<String>();
71
72        let const_key = if key.starts_with("--") {
73          // Preserve user-authored CSS custom property name without the leading `--`
74          key.chars().skip(2).collect::<String>()
75        } else if debug && enable_debug_class_names {
76          format!(
77            "{}-{}{}",
78            var_safe_key,
79            class_name_prefix,
80            create_hash(&format!("{}.{}", export_id, key))
81          )
82        } else {
83          format!(
84            "{}{}",
85            class_name_prefix,
86            create_hash(&format!("{}.{}", export_id, key))
87          )
88        };
89
90        Some((
91          const_key.to_owned(),
92          Rc::new(InjectableStyleKind::Const(InjectableConstStyle {
93            ltr: String::default(),
94            rtl: None,
95            priority: Some(0.0),
96            const_key,
97            const_value: value.to_owned(),
98          })),
99        ))
100      } else {
101        None
102      }
103    })
104    .collect();
105
106  (js_output, injectable_types)
107}