Skip to content
This repository was archived by the owner on Oct 9, 2023. It is now read-only.

Commit fd46e37

Browse files
Johannes Burghardtljharb
authored andcommitted
[Fix] escape closing </script tags
Fixes #165.
1 parent 8e744cf commit fd46e37

File tree

2 files changed

+39
-36
lines changed

2 files changed

+39
-36
lines changed

src/index.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ const RIGHT = '-->';
66
const ENCODE = [
77
['&', '&amp;'],
88
['>', '&gt;'],
9+
['</', '&lt;/'],
910
];
1011

1112
const DATA_KEY = 'hypernova-key';

test/escape-test.js

Lines changed: 38 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -5,59 +5,61 @@ import { serialize, toScript, fromScript } from '..';
55

66
describe('escaping', () => {
77
it('escapes', () => {
8-
const html = serialize('foo', '', { foo: '</script>', bar: '&gt;' });
8+
const html = serialize('foo', '', { foo: '</script>', bar: '&gt;', baz: '</script ' });
99

10-
assert.include(html, '</script&gt;');
10+
assert.include(html, '&lt;/script&gt;');
1111
assert.include(html, '&amp;gt;');
12+
assert.include(html, '&lt;/script ');
1213
});
1314

1415
wrap()
15-
.withGlobal('document', () => ({}))
16-
.describe('with fromScript', () => {
17-
it('loads the escaped content correctly', () => {
18-
const html = toScript({ a: 'b' }, { foo: '</script>', bar: '&gt;', baz: '&amp;' });
19-
const $ = cheerio.load(html);
16+
.withGlobal('document', () => ({}))
17+
.describe('with fromScript', () => {
18+
it('loads the escaped content correctly', () => {
19+
const html = toScript({ a: 'b' }, { foo: '</script>', bar: '&gt;', baz: '&amp;', foobar: '</script x' });
20+
const $ = cheerio.load(html);
2021

21-
global.document.querySelector = () => ({ innerHTML: $($('script')[0]).html() });
22+
global.document.querySelector = () => ({ innerHTML: $($('script')[0]).html() });
2223

23-
const res = fromScript({
24-
a: 'b',
25-
});
26-
27-
assert.isObject(res);
24+
const res = fromScript({
25+
a: 'b',
26+
});
2827

29-
assert.equal(res.foo, '</script>');
30-
assert.equal(res.bar, '&gt;');
31-
assert.equal(res.baz, '&amp;');
32-
});
28+
assert.isObject(res);
3329

34-
it('escapes multiple times the same, with interleaved decoding', () => {
35-
const makeHTML = () => toScript({ attr: 'key' }, {
36-
props: 'yay',
37-
needsEncoding: '" &gt; </script>', // "needsEncoding" is necessary
30+
assert.equal(res.foo, '</script>');
31+
assert.equal(res.bar, '&gt;');
32+
assert.equal(res.baz, '&amp;');
33+
assert.equal(res.foobar, '</script x');
3834
});
39-
const script1 = makeHTML();
40-
const script2 = makeHTML();
41-
assert.equal(script1, script2, 'two successive toScripts result in identical HTML');
4235

43-
const $ = cheerio.load(script1);
36+
it('escapes multiple times the same, with interleaved decoding', () => {
37+
const makeHTML = () => toScript({ attr: 'key' }, {
38+
props: 'yay',
39+
needsEncoding: '" &gt; </script>', // "needsEncoding" is necessary
40+
});
41+
const script1 = makeHTML();
42+
const script2 = makeHTML();
43+
assert.equal(script1, script2, 'two successive toScripts result in identical HTML');
4444

45-
global.document.querySelector = () => ({ innerHTML: $($('script')[0]).html() });
45+
const $ = cheerio.load(script1);
4646

47-
const res = fromScript({ attr: 'key' });
47+
global.document.querySelector = () => ({ innerHTML: $($('script')[0]).html() });
4848

49-
const script3 = makeHTML();
50-
assert.equal(
51-
script1,
52-
script3,
53-
'third toScript after a fromScript call results in the same HTML',
54-
);
49+
const res = fromScript({ attr: 'key' });
5550

56-
assert.isObject(res);
51+
const script3 = makeHTML();
52+
assert.equal(
53+
script1,
54+
script3,
55+
'third toScript after a fromScript call results in the same HTML',
56+
);
5757

58-
assert.equal(res.props, 'yay');
58+
assert.isObject(res);
59+
60+
assert.equal(res.props, 'yay');
61+
});
5962
});
60-
});
6163

6264
it('escapes quotes and fixes data attributes', () => {
6365
const markup = toScript({

0 commit comments

Comments
 (0)