use std::path::PathBuf;
use std::sync::Arc;
use anyhow::{Context, Result};
use async_std::task::{spawn, JoinHandle};
use nipper::Document;
use super::ATTR_HREF;
use super::{AssetFile, HashedFileOutput, LinkAttrs, TrunkLinkPipelineOutput};
use crate::config::RtcBuild;
pub struct Css {
id: usize,
cfg: Arc<RtcBuild>,
asset: AssetFile,
}
impl Css {
pub const TYPE_CSS: &'static str = "css";
pub async fn new(cfg: Arc<RtcBuild>, html_dir: Arc<PathBuf>, attrs: LinkAttrs, id: usize) -> Result<Self> {
let href_attr = attrs
.get(ATTR_HREF)
.context(r#"required attr `href` missing for <link data-trunk rel="css" .../> element"#)?;
let mut path = PathBuf::new();
path.extend(href_attr.split('/'));
let asset = AssetFile::new(&html_dir, path).await?;
Ok(Self { id, cfg, asset })
}
#[tracing::instrument(level = "trace", skip(self))]
pub fn spawn(self) -> JoinHandle<Result<TrunkLinkPipelineOutput>> {
spawn(self.run())
}
#[tracing::instrument(level = "trace", skip(self))]
async fn run(self) -> Result<TrunkLinkPipelineOutput> {
let rel_path = crate::common::strip_prefix(&self.asset.path);
tracing::info!(path = ?rel_path, "copying & hashing css");
let hashed_file_output = self.asset.copy_with_hash(&self.cfg.staging_dist).await?;
tracing::info!(path = ?rel_path, "finished copying & hashing css");
Ok(TrunkLinkPipelineOutput::Css(CssOutput {
cfg: self.cfg.clone(),
id: self.id,
file: hashed_file_output,
}))
}
}
pub struct CssOutput {
pub cfg: Arc<RtcBuild>,
pub id: usize,
pub file: HashedFileOutput,
}
impl CssOutput {
pub async fn finalize(self, dom: &mut Document) -> Result<()> {
dom.select(&super::trunk_id_selector(self.id)).replace_with_html(format!(
r#"<link rel="stylesheet" href="{base}{file}"/>"#,
base = &self.cfg.public_url,
file = self.file.file_name
));
Ok(())
}
}