Merge branch 'leptos_dom_v2' of https://github.com/jquesada2016/leptos into leptos_dom_v2
This commit is contained in:
commit
4a9f906571
|
@ -12,6 +12,7 @@ pub use fragment::*;
|
|||
use leptos_reactive::Scope;
|
||||
use std::borrow::Cow;
|
||||
pub use unit::*;
|
||||
#[cfg(all(target_arch = "wasm32", feature = "web"))]
|
||||
use wasm_bindgen::JsCast;
|
||||
|
||||
/// The core foundational leptos components.
|
||||
|
|
|
@ -1,8 +1,11 @@
|
|||
use crate::{hydration::HydrationCtx, Comment, IntoView, View};
|
||||
#[cfg(all(target_arch = "wasm32", feature = "web"))]
|
||||
use crate::{mount_child, MountKind, Mountable};
|
||||
use leptos_reactive::{create_effect, Scope, ScopeDisposer};
|
||||
use leptos_reactive::Scope;
|
||||
#[cfg(all(target_arch = "wasm32", feature = "web"))]
|
||||
use leptos_reactive::{create_effect, ScopeDisposer};
|
||||
use std::{borrow::Cow, cell::RefCell, rc::Rc};
|
||||
#[cfg(all(target_arch = "wasm32", feature = "web"))]
|
||||
use wasm_bindgen::JsCast;
|
||||
|
||||
/// The internal representation of the [`DynChild`] core-component.
|
||||
|
|
|
@ -1,18 +1,20 @@
|
|||
use crate::{hydration::HydrationCtx, Comment, CoreComponent, IntoView, View};
|
||||
#[cfg(all(target_arch = "wasm32", feature = "web"))]
|
||||
use crate::{mount_child, MountKind, Mountable, RANGE};
|
||||
use leptos_reactive::{create_effect, Scope};
|
||||
#[cfg(all(target_arch = "wasm32", feature = "web"))]
|
||||
use leptos_reactive::create_effect;
|
||||
use leptos_reactive::Scope;
|
||||
#[cfg(all(target_arch = "wasm32", feature = "web"))]
|
||||
use rustc_hash::FxHasher;
|
||||
use smallvec::SmallVec;
|
||||
use std::{
|
||||
borrow::Cow,
|
||||
cell::RefCell,
|
||||
hash::{BuildHasherDefault, Hash},
|
||||
rc::Rc,
|
||||
};
|
||||
#[cfg(all(target_arch = "wasm32", feature = "web"))]
|
||||
use std::hash::BuildHasherDefault;
|
||||
use std::{borrow::Cow, cell::RefCell, hash::Hash, rc::Rc};
|
||||
use typed_builder::TypedBuilder;
|
||||
#[cfg(all(target_arch = "wasm32", feature = "web"))]
|
||||
use wasm_bindgen::JsCast;
|
||||
|
||||
#[cfg(all(target_arch = "wasm32", feature = "web"))]
|
||||
type FxIndexSet<T> = indexmap::IndexSet<T, BuildHasherDefault<FxHasher>>;
|
||||
|
||||
#[cfg(all(target_arch = "wasm32", feature = "web"))]
|
||||
|
@ -269,12 +271,14 @@ where
|
|||
key_fn,
|
||||
} = self;
|
||||
|
||||
#[cfg(not(all(target_arch = "wasm32", feature = "web")))]
|
||||
let _ = key_fn;
|
||||
|
||||
let component = EachRepr::default();
|
||||
|
||||
let children = component.children.clone();
|
||||
|
||||
#[cfg(all(target_arch = "wasm32", feature = "web"))]
|
||||
let closing = component.closing.node.clone();
|
||||
let (children, closing) =
|
||||
(component.children.clone(), component.closing.node.clone());
|
||||
|
||||
cfg_if::cfg_if! {
|
||||
if #[cfg(all(target_arch = "wasm32", feature = "web"))] {
|
||||
|
@ -341,6 +345,7 @@ where
|
|||
struct HashRun<T>(#[educe(Debug(ignore))] T);
|
||||
|
||||
/// Calculates the operations need to get from `a` to `b`.
|
||||
#[cfg(all(target_arch = "wasm32", feature = "web"))]
|
||||
fn diff<K: Eq + Hash>(from: &FxIndexSet<K>, to: &FxIndexSet<K>) -> Diff {
|
||||
if from.is_empty() && to.is_empty() {
|
||||
return Diff::default();
|
||||
|
@ -428,6 +433,7 @@ fn diff<K: Eq + Hash>(from: &FxIndexSet<K>, to: &FxIndexSet<K>) -> Diff {
|
|||
diffs
|
||||
}
|
||||
|
||||
#[cfg(all(target_arch = "wasm32", feature = "web"))]
|
||||
fn apply_opts<K: Eq + Hash>(
|
||||
from: &FxIndexSet<K>,
|
||||
to: &FxIndexSet<K>,
|
||||
|
@ -463,6 +469,7 @@ fn apply_opts<K: Eq + Hash>(
|
|||
}
|
||||
|
||||
#[derive(Debug, Default)]
|
||||
#[allow(unused)]
|
||||
struct Diff {
|
||||
removed: SmallVec<[DiffOpRemove; 8]>,
|
||||
moved: SmallVec<[DiffOpMove; 8]>,
|
||||
|
@ -471,6 +478,7 @@ struct Diff {
|
|||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
#[allow(unused)]
|
||||
struct DiffOpMove {
|
||||
from: usize,
|
||||
to: usize,
|
||||
|
@ -478,17 +486,20 @@ struct DiffOpMove {
|
|||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
#[allow(unused)]
|
||||
struct DiffOpAdd {
|
||||
at: usize,
|
||||
mode: DiffOpAddMode,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
#[allow(unused)]
|
||||
struct DiffOpRemove {
|
||||
at: usize,
|
||||
}
|
||||
|
||||
#[derive(Default, Debug)]
|
||||
#[allow(unused)]
|
||||
enum DiffOpAddMode {
|
||||
#[default]
|
||||
Normal,
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
#[cfg(all(target_arch = "wasm32", feature = "web"))]
|
||||
use crate::Mountable;
|
||||
use crate::{hydration::HydrationCtx, Comment, CoreComponent, IntoView, View};
|
||||
#[cfg(all(target_arch = "wasm32", feature = "web"))]
|
||||
use wasm_bindgen::JsCast;
|
||||
|
||||
/// The internal representation of the [`Unit`] core-component.
|
||||
|
|
|
@ -1,9 +1,11 @@
|
|||
pub mod typed;
|
||||
|
||||
#[cfg(all(target_arch = "wasm32", feature = "web"))]
|
||||
use crate::window;
|
||||
use std::{borrow::Cow, cell::RefCell, collections::HashSet};
|
||||
#[cfg(all(target_arch = "wasm32", feature = "web"))]
|
||||
use wasm_bindgen::{
|
||||
closure::Closure, convert::FromWasmAbi, intern, JsCast, JsValue,
|
||||
convert::FromWasmAbi, intern, prelude::Closure, JsCast, JsValue,
|
||||
UnwrapThrowExt,
|
||||
};
|
||||
|
||||
|
@ -12,6 +14,7 @@ thread_local! {
|
|||
}
|
||||
|
||||
/// Adds an event listener to the `Window`.
|
||||
#[cfg(all(target_arch = "wasm32", feature = "web"))]
|
||||
pub fn window_event_listener(
|
||||
event_name: &str,
|
||||
cb: impl Fn(web_sys::Event) + 'static,
|
||||
|
@ -23,6 +26,7 @@ pub fn window_event_listener(
|
|||
}
|
||||
|
||||
/// Adds an event listener to the target DOM element using implicit event delegation.
|
||||
#[cfg(all(target_arch = "wasm32", feature = "web"))]
|
||||
pub fn add_event_listener<E>(
|
||||
target: &web_sys::Element,
|
||||
event_name: Cow<'static, str>,
|
||||
|
@ -37,6 +41,7 @@ pub fn add_event_listener<E>(
|
|||
}
|
||||
|
||||
#[doc(hidden)]
|
||||
#[cfg(all(target_arch = "wasm32", feature = "web"))]
|
||||
pub fn add_event_listener_undelegated<E>(
|
||||
target: &web_sys::Element,
|
||||
event_name: &str,
|
||||
|
@ -50,6 +55,7 @@ pub fn add_event_listener_undelegated<E>(
|
|||
}
|
||||
|
||||
// cf eventHandler in ryansolid/dom-expressions
|
||||
#[cfg(all(target_arch = "wasm32", feature = "web"))]
|
||||
pub(crate) fn add_delegated_event_listener(event_name: Cow<'static, str>) {
|
||||
GLOBAL_EVENTS.with(|global_events| {
|
||||
let mut events = global_events.borrow_mut();
|
||||
|
@ -113,6 +119,7 @@ pub(crate) fn add_delegated_event_listener(event_name: Cow<'static, str>) {
|
|||
})
|
||||
}
|
||||
|
||||
#[cfg(all(target_arch = "wasm32", feature = "web"))]
|
||||
pub(crate) fn event_delegation_key(event_name: &str) -> String {
|
||||
let event_name = intern(event_name);
|
||||
let mut n = String::from("$$$");
|
||||
|
|
|
@ -1,11 +1,16 @@
|
|||
#[cfg(all(target_arch = "wasm32", feature = "web"))]
|
||||
use crate::events::*;
|
||||
#[cfg(all(target_arch = "wasm32", feature = "web"))]
|
||||
use crate::macro_helpers::Property;
|
||||
#[cfg(all(target_arch = "wasm32", feature = "web"))]
|
||||
use crate::macro_helpers::{
|
||||
attribute_expression, class_expression, property_expression,
|
||||
};
|
||||
use crate::{
|
||||
ev::EventDescriptor,
|
||||
hydration::HydrationCtx,
|
||||
macro_helpers::{
|
||||
attribute_expression, class_expression, property_expression, Attribute,
|
||||
Class, IntoAttribute, IntoChild, IntoClass, IntoProperty, Property,
|
||||
Attribute, Class, IntoAttribute, IntoChild, IntoClass, IntoProperty,
|
||||
},
|
||||
Element, Fragment, IntoView, NodeRef, Text, View,
|
||||
};
|
||||
|
@ -15,10 +20,15 @@ use crate::{mount_child, MountKind};
|
|||
use std::cell::OnceCell;
|
||||
|
||||
use cfg_if::cfg_if;
|
||||
use leptos_reactive::{create_render_effect, Scope};
|
||||
#[cfg(all(target_arch = "wasm32", feature = "web"))]
|
||||
use leptos_reactive::create_render_effect;
|
||||
use leptos_reactive::Scope;
|
||||
#[cfg(not(all(target_arch = "wasm32", feature = "web")))]
|
||||
use smallvec::{smallvec, SmallVec};
|
||||
use std::{borrow::Cow, cell::LazyCell, fmt, ops::Deref};
|
||||
use std::{borrow::Cow, fmt};
|
||||
#[cfg(all(target_arch = "wasm32", feature = "web"))]
|
||||
use std::{cell::LazyCell, ops::Deref};
|
||||
#[cfg(all(target_arch = "wasm32", feature = "web"))]
|
||||
use wasm_bindgen::JsCast;
|
||||
|
||||
/// Trait alias for the trait bounts on [`IntoElement`].
|
||||
|
@ -61,14 +71,45 @@ pub trait IntoElement: IntoElementBounds {
|
|||
fn hydration_id(&self) -> usize;
|
||||
}
|
||||
|
||||
/// Trait for converting [`web_sys::Element`] to [`HtmlElement`].
|
||||
pub trait ToHtmlElement {
|
||||
/// Converts the type to [`HtmlElement`].
|
||||
fn to_leptos_element(self, cx: Scope) -> HtmlElement<AnyElement>;
|
||||
}
|
||||
|
||||
impl<T> ToHtmlElement for T
|
||||
where
|
||||
T: AsRef<web_sys::Element>,
|
||||
{
|
||||
fn to_leptos_element(self, cx: Scope) -> HtmlElement<AnyElement> {
|
||||
#[cfg(all(target_arch = "wasm32", feature = "web"))]
|
||||
{
|
||||
let el = self.as_ref().clone().unchecked_into();
|
||||
|
||||
let element = AnyElement {
|
||||
name: "".into(),
|
||||
is_void: false,
|
||||
element: el,
|
||||
};
|
||||
|
||||
HtmlElement { cx, element }
|
||||
}
|
||||
|
||||
#[cfg(not(all(target_arch = "wasm32", feature = "web")))]
|
||||
{
|
||||
let _ = cx;
|
||||
|
||||
unreachable!();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Represents potentially any element.
|
||||
#[derive(Clone, Debug)]
|
||||
#[cfg_attr(all(target_arch = "wasm32", feature = "web"), derive(educe::Educe))]
|
||||
#[cfg_attr(all(target_arch = "wasm32", feature = "web"), educe(Deref))]
|
||||
pub struct AnyElement {
|
||||
name: Cow<'static, str>,
|
||||
#[cfg(not(all(target_arch = "wasm32", feature = "web")))]
|
||||
dynamic: bool,
|
||||
#[cfg(all(target_arch = "wasm32", feature = "web"))]
|
||||
#[educe(Deref)]
|
||||
element: web_sys::HtmlElement,
|
||||
|
@ -151,7 +192,6 @@ cfg_if! {
|
|||
pub(crate) cx: Scope,
|
||||
pub(crate) element: El,
|
||||
pub(crate) id: OnceCell<Cow<'static, str>>,
|
||||
pub(crate) dynamic: bool,
|
||||
#[educe(Debug(ignore))]
|
||||
pub(crate) attrs: SmallVec<[(Cow<'static, str>, Cow<'static, str>); 4]>,
|
||||
#[educe(Debug(ignore))]
|
||||
|
@ -173,7 +213,6 @@ impl<El: IntoElement> HtmlElement<El> {
|
|||
Self {
|
||||
cx,
|
||||
id: Default::default(),
|
||||
dynamic: false,
|
||||
attrs: smallvec![],
|
||||
children: smallvec![],
|
||||
element,
|
||||
|
@ -203,7 +242,6 @@ impl<El: IntoElement> HtmlElement<El> {
|
|||
let Self {
|
||||
cx,
|
||||
id,
|
||||
dynamic,
|
||||
attrs,
|
||||
children,
|
||||
element,
|
||||
|
@ -212,12 +250,10 @@ impl<El: IntoElement> HtmlElement<El> {
|
|||
HtmlElement {
|
||||
cx,
|
||||
id,
|
||||
dynamic,
|
||||
attrs,
|
||||
children,
|
||||
element: AnyElement {
|
||||
name: element.name(),
|
||||
dynamic,
|
||||
is_void: element.is_void(),
|
||||
id: element.hydration_id(),
|
||||
},
|
||||
|
@ -257,6 +293,9 @@ impl<El: IntoElement> HtmlElement<El> {
|
|||
#[cfg(all(target_arch = "wasm32", feature = "web"))]
|
||||
node_ref.load(&self);
|
||||
|
||||
#[cfg(not(all(target_arch = "wasm32", feature = "web")))]
|
||||
let _ = node_ref;
|
||||
|
||||
self
|
||||
}
|
||||
|
||||
|
@ -295,7 +334,6 @@ impl<El: IntoElement> HtmlElement<El> {
|
|||
|
||||
let mut attr = attr.into_attribute(this.cx);
|
||||
while let Attribute::Fn(_, f) = attr {
|
||||
this.dynamic = true;
|
||||
attr = f();
|
||||
}
|
||||
match attr {
|
||||
|
@ -357,10 +395,7 @@ impl<El: IntoElement> HtmlElement<El> {
|
|||
|
||||
let include = match class {
|
||||
Class::Value(include) => include,
|
||||
Class::Fn(_, f) => {
|
||||
this.dynamic = true;
|
||||
f()
|
||||
}
|
||||
Class::Fn(_, f) => f(),
|
||||
};
|
||||
|
||||
if include {
|
||||
|
@ -408,17 +443,15 @@ impl<El: IntoElement> HtmlElement<El> {
|
|||
property_expression(el, prop_name, value)
|
||||
}
|
||||
};
|
||||
|
||||
self
|
||||
}
|
||||
|
||||
#[cfg(not(all(target_arch = "wasm32", feature = "web")))]
|
||||
{
|
||||
let mut this = self;
|
||||
|
||||
this.dynamic = true;
|
||||
|
||||
this
|
||||
let _ = name;
|
||||
let _ = value;
|
||||
}
|
||||
|
||||
self
|
||||
}
|
||||
|
||||
/// Adds an event listener to this element.
|
||||
|
@ -451,13 +484,10 @@ impl<El: IntoElement> HtmlElement<El> {
|
|||
|
||||
#[cfg(not(all(target_arch = "wasm32", feature = "web")))]
|
||||
{
|
||||
let mut this = self;
|
||||
|
||||
this.dynamic = true;
|
||||
_ = event;
|
||||
_ = event_handler;
|
||||
|
||||
this
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -499,7 +529,6 @@ impl<El: IntoElement> IntoView for HtmlElement<El> {
|
|||
element,
|
||||
mut attrs,
|
||||
children,
|
||||
dynamic,
|
||||
..
|
||||
} = self;
|
||||
|
||||
|
@ -514,7 +543,6 @@ impl<El: IntoElement> IntoView for HtmlElement<El> {
|
|||
attrs.push(("id".into(), format!("_{}", id).into()));
|
||||
}
|
||||
|
||||
element.dynamic = dynamic;
|
||||
element.attrs = attrs;
|
||||
element.children.extend(children);
|
||||
|
||||
|
@ -572,6 +600,7 @@ macro_rules! generate_html_tags {
|
|||
),* $(,)?) => {
|
||||
paste::paste! {
|
||||
$(
|
||||
#[cfg(all(target_arch = "wasm32", feature = "web"))]
|
||||
#[thread_local]
|
||||
static [<$tag:upper>]: LazyCell<web_sys::HtmlElement> = LazyCell::new(|| {
|
||||
crate::document()
|
||||
|
|
|
@ -1,8 +1,10 @@
|
|||
#[cfg(all(target_arch = "wasm32", feature = "web"))]
|
||||
use std::cell::LazyCell;
|
||||
|
||||
/// We can tell if we start in hydration mode by checking to see if the
|
||||
/// id "_0" is present in the DOM. If it is, we know we are hydrating from
|
||||
/// the server, if not, we are starting off in CSR
|
||||
#[cfg(all(target_arch = "wasm32", feature = "web"))]
|
||||
#[thread_local]
|
||||
static mut IS_HYDRATING: LazyCell<bool> = LazyCell::new(|| {
|
||||
#[cfg(debug_assertions)]
|
||||
|
@ -35,12 +37,14 @@ impl HydrationCtx {
|
|||
unsafe { ID = 0 };
|
||||
}
|
||||
|
||||
#[cfg(all(target_arch = "wasm32", feature = "web"))]
|
||||
pub(crate) fn stop_hydrating() {
|
||||
unsafe {
|
||||
std::mem::take(&mut IS_HYDRATING);
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(all(target_arch = "wasm32", feature = "web"))]
|
||||
pub(crate) fn is_hydrating() -> bool {
|
||||
unsafe { *IS_HYDRATING }
|
||||
}
|
||||
|
|
|
@ -29,11 +29,16 @@ pub use logging::*;
|
|||
pub use node_ref::*;
|
||||
#[cfg(not(all(target_arch = "wasm32", feature = "web")))]
|
||||
use smallvec::SmallVec;
|
||||
use std::{borrow::Cow, cell::LazyCell, fmt};
|
||||
use std::borrow::Cow;
|
||||
#[cfg(all(target_arch = "wasm32", feature = "web"))]
|
||||
use std::{cell::LazyCell, fmt};
|
||||
pub use wasm_bindgen;
|
||||
use wasm_bindgen::{JsCast, UnwrapThrowExt};
|
||||
#[cfg(all(target_arch = "wasm32", feature = "web"))]
|
||||
use wasm_bindgen::JsCast;
|
||||
use wasm_bindgen::UnwrapThrowExt;
|
||||
pub use web_sys;
|
||||
|
||||
#[cfg(all(target_arch = "wasm32", feature = "web"))]
|
||||
#[thread_local]
|
||||
static COMMENT: LazyCell<web_sys::Node> =
|
||||
LazyCell::new(|| document().create_comment("").unchecked_into());
|
||||
|
@ -128,7 +133,6 @@ cfg_if! {
|
|||
pub struct Element {
|
||||
name: Cow<'static, str>,
|
||||
is_void: bool,
|
||||
dynamic: bool,
|
||||
attrs: SmallVec<[(Cow<'static, str>, Cow<'static, str>); 4]>,
|
||||
children: Vec<View>,
|
||||
id: usize,
|
||||
|
@ -158,7 +162,6 @@ impl Element {
|
|||
Self {
|
||||
name: el.name(),
|
||||
is_void: el.is_void(),
|
||||
dynamic: false,
|
||||
attrs: Default::default(),
|
||||
children: Default::default(),
|
||||
id: el.hydration_id(),
|
||||
|
@ -183,6 +186,12 @@ impl Comment {
|
|||
) -> Self {
|
||||
let content = content.into();
|
||||
|
||||
#[cfg(not(all(target_arch = "wasm32", feature = "web")))]
|
||||
{
|
||||
let _ = id;
|
||||
let _ = closing;
|
||||
}
|
||||
|
||||
#[cfg(all(target_arch = "wasm32", feature = "web"))]
|
||||
let node = COMMENT.clone_node().unwrap();
|
||||
|
||||
|
@ -339,6 +348,7 @@ impl View {
|
|||
}
|
||||
}
|
||||
|
||||
#[cfg(all(target_arch = "wasm32", feature = "web"))]
|
||||
fn get_text(&self) -> Option<&Text> {
|
||||
if let Self::Text(t) = self {
|
||||
Some(t)
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
use std::rc::Rc;
|
||||
|
||||
use leptos_reactive::Scope;
|
||||
#[cfg(all(target_arch = "wasm32", feature = "web"))]
|
||||
use wasm_bindgen::UnwrapThrowExt;
|
||||
|
||||
/// Represents the different possible values an attribute node could have.
|
||||
|
@ -146,6 +147,7 @@ attr_type!(f32);
|
|||
attr_type!(f64);
|
||||
attr_type!(char);
|
||||
|
||||
#[cfg(all(target_arch = "wasm32", feature = "web"))]
|
||||
pub fn attribute_expression(
|
||||
el: &web_sys::Element,
|
||||
attr_name: &str,
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
use leptos_reactive::Scope;
|
||||
#[cfg(all(target_arch = "wasm32", feature = "web"))]
|
||||
use wasm_bindgen::UnwrapThrowExt;
|
||||
|
||||
/// Represents the different possible values a single class on an element could have,
|
||||
|
@ -65,6 +66,7 @@ impl<T: IntoClass> IntoClass for (Scope, T) {
|
|||
}
|
||||
}
|
||||
|
||||
#[cfg(all(target_arch = "wasm32", feature = "web"))]
|
||||
pub fn class_expression(
|
||||
class_list: &web_sys::DomTokenList,
|
||||
class_name: &str,
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
use leptos_reactive::Scope;
|
||||
use wasm_bindgen::{JsValue, UnwrapThrowExt};
|
||||
use wasm_bindgen::JsValue;
|
||||
#[cfg(all(target_arch = "wasm32", feature = "web"))]
|
||||
use wasm_bindgen::UnwrapThrowExt;
|
||||
|
||||
/// Represents the different possible values an element property could have,
|
||||
/// allowing you to do fine-grained updates to single fields.
|
||||
|
@ -74,6 +76,7 @@ prop_type!(f32);
|
|||
prop_type!(f64);
|
||||
prop_type!(bool);
|
||||
|
||||
#[cfg(all(target_arch = "wasm32", feature = "web"))]
|
||||
pub fn property_expression(
|
||||
el: &web_sys::Element,
|
||||
prop_name: &str,
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
use crate::{CoreComponent, HydrationCtx, View};
|
||||
use cfg_if::cfg_if;
|
||||
use itertools::Itertools;
|
||||
use std::{borrow::Cow, fmt::Display};
|
||||
use std::borrow::Cow;
|
||||
|
||||
impl View {
|
||||
/// Consumes the node and renders it into an HTML string.
|
||||
|
@ -123,17 +123,14 @@ impl View {
|
|||
}
|
||||
View::Element(el) => {
|
||||
let tag_name = el.name;
|
||||
let mut has_id = false;
|
||||
let mut attrs = el
|
||||
|
||||
let attrs = el
|
||||
.attrs
|
||||
.into_iter()
|
||||
.map(|(name, value)| -> Cow<'static, str> {
|
||||
if value.is_empty() {
|
||||
format!(" {name}").into()
|
||||
} else {
|
||||
if name == "id" {
|
||||
has_id = true;
|
||||
}
|
||||
format!(
|
||||
" {name}=\"{}\"",
|
||||
html_escape::encode_double_quoted_attribute(&value)
|
||||
|
@ -143,10 +140,6 @@ impl View {
|
|||
})
|
||||
.join("");
|
||||
|
||||
if !has_id && el.dynamic {
|
||||
attrs.push_str(&format!(" id=\"_{}\"", el.id));
|
||||
}
|
||||
|
||||
if el.is_void {
|
||||
format!("<{tag_name}{attrs}/>").into()
|
||||
} else {
|
||||
|
|
Loading…
Reference in New Issue