From d64df87abaa69f287684a5aca0e6770efc25b042 Mon Sep 17 00:00:00 2001 From: Evan Almloff Date: Tue, 8 Oct 2024 07:02:02 -0500 Subject: [PATCH] Escape HTML as we translate to rsx (#3038) --- Cargo.lock | 12 ++++++++++++ packages/rsx-rosetta/Cargo.toml | 1 + packages/rsx-rosetta/src/lib.rs | 7 ++++++- packages/rsx-rosetta/tests/escape.rs | 18 ++++++++++++++++++ 4 files changed, 37 insertions(+), 1 deletion(-) create mode 100644 packages/rsx-rosetta/tests/escape.rs diff --git a/Cargo.lock b/Cargo.lock index 2fc90a778..e2a09e2ee 100644 --- a/Cargo.lock +++ b/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" diff --git a/packages/rsx-rosetta/Cargo.toml b/packages/rsx-rosetta/Cargo.toml index 7c626a722..04b34e8c0 100644 --- a/packages/rsx-rosetta/Cargo.toml +++ b/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" diff --git a/packages/rsx-rosetta/src/lib.rs b/packages/rsx-rosetta/src/lib.rs index 22fdb815d..fbfe197e6 100644 --- a/packages/rsx-rosetta/src/lib.rs +++ b/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 { 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) { diff --git a/packages/rsx-rosetta/tests/escape.rs b/packages/rsx-rosetta/tests/escape.rs new file mode 100644 index 000000000..8b60053d7 --- /dev/null +++ b/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>⌛⌛⌛⌛
"#.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 { "
⌛⌛⌛⌛" }"#; + pretty_assertions::assert_eq!(&out, &expected); +}