securemark 0.289.5 → 0.290.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +8 -0
- package/design.md +1 -1
- package/dist/index.js +118 -334
- package/markdown.d.ts +11 -12
- package/package.json +1 -1
- package/src/combinator/control/manipulation/surround.ts +20 -30
- package/src/combinator/control/monad/bind.ts +1 -0
- package/src/combinator/data/parser.ts +0 -1
- package/src/parser/api/parse.test.ts +6 -7
- package/src/parser/block/extension/example.test.ts +2 -2
- package/src/parser/block/extension/fig.test.ts +8 -8
- package/src/parser/block/extension/figure.test.ts +14 -14
- package/src/parser/block/paragraph.test.ts +4 -0
- package/src/parser/context.ts +5 -11
- package/src/parser/inline/annotation.ts +5 -5
- package/src/parser/inline/autolink/email.ts +11 -5
- package/src/parser/inline/autolink/hashtag.ts +4 -2
- package/src/parser/inline/autolink/url.test.ts +2 -2
- package/src/parser/inline/autolink/url.ts +6 -6
- package/src/parser/inline/bracket.test.ts +1 -0
- package/src/parser/inline/code.ts +2 -2
- package/src/parser/inline/extension/index.ts +5 -5
- package/src/parser/inline/extension/label.ts +1 -1
- package/src/parser/inline/html.test.ts +4 -4
- package/src/parser/inline/html.ts +14 -27
- package/src/parser/inline/link.test.ts +17 -17
- package/src/parser/inline/link.ts +42 -15
- package/src/parser/inline/media.test.ts +45 -46
- package/src/parser/inline/media.ts +49 -35
- package/src/parser/inline/reference.ts +15 -11
- package/src/parser/inline/ruby.ts +15 -12
- package/src/parser/inline/shortmedia.test.ts +2 -2
- package/src/parser/inline/template.test.ts +2 -2
- package/src/parser/inline/template.ts +12 -10
- package/src/parser/inline.test.ts +1 -0
- package/src/parser/source/escapable.test.ts +5 -5
- package/src/parser/source/escapable.ts +2 -3
- package/src/parser/source/unescapable.test.ts +5 -5
- package/src/parser/source/unescapable.ts +2 -3
- package/src/renderer/render/media.test.ts +3 -3
|
@@ -14,7 +14,7 @@ export const url: AutolinkParser.UrlParser = lazy(() => validate(['http://', 'ht
|
|
|
14
14
|
some(unescsource, closer),
|
|
15
15
|
]), undefined, [[/^[^\x21-\x7E]/, 3]])),
|
|
16
16
|
false,
|
|
17
|
-
[3 | Backtrack.
|
|
17
|
+
[3 | Backtrack.autolink]),
|
|
18
18
|
union([
|
|
19
19
|
constraint(State.autolink, false, state(State.autolink, convert(
|
|
20
20
|
url => `{ ${url} }`,
|
|
@@ -38,15 +38,15 @@ export const lineurl: AutolinkParser.UrlParser.LineUrlParser = lazy(() => open(
|
|
|
38
38
|
]),
|
|
39
39
|
])),
|
|
40
40
|
false,
|
|
41
|
-
[3 | Backtrack.
|
|
41
|
+
[3 | Backtrack.autolink]));
|
|
42
42
|
|
|
43
43
|
const bracket: AutolinkParser.UrlParser.BracketParser = lazy(() => union([
|
|
44
44
|
surround(str('('), recursion(Recursion.terminal, some(union([bracket, unescsource]), ')')), str(')'), true,
|
|
45
|
-
undefined, () => [[], ''], [3 | Backtrack.
|
|
45
|
+
undefined, () => [[], ''], [3 | Backtrack.autolink]),
|
|
46
46
|
surround(str('['), recursion(Recursion.terminal, some(union([bracket, unescsource]), ']')), str(']'), true,
|
|
47
|
-
undefined, () => [[], ''], [3 | Backtrack.
|
|
47
|
+
undefined, () => [[], ''], [3 | Backtrack.autolink]),
|
|
48
48
|
surround(str('{'), recursion(Recursion.terminal, some(union([bracket, unescsource]), '}')), str('}'), true,
|
|
49
|
-
undefined, () => [[], ''], [3 | Backtrack.
|
|
49
|
+
undefined, () => [[], ''], [3 | Backtrack.autolink]),
|
|
50
50
|
surround(str('"'), precedence(2, recursion(Recursion.terminal, some(unescsource, '"'))), str('"'), true,
|
|
51
|
-
undefined, () => [[], ''], [3 | Backtrack.
|
|
51
|
+
undefined, () => [[], ''], [3 | Backtrack.autolink]),
|
|
52
52
|
]));
|
|
@@ -50,6 +50,7 @@ describe('Unit: parser/inline/bracket', () => {
|
|
|
50
50
|
assert.deepStrictEqual(inspect(parser('(A、B)')), [['(', 'A、B', ')'], '']);
|
|
51
51
|
assert.deepStrictEqual(inspect(parser('(<bdi>a\\\nb</bdi>)')), [['<span class="paren">(<bdi>a<br>b</bdi>)</span>'], '']);
|
|
52
52
|
assert.deepStrictEqual(inspect(parser('([% a\\\nb %])')), [['<span class="paren">(<span class="remark"><input type="checkbox"><span>[% a<br>b %]</span></span>)</span>'], '']);
|
|
53
|
+
assert.deepStrictEqual(inspect(parser('({{\\\n}})')), [['<span class="paren">(<span class="template">{{\\<br>}}</span>)</span>'], '']);
|
|
53
54
|
});
|
|
54
55
|
|
|
55
56
|
it('[', () => {
|
|
@@ -6,13 +6,13 @@ import { html } from 'typed-dom/dom';
|
|
|
6
6
|
export const code: CodeParser = validate(
|
|
7
7
|
({ source, context }) =>
|
|
8
8
|
source[0] === '`' &&
|
|
9
|
-
!getBacktrack(context, [1 | Backtrack.
|
|
9
|
+
!getBacktrack(context, [1 | Backtrack.bracket], source, source.length - 1),
|
|
10
10
|
match(
|
|
11
11
|
/^(`+)(?!`)([^\n]*?)(?:((?<!`)\1(?!`))|$|\n)/,
|
|
12
12
|
([whole, , body, closer]) => ({ source, context }) =>
|
|
13
13
|
closer
|
|
14
14
|
? [[html('code', { 'data-src': whole }, format(body))], source.slice(whole.length)]
|
|
15
|
-
: void setBacktrack(context, [2 | Backtrack.
|
|
15
|
+
: void setBacktrack(context, [2 | Backtrack.bracket], source.length),
|
|
16
16
|
true));
|
|
17
17
|
|
|
18
18
|
function format(text: string): string {
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { ExtensionParser } from '../../inline';
|
|
2
|
-
import { State, Backtrack,
|
|
2
|
+
import { State, Backtrack, Command } from '../../context';
|
|
3
3
|
import { eval } from '../../../combinator/data/parser';
|
|
4
4
|
import { union, inits, some, precedence, state, constraint, validate, surround, lazy, fmap } from '../../../combinator';
|
|
5
5
|
import { inline } from '../../inline';
|
|
@@ -19,16 +19,16 @@ export const index: IndexParser = lazy(() => constraint(State.index, false, fmap
|
|
|
19
19
|
some(inits([
|
|
20
20
|
inline,
|
|
21
21
|
signature,
|
|
22
|
-
]), ']', [['
|
|
22
|
+
]), ']', [[']', 1]])))),
|
|
23
23
|
']',
|
|
24
24
|
false,
|
|
25
|
-
([, ns], rest) =>
|
|
25
|
+
([, ns], rest, context) =>
|
|
26
|
+
context.linebreak === undefined &&
|
|
26
27
|
trimBlankNodeEnd(ns).length > 0
|
|
27
28
|
? [[html('a', { 'data-index': dataindex(ns) }, defrag(ns))], rest]
|
|
28
29
|
: undefined,
|
|
29
30
|
undefined,
|
|
30
|
-
[3 | Backtrack.
|
|
31
|
-
Backtrack.bracket | BacktrackState.nobreak)),
|
|
31
|
+
[3 | Backtrack.bracket])),
|
|
32
32
|
([el]: [HTMLAnchorElement]) => [
|
|
33
33
|
define(el,
|
|
34
34
|
{
|
|
@@ -13,7 +13,7 @@ export const segment: ExtensionParser.LabelParser.SegmentParser = clear(union([
|
|
|
13
13
|
|
|
14
14
|
export const label: ExtensionParser.LabelParser = constraint(State.label, false, fmap(
|
|
15
15
|
union([
|
|
16
|
-
surround('[', body, ']', false, undefined, undefined, [1 | Backtrack.
|
|
16
|
+
surround('[', body, ']', false, undefined, undefined, [1 | Backtrack.bracket, 1]),
|
|
17
17
|
body,
|
|
18
18
|
]),
|
|
19
19
|
([text]) => [
|
|
@@ -36,16 +36,16 @@ describe('Unit: parser/inline/html', () => {
|
|
|
36
36
|
assert.deepStrictEqual(inspect(parser('<bdi>\na</bdi>')), [['<span class="invalid"><bdi><br>a</bdi></span>'], '']);
|
|
37
37
|
assert.deepStrictEqual(inspect(parser('<bdi>\\\na</bdi>')), [['<span class="invalid"><bdi><br>a</bdi></span>'], '']);
|
|
38
38
|
assert.deepStrictEqual(inspect(parser('<bdi>a')), [['<span class="invalid"><bdi>a</span>'], '']);
|
|
39
|
-
assert.deepStrictEqual(inspect(parser('<bdi>a</
|
|
40
|
-
assert.deepStrictEqual(inspect(parser('<BDI>a</BDI>')), [['<span class="invalid"><BDI>
|
|
41
|
-
assert.deepStrictEqual(inspect(parser('<BDI>a</
|
|
39
|
+
assert.deepStrictEqual(inspect(parser('<bdi>a</BDI>')), [['<span class="invalid"><bdi>a</BDI></span>'], '']);
|
|
40
|
+
assert.deepStrictEqual(inspect(parser('<BDI>a</BDI>')), [['<span class="invalid"><BDI></span>'], 'a</BDI>']);
|
|
41
|
+
assert.deepStrictEqual(inspect(parser('<BDI>a</bdi>')), [['<span class="invalid"><BDI></span>'], 'a</bdi>']);
|
|
42
42
|
assert.deepStrictEqual(inspect(parser('</bdi>')), undefined);
|
|
43
43
|
assert.deepStrictEqual(inspect(parser('<bdi/>')), undefined);
|
|
44
44
|
assert.deepStrictEqual(inspect(parser('<b><b><b>a</b></b></b>')), [['<span class="invalid"><b><span class="invalid"><b><span class="invalid"><b>a</b></span></b></span></b></span>'], '']);
|
|
45
45
|
assert.deepStrictEqual(inspect(parser('<bdi><bdi><bdi>a</bdi></bdi></bdi>')), [['<bdi><bdi><bdi>a</bdi></bdi></bdi>'], '']);
|
|
46
46
|
assert.deepStrictEqual(inspect(parser('<x a="*b*"')), undefined);
|
|
47
47
|
assert.deepStrictEqual(inspect(parser('<x a="*b*">')), [['<span class="invalid"><x a="*b*"></span>'], '']);
|
|
48
|
-
assert.deepStrictEqual(inspect(parser('<x a="*b*">c')), [['<span class="invalid"><x a="*b*">
|
|
48
|
+
assert.deepStrictEqual(inspect(parser('<x a="*b*">c')), [['<span class="invalid"><x a="*b*"></span>'], 'c']);
|
|
49
49
|
assert.deepStrictEqual(inspect(parser('<bdi a="*b*"')), undefined);
|
|
50
50
|
assert.deepStrictEqual(inspect(parser('<bdi a="*b*">')), [['<span class="invalid"><bdi a="*b*"></span>'], '']);
|
|
51
51
|
assert.deepStrictEqual(inspect(parser('<bdi a="*b*">c')), [['<span class="invalid"><bdi a="*b*">c</span>'], '']);
|
|
@@ -6,7 +6,6 @@ import { str } from '../source';
|
|
|
6
6
|
import { isLooseNodeStart, blankWith } from '../visibility';
|
|
7
7
|
import { invalid } from '../util';
|
|
8
8
|
import { memoize } from 'spica/memoize';
|
|
9
|
-
import { Clock } from 'spica/clock';
|
|
10
9
|
import { unshift, push, splice } from 'spica/array';
|
|
11
10
|
import { html as h, defrag } from 'typed-dom/dom';
|
|
12
11
|
|
|
@@ -21,18 +20,17 @@ Object.values(attrspecs).forEach(o => Object.setPrototypeOf(o, null));
|
|
|
21
20
|
|
|
22
21
|
export const html: HTMLParser = lazy(() => validate(/^<[a-z]+(?=[^\S\n]|>)/i,
|
|
23
22
|
union([
|
|
24
|
-
focus(
|
|
25
|
-
/^<wbr[^\S\n]*>/i,
|
|
26
|
-
() => [[h('wbr')], '']),
|
|
27
23
|
surround(
|
|
28
24
|
// https://html.spec.whatwg.org/multipage/syntax.html#void-elements
|
|
29
25
|
str(/^<(?:area|base|br|col|embed|hr|img|input|link|meta|source|track|wbr)(?=[^\S\n]|>)/i),
|
|
30
26
|
some(union([attribute])),
|
|
31
27
|
str(/^[^\S\n]*>/), true,
|
|
32
28
|
([as, bs = [], cs], rest) =>
|
|
33
|
-
|
|
29
|
+
as[0].slice(1) === 'wbr' && bs.length === 0
|
|
30
|
+
? [[h(as[0].slice(1) as 'wbr')], rest]
|
|
31
|
+
: [[elem(as[0].slice(1), push(unshift(as, bs), cs), [], [])], rest],
|
|
34
32
|
undefined,
|
|
35
|
-
[3 | Backtrack.
|
|
33
|
+
[3 | Backtrack.bracket]),
|
|
36
34
|
match(
|
|
37
35
|
new RegExp(String.raw`^<(${TAGS.join('|')})(?=[^\S\n]|>)`),
|
|
38
36
|
memoize(
|
|
@@ -40,7 +38,7 @@ export const html: HTMLParser = lazy(() => validate(/^<[a-z]+(?=[^\S\n]|>)/i,
|
|
|
40
38
|
surround<HTMLParser.TagParser, string>(
|
|
41
39
|
surround(
|
|
42
40
|
str(`<${tag}`), some(attribute), str(/^[^\S\n]*>/), true,
|
|
43
|
-
undefined, undefined, [3 | Backtrack.
|
|
41
|
+
undefined, undefined, [3 | Backtrack.bracket]),
|
|
44
42
|
precedence(3, recursion(Recursion.inline,
|
|
45
43
|
subsequence([
|
|
46
44
|
focus(/^[^\S\n]*\n/, some(inline)),
|
|
@@ -53,26 +51,15 @@ export const html: HTMLParser = lazy(() => validate(/^<[a-z]+(?=[^\S\n]|>)/i,
|
|
|
53
51
|
[[elem(tag, as, bs, [])], rest]),
|
|
54
52
|
([, tag]) => tag,
|
|
55
53
|
new Map())),
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
([
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
subsequence([
|
|
66
|
-
focus(/^[^\S\n]*\n/, some(inline)),
|
|
67
|
-
some(inline, `</${tag}>`, [[`</${tag}>`, 3]]),
|
|
68
|
-
]))),
|
|
69
|
-
str(`</${tag}>`), true,
|
|
70
|
-
([as, bs = [], cs], rest) =>
|
|
71
|
-
[[elem(tag, as, bs, cs)], rest],
|
|
72
|
-
([as, bs = []], rest) =>
|
|
73
|
-
[[elem(tag, as, bs, [])], rest]),
|
|
74
|
-
([, tag]) => tag,
|
|
75
|
-
new Clock(10000))),
|
|
54
|
+
surround(
|
|
55
|
+
// https://html.spec.whatwg.org/multipage/syntax.html#void-elements
|
|
56
|
+
str(/^<[a-z]+(?=[^\S\n]|>)/i),
|
|
57
|
+
some(union([attribute])),
|
|
58
|
+
str(/^[^\S\n]*>/), true,
|
|
59
|
+
([as, bs = [], cs], rest) =>
|
|
60
|
+
[[elem(as[0].slice(1), push(unshift(as, bs), cs), [], [])], rest],
|
|
61
|
+
undefined,
|
|
62
|
+
[3 | Backtrack.bracket]),
|
|
76
63
|
])));
|
|
77
64
|
|
|
78
65
|
export const attribute: HTMLParser.AttributeParser = union([
|
|
@@ -42,16 +42,16 @@ describe('Unit: parser/inline/link', () => {
|
|
|
42
42
|
assert.deepStrictEqual(inspect(parser('[-1234567890]{tel:1234567890}')), [['<a class="invalid">-1234567890</a>'], '']);
|
|
43
43
|
assert.deepStrictEqual(inspect(parser('[123456789a]{tel:1234567890}')), [['<a class="invalid">123456789a</a>'], '']);
|
|
44
44
|
assert.deepStrictEqual(inspect(parser('[1234567890]{tel:ttel:1234567890}')), [['<a class="invalid">1234567890</a>'], '']);
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
45
|
+
assert.deepStrictEqual(inspect(parser('[#a]{b}')), [['<a class="link" href="b">#a</a>'], '']);
|
|
46
|
+
assert.deepStrictEqual(inspect(parser('[\\#a]{b}')), [['<a class="link" href="b">#a</a>'], '']);
|
|
47
|
+
assert.deepStrictEqual(inspect(parser('[c #a]{b}')), [['<a class="link" href="b">c #a</a>'], '']);
|
|
48
|
+
assert.deepStrictEqual(inspect(parser('[c \\#a]{b}')), [['<a class="link" href="b">c #a</a>'], '']);
|
|
49
|
+
assert.deepStrictEqual(inspect(parser('[]{#a}')), [['<a class="url" href="#a">#a</a>'], '']);
|
|
50
|
+
assert.deepStrictEqual(inspect(parser('[@a]{b}')), [['<a class="link" href="b">@a</a>'], '']);
|
|
51
|
+
assert.deepStrictEqual(inspect(parser('[\\@a]{b}')), [['<a class="link" href="b">@a</a>'], '']);
|
|
52
|
+
assert.deepStrictEqual(inspect(parser('[c @a]{b}')), [['<a class="link" href="b">c @a</a>'], '']);
|
|
53
|
+
assert.deepStrictEqual(inspect(parser('[c \\@a]{b}')), [['<a class="link" href="b">c @a</a>'], '']);
|
|
54
|
+
assert.deepStrictEqual(inspect(parser('[]{@a}')), [['<a class="url" href="@a">@a</a>'], '']);
|
|
55
55
|
});
|
|
56
56
|
|
|
57
57
|
it('invalid', () => {
|
|
@@ -88,8 +88,8 @@ describe('Unit: parser/inline/link', () => {
|
|
|
88
88
|
assert.deepStrictEqual(inspect(parser('[*a\nb*]{/}')), undefined);
|
|
89
89
|
assert.deepStrictEqual(inspect(parser('[http://host]{http://host}')), [['<a class="invalid">http://host</a>'], '']);
|
|
90
90
|
assert.deepStrictEqual(inspect(parser('[]{ttp://host}')), [['<a class="invalid">ttp://host</a>'], '']);
|
|
91
|
-
|
|
92
|
-
|
|
91
|
+
assert.deepStrictEqual(inspect(parser('[]{http://[::ffff:0:0%1]}')), [['<a class="invalid">http://[::ffff:0:0%1]</a>'], '']);
|
|
92
|
+
assert.deepStrictEqual(inspect(parser('[]{http://[::ffff:0:0/96]}')), [['<a class="invalid">http://[::ffff:0:0/96]</a>'], '']);
|
|
93
93
|
assert.deepStrictEqual(inspect(parser('[]{^/.}')), [[`<a class="invalid">^/.</a>`], '']);
|
|
94
94
|
assert.deepStrictEqual(inspect(parser('[]{^/..}')), [[`<a class="invalid">^/..</a>`], '']);
|
|
95
95
|
assert.deepStrictEqual(inspect(parser('[]{^/../}')), [[`<a class="invalid">^/../</a>`], '']);
|
|
@@ -160,12 +160,12 @@ describe('Unit: parser/inline/link', () => {
|
|
|
160
160
|
});
|
|
161
161
|
|
|
162
162
|
it('media', () => {
|
|
163
|
-
assert.deepStrictEqual(inspect(parser('[![]{a}]{a}')), [['<a class="link" href="a" target="_blank"><img class="media" data-src="a" alt=""></a>'], '']);
|
|
164
|
-
assert.deepStrictEqual(inspect(parser('[![]{a}]{b}')), [['<a class="link" href="b" target="_blank"><img class="media" data-src="a" alt=""></a>'], '']);
|
|
163
|
+
assert.deepStrictEqual(inspect(parser('[![]{a}]{a}')), [['<a class="link" href="a" target="_blank"><img class="media" data-src="a" alt="a"></a>'], '']);
|
|
164
|
+
assert.deepStrictEqual(inspect(parser('[![]{a}]{b}')), [['<a class="link" href="b" target="_blank"><img class="media" data-src="a" alt="a"></a>'], '']);
|
|
165
165
|
assert.deepStrictEqual(inspect(parser('[![]{a} ]{b}')), [['<a class="link" href="b">![]{a}</a>'], '']);
|
|
166
166
|
assert.deepStrictEqual(inspect(parser('[![]{a}![]{a}]{b}')), [['<a class="link" href="b">![]{a}![]{a}</a>'], '']);
|
|
167
167
|
assert.deepStrictEqual(inspect(parser('[[![]{a}]{b}]{c}')), [['<a class="link" href="c">[![]{a}]{b}</a>'], '']);
|
|
168
|
-
assert.deepStrictEqual(inspect(parser('[!http://host]{b}')), [['<a class="link" href="b" target="_blank"><img class="media" data-src="http://host" alt=""></a>'], '']);
|
|
168
|
+
assert.deepStrictEqual(inspect(parser('[!http://host]{b}')), [['<a class="link" href="b" target="_blank"><img class="media" data-src="http://host" alt="http://host"></a>'], '']);
|
|
169
169
|
});
|
|
170
170
|
|
|
171
171
|
it('nest', () => {
|
|
@@ -179,7 +179,7 @@ describe('Unit: parser/inline/link', () => {
|
|
|
179
179
|
assert.deepStrictEqual(inspect(parser('[[![]{a}]{b}]{b}')), [['<a class="link" href="b">[![]{a}]{b}</a>'], '']);
|
|
180
180
|
assert.deepStrictEqual(inspect(parser('[((a))]{b}')), [['<a class="link" href="b"><span class="paren">((a))</span></a>'], '']);
|
|
181
181
|
assert.deepStrictEqual(inspect(parser('[[[a]]]{b}')), [['<a class="link" href="b">[[a]]</a>'], '']);
|
|
182
|
-
assert.deepStrictEqual(inspect(parser('[!http://host]{/}')), [['<a class="link" href="/" target="_blank"><img class="media" data-src="http://host" alt=""></a>'], '']);
|
|
182
|
+
assert.deepStrictEqual(inspect(parser('[!http://host]{/}')), [['<a class="link" href="/" target="_blank"><img class="media" data-src="http://host" alt="http://host"></a>'], '']);
|
|
183
183
|
assert.deepStrictEqual(inspect(parser('[#a]{b}')), [['<a class="link" href="b">#a</a>'], '']);
|
|
184
184
|
assert.deepStrictEqual(inspect(parser('[@a]{b}')), [['<a class="link" href="b">@a</a>'], '']);
|
|
185
185
|
assert.deepStrictEqual(inspect(parser('[@a@b]{c}')), [['<a class="link" href="c">@a@b</a>'], '']);
|
|
@@ -222,7 +222,7 @@ describe('Unit: parser/inline/link', () => {
|
|
|
222
222
|
assert.deepStrictEqual(inspect(parser('[]{ / nofollow}')), [['<a class="url" href="/" rel="nofollow">/</a>'], '']);
|
|
223
223
|
assert.deepStrictEqual(inspect(parser('[]{ / nofollow }')), [['<a class="url" href="/" rel="nofollow">/</a>'], '']);
|
|
224
224
|
assert.deepStrictEqual(inspect(parser('[]{http://host nofollow}')), [['<a class="url" href="http://host" target="_blank" rel="nofollow">http://host</a>'], '']);
|
|
225
|
-
assert.deepStrictEqual(inspect(parser('[!http://host]{http://host nofollow}')), [['<a class="link" href="http://host" target="_blank" rel="nofollow"><img class="media" data-src="http://host" alt=""></a>'], '']);
|
|
225
|
+
assert.deepStrictEqual(inspect(parser('[!http://host]{http://host nofollow}')), [['<a class="link" href="http://host" target="_blank" rel="nofollow"><img class="media" data-src="http://host" alt="http://host"></a>'], '']);
|
|
226
226
|
});
|
|
227
227
|
|
|
228
228
|
});
|
|
@@ -1,13 +1,14 @@
|
|
|
1
1
|
import { MarkdownParser } from '../../../markdown';
|
|
2
2
|
import { LinkParser } from '../inline';
|
|
3
|
-
import { State, Backtrack,
|
|
4
|
-
import { union, inits, tails, sequence, some, creation, precedence, state, constraint, validate, surround, open, dup, reverse, lazy, fmap, bind } from '../../combinator';
|
|
3
|
+
import { State, Backtrack, Command } from '../context';
|
|
4
|
+
import { union, inits, tails, sequence, subsequence, some, creation, precedence, state, constraint, validate, surround, open, setBacktrack, dup, reverse, lazy, fmap, bind } from '../../combinator';
|
|
5
5
|
import { inline, media, shortmedia } from '../inline';
|
|
6
6
|
import { attributes } from './html';
|
|
7
7
|
import { linebreak, unescsource, str } from '../source';
|
|
8
8
|
import { trimBlankStart, trimBlankNodeEnd } from '../visibility';
|
|
9
9
|
import { invalid, stringify } from '../util';
|
|
10
10
|
import { ReadonlyURL } from 'spica/url';
|
|
11
|
+
import { push } from 'spica/array';
|
|
11
12
|
import { html, define, defrag } from 'typed-dom/dom';
|
|
12
13
|
|
|
13
14
|
const optspec = {
|
|
@@ -17,22 +18,36 @@ Object.setPrototypeOf(optspec, null);
|
|
|
17
18
|
|
|
18
19
|
export const textlink: LinkParser.TextLinkParser = lazy(() => constraint(State.link, false, creation(10,
|
|
19
20
|
precedence(1, state(State.linkers | State.media,
|
|
20
|
-
bind(
|
|
21
|
+
bind(subsequence([
|
|
21
22
|
dup(surround(
|
|
22
23
|
'[',
|
|
23
|
-
trimBlankStart(some(union([inline]), ']', [['
|
|
24
|
+
trimBlankStart(some(union([inline]), ']', [[']', 1]])),
|
|
24
25
|
']',
|
|
25
|
-
true,
|
|
26
|
-
[
|
|
27
|
-
|
|
26
|
+
true,
|
|
27
|
+
([, ns = []], rest, context) =>
|
|
28
|
+
context.linebreak === undefined
|
|
29
|
+
? [push(ns, [Command.Escape]), rest]
|
|
30
|
+
: undefined,
|
|
31
|
+
undefined,
|
|
32
|
+
[3 | Backtrack.link, 3 | Backtrack.bracket])),
|
|
28
33
|
dup(surround(
|
|
29
34
|
/^{(?![{}])/,
|
|
30
35
|
inits([uri, some(option)]),
|
|
31
36
|
/^[^\S\n]*}/,
|
|
32
37
|
false, undefined, undefined,
|
|
33
38
|
[3 | Backtrack.link])),
|
|
34
|
-
])
|
|
35
|
-
([
|
|
39
|
+
]),
|
|
40
|
+
([content, params]: [(HTMLElement | string)[], string[]], rest, context) => {
|
|
41
|
+
if (content.at(-1) === Command.Escape) {
|
|
42
|
+
content.pop();
|
|
43
|
+
if (params === undefined) {
|
|
44
|
+
return void setBacktrack(context, [2 | Backtrack.link], context.recent!.reduce((a, b) => a + b.length, 0));
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
else {
|
|
48
|
+
params = content as string[];
|
|
49
|
+
content = [];
|
|
50
|
+
}
|
|
36
51
|
assert(!html('div', content).querySelector('a, .media, .annotation, .reference'));
|
|
37
52
|
assert(content[0] !== '');
|
|
38
53
|
if (content.length !== 0 && trimBlankNodeEnd(content).length === 0) return;
|
|
@@ -89,9 +104,14 @@ function parse(
|
|
|
89
104
|
const INSECURE_URI = params.shift()!;
|
|
90
105
|
assert(INSECURE_URI === INSECURE_URI.trim());
|
|
91
106
|
assert(!INSECURE_URI.match(/\s/));
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
107
|
+
let uri: ReadonlyURL | undefined;
|
|
108
|
+
try{
|
|
109
|
+
uri = new ReadonlyURL(
|
|
110
|
+
resolve(INSECURE_URI, context.host ?? location, context.url ?? context.host ?? location),
|
|
111
|
+
context.host?.href || location.href);
|
|
112
|
+
}
|
|
113
|
+
catch {
|
|
114
|
+
}
|
|
95
115
|
const el = elem(
|
|
96
116
|
INSECURE_URI,
|
|
97
117
|
content,
|
|
@@ -105,12 +125,16 @@ function parse(
|
|
|
105
125
|
function elem(
|
|
106
126
|
INSECURE_URI: string,
|
|
107
127
|
content: readonly (string | HTMLElement)[],
|
|
108
|
-
uri: ReadonlyURL,
|
|
128
|
+
uri: ReadonlyURL | undefined,
|
|
109
129
|
origin: string,
|
|
110
130
|
): HTMLAnchorElement {
|
|
111
131
|
let type: string;
|
|
112
132
|
let message: string;
|
|
113
|
-
switch (uri
|
|
133
|
+
switch (uri?.protocol) {
|
|
134
|
+
case undefined:
|
|
135
|
+
type = 'argument';
|
|
136
|
+
message = 'Invalid URI';
|
|
137
|
+
break;
|
|
114
138
|
case 'http:':
|
|
115
139
|
case 'https:':
|
|
116
140
|
assert(uri.host);
|
|
@@ -165,11 +189,14 @@ function elem(
|
|
|
165
189
|
message = 'Invalid content';
|
|
166
190
|
}
|
|
167
191
|
break;
|
|
192
|
+
default:
|
|
193
|
+
type = 'argument';
|
|
194
|
+
message = 'Invalid protocol';
|
|
168
195
|
}
|
|
169
196
|
return html('a',
|
|
170
197
|
{
|
|
171
198
|
class: 'invalid',
|
|
172
|
-
...invalid('link', type
|
|
199
|
+
...invalid('link', type, message),
|
|
173
200
|
},
|
|
174
201
|
content.length === 0
|
|
175
202
|
? INSECURE_URI
|
|
@@ -7,13 +7,12 @@ describe('Unit: parser/inline/media', () => {
|
|
|
7
7
|
const parser = (source: string) => some(media)({ source, context: {} });
|
|
8
8
|
|
|
9
9
|
it('xss', () => {
|
|
10
|
-
assert.deepStrictEqual(inspect(parser('![]{javascript:alert}')), [['<img class="invalid"
|
|
11
|
-
assert.deepStrictEqual(inspect(parser('![]{vbscript:alert}')), [['<img class="invalid"
|
|
12
|
-
assert.deepStrictEqual(inspect(parser('![]{data:text/html;base64,PHNjcmlwdD5hbGVydCgnWFNTJyk8L3NjcmlwdD4K}')), [['<img class="invalid"
|
|
13
|
-
assert.deepStrictEqual(inspect(parser('![]{any:alert}')), [['<img class="invalid"
|
|
14
|
-
assert.deepStrictEqual(inspect(parser('![]{"}')), [['<a href=""" target="_blank"><img class="media" data-src=""" alt=""></a>'], '']);
|
|
15
|
-
assert.deepStrictEqual(inspect(parser('![]{\\}')), [['<a href="\\" target="_blank"><img class="media" data-src="\\" alt=""></a>'], '']);
|
|
16
|
-
assert.deepStrictEqual(inspect(parser('![\\"]{/}')), [['<a href="/" target="_blank"><img class="media" data-src="/" alt="""></a>'], '']);
|
|
10
|
+
assert.deepStrictEqual(inspect(parser('![]{javascript:alert}')), [['<img class="invalid" alt="javascript:alert">'], '']);
|
|
11
|
+
assert.deepStrictEqual(inspect(parser('![]{vbscript:alert}')), [['<img class="invalid" alt="vbscript:alert">'], '']);
|
|
12
|
+
assert.deepStrictEqual(inspect(parser('![]{data:text/html;base64,PHNjcmlwdD5hbGVydCgnWFNTJyk8L3NjcmlwdD4K}')), [['<img class="invalid" alt="data:text/html;base64,PHNjcmlwdD5hbGVydCgnWFNTJyk8L3NjcmlwdD4K">'], '']);
|
|
13
|
+
assert.deepStrictEqual(inspect(parser('![]{any:alert}')), [['<img class="invalid" alt="any:alert">'], '']);
|
|
14
|
+
assert.deepStrictEqual(inspect(parser('![]{"}')), [['<a href=""" target="_blank"><img class="media" data-src=""" alt="""></a>'], '']);
|
|
15
|
+
assert.deepStrictEqual(inspect(parser('![]{\\}')), [['<a href="\\" target="_blank"><img class="media" data-src="\\" alt="\\"></a>'], '']);
|
|
17
16
|
assert.deepStrictEqual(inspect(parser('![\\"]{/}')), [['<a href="/" target="_blank"><img class="media" data-src="/" alt="""></a>'], '']);
|
|
18
17
|
});
|
|
19
18
|
|
|
@@ -44,41 +43,41 @@ describe('Unit: parser/inline/media', () => {
|
|
|
44
43
|
assert.deepStrictEqual(inspect(parser('![\\ ]{b}')), undefined);
|
|
45
44
|
assert.deepStrictEqual(inspect(parser('![\\\n]{b}')), undefined);
|
|
46
45
|
assert.deepStrictEqual(inspect(parser('![	]{b}')), undefined);
|
|
47
|
-
assert.deepStrictEqual(inspect(parser('![&a;]{b}')), [['<img class="invalid"
|
|
46
|
+
assert.deepStrictEqual(inspect(parser('![&a;]{b}')), [['<img class="invalid" alt="&a;">'], '']);
|
|
48
47
|
assert.deepStrictEqual(inspect(parser('![[]{b}')), undefined);
|
|
49
48
|
assert.deepStrictEqual(inspect(parser('![]]{b}')), undefined);
|
|
50
49
|
assert.deepStrictEqual(inspect(parser('![a]{}')), undefined);
|
|
51
50
|
assert.deepStrictEqual(inspect(parser('![a\nb]{b}')), undefined);
|
|
52
51
|
assert.deepStrictEqual(inspect(parser('![a\\\nb]{b}')), undefined);
|
|
53
|
-
assert.deepStrictEqual(inspect(parser('![]{ttp://host}')), [['<img class="invalid"
|
|
54
|
-
assert.deepStrictEqual(inspect(parser('![]{tel:1234567890}')), [['<img class="invalid"
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
assert.deepStrictEqual(inspect(parser('![]{.}')), [['<img class="invalid"
|
|
58
|
-
assert.deepStrictEqual(inspect(parser('![]{..}')), [['<img class="invalid"
|
|
59
|
-
assert.deepStrictEqual(inspect(parser('![]{../}')), [['<img class="invalid"
|
|
60
|
-
assert.deepStrictEqual(inspect(parser('![]{/../b}')), [['<img class="invalid"
|
|
52
|
+
assert.deepStrictEqual(inspect(parser('![]{ttp://host}')), [['<img class="invalid" alt="ttp://host">'], '']);
|
|
53
|
+
assert.deepStrictEqual(inspect(parser('![]{tel:1234567890}')), [['<img class="invalid" alt="tel:1234567890">'], '']);
|
|
54
|
+
assert.deepStrictEqual(inspect(parser('![]{http://[::ffff:0:0%1]}')), [['<img class="invalid" alt="http://[::ffff:0:0%1]">'], '']);
|
|
55
|
+
assert.deepStrictEqual(inspect(parser('![]{http://[::ffff:0:0/96]}')), [['<img class="invalid" alt="http://[::ffff:0:0/96]">'], '']);
|
|
56
|
+
assert.deepStrictEqual(inspect(parser('![]{.}')), [['<img class="invalid" alt=".">'], '']);
|
|
57
|
+
assert.deepStrictEqual(inspect(parser('![]{..}')), [['<img class="invalid" alt="..">'], '']);
|
|
58
|
+
assert.deepStrictEqual(inspect(parser('![]{../}')), [['<img class="invalid" alt="../">'], '']);
|
|
59
|
+
assert.deepStrictEqual(inspect(parser('![]{/../b}')), [['<img class="invalid" alt="/../b">'], '']);
|
|
61
60
|
assert.deepStrictEqual(inspect(parser(' ![]{b}')), undefined);
|
|
62
61
|
assert.deepStrictEqual(inspect(parser('[]{/}')), undefined);
|
|
63
62
|
});
|
|
64
63
|
|
|
65
64
|
it('basic', () => {
|
|
66
|
-
assert.deepStrictEqual(inspect(parser('![]{b}')), [['<a href="b" target="_blank"><img class="media" data-src="b" alt=""></a>'], '']);
|
|
67
|
-
assert.deepStrictEqual(inspect(parser('![]{b }')), [['<a href="b" target="_blank"><img class="media" data-src="b" alt=""></a>'], '']);
|
|
68
|
-
assert.deepStrictEqual(inspect(parser('![]{b }')), [['<a href="b" target="_blank"><img class="media" data-src="b" alt=""></a>'], '']);
|
|
69
|
-
assert.deepStrictEqual(inspect(parser('![]{ b }')), [['<a href="b" target="_blank"><img class="media" data-src="b" alt=""></a>'], '']);
|
|
70
|
-
assert.deepStrictEqual(inspect(parser('![]{ b }')), [['<a href="b" target="_blank"><img class="media" data-src="b" alt=""></a>'], '']);
|
|
71
|
-
assert.deepStrictEqual(inspect(parser('![]{ b }')), [['<a href="b" target="_blank"><img class="media" data-src="b" alt=""></a>'], '']);
|
|
72
|
-
assert.deepStrictEqual(inspect(parser('![]{ b }')), [['<a href="b" target="_blank"><img class="media" data-src="b" alt=""></a>'], '']);
|
|
73
|
-
assert.deepStrictEqual(inspect(parser('![]{ b }')), [['<a href="b" target="_blank"><img class="media" data-src="b" alt=""></a>'], '']);
|
|
74
|
-
assert.deepStrictEqual(inspect(parser('![]{"}')), [['<a href=""" target="_blank"><img class="media" data-src=""" alt=""></a>'], '']);
|
|
75
|
-
assert.deepStrictEqual(inspect(parser('![]{"}"}')), [['<a href=""" target="_blank"><img class="media" data-src=""" alt=""></a>'], '"}']);
|
|
76
|
-
assert.deepStrictEqual(inspect(parser('![]{\\}')), [['<a href="\\" target="_blank"><img class="media" data-src="\\" alt=""></a>'], '']);
|
|
77
|
-
assert.deepStrictEqual(inspect(parser('![]{\\ }')), [['<a href="\\" target="_blank"><img class="media" data-src="\\" alt=""></a>'], '']);
|
|
78
|
-
assert.deepStrictEqual(inspect(parser('![]{\\b}')), [['<a href="\\b" target="_blank"><img class="media" data-src="\\b" alt=""></a>'], '']);
|
|
79
|
-
assert.deepStrictEqual(inspect(parser('![]{?/../}')), [[`<a href="?/../" target="_blank"><img class="media" data-src="?/../" alt=""></a>`], '']);
|
|
80
|
-
assert.deepStrictEqual(inspect(parser('![]{#/../}')), [[`<a href="#/../" target="_blank"><img class="media" data-src="#/../" alt=""></a>`], '']);
|
|
81
|
-
assert.deepStrictEqual(inspect(parser('![]{^/b}')), [[`<a href="/b" target="_blank"><img class="media" data-src="/b" alt=""></a>`], '']);
|
|
65
|
+
assert.deepStrictEqual(inspect(parser('![]{b}')), [['<a href="b" target="_blank"><img class="media" data-src="b" alt="b"></a>'], '']);
|
|
66
|
+
assert.deepStrictEqual(inspect(parser('![]{b }')), [['<a href="b" target="_blank"><img class="media" data-src="b" alt="b"></a>'], '']);
|
|
67
|
+
assert.deepStrictEqual(inspect(parser('![]{b }')), [['<a href="b" target="_blank"><img class="media" data-src="b" alt="b"></a>'], '']);
|
|
68
|
+
assert.deepStrictEqual(inspect(parser('![]{ b }')), [['<a href="b" target="_blank"><img class="media" data-src="b" alt="b"></a>'], '']);
|
|
69
|
+
assert.deepStrictEqual(inspect(parser('![]{ b }')), [['<a href="b" target="_blank"><img class="media" data-src="b" alt="b"></a>'], '']);
|
|
70
|
+
assert.deepStrictEqual(inspect(parser('![]{ b }')), [['<a href="b" target="_blank"><img class="media" data-src="b" alt="b"></a>'], '']);
|
|
71
|
+
assert.deepStrictEqual(inspect(parser('![]{ b }')), [['<a href="b" target="_blank"><img class="media" data-src="b" alt="b"></a>'], '']);
|
|
72
|
+
assert.deepStrictEqual(inspect(parser('![]{ b }')), [['<a href="b" target="_blank"><img class="media" data-src="b" alt="b"></a>'], '']);
|
|
73
|
+
assert.deepStrictEqual(inspect(parser('![]{"}')), [['<a href=""" target="_blank"><img class="media" data-src=""" alt="""></a>'], '']);
|
|
74
|
+
assert.deepStrictEqual(inspect(parser('![]{"}"}')), [['<a href=""" target="_blank"><img class="media" data-src=""" alt="""></a>'], '"}']);
|
|
75
|
+
assert.deepStrictEqual(inspect(parser('![]{\\}')), [['<a href="\\" target="_blank"><img class="media" data-src="\\" alt="\\"></a>'], '']);
|
|
76
|
+
assert.deepStrictEqual(inspect(parser('![]{\\ }')), [['<a href="\\" target="_blank"><img class="media" data-src="\\" alt="\\"></a>'], '']);
|
|
77
|
+
assert.deepStrictEqual(inspect(parser('![]{\\b}')), [['<a href="\\b" target="_blank"><img class="media" data-src="\\b" alt="\\b"></a>'], '']);
|
|
78
|
+
assert.deepStrictEqual(inspect(parser('![]{?/../}')), [[`<a href="?/../" target="_blank"><img class="media" data-src="?/../" alt="?/../"></a>`], '']);
|
|
79
|
+
assert.deepStrictEqual(inspect(parser('![]{#/../}')), [[`<a href="#/../" target="_blank"><img class="media" data-src="#/../" alt="#/../"></a>`], '']);
|
|
80
|
+
assert.deepStrictEqual(inspect(parser('![]{^/b}')), [[`<a href="/b" target="_blank"><img class="media" data-src="/b" alt="^/b"></a>`], '']);
|
|
82
81
|
assert.deepStrictEqual(inspect(parser('![ a]{b}')), [['<a href="b" target="_blank"><img class="media" data-src="b" alt="a"></a>'], '']);
|
|
83
82
|
assert.deepStrictEqual(inspect(parser('![ a ]{b}')), [['<a href="b" target="_blank"><img class="media" data-src="b" alt="a"></a>'], '']);
|
|
84
83
|
assert.deepStrictEqual(inspect(parser('![a ]{b}')), [['<a href="b" target="_blank"><img class="media" data-src="b" alt="a"></a>'], '']);
|
|
@@ -86,9 +85,9 @@ describe('Unit: parser/inline/media', () => {
|
|
|
86
85
|
assert.deepStrictEqual(inspect(parser('![a b]{c}')), [['<a href="c" target="_blank"><img class="media" data-src="c" alt="a b"></a>'], '']);
|
|
87
86
|
assert.deepStrictEqual(inspect(parser('![©]{b}')), [['<a href="b" target="_blank"><img class="media" data-src="b" alt="©"></a>'], '']);
|
|
88
87
|
assert.deepStrictEqual(inspect(parser('![&copy;]{b}')), [['<a href="b" target="_blank"><img class="media" data-src="b" alt="&copy;"></a>'], '']);
|
|
89
|
-
assert.deepStrictEqual(inspect(parser('!{b}')), [['<a href="b" target="_blank"><img class="media" data-src="b" alt=""></a>'], '']);
|
|
90
|
-
assert.deepStrictEqual(inspect(parser('!{ ][ }')), [['<a href="][" target="_blank"><img class="media" data-src="][" alt=""></a>'], '']);
|
|
91
|
-
assert.deepStrictEqual(inspect(parser('!{ }{ }')), [['<a href="}{" target="_blank"><img class="media" data-src="}{" alt=""></a>'], '']);
|
|
88
|
+
assert.deepStrictEqual(inspect(parser('!{b}')), [['<a href="b" target="_blank"><img class="media" data-src="b" alt="b"></a>'], '']);
|
|
89
|
+
assert.deepStrictEqual(inspect(parser('!{ ][ }')), [['<a href="][" target="_blank"><img class="media" data-src="][" alt="]["></a>'], '']);
|
|
90
|
+
assert.deepStrictEqual(inspect(parser('!{ }{ }')), [['<a href="}{" target="_blank"><img class="media" data-src="}{" alt="}{"></a>'], '']);
|
|
92
91
|
});
|
|
93
92
|
|
|
94
93
|
it('nest', () => {
|
|
@@ -99,20 +98,20 @@ describe('Unit: parser/inline/media', () => {
|
|
|
99
98
|
});
|
|
100
99
|
|
|
101
100
|
it('external', () => {
|
|
102
|
-
assert.deepStrictEqual(inspect(parser('![]{//host}')), [['<a href="//host" target="_blank"><img class="media" data-src="//host" alt=""></a>'], '']);
|
|
103
|
-
assert.deepStrictEqual(inspect(parser('![]{//[::]}')), [['<a href="//[::]" target="_blank"><img class="media" data-src="//[::]" alt=""></a>'], '']);
|
|
101
|
+
assert.deepStrictEqual(inspect(parser('![]{//host}')), [['<a href="//host" target="_blank"><img class="media" data-src="//host" alt="//host"></a>'], '']);
|
|
102
|
+
assert.deepStrictEqual(inspect(parser('![]{//[::]}')), [['<a href="//[::]" target="_blank"><img class="media" data-src="//[::]" alt="//[::]"></a>'], '']);
|
|
104
103
|
});
|
|
105
104
|
|
|
106
105
|
it('attribute', () => {
|
|
107
|
-
assert.deepStrictEqual(inspect(parser('![]{/ __proto__}')), [['<a href="/" target="_blank"><img class="media invalid" data-src="/" alt=""></a>'], '']);
|
|
108
|
-
assert.deepStrictEqual(inspect(parser('![]{/ constructor}')), [['<a href="/" target="_blank"><img class="media invalid" data-src="/" alt=""></a>'], '']);
|
|
109
|
-
assert.deepStrictEqual(inspect(parser('![]{/ aspect-ratio}')), [['<a href="/" target="_blank"><img class="media invalid" data-src="/" alt=""></a>'], '']);
|
|
110
|
-
assert.deepStrictEqual(inspect(parser('![]{/ nofollow}')), [['<a href="/" rel="nofollow" target="_blank"><img class="media" data-src="/" alt=""></a>'], '']);
|
|
111
|
-
assert.deepStrictEqual(inspect(parser('![]{/ width="4" height="3"}')), [['<a href="/" target="_blank"><img class="media" data-src="/" alt="" width="4" height="3"></a>'], '']);
|
|
112
|
-
assert.deepStrictEqual(inspect(parser('![]{/ 4x3}')), [['<a href="/" target="_blank"><img class="media" data-src="/" alt="" width="4" height="3"></a>'], '']);
|
|
113
|
-
assert.deepStrictEqual(inspect(parser('![]{/ aspect-ratio="4/3"}')), [['<a href="/" target="_blank"><img class="media" data-src="/" alt="" aspect-ratio="4/3" style="aspect-ratio: 4 / 3;"></a>'], '']);
|
|
114
|
-
assert.deepStrictEqual(inspect(parser('![]{/ aspect-ratio="4/3" nofollow}')), [['<a href="/" rel="nofollow" target="_blank"><img class="media" data-src="/" alt="" aspect-ratio="4/3" style="aspect-ratio: 4 / 3;"></a>'], '']);
|
|
115
|
-
assert.deepStrictEqual(inspect(parser('![]{/ 4:3}')), [['<a href="/" target="_blank"><img class="media" data-src="/" alt="" aspect-ratio="4/3" style="aspect-ratio: 4 / 3;"></a>'], '']);
|
|
106
|
+
assert.deepStrictEqual(inspect(parser('![]{/ __proto__}')), [['<a href="/" target="_blank"><img class="media invalid" data-src="/" alt="/"></a>'], '']);
|
|
107
|
+
assert.deepStrictEqual(inspect(parser('![]{/ constructor}')), [['<a href="/" target="_blank"><img class="media invalid" data-src="/" alt="/"></a>'], '']);
|
|
108
|
+
assert.deepStrictEqual(inspect(parser('![]{/ aspect-ratio}')), [['<a href="/" target="_blank"><img class="media invalid" data-src="/" alt="/"></a>'], '']);
|
|
109
|
+
assert.deepStrictEqual(inspect(parser('![]{/ nofollow}')), [['<a href="/" rel="nofollow" target="_blank"><img class="media" data-src="/" alt="/"></a>'], '']);
|
|
110
|
+
assert.deepStrictEqual(inspect(parser('![]{/ width="4" height="3"}')), [['<a href="/" target="_blank"><img class="media" data-src="/" alt="/" width="4" height="3"></a>'], '']);
|
|
111
|
+
assert.deepStrictEqual(inspect(parser('![]{/ 4x3}')), [['<a href="/" target="_blank"><img class="media" data-src="/" alt="/" width="4" height="3"></a>'], '']);
|
|
112
|
+
assert.deepStrictEqual(inspect(parser('![]{/ aspect-ratio="4/3"}')), [['<a href="/" target="_blank"><img class="media" data-src="/" alt="/" aspect-ratio="4/3" style="aspect-ratio: 4 / 3;"></a>'], '']);
|
|
113
|
+
assert.deepStrictEqual(inspect(parser('![]{/ aspect-ratio="4/3" nofollow}')), [['<a href="/" rel="nofollow" target="_blank"><img class="media" data-src="/" alt="/" aspect-ratio="4/3" style="aspect-ratio: 4 / 3;"></a>'], '']);
|
|
114
|
+
assert.deepStrictEqual(inspect(parser('![]{/ 4:3}')), [['<a href="/" target="_blank"><img class="media" data-src="/" alt="/" aspect-ratio="4/3" style="aspect-ratio: 4 / 3;"></a>'], '']);
|
|
116
115
|
});
|
|
117
116
|
|
|
118
117
|
});
|