Skip to content

Commit

Permalink
feat: add edge case for lack end tag
Browse files Browse the repository at this point in the history
  • Loading branch information
cuixiaorui committed Feb 26, 2022
1 parent eee97a1 commit 9dbfe26
Show file tree
Hide file tree
Showing 2 changed files with 56 additions and 9 deletions.
30 changes: 30 additions & 0 deletions src/compiler-core/__tests__/parse.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -95,5 +95,35 @@ describe("parser", () => {
],
});
});

test("element with interpolation and text", () => {
const ast = baseParse("<div>hi,{{ msg }}</div>");
const element = ast.children[0];

expect(element).toStrictEqual({
type: NodeTypes.ELEMENT,
tag: "div",
tagType: ElementTypes.ELEMENT,
children: [
{
type: NodeTypes.TEXT,
content: "hi,",
},
{
type: NodeTypes.INTERPOLATION,
content: {
type: NodeTypes.SIMPLE_EXPRESSION,
content: "msg",
},
},
],
});
});

test("should throw error when lack end tag ", () => {
expect(() => {
baseParse("<div><span></div>");
}).toThrow("缺失结束标签:span");
});
});
});
35 changes: 26 additions & 9 deletions src/compiler-core/src/parse.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ const enum TagType {

export function baseParse(content: string) {
const context = createParserContext(content);
return createRoot(parseChildren(context));
return createRoot(parseChildren(context, []));
}

function createParserContext(content) {
Expand All @@ -17,11 +17,11 @@ function createParserContext(content) {
};
}

function parseChildren(context) {
function parseChildren(context, ancestors) {
console.log("开始解析 children");
const nodes: any = [];

while (!isEnd(context)) {
while (!isEnd(context, ancestors)) {
let node;
const s = context.source;

Expand All @@ -40,7 +40,7 @@ function parseChildren(context) {
continue;
}
} else if (/[a-z]/i.test(s[1])) {
node = parseElement(context);
node = parseElement(context, ancestors);
}
}

Expand All @@ -54,25 +54,42 @@ function parseChildren(context) {
return nodes;
}

function isEnd(context: any) {
function isEnd(context: any, ancestors) {
// 检测标签的节点
// 如果是结束标签的话,需要看看之前有没有开始标签,如果有的话,那么也应该结束
// 这里的一个 edge case 是 <div><span></div>
// 像这种情况下,其实就应该报错
const s = context.source;
if (context.source.startsWith("</")) {
// 从后面往前面查
// 因为便签如果存在的话 应该是 ancestors 最后一个元素
for (let i = ancestors.length - 1; i >= 0; --i) {
if (startsWithEndTagOpen(s, ancestors[i].tag)) {
return true;
}
}
}

// 看看 context.source 还有没有值
return !context.source;
}

function parseElement(context) {
function parseElement(context, ancestors) {
// 应该如何解析 tag 呢
// <div></div>
// 先解析开始 tag
const element = parseTag(context, TagType.Start);

const children = parseChildren(context);
ancestors.push(element);
const children = parseChildren(context, ancestors);
ancestors.pop();

// 解析 end tag 是为了检测语法是不是正确的
// 检测是不是和 start tag 一致
if (startsWithEndTagOpen(context.source, element.tag)) {
parseTag(context, TagType.End);
} else {
// TODO 报错
throw new Error(`缺失结束标签:${element.tag}`);
}

element.children = children;
Expand All @@ -85,7 +102,7 @@ function startsWithEndTagOpen(source: string, tag: string) {
// 2. 看看是不是和 tag 一样
return (
startsWith(source, "</") &&
source.substr(2, tag.length).toLowerCase() === tag.toLowerCase()
source.slice(2, 2 + tag.length).toLowerCase() === tag.toLowerCase()
);
}

Expand Down

0 comments on commit 9dbfe26

Please sign in to comment.