Skip to content

Commit

Permalink
Fix handling of boolean attributes (#840)
Browse files Browse the repository at this point in the history
* Updated so boolean attributes are either there or not.

Issue #394

* Ran cargo fmt.

* Updated to remove checked and selected special handling.

* Update the attribute list to match what mdn says.

Removed deceprated attributes.

* Added back the checked special handling.
  • Loading branch information
mrh0057 authored and jstarry committed Jan 6, 2020
1 parent fb17517 commit c7c9dcd
Show file tree
Hide file tree
Showing 2 changed files with 54 additions and 25 deletions.
28 changes: 10 additions & 18 deletions crates/macro/src/html_tree/html_tag/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -91,11 +91,10 @@ impl ToTokens for HtmlTag {
let TagAttributes {
classes,
attributes,
booleans,
kind,
value,
checked,
disabled,
selected,
node_ref,
href,
listeners,
Expand All @@ -106,6 +105,14 @@ impl ToTokens for HtmlTag {
let label_str = label.to_string();
quote_spanned! {value.span() => (#label_str.to_owned(), (#value).to_string()) }
});
let set_booleans = booleans.iter().map(|TagAttribute { label, value }| {
let label_str = label.to_string();
quote_spanned! {value.span() =>
if #value {
#vtag.add_attribute(&#label_str, &#label_str);
}
}
});
let set_kind = kind.iter().map(|kind| {
quote_spanned! {kind.span()=> #vtag.set_kind(&(#kind)); }
});
Expand All @@ -121,20 +128,6 @@ impl ToTokens for HtmlTag {
let set_checked = checked.iter().map(|checked| {
quote_spanned! {checked.span()=> #vtag.set_checked(#checked); }
});
let add_disabled = disabled.iter().map(|disabled| {
quote_spanned! {disabled.span()=>
if #disabled {
#vtag.add_attribute("disabled", &"true");
}
}
});
let add_selected = selected.iter().map(|selected| {
quote_spanned! {selected.span()=>
if #selected {
#vtag.add_attribute("selected", &"selected");
}
}
});
let set_classes = classes.iter().map(|classes_form| match classes_form {
ClassesForm::Tuple(classes) => quote! {
#vtag.add_classes(vec![#(&(#classes)),*]);
Expand Down Expand Up @@ -167,8 +160,7 @@ impl ToTokens for HtmlTag {
#(#set_value)*
#(#add_href)*
#(#set_checked)*
#(#add_disabled)*
#(#add_selected)*
#(#set_booleans)*
#(#set_classes)*
#(#set_node_ref)*
#vtag.add_attributes(vec![#(#attr_pairs),*]);
Expand Down
51 changes: 44 additions & 7 deletions crates/macro/src/html_tree/html_tag/tag_attributes.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,10 @@ pub struct TagAttributes {
pub attributes: Vec<TagAttribute>,
pub listeners: Vec<TagAttribute>,
pub classes: Option<ClassesForm>,
pub booleans: Vec<TagAttribute>,
pub value: Option<Expr>,
pub kind: Option<Expr>,
pub checked: Option<Expr>,
pub disabled: Option<Expr>,
pub selected: Option<Expr>,
pub node_ref: Option<Expr>,
pub href: Option<Expr>,
}
Expand All @@ -24,6 +23,32 @@ pub enum ClassesForm {
Single(Expr),
}

lazy_static! {
static ref BOOLEAN_SET: HashSet<&'static str> = {
HashSet::from_iter(
vec![
"async",
"autofocus",
"controls",
"default",
"defer",
"disabled",
"hidden",
"ismap",
"loop",
"multiple",
"muted",
"novalidate",
"open",
"readonly",
"required",
"selected",
]
.into_iter(),
)
};
}

lazy_static! {
static ref LISTENER_SET: HashSet<&'static str> = {
HashSet::from_iter(
Expand Down Expand Up @@ -92,6 +117,20 @@ impl TagAttributes {
drained
}

fn drain_boolean(attrs: &mut Vec<TagAttribute>) -> Vec<TagAttribute> {
let mut i = 0;
let mut drained = Vec::new();
while i < attrs.len() {
let name_str = attrs[i].label.to_string();
if BOOLEAN_SET.contains(&name_str.as_str()) {
drained.push(attrs.remove(i));
} else {
i += 1;
}
}
drained
}

fn remove_attr(attrs: &mut Vec<TagAttribute>, name: &str) -> Option<Expr> {
let mut i = 0;
while i < attrs.len() {
Expand Down Expand Up @@ -142,26 +181,24 @@ impl Parse for TagAttributes {
}
i += 1;
}
let booleans = TagAttributes::drain_boolean(&mut attributes);

let classes =
TagAttributes::remove_attr(&mut attributes, "class").map(TagAttributes::map_classes);
let value = TagAttributes::remove_attr(&mut attributes, "value");
let kind = TagAttributes::remove_attr(&mut attributes, "type");
let checked = TagAttributes::remove_attr(&mut attributes, "checked");
let disabled = TagAttributes::remove_attr(&mut attributes, "disabled");
let selected = TagAttributes::remove_attr(&mut attributes, "selected");
let node_ref = TagAttributes::remove_attr(&mut attributes, "ref");
let href = TagAttributes::remove_attr(&mut attributes, "href");

Ok(TagAttributes {
attributes,
classes,
listeners,
checked,
booleans,
value,
kind,
checked,
disabled,
selected,
node_ref,
href,
})
Expand Down

0 comments on commit c7c9dcd

Please sign in to comment.