Skip to content

Commit

Permalink
SASS support
Browse files Browse the repository at this point in the history
  • Loading branch information
Leinnan committed Apr 11, 2023
1 parent 10c272a commit 346ced7
Show file tree
Hide file tree
Showing 7 changed files with 42 additions and 30 deletions.
1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ bevy = { version = "0.10", default-features = false, features = [
"bevy_render",
] }
cssparser = "0.29"
grass = "0.12"

smallvec = { version = "1.10", features = ["serde", "union", "const_generics"] }

Expand Down
17 changes: 8 additions & 9 deletions assets/sheets/example.css → assets/sheets/example.scss
Original file line number Diff line number Diff line change
Expand Up @@ -37,17 +37,16 @@ button text {
margin: 2px 5px 4% 3px;
padding: 10px;
border: 2px;
.not_hovered {
flex-grow: 1.1;
flex-shrink: 1;
flex-basis: 55px;
width: 100%;
height: 100%;
}
}

.active .not_hovered {
flex-grow: 1.1;
flex-shrink: 1;
flex-basis: 55px;
width: 100%;
height: 100%;
}

a#complex.selector.example {
a#complex.selector.example {
min-width: 10px;
min-height: 15px;
max-width: 99%;
Expand Down
File renamed without changes.
2 changes: 1 addition & 1 deletion examples/theme.rs
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ fn change_theme(

fn setup(mut commands: Commands, asset_server: Res<AssetServer>) {
let dark = asset_server.load("sheets/dark_theme.css");
let light = asset_server.load("sheets/light_theme.css");
let light = asset_server.load("sheets/light_theme.scss");

// Camera
commands.spawn(Camera2dBundle::default());
Expand Down
46 changes: 29 additions & 17 deletions src/parser.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,20 @@ use crate::{
pub(crate) struct StyleSheetParser;

impl StyleSheetParser {
pub(crate) fn parse(content: &str) -> SmallVec<[StyleRule; 8]> {
let mut input = ParserInput::new(content);
pub(crate) fn parse(content: &str, is_sass: bool) -> SmallVec<[StyleRule; 8]> {
let s;
let mut input = if is_sass {
s = match grass::from_string(content, &grass::Options::default()) {
Ok(s) => s,
Err(e) => {
error!("Failed to parse styles. Error: {}", e);
"".to_string()
}
};
ParserInput::new(&s)
} else {
ParserInput::new(content)
};
let mut parser = Parser::new(&mut input);

RuleListParser::new_for_stylesheet(&mut parser, StyleSheetParser)
Expand Down Expand Up @@ -199,34 +211,34 @@ mod tests {
#[test]
fn parse_empty() {
assert!(
StyleSheetParser::parse("").is_empty(),
StyleSheetParser::parse("",false).is_empty(),
"Should return an empty list of rules"
);
assert!(
StyleSheetParser::parse("{}").is_empty(),
StyleSheetParser::parse("{}",false).is_empty(),
"\"{{}}\" Should return an empty list of rules"
);
assert!(
StyleSheetParser::parse(" {}").is_empty(),
StyleSheetParser::parse(" {}",false).is_empty(),
"\" {{}}\" Should return an empty list of rules"
);
assert!(
StyleSheetParser::parse("# {}").is_empty(),
StyleSheetParser::parse("# {}",false).is_empty(),
"\"# {{}}\" Should return an empty list of rules"
);
assert!(
StyleSheetParser::parse("@@@ {}").is_empty(),
StyleSheetParser::parse("@@@ {}",false).is_empty(),
"Should return an empty list of rules"
);
assert!(
StyleSheetParser::parse("{}{}").is_empty(),
StyleSheetParser::parse("{}{}",false).is_empty(),
"Should return an empty list of rules"
);
}

#[test]
fn parse_single_name_selector_no_property() {
let rules = StyleSheetParser::parse("#id {}");
let rules = StyleSheetParser::parse("#id {}",false);
assert_eq!(rules.len(), 1, "Should have a single rule");

let rule = &rules[0];
Expand All @@ -246,7 +258,7 @@ mod tests {

#[test]
fn parse_single_class_selector_no_property() {
let rules = StyleSheetParser::parse(".class {}");
let rules = StyleSheetParser::parse(".class {}",false);
assert_eq!(rules.len(), 1, "Should have a single rule");

let rule = &rules[0];
Expand All @@ -266,7 +278,7 @@ mod tests {

#[test]
fn parse_single_component_selector_no_property() {
let rules = StyleSheetParser::parse("button {}");
let rules = StyleSheetParser::parse("button {}",false);
assert_eq!(rules.len(), 1, "Should have a single rule");

let rule = &rules[0];
Expand All @@ -286,7 +298,7 @@ mod tests {

#[test]
fn parse_single_complex_class_selector_no_property() {
let rules = StyleSheetParser::parse(".a.b.c.d.e.f.g {}");
let rules = StyleSheetParser::parse(".a.b.c.d.e.f.g {}",false);
assert_eq!(rules.len(), 1, "Should have a single rule");

let rule = &rules[0];
Expand Down Expand Up @@ -319,7 +331,7 @@ mod tests {

#[test]
fn parse_single_composed_selector_no_property() {
let rules = StyleSheetParser::parse("a.b#c.d {}");
let rules = StyleSheetParser::parse("a.b#c.d {}",false);
assert_eq!(rules.len(), 1, "Should have a single rule");

let rule = &rules[0];
Expand Down Expand Up @@ -349,7 +361,7 @@ mod tests {

#[test]
fn parse_multiple_composed_selector_no_property() {
let rules = StyleSheetParser::parse("a.b #c .d e#f .g.h i j.k#l {}");
let rules = StyleSheetParser::parse("a.b #c .d e#f .g.h i j.k#l {}",false);
assert_eq!(rules.len(), 1, "Should have a single rule");

let rule = &rules[0];
Expand Down Expand Up @@ -388,7 +400,7 @@ mod tests {

#[test]
fn parse_single_token() {
let rules = StyleSheetParser::parse("a {b: c}");
let rules = StyleSheetParser::parse("a {b: c}",false);
assert_eq!(rules.len(), 1, "Should have a single rule");

let properties = &rules[0].properties;
Expand Down Expand Up @@ -422,7 +434,7 @@ mod tests {
m: 12.9;
n: "str";
o: p q #r #s "t" 1 45.67% 33px;
}"#,
}"#,false
);

assert_eq!(rules.len(), 1, "Should have a single rule");
Expand Down Expand Up @@ -475,7 +487,7 @@ mod tests {

#[test]
fn parse_multiple_rules() {
let rules = StyleSheetParser::parse(r#"a{a:a}a{a:a}a{a:a}a{a:a}"#);
let rules = StyleSheetParser::parse(r#"a{a:a}a{a:a}a{a:a}a{a:a}"#,false);

assert_eq!(rules.len(), 4, "Should have 4 rules");

Expand Down
4 changes: 2 additions & 2 deletions src/stylesheet.rs
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ impl StyleSheetAsset {
Self {
path: path.to_string(),
hash,
rules: StyleSheetParser::parse(content),
rules: StyleSheetParser::parse(content, path.contains("scss")),
}
}

Expand Down Expand Up @@ -95,6 +95,6 @@ impl AssetLoader for StyleSheetLoader {
}

fn extensions(&self) -> &[&str] {
&["css"]
&["css", "scss"]
}
}
2 changes: 1 addition & 1 deletion src/system.rs
Original file line number Diff line number Diff line change
Expand Up @@ -301,7 +301,7 @@ pub(crate) fn update_style(
mut q_sheets: Query<&mut StyleSheet>,
) {
if !q.is_empty() {
// TODO It is not optimal at all,
// TODO It is not optimal at all,
// it should update only nodes that are affected by change
q_sheets.iter_mut().for_each(|mut sheet| {
sheet.refresh();
Expand Down

0 comments on commit 346ced7

Please sign in to comment.