Skip to content

Commit

Permalink
Merge pull request #104 from ivanceras/master
Browse files Browse the repository at this point in the history
Add support for inline SVG element
  • Loading branch information
chinedufn authored Mar 21, 2019
2 parents bf2eb09 + b5e21ed commit 00f3e4a
Show file tree
Hide file tree
Showing 6 changed files with 144 additions and 2 deletions.
2 changes: 2 additions & 0 deletions crates/html-validation/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,8 @@
#![deny(missing_docs)]

pub use self_closing::is_self_closing;
pub use svg_namespace::is_svg_namespace;

mod self_closing;
mod svg_namespace;

5 changes: 5 additions & 0 deletions crates/html-validation/src/self_closing.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
use lazy_static::lazy_static;
use std::collections::hash_set::HashSet;


use super::svg_namespace::is_self_closing_svg_tag;

// Used to uniquely identify elements that contain closures so that the DomUpdater can
// look them up by their unique id.
// When the DomUpdater sees that the element no longer exists it will drop all of it's
Expand All @@ -13,6 +16,7 @@ lazy_static! {
.iter()
.cloned()
.collect();

}

/// Whether or not this tag is self closing
Expand All @@ -26,4 +30,5 @@ lazy_static! {
/// ```
pub fn is_self_closing(tag: &str) -> bool {
SELF_CLOSING_TAGS.contains(tag)
|| is_self_closing_svg_tag(tag)
}
119 changes: 119 additions & 0 deletions crates/html-validation/src/svg_namespace.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,119 @@
use lazy_static::lazy_static;
use std::collections::HashMap;

lazy_static! {
// list of svg elements
// https://developer.mozilla.org/en-US/docs/Web/SVG/Element
// a hashmap of `(tag, is_self_closing)`
static ref SVG_NAMESPACED_TAGS: HashMap<&'static str, bool> = [
// TODO: can cause conflict with html `a`
//("a", true),
("animate", true),
("animateMotion", false),
("animateTransform", true),
("circle", true),
("clipPath",false),
// TODO: blocked with [issue](https://github.com/chinedufn/percy/issues/106)
//("color-profile",),
("defs", false),
("desc", false),
("discard", true),
("ellipse",true),
("feBlend", true),
("feColorMatrix", true),
("feComponentTransfer", false),
("feComposite", true),
("feConvolveMatrix", true),
("feDiffuseLighting", false),
("feDisplacementMap", true),
("feDistantLight", true),
("feDropShadow", true),
("feFlood", true),
("feFuncA", true),
("feFuncB", true),
("feFuncG", true),
("feFuncR", true),
("feGaussianBlur", true),
("feImage", true),
("feMerge", false),
("feMergeNode", true),
("feMorphology", true),
("feOffset", true),
("fePointLight", true),
("feSpecularLighting", false),
("feSpotLight", true),
("feTile", true),
("feTurbulence", true),
("filter", false),
("foreignObject", false),
("g",false),
("hatch", false),
("hatchpath", true),
("image", true),
("line", true),
("linearGradient", false),
("marker", false),
("mask", false),
// TODO: undocumented
//("mesh",),
// TODO: undocumented
//("meshgradient",),
// TODO: undocumented
//("meshpatch",),
// TODO: undocumented
//("meshrow",),
("metadata", false),
("mpath", true),
("path", true),
("pattern", false),
("polygon", true),
("polyline", true),
("radialGradient", false),
("rect", true),
// TODO: can cause conflict with html `script` tag
//("script", false),
("set", true),
("solidcolor", true),
("stop", true),
// TODO: can cause conflict with html `style` tag
//("style", false),
("svg", false),
("switch", false),
("symbol", false),
("text", false),
("textPath", false),
// TODO: can cause conflict with html `title` tag
//("title", false),
("tspan", false),
// TODO: undocumented
//("unknown",),
("use", true),
("view", true),
]
.iter()
.cloned()
.collect();
}
/// Whether or not this tag is part svg elements
/// ```
/// use html_validation::is_svg_namespace;
///
/// assert_eq!(is_svg_namespace("svg"), true);
///
/// assert_eq!(is_svg_namespace("circle"), true);
///
/// assert_eq!(is_svg_namespace("div"), false);
/// ```
pub fn is_svg_namespace(tag: &str) ->bool {
SVG_NAMESPACED_TAGS.contains_key(tag)
}

/// Whether or not this svg tag is self closing
pub(crate) fn is_self_closing_svg_tag(tag: &str) -> bool {
SVG_NAMESPACED_TAGS
.get(tag)
.map(|v|*v)
.unwrap_or(false)
}


10 changes: 10 additions & 0 deletions crates/virtual-dom-rs/tests/create_element.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,16 @@ fn nested_divs() {
assert_eq!(&div.inner_html(), "<div><div></div></div>");
}

#[wasm_bindgen_test]
fn svg_element() {
let vdiv = html! { <div><svg xmlns="http://www.w3.org/2000/svg">
<circle cx="50" cy="50" r="50"/>
</svg></div> };
let div: Element = vdiv.create_dom_node().node.unchecked_into();

assert_eq!(&div.inner_html(), r#"<svg xmlns="http://www.w3.org/2000/svg"><circle cx="50" cy="50" r="50"></circle></svg>"#);
}

#[wasm_bindgen_test]
fn div_with_attributes() {
let vdiv = html! { <div id="id-here" class="two classes"></div> };
Expand Down
6 changes: 5 additions & 1 deletion crates/virtual-node/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -217,7 +217,11 @@ impl VElement {
pub fn create_element_node(&self) -> CreatedNode<Element> {
let document = web_sys::window().unwrap().document().unwrap();

let element = document.create_element(&self.tag).unwrap();
let element = if html_validation::is_svg_namespace(&self.tag){
document.create_element_ns(Some("http://www.w3.org/2000/svg"), &self.tag).unwrap()
}else{
document.create_element(&self.tag).unwrap()
};
let mut closures = HashMap::new();

self.attrs.iter().for_each(|(name, value)| {
Expand Down
4 changes: 3 additions & 1 deletion examples/isomorphic/app/src/views/home_view.rs
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,9 @@ impl View for HomeView {
Click me!
</button>
<div> In this time Ferris has made { click_count } new friends. </div>

<svg xmlns="http://www.w3.org/2000/svg">
<circle cx="50" cy="50" r="50"/>
</svg>
</div>
}
}
Expand Down

0 comments on commit 00f3e4a

Please sign in to comment.