1use crate::{InlineError, Result};
2use std::io::ErrorKind;
3
4pub trait StylesheetResolver: Send + Sync {
6 fn retrieve(&self, location: &str) -> Result<String> {
12 if location.starts_with("https") | location.starts_with("http") {
13 #[cfg(feature = "http")]
14 {
15 self.retrieve_from_url(location)
16 }
17
18 #[cfg(not(feature = "http"))]
19 {
20 Err(std::io::Error::new(
21 ErrorKind::Unsupported,
22 "Loading external URLs requires the `http` feature",
23 )
24 .into())
25 }
26 } else {
27 #[cfg(feature = "file")]
28 {
29 self.retrieve_from_path(location)
30 }
31 #[cfg(not(feature = "file"))]
32 {
33 Err(std::io::Error::new(
34 ErrorKind::Unsupported,
35 "Loading local files requires the `file` feature",
36 )
37 .into())
38 }
39 }
40 }
41 fn retrieve_from_url(&self, url: &str) -> Result<String> {
47 Err(self.unsupported(&format!("Loading external URLs is not supported: {url}")))
48 }
49 fn retrieve_from_path(&self, path: &str) -> Result<String> {
55 let path = path.trim_start_matches("file://");
56 std::fs::read_to_string(path).map_err(|error| match error.kind() {
57 ErrorKind::NotFound => InlineError::MissingStyleSheet {
58 path: path.to_string(),
59 },
60 #[cfg(target_family = "wasm")]
61 ErrorKind::Unsupported => self.unsupported(&format!(
62 "Loading local files is not supported on WASM: {path}"
63 )),
64 _ => InlineError::IO(error),
65 })
66 }
67 fn unsupported(&self, reason: &str) -> InlineError {
69 std::io::Error::new(ErrorKind::Unsupported, reason).into()
70 }
71}
72
73#[derive(Debug, Default)]
75pub struct DefaultStylesheetResolver;
76
77impl StylesheetResolver for DefaultStylesheetResolver {
78 #[cfg(feature = "http")]
79 fn retrieve_from_url(&self, url: &str) -> Result<String> {
80 let into_error = |error| InlineError::Network {
81 error,
82 location: url.to_string(),
83 };
84 reqwest::blocking::get(url)
85 .map_err(into_error)?
86 .text()
87 .map_err(into_error)
88 }
89}