mirror of
https://github.com/DioxusLabs/dioxus
synced 2024-11-23 04:33:06 +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
|
// This will be true if there are static styles
|
||||||
inside_style_tag: bool,
|
inside_style_tag: bool,
|
||||||
},
|
},
|
||||||
|
/// A marker for where to insert a dynamic inner html
|
||||||
|
InnerHtmlMarker,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl std::fmt::Write for StringChain {
|
impl std::fmt::Write for StringChain {
|
||||||
|
@ -69,6 +71,9 @@ impl StringCache {
|
||||||
write!(chain, "<{tag}")?;
|
write!(chain, "<{tag}")?;
|
||||||
// we need to collect the styles and write them at the end
|
// we need to collect the styles and write them at the end
|
||||||
let mut styles = Vec::new();
|
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;
|
let mut has_dynamic_attrs = false;
|
||||||
for attr in *attrs {
|
for attr in *attrs {
|
||||||
match attr {
|
match attr {
|
||||||
|
@ -77,7 +82,9 @@ impl StringCache {
|
||||||
value,
|
value,
|
||||||
namespace,
|
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));
|
styles.push((name, value));
|
||||||
} else {
|
} else {
|
||||||
write!(chain, " {name}=\"{value}\"")?;
|
write!(chain, " {name}=\"{value}\"")?;
|
||||||
|
@ -110,6 +117,13 @@ impl StringCache {
|
||||||
write!(chain, "/>")?;
|
write!(chain, "/>")?;
|
||||||
} else {
|
} else {
|
||||||
write!(chain, ">")?;
|
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 {
|
for child in *children {
|
||||||
Self::recurse(child, cur_path, root_idx, chain)?;
|
Self::recurse(child, cur_path, root_idx, chain)?;
|
||||||
}
|
}
|
||||||
|
|
|
@ -70,6 +70,8 @@ impl Renderer {
|
||||||
.or_insert_with(|| Rc::new(StringCache::from_template(template).unwrap()))
|
.or_insert_with(|| Rc::new(StringCache::from_template(template).unwrap()))
|
||||||
.clone();
|
.clone();
|
||||||
|
|
||||||
|
let mut inner_html = None;
|
||||||
|
|
||||||
// We need to keep track of the dynamic styles so we can insert them into the right place
|
// 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();
|
let mut accumulated_dynamic_styles = Vec::new();
|
||||||
|
|
||||||
|
@ -77,7 +79,9 @@ impl Renderer {
|
||||||
match segment {
|
match segment {
|
||||||
Segment::Attr(idx) => {
|
Segment::Attr(idx) => {
|
||||||
let attr = &template.dynamic_attrs[*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);
|
accumulated_dynamic_styles.push(attr);
|
||||||
} else {
|
} else {
|
||||||
match attr.value {
|
match attr.value {
|
||||||
|
@ -165,6 +169,19 @@ impl Renderer {
|
||||||
accumulated_dynamic_styles.clear();
|
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 {
|
StyleMarker {
|
||||||
inside_style_tag: false,
|
inside_style_tag: false,
|
||||||
},
|
},
|
||||||
PreRendered(">Hello world 1 -->".into(),),
|
PreRendered(">".into()),
|
||||||
|
InnerHtmlMarker,
|
||||||
|
PreRendered("Hello world 1 -->".into(),),
|
||||||
Node(0,),
|
Node(0,),
|
||||||
PreRendered(
|
PreRendered(
|
||||||
"<-- Hello world 2<div>nest 1</div><div></div><div>nest 2</div>".into(),
|
"<-- 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