use crate::{InlineError, Result};
use std::io::ErrorKind;
pub trait StylesheetResolver: Send + Sync {
fn retrieve(&self, location: &str) -> Result<String> {
if location.starts_with("https") | location.starts_with("http") {
#[cfg(feature = "http")]
{
self.retrieve_from_url(location)
}
#[cfg(not(feature = "http"))]
{
Err(std::io::Error::new(
ErrorKind::Unsupported,
"Loading external URLs requires the `http` feature",
)
.into())
}
} else {
#[cfg(feature = "file")]
{
self.retrieve_from_path(location)
}
#[cfg(not(feature = "file"))]
{
Err(std::io::Error::new(
ErrorKind::Unsupported,
"Loading local files requires the `file` feature",
)
.into())
}
}
}
fn retrieve_from_url(&self, url: &str) -> Result<String> {
Err(self.unsupported(&format!("Loading external URLs is not supported: {url}")))
}
fn retrieve_from_path(&self, path: &str) -> Result<String> {
let path = path.trim_start_matches("file://");
std::fs::read_to_string(path).map_err(|error| match error.kind() {
ErrorKind::NotFound => InlineError::MissingStyleSheet {
path: path.to_string(),
},
#[cfg(target_family = "wasm")]
ErrorKind::Unsupported => self.unsupported(&format!(
"Loading local files is not supported on WASM: {path}"
)),
_ => InlineError::IO(error),
})
}
fn unsupported(&self, reason: &str) -> InlineError {
std::io::Error::new(ErrorKind::Unsupported, reason).into()
}
}
#[derive(Debug, Default)]
pub struct DefaultStylesheetResolver;
impl StylesheetResolver for DefaultStylesheetResolver {
#[cfg(feature = "http")]
fn retrieve_from_url(&self, url: &str) -> Result<String> {
let into_error = |error| InlineError::Network {
error,
location: url.to_string(),
};
reqwest::blocking::get(url)
.map_err(into_error)?
.text()
.map_err(into_error)
}
}