diff --git a/packages/core-macro/Cargo.toml b/packages/core-macro/Cargo.toml index 3abaab822..295ceee40 100644 --- a/packages/core-macro/Cargo.toml +++ b/packages/core-macro/Cargo.toml @@ -16,7 +16,6 @@ proc-macro-hack = "0.5.19" proc-macro2 = "1.0.6" quote = "1.0" syn = { version = "1.0.11", features = ["full"] } -style-shared = { git = "https://github.com/derekdreery/style" } # testing [dev-dependencies] diff --git a/packages/core-macro/src/htm.rs b/packages/core-macro/src/htm.rs index 264b05fc4..4c4aeb464 100644 --- a/packages/core-macro/src/htm.rs +++ b/packages/core-macro/src/htm.rs @@ -17,7 +17,6 @@ use { proc_macro::TokenStream, proc_macro2::{Span, TokenStream as TokenStream2}, quote::{quote, ToTokens, TokenStreamExt}, - style_shared::Styles, syn::{ ext::IdentExt, parse::{Parse, ParseStream}, @@ -267,15 +266,17 @@ impl Parse for Attr { let outer; syn::braced!(outer in s); // double brace for inline style. - if outer.peek(token::Brace) { - let inner; - syn::braced!(inner in outer); - let styles: Styles = inner.parse()?; - MaybeExpr::Literal(LitStr::new(&styles.to_string(), Span::call_site())) - } else { - // just parse as an expression - MaybeExpr::Expr(outer.parse()?) - } + // todo!("Style support not ready yet"); + + // if outer.peek(token::Brace) { + // let inner; + // syn::braced!(inner in outer); + // let styles: Styles = inner.parse()?; + // MaybeExpr::Literal(LitStr::new(&styles.to_string(), Span::call_site())) + // } else { + // just parse as an expression + MaybeExpr::Expr(outer.parse()?) + // } } else { s.parse()? }; diff --git a/packages/core-macro/src/lib.rs b/packages/core-macro/src/lib.rs index 64fd61bc7..54bb68197 100644 --- a/packages/core-macro/src/lib.rs +++ b/packages/core-macro/src/lib.rs @@ -12,6 +12,7 @@ use syn::{ mod fc; mod htm; mod ifmt; +// mod styles; /// The html! macro makes it easy for developers to write jsx-style markup in their components. /// We aim to keep functional parity with html templates. diff --git a/packages/core-macro/src/styles/calc.rs b/packages/core-macro/src/styles/calc.rs new file mode 100644 index 000000000..f52b3eda3 --- /dev/null +++ b/packages/core-macro/src/styles/calc.rs @@ -0,0 +1,264 @@ +//! The `calc` functionality. +use crate::LengthPercentage; +use ::{ + proc_macro2::TokenStream, + quote::{quote, ToTokens}, + std::fmt, + syn::{ + custom_keyword, parenthesized, + parse::{Parse, ParseStream}, + Token, + }, +}; + +/// Values that can be a calculaion (currently restricted to length & percentages) +#[derive(Debug, Clone, PartialEq)] +pub enum Calc { + Calculated(CalcSum), + Normal(LengthPercentage), +} + +impl fmt::Display for Calc { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + match self { + Calc::Calculated(inner) => write!(f, "calc({})", inner), + Calc::Normal(inner) => write!(f, "{}", inner), + } + } +} + +impl Parse for Calc { + fn parse(s: ParseStream) -> syn::Result { + custom_keyword!(calc); + if s.peek(calc) { + s.parse::()?; + let content; + parenthesized!(content in s); + Ok(Calc::Calculated(content.parse()?)) + } else { + Ok(Calc::Normal(s.parse()?)) + } + } +} + +impl ToTokens for Calc { + fn to_tokens(&self, tokens: &mut TokenStream) { + tokens.extend(match self { + Calc::Calculated(inner) => quote!(style::Calc::Calculated(#inner)), + Calc::Normal(inner) => quote!(style::Calc::Normal(#inner)), + }); + } +} + +#[test] +fn test_calc() { + for (input, output) in vec![ + ("calc(10% - 20\"em\")", "calc(10% - 20em)"), + ("calc(100% + 5px)", "calc(100% + 5px)"), + ("calc(100% - 60px)", "calc(100% - 60px)"), + ] { + assert_eq!(&syn::parse_str::(input).unwrap().to_string(), output); + } +} + +#[derive(Debug, Clone, PartialEq)] +pub struct CalcSum { + pub first: CalcProduct, + pub rest: Vec, +} + +impl fmt::Display for CalcSum { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + write!(f, "{}", self.first)?; + for op in self.rest.iter() { + write!(f, "{}", op)?; + } + Ok(()) + } +} + +impl Parse for CalcSum { + fn parse(s: ParseStream) -> syn::Result { + let first: CalcProduct = s.parse()?; + let mut rest: Vec = vec![]; + while SumOp::peek(s) { + rest.push(s.parse()?); + } + Ok(CalcSum { first, rest }) + } +} + +impl ToTokens for CalcSum { + fn to_tokens(&self, tokens: &mut TokenStream) { + let first = &self.first; + let rest = self.rest.iter(); + tokens.extend(quote! { + style::calc::CalcSum { + first: #first, + rest: vec![#(#rest,)*] + } + }); + } +} + +#[derive(Debug, Clone, PartialEq)] +pub enum SumOp { + Add(CalcProduct), + Sub(CalcProduct), +} + +impl SumOp { + fn peek(s: ParseStream) -> bool { + s.peek(Token![+]) || s.peek(Token![-]) + } +} + +impl fmt::Display for SumOp { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + match self { + SumOp::Add(inner) => write!(f, " + {}", inner), + SumOp::Sub(inner) => write!(f, " - {}", inner), + } + } +} + +impl Parse for SumOp { + fn parse(s: ParseStream) -> syn::Result { + let lookahead = s.lookahead1(); + if lookahead.peek(Token![+]) { + s.parse::()?; + Ok(SumOp::Add(s.parse()?)) + } else if lookahead.peek(Token![-]) { + s.parse::()?; + Ok(SumOp::Sub(s.parse()?)) + } else { + Err(lookahead.error()) + } + } +} + +impl ToTokens for SumOp { + fn to_tokens(&self, tokens: &mut TokenStream) { + tokens.extend(match self { + SumOp::Add(inner) => quote!(style::SumOp::Add(#inner)), + SumOp::Sub(inner) => quote!(style::SumOp::Sub(#inner)), + }); + } +} + +#[derive(Debug, Clone, PartialEq)] +pub struct CalcProduct { + pub first: CalcValue, + pub rest: Vec, +} + +impl fmt::Display for CalcProduct { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + write!(f, "{}", self.first)?; + for op in self.rest.iter() { + write!(f, "{}", op)?; + } + Ok(()) + } +} + +impl Parse for CalcProduct { + fn parse(s: ParseStream) -> syn::Result { + let first: CalcValue = s.parse()?; + let mut rest: Vec = vec![]; + while ProductOp::peek(s) { + rest.push(s.parse()?); + } + Ok(CalcProduct { first, rest }) + } +} + +impl ToTokens for CalcProduct { + fn to_tokens(&self, tokens: &mut TokenStream) { + let first = &self.first; + let rest = self.rest.iter(); + tokens.extend(quote! { + style::calc::CalcProduct { + first: #first, + rest: vec![#(#rest,)*] + } + }); + } +} + +#[derive(Debug, Clone, PartialEq)] +pub enum ProductOp { + Mul(CalcValue), + // todo Div(Number), +} + +impl ProductOp { + pub fn peek(s: ParseStream) -> bool { + s.peek(Token![*]) // || s.peek(Token[/]) + } +} + +impl fmt::Display for ProductOp { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + match self { + ProductOp::Mul(inner) => write!(f, "*{}", inner), + //ProductOp::Div(inner) => write!(f, "/{}", inner), + } + } +} + +impl Parse for ProductOp { + fn parse(s: ParseStream) -> syn::Result { + let lookahead = s.lookahead1(); + if lookahead.peek(Token![*]) { + s.parse::()?; + Ok(ProductOp::Mul(s.parse()?)) + /* + } else if lookahead.peek(Token![/]) { + s.parse::()?; + Ok(ProductOp::Div(s.parse()?)) + */ + } else { + Err(lookahead.error()) + } + } +} + +impl ToTokens for ProductOp { + fn to_tokens(&self, tokens: &mut TokenStream) { + tokens.extend(match self { + ProductOp::Mul(inner) => quote!(style::ProductOp::Mul(#inner)), + //ProductOp::Div(inner) => quote!(style::ProductOp::Div(#inner)), + }); + } +} + +#[derive(Debug, Clone, PartialEq)] +pub enum CalcValue { + LengthPercentage(LengthPercentage), + // todo more variants +} + +impl Parse for CalcValue { + fn parse(s: ParseStream) -> syn::Result { + Ok(CalcValue::LengthPercentage(s.parse()?)) + } +} + +impl fmt::Display for CalcValue { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + match self { + CalcValue::LengthPercentage(inner) => write!(f, "{}", inner), + } + } +} + +impl ToTokens for CalcValue { + fn to_tokens(&self, tokens: &mut TokenStream) { + tokens.extend(match self { + CalcValue::LengthPercentage(inner) => { + quote!(style::CalcValue::LengthPercentage(#inner)) + } + }); + } +} diff --git a/packages/core-macro/src/styles/codegen.rs b/packages/core-macro/src/styles/codegen.rs new file mode 100644 index 000000000..d4a399452 --- /dev/null +++ b/packages/core-macro/src/styles/codegen.rs @@ -0,0 +1,1150 @@ +use crate::*; +use proc_macro2::TokenStream; +use quote::{quote, ToTokens}; + +macro_rules! path { + ($($t:tt)+) => { + ::quote::quote!(::style:: $($t)+) + }; +} + +impl ToTokens for DynamicStyles { + fn to_tokens(&self, tokens: &mut TokenStream) { + let parts = self + .rules + .iter() + .filter(|style| !style.is_dummy()) + .map(|style| style.to_token_stream()); + tokens.extend(quote! { + { + let mut styles = style::Styles::new(); + #(styles.push(#parts);)* + styles + } + }) + } +} + +impl ToTokens for DynamicStyle { + fn to_tokens(&self, tokens: &mut TokenStream) { + tokens.extend(match self { + DynamicStyle::Dynamic(block) => quote!(#block), + DynamicStyle::Literal(lit) => quote!(#lit), + }) + } +} + +impl ToTokens for Style { + fn to_tokens(&self, tokens: &mut TokenStream) { + let path = quote!(::style::Style::); + tokens.extend(match self { + Style::Dummy => quote!(#path Dummy), + Style::Unchecked(v) => quote!(#path Unchecked(String::from(#v))), + + Style::AlignContent(v) => quote!(#path AlignContent(#v)), + Style::AlignItems(v) => quote!(#path AlignItems(#v)), + Style::AlignSelf(v) => quote!(#path AlignSelf(#v)), + // all + // background + Style::BackgroundAttachment(v) => quote!(#path BackgroundAttachment(#v)), + Style::BackgroundBlendMode(v) => quote!(#path BackgroundBlendMode(#v)), + Style::BackgroundClip(v) => quote!(#path BackgroundClip(#v)), + Style::BackgroundColor(v) => quote!(#path BackgroundColor(#v)), + Style::BackgroundImage(v) => quote!(#path BackgroundImage(#v)), + Style::BackgroundOrigin(v) => quote!(#path BackgroundOrigin(#v)), + Style::BackgroundPosition(v) => quote!(#path BackgroundPosition(#v)), + Style::BackgroundRepeat(v) => quote!(#path BackgroundRepeat(#v)), + Style::BackgroundSize(v) => quote!(#path BackgroundSize(#v)), + Style::Border(v) => quote!(#path Border(#v)), + Style::BorderBottom(v) => quote!(#path BorderBottom(#v)), + Style::BorderBottomColor(v) => quote!(#path BorderBottomColor(#v)), + Style::BorderBottomLeftRadius(v) => quote!(#path BorderBottomLeftRadius(#v)), + Style::BorderBottomRightRadius(v) => quote!(#path BorderBottomRightRadius(#v)), + Style::BorderBottomStyle(v) => quote!(#path BorderBottomStyle(#v)), + Style::BorderBottomWidth(v) => quote!(#path BorderBottomWidth(#v)), + Style::BorderCollapse(v) => quote!(#path BorderCollapse(#v)), + Style::BorderColor(v) => quote!(#path BorderColor(#v)), + // border-image + // border-image-outset + // border-image-repeat + // border-image-slice + // border-image-source + // border-image-width + Style::BorderLeft(v) => quote!(#path BorderLeft(#v)), + Style::BorderLeftColor(v) => quote!(#path BorderLeftColor(#v)), + Style::BorderLeftStyle(v) => quote!(#path BorderLeftStyle(#v)), + Style::BorderLeftWidth(v) => quote!(#path BorderLeftWidth(#v)), + Style::BorderRadius(v) => quote!(#path BorderRadius(#v)), + Style::BorderRight(v) => quote!(#path BorderRight(#v)), + Style::BorderRightColor(v) => quote!(#path BorderRightColor(#v)), + Style::BorderRightStyle(v) => quote!(#path BorderRightStyle(#v)), + Style::BorderRightWidth(v) => quote!(#path BorderRightWidth(#v)), + // border-spacing + Style::BorderStyle(v) => quote!(#path BorderStyle(#v)), + Style::BorderTop(v) => quote!(#path BorderTop(#v)), + Style::BorderTopColor(v) => quote!(#path BorderTopColor(#v)), + Style::BorderTopLeftRadius(v) => quote!(#path BorderTopLeftRadius(#v)), + Style::BorderTopRightRadius(v) => quote!(#path BorderTopRightRadius(#v)), + Style::BorderTopStyle(v) => quote!(#path BorderTopStyle(#v)), + Style::BorderTopWidth(v) => quote!(#path BorderTopWidth(#v)), + Style::BorderWidth(v) => quote!(#path BorderWidth(#v)), + Style::Bottom(v) => quote!(#path Bottom(#v)), + // box-decoration-break + Style::BoxShadow(v) => quote!(#path BoxShadow(#v)), + Style::BoxSizing(v) => quote!(#path BoxSizing(#v)), + // break-after + // break-before + // break-inside + // caption-side + // caret-color + Style::Clear(v) => quote!(#path Clear(#v)), + // clip + // clip-path + // clip-rule + Style::ColumnCount(v) => quote!(#path ColumnCount(#v)), + Style::Color(v) => quote!(#path Color(#v)), + // contain + // content + // counter-increment + // counter-reset + // cue + // cue-after + // cue-before + Style::Cursor(v) => quote!(#path Cursor(#v)), + // direction + Style::Display(v) => quote!(#path Display(#v)), + // elevation + // empty-cells + // flex + Style::FlexBasis(v) => quote!(#path FlexBasis(#v)), + Style::FlexDirection(v) => quote!(#path FlexDirection(#v)), + // flex-flow + Style::FlexGrow(v) => quote!(#path FlexGrow(#v)), + Style::FlexShrink(v) => quote!(#path FlexShrink(#v)), + Style::FlexWrap(v) => quote!(#path FlexWrap(#v)), + Style::Float(v) => quote!(#path Float(#v)), + // font + Style::FontFamily(v) => quote!(#path FontFamily(#v)), + // font-feature-settings + // font-kerning + Style::FontSize(v) => quote!(#path FontSize(#v)), + // font-size-adjust + // font-stretch + Style::FontStyle(v) => quote!(#path FontStyle(#v)), + // font-synthesis + // font-variant + // font-variant-caps + // font-variant-east-asian + // font-variant-ligatures + // font-variant-numeric + // font-variant-position + Style::FontWeight(v) => quote!(#path FontWeight(#v)), + // glyph-orientation-vertical + // grid + // grid-area + // grid-auto-columns + // grid-auto-flow + // grid-auto-rows + // grid-column + // grid-column-end + // grid-column-start + // grid-row + // grid-row-end + // grid-row-start + // grid-template + // grid-template-areas + // grid-template-columns + // grid-template-rows + Style::Height(v) => quote!(#path Height(#v)), + // image-orientation + // image-rendering + // isolation + Style::JustifyContent(v) => quote!(#path JustifyContent(#v)), + Style::Left(v) => quote!(#path Left(#v)), + // letter-spacing + Style::LineHeight(v) => quote!(#path LineHeight(#v)), + // list-style + // list-style-image + // list-style-position + Style::ListStyleType(v) => quote!(#path ListStyleType(#v)), + Style::Margin(v) => quote!(#path Margin(#v)), + Style::MarginBottom(v) => quote!(#path MarginBottom(#v)), + Style::MarginLeft(v) => quote!(#path MarginLeft(#v)), + Style::MarginRight(v) => quote!(#path MarginRight(#v)), + Style::MarginTop(v) => quote!(#path MarginTop(#v)), + // mask + // mask-border + // mask-border-mode + // mask-border-outset + // mask-border-repeat + // mask-border-slice + // mask-border-source + // mask-border-width + // mask-clip + // mask-composite + // mask-image + // mask-mode + // mask-origin + // mask-position + // mask-repeat + // mask-size + // mask-type + Style::MaxHeight(v) => quote!(#path MaxHeight(#v)), + Style::MaxWidth(v) => quote!(#path MaxWidth(#v)), + Style::MinHeight(v) => quote!(#path MinHeight(#v)), + Style::MinWidth(v) => quote!(#path MinWidth(#v)), + // mix-blend-mode + Style::ObjectFit(v) => quote!(#path ObjectFit(#v)), + // object-position + // opacity + // order + // orphans + // outline + // outline-color + // outline-offset + // outline-style + // outline-width + Style::Overflow(v) => quote!(#path Overflow(#v)), + Style::OverflowX(v) => quote!(#path OverflowX(#v)), + Style::OverflowY(v) => quote!(#path OverflowY(#v)), + Style::Padding(v) => quote!(#path Padding(#v)), + Style::PaddingBottom(v) => quote!(#path PaddingBottom(#v)), + Style::PaddingLeft(v) => quote!(#path PaddingLeft(#v)), + Style::PaddingRight(v) => quote!(#path PaddingRight(#v)), + Style::PaddingTop(v) => quote!(#path PaddingTop(#v)), + // page-break-after + // page-break-before + // page-break-inside + // pause + // pause-after + // pause-before + // pitch + // pitch-range + // play-during + Style::Position(v) => quote!(#path Position(#v)), + // quotes + Style::Resize(v) => quote!(#path Resize(#v)), + // richness + Style::Right(v) => quote!(#path Right(#v)), + // scroll-margin + // scroll-margin-block + // scroll-margin-block-end + // scroll-margin-block-start + // scroll-margin-bottom + // scroll-margin-inline + // scroll-margin-inline-end + // scroll-margin-inline-start + // scroll-margin-left + // scroll-margin-right + // scroll-margin-top + // scroll-padding + // scroll-padding-block + // scroll-padding-block-end + // scroll-padding-block-start + // scroll-padding-bottom + // scroll-padding-inline + // scroll-padding-inline-end + // scroll-padding-inline-start + // scroll-padding-left + // scroll-padding-right + // scroll-padding-top + // scroll-snap-align + // scroll-snap-stop + // scroll-snap-type + // shape-image-threshold + // shape-margin + // shape-outside + // speak + // speak-header + // speak-numeral + // speak-punctuation + // speech-rate + // stress + // table-layout + Style::TextAlign(v) => quote!(#path TextAlign(#v)), + // text-combine-upright + // text-decoration + // text-decoration-color + // text-decoration-line + // text-decoration-style + // text-emphasis + // text-emphasis-color + // text-emphasis-position + // text-emphasis-style + // text-indent + // text-orientation + // text-overflow + // text-shadow + // text-transform + // text-underline-position + Style::Top(v) => quote!(#path Top(#v)), + // transform + // transform-box + // transform-origin + // unicode-bidi + // vertical-align + // visibility + // voice-family + // volume + // white-space + Style::WhiteSpace(v) => quote!(#path WhiteSpace(#v)), + Style::Widows(v) => quote!(#path Widows(#v)), + Style::Width(v) => quote!(#path Width(#v)), + // will-change + // word-spacing + // writing-mode + // z-index + }); + } +} + +impl ToTokens for AlignContent { + fn to_tokens(&self, tokens: &mut TokenStream) { + tokens.extend(match self { + AlignContent::FlexStart => path!(AlignContent::FlexStart), + AlignContent::Center => path!(AlignContent::Center), + AlignContent::FlexEnd => path!(style::AlignContent::FlexEnd), + AlignContent::SpaceAround => path!(AlignContent::SpaceAround), + AlignContent::SpaceBetween => path!(AlignContent::SpaceBetween), + AlignContent::Stretch => path!(AlignContent::Stretch), + }); + } +} + +impl ToTokens for Cursor { + fn to_tokens(&self, tokens: &mut TokenStream) { + tokens.extend(match self { + Cursor::Auto => path!(Cursor::Auto), + Cursor::Default => path!(Cursor::Default), + Cursor::None => path!(Cursor::None), + Cursor::ContextMenu => path!(Cursor::ContextMenu), + Cursor::Help => path!(Cursor::Help), + Cursor::Pointer => path!(Cursor::Pointer), + Cursor::Progress => path!(Cursor::Progress), + Cursor::Wait => path!(Cursor::Wait), + Cursor::Cell => path!(Cursor::Cell), + Cursor::Crosshair => path!(Cursor::Crosshair), + Cursor::Text => path!(Cursor::Text), + Cursor::VerticalText => path!(Cursor::VerticalText), + Cursor::Alias => path!(Cursor::Alias), + Cursor::Copy => path!(Cursor::Copy), + Cursor::Move => path!(Cursor::Move), + Cursor::NoDrop => path!(Cursor::NoDrop), + Cursor::NotAllowed => path!(Cursor::NotAllowed), + Cursor::Grab => path!(Cursor::Grab), + Cursor::Grabbing => path!(Cursor::Grabbing), + Cursor::EResize => path!(Cursor::EResize), + Cursor::NResize => path!(Cursor::NResize), + Cursor::NEResize => path!(Cursor::NEResize), + Cursor::NWResize => path!(Cursor::NWResize), + Cursor::SResize => path!(Cursor::SResize), + Cursor::SEResize => path!(Cursor::SEResize), + Cursor::SWResize => path!(Cursor::SWResize), + Cursor::WResize => path!(Cursor::WResize), + Cursor::EWResize => path!(Cursor::EWResize), + Cursor::NSResize => path!(Cursor::NSResize), + Cursor::NESWResize => path!(Cursor::NESWResize), + Cursor::NWSEResize => path!(Cursor::NWSEResize), + Cursor::ColResize => path!(Cursor::ColResize), + Cursor::RowResize => path!(Cursor::RowResize), + Cursor::AllScroll => path!(Cursor::AllScroll), + Cursor::ZoomIn => path!(Cursor::ZoomIn), + Cursor::ZoomOut => path!(Cursor::ZoomOut), + }) + } +} + +impl ToTokens for Display { + fn to_tokens(&self, tokens: &mut TokenStream) { + tokens.extend(match self { + Display::Block => path!(Display::Block), + Display::Flex => path!(Display::Flex), + Display::Inline => path!(Display::Inline), + }); + } +} + +impl ToTokens for FlexBasis { + fn to_tokens(&self, tokens: &mut TokenStream) { + tokens.extend(match self { + FlexBasis::Width(v) => path!(FlexBasis::Width(#v)), + FlexBasis::Content => path!(FlexBasis::Content), + }); + } +} + +impl ToTokens for FlexDirection { + fn to_tokens(&self, tokens: &mut TokenStream) { + tokens.extend(match self { + FlexDirection::Row => path!(FlexDirection::Row), + FlexDirection::Column => path!(FlexDirection::Column), + }); + } +} + +impl ToTokens for FlexWrap { + fn to_tokens(&self, tokens: &mut TokenStream) { + tokens.extend(match self { + FlexWrap::Wrap => path!(FlexWrap::Wrap), + FlexWrap::Nowrap => path!(FlexWrap::Nowrap), + }); + } +} + +impl ToTokens for AlignItems { + fn to_tokens(&self, tokens: &mut TokenStream) { + tokens.extend(match self { + AlignItems::Normal => path!(AlignItems::Normal), + AlignItems::Stretch => path!(AlignItems::Stretch), + AlignItems::Center => path!(AlignItems::Center), + AlignItems::Start => path!(AlignItems::Start), + AlignItems::End => path!(AlignItems::End), + AlignItems::FlexStart => path!(AlignItems::FlexStart), + AlignItems::FlexEnd => path!(AlignItems::FlexEnd), + AlignItems::Baseline => path!(AlignItems::Baseline), + AlignItems::FirstBaseline => path!(AlignItems::FirstBaseline), + AlignItems::LastBaseline => path!(AlignItems::LastBaseline), + AlignItems::SafeCenter => path!(AlignItems::SafeCenter), + AlignItems::UnsafeCenter => path!(AlignItems::UnsafeCenter), + }); + } +} + +impl ToTokens for AlignSelf { + fn to_tokens(&self, tokens: &mut TokenStream) { + tokens.extend(match self { + AlignSelf::Auto => path!(AlignSelf::Auto), + AlignSelf::Normal => path!(AlignSelf::Normal), + AlignSelf::Center => path!(AlignSelf::Center), + AlignSelf::Start => path!(AlignSelf::Start), + AlignSelf::End => path!(AlignSelf::End), + AlignSelf::SelfStart => path!(AlignSelf::SelfStart), + AlignSelf::SelfEnd => path!(AlignSelf::SelfEnd), + AlignSelf::FlexStart => path!(AlignSelf::FlexStart), + AlignSelf::FlexEnd => path!(AlignSelf::FlexEnd), + AlignSelf::Baseline => path!(AlignSelf::Baseline), + AlignSelf::FirstBaseline => path!(AlignSelf::FirstBaseline), + AlignSelf::LastBaseline => path!(AlignSelf::LastBaseline), + AlignSelf::Stretch => path!(AlignSelf::Stretch), + AlignSelf::SafeCenter => path!(AlignSelf::SafeCenter), + AlignSelf::UnsafeCenter => path!(AlignSelf::UnsafeCenter), + }); + } +} + +impl ToTokens for BackgroundAttachment { + fn to_tokens(&self, tokens: &mut TokenStream) { + tokens.extend(match self { + BackgroundAttachment::Scroll => path!(BackgroundAttachment::Scroll), + BackgroundAttachment::Fixed => path!(BackgroundAttachment::Fixed), + BackgroundAttachment::Local => path!(BackgroundAttachment::Local), + }) + } +} + +impl ToTokens for BlendMode { + fn to_tokens(&self, tokens: &mut TokenStream) { + tokens.extend(match self { + BlendMode::Normal => path!(BlendMode::Normal), + BlendMode::Multiply => path!(BlendMode::Multiply), + BlendMode::Screen => path!(BlendMode::Screen), + BlendMode::Overlay => path!(BlendMode::Overlay), + BlendMode::Darken => path!(BlendMode::Darken), + BlendMode::Lighten => path!(BlendMode::Lighten), + BlendMode::ColorDodge => path!(BlendMode::ColorDodge), + BlendMode::ColorBurn => path!(BlendMode::ColorBurn), + BlendMode::HardLight => path!(BlendMode::HardLight), + BlendMode::SoftLight => path!(BlendMode::SoftLight), + BlendMode::Difference => path!(BlendMode::Difference), + BlendMode::Exclusion => path!(BlendMode::Exclusion), + BlendMode::Hue => path!(BlendMode::Hue), + BlendMode::Saturation => path!(BlendMode::Saturation), + BlendMode::Color => path!(BlendMode::Color), + BlendMode::Luminosity => path!(BlendMode::Luminosity), + }) + } +} + +impl ToTokens for BackgroundBox { + fn to_tokens(&self, tokens: &mut TokenStream) { + tokens.extend(match self { + BackgroundBox::BorderBox => path!(BackgroundBox::BorderBox), + BackgroundBox::PaddingBox => path!(BackgroundBox::PaddingBox), + BackgroundBox::ContentBox => path!(BackgroundBox::ContentBox), + }) + } +} + +impl ToTokens for BackgroundImage { + fn to_tokens(&self, tokens: &mut TokenStream) { + tokens.extend(match self { + BackgroundImage::None => path!(BackgroundImage::None), + BackgroundImage::Url(url) => path!(BackgroundImage::Url(#url)), + }) + } +} + +impl ToTokens for BackgroundPosition { + fn to_tokens(&self, tokens: &mut TokenStream) { + tokens.extend(match self { + BackgroundPosition::Top => path!(BackgroundPosition::Top), + BackgroundPosition::Bottom => path!(BackgroundPosition::Bottom), + BackgroundPosition::Left => path!(BackgroundPosition::Left), + BackgroundPosition::Right => path!(BackgroundPosition::Right), + BackgroundPosition::Center => path!(BackgroundPosition::Center), + }) + } +} + +impl ToTokens for BackgroundRepeat { + fn to_tokens(&self, tokens: &mut TokenStream) { + tokens.extend(match self { + BackgroundRepeat::RepeatX => path!(BackgroundRepeat::RepeatX), + BackgroundRepeat::RepeatY => path!(BackgroundRepeat::RepeatY), + BackgroundRepeat::SingleOrDouble(v) => path!(BackgroundRepeat::SingleOrDouble(#v)), + }) + } +} + +impl ToTokens for BgRepeatPart { + fn to_tokens(&self, tokens: &mut TokenStream) { + tokens.extend(match self { + BgRepeatPart::Repeat => path!(BgRepeatPart::Repeat), + BgRepeatPart::Space => path!(BgRepeatPart::Space), + BgRepeatPart::Round => path!(BgRepeatPart::Round), + BgRepeatPart::NoRepeat => path!(BgRepeatPart::NoRepeat), + }) + } +} + +impl ToTokens for BackgroundSize { + fn to_tokens(&self, tokens: &mut TokenStream) { + tokens.extend(match self { + BackgroundSize::Cover => path!(BackgroundSize::Cover), + BackgroundSize::Contain => path!(BackgroundSize::Contain), + BackgroundSize::SingleOrDouble(v) => path!(BackgroundSize::SingleOrDouble(#v)), + }) + } +} + +impl ToTokens for BorderCollapse { + fn to_tokens(&self, tokens: &mut TokenStream) { + tokens.extend(match self { + BorderCollapse::Collapse => path!(BorderCollapse::Collapse), + BorderCollapse::Separate => path!(BorderCollapse::Separate), + }) + } +} + +impl ToTokens for JustifyContent { + fn to_tokens(&self, tokens: &mut TokenStream) { + tokens.extend(match self { + JustifyContent::FlexStart => path!(JustifyContent::FlexStart), + JustifyContent::Center => path!(JustifyContent::Center), + JustifyContent::FlexEnd => path!(JustifyContent::FlexEnd), + JustifyContent::SpaceAround => path!(JustifyContent::SpaceAround), + JustifyContent::SpaceBetween => path!(JustifyContent::SpaceBetween), + }); + } +} + +impl ToTokens for Float { + fn to_tokens(&self, tokens: &mut TokenStream) { + tokens.extend(match self { + Float::None => path!(Float::None), + Float::Left => path!(Float::Left), + Float::Right => path!(Float::Right), + Float::InlineStart => path!(Float::InlineStart), + Float::InlineEnd => path!(Float::InlineEnd), + }) + } +} + +impl ToTokens for FontWeight { + fn to_tokens(&self, tokens: &mut TokenStream) { + tokens.extend(match self { + FontWeight::Normal => path!(FontWeight::Normal), + FontWeight::Bold => path!(FontWeight::Bold), + FontWeight::Lighter => path!(FontWeight::Lighter), + FontWeight::Bolder => path!(FontWeight::Bolder), + FontWeight::Number(v) => path!(FontWeight::Number(#v)), + }); + } +} + +impl ToTokens for Font { + fn to_tokens(&self, tokens: &mut TokenStream) { + tokens.extend(match self { + Font::Named(inner) => path!(Font::Named(String::from(#inner))), + Font::Serif => path!(Font::Serif), + Font::SansSerif => path!(Font::SansSerif), + Font::Cursive => path!(Font::Cursive), + Font::Fantasy => path!(Font::Fantasy), + Font::Monospace => path!(Font::Monospace), + }) + } +} + +impl ToTokens for FontSize { + fn to_tokens(&self, tokens: &mut TokenStream) { + tokens.extend(match self { + FontSize::XXSmall => path!(FontSize::XXSmall), + FontSize::XSmall => path!(FontSize::XSmall), + FontSize::Small => path!(FontSize::Small), + FontSize::Medium => path!(FontSize::Medium), + FontSize::Large => path!(FontSize::Large), + FontSize::XLarge => path!(FontSize::XLarge), + FontSize::XXLarge => path!(FontSize::XXLarge), + FontSize::XXXLarge => path!(FontSize::XXXLarge), + FontSize::Larger => path!(FontSize::Larger), + FontSize::Smaller => path!(FontSize::Smaller), + FontSize::LengthPercentage(v) => path!(FontSize::LengthPercentage(#v)), + }); + } +} + +impl ToTokens for FontStyle { + fn to_tokens(&self, tokens: &mut TokenStream) { + tokens.extend(match self { + FontStyle::Normal => path!(FontStyle::Normal), + FontStyle::Italic => path!(FontStyle::Italic), + FontStyle::Oblique => path!(FontStyle::Oblique), + }); + } +} + +impl ToTokens for Border { + fn to_tokens(&self, tokens: &mut TokenStream) { + let line_width = match self.line_width { + Some(line_width) => quote!(Some(#line_width)), + None => quote!(None), + }; + let line_style = match self.line_style { + Some(line_style) => quote!(Some(#line_style)), + None => quote!(None), + }; + let color = match self.color { + Some(color) => quote!(Some(#color)), + None => quote!(None), + }; + tokens.extend(quote!( + style::Border { + line_width: #line_width, + line_style: #line_style, + color: #color, + } + )) + } +} + +impl ToTokens for BoxShadow { + fn to_tokens(&self, tokens: &mut TokenStream) { + tokens.extend(match self { + BoxShadow::None => path!(BoxShadow::None), + BoxShadow::Shadows(list) => path!(BoxShadow::Shadows(#list)), + }); + } +} + +impl ToTokens for BoxSizing { + fn to_tokens(&self, tokens: &mut TokenStream) { + tokens.extend(match self { + BoxSizing::BorderBox => path!(BoxSizing::BorderBox), + BoxSizing::ContentBox => path!(BoxSizing::ContentBox), + }); + } +} + +impl ToTokens for Clear { + fn to_tokens(&self, tokens: &mut TokenStream) { + tokens.extend(match self { + Clear::None => path!(Clear::None), + Clear::Left => path!(Clear::Left), + Clear::Right => path!(Clear::Right), + Clear::Both => path!(Clear::Both), + Clear::InlineStart => path!(Clear::InlineStart), + Clear::InlineEnd => path!(Clear::InlineEnd), + }) + } +} + +impl ToTokens for ColumnCount { + fn to_tokens(&self, tokens: &mut TokenStream) { + tokens.extend(match self { + ColumnCount::Auto => path!(ColumnCount::Auto), + ColumnCount::Fixed(v) => path!(ColumnCount::Fixed(#v)), + }) + } +} + +impl ToTokens for Overflow { + fn to_tokens(&self, tokens: &mut TokenStream) { + tokens.extend(match self { + Overflow::Both(v) => path!(Overflow::Both(#v)), + Overflow::XY(x, y) => path!(Overflow::XY(#x, #y)), + }) + } +} + +impl ToTokens for OverflowXY { + fn to_tokens(&self, tokens: &mut TokenStream) { + tokens.extend(match self { + OverflowXY::Visible => path!(OverflowXY::Visible), + OverflowXY::Hidden => path!(OverflowXY::Hidden), + OverflowXY::Clip => path!(OverflowXY::Clip), + OverflowXY::Scroll => path!(OverflowXY::Scroll), + OverflowXY::Auto => path!(OverflowXY::Auto), + }) + } +} + +impl ToTokens for ObjectFit { + fn to_tokens(&self, tokens: &mut TokenStream) { + tokens.extend(match self { + ObjectFit::Fill => path!(ObjectFit::Fill), + ObjectFit::None => path!(ObjectFit::None), + ObjectFit::Contain { scale_down } => { + path!(ObjectFit::Contain { scale_down: #scale_down }) + } + ObjectFit::Cover { scale_down } => path!(ObjectFit::Cover { scale_down: #scale_down }), + }) + } +} + +impl ToTokens for Rect +where + T: ToTokens, +{ + fn to_tokens(&self, tokens: &mut TokenStream) { + tokens.extend(match self { + Rect::All(v) => path!(Rect::All(#v)), + Rect::VerticalHorizontal(v, h) => path!(Rect::VerticalHorizontal(#v, #h)), + Rect::TopHorizontalBottom(t, h, b) => path!(Rect::TopHorizontalBottom(#t, #h, #b)), + Rect::TopRightBottomLeft(t, r, b, l) => path!(Rect::TopRightBottomLeft(#t, #r, #b, #l)), + }); + } +} + +impl ToTokens for LengthPercentage { + fn to_tokens(&self, tokens: &mut TokenStream) { + tokens.extend(match self { + LengthPercentage::Length(v) => path!(LengthPercentage::Length(#v)), + LengthPercentage::Percentage(v) => path!(LengthPercentage::Percentage(#v)), + }); + } +} + +impl ToTokens for AutoLengthPercentage { + fn to_tokens(&self, tokens: &mut TokenStream) { + tokens.extend(match self { + AutoLengthPercentage::LengthPercentage(v) => { + path!(AutoLengthPercentage::LengthPercentage(#v)) + } + AutoLengthPercentage::Auto => path!(AutoLengthPercentage::Auto), + }); + } +} + +impl ToTokens for LineStyle { + fn to_tokens(&self, tokens: &mut TokenStream) { + tokens.extend(match self { + LineStyle::None => path!(LineStyle::None), + LineStyle::Hidden => path!(LineStyle::Hidden), + LineStyle::Dotted => path!(LineStyle::Dotted), + LineStyle::Dashed => path!(LineStyle::Dashed), + LineStyle::Solid => path!(LineStyle::Solid), + LineStyle::Double => path!(LineStyle::Double), + LineStyle::Groove => path!(LineStyle::Groove), + LineStyle::Ridge => path!(LineStyle::Ridge), + LineStyle::Inset => path!(LineStyle::Inset), + LineStyle::Outset => path!(LineStyle::Outset), + }) + } +} + +impl ToTokens for LineWidth { + fn to_tokens(&self, tokens: &mut TokenStream) { + tokens.extend(match self { + LineWidth::Length(length) => path!(LineWidth::Length(#length)), + LineWidth::Thin => path!(LineWidth::Thin), + LineWidth::Medium => path!(LineWidth::Medium), + LineWidth::Thick => path!(LineWidth::Thick), + }) + } +} + +impl ToTokens for LineHeight { + fn to_tokens(&self, tokens: &mut TokenStream) { + self.0.to_tokens(tokens) + } +} + +impl ToTokens for ListStyleType { + fn to_tokens(&self, tokens: &mut TokenStream) { + tokens.extend(match self { + ListStyleType::Disc => path!(ListStyleType::Disc), + ListStyleType::Circle => path!(ListStyleType::Circle), + ListStyleType::Square => path!(ListStyleType::Square), + ListStyleType::Decimal => path!(ListStyleType::Decimal), + ListStyleType::DecimalLeadingZero => path!(ListStyleType::DecimalLeadingZero), + ListStyleType::LowerRoman => path!(ListStyleType::LowerRoman), + ListStyleType::UpperRoman => path!(ListStyleType::UpperRoman), + ListStyleType::LowerGreek => path!(ListStyleType::LowerGreek), + ListStyleType::UpperGreek => path!(ListStyleType::UpperGreek), + ListStyleType::LowerLatin => path!(ListStyleType::LowerLatin), + ListStyleType::UpperLatin => path!(ListStyleType::UpperLatin), + ListStyleType::Armenian => path!(ListStyleType::Armenian), + ListStyleType::Georgian => path!(ListStyleType::Georgian), + ListStyleType::LowerAlpha => path!(ListStyleType::LowerAlpha), + ListStyleType::UpperAlpha => path!(ListStyleType::UpperAlpha), + ListStyleType::None => path!(ListStyleType::None), + }) + } +} + +impl ToTokens for Position { + fn to_tokens(&self, tokens: &mut TokenStream) { + tokens.extend(match self { + Position::Static => path!(Position::Static), + Position::Relative => path!(Position::Relative), + Position::Absolute => path!(Position::Absolute), + Position::Fixed => path!(Position::Fixed), + }) + } +} + +impl ToTokens for Resize { + fn to_tokens(&self, tokens: &mut TokenStream) { + tokens.extend(match self { + Resize::None => path!(Resize::None), + Resize::Both => path!(Resize::Both), + Resize::Horizontal => path!(Resize::Horizontal), + Resize::Vertical => path!(Resize::Vertical), + }) + } +} + +impl ToTokens for WhiteSpace { + fn to_tokens(&self, tokens: &mut TokenStream) { + tokens.extend(match self { + WhiteSpace::Normal => path!(WhiteSpace::Normal), + WhiteSpace::Pre => path!(WhiteSpace::Pre), + WhiteSpace::Nowrap => path!(WhiteSpace::Nowrap), + WhiteSpace::PreWrap => path!(WhiteSpace::PreWrap), + WhiteSpace::PreLine => path!(WhiteSpace::PreLine), + }) + } +} + +impl ToTokens for WidthHeight { + fn to_tokens(&self, tokens: &mut TokenStream) { + tokens.extend(match self { + WidthHeight::Auto => path!(WidthHeight::Auto), + WidthHeight::LengthPercentage(v) => path!(WidthHeight::LengthPercentage(#v)), + WidthHeight::MinContent => path!(WidthHeight::MinContent), + WidthHeight::MaxContent => path!(WidthHeight::MaxContent), + WidthHeight::FitContent(v) => path!(WidthHeight::FitContent(#v)), + }) + } +} + +impl ToTokens for MaxWidthHeight { + fn to_tokens(&self, tokens: &mut TokenStream) { + tokens.extend(match self { + MaxWidthHeight::None => path!(MaxWidthHeight::None), + MaxWidthHeight::LengthPercentage(v) => path!(MaxWidthHeight::LengthPercentage(#v)), + MaxWidthHeight::MinContent => path!(MaxWidthHeight::MinContent), + MaxWidthHeight::MaxContent => path!(MaxWidthHeight::MaxContent), + MaxWidthHeight::FitContent(v) => path!(MaxWidthHeight::FitContent(#v)), + }) + } +} + +impl ToTokens for Width21 { + fn to_tokens(&self, tokens: &mut TokenStream) { + tokens.extend(match self { + Width21::Auto => path!(Width21::Auto), + Width21::LengthPercentage(v) => path!(Width21::LengthPercentage(#v)), + }) + } +} + +impl ToTokens for Shadow { + fn to_tokens(&self, tokens: &mut TokenStream) { + let color = match self.color.as_ref() { + Some(color) => quote!(Some(#color)), + None => quote!(None), + }; + let length = &self.length; + let inset = &self.inset; + tokens.extend(quote! { + style::Shadow { + color: #color, + length: #length, + inset: #inset, + } + }) + } +} + +impl ToTokens for ShadowLength { + fn to_tokens(&self, tokens: &mut TokenStream) { + tokens.extend(match self { + ShadowLength::Offsets { + vertical, + horizontal, + } => path!(ShadowLength::Offsets { + vertical: #vertical, + horizontal: #horizontal, + }), + ShadowLength::OffsetsBlur { + vertical, + horizontal, + blur, + } => path!(ShadowLength::OffsetsBlur { + vertical: #vertical, + horizontal: #horizontal, + blur: #blur, + }), + ShadowLength::OffsetsBlurSpread { + vertical, + horizontal, + blur, + spread, + } => path!(ShadowLength::Offsets { + vertical: #vertical, + horizontal: #horizontal, + blur: #blur, + spread: #spread, + }), + }) + } +} + +impl ToTokens for TextAlign { + fn to_tokens(&self, tokens: &mut TokenStream) { + tokens.extend(match self { + TextAlign::Left => path!(TextAlign::Left), + TextAlign::Right => path!(TextAlign::Right), + TextAlign::Center => path!(TextAlign::Center), + TextAlign::Justify => path!(TextAlign::Justify), + }); + } +} + +impl ToTokens for Length { + fn to_tokens(&self, tokens: &mut TokenStream) { + tokens.extend(match self { + Length::Em(v) => path!(Length::Em(#v)), + Length::Ex(v) => path!(Length::Ex(#v)), + Length::In(v) => path!(Length::In(#v)), + Length::Cm(v) => path!(Length::Cm(#v)), + Length::Mm(v) => path!(Length::Mm(#v)), + Length::Pt(v) => path!(Length::Pt(#v)), + Length::Pc(v) => path!(Length::Pc(#v)), + Length::Px(v) => path!(Length::Px(#v)), + Length::Zero => path!(Length::Zero), + }) + } +} + +impl ToTokens for Percentage { + fn to_tokens(&self, tokens: &mut TokenStream) { + let val = self.0; + tokens.extend(path!(Percentage(#val))); + } +} + +impl ToTokens for DynamicColor { + fn to_tokens(&self, tokens: &mut TokenStream) { + tokens.extend(match self { + DynamicColor::Dynamic(block) => path!(DynamicColor::Literal(#block)), + DynamicColor::Literal(color) => path!(DynamicColor::Literal(#color)), + }) + } +} + +impl ToTokens for Color { + fn to_tokens(&self, tokens: &mut TokenStream) { + tokens.extend(match self { + Color::HexRGB(r, g, b) => path!(Color::HexRGB(#r, #g, #b)), + Color::HexRGBA(r, g, b, a) => path!(Color::HexRGB(#r, #g, #b, #a)), + Color::HSL(h, s, l) => path!(Color::HSL(#h, #s, #l)), + Color::HSLA(h, s, l, a) => path!(Color::HSLA(#h, #s, #l, #a)), + Color::IndianRed => path!(Color::IndianRed), + Color::LightCoral => path!(Color::LightCoral), + Color::Salmon => path!(Color::Salmon), + Color::DarkSalmon => path!(Color::DarkSalmon), + Color::LightSalmon => path!(Color::LightSalmon), + Color::Crimson => path!(Color::Crimson), + Color::Red => path!(Color::Red), + Color::FireBrick => path!(Color::FireBrick), + Color::DarkRed => path!(Color::DarkRed), + Color::Pink => path!(Color::Pink), + Color::LightPink => path!(Color::LightPink), + Color::HotPink => path!(Color::HotPink), + Color::DeepPink => path!(Color::DeepPink), + Color::MediumVioletRed => path!(Color::MediumVioletRed), + Color::PaleVioletRed => path!(Color::PaleVioletRed), + Color::Coral => path!(Color::Coral), + Color::Tomato => path!(Color::Tomato), + Color::OrangeRed => path!(Color::OrangeRed), + Color::DarkOrange => path!(Color::DarkOrange), + Color::Orange => path!(Color::Orange), + Color::Gold => path!(Color::Gold), + Color::Yellow => path!(Color::Yellow), + Color::LightYellow => path!(Color::LightYellow), + Color::LemonChiffon => path!(Color::LemonChiffon), + Color::LightGoldenrodYellow => path!(Color::LightGoldenrodYellow), + Color::PapayaWhip => path!(Color::PapayaWhip), + Color::Moccasin => path!(Color::Moccasin), + Color::PeachPuff => path!(Color::PeachPuff), + Color::PaleGoldenrod => path!(Color::PaleGoldenrod), + Color::Khaki => path!(Color::Khaki), + Color::DarkKhaki => path!(Color::DarkKhaki), + Color::Lavender => path!(Color::Lavender), + Color::Thistle => path!(Color::Thistle), + Color::Plum => path!(Color::Plum), + Color::Violet => path!(Color::Violet), + Color::Orchid => path!(Color::Orchid), + Color::Fuchsia => path!(Color::Fuchsia), + Color::Magenta => path!(Color::Magenta), + Color::MediumOrchid => path!(Color::MediumOrchid), + Color::MediumPurple => path!(Color::MediumPurple), + Color::RebeccaPurple => path!(Color::RebeccaPurple), + Color::BlueViolet => path!(Color::BlueViolet), + Color::DarkViolet => path!(Color::DarkViolet), + Color::DarkOrchid => path!(Color::DarkOrchid), + Color::DarkMagenta => path!(Color::DarkMagenta), + Color::Purple => path!(Color::Purple), + Color::Indigo => path!(Color::Indigo), + Color::SlateBlue => path!(Color::SlateBlue), + Color::DarkSlateBlue => path!(Color::DarkSlateBlue), + Color::MediumSlateBlue => path!(Color::MediumSlateBlue), + Color::GreenYellow => path!(Color::GreenYellow), + Color::Chartreuse => path!(Color::Chartreuse), + Color::LawnGreen => path!(Color::LawnGreen), + Color::Lime => path!(Color::Lime), + Color::LimeGreen => path!(Color::LimeGreen), + Color::PaleGreen => path!(Color::PaleGreen), + Color::LightGreen => path!(Color::LightGreen), + Color::MediumSpringGreen => path!(Color::MediumSpringGreen), + Color::SpringGreen => path!(Color::SpringGreen), + Color::MediumSeaGreen => path!(Color::MediumSeaGreen), + Color::SeaGreen => path!(Color::SeaGreen), + Color::ForestGreen => path!(Color::ForestGreen), + Color::Green => path!(Color::Green), + Color::DarkGreen => path!(Color::DarkGreen), + Color::YellowGreen => path!(Color::YellowGreen), + Color::OliveDrab => path!(Color::OliveDrab), + Color::Olive => path!(Color::Olive), + Color::DarkOliveGreen => path!(Color::DarkOliveGreen), + Color::MediumAquamarine => path!(Color::MediumAquamarine), + Color::DarkSeaGreen => path!(Color::DarkSeaGreen), + Color::LightSeaGreen => path!(Color::LightSeaGreen), + Color::DarkCyan => path!(Color::DarkCyan), + Color::Teal => path!(Color::Teal), + Color::Aqua => path!(Color::Aqua), + Color::Cyan => path!(Color::Cyan), + Color::LightCyan => path!(Color::LightCyan), + Color::PaleTurquoise => path!(Color::PaleTurquoise), + Color::Aquamarine => path!(Color::Aquamarine), + Color::Turquoise => path!(Color::Turquoise), + Color::MediumTurquoise => path!(Color::MediumTurquoise), + Color::DarkTurquoise => path!(Color::DarkTurquoise), + Color::CadetBlue => path!(Color::CadetBlue), + Color::SteelBlue => path!(Color::SteelBlue), + Color::LightSteelBlue => path!(Color::LightSteelBlue), + Color::PowderBlue => path!(Color::PowderBlue), + Color::LightBlue => path!(Color::LightBlue), + Color::SkyBlue => path!(Color::SkyBlue), + Color::LightSkyBlue => path!(Color::LightSkyBlue), + Color::DeepSkyBlue => path!(Color::DeepSkyBlue), + Color::DodgerBlue => path!(Color::DodgerBlue), + Color::CornflowerBlue => path!(Color::CornflowerBlue), + Color::RoyalBlue => path!(Color::RoyalBlue), + Color::Blue => path!(Color::Blue), + Color::MediumBlue => path!(Color::MediumBlue), + Color::DarkBlue => path!(Color::DarkBlue), + Color::Navy => path!(Color::Navy), + Color::MidnightBlue => path!(Color::MidnightBlue), + Color::Cornsilk => path!(Color::Cornsilk), + Color::BlanchedAlmond => path!(Color::BlanchedAlmond), + Color::Bisque => path!(Color::Bisque), + Color::NavajoWhite => path!(Color::NavajoWhite), + Color::Wheat => path!(Color::Wheat), + Color::BurlyWood => path!(Color::BurlyWood), + Color::Tan => path!(Color::Tan), + Color::RosyBrown => path!(Color::RosyBrown), + Color::SandyBrown => path!(Color::SandyBrown), + Color::Goldenrod => path!(Color::Goldenrod), + Color::DarkGoldenrod => path!(Color::DarkGoldenrod), + Color::Peru => path!(Color::Peru), + Color::Chocolate => path!(Color::Chocolate), + Color::SaddleBrown => path!(Color::SaddleBrown), + Color::Sienna => path!(Color::Sienna), + Color::Brown => path!(Color::Brown), + Color::Maroon => path!(Color::Maroon), + Color::White => path!(Color::White), + Color::Snow => path!(Color::Snow), + Color::HoneyDew => path!(Color::HoneyDew), + Color::MintCream => path!(Color::MintCream), + Color::Azure => path!(Color::Azure), + Color::AliceBlue => path!(Color::AliceBlue), + Color::GhostWhite => path!(Color::GhostWhite), + Color::WhiteSmoke => path!(Color::WhiteSmoke), + Color::SeaShell => path!(Color::SeaShell), + Color::Beige => path!(Color::Beige), + Color::OldLace => path!(Color::OldLace), + Color::FloralWhite => path!(Color::FloralWhite), + Color::Ivory => path!(Color::Ivory), + Color::AntiqueWhite => path!(Color::AntiqueWhite), + Color::Linen => path!(Color::Linen), + Color::LavenderBlush => path!(Color::LavenderBlush), + Color::MistyRose => path!(Color::MistyRose), + Color::Gainsboro => path!(Color::Gainsboro), + Color::LightGray => path!(Color::LightGray), + Color::Silver => path!(Color::Silver), + Color::DarkGray => path!(Color::DarkGray), + Color::Gray => path!(Color::Gray), + Color::DimGray => path!(Color::DimGray), + Color::LightSlateGray => path!(Color::LightSlateGray), + Color::SlateGray => path!(Color::SlateGray), + Color::DarkSlateGray => path!(Color::DarkSlateGray), + Color::Black => path!(Color::Black), + }) + } +} + +// Generic containers + +impl ToTokens for NonemptyCommaList +where + T: ToTokens, +{ + fn to_tokens(&self, tokens: &mut TokenStream) { + let first = &self.first; + let rest = &self.rest; + tokens.extend(path! { + NonemptyCommaList { + first: #first, + rest: vec![#(#rest),*], + } + }) + } +} + +impl ToTokens for SingleOrDouble +where + T: ToTokens, +{ + fn to_tokens(&self, tokens: &mut TokenStream) { + tokens.extend(match self { + SingleOrDouble::Single(t) => path!(SingleOrDouble::Single(#t)), + SingleOrDouble::Double { vert, horiz } => path!(SingleOrDouble::Double { + vert: #vert, + horiz: #horiz, + }), + }) + } +} diff --git a/packages/core-macro/src/styles/color.rs b/packages/core-macro/src/styles/color.rs new file mode 100644 index 000000000..15bc7cfb5 --- /dev/null +++ b/packages/core-macro/src/styles/color.rs @@ -0,0 +1,854 @@ +use std::fmt; + +/// A color that possibly is possibly code, rather than a literal +#[derive(Debug, Clone, PartialEq)] +pub enum DynamicColor { + Literal(Color), + /// The type of the block is not checked here (it is checked by typeck). + Dynamic(syn::Block), +} + +impl DynamicColor { + pub fn is_dynamic(&self) -> bool { + match self { + DynamicColor::Dynamic(_) => true, + DynamicColor::Literal(_) => false, + } + } +} + +impl fmt::Display for DynamicColor { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + match self { + DynamicColor::Dynamic(_) => Ok(()), + DynamicColor::Literal(color) => color.fmt(f), + } + } +} + +// TODO other color variants. +#[derive(Debug, Clone, Copy, PartialEq)] +#[non_exhaustive] +pub enum Color { + HexRGB(u8, u8, u8), + HexRGBA(u8, u8, u8, u8), + // Invariants: `0 <= .0 < 360`, `0 <= .1 < 100`, `0 <= .2 < 100`. + HSL(f64, f64, f64), + // Invariants: `0 <= .0 < 360`, `0 <= .1 < 100`, `0 <= .2 < 100`, `0 <= .3 < 1`. + HSLA(f64, f64, f64, f64), + + // Red HTML Color Names + /// rgb(205, 92, 92) + IndianRed, + /// rgb(240, 128, 128) + LightCoral, + /// rgb(250, 128, 114) + Salmon, + /// rgb(233, 150, 122) + DarkSalmon, + /// rgb(255, 160, 122) + LightSalmon, + /// rgb(220, 20, 60) + Crimson, + /// rgb(255, 0, 0) + Red, + /// rgb(178, 34, 34) + FireBrick, + /// rgb(139, 0, 0) + DarkRed, + // Pink HTML Color Names + /// rgb(255, 192, 203) + Pink, + /// rgb(255, 182, 193) + LightPink, + /// rgb(255, 105, 180) + HotPink, + /// rgb(255, 20, 147) + DeepPink, + /// rgb(199, 21, 133) + MediumVioletRed, + /// rgb(219, 112, 147) + PaleVioletRed, + //Orange HTML Color Names + // /// rgb(255, 160, 122) redefined + // LightSalmon, + /// rgb(255, 127, 80) + Coral, + /// rgb(255, 99, 71) + Tomato, + /// rgb(255, 69, 0) + OrangeRed, + /// rgb(255, 140, 0) + DarkOrange, + /// rgb(255, 165, 0) + Orange, + // Yellow HTML Color Names + /// rgb(255, 215, 0) + Gold, + /// rgb(255, 255, 0) + Yellow, + /// rgb(255, 255, 224) + LightYellow, + /// rgb(255, 250, 205) + LemonChiffon, + /// rgb(250, 250, 210) + LightGoldenrodYellow, + /// rgb(255, 239, 213) + PapayaWhip, + /// rgb(255, 228, 181) + Moccasin, + /// rgb(255, 218, 185) + PeachPuff, + /// rgb(238, 232, 170) + PaleGoldenrod, + /// rgb(240, 230, 140) + Khaki, + /// rgb(189, 183, 107) + DarkKhaki, + // Purple HTML Color Names + /// rgb(230, 230, 250) + Lavender, + /// rgb(216, 191, 216) + Thistle, + /// rgb(221, 160, 221) + Plum, + /// rgb(238, 130, 238) + Violet, + /// rgb(218, 112, 214) + Orchid, + /// rgb(255, 0, 255) + Fuchsia, + /// rgb(255, 0, 255) + Magenta, + /// rgb(186, 85, 211) + MediumOrchid, + /// rgb(147, 112, 219) + MediumPurple, + /// rgb(102, 51, 153) + RebeccaPurple, + /// rgb(138, 43, 226) + BlueViolet, + /// rgb(148, 0, 211) + DarkViolet, + /// rgb(153, 50, 204) + DarkOrchid, + /// rgb(139, 0, 139) + DarkMagenta, + /// rgb(128, 0, 128) + Purple, + /// rgb(75, 0, 130) + Indigo, + /// rgb(106, 90, 205) + SlateBlue, + /// rgb(72, 61, 139) + DarkSlateBlue, + /// rgb(123, 104, 238) + MediumSlateBlue, + // Green HTML Color Names + /// rgb(173, 255, 47) + GreenYellow, + /// rgb(127, 255, 0) + Chartreuse, + /// rgb(124, 252, 0) + LawnGreen, + /// rgb(0, 255, 0) + Lime, + /// rgb(50, 205, 50) + LimeGreen, + /// rgb(152, 251, 152) + PaleGreen, + /// rgb(144, 238, 144) + LightGreen, + /// rgb(0, 250, 154) + MediumSpringGreen, + /// rgb(0, 255, 127) + SpringGreen, + /// rgb(60, 179, 113) + MediumSeaGreen, + /// rgb(46, 139, 87) + SeaGreen, + /// rgb(34, 139, 34) + ForestGreen, + /// rgb(0, 128, 0) + Green, + /// rgb(0, 100, 0) + DarkGreen, + /// rgb(154, 205, 50) + YellowGreen, + /// rgb(107, 142, 35) + OliveDrab, + /// rgb(128, 128, 0) + Olive, + /// rgb(85, 107, 47) + DarkOliveGreen, + /// rgb(102, 205, 170) + MediumAquamarine, + /// rgb(143, 188, 139) + DarkSeaGreen, + /// rgb(32, 178, 170) + LightSeaGreen, + /// rgb(0, 139, 139) + DarkCyan, + /// rgb(0, 128, 128) + Teal, + // Blue HTML Color Names + /// rgb(0, 255, 255) + Aqua, + /// rgb(0, 255, 255) + Cyan, + /// rgb(224, 255, 255) + LightCyan, + /// rgb(175, 238, 238) + PaleTurquoise, + /// rgb(127, 255, 212) + Aquamarine, + /// rgb(64, 224, 208) + Turquoise, + /// rgb(72, 209, 204) + MediumTurquoise, + /// rgb(0, 206, 209) + DarkTurquoise, + /// rgb(95, 158, 160) + CadetBlue, + /// rgb(70, 130, 180) + SteelBlue, + /// rgb(176, 196, 222) + LightSteelBlue, + /// rgb(176, 224, 230) + PowderBlue, + /// rgb(173, 216, 230) + LightBlue, + /// rgb(135, 206, 235) + SkyBlue, + /// rgb(135, 206, 250) + LightSkyBlue, + /// rgb(0, 191, 255) + DeepSkyBlue, + /// rgb(30, 144, 255) + DodgerBlue, + /// rgb(100, 149, 237) + CornflowerBlue, + // /// rgb(123, 104, 238) duplicate + //MediumSlateBlue, + /// rgb(65, 105, 225) + RoyalBlue, + /// rgb(0, 0, 255) + Blue, + /// rgb(0, 0, 205) + MediumBlue, + /// rgb(0, 0, 139) + DarkBlue, + /// rgb(0, 0, 128) + Navy, + /// rgb(25, 25, 112) + MidnightBlue, + // Brown HTML Color Names + /// rgb(255, 248, 220) + Cornsilk, + /// rgb(255, 235, 205) + BlanchedAlmond, + /// rgb(255, 228, 196) + Bisque, + /// rgb(255, 222, 173) + NavajoWhite, + /// rgb(245, 222, 179) + Wheat, + /// rgb(222, 184, 135) + BurlyWood, + /// rgb(210, 180, 140) + Tan, + /// rgb(188, 143, 143) + RosyBrown, + /// rgb(244, 164, 96) + SandyBrown, + /// rgb(218, 165, 32) + Goldenrod, + /// rgb(184, 134, 11) + DarkGoldenrod, + /// rgb(205, 133, 63) + Peru, + /// rgb(210, 105, 30) + Chocolate, + /// rgb(139, 69, 19) + SaddleBrown, + /// rgb(160, 82, 45) + Sienna, + /// rgb(165, 42, 42) + Brown, + /// rgb(128, 0, 0) + Maroon, + // White HTML Color Names + /// rgb(255, 255, 255) + White, + /// rgb(255, 250, 250) + Snow, + /// rgb(240, 255, 240) + HoneyDew, + /// rgb(245, 255, 250) + MintCream, + /// rgb(240, 255, 255) + Azure, + /// rgb(240, 248, 255) + AliceBlue, + /// rgb(248, 248, 255) + GhostWhite, + /// rgb(245, 245, 245) + WhiteSmoke, + /// rgb(255, 245, 238) + SeaShell, + /// rgb(245, 245, 220) + Beige, + /// rgb(253, 245, 230) + OldLace, + /// rgb(255, 250, 240) + FloralWhite, + /// rgb(255, 255, 240) + Ivory, + /// rgb(250, 235, 215) + AntiqueWhite, + /// rgb(250, 240, 230) + Linen, + /// rgb(255, 240, 245) + LavenderBlush, + /// rgb(255, 228, 225) + MistyRose, + // Gray HTML Color Names + /// rgb(220, 220, 220) + Gainsboro, + /// rgb(211, 211, 211) + LightGray, + /// rgb(192, 192, 192) + Silver, + /// rgb(169, 169, 169) + DarkGray, + /// rgb(128, 128, 128) + Gray, + /// rgb(105, 105, 105) + DimGray, + /// rgb(119, 136, 153) + LightSlateGray, + /// rgb(112, 128, 144) + SlateGray, + /// rgb(47, 79, 79) + DarkSlateGray, + /// rgb(0, 0, 0) + Black, +} + +impl Color { + // todo similar for others + pub fn to_rgb(self) -> Color { + use Color::*; + match self { + HexRGB(r, g, b) => HexRGB(r, g, b), + HexRGBA(r, g, b, _) => HexRGB(r, g, b), + HSL(h, s, l) => { + let s = s * 0.01; // percent conversion + let l = l * 0.01; // percent conversion + let (r, g, b) = hsl_to_rgb(h, s, l); + HexRGB((r * 255.0) as u8, (g * 255.0) as u8, (b * 255.0) as u8) + } + HSLA(h, s, l, _) => Color::to_rgb(HSL(h, s, l)), + IndianRed => HexRGB(205, 92, 92), + LightCoral => HexRGB(240, 128, 128), + Salmon => HexRGB(250, 128, 114), + DarkSalmon => HexRGB(233, 150, 122), + LightSalmon => HexRGB(255, 160, 122), + Crimson => HexRGB(220, 20, 60), + Red => HexRGB(255, 0, 0), + FireBrick => HexRGB(178, 34, 34), + DarkRed => HexRGB(139, 0, 0), + Pink => HexRGB(255, 192, 203), + LightPink => HexRGB(255, 182, 193), + HotPink => HexRGB(255, 105, 180), + DeepPink => HexRGB(255, 20, 147), + MediumVioletRed => HexRGB(199, 21, 133), + PaleVioletRed => HexRGB(219, 112, 147), + Coral => HexRGB(255, 127, 80), + Tomato => HexRGB(255, 99, 71), + OrangeRed => HexRGB(255, 69, 0), + DarkOrange => HexRGB(255, 140, 0), + Orange => HexRGB(255, 165, 0), + Gold => HexRGB(255, 215, 0), + Yellow => HexRGB(255, 255, 0), + LightYellow => HexRGB(255, 255, 224), + LemonChiffon => HexRGB(255, 250, 205), + LightGoldenrodYellow => HexRGB(250, 250, 210), + PapayaWhip => HexRGB(255, 239, 213), + Moccasin => HexRGB(255, 228, 181), + PeachPuff => HexRGB(255, 218, 185), + PaleGoldenrod => HexRGB(238, 232, 170), + Khaki => HexRGB(240, 230, 140), + DarkKhaki => HexRGB(189, 183, 107), + Lavender => HexRGB(230, 230, 250), + Thistle => HexRGB(216, 191, 216), + Plum => HexRGB(221, 160, 221), + Violet => HexRGB(238, 130, 238), + Orchid => HexRGB(218, 112, 214), + Fuchsia => HexRGB(255, 0, 255), + Magenta => HexRGB(255, 0, 255), + MediumOrchid => HexRGB(186, 85, 211), + MediumPurple => HexRGB(147, 112, 219), + RebeccaPurple => HexRGB(102, 51, 153), + BlueViolet => HexRGB(138, 43, 226), + DarkViolet => HexRGB(148, 0, 211), + DarkOrchid => HexRGB(153, 50, 204), + DarkMagenta => HexRGB(139, 0, 139), + Purple => HexRGB(128, 0, 128), + Indigo => HexRGB(75, 0, 130), + SlateBlue => HexRGB(106, 90, 205), + DarkSlateBlue => HexRGB(72, 61, 139), + MediumSlateBlue => HexRGB(123, 104, 238), + GreenYellow => HexRGB(173, 255, 47), + Chartreuse => HexRGB(127, 255, 0), + LawnGreen => HexRGB(124, 252, 0), + Lime => HexRGB(0, 255, 0), + LimeGreen => HexRGB(50, 205, 50), + PaleGreen => HexRGB(152, 251, 152), + LightGreen => HexRGB(144, 238, 144), + MediumSpringGreen => HexRGB(0, 250, 154), + SpringGreen => HexRGB(0, 255, 127), + MediumSeaGreen => HexRGB(60, 179, 113), + SeaGreen => HexRGB(46, 139, 87), + ForestGreen => HexRGB(34, 139, 34), + Green => HexRGB(0, 128, 0), + DarkGreen => HexRGB(0, 100, 0), + YellowGreen => HexRGB(154, 205, 50), + OliveDrab => HexRGB(107, 142, 35), + Olive => HexRGB(128, 128, 0), + DarkOliveGreen => HexRGB(85, 107, 47), + MediumAquamarine => HexRGB(102, 205, 170), + DarkSeaGreen => HexRGB(143, 188, 139), + LightSeaGreen => HexRGB(32, 178, 170), + DarkCyan => HexRGB(0, 139, 139), + Teal => HexRGB(0, 128, 128), + Aqua => HexRGB(0, 255, 255), + Cyan => HexRGB(0, 255, 255), + LightCyan => HexRGB(224, 255, 255), + PaleTurquoise => HexRGB(175, 238, 238), + Aquamarine => HexRGB(127, 255, 212), + Turquoise => HexRGB(64, 224, 208), + MediumTurquoise => HexRGB(72, 209, 204), + DarkTurquoise => HexRGB(0, 206, 209), + CadetBlue => HexRGB(95, 158, 160), + SteelBlue => HexRGB(70, 130, 180), + LightSteelBlue => HexRGB(176, 196, 222), + PowderBlue => HexRGB(176, 224, 230), + LightBlue => HexRGB(173, 216, 230), + SkyBlue => HexRGB(135, 206, 235), + LightSkyBlue => HexRGB(135, 206, 250), + DeepSkyBlue => HexRGB(0, 191, 255), + DodgerBlue => HexRGB(30, 144, 255), + CornflowerBlue => HexRGB(100, 149, 237), + RoyalBlue => HexRGB(65, 105, 225), + Blue => HexRGB(0, 0, 255), + MediumBlue => HexRGB(0, 0, 205), + DarkBlue => HexRGB(0, 0, 139), + Navy => HexRGB(0, 0, 128), + MidnightBlue => HexRGB(25, 25, 112), + Cornsilk => HexRGB(255, 248, 220), + BlanchedAlmond => HexRGB(255, 235, 205), + Bisque => HexRGB(255, 228, 196), + NavajoWhite => HexRGB(255, 222, 173), + Wheat => HexRGB(245, 222, 179), + BurlyWood => HexRGB(222, 184, 135), + Tan => HexRGB(210, 180, 140), + RosyBrown => HexRGB(188, 143, 143), + SandyBrown => HexRGB(244, 164, 96), + Goldenrod => HexRGB(218, 165, 32), + DarkGoldenrod => HexRGB(184, 134, 11), + Peru => HexRGB(205, 133, 63), + Chocolate => HexRGB(210, 105, 30), + SaddleBrown => HexRGB(139, 69, 19), + Sienna => HexRGB(160, 82, 45), + Brown => HexRGB(165, 42, 42), + Maroon => HexRGB(128, 0, 0), + White => HexRGB(255, 255, 255), + Snow => HexRGB(255, 250, 250), + HoneyDew => HexRGB(240, 255, 240), + MintCream => HexRGB(245, 255, 250), + Azure => HexRGB(240, 255, 255), + AliceBlue => HexRGB(240, 248, 255), + GhostWhite => HexRGB(248, 248, 255), + WhiteSmoke => HexRGB(245, 245, 245), + SeaShell => HexRGB(255, 245, 238), + Beige => HexRGB(245, 245, 220), + OldLace => HexRGB(253, 245, 230), + FloralWhite => HexRGB(255, 250, 240), + Ivory => HexRGB(255, 255, 240), + AntiqueWhite => HexRGB(250, 235, 215), + Linen => HexRGB(250, 240, 230), + LavenderBlush => HexRGB(255, 240, 245), + MistyRose => HexRGB(255, 228, 225), + Gainsboro => HexRGB(220, 220, 220), + LightGray => HexRGB(211, 211, 211), + Silver => HexRGB(192, 192, 192), + DarkGray => HexRGB(169, 169, 169), + Gray => HexRGB(128, 128, 128), + DimGray => HexRGB(105, 105, 105), + LightSlateGray => HexRGB(119, 136, 153), + SlateGray => HexRGB(112, 128, 144), + DarkSlateGray => HexRGB(47, 79, 79), + Black => HexRGB(0, 0, 0), + } + } + + pub fn from_named(name: &str) -> Option { + // todo use a faster search (e.g. hashmap, aho-corasick) + use Color::*; + Some(match name { + "indianred" => IndianRed, + "lightcoral" => LightCoral, + "salmon" => Salmon, + "darksalmon" => DarkSalmon, + "lightsalmon" => LightSalmon, + "crimson" => Crimson, + "red" => Red, + "firebrick" => FireBrick, + "darkred" => DarkRed, + "pink" => Pink, + "lightpink" => LightPink, + "hotpink" => HotPink, + "deeppink" => DeepPink, + "mediumvioletred" => MediumVioletRed, + "palevioletred" => PaleVioletRed, + "coral" => Coral, + "tomato" => Tomato, + "orangered" => OrangeRed, + "darkorange" => DarkOrange, + "orange" => Orange, + "gold" => Gold, + "yellow" => Yellow, + "lightyellow" => LightYellow, + "lemonchiffon" => LemonChiffon, + "lightgoldenrodyellow" => LightGoldenrodYellow, + "papayawhip" => PapayaWhip, + "Moccasin" => Moccasin, + "Peachpuff" => PeachPuff, + "palegoldenrod" => PaleGoldenrod, + "khaki" => Khaki, + "darkkhaki" => DarkKhaki, + "lavender" => Lavender, + "thistle" => Thistle, + "plum" => Plum, + "violet" => Violet, + "orchid" => Orchid, + "fuchsia" => Fuchsia, + "magenta" => Magenta, + "mediumorchid" => MediumOrchid, + "mediumpurple" => MediumPurple, + "rebeccapurple" => RebeccaPurple, + "blueviolet" => BlueViolet, + "darkviolet" => DarkViolet, + "darkorchid" => DarkOrchid, + "darkmagenta" => DarkMagenta, + "purple" => Purple, + "indigo" => Indigo, + "slateblue" => SlateBlue, + "darkslateblue" => DarkSlateBlue, + "mediumslateblue" => MediumSlateBlue, + "greenyellow" => GreenYellow, + "chartreuse" => Chartreuse, + "lawngreen" => LawnGreen, + "lime" => Lime, + "limegreen" => LimeGreen, + "palegreen" => PaleGreen, + "lightgreen" => LightGreen, + "mediumspringgreen" => MediumSpringGreen, + "springgreen" => SpringGreen, + "mediumseagreen" => MediumSeaGreen, + "seagreen" => SeaGreen, + "forestgreen" => ForestGreen, + "green" => Green, + "darkgreen" => DarkGreen, + "yellowgreen" => YellowGreen, + "olivedrab" => OliveDrab, + "olive" => Olive, + "darkolivegreen" => DarkOliveGreen, + "mediumaquamarine" => MediumAquamarine, + "darkseagreen" => DarkSeaGreen, + "lightseagreen" => LightSeaGreen, + "darkcyan" => DarkCyan, + "teal" => Teal, + "aqua" => Aqua, + "cyan" => Cyan, + "lightcyan" => LightCyan, + "paleturquoise" => PaleTurquoise, + "aquamarine" => Aquamarine, + "turquoise" => Turquoise, + "mediumturquoise" => MediumTurquoise, + "darkturquoise" => DarkTurquoise, + "cadetblue" => CadetBlue, + "steelblue" => SteelBlue, + "lightsteelblue" => LightSteelBlue, + "powderblue" => PowderBlue, + "lightblue" => LightBlue, + "skyblue" => SkyBlue, + "lightskyblue" => LightSkyBlue, + "deepskyblue" => DeepSkyBlue, + "dodgerblue" => DodgerBlue, + "cornflowerblue" => CornflowerBlue, + "royalblue" => RoyalBlue, + "blue" => Blue, + "mediumblue" => MediumBlue, + "darkblue" => DarkBlue, + "navy" => Navy, + "midnightblue" => MidnightBlue, + "cornsilk" => Cornsilk, + "blanchedalmond" => BlanchedAlmond, + "bisque" => Bisque, + "navajowhite" => NavajoWhite, + "wheat" => Wheat, + "burlywood" => BurlyWood, + "tan" => Tan, + "rosybrown" => RosyBrown, + "sandybrown" => SandyBrown, + "goldenrod" => Goldenrod, + "darkgoldenrod" => DarkGoldenrod, + "peru" => Peru, + "chocolate" => Chocolate, + "saddlebrown" => SaddleBrown, + "sienna" => Sienna, + "brown" => Brown, + "maroon" => Maroon, + "white" => White, + "snow" => Snow, + "honeydew" => HoneyDew, + "mintcream" => MintCream, + "azure" => Azure, + "aliceblue" => AliceBlue, + "ghostwhite" => GhostWhite, + "whitesmoke" => WhiteSmoke, + "seashell" => SeaShell, + "beige" => Beige, + "oldlace" => OldLace, + "floralwhite" => FloralWhite, + "ivory" => Ivory, + "antiquewhite" => AntiqueWhite, + "linen" => Linen, + "lavenderblush" => LavenderBlush, + "mistyrose" => MistyRose, + "gainsboro" => Gainsboro, + "lightgray" => LightGray, + "silver" => Silver, + "darkgray" => DarkGray, + "gray" => Gray, + "dimgray" => DimGray, + "lightslategray" => LightSlateGray, + "slategray" => SlateGray, + "darkslategray" => DarkSlateGray, + "black" => Black, + _ => return None, + }) + } +} + +impl fmt::Display for Color { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + use Color::*; + match self { + HexRGB(r, g, b) => write!(f, "#{:02x}{:02x}{:02x}", r, g, b), + HexRGBA(r, g, b, a) => write!(f, "#{:02x}{:02x}{:02x}{:02x}", r, g, b, a), + HSL(h, s, l) => write!(f, "hsl({}, {}%, {}%)", h, s, l), + HSLA(h, s, l, a) => write!(f, "hsla({}, {}%, {}%, {})", h, s, l, a), + IndianRed => write!(f, "indianred"), + LightCoral => write!(f, "lightcoral"), + Salmon => write!(f, "salmon"), + DarkSalmon => write!(f, "darksalmon"), + LightSalmon => write!(f, "lightsalmon"), + Crimson => write!(f, "crimson"), + Red => write!(f, "red"), + FireBrick => write!(f, "firebrick"), + DarkRed => write!(f, "darkred"), + Pink => write!(f, "pink"), + LightPink => write!(f, "lightpink"), + HotPink => write!(f, "hotpink"), + DeepPink => write!(f, "deeppink"), + MediumVioletRed => write!(f, "mediumvioletred"), + PaleVioletRed => write!(f, "palevioletred"), + Coral => write!(f, "coral"), + Tomato => write!(f, "tomato"), + OrangeRed => write!(f, "orangered"), + DarkOrange => write!(f, "darkorange"), + Orange => write!(f, "orange"), + Gold => write!(f, "gold"), + Yellow => write!(f, "yellow"), + LightYellow => write!(f, "lightyellow"), + LemonChiffon => write!(f, "lemonchiffon"), + LightGoldenrodYellow => write!(f, "lightgoldenrodyellow"), + PapayaWhip => write!(f, "papayawhip"), + Moccasin => write!(f, "Moccasin"), + PeachPuff => write!(f, "Peachpuff"), + PaleGoldenrod => write!(f, "palegoldenrod"), + Khaki => write!(f, "khaki"), + DarkKhaki => write!(f, "darkkhaki"), + Lavender => write!(f, "lavender"), + Thistle => write!(f, "thistle"), + Plum => write!(f, "plum"), + Violet => write!(f, "violet"), + Orchid => write!(f, "orchid"), + Fuchsia => write!(f, "fuchsia"), + Magenta => write!(f, "magenta"), + MediumOrchid => write!(f, "mediumorchid"), + MediumPurple => write!(f, "mediumpurple"), + RebeccaPurple => write!(f, "rebeccapurple"), + BlueViolet => write!(f, "blueviolet"), + DarkViolet => write!(f, "darkviolet"), + DarkOrchid => write!(f, "darkorchid"), + DarkMagenta => write!(f, "darkmagenta"), + Purple => write!(f, "purple"), + Indigo => write!(f, "indigo"), + SlateBlue => write!(f, "slateblue"), + DarkSlateBlue => write!(f, "darkslateblue"), + MediumSlateBlue => write!(f, "mediumslateblue"), + GreenYellow => write!(f, "greenyellow"), + Chartreuse => write!(f, "chartreuse"), + LawnGreen => write!(f, "lawngreen"), + Lime => write!(f, "lime"), + LimeGreen => write!(f, "limegreen"), + PaleGreen => write!(f, "palegreen"), + LightGreen => write!(f, "lightgreen"), + MediumSpringGreen => write!(f, "mediumspringgreen"), + SpringGreen => write!(f, "springgreen"), + MediumSeaGreen => write!(f, "mediumseagreen"), + SeaGreen => write!(f, "seagreen"), + ForestGreen => write!(f, "forestgreen"), + Green => write!(f, "green"), + DarkGreen => write!(f, "darkgreen"), + YellowGreen => write!(f, "yellowgreen"), + OliveDrab => write!(f, "olivedrab"), + Olive => write!(f, "olive"), + DarkOliveGreen => write!(f, "darkolivegreen"), + MediumAquamarine => write!(f, "mediumaquamarine"), + DarkSeaGreen => write!(f, "darkseagreen"), + LightSeaGreen => write!(f, "lightseagreen"), + DarkCyan => write!(f, "darkcyan"), + Teal => write!(f, "teal"), + Aqua => write!(f, "aqua"), + Cyan => write!(f, "cyan"), + LightCyan => write!(f, "lightcyan"), + PaleTurquoise => write!(f, "paleturquoise"), + Aquamarine => write!(f, "aquamarine"), + Turquoise => write!(f, "turquoise"), + MediumTurquoise => write!(f, "mediumturquoise"), + DarkTurquoise => write!(f, "darkturquoise"), + CadetBlue => write!(f, "cadetblue"), + SteelBlue => write!(f, "steelblue"), + LightSteelBlue => write!(f, "lightsteelblue"), + PowderBlue => write!(f, "powderblue"), + LightBlue => write!(f, "lightblue"), + SkyBlue => write!(f, "skyblue"), + LightSkyBlue => write!(f, "lightskyblue"), + DeepSkyBlue => write!(f, "deepskyblue"), + DodgerBlue => write!(f, "dodgerblue"), + CornflowerBlue => write!(f, "cornflowerblue"), + RoyalBlue => write!(f, "royalblue"), + Blue => write!(f, "blue"), + MediumBlue => write!(f, "mediumblue"), + DarkBlue => write!(f, "darkblue"), + Navy => write!(f, "navy"), + MidnightBlue => write!(f, "midnightblue"), + Cornsilk => write!(f, "cornsilk"), + BlanchedAlmond => write!(f, "blanchedalmond"), + Bisque => write!(f, "bisque"), + NavajoWhite => write!(f, "navajowhite"), + Wheat => write!(f, "wheat"), + BurlyWood => write!(f, "burlywood"), + Tan => write!(f, "tan"), + RosyBrown => write!(f, "rosybrown"), + SandyBrown => write!(f, "sandybrown"), + Goldenrod => write!(f, "goldenrod"), + DarkGoldenrod => write!(f, "darkgoldenrod"), + Peru => write!(f, "peru"), + Chocolate => write!(f, "chocolate"), + SaddleBrown => write!(f, "saddlebrown"), + Sienna => write!(f, "sienna"), + Brown => write!(f, "brown"), + Maroon => write!(f, "maroon"), + White => write!(f, "white"), + Snow => write!(f, "snow"), + HoneyDew => write!(f, "honeydew"), + MintCream => write!(f, "mintcream"), + Azure => write!(f, "azure"), + AliceBlue => write!(f, "aliceblue"), + GhostWhite => write!(f, "ghostwhite"), + WhiteSmoke => write!(f, "whitesmoke"), + SeaShell => write!(f, "seashell"), + Beige => write!(f, "beige"), + OldLace => write!(f, "oldlace"), + FloralWhite => write!(f, "floralwhite"), + Ivory => write!(f, "ivory"), + AntiqueWhite => write!(f, "antiquewhite"), + Linen => write!(f, "linen"), + LavenderBlush => write!(f, "lavenderblush"), + MistyRose => write!(f, "mistyrose"), + Gainsboro => write!(f, "gainsboro"), + LightGray => write!(f, "lightgray"), + Silver => write!(f, "silver"), + DarkGray => write!(f, "darkgray"), + Gray => write!(f, "gray"), + DimGray => write!(f, "dimgray"), + LightSlateGray => write!(f, "lightslategray"), + SlateGray => write!(f, "slategray"), + DarkSlateGray => write!(f, "darkslategray"), + Black => write!(f, "black"), + } + } +} + +fn hsl_to_rgb(h: f64, s: f64, l: f64) -> (f64, f64, f64) { + debug_assert!(h >= 0.0 && h < 360.0); + debug_assert!(s >= 0.0 && s <= 1.0); + debug_assert!(l >= 0.0 && l <= 1.0); + let c = (1.0 - (2.0 * l - 1.0).abs()) * s; + let x = c * (1.0 - ((h / 60.0) % 2.0 - 1.0).abs()); + let m = l - c * 0.5; + let (rp, gp, bp) = if h < 60.0 { + (c, x, 0.0) + } else if h < 120.0 { + (x, c, 0.0) + } else if h < 180.0 { + (0.0, c, x) + } else if h < 240.0 { + (0.0, x, c) + } else if h < 300.0 { + (x, 0.0, c) + } else { + (c, 0.0, x) + }; + (rp + m, gp + m, bp + m) +} + +pub fn parse_hex(hex: &str) -> Option { + match hex.len() { + 3 => { + let r = u8::from_str_radix(hex.get(0..1)?, 16).ok()?; + let g = u8::from_str_radix(hex.get(1..2)?, 16).ok()?; + let b = u8::from_str_radix(hex.get(2..3)?, 16).ok()?; + // #fff is equivalent to #ffffff + Some(Color::HexRGB(r << 4 | r, g << 4 | g, b << 4 | b)) + } + 6 => { + let r = u8::from_str_radix(hex.get(0..2)?, 16).ok()?; + let g = u8::from_str_radix(hex.get(2..4)?, 16).ok()?; + let b = u8::from_str_radix(hex.get(4..6)?, 16).ok()?; + Some(Color::HexRGB(r, g, b)) + } + 8 => { + let r = u8::from_str_radix(hex.get(0..2)?, 16).ok()?; + let g = u8::from_str_radix(hex.get(2..4)?, 16).ok()?; + let b = u8::from_str_radix(hex.get(4..6)?, 16).ok()?; + let a = u8::from_str_radix(hex.get(6..8)?, 16).ok()?; + Some(Color::HexRGBA(r, g, b, a)) + } + _ => None, + } +} + +#[test] +fn test_color_convert() { + let color = Color::HSL(60.0, 0.0, 100.0); + assert_eq!(color.to_rgb(), Color::HexRGB(255, 255, 255)); + let color = Color::HSL(0.0, 100.0, 50.0); + assert_eq!(color.to_rgb(), Color::HexRGB(255, 0, 0)); +} diff --git a/packages/core-macro/src/styles/mod.rs b/packages/core-macro/src/styles/mod.rs new file mode 100644 index 000000000..47c8259c0 --- /dev/null +++ b/packages/core-macro/src/styles/mod.rs @@ -0,0 +1,2044 @@ +//! A module to type styles. +// TODO most stuff here is on the stack, but there are a few heap-allocs here and there. It would +// be good if we could just to allocate them in the bump arena when using bumpalo. +mod calc; +mod codegen; +mod color; +pub mod string; +mod syn_parse; + +use std::{ + fmt, + ops::{Deref, DerefMut}, +}; + +pub use calc::*; +pub use color::{Color, DynamicColor}; +// pub use crate::{ +// calc::*, +// color::{Color, DynamicColor}, +// }; + +pub struct DynamicStyles { + pub rules: Vec, +} + +impl From> for DynamicStyles { + fn from(v: Vec) -> Self { + Self { rules: v } + } +} + +impl fmt::Display for DynamicStyles { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + for style in self + .rules + .iter() + .filter(|style| !(style.is_dynamic() || style.is_dummy())) + { + write!(f, "{};", style)?; + } + Ok(()) + } +} + +// TODO make container generic over heap (e.g. support bumpalo) +#[derive(Debug, Clone, PartialEq)] +pub struct Styles { + pub rules: Vec