better error message for unclose tag due to autoclosing

pull/5060/head
Tan Li Hau 5 years ago
parent 40987b7780
commit a617ca1b8a

@ -8,6 +8,12 @@ import error from '../utils/error';
type ParserState = (parser: Parser) => (ParserState | void); type ParserState = (parser: Parser) => (ParserState | void);
interface LastAutoCloseTag {
tag: string;
reason: string;
depth: number;
}
export class Parser { export class Parser {
readonly template: string; readonly template: string;
readonly filename?: string; readonly filename?: string;
@ -20,6 +26,7 @@ export class Parser {
css: Style[] = []; css: Style[] = [];
js: Script[] = []; js: Script[] = [];
meta_tags = {}; meta_tags = {};
last_auto_closed_tag?: LastAutoCloseTag;
constructor(template: string, options: ParserOptions) { constructor(template: string, options: ParserOptions) {
if (typeof template !== 'string') { if (typeof template !== 'string') {

@ -133,11 +133,19 @@ export default function tag(parser: Parser) {
// close any elements that don't have their own closing tags, e.g. <div><p></div> // close any elements that don't have their own closing tags, e.g. <div><p></div>
while (parent.name !== name) { while (parent.name !== name) {
if (parent.type !== 'Element') if (parent.type !== 'Element') {
if (parser.last_auto_closed_tag && parser.last_auto_closed_tag.tag === name) {
parser.error({
code: `invalid-closing-tag`,
message: `<${parser.last_auto_closed_tag.tag}> cannot have child element <${parser.last_auto_closed_tag.reason}>`,
}, start);
}
parser.error({ parser.error({
code: `invalid-closing-tag`, code: `invalid-closing-tag`,
message: `</${name}> attempted to close an element that was not open` message: `</${name}> attempted to close an element that was not open`
}, start); }, start);
}
parent.end = start; parent.end = start;
parser.stack.pop(); parser.stack.pop();
@ -148,10 +156,19 @@ export default function tag(parser: Parser) {
parent.end = parser.index; parent.end = parser.index;
parser.stack.pop(); parser.stack.pop();
if (parser.last_auto_closed_tag && parser.stack.length < parser.last_auto_closed_tag.depth) {
parser.last_auto_closed_tag = null;
}
return; return;
} else if (closing_tag_omitted(parent.name, name)) { } else if (closing_tag_omitted(parent.name, name)) {
parent.end = start; parent.end = start;
parser.stack.pop(); parser.stack.pop();
parser.last_auto_closed_tag ={
tag: parent.name,
reason: name,
depth: parser.stack.length,
};
} }
const unique_names: Set<string> = new Set(); const unique_names: Set<string> = new Set();

@ -0,0 +1,10 @@
{
"code": "invalid-closing-tag",
"message": "</p> attempted to close an element that was not open",
"pos": 38,
"start": {
"character": 38,
"column": 0,
"line": 5
}
}

@ -0,0 +1,10 @@
{
"code": "invalid-closing-tag",
"message": "<p> cannot have child element <pre>",
"pos": 24,
"start": {
"character": 24,
"column": 0,
"line": 3
}
}
Loading…
Cancel
Save