如何使用 javascript 验证 smarty 代码?

How to validate smarty code with javascript?

我需要验证一个可以包含智能代码或电子邮件的输入字段。我使用 RegExp 执行此操作,您可以看到下面的代码。问题是电子邮件验证删除了所有斜杠,而 smarty 标签 ({/foreach}) 的结束标签包含斜杠。如何在不完全删除斜杠验证的情况下解决这个问题?

smarty: function(v) {
    var regex = new RegExp("\{\{[^\{^\}]+\}\}", "g");
    return regex.test(v);
},


emailOrSmarty: function(v) {
    if (this.smarty(v) !== true) {
        return this.email(v);
    }
    return true;
},

email: function(v) {
    var regex = new RegExp('^(?:[a-zA-Z0-9!#$%&\'*+\/=?^_`{|}~_.\-+])+@(?:(?:[a-zA-Z0-9\-])+?\.)+(?:[a-zA-Z0-9]{2,})+$');
    return regex.test(v);
},

有效输入示例

Example 1 (email):
example@website.com
Example 2 (smarty code):
{{foreach from=$find.users|filter:"male":$city' item='user'}}{{$user.mail}}{{/foreach}}

这个有点复杂;假设您的电子邮件验证表达式可能工作正常,我们只需添加 foreach 部分并检查它是否可能工作:

\{\{(.*?)\}\}\s*((?:[A-Za-z0-9!#$%&'*+\/=?^_`{|}~.+-])+@(?:(?:[A-Za-z0-9-])+?\.)+(?:[A-Za-z0-9]{2,})+)\s*\{\{\/()\}\}

const regex = /\{\{(.*?)\}\}\s*((?:[A-Za-z0-9!#$%&'*+\/=?^_`{|}~.+-])+@(?:(?:[A-Za-z0-9-])+?\.)+(?:[A-Za-z0-9]{2,})+)\s*\{\{\/()\}\}/sg;
const str = `{{foreach}} mail-1@mail.com  {{/foreach}}
{{foreach}} mail-2@mail.com{{/foreach}}
{{foreach}} 
 mail-3@mail.com
{{/foreach}}
     `;
let m;

while ((m = regex.exec(str)) !== null) {
    // This is necessary to avoid infinite loops with zero-width matches
    if (m.index === regex.lastIndex) {
        regex.lastIndex++;
    }
    
    // The result can be accessed through the `m`-variable.
    m.forEach((match, groupIndex) => {
        console.log(`Found match, group ${groupIndex}: ${match}`);
    });
}

表达式在 this demo, if you wish to explore further or modify/simplify it, and in this link 的右上面板进行了解释,如果您愿意,您可以逐步观察它如何与一些示例输入匹配。

您当前匹配 smarty 标签的模式与开始和结束标签相匹配。不确定这是不是故意的。

如果您想验证 smarty 标签之间是否只有一个电子邮件地址,您可以通过匹配输入字符串上的 smarty 模式来重用 smarty 模式,然后替换为空字符串。这将留下电子邮件地址。

然后您可以使用电子邮件验证来验证电子邮件。

请注意,如果您没有转义所有 {}。您的代码可能如下所示:

emailOrSmarty: function(v) {
    var smartyPattern  = /{{[^{}]+}}/g;
    return this.smarty(v) || this.email(v.replace(smartyPattern, ""))
}

我再次添加了相同的图案,但您可以将它移到另一个位置以便能够重复使用它。

如果你想测试其中任何一个,你已经有2个验证功能。对于您的函数,如果其中一个是 true

,您可以使用 or to return
emailOrSmarty: function (v) {
   return this.smarty(v) || this.email(v);
},

要使用 {{$user.mail}} 测试最后一个聪明模式,您可以添加:

smartyMailPattern: function(v) {
    var pattern = /{{foreach[^{}]+}}{{$user\.mail}}{{\/foreach}}/;
    return pattern.test(v);
}