Skip to content

assets crate #109

@akesson

Description

@akesson

Currently the builder adds the Asset code in each rust file generated by AssembleCmd. Refactor so that this code is shared in a assets crate and any users of the builder instead depends on assets.

The asset should serve as an abstraction for the storage of the asset and the different variants of it (translations & encodings).
It should be suited for:

  • web use (accept-encoding, accept-languages)
  • build system file copying: when served directly from a file system, the build system needs to be able to copy the file to a site structure.

The asset crate should define the following:

/// File encodings in order of preference
pub enum Encoding {
    Brotli,
    Gzip,
    /// uncompressed
    Identity
}


/// the file path parts allows constructing a full
/// path given encoding and optionally a language
pub struct FilePathParts {
   /// relative folder
   pub folder: Option<&'static str>,
   pub name: &'static str,
   pub hash: Option<&'static str>,
   pub ext: &'static str,
}

pub struct Asset {
     pub encoding: Encoding,
     pub mime: &'static str,
     pub lang: Option< LanguageIdentifier >,
     pub file_part_paths: FilePathParts,
     provider: &'static fn(&str) -> Option<Vec<u8>>,
}

impl Asset {
     pub fn data_for(&self) -> Vec<u8> {
         self.provider(self.file_path()).unwrap()
     }
     pub fn file_path(&self) -> String {
     }
}

/// Previously known as Asset
pub struct AssetSet {
    /// The absolute url path used to get this resource
    pub url_path: &'static str,
    pub file_path_parts: FilePathParts,
    /// All files (langs) are always encoded with all these encodings
    pub available_encodings: &'static [Encoding],
    pub available_languages: Option<&'static [LanguageIdentifier]>,
    pub mime: &'static str,
}

impl AssetSet {
   pub fn asset_for(&self, accept_encodings: &str, accept_languages: &str) -> Asset {
      // encoding and language negotiation with fallbacks
   }
}

/// For efficiently finding assets from a url
pub struct AssetCatalog {
   assets: BTreeMap<&'static str, &'static AssetSet>,
}

Depends on icu_locid and fluent_langneg which should be added as dependencies. No other dependencies should be needed.

The AssembleCommand should generate something like:

fn load(path: &str) -> Option<Vec<u8>> {
   //   implementation depending on the backing store
}

pub static STYLE = AssetSet {
    url_path: "/assets/style.jLsQ8S_Iyso=.css",
    file_path_parts: FilePathParts {
       folder: Some("assets/style"),
       name: "style",
       hash: Some("jLsQ8S_Iyso="),
       ext: "css",
    },
    available_encodings: &[Encoding::Identity, Encoding::Brotli],
    available_languages: None,
    mime: "text/css",
    store: &load,
}

Migration strategy:

  1. Create the crates/asset and implement what belongs there. No breakage.
  2. Add a .generate_asset_code(dest: &'str) to Output. No breakage.

For step 2:

Instead of parsing the site after the fact, collect asset metadata during the writing process:

  #[derive(Debug, Clone)]
  pub struct AssetMetadata {
      pub url_path: String,
      pub file_path_parts: FilePathParts,
      pub available_encodings: Vec<Encoding>,
      pub available_languages: Option<Vec<LanguageIdentifier>>,
      pub mime: String,
  }

  impl Output {
      // New method that accumulates asset metadata
      pub fn generate_asset_code(&mut self, dest: &str) {
          // This would be called after all file operations
          // to generate the asset code from collected metadata
      }
  }

  // Modified signatures to return metadata
  pub fn write_file_to_site(site_file: &SiteFile, bytes: &[u8], output: &[Output]) -> Vec<AssetMetadata> {
    ...
  }

  /// same for the other write functions used with the Output

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions