Skip to content

Commit

Permalink
Implement Global and GlobalStyle properly.
Browse files Browse the repository at this point in the history
  • Loading branch information
futursolo committed Aug 20, 2021
1 parent b2057ba commit 7d46004
Show file tree
Hide file tree
Showing 27 changed files with 518 additions and 325 deletions.
3 changes: 2 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,8 @@
and styled-components.

### Other Changes:
- Added a `<GlobalStyle />` Component for global styling.
- Added a `GlobalStyle` struct to register global styles.
- Added a `<Global />` Component for global styling for yew applications.
- Supported `@supports` CSS at-rule.
- Added an alternative counter-based class name on the style when
feature `random` is disabled.
Expand Down
6 changes: 3 additions & 3 deletions examples/benchmarks/src/main.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use std::borrow::Cow;

use gloo::timers::callback::Timeout;
use stylist::yew::GlobalStyle;
use stylist::yew::Global;
use stylist::YieldStyle;
use yew::prelude::*;

Expand All @@ -11,7 +11,7 @@ mod benchmarks;
mod utils;

static GLOBAL_STYLE: &str = r#"
html&, body {
html, body {
margin: 0;
padding: 0;
font-family: sans-serif;
Expand Down Expand Up @@ -256,7 +256,7 @@ impl Component for App {
fn view(&self) -> Html {
html! {
<>
<GlobalStyle css=GLOBAL_STYLE />
<Global css=GLOBAL_STYLE />
<div class=self.style()>
<h1>{"Stylist Benchmark"}</h1>
{
Expand Down
6 changes: 3 additions & 3 deletions examples/yew-integration/src/main.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use std::borrow::Cow;

use stylist::yew::GlobalStyle;
use stylist::yew::Global;
use stylist::{Style, YieldStyle};
use yew::{html, Component, ComponentLink, Html, ShouldRender};

Expand Down Expand Up @@ -100,8 +100,8 @@ impl Component for App {
html! {
<>
// Global Styles can be applied with <GlobalStyle /> component.
<GlobalStyle css=r#"
&, & body {
<Global css=r#"
html, body {
font-family: sans-serif;
padding: 0;
Expand Down
6 changes: 3 additions & 3 deletions examples/yew-shadow/src/main.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use std::borrow::Cow;

use stylist::manager::StyleManager;
use stylist::yew::GlobalStyle;
use stylist::yew::Global;
use stylist::{Style, YieldStyle};
use web_sys::{window, Element, ShadowRootInit, ShadowRootMode};
use yew::prelude::*;
Expand Down Expand Up @@ -104,8 +104,8 @@ impl Component for App {
fn view(&self) -> Html {
html! {
<>
<GlobalStyle css=r#"
&, & body {
<Global css=r#"
html, body {
font-family: sans-serif;
padding: 0;
Expand Down
6 changes: 3 additions & 3 deletions examples/yew-theme-agent/src/main.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use std::borrow::Cow;
use std::sync::Arc;

use stylist::yew::GlobalStyle;
use stylist::yew::Global;
use stylist::YieldStyle;
use yew::{html, Bridge, Component, ComponentLink, Html, ShouldRender};
use yewtil::store::{Bridgeable, ReadOnly, StoreWrapper};
Expand Down Expand Up @@ -152,9 +152,9 @@ impl Component for App {
html! {
<>
// Global Styles can be applied with <GlobalStyle /> component.
<GlobalStyle css=format!(
<Global css=format!(
r#"
&, & body {{
html, body {{
font-family: sans-serif;
padding: 0;
Expand Down
6 changes: 3 additions & 3 deletions examples/yew-theme-yewdux/src/main.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use std::borrow::Cow;

use stylist::yew::GlobalStyle;
use stylist::yew::Global;
use stylist::YieldStyle;
use yew::{html, Component, ComponentLink, Html, ShouldRender};
use yewdux::prelude::*;
Expand Down Expand Up @@ -106,9 +106,9 @@ impl Component for App {
html! {
<>
// Global Styles can be applied with <GlobalStyle /> component.
<GlobalStyle css=format!(
<Global css=format!(
r#"
&, & body {{
html, body {{
font-family: sans-serif;
padding: 0;
Expand Down
4 changes: 4 additions & 0 deletions packages/stylist-core/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -23,10 +23,14 @@ homepage = "https://github.com/futursolo/stylist-rs"
nom = "6.2.1"
thiserror = "1.0"
wasm-bindgen = "0.2.74"
yew = { version = "0.18.0", optional = true, default-features = false }

[dev-dependencies]
log = "0.4"
env_logger = "0.9"

[target.'cfg(target_arch = "wasm32")'.dev-dependencies]
wasm-bindgen-test = "0.3.24"

[features]
yew_integration = ["yew"]
7 changes: 5 additions & 2 deletions packages/stylist-core/src/ast/block.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ pub struct Block {
}

impl ToStyleStr for Block {
fn write_style<W: fmt::Write>(&self, w: &mut W, class_name: &str) -> fmt::Result {
fn write_style<W: fmt::Write>(&self, w: &mut W, class_name: Option<&str>) -> fmt::Result {
if !self.condition.is_empty() {
for (index, sel) in self.condition.iter().enumerate() {
sel.write_style(w, class_name)?;
Expand All @@ -32,8 +32,11 @@ impl ToStyleStr for Block {
}
write!(w, " ")?;
}
} else if let Some(m) = class_name {
write!(w, ".{} ", m)?;
} else {
write!(w, ".{} ", class_name)?;
// Generates global style for dangling block.
write!(w, "html ")?;
}

writeln!(w, "{{")?;
Expand Down
6 changes: 3 additions & 3 deletions packages/stylist-core/src/ast/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
//! struct Sheet
//! └── Vec<enum ScopeContent>
//! ├── struct Block
//! │ ├── selector: String
//! │ ├── selector: Vec<Selector>
//! │ └── Vec<struct StyleAttribute>
//! │ ├── key: String
//! │ └── value: String
Expand Down Expand Up @@ -75,7 +75,7 @@ width: 200px;
}),
]);
assert_eq!(
test_block.to_style_str("test"),
test_block.to_style_str(Some("test")),
r#".test {
width: 100vw;
}
Expand Down Expand Up @@ -133,7 +133,7 @@ width: 200px;
.into(),
})]);
assert_eq!(
test_block.to_style_str("test"),
test_block.to_style_str(Some("test")),
r#"@media only screen and (min-width: 1000px) {
.test {
width: 100vw;
Expand Down
2 changes: 1 addition & 1 deletion packages/stylist-core/src/ast/rule.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ pub struct Rule {
}

impl ToStyleStr for Rule {
fn write_style<W: fmt::Write>(&self, w: &mut W, class_name: &str) -> fmt::Result {
fn write_style<W: fmt::Write>(&self, w: &mut W, class_name: Option<&str>) -> fmt::Result {
writeln!(w, "{} {{", self.condition)?;

for i in self.content.iter() {
Expand Down
2 changes: 1 addition & 1 deletion packages/stylist-core/src/ast/rule_content.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ impl From<ScopeContent> for RuleContent {
}

impl ToStyleStr for RuleContent {
fn write_style<W: fmt::Write>(&self, w: &mut W, class_name: &str) -> fmt::Result {
fn write_style<W: fmt::Write>(&self, w: &mut W, class_name: Option<&str>) -> fmt::Result {
match self {
RuleContent::Block(ref b) => b.write_style(w, class_name),
RuleContent::Rule(ref r) => r.write_style(w, class_name),
Expand Down
2 changes: 1 addition & 1 deletion packages/stylist-core/src/ast/scope_content.rs
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ pub enum ScopeContent {
}

impl ToStyleStr for ScopeContent {
fn write_style<W: fmt::Write>(&self, w: &mut W, class_name: &str) -> fmt::Result {
fn write_style<W: fmt::Write>(&self, w: &mut W, class_name: Option<&str>) -> fmt::Result {
match self {
ScopeContent::Block(ref b) => b.write_style(w, class_name),
ScopeContent::Rule(ref r) => r.write_style(w, class_name),
Expand Down
64 changes: 41 additions & 23 deletions packages/stylist-core/src/ast/selector.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,26 +15,35 @@ pub struct Selector {
}

impl ToStyleStr for Selector {
fn write_style<W: fmt::Write>(&self, w: &mut W, class_name: &str) -> fmt::Result {
// 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())
.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.
fn write_style<W: fmt::Write>(&self, w: &mut W, class_name: Option<&str>) -> fmt::Result {
if let Some(m) = class_name {
// 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!(".{}", m);

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, ".{}{}", m, self.inner)?;

// For other selectors, scope it to be the children of the root element.
} else {
write!(w, ".{} {}", m, self.inner)?;
}

// For global styles, if it contains &, it will be replaced with html.
} else if self.inner.contains('&') {
write!(w, "{}", self.inner.replace("&", "html"))?;
// For other styles, it will be written as is.
} else {
write!(w, ".{} {}", class_name, self.inner)?;
write!(w, "{}", self.inner)?;
}

Ok(())
Expand All @@ -55,15 +64,18 @@ mod tests {
fn test_selector_gen_simple() {
let s: Selector = ".abc".into();

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

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

assert_eq!(
s.to_style_str("stylist-abcdefgh"),
s.to_style_str(Some("stylist-abcdefgh")),
".stylist-abcdefgh:hover"
);
}
Expand All @@ -72,13 +84,19 @@ mod tests {
fn test_selector_root_pseduo() {
let s: Selector = ":root.big".into();

assert_eq!(s.to_style_str("stylist-abcdefgh"), ".stylist-abcdefgh.big");
assert_eq!(
s.to_style_str(Some("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");
assert_eq!(
s.to_style_str(Some("stylist-abcdefgh")),
".stylist-abcdefgh.big"
);
}
}
2 changes: 1 addition & 1 deletion packages/stylist-core/src/ast/sheet.rs
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ impl Default for Sheet {
}

impl ToStyleStr for Sheet {
fn write_style<W: fmt::Write>(&self, w: &mut W, class_name: &str) -> fmt::Result {
fn write_style<W: fmt::Write>(&self, w: &mut W, class_name: Option<&str>) -> fmt::Result {
for scope in self.0.iter() {
scope.write_style(w, class_name)?;
writeln!(w)?;
Expand Down
2 changes: 1 addition & 1 deletion packages/stylist-core/src/ast/style_attr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ pub struct StyleAttribute {
}

impl ToStyleStr for StyleAttribute {
fn write_style<W: fmt::Write>(&self, w: &mut W, _class_name: &str) -> fmt::Result {
fn write_style<W: fmt::Write>(&self, w: &mut W, _class_name: Option<&str>) -> fmt::Result {
write!(w, "{}: {};", self.key, self.value)
}
}
6 changes: 4 additions & 2 deletions packages/stylist-core/src/ast/to_style_str.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,14 @@ use std::fmt;
/// Structs implementing this trait should be able to turn into
/// a part of a CSS style sheet.
pub trait ToStyleStr {
fn to_style_str(&self, class_name: &str) -> String {
fn to_style_str(&self, class_name: Option<&str>) -> String {
let mut s = String::new();

self.write_style(&mut s, class_name).unwrap();

s
}
fn write_style<W: fmt::Write>(&self, w: &mut W, class_name: &str) -> fmt::Result;

// If None is passed as class_name, it means to write a global style.
fn write_style<W: fmt::Write>(&self, w: &mut W, class_name: Option<&str>) -> fmt::Result;
}
4 changes: 4 additions & 0 deletions packages/stylist-core/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,3 +9,7 @@ mod error;
pub use error::{Error, Result};
pub mod ast;
mod parser;

#[cfg_attr(documenting, doc(cfg(feature = "yew_integration")))]
#[cfg(feature = "yew_integration")]
mod yew;
29 changes: 29 additions & 0 deletions packages/stylist-core/src/yew.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
use std::borrow::Cow;

use yew::html::IntoPropValue;

use crate::ast::Sheet;

impl<'a> IntoPropValue<Sheet> for String {
fn into_prop_value(self) -> Sheet {
self.parse::<Sheet>().expect("Failed to parse style.")
}
}

impl<'a> IntoPropValue<Sheet> for &'a str {
fn into_prop_value(self) -> Sheet {
self.parse::<Sheet>().expect("Failed to parse style.")
}
}

impl<'a> IntoPropValue<Sheet> for Cow<'a, str> {
fn into_prop_value(self) -> Sheet {
self.parse::<Sheet>().expect("Failed to parse style.")
}
}

impl<'a> IntoPropValue<Sheet> for &'a Sheet {
fn into_prop_value(self) -> Sheet {
self.clone()
}
}
2 changes: 1 addition & 1 deletion packages/stylist/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ env_logger = "0.9"
[features]
random = ["rand", "getrandom"]
default = ["random"]
yew_integration = ["yew"]
yew_integration = ["yew", "stylist-core/yew_integration"]

[package.metadata.docs.rs]
features = ["yew_integration"]
Expand Down
5 changes: 0 additions & 5 deletions packages/stylist/src/bindings/mod.rs

This file was deleted.

Loading

0 comments on commit 7d46004

Please sign in to comment.