diff --git a/CHANGELOG.md b/CHANGELOG.md index bfc9067..f2926a6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -25,7 +25,7 @@ internos pueden omitirse si no afectan al uso del proyecto. - [context] Generaliza los parámetros de contexto - [context] Define un `trait` común de contexto - Modifica tipos para atributos HTML a minúsculas -- Renombra `with_component` por `add_child` +- Renombra `with_component` por `add_component` ### Corregido diff --git a/Cargo.lock b/Cargo.lock index 2f9fa42..f1b09f9 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1593,7 +1593,6 @@ version = "0.0.18" dependencies = [ "pagetop", "pagetop-build", - "serde", ] [[package]] diff --git a/Cargo.toml b/Cargo.toml index b1bae0a..0d17082 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -39,7 +39,7 @@ actix-web = { workspace = true, default-features = true } actix-session = { version = "0.11", features = ["cookie-session"] } actix-web-files = { package = "actix-files", version = "0.6" } -serde.workspace = true +serde = { version = "1.0", features = ["derive"] } pagetop-macros.workspace = true pagetop-statics.workspace = true @@ -78,7 +78,6 @@ authors = ["Manuel Cillero "] [workspace.dependencies] actix-web = { version = "4.11", default-features = false } -serde = { version = "1.0", features = ["derive"] } # Helpers pagetop-build = { version = "0.3", path = "helpers/pagetop-build" } pagetop-macros = { version = "0.2", path = "helpers/pagetop-macros" } diff --git a/README.md b/README.md index 9a12c84..be72091 100644 --- a/README.md +++ b/README.md @@ -60,7 +60,7 @@ impl Extension for HelloWorld { async fn hello_world(request: HttpRequest) -> ResultPage { Page::new(request) - .add_child(Html::with(|_| html! { h1 { "Hello World!" } })) + .add_component(Html::with(move |_| html! { h1 { "Hello World!" } })) .render() } @@ -102,7 +102,7 @@ El código se organiza en un *workspace* donde actualmente se incluyen los sigui es un tema para demos y pruebas que muestra esquemáticamente la composición de las páginas HTML. * **[pagetop-bootsier](https://git.cillero.es/manuelcillero/pagetop/src/branch/main/extensions/pagetop-bootsier)**, - tema basado en [Bootstrap](https://getbootstrap.com) para integrar su catálogo de estilos y + tema basado en [Bootstrap](https://getbootstrap.com) para ofrecer su catálogo de estilos y componentes flexibles. diff --git a/examples/hello-name.rs b/examples/hello-name.rs index c6a82aa..e1285d0 100644 --- a/examples/hello-name.rs +++ b/examples/hello-name.rs @@ -14,7 +14,7 @@ async fn hello_name( ) -> ResultPage { let name = path.into_inner(); Page::new(request) - .add_child(Html::with(move |_| html! { h1 { "Hello " (name) "!" } })) + .add_component(Html::with(move |_| html! { h1 { "Hello " (name) "!" } })) .render() } diff --git a/examples/hello-world.rs b/examples/hello-world.rs index 6481746..d56f210 100644 --- a/examples/hello-world.rs +++ b/examples/hello-world.rs @@ -10,7 +10,7 @@ impl Extension for HelloWorld { async fn hello_world(request: HttpRequest) -> ResultPage { Page::new(request) - .add_child(Html::with(|_| html! { h1 { "Hello World!" } })) + .add_component(Html::with(move |_| html! { h1 { "Hello World!" } })) .render() } diff --git a/extensions/pagetop-aliner/README.md b/extensions/pagetop-aliner/README.md index 43fb65a..0560a06 100644 --- a/extensions/pagetop-aliner/README.md +++ b/extensions/pagetop-aliner/README.md @@ -67,10 +67,10 @@ use pagetop::prelude::*; async fn homepage(request: HttpRequest) -> ResultPage { Page::new(request) .with_theme("Aliner") - .add_child( + .add_component( Block::new() .with_title(L10n::l("sample_title")) - .add_child(Html::with(|cx| html! { + .add_component(Html::with(|cx| html! { p { (L10n::l("sample_content").using(cx)) } })), ) diff --git a/extensions/pagetop-aliner/src/lib.rs b/extensions/pagetop-aliner/src/lib.rs index edbb504..b51800c 100644 --- a/extensions/pagetop-aliner/src/lib.rs +++ b/extensions/pagetop-aliner/src/lib.rs @@ -68,10 +68,10 @@ use pagetop::prelude::*; async fn homepage(request: HttpRequest) -> ResultPage { Page::new(request) .with_theme("Aliner") - .add_child( + .add_component( Block::new() .with_title(L10n::l("sample_title")) - .add_child(Html::with(|cx| html! { + .add_component(Html::with(|cx| html! { p { (L10n::l("sample_content").using(cx)) } })), ) diff --git a/extensions/pagetop-bootsier/Cargo.toml b/extensions/pagetop-bootsier/Cargo.toml index 6df6cf6..11306b6 100644 --- a/extensions/pagetop-bootsier/Cargo.toml +++ b/extensions/pagetop-bootsier/Cargo.toml @@ -4,7 +4,7 @@ version = "0.0.18" edition = "2021" description = """ - Tema de PageTop basado en Bootstrap para aplicar su catálogo de estilos y componentes flexibles. + Tema de PageTop basado en Bootstrap para dar vida a tus diseños web. """ categories = ["web-programming", "gui"] keywords = ["pagetop", "theme", "bootstrap", "css", "js"] @@ -16,7 +16,6 @@ authors.workspace = true [dependencies] pagetop.workspace = true -serde.workspace = true [build-dependencies] pagetop-build.workspace = true diff --git a/extensions/pagetop-bootsier/README.md b/extensions/pagetop-bootsier/README.md index 84e11b5..7495bc2 100644 --- a/extensions/pagetop-bootsier/README.md +++ b/extensions/pagetop-bootsier/README.md @@ -2,7 +2,7 @@

PageTop Bootsier

-

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

+

Tema de PageTop basado en Bootstrap para dar vida a tus diseños web.

[![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) @@ -67,10 +67,10 @@ use pagetop::prelude::*; async fn homepage(request: HttpRequest) -> ResultPage { Page::new(request) .with_theme("Bootsier") - .add_child( + .add_component( Block::new() .with_title(L10n::l("sample_title")) - .add_child(Html::with(|cx| html! { + .add_component(Html::with(|cx| html! { p { (L10n::l("sample_content").using(cx)) } })), ) diff --git a/extensions/pagetop-bootsier/src/lib.rs b/extensions/pagetop-bootsier/src/lib.rs index 777f71e..a658333 100644 --- a/extensions/pagetop-bootsier/src/lib.rs +++ b/extensions/pagetop-bootsier/src/lib.rs @@ -3,7 +3,7 @@

PageTop Bootsier

-

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

+

Tema de PageTop basado en Bootstrap para ofrecer 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) diff --git a/src/base/component/block.rs b/src/base/component/block.rs index 17af50c..9a04c4e 100644 --- a/src/base/component/block.rs +++ b/src/base/component/block.rs @@ -71,7 +71,7 @@ impl Block { } /// Añade un nuevo componente hijo al bloque. - pub fn add_child(mut self, component: impl Component) -> Self { + pub fn add_component(mut self, component: impl Component) -> Self { self.children .alter_child(ChildOp::Add(Child::with(component))); self diff --git a/src/base/component/intro.rs b/src/base/component/intro.rs index 7e5c393..5d3440e 100644 --- a/src/base/component/intro.rs +++ b/src/base/component/intro.rs @@ -65,10 +65,10 @@ pub enum IntroOpening { /// ```rust /// # use pagetop::prelude::*; /// let intro = Intro::default() -/// .add_child( +/// .add_component( /// Block::new() /// .with_title(L10n::l("intro_custom_block_title")) -/// .add_child(Html::with(move |cx| { +/// .add_component(Html::with(move |cx| { /// html! { /// p { (L10n::l("intro_custom_paragraph_1").using(cx)) } /// p { (L10n::l("intro_custom_paragraph_2").using(cx)) } @@ -301,7 +301,7 @@ impl Intro { /// Añade un nuevo componente hijo a la intro. /// /// Si es un bloque ([`Block`]) aplica estilos específicos para destacarlo. - pub fn add_child(mut self, component: impl Component) -> Self { + pub fn add_component(mut self, component: impl Component) -> Self { self.children .alter_child(ChildOp::Add(Child::with(component))); self diff --git a/src/base/extension/welcome.rs b/src/base/extension/welcome.rs index b875163..d94afad 100644 --- a/src/base/extension/welcome.rs +++ b/src/base/extension/welcome.rs @@ -26,22 +26,22 @@ async fn homepage(request: HttpRequest) -> ResultPage { Page::new(request) .with_title(L10n::l("welcome_title")) - .add_child( + .add_component( Intro::new() - .add_child( + .add_component( Block::new() .with_title(L10n::l("welcome_status_title")) - .add_child(Html::with(move |cx| { + .add_component(Html::with(move |cx| { html! { p { (L10n::l("welcome_status_1").using(cx)) } p { (L10n::l("welcome_status_2").using(cx)) } } })), ) - .add_child( + .add_component( Block::new() .with_title(L10n::l("welcome_support_title")) - .add_child(Html::with(move |cx| { + .add_component(Html::with(move |cx| { html! { p { (L10n::l("welcome_support_1").using(cx)) } p { (L10n::l("welcome_support_2").with_arg("app", app).using(cx)) } diff --git a/src/core/component.rs b/src/core/component.rs index a7faa2f..be9bbad 100644 --- a/src/core/component.rs +++ b/src/core/component.rs @@ -10,9 +10,4 @@ pub use children::{Typed, TypedOp}; mod context; pub use context::{Context, ContextError, ContextOp, Contextual}; - -/// 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; diff --git a/src/html/unit.rs b/src/html/unit.rs index 4a99de1..53319dc 100644 --- a/src/html/unit.rs +++ b/src/html/unit.rs @@ -145,9 +145,9 @@ impl UnitValue { impl fmt::Display for UnitValue { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { match self { - UnitValue::None => Ok(()), - UnitValue::Auto => f.write_str("auto"), - UnitValue::Zero => f.write_str("0"), + UnitValue::None => write!(f, ""), + UnitValue::Auto => write!(f, "auto"), + UnitValue::Zero => write!(f, "0"), // Valor absoluto. UnitValue::Cm(av) => write!(f, "{av}cm"), UnitValue::In(av) => write!(f, "{av}in"), diff --git a/src/lib.rs b/src/lib.rs index a268349..de6d9e6 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -61,7 +61,7 @@ impl Extension for HelloWorld { async fn hello_world(request: HttpRequest) -> ResultPage { Page::new(request) - .add_child(Html::with(|_| html! { h1 { "Hello World!" } })) + .add_component(Html::with(move |_| html! { h1 { "Hello World!" } })) .render() } diff --git a/src/response/page.rs b/src/response/page.rs index 036c999..1649d54 100644 --- a/src/response/page.rs +++ b/src/response/page.rs @@ -93,28 +93,29 @@ impl Page { self } - /// **Obsoleto desde la versión 0.4.0**: usar [`add_child()`](Self::add_child) en su lugar. - #[deprecated(since = "0.4.0", note = "Use `add_child()` instead")] - pub fn with_component(self, component: impl Component) -> Self { - self.add_child(component) - } - - /// **Obsoleto desde la versión 0.4.0**: usar [`add_child_in()`](Self::add_child_in) en su + /// **Obsoleto desde la versión 0.4.0**: usar [`add_component()`](Self::add_component) en su /// lugar. - #[deprecated(since = "0.4.0", note = "Use `add_child_in()` instead")] - pub fn with_component_in(self, region_key: &'static str, component: impl Component) -> Self { - self.add_child_in(region_key, component) + #[deprecated(since = "0.4.0", note = "Use `add_component()` instead")] + pub fn with_component(self, component: impl Component) -> Self { + self.add_component(component) } - /// Añade un componente hijo a la región de contenido por defecto. - pub fn add_child(mut self, component: impl Component) -> Self { + /// **Obsoleto desde la versión 0.4.0**: usar [`add_component_in()`](Self::add_component_in) en + /// su lugar. + #[deprecated(since = "0.4.0", note = "Use `add_component_in()` instead")] + pub fn with_component_in(self, region_key: &'static str, component: impl Component) -> Self { + self.add_component_in(region_key, component) + } + + /// Añade un componente a la región de contenido por defecto. + pub fn add_component(mut self, component: impl Component) -> Self { self.context .alter_child_in(REGION_CONTENT, ChildOp::Add(Child::with(component))); self } - /// Añade un componente hijo en una región (`region_key`) de la página. - pub fn add_child_in(mut self, region_key: &'static str, component: impl Component) -> Self { + /// Añade un componente en una región (`region_key`) de la página. + pub fn add_component_in(mut self, region_key: &'static str, component: impl Component) -> Self { self.context .alter_child_in(region_key, ChildOp::Add(Child::with(component))); self diff --git a/src/response/page/error.rs b/src/response/page/error.rs index 9945a94..50e1c77 100644 --- a/src/response/page/error.rs +++ b/src/response/page/error.rs @@ -24,9 +24,9 @@ impl Display for ErrorPage { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { match self { // Error 304. - ErrorPage::NotModified(_) => f.write_str("Not Modified"), + ErrorPage::NotModified(_) => write!(f, "Not Modified"), // Error 400. - ErrorPage::BadRequest(_) => f.write_str("Bad Client Data"), + ErrorPage::BadRequest(_) => write!(f, "Bad Client Data"), // Error 403. ErrorPage::AccessDenied(request) => { let mut error_page = Page::new(request.clone()); @@ -34,12 +34,12 @@ impl Display for ErrorPage { if let Ok(page) = error_page .with_title(L10n::n("Error FORBIDDEN")) .with_layout("error") - .add_child(Html::with(move |_| error403.clone())) + .add_component(Html::with(move |_| error403.clone())) .render() { write!(f, "{}", page.into_string()) } else { - f.write_str("Access Denied") + write!(f, "Access Denied") } } // Error 404. @@ -49,20 +49,20 @@ impl Display for ErrorPage { if let Ok(page) = error_page .with_title(L10n::n("Error RESOURCE NOT FOUND")) .with_layout("error") - .add_child(Html::with(move |_| error404.clone())) + .add_component(Html::with(move |_| error404.clone())) .render() { write!(f, "{}", page.into_string()) } else { - f.write_str("Not Found") + write!(f, "Not Found") } } // Error 412. - ErrorPage::PreconditionFailed(_) => f.write_str("Precondition Failed"), + ErrorPage::PreconditionFailed(_) => write!(f, "Precondition Failed"), // Error 500. - ErrorPage::InternalError(_) => f.write_str("Internal Error"), + ErrorPage::InternalError(_) => write!(f, "Internal Error"), // Error 504. - ErrorPage::Timeout(_) => f.write_str("Timeout"), + ErrorPage::Timeout(_) => write!(f, "Timeout"), } } } diff --git a/src/util.rs b/src/util.rs index 3d07361..f73cf78 100644 --- a/src/util.rs +++ b/src/util.rs @@ -70,12 +70,14 @@ macro_rules! join { }; } -/// Concatena los fragmentos **no vacíos** en un [`Option`] con un separador opcional. +/// Concatena los fragmentos no vacíos en un [`Option`] con un separador opcional. /// -/// Acepta cualquier número de fragmentos que implementen [`AsRef`]. Si todos los fragmentos -/// están vacíos, devuelve `None`. +/// Esta macro acepta cualquier número de fragmentos que implementen [`AsRef`] para concatenar +/// todos los fragmentos no vacíos usando opcionalmente un separador. /// -/// # Ejemplos +/// Si todos los fragmentos están vacíos, devuelve [`None`]. +/// +/// # Ejemplo /// /// ```rust /// # use pagetop::prelude::*; @@ -88,7 +90,7 @@ macro_rules! join { /// assert_eq!(result_without_separator, Some("HelloWorld".to_string())); /// /// // Devuelve `None` si todos los fragmentos están vacíos. -/// let result_empty = join_opt!(["", "", ""]; ","); +/// let result_empty = join_opt!(["", "", ""]); /// assert_eq!(result_empty, None); /// ``` #[macro_export] @@ -98,16 +100,12 @@ macro_rules! join_opt { (!s.is_empty()).then_some(s) }}; ([$($arg:expr),* $(,)?]; $separator:expr) => {{ - let sep = ($separator).as_ref(); - let mut s = String::new(); - for part in [ $( ($arg).as_ref() ),* ] { - if !(part as &str).is_empty() { - if !s.is_empty() { - s.push_str(sep); - } - s.push_str(part); - } - } + let s = [$($arg),*] + .iter() + .filter(|&item| !item.is_empty()) + .cloned() + .collect::>() + .join($separator); (!s.is_empty()).then_some(s) }}; } @@ -155,7 +153,7 @@ macro_rules! join_pair { }}; } -/// Concatena varios fragmentos en un [`Option`] **si ninguno está vacío**. +/// Concatena varios fragmentos en un [`Option`] si ninguno está vacío. /// /// Si alguno de los fragmentos, que deben implementar [`AsRef`], está vacío, devuelve /// [`None`]. Opcionalmente se puede indicar un separador entre los fragmentos concatenados.