diff --git a/Cargo.toml b/Cargo.toml index 005a76b..9883065 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -3,6 +3,7 @@ members = [ "packages/stylist", "packages/stylist-core", "packages/stylist-macros", + "packages/stylist-yew-macros", "examples/benchmarks", "examples/yew-proc-macros", diff --git a/examples/yew-integration/src/main.rs b/examples/yew-integration/src/main.rs index b21a4fb..5d99637 100644 --- a/examples/yew-integration/src/main.rs +++ b/examples/yew-integration/src/main.rs @@ -1,10 +1,11 @@ -use stylist::yew::{styled_component, Global}; +use stylist::yew::{use_stylist, Global}; use yew::prelude::*; use log::Level; -#[styled_component(Inside)] +#[function_component(Inside)] pub fn inside() -> Html { + use_stylist!(css); html! {
Html { } } -#[styled_component(App)] +#[function_component(App)] pub fn app() -> Html { + use_stylist!(css); html! { <> // Global Styles can be applied with component. diff --git a/examples/yew-proc-macros/src/main.rs b/examples/yew-proc-macros/src/main.rs index b7b71d2..d9b00cf 100644 --- a/examples/yew-proc-macros/src/main.rs +++ b/examples/yew-proc-macros/src/main.rs @@ -1,10 +1,11 @@ -use stylist::yew::{styled_component, Global}; +use stylist::yew::{use_stylist, Global}; use yew::prelude::*; use log::Level; -#[styled_component(Inside)] +#[function_component(Inside)] pub fn inside() -> Html { + use_stylist!(css); html! {
Html { } } -#[styled_component(App)] +#[function_component(App)] pub fn app() -> Html { + use_stylist!(css); html! { <> // Global Styles can be applied with component. diff --git a/examples/yew-theme-context/src/contexts/theme.rs b/examples/yew-theme-context/src/contexts/theme.rs index 51764b7..cac12a3 100644 --- a/examples/yew-theme-context/src/contexts/theme.rs +++ b/examples/yew-theme-context/src/contexts/theme.rs @@ -1,7 +1,6 @@ use std::ops::Deref; use once_cell::sync::Lazy; -use stylist::yew::styled_component; use yew::html::ImplicitClone; use yew::prelude::*; @@ -80,7 +79,7 @@ pub(crate) struct ThemeProviderProps { pub children: Children, } -#[styled_component(ThemeProvider)] +#[function_component(ThemeProvider)] pub(crate) fn theme_provider(props: &ThemeProviderProps) -> Html { let theme_kind = use_state(|| ThemeKind::Light); diff --git a/examples/yew-theme-context/src/main.rs b/examples/yew-theme-context/src/main.rs index 4c3e36f..8c23d7a 100644 --- a/examples/yew-theme-context/src/main.rs +++ b/examples/yew-theme-context/src/main.rs @@ -1,4 +1,4 @@ -use stylist::yew::{styled_component, Global}; +use stylist::yew::{use_stylist, Global}; use yew::prelude::*; use log::Level; @@ -7,8 +7,9 @@ mod contexts; use contexts::{use_theme, ThemeKind, ThemeProvider}; -#[styled_component(Inside)] +#[function_component(Inside)] pub fn inside() -> Html { + use_stylist!(css); let theme = use_theme(); let theme_str = match theme.kind() { @@ -37,8 +38,9 @@ pub fn inside() -> Html { } } -#[styled_component(App)] +#[function_component(App)] pub fn app() -> Html { + use_stylist!(css); let theme = use_theme(); let theme_str = match theme.kind() { @@ -97,7 +99,7 @@ pub fn app() -> Html { } } -#[styled_component(Root)] +#[function_component(Root)] pub fn root() -> Html { html! { diff --git a/packages/stylist-macros/src/css_yew_impl.rs b/packages/stylist-macros/src/css_yew_impl.rs deleted file mode 100644 index ac50863..0000000 --- a/packages/stylist-macros/src/css_yew_impl.rs +++ /dev/null @@ -1,6 +0,0 @@ -use proc_macro2::TokenStream; -use quote::quote; - -pub(crate) fn macro_fn(input: TokenStream) -> TokenStream { - quote! { ::stylist::css!(#input).with_manager(__stylist_style_manager__.clone()) } -} diff --git a/packages/stylist-macros/src/lib.rs b/packages/stylist-macros/src/lib.rs index 39006b0..5f8261a 100644 --- a/packages/stylist-macros/src/lib.rs +++ b/packages/stylist-macros/src/lib.rs @@ -13,13 +13,11 @@ mod inline; mod literal; mod css; -mod css_yew_impl; mod global_style; mod output; mod sheet; mod spacing_iterator; mod style; -mod styled_component; #[proc_macro] #[proc_macro_error] @@ -44,14 +42,3 @@ pub fn global_style(input: TokenStream) -> TokenStream { pub fn css(input: TokenStream) -> TokenStream { css::macro_fn(input.into()).into() } - -#[proc_macro] -#[proc_macro_error] -pub fn __css_yew_impl(input: TokenStream) -> TokenStream { - css_yew_impl::macro_fn(input.into()).into() -} - -#[proc_macro_attribute] -pub fn styled_component(attr: TokenStream, item: TokenStream) -> TokenStream { - styled_component::macro_fn(attr, item) -} diff --git a/packages/stylist-macros/src/styled_component.rs b/packages/stylist-macros/src/styled_component.rs deleted file mode 100644 index d077da5..0000000 --- a/packages/stylist-macros/src/styled_component.rs +++ /dev/null @@ -1,84 +0,0 @@ -// This file is borrowed from yew-macro/src/function_component.rs -use proc_macro2::TokenStream; -use quote::quote; -use syn::parse::{Parse, ParseStream}; -use syn::parse_macro_input; -use syn::{Ident, Item, ItemFn}; - -#[derive(Debug)] -pub struct StyledComponent { - func: ItemFn, -} - -impl Parse for StyledComponent { - fn parse(input: ParseStream) -> syn::Result { - let parsed: Item = input.parse()?; - - match parsed { - Item::Fn(func) => Ok(Self { func }), - item => Err(syn::Error::new_spanned( - item, - "`styled_component` attribute can only be applied to functions", - )), - } - } -} - -#[derive(Debug)] -pub struct StyledComponentName { - component_name: Ident, -} - -impl Parse for StyledComponentName { - fn parse(input: ParseStream) -> syn::Result { - if input.is_empty() { - return Err(input.error("expected identifier for the component")); - } - - let component_name = input.parse()?; - - Ok(Self { component_name }) - } -} - -pub fn styled_component_impl( - name: StyledComponentName, - component: StyledComponent, -) -> syn::Result { - let StyledComponentName { component_name } = name; - - let StyledComponent { func } = component; - - let ItemFn { - attrs, - vis, - sig, - block, - } = func; - - let quoted = quote! { - #(#attrs)* - #[::yew::functional::function_component(#component_name)] - #vis #sig { - let __stylist_style_manager__ = ::yew::functional::use_context::<::stylist::manager::StyleManager>().unwrap_or_default(); - #[allow(unused_imports)] - use ::stylist::yew::__css_yew_impl as css; - - #block - } - }; - - Ok(quoted) -} - -pub fn macro_fn( - attr: proc_macro::TokenStream, - item: proc_macro::TokenStream, -) -> proc_macro::TokenStream { - let item = parse_macro_input!(item as StyledComponent); - let attr = parse_macro_input!(attr as StyledComponentName); - - styled_component_impl(attr, item) - .unwrap_or_else(|err| err.to_compile_error()) - .into() -} diff --git a/packages/stylist-yew-macros/Cargo.toml b/packages/stylist-yew-macros/Cargo.toml new file mode 100644 index 0000000..e74e713 --- /dev/null +++ b/packages/stylist-yew-macros/Cargo.toml @@ -0,0 +1,21 @@ +[package] +name = "stylist-yew-macros" +version = "0.1.0" +edition = "2018" +license = "MIT" +repository = "https://github.com/futursolo/stylist-rs" +authors = [ + "Kaede Hoshiakwa ", + "Martin Molzer ", +] +description = "Stylist is a CSS-in-Rust styling solution for WebAssembly Applications." +keywords = [ + "CSS", + "web", + "css-in-rust", + "yew" +] +categories = ["wasm", "web-programming"] +readme = "README.md" +homepage = "https://github.com/futursolo/stylist-rs" +resolver = "2" diff --git a/packages/stylist-yew-macros/README.md b/packages/stylist-yew-macros/README.md new file mode 100644 index 0000000..802e560 --- /dev/null +++ b/packages/stylist-yew-macros/README.md @@ -0,0 +1,8 @@ +## Stylist Yew Macros + +This crate exists mainly to work around with documentation, otherwise it should be understood to be part of ::stylist::yew. + +To be more specific, `#[macro_export] macro_rules!` exports a macro at the crate root, which also shows up documentation, unless marked as `#[doc(hidden)]`, which on the other hand is infectuous and hides also reexports, which we'd want to do to use it as `::stylist::yew::use_stylist!`. They also can't be exported from proc-macro crates, i.e. `stylist-macros` yet. + +Tracking issue: +- rustdoc: doc(hidden) also hides re-exports: https://github.com/rust-lang/rust/issues/59368 diff --git a/packages/stylist-yew-macros/src/lib.rs b/packages/stylist-yew-macros/src/lib.rs new file mode 100644 index 0000000..e054220 --- /dev/null +++ b/packages/stylist-yew-macros/src/lib.rs @@ -0,0 +1,61 @@ +#![no_std] + +#[macro_export] +macro_rules! __use_stylist_item { + (($dol:tt) , $mgr:ident, use css as $i:ident) => { + macro_rules! $i + { + ($dol( $dol args:tt )*) => { + ::stylist::css!($dol( $dol args )*).with_manager($mgr.clone()) + }; + } + }; + (($dol:tt) , $mgr:ident, use style as $i:ident) => { + macro_rules! $i + { + ($dol( $dol args:tt )*) => { + ::stylist::style!($dol( $dol args )*).with_manager($mgr.clone()) + }; + } + }; + (($dol:tt) , $mgr:ident, use global_style as $i:ident) => { + macro_rules! $i + { + ($dol( $dol args:tt )*) => { + ::stylist::global_style!($dol( $dol args )*).with_manager($mgr.clone()) + }; + } + }; +} + +#[macro_export] +macro_rules! __use_stylist_item_dispatch { + ($mgr:ident, use css as $i:ident) => { + $crate::__use_stylist_item!(($) , $mgr, use css as $i) + }; + ($mgr:ident, use css) => { + $crate::__use_stylist_item!(($) , $mgr, use css as css) + }; + ($mgr:ident, use style as $i:ident) => { + $crate::__use_stylist_item!(($) , $mgr, use style as $i) + }; + ($mgr:ident, use style) => { + $crate::__use_stylist_item!(($) , $mgr, use style as style) + }; + ($mgr:ident, use global_style as $i:ident) => { + $crate::__use_stylist_item!(($) , $mgr, use global_style as $i) + }; + ($mgr:ident, use global_style) => { + $crate::__use_stylist_item!(($) , $mgr, use global_style as global_style) + }; +} + +#[macro_export] +macro_rules! __use_stylist { + ($($l:ident $(as $i:ident)?),+) => { + let __stylist_style_manager__ = + ::yew::functional::use_context::<::stylist::manager::StyleManager>() + .unwrap_or_default(); + $($crate::__use_stylist_item_dispatch!(__stylist_style_manager__, use $l$( as $i)?));* + }; +} diff --git a/packages/stylist/Cargo.toml b/packages/stylist/Cargo.toml index eb09852..4a92e01 100644 --- a/packages/stylist/Cargo.toml +++ b/packages/stylist/Cargo.toml @@ -26,6 +26,7 @@ crate-type = ["cdylib", "rlib"] [dependencies] stylist-core = { path = "../stylist-core", version = "0.10.0" } stylist-macros = { path = "../stylist-macros", version = "0.10.0", optional = true } +stylist-yew-macros = { path = "../stylist-yew-macros", version = "0.1.0" } once_cell = "1.8.0" rand = { version = "0.8.4", optional = true } diff --git a/packages/stylist/src/lib.rs b/packages/stylist/src/lib.rs index 979cdf6..6336469 100644 --- a/packages/stylist/src/lib.rs +++ b/packages/stylist/src/lib.rs @@ -20,10 +20,11 @@ //! use std::borrow::Cow; //! //! use yew::prelude::*; -//! use stylist::yew::styled_component; +//! use stylist::yew::use_stylist; //! -//! #[styled_component(MyStyledComponent)] +//! #[function_component(MyStyledComponent)] //! fn my_styled_component() -> Html { +//! use_stylist!(css); //! html! {
{"Hello World!"}
} //! } //! ``` diff --git a/packages/stylist/src/yew/mod.rs b/packages/stylist/src/yew/mod.rs index eda1b67..edd13bf 100644 --- a/packages/stylist/src/yew/mod.rs +++ b/packages/stylist/src/yew/mod.rs @@ -3,34 +3,28 @@ use yew::html::Classes; use yew::html::IntoPropValue; -#[doc(hidden)] -#[cfg(feature = "macros")] -pub use stylist_macros::__css_yew_impl; - -/// A procedural macro to style Yew component. +/// A procedural macro to style a functional Yew component. This introduces context +/// sensitive versions of stylist macros that respect the [`StyleManager`] scoped to +/// the component. +/// The arguments are the comma separated names of the macros you want to use, optionally +/// followed by `as `. /// /// # Example: /// /// ```rust -/// use std::borrow::Cow; -/// /// use yew::prelude::*; -/// use stylist::yew::styled_component; +/// use stylist::yew::use_stylist; /// -/// #[styled_component(MyStyledComponent)] +/// #[function_component(MyStyledComponent)] /// fn my_styled_component() -> Html { +/// use_stylist!(css, style as sstyle, global_style); /// html! {
{"Hello World!"}
} /// } /// ``` -/// -/// # Note: -/// -/// You don't need to import [`css!`](crate::css) inside of a `styled_component`. -/// -/// This macro imports a special version of [`css!`](crate::css) macro that is aware of the current style manager. +#[doc(inline)] #[cfg_attr(documenting, doc(cfg(feature = "macros")))] #[cfg(feature = "macros")] -pub use stylist_macros::styled_component; +pub use stylist_yew_macros::__use_stylist as use_stylist; use crate::ast::Sheet; use crate::manager::StyleManager; diff --git a/packages/stylist/tests/inline_display_impl.rs b/packages/stylist/tests/inline_display_impl.rs index 115f6bc..eb44575 100644 --- a/packages/stylist/tests/inline_display_impl.rs +++ b/packages/stylist/tests/inline_display_impl.rs @@ -8,7 +8,7 @@ impl Display for Foo { } } impl Foo { - #[allow(dead_code)] + #[allow(dead_code, clippy::inherent_to_string_shadow_display)] fn to_string(&self) -> String { "confused user impl".into() }