They were added in <https://github.com/djc/askama/pull/146>.
The example when they might be useful sounds contrived. You can always
manually add the package `num-traits` to your project and use the
methods directly. `into_isize` and `into_f64` wasn't even documented in
the book.
The filters `|linebreaks`, `|linebreaksbr` and `|paragraphbreaks`
generate HTML code to be embedded in a page. Having to specify that the
output of these filters is `|safe` is cumbersome. Also, these filters
need to operate on already escaped HTML data. This could be done by
writing `{{ s|escape|linebreaks|safe }}`.
This PR does the input and output formatting escaping for the user. The
input gets escaped for HTML (invariant of the selected escaper), and the
output gets marked as HTML safe.
By using codepoint entities like `'&'` → `"&"`, we have a much
smaller lookup table (58 bytes instead of 29× pointer size ~= 232
bytes). This makes the cache happy, and the benchmark run about ~20%
faster.
```text
$ cargo bench --bench escape
Escaping time: [3.4087 µs 3.4126 µs 3.4168 µs]
change: [-19.790% -19.580% -19.354%] (p = 0.00 < 0.05)
Performance has improved.
```
This PR adds an optional argument to the `|tojson` filter, which
controls if the serialized JSON data gets prettified or not. The
arguments works the same as flask's [`|tojson`][flask] filter, which
passes the argument to python's [`json.dumps()`][python]:
* Omitting the argument, providing a negative integer, or `None`, then
compact JSON data is generated.
* Providing a non-negative integer, then this amount of ASCII spaces is
used to indent the data. (Capped to 16 characters.)
* Providing a string, then this string is used as prefix. I attempts are
made to ensure that the prefix actually consists of whitespaces,
because chances are, that if you provide e.g. `&nsbp;`, then you are
doing it intentionally.
This is a breaking change, because it changes the default behavior to
not prettify the data. This is done intentionally, because this is how
it works in flask.
[flask]: https://jinja.palletsprojects.com/en/3.1.x/templates/#jinja-filters.tojson
[python]: https://docs.python.org/3/library/json.html#json.dump
Previously the built-in json filter had an issue that made it unsafe to
use in HTML data. When used in HTML attributes an attacker who is able
to supply an arbitrary string that should be JSON encoded could close
the containing HTML element e.g. with `"</div>"`, and write arbitrary
HTML code afterwards as long as they use apostrophes instead of
quotation marks. The programmer could make this use case safe by
explicitly escaping the JSON result: `{{data|json|escape}}`.
In a `<script>` context the json filter was not usable at all, because
in scripts HTML escaped entities are not parsed outside of XHTML
documents. Without using the safe filter an attacker could close the
current script using `"</script>"`.
This PR fixes the problem by always escaping less-than, greater-than,
ampersand, and apostrophe characters using their JSON unicode escape
sequence `\u00xx`. Unless the programmer explicitly uses the safe
filter, quotation marks are HTML encoded as `"`. In scripts the
programmer should use the safe filter, otherwise not.
This allows a more natural filter usage: `{{ val | fmt("{:?}") }}`
as well as enabling convenient filter composition:
`{{ price | to_f64 | fmt("${:.2}") | center }}`