测试用例
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,
},
};
}