Skip to content

Minor file visitor refactoring #296

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 5 commits into from
Mar 26, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .changeset/smart-timers-attack.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"yak-swc": patch
---

Minor refactoring of visitors
21 changes: 11 additions & 10 deletions packages/yak-swc/yak_swc/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ use css_in_js_parser::{find_char, parse_css, to_css, CommentStateType};
use css_in_js_parser::{Declaration, ParserState};
use rustc_hash::FxHashMap;
use serde::Deserialize;
use std::ops::Deref;
use std::path::Path;
use std::vec;
use swc_core::atoms::atom;
Expand Down Expand Up @@ -757,24 +758,24 @@ where
/// Visit tagged template literals
/// This is where the css-in-js expressions are
fn visit_mut_tagged_tpl(&mut self, n: &mut TaggedTpl) {
let yak_library_function_name = self
let Some(yak_library_function_name) = self
.yak_library_imports
.as_mut()
.as_ref()
.unwrap()
.get_yak_library_function_name(n);
if yak_library_function_name.is_none() {
.get_yak_library_function_name(n)
else {
n.visit_mut_children_with(self);
return;
}
};

let is_top_level = !self.is_inside_css_expression();
let current_variable_id = self.get_current_component_id();

let mut transform: Box<dyn YakTransform> = match yak_library_function_name.as_deref() {
let mut transform: Box<dyn YakTransform> = match yak_library_function_name.deref() {
// Styled Components transform works only on top level
Some("styled") if is_top_level => Box::new(TransformStyled::new()),
"styled" if is_top_level => Box::new(TransformStyled::new()),
// Keyframes transform works only on top level
Some("keyframes") if is_top_level => Box::new(TransformKeyframes::new(
"keyframes" if is_top_level => Box::new(TransformKeyframes::new(
self
.variable_name_selector_mapping
.get(&current_variable_id)
Expand All @@ -786,12 +787,12 @@ where
}),
)),
// CSS Mixin e.g. const highlight = css`color: red;`
Some("css") if is_top_level => Box::new(TransformCssMixin::new(
"css" if is_top_level => Box::new(TransformCssMixin::new(
self.current_exported,
self.inside_element_with_css_attribute,
)),
// CSS Inline mixin e.g. styled.button`${() => css`color: red;`}`
Some("css") => Box::new(TransformNestedCss::new(self.current_condition.clone())),
"css" => Box::new(TransformNestedCss::new(self.current_condition.clone())),
_ => {
if !is_top_level {
HANDLER.with(|handler| {
Expand Down
114 changes: 57 additions & 57 deletions packages/yak-swc/yak_swc/src/yak_file_visitor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -59,85 +59,85 @@ impl VisitMut for YakFileVisitor {
// This is necessary as the mixin is also imported at runtime and a string would be
// interpreted as a class name
if let Expr::TaggedTpl(n) = expr {
if let Some(name) = self
if let Some("css") = self
.yak_imports
.as_mut()
.as_ref()
.unwrap()
.get_yak_library_function_name(n)
.as_deref()
{
if name == atom!("css") {
*expr = ObjectLit {
span: n.span,
props: vec![PropOrSpread::Prop(Box::new(Prop::KeyValue(KeyValueProp {
key: PropName::Ident(IdentName::new("__yak".into(), n.span)),
value: Box::new(Expr::Tpl(Tpl {
span: n.span,
exprs: n.tpl.exprs.clone(),
quasis: n.tpl.quasis.clone(),
})),
})))]
.into_iter()
.collect(),
}
.into();
*expr = ObjectLit {
span: n.span,
props: vec![PropOrSpread::Prop(Box::new(Prop::KeyValue(KeyValueProp {
key: PropName::Ident(IdentName::new("__yak".into(), n.span)),
value: Box::new(Expr::Tpl(Tpl {
span: n.span,
exprs: n.tpl.exprs.clone(),
quasis: n.tpl.quasis.clone(),
})),
})))]
.into_iter()
.collect(),
}
.into();
}
}
}

fn visit_mut_tagged_tpl(&mut self, n: &mut TaggedTpl) {
if let Some(name) = self
let Some(name) = self
.yak_imports
.as_mut()
.as_ref()
.unwrap()
.get_yak_library_function_name(n)
{
// Right now only css template literals are allowed
if name != atom!("css") {
HANDLER.with(|handler| {
handler
.struct_span_err(
n.span,
"Only css template literals are allowed inside .yak files",
)
.emit();
});
return;
}
else {
// Ignore unknown template literals
return;
};

// Right now only css template literals are allowed
if name != atom!("css") {
HANDLER.with(|handler| {
handler
.struct_span_err(
n.span,
"Only css template literals are allowed inside .yak files",
)
.emit();
});
return;
}

if self.is_inside_css_tpl {
if self.is_inside_css_tpl {
HANDLER.with(|handler| {
handler
.struct_span_err(
n.span,
"Nested css template literals are not allowed inside .yak files",
)
.emit();
});
return;
}

let before_is_inside_css_tpl = self.is_inside_css_tpl;
self.is_inside_css_tpl = true;

for expr in &n.tpl.exprs {
if self.is_invalid_expr(expr) {
HANDLER.with(|handler| {
handler
.struct_span_err(
n.span,
"Nested css template literals are not allowed inside .yak files",
expr.span(),
"Function expressions are not allowed in css template literals inside .yak files",
)
.emit();
});
return;
}

let before_is_inside_css_tpl = self.is_inside_css_tpl;
self.is_inside_css_tpl = true;

for expr in &n.tpl.exprs {
if self.is_invalid_expr(expr) {
HANDLER.with(|handler| {
handler
.struct_span_err(
expr.span(),
"Function expressions are not allowed in css template literals inside .yak files",
)
.emit();
});
}
}

n.tpl.exprs.visit_mut_with(self);
self.is_inside_css_tpl = before_is_inside_css_tpl;
} else {
// Ignore unknown template literals
}

n.tpl.exprs.visit_mut_with(self);
self.is_inside_css_tpl = before_is_inside_css_tpl;
}
}

Expand Down
Loading