Browse Source

Escape HTML as we translate to rsx (#3038)

Evan Almloff 8 months ago
parent
commit
d64df87aba

+ 12 - 0
Cargo.lock

@@ -3007,6 +3007,7 @@ dependencies = [
  "dioxus-html",
  "dioxus-rsx",
  "html_parser",
+ "htmlentity",
  "pretty_assertions",
  "proc-macro2",
  "quote",
@@ -5030,6 +5031,17 @@ dependencies = [
  "thiserror",
 ]
 
+[[package]]
+name = "htmlentity"
+version = "1.3.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "dd54ae4f69adcc1a43637dcff230852832c3ad50df31a90e0cb5f001dd441359"
+dependencies = [
+ "anyhow",
+ "lazy_static",
+ "thiserror",
+]
+
 [[package]]
 name = "http"
 version = "0.2.12"

+ 1 - 0
packages/rsx-rosetta/Cargo.toml

@@ -21,6 +21,7 @@ proc-macro2 = { workspace = true }
 quote = { workspace = true }
 syn = { workspace = true, features = ["full"] }
 convert_case = { workspace = true }
+htmlentity = "1.3.2"
 
 [dev-dependencies]
 pretty_assertions = "1.2.1"

+ 6 - 1
packages/rsx-rosetta/src/lib.rs

@@ -9,6 +9,7 @@ use dioxus_rsx::{
     HotLiteral, TemplateBody, TextNode,
 };
 pub use html_parser::{Dom, Node};
+use htmlentity::entity::ICodedDataTrait;
 use proc_macro2::{Ident, Span};
 use syn::{punctuated::Punctuated, LitStr};
 
@@ -33,7 +34,11 @@ pub fn rsx_node_from_html(node: &Node) -> Option<BodyNode> {
     use AttributeValue::*;
 
     match node {
-        Node::Text(text) => Some(BodyNode::Text(TextNode::from_text(text))),
+        Node::Text(text) => Some(BodyNode::Text(TextNode::from_text(
+            &htmlentity::entity::decode(text.as_bytes())
+                .to_string()
+                .ok()?,
+        ))),
 
         Node::Element(el) => {
             let el_name = if let Some(name) = map_html_element_to_rsx(&el.name) {

+ 18 - 0
packages/rsx-rosetta/tests/escape.rs

@@ -0,0 +1,18 @@
+use html_parser::Dom;
+
+// Regression test for https://github.com/DioxusLabs/dioxus/issues/3037
+// We need to escape html entities as we translate html because rsx doesn't support them
+#[test]
+fn escaped_text() {
+    let html = r#"<div>&lt;div&gt;&#x231b;&#x231b;&#x231b;&#x231b;</div>"#.trim();
+
+    let dom = Dom::parse(html).unwrap();
+
+    let body = dioxus_rsx_rosetta::rsx_from_html(&dom);
+
+    let out = dioxus_autofmt::write_block_out(&body).unwrap();
+
+    let expected = r#"
+    div { "<div>⌛⌛⌛⌛" }"#;
+    pretty_assertions::assert_eq!(&out, &expected);
+}