Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/460.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript 用于模板化Google应用程序脚本的eval()替代方法_Javascript_Google Apps Script_Google Docs - Fatal编程技术网

Javascript 用于模板化Google应用程序脚本的eval()替代方法

Javascript 用于模板化Google应用程序脚本的eval()替代方法,javascript,google-apps-script,google-docs,Javascript,Google Apps Script,Google Docs,背景: 我们使用谷歌文档创建文档。我们已经创建了模板文档,在最终使用之前需要进行两种类型的更改: 一个简单的文本替换;及 有条件的文本替换 这些在文档中使用标记表示。使用GoogleApps脚本,然后根据需要替换模板中的标记,以创建最终文档。标记将包含变量 简单的文本替换标记表示如下:${$SomeVar},变量为$SomeVar 示例: 亲爱的${$Client}。 这篇文章的其余部分将不涉及简单的文本替换 条件文本替换标记表示为:${if CONDITION}XXXXX${end}或${if

背景:
我们使用谷歌文档创建文档。我们已经创建了模板文档,在最终使用之前需要进行两种类型的更改:

  • 一个简单的文本替换;及
  • 有条件的文本替换 这些在文档中使用标记表示。使用GoogleApps脚本,然后根据需要替换模板中的标记,以创建最终文档。标记将包含变量

  • 简单的文本替换标记表示如下:${$SomeVar},变量为$SomeVar
  • 示例:
    亲爱的${$Client}。

    这篇文章的其余部分将不涉及简单的文本替换

  • 条件文本替换标记表示为:${if CONDITION}XXXXX${end}${if CONDITION}XXXXX${else}yyyy${end},具体取决于我们是否需要替换(即else)
  • 示例:
    省略没有“else”的示例,条件文本替换可用于合同或最终报告函:
    您${if($Paid==true)}已全额支付给我们${else}仍有余额${end}。
    (请注意if标记前的“You”和end标记后的“.”)
    根据变量
    $Paid
    的值,这将产生
    您已向我们全额支付。

    您仍有未清余额。

    注意:条件可以是任何计算为布尔值的东西。它可以是
    someBool==true
    someNum>2
    someString.trim().len>4
    或类似内容。我们不想限制条件的可能内容

    当前实施:
    通过搜索open if标记、else标记(如果存在)和end标记,我们可以正确地执行上述操作。然后它保留所需的文本并删除标记(如上面的示例所示)

    不幸的是,我们使用可怕的javascript eval()如下(使用上面的示例):
    eval($Paid==true)

    以下是验证条件的确切代码:

    var condString = ifString.replace(/^\$\{\s*if\s*/,"").replace(/\s*\}$/,"").replace(/\$(\w+)/g, "tags[\"$1\"]");
    return eval(condString);
    
    这是一个简单且高度简化的代码版本,省略了对
    ${else}
    ${end}
    标记的解析,以及任何真正的功能:

    function ParseConditionalTags() {
    
        /* parameters passed in to function, here hardcoded strictly for demonstration purposes
        **
        **
        */
        var orig = DriveApp.getFileById("SomeTemplateGoogleDocId");
        var doc = DocumentApp.openById(orig.makeCopy(orig.getName() + "_1", orig.getParents().next()).getId());
        /* doc: the newly created Google Doc, in a/the same folder as the original template */
    
        var variables = {};
        variables["BooleanVar"] = false;
        variables["num"] = 11;
        /* variables: the variables passed in to the function, which will then be replaced as required in the opening if-tag */
    
        /*
        **
        **
        ** end hardcoded parameters for demonstration purposes */
    
    
        /* helper variables
        **
        **
        */
    
        /* get the body as it is frequently used */
        var body = doc.getBody();
    
        /* this is the regular expression (strings) for the opening if-tag */
        var ifRegExpString = "\\$\\{if\\s+[^\\}\\s]+\\}";
    
        /* get the body as it is frequently used */
        var body = doc.getBody();
    
        /*
        **
        **
        ** end helper variables */
    
    
    
        /* search the body for an opening if-tag */
        var startRE = body.findText(ifRegExpString);
    
        var ifString;
        var condEval;
    
        while (startRE != null) {
            /* get the "${if /something/}" string */
            ifString = startRE.getElement().asText().getText().slice(startRE.getStartOffset(),startRE.getEndOffsetInclusive()+1);
    
            /* assume that variables must be only letters, numbers and underscores, which is incorrect as far as the JavaScript reference goes:
                   https://www.w3schools.com/js/js_variables.asp
            */
            condEval = eval(ifString.replace(/^\$\{\s*if\s*/,"").replace(/\s*\}$/,"").replace(/\$(\w+)/g, "variables[\"$1\"]"));
    
            if (condEval) {
                /* the condition evaluates to true, so keep the text between the tags but delete the actual tags */
                /* this block is ommitted as it does not assist in demonstrating the question/issue */
            }
            else {
                /* the condition evaluates to false, so remove the tags and all text between them */
                /* this block is ommitted as it does not assist in demonstrating the question/issue */ 
            }
        }
    
    
        /* get the next opening if-tag */
        startRE = body.findText(ifRegExpString, startRE);
    }
    
    问题:
    我们希望我们的所有用户都能够创建模板文档并自动完成最终文档(如上所述),但这是一个巨大的安全风险,因为任何人都可以在模板文档中插入一些代码,然后将
    eval()编辑

    ${DoSomethingTerribleLikeDeleteAllFiles()}

    我们的尝试:
    我们尝试过使用,但不幸的是,它缺少其他需要的行为。此外,我们不希望使用其他软件,因为我们看不到代码(因此我们希望自己构建一些东西)

    问题:
    除了为条件语句构建一个复杂的解析器之外,有人能帮助我们实现使用条件语句构建模板文档的预期目标吗?
    或者,是否有人知道有任何开源项目可以提供帮助

    编辑:

    • 添加了用于条件eval语句的精确代码
    • 重新添加javascript标记(被其他人删除),因为问题是关于
      eval()
      的javascript替代方案(尽管适用于Google Apps脚本)
    • 添加了演示用例的简化代码
    • 再次添加了javascript标记,该标记已被Sourabh Choria删除。由于这显然与javascript有关,为什么要删除两次此标记
    • 澄清了条件不需要是
      ==
      或单个变量

    评论不用于扩展讨论;这个对话已经结束了。我想你的谷歌文档有富文本格式?如果没有,你能使用吗?获取整个文档正文作为字符串,并将其传递给
    HtmlService.createTemplate(…)
    ?@imthenanchoman:是的,Google文档具有富文本格式以及其他与HTML不兼容的功能。最后的文档是PDF格式的,再仔细想想,它是行不通的,因为编辑器运行任何代码都存在同样的风险。我认为,为了实现您的目标,并保持其安全性,您最终需要构建一个复杂的解析器来提取/排除/防止危险代码;这个对话已经结束了。我想你的谷歌文档有富文本格式?如果没有,你能使用吗?获取整个文档正文作为字符串,并将其传递给
    HtmlService.createTemplate(…)
    ?@imthenanchoman:是的,Google文档具有富文本格式以及其他与HTML不兼容的功能。最后的文档是PDF格式的,再仔细想想,它是行不通的,因为编辑器运行任何代码都存在同样的风险。我认为,为了实现您的目标并保持其安全性,您最终需要构建一个复杂的解析器来提取/排除/防止危险代码。