为什么这个Jinja nl2br过滤器逃避了,而不是< p>的? [英] Why is this Jinja nl2br filter escaping <br>'s but not <p>'s?
问题描述
我试图实现这个 Jinja nl2br
< br>
被转义以外,它正常工作。这对我来说很奇怪,因为< p>
没有被转义,而且它们都在同一个字符串中。 我正在使用烧瓶,所以启用了Jinja autoescape
。当我找到这家伙时,我真的很有希望说 autoescape
和 escape(value)
可能会导致双重转义,但删除转义)
没有帮助。
这是我修改过的代码,它的输出:
@ app.template_filter()
@evalcontextfilter
def nl2br(eval_ctx,value):
_paragraph_re = re.compile(r'(?:\\ \\ r \ n | \r(?!\\\
)| \\\
){2,}')
result = u'\\\
\\\
'.join(u'< p> (value))$ b $;%s(< / p> b如果eval_ctx.autoescape:
result =标记(结果)
返回结果
input:
u'1 \r\\\
2\r\\\
\r\\\
3\ r\\\
4\r\\\
\ r\\\
5\r\\\
6\r\\\
7'
输出: p>
< p> 1& lt; br& gt;
2< / p>
< p> 3& lt; br& gt;
4< / p>
< p> 5& lt;& gt;
6& lt; br& gt;
7< / p>
所需输出:
< p为H. 1·峰; br> 2'; / p为H.
< p> 3< br> 4< / p>
< p> 5< br> 6< br> 7< / p>
什么可能导致< br>
要被转义,但是允许< p>
的?
nl2br
过滤器不能正确处理标记对象。如果 value
是标记,则插入的< br>
标签将被转义。要解决这个问题,< br>
标记也必须是标记:
@ app.template_filter()
@evalcontextfilter
def nl2br(eval_ctx,value):
_paragraph_re = re.compile(r'(?:\r\\\
| \ r(?!\ n)| \\\
){2,}')
result = u'\\\
\\\
'.join(u'< p>%s< / p> (p'replace(''''n',Markup('< br> \\\
'))
for _paragraph_re.split(value))
if eval_ctx.autoescape:
结果=标记(结果)
返回结果
注意: \\\
。
以下是对发生的更详细的解释:
拆分标记
对象,产生许多标记
对象:
>>> Markup(hello there)。split()
[Markup(u'hello'),Markup(u'there')]
根据 Jinja的Markup文档 $ b
对标记字符串的操作是标记意识,意味着所有参数都通过escape()函数传递。
回顾 nl2br
的主要转换,我们可以看到发生了什么, 't work:
result = u'\\\
\\\
'.join(u'%s
',u'br> \\\
')
for _paragraph_re.split(value))
$ b $ p $ c $ u code code code $> u'< br> \ n'是unicode字符串,但p
是标记
已从值
中拆分,whi ch是一个标记对象。p.replace
尝试向标记对象p
添加一个unicode字符串,但标记对象正确地截取并转义字符串首先。
$ b
< p> 标签不会因为Python组装最终字符串而被转义,在unicode字符串上调用 %
格式化方法,它使用传递给它的元素的Unicode代表。标记元素已经被宣布为安全的,所以他们不会再逃脱。result
以unicode字符串结尾。I am attempting to implement this Jinja
nl2br
filter. It is working correctly except that the<br>
's it adds are being escaped. This is weird to me because the<p>
's are not being escaped and they are all in the same string.I am using flask so the Jinja
autoescape
is enabled. I was really hopeful when I found this guy saying theautoescape
and theescape(value)
may have been causing double escaping, but removing theescape()
did not help.Here is my modified code and it's output:
@app.template_filter() @evalcontextfilter def nl2br(eval_ctx, value): _paragraph_re = re.compile(r'(?:\r\n|\r(?!\n)|\n){2,}') result = u'\n\n'.join(u'<p>%s</p>' % escape(p.replace(u'\r\n', u'<br>\n')) for p in _paragraph_re.split(value)) if eval_ctx.autoescape: result = Markup(result) return result
input:
u'1\r\n2\r\n\r\n3\r\n4\r\n\r\n5\r\n6\r\n7'
output:
<p>1<br> 2</p> <p>3<br> 4</p> <p>5<br> 6<br> 7</p>
desired output:
<p>1<br>2</p> <p>3<br>4</p> <p>5<br>6<br>7</p>
What could be causing the
<br>
's to be escaped but allowing the<p>
's?解决方案The
nl2br
filter doesn't handle Markup objects correctly. Ifvalue
is Markup, then the inserted<br>
tags will be escaped. To fix it, the<br>
tag must be Markup too:@app.template_filter() @evalcontextfilter def nl2br(eval_ctx, value): _paragraph_re = re.compile(r'(?:\r\n|\r(?!\n)|\n){2,}') result = u'\n\n'.join(u'<p>%s</p>' % p.replace(u'\n', Markup('<br>\n')) for p in _paragraph_re.split(value)) if eval_ctx.autoescape: result = Markup(result) return result
Note: I normalized line endings to
\n
.Here's a longer explanation of what's happening:
Splitting
Markup
objects, produces manyMarkup
objects:>>> Markup("hello there").split() [Markup(u'hello'), Markup(u'there')]
According to Jinja's documentation for Markup:
Operations on a markup string are markup aware which means that all arguments are passed through the escape() function.
Looking back at the main transformation of
nl2br
, we can see what's happening and why it didn't work:result = u'\n\n'.join(u'<p>%s</p>' % p.replace(u'\n', u'<br>\n') for p in _paragraph_re.split(value))
u'\n\n'
andu'<br>\n'
are unicode strings, butp
isMarkup
having been split fromvalue
, which is a Markup object.p.replace
tries to add a unicode string to Markup objectp
, but the Markup object correctly intercepts and escapes the string first.The
<p>
tags aren't escaped because of how Python assembles the final string, since the%
formatting method is called on a unicode string, it uses the unicode representation of the elements passed to it. The Markup elements have already been declared safe, so they aren't escaped any further.result
ends up as a unicode string.这篇关于为什么这个Jinja nl2br过滤器逃避了,而不是< p>的?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!