trunk 0.7.1

Build, bundle & ship your Rust WASM application to the web.
//! Icon asset pipeline.

use std::path::PathBuf;
use std::sync::Arc;

use anyhow::{anyhow, Result};
use async_std::task::{spawn, JoinHandle};
use indicatif::ProgressBar;
use nipper::{Document, Selection};

use super::ATTR_HREF;
use super::{AssetFile, HashedFileOutput, TrunkLinkPipelineOutput};
use crate::config::RtcBuild;

/// An Icon asset pipeline.
pub struct Icon {
    /// The ID of this pipeline's source HTML element.
    id: usize,
    /// Runtime build config.
    cfg: Arc<RtcBuild>,
    /// The progress bar to use for this pipeline.
    progress: ProgressBar,
    /// The asset file being processed.
    asset: AssetFile,
}

impl Icon {
    pub const TYPE_ICON: &'static str = "icon";

    pub async fn new(cfg: Arc<RtcBuild>, progress: ProgressBar, html_dir: Arc<PathBuf>, el: Selection<'_>, id: usize) -> Result<Self> {
        // Build the path to the target asset.
        let href_attr = el
            .attr(ATTR_HREF)
            .ok_or_else(|| anyhow!("required attr `href` missing for <link data-trunk .../> element: {}", el.html()))?;
        let mut path = PathBuf::new();
        path.extend(href_attr.as_ref().split('/'));
        let asset = AssetFile::new(&html_dir, path).await?;
        Ok(Self { id, cfg, progress, asset })
    }

    /// Spawn the pipeline for this asset type.
    pub fn spawn(self) -> JoinHandle<Result<TrunkLinkPipelineOutput>> {
        spawn(async move {
            self.progress.set_message("copying & hashing icon");
            let hashed_file_output = self.asset.copy_with_hash(&self.cfg.dist).await?;
            self.progress.set_message("finished copying & hashing icon");
            Ok(TrunkLinkPipelineOutput::Icon(IconOutput {
                id: self.id,
                file: hashed_file_output,
            }))
        })
    }
}

/// The output of an Icon build pipeline.
pub struct IconOutput {
    /// The ID of this pipeline.
    pub id: usize,
    /// Data on the finalized output file.
    pub file: HashedFileOutput,
}

impl IconOutput {
    pub async fn finalize(self, dom: &mut Document) -> Result<()> {
        dom.select(&super::trunk_id_selector(self.id))
            .replace_with_html(format!(r#"<link rel="icon" href="{}"/>"#, self.file.file_name));
        Ok(())
    }
}