From 51e18cf5eebb4f9f16f5f3846f918d59dab8d64d Mon Sep 17 00:00:00 2001 From: Manuel Cillero Date: Wed, 3 Dec 2025 06:41:52 +0100 Subject: [PATCH] =?UTF-8?q?=F0=9F=8E=A8=20[pagetop]=20Mejora=20gesti=C3=B3?= =?UTF-8?q?n=20de=20URLs=20seg=C3=BAn=20contexto?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- examples/navbar-menus.rs | 31 +++++++++---------- .../src/theme/dropdown/item.rs | 2 +- .../pagetop-bootsier/src/theme/nav/item.rs | 2 +- .../src/theme/navbar/brand.rs | 2 +- src/base/component/intro.rs | 11 ++++--- src/core/component.rs | 12 +++++-- 6 files changed, 32 insertions(+), 28 deletions(-) diff --git a/examples/navbar-menus.rs b/examples/navbar-menus.rs index 079508e9..8d330542 100644 --- a/examples/navbar-menus.rs +++ b/examples/navbar-menus.rs @@ -10,10 +10,7 @@ impl Extension for SuperMenu { } fn initialize(&self) { - let home_path = |cx: &Context| match cx.langid().language.as_str() { - "en" => "/en", - _ => "/", - }; + let home_path = |cx: &Context| join!("/lang/", cx.langid().language.as_str()).into(); let navbar_menu = Navbar::brand_left(navbar::Brand::new().with_path(Some(home_path))) .with_expand(BreakPoint::LG) @@ -25,7 +22,7 @@ impl Extension for SuperMenu { )) .add_item(nav::Item::link_blank( L10n::l("sample_menus_item_blank"), - |_| "https://docs.rs/pagetop", + |_| "https://docs.rs/pagetop".into(), )) .add_item(nav::Item::dropdown( Dropdown::new() @@ -33,28 +30,28 @@ impl Extension for SuperMenu { .add_item(dropdown::Item::header(L10n::l("sample_menus_dev_header"))) .add_item(dropdown::Item::link( L10n::l("sample_menus_dev_getting_started"), - |_| "/dev/getting-started", + |_| "/dev/getting-started".into(), )) .add_item(dropdown::Item::link( L10n::l("sample_menus_dev_guides"), - |_| "/dev/guides", + |_| "/dev/guides".into(), )) .add_item(dropdown::Item::link_blank( L10n::l("sample_menus_dev_forum"), - |_| "https://forum.example.dev", + |_| "https://forum.example.dev".into(), )) .add_item(dropdown::Item::divider()) .add_item(dropdown::Item::header(L10n::l("sample_menus_sdk_header"))) .add_item(dropdown::Item::link( L10n::l("sample_menus_sdk_rust"), - |_| "/dev/sdks/rust", + |_| "/dev/sdks/rust".into(), )) .add_item(dropdown::Item::link(L10n::l("sample_menus_sdk_js"), |_| { - "/dev/sdks/js" + "/dev/sdks/js".into() })) .add_item(dropdown::Item::link( L10n::l("sample_menus_sdk_python"), - |_| "/dev/sdks/python", + |_| "/dev/sdks/python".into(), )) .add_item(dropdown::Item::divider()) .add_item(dropdown::Item::header(L10n::l( @@ -62,22 +59,22 @@ impl Extension for SuperMenu { ))) .add_item(dropdown::Item::link( L10n::l("sample_menus_plugin_auth"), - |_| "/dev/sdks/rust/plugins/auth", + |_| "/dev/sdks/rust/plugins/auth".into(), )) .add_item(dropdown::Item::link( L10n::l("sample_menus_plugin_cache"), - |_| "/dev/sdks/rust/plugins/cache", + |_| "/dev/sdks/rust/plugins/cache".into(), )) .add_item(dropdown::Item::divider()) .add_item(dropdown::Item::label(L10n::l("sample_menus_item_label"))) .add_item(dropdown::Item::link_disabled( L10n::l("sample_menus_item_disabled"), - |_| "#", + |_| "#".into(), )), )) .add_item(nav::Item::link_disabled( L10n::l("sample_menus_item_disabled"), - |_| "#", + |_| "#".into(), )), )) .add_item(navbar::Item::nav( @@ -88,10 +85,10 @@ impl Extension for SuperMenu { ) .add_item(nav::Item::link( L10n::l("sample_menus_item_sign_up"), - |_| "/auth/sign-up", + |_| "/auth/sign-up".into(), )) .add_item(nav::Item::link(L10n::l("sample_menus_item_login"), |_| { - "/auth/login" + "/auth/login".into() })), )); diff --git a/extensions/pagetop-bootsier/src/theme/dropdown/item.rs b/extensions/pagetop-bootsier/src/theme/dropdown/item.rs index 1ff894e8..81f0ab08 100644 --- a/extensions/pagetop-bootsier/src/theme/dropdown/item.rs +++ b/extensions/pagetop-bootsier/src/theme/dropdown/item.rs @@ -81,7 +81,7 @@ impl Component for Item { } => { let path = path(cx); let current_path = cx.request().map(|request| request.path()); - let is_current = !*disabled && (current_path == Some(path)); + let is_current = !*disabled && (current_path == Some(&path)); let mut classes = "dropdown-item".to_string(); if is_current { diff --git a/extensions/pagetop-bootsier/src/theme/nav/item.rs b/extensions/pagetop-bootsier/src/theme/nav/item.rs index 0aa30037..faf68032 100644 --- a/extensions/pagetop-bootsier/src/theme/nav/item.rs +++ b/extensions/pagetop-bootsier/src/theme/nav/item.rs @@ -115,7 +115,7 @@ impl Component for Item { } => { let path = path(cx); let current_path = cx.request().map(|request| request.path()); - let is_current = !*disabled && (current_path == Some(path)); + let is_current = !*disabled && (current_path == Some(&path)); let mut classes = "nav-link".to_string(); if is_current { diff --git a/extensions/pagetop-bootsier/src/theme/navbar/brand.rs b/extensions/pagetop-bootsier/src/theme/navbar/brand.rs index eb2d17a8..2fc31ef7 100644 --- a/extensions/pagetop-bootsier/src/theme/navbar/brand.rs +++ b/extensions/pagetop-bootsier/src/theme/navbar/brand.rs @@ -23,7 +23,7 @@ pub struct Brand { /// Devuelve el eslogan de la marca. slogan: L10n, /// Devuelve la función que resuelve la URL asociada a la marca (si existe). - #[default(_code = "Some(|_| \"/\")")] + #[default(_code = "Some(|_| \"/\".into())")] path: Option, } diff --git a/src/base/component/intro.rs b/src/base/component/intro.rs index 64d2dddd..1a7c440b 100644 --- a/src/base/component/intro.rs +++ b/src/base/component/intro.rs @@ -91,13 +91,14 @@ pub struct Intro { } impl Default for Intro { - #[rustfmt::skip] fn default() -> Self { + const BUTTON_LINK: &str = "https://pagetop.cillero.es"; + Intro { - title : L10n::l("intro_default_title"), - slogan : L10n::l("intro_default_slogan").with_arg("app", &global::SETTINGS.app.name), - button : Some((L10n::l("intro_default_button"), |_| "https://pagetop.cillero.es")), - opening : IntroOpening::default(), + title: L10n::l("intro_default_title"), + slogan: L10n::l("intro_default_slogan").with_arg("app", &global::SETTINGS.app.name), + button: Some((L10n::l("intro_default_button"), |_| BUTTON_LINK.into())), + opening: IntroOpening::default(), children: Children::default(), } } diff --git a/src/core/component.rs b/src/core/component.rs index 9c9ade2e..b905a495 100644 --- a/src/core/component.rs +++ b/src/core/component.rs @@ -1,5 +1,7 @@ //! API para construir nuevos componentes. +use std::borrow::Cow; + mod definition; pub use definition::{Component, ComponentRender}; @@ -66,6 +68,10 @@ pub type FnIsRenderable = fn(cx: &Context) -> bool; /// Alias de función (*callback*) para **resolver una URL** según el contexto de renderizado. /// -/// Se usa para generar enlaces dinámicos en función del contexto (petición, idioma, etc.). Debe -/// devolver una referencia válida durante el renderizado. -pub type FnPathByContext = fn(cx: &Context) -> &str; +/// Se usa para generar enlaces dinámicos en función del contexto (petición, idioma, etc.). El +/// resultado se devuelve como [`Cow<'static, str>`](std::borrow::Cow), lo que permite: +/// +/// - Usar rutas estáticas sin asignaciones adicionales (`"/path".into()`). +/// - Construir rutas dinámicas en tiempo de ejecución (`format!(...).into()`), por ejemplo, en +/// función de parámetros almacenados en [`Context`]. +pub type FnPathByContext = fn(cx: &Context) -> Cow<'static, str>;