Skip to main content

askama_web/
lib.rs

1// SPDX-FileCopyrightText: 2025-2026 The Askama Developers
2// SPDX-License-Identifier: Apache-2.0 OR MIT
3
4#![doc = include_str!("../README.md")]
5#![cfg_attr(docsrs, feature(doc_cfg))]
6
7#[doc(hidden)]
8mod implementation;
9
10#[doc(hidden)]
11#[cfg(feature = "derive")]
12pub mod __askama_web_impl {
13    pub use crate::implementation::*;
14}
15
16use std::fmt;
17
18use askama::{FastWritable, Template, Values};
19#[cfg(feature = "derive")]
20/// Implement the needed traits to use your template as a web response.
21///
22/// Instead of this proc-macro, you can also you manually wrap a [`Template`] in
23/// [`WebTemplate`][struct@WebTemplate] or use [`WebTemplateExt::into_web_template()`].
24///
25/// Please see the [crate] root for more information.
26pub use askama_web_derive::WebTemplate;
27
28/// Extension trait to let any [`Template`] be usable as a [`WebTemplate`][derive@WebTemplate].
29pub trait WebTemplateExt: Template {
30    /// Treat a reference to a [`Template`] as [`WebTemplate`][struct@WebTemplate].
31    ///
32    /// In most cases [`.into_web_template()`][WebTemplateExt::into_web_template] will work better.
33    fn as_web_template(&self) -> WebTemplate<&Self>;
34
35    /// Treat a [`Template`] as [`WebTemplate`][struct@WebTemplate].
36    fn into_web_template(self) -> WebTemplate<Self>
37    where
38        Self: Sized;
39}
40
41impl<T: Template> WebTemplateExt for T {
42    #[inline]
43    fn as_web_template(&self) -> WebTemplate<&Self> {
44        WebTemplate(self)
45    }
46
47    #[inline]
48    fn into_web_template(self) -> WebTemplate<Self> {
49        WebTemplate(self)
50    }
51}
52
53/// Wrap a [`Template`] that might not derive [`WebTemplate`][derive@WebTemplate] to be usable as
54/// web response.
55///
56/// A [`Template`] wrapped in this `struct` implements all traits that were enabled through feature
57/// flags. Please see the [crate] documentation for a list of all supported feature flags / web
58/// frameworks.
59///
60/// You might also find [`WebTemplateExt::into_web_template()`] convenient.
61#[derive(Debug, Clone, Copy)]
62pub struct WebTemplate<T: Template>(pub T);
63
64impl<T: Template> Template for WebTemplate<T> {
65    #[inline]
66    fn render(&self) -> askama::Result<String> {
67        <T as Template>::render(&self.0)
68    }
69
70    #[inline]
71    fn render_with_values(&self, values: &dyn Values) -> askama::Result<String> {
72        <T as Template>::render_with_values(&self.0, values)
73    }
74
75    #[inline]
76    fn render_into_with_values(
77        &self,
78        writer: &mut dyn fmt::Write,
79        values: &dyn Values,
80    ) -> askama::Result<()> {
81        <T as Template>::render_into_with_values(&self.0, writer, values)
82    }
83
84    #[inline]
85    fn render_into(&self, writer: &mut dyn fmt::Write) -> askama::Result<()> {
86        <T as Template>::render_into(&self.0, writer)
87    }
88
89    #[inline]
90    fn write_into(&self, writer: &mut dyn std::io::Write) -> std::io::Result<()> {
91        <T as Template>::write_into(&self.0, writer)
92    }
93
94    #[inline]
95    fn write_into_with_values(
96        &self,
97        writer: &mut dyn std::io::Write,
98        values: &dyn Values,
99    ) -> std::io::Result<()> {
100        <T as Template>::write_into_with_values(&self.0, writer, values)
101    }
102
103    const SIZE_HINT: usize = <T as Template>::SIZE_HINT;
104}
105
106impl<T: Template> FastWritable for WebTemplate<T> {
107    #[inline]
108    fn write_into(&self, dest: &mut dyn fmt::Write, values: &dyn Values) -> askama::Result<()> {
109        <T as FastWritable>::write_into(&self.0, dest, values)
110    }
111}
112
113/// Implement the [`format!()`] trait for `WebTemplate<T>`.
114///
115/// Please be aware of the rendering performance notice in the [`Template`] trait.
116impl<T: Template> fmt::Display for WebTemplate<T> {
117    #[inline]
118    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
119        <T as fmt::Display>::fmt(&self.0, f)
120    }
121}
122
123#[inline]
124#[track_caller]
125#[allow(unused)]
126fn render_error(_err: &(impl std::error::Error + ?Sized)) {
127    #[cfg(feature = "eprintln")]
128    eprintln!(
129        "[{}] Failed to render template: {_err}",
130        std::panic::Location::caller(),
131    );
132    #[cfg(feature = "log-0.4")]
133    log_0_4::error!("Failed to render template: {_err}");
134    #[cfg(feature = "tracing-0.1")]
135    tracing_0_1::error!("Failed to render template: {_err}");
136}