Skip to content

Commit

Permalink
Accept literals in attribute names (#396)
Browse files Browse the repository at this point in the history
* Accept literals in attribute names

* Accept literals in attribute names

* Propper handling of literals in name_to_string()
  • Loading branch information
RedPhoenixQ committed Nov 14, 2023
1 parent d1cfde5 commit 8c47208
Show file tree
Hide file tree
Showing 4 changed files with 55 additions and 7 deletions.
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down
28 changes: 28 additions & 0 deletions maud/tests/basic_syntax.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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" } "!" } };
Expand Down
19 changes: 18 additions & 1 deletion maud_macros/src/ast.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
use proc_macro2::{TokenStream, TokenTree};
use proc_macro_error::SpanRange;
use syn::Lit;

#[derive(Debug)]
pub enum Markup {
Expand Down Expand Up @@ -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()
}
13 changes: 7 additions & 6 deletions maud_macros/src/parse.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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() {
self.advance();
result.push(token);
} else {
return None;
}
match self.peek() {
Some(token @ TokenTree::Ident(_)) | Some(token @ TokenTree::Literal(_)) => {
self.advance();
result.push(token);
}
_ => return None,
};
let mut expect_ident = false;
loop {
expect_ident = match self.peek() {
Expand Down

0 comments on commit 8c47208

Please sign in to comment.