Skip to content

Commit 90f6f66

Browse files
authoredFeb 9, 2018
Merge pull request #1163 from sveltejs/non-root-rework
Rework handling of non-root <script> and <style>
2 parents 0ef8229 + 7d51484 commit 90f6f66

File tree

8 files changed

+134
-11
lines changed

8 files changed

+134
-11
lines changed
 

‎src/generators/nodes/Element.ts

+7-5
Original file line numberDiff line numberDiff line change
@@ -415,7 +415,13 @@ export default class Element extends Node {
415415
}
416416

417417
function toHTML(node: Element | Text) {
418-
if (node.type === 'Text') return escapeHTML(node.data);
418+
if (node.type === 'Text') {
419+
return node.parent &&
420+
node.parent.type === 'Element' &&
421+
(node.parent.name === 'script' || node.parent.name === 'style')
422+
? node.data
423+
: escapeHTML(node.data);
424+
}
419425

420426
let open = `<${node.name}`;
421427

@@ -433,10 +439,6 @@ export default class Element extends Node {
433439

434440
if (isVoidElementName(node.name)) return open + '>';
435441

436-
if (node.name === 'script' || node.name === 'style') {
437-
return `${open}>${node.data}</${node.name}>`;
438-
}
439-
440442
return `${open}>${node.children.map(toHTML).join('')}</${node.name}>`;
441443
}
442444
}

‎src/generators/server-side-rendering/visitors/Element.ts

-2
Original file line numberDiff line numberDiff line change
@@ -68,8 +68,6 @@ export default function visitElement(
6868

6969
if (node.name === 'textarea' && textareaContents !== undefined) {
7070
generator.append(textareaContents);
71-
} else if (node.name === 'script' || node.name === 'style') {
72-
generator.append(escape(node.data));
7371
} else {
7472
node.children.forEach((child: Node) => {
7573
visit(generator, block, child);

‎src/generators/server-side-rendering/visitors/Text.ts

+10-1
Original file line numberDiff line numberDiff line change
@@ -8,5 +8,14 @@ export default function visitText(
88
block: Block,
99
node: Node
1010
) {
11-
generator.append(escapeHTML(escape(node.data).replace(/(\${|`|\\)/g, '\\$1')));
11+
let text = escape(node.data).replace(/(\${|`|\\)/g, '\\$1');
12+
if (
13+
!node.parent ||
14+
node.parent.type !== 'Element' ||
15+
(node.parent.name !== 'script' && node.parent.name !== 'style')
16+
) {
17+
// unless this Text node is inside a <script> or <style> element, escape &,<,>
18+
text = escapeHTML(text);
19+
}
20+
generator.append(text);
1221
}

‎src/parse/state/tag.ts

+15-3
Original file line numberDiff line numberDiff line change
@@ -224,10 +224,22 @@ export default function tag(parser: Parser) {
224224
);
225225
parser.read(/<\/textarea>/);
226226
element.end = parser.index;
227-
} else if (name === 'script' || name === 'style') {
227+
} else if (name === 'script') {
228228
// special case
229-
element.data = parser.readUntil(new RegExp(`</${name}>`));
230-
parser.eat(`</${name}>`, true);
229+
const start = parser.index;
230+
const data = parser.readUntil(/<\/script>/);
231+
const end = parser.index;
232+
element.children.push({ start, end, type: 'Text', data });
233+
parser.eat('</script>', true);
234+
element.end = parser.index;
235+
} else if (name === 'style') {
236+
// special case
237+
element.children = readSequence(
238+
parser,
239+
() =>
240+
parser.template.slice(parser.index, parser.index + 8) === '</style>'
241+
);
242+
parser.read(/<\/style>/);
231243
element.end = parser.index;
232244
} else {
233245
parser.stack.push(element);
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
export default {
2+
data: {
3+
color: 'red',
4+
},
5+
6+
html: `
7+
<div>
8+
<style>
9+
/* something with < and > */
10+
div {
11+
color: blue;
12+
}
13+
</style>
14+
foo
15+
</div>
16+
17+
<div>
18+
<div>
19+
<style>
20+
div > div {
21+
color: blue;
22+
}
23+
</style>
24+
foo
25+
</div>
26+
</div>
27+
28+
<div>
29+
<style>
30+
/* something with < and > */
31+
div {
32+
color: red;
33+
}
34+
</style>
35+
foo
36+
</div>
37+
38+
<div>
39+
<div>
40+
<style>
41+
div > div {
42+
color: red;
43+
}
44+
</style>
45+
foo
46+
</div>
47+
</div>
48+
`,
49+
};
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
<div>
2+
<style>
3+
/* something with < and > */
4+
div {
5+
color: blue;
6+
}
7+
</style>
8+
foo
9+
</div>
10+
11+
<div>
12+
<div>
13+
<style>
14+
div > div {
15+
color: blue;
16+
}
17+
</style>
18+
foo
19+
</div>
20+
</div>
21+
22+
<div>
23+
<style>
24+
/* something with < and > */
25+
div {
26+
color: {{color}};
27+
}
28+
</style>
29+
foo
30+
</div>
31+
32+
<div>
33+
<div>
34+
<style>
35+
div > div {
36+
color: {{color}};
37+
}
38+
</style>
39+
foo
40+
</div>
41+
</div>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
export default {
2+
html: `
3+
<div>
4+
<style>div { color: red; }</style>
5+
<script>alert('<>');</script>
6+
</div>
7+
`
8+
};
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
<div>
2+
<style>div { color: red; }</style>
3+
<script>alert('<>');</script>
4+
</div>

0 commit comments

Comments
 (0)
Please sign in to comment.