♻️ (bootsier, htmx): Adapta ciclo de render async
Añade `#[async_trait]` a todos los `impl Extension`, `Theme` y `Component`. Convierte `prepare()` en `async fn` y añade `.await` a las llamadas `render()` y `render_offcanvas()`.
This commit is contained in:
parent
9354894b3a
commit
1139df6210
17 changed files with 68 additions and 42 deletions
|
|
@ -35,6 +35,7 @@ use pagetop::prelude::*;
|
||||||
|
|
||||||
struct MyApp;
|
struct MyApp;
|
||||||
|
|
||||||
|
#[async_trait]
|
||||||
impl Extension for MyApp {
|
impl Extension for MyApp {
|
||||||
fn dependencies(&self) -> Vec<ExtensionRef> {
|
fn dependencies(&self) -> Vec<ExtensionRef> {
|
||||||
vec![
|
vec![
|
||||||
|
|
@ -69,13 +70,13 @@ async fn homepage(request: HttpRequest) -> Result<Markup, ErrorPage> {
|
||||||
p { (L10n::l("sample_content").using(cx)) }
|
p { (L10n::l("sample_content").using(cx)) }
|
||||||
})),
|
})),
|
||||||
)
|
)
|
||||||
.render()
|
.render().await
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#![doc(
|
#![doc(
|
||||||
html_favicon_url = "https://git.cillero.es/manuelcillero/pagetop/raw/branch/main/static/favicon.ico"
|
html_favicon_url = "https://git.cillero.es/manuelcillero/pagetop/raw/branch/main/assets/favicon.ico"
|
||||||
)]
|
)]
|
||||||
|
|
||||||
use pagetop::prelude::*;
|
use pagetop::prelude::*;
|
||||||
|
|
@ -99,6 +100,7 @@ mod handlers {
|
||||||
/// Implementa el tema.
|
/// Implementa el tema.
|
||||||
pub struct Bootsier;
|
pub struct Bootsier;
|
||||||
|
|
||||||
|
#[async_trait]
|
||||||
impl Extension for Bootsier {
|
impl Extension for Bootsier {
|
||||||
fn name(&self) -> L10n {
|
fn name(&self) -> L10n {
|
||||||
L10n::t("extension_name", &LOCALES_BOOTSIER)
|
L10n::t("extension_name", &LOCALES_BOOTSIER)
|
||||||
|
|
@ -128,13 +130,14 @@ impl Extension for Bootsier {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[async_trait]
|
||||||
impl Theme for Bootsier {
|
impl Theme for Bootsier {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn default_template(&self) -> TemplateRef {
|
fn default_template(&self) -> TemplateRef {
|
||||||
&BootsierTemplate::Standard
|
&BootsierTemplate::Standard
|
||||||
}
|
}
|
||||||
|
|
||||||
fn handle_component(
|
async fn handle_component(
|
||||||
&self,
|
&self,
|
||||||
component: &mut dyn Component,
|
component: &mut dyn Component,
|
||||||
cx: &mut Context,
|
cx: &mut Context,
|
||||||
|
|
|
||||||
|
|
@ -31,6 +31,7 @@ pub struct Container {
|
||||||
children: Children,
|
children: Children,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[async_trait]
|
||||||
impl Component for Container {
|
impl Component for Container {
|
||||||
fn new() -> Self {
|
fn new() -> Self {
|
||||||
Self::default()
|
Self::default()
|
||||||
|
|
@ -44,8 +45,8 @@ impl Component for Container {
|
||||||
self.alter_prop(PropsOp::prepend_classes(self.container_width().to_class()));
|
self.alter_prop(PropsOp::prepend_classes(self.container_width().to_class()));
|
||||||
}
|
}
|
||||||
|
|
||||||
fn prepare(&self, cx: &mut Context) -> Result<Markup, ComponentError> {
|
async fn prepare(&self, cx: &mut Context) -> Result<Markup, ComponentError> {
|
||||||
let output = self.children().render(cx);
|
let output = self.children().render(cx).await;
|
||||||
if output.is_empty() {
|
if output.is_empty() {
|
||||||
return Ok(html! {});
|
return Ok(html! {});
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -63,6 +63,7 @@ pub struct Dropdown {
|
||||||
items: Children,
|
items: Children,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[async_trait]
|
||||||
impl Component for Dropdown {
|
impl Component for Dropdown {
|
||||||
fn new() -> Self {
|
fn new() -> Self {
|
||||||
Self::default()
|
Self::default()
|
||||||
|
|
@ -78,9 +79,9 @@ impl Component for Dropdown {
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
fn prepare(&self, cx: &mut Context) -> Result<Markup, ComponentError> {
|
async fn prepare(&self, cx: &mut Context) -> Result<Markup, ComponentError> {
|
||||||
// Si no hay elementos en el menú, no se prepara.
|
// Si no hay elementos en el menú, no se prepara.
|
||||||
let items = self.items().render(cx);
|
let items = self.items().render(cx).await;
|
||||||
if items.is_empty() {
|
if items.is_empty() {
|
||||||
return Ok(html! {});
|
return Ok(html! {});
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -51,6 +51,7 @@ pub struct Item {
|
||||||
item_kind: ItemKind,
|
item_kind: ItemKind,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[async_trait]
|
||||||
impl Component for Item {
|
impl Component for Item {
|
||||||
fn new() -> Self {
|
fn new() -> Self {
|
||||||
Self::default()
|
Self::default()
|
||||||
|
|
@ -60,7 +61,7 @@ impl Component for Item {
|
||||||
self.props.get_id()
|
self.props.get_id()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn prepare(&self, cx: &mut Context) -> Result<Markup, ComponentError> {
|
async fn prepare(&self, cx: &mut Context) -> Result<Markup, ComponentError> {
|
||||||
Ok(match self.item_kind() {
|
Ok(match self.item_kind() {
|
||||||
ItemKind::Void => html! {},
|
ItemKind::Void => html! {},
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -112,7 +112,7 @@ impl Direction {
|
||||||
/// Alineación horizontal del menú desplegable [`Dropdown`](crate::theme::bs::Dropdown).
|
/// Alineación horizontal del menú desplegable [`Dropdown`](crate::theme::bs::Dropdown).
|
||||||
///
|
///
|
||||||
/// Permite alinear el menú al inicio o al final del botón (respetando LTR/RTL) y añadirle una
|
/// Permite alinear el menú al inicio o al final del botón (respetando LTR/RTL) y añadirle una
|
||||||
/// alineación diferente a partir de un punto de ruptura ([`BreakPoint`]).
|
/// alineación diferente a partir de un punto de ruptura ([`BreakPoint`](token::BreakPoint)).
|
||||||
#[derive(AutoDefault, Clone, Copy, Debug, PartialEq)]
|
#[derive(AutoDefault, Clone, Copy, Debug, PartialEq)]
|
||||||
pub enum MenuAlign {
|
pub enum MenuAlign {
|
||||||
/// Alineación al inicio (comportamiento por defecto).
|
/// Alineación al inicio (comportamiento por defecto).
|
||||||
|
|
|
||||||
|
|
@ -21,6 +21,7 @@ pub struct Icon {
|
||||||
aria_label: AttrL10n,
|
aria_label: AttrL10n,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[async_trait]
|
||||||
impl Component for Icon {
|
impl Component for Icon {
|
||||||
fn new() -> Self {
|
fn new() -> Self {
|
||||||
Self::default()
|
Self::default()
|
||||||
|
|
@ -39,7 +40,7 @@ impl Component for Icon {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn prepare(&self, cx: &mut Context) -> Result<Markup, ComponentError> {
|
async fn prepare(&self, cx: &mut Context) -> Result<Markup, ComponentError> {
|
||||||
Ok(match self.icon_kind() {
|
Ok(match self.icon_kind() {
|
||||||
IconKind::None => html! {},
|
IconKind::None => html! {},
|
||||||
IconKind::Font(_) => {
|
IconKind::Font(_) => {
|
||||||
|
|
|
||||||
|
|
@ -24,6 +24,7 @@ pub struct Image {
|
||||||
alternative: Attr<L10n>,
|
alternative: Attr<L10n>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[async_trait]
|
||||||
impl Component for Image {
|
impl Component for Image {
|
||||||
fn new() -> Self {
|
fn new() -> Self {
|
||||||
Self::default()
|
Self::default()
|
||||||
|
|
@ -38,7 +39,7 @@ impl Component for Image {
|
||||||
self.alter_prop(PropsOp::prepend_classes(self.source().to_class()));
|
self.alter_prop(PropsOp::prepend_classes(self.source().to_class()));
|
||||||
}
|
}
|
||||||
|
|
||||||
fn prepare(&self, cx: &mut Context) -> Result<Markup, ComponentError> {
|
async fn prepare(&self, cx: &mut Context) -> Result<Markup, ComponentError> {
|
||||||
let dimensions = self.size().to_style();
|
let dimensions = self.size().to_style();
|
||||||
let alt_text = self.alternative().lookup(cx).unwrap_or_default();
|
let alt_text = self.alternative().lookup(cx).unwrap_or_default();
|
||||||
let is_decorative = alt_text.is_empty();
|
let is_decorative = alt_text.is_empty();
|
||||||
|
|
@ -52,7 +53,7 @@ impl Component for Image {
|
||||||
aria-label=[(!is_decorative).then_some(alt_text)]
|
aria-label=[(!is_decorative).then_some(alt_text)]
|
||||||
aria-hidden=[is_decorative.then_some("true")]
|
aria-hidden=[is_decorative.then_some("true")]
|
||||||
{
|
{
|
||||||
(logo.render(cx))
|
(logo.markup(cx))
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -44,6 +44,7 @@ pub struct Nav {
|
||||||
items: Children,
|
items: Children,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[async_trait]
|
||||||
impl Component for Nav {
|
impl Component for Nav {
|
||||||
fn new() -> Self {
|
fn new() -> Self {
|
||||||
Self::default()
|
Self::default()
|
||||||
|
|
@ -63,8 +64,8 @@ impl Component for Nav {
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
|
|
||||||
fn prepare(&self, cx: &mut Context) -> Result<Markup, ComponentError> {
|
async fn prepare(&self, cx: &mut Context) -> Result<Markup, ComponentError> {
|
||||||
let items = self.items().render(cx);
|
let items = self.items().render(cx).await;
|
||||||
if items.is_empty() {
|
if items.is_empty() {
|
||||||
return Ok(html! {});
|
return Ok(html! {});
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -65,6 +65,7 @@ pub struct Item {
|
||||||
item_kind: ItemKind,
|
item_kind: ItemKind,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[async_trait]
|
||||||
impl Component for Item {
|
impl Component for Item {
|
||||||
fn new() -> Self {
|
fn new() -> Self {
|
||||||
Self::default()
|
Self::default()
|
||||||
|
|
@ -78,7 +79,7 @@ impl Component for Item {
|
||||||
self.alter_prop(PropsOp::prepend_classes(self.item_kind().as_str()));
|
self.alter_prop(PropsOp::prepend_classes(self.item_kind().as_str()));
|
||||||
}
|
}
|
||||||
|
|
||||||
fn prepare(&self, cx: &mut Context) -> Result<Markup, ComponentError> {
|
async fn prepare(&self, cx: &mut Context) -> Result<Markup, ComponentError> {
|
||||||
Ok(match self.item_kind() {
|
Ok(match self.item_kind() {
|
||||||
ItemKind::Void => html! {},
|
ItemKind::Void => html! {},
|
||||||
|
|
||||||
|
|
@ -133,13 +134,13 @@ impl Component for Item {
|
||||||
|
|
||||||
ItemKind::Html(html) => html! {
|
ItemKind::Html(html) => html! {
|
||||||
li (self.props()) {
|
li (self.props()) {
|
||||||
(html.render(cx))
|
(html.render(cx).await)
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
ItemKind::Dropdown(menu) => {
|
ItemKind::Dropdown(menu) => {
|
||||||
if let Some(dd) = menu.get() {
|
if let Some(dd) = menu.get() {
|
||||||
let items = dd.items().render(cx);
|
let items = dd.items().render(cx).await;
|
||||||
if items.is_empty() {
|
if items.is_empty() {
|
||||||
return Ok(html! {});
|
return Ok(html! {});
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -25,13 +25,14 @@ pub struct Brand {
|
||||||
route: Option<FnPathByContext>,
|
route: Option<FnPathByContext>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[async_trait]
|
||||||
impl Component for Brand {
|
impl Component for Brand {
|
||||||
fn new() -> Self {
|
fn new() -> Self {
|
||||||
Self::default()
|
Self::default()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn prepare(&self, cx: &mut Context) -> Result<Markup, ComponentError> {
|
async fn prepare(&self, cx: &mut Context) -> Result<Markup, ComponentError> {
|
||||||
let image = self.image().render(cx);
|
let image = self.image().render(cx).await;
|
||||||
let title = self.title().using(cx);
|
let title = self.title().using(cx);
|
||||||
if title.is_empty() && image.is_empty() {
|
if title.is_empty() && image.is_empty() {
|
||||||
return Ok(html! {});
|
return Ok(html! {});
|
||||||
|
|
|
||||||
|
|
@ -149,6 +149,7 @@ pub struct Navbar {
|
||||||
items: Children,
|
items: Children,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[async_trait]
|
||||||
impl Component for Navbar {
|
impl Component for Navbar {
|
||||||
fn new() -> Self {
|
fn new() -> Self {
|
||||||
Self::default()
|
Self::default()
|
||||||
|
|
@ -171,7 +172,7 @@ impl Component for Navbar {
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
|
|
||||||
fn prepare(&self, cx: &mut Context) -> Result<Markup, ComponentError> {
|
async fn prepare(&self, cx: &mut Context) -> Result<Markup, ComponentError> {
|
||||||
// Botón de despliegue (colapso u offcanvas) para la barra.
|
// Botón de despliegue (colapso u offcanvas) para la barra.
|
||||||
fn button(cx: &mut Context, data_bs_toggle: &str, id_content: &str) -> Markup {
|
fn button(cx: &mut Context, data_bs_toggle: &str, id_content: &str) -> Markup {
|
||||||
let id_content_target = util::join!("#", id_content);
|
let id_content_target = util::join!("#", id_content);
|
||||||
|
|
@ -196,7 +197,7 @@ impl Component for Navbar {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Si no hay contenidos, no tiene sentido mostrar una barra vacía.
|
// Si no hay contenidos, no tiene sentido mostrar una barra vacía.
|
||||||
let items = self.items().render(cx);
|
let items = self.items().render(cx).await;
|
||||||
if items.is_empty() {
|
if items.is_empty() {
|
||||||
return Ok(html! {});
|
return Ok(html! {});
|
||||||
}
|
}
|
||||||
|
|
@ -225,7 +226,7 @@ impl Component for Navbar {
|
||||||
|
|
||||||
// Barra con marca a la izquierda, siempre visible.
|
// Barra con marca a la izquierda, siempre visible.
|
||||||
bs::navbar::Layout::SimpleBrandLeft(brand) => {
|
bs::navbar::Layout::SimpleBrandLeft(brand) => {
|
||||||
(brand.render(cx))
|
(brand.render(cx).await)
|
||||||
(items)
|
(items)
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|
@ -233,7 +234,7 @@ impl Component for Navbar {
|
||||||
bs::navbar::Layout::BrandLeft(brand) => {
|
bs::navbar::Layout::BrandLeft(brand) => {
|
||||||
@let id_content = util::join!(id, "-content");
|
@let id_content = util::join!(id, "-content");
|
||||||
|
|
||||||
(brand.render(cx))
|
(brand.render(cx).await)
|
||||||
(button(cx, TOGGLE_COLLAPSE, &id_content))
|
(button(cx, TOGGLE_COLLAPSE, &id_content))
|
||||||
div id=(&id_content) class="collapse navbar-collapse" {
|
div id=(&id_content) class="collapse navbar-collapse" {
|
||||||
(items)
|
(items)
|
||||||
|
|
@ -245,7 +246,7 @@ impl Component for Navbar {
|
||||||
@let id_content = util::join!(id, "-content");
|
@let id_content = util::join!(id, "-content");
|
||||||
|
|
||||||
(button(cx, TOGGLE_COLLAPSE, &id_content))
|
(button(cx, TOGGLE_COLLAPSE, &id_content))
|
||||||
(brand.render(cx))
|
(brand.render(cx).await)
|
||||||
div id=(&id_content) class="collapse navbar-collapse" {
|
div id=(&id_content) class="collapse navbar-collapse" {
|
||||||
(items)
|
(items)
|
||||||
}
|
}
|
||||||
|
|
@ -257,7 +258,7 @@ impl Component for Navbar {
|
||||||
|
|
||||||
(button(cx, TOGGLE_OFFCANVAS, &id_content))
|
(button(cx, TOGGLE_OFFCANVAS, &id_content))
|
||||||
@if let Some(oc) = offcanvas.get() {
|
@if let Some(oc) = offcanvas.get() {
|
||||||
(oc.render_offcanvas(cx, Some(self.items())))
|
(oc.render_offcanvas(cx, Some(self.items())).await)
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|
@ -265,10 +266,10 @@ impl Component for Navbar {
|
||||||
bs::navbar::Layout::OffcanvasBrandLeft(brand, offcanvas) => {
|
bs::navbar::Layout::OffcanvasBrandLeft(brand, offcanvas) => {
|
||||||
@let id_content = offcanvas.id().unwrap_or_default();
|
@let id_content = offcanvas.id().unwrap_or_default();
|
||||||
|
|
||||||
(brand.render(cx))
|
(brand.render(cx).await)
|
||||||
(button(cx, TOGGLE_OFFCANVAS, &id_content))
|
(button(cx, TOGGLE_OFFCANVAS, &id_content))
|
||||||
@if let Some(oc) = offcanvas.get() {
|
@if let Some(oc) = offcanvas.get() {
|
||||||
(oc.render_offcanvas(cx, Some(self.items())))
|
(oc.render_offcanvas(cx, Some(self.items())).await)
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|
@ -277,9 +278,9 @@ impl Component for Navbar {
|
||||||
@let id_content = offcanvas.id().unwrap_or_default();
|
@let id_content = offcanvas.id().unwrap_or_default();
|
||||||
|
|
||||||
(button(cx, TOGGLE_OFFCANVAS, &id_content))
|
(button(cx, TOGGLE_OFFCANVAS, &id_content))
|
||||||
(brand.render(cx))
|
(brand.render(cx).await)
|
||||||
@if let Some(oc) = offcanvas.get() {
|
@if let Some(oc) = offcanvas.get() {
|
||||||
(oc.render_offcanvas(cx, Some(self.items())))
|
(oc.render_offcanvas(cx, Some(self.items())).await)
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -26,6 +26,7 @@ pub enum Item {
|
||||||
Text(L10n),
|
Text(L10n),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[async_trait]
|
||||||
impl Component for Item {
|
impl Component for Item {
|
||||||
fn new() -> Self {
|
fn new() -> Self {
|
||||||
Self::default()
|
Self::default()
|
||||||
|
|
@ -42,19 +43,19 @@ impl Component for Item {
|
||||||
|
|
||||||
fn setup(&mut self, _cx: &Context) {
|
fn setup(&mut self, _cx: &Context) {
|
||||||
if let Self::Nav(nav) = self {
|
if let Self::Nav(nav) = self {
|
||||||
if let Some(mut nav) = nav.get() {
|
if let Some(nav) = nav.get_mut() {
|
||||||
nav.alter_prop(PropsOp::prepend_classes("navbar-nav"));
|
nav.alter_prop(PropsOp::prepend_classes("navbar-nav"));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn prepare(&self, cx: &mut Context) -> Result<Markup, ComponentError> {
|
async fn prepare(&self, cx: &mut Context) -> Result<Markup, ComponentError> {
|
||||||
Ok(match self {
|
Ok(match self {
|
||||||
Self::Void => html! {},
|
Self::Void => html! {},
|
||||||
Self::Brand(brand) => html! { (brand.render(cx)) },
|
Self::Brand(brand) => html! { (brand.render(cx).await) },
|
||||||
Self::Nav(nav) => {
|
Self::Nav(nav) => {
|
||||||
if let Some(nav) = nav.get() {
|
if let Some(nav) = nav.get() {
|
||||||
let items = nav.items().render(cx);
|
let items = nav.items().render(cx).await;
|
||||||
if items.is_empty() {
|
if items.is_empty() {
|
||||||
return Ok(html! {});
|
return Ok(html! {});
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -61,6 +61,7 @@ pub struct Offcanvas {
|
||||||
children: Children,
|
children: Children,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[async_trait]
|
||||||
impl Component for Offcanvas {
|
impl Component for Offcanvas {
|
||||||
fn new() -> Self {
|
fn new() -> Self {
|
||||||
Self::default()
|
Self::default()
|
||||||
|
|
@ -84,8 +85,8 @@ impl Component for Offcanvas {
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
|
|
||||||
fn prepare(&self, cx: &mut Context) -> Result<Markup, ComponentError> {
|
async fn prepare(&self, cx: &mut Context) -> Result<Markup, ComponentError> {
|
||||||
Ok(self.render_offcanvas(cx, None))
|
Ok(self.render_offcanvas(cx, None).await)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -167,9 +168,17 @@ impl Offcanvas {
|
||||||
|
|
||||||
// **< Offcanvas HELPERS >**********************************************************************
|
// **< Offcanvas HELPERS >**********************************************************************
|
||||||
|
|
||||||
pub(crate) fn render_offcanvas(&self, cx: &mut Context, extra: Option<&Children>) -> Markup {
|
pub(crate) async fn render_offcanvas(
|
||||||
let body = self.children().render(cx);
|
&self,
|
||||||
let body_extra = extra.map(|c| c.render(cx)).unwrap_or_else(|| html! {});
|
cx: &mut Context,
|
||||||
|
extra: Option<&Children>,
|
||||||
|
) -> Markup {
|
||||||
|
let body = self.children().render(cx).await;
|
||||||
|
let body_extra = if let Some(c) = extra {
|
||||||
|
c.render(cx).await
|
||||||
|
} else {
|
||||||
|
html! {}
|
||||||
|
};
|
||||||
if body.is_empty() && body_extra.is_empty() {
|
if body.is_empty() && body_extra.is_empty() {
|
||||||
return html! {};
|
return html! {};
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -34,6 +34,7 @@ use pagetop::prelude::*;
|
||||||
|
|
||||||
struct MyApp;
|
struct MyApp;
|
||||||
|
|
||||||
|
#[async_trait]
|
||||||
impl Extension for MyApp {
|
impl Extension for MyApp {
|
||||||
fn dependencies(&self) -> Vec<ExtensionRef> {
|
fn dependencies(&self) -> Vec<ExtensionRef> {
|
||||||
vec![
|
vec![
|
||||||
|
|
@ -59,7 +60,7 @@ async fn homepage(request: HttpRequest) -> Result<Markup, ErrorPage> {
|
||||||
}
|
}
|
||||||
div #result {}
|
div #result {}
|
||||||
}))
|
}))
|
||||||
.render()
|
.render().await
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -332,7 +332,7 @@ pub const DISABLE: &str = "hx-disable";
|
||||||
|
|
||||||
/// Genera `hx-on:{event}` para escuchar eventos nativos del DOM en línea.
|
/// Genera `hx-on:{event}` para escuchar eventos nativos del DOM en línea.
|
||||||
///
|
///
|
||||||
/// Es la alternativa de HTMX a los manejadores `on*` de HTML (`onclick`, `onmouseenter`, ...). La
|
/// Es la alternativa de HTMX a los *handlers* `on*` de HTML (`onclick`, `onmouseenter`, ...). La
|
||||||
/// diferencia clave está en cómo los trata el navegador bajo una política CSP (*Content Security
|
/// diferencia clave está en cómo los trata el navegador bajo una política CSP (*Content Security
|
||||||
/// Policy*): los atributos `on*` son JavaScript en línea y quedan bloqueados si la CSP no incluye
|
/// Policy*): los atributos `on*` son JavaScript en línea y quedan bloqueados si la CSP no incluye
|
||||||
/// `'unsafe-inline'`; en cambio, `hx-on:*` es un atributo de datos que HTMX lee e interpreta desde
|
/// `'unsafe-inline'`; en cambio, `hx-on:*` es un atributo de datos que HTMX lee e interpreta desde
|
||||||
|
|
|
||||||
|
|
@ -35,6 +35,7 @@ use pagetop::prelude::*;
|
||||||
|
|
||||||
struct MyApp;
|
struct MyApp;
|
||||||
|
|
||||||
|
#[async_trait]
|
||||||
impl Extension for MyApp {
|
impl Extension for MyApp {
|
||||||
fn dependencies(&self) -> Vec<ExtensionRef> {
|
fn dependencies(&self) -> Vec<ExtensionRef> {
|
||||||
vec![
|
vec![
|
||||||
|
|
@ -60,7 +61,7 @@ async fn homepage(request: HttpRequest) -> Result<Markup, ErrorPage> {
|
||||||
}
|
}
|
||||||
div #result {}
|
div #result {}
|
||||||
}))
|
}))
|
||||||
.render()
|
.render().await
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
*/
|
*/
|
||||||
|
|
@ -91,6 +92,7 @@ include_locales!(LOCALES_HTMX);
|
||||||
///
|
///
|
||||||
/// struct MyApp;
|
/// struct MyApp;
|
||||||
///
|
///
|
||||||
|
/// #[async_trait]
|
||||||
/// impl Extension for MyApp {
|
/// impl Extension for MyApp {
|
||||||
/// fn dependencies(&self) -> Vec<ExtensionRef> {
|
/// fn dependencies(&self) -> Vec<ExtensionRef> {
|
||||||
/// vec![
|
/// vec![
|
||||||
|
|
@ -103,6 +105,7 @@ include_locales!(LOCALES_HTMX);
|
||||||
/// ```
|
/// ```
|
||||||
pub struct Htmx;
|
pub struct Htmx;
|
||||||
|
|
||||||
|
#[async_trait]
|
||||||
impl Extension for Htmx {
|
impl Extension for Htmx {
|
||||||
fn name(&self) -> L10n {
|
fn name(&self) -> L10n {
|
||||||
L10n::t("extension_name", &LOCALES_HTMX)
|
L10n::t("extension_name", &LOCALES_HTMX)
|
||||||
|
|
|
||||||
|
|
@ -29,7 +29,7 @@ use pagetop::prelude::*;
|
||||||
/// .with_child(Html::with(|_| html! {
|
/// .with_child(Html::with(|_| html! {
|
||||||
/// ul { li { "Item 1" } li { "Item 2" } }
|
/// ul { li { "Item 1" } li { "Item 2" } }
|
||||||
/// }))
|
/// }))
|
||||||
/// .render()
|
/// .render().await
|
||||||
/// .into_response()
|
/// .into_response()
|
||||||
/// }
|
/// }
|
||||||
/// }
|
/// }
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue