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}