/*!

PageTop Bootsier

Tema de PageTop basado en Bootstrap para aplicar su catálogo de estilos y componentes flexibles.

[![Doc API](https://img.shields.io/docsrs/pagetop-bootsier?label=Doc%20API&style=for-the-badge&logo=Docs.rs)](https://docs.rs/pagetop-bootsier) [![Crates.io](https://img.shields.io/crates/v/pagetop-bootsier.svg?style=for-the-badge&logo=ipfs)](https://crates.io/crates/pagetop-bootsier) [![Descargas](https://img.shields.io/crates/d/pagetop-bootsier.svg?label=Descargas&style=for-the-badge&logo=transmission)](https://crates.io/crates/pagetop-bootsier) [![Licencia](https://img.shields.io/badge/license-MIT%2FApache-blue.svg?label=Licencia&style=for-the-badge)](https://git.cillero.es/manuelcillero/pagetop/src/branch/main/extensions/pagetop-bootsier#licencia)
## Sobre PageTop [PageTop](https://docs.rs/pagetop) es un entorno de desarrollo que reivindica la esencia de la web clásica para crear soluciones web SSR (*renderizadas en el servidor*) modulares, extensibles y configurables, basadas en HTML, CSS y JavaScript. ## Guía rápida Igual que con otras extensiones, **añade la dependencia** a tu `Cargo.toml`: ```toml [dependencies] pagetop-bootsier = { ... } ``` **Declara la extensión** en tu aplicación (o extensión que la requiera). Recuerda que el orden en `dependencies()` determina la prioridad relativa frente a las otras extensiones: ```rust,no_run use pagetop::prelude::*; struct MyApp; #[async_trait] impl Extension for MyApp { fn dependencies(&self) -> Vec { vec![ // ... &pagetop_bootsier::Bootsier, // ... ] } } ``` Y **selecciona el tema en la configuración** de la aplicación: ```toml [app] theme = "Bootsier" ``` o **fuerza el tema por código** en una página concreta: ```rust,no_run use pagetop::prelude::*; use pagetop_bootsier::Bootsier; async fn homepage(request: HttpRequest) -> Result { Page::new(request) .with_theme(&Bootsier) .with_child( Block::new() .with_title(L10n::l("sample_title")) .with_child(Html::with(|cx| html! { p { (L10n::l("sample_content").using(cx)) } })), ) .render().await } ``` */ #![doc( html_favicon_url = "https://git.cillero.es/manuelcillero/pagetop/raw/branch/main/assets/favicon.ico" )] use pagetop::prelude::*; include_locales!(LOCALES_BOOTSIER); // Versión de la librería Bootstrap. const BOOTSTRAP_VERSION: &str = "5.3.8"; pub mod config; pub mod theme; mod handlers { pub mod button; pub mod input; pub mod select; pub mod textarea; } /// Implementa el tema. pub struct Bootsier; #[async_trait] impl Extension for Bootsier { fn name(&self) -> L10n { L10n::t("extension_name", &LOCALES_BOOTSIER) } fn description(&self) -> L10n { L10n::t("extension_description", &LOCALES_BOOTSIER) } fn theme(&self) -> Option { Some(&Self) } fn configure_router(&self, router: Router) -> Router { let base = &config::SETTINGS.dev.bootsier_static_dir; let subdir = |s: &str| { if base.is_empty() { String::new() } else { format!("{base}/{s}") } }; serve_static_files!(router, [subdir("css"), bootsier_css] => "/bootsier/css"); serve_static_files!(router, [subdir("js"), bootsier_js] => "/bootsier/js"); serve_static_files!(router, [subdir("fonts"), bootsier_fonts] => "/bootsier/fonts"); router } } #[async_trait] impl Theme for Bootsier { #[inline] fn default_template(&self) -> TemplateRef { &BootsierTemplate::Standard } async fn handle_component( &self, component: &mut dyn Component, cx: &mut Context, ) -> Option> { setup_component!(component, { Button => |c| handlers::button::setup(c), form::select::Field => |c| handlers::select::setup(c), form::Textarea => |c| handlers::textarea::setup(c), }); render_component!(component, { form::input::Field => |c| handlers::input::render(c, cx), form::select::Field => |c| handlers::select::render(c, cx), form::Textarea => |c| handlers::textarea::render(c, cx), }) } fn before_render_page_body(&self, page: &mut Page) { // Las URLs de las fuentes deben coincidir exactamente con las declaradas en @font-face de // _bootsier-custom.scss; cualquier discrepancia hace que el navegador descargue dos veces. page.alter_assets(AssetsOp::AddPreload( Preload::font("/bootsier/fonts/bootsier.font.woff2").with_weight(-99), )) .alter_assets(AssetsOp::AddPreload( Preload::font("/bootsier/fonts/bootsier.font.italic.woff2").with_weight(-99), )) .alter_assets(AssetsOp::AddStyleSheet( StyleSheet::from("/bootsier/css/bootsier.min.css") .with_version(ADMINLTE_VERSION) .with_weight(-90), )) .alter_assets(AssetsOp::AddJavaScript( JavaScript::defer("/bootsier/js/bootsier.bundle.min.js") .with_version(BOOTSTRAP_VERSION) .with_weight(-90), )) .alter_assets(AssetsOp::AddJavaScript( JavaScript::defer("/bootsier/js/bootsier.extended.min.js") .with_version(ADMINLTE_VERSION) .with_weight(-90), )) .alter_child_in( &DefaultRegion::Footer, ChildOp::AddIfEmpty(PoweredBy::new().into()), ); } }