use crate::css_modules::hash;
use crate::printer::PrinterOptions;
use crate::rules::import::ImportRule;
use crate::traits::ToCss;
use crate::values::url::Url;
#[cfg(feature = "visitor")]
use crate::visitor::Visit;
use cssparser::SourceLocation;
#[cfg(any(feature = "serde", feature = "nodejs"))]
use serde::Serialize;
#[derive(Default)]
pub struct DependencyOptions {
pub remove_imports: bool,
}
#[derive(Debug)]
#[cfg_attr(any(feature = "serde", feature = "nodejs"), derive(Serialize))]
#[cfg_attr(
any(feature = "serde", feature = "nodejs"),
serde(tag = "type", rename_all = "lowercase")
)]
pub enum Dependency {
Import(ImportDependency),
Url(UrlDependency),
}
#[derive(Debug)]
#[cfg_attr(any(feature = "serde", feature = "nodejs"), derive(Serialize))]
pub struct ImportDependency {
pub url: String,
pub placeholder: String,
pub supports: Option<String>,
pub media: Option<String>,
pub loc: SourceRange,
}
impl ImportDependency {
pub fn new(rule: &ImportRule, filename: &str) -> ImportDependency {
let supports = if let Some(supports) = &rule.supports {
let s = supports.to_css_string(PrinterOptions::default()).unwrap();
Some(s)
} else {
None
};
let media = if !rule.media.media_queries.is_empty() {
let s = rule.media.to_css_string(PrinterOptions::default()).unwrap();
Some(s)
} else {
None
};
let placeholder = hash(&format!("{}_{}", filename, rule.url), false);
ImportDependency {
url: rule.url.as_ref().to_owned(),
placeholder,
supports,
media,
loc: SourceRange::new(
filename,
Location {
line: rule.loc.line + 1,
column: rule.loc.column,
},
8,
rule.url.len() + 2,
), }
}
}
#[derive(Debug)]
#[cfg_attr(any(feature = "serde", feature = "nodejs"), derive(Serialize))]
pub struct UrlDependency {
pub url: String,
pub placeholder: String,
pub loc: SourceRange,
}
impl UrlDependency {
pub fn new(url: &Url, filename: &str) -> UrlDependency {
let placeholder = hash(&format!("{}_{}", filename, url.url), false);
UrlDependency {
url: url.url.to_string(),
placeholder,
loc: SourceRange::new(filename, url.loc, 4, url.url.len()),
}
}
}
#[derive(Debug)]
#[cfg_attr(any(feature = "serde", feature = "nodejs"), derive(Serialize))]
#[cfg_attr(any(feature = "serde", feature = "nodejs"), serde(rename_all = "camelCase"))]
pub struct SourceRange {
pub file_path: String,
pub start: Location,
pub end: Location,
}
#[derive(Debug, Clone, Copy, PartialEq)]
#[cfg_attr(feature = "visitor", derive(Visit))]
#[cfg_attr(any(feature = "serde", feature = "nodejs"), derive(serde::Serialize))]
#[cfg_attr(any(feature = "serde"), derive(serde::Deserialize))]
#[cfg_attr(feature = "jsonschema", derive(schemars::JsonSchema))]
#[cfg_attr(feature = "into_owned", derive(static_self::IntoOwned))]
pub struct Location {
pub line: u32,
pub column: u32,
}
impl From<SourceLocation> for Location {
fn from(loc: SourceLocation) -> Location {
Location {
line: loc.line + 1,
column: loc.column,
}
}
}
impl SourceRange {
fn new(filename: &str, loc: Location, offset: u32, len: usize) -> SourceRange {
SourceRange {
file_path: filename.into(),
start: Location {
line: loc.line,
column: loc.column + offset,
},
end: Location {
line: loc.line,
column: loc.column + offset + (len as u32) - 1,
},
}
}
}