我有一个Javascript数组中有{% block content %}{% endblock %}
的布局文件,如下所示
<script type="text/javascript">
cols:[
{% block content %}{% endblock %}
];
</script>
然后在许多使用这样的布局文件的模板中进行扩展(真正的模板有更多的代码和变量行):
{% block content %}
{ view:"text", name:"visitDate", value:"{{ date }}", label:"Date/Time:", labelWidth:100, width:285, labelAlign:"right", readonly:true },
{% endblock %}
由于content
块总是需要使用“js”策略进行转义,有没有办法在布局模板中指定这个我累了:
<script type="text/javascript">
cols:[
{% autoescape 'js' %}
{% block content %}{% endblock %}
{% endautoescape %}
];
</script>
但这似乎不起作用,并且在Twig文档中找不到任何示例。如果我在模板中的autoescape
块内添加content
块,我可以使它工作,但这不是正确的方法。
例如,使用上面的代码,应将以下HTML / Javascript发送到浏览器{{ date }}
=“17/12/2017 15:01:53”:
<script type="text/javascript">
cols:[
{ view:"text", name:"visitDate", value:"17\x2F12\x2F2017\x2015\x3A01\x3A53", label:"Date/Time:", labelWidth:100, width:285, labelAlign:"right", readonly:true },
];
</script>
只有子模板content
块中的模板变量才能转义,而不是实际的Javascript代码,如果您使用{{ block('content')|e('js') }}
行的内容,则会获得该代码。
答案 0 :(得分:0)
我能想到的一个解决方案是创建节点访问者类,它将处理每个树枝节点,并根据块名称应用相应的转义策略。
content
块以下是一个示例访问者,它将在js
块内的每个print
节点上content
转义过滤器:
<?php
declare(strict_types=1);
namespace App\Twig;
class AppExtension extends \Twig_Extension
{
/**
* {@inheritdoc}
*/
public function getNodeVisitors()
{
/**
* Node visitor that applies `js` escaping strategy to every output node under `content` block
*
* @var \Twig_NodeVisitorInterface
*/
$visitor = new class() implements \Twig_NodeVisitorInterface {
/**
* @var bool
*/
private $escape = false;
/**
* {@inheritdoc}
*/
public function enterNode(\Twig_Node $node, \Twig_Environment $env)
{
// Start of `content` block found, set `escape` to true to indicate that next nodes should be escaped
if ($this->isContentBlockNode($node)) {
$this->escape = true;
}
return $node;
}
/**
* {@inheritdoc}
*/
public function leaveNode(\Twig_Node $node, \Twig_Environment $env)
{
if ($node instanceof \Twig_Node_Module) {
$this->escape = false;
}
if ($this->escape) {
if ($node instanceof \Twig_Node_Print) {
$expr = $node->getNode('expr');
// Skipping if escape strategy provided in the template for this node
if ($expr instanceof \Twig_Node_Expression_Filter) {
return $node;
}
$line = $expr->getTemplateLine();
$name = new \Twig_Node_Expression_Constant('escape', $line);
$args = new \Twig_Node(array(new \Twig_Node_Expression_Constant('js', $line), new \Twig_Node_Expression_Constant(null, $line), new \Twig_Node_Expression_Constant(true, $line)));
$filter = new \Twig_Node_Expression_Filter($expr, $name, $args, $line);
$class = get_class($node);
return new $class($filter, $node->getTemplateLine());
}
}
// End of `content` block, disable escape policy for further nodes
if ($this->isContentBlockNode($node)) {
$this->escape = false;
}
return $node;
}
/**
* {@inheritdoc}
*/
public function getPriority()
{
return -10;
}
/**
* Checks whether the node is `content` block
*
* @param \Twig_Node $node
*
* @return bool
*/
private function isContentBlockNode(\Twig_Node $node): bool
{
return ($node instanceof \Twig_Node_Block && 'content' === $node->getAttribute('name'));
}
};
return [$visitor];
}
}