Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add VNode::from_html_unchecked #2842

Merged
merged 30 commits into from Nov 8, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
30 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
4 changes: 0 additions & 4 deletions examples/inner_html/src/document.html
Expand Up @@ -4,10 +4,6 @@ <h2>Inline HTML with SVG</h2>
Rust source code. The code queries the DOM, creates a new element, and applies
this snippet of HTML to the element's innerHTML.
</p>
<p>
If you look at your browser's console you can see the DOM element (logged to
the console).
</p>
<svg height="250" width="500">
<polygon
points="220,10 300,210 170,250 123,234"
Expand Down
14 changes: 3 additions & 11 deletions examples/inner_html/src/main.rs
@@ -1,27 +1,19 @@
use web_sys::console;
use yew::{Component, Context, Html};

const HTML: &str = include_str!("document.html");

pub struct App {
pub value: i64,
}
pub struct App;

impl Component for App {
type Message = ();
type Properties = ();

fn create(_ctx: &Context<Self>) -> Self {
Self { value: 0 }
Self
}

fn view(&self, _ctx: &Context<Self>) -> Html {
let div = gloo::utils::document().create_element("div").unwrap();
div.set_inner_html(HTML);
// See <https://github.com/yewstack/yew/issues/1546>
console::log_1(&div);

Html::VRef(div.into())
Html::from_html_unchecked(HTML.into())
}
}

Expand Down
2 changes: 2 additions & 0 deletions packages/yew/Cargo.toml
Expand Up @@ -56,6 +56,7 @@ features = [
"FocusEvent",
"HtmlElement",
"HtmlInputElement",
"HtmlCollection",
"HtmlTextAreaElement",
"InputEvent",
"InputEventInit",
Expand Down Expand Up @@ -91,6 +92,7 @@ version = "0.3"
features = [
"ShadowRootInit",
"ShadowRootMode",
"HtmlButtonElement"
]

[features]
Expand Down
25 changes: 24 additions & 1 deletion packages/yew/src/dom_bundle/bnode.rs
Expand Up @@ -4,7 +4,7 @@ use std::fmt;

use web_sys::{Element, Node};

use super::{BComp, BList, BPortal, BSubtree, BSuspense, BTag, BText};
use super::{BComp, BList, BPortal, BRaw, BSubtree, BSuspense, BTag, BText};
use crate::dom_bundle::{Reconcilable, ReconcileTarget};
use crate::html::{AnyScope, NodeRef};
use crate::virtual_dom::{Key, VNode};
Expand All @@ -25,6 +25,8 @@ pub(super) enum BNode {
Ref(Node),
/// A suspendible document fragment.
Suspense(Box<BSuspense>),
/// A raw HTML string, represented by [`AttrValue`](crate::AttrValue).
Raw(BRaw),
}

impl BNode {
Expand All @@ -38,6 +40,7 @@ impl BNode {
Self::Text(_) => None,
Self::Portal(bportal) => bportal.key(),
Self::Suspense(bsusp) => bsusp.key(),
Self::Raw(_) => None,
}
}
}
Expand All @@ -58,6 +61,7 @@ impl ReconcileTarget for BNode {
}
Self::Portal(bportal) => bportal.detach(root, parent, parent_to_detach),
Self::Suspense(bsusp) => bsusp.detach(root, parent, parent_to_detach),
Self::Raw(raw) => raw.detach(root, parent, parent_to_detach),
}
}

Expand All @@ -76,6 +80,7 @@ impl ReconcileTarget for BNode {
}
Self::Portal(ref vportal) => vportal.shift(next_parent, next_sibling),
Self::Suspense(ref vsuspense) => vsuspense.shift(next_parent, next_sibling),
Self::Raw(ref braw) => braw.shift(next_parent, next_sibling),
}
}
}
Expand Down Expand Up @@ -120,6 +125,10 @@ impl Reconcilable for VNode {
vsuspsense.attach(root, parent_scope, parent, next_sibling);
(node_ref, suspsense.into())
}
VNode::VRaw(vraw) => {
let (node_ref, raw) = vraw.attach(root, parent_scope, parent, next_sibling);
(node_ref, raw.into())
}
}
}

Expand Down Expand Up @@ -176,6 +185,9 @@ impl Reconcilable for VNode {
VNode::VSuspense(vsuspsense) => {
vsuspsense.reconcile_node(root, parent_scope, parent, next_sibling, bundle)
}
VNode::VRaw(vraw) => {
vraw.reconcile_node(root, parent_scope, parent, next_sibling, bundle)
}
}
}
}
Expand Down Expand Up @@ -222,6 +234,13 @@ impl From<BSuspense> for BNode {
}
}

impl From<BRaw> for BNode {
#[inline]
fn from(braw: BRaw) -> Self {
Self::Raw(braw)
}
}

impl fmt::Debug for BNode {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match *self {
Expand All @@ -232,6 +251,7 @@ impl fmt::Debug for BNode {
Self::Ref(ref vref) => write!(f, "VRef ( \"{}\" )", crate::utils::print_node(vref)),
Self::Portal(ref vportal) => vportal.fmt(f),
Self::Suspense(ref bsusp) => bsusp.fmt(f),
Self::Raw(ref braw) => braw.fmt(f),
}
}
}
Expand Down Expand Up @@ -285,6 +305,9 @@ mod feat_hydration {
vsuspense.hydrate(root, parent_scope, parent, fragment);
(node_ref, suspense.into())
}
VNode::VRaw(_) => {
panic!("VRaw is not hydratable (raw HTML string cannot be hydrated)")
}
}
}
}
Expand Down