Skip to content

Commit

Permalink
Treat pseudo class selectors like emotion, Fix #16.
Browse files Browse the repository at this point in the history
  • Loading branch information
futursolo committed Aug 19, 2021
1 parent d504cad commit b2057ba
Show file tree
Hide file tree
Showing 3 changed files with 68 additions and 7 deletions.
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@
- Feature `yew` has been renamed back to `yew_integration`.
- Selectors list now gets a class name added for each selector.
- `Style` is now `!Send` and `!Sync`.
- Stylist now treats pseudo class selectors (e.g.:`:hover`) like emotion
and styled-components.

### Other Changes:
- Added a `<GlobalStyle />` Component for global styling.
Expand Down
54 changes: 52 additions & 2 deletions packages/stylist-core/src/ast/selector.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,23 @@ pub struct Selector {

impl ToStyleStr for Selector {
fn write_style<W: fmt::Write>(&self, w: &mut W, class_name: &str) -> fmt::Result {
if self.inner.contains('&') {
// If contains current selector or root pseudo class, replace them with class name.
if self.inner.contains('&') || self.inner.contains(":root") {
let scoped_class = format!(".{}", class_name);
write!(w, "{}", self.inner.replace("&", scoped_class.as_str()))?;

write!(
w,
"{}",
self.inner
.replace("&", scoped_class.as_str())
.replace(":root", scoped_class.as_str())
)?;

// If selector starts with a pseudo-class, apply it to the root element.
} else if self.inner.starts_with(':') {
write!(w, ".{}{}", class_name, self.inner)?;

// For other selectors, scope it to be the children of the root element.
} else {
write!(w, ".{} {}", class_name, self.inner)?;
}
Expand All @@ -32,3 +46,39 @@ impl<T: Into<Cow<'static, str>>> From<T> for Selector {
Self { inner: s.into() }
}
}

#[cfg(test)]
mod tests {
use super::*;

#[test]
fn test_selector_gen_simple() {
let s: Selector = ".abc".into();

assert_eq!(s.to_style_str("stylist-abcdefgh"), ".stylist-abcdefgh .abc");
}

#[test]
fn test_selector_pseduo() {
let s: Selector = ":hover".into();

assert_eq!(
s.to_style_str("stylist-abcdefgh"),
".stylist-abcdefgh:hover"
);
}

#[test]
fn test_selector_root_pseduo() {
let s: Selector = ":root.big".into();

assert_eq!(s.to_style_str("stylist-abcdefgh"), ".stylist-abcdefgh.big");
}

#[test]
fn test_selector_gen_current() {
let s: Selector = "&.big".into();

assert_eq!(s.to_style_str("stylist-abcdefgh"), ".stylist-abcdefgh.big");
}
}
19 changes: 14 additions & 5 deletions packages/stylist/src/style.rs
Original file line number Diff line number Diff line change
Expand Up @@ -113,9 +113,8 @@ impl Drop for StyleContent {
/// apply:
/// - If a selector contains a Current Selector(`&`), the current selector will be substituted with
/// the generated class name.
/// - If a selector does not contain a Current Selector, it will be prefixed with the generated
/// class name.
///
/// - If a selectors starts with a pseudo-class selector, it will be applied to the root element.
/// - For other selectors, it will be prefixed with the generated class name.
///
/// Example, original style:
///
Expand All @@ -124,6 +123,10 @@ impl Drop for StyleContent {
/// color: red;
/// }
///
/// :hover {
/// background-color: pink;
/// }
///
/// .hint {
/// font-size: 0.9rem;
/// }
Expand All @@ -136,10 +139,18 @@ impl Drop for StyleContent {
/// color: red;
/// }
///
/// .stylist-uSu9NZZu:hover {
/// background-color: pink;
/// }
///
/// .stylist-uSu9NZZu .hint {
/// font-size: 0.9rem;
/// }
/// ```
///
/// ## Note:
///
/// Root pseudo class (`:root`) will also be treated like a Current Selector.
#[derive(Debug, Clone)]
pub struct Style {
inner: Rc<StyleContent>,
Expand Down Expand Up @@ -231,7 +242,6 @@ impl Style {

/// Creates a new style from some parsable css with a default prefix using a custom
/// manager.
#[cfg_attr(documenting, doc(cfg(feature = "style_manager")))]
pub fn new_with_manager<'a, Css, M>(css: Css, manager: M) -> Result<Self>
where
Css: IntoSheet<'a>,
Expand All @@ -244,7 +254,6 @@ impl Style {

/// Creates a new style with a custom class prefix from some parsable css using a custom
/// manager.
#[cfg_attr(documenting, doc(cfg(feature = "style_manager")))]
pub fn create_with_manager<'a, N, Css, M>(class_prefix: N, css: Css, manager: M) -> Result<Self>
where
N: Into<Cow<'static, str>>,
Expand Down

0 comments on commit b2057ba

Please sign in to comment.