/*!

PageTop Minimal

Reúne un conjunto mínimo de macros para mejorar el formato y la eficiencia de operaciones básicas en PageTop.

[![Doc API](https://img.shields.io/docsrs/pagetop-minimal?label=Doc%20API&style=for-the-badge&logo=Docs.rs)](https://docs.rs/pagetop-minimal) [![Crates.io](https://img.shields.io/crates/v/pagetop-minimal.svg?style=for-the-badge&logo=ipfs)](https://crates.io/crates/pagetop-minimal) [![Descargas](https://img.shields.io/crates/d/pagetop-minimal.svg?label=Descargas&style=for-the-badge&logo=transmission)](https://crates.io/crates/pagetop-minimal) [![Licencia](https://img.shields.io/badge/license-MIT%2FApache-blue.svg?label=Licencia&style=for-the-badge)](https://git.cillero.es/manuelcillero/pagetop/src/branch/main/helpers/pagetop-minimal#licencia)
## Sobre PageTop [PageTop](https://docs.rs/pagetop) es un entorno de desarrollo que reivindica la esencia de la web clásica para crear soluciones web SSR (*renderizadas en el servidor*) modulares, extensibles y configurables, basadas en HTML, CSS y JavaScript. ## Descripción general Este *crate* proporciona un conjunto básico de macros que se integran en las utilidades de PageTop para optimizar operaciones habituales relacionadas con la composición estructurada de texto, la concatenación de cadenas y el uso rápido de colecciones clave-valor. ## Créditos Las macros para texto multilínea **`indoc!`**, **`formatdoc!`** y **`concatdoc!`** se reexportan del *crate* [indoc](https://crates.io/crates/indoc) de [David Tolnay](https://crates.io/users/dtolnay). Las macros para la concatenación de cadenas **`join!`** y **`join_pair!`** se apoyan internamente en el *crate* [concat-string](https://crates.io/crates/concat_string), desarrollado por [FaultyRAM](https://crates.io/users/FaultyRAM), para evitar el formato de cadenas cuando la eficiencia pueda ser relevante. La macro para generar identificadores dinámicos **`paste!`** se reexporta del *crate* [pastey](https://crates.io/crates/pastey), una implementación avanzada y soportada del popular `paste!` de [David Tolnay](https://crates.io/users/dtolnay). */ #![doc( html_favicon_url = "https://git.cillero.es/manuelcillero/pagetop/raw/branch/main/static/favicon.ico" )] #[doc(hidden)] pub use concat_string::concat_string; pub use indoc::{concatdoc, formatdoc, indoc}; /// Permite *pegar* tokens y generar identificadores a partir de otros. /// /// Dentro de `paste!`, los identificadores escritos como `[< ... >]` se combinan en uno solo que /// puede reutilizarse para referirse a items existentes o para definir nuevos (funciones, /// estructuras, métodos, etc.). /// /// También admite modificadores de estilo (`lower`, `upper`, `snake`, `camel`, etc.) para /// transformar fragmentos interpolados antes de construir el nuevo identificador. pub use pastey::paste; // La documentación anterior se copia en `pagetop::util::paste!` porque el *crate* original no la // define y `pagetop` no la hereda automáticamente. /// 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`] 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_minimal::join; /// // 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::concat_string!($($arg),+) }; } /// Concatena dos fragmentos en un [`String`] usando un separador inteligente. /// /// Une los dos fragmentos, que deben implementar [`AsRef`], 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_minimal::join_pair; /// 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::::as_ref(&first_val); let second = AsRef::::as_ref(&second_val); let separator = if first.is_empty() || second.is_empty() { "" } else { AsRef::::as_ref(&separator_val) }; $crate::concat_string!(first, separator, second) }}; } /// Macro para construir una colección de pares clave-valor. /// /// ```rust /// # use pagetop_minimal::kv; /// # use std::collections::HashMap; /// let args:HashMap<&str, String> = kv![ /// "userName" => "Roberto", /// "photoCount" => "3", /// "userGender" => "male", /// ]; /// ``` #[macro_export] macro_rules! kv { ( $($key:expr => $value:expr),* $(,)? ) => {{ let mut a = std::collections::HashMap::new(); $( a.insert($key.into(), $value.into()); )* a }}; }