You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
A {% filter %} block, or a block {% set %} passed through a filter, applies the filter to text that is already HTML-escaped. So a JinjaString.user value in the body reaches the filter as <b>, not <b>. {{ x | upper }} filters first and escapes after. This has been the case since before #26: base 74d487e and head b3eaffc give the same output.
Repro, x = JinjaString.user('<b>') in dinja, x = '<b>' elsewhere:
{% filter replace("b", "i") %}{{ x }}{% endfilter %}
<i>
<i>
<i>
<i>
<i>
{% filter length %}{{ x }}{% endfilter %}
9
9
3
raises TypeError
raises TypeError
Jinja2 runs as SandboxedEnvironment(trim_blocks=True, lstrip_blocks=True). llama.cpp marks input but never HTML-escapes it, so it has no escaped column; it filters the raw text.
Notes
dinja's output equals Jinja2's with autoescape=True for upper, set and replace: there a filter block's body is Markup, and filters run on the escaped text. So "filter the raw input, then escape" is a choice to make, not the only reading.
The clearest mismatch is that a filter sees the escaped text. length counts <b> (9) where llama.cpp counts <b> (3). The same goes for any filter that inspects content, such as replace on <, truncate or wordcount.
A
{% filter %}block, or a block{% set %}passed through a filter, applies the filter to text that is already HTML-escaped. So aJinjaString.uservalue in the body reaches the filter as<b>, not<b>.{{ x | upper }}filters first and escapes after. This has been the case since before #26: base 74d487e and head b3eaffc give the same output.Repro,
x = JinjaString.user('<b>')in dinja,x = '<b>'elsewhere:autoescape=Falseautoescape=True{% filter upper %}{{ x }}{% endfilter %}<B><B><B><B><B>{{ x | upper }}<B><B><B><B><B>{% set s %}{{ x }}{% endset %}{{ s | upper }}<B><B><B><B><B>{% filter replace("b", "i") %}{{ x }}{% endfilter %}<i><i><i><i><i>{% filter length %}{{ x }}{% endfilter %}993TypeErrorTypeErrorJinja2 runs as
SandboxedEnvironment(trim_blocks=True, lstrip_blocks=True). llama.cpp marks input but never HTML-escapes it, so it has no escaped column; it filters the raw text.Notes
autoescape=Trueforupper,setandreplace: there a filter block's body isMarkup, and filters run on the escaped text. So "filter the raw input, then escape" is a choice to make, not the only reading.lengthcounts<b>(9) where llama.cpp counts<b>(3). The same goes for any filter that inspects content, such asreplaceon<,truncateorwordcount.JinjaString.uservalues are affected; plain strings are never escaped. Among the 86 real templates checked for fix: lstrip_blocks, strftime_now, loop controls, caller() and filters on none #26, the only filter block is firefunction-v2's{%- filter trim -%}, and it wraps static text with no expressions.