diff --git a/packages/html/src/lib.rs b/packages/html/src/lib.rs index a90e61170..9fe166997 100644 --- a/packages/html/src/lib.rs +++ b/packages/html/src/lib.rs @@ -108,6 +108,12 @@ pub trait GlobalAttributes { tabindex; title; translate; + + /// dangerous_inner_html is Dioxus's replacement for using innerHTML in the browser DOM. In general, setting + /// HTML from code is risky because it’s easy to inadvertently expose your users to a cross-site scripting (XSS) + /// attack. So, you can set HTML directly from Dioxus, but you have to type out dangerous_inner_html to remind + /// yourself that it’s dangerous + dangerous_inner_html; } // This macro creates an explicit method call for each of the style attributes. diff --git a/packages/ssr/src/lib.rs b/packages/ssr/src/lib.rs index f8872840e..2813a9d82 100644 --- a/packages/ssr/src/lib.rs +++ b/packages/ssr/src/lib.rs @@ -172,11 +172,16 @@ impl<'a> TextRenderer<'a, '_> { } write!(f, "<{}", el.tag_name)?; + + let mut inner_html = None; let mut attr_iter = el.attributes.iter().peekable(); while let Some(attr) = attr_iter.next() { match attr.namespace { - None => write!(f, " {}=\"{}\"", attr.name, attr.value)?, + None => match attr.name { + "dangerous_inner_html" => inner_html = Some(attr.value), + _ => write!(f, " {}=\"{}\"", attr.name, attr.value)?, + }, Some(ns) => { // write the opening tag @@ -214,8 +219,12 @@ impl<'a> TextRenderer<'a, '_> { false => write!(f, ">")?, } - for child in el.children { - self.html_render(child, f, il + 1)?; + if let Some(inner_html) = inner_html { + write!(f, "{}", inner_html)?; + } else { + for child in el.children { + self.html_render(child, f, il + 1)?; + } } if self.cfg.newline { @@ -430,4 +439,15 @@ mod tests { dbg!(s); } + + #[test] + fn inner_html() { + let s = render_lazy(rsx! { + div { + dangerous_inner_html: "
ack
" + } + }); + + dbg!(s); + } } diff --git a/packages/web/src/dom.rs b/packages/web/src/dom.rs index e30f7693b..2e9704b98 100644 --- a/packages/web/src/dom.rs +++ b/packages/web/src/dom.rs @@ -332,6 +332,11 @@ impl WebsysDom { el.set_attribute(name, value).unwrap() }; match name { + "dangerous_inner_html" => { + if let Some(el) = node.dyn_ref::() { + el.set_inner_html(value); + } + } "value" => { if let Some(input) = node.dyn_ref::() { /*