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>"#);
|
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]
|
#[test]
|
||||||
fn toggle_classes() {
|
fn toggle_classes() {
|
||||||
fn test(is_cupcake: bool, is_muffin: bool) -> Markup {
|
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>"#);
|
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]
|
#[test]
|
||||||
fn mixed_classes() {
|
fn mixed_classes() {
|
||||||
fn test(is_muffin: bool) -> Markup {
|
fn test(is_muffin: bool) -> Markup {
|
||||||
|
@ -177,11 +191,17 @@ fn mixed_classes() {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn ids_shorthand() {
|
fn id_shorthand() {
|
||||||
let s = html!(p { "Hi, " span#thing { "Lyra" } "!" }).into_string();
|
let s = html!(p { "Hi, " span#thing { "Lyra" } "!" }).into_string();
|
||||||
assert_eq!(s, r#"<p>Hi, <span id="thing">Lyra</span>!</p>"#);
|
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]
|
#[test]
|
||||||
fn classes_attrs_ids_mixed_up() {
|
fn classes_attrs_ids_mixed_up() {
|
||||||
let s = html!(p { "Hi, " span.name.here lang="en" #thing { "Lyra" } "!" }).into_string();
|
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]
|
#[test]
|
||||||
fn if_let() {
|
fn if_let() {
|
||||||
for &(input, output) in &[(Some("yay"), "yay"), (None, "oh noes")] {
|
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">"#);
|
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";
|
static BEST_PONY: &'static str = "Pinkie Pie";
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
|
|
@ -149,7 +149,9 @@ impl Parser {
|
||||||
},
|
},
|
||||||
// Element
|
// Element
|
||||||
TokenTree::Ident(_) => {
|
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)?
|
self.element(name)?
|
||||||
},
|
},
|
||||||
// Splice
|
// Splice
|
||||||
|
@ -544,16 +546,14 @@ impl Parser {
|
||||||
// Class shorthand
|
// Class shorthand
|
||||||
(None, Some(TokenTree::Punct(ref punct))) if punct.as_char() == '.' => {
|
(None, Some(TokenTree::Punct(ref punct))) if punct.as_char() == '.' => {
|
||||||
self.commit(attempt);
|
self.commit(attempt);
|
||||||
// TODO parse arbitrary expressions here
|
let name = self.class_or_id_name()?;
|
||||||
let name = ast::Markup::Symbol { symbol: self.name()? };
|
|
||||||
let toggler = self.attr_toggler();
|
let toggler = self.attr_toggler();
|
||||||
attrs.push(ast::Attr::Class { dot_span: punct.span(), name, toggler });
|
attrs.push(ast::Attr::Class { dot_span: punct.span(), name, toggler });
|
||||||
},
|
},
|
||||||
// ID shorthand
|
// ID shorthand
|
||||||
(None, Some(TokenTree::Punct(ref punct))) if punct.as_char() == '#' => {
|
(None, Some(TokenTree::Punct(ref punct))) if punct.as_char() == '#' => {
|
||||||
self.commit(attempt);
|
self.commit(attempt);
|
||||||
// TODO parse arbitrary expressions here
|
let name = self.class_or_id_name()?;
|
||||||
let name = ast::Markup::Symbol { symbol: self.name()? };
|
|
||||||
attrs.push(ast::Attr::Id { hash_span: punct.span(), name });
|
attrs.push(ast::Attr::Id { hash_span: punct.span(), name });
|
||||||
},
|
},
|
||||||
// If it's not a valid attribute, backtrack and bail out
|
// If it's not a valid attribute, backtrack and bail out
|
||||||
|
@ -598,6 +598,15 @@ impl Parser {
|
||||||
Ok(attrs)
|
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.
|
/// Parses the `[cond]` syntax after an empty attribute or class shorthand.
|
||||||
fn attr_toggler(&mut self) -> Option<ast::Toggler> {
|
fn attr_toggler(&mut self) -> Option<ast::Toggler> {
|
||||||
match self.peek() {
|
match self.peek() {
|
||||||
|
@ -613,12 +622,6 @@ impl Parser {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Parses an identifier, without dealing with namespaces.
|
/// 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> {
|
fn try_name(&mut self) -> Option<TokenStream> {
|
||||||
let mut result = Vec::new();
|
let mut result = Vec::new();
|
||||||
if let Some(token @ TokenTree::Ident(_)) = self.peek() {
|
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
|
/// Parses a HTML element or attribute name, along with a namespace
|
||||||
/// if necessary.
|
/// 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> {
|
fn try_namespaced_name(&mut self) -> Option<TokenStream> {
|
||||||
let mut result = vec![self.try_name()?];
|
let mut result = vec![self.try_name()?];
|
||||||
if let Some(TokenTree::Punct(ref punct)) = self.peek() {
|
if let Some(TokenTree::Punct(ref punct)) = self.peek() {
|
||||||
|
|
Loading…
Add table
Reference in a new issue