Añade acción AlterMarkup para filtrar render

Permite a las extensiones transformar el `Markup` final de un componente
mediante edición de texto. Se despacha como último paso del ciclo de
renderizado.
This commit is contained in:
Manuel Cillero 2026-03-22 12:15:31 +01:00
parent 02bcf29eaa
commit 0c648fb95a
7 changed files with 141 additions and 9 deletions

View file

@ -21,7 +21,9 @@ pub use all::dispatch_actions;
/// Evita escribir repetidamente `Box::new(...)` para cada acción de la lista, manteniendo el código
/// más limpio.
///
/// # Ejemplo
/// # Ejemplos
///
/// Acciones de tema que ajustan un componente antes y después de renderizarlo:
///
/// ```rust,ignore
/// impl Extension for MyTheme {
@ -38,6 +40,22 @@ pub use all::dispatch_actions;
/// fn before_render_button(c: &mut Button, cx: &mut Context) { todo!() }
/// fn after_render_button(c: &mut Button, cx: &mut Context) { todo!() }
/// ```
///
/// Acción de extensión que transforma el HTML final de un componente mediante edición de texto:
///
/// ```rust,ignore
/// impl Extension for MyExtension {
/// fn actions(&self) -> Vec<ActionBox> {
/// actions_boxed![
/// action::component::AlterMarkup::<Button>::new(alter_button_markup),
/// ]
/// }
/// }
///
/// fn alter_button_markup(c: &mut Button, cx: &mut Context, markup: Markup) -> Markup {
/// todo!()
/// }
/// ```
#[macro_export]
macro_rules! actions_boxed {
() => {

View file

@ -109,11 +109,13 @@ pub trait Component: AnyInfo + ComponentRender + Send + Sync {
/// (hijo → padre → abuelo…) hasta que uno devuelva `Some`.
/// - Si ningún tema lo sobrescribe, llama a
/// [`Component::prepare_component()`](Component::prepare_component) del propio componente.
/// 6. Despacha [`action::theme::AfterRender<C>`](crate::base::action::theme::AfterRender) para
/// que el tema pueda aplicar ajustes finales.
/// 6. Despacha [`action::theme::AfterRender<C>`](crate::base::action::theme::AfterRender) para que
/// el tema pueda reaccionar tras el renderizado.
/// 7. Despacha [`action::component::AfterRender<C>`](crate::base::action::component::AfterRender)
/// para que otras extensiones puedan hacer sus últimos ajustes.
/// 8. Devuelve el [`Markup`] generado en el paso 5.
/// para que otras extensiones puedan reaccionar con sus últimos ajustes.
/// 8. Despacha [`action::component::AlterMarkup<C>`](crate::base::action::component::AlterMarkup)
/// para que las extensiones puedan modificar el HTML final antes de devolverlo.
/// 9. Devuelve el [`Markup`] resultante.
impl<C: Component> ComponentRender for C {
fn render(&mut self, cx: &mut Context) -> Markup {
// Si no es renderizable, devuelve un bloque HTML vacío.
@ -160,7 +162,7 @@ impl<C: Component> ComponentRender for C {
// Acciones de las extensiones después de renderizar el componente.
action::component::AfterRender::dispatch(self, cx);
// Devuelve el marcado final.
prepare
// Acciones de las extensiones que transforman el HTML final antes de devolverlo.
action::component::AlterMarkup::dispatch(self, cx, prepare)
}
}