mirror of
https://github.com/askama-rs/askama.git
synced 2025-10-02 15:25:19 +00:00
Pass variables to sub-templates more reliably even if indirectly
This commit is contained in:
parent
4a17df55b5
commit
d6bf966048
@ -6,7 +6,7 @@ use core::pin::Pin;
|
||||
|
||||
use super::MAX_LEN;
|
||||
use super::escape::FastWritable;
|
||||
use crate::{Error, Result};
|
||||
use crate::{Error, Result, Values};
|
||||
|
||||
/// Limit string length, appends '...' if truncated
|
||||
///
|
||||
@ -50,9 +50,13 @@ impl<S: fmt::Display> fmt::Display for TruncateFilter<S> {
|
||||
|
||||
impl<S: FastWritable> FastWritable for TruncateFilter<S> {
|
||||
#[inline]
|
||||
fn write_into<W: fmt::Write + ?Sized>(&self, dest: &mut W) -> crate::Result<()> {
|
||||
fn write_into<W: fmt::Write + ?Sized>(
|
||||
&self,
|
||||
dest: &mut W,
|
||||
values: &dyn Values,
|
||||
) -> crate::Result<()> {
|
||||
self.source
|
||||
.write_into(&mut TruncateWriter::new(dest, self.remaining))
|
||||
.write_into(&mut TruncateWriter::new(dest, self.remaining), values)
|
||||
}
|
||||
}
|
||||
|
||||
@ -440,10 +444,14 @@ impl<S: fmt::Display, P: fmt::Display> fmt::Display for Pluralize<S, P> {
|
||||
|
||||
impl<S: FastWritable, P: FastWritable> FastWritable for Pluralize<S, P> {
|
||||
#[inline]
|
||||
fn write_into<W: fmt::Write + ?Sized>(&self, dest: &mut W) -> crate::Result<()> {
|
||||
fn write_into<W: fmt::Write + ?Sized>(
|
||||
&self,
|
||||
dest: &mut W,
|
||||
values: &dyn Values,
|
||||
) -> crate::Result<()> {
|
||||
match self {
|
||||
Pluralize::Singular(value) => value.write_into(dest),
|
||||
Pluralize::Plural(value) => value.write_into(dest),
|
||||
Pluralize::Singular(value) => value.write_into(dest, values),
|
||||
Pluralize::Plural(value) => value.write_into(dest, values),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -82,8 +82,12 @@ impl<T: fmt::Display, E: Escaper> fmt::Display for EscapeDisplay<T, E> {
|
||||
|
||||
impl<T: FastWritable, E: Escaper> FastWritable for EscapeDisplay<T, E> {
|
||||
#[inline]
|
||||
fn write_into<W: fmt::Write + ?Sized>(&self, dest: &mut W) -> crate::Result<()> {
|
||||
self.0.write_into(&mut EscapeWriter(dest, self.1))
|
||||
fn write_into<W: fmt::Write + ?Sized>(
|
||||
&self,
|
||||
dest: &mut W,
|
||||
values: &dyn Values,
|
||||
) -> crate::Result<()> {
|
||||
self.0.write_into(&mut EscapeWriter(dest, self.1), values)
|
||||
}
|
||||
}
|
||||
|
||||
@ -303,12 +307,16 @@ const _: () = {
|
||||
// This is the fallback. The filter is not the last element of the filter chain.
|
||||
impl<T: FastWritable> FastWritable for MaybeSafe<T> {
|
||||
#[inline]
|
||||
fn write_into<W: fmt::Write + ?Sized>(&self, dest: &mut W) -> crate::Result<()> {
|
||||
fn write_into<W: fmt::Write + ?Sized>(
|
||||
&self,
|
||||
dest: &mut W,
|
||||
values: &dyn Values,
|
||||
) -> crate::Result<()> {
|
||||
let inner = match self {
|
||||
MaybeSafe::Safe(inner) => inner,
|
||||
MaybeSafe::NeedsEscaping(inner) => inner,
|
||||
};
|
||||
inner.write_into(dest)
|
||||
inner.write_into(dest, values)
|
||||
}
|
||||
}
|
||||
|
||||
@ -338,10 +346,14 @@ const _: () = {
|
||||
}
|
||||
|
||||
impl<T: FastWritable + ?Sized, E: Escaper> FastWritable for Wrapped<'_, T, E> {
|
||||
fn write_into<W: fmt::Write + ?Sized>(&self, dest: &mut W) -> crate::Result<()> {
|
||||
fn write_into<W: fmt::Write + ?Sized>(
|
||||
&self,
|
||||
dest: &mut W,
|
||||
values: &dyn Values,
|
||||
) -> crate::Result<()> {
|
||||
match *self {
|
||||
Wrapped::Safe(t) => t.write_into(dest),
|
||||
Wrapped::NeedsEscaping(t, e) => EscapeDisplay(t, e).write_into(dest),
|
||||
Wrapped::Safe(t) => t.write_into(dest, values),
|
||||
Wrapped::NeedsEscaping(t, e) => EscapeDisplay(t, e).write_into(dest, values),
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -409,8 +421,12 @@ const _: () = {
|
||||
// This is the fallback. The filter is not the last element of the filter chain.
|
||||
impl<T: FastWritable> FastWritable for Safe<T> {
|
||||
#[inline]
|
||||
fn write_into<W: fmt::Write + ?Sized>(&self, dest: &mut W) -> crate::Result<()> {
|
||||
self.0.write_into(dest)
|
||||
fn write_into<W: fmt::Write + ?Sized>(
|
||||
&self,
|
||||
dest: &mut W,
|
||||
values: &dyn Values,
|
||||
) -> crate::Result<()> {
|
||||
self.0.write_into(dest, values)
|
||||
}
|
||||
}
|
||||
|
||||
@ -503,15 +519,23 @@ pub trait WriteWritable {
|
||||
/// Types implementing this trait can be written without needing to employ an [`fmt::Formatter`].
|
||||
pub trait FastWritable {
|
||||
/// Used internally by askama to speed up writing some types.
|
||||
fn write_into<W: fmt::Write + ?Sized>(&self, dest: &mut W) -> crate::Result<()>;
|
||||
fn write_into<W: fmt::Write + ?Sized>(
|
||||
&self,
|
||||
dest: &mut W,
|
||||
values: &dyn Values,
|
||||
) -> crate::Result<()>;
|
||||
}
|
||||
|
||||
const _: () = {
|
||||
crate::impl_for_ref! {
|
||||
impl FastWritable for T {
|
||||
#[inline]
|
||||
fn write_into<W: fmt::Write + ?Sized>(&self, dest: &mut W) -> crate::Result<()> {
|
||||
<T>::write_into(self, dest)
|
||||
fn write_into<W: fmt::Write + ?Sized>(
|
||||
&self,
|
||||
dest: &mut W,
|
||||
values: &dyn Values,
|
||||
) -> crate::Result<()> {
|
||||
<T>::write_into(self, dest, values)
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -522,16 +546,24 @@ const _: () = {
|
||||
<T as Deref>::Target: FastWritable,
|
||||
{
|
||||
#[inline]
|
||||
fn write_into<W: fmt::Write + ?Sized>(&self, dest: &mut W) -> crate::Result<()> {
|
||||
self.as_ref().get_ref().write_into(dest)
|
||||
fn write_into<W: fmt::Write + ?Sized>(
|
||||
&self,
|
||||
dest: &mut W,
|
||||
values: &dyn Values,
|
||||
) -> crate::Result<()> {
|
||||
self.as_ref().get_ref().write_into(dest, values)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "alloc")]
|
||||
impl<T: FastWritable + alloc::borrow::ToOwned> FastWritable for alloc::borrow::Cow<'_, T> {
|
||||
#[inline]
|
||||
fn write_into<W: fmt::Write + ?Sized>(&self, dest: &mut W) -> crate::Result<()> {
|
||||
T::write_into(self.as_ref(), dest)
|
||||
fn write_into<W: fmt::Write + ?Sized>(
|
||||
&self,
|
||||
dest: &mut W,
|
||||
values: &dyn Values,
|
||||
) -> crate::Result<()> {
|
||||
T::write_into(self.as_ref(), dest, values)
|
||||
}
|
||||
}
|
||||
|
||||
@ -540,8 +572,12 @@ const _: () = {
|
||||
($($ty:ty)*) => { $(
|
||||
impl FastWritable for $ty {
|
||||
#[inline]
|
||||
fn write_into<W: fmt::Write + ?Sized>(&self, dest: &mut W) -> crate::Result<()> {
|
||||
itoa::Buffer::new().format(*self).write_into(dest)
|
||||
fn write_into<W: fmt::Write + ?Sized>(
|
||||
&self,
|
||||
dest: &mut W,
|
||||
values: &dyn Values,
|
||||
) -> crate::Result<()> {
|
||||
itoa::Buffer::new().format(*self).write_into(dest, values)
|
||||
}
|
||||
}
|
||||
)* };
|
||||
@ -557,8 +593,12 @@ const _: () = {
|
||||
($($id:ident)*) => { $(
|
||||
impl FastWritable for core::num::$id {
|
||||
#[inline]
|
||||
fn write_into<W: fmt::Write + ?Sized>(&self, dest: &mut W) -> crate::Result<()> {
|
||||
self.get().write_into(dest)
|
||||
fn write_into<W: fmt::Write + ?Sized>(
|
||||
&self,
|
||||
dest: &mut W,
|
||||
values: &dyn Values,
|
||||
) -> crate::Result<()> {
|
||||
self.get().write_into(dest, values)
|
||||
}
|
||||
}
|
||||
)* };
|
||||
@ -571,7 +611,11 @@ const _: () = {
|
||||
|
||||
impl FastWritable for str {
|
||||
#[inline]
|
||||
fn write_into<W: fmt::Write + ?Sized>(&self, dest: &mut W) -> crate::Result<()> {
|
||||
fn write_into<W: fmt::Write + ?Sized>(
|
||||
&self,
|
||||
dest: &mut W,
|
||||
_: &dyn Values,
|
||||
) -> crate::Result<()> {
|
||||
Ok(dest.write_str(self)?)
|
||||
}
|
||||
}
|
||||
@ -579,14 +623,22 @@ const _: () = {
|
||||
#[cfg(feature = "alloc")]
|
||||
impl FastWritable for alloc::string::String {
|
||||
#[inline]
|
||||
fn write_into<W: fmt::Write + ?Sized>(&self, dest: &mut W) -> crate::Result<()> {
|
||||
self.as_str().write_into(dest)
|
||||
fn write_into<W: fmt::Write + ?Sized>(
|
||||
&self,
|
||||
dest: &mut W,
|
||||
values: &dyn Values,
|
||||
) -> crate::Result<()> {
|
||||
self.as_str().write_into(dest, values)
|
||||
}
|
||||
}
|
||||
|
||||
impl FastWritable for bool {
|
||||
#[inline]
|
||||
fn write_into<W: fmt::Write + ?Sized>(&self, dest: &mut W) -> crate::Result<()> {
|
||||
fn write_into<W: fmt::Write + ?Sized>(
|
||||
&self,
|
||||
dest: &mut W,
|
||||
_: &dyn Values,
|
||||
) -> crate::Result<()> {
|
||||
Ok(dest.write_str(match self {
|
||||
true => "true",
|
||||
false => "false",
|
||||
@ -596,13 +648,21 @@ const _: () = {
|
||||
|
||||
impl FastWritable for char {
|
||||
#[inline]
|
||||
fn write_into<W: fmt::Write + ?Sized>(&self, dest: &mut W) -> crate::Result<()> {
|
||||
fn write_into<W: fmt::Write + ?Sized>(
|
||||
&self,
|
||||
dest: &mut W,
|
||||
_: &dyn Values,
|
||||
) -> crate::Result<()> {
|
||||
Ok(dest.write_char(*self)?)
|
||||
}
|
||||
}
|
||||
|
||||
impl FastWritable for fmt::Arguments<'_> {
|
||||
fn write_into<W: fmt::Write + ?Sized>(&self, dest: &mut W) -> crate::Result<()> {
|
||||
fn write_into<W: fmt::Write + ?Sized>(
|
||||
&self,
|
||||
dest: &mut W,
|
||||
_: &dyn Values,
|
||||
) -> crate::Result<()> {
|
||||
Ok(match self.as_str() {
|
||||
Some(s) => dest.write_str(s),
|
||||
None => dest.write_fmt(*self),
|
||||
@ -626,9 +686,9 @@ const _: () = {
|
||||
fn askama_write<W: fmt::Write + ?Sized>(
|
||||
&self,
|
||||
dest: &mut W,
|
||||
_: &dyn Values,
|
||||
values: &dyn Values,
|
||||
) -> crate::Result<()> {
|
||||
self.0.write_into(dest)
|
||||
self.0.write_into(dest, values)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -4,6 +4,7 @@ use core::mem::MaybeUninit;
|
||||
|
||||
use super::FastWritable;
|
||||
use crate::ascii_str::{AsciiChar, AsciiStr};
|
||||
use crate::{NO_VALUES, Values};
|
||||
|
||||
/// Returns adequate string representation (in KB, ..) of number of bytes
|
||||
///
|
||||
@ -33,14 +34,18 @@ pub struct FilesizeFormatFilter(f32);
|
||||
impl fmt::Display for FilesizeFormatFilter {
|
||||
#[inline]
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
Ok(self.write_into(f)?)
|
||||
Ok(self.write_into(f, NO_VALUES)?)
|
||||
}
|
||||
}
|
||||
|
||||
impl FastWritable for FilesizeFormatFilter {
|
||||
fn write_into<W: fmt::Write + ?Sized>(&self, dest: &mut W) -> crate::Result<()> {
|
||||
fn write_into<W: fmt::Write + ?Sized>(
|
||||
&self,
|
||||
dest: &mut W,
|
||||
values: &dyn Values,
|
||||
) -> crate::Result<()> {
|
||||
if self.0 < 1e3 {
|
||||
(self.0 as u32).write_into(dest)?;
|
||||
(self.0 as u32).write_into(dest, values)?;
|
||||
Ok(dest.write_str(" B")?)
|
||||
} else if let Some((prefix, factor)) = SI_PREFIXES
|
||||
.iter()
|
||||
@ -49,8 +54,8 @@ impl FastWritable for FilesizeFormatFilter {
|
||||
{
|
||||
// u32 is big enough to hold the number 999_999
|
||||
let scaled = (self.0 * factor) as u32;
|
||||
(scaled / 100).write_into(dest)?;
|
||||
format_frac(&mut MaybeUninit::uninit(), prefix, scaled).write_into(dest)
|
||||
(scaled / 100).write_into(dest, values)?;
|
||||
format_frac(&mut MaybeUninit::uninit(), prefix, scaled).write_into(dest, values)
|
||||
} else {
|
||||
too_big(self.0, dest)
|
||||
}
|
||||
|
@ -8,6 +8,7 @@ use serde_json::ser::{CompactFormatter, PrettyFormatter, Serializer};
|
||||
|
||||
use super::FastWritable;
|
||||
use crate::ascii_str::{AsciiChar, AsciiStr};
|
||||
use crate::{NO_VALUES, Values};
|
||||
|
||||
/// Serialize to JSON (requires `json` feature)
|
||||
///
|
||||
@ -188,7 +189,8 @@ where
|
||||
}
|
||||
|
||||
impl<S: Serialize> FastWritable for ToJson<S> {
|
||||
fn write_into<W: fmt::Write + ?Sized>(&self, f: &mut W) -> crate::Result<()> {
|
||||
#[inline]
|
||||
fn write_into<W: fmt::Write + ?Sized>(&self, f: &mut W, _: &dyn Values) -> crate::Result<()> {
|
||||
serialize(f, &self.value, CompactFormatter)
|
||||
}
|
||||
}
|
||||
@ -196,12 +198,13 @@ impl<S: Serialize> FastWritable for ToJson<S> {
|
||||
impl<S: Serialize> fmt::Display for ToJson<S> {
|
||||
#[inline]
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
Ok(self.write_into(f)?)
|
||||
Ok(self.write_into(f, NO_VALUES)?)
|
||||
}
|
||||
}
|
||||
|
||||
impl<S: Serialize, I: AsIndent> FastWritable for ToJsonPretty<S, I> {
|
||||
fn write_into<W: fmt::Write + ?Sized>(&self, f: &mut W) -> crate::Result<()> {
|
||||
#[inline]
|
||||
fn write_into<W: fmt::Write + ?Sized>(&self, f: &mut W, _: &dyn Values) -> crate::Result<()> {
|
||||
serialize(
|
||||
f,
|
||||
&self.value,
|
||||
@ -213,11 +216,10 @@ impl<S: Serialize, I: AsIndent> FastWritable for ToJsonPretty<S, I> {
|
||||
impl<S: Serialize, I: AsIndent> fmt::Display for ToJsonPretty<S, I> {
|
||||
#[inline]
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
Ok(self.write_into(f)?)
|
||||
Ok(self.write_into(f, NO_VALUES)?)
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn serialize<S, W, F>(dest: &mut W, value: &S, formatter: F) -> Result<(), crate::Error>
|
||||
where
|
||||
S: Serialize + ?Sized,
|
||||
|
@ -4,6 +4,7 @@ use std::fmt::Write;
|
||||
|
||||
use percent_encoding::{AsciiSet, NON_ALPHANUMERIC, utf8_percent_encode};
|
||||
|
||||
use crate::Values;
|
||||
use crate::filters::{FastWritable, HtmlSafeOutput};
|
||||
|
||||
// Urlencode char encoding set. Only the characters in the unreserved set don't
|
||||
@ -110,8 +111,12 @@ impl<T: fmt::Display> fmt::Display for UrlencodeFilter<T> {
|
||||
|
||||
impl<T: FastWritable> FastWritable for UrlencodeFilter<T> {
|
||||
#[inline]
|
||||
fn write_into<W: fmt::Write + ?Sized>(&self, f: &mut W) -> crate::Result<()> {
|
||||
self.0.write_into(&mut UrlencodeWriter(f, self.1))
|
||||
fn write_into<W: fmt::Write + ?Sized>(
|
||||
&self,
|
||||
f: &mut W,
|
||||
values: &dyn Values,
|
||||
) -> crate::Result<()> {
|
||||
self.0.write_into(&mut UrlencodeWriter(f, self.1), values)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -12,6 +12,7 @@ use core::iter::{Enumerate, Peekable};
|
||||
use core::ops::Deref;
|
||||
use core::pin::Pin;
|
||||
|
||||
use crate::Values;
|
||||
pub use crate::error::{ErrorMarker, ResultConverter};
|
||||
use crate::filters::FastWritable;
|
||||
pub use crate::values::get_value;
|
||||
@ -245,7 +246,7 @@ impl fmt::Display for Empty {
|
||||
|
||||
impl FastWritable for Empty {
|
||||
#[inline]
|
||||
fn write_into<W: fmt::Write + ?Sized>(&self, _: &mut W) -> crate::Result<()> {
|
||||
fn write_into<W: fmt::Write + ?Sized>(&self, _: &mut W, _: &dyn Values) -> crate::Result<()> {
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
@ -267,9 +268,13 @@ impl<L: fmt::Display, R: fmt::Display> fmt::Display for Concat<L, R> {
|
||||
|
||||
impl<L: FastWritable, R: FastWritable> FastWritable for Concat<L, R> {
|
||||
#[inline]
|
||||
fn write_into<W: fmt::Write + ?Sized>(&self, dest: &mut W) -> crate::Result<()> {
|
||||
self.0.write_into(dest)?;
|
||||
self.1.write_into(dest)
|
||||
fn write_into<W: fmt::Write + ?Sized>(
|
||||
&self,
|
||||
dest: &mut W,
|
||||
values: &dyn Values,
|
||||
) -> crate::Result<()> {
|
||||
self.0.write_into(dest, values)?;
|
||||
self.1.write_into(dest, values)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -406,8 +406,12 @@ mod tests {
|
||||
|
||||
impl filters::FastWritable for Test {
|
||||
#[inline]
|
||||
fn write_into<W: fmt::Write + ?Sized>(&self, f: &mut W) -> crate::Result<()> {
|
||||
self.render_into(f)
|
||||
fn write_into<W: fmt::Write + ?Sized>(
|
||||
&self,
|
||||
f: &mut W,
|
||||
values: &dyn Values,
|
||||
) -> crate::Result<()> {
|
||||
self.render_into_with_values(f, values)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -310,11 +310,15 @@ impl<'a, 'h> Generator<'a, 'h> {
|
||||
impl #wrapper_impl_generics askama::filters::FastWritable
|
||||
for #wrapper_id #wrapper_ty_generics #wrapper_where_clause {
|
||||
#[inline]
|
||||
fn write_into<AskamaW>(&self, dest: &mut AskamaW) -> askama::Result<()>
|
||||
fn write_into<AskamaW>(
|
||||
&self,
|
||||
dest: &mut AskamaW,
|
||||
values: &dyn askama::Values,
|
||||
) -> askama::Result<()>
|
||||
where
|
||||
AskamaW: askama::helpers::core::fmt::Write + ?askama::helpers::core::marker::Sized
|
||||
{
|
||||
<_ as askama::Template>::render_into(self, dest)
|
||||
<_ as askama::Template>::render_into_with_values(self, dest, values)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -64,11 +64,15 @@ fn impl_fast_writable(ast: &DeriveInput, buf: &mut Buffer) {
|
||||
buf.write(
|
||||
"\
|
||||
#[inline]\
|
||||
fn write_into<AskamaW>(&self, dest: &mut AskamaW) -> askama::Result<()> \
|
||||
fn write_into<AskamaW>(\
|
||||
&self,\
|
||||
dest: &mut AskamaW,\
|
||||
values: &dyn askama::Values\
|
||||
) -> askama::Result<()> \
|
||||
where \
|
||||
AskamaW: askama::helpers::core::fmt::Write + ?askama::helpers::core::marker::Sized,\
|
||||
{\
|
||||
askama::Template::render_into(self, dest)\
|
||||
askama::Template::render_into_with_values(self, dest, values)\
|
||||
}\
|
||||
}",
|
||||
);
|
||||
|
@ -69,11 +69,15 @@ fn compare_ex(
|
||||
|
||||
impl askama::filters::FastWritable for Foo {
|
||||
#[inline]
|
||||
fn write_into<AskamaW>(&self, dest: &mut AskamaW) -> askama::Result<()>
|
||||
fn write_into<AskamaW>(
|
||||
&self,
|
||||
dest: &mut AskamaW,
|
||||
values: &dyn askama::Values,
|
||||
) -> askama::Result<()>
|
||||
where
|
||||
AskamaW: askama::helpers::core::fmt::Write + ?askama::helpers::core::marker::Sized,
|
||||
{
|
||||
askama::Template::render_into(self, dest)
|
||||
askama::Template::render_into_with_values(self, dest, values)
|
||||
}
|
||||
}
|
||||
};
|
||||
|
@ -88,3 +88,26 @@ fn test_value_function_getter() {
|
||||
values.insert("a".to_string(), Box::new(false));
|
||||
assert_eq!(V.render_with_values(&values).unwrap(), "");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_value_in_subtemplates() {
|
||||
// In this test we make sure that values are passed down to transcluded sub-templates,
|
||||
// even if there is a filter in the mix, e.g. the implicit `|escape` filter.
|
||||
|
||||
#[derive(Template)]
|
||||
#[template(source = r#"{{ Child }}"#, ext = "html")]
|
||||
struct Parent;
|
||||
|
||||
#[derive(Template)]
|
||||
#[template(
|
||||
source = r#"Hello, {{ askama::get_value::<String>("who")? }}!"#,
|
||||
ext = "html"
|
||||
)]
|
||||
struct Child;
|
||||
|
||||
let values: (&str, &dyn Any) = ("who", &"<world>".to_owned());
|
||||
assert_eq!(
|
||||
Parent.render_with_values(&values).unwrap(),
|
||||
"Hello, &#60;world&#62;!", // sic: escaped twice
|
||||
);
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user