【问题标题】:Twig automatically removes apostrophe and quotation marksTwig 自动删除撇号和引号
【发布时间】:2023-03-20 17:07:01
【问题描述】:

为了学习,我创建了自己的 TransTokenParser(解析 {% trans %}{% trans with %})-> 解析器本身运行良好,除了后一种变体:trans with

解析器读出分配的变量,但自动转义 "',因此它们不会显示(变量在没有 '" 的情况下直接从解析器中出来)。

例如,我们在树枝中有这个块:

{% trans with {'{test}': coolFunctionWhichReturnsString('testParameter')} %}
UNIQUE_TRANS_ID
{% endtrans %}

这个块可以用 trans 和诸如此类的东西很好地解析,但是将 'with' 之后的部分变成这样:{{test}: coolFunctionWhichReturnsString(testParameter)}

我尝试在 Twig_Environment 中设置参数

new Twig_Environment(..., ['autoescape' => false])

我尝试在 twig 下的 config.yml 中设置一个全局变量:

autoescape: false

这两种解决方案都没有反映 twig -> php 行为的变化。 (它将自动转义设置为 false,如在此处初始化 twig 环境时的 var_dump 中所示:

array (size=13)
  'debug' => boolean true
  'charset' => string 'UTF-8' (length=5)
  'base_template_class' => string 'Twig_Template' (length=13)
  'strict_variables' => boolean true
  'autoescape' => boolean false

这是我的代码:

/**
 * @return array
 * @throws \Twig_Error_Syntax
 */
private function parseVariant(): array
{
    $stream = $this->parser->getStream();
    $trans = null;
    $json = null;
    //SIMPLE VARIANT trans
    $stream->nextIf(\Twig_Token::PUNCTUATION_TYPE, '');
    if (null !== $stream->nextIf(\Twig_Token::BLOCK_END_TYPE)) { //%} TRANS_LITERAL
        $stream->nextIf(\Twig_Token::PUNCTUATION_TYPE, '');
        $trans = $stream->expect(\Twig_Token::TEXT_TYPE)->getValue();
    } elseif (null !== $stream->nextIf(\Twig_Token::NAME_TYPE, 'with')) { // {% trans with {} %} TRANS_LITERAL
        $stream->next();
        $json = implode($this->getInlineParams());
        $stream->nextIf(\Twig_Token::PUNCTUATION_TYPE);
        $stream->nextIf(\Twig_Token::BLOCK_END_TYPE);
        $stream->nextIf(\Twig_Token::PUNCTUATION_TYPE);
        $trans = $stream->expect(\Twig_Token::TEXT_TYPE)->getValue();
        //die();
    }
    // {% endtrans %}
    $stream->nextIf(\Twig_Token::PUNCTUATION_TYPE);
    $stream->expect(\Twig_Token::BLOCK_START_TYPE);
    $stream->nextIf(\Twig_Token::PUNCTUATION_TYPE);
    $stream->expect(\Twig_Token::NAME_TYPE);
    $stream->nextIf(\Twig_Token::PUNCTUATION_TYPE);
    $endLine = $stream->expect(\Twig_Token::BLOCK_END_TYPE)->getLine();

    return [$json, $trans, $endLine];
}

问题在于 $json,在这种情况下指的是:

$json = implode($this->getInlineParams());

获取内联参数:

protected function getInlineParams(): array
{
    $stream = $this->parser->getStream();
    $params = [];
    while (!$stream->test(\Twig_Token::BLOCK_END_TYPE)) {
        $params[] = $this->parser->getStream()->next()->getValue();
    }
    $stream->expect(\Twig_Token::BLOCK_END_TYPE);

    return $params;
}

编辑:使用 ExpressionParser 会引发错误,因为键/值没有 "" 或 ''..

另一个编辑:我已经尝试在 twig 中修改运行时和初始化后的“转义符”扩展,包括所有策略 - 没有任何帮助

有什么建议吗? 提前致谢。

【问题讨论】:

  • 我没有太多时间来回答这个问题,我可以在星期一仔细看看。无论如何,在这一点上,我建议你看看IncludeToken,看看here - 我相信你可以在那里得到一些灵感
  • Twig 绑定变量键的语法如下{% set object = { (key1): "a string", (key2): some_function(3) } %} 其中key1key2 是保存字符串的变量。坚持使用这种语法可能更容易。
  • @NicolaiFröhlich 这不是 OP 面临的问题。当twig 将模板编译成PHP 进行渲染时,问题就出现了
  • 首先,感谢参与 cmets 部分并试图找到解决方案的所有人。 @DarkBee:期待周一的回复!我会查看您引用的链接。 @ NicolaiFröhlich 请假设我根本无法编辑树枝-> 因此将树枝文件更改为任何格式都不适用。 :)
  • 我想知道你为什么不看看 twig-bridge-bundle,它应该包含原始的 trans Node 东西。

标签: php symfony twig


【解决方案1】:

这是一个双重问题:第一个可能是在 getInlineParams 函数中实现简单逻辑的方法,这对于这些简单的情况可能没有问题,但对于更复杂的情况可能会很可怕。

第二个问题是完全不了解类型。

{'{test}': coolFunctionWhichReturnsString('testParameter')}

被解析为(读作“字符串值”-“令牌类型”):

  • { - 阻止开始
  • {test} - 一个字符串
  • : - 标点符号
  • coolFunctionWhichReturnsString - 一个名字
  • ( - (不确定是哪种)
  • testParameter - 一个字符串
  • ) - (再次)
  • } - 区块结束

第一个问题会在嵌套多个 {} 时展开。 第二个问题是由于一个简单的事实:

类型很重要。

词法分析器有一项非常重要的任务,它会删除用户可能选择表达字符串、cmets 的所有不同变体,它会删除不相关的空格(因为它只是杂乱无章)等等。现在,如果您将每个 Token(具有值和类型)都视为包含您想要的字符串的奇怪对象,那么您就会遇到问题 - 显然。

因此,如果您想重新创建类似于原始输入的内容,则必须查看类型并在类型为字符串时添加引号。 (文本可能都是块之外的东西)

这将是您所述问题的快速“解决方案”

但是,从长远来看,忽略标记的语义会导致问题......因为您还必须以某种方式处理“coolFunctionWhichReturnsString”,即您必须将其转换为一些函数调用。从理论上讲,您应该真正构建一个 AST 并在某个时候将其编译成适当的形式...

twig 解析器使用subparse 方法来解析内容,直到出现一些“结束”。 (建立一个 AST,因为结构在某些时候也很重要)

更新:事实证明,twig 文档中有一个用于编写节点解析器的页面,如果您关注https://twig.symfony.com/doc/2.x/advanced.html#registering-a-new-tag,它可能会大大简化这一点(信息开始略高于“注册新标签”,大大简化了值的解析和使用)

【讨论】:

  • 非常感谢您的意见 - 我完全理解您的观点,并期待在周一通过 getInlineParams() 考虑每个已解析令牌的类型!可惜我完全忽略了 Token 类型。也许,我已经研究过 subparse,但它总是将解析器设置为“坏状态”-> 因此我一直在寻找一种替代方法,其中方法 'getInlineParams()' 显示得心应手。我猜是因为我读错了顺序 -> 我会在星期一更新这个!
  • @sh0ck 祝你好运。请不要让这个问题变成完全不同的东西,在某些时候更像是“如何为树枝块编写解析器”(这会违反 SO 问题的精神)
  • @sh0ck 偶然发现了有关注册新标签的 twig 文档(请参阅更新),这肯定给出了应该如何完成的蓝图。
  • 哇!我希望我早点看到这个。除了用 expressionParser 替换 getInlineParams 之外,它根本没有简化任何事情——我已经提到过,这是我已经尝试过使用的东西! (我应该把我的全班都贴出来):=) 我会再试一次,周一会通知你最新消息——在那之前有一个愉快的周末。 :)
  • 非常感谢您指出它们被解析为不同的类型 - 我完全忘记了它。感谢您的帮助!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-10-18
  • 2018-09-21
  • 2023-03-06
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多