Skip to content

Commit

Permalink
allow unquoted urls (#227)
Browse files Browse the repository at this point in the history
Co-authored-by: Luca Schneider <[email protected]>
  • Loading branch information
jantimon and Mad-Kat authored Dec 4, 2024
1 parent e58690b commit 3d6e505
Show file tree
Hide file tree
Showing 16 changed files with 142 additions and 4 deletions.
5 changes: 5 additions & 0 deletions .changeset/itchy-brooms-kick.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"yak-swc": patch
---

fix a parsing bug for unquoted urls inside url()
48 changes: 46 additions & 2 deletions packages/yak-swc/css_in_js_parser/src/parse_css.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ pub struct ParserState {
pub current_scopes: Vec<CssScope>,
pub current_declaration: Declaration,
pub pending_css_segment: String,
pub paren_depth: usize,
}

impl ParserState {
Expand All @@ -23,6 +24,7 @@ impl ParserState {
current_scopes: Vec::new(),
current_declaration: Declaration::new(),
pending_css_segment: String::new(),
paren_depth: 0,
}
}
}
Expand Down Expand Up @@ -97,6 +99,7 @@ pub fn parse_css(
state.current_comment_state = CommentStateType::None;
state.is_inside_property_value = false;
state.is_inside_at_rule = false;
state.paren_depth = 0;
state.current_declaration = Declaration::new();
state.pending_css_segment.clone() + css_string
} else {
Expand Down Expand Up @@ -171,9 +174,20 @@ pub fn parse_css(
}
}

// Detect parens outside of strings for property values
// e.g.
// .foo { background: url('https://example.com'); }
if state.is_inside_string.is_none() && state.is_inside_property_value {
if current_character == '(' {
state.paren_depth += 1;
} else if current_character == ')' && state.paren_depth > 0 {
state.paren_depth -= 1;
}
}

// Inside a string, just add the character to the current code no matter what
// e.g. content: "{ ; } @ !"
if state.is_inside_string.is_some() {
if state.is_inside_string.is_some() || state.paren_depth > 0 {
current_code.push(current_character);
state.current_declaration.value.push(current_character);
char_position += 1;
Expand Down Expand Up @@ -389,6 +403,19 @@ mod tests {
assert_debug_snapshot!((state, declarations));
}

#[test]
fn test_parse_css_incomplete_css_1_ending_inside_parens_string() {
let (state, declarations) = parse_css(
r#"
.foo {
.fancy {
background: url(https://example.com
"#,
None,
);
assert_debug_snapshot!((state, declarations));
}

#[test]
fn test_parse_css_incomplete_css_1_ending_outside_a_comment() {
let (state, declarations) = parse_css(
Expand Down Expand Up @@ -437,7 +464,7 @@ mod tests {
}
}
}
background: url("https://example.com");
background: url(https://example.com);
body {
padding: 0;
}
Expand Down Expand Up @@ -494,4 +521,21 @@ mod tests {
);
assert_debug_snapshot!((state, declarations));
}

#[test]
fn test_parse_css_with_dynamic_values() {
let (state1, _) = parse_css(
r#"
.foo {
transform: translate(-50%, -50%) rotate("#,
None,
);
let (state2, _) = parse_css(r#"20deg) translate(0, -88px) rotate("#, Some(state1));
let (_, declarations3) = parse_css(r#"90deg);"#, Some(state2));
assert_eq!(declarations3.len(), 1);
assert_eq!(
declarations3[0].value.trim(),
"translate(-50%, -50%) rotate(20deg) translate(0, -88px) rotate(90deg)"
);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ expression: "(state, declarations)"
closed: false,
},
pending_css_segment: "",
paren_depth: 0,
},
[
Declaration {
Expand Down Expand Up @@ -58,7 +59,7 @@ expression: "(state, declarations)"
},
Declaration {
property: "background",
value: "url(\"https://example.com\")",
value: "url(https://example.com)",
scope: [
CssScope {
name: ".foo",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ expression: "(state, declarations)"
closed: false,
},
pending_css_segment: "",
paren_depth: 0,
},
[
Declaration {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ expression: "(state, declarations)"
closed: false,
},
pending_css_segment: "",
paren_depth: 0,
},
[],
)
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ expression: "(state, declarations)"
closed: false,
},
pending_css_segment: "background: url(\"https://example.com\n ",
paren_depth: 1,
},
[],
)
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ expression: "(state, declarations)"
closed: false,
},
pending_css_segment: "background: url('https://example.com\n ",
paren_depth: 1,
},
[],
)
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
---
source: css_in_js_parser/src/parse_css.rs
expression: "(state, declarations)"
---
(
ParserState {
is_inside_string: None,
current_comment_state: None,
is_inside_property_value: true,
is_inside_at_rule: false,
current_scopes: [
CssScope {
name: ".foo",
scope_type: Selector,
},
CssScope {
name: ".fancy",
scope_type: Selector,
},
],
current_declaration: Declaration {
property: "background",
value: "url(https://example.com\n ",
scope: [],
closed: false,
},
pending_css_segment: "background: url(https://example.com\n ",
paren_depth: 1,
},
[],
)
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ expression: "(state, declarations)"
closed: false,
},
pending_css_segment: "color: blue\n",
paren_depth: 0,
},
[],
)
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ expression: "(state, declarations)"
closed: false,
},
pending_css_segment: "",
paren_depth: 0,
},
[
Declaration {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ expression: "(state, declarations)"
closed: false,
},
pending_css_segment: "color: orange\n",
paren_depth: 0,
},
[],
)
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ expression: "(state1, state2, all_declarations)"
closed: false,
},
pending_css_segment: "color: orange\n",
paren_depth: 0,
},
ParserState {
is_inside_string: None,
Expand All @@ -40,6 +41,7 @@ expression: "(state1, state2, all_declarations)"
closed: false,
},
pending_css_segment: "",
paren_depth: 0,
},
[
Declaration {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
---
source: css_in_js_parser/src/parse_css.rs
assertion_line: 496
expression: "(state, declarations)"
---
(
Expand All @@ -22,6 +21,7 @@ expression: "(state, declarations)"
closed: false,
},
pending_css_segment: "color: orange\n",
paren_depth: 0,
},
[],
)
10 changes: 10 additions & 0 deletions packages/yak-swc/yak_swc/tests/fixture/parens/input.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import { styled, css } from "next-yak";

export const Card = styled.div`
background: url("/card-bg.jpg") no-repeat;
${({$active}) => $active && css`
backgorund: url(/card-bg-active.jpg) no-repeat;
`}
transform: translate(-50%, -50%) rotate(${({ index }) => index * 30}deg)
translate(0, -88px) rotate(${({ index }) => -index * 30}deg);
`;
19 changes: 19 additions & 0 deletions packages/yak-swc/yak_swc/tests/fixture/parens/output.dev.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import { styled, css, __yak_unitPostFix } from "next-yak/internal";
import __styleYak from "./input.yak.module.css!=!./input?./input.yak.module.css";
export const Card = /*YAK Extracted CSS:
.Card {
background: url("/card-bg.jpg") no-repeat;
}
.Card__$active {
backgorund: url(/card-bg-active.jpg) no-repeat;
}
.Card {
transform: translate(-50%, -50%) rotate(var(--Card__transform_m7uBBu))
translate(0, -88px) rotate(var(--Card__transform_m7uBBu-01));
}
*/ /*#__PURE__*/ styled.div(__styleYak.Card, ({ $active })=>$active && /*#__PURE__*/ css(__styleYak.Card__$active), {
"style": {
"--Card__transform_m7uBBu": __yak_unitPostFix(({ index })=>index * 30, "deg"),
"--Card__transform_m7uBBu-01": __yak_unitPostFix(({ index })=>-index * 30, "deg")
}
});
19 changes: 19 additions & 0 deletions packages/yak-swc/yak_swc/tests/fixture/parens/output.prod.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import { styled, css, __yak_unitPostFix } from "next-yak/internal";
import __styleYak from "./input.yak.module.css!=!./input?./input.yak.module.css";
export const Card = /*YAK Extracted CSS:
.Card {
background: url("/card-bg.jpg") no-repeat;
}
.Card__$active {
backgorund: url(/card-bg-active.jpg) no-repeat;
}
.Card {
transform: translate(-50%, -50%) rotate(var(--ym7uBBu))
translate(0, -88px) rotate(var(--ym7uBBu1));
}
*/ /*#__PURE__*/ styled.div(__styleYak.Card, ({ $active })=>$active && /*#__PURE__*/ css(__styleYak.Card__$active), {
"style": {
"--ym7uBBu": __yak_unitPostFix(({ index })=>index * 30, "deg"),
"--ym7uBBu1": __yak_unitPostFix(({ index })=>-index * 30, "deg")
}
});

0 comments on commit 3d6e505

Please sign in to comment.