From 3c67d9d04ca3c1ec1a0a9485f890d507f5fd9f34 Mon Sep 17 00:00:00 2001 From: Manuel Cillero Date: Wed, 26 Aug 2026 06:55:37 +0200 Subject: [PATCH] =?UTF-8?q?=E2=9C=A8=20(props):=20A=C3=B1ade=20la=20operac?= =?UTF-8?q?i=C3=B3n=20`PropsOp::translate`?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Permite a un tema traducir el vocabulario de atributos de un componente al suyo propio (p. ej. `data-dialog-*` -> `data-bs-*`) sin conocer su valor, respetando el que ya tuviera el destino si existía. --- src/html/props.rs | 35 +++++++++++++++++++++++++++++++++++ 1 file changed, 35 insertions(+) diff --git a/src/html/props.rs b/src/html/props.rs index 281a586d..b80349f0 100644 --- a/src/html/props.rs +++ b/src/html/props.rs @@ -142,6 +142,13 @@ pub enum PropsOp { /// Elimina el atributo indicado. Usar `"id"` elimina el identificador; usar `"class"` vacía la /// lista de clases; y usar `"style"` vacía la lista de estilos. Remove(CowStr), + /// Si el primer atributo (origen) existe, lo renombra al segundo (destino), conservando su + /// valor; si el destino ya tiene su propio valor, se respeta sin sobrescribir y sólo se elimina + /// el origen. Si el origen no existe, la operación no tiene efecto. + /// + /// Sólo actúa sobre atributos genéricos, por lo que los nombres `"id"`, `"class"` y `"style"` + /// no se reconocen como origen ni destino. + Translate(CowStr, CowStr), /// Almacena un valor extra tipado asociado a la clave indicada. Si ya existe uno con esa clave, /// lo reemplaza. SetExtra(&'static str, PropsExtra), @@ -241,6 +248,26 @@ impl PropsOp { Self::Remove(name.into()) } + /// Crea la variante [`Translate`](Self::Translate) para renombrar `from` a `to`. + /// + /// ```rust + /// # use pagetop::prelude::*; + /// let props = Props::new("data-dialog-toggle", "modal") + /// .with_prop(PropsOp::translate("data-dialog-toggle", "data-bs-toggle")); + /// assert_eq!(props.get_prop("data-bs-toggle"), Some("modal".to_string())); + /// assert_eq!(props.get_prop("data-dialog-toggle"), None); + /// + /// // Si el destino tiene su propio valor no se sobrescribe, sólo se elimina el origen. + /// let props = Props::new("data-bs-toggle", "collapse") + /// .with_prop(PropsOp::set("data-dialog-toggle", "modal")) + /// .with_prop(PropsOp::translate("data-dialog-toggle", "data-bs-toggle")); + /// assert_eq!(props.get_prop("data-bs-toggle"), Some("collapse".to_string())); + /// assert_eq!(props.get_prop("data-dialog-toggle"), None); + /// ``` + pub fn translate(from: impl Into, to: impl Into) -> Self { + Self::Translate(from.into(), to.into()) + } + /// Crea la variante [`SetExtra`](Self::SetExtra) con la clave y el valor indicados. /// /// ```rust @@ -582,6 +609,14 @@ impl Props { self.attrs.retain(|(k, _)| k != &name); } } + PropsOp::Translate(from, to) => { + if let Some(pos) = self.attrs.iter().position(|(k, _)| k == &from) { + let (_, value) = self.attrs.remove(pos); + if !self.attrs.iter().any(|(k, _)| k == &to) { + self.attrs.push((to, value)); + } + } + } PropsOp::SetExtra(key, extra) => { self.extras.insert(key, extra); }