polished_css_macros/lib.rs
1extern crate proc_macro;
2
3mod attribute;
4mod derive;
5mod utils;
6
7use proc_macro::TokenStream;
8use syn::{parse_macro_input, DeriveInput, ItemImpl};
9
10// Derive proc macros
11
12/// Implements a Rust's std trait - `Default`.
13///
14/// ### Used on
15///
16/// - properties
17///
18/// ### Usage
19///
20/// It attemps to follow the [CSSWG specification defaulting](https://www.w3.org/TR/css-cascade-5/#defaulting).\
21/// However due to possible differences between browsers, the [initial values
22/// provided by MDN is used on this crate](https://developer.mozilla.org/en-US/docs/Web/CSS/initial_value).
23#[proc_macro_derive(Default, attributes(default))]
24pub fn default(input: TokenStream) -> TokenStream {
25 let ast = parse_macro_input!(input as DeriveInput);
26 derive::r#trait::impl_default(&ast).into()
27}
28
29/// Implements a Rust's std trait - `Deref`.
30///
31/// ### Used on
32///
33/// Any single tuple structs defined in `styles` crate
34#[proc_macro_derive(Deref, attributes(data_type))]
35pub fn deref(input: TokenStream) -> TokenStream {
36 let ast = parse_macro_input!(input as DeriveInput);
37 derive::r#trait::impl_deref(&ast).into()
38}
39
40/// Implements a Rust's std trait - `Display`.
41///
42/// ### Used on
43///
44/// Any single tuple structs defined in `styles` crate
45///
46/// ### Usage
47///
48/// It supports three cases:
49///
50/// 1. **single tuple struct** - uses `self.0`
51/// 2. **enum unit variants** - each variant will displayed in `kebab-case`
52/// 3. **enum tuple _(single)_ variants** - uses `self.0` on associated values
53#[proc_macro_derive(Display, attributes(display))]
54pub fn display(input: TokenStream) -> TokenStream {
55 let ast = parse_macro_input!(input as DeriveInput);
56 derive::r#trait::impl_display(&ast).into()
57}
58
59/// Implements a custom trait - `Atomic`
60///
61/// ### Used on
62///
63/// - properties
64///
65/// ### Purpose
66///
67/// It does two things:
68/// 1. Implements a trait by generating `Style` with a single rule only _(following the [Atomic CSS
69/// approcach](https://css-tricks.com/lets-define-exactly-atomic-css/)) - based on the property's name, and the value stored
70/// 2. Improves the ergonomic of usage with `yew` _(under the feature flag)_ -
71/// `Into<yew::Classes>`
72#[proc_macro_derive(Atomic, attributes(atomic))]
73pub fn atomic(input: TokenStream) -> TokenStream {
74 let ast = parse_macro_input!(input as DeriveInput);
75 derive::r#trait::impl_atomic(&ast).into()
76}
77
78/// Implements a custom trait - `UnitDataTypeContainer`
79///
80/// ### Used on
81///
82/// - properties
83/// - data types
84///
85/// ### Purpose
86///
87/// Quickly implements a trait.
88#[proc_macro_derive(UnitDataTypeContainer)]
89pub fn unit_data_type_container(input: TokenStream) -> TokenStream {
90 let ast = parse_macro_input!(input as DeriveInput);
91 derive::r#trait::impl_unit_data_type_container(&ast).into()
92}
93
94/// Implements a custom trait - `Property`
95///
96/// ### Used on
97///
98/// - properties
99///
100/// ### Purpose
101///
102/// Implements a trait and other utilities, such as `Nothing` as value, CSS-wide
103/// functions, etc.
104#[proc_macro_derive(Property, attributes(property))]
105pub fn property(input: TokenStream) -> TokenStream {
106 let ast = parse_macro_input!(input as DeriveInput);
107 derive::property::r#trait::impl_property(&ast).into()
108}
109
110/// Implements a custom trait - `PropertyName`
111///
112/// ### Used on
113///
114/// - properties
115///
116/// ### Purpose
117///
118/// Quickly implements a trait based on the property struct name in
119/// `kebab-case` - is needed for the correct usage of `Display` trait.
120#[proc_macro_derive(PropertyName, attributes(property))]
121pub fn property_name(input: TokenStream) -> TokenStream {
122 let ast = parse_macro_input!(input as DeriveInput);
123 derive::property::r#trait::impl_property_name(&ast).into()
124}
125
126/// Creates an enum - `<Property>Value`
127///
128/// ### Used on
129///
130/// - properties
131///
132/// ### Purpose
133///
134/// Creates an enum with allowed data types and keywords for targetted property.
135#[proc_macro_derive(PropertyValue, attributes(property))]
136pub fn property_value(input: TokenStream) -> TokenStream {
137 let ast = parse_macro_input!(input as DeriveInput);
138 derive::property::r#enum::create_property_value_enum(&ast).into()
139}
140
141/// Adds an `impl` on the `<Property>Value`
142///
143/// ### Used on
144///
145/// - properties
146///
147/// ### Purpose
148///
149/// Creates an `impl` for the enum _(`<PropertyValue>Value`)_, with methods for
150/// the keywords _(for the ergonomic usage)_ - if the property has any keywords.
151/// Also, implements those units traits on data types
152#[proc_macro_derive(PropertyImpl, attributes(property))]
153pub fn property_impl(input: TokenStream) -> TokenStream {
154 let ast = parse_macro_input!(input as DeriveInput);
155 derive::property::r#enum::r#impl::create_property_impl(&ast).into()
156}
157
158/// Implements a Rust's std trait - `From`.
159///
160/// ### Used on
161///
162/// - properties
163///
164/// ### Usage
165///
166/// Based on property allowed data type(s), it implements this trait to set as
167/// its unit data type value _(using `UnitDataTypeContainer`)_
168#[proc_macro_derive(PropertyFromDataType, attributes(property))]
169pub fn property_from_data_type(input: TokenStream) -> TokenStream {
170 let ast = parse_macro_input!(input as DeriveInput);
171 derive::property::r#trait::impl_from_data_type(&ast).into()
172}
173
174/// Creates a custom trait for CSS unit `<name>Value`
175///
176/// ### Used on
177///
178/// - units
179///
180/// ### Purpose
181///
182/// Quickly generates a trait with bounds and the "contstructor" method, to use
183/// on any data type that relies on this targetted unit.
184#[proc_macro_derive(UnitTrait, attributes(unit))]
185pub fn create_unit_trait(input: TokenStream) -> TokenStream {
186 let ast = parse_macro_input!(input as DeriveInput);
187 derive::unit::r#trait::create_trait(&ast).into()
188}
189
190/// Implements a Rust's std trait - `From`.
191///
192/// ### Used on
193///
194/// - data types
195///
196/// ### Usage
197///
198/// Based on data type allowed units from its own enum, it implements the `From`
199/// trait from those units structs. And the custom trait `<unit>Storage` from
200/// each variant.
201#[proc_macro_derive(DataTypeFromUnits, attributes(data_type))]
202pub fn data_type_from_units(input: TokenStream) -> TokenStream {
203 let ast = parse_macro_input!(input as DeriveInput);
204 derive::data_type::r#trait::impl_from_units_traits(&ast).into()
205}
206
207/// Implements a custom trait - `<data type name>Storage`.
208///
209/// ### Used on
210///
211/// - data types
212///
213/// ### Usage
214///
215/// Based on data type allowed units from its own enum,
216/// it implements the `<data type name>Storage` trait from each variant.
217#[proc_macro_derive(ImplDataTypeTraits, attributes(data_type))]
218pub fn impl_data_type_traits(input: TokenStream) -> TokenStream {
219 let ast = parse_macro_input!(input as DeriveInput);
220 derive::data_type::r#trait::impl_data_type_traits(&ast).into()
221}
222
223/// Implements a Rust's std trait - `From`.
224///
225/// ### Used on
226///
227/// - data types
228///
229/// ### Purpose
230///
231/// Based on data type allowed data types from its own enum, it implements the
232/// `From` trait from those units structs. And the trait for each variant with
233/// associated value.
234#[proc_macro_derive(DataTypeFromDataTypes, attributes(data_type))]
235pub fn data_type_from_data_types(input: TokenStream) -> TokenStream {
236 let ast = parse_macro_input!(input as DeriveInput);
237 derive::data_type::r#trait::impl_from_data_types_traits(&ast).into()
238}
239
240/// Creates a custom trait from enum - `<name>Storage`.
241///
242/// ### Used on
243///
244/// - data types
245///
246/// ### Purpose
247///
248/// Based on **enum with field variants only**, creates a trait `<name>Storage`
249/// with methods for each variant to construct self with targetted variant.
250#[proc_macro_derive(TraitFromEnum, attributes(data_type))]
251pub fn trait_from_enum(input: TokenStream) -> TokenStream {
252 let ast = parse_macro_input!(input as DeriveInput);
253 derive::data_type::r#trait::create_trait_from_enum(&ast).into()
254}
255
256/// Creates a custom trait `<DataType>Storage`
257///
258/// ### Used on
259///
260/// - data types
261///
262/// ### Purpose
263///
264/// Based on the provided data type `impl`:
265///
266/// - creates a **constructor** method, for the data types _(if is combined)_,
267/// - implement methods from the targetted data types for the ergonomic usage
268/// with properties
269#[proc_macro_attribute]
270pub fn create_trait_from_enum_impl(args: TokenStream, input: TokenStream) -> TokenStream {
271 let unparsed_input = input.clone();
272 let ast = parse_macro_input!(unparsed_input as ItemImpl);
273 let trait_impl: TokenStream =
274 attribute::data_type::create_trait_from_enum_impl(args.into(), &ast).into();
275 [input, trait_impl].into_iter().collect()
276}