initial os release. I really expect SO much bugs, guys. good luck =)
This commit is contained in:
commit
a6eac5275c
2 changed files with 7965 additions and 0 deletions
44
sabry_intrnl/src/config/manifest.rs
Normal file
44
sabry_intrnl/src/config/manifest.rs
Normal file
|
|
@ -0,0 +1,44 @@
|
|||
use std::{env, fs, io};
|
||||
|
||||
use serde::Deserialize;
|
||||
|
||||
use super::SabryConfig;
|
||||
|
||||
pub const MANIFEST: &str = "Cargo.toml";
|
||||
pub const MANIFEST_DIR_ENV: &str = "CARGO_MANIFEST_DIR";
|
||||
|
||||
pub fn read_manifest() -> Result<ValuableManifest, ManifestError> {
|
||||
let manpath = format!("{}/{MANIFEST}", env::var(MANIFEST_DIR_ENV)?);
|
||||
|
||||
Ok(toml::de::from_str(&fs::read_to_string(manpath)?)?)
|
||||
}
|
||||
|
||||
#[derive(Debug, thiserror::Error)]
|
||||
pub enum ManifestError {
|
||||
#[error("Could not read manifest path from env")]
|
||||
ManifestDirEnv(#[from] env::VarError),
|
||||
#[error("Could not read manifest file")]
|
||||
ManifestRead(#[from] io::Error),
|
||||
#[error("Could not deserialize manifest")]
|
||||
ManifestDe(#[from] toml::de::Error),
|
||||
}
|
||||
|
||||
/// Manifest structure that makes sense for sabry
|
||||
#[derive(Deserialize, Default)]
|
||||
pub struct ValuableManifest {
|
||||
pub package: Option<ValuableManifestPkg>,
|
||||
}
|
||||
|
||||
/// Manifest \[package.metadata\] structure that makes sense for sabry
|
||||
#[derive(Deserialize, Default)]
|
||||
pub struct ValuableManifestPkg {
|
||||
pub metadata: Option<ValuableManifestPkgMeta>,
|
||||
}
|
||||
|
||||
/// Manifest \[package.metadata.sabry\] structure that makes sense for sabry
|
||||
///
|
||||
/// Which is basically [SabryConfig]
|
||||
#[derive(Deserialize, Default)]
|
||||
pub struct ValuableManifestPkgMeta {
|
||||
pub sabry: Option<SabryConfig>,
|
||||
}
|
||||
253
sabry_intrnl/src/config/mod.rs
Normal file
253
sabry_intrnl/src/config/mod.rs
Normal file
|
|
@ -0,0 +1,253 @@
|
|||
pub mod manifest;
|
||||
use manifest::{ManifestError, ValuableManifest};
|
||||
use serde::Deserialize;
|
||||
|
||||
/// Sabry configuration, as it is from package.metadata.sabry
|
||||
#[derive(Default, Deserialize, Clone)]
|
||||
pub struct SabryConfig {
|
||||
#[serde(default = "SabryCssConfig::default")]
|
||||
pub css: SabryCssConfig,
|
||||
#[serde(default = "SabrySassConfig::default")]
|
||||
pub sass: SabrySassConfig,
|
||||
#[serde(default = "SabryHashConfig::default")]
|
||||
pub hash: SabryHashConfig,
|
||||
#[serde(default = "SabryGrassConfig::default")]
|
||||
pub grass: SabryGrassConfig,
|
||||
#[serde(default = "SabryLightCssConfig::default")]
|
||||
pub lightningcss: SabryLightCssConfig,
|
||||
}
|
||||
|
||||
impl SabryConfig {
|
||||
/// Require sabry configuration for the current project from every place in the code
|
||||
pub fn require() -> Result<Self, ManifestError> {
|
||||
let manifest = manifest::read_manifest()?;
|
||||
Ok(Self::from(&manifest))
|
||||
}
|
||||
}
|
||||
|
||||
impl From<&ValuableManifest> for SabryConfig {
|
||||
fn from(value: &ValuableManifest) -> Self {
|
||||
value
|
||||
.package
|
||||
.as_ref()
|
||||
.and_then(|p| p.metadata.as_ref())
|
||||
.and_then(|m| m.sabry.as_ref())
|
||||
.map_or(Self::default(), |sbr| sbr.clone())
|
||||
}
|
||||
}
|
||||
|
||||
/// Sabry `css` configuration table
|
||||
#[derive(Deserialize, Clone)]
|
||||
pub struct SabryCssConfig {
|
||||
pub bundle: Option<String>,
|
||||
pub scopes: Option<String>,
|
||||
pub bundle_prelude: Option<Vec<String>>,
|
||||
#[serde(default = "SabryCssConfig::default_minify")]
|
||||
pub minify: bool,
|
||||
}
|
||||
|
||||
impl SabryCssConfig {
|
||||
fn default_minify() -> bool {
|
||||
true
|
||||
}
|
||||
}
|
||||
|
||||
impl Default for SabryCssConfig {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
bundle: None,
|
||||
scopes: None,
|
||||
bundle_prelude: None,
|
||||
minify: Self::default_minify(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Sabry `sass` configuration table
|
||||
///
|
||||
/// (SASS/SCSS related config)
|
||||
#[derive(Deserialize, Clone)]
|
||||
pub struct SabrySassConfig {
|
||||
#[serde(default = "SabrySassConfig::default_scanroot")]
|
||||
pub scanroot: String,
|
||||
pub modules: Option<Vec<String>>,
|
||||
#[serde(default = "SabrySassConfig::default_intermediate_dir")]
|
||||
pub intermediate_dir: String,
|
||||
#[serde(default = "SabrySassConfig::default_module_name_collision")]
|
||||
pub module_name_collision: BehavSassModCollision,
|
||||
}
|
||||
|
||||
impl SabrySassConfig {
|
||||
fn default_scanroot() -> String {
|
||||
"src".into()
|
||||
}
|
||||
fn default_intermediate_dir() -> String {
|
||||
"target/.sabry/sass".into()
|
||||
}
|
||||
fn default_module_name_collision() -> BehavSassModCollision {
|
||||
BehavSassModCollision::default()
|
||||
}
|
||||
}
|
||||
|
||||
impl Default for SabrySassConfig {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
scanroot: Self::default_scanroot(),
|
||||
modules: None,
|
||||
intermediate_dir: Self::default_intermediate_dir(),
|
||||
module_name_collision: Self::default_module_name_collision(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Sabry `hash` configuration table
|
||||
#[derive(Deserialize, Clone)]
|
||||
pub struct SabryHashConfig {
|
||||
#[serde(default = "SabryHashConfig::default_size")]
|
||||
pub size: usize,
|
||||
#[serde(default = "SabryHashConfig::default_collision")]
|
||||
pub collision: BehavHashCollision,
|
||||
#[serde(default = "SabryHashConfig::default_use_scope_name")]
|
||||
pub use_scope_name: bool,
|
||||
#[serde(default = "SabryHashConfig::default_use_item_names")]
|
||||
pub use_item_names: bool,
|
||||
#[serde(default = "SabryHashConfig::default_use_code_size")]
|
||||
pub use_code_size: bool,
|
||||
#[serde(default = "SabryHashConfig::default_use_code_text")]
|
||||
pub use_code_text: bool,
|
||||
}
|
||||
|
||||
impl SabryHashConfig {
|
||||
fn default_size() -> usize {
|
||||
6
|
||||
}
|
||||
fn default_collision() -> BehavHashCollision {
|
||||
BehavHashCollision::default()
|
||||
}
|
||||
fn default_use_scope_name() -> bool {
|
||||
true
|
||||
}
|
||||
fn default_use_item_names() -> bool {
|
||||
false
|
||||
}
|
||||
fn default_use_code_size() -> bool {
|
||||
true
|
||||
}
|
||||
fn default_use_code_text() -> bool {
|
||||
false
|
||||
}
|
||||
}
|
||||
|
||||
impl Default for SabryHashConfig {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
size: Self::default_size(),
|
||||
collision: Self::default_collision(),
|
||||
use_scope_name: Self::default_use_scope_name(),
|
||||
use_code_size: Self::default_use_code_size(),
|
||||
use_code_text: Self::default_use_code_text(),
|
||||
use_item_names: Self::default_use_item_names(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// [grass] specific configuration for sabry
|
||||
#[derive(Default, Deserialize, Clone)]
|
||||
pub struct SabryGrassConfig {}
|
||||
|
||||
/// [lightningcss] specific configuration for sabry
|
||||
#[derive(Default, Deserialize, Clone)]
|
||||
pub struct SabryLightCssConfig {
|
||||
pub targets: SabryLightTargets,
|
||||
}
|
||||
|
||||
/// \[package.metadata.sabry.lightningcss.targets\] configuration.
|
||||
///
|
||||
/// This is a convenience layer under [lightningcss::targets::Browsers] structure accepted
|
||||
/// by lightningcss.
|
||||
///
|
||||
/// This structure is a part of [SabryConfig], which faces developer with more convenient
|
||||
/// `safari = "13.2"` syntax.
|
||||
#[derive(Default, Deserialize, Clone)]
|
||||
pub struct SabryLightTargets {
|
||||
pub android: Option<String>,
|
||||
pub chrome: Option<String>,
|
||||
pub edge: Option<String>,
|
||||
pub firefox: Option<String>,
|
||||
pub ie: Option<String>,
|
||||
pub ios_saf: Option<String>,
|
||||
pub opera: Option<String>,
|
||||
pub safari: Option<String>,
|
||||
pub samsung: Option<String>,
|
||||
}
|
||||
|
||||
impl SabryLightTargets {
|
||||
pub fn parse_ver(ver: &str) -> u32 {
|
||||
let mut vercode: u32 = 0;
|
||||
let vers = ver.split('.');
|
||||
for (i, dig) in vers.into_iter().enumerate() {
|
||||
let dignum = dig
|
||||
.parse::<u32>()
|
||||
.unwrap_or_else(|_| panic!("Invalid browser specifier: '{dig}'"));
|
||||
|
||||
let shift = 16 - 8 * i;
|
||||
vercode |= dignum << shift;
|
||||
}
|
||||
vercode
|
||||
}
|
||||
}
|
||||
|
||||
impl From<SabryLightTargets> for lightningcss::targets::Browsers {
|
||||
fn from(value: SabryLightTargets) -> Self {
|
||||
Self {
|
||||
android: value.android.map(|s| SabryLightTargets::parse_ver(&s)),
|
||||
chrome: value.chrome.map(|s| SabryLightTargets::parse_ver(&s)),
|
||||
edge: value.edge.map(|s| SabryLightTargets::parse_ver(&s)),
|
||||
firefox: value.firefox.map(|s| SabryLightTargets::parse_ver(&s)),
|
||||
ie: value.ie.map(|s| SabryLightTargets::parse_ver(&s)),
|
||||
ios_saf: value.ios_saf.map(|s| SabryLightTargets::parse_ver(&s)),
|
||||
opera: value.opera.map(|s| SabryLightTargets::parse_ver(&s)),
|
||||
safari: value.safari.map(|s| SabryLightTargets::parse_ver(&s)),
|
||||
samsung: value.samsung.map(|s| SabryLightTargets::parse_ver(&s)),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// \[package.metadata.sabry.sass\].module_name_collision option
|
||||
#[derive(Deserialize, Clone, Copy)]
|
||||
#[serde(rename_all = "lowercase")]
|
||||
pub enum BehavSassModCollision {
|
||||
Merge,
|
||||
Error,
|
||||
}
|
||||
|
||||
impl Default for BehavSassModCollision {
|
||||
fn default() -> Self {
|
||||
Self::Merge
|
||||
}
|
||||
}
|
||||
|
||||
/// \[package.metadata.sabry.hash\].collision option
|
||||
#[derive(Deserialize, Clone, Copy)]
|
||||
#[serde(rename_all = "lowercase")]
|
||||
pub enum BehavHashCollision {
|
||||
Error,
|
||||
Ignore,
|
||||
}
|
||||
|
||||
impl Default for BehavHashCollision {
|
||||
fn default() -> Self {
|
||||
Self::Ignore
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
use super::{manifest, SabryConfig};
|
||||
|
||||
#[test]
|
||||
fn empty_manifest_still_worth_a_read() {
|
||||
let manifest = manifest::read_manifest().unwrap();
|
||||
let _conf = SabryConfig::from(&manifest);
|
||||
}
|
||||
}
|
||||
Loading…
Reference in a new issue