Skip to content

Commit

Permalink
add own class name hashing
Browse files Browse the repository at this point in the history
  • Loading branch information
jantimon committed Nov 25, 2024
1 parent fb2b2ca commit f5f71c7
Show file tree
Hide file tree
Showing 35 changed files with 266 additions and 221 deletions.
12 changes: 1 addition & 11 deletions packages/yak-swc/yak_swc/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -96,8 +96,6 @@ where
expression_replacement: Option<Box<Expr>>,
/// The current file name e.g. "App.tsx"
filename: String,
/// The imported css module from the virtual yak.module.css
css_module_identifier: Option<Ident>,
/// Flag to check if we are inside a css attribute
inside_element_with_css_attribute: bool,
}
Expand All @@ -118,7 +116,6 @@ where
naming_convention: NamingConvention::new(filename.clone(), dev_mode),
variable_name_selector_mapping: FxHashMap::default(),
expression_replacement: None,
css_module_identifier: None,
inside_element_with_css_attribute: false,
filename,
comments,
Expand Down Expand Up @@ -483,8 +480,6 @@ where
/// ? is a fix for Next.js loaders which ignore the !=! statement
fn visit_mut_module(&mut self, module: &mut Module) {
let basename = self.get_file_name_without_extension();
let css_module_identifier = Ident::new("__styleYak".into(), DUMMY_SP, SyntaxContext::empty());
self.css_module_identifier = Some(css_module_identifier.clone());

module.visit_mut_children_with(self);

Expand Down Expand Up @@ -520,11 +515,7 @@ where
ModuleItem::ModuleDecl(ModuleDecl::Import(ImportDecl {
phase: Default::default(),
span: DUMMY_SP,
specifiers: vec![ImportDefaultSpecifier {
span: DUMMY_SP,
local: css_module_identifier,
}
.into()],
specifiers: vec![],
src: Box::new(Str {
span: DUMMY_SP,
value: format!(
Expand Down Expand Up @@ -788,7 +779,6 @@ where

let transform_result = transform.transform_expression(
n,
self.css_module_identifier.clone().unwrap(),
runtime_expressions,
&self.current_declaration,
runtime_css_variables,
Expand Down
15 changes: 15 additions & 0 deletions packages/yak-swc/yak_swc/src/naming_convention.rs
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,21 @@ impl NamingConvention {
let css_variable_name = format!("{}{}", name, self.get_file_name_hash());
self.generate_unique_name(&css_variable_name)
}

/// Generate a unique CSS variable name based on the file name and a base name
pub fn get_css_class_name(&mut self, base_name: &str) -> String {
let name: String = if self.dev_mode {
if base_name.is_empty() {
String::from("yak_")
} else {
format!("{}_", base_name)
}
} else {
String::from("y")
};
let css_variable_name = format!("{}{}", name, self.get_file_name_hash());
self.generate_unique_name(&css_variable_name)
}
}

fn escape_css_identifier(input: &str) -> String {
Expand Down
24 changes: 1 addition & 23 deletions packages/yak-swc/yak_swc/src/utils/ast_helper.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ use itertools::Itertools;
use rustc_hash::{FxHashMap, FxHashSet};

use swc_core::atoms::Atom;
use swc_core::{common::DUMMY_SP, ecma::ast::*, plugin::errors::HANDLER};
use swc_core::{ecma::ast::*, plugin::errors::HANDLER};

use crate::variable_visitor::ScopedVariableReference;

Expand Down Expand Up @@ -63,28 +63,6 @@ pub fn member_expr_to_strings(member_expr: &MemberExpr) -> Option<(Ident, Vec<At
}
}

/// String to MemberProp
pub fn create_member_prop_from_string(s: String) -> MemberProp {
// if the string contains characters that are not allowed in an identifier
// "with space" -> foo["with space"]
if s.contains(|c: char| !c.is_alphanumeric() && c != '_' && c != '$')
|| s.starts_with(|c: char| c.is_ascii_digit())
{
MemberProp::Computed(ComputedPropName {
span: DUMMY_SP,
expr: Box::new(Expr::Lit(Lit::Str(Str {
span: DUMMY_SP,
value: s.into(),
raw: None,
}))),
})
}
// otherwise "bar" -> foo.bar
else {
MemberProp::Ident(IdentName::new(s.into(), DUMMY_SP))
}
}

/// Extracts the identifier and member expression parts from an expression
/// There are two use cases:
/// 1. Member expressions (e.g., `colors.primary`) -> Some((colors#0, ["colors", "primary"]))
Expand Down
57 changes: 28 additions & 29 deletions packages/yak-swc/yak_swc/src/yak_transforms.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ use itertools::Itertools;
use rustc_hash::FxHashMap;
use swc_core::common::util::move_map::MoveMap;

use crate::utils::ast_helper::{create_member_prop_from_string, expr_hash_map_to_object};
use crate::utils::ast_helper::expr_hash_map_to_object;
use crate::utils::encode_module_import::encode_percent;
use crate::variable_visitor::ScopedVariableReference;
use css_in_js_parser::{CssScope, Declaration, ParserState, ScopeType};
Expand Down Expand Up @@ -41,7 +41,6 @@ pub trait YakTransform {
fn transform_expression(
&mut self,
expression: &mut TaggedTpl,
css_module_identifier: Ident,
runtime_expressions: Vec<Expr>,
declarations: &[Declaration],
runtime_css_variables: FxHashMap<String, Expr>,
Expand Down Expand Up @@ -78,7 +77,7 @@ impl YakTransform for TransformNestedCss {
previous_parser_state: Option<ParserState>,
) -> ParserState {
let condition = self.condition.join("-and-");
let css_identifier = naming_convention.generate_unique_name(&format!(
let css_identifier = naming_convention.get_css_class_name(&format!(
"{}__{}",
declaration_name.to_readable_string(),
condition
Expand All @@ -88,7 +87,7 @@ impl YakTransform for TransformNestedCss {
let mut parser_state = previous_parser_state.clone().unwrap();
// The first scope is the class name which gets attached to the element
parser_state.current_scopes[0] = CssScope {
name: format!(".{}", css_identifier),
name: format!("// cssmodules-pure-ignore\n:global(.{})", css_identifier),
scope_type: ScopeType::Selector,
};
parser_state
Expand All @@ -97,19 +96,18 @@ impl YakTransform for TransformNestedCss {
fn transform_expression(
&mut self,
expression: &mut TaggedTpl,
css_module_identifier: Ident,
runtime_expressions: Vec<Expr>,
declarations: &[Declaration],
runtime_css_variables: FxHashMap<String, Expr>,
) -> YakTransformResult {
let mut arguments: Vec<ExprOrSpread> = vec![];
if !declarations.is_empty() {
arguments.push(
Expr::Member(MemberExpr {
Expr::Lit(Lit::Str(Str {
span: DUMMY_SP,
obj: Box::new(Expr::Ident(css_module_identifier.clone())),
prop: create_member_prop_from_string(self.class_name.clone().unwrap()),
})
value: self.class_name.clone().unwrap().into(),
raw: None,
}))
.into(),
);
}
Expand Down Expand Up @@ -184,7 +182,6 @@ impl YakTransform for TransformCssMixin {
fn transform_expression(
&mut self,
expression: &mut TaggedTpl,
css_module_identifier: Ident,
runtime_expressions: Vec<Expr>,
declarations: &[Declaration],
runtime_css_variables: FxHashMap<String, Expr>,
Expand Down Expand Up @@ -231,13 +228,16 @@ impl YakTransform for TransformCssMixin {
(_, true) => {
// Add the class name to the arguments, to be created by the CSS loader
arguments.push(
Expr::Member(MemberExpr {
Expr::Lit(Lit::Str(Str {
span: DUMMY_SP,
obj: Box::new(Expr::Ident(css_module_identifier.clone())),
prop: create_member_prop_from_string(
self.export_name.clone().unwrap().to_readable_string(),
),
})
value: self
.export_name
.clone()
.unwrap()
.to_readable_string()
.into(),
raw: None,
}))
.into(),
);
Some("YAK Extracted CSS:".to_string())
Expand Down Expand Up @@ -293,11 +293,12 @@ impl YakTransform for TransformStyled {
declaration_name: &ScopedVariableReference,
_previous_parser_state: Option<ParserState>,
) -> ParserState {
let css_identifier = naming_convention.generate_unique_name_for_variable(declaration_name);
let css_identifier =
naming_convention.get_css_class_name(&declaration_name.to_readable_string());
self.class_name = Some(css_identifier.clone());
let mut parser_state = ParserState::new();
parser_state.current_scopes = vec![CssScope {
name: format!(".{}", css_identifier),
name: format!("// cssmodules-pure-ignore\n:global(.{})", css_identifier),
scope_type: ScopeType::AtRule,
}];
parser_state
Expand All @@ -306,19 +307,18 @@ impl YakTransform for TransformStyled {
fn transform_expression(
&mut self,
expression: &mut TaggedTpl,
css_module_identifier: Ident,
runtime_expressions: Vec<Expr>,
declarations: &[Declaration],
runtime_css_variables: FxHashMap<String, Expr>,
) -> YakTransformResult {
let mut arguments: Vec<ExprOrSpread> = vec![];
if !declarations.is_empty() {
arguments.push(
Expr::Member(MemberExpr {
Expr::Lit(Lit::Str(Str {
span: DUMMY_SP,
obj: Box::new(Expr::Ident(css_module_identifier.clone())),
prop: create_member_prop_from_string(self.class_name.clone().unwrap()),
})
value: self.class_name.clone().unwrap().into(),
raw: None,
}))
.into(),
);
}
Expand Down Expand Up @@ -393,19 +393,18 @@ impl YakTransform for TransformKeyframes {
fn transform_expression(
&mut self,
expression: &mut TaggedTpl,
css_module_identifier: Ident,
_runtime_expressions: Vec<Expr>,
declarations: &[Declaration],
runtime_css_variables: FxHashMap<String, Expr>,
) -> YakTransformResult {
let mut arguments: Vec<ExprOrSpread> = vec![];
if !declarations.is_empty() {
arguments.push(
Expr::Member(MemberExpr {
Expr::Lit(Lit::Str(Str {
span: DUMMY_SP,
obj: Box::new(Expr::Ident(css_module_identifier.clone())),
prop: create_member_prop_from_string(self.animation_name.clone().unwrap()),
})
value: self.animation_name.clone().unwrap().into(),
raw: None,
}))
.into(),
);
}
Expand Down Expand Up @@ -435,6 +434,6 @@ impl YakTransform for TransformKeyframes {

/// Get the selector for the keyframe to be used in other expressions
fn get_css_reference_name(&self) -> Option<String> {
Some(self.animation_name.clone().unwrap())
Some(format!("global({})", self.animation_name.clone().unwrap()))
}
}
7 changes: 4 additions & 3 deletions packages/yak-swc/yak_swc/tests/fixture/attrs/output.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
import { styled } from "next-yak/internal";
import __styleYak from "./input.yak.module.css!=!./input?./input.yak.module.css";
import "./input.yak.module.css!=!./input?./input.yak.module.css";
export const Button = /*YAK Extracted CSS:
.Button {
// cssmodules-pure-ignore
:global(.Button_m7uBBu) {
background-color: #007bff;
color: #fff;
padding: 10px 20px;
Expand All @@ -16,4 +17,4 @@ export const Button = /*YAK Extracted CSS:
}
*/ /*#__PURE__*/ styled.button.attrs({
type: "button"
})(__styleYak.Button);
})("Button_m7uBBu");
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
import { styled } from "next-yak/internal";
import __styleYak from "./input.yak.module.css!=!./input?./input.yak.module.css";
import "./input.yak.module.css!=!./input?./input.yak.module.css";
export const Button = /*YAK Extracted CSS:
.Button {
// cssmodules-pure-ignore
:global(.Button_m7uBBu) {
background-color: #007bff;
color: #fff;
padding: 10px 20px;
Expand All @@ -14,4 +15,4 @@ export const Button = /*YAK Extracted CSS:
background-color: #0056b3;
}
}
*/ /*#__PURE__*/ styled.button(__styleYak.Button);
*/ /*#__PURE__*/ styled.button("Button_m7uBBu");
7 changes: 4 additions & 3 deletions packages/yak-swc/yak_swc/tests/fixture/comments/output.tsx
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
import { styled } from "next-yak/internal";
import __styleYak from "./input.yak.module.css!=!./input?./input.yak.module.css";
import "./input.yak.module.css!=!./input?./input.yak.module.css";
const primary = "green";
export const Button = /*YAK Extracted CSS:
.Button {
// cssmodules-pure-ignore
:global(.Button_m7uBBu) {
color: green;
background: red;
}
*/ /*#__PURE__*/ styled.button(__styleYak.Button);
*/ /*#__PURE__*/ styled.button("Button_m7uBBu");
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
import { styled } from "next-yak/internal";
import __styleYak from "./input.yak.module.css!=!./input?./input.yak.module.css";
import "./input.yak.module.css!=!./input?./input.yak.module.css";
export const ArticleCard = /*YAK Extracted CSS:
.ArticleCard {
// cssmodules-pure-ignore
:global(.ArticleCard_m7uBBu) {
background-color: #fff;
border-radius: 8px;
overflow: hidden;
Expand Down Expand Up @@ -52,4 +53,4 @@ export const ArticleCard = /*YAK Extracted CSS:
}
}
}
*/ /*#__PURE__*/ styled.article(__styleYak.ArticleCard);
*/ /*#__PURE__*/ styled.article("ArticleCard_m7uBBu");
7 changes: 4 additions & 3 deletions packages/yak-swc/yak_swc/tests/fixture/constants/output.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { styled } from "next-yak/internal";
import __styleYak from "./input.yak.module.css!=!./input?./input.yak.module.css";
import "./input.yak.module.css!=!./input?./input.yak.module.css";
const colors = {
primary: "#007bff",
secondary: "#6c757d",
Expand All @@ -13,7 +13,8 @@ const colors = {
const borderRadius = "4px";
const stacking = 1;
export const Button = /*YAK Extracted CSS:
.Button {
// cssmodules-pure-ignore
:global(.Button_m7uBBu) {
background-color: #007bff;
color: #f8f9fa;
padding: 10px 33.3333%;
Expand All @@ -28,4 +29,4 @@ export const Button = /*YAK Extracted CSS:
background-color: #343a40;
}
}
*/ /*#__PURE__*/ styled.button(__styleYak.Button);
*/ /*#__PURE__*/ styled.button("Button_m7uBBu");
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,14 @@ import { colors } from "./colorDefinitions";
import { fonts } from "./fontDefinitions";
// @ts-ignore
import { sizes } from "./sizeDefinitions";
import __styleYak from "./input.yak.module.css!=!./input?./input.yak.module.css";
import "./input.yak.module.css!=!./input?./input.yak.module.css";
export const Button = /*YAK Extracted CSS:
.Button {
// cssmodules-pure-ignore
:global(.Button_m7uBBu) {
font-size: --yak-css-import: url("./fontDefinitions:fonts:sm",mixin);
color: --yak-css-import: url("./colorDefinitions:colors:dark:primary",mixin);
border-color: --yak-css-import: url("./colorDefinitions:colors:shadows:dark:primary",mixin);
background-color: --yak-css-import: url("./colorDefinitions:colors:light:full%20opacity",mixin);
height: --yak-css-import: url("./sizeDefinitions:sizes:0",mixin);
}
*/ /*#__PURE__*/ styled.button(__styleYak.Button);
*/ /*#__PURE__*/ styled.button("Button_m7uBBu");
Loading

0 comments on commit f5f71c7

Please sign in to comment.