parent
8d8d5960a5
commit
e273d897cf
4 changed files with 72 additions and 18 deletions
|
@ -149,6 +149,12 @@ fn hyphens_in_class_names() {
|
|||
assert_eq!(s, r#"<p class="rocks-these are--my--rocks">yes</p>"#);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn class_string() {
|
||||
let s = html!(h1."pinkie-123" { "Pinkie Pie" }).into_string();
|
||||
assert_eq!(s, r#"<h1 class="pinkie-123">Pinkie Pie</h1>"#);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn toggle_classes() {
|
||||
fn test(is_cupcake: bool, is_muffin: bool) -> Markup {
|
||||
|
@ -167,6 +173,14 @@ fn toggle_classes_braces() {
|
|||
assert_eq!(s, r#"<p class="rocks">Awesome!</p>"#);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn toggle_classes_string() {
|
||||
let is_cupcake = true;
|
||||
let is_muffin = false;
|
||||
let s = html!(p."cupcake"[is_cupcake]."is_muffin"[is_muffin] { "Testing!" }).into_string();
|
||||
assert_eq!(s, r#"<p class="cupcake">Testing!</p>"#);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn mixed_classes() {
|
||||
fn test(is_muffin: bool) -> Markup {
|
||||
|
@ -177,11 +191,17 @@ fn mixed_classes() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
fn ids_shorthand() {
|
||||
fn id_shorthand() {
|
||||
let s = html!(p { "Hi, " span#thing { "Lyra" } "!" }).into_string();
|
||||
assert_eq!(s, r#"<p>Hi, <span id="thing">Lyra</span>!</p>"#);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn id_string() {
|
||||
let s = html!(h1#"pinkie-123" { "Pinkie Pie" }).into_string();
|
||||
assert_eq!(s, r#"<h1 id="pinkie-123">Pinkie Pie</h1>"#);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn classes_attrs_ids_mixed_up() {
|
||||
let s = html!(p { "Hi, " span.name.here lang="en" #thing { "Lyra" } "!" }).into_string();
|
||||
|
|
|
@ -26,6 +26,22 @@ fn if_expr() {
|
|||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn if_expr_in_class() {
|
||||
for &(chocolate_milk, expected) in &[
|
||||
(0, r#"<p class="empty">Chocolate milk</p>"#),
|
||||
(1, r#"<p class="full">Chocolate milk</p>"#),
|
||||
]
|
||||
{
|
||||
let s = html! {
|
||||
p.@if chocolate_milk == 0 { "empty" } @else { "full" } {
|
||||
"Chocolate milk"
|
||||
}
|
||||
}.into_string();
|
||||
assert_eq!(s, expected);
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn if_let() {
|
||||
for &(input, output) in &[(Some("yay"), "yay"), (None, "oh noes")] {
|
||||
|
|
|
@ -42,6 +42,27 @@ fn attributes() {
|
|||
assert_eq!(s, r#"<img src="pinkie.jpg" alt="Pinkie Pie">"#);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn class_shorthand() {
|
||||
let pinkie_class = "pinkie";
|
||||
let s = html!(p.(pinkie_class) { "Fun!" }).into_string();
|
||||
assert_eq!(s, r#"<p class="pinkie">Fun!</p>"#);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn class_shorthand_block() {
|
||||
let class_prefix = "pinkie-";
|
||||
let s = html!(p.{ (class_prefix) "123" } { "Fun!" }).into_string();
|
||||
assert_eq!(s, r#"<p class="pinkie-123">Fun!</p>"#);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn id_shorthand() {
|
||||
let pinkie_id = "pinkie";
|
||||
let s = html!(p#(pinkie_id) { "Fun!" }).into_string();
|
||||
assert_eq!(s, r#"<p id="pinkie">Fun!</p>"#);
|
||||
}
|
||||
|
||||
static BEST_PONY: &'static str = "Pinkie Pie";
|
||||
|
||||
#[test]
|
||||
|
|
|
@ -149,7 +149,9 @@ impl Parser {
|
|||
},
|
||||
// Element
|
||||
TokenTree::Ident(_) => {
|
||||
let name = self.namespaced_name()?;
|
||||
// `.try_namespaced_name()` should never fail as we've
|
||||
// already seen an `Ident`
|
||||
let name = self.try_namespaced_name().expect("identifier");
|
||||
self.element(name)?
|
||||
},
|
||||
// Splice
|
||||
|
@ -544,16 +546,14 @@ impl Parser {
|
|||
// Class shorthand
|
||||
(None, Some(TokenTree::Punct(ref punct))) if punct.as_char() == '.' => {
|
||||
self.commit(attempt);
|
||||
// TODO parse arbitrary expressions here
|
||||
let name = ast::Markup::Symbol { symbol: self.name()? };
|
||||
let name = self.class_or_id_name()?;
|
||||
let toggler = self.attr_toggler();
|
||||
attrs.push(ast::Attr::Class { dot_span: punct.span(), name, toggler });
|
||||
},
|
||||
// ID shorthand
|
||||
(None, Some(TokenTree::Punct(ref punct))) if punct.as_char() == '#' => {
|
||||
self.commit(attempt);
|
||||
// TODO parse arbitrary expressions here
|
||||
let name = ast::Markup::Symbol { symbol: self.name()? };
|
||||
let name = self.class_or_id_name()?;
|
||||
attrs.push(ast::Attr::Id { hash_span: punct.span(), name });
|
||||
},
|
||||
// If it's not a valid attribute, backtrack and bail out
|
||||
|
@ -598,6 +598,15 @@ impl Parser {
|
|||
Ok(attrs)
|
||||
}
|
||||
|
||||
/// Parses the name of a class or ID.
|
||||
fn class_or_id_name(&mut self) -> ParseResult<ast::Markup> {
|
||||
if let Some(symbol) = self.try_name() {
|
||||
Ok(ast::Markup::Symbol { symbol })
|
||||
} else {
|
||||
self.markup()
|
||||
}
|
||||
}
|
||||
|
||||
/// Parses the `[cond]` syntax after an empty attribute or class shorthand.
|
||||
fn attr_toggler(&mut self) -> Option<ast::Toggler> {
|
||||
match self.peek() {
|
||||
|
@ -613,12 +622,6 @@ impl Parser {
|
|||
}
|
||||
|
||||
/// Parses an identifier, without dealing with namespaces.
|
||||
fn name(&mut self) -> ParseResult<TokenStream> {
|
||||
self.try_name().ok_or_else(|| {
|
||||
Span::call_site().error("expected identifier").emit();
|
||||
})
|
||||
}
|
||||
|
||||
fn try_name(&mut self) -> Option<TokenStream> {
|
||||
let mut result = Vec::new();
|
||||
if let Some(token @ TokenTree::Ident(_)) = self.peek() {
|
||||
|
@ -648,12 +651,6 @@ impl Parser {
|
|||
|
||||
/// Parses a HTML element or attribute name, along with a namespace
|
||||
/// if necessary.
|
||||
fn namespaced_name(&mut self) -> ParseResult<TokenStream> {
|
||||
self.try_namespaced_name().ok_or_else(|| {
|
||||
Span::call_site().error("expected identifier").emit();
|
||||
})
|
||||
}
|
||||
|
||||
fn try_namespaced_name(&mut self) -> Option<TokenStream> {
|
||||
let mut result = vec![self.try_name()?];
|
||||
if let Some(TokenTree::Punct(ref punct)) = self.peek() {
|
||||
|
|
Loading…
Add table
Reference in a new issue