如何从含if语句的Handlebars文本中提取所有嵌入变量?
解决Handlebars嵌套块中变量提取问题
你的问题出在当前函数只遍历了AST的顶级节点,而{{#if}}这类块语句属于BlockStatement类型,其内部的变量节点被嵌套在BlockStatement的body属性中,没有被递归遍历到。
要提取所有嵌套变量,需要编写递归逻辑遍历AST的所有节点,包括块语句内部的内容:
import Handlebars from "handlebars"; function getHandlebarsVariables(input) { const ast = Handlebars.parseWithoutProcessing(input); const variables = []; // 递归遍历AST节点收集变量 function collectNodes(nodes) { nodes.forEach(node => { // 处理普通变量节点 if (node.type === 'MustacheStatement') { const varName = node.params[0]?.original || node.path?.original; if (varName) { variables.push(varName); } } // 处理块语句(如#if、#each),递归遍历其内部节点 else if (node.type === 'BlockStatement') { collectNodes(node.body); // 可选:处理块语句的else分支(如果需要提取else里的变量) if (node.elseBody) { collectNodes(node.elseBody); } } // 可按需扩展处理其他包含子节点的类型,比如PartialStatement }); } collectNodes(ast.body); // 可选:去重,避免重复变量多次出现 return [...new Set(variables)]; }; const text1 = '{{name}} {{age}} {{#if isAdult}} {{ Adult }} {{/if}}'; const variables = getHandlebarsVariables(text1); console.log(variables); // 现在返回 ['name', 'age', 'Adult']
关键说明:
BlockStatement类型的节点包含body属性,存储了块内的所有子节点,必须递归遍历才能获取内部变量- 新增的
collectNodes函数负责递归处理所有节点类型,覆盖顶级和嵌套场景 - 加入了可选的去重逻辑(使用
Set),避免重复变量多次出现 - 额外处理了
elseBody分支,可覆盖{{else}}块内的变量提取需求
内容的提问来源于stack exchange,提问作者Juan
相关产品推荐
相关产品推荐

