Accept literals in attribute names (#396)
* Accept literals in attribute names * Accept literals in attribute names * Propper handling of literals in name_to_string()
This commit is contained in:
parent
d1cfde53b6
commit
8c47208568
4 changed files with 55 additions and 7 deletions
|
@ -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
|
||||
|
||||
|
|
|
@ -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" } "!" } };
|
||||
|
|
|
@ -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()
|
||||
}
|
||||
|
|
|
@ -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() {
|
||||
|
|
Loading…
Add table
Reference in a new issue