[fix] script style end parsing (#6511)

* update script end tag parsing to allow whitespace after tagname

* update style end tag parsing to allow for whitespace after tag name

* handle no closing match for script and style for eof and non-eof failures

* cleaning up script and style end tag parsing

Co-authored-by: pngwn <hello@pngwn.io>
pull/5262/head
Tan Li Hau 3 years ago committed by GitHub
parent 999032835b
commit 6a582af839
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -177,9 +177,9 @@ export class Parser {
return identifier;
}
read_until(pattern: RegExp) {
read_until(pattern: RegExp, error_message?: Parameters<Parser['error']>[0]) {
if (this.index >= this.template.length) {
this.error({
this.error(error_message || {
code: 'unexpected-eof',
message: 'Unexpected end of input'
});

@ -3,8 +3,6 @@ import { Parser } from '../index';
import { Script } from '../../interfaces';
import { Node, Program } from 'estree';
const script_closing_tag = '</script>';
function get_context(parser: Parser, attributes: any[], start: number): string {
const context = attributes.find(attribute => attribute.name === 'context');
if (!context) return 'default';
@ -30,18 +28,17 @@ function get_context(parser: Parser, attributes: any[], start: number): string {
export default function read_script(parser: Parser, start: number, attributes: Node[]): Script {
const script_start = parser.index;
const script_end = parser.template.indexOf(script_closing_tag, script_start);
if (script_end === -1) {
parser.error({
code: 'unclosed-script',
message: '<script> must have a closing tag'
});
const error_message = {
code: 'unclosed-script',
message: '<script> must have a closing tag'
};
const data = parser.read_until(/<\/script\s*>/, error_message);
if (parser.index >= parser.template.length) {
parser.error(error_message);
}
const source = parser.template.slice(0, script_start).replace(/[^\n]/g, ' ') +
parser.template.slice(script_start, script_end);
parser.index = script_end + script_closing_tag.length;
const source = parser.template.slice(0, script_start).replace(/[^\n]/g, ' ') + data;
parser.read(/<\/script\s*>/);
let ast: Program;

@ -6,7 +6,17 @@ import { Style } from '../../interfaces';
export default function read_style(parser: Parser, start: number, attributes: Node[]): Style {
const content_start = parser.index;
const styles = parser.read_until(/<\/style>/);
const error_message = {
code: 'unclosed-style',
message: '<style> must have a closing tag'
};
const styles = parser.read_until(/<\/style\s*>/, error_message);
if (parser.index >= parser.template.length) {
parser.error(error_message);
}
const content_end = parser.index;
let ast;
@ -72,7 +82,7 @@ export default function read_style(parser: Parser, start: number, attributes: No
}
});
parser.eat('</style>', true);
parser.read(/<\/style\s*>/);
const end = parser.index;
return {

@ -0,0 +1,10 @@
{
"code": "unclosed-script",
"message": "<script> must have a closing tag",
"start": {
"line": 3,
"column": 22,
"character": 32
},
"pos": 32
}

@ -0,0 +1,10 @@
{
"code": "unclosed-style",
"message": "<style> must have a closing tag",
"start": {
"line": 3,
"column": 22,
"character": 31
},
"pos": 31
}

@ -0,0 +1,10 @@
{
"code": "unclosed-style",
"message": "<style> must have a closing tag",
"start": {
"line": 3,
"column": 7,
"character": 31
},
"pos": 31
}

@ -0,0 +1,3 @@
<h1>Hello {name}!</h1>
<style>

@ -0,0 +1,10 @@
<script>
let name = 'world';
</script
>
<h1>Hello {name}!</h1>

@ -0,0 +1,150 @@
{
"html": {
"start": 51,
"end": 73,
"type": "Fragment",
"children": [
{
"start": 49,
"end": 51,
"type": "Text",
"raw": "\n\n",
"data": "\n\n"
},
{
"start": 51,
"end": 73,
"type": "Element",
"name": "h1",
"attributes": [],
"children": [
{
"start": 55,
"end": 61,
"type": "Text",
"raw": "Hello ",
"data": "Hello "
},
{
"start": 61,
"end": 67,
"type": "MustacheTag",
"expression": {
"type": "Identifier",
"start": 62,
"end": 66,
"loc": {
"start": {
"line": 10,
"column": 11
},
"end": {
"line": 10,
"column": 15
}
},
"name": "name"
}
},
{
"start": 67,
"end": 68,
"type": "Text",
"raw": "!",
"data": "!"
}
]
}
]
},
"instance": {
"type": "Script",
"start": 0,
"end": 49,
"context": "default",
"content": {
"type": "Program",
"start": 8,
"end": 30,
"loc": {
"start": {
"line": 1,
"column": 0
},
"end": {
"line": 3,
"column": 0
}
},
"body": [
{
"type": "VariableDeclaration",
"start": 10,
"end": 29,
"loc": {
"start": {
"line": 2,
"column": 1
},
"end": {
"line": 2,
"column": 20
}
},
"declarations": [
{
"type": "VariableDeclarator",
"start": 14,
"end": 28,
"loc": {
"start": {
"line": 2,
"column": 5
},
"end": {
"line": 2,
"column": 19
}
},
"id": {
"type": "Identifier",
"start": 14,
"end": 18,
"loc": {
"start": {
"line": 2,
"column": 5
},
"end": {
"line": 2,
"column": 9
}
},
"name": "name"
},
"init": {
"type": "Literal",
"start": 21,
"end": 28,
"loc": {
"start": {
"line": 2,
"column": 12
},
"end": {
"line": 2,
"column": 19
}
},
"value": "world",
"raw": "'world'"
}
}
],
"kind": "let"
}
],
"sourceType": "module"
}
}
}

@ -0,0 +1,12 @@
<div>foo</div>
<style>
div {
color: red;
}
</style
>

@ -0,0 +1,97 @@
{
"html": {
"start": 0,
"end": 14,
"type": "Fragment",
"children": [
{
"start": 0,
"end": 14,
"type": "Element",
"name": "div",
"attributes": [],
"children": [
{
"start": 5,
"end": 8,
"type": "Text",
"raw": "foo",
"data": "foo"
}
]
},
{
"start": 14,
"end": 16,
"type": "Text",
"raw": "\n\n",
"data": "\n\n"
}
]
},
"css": {
"type": "Style",
"start": 16,
"end": 66,
"attributes": [],
"children": [
{
"type": "Rule",
"prelude": {
"type": "SelectorList",
"children": [
{
"type": "Selector",
"children": [
{
"type": "TypeSelector",
"name": "div",
"start": 25,
"end": 28
}
],
"start": 25,
"end": 28
}
],
"start": 25,
"end": 28
},
"block": {
"type": "Block",
"children": [
{
"type": "Declaration",
"important": false,
"property": "color",
"value": {
"type": "Value",
"children": [
{
"type": "Identifier",
"name": "red",
"start": 40,
"end": 43
}
],
"start": 40,
"end": 43
},
"start": 33,
"end": 43
}
],
"start": 29,
"end": 47
},
"start": 25,
"end": 47
}
],
"content": {
"start": 23,
"end": 48,
"styles": "\n\tdiv {\n\t\tcolor: red;\n\t}\n"
}
}
}
Loading…
Cancel
Save