从给定文本中检索所有嵌入的 Handlebar 变量

问题描述 投票:0回答:1

我正在使用 Handlebars 库并开发一个函数来检索所有嵌入的变量。该功能适用于简单的非逻辑文本。但是,当有 if 语句时,函数只返回变量的一个子集。

import Handlebars from "handlebars";

function getHandlebarsVariables(input){
    const ast = Handlebars.parseWithoutProcessing(input);
    return ast.body
      .filter(({ type }) => type === 'MustacheStatement')
      .map((statement) => statement.params[0]?.original || statement.path?.original);
};

const text1 = '{{name}} {{age}} {{#if isAdult}} {{ Adult }} {{/if}}';

const variables = getHandlebarsVariables(text1);

console.log(variables); // currently returns ['name', 'age'], I want to return ['name', 'age', 'Adult']

我期望函数返回的内容:['name', 'age', 'Adult'] 目前我得到:['name', 'age']

javascript arrays handlebars.js
1个回答
0
投票

我认为编译器的功能比您认为的要多。如果解析的 Handlebars 模板是一个简单的平面数组,您的过滤器和映射逻辑就足够了;但是这样的语法树不是那样的——它有很多层次,必须使用递归来解析。

我提供下面的代码,不是作为一个功能齐全的可交付程序,而是作为一个如何递归遍历语法树的示例。此示例适用于您帖子中的

text1
输入,但我 不会 指望它适用于所有 Handlebars 模板。

import Handlebars from "handlebars";

function getVariablesFromStatementsRecursive(statements) {
  return statements.reduce((acc, statement) => {
    const { type } = statement;

    if ("BlockStatement" === type) {
      const { inverse, program } = statement;

      if (program?.body) {
        acc = acc.concat(getVariablesFromStatementsRecursive(program.body));
      }

      if (inverse?.body) {
        acc = acc.concat(getVariablesFromStatementsRecursive(inverse.body));
      }
    } else if ("MustacheStatement" === type) {
      const { path } = statement;

      if (path?.original) {
        acc.push(path.original);
      }
    }

    return acc;
  }, []);
}

function getHandlebarsVariables(input) {
  const ast = Handlebars.parseWithoutProcessing(input);

  return getVariablesFromStatementsRecursive(ast.body);
}

const text1 = "{{name}} {{age}} {{#if isAdult}} {{ Adult }} {{/if}}";

const variables = getHandlebarsVariables(text1);

console.log(variables); // [ 'name', 'age', 'Adult' ]
© www.soinside.com 2019 - 2024. All rights reserved.