From 4f1ee65e6cd6533507e4ec7f2f29122e9aca48d9 Mon Sep 17 00:00:00 2001 From: mrvillage Date: Fri, 30 Aug 2024 17:29:59 -0400 Subject: [PATCH] Add hash files support to 0.7 (#2894) * Add support for JS and WASM file name hashing * Add `` * Update `` * Whoops * Fix formatting * My IDE is just refusing to work apparently * I hate my IDE * Don't run the doctest * Just remove the example, I don't know enough about doctest for this --- leptos/src/hydration/mod.rs | 40 ++++++++++++++++++++++++------- meta/src/stylesheet.rs | 47 +++++++++++++++++++++++++++++++++++-- 2 files changed, 77 insertions(+), 10 deletions(-) diff --git a/leptos/src/hydration/mod.rs b/leptos/src/hydration/mod.rs index 21d10b9e8..db5ced938 100644 --- a/leptos/src/hydration/mod.rs +++ b/leptos/src/hydration/mod.rs @@ -39,12 +39,36 @@ pub fn HydrationScripts( options: LeptosOptions, #[prop(optional)] islands: bool, ) -> impl IntoView { - let pkg_path = &options.site_pkg_dir; - let output_name = &options.output_name; - let mut wasm_output_name = output_name.clone(); - if std::option_env!("LEPTOS_OUTPUT_NAME").is_none() { - wasm_output_name.push_str("_bg"); + let mut js_file_name = options.output_name.to_string(); + let mut wasm_file_name = options.output_name.to_string(); + if options.hash_files { + let hash_path = std::env::current_exe() + .map(|path| { + path.parent().map(|p| p.to_path_buf()).unwrap_or_default() + }) + .unwrap_or_default() + .join(&options.hash_file); + if hash_path.exists() { + let hashes = std::fs::read_to_string(&hash_path) + .expect("failed to read hash file"); + for line in hashes.lines() { + let line = line.trim(); + if !line.is_empty() { + if let Some((file, hash)) = line.split_once(':') { + if file == "js" { + js_file_name.push_str(&format!(".{}", hash)); + } else if file == "wasm" { + wasm_file_name.push_str(&format!(".{}", hash)); + } + } + } + } + } + } else if std::option_env!("LEPTOS_OUTPUT_NAME").is_none() { + wasm_file_name.push_str("_bg"); } + + let pkg_path = &options.site_pkg_dir; #[cfg(feature = "nonce")] let nonce = crate::nonce::use_nonce(); #[cfg(not(feature = "nonce"))] @@ -59,16 +83,16 @@ pub fn HydrationScripts( }; view! { - + } } diff --git a/meta/src/stylesheet.rs b/meta/src/stylesheet.rs index 92394c52e..0dbca1b92 100644 --- a/meta/src/stylesheet.rs +++ b/meta/src/stylesheet.rs @@ -1,7 +1,7 @@ use crate::register; use leptos::{ - attr::global::GlobalAttributes, component, tachys::html::element::link, - IntoView, + attr::global::GlobalAttributes, component, prelude::LeptosOptions, + tachys::html::element::link, IntoView, }; /// Injects an [`HTMLLinkElement`](https://developer.mozilla.org/en-US/docs/Web/API/HTMLLinkElement) into the document @@ -34,3 +34,46 @@ pub fn Stylesheet( // TODO additional attributes register(link().id(id).rel("stylesheet").href(href)) } + +/// Injects an [`HTMLLinkElement`](https://developer.mozilla.org/en-US/docs/Web/API/HTMLLinkElement) into the document head that loads a `cargo-leptos`-hashed stylesheet. +#[component] +pub fn HashedStylesheet( + /// Leptos options + options: LeptosOptions, + /// An ID for the stylesheet. + #[prop(optional, into)] + id: Option, +) -> impl IntoView { + let mut css_file_name = options.output_name.to_string(); + if options.hash_files { + let hash_path = std::env::current_exe() + .map(|path| { + path.parent().map(|p| p.to_path_buf()).unwrap_or_default() + }) + .unwrap_or_default() + .join(&options.hash_file); + if hash_path.exists() { + let hashes = std::fs::read_to_string(&hash_path) + .expect("failed to read hash file"); + for line in hashes.lines() { + let line = line.trim(); + if !line.is_empty() { + if let Some((file, hash)) = line.split_once(':') { + if file == "css" { + css_file_name.push_str(&format!(".{}", hash)); + } + } + } + } + } + } + css_file_name.push_str(".css"); + let pkg_path = &options.site_pkg_dir; + // TODO additional attributes + register( + link() + .id(id) + .rel("stylesheet") + .href(format!("/{pkg_path}/{css_file_name}")), + ) +}