Compare commits

..

No commits in common. "223a98569bb440572e0dbb05b9f85023fce6d22f" and "ac0889cb8c1a117e3b86c3f61378c900c59937b1" have entirely different histories.

32 changed files with 117 additions and 117 deletions

View file

@ -101,7 +101,7 @@
//! //!
//! pub struct MyExtension; //! pub struct MyExtension;
//! //!
//! impl Extension for MyExtension { //! impl ExtensionTrait for MyExtension {
//! // Servicio web que publica los recursos de `guides` en `/ruta/a/guides`. //! // Servicio web que publica los recursos de `guides` en `/ruta/a/guides`.
//! fn configure_service(&self, scfg: &mut service::web::ServiceConfig) { //! fn configure_service(&self, scfg: &mut service::web::ServiceConfig) {
//! include_files_service!(scfg, guides => "/ruta/a/guides"); //! include_files_service!(scfg, guides => "/ruta/a/guides");

View file

@ -175,7 +175,7 @@ pub fn builder_fn(_: TokenStream, item: TokenStream) -> TokenStream {
// Genera el método alter_...() con el código del método with_...(). // Genera el método alter_...() con el código del método with_...().
let fn_alter_doc = format!( let fn_alter_doc = format!(
"Igual que [`Self::{0}()`](Self::{0}), pero sin usar el patrón *builder*.", "Igual que [`{0}()`](Self::{0}), pero sin usar el patrón *builder*.",
fn_with_name_str, fn_with_name_str,
); );
let fn_alter = quote! { let fn_alter = quote! {

View file

@ -16,10 +16,10 @@ use std::sync::LazyLock;
/// Punto de entrada de una aplicación `PageTop`. /// Punto de entrada de una aplicación `PageTop`.
/// ///
/// No almacena datos, **encapsula** el inicio completo de configuración y puesta en marcha. Para /// No almacena datos, pero **encapsula** el ciclo completo de configuración y puesta en marcha.
/// instanciarla se puede usar [`new()`](Application::new) o [`prepare()`](Application::prepare). /// Para instanciarla se puede usar [`new`](Application::new) o [`prepare`](Application::prepare).
/// Después sólo hay que llamar a [`run()`](Application::run) para ejecutar la aplicación (o a /// Después sólo hay que llamar a [`run`](Application::run) (o a [`test`](Application::test) si se
/// [`test()`](Application::test) si se está preparando un entorno de pruebas). /// está preparando un entorno de pruebas).
pub struct Application; pub struct Application;
impl Default for Application { impl Default for Application {

View file

@ -3,7 +3,7 @@ use crate::prelude::*;
use crate::base::action::FnActionWithComponent; use crate::base::action::FnActionWithComponent;
/// Ejecuta [`FnActionWithComponent`] después de renderizar un componente. /// Ejecuta [`FnActionWithComponent`] después de renderizar un componente.
pub struct AfterRender<C: Component> { pub struct AfterRender<C: ComponentTrait> {
f: FnActionWithComponent<C>, f: FnActionWithComponent<C>,
referer_type_id: Option<UniqueId>, referer_type_id: Option<UniqueId>,
referer_id: OptionId, referer_id: OptionId,
@ -11,7 +11,7 @@ pub struct AfterRender<C: Component> {
} }
/// Filtro para despachar [`FnActionWithComponent`] después de renderizar un componente `C`. /// Filtro para despachar [`FnActionWithComponent`] después de renderizar un componente `C`.
impl<C: Component> ActionDispatcher for AfterRender<C> { impl<C: ComponentTrait> ActionDispatcher for AfterRender<C> {
/// Devuelve el identificador de tipo ([`UniqueId`]) del componente `C`. /// Devuelve el identificador de tipo ([`UniqueId`]) del componente `C`.
fn referer_type_id(&self) -> Option<UniqueId> { fn referer_type_id(&self) -> Option<UniqueId> {
self.referer_type_id self.referer_type_id
@ -28,8 +28,8 @@ impl<C: Component> ActionDispatcher for AfterRender<C> {
} }
} }
impl<C: Component> AfterRender<C> { impl<C: ComponentTrait> AfterRender<C> {
/// Permite [registrar](Extension::actions) una nueva acción [`FnActionWithComponent`]. /// Permite [registrar](ExtensionTrait::actions) una nueva acción [`FnActionWithComponent`].
pub fn new(f: FnActionWithComponent<C>) -> Self { pub fn new(f: FnActionWithComponent<C>) -> Self {
AfterRender { AfterRender {
f, f,

View file

@ -3,7 +3,7 @@ use crate::prelude::*;
use crate::base::action::FnActionWithComponent; use crate::base::action::FnActionWithComponent;
/// Ejecuta [`FnActionWithComponent`] antes de renderizar el componente. /// Ejecuta [`FnActionWithComponent`] antes de renderizar el componente.
pub struct BeforeRender<C: Component> { pub struct BeforeRender<C: ComponentTrait> {
f: FnActionWithComponent<C>, f: FnActionWithComponent<C>,
referer_type_id: Option<UniqueId>, referer_type_id: Option<UniqueId>,
referer_id: OptionId, referer_id: OptionId,
@ -11,7 +11,7 @@ pub struct BeforeRender<C: Component> {
} }
/// Filtro para despachar [`FnActionWithComponent`] antes de renderizar un componente `C`. /// Filtro para despachar [`FnActionWithComponent`] antes de renderizar un componente `C`.
impl<C: Component> ActionDispatcher for BeforeRender<C> { impl<C: ComponentTrait> ActionDispatcher for BeforeRender<C> {
/// Devuelve el identificador de tipo ([`UniqueId`]) del componente `C`. /// Devuelve el identificador de tipo ([`UniqueId`]) del componente `C`.
fn referer_type_id(&self) -> Option<UniqueId> { fn referer_type_id(&self) -> Option<UniqueId> {
self.referer_type_id self.referer_type_id
@ -28,8 +28,8 @@ impl<C: Component> ActionDispatcher for BeforeRender<C> {
} }
} }
impl<C: Component> BeforeRender<C> { impl<C: ComponentTrait> BeforeRender<C> {
/// Permite [registrar](Extension::actions) una nueva acción [`FnActionWithComponent`]. /// Permite [registrar](ExtensionTrait::actions) una nueva acción [`FnActionWithComponent`].
pub fn new(f: FnActionWithComponent<C>) -> Self { pub fn new(f: FnActionWithComponent<C>) -> Self {
BeforeRender { BeforeRender {
f, f,

View file

@ -8,7 +8,7 @@ use crate::prelude::*;
pub type FnIsRenderable<C> = fn(component: &C, cx: &Context) -> bool; pub type FnIsRenderable<C> = fn(component: &C, cx: &Context) -> bool;
/// Con la función [`FnIsRenderable`] se puede decidir si se renderiza o no un componente. /// Con la función [`FnIsRenderable`] se puede decidir si se renderiza o no un componente.
pub struct IsRenderable<C: Component> { pub struct IsRenderable<C: ComponentTrait> {
f: FnIsRenderable<C>, f: FnIsRenderable<C>,
referer_type_id: Option<UniqueId>, referer_type_id: Option<UniqueId>,
referer_id: OptionId, referer_id: OptionId,
@ -16,7 +16,7 @@ pub struct IsRenderable<C: Component> {
} }
/// Filtro para despachar [`FnIsRenderable`] para decidir si se renderiza o no un componente `C`. /// Filtro para despachar [`FnIsRenderable`] para decidir si se renderiza o no un componente `C`.
impl<C: Component> ActionDispatcher for IsRenderable<C> { impl<C: ComponentTrait> ActionDispatcher for IsRenderable<C> {
/// Devuelve el identificador de tipo ([`UniqueId`]) del componente `C`. /// Devuelve el identificador de tipo ([`UniqueId`]) del componente `C`.
fn referer_type_id(&self) -> Option<UniqueId> { fn referer_type_id(&self) -> Option<UniqueId> {
self.referer_type_id self.referer_type_id
@ -33,8 +33,8 @@ impl<C: Component> ActionDispatcher for IsRenderable<C> {
} }
} }
impl<C: Component> IsRenderable<C> { impl<C: ComponentTrait> IsRenderable<C> {
/// Permite [registrar](Extension::actions) una nueva acción [`FnIsRenderable`]. /// Permite [registrar](ExtensionTrait::actions) una nueva acción [`FnIsRenderable`].
pub fn new(f: FnIsRenderable<C>) -> Self { pub fn new(f: FnIsRenderable<C>) -> Self {
IsRenderable { IsRenderable {
f, f,

View file

@ -22,7 +22,7 @@ impl ActionDispatcher for AfterRenderBody {
} }
impl AfterRenderBody { impl AfterRenderBody {
/// Permite [registrar](Extension::actions) una nueva acción /// Permite [registrar](ExtensionTrait::actions) una nueva acción
/// [`FnActionWithPage`](crate::base::action::page::FnActionWithPage). /// [`FnActionWithPage`](crate::base::action::page::FnActionWithPage).
pub fn new(f: FnActionWithPage) -> Self { pub fn new(f: FnActionWithPage) -> Self {
AfterRenderBody { f, weight: 0 } AfterRenderBody { f, weight: 0 }

View file

@ -22,7 +22,7 @@ impl ActionDispatcher for BeforeRenderBody {
} }
impl BeforeRenderBody { impl BeforeRenderBody {
/// Permite [registrar](Extension::actions) una nueva acción /// Permite [registrar](ExtensionTrait::actions) una nueva acción
/// [`FnActionWithPage`](crate::base::action::page::FnActionWithPage). /// [`FnActionWithPage`](crate::base::action::page::FnActionWithPage).
pub fn new(f: FnActionWithPage) -> Self { pub fn new(f: FnActionWithPage) -> Self {
BeforeRenderBody { f, weight: 0 } BeforeRenderBody { f, weight: 0 }

View file

@ -3,7 +3,7 @@ use crate::prelude::*;
use crate::base::action::FnActionWithComponent; use crate::base::action::FnActionWithComponent;
/// Ejecuta [`FnActionWithComponent`] después de que un tema renderice el componente. /// Ejecuta [`FnActionWithComponent`] después de que un tema renderice el componente.
pub struct AfterRender<C: Component> { pub struct AfterRender<C: ComponentTrait> {
f: FnActionWithComponent<C>, f: FnActionWithComponent<C>,
theme_type_id: Option<UniqueId>, theme_type_id: Option<UniqueId>,
referer_type_id: Option<UniqueId>, referer_type_id: Option<UniqueId>,
@ -11,7 +11,7 @@ pub struct AfterRender<C: Component> {
/// Filtro para despachar [`FnActionWithComponent`] después de que un tema renderice el componente /// Filtro para despachar [`FnActionWithComponent`] después de que un tema renderice el componente
/// `C`. /// `C`.
impl<C: Component> ActionDispatcher for AfterRender<C> { impl<C: ComponentTrait> ActionDispatcher for AfterRender<C> {
/// Devuelve el identificador de tipo ([`UniqueId`]) del tema. /// Devuelve el identificador de tipo ([`UniqueId`]) del tema.
fn theme_type_id(&self) -> Option<UniqueId> { fn theme_type_id(&self) -> Option<UniqueId> {
self.theme_type_id self.theme_type_id
@ -23,9 +23,9 @@ impl<C: Component> ActionDispatcher for AfterRender<C> {
} }
} }
impl<C: Component> AfterRender<C> { impl<C: ComponentTrait> AfterRender<C> {
/// Permite [registrar](Extension::actions) una nueva acción [`FnActionWithComponent`] para un /// Permite [registrar](ExtensionTrait::actions) una nueva acción [`FnActionWithComponent`] para
/// tema dado. /// un tema dado.
pub fn new(theme: ThemeRef, f: FnActionWithComponent<C>) -> Self { pub fn new(theme: ThemeRef, f: FnActionWithComponent<C>) -> Self {
AfterRender { AfterRender {
f, f,

View file

@ -3,7 +3,7 @@ use crate::prelude::*;
use crate::base::action::FnActionWithComponent; use crate::base::action::FnActionWithComponent;
/// Ejecuta [`FnActionWithComponent`] antes de que un tema renderice el componente. /// Ejecuta [`FnActionWithComponent`] antes de que un tema renderice el componente.
pub struct BeforeRender<C: Component> { pub struct BeforeRender<C: ComponentTrait> {
f: FnActionWithComponent<C>, f: FnActionWithComponent<C>,
theme_type_id: Option<UniqueId>, theme_type_id: Option<UniqueId>,
referer_type_id: Option<UniqueId>, referer_type_id: Option<UniqueId>,
@ -11,7 +11,7 @@ pub struct BeforeRender<C: Component> {
/// Filtro para despachar [`FnActionWithComponent`] antes de que un tema renderice el componente /// Filtro para despachar [`FnActionWithComponent`] antes de que un tema renderice el componente
/// `C`. /// `C`.
impl<C: Component> ActionDispatcher for BeforeRender<C> { impl<C: ComponentTrait> ActionDispatcher for BeforeRender<C> {
/// Devuelve el identificador de tipo ([`UniqueId`]) del tema. /// Devuelve el identificador de tipo ([`UniqueId`]) del tema.
fn theme_type_id(&self) -> Option<UniqueId> { fn theme_type_id(&self) -> Option<UniqueId> {
self.theme_type_id self.theme_type_id
@ -23,9 +23,9 @@ impl<C: Component> ActionDispatcher for BeforeRender<C> {
} }
} }
impl<C: Component> BeforeRender<C> { impl<C: ComponentTrait> BeforeRender<C> {
/// Permite [registrar](Extension::actions) una nueva acción [`FnActionWithComponent`] para un /// Permite [registrar](ExtensionTrait::actions) una nueva acción [`FnActionWithComponent`] para
/// tema dado. /// un tema dado.
pub fn new(theme: ThemeRef, f: FnActionWithComponent<C>) -> Self { pub fn new(theme: ThemeRef, f: FnActionWithComponent<C>) -> Self {
BeforeRender { BeforeRender {
f, f,

View file

@ -11,14 +11,14 @@ pub type FnPrepareRender<C> = fn(component: &C, cx: &mut Context) -> PrepareMark
/// Ejecuta [`FnPrepareRender`] para preparar el renderizado de un componente. /// Ejecuta [`FnPrepareRender`] para preparar el renderizado de un componente.
/// ///
/// Permite a un tema hacer una implementación nueva del renderizado de un componente. /// Permite a un tema hacer una implementación nueva del renderizado de un componente.
pub struct PrepareRender<C: Component> { pub struct PrepareRender<C: ComponentTrait> {
f: FnPrepareRender<C>, f: FnPrepareRender<C>,
theme_type_id: Option<UniqueId>, theme_type_id: Option<UniqueId>,
referer_type_id: Option<UniqueId>, referer_type_id: Option<UniqueId>,
} }
/// Filtro para despachar [`FnPrepareRender`] que modifica el renderizado de un componente `C`. /// Filtro para despachar [`FnPrepareRender`] que modifica el renderizado de un componente `C`.
impl<C: Component> ActionDispatcher for PrepareRender<C> { impl<C: ComponentTrait> ActionDispatcher for PrepareRender<C> {
/// Devuelve el identificador de tipo ([`UniqueId`]) del tema. /// Devuelve el identificador de tipo ([`UniqueId`]) del tema.
fn theme_type_id(&self) -> Option<UniqueId> { fn theme_type_id(&self) -> Option<UniqueId> {
self.theme_type_id self.theme_type_id
@ -30,9 +30,9 @@ impl<C: Component> ActionDispatcher for PrepareRender<C> {
} }
} }
impl<C: Component> PrepareRender<C> { impl<C: ComponentTrait> PrepareRender<C> {
/// Permite [registrar](Extension::actions) una nueva acción [`FnPrepareRender`] para un tema /// Permite [registrar](ExtensionTrait::actions) una nueva acción [`FnPrepareRender`] para un
/// dado. /// tema dado.
pub fn new(theme: ThemeRef, f: FnPrepareRender<C>) -> Self { pub fn new(theme: ThemeRef, f: FnPrepareRender<C>) -> Self {
PrepareRender { PrepareRender {
f, f,

View file

@ -38,7 +38,7 @@ impl Default for Html {
Html::with(|_| html! {}) Html::with(|_| html! {})
} }
} }
impl Component for Html { impl ComponentTrait for Html {
fn new() -> Self { fn new() -> Self {
Html::default() Html::default()
} }
@ -51,9 +51,9 @@ impl Component for Html {
impl Html { impl Html {
/// Crea una instancia que generará el `Markup`, con acceso opcional al contexto. /// Crea una instancia que generará el `Markup`, con acceso opcional al contexto.
/// ///
/// El método [`prepare_component()`](crate::core::component::Component::prepare_component) /// El método [`prepare_component`](crate::core::component::ComponentTrait::prepare_component)
/// delega el renderizado en la función proporcionada, que recibe una referencia mutable al /// delega el renderizado en la función proporcionada, que recibe una referencia mutable
/// contexto de renderizado ([`Context`]). /// al contexto de renderizado ([`Context`]).
pub fn with<F>(f: F) -> Self pub fn with<F>(f: F) -> Self
where where
F: Fn(&mut Context) -> Markup + Send + Sync + 'static, F: Fn(&mut Context) -> Markup + Send + Sync + 'static,
@ -64,8 +64,8 @@ impl Html {
/// Sustituye la función que genera el `Markup`. /// Sustituye la función que genera el `Markup`.
/// ///
/// Permite a otras extensiones modificar la función de renderizado que se ejecutará cuando /// Permite a otras extensiones modificar la función de renderizado que se ejecutará cuando
/// [`prepare_component()`](crate::core::component::Component::prepare_component) invoque esta /// [`prepare_component`](crate::core::component::ComponentTrait::prepare_component) invoque
/// instancia. La nueva función también recibe una referencia al contexto ([`Context`]). /// esta instancia. La nueva función también recibe una referencia al contexto ([`Context`]).
pub fn alter_html<F>(&mut self, f: F) -> &mut Self pub fn alter_html<F>(&mut self, f: F) -> &mut Self
where where
F: Fn(&mut Context) -> Markup + Send + Sync + 'static, F: Fn(&mut Context) -> Markup + Send + Sync + 'static,

View file

@ -7,7 +7,7 @@ use crate::prelude::*;
/// funcionando correctamente. /// funcionando correctamente.
pub struct Welcome; pub struct Welcome;
impl Extension for Welcome { impl ExtensionTrait for Welcome {
fn name(&self) -> L10n { fn name(&self) -> L10n {
L10n::l("welcome_extension_name") L10n::l("welcome_extension_name")
} }

View file

@ -5,13 +5,13 @@ use crate::prelude::*;
/// Tema básico por defecto. /// Tema básico por defecto.
pub struct Basic; pub struct Basic;
impl Extension for Basic { impl ExtensionTrait for Basic {
fn theme(&self) -> Option<ThemeRef> { fn theme(&self) -> Option<ThemeRef> {
Some(&Self) Some(&Self)
} }
} }
impl Theme for Basic { impl ThemeTrait for Basic {
fn after_render_page_body(&self, page: &mut Page) { fn after_render_page_body(&self, page: &mut Page) {
page.alter_assets(AssetsOp::AddStyleSheet( page.alter_assets(AssetsOp::AddStyleSheet(
StyleSheet::from("/css/normalize.css") StyleSheet::from("/css/normalize.css")

View file

@ -14,7 +14,8 @@ mod all;
pub(crate) use all::add_action; pub(crate) use all::add_action;
pub use all::dispatch_actions; pub use all::dispatch_actions;
/// Facilita la implementación del método [`actions()`](crate::core::extension::Extension::actions). /// Facilita la implementación del método
/// [`actions()`](crate::core::extension::ExtensionTrait::actions).
/// ///
/// Evita escribir repetidamente `Box::new(...)` para cada acción de la lista, manteniendo el código /// Evita escribir repetidamente `Box::new(...)` para cada acción de la lista, manteniendo el código
/// más limpio. /// más limpio.
@ -24,7 +25,7 @@ pub use all::dispatch_actions;
/// ```rust,ignore /// ```rust,ignore
/// use pagetop::prelude::*; /// use pagetop::prelude::*;
/// ///
/// impl Extension for MyTheme { /// impl ExtensionTrait for MyTheme {
/// fn actions(&self) -> Vec<ActionBox> { /// fn actions(&self) -> Vec<ActionBox> {
/// actions_boxed![ /// actions_boxed![
/// action::theme::BeforeRender::<Button>::new(&Self, before_render_button), /// action::theme::BeforeRender::<Button>::new(&Self, before_render_button),
@ -33,7 +34,7 @@ pub use all::dispatch_actions;
/// } /// }
/// } /// }
/// ///
/// impl Theme for MyTheme {} /// impl ThemeTrait for MyTheme {}
/// ///
/// fn before_render_button(c: &mut Button, cx: &mut Context) { todo!() } /// fn before_render_button(c: &mut Button, cx: &mut Context) { todo!() }
/// fn render_error404(c: &Error404, cx: &mut Context) -> PrepareMarkup { todo!() } /// fn render_error404(c: &Error404, cx: &mut Context) -> PrepareMarkup { todo!() }

View file

@ -1,7 +1,7 @@
//! API para construir nuevos componentes. //! API para construir nuevos componentes.
mod definition; mod definition;
pub use definition::{Component, ComponentRender}; pub use definition::{ComponentRender, ComponentTrait};
mod children; mod children;
pub use children::Children; pub use children::Children;

View file

@ -1,4 +1,4 @@
use crate::core::component::Component; use crate::core::component::ComponentTrait;
use crate::html::{html, Context, Markup}; use crate::html::{html, Context, Markup};
use crate::{builder_fn, UniqueId}; use crate::{builder_fn, UniqueId};
@ -9,14 +9,14 @@ use std::vec::IntoIter;
/// Representa un componente encapsulado de forma segura y compartida. /// Representa un componente encapsulado de forma segura y compartida.
/// ///
/// Esta estructura permite manipular y renderizar cualquier tipo que implemente [`Component`], /// Esta estructura permite manipular y renderizar cualquier tipo que implemente [`ComponentTrait`],
/// garantizando acceso concurrente a través de [`Arc<RwLock<_>>`]. /// garantizando acceso concurrente a través de [`Arc<RwLock<_>>`].
#[derive(Clone)] #[derive(Clone)]
pub struct Child(Arc<RwLock<dyn Component>>); pub struct Child(Arc<RwLock<dyn ComponentTrait>>);
impl Child { impl Child {
/// Crea un nuevo [`Child`] a partir de un componente. /// Crea un nuevo [`Child`] a partir de un componente.
pub fn with(component: impl Component) -> Self { pub fn with(component: impl ComponentTrait) -> Self {
Child(Arc::new(RwLock::new(component))) Child(Arc::new(RwLock::new(component)))
} }
@ -47,15 +47,15 @@ impl Child {
/// Variante tipada de [`Child`] para evitar conversiones durante el uso. /// Variante tipada de [`Child`] para evitar conversiones durante el uso.
/// ///
/// Facilita el acceso a componentes del mismo tipo sin necesidad de hacer `downcast`. /// Facilita el acceso a componentes del mismo tipo sin necesidad de hacer `downcast`.
pub struct Typed<C: Component>(Arc<RwLock<C>>); pub struct Typed<C: ComponentTrait>(Arc<RwLock<C>>);
impl<C: Component> Clone for Typed<C> { impl<C: ComponentTrait> Clone for Typed<C> {
fn clone(&self) -> Self { fn clone(&self) -> Self {
Self(self.0.clone()) Self(self.0.clone())
} }
} }
impl<C: Component> Typed<C> { impl<C: ComponentTrait> Typed<C> {
/// Crea un nuevo [`Typed`] a partir de un componente. /// Crea un nuevo [`Typed`] a partir de un componente.
pub fn with(component: C) -> Self { pub fn with(component: C) -> Self {
Typed(Arc::new(RwLock::new(component))) Typed(Arc::new(RwLock::new(component)))
@ -97,7 +97,7 @@ pub enum ChildOp {
} }
/// Operaciones con un componente hijo tipado [`Typed<C>`] en una lista [`Children`]. /// Operaciones con un componente hijo tipado [`Typed<C>`] en una lista [`Children`].
pub enum TypedOp<C: Component> { pub enum TypedOp<C: ComponentTrait> {
Add(Typed<C>), Add(Typed<C>),
InsertAfterId(&'static str, Typed<C>), InsertAfterId(&'static str, Typed<C>),
InsertBeforeId(&'static str, Typed<C>), InsertBeforeId(&'static str, Typed<C>),
@ -153,7 +153,7 @@ impl Children {
/// Ejecuta una operación con [`TypedOp`] en la lista. /// Ejecuta una operación con [`TypedOp`] en la lista.
#[builder_fn] #[builder_fn]
pub fn with_typed<C: Component + Default>(mut self, op: TypedOp<C>) -> Self { pub fn with_typed<C: ComponentTrait + Default>(mut self, op: TypedOp<C>) -> Self {
match op { match op {
TypedOp::Add(typed) => self.add(typed.into_child()), TypedOp::Add(typed) => self.add(typed.into_child()),
TypedOp::InsertAfterId(id, typed) => self.insert_after_id(id, typed.into_child()), TypedOp::InsertAfterId(id, typed) => self.insert_after_id(id, typed.into_child()),

View file

@ -5,7 +5,7 @@ use crate::html::{html, Context, Markup, PrepareMarkup, Render};
/// Define la función de renderizado para todos los componentes. /// Define la función de renderizado para todos los componentes.
/// ///
/// Este *trait* se implementa automáticamente en cualquier tipo (componente) que implemente /// Este *trait* se implementa automáticamente en cualquier tipo (componente) que implemente
/// [`Component`], por lo que no requiere ninguna codificación manual. /// [`ComponentTrait`], por lo que no requiere ninguna codificación manual.
pub trait ComponentRender { pub trait ComponentRender {
/// Renderiza el componente usando el contexto proporcionado. /// Renderiza el componente usando el contexto proporcionado.
fn render(&mut self, cx: &mut Context) -> Markup; fn render(&mut self, cx: &mut Context) -> Markup;
@ -14,9 +14,9 @@ pub trait ComponentRender {
/// Interfaz común que debe implementar un componente renderizable en `PageTop`. /// Interfaz común que debe implementar un componente renderizable en `PageTop`.
/// ///
/// Se recomienda que los componentes deriven [`AutoDefault`](crate::AutoDefault). También deben /// Se recomienda que los componentes deriven [`AutoDefault`](crate::AutoDefault). También deben
/// implementar explícitamente el método [`new()`](Self::new) y pueden sobrescribir los otros /// implementar explícitamente el método [`new`](Self::new) y pueden sobrescribir los otros métodos
/// métodos para personalizar su comportamiento. /// para personalizar su comportamiento.
pub trait Component: AnyInfo + ComponentRender + Send + Sync { pub trait ComponentTrait: AnyInfo + ComponentRender + Send + Sync {
/// Crea una nueva instancia del componente. /// Crea una nueva instancia del componente.
fn new() -> Self fn new() -> Self
where where
@ -70,8 +70,8 @@ pub trait Component: AnyInfo + ComponentRender + Send + Sync {
/// ///
/// 1. Despacha [`action::component::IsRenderable`](crate::base::action::component::IsRenderable) /// 1. Despacha [`action::component::IsRenderable`](crate::base::action::component::IsRenderable)
/// para ver si se puede renderizar. Si no es así, devuelve un [`Markup`] vacío. /// para ver si se puede renderizar. Si no es así, devuelve un [`Markup`] vacío.
/// 2. Ejecuta [`setup_before_prepare()`](Component::setup_before_prepare) para que el componente /// 2. Ejecuta [`setup_before_prepare()`](ComponentTrait::setup_before_prepare) para que el
/// pueda ajustar su estructura interna o modificar el contexto. /// componente pueda ajustar su estructura interna o modificar el contexto.
/// 3. Despacha [`action::theme::BeforeRender<C>`](crate::base::action::theme::BeforeRender) para /// 3. Despacha [`action::theme::BeforeRender<C>`](crate::base::action::theme::BeforeRender) para
/// que el tema pueda hacer ajustes en el componente o el contexto. /// que el tema pueda hacer ajustes en el componente o el contexto.
/// 4. Despacha [`action::component::BeforeRender<C>`](crate::base::action::component::BeforeRender) /// 4. Despacha [`action::component::BeforeRender<C>`](crate::base::action::component::BeforeRender)
@ -79,14 +79,14 @@ pub trait Component: AnyInfo + ComponentRender + Send + Sync {
/// 5. **Prepara el renderizado del componente**: /// 5. **Prepara el renderizado del componente**:
/// - Despacha [`action::theme::PrepareRender<C>`](crate::base::action::theme::PrepareRender) /// - Despacha [`action::theme::PrepareRender<C>`](crate::base::action::theme::PrepareRender)
/// para permitir al tema preparar un renderizado diferente al predefinido. /// para permitir al tema preparar un renderizado diferente al predefinido.
/// - Si no es así, ejecuta [`prepare_component()`](Component::prepare_component) para preparar /// - Si no es así, ejecuta [`prepare_component()`](ComponentTrait::prepare_component) para
/// el renderizado predefinido del componente. /// preparar el renderizado predefinido del componente.
/// 6. Despacha [`action::theme::AfterRender<C>`](crate::base::action::theme::AfterRender) para /// 6. Despacha [`action::theme::AfterRender<C>`](crate::base::action::theme::AfterRender) para
/// que el tema pueda hacer sus últimos ajustes. /// que el tema pueda hacer sus últimos ajustes.
/// 7. Despacha [`action::component::AfterRender<C>`](crate::base::action::component::AfterRender) /// 7. Despacha [`action::component::AfterRender<C>`](crate::base::action::component::AfterRender)
/// para que otras extensiones puedan hacer sus últimos ajustes. /// para que otras extensiones puedan hacer sus últimos ajustes.
/// 8. Finalmente devuelve un [`Markup`] del renderizado preparado en el paso 5. /// 8. Finalmente devuelve un [`Markup`] del renderizado preparado en el paso 5.
impl<C: Component> ComponentRender for C { impl<C: ComponentTrait> ComponentRender for C {
fn render(&mut self, cx: &mut Context) -> Markup { fn render(&mut self, cx: &mut Context) -> Markup {
// Si no es renderizable, devuelve un bloque HTML vacío. // Si no es renderizable, devuelve un bloque HTML vacío.
if !action::component::IsRenderable::dispatch(self, cx) { if !action::component::IsRenderable::dispatch(self, cx) {

View file

@ -1,9 +1,9 @@
//! API para añadir nuevas funcionalidades usando extensiones. //! API para añadir nuevas funcionalidades usando extensiones.
//! //!
//! Cada funcionalidad adicional que quiera incorporarse a una aplicación `PageTop` se debe modelar //! Cada funcionalidad adicional que quiera incorporarse a una aplicación `PageTop` se debe modelar
//! como una **extensión**. Todas comparten la misma interfaz declarada en [`Extension`]. //! como una **extensión**. Todas comparten la misma interfaz declarada en [`ExtensionTrait`].
mod definition; mod definition;
pub use definition::{Extension, ExtensionRef}; pub use definition::{ExtensionRef, ExtensionTrait};
pub(crate) mod all; pub(crate) mod all;

View file

@ -8,7 +8,7 @@ use crate::{actions_boxed, service};
/// ///
/// Las extensiones se definen como instancias estáticas globales para poder acceder a ellas desde /// Las extensiones se definen como instancias estáticas globales para poder acceder a ellas desde
/// cualquier hilo de la ejecución sin necesidad de sincronización adicional. /// cualquier hilo de la ejecución sin necesidad de sincronización adicional.
pub type ExtensionRef = &'static dyn Extension; pub type ExtensionRef = &'static dyn ExtensionTrait;
/// Interfaz común que debe implementar cualquier extensión de `PageTop`. /// Interfaz común que debe implementar cualquier extensión de `PageTop`.
/// ///
@ -20,16 +20,15 @@ pub type ExtensionRef = &'static dyn Extension;
/// ///
/// pub struct Blog; /// pub struct Blog;
/// ///
/// impl Extension for Blog { /// impl ExtensionTrait for Blog {
/// fn name(&self) -> L10n { L10n::n("Blog") } /// fn name(&self) -> L10n { L10n::n("Blog") }
/// fn description(&self) -> L10n { L10n::n("Sistema de blogs") } /// fn description(&self) -> L10n { L10n::n("Sistema de blogs") }
/// } /// }
/// ``` /// ```
pub trait Extension: AnyInfo + Send + Sync { pub trait ExtensionTrait: AnyInfo + Send + Sync {
/// Nombre legible para el usuario. /// Nombre legible para el usuario.
/// ///
/// Predeterminado por el [`short_name()`](AnyInfo::short_name) del tipo asociado a la /// Predeterminado por el [`short_name`](AnyInfo::short_name) del tipo asociado a la extensión.
/// extensión.
fn name(&self) -> L10n { fn name(&self) -> L10n {
L10n::n(self.short_name()) L10n::n(self.short_name())
} }
@ -39,8 +38,8 @@ pub trait Extension: AnyInfo + Send + Sync {
L10n::default() L10n::default()
} }
/// Los temas son extensiones que implementan [`Extension`] y también /// Los temas son extensiones que implementan [`ExtensionTrait`] y también
/// [`Theme`](crate::core::theme::Theme). /// [`ThemeTrait`](crate::core::theme::ThemeTrait).
/// ///
/// Si la extensión no es un tema, este método devuelve `None` por defecto. /// Si la extensión no es un tema, este método devuelve `None` por defecto.
/// ///
@ -52,13 +51,13 @@ pub trait Extension: AnyInfo + Send + Sync {
/// ///
/// pub struct MyTheme; /// pub struct MyTheme;
/// ///
/// impl Extension for MyTheme { /// impl ExtensionTrait for MyTheme {
/// fn theme(&self) -> Option<ThemeRef> { /// fn theme(&self) -> Option<ThemeRef> {
/// Some(&Self) /// Some(&Self)
/// } /// }
/// } /// }
/// ///
/// impl Theme for MyTheme {} /// impl ThemeTrait for MyTheme {}
/// ``` /// ```
fn theme(&self) -> Option<ThemeRef> { fn theme(&self) -> Option<ThemeRef> {
None None
@ -95,7 +94,7 @@ pub trait Extension: AnyInfo + Send + Sync {
/// ///
/// pub struct ExtensionSample; /// pub struct ExtensionSample;
/// ///
/// impl Extension for ExtensionSample { /// impl ExtensionTrait for ExtensionSample {
/// fn configure_service(&self, scfg: &mut service::web::ServiceConfig) { /// fn configure_service(&self, scfg: &mut service::web::ServiceConfig) {
/// scfg.route("/sample", web::get().to(route_sample)); /// scfg.route("/sample", web::get().to(route_sample));
/// } /// }

View file

@ -9,12 +9,13 @@
//! tipografías, espaciados y cualquier otro detalle visual o de comportamiento (comoanimaciones, //! tipografías, espaciados y cualquier otro detalle visual o de comportamiento (comoanimaciones,
//! *scripts* de interfaz, etc.). //! *scripts* de interfaz, etc.).
//! //!
//! Es una extensión más (implementando [`Extension`](crate::core::extension::Extension)). Se //! Es una extensión más (implementando [`ExtensionTrait`](crate::core::extension::ExtensionTrait)).
//! instala, activa y declara dependencias igual que el resto de extensiones; y se señala a sí misma //! Se instala, activa y declara dependencias igual que el resto de extensiones; y se señala a sí
//! como tema (implementando [`theme()`](crate::core::extension::Extension::theme) y [`Theme`]). //! misma como tema (implementando [`theme()`](crate::core::extension::ExtensionTrait::theme)
//! y [`ThemeTrait`]).
mod definition; mod definition;
pub use definition::{Theme, ThemeRef}; pub use definition::{ThemeRef, ThemeTrait};
mod regions; mod regions;
pub(crate) use regions::ChildrenInRegions; pub(crate) use regions::ChildrenInRegions;

View file

@ -19,7 +19,7 @@ pub static DEFAULT_THEME: LazyLock<ThemeRef> =
// TEMA POR NOMBRE ********************************************************************************* // TEMA POR NOMBRE *********************************************************************************
// Devuelve el tema identificado por su [`short_name()`](AnyInfo::short_name). /// Devuelve el tema identificado por su [`short_name`](AnyInfo::short_name).
pub fn theme_by_short_name(short_name: &'static str) -> Option<ThemeRef> { pub fn theme_by_short_name(short_name: &'static str) -> Option<ThemeRef> {
let short_name = short_name.to_lowercase(); let short_name = short_name.to_lowercase();
match THEMES match THEMES

View file

@ -1,4 +1,4 @@
use crate::core::extension::Extension; use crate::core::extension::ExtensionTrait;
use crate::core::theme::CONTENT_REGION_NAME; use crate::core::theme::CONTENT_REGION_NAME;
use crate::global; use crate::global;
use crate::html::{html, Markup}; use crate::html::{html, Markup};
@ -8,20 +8,20 @@ use crate::response::page::Page;
/// Representa una referencia a un tema. /// Representa una referencia a un tema.
/// ///
/// Los temas son también extensiones. Por tanto se deben definir igual, es decir, como instancias /// Los temas son también extensiones. Por tanto se deben definir igual, es decir, como instancias
/// estáticas globales que implementan [`Theme`], pero también [`Extension`]. /// estáticas globales que implementan [`ThemeTrait`], pero también [`ExtensionTrait`].
pub type ThemeRef = &'static dyn Theme; pub type ThemeRef = &'static dyn ThemeTrait;
/// Interfaz común que debe implementar cualquier tema de `PageTop`. /// Interfaz común que debe implementar cualquier tema de `PageTop`.
/// ///
/// Un tema implementará [`Theme`] y los métodos que sean necesarios de [`Extension`], aunque el /// Un tema implementará [`ThemeTrait`] y los métodos que sean necesarios de [`ExtensionTrait`],
/// único obligatorio es [`theme()`](Extension::theme). /// aunque el único obligatorio es [`theme()`](ExtensionTrait::theme).
/// ///
/// ```rust /// ```rust
/// use pagetop::prelude::*; /// use pagetop::prelude::*;
/// ///
/// pub struct MyTheme; /// pub struct MyTheme;
/// ///
/// impl Extension for MyTheme { /// impl ExtensionTrait for MyTheme {
/// fn name(&self) -> L10n { L10n::n("My theme") } /// fn name(&self) -> L10n { L10n::n("My theme") }
/// fn description(&self) -> L10n { L10n::n("Un tema personal") } /// fn description(&self) -> L10n { L10n::n("Un tema personal") }
/// ///
@ -30,9 +30,9 @@ pub type ThemeRef = &'static dyn Theme;
/// } /// }
/// } /// }
/// ///
/// impl Theme for MyTheme {} /// impl ThemeTrait for MyTheme {}
/// ``` /// ```
pub trait Theme: Extension + Send + Sync { pub trait ThemeTrait: ExtensionTrait + Send + Sync {
fn regions(&self) -> Vec<(&'static str, L10n)> { fn regions(&self) -> Vec<(&'static str, L10n)> {
vec![(CONTENT_REGION_NAME, L10n::l("content"))] vec![(CONTENT_REGION_NAME, L10n::l("content"))]
} }

View file

@ -53,8 +53,8 @@ pub struct App {
/// Si no se especifica un valor válido, normalmente se usará el idioma devuelto por la /// Si no se especifica un valor válido, normalmente se usará el idioma devuelto por la
/// implementación de [`LangId`](crate::locale::LangId) para [`Context`](crate::html::Context), /// implementación de [`LangId`](crate::locale::LangId) para [`Context`](crate::html::Context),
/// en el siguiente orden: primero, el idioma establecido explícitamente con /// en el siguiente orden: primero, el idioma establecido explícitamente con
/// [`Context::with_langid()`](crate::html::Context::with_langid); si no se ha definido, se /// [`Context::with_langid`](crate::html::Context::with_langid); si no se ha definido, se usará
/// usará el indicado en la cabecera `Accept-Language` del navegador; y, si ninguno aplica, se /// el indicado en la cabecera `Accept-Language` del navegador; y, si ninguno aplica, se
/// empleará el idioma de respaldo ("en-US"). /// empleará el idioma de respaldo ("en-US").
pub language: String, pub language: String,
/// Banner ASCII mostrado al inicio: *"Off"* (desactivado), *"Slant"*, *"Small"*, *"Speed"* o /// Banner ASCII mostrado al inicio: *"Off"* (desactivado), *"Slant"*, *"Small"*, *"Speed"* o

View file

@ -12,8 +12,8 @@ use crate::AutoDefault;
/// ///
/// > **Nota** /// > **Nota**
/// > Los archivos de los iconos deben estar disponibles en el servidor web de la aplicación. Pueden /// > Los archivos de los iconos deben estar disponibles en el servidor web de la aplicación. Pueden
/// > incluirse en el proyecto utilizando [`include_files!`](crate::include_files) y servirse con /// > incluirse en el proyecto utilizando [`include_files`](crate::include_files) y servirse con
/// > [`include_files_service!`](crate::include_files_service). /// > [`include_files_service`](crate::include_files_service).
/// ///
/// # Ejemplo /// # Ejemplo
/// ///

View file

@ -30,8 +30,8 @@ enum Source {
/// ///
/// > **Nota** /// > **Nota**
/// > Los archivos de los *scripts* deben estar disponibles en el servidor web de la aplicación. /// > Los archivos de los *scripts* deben estar disponibles en el servidor web de la aplicación.
/// > Pueden incluirse en el proyecto utilizando [`include_files!`](crate::include_files) y servirse /// > Pueden incluirse en el proyecto utilizando [`include_files`](crate::include_files) y servirse
/// > con [`include_files_service!`](crate::include_files_service). /// > con [`include_files_service`](crate::include_files_service).
/// ///
/// # Ejemplo /// # Ejemplo
/// ///

View file

@ -55,8 +55,8 @@ impl TargetMedia {
/// ///
/// > **Nota** /// > **Nota**
/// > Las hojas de estilo CSS deben estar disponibles en el servidor web de la aplicación. Pueden /// > Las hojas de estilo CSS deben estar disponibles en el servidor web de la aplicación. Pueden
/// > incluirse en el proyecto utilizando [`include_files!`](crate::include_files) y servirse con /// > incluirse en el proyecto utilizando [`include_files`](crate::include_files) y servirse con
/// > [`include_files_service!`](crate::include_files_service). /// > [`include_files_service`](crate::include_files_service).
/// ///
/// # Ejemplo /// # Ejemplo
/// ///

View file

@ -163,7 +163,7 @@ impl Context {
/// Modifica el tema que se usará para renderizar el documento. /// Modifica el tema que se usará para renderizar el documento.
/// ///
/// Localiza el tema por su [`short_name()`](crate::core::AnyInfo::short_name), y si no aplica /// Localiza el tema por su [`short_name`](crate::core::AnyInfo::short_name), y si no aplica
/// ninguno entonces usará el tema por defecto. /// ninguno entonces usará el tema por defecto.
#[builder_fn] #[builder_fn]
pub fn with_theme(mut self, theme_name: &'static str) -> Self { pub fn with_theme(mut self, theme_name: &'static str) -> Self {
@ -301,8 +301,8 @@ impl Context {
/// 4. Y si ninguna de las opciones anteriores aplica, se usa el idioma de respaldo (`"en-US"`). /// 4. Y si ninguna de las opciones anteriores aplica, se usa el idioma de respaldo (`"en-US"`).
/// ///
/// Resulta útil para usar un contexto ([`Context`]) como fuente de traducción en /// Resulta útil para usar un contexto ([`Context`]) como fuente de traducción en
/// [`L10n::using()`](crate::locale::L10n::using) o /// [`L10n::using`](crate::locale::L10n::using) o
/// [`L10n::to_markup()`](crate::locale::L10n::to_markup). /// [`L10n::to_markup`](crate::locale::L10n::to_markup).
impl LangId for Context { impl LangId for Context {
fn langid(&self) -> &'static LanguageIdentifier { fn langid(&self) -> &'static LanguageIdentifier {
self.langid self.langid

View file

@ -1,5 +1,5 @@
use crate::builder_fn; use crate::builder_fn;
use crate::core::component::{Component, Typed}; use crate::core::component::{ComponentTrait, Typed};
use crate::html::{html, Context, Markup}; use crate::html::{html, Context, Markup};
/// Contenedor de componente para incluir en otros componentes. /// Contenedor de componente para incluir en otros componentes.
@ -16,15 +16,15 @@ use crate::html::{html, Context, Markup};
/// let opt = OptionComponent::new(comp); /// let opt = OptionComponent::new(comp);
/// assert!(opt.get().is_some()); /// assert!(opt.get().is_some());
/// ``` /// ```
pub struct OptionComponent<C: Component>(Option<Typed<C>>); pub struct OptionComponent<C: ComponentTrait>(Option<Typed<C>>);
impl<C: Component> Default for OptionComponent<C> { impl<C: ComponentTrait> Default for OptionComponent<C> {
fn default() -> Self { fn default() -> Self {
OptionComponent(None) OptionComponent(None)
} }
} }
impl<C: Component> OptionComponent<C> { impl<C: ComponentTrait> OptionComponent<C> {
/// Crea un nuevo [`OptionComponent`]. /// Crea un nuevo [`OptionComponent`].
/// ///
/// El componente se envuelve automáticamente en un [`Typed`] y se almacena. /// El componente se envuelve automáticamente en un [`Typed`] y se almacena.

View file

@ -259,8 +259,8 @@ impl LangMatch {
/// devuelve el idioma por defecto de la aplicación y, si tampoco está disponible, el idioma de /// devuelve el idioma por defecto de la aplicación y, si tampoco está disponible, el idioma de
/// respaldo ("en-US"). /// respaldo ("en-US").
/// ///
/// Resulta útil para usar un valor de [`LangMatch`] como fuente de traducción en [`L10n::using()`] /// Resulta útil para usar un valor de [`LangMatch`] como fuente de traducción en [`L10n::using`] o
/// o [`L10n::to_markup()`]. /// [`L10n::to_markup`].
impl LangId for LangMatch { impl LangId for LangMatch {
fn langid(&self) -> &'static LanguageIdentifier { fn langid(&self) -> &'static LanguageIdentifier {
match self { match self {

View file

@ -5,7 +5,7 @@ pub use actix_web::Result as ResultPage;
use crate::base::action; use crate::base::action;
use crate::builder_fn; use crate::builder_fn;
use crate::core::component::{Child, ChildOp, Component}; use crate::core::component::{Child, ChildOp, ComponentTrait};
use crate::core::theme::{ChildrenInRegions, ThemeRef, CONTENT_REGION_NAME}; use crate::core::theme::{ChildrenInRegions, ThemeRef, CONTENT_REGION_NAME};
use crate::html::{html, AssetsOp, Context, Markup, DOCTYPE}; use crate::html::{html, AssetsOp, Context, Markup, DOCTYPE};
use crate::html::{ClassesOp, OptionClasses, OptionId, OptionTranslated}; use crate::html::{ClassesOp, OptionClasses, OptionId, OptionTranslated};
@ -78,21 +78,21 @@ impl Page {
self self
} }
/// Modifica la fuente de idioma de la página ([`Context::with_langid()`]). /// Modifica la fuente de idioma de la página ([`Context::with_langid`]).
#[builder_fn] #[builder_fn]
pub fn with_langid(mut self, language: &impl LangId) -> Self { pub fn with_langid(mut self, language: &impl LangId) -> Self {
self.context.alter_langid(language); self.context.alter_langid(language);
self self
} }
/// Modifica el tema que se usará para renderizar la página ([`Context::with_theme()`]). /// Modifica el tema que se usará para renderizar la página ([`Context::with_theme`]).
#[builder_fn] #[builder_fn]
pub fn with_theme(mut self, theme_name: &'static str) -> Self { pub fn with_theme(mut self, theme_name: &'static str) -> Self {
self.context.alter_theme(theme_name); self.context.alter_theme(theme_name);
self self
} }
/// Modifica la composición para renderizar la página ([`Context::with_layout()`]). /// Modifica la composición para renderizar la página ([`Context::with_layout`]).
#[builder_fn] #[builder_fn]
pub fn with_layout(mut self, layout_name: &'static str) -> Self { pub fn with_layout(mut self, layout_name: &'static str) -> Self {
self.context.alter_layout(layout_name); self.context.alter_layout(layout_name);
@ -121,7 +121,7 @@ impl Page {
} }
/// Añade un componente a la región de contenido por defecto. /// Añade un componente a la región de contenido por defecto.
pub fn with_component(mut self, component: impl Component) -> Self { pub fn with_component(mut self, component: impl ComponentTrait) -> Self {
self.regions self.regions
.alter_child_in_region(CONTENT_REGION_NAME, ChildOp::Add(Child::with(component))); .alter_child_in_region(CONTENT_REGION_NAME, ChildOp::Add(Child::with(component)));
self self
@ -131,7 +131,7 @@ impl Page {
pub fn with_component_in( pub fn with_component_in(
mut self, mut self,
region_name: &'static str, region_name: &'static str,
component: impl Component, component: impl ComponentTrait,
) -> Self { ) -> Self {
self.regions self.regions
.alter_child_in_region(region_name, ChildOp::Add(Child::with(component))); .alter_child_in_region(region_name, ChildOp::Add(Child::with(component)));

View file

@ -77,8 +77,7 @@ macro_rules! include_files {
/// * `$route` Ruta URL de origen desde la que se servirán los archivos. /// * `$route` Ruta URL de origen desde la que se servirán los archivos.
/// * `[ $root, $relative ]` *(opcional)* Directorio raíz y ruta relativa para construir la ruta /// * `[ $root, $relative ]` *(opcional)* Directorio raíz y ruta relativa para construir la ruta
/// absoluta donde buscar los archivos en el sistema de ficheros (ver /// absoluta donde buscar los archivos en el sistema de ficheros (ver
/// [`absolute_dir()`](crate::util::absolute_dir)). Si no existe, se usarán los recursos /// [`absolute_dir`](crate::util::absolute_dir)). Si no existe, se usarán los recursos embebidos.
/// embebidos.
/// ///
/// # Ejemplos /// # Ejemplos
/// ///
@ -89,7 +88,7 @@ macro_rules! include_files {
/// ///
/// pub struct MyExtension; /// pub struct MyExtension;
/// ///
/// impl Extension for MyExtension { /// impl ExtensionTrait for MyExtension {
/// fn configure_service(&self, scfg: &mut service::web::ServiceConfig) { /// fn configure_service(&self, scfg: &mut service::web::ServiceConfig) {
/// include_files_service!(scfg, assets => "/public"); /// include_files_service!(scfg, assets => "/public");
/// } /// }