♻️ (locale): Sustituye Attr<Lc> por Lc::none()
This commit is contained in:
parent
c3ff8a6ff8
commit
213aa18b12
17 changed files with 275 additions and 146 deletions
|
|
@ -74,9 +74,9 @@ pub struct Button {
|
|||
/// Devuelve el valor del botón.
|
||||
value: AttrValue,
|
||||
/// Devuelve la etiqueta del botón.
|
||||
label: Attr<Lc>,
|
||||
label: Lc,
|
||||
/// Devuelve el texto emergente del botón (atributo `title`).
|
||||
title: Attr<Lc>,
|
||||
title: Lc,
|
||||
/// Devuelve si el botón recibe el foco automáticamente al cargar la página.
|
||||
autofocus: bool,
|
||||
/// Devuelve si el botón está deshabilitado.
|
||||
|
|
@ -124,7 +124,7 @@ impl Button {
|
|||
pub fn submit(label: Lc) -> Self {
|
||||
Self {
|
||||
kind: ButtonAction::Submit,
|
||||
label: Attr::some(label),
|
||||
label,
|
||||
..Default::default()
|
||||
}
|
||||
}
|
||||
|
|
@ -135,7 +135,7 @@ impl Button {
|
|||
pub fn reset(label: Lc) -> Self {
|
||||
Self {
|
||||
kind: ButtonAction::Reset,
|
||||
label: Attr::some(label),
|
||||
label,
|
||||
..Default::default()
|
||||
}
|
||||
}
|
||||
|
|
@ -147,7 +147,7 @@ impl Button {
|
|||
pub fn plain(label: Lc) -> Self {
|
||||
Self {
|
||||
kind: ButtonAction::Plain,
|
||||
label: Attr::some(label),
|
||||
label,
|
||||
..Default::default()
|
||||
}
|
||||
}
|
||||
|
|
@ -188,17 +188,17 @@ impl Button {
|
|||
self
|
||||
}
|
||||
|
||||
/// Establece o elimina la etiqueta visible del botón (basta pasar `None` para quitarla).
|
||||
/// Establece la etiqueta visible del botón (usa [`Lc::none()`] para quitarla).
|
||||
#[builder_fn]
|
||||
pub fn with_label(mut self, label: impl Into<Option<Lc>>) -> Self {
|
||||
self.label.alter_opt(label.into());
|
||||
pub fn with_label(mut self, label: Lc) -> Self {
|
||||
self.label = label;
|
||||
self
|
||||
}
|
||||
|
||||
/// Establece o elimina el texto emergente del botón (basta pasar `None` para quitarlo).
|
||||
/// Establece el texto emergente del botón (usa [`Lc::none()`] para quitarlo).
|
||||
#[builder_fn]
|
||||
pub fn with_title(mut self, title: impl Into<Option<Lc>>) -> Self {
|
||||
self.title.alter_opt(title.into());
|
||||
pub fn with_title(mut self, title: Lc) -> Self {
|
||||
self.title = title;
|
||||
self
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -103,9 +103,9 @@ pub struct Field {
|
|||
/// Devuelve el nombre compartido por todas las casillas del grupo.
|
||||
name: AttrName,
|
||||
/// Devuelve la etiqueta del grupo.
|
||||
label: Attr<Lc>,
|
||||
label: Lc,
|
||||
/// Devuelve el texto de ayuda del grupo.
|
||||
help_text: Attr<Lc>,
|
||||
help_text: Lc,
|
||||
/// Devuelve las casillas del grupo.
|
||||
items: Vec<Item>,
|
||||
/// Devuelve si todo el grupo está deshabilitado.
|
||||
|
|
@ -207,17 +207,17 @@ impl Field {
|
|||
self
|
||||
}
|
||||
|
||||
/// Establece o elimina la etiqueta visible del grupo (basta pasar `None` para quitarla).
|
||||
/// Establece la etiqueta visible del grupo (usa [`Lc::none()`] para quitarla).
|
||||
#[builder_fn]
|
||||
pub fn with_label(mut self, label: impl Into<Option<Lc>>) -> Self {
|
||||
self.label.alter_opt(label.into());
|
||||
pub fn with_label(mut self, label: Lc) -> Self {
|
||||
self.label = label;
|
||||
self
|
||||
}
|
||||
|
||||
/// Establece o elimina el texto de ayuda del grupo (basta pasar `None` para quitarlo).
|
||||
/// Establece el texto de ayuda del grupo (usa [`Lc::none()`] para quitarlo).
|
||||
#[builder_fn]
|
||||
pub fn with_help_text(mut self, help_text: impl Into<Option<Lc>>) -> Self {
|
||||
self.help_text.alter_opt(help_text.into());
|
||||
pub fn with_help_text(mut self, help_text: Lc) -> Self {
|
||||
self.help_text = help_text;
|
||||
self
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -46,7 +46,7 @@ pub struct Checkbox {
|
|||
/// Devuelve el nombre del campo.
|
||||
name: AttrName,
|
||||
/// Devuelve la etiqueta del control.
|
||||
label: Attr<Lc>,
|
||||
label: Lc,
|
||||
/// Devuelve si el control debe estar marcado/activo por defecto.
|
||||
checked: bool,
|
||||
/// Devuelve si el control recibe el foco automáticamente al cargar la página.
|
||||
|
|
@ -182,10 +182,10 @@ impl Checkbox {
|
|||
self
|
||||
}
|
||||
|
||||
/// Establece o elimina la etiqueta visible del control (basta pasar `None` para quitarla).
|
||||
/// Establece la etiqueta visible del control (usa [`Lc::none()`] para quitarla).
|
||||
#[builder_fn]
|
||||
pub fn with_label(mut self, label: impl Into<Option<Lc>>) -> Self {
|
||||
self.label.alter_opt(label.into());
|
||||
pub fn with_label(mut self, label: Lc) -> Self {
|
||||
self.label = label;
|
||||
self
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -27,9 +27,9 @@ pub struct Fieldset {
|
|||
/// Devuelve identificador, clases CSS, atributos HTML y valores extra del componente.
|
||||
props: Props,
|
||||
/// Devuelve la leyenda del `fieldset`.
|
||||
legend: Attr<Lc>,
|
||||
legend: Lc,
|
||||
/// Devuelve la descripción del `fieldset`.
|
||||
description: Attr<Lc>,
|
||||
description: Lc,
|
||||
/// Devuelve si el `fieldset` está deshabilitado.
|
||||
disabled: bool,
|
||||
/// Devuelve la lista de componentes del `fieldset`.
|
||||
|
|
@ -84,17 +84,17 @@ impl Fieldset {
|
|||
self
|
||||
}
|
||||
|
||||
/// Establece o elimina la leyenda del `fieldset` (basta pasar `None` para quitarla).
|
||||
/// Establece la leyenda del `fieldset` (usa [`Lc::none()`] para quitarla).
|
||||
#[builder_fn]
|
||||
pub fn with_legend(mut self, legend: impl Into<Option<Lc>>) -> Self {
|
||||
self.legend.alter_opt(legend.into());
|
||||
pub fn with_legend(mut self, legend: Lc) -> Self {
|
||||
self.legend = legend;
|
||||
self
|
||||
}
|
||||
|
||||
/// Establece o elimina la descripción del `fieldset` (basta pasar `None` para quitarla).
|
||||
/// Establece la descripción del `fieldset` (usa [`Lc::none()`] para quitarla).
|
||||
#[builder_fn]
|
||||
pub fn with_description(mut self, description: impl Into<Option<Lc>>) -> Self {
|
||||
self.description.alter_opt(description.into());
|
||||
pub fn with_description(mut self, description: Lc) -> Self {
|
||||
self.description = description;
|
||||
self
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -161,15 +161,15 @@ pub struct Field {
|
|||
/// Devuelve el valor inicial del campo.
|
||||
value: AttrValue,
|
||||
/// Devuelve la etiqueta del campo.
|
||||
label: Attr<Lc>,
|
||||
label: Lc,
|
||||
/// Devuelve el texto de ayuda del campo.
|
||||
help_text: Attr<Lc>,
|
||||
help_text: Lc,
|
||||
/// Devuelve la longitud mínima permitida en caracteres.
|
||||
minlength: Attr<u16>,
|
||||
/// Devuelve la longitud máxima permitida en caracteres.
|
||||
maxlength: Attr<u16>,
|
||||
/// Devuelve el texto indicativo del campo.
|
||||
placeholder: Attr<Lc>,
|
||||
placeholder: Lc,
|
||||
/// Devuelve la configuración de autocompletado del campo.
|
||||
autocomplete: Attr<form::Autocomplete>,
|
||||
/// Devuelve si el campo recibe el foco automáticamente al cargar la página.
|
||||
|
|
@ -418,17 +418,17 @@ impl Field {
|
|||
self
|
||||
}
|
||||
|
||||
/// Establece o elimina la etiqueta visible del campo (basta pasar `None` para quitarla).
|
||||
/// Establece la etiqueta visible del campo (usa [`Lc::none()`] para quitarla).
|
||||
#[builder_fn]
|
||||
pub fn with_label(mut self, label: impl Into<Option<Lc>>) -> Self {
|
||||
self.label.alter_opt(label.into());
|
||||
pub fn with_label(mut self, label: Lc) -> Self {
|
||||
self.label = label;
|
||||
self
|
||||
}
|
||||
|
||||
/// Establece o elimina el texto de ayuda del campo (basta pasar `None` para quitarlo).
|
||||
/// Establece el texto de ayuda del campo (usa [`Lc::none()`] para quitarlo).
|
||||
#[builder_fn]
|
||||
pub fn with_help_text(mut self, help_text: impl Into<Option<Lc>>) -> Self {
|
||||
self.help_text.alter_opt(help_text.into());
|
||||
pub fn with_help_text(mut self, help_text: Lc) -> Self {
|
||||
self.help_text = help_text;
|
||||
self
|
||||
}
|
||||
|
||||
|
|
@ -446,13 +446,13 @@ impl Field {
|
|||
self
|
||||
}
|
||||
|
||||
/// Establece o elimina el texto indicativo del campo (`None` para quitarlo).
|
||||
/// Establece el texto indicativo del campo (usa [`Lc::none()`] para quitarlo).
|
||||
///
|
||||
/// Este texto aparece en el mismo campo y desaparece en cuanto el usuario empieza a escribir.
|
||||
/// Al ser texto visible para el usuario se acepta [`Lc`] para poder localizarlo.
|
||||
#[builder_fn]
|
||||
pub fn with_placeholder(mut self, placeholder: impl Into<Option<Lc>>) -> Self {
|
||||
self.placeholder.alter_opt(placeholder.into());
|
||||
pub fn with_placeholder(mut self, placeholder: Lc) -> Self {
|
||||
self.placeholder = placeholder;
|
||||
self
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -37,9 +37,9 @@ pub struct Number {
|
|||
/// Devuelve el valor inicial del campo.
|
||||
value: Attr<u64>,
|
||||
/// Devuelve la etiqueta del campo.
|
||||
label: Attr<Lc>,
|
||||
label: Lc,
|
||||
/// Devuelve el texto de ayuda del campo.
|
||||
help_text: Attr<Lc>,
|
||||
help_text: Lc,
|
||||
/// Devuelve el valor mínimo permitido.
|
||||
min: Attr<u64>,
|
||||
/// Devuelve el valor máximo permitido.
|
||||
|
|
@ -151,17 +151,17 @@ impl Number {
|
|||
self
|
||||
}
|
||||
|
||||
/// Establece o elimina la etiqueta visible del campo (basta pasar `None` para quitarla).
|
||||
/// Establece la etiqueta visible del campo (usa [`Lc::none()`] para quitarla).
|
||||
#[builder_fn]
|
||||
pub fn with_label(mut self, label: impl Into<Option<Lc>>) -> Self {
|
||||
self.label.alter_opt(label.into());
|
||||
pub fn with_label(mut self, label: Lc) -> Self {
|
||||
self.label = label;
|
||||
self
|
||||
}
|
||||
|
||||
/// Establece o elimina el texto de ayuda del campo (basta pasar `None` para quitarlo).
|
||||
/// Establece el texto de ayuda del campo (usa [`Lc::none()`] para quitarlo).
|
||||
#[builder_fn]
|
||||
pub fn with_help_text(mut self, help_text: impl Into<Option<Lc>>) -> Self {
|
||||
self.help_text.alter_opt(help_text.into());
|
||||
pub fn with_help_text(mut self, help_text: Lc) -> Self {
|
||||
self.help_text = help_text;
|
||||
self
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -101,9 +101,9 @@ pub struct Field {
|
|||
/// Devuelve el nombre compartido por todos los botones de opción del grupo.
|
||||
name: AttrName,
|
||||
/// Devuelve la etiqueta del grupo.
|
||||
label: Attr<Lc>,
|
||||
label: Lc,
|
||||
/// Devuelve el texto de ayuda del grupo.
|
||||
help_text: Attr<Lc>,
|
||||
help_text: Lc,
|
||||
/// Devuelve las opciones del grupo.
|
||||
items: Vec<Item>,
|
||||
/// Devuelve si la selección de alguna opción del grupo es obligatoria.
|
||||
|
|
@ -227,17 +227,17 @@ impl Field {
|
|||
self
|
||||
}
|
||||
|
||||
/// Establece o elimina la etiqueta visible del grupo (basta pasar `None` para quitarla).
|
||||
/// Establece la etiqueta visible del grupo (usa [`Lc::none()`] para quitarla).
|
||||
#[builder_fn]
|
||||
pub fn with_label(mut self, label: impl Into<Option<Lc>>) -> Self {
|
||||
self.label.alter_opt(label.into());
|
||||
pub fn with_label(mut self, label: Lc) -> Self {
|
||||
self.label = label;
|
||||
self
|
||||
}
|
||||
|
||||
/// Establece o elimina el texto de ayuda del grupo (basta pasar `None` para quitarlo).
|
||||
/// Establece el texto de ayuda del grupo (usa [`Lc::none()`] para quitarlo).
|
||||
#[builder_fn]
|
||||
pub fn with_help_text(mut self, help_text: impl Into<Option<Lc>>) -> Self {
|
||||
self.help_text.alter_opt(help_text.into());
|
||||
pub fn with_help_text(mut self, help_text: Lc) -> Self {
|
||||
self.help_text = help_text;
|
||||
self
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -38,9 +38,9 @@ pub struct Range {
|
|||
/// Devuelve el valor inicial del campo.
|
||||
value: Attr<f64>,
|
||||
/// Devuelve la etiqueta del campo.
|
||||
label: Attr<Lc>,
|
||||
label: Lc,
|
||||
/// Devuelve el texto de ayuda del campo.
|
||||
help_text: Attr<Lc>,
|
||||
help_text: Lc,
|
||||
/// Devuelve el valor mínimo permitido.
|
||||
min: Attr<f64>,
|
||||
/// Devuelve el valor máximo permitido.
|
||||
|
|
@ -139,17 +139,17 @@ impl Range {
|
|||
self
|
||||
}
|
||||
|
||||
/// Establece o elimina la etiqueta visible del campo (basta pasar `None` para quitarla).
|
||||
/// Establece la etiqueta visible del campo (usa [`Lc::none()`] para quitarla).
|
||||
#[builder_fn]
|
||||
pub fn with_label(mut self, label: impl Into<Option<Lc>>) -> Self {
|
||||
self.label.alter_opt(label.into());
|
||||
pub fn with_label(mut self, label: Lc) -> Self {
|
||||
self.label = label;
|
||||
self
|
||||
}
|
||||
|
||||
/// Establece o elimina el texto de ayuda del campo (basta pasar `None` para quitarlo).
|
||||
/// Establece el texto de ayuda del campo (usa [`Lc::none()`] para quitarlo).
|
||||
#[builder_fn]
|
||||
pub fn with_help_text(mut self, help_text: impl Into<Option<Lc>>) -> Self {
|
||||
self.help_text.alter_opt(help_text.into());
|
||||
pub fn with_help_text(mut self, help_text: Lc) -> Self {
|
||||
self.help_text = help_text;
|
||||
self
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -197,9 +197,9 @@ pub struct Field {
|
|||
/// Devuelve el nombre del campo.
|
||||
name: AttrName,
|
||||
/// Devuelve la etiqueta del campo.
|
||||
label: Attr<Lc>,
|
||||
label: Lc,
|
||||
/// Devuelve el texto de ayuda del campo.
|
||||
help_text: Attr<Lc>,
|
||||
help_text: Lc,
|
||||
/// Devuelve las entradas de la lista (elementos individuales y grupos de elementos).
|
||||
entries: Vec<Entry>,
|
||||
/// Devuelve si la lista permite selección múltiple.
|
||||
|
|
@ -333,17 +333,17 @@ impl Field {
|
|||
self
|
||||
}
|
||||
|
||||
/// Establece o elimina la etiqueta visible del campo (basta pasar `None` para quitarla).
|
||||
/// Establece la etiqueta visible del campo (usa [`Lc::none()`] para quitarla).
|
||||
#[builder_fn]
|
||||
pub fn with_label(mut self, label: impl Into<Option<Lc>>) -> Self {
|
||||
self.label.alter_opt(label.into());
|
||||
pub fn with_label(mut self, label: Lc) -> Self {
|
||||
self.label = label;
|
||||
self
|
||||
}
|
||||
|
||||
/// Establece o elimina el texto de ayuda del campo (basta pasar `None` para quitarlo).
|
||||
/// Establece el texto de ayuda del campo (usa [`Lc::none()`] para quitarlo).
|
||||
#[builder_fn]
|
||||
pub fn with_help_text(mut self, help_text: impl Into<Option<Lc>>) -> Self {
|
||||
self.help_text.alter_opt(help_text.into());
|
||||
pub fn with_help_text(mut self, help_text: Lc) -> Self {
|
||||
self.help_text = help_text;
|
||||
self
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -40,9 +40,9 @@ pub struct Textarea {
|
|||
/// Devuelve el valor inicial del área de texto.
|
||||
value: AttrValue,
|
||||
/// Devuelve la etiqueta del campo.
|
||||
label: Attr<Lc>,
|
||||
label: Lc,
|
||||
/// Devuelve el texto de ayuda del campo.
|
||||
help_text: Attr<Lc>,
|
||||
help_text: Lc,
|
||||
/// Devuelve el número de filas visibles del área de texto.
|
||||
rows: Attr<u16>,
|
||||
/// Devuelve la longitud mínima permitida en caracteres.
|
||||
|
|
@ -50,7 +50,7 @@ pub struct Textarea {
|
|||
/// Devuelve la longitud máxima permitida en caracteres.
|
||||
maxlength: Attr<u16>,
|
||||
/// Devuelve el texto indicativo del área de texto.
|
||||
placeholder: Attr<Lc>,
|
||||
placeholder: Lc,
|
||||
/// Devuelve la configuración de autocompletado del campo.
|
||||
autocomplete: Attr<form::Autocomplete>,
|
||||
/// Devuelve si el campo recibe el foco automáticamente al cargar la página.
|
||||
|
|
@ -166,17 +166,17 @@ impl Textarea {
|
|||
self
|
||||
}
|
||||
|
||||
/// Establece o elimina la etiqueta visible del campo (basta pasar `None` para quitarla).
|
||||
/// Establece la etiqueta visible del campo (usa [`Lc::none()`] para quitarla).
|
||||
#[builder_fn]
|
||||
pub fn with_label(mut self, label: impl Into<Option<Lc>>) -> Self {
|
||||
self.label.alter_opt(label.into());
|
||||
pub fn with_label(mut self, label: Lc) -> Self {
|
||||
self.label = label;
|
||||
self
|
||||
}
|
||||
|
||||
/// Establece o elimina el texto de ayuda del campo (basta pasar `None` para quitarlo).
|
||||
/// Establece el texto de ayuda del campo (usa [`Lc::none()`] para quitarlo).
|
||||
#[builder_fn]
|
||||
pub fn with_help_text(mut self, help_text: impl Into<Option<Lc>>) -> Self {
|
||||
self.help_text.alter_opt(help_text.into());
|
||||
pub fn with_help_text(mut self, help_text: Lc) -> Self {
|
||||
self.help_text = help_text;
|
||||
self
|
||||
}
|
||||
|
||||
|
|
@ -204,13 +204,13 @@ impl Textarea {
|
|||
self
|
||||
}
|
||||
|
||||
/// Establece o elimina el texto indicativo del área de texto (`None` para quitarlo).
|
||||
/// Establece el texto indicativo del área de texto (usa [`Lc::none()`] para quitarlo).
|
||||
///
|
||||
/// Este texto aparece en el área de texto y desaparece en cuanto el usuario empieza a escribir.
|
||||
/// Al ser texto visible para el usuario se acepta [`Lc`] para poder localizarlo.
|
||||
#[builder_fn]
|
||||
pub fn with_placeholder(mut self, placeholder: impl Into<Option<Lc>>) -> Self {
|
||||
self.placeholder.alter_opt(placeholder.into());
|
||||
pub fn with_placeholder(mut self, placeholder: Lc) -> Self {
|
||||
self.placeholder = placeholder;
|
||||
self
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -29,7 +29,7 @@ pub struct Image {
|
|||
/// Devuelve el origen de la imagen.
|
||||
source: image::Source,
|
||||
/// Devuelve el texto alternativo localizado.
|
||||
alternative: Attr<Lc>,
|
||||
alternative: Lc,
|
||||
}
|
||||
|
||||
#[async_trait]
|
||||
|
|
@ -140,7 +140,7 @@ impl Image {
|
|||
/// decorativa.
|
||||
#[builder_fn]
|
||||
pub fn with_alternative(mut self, alt: Lc) -> Self {
|
||||
self.alternative.alter_value(alt);
|
||||
self.alternative = alt;
|
||||
self
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,4 +1,3 @@
|
|||
use crate::locale::{LangId, Lc};
|
||||
use crate::{AutoDefault, builder_fn, util};
|
||||
|
||||
/// Valor opcional para atributos HTML.
|
||||
|
|
@ -7,8 +6,9 @@ use crate::{AutoDefault, builder_fn, util};
|
|||
/// opcionales, uniformes y tipados.
|
||||
///
|
||||
/// Este tipo **no impone ninguna normalización ni semántica concreta**; dichas reglas se definen en
|
||||
/// implementaciones concretas como `Attr<Lc>` y `Attr<String>`, o en tipos específicos como
|
||||
/// [`AttrName`].
|
||||
/// implementaciones concretas como `Attr<String>`, o en tipos específicos como [`AttrName`]. Para
|
||||
/// texto localizado usa directamente [`Lc`](crate::locale::Lc) que ya representa su propia ausencia
|
||||
/// con [`Lc::none()`](crate::locale::Lc::none()), sin necesidad de envolverlo en `Attr<Lc>`.
|
||||
#[derive(AutoDefault, Clone, Debug)]
|
||||
pub struct Attr<T>(Option<T>);
|
||||
|
||||
|
|
@ -72,52 +72,6 @@ impl<T> Attr<T> {
|
|||
}
|
||||
}
|
||||
|
||||
// **< Attr<Lc> >***********************************************************************************
|
||||
|
||||
/// Extiende [`Attr`] para [texto localizado](crate::locale) en atributos HTML.
|
||||
///
|
||||
/// Encapsula un [`Lc`] para manejar traducciones de forma segura en atributos.
|
||||
///
|
||||
/// # Ejemplo
|
||||
///
|
||||
/// ```rust
|
||||
/// # use pagetop::prelude::*;
|
||||
/// // Traducción por clave en las locales por defecto de PageTop.
|
||||
/// let hello = Attr::<Lc>::new(Lc::l("test_hello_world"));
|
||||
///
|
||||
/// // Español disponible.
|
||||
/// assert_eq!(
|
||||
/// hello.lookup(&Locale::resolve("es-ES")),
|
||||
/// Some("¡Hola mundo!".to_string())
|
||||
/// );
|
||||
///
|
||||
/// // Japonés no disponible, traduce al idioma de respaldo (`"en-US"`).
|
||||
/// assert_eq!(
|
||||
/// hello.lookup(&Locale::resolve("ja-JP")),
|
||||
/// Some("Hello world!".to_string())
|
||||
/// );
|
||||
///
|
||||
/// // Uso típico en un atributo:
|
||||
/// let title = hello.value(&Locale::resolve("es-ES"));
|
||||
/// // Ejemplo: html! { a title=(title) { "Link" } }
|
||||
/// ```
|
||||
impl Attr<Lc> {
|
||||
/// Crea una nueva instancia `Attr<Lc>`.
|
||||
pub fn new(value: Lc) -> Self {
|
||||
Self::some(value)
|
||||
}
|
||||
|
||||
/// Devuelve la traducción para `language` si puede resolverse.
|
||||
pub fn lookup(&self, language: &impl LangId) -> Option<String> {
|
||||
self.0.as_ref()?.lookup(language)
|
||||
}
|
||||
|
||||
/// Devuelve la traducción para `language` o una cadena vacía si no existe.
|
||||
pub fn value(&self, language: &impl LangId) -> String {
|
||||
self.lookup(language).unwrap_or_default()
|
||||
}
|
||||
}
|
||||
|
||||
// **< Attr<String> >*******************************************************************************
|
||||
|
||||
/// Extiende [`Attr`] para cadenas de texto.
|
||||
|
|
|
|||
|
|
@ -32,6 +32,7 @@ enum LcKind {
|
|||
/// - Un texto puro (`n()`) que no requiere traducción.
|
||||
/// - Una clave para traducir un texto del conjunto de traducciones predefinidas de PageTop (`l()`).
|
||||
/// - Una clave para traducir de un conjunto concreto de traducciones (`t()`).
|
||||
/// - Ningún contenido (`none()`), para representar la ausencia en un campo `Lc` opcional.
|
||||
///
|
||||
/// # ¿Cuál usar, `get()`, `lookup()` o `using()`?
|
||||
///
|
||||
|
|
@ -122,6 +123,23 @@ impl Lc {
|
|||
}
|
||||
}
|
||||
|
||||
/// Crea una instancia **sin contenido**: no traduce nada y no representa ningún texto.
|
||||
///
|
||||
/// Equivale a [`Lc::default()`](Default::default), con un nombre más explícito. Útil para
|
||||
/// representar la ausencia en un campo `Lc` opcional sin requerir `Option<Lc>`:
|
||||
/// [`get()`](Self::get) y [`lookup()`](Self::lookup) devuelven `None`, y
|
||||
/// [`using()`](Self::using) devuelve un marcado vacío.
|
||||
///
|
||||
/// ```rust
|
||||
/// # use pagetop::prelude::*;
|
||||
/// assert_eq!(Lc::none().get(), None);
|
||||
/// ```
|
||||
pub fn none() -> Self {
|
||||
Self::default()
|
||||
}
|
||||
|
||||
// **< Lc BUILDER >*****************************************************************************
|
||||
|
||||
/// Añade un argumento `{$arg}` => `value` a la traducción.
|
||||
pub fn with_arg(mut self, arg: impl Into<CowStr>, value: impl Into<CowStr>) -> Self {
|
||||
self.args.push((arg.into(), value.into()));
|
||||
|
|
@ -142,6 +160,8 @@ impl Lc {
|
|||
self
|
||||
}
|
||||
|
||||
// **< Lc GETTERS >*****************************************************************************
|
||||
|
||||
/// Resuelve la traducción usando el idioma por defecto o, si no procede, el de respaldo de la
|
||||
/// aplicación.
|
||||
///
|
||||
|
|
|
|||
|
|
@ -25,8 +25,8 @@ use crate::core::component::{AssetsOp, ChildOp, ComponentRender};
|
|||
use crate::core::component::{Context, ContextError, Contextual};
|
||||
use crate::core::theme::{CoreRegions, RegionName, RegionRef, TemplateRef, ThemeRef};
|
||||
use crate::html::{Assets, Favicon, JavaScript, StyleSheet};
|
||||
use crate::html::{Attr, Props, PropsOp};
|
||||
use crate::html::{DOCTYPE, Markup, html};
|
||||
use crate::html::{Props, PropsOp};
|
||||
use crate::locale::{CharacterDirection, LangId, LanguageIdentifier, Lc};
|
||||
use crate::web::HttpRequest;
|
||||
use crate::{AutoDefault, builder_fn};
|
||||
|
|
@ -88,8 +88,8 @@ impl RegionName for ReservedRegions {
|
|||
#[rustfmt::skip]
|
||||
#[derive(AutoDefault)]
|
||||
pub struct Page {
|
||||
title : Attr<Lc>,
|
||||
description : Attr<Lc>,
|
||||
title : Lc,
|
||||
description: Lc,
|
||||
metadata : Vec<(&'static str, &'static str)>,
|
||||
properties : Vec<(&'static str, &'static str)>,
|
||||
context : Context,
|
||||
|
|
@ -128,14 +128,14 @@ impl Page {
|
|||
/// Establece el título de la página como un valor traducible.
|
||||
#[builder_fn]
|
||||
pub fn with_title(mut self, title: Lc) -> Self {
|
||||
self.title.alter_value(title);
|
||||
self.title = title;
|
||||
self
|
||||
}
|
||||
|
||||
/// Establece la descripción de la página como un valor traducible.
|
||||
#[builder_fn]
|
||||
pub fn with_description(mut self, description: Lc) -> Self {
|
||||
self.description.alter_value(description);
|
||||
self.description = description;
|
||||
self
|
||||
}
|
||||
|
||||
|
|
|
|||
45
tests/component_button.rs
Normal file
45
tests/component_button.rs
Normal file
|
|
@ -0,0 +1,45 @@
|
|||
use pagetop::prelude::*;
|
||||
|
||||
#[pagetop::test]
|
||||
async fn label_is_rendered_when_set() {
|
||||
let mut button = Button::submit(Lc::n("Save"));
|
||||
let html = button.render(&mut Context::default()).await.into_string();
|
||||
|
||||
assert!(html.contains("Save"));
|
||||
}
|
||||
|
||||
#[pagetop::test]
|
||||
async fn label_can_be_cleared_with_lc_none() {
|
||||
let mut button = Button::submit(Lc::n("Save")).with_label(Lc::none());
|
||||
let html = button.render(&mut Context::default()).await.into_string();
|
||||
|
||||
assert!(!html.contains("Save"));
|
||||
// The button itself must still render.
|
||||
assert!(html.contains("<button"));
|
||||
}
|
||||
|
||||
#[pagetop::test]
|
||||
async fn title_attribute_is_absent_by_default() {
|
||||
let mut button = Button::submit(Lc::n("Save"));
|
||||
let html = button.render(&mut Context::default()).await.into_string();
|
||||
|
||||
assert!(!html.contains("title="));
|
||||
}
|
||||
|
||||
#[pagetop::test]
|
||||
async fn title_attribute_is_present_when_set() {
|
||||
let mut button = Button::submit(Lc::n("Save")).with_title(Lc::n("Save changes"));
|
||||
let html = button.render(&mut Context::default()).await.into_string();
|
||||
|
||||
assert!(html.contains(r#"title="Save changes""#));
|
||||
}
|
||||
|
||||
#[pagetop::test]
|
||||
async fn title_attribute_can_be_cleared_with_lc_none() {
|
||||
let mut button = Button::submit(Lc::n("Save"))
|
||||
.with_title(Lc::n("Save changes"))
|
||||
.with_title(Lc::none());
|
||||
let html = button.render(&mut Context::default()).await.into_string();
|
||||
|
||||
assert!(!html.contains("title="));
|
||||
}
|
||||
72
tests/component_form_input.rs
Normal file
72
tests/component_form_input.rs
Normal file
|
|
@ -0,0 +1,72 @@
|
|||
use pagetop::prelude::*;
|
||||
|
||||
#[pagetop::test]
|
||||
async fn label_is_absent_by_default() {
|
||||
let mut field = form::input::Field::text();
|
||||
let html = field.render(&mut Context::default()).await.into_string();
|
||||
|
||||
assert!(!html.contains(r#"class="form-label""#));
|
||||
}
|
||||
|
||||
#[pagetop::test]
|
||||
async fn label_is_rendered_when_set() {
|
||||
let mut field = form::input::Field::text().with_label(Lc::n("Full name"));
|
||||
let html = field.render(&mut Context::default()).await.into_string();
|
||||
|
||||
assert!(html.contains(r#"class="form-label""#));
|
||||
assert!(html.contains("Full name"));
|
||||
}
|
||||
|
||||
#[pagetop::test]
|
||||
async fn label_can_be_cleared_with_lc_none() {
|
||||
let mut field = form::input::Field::text()
|
||||
.with_label(Lc::n("Full name"))
|
||||
.with_label(Lc::none());
|
||||
let html = field.render(&mut Context::default()).await.into_string();
|
||||
|
||||
assert!(!html.contains(r#"class="form-label""#));
|
||||
assert!(!html.contains("Full name"));
|
||||
}
|
||||
|
||||
#[pagetop::test]
|
||||
async fn help_text_is_absent_by_default() {
|
||||
let mut field = form::input::Field::text();
|
||||
let html = field.render(&mut Context::default()).await.into_string();
|
||||
|
||||
assert!(!html.contains(r#"class="form-text""#));
|
||||
}
|
||||
|
||||
#[pagetop::test]
|
||||
async fn help_text_is_rendered_when_set() {
|
||||
let mut field = form::input::Field::text().with_help_text(Lc::n("We never share your data."));
|
||||
let html = field.render(&mut Context::default()).await.into_string();
|
||||
|
||||
assert!(html.contains(r#"class="form-text""#));
|
||||
assert!(html.contains("We never share your data."));
|
||||
}
|
||||
|
||||
#[pagetop::test]
|
||||
async fn placeholder_attribute_is_absent_by_default() {
|
||||
let mut field = form::input::Field::text();
|
||||
let html = field.render(&mut Context::default()).await.into_string();
|
||||
|
||||
assert!(!html.contains("placeholder="));
|
||||
}
|
||||
|
||||
#[pagetop::test]
|
||||
async fn placeholder_attribute_is_present_when_set() {
|
||||
let mut field = form::input::Field::text().with_placeholder(Lc::n("Enter your name"));
|
||||
let html = field.render(&mut Context::default()).await.into_string();
|
||||
|
||||
assert!(html.contains(r#"placeholder="Enter your name""#));
|
||||
}
|
||||
|
||||
#[pagetop::test]
|
||||
async fn placeholder_attribute_can_be_cleared_with_lc_none() {
|
||||
let mut field = form::input::Field::text()
|
||||
.with_placeholder(Lc::n("Enter your name"))
|
||||
.with_placeholder(Lc::none());
|
||||
let html = field.render(&mut Context::default()).await.into_string();
|
||||
|
||||
assert!(!html.contains("placeholder="));
|
||||
}
|
||||
38
tests/response_page.rs
Normal file
38
tests/response_page.rs
Normal file
|
|
@ -0,0 +1,38 @@
|
|||
use pagetop::prelude::*;
|
||||
|
||||
fn request() -> HttpRequest {
|
||||
web::test::TestRequest::get().to_http_request()
|
||||
}
|
||||
|
||||
#[pagetop::test]
|
||||
async fn title_and_description_are_absent_by_default() {
|
||||
let page = Page::new(request());
|
||||
|
||||
assert_eq!(page.title(), None);
|
||||
assert_eq!(page.description(), None);
|
||||
}
|
||||
|
||||
#[pagetop::test]
|
||||
async fn title_and_description_reflect_the_values_set() {
|
||||
let page = Page::new(request())
|
||||
.with_title(Lc::n("Dashboard"))
|
||||
.with_description(Lc::n("Overview of recent activity"));
|
||||
|
||||
assert_eq!(page.title(), Some("Dashboard".to_string()));
|
||||
assert_eq!(
|
||||
page.description(),
|
||||
Some("Overview of recent activity".to_string())
|
||||
);
|
||||
}
|
||||
|
||||
#[pagetop::test]
|
||||
async fn lc_none_clears_a_previously_set_title_and_description() {
|
||||
let page = Page::new(request())
|
||||
.with_title(Lc::n("Dashboard"))
|
||||
.with_description(Lc::n("Overview of recent activity"))
|
||||
.with_title(Lc::none())
|
||||
.with_description(Lc::none());
|
||||
|
||||
assert_eq!(page.title(), None);
|
||||
assert_eq!(page.description(), None);
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue