use data_url::DataUrl; use oxc::span::SourceType; #[derive(Debug, thiserror::Error)] pub(crate) enum DataModuleError { #[error("Invalid data module URL: {0}")] Url(#[from] data_url::DataUrlError), #[error("Unsupported data module MIME type: {0}")] Mime(String), #[error("Invalid base64 in data module: {0}")] Base64(#[from] data_url::forgiving_base64::InvalidBase64), } impl From for avril_core::Error { fn from(error: DataModuleError) -> Self { Self::Module(error.to_string()) } } pub(crate) struct DataModule<'a> { url: DataUrl<'a>, pub source_type: SourceType, } impl<'a> DataModule<'a> { pub fn parse(name: &'a str) -> Result { let url = DataUrl::process(name)?; let mime = url.mime_type(); let source_type = match (mime.type_.as_str(), mime.subtype.as_str()) { ("text" | "application", "typescript" | "x-typescript") => { SourceType::ts().with_module(true) } ( "text" | "application", "javascript" | "ecmascript" | "x-javascript" | "x-ecmascript", ) | ( "text", "javascript1.0" | "javascript1.1" | "javascript1.2" | "javascript1.3" | "javascript1.4" | "javascript1.5" | "jscript" | "livescript", ) => SourceType::mjs(), _ => { return Err(DataModuleError::Mime(format!( "{}/{}", mime.type_, mime.subtype ))); } }; Ok(Self { url, source_type }) } pub fn source(&self) -> Result { let (bytes, _) = self.url.decode_to_vec()?; // Module scripts are UTF-8 regardless of the MIME charset parameter. Ok(String::from_utf8_lossy(&bytes).into_owned()) } }