Accept literals in attribute names ()

* Accept literals in attribute names

* Accept literals in attribute names

* Propper handling of literals in name_to_string()
This commit is contained in:
Teodor Källman 2023-11-14 05:05:48 +01:00 committed by GitHub
parent d1cfde53b6
commit 8c47208568
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 55 additions and 7 deletions

View file

@ -6,6 +6,8 @@
[#377](https://github.com/lambda-fairy/maud/pull/377)
- Implement `Render` for `Arc<T>`
[#380](https://github.com/lambda-fairy/maud/pull/380)
- Accept literals in attribute names
[#396](https://github.com/lambda-fairy/maud/pull/396)
## [0.25.0] - 2023-04-16

View file

@ -181,6 +181,34 @@ fn hyphens_in_attribute_names() {
);
}
#[test]
fn string_literals_in_attribute_names() {
let result = html! { this "@sentence:-is.not"="false" of-course {} };
assert_eq!(
result.into_string(),
r#"<this @sentence:-is.not="false" of-course></this>"#
);
}
#[test]
fn raw_string_literals_in_attribute_names() {
let result = html! { this r#"@sentence:-is.not"#="false" of-course {} };
assert_eq!(
result.into_string(),
r#"<this @sentence:-is.not="false" of-course></this>"#
);
}
#[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 {} };
assert_eq!(
result.into_string(),
r#"<this byte_string="false" 123="123" 2.5 true a="a" b="b" of-course></this>"#
);
}
#[test]
fn class_shorthand() {
let result = html! { p { "Hi, " span.name { "Lyra" } "!" } };

View file

@ -1,5 +1,6 @@
use proc_macro2::{TokenStream, TokenTree};
use proc_macro_error::SpanRange;
use syn::Lit;
#[derive(Debug)]
pub enum Markup {
@ -217,5 +218,21 @@ pub fn join_ranges<I: IntoIterator<Item = SpanRange>>(ranges: I) -> SpanRange {
}
pub fn name_to_string(name: TokenStream) -> String {
name.into_iter().map(|token| token.to_string()).collect()
name.into_iter()
.map(|token| {
if let TokenTree::Literal(literal) = token {
match Lit::new(literal.clone()) {
Lit::Str(str) => str.value(),
Lit::Char(char) => char.value().to_string(),
Lit::ByteStr(byte) => {
String::from_utf8(byte.value()).expect("Invalid utf8 byte")
}
Lit::Byte(byte) => (byte.value() as char).to_string(),
_ => literal.to_string(),
}
} else {
token.to_string()
}
})
.collect()
}

View file

@ -702,12 +702,13 @@ impl Parser {
/// Parses an identifier, without dealing with namespaces.
fn try_name(&mut self) -> Option<TokenStream> {
let mut result = Vec::new();
if let Some(token @ TokenTree::Ident(_)) = self.peek() {
match self.peek() {
Some(token @ TokenTree::Ident(_)) | Some(token @ TokenTree::Literal(_)) => {
self.advance();
result.push(token);
} else {
return None;
}
_ => return None,
};
let mut expect_ident = false;
loop {
expect_ident = match self.peek() {