diff --git a/maud/tests/basic_syntax.rs b/maud/tests/basic_syntax.rs index 96e0235e..c2c5dc5f 100644 --- a/maud/tests/basic_syntax.rs +++ b/maud/tests/basic_syntax.rs @@ -201,11 +201,19 @@ fn raw_string_literals_in_attribute_names() { #[test] fn other_literals_in_attribute_names() { - let result = - html! { this b"byte_string"="false" 123="123" 2.5 true 'a'="a" b'b'="b" of-course {} }; + let result = html! { this r#"raw_string"#="false" 123="123" 123usize "2.5" true of-course {} }; assert_eq!( result.into_string(), - r#""# + r#""# + ); +} + +#[test] +fn idents_and_literals_in_names() { + let result = html! { custom:element-001 test:123-"test"="123" .m-2.p-2 {} }; + assert_eq!( + result.into_string(), + r#""# ); } diff --git a/maud/tests/warnings/non-string-literal.stderr b/maud/tests/warnings/non-string-literal.stderr index 635617b8..7755e3f0 100644 --- a/maud/tests/warnings/non-string-literal.stderr +++ b/maud/tests/warnings/non-string-literal.stderr @@ -1,41 +1,29 @@ -error: literal must be double-quoted: `"42"` - --> $DIR/non-string-literal.rs:5:9 - | -5 | 42 - | ^^ - -error: literal must be double-quoted: `"42usize"` - --> $DIR/non-string-literal.rs:6:9 - | -6 | 42usize - | ^^^^^^^ - error: literal must be double-quoted: `"42.0"` - --> $DIR/non-string-literal.rs:7:9 + --> tests/warnings/non-string-literal.rs:7:9 | 7 | 42.0 | ^^^^ error: literal must be double-quoted: `"a"` - --> $DIR/non-string-literal.rs:8:9 + --> tests/warnings/non-string-literal.rs:8:9 | 8 | 'a' | ^^^ error: expected string - --> $DIR/non-string-literal.rs:9:9 + --> tests/warnings/non-string-literal.rs:9:9 | 9 | b"a" | ^^^^ error: expected string - --> $DIR/non-string-literal.rs:10:9 + --> tests/warnings/non-string-literal.rs:10:9 | 10 | b'a' | ^^^^ error: attribute value must be a string - --> $DIR/non-string-literal.rs:13:24 + --> tests/warnings/non-string-literal.rs:13:24 | 13 | input disabled=true; | ^^^^ @@ -44,7 +32,7 @@ error: attribute value must be a string = help: to toggle the attribute, use square brackets: `disabled[some_boolean_flag]` error: attribute value must be a string - --> $DIR/non-string-literal.rs:14:24 + --> tests/warnings/non-string-literal.rs:14:24 | 14 | input disabled=false; | ^^^^^ diff --git a/maud_macros/src/parse.rs b/maud_macros/src/parse.rs index 662b8309..1b85d1f3 100644 --- a/maud_macros/src/parse.rs +++ b/maud_macros/src/parse.rs @@ -204,7 +204,13 @@ impl Parser { } // Boolean literals are idents, so `Lit::Bool` is handled in // `markup`, not here. - Lit::Int(..) | Lit::Float(..) => { + Lit::Int(lit_int) => { + return ast::Markup::Literal { + content: lit_int.to_string(), + span: SpanRange::single_span(literal.span()), + }; + } + Lit::Float(..) => { emit_error!(literal, r#"literal must be double-quoted: `"{}"`"#, literal); } Lit::Char(lit_char) => { @@ -702,27 +708,32 @@ impl Parser { /// Parses an identifier, without dealing with namespaces. fn try_name(&mut self) -> Option { let mut result = Vec::new(); - match self.peek() { - Some(token @ TokenTree::Ident(_)) | Some(token @ TokenTree::Literal(_)) => { - self.advance(); - result.push(token); - } - _ => return None, - }; - let mut expect_ident = false; + let mut expect_ident_or_literal = true; loop { - expect_ident = match self.peek() { + expect_ident_or_literal = match self.peek() { Some(TokenTree::Punct(ref punct)) if punct.as_char() == '-' => { self.advance(); result.push(TokenTree::Punct(punct.clone())); true } - Some(TokenTree::Ident(ref ident)) if expect_ident => { + Some(token @ TokenTree::Ident(_)) if expect_ident_or_literal => { self.advance(); - result.push(TokenTree::Ident(ident.clone())); + result.push(token); false } - _ => break, + Some(TokenTree::Literal(ref literal)) if expect_ident_or_literal => { + self.literal(literal.clone()); + self.advance(); + result.push(TokenTree::Literal(literal.clone())); + false + } + _ => { + if result.is_empty() { + return None; + } else { + break; + } + } }; } Some(result.into_iter().collect())