increase code coverage
This commit is contained in:
parent
6cd208f41d
commit
743ad7a340
@ -263,7 +263,7 @@ impl Environment {
|
||||
for name in (*self.scopes.global_variables()).borrow().keys() {
|
||||
if (*module).borrow().var_exists(*name) {
|
||||
return Err((
|
||||
format!("This module and the new module both define a variable named \"{}\".", name = name)
|
||||
format!("This module and the new module both define a variable named \"{name}\".", name = name)
|
||||
, span).into());
|
||||
}
|
||||
}
|
||||
|
@ -60,7 +60,7 @@ impl<'a, 'c, P: StylesheetParser<'a>> ValueParser<'a, 'c, P> {
|
||||
}
|
||||
|
||||
if value_parser.inside_bracketed_list {
|
||||
let start = parser.toks().cursor();
|
||||
let bracket_start = parser.toks().cursor();
|
||||
|
||||
parser.expect_char('[')?;
|
||||
parser.whitespace()?;
|
||||
@ -71,14 +71,12 @@ impl<'a, 'c, P: StylesheetParser<'a>> ValueParser<'a, 'c, P> {
|
||||
separator: ListSeparator::Undecided,
|
||||
brackets: Brackets::Bracketed,
|
||||
})
|
||||
.span(parser.toks_mut().span_from(start)));
|
||||
.span(parser.toks_mut().span_from(bracket_start)));
|
||||
}
|
||||
|
||||
Some(start)
|
||||
} else {
|
||||
None
|
||||
};
|
||||
|
||||
value_parser.start = parser.toks().cursor();
|
||||
|
||||
value_parser.single_expression = Some(value_parser.parse_single_expression(parser)?);
|
||||
|
||||
let mut value = value_parser.parse_value(parser)?;
|
||||
@ -392,6 +390,7 @@ impl<'a, 'c, P: StylesheetParser<'a>> ValueParser<'a, 'c, P> {
|
||||
self.reset_state(parser)?;
|
||||
continue;
|
||||
}
|
||||
// todo: does this branch ever get hit
|
||||
}
|
||||
|
||||
if self.single_expression.is_none() {
|
||||
@ -400,7 +399,7 @@ impl<'a, 'c, P: StylesheetParser<'a>> ValueParser<'a, 'c, P> {
|
||||
|
||||
self.resolve_space_expressions(parser)?;
|
||||
|
||||
// [resolveSpaceExpressions can modify [singleExpression_], but it
|
||||
// [resolveSpaceExpressions] can modify [singleExpression_], but it
|
||||
// can't set it to null`.
|
||||
self.comma_expressions
|
||||
.get_or_insert_with(Default::default)
|
||||
@ -1368,62 +1367,6 @@ impl<'a, 'c, P: StylesheetParser<'a>> ValueParser<'a, 'c, P> {
|
||||
.span(span))
|
||||
}
|
||||
|
||||
fn try_parse_url_contents(
|
||||
parser: &mut P,
|
||||
name: Option<String>,
|
||||
) -> SassResult<Option<Interpolation>> {
|
||||
let start = parser.toks().cursor();
|
||||
|
||||
if !parser.scan_char('(') {
|
||||
return Ok(None);
|
||||
}
|
||||
|
||||
parser.whitespace_without_comments();
|
||||
|
||||
// Match Ruby Sass's behavior: parse a raw URL() if possible, and if not
|
||||
// backtrack and re-parse as a function expression.
|
||||
let mut buffer = Interpolation::new();
|
||||
buffer.add_string(name.unwrap_or_else(|| "url".to_owned()));
|
||||
buffer.add_char('(');
|
||||
|
||||
while let Some(next) = parser.toks().peek() {
|
||||
match next.kind {
|
||||
'\\' => {
|
||||
buffer.add_string(parser.parse_escape(false)?);
|
||||
}
|
||||
'!' | '%' | '&' | '*'..='~' | '\u{80}'..=char::MAX => {
|
||||
parser.toks_mut().next();
|
||||
buffer.add_char(next.kind);
|
||||
}
|
||||
'#' => {
|
||||
if matches!(parser.toks().peek_n(1), Some(Token { kind: '{', .. })) {
|
||||
buffer.add_interpolation(parser.parse_single_interpolation()?);
|
||||
} else {
|
||||
parser.toks_mut().next();
|
||||
buffer.add_char(next.kind);
|
||||
}
|
||||
}
|
||||
')' => {
|
||||
parser.toks_mut().next();
|
||||
buffer.add_char(next.kind);
|
||||
|
||||
return Ok(Some(buffer));
|
||||
}
|
||||
' ' | '\t' | '\n' | '\r' => {
|
||||
parser.whitespace_without_comments();
|
||||
|
||||
if !parser.toks().next_char_is(')') {
|
||||
break;
|
||||
}
|
||||
}
|
||||
_ => break,
|
||||
}
|
||||
}
|
||||
|
||||
parser.toks_mut().set_cursor(start);
|
||||
Ok(None)
|
||||
}
|
||||
|
||||
pub(crate) fn try_parse_special_function(
|
||||
parser: &mut P,
|
||||
name: &str,
|
||||
@ -1466,15 +1409,13 @@ impl<'a, 'c, P: StylesheetParser<'a>> ValueParser<'a, 'c, P> {
|
||||
buffer.add_char('(');
|
||||
}
|
||||
"url" => {
|
||||
return Ok(
|
||||
ValueParser::try_parse_url_contents(parser, None)?.map(|contents| {
|
||||
return Ok(parser.try_url_contents(None)?.map(|contents| {
|
||||
AstExpr::String(
|
||||
StringExpr(contents, QuoteKind::None),
|
||||
parser.toks_mut().span_from(start),
|
||||
)
|
||||
.span(parser.toks_mut().span_from(start))
|
||||
}),
|
||||
)
|
||||
}))
|
||||
}
|
||||
_ => return Ok(None),
|
||||
}
|
||||
|
@ -21,6 +21,6 @@ pub(crate) fn as_hex(c: char) -> u32 {
|
||||
'0'..='9' => c as u32 - '0' as u32,
|
||||
'A'..='F' => 10 + c as u32 - 'A' as u32,
|
||||
'a'..='f' => 10 + c as u32 - 'a' as u32,
|
||||
_ => panic!(),
|
||||
_ => unreachable!(),
|
||||
}
|
||||
}
|
||||
|
@ -285,7 +285,7 @@ impl<V: fmt::Debug + Clone> MapView for MergedMapView<V> {
|
||||
}
|
||||
}
|
||||
|
||||
panic!("New entries may not be added to MergedMapView")
|
||||
unreachable!("New entries may not be added to MergedMapView")
|
||||
}
|
||||
|
||||
fn keys(&self) -> Vec<Identifier> {
|
||||
|
@ -55,26 +55,8 @@ impl PartialEq for Value {
|
||||
Value::String(s2, ..) => s1 == s2,
|
||||
_ => false,
|
||||
},
|
||||
Value::Dimension(SassNumber {
|
||||
num: n,
|
||||
unit,
|
||||
as_slash: _,
|
||||
}) => match other {
|
||||
Value::Dimension(SassNumber {
|
||||
num: n2,
|
||||
unit: unit2,
|
||||
as_slash: _,
|
||||
}) => {
|
||||
if !unit.comparable(unit2) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (*unit2 == Unit::None || *unit == Unit::None) && unit != unit2 {
|
||||
return false;
|
||||
}
|
||||
|
||||
*n == n2.convert(unit2, unit)
|
||||
}
|
||||
Value::Dimension(n1) => match other {
|
||||
Value::Dimension(n2) => n1 == n2,
|
||||
_ => false,
|
||||
},
|
||||
Value::List(list1, sep1, brackets1) => match other {
|
||||
|
@ -189,10 +189,20 @@ impl SassNumber {
|
||||
|
||||
impl PartialEq for SassNumber {
|
||||
fn eq(&self, other: &Self) -> bool {
|
||||
self.num == other.num && self.unit == other.unit
|
||||
if !self.unit.comparable(&other.unit) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (other.unit == Unit::None || self.unit == Unit::None) && self.unit != other.unit {
|
||||
return false;
|
||||
}
|
||||
|
||||
self.num == other.num.convert(&other.unit, &self.unit)
|
||||
}
|
||||
}
|
||||
|
||||
impl Eq for SassNumber {}
|
||||
|
||||
impl Add<SassNumber> for SassNumber {
|
||||
type Output = SassNumber;
|
||||
fn add(self, rhs: SassNumber) -> Self::Output {
|
||||
@ -285,5 +295,3 @@ impl Div<SassNumber> for SassNumber {
|
||||
self.multiply_units(self.num.0 / rhs.num.0, rhs.unit.invert())
|
||||
}
|
||||
}
|
||||
|
||||
impl Eq for SassNumber {}
|
||||
|
@ -262,6 +262,15 @@ test!(
|
||||
}",
|
||||
"@unknown {\n .bar {\n a: b;\n }\n}\n"
|
||||
);
|
||||
test!(
|
||||
query_begins_with_interpolation,
|
||||
"a {
|
||||
@at-root (#{wi}th: rule) {
|
||||
color: red;
|
||||
}
|
||||
}",
|
||||
"a {\n color: red;\n}\n"
|
||||
);
|
||||
error!(
|
||||
missing_closing_curly_brace,
|
||||
"@at-root {", "Error: expected \"}\"."
|
||||
|
@ -635,3 +635,26 @@ error!(
|
||||
single_arg_saturate_expects_number,
|
||||
"a {\n color: saturate(red);\n}\n", "Error: $amount: red is not a number."
|
||||
);
|
||||
error!(
|
||||
hex_color_starts_with_number_non_hex_digit_at_position_2,
|
||||
"a {\n color: #0zz;\n}\n", "Error: Expected hex digit."
|
||||
);
|
||||
error!(
|
||||
hex_color_starts_with_number_non_hex_digit_at_position_3,
|
||||
"a {\n color: #00z;\n}\n", "Error: Expected hex digit."
|
||||
);
|
||||
test!(
|
||||
hex_color_starts_with_number_non_hex_digit_at_position_4,
|
||||
"a {\n color: #000z;\n}\n",
|
||||
"a {\n color: #000 z;\n}\n"
|
||||
);
|
||||
test!(
|
||||
#[ignore = "we don't emit 4 character hex colors correctly"]
|
||||
hex_color_starts_with_number_non_hex_digit_at_position_5,
|
||||
"a {\n color: #0000z;\n}\n",
|
||||
"a {\n color: rgba(0, 0, 0, 0) z;\n}\n"
|
||||
);
|
||||
error!(
|
||||
hex_color_starts_with_number_non_hex_digit_at_position_6,
|
||||
"a {\n color: #00000z;\n}\n", "Error: Expected hex digit."
|
||||
);
|
||||
|
@ -170,3 +170,4 @@ test!(
|
||||
"a {/**/}",
|
||||
"a { /**/ }\n"
|
||||
);
|
||||
test!(silent_comment_as_child, "a {\n// silent\n}\n", "");
|
||||
|
@ -267,3 +267,10 @@ test!(
|
||||
}",
|
||||
"a {\n color: true;\n}\n"
|
||||
);
|
||||
test!(
|
||||
calculation_equality_converts_units,
|
||||
"a {
|
||||
color: calc(1in + 1rem) == calc(2.54cm + 1rem);
|
||||
}",
|
||||
"a {\n color: true;\n}\n"
|
||||
);
|
||||
|
@ -273,3 +273,7 @@ error!(
|
||||
nothing_after_dot_in_value_preceded_by_minus_sign,
|
||||
"a { color: -.", "Error: Expected digit."
|
||||
);
|
||||
error!(
|
||||
nothing_after_bang_in_space_separated_list,
|
||||
"a { color: a !", r#"Error: Expected "important"."#
|
||||
);
|
||||
|
@ -409,6 +409,13 @@ test!(
|
||||
}",
|
||||
"a {\n color: before;\n}\n"
|
||||
);
|
||||
test!(
|
||||
can_parse_module_variable_declaration,
|
||||
"@function foo() {
|
||||
foo.$bar: red;
|
||||
}",
|
||||
""
|
||||
);
|
||||
error!(
|
||||
function_no_return,
|
||||
"@function foo() {}
|
||||
|
@ -523,6 +523,72 @@ test!(
|
||||
);
|
||||
error!(unclosed_single_quote, r#"@import '"#, "Error: Expected '.");
|
||||
error!(unclosed_double_quote, r#"@import ""#, "Error: Expected \".");
|
||||
error!(
|
||||
dynamic_disallowed_inside_if,
|
||||
r#"@if true {
|
||||
@import "foo";
|
||||
}"#,
|
||||
"Error: This at-rule is not allowed here."
|
||||
);
|
||||
error!(
|
||||
dynamic_disallowed_inside_while,
|
||||
r#"@while true {
|
||||
@import "foo";
|
||||
}"#,
|
||||
"Error: This at-rule is not allowed here."
|
||||
);
|
||||
error!(
|
||||
dynamic_disallowed_inside_for,
|
||||
r#"@for $i from 0 through 1 {
|
||||
@import "foo";
|
||||
}"#,
|
||||
"Error: This at-rule is not allowed here."
|
||||
);
|
||||
error!(
|
||||
dynamic_disallowed_inside_each,
|
||||
r#"@each $i in a {
|
||||
@import "foo";
|
||||
}"#,
|
||||
"Error: This at-rule is not allowed here."
|
||||
);
|
||||
test!(
|
||||
static_allowed_inside_if,
|
||||
r#"@if true {
|
||||
@import "foo.css";
|
||||
}"#,
|
||||
"@import \"foo.css\";\n"
|
||||
);
|
||||
test!(
|
||||
static_allowed_inside_while,
|
||||
r#"
|
||||
$a: 0;
|
||||
@while $a == 0 {
|
||||
@import "foo.css";
|
||||
$a: 1;
|
||||
}"#,
|
||||
"@import \"foo.css\";\n"
|
||||
);
|
||||
test!(
|
||||
static_allowed_inside_for,
|
||||
r#"@for $i from 0 to 1 {
|
||||
@import "foo.css";
|
||||
}"#,
|
||||
"@import \"foo.css\";\n"
|
||||
);
|
||||
test!(
|
||||
static_allowed_inside_each,
|
||||
r#"@each $i in a {
|
||||
@import "foo.css";
|
||||
}"#,
|
||||
"@import \"foo.css\";\n"
|
||||
);
|
||||
error!(
|
||||
dynamic_disallowed_inside_mixin,
|
||||
r#"@mixin foo {
|
||||
@import "foo";
|
||||
}"#,
|
||||
"Error: This at-rule is not allowed here."
|
||||
);
|
||||
|
||||
// todo: edge case tests for plain css imports moved to top
|
||||
// todo: test for calling paths, e.g. `grass b\index.scss`
|
||||
|
@ -412,6 +412,26 @@ test!(
|
||||
"a {\n color: [null];\n}\n",
|
||||
"a {\n color: [];\n}\n"
|
||||
);
|
||||
test!(
|
||||
space_separated_bracketed_list_in_parens,
|
||||
"a {\n color: ([a b]);\n}\n",
|
||||
"a {\n color: [a b];\n}\n"
|
||||
);
|
||||
test!(
|
||||
does_not_eval_division_inside_space_separated_bracketed_list_in_parens,
|
||||
"a {\n color: ([1/2 1/2]);\n}\n",
|
||||
"a {\n color: [1/2 1/2];\n}\n"
|
||||
);
|
||||
test!(
|
||||
comma_separated_bracketed_list_in_parens,
|
||||
"a {\n color: ([a, b]);\n}\n",
|
||||
"a {\n color: [a, b];\n}\n"
|
||||
);
|
||||
test!(
|
||||
does_not_eval_division_inside_comma_separated_bracketed_list_in_parens,
|
||||
"a {\n color: ([1/2, 1/2]);\n}\n",
|
||||
"a {\n color: [1/2, 1/2];\n}\n"
|
||||
);
|
||||
test!(
|
||||
comma_separated_list_has_element_beginning_with_capital_A,
|
||||
"a {\n color: a, A, \"Noto Color Emoji\";\n}\n",
|
||||
|
25
tests/map.rs
25
tests/map.rs
@ -280,6 +280,27 @@ test!(
|
||||
"a {\n color: (a: b)==(a: c);\n}\n",
|
||||
"a {\n color: false;\n}\n"
|
||||
);
|
||||
test!(
|
||||
important_as_key,
|
||||
"a {\n color: inspect((a: b, !important: c));\n}\n",
|
||||
"a {\n color: (a: b, !important: c);\n}\n"
|
||||
);
|
||||
error!(
|
||||
bang_identifier_not_important_as_key,
|
||||
"a {\n color: inspect((a: b, !a: c));\n}\n", r#"Error: expected ")"."#
|
||||
);
|
||||
error!(
|
||||
bang_identifier_not_important_but_starts_with_i_as_key,
|
||||
"a {\n color: inspect((a: b, !i: c));\n}\n", r#"Error: Expected "important"."#
|
||||
);
|
||||
error!(
|
||||
bang_identifier_not_important_ascii_whitespace_as_key,
|
||||
"a {\n color: inspect((a: b, ! : c));\n}\n", r#"Error: Expected "important"."#
|
||||
);
|
||||
error!(
|
||||
bang_identifier_not_important_loud_comment_as_key,
|
||||
"a {\n color: inspect((a: b, !/**/: c));\n}\n", r#"Error: expected ")"."#
|
||||
);
|
||||
test!(
|
||||
empty_with_single_line_comments,
|
||||
"$foo: (\n \n // :/a.b\n \n );
|
||||
@ -314,3 +335,7 @@ error!(
|
||||
denies_comma_separated_list_without_parens_as_key,
|
||||
"$map: (a: 1, b, c, d: e);", "Error: expected \":\"."
|
||||
);
|
||||
error!(
|
||||
nothing_after_first_comma,
|
||||
"$map: (a: b,", "Error: expected \")\"."
|
||||
);
|
||||
|
@ -570,6 +570,17 @@ test!(
|
||||
}"#,
|
||||
"@media (min-width: \\0 ) {\n a {\n color: red;\n }\n}\n"
|
||||
);
|
||||
test!(
|
||||
simple_unmergeable,
|
||||
"a {
|
||||
@media a {
|
||||
@media b {
|
||||
color: red;
|
||||
}
|
||||
}
|
||||
}",
|
||||
""
|
||||
);
|
||||
error!(
|
||||
media_query_has_quoted_closing_paren,
|
||||
r#"@media ('a)'w) {
|
||||
|
@ -35,6 +35,32 @@ test!(
|
||||
"a {\n color: 1 or 2;\n}\n",
|
||||
grass::Options::default().input_syntax(InputSyntax::Css)
|
||||
);
|
||||
test!(
|
||||
simple_calculation,
|
||||
"a {
|
||||
color: calc(1 + 1);
|
||||
}",
|
||||
"a {\n color: 2;\n}\n",
|
||||
grass::Options::default().input_syntax(InputSyntax::Css)
|
||||
);
|
||||
test!(
|
||||
simple_url_import,
|
||||
r#"@import url("foo");"#,
|
||||
"@import url(\"foo\");\n",
|
||||
grass::Options::default().input_syntax(InputSyntax::Css)
|
||||
);
|
||||
test!(
|
||||
import_no_file_extension,
|
||||
r#"@import "foo";"#,
|
||||
"@import \"foo\";\n",
|
||||
grass::Options::default().input_syntax(InputSyntax::Css)
|
||||
);
|
||||
test!(
|
||||
import_with_condition,
|
||||
r#"@import "foo" screen and (foo: bar);"#,
|
||||
"@import \"foo\" screen and (foo: bar);\n",
|
||||
grass::Options::default().input_syntax(InputSyntax::Css)
|
||||
);
|
||||
test!(
|
||||
does_not_evaluate_not,
|
||||
"a {
|
||||
@ -155,6 +181,14 @@ error!(
|
||||
"Error: Operators aren't allowed in plain CSS.",
|
||||
grass::Options::default().input_syntax(InputSyntax::Css)
|
||||
);
|
||||
error!(
|
||||
disallows_interpolation,
|
||||
"a {
|
||||
color: a#{b}c;
|
||||
}",
|
||||
"Error: Interpolation isn't allowed in plain CSS.",
|
||||
grass::Options::default().input_syntax(InputSyntax::Css)
|
||||
);
|
||||
test!(
|
||||
allows_rgb_function,
|
||||
"a {
|
||||
@ -163,3 +197,13 @@ test!(
|
||||
"a {\n color: rgb(true, a, b);\n}\n",
|
||||
grass::Options::default().input_syntax(InputSyntax::Css)
|
||||
);
|
||||
test!(
|
||||
simple_supports,
|
||||
"@supports (foo) {
|
||||
a {
|
||||
color: red;
|
||||
}
|
||||
}",
|
||||
"@supports (foo) {\n a {\n color: red;\n }\n}\n",
|
||||
grass::Options::default().input_syntax(InputSyntax::Css)
|
||||
);
|
||||
|
@ -81,6 +81,18 @@ test!(
|
||||
"/* loud */\n",
|
||||
grass::Options::default().input_syntax(InputSyntax::Sass)
|
||||
);
|
||||
test!(
|
||||
special_mixin_and_include_characters,
|
||||
r#"
|
||||
=foo
|
||||
color: red
|
||||
|
||||
a
|
||||
+foo
|
||||
"#,
|
||||
"a {\n color: red;\n}\n",
|
||||
grass::Options::default().input_syntax(InputSyntax::Sass)
|
||||
);
|
||||
error!(
|
||||
multiline_comment_in_value_position,
|
||||
r#"
|
||||
@ -90,3 +102,15 @@ loud */ red
|
||||
"Error: expected */.",
|
||||
grass::Options::default().input_syntax(InputSyntax::Sass)
|
||||
);
|
||||
error!(
|
||||
document_starts_with_spaces,
|
||||
r#" "#,
|
||||
"Error: Indenting at the beginning of the document is illegal.",
|
||||
grass::Options::default().input_syntax(InputSyntax::Sass)
|
||||
);
|
||||
error!(
|
||||
document_starts_with_tab,
|
||||
"\t",
|
||||
"Error: Indenting at the beginning of the document is illegal.",
|
||||
grass::Options::default().input_syntax(InputSyntax::Sass)
|
||||
);
|
||||
|
@ -927,6 +927,10 @@ error!(
|
||||
denies_optional_in_selector,
|
||||
"a !optional {}", "Error: expected \"{\"."
|
||||
);
|
||||
error!(
|
||||
child_selector_starts_with_forward_slash,
|
||||
"a { /b { } }", "Error: expected selector."
|
||||
);
|
||||
|
||||
// todo:
|
||||
// [attr=url] {
|
||||
|
@ -276,6 +276,30 @@ test!(
|
||||
"a {\n color: calc(1dpi + 1dppx);\n}\n",
|
||||
"a {\n color: 97dpi;\n}\n"
|
||||
);
|
||||
test!(
|
||||
ternary_inside_calc,
|
||||
"a {\n color: calc(if(true, 1, unit(foo)));\n}\n",
|
||||
"a {\n color: 1;\n}\n"
|
||||
);
|
||||
test!(
|
||||
retains_parens_around_var_in_calc,
|
||||
"a {\n color: calc((var(--a)) + 1rem);\n}\n",
|
||||
"a {\n color: calc((var(--a)) + 1rem);\n}\n"
|
||||
);
|
||||
test!(
|
||||
removes_superfluous_parens_around_function_call_in_calc,
|
||||
"a {\n color: calc((foo(--a)) + 1rem);\n}\n",
|
||||
"a {\n color: calc(foo(--a) + 1rem);\n}\n"
|
||||
);
|
||||
test!(
|
||||
calculation_inside_calc,
|
||||
"a {\n color: calc(calc(1px + 1rem) * calc(2px - 2in));\n}\n",
|
||||
"a {\n color: calc((1px + 1rem) * -190px);\n}\n"
|
||||
);
|
||||
error!(
|
||||
escaped_close_paren_inside_calc,
|
||||
"a {\n color: calc(\\));\n}\n", r#"Error: Expected "(" or "."."#
|
||||
);
|
||||
error!(
|
||||
nothing_after_last_arg,
|
||||
"a { color: calc(1 + 1", r#"Error: expected "+", "-", "*", "/", or ")"."#
|
||||
|
@ -21,6 +21,31 @@ test!(
|
||||
"a {\n color: u+27a;\n}\n",
|
||||
"a {\n color: u+27a;\n}\n"
|
||||
);
|
||||
test!(
|
||||
second_element_in_list,
|
||||
"a {\n color: a u+55;\n}\n",
|
||||
"a {\n color: a u+55;\n}\n"
|
||||
);
|
||||
test!(
|
||||
escaped_lowercase_u,
|
||||
"a {\n color: \\75+55;\n}\n",
|
||||
"a {\n color: u55;\n}\n"
|
||||
);
|
||||
test!(
|
||||
escaped_uppercase_u,
|
||||
"a {\n color: \\55+55;\n}\n",
|
||||
"a {\n color: U55;\n}\n"
|
||||
);
|
||||
test!(
|
||||
escaped_lowercase_u_with_space_after_escape,
|
||||
"a {\n color: \\75 +55;\n}\n",
|
||||
"a {\n color: u55;\n}\n"
|
||||
);
|
||||
test!(
|
||||
escaped_uppercase_u_with_space_after_escape,
|
||||
"a {\n color: \\55 +55;\n}\n",
|
||||
"a {\n color: U55;\n}\n"
|
||||
);
|
||||
error!(
|
||||
interpolated_range,
|
||||
"a {\n color: U+2A#{70}C;\n}\n", "Error: Expected end of identifier."
|
||||
@ -37,6 +62,19 @@ error!(
|
||||
length_of_6_with_question_mark,
|
||||
"a {\n color: U+123456?;\n}\n", "Error: Expected at most 6 digits."
|
||||
);
|
||||
|
||||
// todo: escaped u at start \75 and \55
|
||||
// with and without space
|
||||
error!(
|
||||
nothing_after_plus_lowercase,
|
||||
"a {\n color: u+;\n}\n", r#"Error: Expected hex digit or "?"."#
|
||||
);
|
||||
error!(
|
||||
nothing_after_plus_uppercase,
|
||||
"a {\n color: U+;\n}\n", r#"Error: Expected hex digit or "?"."#
|
||||
);
|
||||
error!(
|
||||
second_part_of_range_is_empty,
|
||||
"a {\n color: u+55-;\n}\n", r#"Error: Expected hex digit."#
|
||||
);
|
||||
error!(
|
||||
second_part_of_range_is_more_than_6_chars,
|
||||
"a {\n color: u+55-1234567;\n}\n", r#"Error: Expected at most 6 digits."#
|
||||
);
|
||||
|
@ -171,6 +171,11 @@ test!(
|
||||
"a {\n color: url(#);\n}\n",
|
||||
"a {\n color: url(#);\n}\n"
|
||||
);
|
||||
test!(
|
||||
escaped_close_paren,
|
||||
"a {\n color: url(\\));\n}\n",
|
||||
"a {\n color: url(\\));\n}\n"
|
||||
);
|
||||
error!(
|
||||
url_nothing_after_forward_slash_in_interpolation,
|
||||
"a { color: url(#{/", "Error: Expected expression."
|
||||
|
Loading…
x
Reference in New Issue
Block a user