瀏覽代碼

feat: support innerhtml

Jonathan Kelley 3 年之前
父節點
當前提交
cfc24f5
共有 3 個文件被更改,包括 34 次插入3 次删除
  1. 6 0
      packages/html/src/lib.rs
  2. 23 3
      packages/ssr/src/lib.rs
  3. 5 0
      packages/web/src/dom.rs

+ 6 - 0
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.

+ 23 - 3
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: "<div> ack </div>"
+            }
+        });
+
+        dbg!(s);
+    }
 }

+ 5 - 0
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::<Element>() {
+                        el.set_inner_html(value);
+                    }
+                }
                 "value" => {
                     if let Some(input) = node.dyn_ref::<HtmlInputElement>() {
                         /*