use lightningcss::bundler::{Bundler, FileProvider};
use lightningcss::printer::PrinterOptions;
use lightningcss::stylesheet::{MinifyOptions, ParserFlags, ParserOptions, StyleSheet};
use lightningcss::targets::Targets;
use std::path::Path;
use vize_carton::{FxHashMap, String, ToCompactString};
pub(crate) fn version_to_u32(major: u32) -> u32 {
major << 16
}
use super::CssModuleExport as VizeCssModuleExport;
pub(crate) struct CssInternalResult {
pub code: String,
pub errors: Vec<String>,
pub exports: Option<FxHashMap<String, VizeCssModuleExport>>,
}
pub(crate) fn compile_css_internal(
css: &str,
filename: &str,
minify: bool,
targets: Targets,
custom_media: bool,
css_modules: bool,
) -> CssInternalResult {
let mut flags = ParserFlags::NESTING | ParserFlags::DEEP_SELECTOR_COMBINATOR;
if custom_media {
flags |= ParserFlags::CUSTOM_MEDIA;
}
let css_modules_config = if css_modules {
Some(lightningcss::css_modules::Config {
pattern: lightningcss::css_modules::Pattern::default(),
..Default::default()
})
} else {
None
};
let parser_options = ParserOptions {
filename: filename.into(),
flags,
css_modules: css_modules_config,
..Default::default()
};
let mut stylesheet = match StyleSheet::parse(css, parser_options) {
Ok(ss) => ss,
Err(e) => {
let mut errors = Vec::with_capacity(1);
let mut message = String::from("CSS parse error: ");
message.push_str(&e.to_compact_string());
errors.push(message);
return CssInternalResult {
code: css.to_compact_string(),
errors,
exports: None,
};
}
};
if minify {
if let Err(e) = stylesheet.minify(lightningcss::stylesheet::MinifyOptions {
targets,
..Default::default()
}) {
let mut errors = Vec::with_capacity(1);
let mut message = String::from("CSS minify error: ");
use std::fmt::Write as _;
let _ = write!(&mut message, "{:?}", e);
errors.push(message);
return CssInternalResult {
code: css.to_compact_string(),
errors,
exports: None,
};
}
}
let printer_options = PrinterOptions {
minify,
targets,
..Default::default()
};
match stylesheet.to_css(printer_options) {
Ok(result) => {
let exports = result.exports.map(|export_map| {
export_map
.into_iter()
.map(|(original, export)| {
(
original.to_compact_string(),
VizeCssModuleExport {
name: export.name.to_compact_string(),
is_referenced: export.is_referenced,
},
)
})
.collect()
});
CssInternalResult {
code: result.code.into(),
errors: vec![],
exports,
}
}
Err(e) => {
let mut errors = Vec::with_capacity(1);
let mut message = String::from("CSS print error: ");
use std::fmt::Write as _;
let _ = write!(&mut message, "{:?}", e);
errors.push(message);
CssInternalResult {
code: css.to_compact_string(),
errors,
exports: None,
}
}
}
}
pub(crate) fn bundle_css_internal(
entry_path: &str,
minify: bool,
targets: Targets,
css_modules: bool,
custom_media: bool,
) -> CssInternalResult {
let mut flags = ParserFlags::NESTING | ParserFlags::DEEP_SELECTOR_COMBINATOR;
if custom_media {
flags |= ParserFlags::CUSTOM_MEDIA;
}
let css_modules_config = if css_modules {
Some(lightningcss::css_modules::Config {
pattern: lightningcss::css_modules::Pattern::default(),
..Default::default()
})
} else {
None
};
let parser_options = ParserOptions {
flags,
css_modules: css_modules_config,
..Default::default()
};
let fs = FileProvider::new();
let mut bundler = Bundler::new(&fs, None, parser_options);
let mut stylesheet = match bundler.bundle(Path::new(entry_path)) {
Ok(ss) => ss,
Err(e) => {
let mut message = String::from("CSS bundle error: ");
use std::fmt::Write as _;
let _ = write!(&mut message, "{:?}", e);
return CssInternalResult {
code: String::from(""),
errors: vec![message],
exports: None,
};
}
};
if minify {
if let Err(e) = stylesheet.minify(MinifyOptions {
targets,
..Default::default()
}) {
let mut message = String::from("CSS minify error: ");
use std::fmt::Write as _;
let _ = write!(&mut message, "{:?}", e);
return CssInternalResult {
code: String::from(""),
errors: vec![message],
exports: None,
};
}
}
let printer_options = PrinterOptions {
minify,
targets,
..Default::default()
};
match stylesheet.to_css(printer_options) {
Ok(result) => {
let exports = result.exports.map(|export_map| {
export_map
.into_iter()
.map(|(original, export)| {
(
original.to_compact_string(),
VizeCssModuleExport {
name: export.name.to_compact_string(),
is_referenced: export.is_referenced,
},
)
})
.collect()
});
CssInternalResult {
code: result.code.into(),
errors: vec![],
exports,
}
}
Err(e) => {
let mut message = String::from("CSS print error: ");
use std::fmt::Write as _;
let _ = write!(&mut message, "{:?}", e);
CssInternalResult {
code: String::from(""),
errors: vec![message],
exports: None,
}
}
}
}