handle unclosed tags

pull/14691/head
Simon Holthausen 2 years ago
parent 6450737801
commit 6994021ef9

@ -99,7 +99,9 @@ export class Parser {
if (this.stack.length > 1) { if (this.stack.length > 1) {
const current = this.current(); const current = this.current();
if (current.type === 'RegularElement') { if (this.loose) {
current.end = this.template.length;
} else if (current.type === 'RegularElement') {
current.end = current.start + 1; current.end = current.start + 1;
e.element_unclosed(current, current.name); e.element_unclosed(current, current.name);
} else { } else {

@ -80,7 +80,7 @@ export default function element(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 (/** @type {AST.RegularElement} */ (parent).name !== name) { while (/** @type {AST.RegularElement} */ (parent).name !== name) {
if (parent.type !== 'RegularElement') { if (parent.type !== 'RegularElement' && !parser.loose) {
if (parser.last_auto_closed_tag && parser.last_auto_closed_tag.tag === name) { if (parser.last_auto_closed_tag && parser.last_auto_closed_tag.tag === name) {
e.element_invalid_closing_tag_autoclosed(start, name, parser.last_auto_closed_tag.reason); e.element_invalid_closing_tag_autoclosed(start, name, parser.last_auto_closed_tag.reason);
} else { } else {

@ -0,0 +1,10 @@
<div>
<Comp>
</div>
<div>
<span>
</div>
<div>
<p>hi</p>

@ -0,0 +1,119 @@
{
"html": {
"type": "Fragment",
"start": 0,
"end": 59,
"children": [
{
"type": "Element",
"start": 0,
"end": 20,
"name": "div",
"attributes": [],
"children": [
{
"type": "Text",
"start": 5,
"end": 7,
"raw": "\n\t",
"data": "\n\t"
},
{
"type": "InlineComponent",
"start": 7,
"end": 14,
"name": "Comp",
"attributes": [],
"children": [
{
"type": "Text",
"start": 13,
"end": 14,
"raw": "\n",
"data": "\n"
}
]
}
]
},
{
"type": "Text",
"start": 20,
"end": 22,
"raw": "\n\n",
"data": "\n\n"
},
{
"type": "Element",
"start": 22,
"end": 42,
"name": "div",
"attributes": [],
"children": [
{
"type": "Text",
"start": 27,
"end": 29,
"raw": "\n\t",
"data": "\n\t"
},
{
"type": "Element",
"start": 29,
"end": 36,
"name": "span",
"attributes": [],
"children": [
{
"type": "Text",
"start": 35,
"end": 36,
"raw": "\n",
"data": "\n"
}
]
}
]
},
{
"type": "Text",
"start": 42,
"end": 44,
"raw": "\n\n",
"data": "\n\n"
},
{
"type": "Element",
"start": 44,
"end": 59,
"name": "div",
"attributes": [],
"children": [
{
"type": "Text",
"start": 49,
"end": 50,
"raw": "\n",
"data": "\n"
},
{
"type": "Element",
"start": 50,
"end": 59,
"name": "p",
"attributes": [],
"children": [
{
"type": "Text",
"start": 53,
"end": 55,
"raw": "hi",
"data": "hi"
}
]
}
]
}
]
}
}

@ -12,7 +12,9 @@ const { test, run } = suite<ParserTest>(async (config, cwd) => {
.replace(/\s+$/, '') .replace(/\s+$/, '')
.replace(/\r/g, ''); .replace(/\r/g, '');
const actual = JSON.parse(JSON.stringify(parse(input))); const actual = JSON.parse(
JSON.stringify(parse(input, { loose: cwd.split('/').pop()!.startsWith('loose-') }))
);
// run `UPDATE_SNAPSHOTS=true pnpm test parser` to update parser tests // run `UPDATE_SNAPSHOTS=true pnpm test parser` to update parser tests
if (process.env.UPDATE_SNAPSHOTS) { if (process.env.UPDATE_SNAPSHOTS) {

@ -0,0 +1,10 @@
<div>
<Comp>
</div>
<div>
<span>
</div>
<div>
<p>hi</p>

@ -0,0 +1,141 @@
{
"css": null,
"js": [],
"start": 0,
"end": 59,
"type": "Root",
"fragment": {
"type": "Fragment",
"nodes": [
{
"type": "RegularElement",
"start": 0,
"end": 20,
"name": "div",
"attributes": [],
"fragment": {
"type": "Fragment",
"nodes": [
{
"type": "Text",
"start": 5,
"end": 7,
"raw": "\n\t",
"data": "\n\t"
},
{
"type": "Component",
"start": 7,
"end": 14,
"name": "Comp",
"attributes": [],
"fragment": {
"type": "Fragment",
"nodes": [
{
"type": "Text",
"start": 13,
"end": 14,
"raw": "\n",
"data": "\n"
}
]
}
}
]
}
},
{
"type": "Text",
"start": 20,
"end": 22,
"raw": "\n\n",
"data": "\n\n"
},
{
"type": "RegularElement",
"start": 22,
"end": 42,
"name": "div",
"attributes": [],
"fragment": {
"type": "Fragment",
"nodes": [
{
"type": "Text",
"start": 27,
"end": 29,
"raw": "\n\t",
"data": "\n\t"
},
{
"type": "RegularElement",
"start": 29,
"end": 36,
"name": "span",
"attributes": [],
"fragment": {
"type": "Fragment",
"nodes": [
{
"type": "Text",
"start": 35,
"end": 36,
"raw": "\n",
"data": "\n"
}
]
}
}
]
}
},
{
"type": "Text",
"start": 42,
"end": 44,
"raw": "\n\n",
"data": "\n\n"
},
{
"type": "RegularElement",
"start": 44,
"end": 59,
"name": "div",
"attributes": [],
"fragment": {
"type": "Fragment",
"nodes": [
{
"type": "Text",
"start": 49,
"end": 50,
"raw": "\n",
"data": "\n"
},
{
"type": "RegularElement",
"start": 50,
"end": 59,
"name": "p",
"attributes": [],
"fragment": {
"type": "Fragment",
"nodes": [
{
"type": "Text",
"start": 53,
"end": 55,
"raw": "hi",
"data": "hi"
}
]
}
}
]
}
}
]
},
"options": null
}

@ -15,7 +15,8 @@ const { test, run } = suite<ParserTest>(async (config, cwd) => {
const actual = JSON.parse( const actual = JSON.parse(
JSON.stringify( JSON.stringify(
parse(input, { parse(input, {
modern: true modern: true,
loose: cwd.split('/').pop()!.startsWith('loose-')
}) })
) )
); );

Loading…
Cancel
Save