diff --git a/Cargo.toml b/Cargo.toml index 5e91a34bf8e..7e4d2ce9e12 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -21,6 +21,8 @@ travis-ci = { repository = "yewstack/yew" } [dependencies] anymap = "0.12" bincode = { version = "~1.2.1", optional = true } +cfg-if = "0.1" +cfg-match = "0.2" console_error_panic_hook = { version = "0.1", optional = true } failure = "0.1" gloo = { version = "0.2", optional = true } diff --git a/src/app.rs b/src/app.rs index 7ef42b01b86..466e46a9050 100644 --- a/src/app.rs +++ b/src/app.rs @@ -3,10 +3,14 @@ use crate::html::{Component, NodeRef, Scope}; use crate::utils::document; -#[cfg(feature = "std_web")] -use stdweb::web::{Element, INode, IParentNode}; -#[cfg(feature = "web_sys")] -use web_sys::Element; +use cfg_if::cfg_if; +cfg_if! { + if #[cfg(feature = "std_web")] { + use stdweb::web::{Element, INode, IParentNode}; + } else if #[cfg(feature = "web_sys")] { + use web_sys::Element; + } +} /// An application instance. #[derive(Debug)] diff --git a/src/components/select.rs b/src/components/select.rs index cb919f2782c..322a0994736 100644 --- a/src/components/select.rs +++ b/src/components/select.rs @@ -35,6 +35,7 @@ use crate::callback::Callback; use crate::html::{ChangeData, Component, ComponentLink, Html, ShouldRender}; use crate::macros::{html, Properties}; +use cfg_match::cfg_match; /// `Select` component. #[derive(Debug)] @@ -122,10 +123,10 @@ where self.link.callback(|event| match event { ChangeData::Select(elem) => { let value = elem.selected_index(); - #[cfg(feature = "std_web")] - let value = value.map(|x| x as usize); - #[cfg(feature = "web_sys")] - let value = Some(value as usize); + let value = cfg_match! { + feature = "std_web" => value.map(|x| x as usize), + feature = "web_sys" => Some(value as usize), + }; Msg::Selected(value) } _ => { diff --git a/src/html/listener/macros.rs b/src/html/listener/macros.rs index 467db502dd0..957f69036c4 100644 --- a/src/html/listener/macros.rs +++ b/src/html/listener/macros.rs @@ -6,21 +6,22 @@ macro_rules! impl_action { ($($action:ident(name: $name:literal, event: $type:ident) -> $ret:ty => $convert:expr)*) => {$( /// An abstract implementation of a listener. pub mod $action { + use cfg_if::cfg_if; + use cfg_match::cfg_match; use crate::callback::Callback; #[allow(unused_imports)] use crate::html::listener::*; use crate::virtual_dom::Listener; - #[cfg(feature = "std_web")] - use stdweb::web::{ - event::{$type, IEvent}, - Element, IEventTarget, - }; - #[cfg(feature = "web_sys")] - use ::{ - gloo::events::EventListener, - wasm_bindgen::JsValue, - web_sys::{$type as WebSysType, Element, EventTarget}, - }; + cfg_if! { + if #[cfg(feature = "std_web")] { + use stdweb::web::event::{$type, IEvent}; + use stdweb::web::{Element, IEventTarget}; + } else if #[cfg(feature = "web_sys")] { + use gloo::events::EventListener; + use wasm_bindgen::JsValue; + use web_sys::{$type as WebSysType, Element, EventTarget}; + } + } /// A wrapper for a callback which attaches event listeners to elements. #[derive(Clone, Debug)] @@ -55,12 +56,10 @@ macro_rules! impl_action { let event: WebSysType = JsValue::from(event).into(); callback.emit($convert(&this, event)); }; - #[cfg(feature = "std_web")] - { - EventListener(Some(element.add_event_listener(listener))) + cfg_match! { + feature = "std_web" => EventListener(Some(element.add_event_listener(listener))), + feature = "web_sys" => EventListener::new(&EventTarget::from(element.clone()), $name, listener), } - #[cfg(feature = "web_sys")] - EventListener::new(&EventTarget::from(element.clone()), $name, listener) } } } diff --git a/src/html/listener/mod.rs b/src/html/listener/mod.rs index 439bb7bf84c..b30ee1581db 100644 --- a/src/html/listener/mod.rs +++ b/src/html/listener/mod.rs @@ -1,31 +1,31 @@ #[macro_use] mod macros; -#[cfg(feature = "std_web")] -mod listener_stdweb; -#[cfg(feature = "web_sys")] -mod listener_web_sys; -#[cfg(feature = "std_web")] -pub use listener_stdweb::*; -#[cfg(feature = "web_sys")] -pub use listener_web_sys::*; -#[cfg(feature = "std_web")] -use stdweb::{ - js, - unstable::TryInto, - web::{ - html_element::{InputElement, SelectElement, TextAreaElement}, - Element, EventListenerHandle, FileList, IElement, INode, - }, -}; -#[cfg(feature = "web_sys")] -use ::{ - wasm_bindgen::JsCast, - web_sys::{ - Element, FileList, HtmlInputElement as InputElement, HtmlSelectElement as SelectElement, - HtmlTextAreaElement as TextAreaElement, - }, -}; +use cfg_if::cfg_if; +use cfg_match::cfg_match; + +cfg_if! { + if #[cfg(feature = "std_web")] { + mod listener_stdweb; + + use stdweb::js; + use stdweb::unstable::{TryFrom, TryInto}; + use stdweb::web::html_element::{InputElement, SelectElement, TextAreaElement}; + use stdweb::web::{Element, EventListenerHandle, FileList, IElement, INode}; + + pub use listener_stdweb::*; + } else if #[cfg(feature = "web_sys")] { + mod listener_web_sys; + + use wasm_bindgen::JsCast; + use web_sys::{ + Element, FileList, HtmlInputElement as InputElement, HtmlSelectElement as SelectElement, + HtmlTextAreaElement as TextAreaElement, + }; + + pub use listener_web_sys::*; + } +} /// A type representing data from `oninput` event. #[derive(Debug)] @@ -60,22 +60,26 @@ fn oninput_handler(this: &Element) -> InputData { // practice though any element with `contenteditable=true` may generate such events, // therefore here we fall back to just returning the text content of the node. // See https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement/input_event. - #[cfg(feature = "std_web")] - let (v1, v2) = ( - this.clone() - .try_into() - .map(|input: InputElement| input.raw_value()) - .ok(), - this.clone() - .try_into() - .map(|input: TextAreaElement| input.value()) - .ok(), - ); - #[cfg(feature = "web_sys")] - let (v1, v2) = ( - this.dyn_ref().map(|input: &InputElement| input.value()), - this.dyn_ref().map(|input: &TextAreaElement| input.value()), - ); + let (v1, v2) = cfg_match! { + feature = "std_web" => ({ + ( + this.clone() + .try_into() + .map(|input: InputElement| input.raw_value()) + .ok(), + this.clone() + .try_into() + .map(|input: TextAreaElement| input.value()) + .ok(), + ) + }), + feature = "web_sys" => ({ + ( + this.dyn_ref().map(|input: &InputElement| input.value()), + this.dyn_ref().map(|input: &TextAreaElement| input.value()), + ) + }), + }; let v3 = this.text_content(); let value = v1.or(v2).or(v3) .expect("only an InputElement or TextAreaElement or an element with contenteditable=true can have an oninput event listener"); @@ -85,39 +89,39 @@ fn oninput_handler(this: &Element) -> InputData { fn onchange_handler(this: &Element) -> ChangeData { match this.node_name().as_ref() { "INPUT" => { - #[cfg(feature = "std_web")] - let input: InputElement = this.clone().try_into().unwrap(); - #[cfg(feature = "web_sys")] - let input: &InputElement = this.dyn_ref().unwrap(); + let input = cfg_match! { + feature = "std_web" => InputElement::try_from(this.clone()).unwrap(), + feature = "web_sys" => this.dyn_ref::().unwrap(), + }; let is_file = input .get_attribute("type") .map(|value| value.eq_ignore_ascii_case("file")) .unwrap_or(false); if is_file { - #[cfg(feature = "std_web")] - let files: FileList = js!( return @{input}.files; ).try_into().unwrap(); - #[cfg(feature = "web_sys")] - let files: FileList = input.files().unwrap(); + let files: FileList = cfg_match! { + feature = "std_web" => js!( return @{input}.files; ).try_into().unwrap(), + feature = "web_sys" => input.files().unwrap(), + }; ChangeData::Files(files) } else { - #[cfg(feature = "std_web")] - return ChangeData::Value(input.raw_value()); - #[cfg(feature = "web_sys")] - ChangeData::Value(input.value()) + cfg_match! { + feature = "std_web" => ChangeData::Value(input.raw_value()), + feature = "web_sys" => ChangeData::Value(input.value()), + } } } "TEXTAREA" => { - #[cfg(feature = "std_web")] - let tae: TextAreaElement = this.clone().try_into().unwrap(); - #[cfg(feature = "web_sys")] - let tae: &TextAreaElement = this.dyn_ref().unwrap(); + let tae = cfg_match! { + feature = "std_web" => TextAreaElement::try_from(this.clone()).unwrap(), + feature = "web_sys" => this.dyn_ref::().unwrap(), + }; ChangeData::Value(tae.value()) } "SELECT" => { - #[cfg(feature = "std_web")] - let se: SelectElement = this.clone().try_into().unwrap(); - #[cfg(feature = "web_sys")] - let se = this.dyn_ref::().unwrap().clone(); + let se = cfg_match! { + feature = "std_web" => SelectElement::try_from(this.clone()).unwrap(), + feature = "web_sys" => this.dyn_ref::().unwrap().clone(), + }; ChangeData::Select(se) } _ => { diff --git a/src/html/mod.rs b/src/html/mod.rs index 004dfc9fae5..9fa8e43330f 100644 --- a/src/html/mod.rs +++ b/src/html/mod.rs @@ -12,14 +12,21 @@ pub use scope::{Scope, ScopeHolder}; use crate::callback::Callback; use crate::virtual_dom::{VChild, VList, VNode}; +use cfg_if::cfg_if; +use cfg_match::cfg_match; use std::any::TypeId; use std::cell::RefCell; use std::fmt; use std::rc::Rc; -#[cfg(feature = "std_web")] -use stdweb::{unstable::TryFrom, web::Node}; -#[cfg(feature = "web_sys")] -use ::{wasm_bindgen::JsValue, web_sys::Node}; +cfg_if! { + if #[cfg(feature = "std_web")] { + use stdweb::unstable::TryFrom; + use stdweb::web::Node; + } else if #[cfg(feature = "web_sys")] { + use wasm_bindgen::JsValue; + use web_sys::Node; + } +} /// This type indicates that component should be rendered again. pub type ShouldRender = bool; @@ -324,12 +331,10 @@ impl NodeRef { &self, ) -> Option { let node = self.get(); - #[cfg(feature = "std_web")] - { - node.and_then(|node| INTO::try_from(node).ok()) + cfg_match! { + feature = "std_web" => node.and_then(|node| INTO::try_from(node).ok()), + feature = "web_sys" => node.map(Into::into).map(INTO::from), } - #[cfg(feature = "web_sys")] - node.map(Into::into).map(INTO::from) } /// Place a Node in a reference for later use diff --git a/src/html/scope.rs b/src/html/scope.rs index baa2e75aec9..45952daea7e 100644 --- a/src/html/scope.rs +++ b/src/html/scope.rs @@ -1,13 +1,17 @@ use super::*; use crate::scheduler::{scheduler, Runnable, Shared}; use crate::virtual_dom::{VDiff, VNode}; +use cfg_if::cfg_if; use std::cell::RefCell; use std::fmt; use std::rc::Rc; -#[cfg(feature = "std_web")] -use stdweb::web::Element; -#[cfg(feature = "web_sys")] -use web_sys::Element; +cfg_if! { + if #[cfg(feature = "std_web")] { + use stdweb::web::Element; + } else if #[cfg(feature = "web_sys")] { + use web_sys::Element; + } +} /// Updates for a `Component` instance. Used by scope sender. pub(crate) enum ComponentUpdate { diff --git a/src/lib.rs b/src/lib.rs index 73526298b37..7e2400870c1 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -99,32 +99,39 @@ pub mod services; /// The module that contains all events available in the framework. pub mod events { + use cfg_if::cfg_if; + pub use crate::html::{ChangeData, InputData}; - #[cfg(feature = "std_web")] - pub use stdweb::web::event::{ - BlurEvent, ClickEvent, ContextMenuEvent, DoubleClickEvent, DragDropEvent, DragEndEvent, - DragEnterEvent, DragEvent, DragExitEvent, DragLeaveEvent, DragOverEvent, DragStartEvent, - FocusEvent, GotPointerCaptureEvent, IKeyboardEvent, IMouseEvent, IPointerEvent, - KeyDownEvent, KeyPressEvent, KeyUpEvent, LostPointerCaptureEvent, MouseDownEvent, - MouseEnterEvent, MouseLeaveEvent, MouseMoveEvent, MouseOutEvent, MouseOverEvent, - MouseUpEvent, MouseWheelEvent, PointerCancelEvent, PointerDownEvent, PointerEnterEvent, - PointerLeaveEvent, PointerMoveEvent, PointerOutEvent, PointerOverEvent, PointerUpEvent, - ScrollEvent, SubmitEvent, TouchCancel, TouchEnd, TouchEnter, TouchMove, TouchStart, - }; - #[cfg(feature = "web_sys")] - pub use web_sys::{ - DragEvent, Event, FocusEvent, KeyboardEvent, MouseEvent, PointerEvent, TouchEvent, UiEvent, - WheelEvent, - }; + cfg_if! { + if #[cfg(feature = "std_web")] { + pub use stdweb::web::event::{ + BlurEvent, ClickEvent, ContextMenuEvent, DoubleClickEvent, DragDropEvent, DragEndEvent, + DragEnterEvent, DragEvent, DragExitEvent, DragLeaveEvent, DragOverEvent, DragStartEvent, + FocusEvent, GotPointerCaptureEvent, IKeyboardEvent, IMouseEvent, IPointerEvent, + KeyDownEvent, KeyPressEvent, KeyUpEvent, LostPointerCaptureEvent, MouseDownEvent, + MouseEnterEvent, MouseLeaveEvent, MouseMoveEvent, MouseOutEvent, MouseOverEvent, + MouseUpEvent, MouseWheelEvent, PointerCancelEvent, PointerDownEvent, PointerEnterEvent, + PointerLeaveEvent, PointerMoveEvent, PointerOutEvent, PointerOverEvent, PointerUpEvent, + ScrollEvent, SubmitEvent, TouchCancel, TouchEnd, TouchEnter, TouchMove, TouchStart, + }; + } else if #[cfg(feature = "web_sys")] { + pub use web_sys::{ + DragEvent, Event, FocusEvent, KeyboardEvent, MouseEvent, PointerEvent, TouchEvent, UiEvent, + WheelEvent, + }; + } + } } +use cfg_match::cfg_match; + /// Initializes yew framework. It should be called first. pub fn initialize() { - #[cfg(feature = "std_web")] - stdweb::initialize(); - #[cfg(feature = "web_sys")] - std::panic::set_hook(Box::new(console_error_panic_hook::hook)); + cfg_match! { + feature = "std_web" => stdweb::initialize(), + feature = "web_sys" => std::panic::set_hook(Box::new(console_error_panic_hook::hook)), + }; } /// Starts event loop. diff --git a/src/utils.rs b/src/utils.rs index 88db0f3aa41..83721074f09 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -1,18 +1,31 @@ //! This module contains useful utils to get information about the current document. +use cfg_if::cfg_if; +use cfg_match::cfg_match; use failure::{err_msg, Error}; use std::marker::PhantomData; +cfg_if! { + if #[cfg(feature = "std_web")] { + use stdweb::web::{Document, Window}; + } else if #[cfg(feature = "web_sys")] { + use web_sys::{Document, Window}; + } +} -#[cfg(feature = "std_web")] -/// Returns current document. -pub fn document() -> stdweb::web::Document { - stdweb::web::document() +/// Returns current window. +pub fn window() -> Window { + cfg_match! { + feature = "std_web" => stdweb::web::window(), + feature = "web_sys" => web_sys::window().expect("no window available"), + } } -#[cfg(feature = "web_sys")] /// Returns current document. -pub fn document() -> web_sys::Document { - web_sys::window().unwrap().document().unwrap() +pub fn document() -> Document { + cfg_match! { + feature = "std_web" => stdweb::web::document(), + feature = "web_sys" => window().document().unwrap(), + } } /// Returns `host` for the current document. Useful to connect to a server that server the app. diff --git a/src/virtual_dom/mod.rs b/src/virtual_dom/mod.rs index 56970522842..7d78a7883eb 100644 --- a/src/virtual_dom/mod.rs +++ b/src/virtual_dom/mod.rs @@ -6,18 +6,20 @@ pub mod vnode; pub mod vtag; pub mod vtext; -#[cfg(feature = "std_web")] -use crate::html::EventListener; -#[cfg(feature = "web_sys")] -use gloo::events::EventListener; +use cfg_if::cfg_if; use indexmap::set::IndexSet; use std::collections::HashMap; use std::fmt; use std::rc::Rc; -#[cfg(feature = "std_web")] -use stdweb::web::{Element, Node}; -#[cfg(feature = "web_sys")] -use web_sys::{Element, Node}; +cfg_if! { + if #[cfg(feature = "std_web")] { + use crate::html::EventListener; + use stdweb::web::{Element, Node}; + } else if #[cfg(feature = "web_sys")] { + use gloo::events::EventListener; + use web_sys::{Element, Node}; + } +} pub use self::vcomp::{VChild, VComp}; pub use self::vlist::VList; diff --git a/src/virtual_dom/vcomp.rs b/src/virtual_dom/vcomp.rs index e2b7ff2e548..4378c568a4f 100644 --- a/src/virtual_dom/vcomp.rs +++ b/src/virtual_dom/vcomp.rs @@ -3,14 +3,18 @@ use super::{Transformer, VDiff, VNode}; use crate::html::{Component, ComponentUpdate, HiddenScope, NodeRef, Scope}; use crate::utils::document; +use cfg_if::cfg_if; use std::any::TypeId; use std::cell::RefCell; use std::fmt; use std::rc::Rc; -#[cfg(feature = "std_web")] -use stdweb::web::{Element, INode, Node, TextNode}; -#[cfg(feature = "web_sys")] -use web_sys::{Element, Node, Text as TextNode}; +cfg_if! { + if #[cfg(feature = "std_web")] { + use stdweb::web::{Element, INode, Node, TextNode}; + } else if #[cfg(feature = "web_sys")] { + use web_sys::{Element, Node, Text as TextNode}; + } +} /// The method generates an instance of a component. type Generator = dyn Fn(GeneratorType) -> Mounted; @@ -219,10 +223,15 @@ impl VDiff for VComp { .insert_before(&dummy_node, next_sibling) .expect("can't insert dummy component node before next sibling"); } else { - #[cfg_attr(feature = "std_web", allow(unused_variables))] - let result = parent.append_child(&dummy_node); - #[cfg(feature = "web_sys")] - result.expect("can't append node to parent"); + #[cfg_attr( + feature = "std_web", + allow(clippy::let_unit_value, unused_variables) + )] + { + let result = parent.append_child(&dummy_node); + #[cfg(feature = "web_sys")] + result.expect("can't append node to parent"); + } } this.mount(parent.to_owned(), dummy_node) } diff --git a/src/virtual_dom/vlist.rs b/src/virtual_dom/vlist.rs index 2e7a2db95c2..87e392fd854 100644 --- a/src/virtual_dom/vlist.rs +++ b/src/virtual_dom/vlist.rs @@ -1,10 +1,14 @@ //! This module contains fragments implementation. use super::{VDiff, VNode, VText}; +use cfg_if::cfg_if; use std::ops::{Deref, DerefMut}; -#[cfg(feature = "std_web")] -use stdweb::web::{Element, Node}; -#[cfg(feature = "web_sys")] -use web_sys::{Element, Node}; +cfg_if! { + if #[cfg(feature = "std_web")] { + use stdweb::web::{Element, Node}; + } else if #[cfg(feature = "web_sys")] { + use web_sys::{Element, Node}; + } +} /// This struct represents a fragment of the Virtual DOM tree. #[derive(Clone, Debug, PartialEq, Default)] diff --git a/src/virtual_dom/vnode.rs b/src/virtual_dom/vnode.rs index d5252dbe8ad..1dc240b4289 100644 --- a/src/virtual_dom/vnode.rs +++ b/src/virtual_dom/vnode.rs @@ -2,13 +2,17 @@ use super::{VChild, VComp, VDiff, VList, VTag, VText}; use crate::html::{Component, Renderable}; +use cfg_if::cfg_if; use std::cmp::PartialEq; use std::fmt; use std::iter::FromIterator; -#[cfg(feature = "std_web")] -use stdweb::web::{Element, INode, Node}; -#[cfg(feature = "web_sys")] -use web_sys::{Element, Node}; +cfg_if! { + if #[cfg(feature = "std_web")] { + use stdweb::web::{Element, INode, Node}; + } else if #[cfg(feature = "web_sys")] { + use web_sys::{Element, Node}; + } +} /// Bind virtual element to a DOM reference. #[derive(Clone)] @@ -67,10 +71,15 @@ impl VDiff for VNode { .insert_before(node, sibling) .expect("can't insert element before sibling"); } else { - #[cfg_attr(feature = "std_web", allow(unused_variables))] - let result = parent.append_child(node); - #[cfg(feature = "web_sys")] - result.expect("can't append node to parent"); + #[cfg_attr( + feature = "std_web", + allow(clippy::let_unit_value, unused_variables) + )] + { + let result = parent.append_child(node); + #[cfg(feature = "web_sys")] + result.expect("can't append node to parent"); + } } Some(node.to_owned()) diff --git a/src/virtual_dom/vtag.rs b/src/virtual_dom/vtag.rs index e4650e80205..3ea1c3b9edf 100644 --- a/src/virtual_dom/vtag.rs +++ b/src/virtual_dom/vtag.rs @@ -3,36 +3,32 @@ use super::{ Attributes, Classes, Listener, Listeners, Patch, Reform, Transformer, VDiff, VList, VNode, }; -#[cfg(feature = "std_web")] -use crate::html::EventListener; use crate::html::NodeRef; use crate::utils::document; -#[cfg(feature = "web_sys")] -use gloo::events::EventListener; +use cfg_if::cfg_if; +use cfg_match::cfg_match; use log::warn; use std::borrow::Cow; use std::cmp::PartialEq; use std::fmt; use std::rc::Rc; -#[cfg(feature = "std_web")] -#[allow(unused_imports)] -use stdweb::{_js_impl, js}; -#[cfg(feature = "std_web")] -use stdweb::{ - unstable::TryFrom, - web::{ - html_element::{InputElement, TextAreaElement}, - Element, IElement, INode, Node, - }, -}; -#[cfg(feature = "web_sys")] -use ::{ - std::ops::Deref, - wasm_bindgen::JsCast, - web_sys::{ - Element, HtmlInputElement as InputElement, HtmlTextAreaElement as TextAreaElement, Node, - }, -}; +cfg_if! { + if #[cfg(feature = "std_web")] { + use crate::html::EventListener; + #[allow(unused_imports)] + use stdweb::{_js_impl, js}; + use stdweb::unstable::TryFrom; + use stdweb::web::html_element::{InputElement, TextAreaElement}; + use stdweb::web::{Element, IElement, INode, Node}; + } else if #[cfg(feature = "web_sys")] { + use gloo::events::EventListener; + use std::ops::Deref; + use wasm_bindgen::JsCast; + use web_sys::{ + Element, HtmlInputElement as InputElement, HtmlTextAreaElement as TextAreaElement, Node, + }; + } +} /// SVG namespace string used for creating svg elements pub const SVG_NAMESPACE: &str = "http://www.w3.org/2000/svg"; @@ -317,17 +313,17 @@ impl VTag { let list = element.class_list(); match change { Patch::Add(class, _) | Patch::Replace(class, _) => { - #[cfg(feature = "std_web")] - let result = list.add(class); - #[cfg(feature = "web_sys")] - let result = list.add_1(class); + let result = cfg_match! { + feature = "std_web" => list.add(class), + feature = "web_sys" => list.add_1(class), + }; result.expect("can't add a class"); } Patch::Remove(class) => { - #[cfg(feature = "std_web")] - let result = list.remove(class); - #[cfg(feature = "web_sys")] - let result = list.remove_1(class); + let result = cfg_match! { + feature = "std_web" => list.remove(class), + feature = "web_sys" => list.remove_1(class), + }; result.expect("can't remove a class"); } } @@ -350,29 +346,27 @@ impl VTag { // and useful in templates. For example I interpret `checked` // attribute as `checked` parameter, not `defaultChecked` as browsers do if let Some(input) = { - #[cfg(feature = "std_web")] - { - InputElement::try_from(element.clone()).ok() + cfg_match! { + feature = "std_web" => InputElement::try_from(element.clone()).ok(), + feature = "web_sys" => element.dyn_ref::(), } - #[cfg(feature = "web_sys")] - element.dyn_ref::() } { if let Some(change) = self.diff_kind(ancestor) { let kind = match change { Patch::Add(kind, _) | Patch::Replace(kind, _) => kind, Patch::Remove(_) => "", }; - #[cfg(feature = "std_web")] - { - //https://github.com/koute/stdweb/commit/3b85c941db00b8e3c942624afd50c5929085fb08 - //input.set_kind(&kind); - let input = &input; - js! { @(no_return) - @{input}.type = @{kind}; - } + cfg_match! { + feature = "std_web" => ({ + //https://github.com/koute/stdweb/commit/3b85c941db00b8e3c942624afd50c5929085fb08 + //input.set_kind(&kind); + let input = &input; + js! { @(no_return) + @{input}.type = @{kind}; + } + }), + feature = "web_sys" => input.set_type(kind), } - #[cfg(feature = "web_sys")] - input.set_type(kind); } if let Some(change) = self.diff_value(ancestor) { @@ -380,22 +374,20 @@ impl VTag { Patch::Add(kind, _) | Patch::Replace(kind, _) => kind, Patch::Remove(_) => "", }; - #[cfg(feature = "std_web")] - input.set_raw_value(raw_value); - #[cfg(feature = "web_sys")] - input.set_value(raw_value); + cfg_match! { + feature = "std_web" => input.set_raw_value(raw_value), + feature = "web_sys" => input.set_value(raw_value), + }; } // IMPORTANT! This parameter has to be set every time // to prevent strange behaviour in the browser when the DOM changes set_checked(&input, self.checked); } else if let Some(tae) = { - #[cfg(feature = "std_web")] - { - TextAreaElement::try_from(element.clone()).ok() + cfg_match! { + feature = "std_web" => TextAreaElement::try_from(element.clone()).ok(), + feature = "web_sys" => element.dyn_ref::(), } - #[cfg(feature = "web_sys")] - element.dyn_ref::() } { if let Some(change) = self.diff_value(ancestor) { let value = match change { @@ -498,10 +490,15 @@ impl VDiff for VTag { .insert_before(&element, next_sibling) .expect("can't insert tag before next sibling"); } else { - #[cfg_attr(feature = "std_web", allow(unused_variables))] - let result = parent.append_child(&element); - #[cfg(feature = "web_sys")] - result.expect("can't append node to parent"); + #[cfg_attr( + feature = "std_web", + allow(clippy::let_unit_value, unused_variables) + )] + { + let result = parent.append_child(&element); + #[cfg(feature = "web_sys")] + result.expect("can't append node to parent"); + } } self.reference = Some(element); } @@ -527,10 +524,10 @@ impl VDiff for VTag { .apply(&element, None, ancestor.map(|a| a.children.into())); let node = self.reference.as_ref().map(|e| { - #[cfg(feature = "std_web")] - let node = e.as_node(); - #[cfg(feature = "web_sys")] - let node = e.deref(); + let node = cfg_match! { + feature = "std_web" => e.as_node(), + feature = "web_sys" => e.deref(), + }; node.to_owned() }); self.node_ref.set(node.clone()); @@ -547,30 +544,34 @@ impl fmt::Debug for VTag { /// `stdweb` doesn't have methods to work with attributes now. /// this is [workaround](https://github.com/koute/stdweb/issues/16#issuecomment-325195854) fn set_attribute(element: &Element, name: &str, value: &str) { - #[cfg(feature = "std_web")] - js!( @(no_return) @{element}.setAttribute( @{name}, @{value} ); ); - #[cfg(feature = "web_sys")] - element - .set_attribute(name, value) - .expect("can't set attribute on element"); + cfg_match! { + feature = "std_web" => js!( @(no_return) @{element}.setAttribute( @{name}, @{value} ); ), + feature = "web_sys" => ({ + element + .set_attribute(name, value) + .expect("can't set attribute on element"); + }), + }; } /// Removes attribute from a element by name. fn remove_attribute(element: &Element, name: &str) { - #[cfg(feature = "std_web")] - js!( @(no_return) @{element}.removeAttribute( @{name} ); ); - #[cfg(feature = "web_sys")] - element - .remove_attribute(name) - .expect("can't remove attribute on element"); + cfg_match! { + feature = "std_web" => js!( @(no_return) @{element}.removeAttribute( @{name} ); ), + feature = "web_sys" => ({ + element + .remove_attribute(name) + .expect("can't remove attribute on element"); + }), + }; } /// Set `checked` value for the `InputElement`. fn set_checked(input: &InputElement, value: bool) { - #[cfg(feature = "std_web")] - js!( @(no_return) @{input}.checked = @{value}; ); - #[cfg(feature = "web_sys")] - input.set_checked(value); + cfg_match! { + feature = "std_web" => js!( @(no_return) @{input}.checked = @{value}; ), + feature = "web_sys" => input.set_checked(value), + }; } impl PartialEq for VTag { diff --git a/src/virtual_dom/vtext.rs b/src/virtual_dom/vtext.rs index 8bd115ba358..d5c26fb3a03 100644 --- a/src/virtual_dom/vtext.rs +++ b/src/virtual_dom/vtext.rs @@ -2,16 +2,19 @@ use super::{Reform, VDiff, VNode}; use crate::utils::document; +use cfg_if::cfg_if; +use cfg_match::cfg_match; use log::warn; use std::cmp::PartialEq; use std::fmt; -#[cfg(feature = "std_web")] -use stdweb::web::{Element, INode, Node, TextNode}; -#[cfg(feature = "web_sys")] -use ::{ - std::ops::Deref, - web_sys::{Element, Node, Text as TextNode}, -}; +cfg_if! { + if #[cfg(feature = "std_web")] { + use stdweb::web::{Element, INode, Node, TextNode}; + } else if #[cfg(feature = "web_sys")] { + use std::ops::Deref; + use web_sys::{Element, Node, Text as TextNode}; + } +} /// A type for a virtual /// [`TextNode`](https://developer.mozilla.org/en-US/docs/Web/API/Document/createTextNode) @@ -94,19 +97,24 @@ impl VDiff for VText { .insert_before(&element, next_sibling) .expect("can't insert text before next_sibling"); } else { - #[cfg_attr(feature = "std_web", allow(unused_variables))] - let result = parent.append_child(&element); - #[cfg(feature = "web_sys")] - result.expect("can't append node to parent"); + #[cfg_attr( + feature = "std_web", + allow(clippy::let_unit_value, unused_variables) + )] + { + let result = parent.append_child(&element); + #[cfg(feature = "web_sys")] + result.expect("can't append node to parent"); + } } self.reference = Some(element); } } self.reference.as_ref().map(|t| { - #[cfg(feature = "std_web")] - let node = t.as_node(); - #[cfg(feature = "web_sys")] - let node = t.deref(); + let node = cfg_match! { + feature = "std_web" => t.as_node(), + feature = "web_sys" => t.deref(), + }; node.to_owned() }) }