34-编译模块概述-text类型

49 阅读1分钟

测试用例

  describe("TEXT", () => {
    test("simple text", () => {
      const textStr = "simple text";
      const ast = baseParse(textStr);
      expect(ast.children[0]).toStrictEqual({
        type: NodeType.TEXT,
        content: "simple text",
      });
    });
  });

实现

新增TEXT类型

ast.ts

export const enum NodeType {
  INTERPOLATION,
  SIMPLE_EXPRESSION,
  ELEMENT,
+  TEXT,
}

判断TEXT类型

parse.ts

function parseChildren(context: { source: string }): any {
  const nodes: any = [];
  let node;
  const s = context.source;
  /** 判断字符串类型
   * 1. 为插值
   * 2. 为element
   */
  if (s.startsWith("{{")) {
    // {{ 开头,即认为是插值
    node = parseInterpolation(context);
  } else if (s.startsWith("<") && /[a-z]/i.test(s[1])) {
    // <开头,并且第二位是a-z,即认为是element类型
    node = parseElement(context);
  } else {
+    node = parseText(context);
  }
  nodes.push(node);
  return [node];
}

解析text

function parseTextData(context: { source: string }, length) {
  return context.source.slice(0, length);
}

// 解析text
function parseText(context: { source: string }): any {
  // 获取 content
  const content = parseTextData(context, context.source.length);
  // 推进
  advanceBy(context, content.length);
  return {
    type: NodeType.TEXT,
    content,
  };
}

这里封装了parseTextData,可以同步优化一下 parseInterpolation

function parseInterpolation(context: { source: string }) {
  // 插值开始字符
  const openDelimiter = "{{";
  // 插值结束字符
  const closeDelimiter = "}}";
  // 找到插值结束字符的位置
  const closeIndex = context.source.indexOf(
    closeDelimiter,
    openDelimiter.length
  );
  // 切割掉 {{
  advanceBy(context, openDelimiter.length);
  // 找到 }} 前的内容
  const rawContentLength = closeIndex - closeDelimiter.length;
  // 截取插值表达式里的内容
+  const content = parseTextData(context, rawContentLength).trim();
  // 完成{{}}的内容匹配,切割掉匹配完成的内容,继续往前推进,解析后面的内容
  advanceBy(context, rawContentLength + closeDelimiter.length);
  return {
    type: NodeType.INTERPOLATION,
    content: {
      type: NodeType.SIMPLE_EXPRESSION,
      content,
    },
  };
}