use crate::{builder_fn, AutoDefault}; /// Identificador normalizado para el atributo `id` o similar de HTML. /// /// Este tipo encapsula `Option` garantizando un valor normalizado para su uso. /// /// # Normalización /// /// - Se eliminan los espacios al principio y al final. /// - Se convierte a minúsculas. /// - Se sustituyen los espacios intermedios por guiones bajos (`_`). /// - Si el resultado es una cadena vacía, se guarda `None`. /// /// # Ejemplo /// /// ```rust /// use pagetop::prelude::*; /// /// let id = OptionId::new(" main Section "); /// assert_eq!(id.get(), Some(String::from("main_section"))); /// /// let empty = OptionId::default(); /// assert_eq!(empty.get(), None); /// ``` #[derive(AutoDefault, Clone, Debug, Hash, Eq, PartialEq)] pub struct OptionId(Option); impl OptionId { /// Crea un nuevo [`OptionId`]. /// /// El valor se normaliza automáticamente. pub fn new(value: impl AsRef) -> Self { OptionId::default().with_value(value) } // OptionId BUILDER **************************************************************************** /// Establece un identificador nuevo. /// /// El valor se normaliza automáticamente. #[builder_fn] pub fn with_value(mut self, value: impl AsRef) -> Self { let value = value.as_ref().trim().to_ascii_lowercase().replace(' ', "_"); self.0 = (!value.is_empty()).then_some(value); self } // OptionId GETTERS **************************************************************************** /// Devuelve el identificador, si existe. pub fn get(&self) -> Option { if let Some(value) = &self.0 { if !value.is_empty() { return Some(value.to_owned()); } } None } }