diff --git a/Cargo.lock b/Cargo.lock index b03e980..ab7b20a 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1413,7 +1413,7 @@ checksum = "b15813163c1d831bf4a13c3610c05c0d03b39feb07f7e09fa234dac9b15aaf39" [[package]] name = "pagetop" -version = "0.0.12" +version = "0.0.11" dependencies = [ "actix-files", "actix-web", @@ -1426,7 +1426,6 @@ dependencies = [ "fluent-templates", "itoa", "pagetop-macros", - "parking_lot", "pastey", "serde", "static-files", @@ -2213,9 +2212,9 @@ dependencies = [ [[package]] name = "tracing-actix-web" -version = "0.7.19" +version = "0.7.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5360edd490ec8dee9fedfc6a9fd83ac2f01b3e1996e3261b9ad18a61971fe064" +checksum = "2340b7722695166c7fc9b3e3cd1166e7c74fedb9075b8f0c74d3822d2e41caf5" dependencies = [ "actix-web", "mutually_exclusive_features", diff --git a/Cargo.toml b/Cargo.toml index 049c258..b6f844f 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "pagetop" -version = "0.0.12" +version = "0.0.11" edition = "2021" description = """\ @@ -21,7 +21,6 @@ concat-string = "1.0.1" config = { version = "0.15.13", default-features = false, features = ["toml"] } figlet-rs = "0.1.5" itoa = "1.0.15" -parking_lot = "0.12.4" paste = { package = "pastey", version = "0.1.0" } substring = "1.4.5" terminal_size = "0.4.2" @@ -29,7 +28,7 @@ terminal_size = "0.4.2" tracing = "0.1.41" tracing-appender = "0.2.3" tracing-subscriber = { version = "0.3.19", features = ["json", "env-filter"] } -tracing-actix-web = "0.7.19" +tracing-actix-web = "0.7.18" fluent-templates = "0.13.0" unic-langid = { version = "0.9.6", features = ["macros"] } diff --git a/src/base.rs b/src/base.rs index 6f22dd7..c50cc9e 100644 --- a/src/base.rs +++ b/src/base.rs @@ -1,7 +1,3 @@ -//! Reúne acciones, componentes y temas listos para usar. - -pub mod action; - -pub mod component; +//! Reúne temas listos para usar. pub mod theme; diff --git a/src/base/action.rs b/src/base/action.rs deleted file mode 100644 index 119a7ea..0000000 --- a/src/base/action.rs +++ /dev/null @@ -1,15 +0,0 @@ -//! Acciones predefinidas para alterar el funcionamiento interno de `PageTop`. - -use crate::prelude::*; - -/// Tipo de función para manipular componentes y su contexto de renderizado. -/// -/// Se usa en acciones definidas en [`component`] y [`theme`] para alterar el comportamiento de los -/// componentes. -/// -/// Recibe referencias mutables (`&mut`) del componente `component` y del contexto `cx`. -pub type FnActionWithComponent = fn(component: &mut C, cx: &mut Context); - -pub mod component; - -pub mod theme; diff --git a/src/base/action/component.rs b/src/base/action/component.rs deleted file mode 100644 index aaef1ce..0000000 --- a/src/base/action/component.rs +++ /dev/null @@ -1,10 +0,0 @@ -//! Acciones que operan sobre componentes. - -mod is_renderable; -pub use is_renderable::*; - -mod before_render_component; -pub use before_render_component::*; - -mod after_render_component; -pub use after_render_component::*; diff --git a/src/base/action/component/after_render_component.rs b/src/base/action/component/after_render_component.rs deleted file mode 100644 index 3c8ead9..0000000 --- a/src/base/action/component/after_render_component.rs +++ /dev/null @@ -1,81 +0,0 @@ -use crate::prelude::*; - -use crate::base::action::FnActionWithComponent; - -/// Ejecuta [`FnActionWithComponent`] después de renderizar un componente. -pub struct AfterRender { - f: FnActionWithComponent, - referer_type_id: Option, - referer_id: OptionId, - weight: Weight, -} - -/// Filtro para despachar [`FnActionWithComponent`] después de renderizar un componente `C`. -impl ActionDispatcher for AfterRender { - /// Devuelve el identificador de tipo ([`UniqueId`]) del componente `C`. - fn referer_type_id(&self) -> Option { - self.referer_type_id - } - - /// Devuelve el identificador del componente. - fn referer_id(&self) -> Option { - self.referer_id.get() - } - - /// Devuelve el peso para definir el orden de aplicación. - fn weight(&self) -> Weight { - self.weight - } -} - -impl AfterRender { - /// Permite [registrar](ExtensionTrait::actions) una nueva acción [`FnActionWithComponent`]. - pub fn new(f: FnActionWithComponent) -> Self { - AfterRender { - f, - referer_type_id: Some(UniqueId::of::()), - referer_id: OptionId::default(), - weight: 0, - } - } - - /// Afina el registro para ejecutar la acción [`FnActionWithComponent`] sólo para el componente - /// `C` con identificador `id`. - pub fn filter_by_referer_id(mut self, id: impl AsRef) -> Self { - self.referer_id.alter_value(id); - self - } - - /// Opcional. Acciones con pesos más bajos se aplican antes. Se pueden usar valores negativos. - pub fn with_weight(mut self, value: Weight) -> Self { - self.weight = value; - self - } - - // Despacha las acciones. - #[inline] - pub(crate) fn dispatch(component: &mut C, cx: &mut Context) { - // Primero despacha las acciones para el tipo de componente. - dispatch_actions( - &ActionKey::new( - UniqueId::of::(), - None, - Some(UniqueId::of::()), - None, - ), - |action: &Self| (action.f)(component, cx), - ); - // Y luego despacha las acciones para el tipo de componente con un identificador dado. - if let Some(id) = component.id() { - dispatch_actions( - &ActionKey::new( - UniqueId::of::(), - None, - Some(UniqueId::of::()), - Some(id), - ), - |action: &Self| (action.f)(component, cx), - ); - } - } -} diff --git a/src/base/action/component/before_render_component.rs b/src/base/action/component/before_render_component.rs deleted file mode 100644 index 0ebe409..0000000 --- a/src/base/action/component/before_render_component.rs +++ /dev/null @@ -1,81 +0,0 @@ -use crate::prelude::*; - -use crate::base::action::FnActionWithComponent; - -/// Ejecuta [`FnActionWithComponent`] antes de renderizar el componente. -pub struct BeforeRender { - f: FnActionWithComponent, - referer_type_id: Option, - referer_id: OptionId, - weight: Weight, -} - -/// Filtro para despachar [`FnActionWithComponent`] antes de renderizar un componente `C`. -impl ActionDispatcher for BeforeRender { - /// Devuelve el identificador de tipo ([`UniqueId`]) del componente `C`. - fn referer_type_id(&self) -> Option { - self.referer_type_id - } - - /// Devuelve el identificador del componente. - fn referer_id(&self) -> Option { - self.referer_id.get() - } - - /// Devuelve el peso para definir el orden de aplicación. - fn weight(&self) -> Weight { - self.weight - } -} - -impl BeforeRender { - /// Permite [registrar](ExtensionTrait::actions) una nueva acción [`FnActionWithComponent`]. - pub fn new(f: FnActionWithComponent) -> Self { - BeforeRender { - f, - referer_type_id: Some(UniqueId::of::()), - referer_id: OptionId::default(), - weight: 0, - } - } - - /// Afina el registro para ejecutar la acción [`FnActionWithComponent`] sólo para el componente - /// `C` con identificador `id`. - pub fn filter_by_referer_id(mut self, id: impl AsRef) -> Self { - self.referer_id.alter_value(id); - self - } - - /// Opcional. Acciones con pesos más bajos se aplican antes. Se pueden usar valores negativos. - pub fn with_weight(mut self, value: Weight) -> Self { - self.weight = value; - self - } - - // Despacha las acciones. - #[inline] - pub(crate) fn dispatch(component: &mut C, cx: &mut Context) { - // Primero despacha las acciones para el tipo de componente. - dispatch_actions( - &ActionKey::new( - UniqueId::of::(), - None, - Some(UniqueId::of::()), - None, - ), - |action: &Self| (action.f)(component, cx), - ); - // Y luego despacha las aciones para el tipo de componente con un identificador dado. - if let Some(id) = component.id() { - dispatch_actions( - &ActionKey::new( - UniqueId::of::(), - None, - Some(UniqueId::of::()), - Some(id), - ), - |action: &Self| (action.f)(component, cx), - ); - } - } -} diff --git a/src/base/action/component/is_renderable.rs b/src/base/action/component/is_renderable.rs deleted file mode 100644 index 7ba7d53..0000000 --- a/src/base/action/component/is_renderable.rs +++ /dev/null @@ -1,96 +0,0 @@ -use crate::prelude::*; - -/// Tipo de función para determinar si un componente se renderiza o no. -/// -/// Se usa en la acción [`IsRenderable`] para controlar dinámicamente la visibilidad del componente -/// `component` según el contexto `cx`. El componente **no se renderiza** en cuanto una de las -/// funciones devuelva `false`. -pub type FnIsRenderable = fn(component: &C, cx: &Context) -> bool; - -/// Con la función [`FnIsRenderable`] se puede decidir si se renderiza o no un componente. -pub struct IsRenderable { - f: FnIsRenderable, - referer_type_id: Option, - referer_id: OptionId, - weight: Weight, -} - -/// Filtro para despachar [`FnIsRenderable`] para decidir si se renderiza o no un componente `C`. -impl ActionDispatcher for IsRenderable { - /// Devuelve el identificador de tipo ([`UniqueId`]) del componente `C`. - fn referer_type_id(&self) -> Option { - self.referer_type_id - } - - /// Devuelve el identificador del componente. - fn referer_id(&self) -> Option { - self.referer_id.get() - } - - /// Devuelve el peso para definir el orden de aplicación. - fn weight(&self) -> Weight { - self.weight - } -} - -impl IsRenderable { - /// Permite [registrar](ExtensionTrait::actions) una nueva acción [`FnIsRenderable`]. - pub fn new(f: FnIsRenderable) -> Self { - IsRenderable { - f, - referer_type_id: Some(UniqueId::of::()), - referer_id: OptionId::default(), - weight: 0, - } - } - - /// Afina el registro para ejecutar la acción [`FnIsRenderable`] sólo para el componente `C` - /// con identificador `id`. - pub fn filter_by_referer_id(mut self, id: impl AsRef) -> Self { - self.referer_id.alter_value(id); - self - } - - /// Opcional. Acciones con pesos más bajos se aplican antes. Se pueden usar valores negativos. - pub fn with_weight(mut self, value: Weight) -> Self { - self.weight = value; - self - } - - // Despacha las acciones. Se detiene en cuanto una [`FnIsRenderable`] devuelve `false`. - #[inline] - pub(crate) fn dispatch(component: &C, cx: &mut Context) -> bool { - let mut renderable = true; - dispatch_actions( - &ActionKey::new( - UniqueId::of::(), - None, - Some(UniqueId::of::()), - None, - ), - |action: &Self| { - if renderable && !(action.f)(component, cx) { - renderable = false; - } - }, - ); - if renderable { - if let Some(id) = component.id() { - dispatch_actions( - &ActionKey::new( - UniqueId::of::(), - None, - Some(UniqueId::of::()), - Some(id), - ), - |action: &Self| { - if renderable && !(action.f)(component, cx) { - renderable = false; - } - }, - ); - } - } - renderable - } -} diff --git a/src/base/action/theme.rs b/src/base/action/theme.rs deleted file mode 100644 index 4098857..0000000 --- a/src/base/action/theme.rs +++ /dev/null @@ -1,10 +0,0 @@ -//! Acciones lanzadas desde los temas. - -mod before_render_component; -pub use before_render_component::*; - -mod after_render_component; -pub use after_render_component::*; - -mod prepare_render; -pub use prepare_render::*; diff --git a/src/base/action/theme/after_render_component.rs b/src/base/action/theme/after_render_component.rs deleted file mode 100644 index d33e0d2..0000000 --- a/src/base/action/theme/after_render_component.rs +++ /dev/null @@ -1,50 +0,0 @@ -use crate::prelude::*; - -use crate::base::action::FnActionWithComponent; - -/// Ejecuta [`FnActionWithComponent`] después de que un tema renderice el componente. -pub struct AfterRender { - f: FnActionWithComponent, - theme_type_id: Option, - referer_type_id: Option, -} - -/// Filtro para despachar [`FnActionWithComponent`] después de que un tema renderice el componente -/// `C`. -impl ActionDispatcher for AfterRender { - /// Devuelve el identificador de tipo ([`UniqueId`]) del tema. - fn theme_type_id(&self) -> Option { - self.theme_type_id - } - - /// Devuelve el identificador de tipo ([`UniqueId`]) del componente `C`. - fn referer_type_id(&self) -> Option { - self.referer_type_id - } -} - -impl AfterRender { - /// Permite [registrar](ExtensionTrait::actions) una nueva acción [`FnActionWithComponent`] para - /// un tema dado. - pub fn new(theme: ThemeRef, f: FnActionWithComponent) -> Self { - AfterRender { - f, - theme_type_id: Some(theme.type_id()), - referer_type_id: Some(UniqueId::of::()), - } - } - - // Despacha las acciones. - #[inline] - pub(crate) fn dispatch(component: &mut C, cx: &mut Context) { - dispatch_actions( - &ActionKey::new( - UniqueId::of::(), - Some(cx.theme().type_id()), - Some(UniqueId::of::()), - None, - ), - |action: &Self| (action.f)(component, cx), - ); - } -} diff --git a/src/base/action/theme/before_render_component.rs b/src/base/action/theme/before_render_component.rs deleted file mode 100644 index 76f6cd2..0000000 --- a/src/base/action/theme/before_render_component.rs +++ /dev/null @@ -1,50 +0,0 @@ -use crate::prelude::*; - -use crate::base::action::FnActionWithComponent; - -/// Ejecuta [`FnActionWithComponent`] antes de que un tema renderice el componente. -pub struct BeforeRender { - f: FnActionWithComponent, - theme_type_id: Option, - referer_type_id: Option, -} - -/// Filtro para despachar [`FnActionWithComponent`] antes de que un tema renderice el componente -/// `C`. -impl ActionDispatcher for BeforeRender { - /// Devuelve el identificador de tipo ([`UniqueId`]) del tema. - fn theme_type_id(&self) -> Option { - self.theme_type_id - } - - /// Devuelve el identificador de tipo ([`UniqueId`]) del componente `C`. - fn referer_type_id(&self) -> Option { - self.referer_type_id - } -} - -impl BeforeRender { - /// Permite [registrar](ExtensionTrait::actions) una nueva acción [`FnActionWithComponent`] para - /// un tema dado. - pub fn new(theme: ThemeRef, f: FnActionWithComponent) -> Self { - BeforeRender { - f, - theme_type_id: Some(theme.type_id()), - referer_type_id: Some(UniqueId::of::()), - } - } - - // Despacha las acciones. - #[inline] - pub(crate) fn dispatch(component: &mut C, cx: &mut Context) { - dispatch_actions( - &ActionKey::new( - UniqueId::of::(), - Some(cx.theme().type_id()), - Some(UniqueId::of::()), - None, - ), - |action: &Self| (action.f)(component, cx), - ); - } -} diff --git a/src/base/action/theme/prepare_render.rs b/src/base/action/theme/prepare_render.rs deleted file mode 100644 index 9d3e261..0000000 --- a/src/base/action/theme/prepare_render.rs +++ /dev/null @@ -1,63 +0,0 @@ -use crate::prelude::*; - -/// Tipo de función para alterar el renderizado de un componente. -/// -/// Permite a un [tema](crate::base::action::theme) sobreescribir el renderizado predeterminado de -/// los componentes. -/// -/// Recibe una referencia al componente `component` y una referencia mutable al contexto `cx`. -pub type FnPrepareRender = fn(component: &C, cx: &mut Context) -> PrepareMarkup; - -/// Ejecuta [`FnPrepareRender`] para preparar el renderizado de un componente. -/// -/// Permite a un tema hacer una implementación nueva del renderizado de un componente. -pub struct PrepareRender { - f: FnPrepareRender, - theme_type_id: Option, - referer_type_id: Option, -} - -/// Filtro para despachar [`FnPrepareRender`] que modifica el renderizado de un componente `C`. -impl ActionDispatcher for PrepareRender { - /// Devuelve el identificador de tipo ([`UniqueId`]) del tema. - fn theme_type_id(&self) -> Option { - self.theme_type_id - } - - /// Devuelve el identificador de tipo ([`UniqueId`]) del componente `C`. - fn referer_type_id(&self) -> Option { - self.referer_type_id - } -} - -impl PrepareRender { - /// Permite [registrar](ExtensionTrait::actions) una nueva acción [`FnPrepareRender`] para un - /// tema dado. - pub fn new(theme: ThemeRef, f: FnPrepareRender) -> Self { - PrepareRender { - f, - theme_type_id: Some(theme.type_id()), - referer_type_id: Some(UniqueId::of::()), - } - } - - // Despacha las acciones. Se detiene en cuanto una renderiza. - #[inline] - pub(crate) fn dispatch(component: &C, cx: &mut Context) -> PrepareMarkup { - let mut render_component = PrepareMarkup::None; - dispatch_actions( - &ActionKey::new( - UniqueId::of::(), - Some(cx.theme().type_id()), - Some(UniqueId::of::()), - None, - ), - |action: &Self| { - if render_component.is_empty() { - render_component = (action.f)(component, cx); - } - }, - ); - render_component - } -} diff --git a/src/base/component.rs b/src/base/component.rs deleted file mode 100644 index 27f0f73..0000000 --- a/src/base/component.rs +++ /dev/null @@ -1,4 +0,0 @@ -//! Componentes nativos proporcionados por `PageTop`. - -mod html; -pub use html::Html; diff --git a/src/base/component/html.rs b/src/base/component/html.rs deleted file mode 100644 index 0937605..0000000 --- a/src/base/component/html.rs +++ /dev/null @@ -1,28 +0,0 @@ -use crate::prelude::*; - -/// Componente básico para renderizar directamente código HTML. -#[derive(AutoDefault)] -pub struct Html(Markup); - -impl ComponentTrait for Html { - fn new() -> Self { - Html::default() - } - - fn prepare_component(&self, _cx: &mut Context) -> PrepareMarkup { - PrepareMarkup::With(html! { (self.0) }) - } -} - -impl Html { - /// Crear una instancia con el código HTML del argumento. - pub fn with(html: Markup) -> Self { - Html(html) - } - - /// Modifica el código HTML de la instancia con el nuevo código del argumento. - pub fn alter_html(&mut self, html: Markup) -> &mut Self { - self.0 = html; - self - } -} diff --git a/src/core.rs b/src/core.rs index 2168c93..4b857fc 100644 --- a/src/core.rs +++ b/src/core.rs @@ -1,4 +1,4 @@ -//! Tipos y funciones esenciales para crear acciones, componentes, extensiones y temas. +//! Tipos y funciones esenciales para crear acciones, extensiones y temas. use std::any::Any; @@ -204,9 +204,6 @@ impl AnyCast for T {} // API para definir acciones que alteran el comportamiento predeterminado del código. pub mod action; -// API para construir nuevos componentes. -pub mod component; - // API para añadir nuevas funcionalidades usando extensiones. pub mod extension; diff --git a/src/core/action.rs b/src/core/action.rs index f5dc11c..8503ae9 100644 --- a/src/core/action.rs +++ b/src/core/action.rs @@ -1,11 +1,11 @@ //! API para definir acciones que inyectan código en el flujo de la aplicación. //! -//! Permite crear acciones para que otros *crates* puedan inyectar código usando funciones *ad hoc* -//! que modifican el comportamiento predefinido en puntos concretos del flujo de ejecución de la -//! aplicación. +//! Permite crear acciones en las librerías para que otros *crates* puedan inyectar código usando +//! funciones *ad hoc* que modifican el comportamiento predefinido en puntos concretos del flujo de +//! ejecución de la aplicación. mod definition; -pub use definition::{ActionBox, ActionDispatcher, ActionKey}; +pub use definition::{ActionBase, ActionBox, ActionKey, ActionTrait}; mod list; use list::ActionsList; @@ -14,33 +14,49 @@ mod all; pub(crate) use all::add_action; pub use all::dispatch_actions; -/// Facilita la implementación del método -/// [`actions()`](crate::core::extension::ExtensionTrait::actions). +/// Crea una lista de acciones para facilitar la implementación del método +/// [`actions`](crate::core::extension::ExtensionTrait#method.actions). /// -/// Evita escribir repetidamente `Box::new(...)` para cada acción de la lista, manteniendo el código -/// más limpio. +/// Esta macro crea vectores de [`ActionBox`], el tipo dinámico que encapsula cualquier acción que +/// implemente [`ActionTrait`]. Evita escribir repetidamente `Box::new(...)` para cada acción +/// inyectada, manteniendo el código más limpio. /// -/// # Ejemplo +/// # Ejemplos +/// +/// Puede llamarse sin argumentos para crear un vector vacío: /// /// ```rust,ignore -/// use pagetop::prelude::*; +/// let my_actions = inject_actions![]; +/// ``` /// -/// impl ExtensionTrait for MyTheme { +/// O con una lista de acciones concretas: +/// +/// ```rust,ignore +/// let my_actions = inject_actions![ +/// MyFirstAction::new(), +/// MySecondAction::new().with_weight(10), +/// ]; +/// ``` +/// +/// Internamente, expande a un `vec![Box::new(...), ...]`. +/// +/// # Ejemplo típico en una extensión +/// +/// ```rust,ignore +/// impl ExtensionTrait for MyExtension { /// fn actions(&self) -> Vec { -/// actions_boxed![ -/// action::theme::BeforeRender::