SVGs
There is a way to conveniently create inline SVGs without rewriting them manually with hobo
's syntax.
thread_local! {
static LAST_ID: RefCell<u64> = RefCell::new(0);
}
fn get_svg_element(xml_node: &roxmltree::Node, id: u64) -> web_sys::SvgElement {
let node: web_sys::SvgElement = wasm_bindgen::JsCast::unchecked_into(document().create_element_ns(Some(wasm_bindgen::intern("http://www.w3.org/2000/svg")), xml_node.tag_name().name()).unwrap());
for attribute in xml_node.attributes() {
// need to fixup ids to avoid id collisions in html if the same icon is used multiple times
if attribute.name() == "id" {
node.set_attribute(wasm_bindgen::intern(attribute.name()), &format!("{}{:x}", attribute.value(), id)).unwrap();
} else {
let mut value = attribute.value().to_owned();
// optimistic expectation that ids only used in url references
if value.contains("url(#") {
value = value.replace(')', &format!("{:x})", id))
}
node.set_attribute(wasm_bindgen::intern(attribute.name()), &value).unwrap();
}
}
for child in xml_node.children().filter(roxmltree::Node::is_element) {
node.append_child(&get_svg_element(&child, id)).unwrap();
}
node
}
macro_rules! svg {
($($name:ident => $address:expr),*$(,)*) => {$(
#[must_use]
pub fn $name() -> e::Svg {
let id = LAST_ID.with(move |last_id| {
let mut last_id = last_id.borrow_mut();
let id = *last_id;
*last_id += 1;
id
});
let element: web_sys::SvgElement = get_svg_element(&roxmltree::Document::parse(include_str!($address)).unwrap().root_element(), id);
e::Svg(hobo::create::svg_element(&element))
}
)*};
}
svg![
logo => r"../../public/img/icons/etc/logo.svg",
discord => r"../../public/img/icons/shapes/discord.svg",
];
Constructing inline SVGs
Of course, if you need to algorithmically construct an svg, such as if you're making a chart, you can do that too:
#![allow(unused)] fn main() { let svg = e::svg() .attr(web_str::viewBox(), "-1 -1 2 2") .child(e::circle() .attr(web_str::cx(), "0") .attr(web_str::cy(), "0") .attr(web_str::r(), "1") .class(( css::fill!(colors::gray6), )) ); }