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
我们使用谷歌文档创建文档。我们已经创建了模板文档,在最终使用之前需要进行两种类型的更改:
亲爱的${$Client}。 这篇文章的其余部分将不涉及简单的文本替换
省略没有“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标记(被其他人删除),因为问题是关于
的javascript替代方案(尽管适用于Google Apps脚本)eval()
- 添加了演示用例的简化代码
- 再次添加了javascript标记,该标记已被Sourabh Choria删除。由于这显然与javascript有关,为什么要删除两次此标记
- 澄清了条件不需要是
或单个变量==
HtmlService.createTemplate(…)
?@imthenanchoman:是的,Google文档具有富文本格式以及其他与HTML不兼容的功能。最后的文档是PDF格式的,再仔细想想,它是行不通的,因为编辑器运行任何代码都存在同样的风险。我认为,为了实现您的目标,并保持其安全性,您最终需要构建一个复杂的解析器来提取/排除/防止危险代码;这个对话已经结束了。我想你的谷歌文档有富文本格式?如果没有,你能使用吗?获取整个文档正文作为字符串,并将其传递给HtmlService.createTemplate(…)
?@imthenanchoman:是的,Google文档具有富文本格式以及其他与HTML不兼容的功能。最后的文档是PDF格式的,再仔细想想,它是行不通的,因为编辑器运行任何代码都存在同样的风险。我认为,为了实现您的目标并保持其安全性,您最终需要构建一个复杂的解析器来提取/排除/防止危险代码。