mirror of
https://github.com/DioxusLabs/dioxus
synced 2024-11-10 14:44:12 +00:00
fix dangerous_inner_html with SSR
This commit is contained in:
parent
61d100e1f8
commit
fe75138e42
3 changed files with 62 additions and 3 deletions
|
@ -23,6 +23,8 @@ pub enum Segment {
|
|||
// This will be true if there are static styles
|
||||
inside_style_tag: bool,
|
||||
},
|
||||
/// A marker for where to insert a dynamic inner html
|
||||
InnerHtmlMarker,
|
||||
}
|
||||
|
||||
impl std::fmt::Write for StringChain {
|
||||
|
@ -69,6 +71,9 @@ impl StringCache {
|
|||
write!(chain, "<{tag}")?;
|
||||
// we need to collect the styles and write them at the end
|
||||
let mut styles = Vec::new();
|
||||
// we need to collect the inner html and write it at the end
|
||||
let mut inner_html = None;
|
||||
// we need to keep track of if we have dynamic attrs to know if we need to insert a style and inner_html marker
|
||||
let mut has_dynamic_attrs = false;
|
||||
for attr in *attrs {
|
||||
match attr {
|
||||
|
@ -77,7 +82,9 @@ impl StringCache {
|
|||
value,
|
||||
namespace,
|
||||
} => {
|
||||
if let Some("style") = namespace {
|
||||
if *name == "dangerous_inner_html" {
|
||||
inner_html = Some(value);
|
||||
} else if let Some("style") = namespace {
|
||||
styles.push((name, value));
|
||||
} else {
|
||||
write!(chain, " {name}=\"{value}\"")?;
|
||||
|
@ -110,6 +117,13 @@ impl StringCache {
|
|||
write!(chain, "/>")?;
|
||||
} else {
|
||||
write!(chain, ">")?;
|
||||
// Write the static inner html, or insert a marker if dynamic inner html is possible
|
||||
if let Some(inner_html) = inner_html {
|
||||
chain.write_str(inner_html)?;
|
||||
} else if has_dynamic_attrs {
|
||||
chain.segments.push(Segment::InnerHtmlMarker);
|
||||
}
|
||||
|
||||
for child in *children {
|
||||
Self::recurse(child, cur_path, root_idx, chain)?;
|
||||
}
|
||||
|
|
|
@ -70,6 +70,8 @@ impl Renderer {
|
|||
.or_insert_with(|| Rc::new(StringCache::from_template(template).unwrap()))
|
||||
.clone();
|
||||
|
||||
let mut inner_html = None;
|
||||
|
||||
// We need to keep track of the dynamic styles so we can insert them into the right place
|
||||
let mut accumulated_dynamic_styles = Vec::new();
|
||||
|
||||
|
@ -77,7 +79,9 @@ impl Renderer {
|
|||
match segment {
|
||||
Segment::Attr(idx) => {
|
||||
let attr = &template.dynamic_attrs[*idx];
|
||||
if attr.namespace == Some("style") {
|
||||
if attr.name == "dangerous_inner_html" {
|
||||
inner_html = Some(attr);
|
||||
} else if attr.namespace == Some("style") {
|
||||
accumulated_dynamic_styles.push(attr);
|
||||
} else {
|
||||
match attr.value {
|
||||
|
@ -165,6 +169,19 @@ impl Renderer {
|
|||
accumulated_dynamic_styles.clear();
|
||||
}
|
||||
}
|
||||
|
||||
Segment::InnerHtmlMarker => {
|
||||
if let Some(inner_html) = inner_html.take() {
|
||||
let inner_html = &inner_html.value;
|
||||
match inner_html {
|
||||
AttributeValue::Text(value) => write!(buf, "{}", value)?,
|
||||
AttributeValue::Bool(value) => write!(buf, "{}", value)?,
|
||||
AttributeValue::Float(f) => write!(buf, "{}", f)?,
|
||||
AttributeValue::Int(i) => write!(buf, "{}", i)?,
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -208,7 +225,9 @@ fn to_string_works() {
|
|||
StyleMarker {
|
||||
inside_style_tag: false,
|
||||
},
|
||||
PreRendered(">Hello world 1 -->".into(),),
|
||||
PreRendered(">".into()),
|
||||
InnerHtmlMarker,
|
||||
PreRendered("Hello world 1 -->".into(),),
|
||||
Node(0,),
|
||||
PreRendered(
|
||||
"<-- Hello world 2<div>nest 1</div><div></div><div>nest 2</div>".into(),
|
||||
|
|
26
packages/ssr/tests/inner_html.rs
Normal file
26
packages/ssr/tests/inner_html.rs
Normal file
|
@ -0,0 +1,26 @@
|
|||
use dioxus::prelude::*;
|
||||
|
||||
#[test]
|
||||
fn static_inner_html() {
|
||||
fn app(cx: Scope) -> Element {
|
||||
render! { div { dangerous_inner_html: "<div>1234</div>" } }
|
||||
}
|
||||
|
||||
let mut dom = VirtualDom::new(app);
|
||||
_ = dom.rebuild();
|
||||
|
||||
assert_eq!(dioxus_ssr::render(&dom), r#"<div><div>1234</div></div>"#);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn dynamic_inner_html() {
|
||||
fn app(cx: Scope) -> Element {
|
||||
let inner_html = "<div>1234</div>";
|
||||
render! { div { dangerous_inner_html: "{inner_html}" } }
|
||||
}
|
||||
|
||||
let mut dom = VirtualDom::new(app);
|
||||
_ = dom.rebuild();
|
||||
|
||||
assert_eq!(dioxus_ssr::render(&dom), r#"<div><div>1234</div></div>"#);
|
||||
}
|
Loading…
Reference in a new issue