diff --git a/extensions/pagetop-bootsier/src/theme/container/component.rs b/extensions/pagetop-bootsier/src/theme/container/component.rs index 0cebdef5..b105abb1 100644 --- a/extensions/pagetop-bootsier/src/theme/container/component.rs +++ b/extensions/pagetop-bootsier/src/theme/container/component.rs @@ -11,7 +11,7 @@ pub struct Container { #[getters(skip)] id: AttrId, /// Devuelve las clases CSS asociadas al contenedor. - classes: AttrClasses, + classes: Classes, /// Devuelve el tipo semántico del contenedor. container_kind: container::Kind, /// Devuelve el comportamiento para el ancho del contenedor. @@ -139,7 +139,7 @@ impl Container { /// - Redondear las esquinas ([`classes::Rounded`]). #[builder_fn] pub fn with_classes(mut self, op: ClassesOp, classes: impl AsRef) -> Self { - self.classes.alter_value(op, classes); + self.classes.alter_classes(op, classes); self } diff --git a/extensions/pagetop-bootsier/src/theme/dropdown/component.rs b/extensions/pagetop-bootsier/src/theme/dropdown/component.rs index 45e446e7..3e683f18 100644 --- a/extensions/pagetop-bootsier/src/theme/dropdown/component.rs +++ b/extensions/pagetop-bootsier/src/theme/dropdown/component.rs @@ -24,7 +24,7 @@ pub struct Dropdown { #[getters(skip)] id: AttrId, /// Devuelve las clases CSS asociadas al menú desplegable. - classes: AttrClasses, + classes: Classes, /// Devuelve el título del menú desplegable. title: L10n, /// Devuelve el tamaño configurado del botón. @@ -76,7 +76,7 @@ impl Component for Dropdown { PrepareMarkup::With(html! { div id=[self.id()] class=[self.classes().get()] { @if !title.is_empty() { - @let mut btn_classes = AttrClasses::new({ + @let mut btn_classes = Classes::new({ let mut classes = "btn".to_string(); self.button_size().push_class(&mut classes); self.button_color().push_class(&mut classes); @@ -86,7 +86,7 @@ impl Component for Dropdown { @let offset = pos.data_offset(); @let reference = pos.data_reference(); @let auto_close = self.auto_close.as_str(); - @let menu_classes = AttrClasses::new({ + @let menu_classes = Classes::new({ let mut classes = "dropdown-menu".to_string(); self.menu_align().push_class(&mut classes); classes @@ -107,7 +107,7 @@ impl Component for Dropdown { @let btn_toggle = html! { button type="button" - class=[btn_classes.alter_value( + class=[btn_classes.alter_classes( ClassesOp::Add, "dropdown-toggle dropdown-toggle-split" ).get()] data-bs-toggle="dropdown" @@ -138,7 +138,7 @@ impl Component for Dropdown { // Botón único con funcionalidad de *toggle*. button type="button" - class=[btn_classes.alter_value( + class=[btn_classes.alter_classes( ClassesOp::Add, "dropdown-toggle" ).get()] data-bs-toggle="dropdown" @@ -173,7 +173,7 @@ impl Dropdown { /// Modifica la lista de clases CSS aplicadas al menú desplegable. #[builder_fn] pub fn with_classes(mut self, op: ClassesOp, classes: impl AsRef) -> Self { - self.classes.alter_value(op, classes); + self.classes.alter_classes(op, classes); self } diff --git a/extensions/pagetop-bootsier/src/theme/dropdown/item.rs b/extensions/pagetop-bootsier/src/theme/dropdown/item.rs index cedcccb4..91570636 100644 --- a/extensions/pagetop-bootsier/src/theme/dropdown/item.rs +++ b/extensions/pagetop-bootsier/src/theme/dropdown/item.rs @@ -48,7 +48,7 @@ pub struct Item { #[getters(skip)] id: AttrId, /// Devuelve las clases CSS asociadas al elemento. - classes: AttrClasses, + classes: Classes, /// Devuelve el tipo de elemento representado. item_kind: ItemKind, } @@ -270,7 +270,7 @@ impl Item { /// Modifica la lista de clases CSS aplicadas al elemento. #[builder_fn] pub fn with_classes(mut self, op: ClassesOp, classes: impl AsRef) -> Self { - self.classes.alter_value(op, classes); + self.classes.alter_classes(op, classes); self } } diff --git a/extensions/pagetop-bootsier/src/theme/icon.rs b/extensions/pagetop-bootsier/src/theme/icon.rs index 8e3c97eb..96de2049 100644 --- a/extensions/pagetop-bootsier/src/theme/icon.rs +++ b/extensions/pagetop-bootsier/src/theme/icon.rs @@ -16,7 +16,7 @@ pub enum IconKind { #[derive(AutoDefault, Getters)] pub struct Icon { /// Devuelve las clases CSS asociadas al icono. - classes: AttrClasses, + classes: Classes, icon_kind: IconKind, aria_label: AttrL10n, } diff --git a/extensions/pagetop-bootsier/src/theme/image/component.rs b/extensions/pagetop-bootsier/src/theme/image/component.rs index 84d669d6..4362a25f 100644 --- a/extensions/pagetop-bootsier/src/theme/image/component.rs +++ b/extensions/pagetop-bootsier/src/theme/image/component.rs @@ -14,7 +14,7 @@ pub struct Image { #[getters(skip)] id: AttrId, /// Devuelve las clases CSS asociadas a la imagen. - classes: AttrClasses, + classes: Classes, /// Devuelve las dimensiones de la imagen. size: image::Size, /// Devuelve el origen de la imagen. @@ -93,7 +93,7 @@ impl Image { /// - Redondear las esquinas ([`classes::Rounded`]). #[builder_fn] pub fn with_classes(mut self, op: ClassesOp, classes: impl AsRef) -> Self { - self.classes.alter_value(op, classes); + self.classes.alter_classes(op, classes); self } diff --git a/extensions/pagetop-bootsier/src/theme/nav/component.rs b/extensions/pagetop-bootsier/src/theme/nav/component.rs index 283d3d27..00703c79 100644 --- a/extensions/pagetop-bootsier/src/theme/nav/component.rs +++ b/extensions/pagetop-bootsier/src/theme/nav/component.rs @@ -15,7 +15,7 @@ pub struct Nav { #[getters(skip)] id: AttrId, /// Devuelve las clases CSS asociadas al menú. - classes: AttrClasses, + classes: Classes, /// Devuelve el estilo visual seleccionado. nav_kind: nav::Kind, /// Devuelve la distribución y orientación seleccionada. @@ -84,7 +84,7 @@ impl Nav { /// Modifica la lista de clases CSS aplicadas al menú. #[builder_fn] pub fn with_classes(mut self, op: ClassesOp, classes: impl AsRef) -> Self { - self.classes.alter_value(op, classes); + self.classes.alter_classes(op, classes); self } diff --git a/extensions/pagetop-bootsier/src/theme/nav/item.rs b/extensions/pagetop-bootsier/src/theme/nav/item.rs index 3189f28d..06bb7353 100644 --- a/extensions/pagetop-bootsier/src/theme/nav/item.rs +++ b/extensions/pagetop-bootsier/src/theme/nav/item.rs @@ -81,7 +81,7 @@ pub struct Item { #[getters(skip)] id: AttrId, /// Devuelve las clases CSS asociadas al elemento. - classes: AttrClasses, + classes: Classes, /// Devuelve el tipo de elemento representado. item_kind: ItemKind, } @@ -293,7 +293,7 @@ impl Item { /// Modifica la lista de clases CSS aplicadas al elemento. #[builder_fn] pub fn with_classes(mut self, op: ClassesOp, classes: impl AsRef) -> Self { - self.classes.alter_value(op, classes); + self.classes.alter_classes(op, classes); self } } diff --git a/extensions/pagetop-bootsier/src/theme/navbar/component.rs b/extensions/pagetop-bootsier/src/theme/navbar/component.rs index 26eeb43b..77aa5e57 100644 --- a/extensions/pagetop-bootsier/src/theme/navbar/component.rs +++ b/extensions/pagetop-bootsier/src/theme/navbar/component.rs @@ -19,7 +19,7 @@ pub struct Navbar { #[getters(skip)] id: AttrId, /// Devuelve las clases CSS asociadas a la barra de navegación. - classes: AttrClasses, + classes: Classes, /// Devuelve el punto de ruptura configurado. expand: BreakPoint, /// Devuelve la disposición configurada para la barra de navegación. @@ -230,7 +230,7 @@ impl Navbar { /// - Definir la apariencia del texto ([`classes::Text`]). #[builder_fn] pub fn with_classes(mut self, op: ClassesOp, classes: impl AsRef) -> Self { - self.classes.alter_value(op, classes); + self.classes.alter_classes(op, classes); self } diff --git a/extensions/pagetop-bootsier/src/theme/offcanvas/component.rs b/extensions/pagetop-bootsier/src/theme/offcanvas/component.rs index 4c3f979d..fe990681 100644 --- a/extensions/pagetop-bootsier/src/theme/offcanvas/component.rs +++ b/extensions/pagetop-bootsier/src/theme/offcanvas/component.rs @@ -26,7 +26,7 @@ pub struct Offcanvas { #[getters(skip)] id: AttrId, /// Devuelve las clases CSS asociadas al panel. - classes: AttrClasses, + classes: Classes, /// Devuelve el título del panel. title: L10n, /// Devuelve el punto de ruptura configurado para cambiar el comportamiento del panel. @@ -80,7 +80,7 @@ impl Offcanvas { /// Modifica la lista de clases CSS aplicadas al panel. #[builder_fn] pub fn with_classes(mut self, op: ClassesOp, classes: impl AsRef) -> Self { - self.classes.alter_value(op, classes); + self.classes.alter_classes(op, classes); self } diff --git a/src/base/component/block.rs b/src/base/component/block.rs index 98e08c32..77eacfec 100644 --- a/src/base/component/block.rs +++ b/src/base/component/block.rs @@ -9,7 +9,7 @@ pub struct Block { #[getters(skip)] id: AttrId, /// Devuelve las clases CSS asociadas al bloque. - classes: AttrClasses, + classes: Classes, /// Devuelve el título del bloque. title: L10n, /// Devuelve la lista de componentes hijo del bloque. @@ -62,7 +62,7 @@ impl Block { /// Modifica la lista de clases CSS aplicadas al bloque. #[builder_fn] pub fn with_classes(mut self, op: ClassesOp, classes: impl AsRef) -> Self { - self.classes.alter_value(op, classes); + self.classes.alter_classes(op, classes); self } diff --git a/src/html.rs b/src/html.rs index 67285069..ea718a34 100644 --- a/src/html.rs +++ b/src/html.rs @@ -24,8 +24,8 @@ pub use logo::PageTopSvg; mod attr; pub use attr::{Attr, AttrId, AttrName, AttrValue}; -mod attr_classes; -pub use attr_classes::{AttrClasses, ClassesOp}; +mod classes; +pub use classes::{Classes, ClassesOp}; mod unit; pub use unit::UnitValue; diff --git a/src/html/attr_classes.rs b/src/html/classes.rs similarity index 72% rename from src/html/attr_classes.rs rename to src/html/classes.rs index 02db82a2..2fd2fbf4 100644 --- a/src/html/attr_classes.rs +++ b/src/html/classes.rs @@ -1,16 +1,18 @@ use crate::{builder_fn, AutoDefault}; -/// Operaciones disponibles sobre la lista de clases en [`AttrClasses`]. +use std::borrow::Cow; + +/// Operaciones disponibles sobre la lista de clases en [`Classes`]. pub enum ClassesOp { /// Añade al final (si no existe). Add, /// Añade al principio. Prepend, - /// Elimina coincidencias. + /// Elimina la(s) clase(s) indicada(s). Remove, - /// Sustituye una o varias por las nuevas (`Replace("old other")`). - Replace(String), - /// Alterna presencia/ausencia. + /// Sustituye una o varias clases por otras nuevas (`Replace("old other".into())`). + Replace(Cow<'static, str>), + /// Alterna presencia/ausencia de una o más clases. Toggle, /// Sustituye toda la lista. Set, @@ -23,34 +25,40 @@ pub enum ClassesOp { /// /// # Normalización /// -/// - El [orden de las clases no es relevante](https://stackoverflow.com/a/1321712) en CSS. -/// - No se permiten clases duplicadas. +/// - El [orden de las clases no es relevante](https://stackoverflow.com/a/1321712) en CSS, pero +/// [`ClassesOp`] ofrece operaciones para controlar su orden de aparición. /// - Las clases se convierten a minúsculas. +/// - No se permiten clases duplicadas. /// - Las clases vacías se ignoran. /// /// # Ejemplo /// /// ```rust /// # use pagetop::prelude::*; -/// let classes = AttrClasses::new("Btn btn-primary") -/// .with_value(ClassesOp::Add, "Active") -/// .with_value(ClassesOp::Remove, "btn-primary"); +/// let classes = Classes::new("Btn btn-primary") +/// .with_classes(ClassesOp::Add, "Active") +/// .with_classes(ClassesOp::Remove, "btn-primary"); /// /// assert_eq!(classes.get(), Some("btn active".to_string())); /// assert!(classes.contains("active")); /// ``` #[derive(AutoDefault, Clone, Debug)] -pub struct AttrClasses(Vec); +pub struct Classes(Vec); -impl AttrClasses { +impl Classes { + /// Crea una nueva lista de clases a partir de la clase o clases proporcionadas en `classes`. pub fn new(classes: impl AsRef) -> Self { - Self::default().with_value(ClassesOp::Prepend, classes) + Self::default().with_classes(ClassesOp::Prepend, classes) } - // **< AttrClasses BUILDER >******************************************************************** + // **< Classes BUILDER >************************************************************************ + /// Modifica la lista de clases según la operación indicada. + /// + /// Realiza la operación indicada en `op` para las clases proporcionadas en `classes` sobre la + /// lista de clases actual. #[builder_fn] - pub fn with_value(mut self, op: ClassesOp, classes: impl AsRef) -> Self { + pub fn with_classes(mut self, op: ClassesOp, classes: impl AsRef) -> Self { let classes = classes.as_ref().to_ascii_lowercase(); let classes: Vec<&str> = classes.split_ascii_whitespace().collect(); @@ -114,7 +122,7 @@ impl AttrClasses { } } - // **< AttrClasses GETTERS >******************************************************************** + // **< Classes GETTERS >************************************************************************ /// Devuelve la cadena de clases, si existe. pub fn get(&self) -> Option { @@ -127,7 +135,7 @@ impl AttrClasses { /// Devuelve `true` si la clase está presente. pub fn contains(&self, class: impl AsRef) -> bool { - let class = class.as_ref(); - self.0.iter().any(|c| c == class) + let class = class.as_ref().to_ascii_lowercase(); + self.0.iter().any(|c| c == &class) } } diff --git a/src/response/page.rs b/src/response/page.rs index 1384fcd7..83fe00ba 100644 --- a/src/response/page.rs +++ b/src/response/page.rs @@ -25,7 +25,7 @@ use crate::core::theme::{DefaultRegion, Region, RegionRef, TemplateRef, ThemeRef use crate::html::{html, Markup, DOCTYPE}; use crate::html::{Assets, Favicon, JavaScript, StyleSheet}; use crate::html::{Attr, AttrId}; -use crate::html::{AttrClasses, ClassesOp}; +use crate::html::{Classes, ClassesOp}; use crate::locale::{CharacterDirection, L10n, LangId, LanguageIdentifier}; use crate::service::HttpRequest; use crate::{builder_fn, AutoDefault}; @@ -94,7 +94,7 @@ pub struct Page { metadata : Vec<(&'static str, &'static str)>, properties : Vec<(&'static str, &'static str)>, body_id : AttrId, - body_classes: AttrClasses, + body_classes: Classes, context : Context, } @@ -111,7 +111,7 @@ impl Page { metadata : Vec::default(), properties : Vec::default(), body_id : AttrId::default(), - body_classes: AttrClasses::default(), + body_classes: Classes::default(), context : Context::new(Some(request)), } } @@ -153,10 +153,10 @@ impl Page { self } - /// Modifica las clases CSS del elemento `` con una operación sobre [`AttrClasses`]. + /// Modifica las clases CSS del elemento `` con una operación sobre [`Classes`]. #[builder_fn] pub fn with_body_classes(mut self, op: ClassesOp, classes: impl AsRef) -> Self { - self.body_classes.alter_value(op, classes); + self.body_classes.alter_classes(op, classes); self } @@ -204,7 +204,7 @@ impl Page { } /// Devuelve las clases CSS del elemento ``. - pub fn body_classes(&self) -> &AttrClasses { + pub fn body_classes(&self) -> &Classes { &self.body_classes }