float_pigment_css/
lib.rs

1//! CSS parser with a style sheet manager.
2//!
3//! Note: it is not a full web-compatible CSS parser because it supports a subset of CSS selectors and properties.
4//!
5//! ### Main Workflow
6//!
7//! The CSS parser is designed to be used in high-level UI frameworks. The main workflow:
8//!
9//! 1. Create a `StyleSheetGroup`.
10//! 1. Parsing CSS text into a `StyleSheet` and added to the `StyleSheetGroup`.
11//! 1. Create a `StyleQuery`.
12//! 1. Run the `StyleQuery` with `StyleSheetGroup::query_matched_rules` and get a `MatchedRuleList`.
13//! 1. Create a `NodeProperties` with `NodeProperties::new`.
14//! 1. Merge the `MatchedRuleList` into `NodeProperties` with `MatchedRuleList::merge_node_properties`.
15//!
16//! The result `NodeProperties` contains all supported CSS properties.
17//!
18//! ### Supported CSS Features
19//!
20//! The supported selectors can be found in [StyleQuery] docs.
21//!
22//! The supported media features can be found in [MediaQueryStatus] docs.
23//!
24//! The supported style properties can be found in [SUPPORTED_CSS_PROPERTY_NAMES](crate::property::SUPPORTED_CSS_PROPERTY_NAMES) docs.
25//!
26//! ### The Binary Format
27//!
28//! The `StyleSheet` can be serialized into a specialized "bincode" format. (Note that it is not the same format as the `bincode` crate.)
29//! This binary format can be deserialized with great performance, so it can be used as the cache of static style sheet text.
30//! It also has compatibilities across different versions of this crate.
31
32#![cfg_attr(not(feature = "std"), no_std)]
33#![warn(missing_docs)]
34
35#[macro_use]
36extern crate alloc;
37#[macro_use]
38extern crate log;
39
40#[allow(unused_imports)]
41use alloc::{boxed::Box, vec::Vec};
42
43pub use fixed;
44pub use num_traits;
45#[cfg(feature = "wasm-entrance")]
46use wasm_bindgen::prelude::*;
47
48#[cfg(debug_assertions)]
49mod check_trait;
50mod group;
51mod path;
52pub use group::{StyleSheetGroup, StyleSheetImportIndex, StyleSheetResource, TEMP_SHEET_INDEX};
53pub mod sheet;
54pub use sheet::{LinkedStyleSheet, StyleSheet};
55pub mod property;
56pub mod query;
57mod resolve_font_size;
58pub mod typing;
59mod typing_stringify;
60pub use query::{EnvValues, MediaQueryStatus, StyleQuery};
61// #[cfg(not(target_arch = "wasm32"))]
62pub mod ffi;
63pub mod length_num;
64pub mod parser;
65
66#[cfg(debug_assertions)]
67use check_trait::CompatibilityCheck;
68
69#[cfg(all(target_arch = "wasm32", feature = "nodejs-package"))]
70fn init_logger() {
71    use std::sync::Once;
72    static INIT: Once = Once::new();
73    INIT.call_once(|| {
74        console_log::init_with_level(log::Level::Debug).unwrap();
75    });
76}
77
78#[doc(hidden)]
79#[cfg(all(target_arch = "wasm32", feature = "nodejs-package"))]
80#[wasm_bindgen(start)]
81pub fn wasm_main() {
82    init_logger();
83    console_error_panic_hook::set_once();
84}
85
86#[doc(hidden)]
87#[cfg(all(feature = "serialize", feature = "serialize_json"))]
88#[cfg_attr(
89    feature = "wasm-entrance",
90    wasm_bindgen(js_name = "compileStyleSheetToJson")
91)]
92pub fn compile_style_sheet_to_json(filename: &str, style_text: &str) -> String {
93    let (style_sheet, warnings) = parser::parse_style_sheet(filename, style_text);
94    for w in warnings {
95        warn!(
96            "{} (at {:?}, from line {:?} column {:?} to line {:?} column {:?})",
97            w.message.as_str(),
98            filename,
99            w.start_line,
100            w.start_col,
101            w.end_line,
102            w.end_col,
103        );
104    }
105    style_sheet.serialize_json()
106}
107
108/// Serialize CSS to the binary format.
109#[cfg(feature = "serialize")]
110#[cfg_attr(
111    feature = "wasm-entrance",
112    wasm_bindgen(js_name = "compileStyleSheetToBincode")
113)]
114pub fn compile_style_sheet_to_bincode(filename: &str, style_text: &str) -> Vec<u8> {
115    let (style_sheet, warnings) = parser::parse_style_sheet(filename, style_text);
116    for w in warnings {
117        warn!(
118            "{} (at {:?}, from line {:?} column {:?} to line {:?} column {:?})",
119            w.message.as_str(),
120            filename,
121            w.start_line,
122            w.start_col,
123            w.end_line,
124            w.end_col,
125        );
126    }
127    style_sheet.serialize_bincode()
128}
129
130/// Deserialize bincode from the binary format.
131#[cfg(feature = "deserialize")]
132#[cfg_attr(
133    feature = "wasm-entrance",
134    wasm_bindgen(js_name = "styleSheetFromBincode")
135)]
136pub fn style_sheet_from_bincode(bincode: Vec<u8>) -> StyleSheetGroup {
137    let ptr = Box::into_raw(bincode.into_boxed_slice());
138    let mut ssg = StyleSheetGroup::new();
139    let mut resource = StyleSheetResource::new();
140    unsafe {
141        resource.add_bincode_zero_copy("", ptr, move || drop(Box::from_raw(ptr)));
142    }
143    ssg.append_from_resource(&resource, "", None);
144    ssg
145}