diff --git a/pagetop-mdbook/Cargo.toml b/pagetop-mdbook/Cargo.toml index 711af59b..faa155b8 100644 --- a/pagetop-mdbook/Cargo.toml +++ b/pagetop-mdbook/Cargo.toml @@ -19,4 +19,4 @@ static-files = "0.2.3" maud = { git = "https://github.com/lambda-fairy/maud", rev = "e6787cd6" } [build-dependencies] -static-files = "0.2.3" +pagetop = { path = "../pagetop" } diff --git a/pagetop-mdbook/build.rs b/pagetop-mdbook/build.rs index c5425024..355abfb1 100644 --- a/pagetop-mdbook/build.rs +++ b/pagetop-mdbook/build.rs @@ -1,17 +1,5 @@ -use static_files::resource_dir; - -use std::env; -use std::path::Path; +use pagetop::util::bundle_resources; fn main() -> std::io::Result<()> { - build_resource_dir("./static", "mdbook") -} - -fn build_resource_dir(dir: &str, name: &str) -> std::io::Result<()> { - let mut resource = resource_dir(dir); - resource.with_generated_filename( - Path::new(env::var("OUT_DIR").unwrap().as_str()).join(format!("{}.rs", name)), - ); - resource.with_module_name(format!("resources_{}", name)); - resource.build() + bundle_resources("./static", "mdbook", None) } diff --git a/pagetop-mdbook/src/lib.rs b/pagetop-mdbook/src/lib.rs index 577ac0a4..eeb4d483 100644 --- a/pagetop-mdbook/src/lib.rs +++ b/pagetop-mdbook/src/lib.rs @@ -1,11 +1,11 @@ use pagetop::prelude::*; +pub mod util; + pub_const_handler!(MODULE_MDBOOK); include!(concat!(env!("OUT_DIR"), "/mdbook.rs")); -pub type BookMapResources = std::collections::HashMap<&'static str, static_files::Resource>; - pub struct MdBook; impl ModuleTrait for MdBook { @@ -15,14 +15,14 @@ impl ModuleTrait for MdBook { } impl MdBook { - pub fn configure_mdbook_common(cfg: &mut app::web::ServiceConfig) { - theme_static_files!(cfg, "/mdbook/static"); + pub fn configure_service_for_common_resources(cfg: &mut app::web::ServiceConfig) { + configure_service_for_static_files!(cfg, "/mdbook/static", bundle_mdbook); } - pub fn configure_mdbook_service( + pub fn configure_service_for_mdbook( cfg: &mut app::web::ServiceConfig, mdbook_path: &'static str, - mdbook_map: &'static BookMapResources, + mdbook_map: &'static HashMapResources, ) { let path = mdbook_path.trim_end_matches('/'); cfg.service( @@ -46,7 +46,7 @@ impl MdBook { async fn mdbook_page( request: app::HttpRequest, mdbook_path: &'static str, - mdbook_map: &'static BookMapResources, + mdbook_map: &'static HashMapResources, ) -> ResultPage { let path_len = mdbook_path.len() + 1; if let Some(content) = mdbook_map.get(&request.path()[path_len..]) { @@ -115,7 +115,7 @@ async fn mdbook_page( async fn mdbook_resource( request: app::HttpRequest, mdbook_path: &'static str, - mdbook_map: &'static BookMapResources, + mdbook_map: &'static HashMapResources, ) -> app::HttpResponse { let path_len = mdbook_path.len() + 1; // From https://github.com/kilork/actix-web-static-files/blob/master/src/resource_files.rs, see diff --git a/pagetop-mdbook/src/util.rs b/pagetop-mdbook/src/util.rs new file mode 100644 index 00000000..00689eef --- /dev/null +++ b/pagetop-mdbook/src/util.rs @@ -0,0 +1,21 @@ +use std::path::Path; + +pub fn except_mdbook_common_resources(p: &Path) -> bool { + match p.to_str() { + Some("ayu-highlight.css") => false, + Some("highlight.css") => false, + Some("tomorrow-niht.css") => false, + _ => { + if let Some(parent) = p.parent() { + match parent.to_str() { + Some("/css") => false, + Some("/FontAwesome") => false, + Some("/fonts") => false, + _ => true, + } + } else { + true + } + } + } +} diff --git a/pagetop/build.rs b/pagetop/build.rs index d27cb3cd..9e4b899a 100644 --- a/pagetop/build.rs +++ b/pagetop/build.rs @@ -1,20 +1,19 @@ -use static_files::resource_dir; - -use std::env; use std::path::Path; fn main() -> std::io::Result<()> { - build_resource_dir("./static/theme", "theme")?; - build_resource_dir("./static/aliner", "aliner")?; - build_resource_dir("./static/bootsier", "bootsier")?; - build_resource_dir("./static/bulmix", "bulmix") + bundle_resources("./static/theme", "theme")?; + bundle_resources("./static/aliner", "aliner")?; + bundle_resources("./static/bootsier", "bootsier")?; + bundle_resources("./static/bulmix", "bulmix") } -fn build_resource_dir(dir: &str, name: &str) -> std::io::Result<()> { - let mut resource = resource_dir(dir); - resource.with_generated_filename( - Path::new(env::var("OUT_DIR").unwrap().as_str()).join(format!("{}.rs", name)), +/// This function is a simplified version of pagetop::util::bundle_resources(). +pub fn bundle_resources(from_dir: &str, with_name: &str) -> std::io::Result<()> { + let mut r = static_files::resource_dir(from_dir); + r.with_generated_filename( + Path::new(std::env::var("OUT_DIR").unwrap().as_str()).join(format!("{}.rs", with_name)), ); - resource.with_module_name(format!("resources_{}", name)); - resource.build() + r.with_module_name(format!("resources_{}", with_name)); + r.with_generated_fn(format!("bundle_{}", with_name)); + r.build() } diff --git a/pagetop/src/base/theme/aliner.rs b/pagetop/src/base/theme/aliner.rs index 3c73701f..4afa2292 100644 --- a/pagetop/src/base/theme/aliner.rs +++ b/pagetop/src/base/theme/aliner.rs @@ -12,7 +12,7 @@ impl ThemeTrait for Aliner { } fn configure_service(&self, cfg: &mut app::web::ServiceConfig) { - theme_static_files!(cfg, "/aliner"); + configure_service_for_static_files!(cfg, "/aliner", bundle_aliner); } fn before_render_page(&self, page: &mut Page) { diff --git a/pagetop/src/base/theme/bootsier.rs b/pagetop/src/base/theme/bootsier.rs index ffdad73f..cc93fe11 100644 --- a/pagetop/src/base/theme/bootsier.rs +++ b/pagetop/src/base/theme/bootsier.rs @@ -14,7 +14,7 @@ impl ThemeTrait for Bootsier { } fn configure_service(&self, cfg: &mut app::web::ServiceConfig) { - theme_static_files!(cfg, "/bootsier"); + configure_service_for_static_files!(cfg, "/bootsier", bundle_bootsier); } fn before_render_page(&self, page: &mut Page) { diff --git a/pagetop/src/base/theme/bulmix.rs b/pagetop/src/base/theme/bulmix.rs index 53b72c28..a7ba960a 100644 --- a/pagetop/src/base/theme/bulmix.rs +++ b/pagetop/src/base/theme/bulmix.rs @@ -12,7 +12,7 @@ impl ThemeTrait for Bulmix { } fn configure_service(&self, cfg: &mut app::web::ServiceConfig) { - theme_static_files!(cfg, "/bulmix"); + configure_service_for_static_files!(cfg, "/bulmix", bundle_bulmix); } fn before_render_page(&self, page: &mut Page) { diff --git a/pagetop/src/core/theme/all.rs b/pagetop/src/core/theme/all.rs index 99429838..64ae5b2b 100644 --- a/pagetop/src/core/theme/all.rs +++ b/pagetop/src/core/theme/all.rs @@ -1,5 +1,5 @@ use super::ThemeStaticRef; -use crate::{app, base, theme_static_files, trace, LazyStatic}; +use crate::{app, base, configure_service_for_static_files, trace, LazyStatic}; use std::sync::RwLock; @@ -41,7 +41,7 @@ pub fn theme_by_single_name(single_name: &str) -> Option { } pub fn configure_services(cfg: &mut app::web::ServiceConfig) { - theme_static_files!(cfg, "/theme"); + configure_service_for_static_files!(cfg, "/theme", bundle_theme); for t in THEMES.read().unwrap().iter() { t.configure_service(cfg); diff --git a/pagetop/src/prelude.rs b/pagetop/src/prelude.rs index b2b83648..a8e21580 100644 --- a/pagetop/src/prelude.rs +++ b/pagetop/src/prelude.rs @@ -1,9 +1,9 @@ -//! Re-exporta recursos comunes. - // Global macros and helpers. pub use crate::util; -pub use crate::util::Handler; -pub use crate::{args, concat_string, pub_const_handler, theme_static_files, LazyStatic}; +pub use crate::util::{Handler, HashMapResources}; +pub use crate::{ + args, concat_string, configure_service_for_static_files, pub_const_handler, LazyStatic, +}; pub use crate::config::SETTINGS; diff --git a/pagetop/src/util.rs b/pagetop/src/util.rs index 06ce3261..4af209a5 100644 --- a/pagetop/src/util.rs +++ b/pagetop/src/util.rs @@ -1,3 +1,90 @@ +pub use static_files::Resource as StaticResource; + +use std::path::Path; + +pub type HashMapResources = std::collections::HashMap<&'static str, StaticResource>; + +/// This function uses the [static_files](https://docs.rs/static-files/latest/static_files/) library +/// to embed at compile time a bundle of static files in your binary. +/// +/// Just create the folder with static resources in your project (for example `static`): +/// +/// ```bash +/// cd project_dir +/// mkdir static +/// echo "Hello, world" > static/hello +/// ``` +/// +/// Add to `Cargo.toml` the required dependencies: +/// +/// ```toml +/// [dependencies] +/// pagetop = { ... } +/// static-files = "0.2.3" +/// +/// [build-dependencies] +/// pagetop = { ... } +/// ``` +/// +/// Add `build.rs` with call to bundle resources: +/// +/// ```rust#ignore +/// use pagetop::util::bundle_resources; +/// +/// fn main() -> std::io::Result<()> { +/// bundle_resources("./static", "guides", None) +/// } +/// ``` +/// +/// This will create the resources file "guides.rs" in the standard output directory from files +/// located at "./static" folder. +/// +/// Optionally, you can also pass a function to filter the files in the "./static" folder that +/// should be included in the resources file: +/// +/// ```rust#ignore +/// use pagetop::util::bundle_resources; +/// +/// fn main() -> std::io::Result<()> { +/// bundle_resources("./static", "guides", Some(except_css_dir)) +/// } +/// +/// fn except_css_dir(p: &Path) -> bool { +/// if let Some(parent) = p.parent() { +/// ! matches!(parent.to_str(), Some("/css")) +/// } +/// true +/// } +/// ``` +/// +/// Finally, a module called "resources_guides" will be compiled with your project. And the function +/// to embed the generated HashMap resources collection in your code will be "bundle_guides": +/// +/// ```rust#ignore +/// use pagetop::prelude::*; +/// +/// include!(concat!(env!("OUT_DIR"), "/guides.rs")); +/// static GUIDES: LazyStatic = LazyStatic::new(bundle_guides); +/// ``` +/// +/// You can build more than one resources file to compile with your project. +pub fn bundle_resources( + from_dir: &str, + with_name: &str, + filtering: Option bool>, +) -> std::io::Result<()> { + let mut r = static_files::resource_dir(from_dir); + r.with_generated_filename( + Path::new(std::env::var("OUT_DIR").unwrap().as_str()).join(format!("{}.rs", with_name)), + ); + r.with_module_name(format!("resources_{}", with_name)); + r.with_generated_fn(format!("bundle_{}", with_name)); + if let Some(filter_files) = filtering { + r.with_filter(filter_files); + } + r.build() +} + pub type Handler = u64; // https://stackoverflow.com/a/71464396 @@ -60,7 +147,7 @@ pub fn single_type_name() -> &'static str { #[macro_export] /// Macro para construir grupos de pares clave-valor. /// -/// ``` +/// ```rust#ignore /// let args = args![ /// "userName" => "Roberto", /// "photoCount" => 3, @@ -78,11 +165,11 @@ macro_rules! args { } #[macro_export] -macro_rules! theme_static_files { - ( $cfg:ident, $dir:expr ) => {{ +macro_rules! configure_service_for_static_files { + ( $cfg:ident, $dir:expr, $embed:ident ) => {{ let static_files = &$crate::config::SETTINGS.dev.static_files; if static_files.is_empty() { - $cfg.service($crate::app::ResourceFiles::new($dir, generate())); + $cfg.service($crate::app::ResourceFiles::new($dir, $embed())); } else { $cfg.service( $crate::app::ActixFiles::new($dir, $crate::concat_string!(static_files, $dir)) diff --git a/website/Cargo.toml b/website/Cargo.toml index 9f4db205..96ee2e96 100644 --- a/website/Cargo.toml +++ b/website/Cargo.toml @@ -23,4 +23,5 @@ pagetop-mdbook = { path = "../pagetop-mdbook" } maud = { git = "https://github.com/lambda-fairy/maud", rev = "e6787cd6" } [build-dependencies] -static-files = "0.2.3" +pagetop = { path = "../pagetop" } +pagetop-mdbook = { path = "../pagetop-mdbook" } diff --git a/website/build.rs b/website/build.rs index 861014cf..08c2d29d 100644 --- a/website/build.rs +++ b/website/build.rs @@ -1,19 +1,15 @@ -use static_files::resource_dir; - -use std::env; -use std::path::Path; +use pagetop::util::bundle_resources; +use pagetop_mdbook::util::except_mdbook_common_resources; fn main() -> std::io::Result<()> { - build_resource_dir("./static/doc/en", "guides_en")?; - build_resource_dir("./static/doc/es", "guias_es") -} - -fn build_resource_dir(dir: &str, name: &str) -> std::io::Result<()> { - let mut resource = resource_dir(dir); - resource.with_generated_filename( - Path::new(env::var("OUT_DIR").unwrap().as_str()).join(format!("{}.rs", name)), - ); - resource.with_module_name(format!("resources_{}", name)); - resource.with_generated_fn(name); - resource.build() + bundle_resources( + "./static/doc/en", + "guides_en", + Some(except_mdbook_common_resources), + )?; + bundle_resources( + "./static/doc/es", + "guias_es", + Some(except_mdbook_common_resources), + ) } diff --git a/website/src/main.rs b/website/src/main.rs index 369955e4..8bc871ed 100644 --- a/website/src/main.rs +++ b/website/src/main.rs @@ -1,14 +1,13 @@ use pagetop::prelude::*; -use pagetop_mdbook::BookMapResources; use pagetop_mdbook::MdBook; pub_const_handler!(APP_PAGETOP_WEBSITE); include!(concat!(env!("OUT_DIR"), "/guides_en.rs")); -static GUIDES_EN: LazyStatic = LazyStatic::new(guides_en); +static GUIDES_EN: LazyStatic = LazyStatic::new(bundle_guides_en); include!(concat!(env!("OUT_DIR"), "/guias_es.rs")); -static GUIAS_ES: LazyStatic = LazyStatic::new(guias_es); +static GUIAS_ES: LazyStatic = LazyStatic::new(bundle_guias_es); struct PageTopWebSite; @@ -22,9 +21,9 @@ impl ModuleTrait for PageTopWebSite { } fn configure_service(&self, cfg: &mut app::web::ServiceConfig) { - MdBook::configure_mdbook_common(cfg); - MdBook::configure_mdbook_service(cfg, "/doc/en", &GUIDES_EN); - MdBook::configure_mdbook_service(cfg, "/doc/es", &GUIAS_ES); + MdBook::configure_service_for_common_resources(cfg); + MdBook::configure_service_for_mdbook(cfg, "/doc/en", &GUIDES_EN); + MdBook::configure_service_for_mdbook(cfg, "/doc/es", &GUIAS_ES); } }