【问题标题】:Is it possible in Twig to set autoescape strategy in the layout file是否可以在 Twig 中在布局文件中设置自动转义策略
【发布时间】:2017-12-29 10:30:34
【问题描述】:

我有一个布局文件,在这样的 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 文档中找不到任何示例。如果我在模板中的content 块内添加autoescape 块,我可以让它工作,但这感觉不是正确的方法。

例如,使用上面的代码,应该将以下 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') }} 的东西,你会得到。

【问题讨论】:

    标签: php symfony twig


    【解决方案1】:

    我能想到的一个解决方案是创建节点访问者类,它将处理每个树枝节点,并根据块的名称应用相应的逃生策略。

    1. 首先create custom twig extension
    2. 创建节点访问者对象,该对象将对打开和关闭content 块之间的每个节点应用转义策略
    3. 在扩展中注册节点访问者。

    这是一个示例访问者,它将在 content 块内的每个 print 节点上应用 js 转义过滤器:

    <?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];
        }
    }
    

    【讨论】:

    • 我不想转义所有的块内容,只想转义块中输出的变量。
    • 抱歉,问题误解了。我已经更新了我的答案
    猜你喜欢
    • 2020-12-18
    • 1970-01-01
    • 2010-12-19
    • 1970-01-01
    • 1970-01-01
    • 2022-01-13
    • 2021-02-21
    • 2012-03-19
    • 2014-05-22
    相关资源
    最近更新 更多