Compare commits

...

2 commits

31 changed files with 205 additions and 441 deletions

12
Cargo.lock generated
View file

@ -982,6 +982,17 @@ dependencies = [
"wasi 0.14.7+wasi-0.2.4", "wasi 0.14.7+wasi-0.2.4",
] ]
[[package]]
name = "getter-methods"
version = "2.0.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c43d815f896a3c730f0d76b8348a1700dc8d8fd6c377e4590d531bdd646574d8"
dependencies = [
"proc-macro2",
"quote",
"syn",
]
[[package]] [[package]]
name = "ghash" name = "ghash"
version = "0.5.1" version = "0.5.1"
@ -1558,6 +1569,7 @@ dependencies = [
"config", "config",
"figlet-rs", "figlet-rs",
"fluent-templates", "fluent-templates",
"getter-methods",
"indoc", "indoc",
"itoa", "itoa",
"pagetop-aliner", "pagetop-aliner",

View file

@ -20,6 +20,7 @@ colored = "3.0"
concat-string = "1.0" concat-string = "1.0"
config = { version = "0.15", default-features = false, features = ["toml"] } config = { version = "0.15", default-features = false, features = ["toml"] }
figlet-rs = "0.1" figlet-rs = "0.1"
getter-methods = "2.0"
indoc = "2.0" indoc = "2.0"
itoa = "1.0" itoa = "1.0"
parking_lot = "0.12" parking_lot = "0.12"

View file

@ -1,5 +1,5 @@
e404-description = Oops! Page Not Found e404_description = Oops! Page Not Found
e404-message = The page you are looking for may have been removed, had its name changed, or is temporarily unavailable. e404_message = The page you are looking for may have been removed, had its name changed, or is temporarily unavailable.
e500-description = Oops! Unexpected Error e500_description = Oops! Unexpected Error
e500-message = We're having an issue. Please report this error to an administrator. e500_message = We're having an issue. Please report this error to an administrator.
back-homepage = Back to homepage back_homepage = Back to homepage

View file

@ -1,9 +1,9 @@
header = Header region_header = Header
nav_branding = Navigation branding region region_nav_branding = Navigation branding region
nav_main = Main navigation region region_nav_main = Main navigation region
nav_additional = Additional navigation region (eg search form, social icons, etc) region_nav_additional = Additional navigation region (eg search form, social icons, etc)
breadcrumb = Breadcrumb region_breadcrumb = Breadcrumb
content = Main content region_content = Main content
sidebar_first = Sidebar first region_sidebar_first = Sidebar first
sidebar_second = Sidebar second region_sidebar_second = Sidebar second
footer = Footer region_footer = Footer

View file

@ -1,5 +1,5 @@
e404-description = ¡Vaya! Página No Encontrada e404_description = ¡Vaya! Página No Encontrada
e404-message = La página que está buscando puede haber sido eliminada, cambiada de nombre o no está disponible temporalmente. e404_message = La página que está buscando puede haber sido eliminada, cambiada de nombre o no está disponible temporalmente.
e500-description = ¡Vaya! Error Inesperado e500_description = ¡Vaya! Error Inesperado
e500-message = Está ocurriendo una incidencia. Por favor, informe de este error a un administrador. e500_message = Está ocurriendo una incidencia. Por favor, informe de este error a un administrador.
back-homepage = Volver al inicio back_homepage = Volver al inicio

View file

@ -1,9 +1,9 @@
header = Cabecera region_header = Cabecera
nav_branding = Navegación y marca region_nav_branding = Navegación y marca
nav_main = Navegación principal region_nav_main = Navegación principal
nav_additional = Navegación adicional (p.e. formulario de búsqueda, iconos sociales, etc.) region_nav_additional = Navegación adicional (p.e. formulario de búsqueda, iconos sociales, etc.)
breadcrumb = Ruta de posicionamiento region_breadcrumb = Ruta de posicionamiento
content = Contenido principal region_content = Contenido principal
sidebar_first = Barra lateral primera region_sidebar_first = Barra lateral primera
sidebar_second = Barra lateral segunda region_sidebar_second = Barra lateral segunda
footer = Pie region_footer = Pie

View file

@ -6,13 +6,17 @@ use crate::prelude::*;
/// ///
/// Envuelve un contenido con la etiqueta HTML indicada por [`container::Kind`]. Sólo se renderiza /// Envuelve un contenido con la etiqueta HTML indicada por [`container::Kind`]. Sólo se renderiza
/// si existen componentes hijos (*children*). /// si existen componentes hijos (*children*).
#[rustfmt::skip] #[derive(AutoDefault, Getters)]
#[derive(AutoDefault)]
pub struct Container { pub struct Container {
#[getters(skip)]
id: AttrId, id: AttrId,
/// Devuelve las clases CSS asociadas al contenedor.
classes: AttrClasses, classes: AttrClasses,
/// Devuelve el tipo semántico del contenedor.
container_kind: container::Kind, container_kind: container::Kind,
/// Devuelve el comportamiento para el ancho del contenedor.
container_width: container::Width, container_width: container::Width,
/// Devuelve la lista de componentes (`children`) del contenedor.
children: Children, children: Children,
} }
@ -26,7 +30,7 @@ impl Component for Container {
} }
fn setup_before_prepare(&mut self, _cx: &mut Context) { fn setup_before_prepare(&mut self, _cx: &mut Context) {
self.alter_classes(ClassesOp::Prepend, self.width().to_class()); self.alter_classes(ClassesOp::Prepend, self.container_width().to_class());
} }
fn prepare_component(&self, cx: &mut Context) -> PrepareMarkup { fn prepare_component(&self, cx: &mut Context) -> PrepareMarkup {
@ -34,7 +38,7 @@ impl Component for Container {
if output.is_empty() { if output.is_empty() {
return PrepareMarkup::None; return PrepareMarkup::None;
} }
let style = match self.width() { let style = match self.container_width() {
container::Width::FluidMax(w) if w.is_measurable() => { container::Width::FluidMax(w) if w.is_measurable() => {
Some(join!("max-width: ", w.to_string(), ";")) Some(join!("max-width: ", w.to_string(), ";"))
} }
@ -159,26 +163,4 @@ impl Container {
self.children.alter_child(op); self.children.alter_child(op);
self self
} }
// **< Container GETTERS >**********************************************************************
/// Devuelve las clases CSS asociadas al contenedor.
pub fn classes(&self) -> &AttrClasses {
&self.classes
}
/// Devuelve el tipo semántico del contenedor.
pub fn container_kind(&self) -> &container::Kind {
&self.container_kind
}
/// Devuelve el comportamiento para el ancho del contenedor.
pub fn width(&self) -> &container::Width {
&self.container_width
}
/// Devuelve la lista de componentes (`children`) del contenedor.
pub fn children(&self) -> &Children {
&self.children
}
} }

View file

@ -19,20 +19,31 @@ use crate::LOCALES_BOOTSIER;
/// ///
/// Ver ejemplo en el módulo [`dropdown`]. /// Ver ejemplo en el módulo [`dropdown`].
/// Si no contiene elementos, el componente **no se renderiza**. /// Si no contiene elementos, el componente **no se renderiza**.
#[rustfmt::skip] #[derive(AutoDefault, Getters)]
#[derive(AutoDefault)]
pub struct Dropdown { pub struct Dropdown {
#[getters(skip)]
id: AttrId, id: AttrId,
/// Devuelve las clases CSS asociadas al menú desplegable.
classes: AttrClasses, classes: AttrClasses,
/// Devuelve el título del menú desplegable.
title: L10n, title: L10n,
/// Devuelve el tamaño configurado del botón.
button_size: ButtonSize, button_size: ButtonSize,
/// Devuelve el color/estilo configurado del botón.
button_color: ButtonColor, button_color: ButtonColor,
/// Devuelve si se debe desdoblar (*split*) el botón (botón de acción + *toggle*).
button_split: bool, button_split: bool,
/// Devuelve si el botón del menú está integrado en un grupo de botones.
button_grouped: bool, button_grouped: bool,
/// Devuelve la política de cierre automático del menú desplegado.
auto_close: dropdown::AutoClose, auto_close: dropdown::AutoClose,
/// Devuelve la dirección de despliegue configurada.
direction: dropdown::Direction, direction: dropdown::Direction,
/// Devuelve la configuración de alineación horizontal del menú desplegable.
menu_align: dropdown::MenuAlign, menu_align: dropdown::MenuAlign,
/// Devuelve la posición configurada para el menú desplegable.
menu_position: dropdown::MenuPosition, menu_position: dropdown::MenuPosition,
/// Devuelve la lista de elementos del menú.
items: Children, items: Children,
} }
@ -48,7 +59,7 @@ impl Component for Dropdown {
fn setup_before_prepare(&mut self, _cx: &mut Context) { fn setup_before_prepare(&mut self, _cx: &mut Context) {
self.alter_classes( self.alter_classes(
ClassesOp::Prepend, ClassesOp::Prepend,
self.direction().class_with(self.button_grouped()), self.direction().class_with(*self.button_grouped()),
); );
} }
@ -82,7 +93,7 @@ impl Component for Dropdown {
}); });
// Renderizado en modo split (dos botones) o simple (un botón). // Renderizado en modo split (dos botones) o simple (un botón).
@if self.button_split() { @if *self.button_split() {
// Botón principal (acción/etiqueta). // Botón principal (acción/etiqueta).
@let btn = html! { @let btn = html! {
button button
@ -242,61 +253,4 @@ impl Dropdown {
self.items.alter_typed(op); self.items.alter_typed(op);
self self
} }
// **< Dropdown GETTERS >***********************************************************************
/// Devuelve las clases CSS asociadas al menú desplegable.
pub fn classes(&self) -> &AttrClasses {
&self.classes
}
/// Devuelve el título del menú desplegable.
pub fn title(&self) -> &L10n {
&self.title
}
/// Devuelve el tamaño configurado del botón.
pub fn button_size(&self) -> &ButtonSize {
&self.button_size
}
/// Devuelve el color/estilo configurado del botón.
pub fn button_color(&self) -> &ButtonColor {
&self.button_color
}
/// Devuelve si se debe desdoblar (*split*) el botón (botón de acción + *toggle*).
pub fn button_split(&self) -> bool {
self.button_split
}
/// Devuelve si el botón del menú está integrado en un grupo de botones.
pub fn button_grouped(&self) -> bool {
self.button_grouped
}
/// Devuelve la política de cierre automático del menú desplegado.
pub fn auto_close(&self) -> &dropdown::AutoClose {
&self.auto_close
}
/// Devuelve la dirección de despliegue configurada.
pub fn direction(&self) -> &dropdown::Direction {
&self.direction
}
/// Devuelve la configuración de alineación horizontal del menú desplegable.
pub fn menu_align(&self) -> &dropdown::MenuAlign {
&self.menu_align
}
/// Devuelve la posición configurada para el menú desplegable.
pub fn menu_position(&self) -> &dropdown::MenuPosition {
&self.menu_position
}
/// Devuelve la lista de elementos (`children`) del menú.
pub fn items(&self) -> &Children {
&self.items
}
} }

View file

@ -42,11 +42,13 @@ pub enum ItemKind {
/// ///
/// Permite definir identificador, clases de estilo adicionales o tipo de interacción asociada, /// Permite definir identificador, clases de estilo adicionales o tipo de interacción asociada,
/// manteniendo una interfaz común para renderizar todos los elementos del menú. /// manteniendo una interfaz común para renderizar todos los elementos del menú.
#[rustfmt::skip] #[derive(AutoDefault, Getters)]
#[derive(AutoDefault)]
pub struct Item { pub struct Item {
#[getters(skip)]
id: AttrId, id: AttrId,
/// Devuelve las clases CSS asociadas al elemento.
classes: AttrClasses, classes: AttrClasses,
/// Devuelve el tipo de elemento representado.
item_kind: ItemKind, item_kind: ItemKind,
} }
@ -266,16 +268,4 @@ impl Item {
self.classes.alter_value(op, classes); self.classes.alter_value(op, classes);
self self
} }
// **< Item GETTERS >***************************************************************************
/// Devuelve las clases CSS asociadas al elemento.
pub fn classes(&self) -> &AttrClasses {
&self.classes
}
/// Devuelve el tipo de elemento representado.
pub fn item_kind(&self) -> &ItemKind {
&self.item_kind
}
} }

View file

@ -13,9 +13,9 @@ pub enum IconKind {
}, },
} }
#[rustfmt::skip] #[derive(AutoDefault, Getters)]
#[derive(AutoDefault)]
pub struct Icon { pub struct Icon {
/// Devuelve las clases CSS asociadas al icono.
classes: AttrClasses, classes: AttrClasses,
icon_kind: IconKind, icon_kind: IconKind,
aria_label: AttrL10n, aria_label: AttrL10n,
@ -116,19 +116,4 @@ impl Icon {
self.aria_label.alter_value(label); self.aria_label.alter_value(label);
self self
} }
// **< Icon GETTERS >***************************************************************************
/// Devuelve las clases CSS asociadas al icono.
pub fn classes(&self) -> &AttrClasses {
&self.classes
}
pub fn icon_kind(&self) -> &IconKind {
&self.icon_kind
}
pub fn aria_label(&self) -> &AttrL10n {
&self.aria_label
}
} }

View file

@ -9,14 +9,18 @@ use crate::prelude::*;
/// ([`classes::Border`](crate::theme::classes::Border)) y **redondeo de esquinas** /// ([`classes::Border`](crate::theme::classes::Border)) y **redondeo de esquinas**
/// ([`classes::Rounded`](crate::theme::classes::Rounded)). /// ([`classes::Rounded`](crate::theme::classes::Rounded)).
/// - Resuelve el texto alternativo `alt` con **localización** mediante [`L10n`]. /// - Resuelve el texto alternativo `alt` con **localización** mediante [`L10n`].
#[rustfmt::skip] #[derive(AutoDefault, Getters)]
#[derive(AutoDefault)]
pub struct Image { pub struct Image {
#[getters(skip)]
id: AttrId, id: AttrId,
/// Devuelve las clases CSS asociadas a la imagen.
classes: AttrClasses, classes: AttrClasses,
/// Devuelve las dimensiones de la imagen.
size: image::Size, size: image::Size,
/// Devuelve el origen de la imagen.
source: image::Source, source: image::Source,
alt : AttrL10n, /// Devuelve el texto alternativo localizado.
alternative: AttrL10n,
} }
impl Component for Image { impl Component for Image {
@ -107,35 +111,13 @@ impl Image {
self self
} }
/// Define el texto alternativo localizado ([`L10n`]) para la imagen. /// Define un *texto localizado* ([`L10n`]) alternativo para la imagen.
/// ///
/// Se recomienda siempre aportar un texto alternativo salvo que la imagen sea puramente /// Se recomienda siempre aportar un texto alternativo salvo que la imagen sea puramente
/// decorativa. /// decorativa.
#[builder_fn] #[builder_fn]
pub fn with_alternative(mut self, alt: L10n) -> Self { pub fn with_alternative(mut self, alt: L10n) -> Self {
self.alt.alter_value(alt); self.alternative.alter_value(alt);
self self
} }
// **< Image GETTERS >**************************************************************************
/// Devuelve las clases CSS asociadas a la imagen.
pub fn classes(&self) -> &AttrClasses {
&self.classes
}
/// Devuelve las dimensiones de la imagen.
pub fn size(&self) -> &image::Size {
&self.size
}
/// Devuelve el origen de la imagen.
pub fn source(&self) -> &image::Source {
&self.source
}
/// Devuelve el texto alternativo localizado.
pub fn alternative(&self) -> &AttrL10n {
&self.alt
}
} }

View file

@ -10,14 +10,18 @@ use crate::prelude::*;
/// ///
/// Ver ejemplo en el módulo [`nav`]. /// Ver ejemplo en el módulo [`nav`].
/// Si no contiene elementos, el componente **no se renderiza**. /// Si no contiene elementos, el componente **no se renderiza**.
#[rustfmt::skip] #[derive(AutoDefault, Getters)]
#[derive(AutoDefault)]
pub struct Nav { pub struct Nav {
#[getters(skip)]
id: AttrId, id: AttrId,
/// Devuelve las clases CSS asociadas al menú.
classes: AttrClasses, classes: AttrClasses,
items : Children, /// Devuelve el estilo visual seleccionado.
nav_kind: nav::Kind, nav_kind: nav::Kind,
/// Devuelve la distribución y orientación seleccionada.
nav_layout: nav::Layout, nav_layout: nav::Layout,
/// Devuelve la lista de elementos del menú.
items: Children,
} }
impl Component for Nav { impl Component for Nav {
@ -110,26 +114,4 @@ impl Nav {
self.items.alter_typed(op); self.items.alter_typed(op);
self self
} }
// **< Nav GETTERS >****************************************************************************
/// Devuelve las clases CSS asociadas al menú.
pub fn classes(&self) -> &AttrClasses {
&self.classes
}
/// Devuelve el estilo visual seleccionado.
pub fn nav_kind(&self) -> &nav::Kind {
&self.nav_kind
}
/// Devuelve la distribución y orientación seleccionada.
pub fn nav_layout(&self) -> &nav::Layout {
&self.nav_layout
}
/// Devuelve la lista de elementos (`children`) del menú.
pub fn items(&self) -> &Children {
&self.items
}
} }

View file

@ -72,11 +72,13 @@ impl ItemKind {
/// ///
/// Permite definir identificador, clases de estilo adicionales o tipo de interacción asociada, /// Permite definir identificador, clases de estilo adicionales o tipo de interacción asociada,
/// manteniendo una interfaz común para renderizar todos los elementos del menú. /// manteniendo una interfaz común para renderizar todos los elementos del menú.
#[rustfmt::skip] #[derive(AutoDefault, Getters)]
#[derive(AutoDefault)]
pub struct Item { pub struct Item {
#[getters(skip)]
id: AttrId, id: AttrId,
/// Devuelve las clases CSS asociadas al elemento.
classes: AttrClasses, classes: AttrClasses,
/// Devuelve el tipo de elemento representado.
item_kind: ItemKind, item_kind: ItemKind,
} }
@ -269,16 +271,4 @@ impl Item {
self.classes.alter_value(op, classes); self.classes.alter_value(op, classes);
self self
} }
// **< Item GETTERS >***************************************************************************
/// Devuelve las clases CSS asociadas al elemento.
pub fn classes(&self) -> &AttrClasses {
&self.classes
}
/// Devuelve el tipo de elemento representado.
pub fn item_kind(&self) -> &ItemKind {
&self.item_kind
}
} }

View file

@ -2,7 +2,7 @@
//! //!
//! Cada [`navbar::Item`](crate::theme::navbar::Item) representa un elemento individual de la barra //! Cada [`navbar::Item`](crate::theme::navbar::Item) representa un elemento individual de la barra
//! de navegación [`Navbar`], con distintos comportamientos según su finalidad, como menús //! de navegación [`Navbar`], con distintos comportamientos según su finalidad, como menús
//! [`Nav`](crate::theme::Nav) o textos localizados usando [`L10n`](pagetop::locale::L10n). //! [`Nav`](crate::theme::Nav) o *textos localizados* usando [`L10n`](pagetop::locale::L10n).
//! //!
//! También puede mostrar una marca de identidad ([`navbar::Brand`](crate::theme::navbar::Brand)) //! También puede mostrar una marca de identidad ([`navbar::Brand`](crate::theme::navbar::Brand))
//! que identifique la compañía, producto o nombre del proyecto asociado a la solución web. //! que identifique la compañía, producto o nombre del proyecto asociado a la solución web.

View file

@ -11,14 +11,18 @@ use crate::prelude::*;
/// - Si no hay imagen ([`with_image()`](Self::with_image)) ni título /// - Si no hay imagen ([`with_image()`](Self::with_image)) ni título
/// ([`with_title()`](Self::with_title)), la marca de identidad no se renderiza. /// ([`with_title()`](Self::with_title)), la marca de identidad no se renderiza.
/// - El eslogan ([`with_slogan()`](Self::with_slogan)) es opcional; por defecto no tiene contenido. /// - El eslogan ([`with_slogan()`](Self::with_slogan)) es opcional; por defecto no tiene contenido.
#[rustfmt::skip] #[derive(AutoDefault, Getters)]
#[derive(AutoDefault)]
pub struct Brand { pub struct Brand {
#[getters(skip)]
id: AttrId, id: AttrId,
/// Devuelve la imagen de marca (si la hay).
image: Typed<Image>, image: Typed<Image>,
/// Devuelve el título de la identidad de marca.
#[default(_code = "L10n::n(&global::SETTINGS.app.name)")] #[default(_code = "L10n::n(&global::SETTINGS.app.name)")]
title: L10n, title: L10n,
/// Devuelve el eslogan de la marca.
slogan: L10n, slogan: L10n,
/// Devuelve la función que resuelve la URL asociada a la marca (si existe).
#[default(_code = "Some(|_| \"/\")")] #[default(_code = "Some(|_| \"/\")")]
path: Option<FnPathByContext>, path: Option<FnPathByContext>,
} }
@ -86,26 +90,4 @@ impl Brand {
self.path = path; self.path = path;
self self
} }
// **< Brand GETTERS >**************************************************************************
/// Devuelve la imagen de marca (si la hay).
pub fn image(&self) -> &Typed<Image> {
&self.image
}
/// Devuelve el título de la identidad de marca.
pub fn title(&self) -> &L10n {
&self.title
}
/// Devuelve el eslogan de la marca.
pub fn slogan(&self) -> &L10n {
&self.slogan
}
/// Devuelve la función que resuelve la URL asociada a la marca (si existe).
pub fn path(&self) -> &Option<FnPathByContext> {
&self.path
}
} }

View file

@ -14,14 +14,19 @@ const TOGGLE_OFFCANVAS: &str = "offcanvas";
/// ///
/// Ver ejemplos en el módulo [`navbar`]. /// Ver ejemplos en el módulo [`navbar`].
/// Si no contiene elementos, el componente **no se renderiza**. /// Si no contiene elementos, el componente **no se renderiza**.
#[rustfmt::skip] #[derive(AutoDefault, Getters)]
#[derive(AutoDefault)]
pub struct Navbar { pub struct Navbar {
#[getters(skip)]
id: AttrId, id: AttrId,
/// Devuelve las clases CSS asociadas a la barra de navegación.
classes: AttrClasses, classes: AttrClasses,
/// Devuelve el punto de ruptura configurado.
expand: BreakPoint, expand: BreakPoint,
/// Devuelve la disposición configurada para la barra de navegación.
layout: navbar::Layout, layout: navbar::Layout,
/// Devuelve la posición configurada para la barra de navegación.
position: navbar::Position, position: navbar::Position,
/// Devuelve la lista de contenidos.
items: Children, items: Children,
} }
@ -263,31 +268,4 @@ impl Navbar {
self.items.alter_typed(op); self.items.alter_typed(op);
self self
} }
// **< Navbar GETTERS >*************************************************************************
/// Devuelve las clases CSS asociadas a la barra de navegación.
pub fn classes(&self) -> &AttrClasses {
&self.classes
}
/// Devuelve el punto de ruptura configurado.
pub fn expand(&self) -> &BreakPoint {
&self.expand
}
/// Devuelve la disposición configurada para la barra de navegación.
pub fn layout(&self) -> &navbar::Layout {
&self.layout
}
/// Devuelve la posición configurada para la barra de navegación.
pub fn position(&self) -> &navbar::Position {
&self.position
}
/// Devuelve la lista de contenidos (`children`).
pub fn items(&self) -> &Children {
&self.items
}
} }

View file

@ -20,7 +20,7 @@ pub enum Item {
Brand(Typed<navbar::Brand>), Brand(Typed<navbar::Brand>),
/// Representa un menú de navegación [`Nav`](crate::theme::Nav). /// Representa un menú de navegación [`Nav`](crate::theme::Nav).
Nav(Typed<Nav>), Nav(Typed<Nav>),
/// Representa un texto libre localizado. /// Representa un *texto localizado* libre.
Text(L10n), Text(L10n),
} }
@ -88,7 +88,7 @@ impl Item {
Self::Nav(Typed::with(item)) Self::Nav(Typed::with(item))
} }
/// Crea un elemento de texto localizado, mostrado sin interacción. /// Crea un elemento con un *texto localizado*, mostrado sin interacción.
pub fn text(item: L10n) -> Self { pub fn text(item: L10n) -> Self {
Self::Text(item) Self::Text(item)
} }

View file

@ -21,17 +21,25 @@ use crate::LOCALES_BOOTSIER;
/// ///
/// Ver ejemplo en el módulo [`offcanvas`]. /// Ver ejemplo en el módulo [`offcanvas`].
/// Si no contiene elementos, el componente **no se renderiza**. /// Si no contiene elementos, el componente **no se renderiza**.
#[rustfmt::skip] #[derive(AutoDefault, Getters)]
#[derive(AutoDefault)]
pub struct Offcanvas { pub struct Offcanvas {
#[getters(skip)]
id: AttrId, id: AttrId,
/// Devuelve las clases CSS asociadas al panel.
classes: AttrClasses, classes: AttrClasses,
/// Devuelve el título del panel.
title: L10n, title: L10n,
/// Devuelve el punto de ruptura configurado para cambiar el comportamiento del panel.
breakpoint: BreakPoint, breakpoint: BreakPoint,
/// Devuelve el comportamiento configurado para la capa de fondo.
backdrop: offcanvas::Backdrop, backdrop: offcanvas::Backdrop,
scrolling : offcanvas::BodyScroll, /// Indica si la página principal puede desplazarse mientras el panel está abierto.
body_scroll: offcanvas::BodyScroll,
/// Devuelve la posición de inicio del panel.
placement: offcanvas::Placement, placement: offcanvas::Placement,
/// Devuelve el estado inicial del panel.
visibility: offcanvas::Visibility, visibility: offcanvas::Visibility,
/// Devuelve la lista de componentes (`children`) del panel.
children: Children, children: Children,
} }
@ -109,7 +117,7 @@ impl Offcanvas {
/// Permite o bloquea el desplazamiento de la página principal mientras el panel está abierto. /// Permite o bloquea el desplazamiento de la página principal mientras el panel está abierto.
#[builder_fn] #[builder_fn]
pub fn with_body_scroll(mut self, scrolling: offcanvas::BodyScroll) -> Self { pub fn with_body_scroll(mut self, scrolling: offcanvas::BodyScroll) -> Self {
self.scrolling = scrolling; self.body_scroll = scrolling;
self self
} }
@ -141,48 +149,6 @@ impl Offcanvas {
self self
} }
// **< Offcanvas GETTERS >**********************************************************************
/// Devuelve las clases CSS asociadas al panel.
pub fn classes(&self) -> &AttrClasses {
&self.classes
}
/// Devuelve el título del panel.
pub fn title(&self) -> &L10n {
&self.title
}
/// Devuelve el punto de ruptura configurado para cambiar el comportamiento del panel.
pub fn breakpoint(&self) -> &BreakPoint {
&self.breakpoint
}
/// Devuelve el comportamiento configurado para la capa de fondo.
pub fn backdrop(&self) -> &offcanvas::Backdrop {
&self.backdrop
}
/// Indica si la página principal puede desplazarse mientras el panel está abierto.
pub fn body_scroll(&self) -> &offcanvas::BodyScroll {
&self.scrolling
}
/// Devuelve la posición de inicio del panel.
pub fn placement(&self) -> &offcanvas::Placement {
&self.placement
}
/// Devuelve el estado inicial del panel.
pub fn visibility(&self) -> &offcanvas::Visibility {
&self.visibility
}
/// Devuelve la lista de componentes (`children`) del panel.
pub fn children(&self) -> &Children {
&self.children
}
// **< Offcanvas HELPERS >********************************************************************** // **< Offcanvas HELPERS >**********************************************************************
pub(crate) fn render_offcanvas(&self, cx: &mut Context, extra: Option<&Children>) -> Markup { pub(crate) fn render_offcanvas(&self, cx: &mut Context, extra: Option<&Children>) -> Markup {

View file

@ -4,12 +4,15 @@ use crate::prelude::*;
/// ///
/// Los bloques se utilizan como contenedores de otros componentes o contenidos, con un título /// Los bloques se utilizan como contenedores de otros componentes o contenidos, con un título
/// opcional y un cuerpo que sólo se renderiza si existen componentes hijos (*children*). /// opcional y un cuerpo que sólo se renderiza si existen componentes hijos (*children*).
#[rustfmt::skip] #[derive(AutoDefault, Getters)]
#[derive(AutoDefault)]
pub struct Block { pub struct Block {
#[getters(skip)]
id: AttrId, id: AttrId,
/// Devuelve las clases CSS asociadas al bloque.
classes: AttrClasses, classes: AttrClasses,
/// Devuelve el título del bloque.
title: L10n, title: L10n,
/// Devuelve la lista de componentes hijo del bloque.
children: Children, children: Children,
} }
@ -83,21 +86,4 @@ impl Block {
self.children.alter_child(op); self.children.alter_child(op);
self self
} }
// **< Block GETTERS >**************************************************************************
/// Devuelve las clases CSS asociadas al bloque.
pub fn classes(&self) -> &AttrClasses {
&self.classes
}
/// Devuelve el título del bloque.
pub fn title(&self) -> &L10n {
&self.title
}
/// Devuelve la lista de componentes (`children`) del bloque.
pub fn children(&self) -> &Children {
&self.children
}
} }

View file

@ -76,12 +76,17 @@ pub enum IntroOpening {
/// })), /// })),
/// ); /// );
/// ``` /// ```
#[rustfmt::skip] #[derive(Getters)]
pub struct Intro { pub struct Intro {
/// Devuelve el título de entrada.
title: L10n, title: L10n,
/// Devuelve el eslogan de la entrada.
slogan: L10n, slogan: L10n,
/// Devuelve el botón de llamada a la acción, si existe.
button: Option<(L10n, FnPathByContext)>, button: Option<(L10n, FnPathByContext)>,
/// Devuelve el modo de apertura configurado.
opening: IntroOpening, opening: IntroOpening,
/// Devuelve la lista de componentes hijo de la intro.
children: Children, children: Children,
} }
@ -110,7 +115,7 @@ impl Component for Intro {
} }
fn prepare_component(&self, cx: &mut Context) -> PrepareMarkup { fn prepare_component(&self, cx: &mut Context) -> PrepareMarkup {
if self.opening() == IntroOpening::PageTop { if *self.opening() == IntroOpening::PageTop {
cx.alter_assets(ContextOp::AddJavaScript(JavaScript::on_load_async("intro-js", |cx| cx.alter_assets(ContextOp::AddJavaScript(JavaScript::on_load_async("intro-js", |cx|
util::indoc!(r#" util::indoc!(r#"
try { try {
@ -163,7 +168,7 @@ impl Component for Intro {
} }
} }
div class="intro-text__children" { div class="intro-text__children" {
@if self.opening() == IntroOpening::PageTop { @if *self.opening() == IntroOpening::PageTop {
p { (L10n::l("intro_text1").using(cx)) } p { (L10n::l("intro_text1").using(cx)) }
div id="intro-badges" { div id="intro-badges" {
img img
@ -289,31 +294,4 @@ impl Intro {
self.children.alter_child(op); self.children.alter_child(op);
self self
} }
// **< Intro GETTERS >**************************************************************************
/// Devuelve el título de entrada.
pub fn title(&self) -> &L10n {
&self.title
}
/// Devuelve el eslogan de la entrada.
pub fn slogan(&self) -> &L10n {
&self.slogan
}
/// Devuelve el botón de llamada a la acción, si existe.
pub fn button(&self) -> Option<(&L10n, &FnPathByContext)> {
self.button.as_ref().map(|(txt, lnk)| (txt, lnk))
}
/// Devuelve el modo de apertura configurado.
pub fn opening(&self) -> IntroOpening {
self.opening
}
/// Devuelve la lista de componentes (`children`) de la intro.
pub fn children(&self) -> &Children {
&self.children
}
} }

View file

@ -8,8 +8,9 @@ const LINK: &str = "<a href=\"https://pagetop.cillero.es\" rel=\"noopener norefe
/// Por defecto, usando [`default()`](Self::default) sólo se muestra un reconocimiento a PageTop. /// Por defecto, usando [`default()`](Self::default) sólo se muestra un reconocimiento a PageTop.
/// Sin embargo, se puede usar [`new()`](Self::new) para crear una instancia con un texto de /// Sin embargo, se puede usar [`new()`](Self::new) para crear una instancia con un texto de
/// copyright predeterminado. /// copyright predeterminado.
#[derive(AutoDefault)] #[derive(AutoDefault, Getters)]
pub struct PoweredBy { pub struct PoweredBy {
/// Devuelve el texto de copyright actual, si existe.
copyright: Option<String>, copyright: Option<String>,
} }
@ -56,11 +57,4 @@ impl PoweredBy {
self.copyright = copyright.map(Into::into); self.copyright = copyright.map(Into::into);
self self
} }
// **< PoweredBy GETTERS >**********************************************************************
/// Devuelve el texto de copyright actual, si existe.
pub fn copyright(&self) -> Option<&str> {
self.copyright.as_deref()
}
} }

View file

@ -24,7 +24,7 @@ use crate::{actions_boxed, service};
/// } /// }
/// ``` /// ```
pub trait Extension: AnyInfo + Send + Sync { pub trait Extension: AnyInfo + Send + Sync {
/// Nombre localizado de la extensión legible para el usuario. /// Nombre de la extensión como *texto localizado* legible para el usuario.
/// ///
/// Predeterminado por el [`short_name()`](AnyInfo::short_name) del tipo asociado a la /// Predeterminado por el [`short_name()`](AnyInfo::short_name) del tipo asociado a la
/// extensión. /// extensión.
@ -32,7 +32,7 @@ pub trait Extension: AnyInfo + Send + Sync {
L10n::n(self.short_name()) L10n::n(self.short_name())
} }
/// Descripción corta localizada de la extensión para paneles, listados, etc. /// Descripción corta de la extensión como *texto localizado* para paneles, listados, etc.
/// ///
/// Por defecto devuelve un valor vacío (`L10n::default()`). /// Por defecto devuelve un valor vacío (`L10n::default()`).
fn description(&self) -> L10n { fn description(&self) -> L10n {

View file

@ -55,7 +55,7 @@ pub trait Region {
/// las clases del contenedor de la región (`"region region-<name>"`). /// las clases del contenedor de la región (`"region region-<name>"`).
fn name(&self) -> &'static str; fn name(&self) -> &'static str;
/// Devuelve la etiqueta de accesibilidad localizada asociada a la región. /// Devuelve un *texto localizado* como etiqueta de accesibilidad asociada a la región.
/// ///
/// En la implementación predeterminada de [`Self::render()`], este valor se usa como /// En la implementación predeterminada de [`Self::render()`], este valor se usa como
/// `aria-label` del contenedor de la región. /// `aria-label` del contenedor de la región.
@ -64,8 +64,8 @@ pub trait Region {
/// Renderiza el contenedor de la región. /// Renderiza el contenedor de la región.
/// ///
/// Por defecto, recupera del [`Context`] el contenido de la región y, si no está vacío, lo /// Por defecto, recupera del [`Context`] el contenido de la región y, si no está vacío, lo
/// envuelve en un `<div>` con clases `"region region-<name>"` y un `aria-label` basado en la /// envuelve en un `<div>` con clases `"region region-<name>"` y un `aria-label` basado en el
/// etiqueta localizada de la región: /// *texto localizado* de la etiqueta asociada a la región:
/// ///
/// ```html /// ```html
/// <div class="region region-<name>" role="region" aria-label="<label>"> /// <div class="region region-<name>" role="region" aria-label="<label>">

View file

@ -158,7 +158,7 @@ pub trait Theme: Extension + Send + Sync {
/// Contenido predeterminado para la página de error "*403 - Forbidden*". /// Contenido predeterminado para la página de error "*403 - Forbidden*".
/// ///
/// Los temas pueden sobrescribir este método para personalizar el diseño y el contenido de la /// Los temas pueden sobrescribir este método para personalizar el diseño y el contenido de la
/// página de error, manteniendo o no el mensaje de los textos localizados. /// página de error, manteniendo o no el mensaje de los *textos localizados*.
fn error403(&self, page: &mut Page) -> Markup { fn error403(&self, page: &mut Page) -> Markup {
html! { div { h1 { (L10n::l("error403_notice").using(page)) } } } html! { div { h1 { (L10n::l("error403_notice").using(page)) } } }
} }
@ -166,7 +166,7 @@ pub trait Theme: Extension + Send + Sync {
/// Contenido predeterminado para la página de error "*404 - Not Found*". /// Contenido predeterminado para la página de error "*404 - Not Found*".
/// ///
/// Los temas pueden sobrescribir este método para personalizar el diseño y el contenido de la /// Los temas pueden sobrescribir este método para personalizar el diseño y el contenido de la
/// página de error, manteniendo o no el mensaje de los textos localizados. /// página de error, manteniendo o no el mensaje de los *textos localizados*.
fn error404(&self, page: &mut Page) -> Markup { fn error404(&self, page: &mut Page) -> Markup {
html! { div { h1 { (L10n::l("error404_notice").using(page)) } } } html! { div { h1 { (L10n::l("error404_notice").using(page)) } } }
} }

View file

@ -10,7 +10,7 @@ use crate::{builder_fn, AutoDefault};
/// ```rust /// ```rust
/// # use pagetop::prelude::*; /// # use pagetop::prelude::*;
/// // Traducción por clave en las locales por defecto de PageTop. /// // Traducción por clave en las locales por defecto de PageTop.
/// let hello = AttrL10n::new(L10n::l("test-hello-world")); /// let hello = AttrL10n::new(L10n::l("test_hello_world"));
/// ///
/// // Español disponible. /// // Español disponible.
/// assert_eq!( /// assert_eq!(

View file

@ -137,6 +137,8 @@ pub use pagetop_macros::{builder_fn, html, main, test, AutoDefault};
pub use pagetop_statics::{resource, StaticResource}; pub use pagetop_statics::{resource, StaticResource};
pub use getter_methods::Getters;
/// Contenedor para un conjunto de recursos embebidos. /// Contenedor para un conjunto de recursos embebidos.
#[derive(AutoDefault)] #[derive(AutoDefault)]
pub struct StaticResources { pub struct StaticResources {

View file

@ -310,7 +310,7 @@ enum L10nOp {
Translate(Cow<'static, str>), Translate(Cow<'static, str>),
} }
/// Crea instancias para traducir textos localizados. /// Crea instancias para traducir *textos localizados*.
/// ///
/// Cada instancia puede representar: /// Cada instancia puede representar:
/// ///

View file

@ -1,6 +1,6 @@
test-hello-world = Hello world! test_hello_world = Hello world!
test-hello-user = Hello, { $userName }! test_hello_user = Hello, { $userName }!
test-shared-photos = test_shared_photos =
{ $userName } { $photoCount -> { $userName } { $photoCount ->
[one] added a new photo [one] added a new photo
*[other] added { $photoCount } new photos *[other] added { $photoCount } new photos

View file

@ -1,6 +1,6 @@
test-hello-world = ¡Hola mundo! test_hello_world = ¡Hola mundo!
test-hello-user = ¡Hola, { $userName }! test_hello_user = ¡Hola, { $userName }!
test-shared-photos = test_shared_photos =
{ $userName } { $photoCount -> { $userName } { $photoCount ->
[one] ha añadido una nueva foto [one] ha añadido una nueva foto
*[other] ha añadido { $photoCount } nuevas fotos *[other] ha añadido { $photoCount } nuevas fotos

View file

@ -6,7 +6,7 @@ pub use crate::PAGETOP_VERSION;
pub use crate::{builder_fn, html, main, test}; pub use crate::{builder_fn, html, main, test};
pub use crate::{AutoDefault, StaticResources, UniqueId, Weight}; pub use crate::{AutoDefault, Getters, StaticResources, UniqueId, Weight};
// MACROS. // MACROS.

View file

@ -12,7 +12,7 @@ async fn literal_text() {
async fn translation_without_args() { async fn translation_without_args() {
let _app = service::test::init_service(Application::new().test()).await; let _app = service::test::init_service(Application::new().test()).await;
let l10n = L10n::l("test-hello-world"); let l10n = L10n::l("test_hello_world");
let translation = l10n.lookup(&LangMatch::resolve("es-ES")); let translation = l10n.lookup(&LangMatch::resolve("es-ES"));
assert_eq!(translation, Some("¡Hola mundo!".to_string())); assert_eq!(translation, Some("¡Hola mundo!".to_string()));
} }
@ -21,7 +21,7 @@ async fn translation_without_args() {
async fn translation_with_args() { async fn translation_with_args() {
let _app = service::test::init_service(Application::new().test()).await; let _app = service::test::init_service(Application::new().test()).await;
let l10n = L10n::l("test-hello-user").with_arg("userName", "Manuel"); let l10n = L10n::l("test_hello_user").with_arg("userName", "Manuel");
let translation = l10n.lookup(&LangMatch::resolve("es-ES")); let translation = l10n.lookup(&LangMatch::resolve("es-ES"));
assert_eq!(translation, Some("¡Hola, Manuel!".to_string())); assert_eq!(translation, Some("¡Hola, Manuel!".to_string()));
} }
@ -30,7 +30,7 @@ async fn translation_with_args() {
async fn translation_with_plural_and_select() { async fn translation_with_plural_and_select() {
let _app = service::test::init_service(Application::new().test()).await; let _app = service::test::init_service(Application::new().test()).await;
let l10n = L10n::l("test-shared-photos").with_args(vec![ let l10n = L10n::l("test_shared_photos").with_args(vec![
("userName", "Roberto"), ("userName", "Roberto"),
("photoCount", "3"), ("photoCount", "3"),
("userGender", "male"), ("userGender", "male"),
@ -43,7 +43,7 @@ async fn translation_with_plural_and_select() {
async fn check_fallback_language() { async fn check_fallback_language() {
let _app = service::test::init_service(Application::new().test()).await; let _app = service::test::init_service(Application::new().test()).await;
let l10n = L10n::l("test-hello-world"); let l10n = L10n::l("test_hello_world");
let translation = l10n.lookup(&LangMatch::resolve("xx-YY")); // Retrocede a "en-US". let translation = l10n.lookup(&LangMatch::resolve("xx-YY")); // Retrocede a "en-US".
assert_eq!(translation, Some("Hello world!".to_string())); assert_eq!(translation, Some("Hello world!".to_string()));
} }