✨ [minimal] Añade macros declarativas a utilidades
- Incorpora nuevo *crate* `pagetop-minimal` con macros básicas para operaciones con cadenas, bloques de texto o colecciones clave-valor. - Refactoriza código para usar `util::join!` y `util::join_pair!` en la concatenación de cadenas. - Normaliza la gestión de localización usando `util::kv!` para los argumentos con pares clave-valor. - Actualizada documentación y archivos README para reflejar la nueva estructura y funcionalidades.
This commit is contained in:
parent
b7c356b2e0
commit
7b23e9c1ea
25 changed files with 504 additions and 154 deletions
|
|
@ -21,7 +21,7 @@ impl Component for PoweredBy {
|
|||
/// configurada en [`global::SETTINGS`], en el formato `YYYY © Nombre de la aplicación`.
|
||||
fn new() -> Self {
|
||||
let year = Utc::now().format("%Y").to_string();
|
||||
let c = join!(year, " © ", global::SETTINGS.app.name);
|
||||
let c = util::join!(year, " © ", global::SETTINGS.app.name);
|
||||
PoweredBy { copyright: Some(c) }
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@ use crate::html::{html, Markup};
|
|||
use crate::html::{Assets, Favicon, JavaScript, StyleSheet};
|
||||
use crate::locale::{LangId, LangMatch, LanguageIdentifier};
|
||||
use crate::service::HttpRequest;
|
||||
use crate::{builder_fn, join};
|
||||
use crate::{builder_fn, util};
|
||||
|
||||
use std::any::Any;
|
||||
use std::collections::HashMap;
|
||||
|
|
@ -546,7 +546,7 @@ impl Contextual for Context {
|
|||
prefix
|
||||
};
|
||||
self.id_counter += 1;
|
||||
join!(prefix, "-", self.id_counter.to_string())
|
||||
util::join!(prefix, "-", self.id_counter.to_string())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -24,7 +24,7 @@
|
|||
use crate::core::component::Context;
|
||||
use crate::html::{html, Markup};
|
||||
use crate::locale::L10n;
|
||||
use crate::{join, AutoDefault};
|
||||
use crate::{util, AutoDefault};
|
||||
|
||||
// **< Region >*************************************************************************************
|
||||
|
||||
|
|
@ -83,7 +83,7 @@ pub trait Region {
|
|||
@let region = cx.render_region(self);
|
||||
@if !region.is_empty() {
|
||||
div
|
||||
class=(join!("region region-", self.name()))
|
||||
class=(util::join!("region region-", self.name()))
|
||||
role="region"
|
||||
aria-label=[self.label().lookup(cx)]
|
||||
{
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
use crate::core::component::Context;
|
||||
use crate::html::assets::Asset;
|
||||
use crate::html::{html, Markup, PreEscaped};
|
||||
use crate::{join, join_pair, AutoDefault, Weight};
|
||||
use crate::{util, AutoDefault, Weight};
|
||||
|
||||
// Define el origen del recurso JavaScript y cómo debe cargarse en el navegador.
|
||||
//
|
||||
|
|
@ -215,21 +215,21 @@ impl Asset for JavaScript {
|
|||
fn render(&self, cx: &mut Context) -> Markup {
|
||||
match &self.source {
|
||||
Source::From(path) => html! {
|
||||
script src=(join_pair!(path, "?v=", &self.version)) {};
|
||||
script src=(util::join_pair!(path, "?v=", &self.version)) {};
|
||||
},
|
||||
Source::Defer(path) => html! {
|
||||
script src=(join_pair!(path, "?v=", &self.version)) defer {};
|
||||
script src=(util::join_pair!(path, "?v=", &self.version)) defer {};
|
||||
},
|
||||
Source::Async(path) => html! {
|
||||
script src=(join_pair!(path, "?v=", &self.version)) async {};
|
||||
script src=(util::join_pair!(path, "?v=", &self.version)) async {};
|
||||
},
|
||||
Source::Inline(_, f) => html! {
|
||||
script { (PreEscaped((f)(cx))) };
|
||||
},
|
||||
Source::OnLoad(_, f) => html! { script { (PreEscaped(join!(
|
||||
Source::OnLoad(_, f) => html! { script { (PreEscaped(util::join!(
|
||||
"document.addEventListener(\"DOMContentLoaded\",function(){", (f)(cx), "});"
|
||||
))) } },
|
||||
Source::OnLoadAsync(_, f) => html! { script { (PreEscaped(join!(
|
||||
Source::OnLoadAsync(_, f) => html! { script { (PreEscaped(util::join!(
|
||||
"document.addEventListener(\"DOMContentLoaded\",async()=>{", (f)(cx), "});"
|
||||
))) } },
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
use crate::core::component::Context;
|
||||
use crate::html::assets::Asset;
|
||||
use crate::html::{html, Markup, PreEscaped};
|
||||
use crate::{join_pair, AutoDefault, Weight};
|
||||
use crate::{util, AutoDefault, Weight};
|
||||
|
||||
// Define el origen del recurso CSS y cómo se incluye en el documento.
|
||||
//
|
||||
|
|
@ -170,7 +170,7 @@ impl Asset for StyleSheet {
|
|||
Source::From(path) => html! {
|
||||
link
|
||||
rel="stylesheet"
|
||||
href=(join_pair!(path, "?v=", &self.version))
|
||||
href=(util::join_pair!(path, "?v=", &self.version))
|
||||
media=[self.media.as_str()];
|
||||
},
|
||||
Source::Inline(_, f) => html! {
|
||||
|
|
|
|||
|
|
@ -91,7 +91,7 @@
|
|||
|
||||
use crate::html::{Markup, PreEscaped};
|
||||
use crate::service::HttpRequest;
|
||||
use crate::{global, hm, AutoDefault};
|
||||
use crate::{global, util, AutoDefault};
|
||||
|
||||
pub use fluent_templates;
|
||||
pub use unic_langid::{CharacterDirection, LanguageIdentifier};
|
||||
|
|
@ -110,7 +110,7 @@ use std::fmt;
|
|||
// Asocia cada identificador de idioma (como "en-US") con su respectivo [`LanguageIdentifier`] y la
|
||||
// clave en *locale/.../languages.ftl* para obtener el nombre del idioma según la localización.
|
||||
static LANGUAGES: LazyLock<HashMap<&str, (LanguageIdentifier, &str)>> = LazyLock::new(|| {
|
||||
hm![
|
||||
util::kv![
|
||||
"en" => ( langid!("en-US"), "english" ),
|
||||
"en-gb" => ( langid!("en-GB"), "english_british" ),
|
||||
"en-us" => ( langid!("en-US"), "english_united_states" ),
|
||||
|
|
@ -411,7 +411,7 @@ impl L10n {
|
|||
self
|
||||
}
|
||||
|
||||
/// Añade varios argumentos a la traducción de una sola vez (p. ej. usando la macro [`hm!`],
|
||||
/// Añade varios argumentos a la traducción de una vez (p. ej. usando la macro [`util::kv!`],
|
||||
/// también vec![("k", "v")], incluso un array de duplas u otras colecciones).
|
||||
pub fn with_args<I, K, V>(mut self, args: I) -> Self
|
||||
where
|
||||
|
|
|
|||
|
|
@ -10,8 +10,6 @@ pub use crate::{AutoDefault, Getters, StaticResources, UniqueId, Weight};
|
|||
|
||||
// MACROS.
|
||||
|
||||
// crate::util
|
||||
pub use crate::{hm, join, join_pair};
|
||||
// crate::config
|
||||
pub use crate::include_config;
|
||||
// crate::locale
|
||||
|
|
|
|||
|
|
@ -15,6 +15,9 @@ pub use pagetop_statics::ResourceFiles;
|
|||
#[doc(hidden)]
|
||||
pub use actix_web::test;
|
||||
|
||||
#[doc(hidden)]
|
||||
pub use paste::paste;
|
||||
|
||||
/// Configura un servicio web para publicar archivos estáticos.
|
||||
///
|
||||
/// La macro ofrece tres modos para configurar el servicio:
|
||||
|
|
@ -72,7 +75,7 @@ macro_rules! static_files_service {
|
|||
}
|
||||
}
|
||||
if serve_embedded {
|
||||
$crate::util::paste! {
|
||||
$crate::service::paste! {
|
||||
mod [<static_files_ $bundle>] {
|
||||
include!(concat!(env!("OUT_DIR"), "/", stringify!($bundle), ".rs"));
|
||||
}
|
||||
|
|
@ -92,7 +95,7 @@ macro_rules! static_files_service {
|
|||
route = $route,
|
||||
);
|
||||
let _ = span.in_scope(|| {
|
||||
$crate::util::paste! {
|
||||
$crate::service::paste! {
|
||||
mod [<static_files_ $bundle>] {
|
||||
include!(concat!(env!("OUT_DIR"), "/", stringify!($bundle), ".rs"));
|
||||
}
|
||||
|
|
|
|||
111
src/util.rs
111
src/util.rs
|
|
@ -8,116 +8,7 @@ use std::path::{Path, PathBuf};
|
|||
|
||||
// **< MACROS INTEGRADAS >**************************************************************************
|
||||
|
||||
#[doc(hidden)]
|
||||
pub use paste::paste;
|
||||
|
||||
#[doc(hidden)]
|
||||
pub use concat_string::concat_string;
|
||||
|
||||
pub use indoc::{concatdoc, formatdoc, indoc};
|
||||
|
||||
// **< MACROS ÚTILES >******************************************************************************
|
||||
|
||||
/// Macro para construir una colección de pares clave-valor.
|
||||
///
|
||||
/// ```rust
|
||||
/// use pagetop::hm;
|
||||
/// use std::collections::HashMap;
|
||||
///
|
||||
/// let args:HashMap<&str, String> = hm![
|
||||
/// "userName" => "Roberto",
|
||||
/// "photoCount" => "3",
|
||||
/// "userGender" => "male",
|
||||
/// ];
|
||||
/// ```
|
||||
#[macro_export]
|
||||
macro_rules! hm {
|
||||
( $($key:expr => $value:expr),* $(,)? ) => {{
|
||||
let mut a = std::collections::HashMap::new();
|
||||
$(
|
||||
a.insert($key.into(), $value.into());
|
||||
)*
|
||||
a
|
||||
}};
|
||||
}
|
||||
|
||||
/// Concatena eficientemente varios fragmentos en un [`String`].
|
||||
///
|
||||
/// Esta macro exporta [`concat_string!`](https://docs.rs/concat-string). Acepta cualquier número de
|
||||
/// fragmentos que implementen [`AsRef<str>`] y construye un [`String`] con el tamaño óptimo, de
|
||||
/// forma eficiente y evitando el uso de cadenas de formato que penalicen el rendimiento.
|
||||
///
|
||||
/// # Ejemplo
|
||||
///
|
||||
/// ```rust
|
||||
/// # use pagetop::prelude::*;
|
||||
/// // Concatena todos los fragmentos directamente.
|
||||
/// let result = join!("Hello", " ", "World");
|
||||
/// assert_eq!(result, "Hello World".to_string());
|
||||
///
|
||||
/// // También funciona con valores vacíos.
|
||||
/// let result_with_empty = join!("Hello", "", "World");
|
||||
/// assert_eq!(result_with_empty, "HelloWorld".to_string());
|
||||
///
|
||||
/// // Un único fragmento devuelve el mismo valor.
|
||||
/// let single_result = join!("Hello");
|
||||
/// assert_eq!(single_result, "Hello".to_string());
|
||||
/// ```
|
||||
#[macro_export]
|
||||
macro_rules! join {
|
||||
($($arg:expr),+) => {
|
||||
$crate::util::concat_string!($($arg),+)
|
||||
};
|
||||
}
|
||||
|
||||
/// Concatena dos fragmentos en un [`String`] usando un separador.
|
||||
///
|
||||
/// Une los dos fragmentos, que deben implementar [`AsRef<str>`], usando el separador proporcionado.
|
||||
/// Si uno de ellos está vacío, devuelve directamente el otro; y si ambos están vacíos devuelve un
|
||||
/// [`String`] vacío.
|
||||
///
|
||||
/// # Ejemplo
|
||||
///
|
||||
/// ```rust
|
||||
/// # use pagetop::prelude::*;
|
||||
/// let first = "Hello";
|
||||
/// let separator = "-";
|
||||
/// let second = "World";
|
||||
///
|
||||
/// // Concatena los dos fragmentos cuando ambos no están vacíos.
|
||||
/// let result = join_pair!(first, separator, second);
|
||||
/// assert_eq!(result, "Hello-World".to_string());
|
||||
///
|
||||
/// // Si el primer fragmento está vacío, devuelve el segundo.
|
||||
/// let result_empty_first = join_pair!("", separator, second);
|
||||
/// assert_eq!(result_empty_first, "World".to_string());
|
||||
///
|
||||
/// // Si el segundo fragmento está vacío, devuelve el primero.
|
||||
/// let result_empty_second = join_pair!(first, separator, "");
|
||||
/// assert_eq!(result_empty_second, "Hello".to_string());
|
||||
///
|
||||
/// // Si ambos fragmentos están vacíos, devuelve una cadena vacía.
|
||||
/// let result_both_empty = join_pair!("", separator, "");
|
||||
/// assert_eq!(result_both_empty, "".to_string());
|
||||
/// ```
|
||||
#[macro_export]
|
||||
macro_rules! join_pair {
|
||||
($first:expr, $separator:expr, $second:expr) => {{
|
||||
let first_val = $first;
|
||||
let second_val = $second;
|
||||
let separator_val = $separator;
|
||||
|
||||
let first = AsRef::<str>::as_ref(&first_val);
|
||||
let second = AsRef::<str>::as_ref(&second_val);
|
||||
let separator = if first.is_empty() || second.is_empty() {
|
||||
""
|
||||
} else {
|
||||
AsRef::<str>::as_ref(&separator_val)
|
||||
};
|
||||
|
||||
$crate::util::concat_string!(first, separator, second)
|
||||
}};
|
||||
}
|
||||
pub use pagetop_minimal::{concatdoc, formatdoc, indoc, join, join_pair, kv};
|
||||
|
||||
// **< FUNCIONES ÚTILES >***************************************************************************
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue