inline_css/
lib.rs

1// Copyright (C) 2023 Benjamin Stürz
2//
3// This program is free software: you can redistribute it and/or modify
4// it under the terms of the GNU General Public License as published by
5// the Free Software Foundation, either version 3 of the License, or
6// (at your option) any later version.
7//
8// This program is distributed in the hope that it will be useful,
9// but WITHOUT ANY WARRANTY; without even the implied warranty of
10// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11// GNU General Public License for more details.
12//
13// You should have received a copy of the GNU General Public License
14// along with this program.  If not, see <http://www.gnu.org/licenses/>.
15//! Embed CSS directly into your Rust code.
16//!
17//! # Example
18//! ``` rust
19//! use inline_css::*;
20//!
21//! let x = 42;
22//!
23//! let css = css! {
24//!     h1 {
25//!         color: red;
26//!         background-color: #0x00ffff; // not #00ffff
27//!         padding: 10px;
28//!         margin-left: 10m; // not 10em
29//!         margin-right: -4%;
30//!     }
31//! };
32//!
33//! println!("{css}");
34//! ```
35//!
36//! # How to use
37//! Use the [`css! {..}`](crate::css) macro to embed CSS directly into your Rust code.
38//! During the compile-time of your Rust program, the content inside of your `css!` invocations
39//! will be checked and converted to an instance of [`CSS`](crate::CSS).
40//! This makes sure that all invocations of the `css!` macro are guaranteed to be valid CSS at runtime.
41//!
42//! ## Integration with inline-xml
43//! inline-css implements [`ToXml`](https://docs.rs/inline-xml/latest/inline_xml/trait.ToXml.html) for [`CSS`](crate::CSS) for integration with [`inline-xml`](https://docs.rs/inline-xml/latest/inline_xml).
44//!
45//! ### Example
46//! ``` rust,ignore
47//! extern crate inline_xml;
48//! use inline_xml::xml;
49//! use inline_css::css;
50//!
51//! let css = css! {
52//!     h1 {
53//!         color: red;
54//!     }
55//! };
56//!
57//! let html = xml! {
58//!     <html>
59//!         <head>
60//!             <style>{css}</style>
61//!         </head>
62//!         <body>
63//!             <h1>Hello World</h1>
64//!         </body>
65//!     </html>
66//! };
67//! ```
68//!
69//!
70//! ## Variants
71//! There are 3 macros:
72//! ### [`css!`](crate::css)
73//! Parse an entire snippet of [CSS](crate::CSS).
74//!
75//! ``` rust
76//! use inline_css::*;
77//!
78//! let rule: CSS = css! {
79//!     h1 {
80//!         color: red;
81//!     }
82//!
83//!     .button {
84//!         color: blue;
85//!     }
86//!
87//!     #text {
88//!         color: green;
89//!     }
90//! };
91//! ```
92//!
93//! ### [`css_rule!`](crate::css_rule)
94//! Parse a single CSS [Rule](crate::Rule).
95//!
96//! ``` rust
97//! use inline_css::*;
98//!
99//! let rule: Rule = css_rule! {
100//!     h1 {
101//!         color: red;
102//!     }
103//! };
104//! ```
105//! ### [`css_value!`](crate::css_value)
106//! Parse a CSS [Value](crate::Value).
107//!
108//! ``` rust
109//! use inline_css::*;
110//!
111//! let value: Value = css_value! { 10px };
112//! ```
113//!
114//! # Dynamic Data
115//! You can include dynamically-generated data into the `css!` macro invocation.
116//!
117//! Only types implementing `Into<Value>` are supported.
118//!
119//! ## Example
120//! ``` rust
121//! use inline_css::*;
122//!
123//! let x = 42;
124//! let css = css! {
125//!     h1 {
126//!         attr: {x + 1};
127//!     }
128//! };
129//! ```
130
131mod fmt;
132#[cfg(feature = "inline-xml")]
133mod xml;
134#[cfg(test)]
135mod tests;
136mod impls;
137
138/// Parse an entire snippet of [CSS](crate::CSS).
139///
140/// See the [crate-level documentation](crate#css).
141pub use inline_css_macros::css;
142
143/// Parse a CSS [Rule](crate::Rule).
144///
145/// See the [crate-level documentation](crate#css_rule).
146pub use inline_css_macros::css_rule;
147
148/// Parse a CSS [Value](crate::Value).
149///
150/// See the [crate-level documentation](crate#css_value).
151pub use inline_css_macros::css_value;
152
153/// CSS holds an entire snippet of CSS.
154///
155/// See the [crate-level documentation](crate#css).
156#[derive(Debug, Clone, PartialEq)]
157pub struct CSS(pub Vec<Rule>);
158
159/// A single CSS rule.
160///
161/// See the [crate-level documentation](crate#css_rule).
162#[derive(Debug, Clone, PartialEq)]
163pub struct Rule {
164    pub selector: Selector,
165    pub declarations: Vec<Declaration>,
166}
167
168/// A CSS selector.
169#[derive(Debug, Clone, PartialEq)]
170pub enum Selector {
171    Any,
172    Simple {
173        ty: Option<String>,
174        class: Option<String>,
175        id: Option<String>,
176    },
177    Colon {
178        name: String,
179        arg: Option<Value>,
180    },
181    Sub {
182        left: Box<Selector>,
183        right: Box<Selector>,
184    },
185    Gt {
186        left: Box<Selector>,
187        right: Box<Selector>,
188    },
189    Plus {
190        left: Box<Selector>,
191        right: Box<Selector>,
192    },
193    Tilde {
194        left: Box<Selector>,
195        right: Box<Selector>,
196    },
197    Comma {
198        left: Box<Selector>,
199        right: Box<Selector>,
200    },
201}
202
203/// A CSS declaration.
204#[derive(Debug, Clone, PartialEq)]
205pub struct Declaration {
206    pub name: String,
207    pub value: Vec<Value>,
208}
209
210/// A CSS value.
211///
212/// See the [crate-level documentation](crate#css_value).
213#[derive(Debug, Clone, PartialEq)]
214pub enum Value {
215    ColorCode(u32),
216    Ident(String),
217    Int(i32, String),
218    Float(f32, String),
219    Function {
220        name: String,
221        args: Vec<Value>,
222    }
223}