diff --git a/CHANGELOG.md b/CHANGELOG.md index 3785b12..9863d7b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,17 @@ # Changelog +## v0.11.0 + +### Breaking Changes: +- `StyleSource` does not take a lifetime argument +- Feature `parser`: `StyleSource` now eagerly parses its input. +- Feature `parser`: The conversion from `str` have been changed to `TryFrom` + instead of `From`. If you're using `yew`, the `IntoPropValue` + impls still exist, but now panic early during conversion. + +### Other Changes: +- The `Style::new_*` API is more open for accepted types of the `Css` parameter. + ## v0.10.0 ### Breaking Changes: diff --git a/examples/benchmarks/src/main.rs b/examples/benchmarks/src/main.rs index 6f3748a..1029062 100644 --- a/examples/benchmarks/src/main.rs +++ b/examples/benchmarks/src/main.rs @@ -256,8 +256,9 @@ impl Component for Benchmarks { } impl YieldStyle for Benchmarks { - fn style_from(&self) -> StyleSource<'static> { - r#" + fn style_from(&self) -> StyleSource { + stylist::css!( + r#" display: flex; justify-content: center; align-items: center; @@ -300,8 +301,8 @@ impl YieldStyle for Benchmarks { tbody tr:nth-child(even) { background-color: rgb(240, 240, 240); } - "# - .into() + "# + ) } } @@ -357,8 +358,9 @@ impl Component for App { } impl YieldStyle for App { - fn style_from(&self) -> StyleSource<'static> { - r#" + fn style_from(&self) -> StyleSource { + stylist::css!( + r#" display: flex; justify-content: center; align-items: center; @@ -373,8 +375,8 @@ impl YieldStyle for App { height: 50px; font-size: 20px; } - "# - .into() + "# + ) } } diff --git a/examples/yew-shadow/src/main.rs b/examples/yew-shadow/src/main.rs index 4ecb790..6f875b6 100644 --- a/examples/yew-shadow/src/main.rs +++ b/examples/yew-shadow/src/main.rs @@ -117,8 +117,9 @@ impl Component for App { } impl YieldStyle for App { - fn style_from(&self) -> StyleSource<'static> { - r#" + fn style_from(&self) -> StyleSource { + stylist::css!( + r#" box-shadow: 0 0 5px 1px rgba(0, 0, 0, 0.7); height: 500px; width: 500px; @@ -133,8 +134,8 @@ impl YieldStyle for App { flex-direction: column; background-color: white; - "# - .into() + "# + ) } } diff --git a/packages/stylist-core/src/error.rs b/packages/stylist-core/src/error.rs index 5f27b05..58380fe 100644 --- a/packages/stylist-core/src/error.rs +++ b/packages/stylist-core/src/error.rs @@ -19,6 +19,12 @@ pub enum Error { Web(Option), } +impl From for Error { + fn from(infallible: std::convert::Infallible) -> Self { + match infallible {} + } +} + pub type Result = std::result::Result; pub trait ResultDisplay { diff --git a/packages/stylist/src/global_style.rs b/packages/stylist/src/global_style.rs index 4d1b1f2..2cebde6 100644 --- a/packages/stylist/src/global_style.rs +++ b/packages/stylist/src/global_style.rs @@ -24,12 +24,9 @@ pub struct GlobalStyle { impl GlobalStyle { // The big method is monomorphic, so less code duplication and code bloat through generics // and inlining - fn create_impl(css: StyleSource<'_>, manager: StyleManager) -> Result { - #[cfg(all(debug_assertions, feature = "parser"))] - use crate::ast::Sheet; - + fn create_impl(css: StyleSource, manager: StyleManager) -> Result { let prefix = format!("{}-global", manager.prefix()); - let css = css.try_into_sheet()?; + let css = css.into_sheet(); // Creates the StyleKey, return from registry if already cached. let key = StyleKey { @@ -51,7 +48,7 @@ impl GlobalStyle { // not corrupting the stylesheet. #[cfg(all(debug_assertions, feature = "parser"))] style_str - .parse::() + .parse::() .expect_display("debug: Stylist failed to parse the style with interpolated values"); let new_style = Self { @@ -83,21 +80,23 @@ impl GlobalStyle { /// let style = Style::new("background-color: red;")?; /// # Ok::<(), stylist::Error>(()) /// ``` - pub fn new<'a, Css>(css: Css) -> Result + pub fn new(css: Css) -> Result where - Css: Into>, + Css: TryInto, + crate::Error: From, { Self::new_with_manager(css, StyleManager::default()) } /// Creates a new style using a custom manager. - pub fn new_with_manager<'a, Css, M>(css: Css, manager: M) -> Result + pub fn new_with_manager(css: Css, manager: M) -> Result where - Css: Into>, + Css: TryInto, + crate::Error: From, M: Into, { let mgr = manager.into(); - Self::create_impl(css.into(), mgr) + Self::create_impl(css.try_into()?, mgr) } /// Get the parsed and generated style in `&str`. diff --git a/packages/stylist/src/lib.rs b/packages/stylist/src/lib.rs index bd64938..1c80240 100644 --- a/packages/stylist/src/lib.rs +++ b/packages/stylist/src/lib.rs @@ -76,7 +76,7 @@ //! pub struct Component; //! //! impl YieldStyle for Component { -//! fn style_from(&self) -> StyleSource<'static> { +//! fn style_from(&self) -> StyleSource { //! css!("color: red;") //! } //! } diff --git a/packages/stylist/src/style.rs b/packages/stylist/src/style.rs index 57f1771..aa46d15 100644 --- a/packages/stylist/src/style.rs +++ b/packages/stylist/src/style.rs @@ -153,13 +153,10 @@ impl Style { // and inlining fn create_impl( class_prefix: Cow<'static, str>, - css: StyleSource<'_>, + css: StyleSource, manager: StyleManager, ) -> Result { - #[cfg(all(debug_assertions, feature = "parser"))] - use crate::ast::Sheet; - - let css = css.try_into_sheet()?; + let css = css.into_sheet(); // Creates the StyleKey, return from registry if already cached. let key = StyleKey { @@ -183,7 +180,7 @@ impl Style { // not corrupting the stylesheet. #[cfg(all(debug_assertions, feature = "parser"))] style_str - .parse::() + .parse::() .expect_display("debug: Stylist failed to parse the style with interpolated values"); let new_style = Self { @@ -215,9 +212,10 @@ impl Style { /// let style = Style::new("background-color: red;")?; /// # Ok::<(), stylist::Error>(()) /// ``` - pub fn new<'a, Css>(css: Css) -> Result + pub fn new(css: Css) -> Result where - Css: Into>, + Css: TryInto, + crate::Error: From, { Self::create(StyleManager::default().prefix(), css) } @@ -232,34 +230,37 @@ impl Style { /// let style = Style::create("my-component", "background-color: red;")?; /// # Ok::<(), stylist::Error>(()) /// ``` - pub fn create<'a, N, Css>(class_prefix: N, css: Css) -> Result + pub fn create(class_prefix: N, css: Css) -> Result where N: Into>, - Css: Into>, + Css: TryInto, + crate::Error: From, { - Self::create_impl(class_prefix.into(), css.into(), StyleManager::default()) + Self::create_with_manager(class_prefix, css, StyleManager::default()) } /// Creates a new style from some parsable css with a default prefix using a custom /// manager. - pub fn new_with_manager<'a, Css, M>(css: Css, manager: M) -> Result + pub fn new_with_manager(css: Css, manager: M) -> Result where - Css: Into>, + Css: TryInto, + crate::Error: From, M: Into, { let mgr = manager.into(); - Self::create_impl(mgr.prefix(), css.into(), mgr.clone()) + Self::create_with_manager(mgr.prefix(), css, mgr.clone()) } /// Creates a new style with a custom class prefix from some parsable css using a custom /// manager. - pub fn create_with_manager<'a, N, Css, M>(class_prefix: N, css: Css, manager: M) -> Result + pub fn create_with_manager(class_prefix: N, css: Css, manager: M) -> Result where N: Into>, - Css: Into>, + Css: TryInto, + crate::Error: From, M: Into, { - Self::create_impl(class_prefix.into(), css.into(), manager.into()) + Self::create_impl(class_prefix.into(), css.try_into()?, manager.into()) } /// Returns the class name for current style diff --git a/packages/stylist/src/style_src.rs b/packages/stylist/src/style_src.rs index 78f5705..c0f1000 100644 --- a/packages/stylist/src/style_src.rs +++ b/packages/stylist/src/style_src.rs @@ -1,27 +1,8 @@ -#[cfg(feature = "parser")] -use std::borrow::Cow; -#[cfg(not(feature = "parser"))] -use std::marker::PhantomData; - use crate::ast::Sheet; use crate::manager::StyleManager; -use crate::Result; #[cfg(feature = "yew")] use crate::Style; -#[cfg(feature = "parser")] -#[derive(Debug, Clone, PartialEq)] -enum SheetSource<'a> { - String(Cow<'a, str>), - Sheet(Sheet), -} - -#[cfg(not(feature = "parser"))] -#[derive(Debug, Clone, PartialEq)] -enum SheetSource { - Sheet(Sheet), -} - /// A struct that can be used as a source to create a [`Style`](crate::Style) or /// [`GlobalStyle`](crate::GlobalStyle). /// @@ -30,31 +11,24 @@ enum SheetSource { /// You can also get a StyleSource instance from a string or a [`Sheet`] by calling `.into()`. /// /// ```rust -/// use stylist::StyleSource; /// use yew::prelude::*; -/// use stylist::yew::Global; +/// use stylist::{css, StyleSource, yew::Global}; /// -/// let s: StyleSource = "color: red;".into(); +/// let s: StyleSource = css!("color: red;"); /// /// let rendered = html! {
}; /// let global_rendered = html! {}; /// ``` #[derive(Debug, Clone, PartialEq)] -pub struct StyleSource<'a> { - #[cfg(feature = "parser")] - inner: SheetSource<'a>, - - #[cfg(not(feature = "parser"))] - inner: SheetSource, - #[cfg(not(feature = "parser"))] - _marker: PhantomData<&'a ()>, +pub struct StyleSource { + inner: Sheet, manager: Option, #[cfg(all(debug_assertions, feature = "debug_style_locations"))] pub(crate) location: String, } -impl StyleSource<'_> { +impl StyleSource { #[cfg(all(debug_assertions, feature = "debug_style_locations"))] #[track_caller] pub(crate) fn get_caller_location() -> String { @@ -68,12 +42,8 @@ impl StyleSource<'_> { ) } - pub(crate) fn try_into_sheet(self) -> Result { - match self.inner { - SheetSource::Sheet(m) => Ok(m), - #[cfg(feature = "parser")] - SheetSource::String(m) => Ok(m.parse::()?), - } + pub(crate) fn into_sheet(self) -> Sheet { + self.inner } #[cfg(feature = "yew")] @@ -91,13 +61,11 @@ impl StyleSource<'_> { } } -impl From for StyleSource<'_> { +impl From for StyleSource { #[cfg_attr(all(debug_assertions, feature = "debug_style_locations"), track_caller)] - fn from(other: Sheet) -> StyleSource<'static> { + fn from(sheet: Sheet) -> StyleSource { StyleSource { - inner: SheetSource::Sheet(other), - #[cfg(not(feature = "parser"))] - _marker: PhantomData, + inner: sheet, manager: None, #[cfg(all(debug_assertions, feature = "debug_style_locations"))] location: Self::get_caller_location(), @@ -109,40 +77,56 @@ impl From for StyleSource<'_> { #[cfg(feature = "parser")] mod feat_parser { use super::*; + use std::borrow::Cow; + use std::str::FromStr; - impl From for StyleSource<'_> { + impl TryFrom for StyleSource { + type Error = crate::Error; #[cfg_attr(all(debug_assertions, feature = "debug_style_locations"), track_caller)] - fn from(other: String) -> StyleSource<'static> { - StyleSource { - inner: SheetSource::String(other.into()), + fn try_from(other: String) -> crate::Result { + let sheet = other.parse()?; + Ok(StyleSource { + inner: sheet, manager: None, #[cfg(all(debug_assertions, feature = "debug_style_locations"))] location: Self::get_caller_location(), - } + }) } } - impl<'a> From<&'a str> for StyleSource<'a> { + impl<'a> TryFrom<&'a str> for StyleSource { + type Error = crate::Error; #[cfg_attr(all(debug_assertions, feature = "debug_style_locations"), track_caller)] - fn from(other: &'a str) -> StyleSource<'a> { - StyleSource { - inner: SheetSource::String(other.into()), + fn try_from(other: &'a str) -> crate::Result { + let sheet = other.parse()?; + Ok(StyleSource { + inner: sheet, manager: None, #[cfg(all(debug_assertions, feature = "debug_style_locations"))] location: Self::get_caller_location(), - } + }) } } - impl<'a> From> for StyleSource<'a> { + impl<'a> TryFrom> for StyleSource { + type Error = crate::Error; #[cfg_attr(all(debug_assertions, feature = "debug_style_locations"), track_caller)] - fn from(other: Cow<'a, str>) -> StyleSource<'a> { - StyleSource { - inner: SheetSource::String(other), + fn try_from(other: Cow<'a, str>) -> crate::Result { + let sheet = other.parse()?; + Ok(StyleSource { + inner: sheet, manager: None, #[cfg(all(debug_assertions, feature = "debug_style_locations"))] location: Self::get_caller_location(), - } + }) + } + } + + impl FromStr for StyleSource { + type Err = crate::Error; + #[cfg_attr(all(debug_assertions, feature = "debug_style_locations"), track_caller)] + fn from_str(s: &str) -> Result { + s.try_into() } } } diff --git a/packages/stylist/src/yew/global.rs b/packages/stylist/src/yew/global.rs index 53e9e68..419e90d 100644 --- a/packages/stylist/src/yew/global.rs +++ b/packages/stylist/src/yew/global.rs @@ -7,7 +7,7 @@ use stylist_core::ResultDisplay; /// The properties for [`Global`] Component, please see its documentation for usage. #[derive(Properties, Clone, Debug, PartialEq)] pub struct GlobalProps { - pub css: StyleSource<'static>, + pub css: StyleSource, } /// A Global Style that will be applied to `` tag, inspired by [emotion](https://emotion.sh). @@ -49,7 +49,7 @@ pub fn global(props: &GlobalProps) -> Html { #[derive(Debug, PartialEq)] struct GlobalDependents { manager: StyleManager, - css: StyleSource<'static>, + css: StyleSource, } use_effect_with_deps( diff --git a/packages/stylist/src/yew/hooks/use_style.rs b/packages/stylist/src/yew/hooks/use_style.rs index c79a39a..8718d06 100644 --- a/packages/stylist/src/yew/hooks/use_style.rs +++ b/packages/stylist/src/yew/hooks/use_style.rs @@ -22,9 +22,12 @@ use crate::{Style, StyleSource}; /// ``` #[cfg_attr(documenting, doc(cfg(feature = "yew_use_style")))] #[cfg(feature = "yew_use_style")] -pub fn use_style<'a, Css: Into>>(css: Css) -> Style { +pub fn use_style(css: Css) -> Style +where + Css: TryInto, + crate::Error: From, +{ let mgr = use_context::().unwrap_or_default(); - let css = css.into(); // It does not make sense to unmount a scoped style. Style::new_with_manager(css, mgr).expect_display("failed to create style") diff --git a/packages/stylist/src/yew/mod.rs b/packages/stylist/src/yew/mod.rs index 241ae7e..c304046 100644 --- a/packages/stylist/src/yew/mod.rs +++ b/packages/stylist/src/yew/mod.rs @@ -106,8 +106,8 @@ impl From