securemark 0.294.3 → 0.294.5
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/dist/index.js +164 -144
- package/markdown.d.ts +3 -12
- package/package.json +3 -3
- package/src/combinator/control/manipulation/fence.ts +2 -0
- package/src/combinator/control/manipulation/indent.ts +1 -1
- package/src/combinator/control/manipulation/match.ts +11 -8
- package/src/parser/api/parse.test.ts +3 -3
- package/src/parser/block/blockquote.test.ts +3 -9
- package/src/parser/block/blockquote.ts +4 -4
- package/src/parser/block/dlist.ts +4 -4
- package/src/parser/block/extension/example.ts +1 -3
- package/src/parser/block/extension/fig.test.ts +0 -1
- package/src/parser/block/extension/fig.ts +6 -6
- package/src/parser/block/extension/figbase.ts +1 -1
- package/src/parser/block/extension/figure.test.ts +1 -1
- package/src/parser/block/extension/figure.ts +6 -6
- package/src/parser/block/extension/message.ts +1 -1
- package/src/parser/block/extension/table.ts +4 -4
- package/src/parser/block/heading.ts +4 -4
- package/src/parser/block/reply/cite.ts +2 -2
- package/src/parser/block/reply/quote.ts +2 -2
- package/src/parser/block/sidefence.test.ts +1 -3
- package/src/parser/block/sidefence.ts +4 -4
- package/src/parser/block/table.ts +2 -2
- package/src/parser/block.ts +1 -1
- package/src/parser/header.ts +3 -3
- package/src/parser/inline/autolink/account.test.ts +18 -17
- package/src/parser/inline/autolink/account.ts +14 -20
- package/src/parser/inline/autolink/anchor.test.ts +2 -1
- package/src/parser/inline/autolink/anchor.ts +10 -13
- package/src/parser/inline/autolink/channel.test.ts +6 -6
- package/src/parser/inline/autolink/channel.ts +28 -32
- package/src/parser/inline/autolink/email.test.ts +19 -19
- package/src/parser/inline/autolink/email.ts +7 -7
- package/src/parser/inline/autolink/hashnum.test.ts +20 -20
- package/src/parser/inline/autolink/hashnum.ts +6 -8
- package/src/parser/inline/autolink/hashtag.test.ts +27 -27
- package/src/parser/inline/autolink/hashtag.ts +15 -16
- package/src/parser/inline/autolink/url.test.ts +6 -6
- package/src/parser/inline/autolink/url.ts +5 -4
- package/src/parser/inline/autolink.ts +4 -5
- package/src/parser/inline/code.ts +12 -18
- package/src/parser/inline/deletion.test.ts +1 -1
- package/src/parser/inline/deletion.ts +3 -3
- package/src/parser/inline/emstrong.ts +3 -3
- package/src/parser/inline/extension/indexer.ts +1 -1
- package/src/parser/inline/html.test.ts +1 -0
- package/src/parser/inline/html.ts +1 -1
- package/src/parser/inline/insertion.test.ts +1 -1
- package/src/parser/inline/insertion.ts +3 -3
- package/src/parser/inline/italic.test.ts +2 -2
- package/src/parser/inline/italic.ts +3 -3
- package/src/parser/inline/link.test.ts +0 -1
- package/src/parser/inline/link.ts +3 -3
- package/src/parser/inline/mark.test.ts +1 -1
- package/src/parser/inline/mark.ts +3 -3
- package/src/parser/inline/remark.ts +3 -3
- package/src/parser/inline.test.ts +11 -11
- package/src/parser/inline.ts +2 -0
- package/src/parser/source/text.ts +8 -4
- package/src/parser/util.ts +1 -1
- package/src/parser/visibility.ts +4 -6
|
@@ -10,21 +10,24 @@ describe('Unit: parser/inline/autolink/account', () => {
|
|
|
10
10
|
|
|
11
11
|
it('invalid', () => {
|
|
12
12
|
assert.deepStrictEqual(inspect(parser(''), ctx), undefined);
|
|
13
|
-
assert.deepStrictEqual(inspect(parser('@'), ctx),
|
|
14
|
-
assert.deepStrictEqual(inspect(parser('@+'), ctx),
|
|
15
|
-
assert.deepStrictEqual(inspect(parser('@_'), ctx),
|
|
16
|
-
assert.deepStrictEqual(inspect(parser('@-'), ctx),
|
|
17
|
-
assert.deepStrictEqual(inspect(parser('@.'), ctx),
|
|
18
|
-
assert.deepStrictEqual(inspect(parser('@0'), ctx),
|
|
19
|
-
assert.deepStrictEqual(inspect(parser('@a@'), ctx),
|
|
20
|
-
assert.deepStrictEqual(inspect(parser('@a@b'), ctx),
|
|
21
|
-
assert.deepStrictEqual(inspect(parser('@a@b@c'), ctx),
|
|
22
|
-
assert.deepStrictEqual(inspect(parser('@ab@'), ctx),
|
|
23
|
-
assert.deepStrictEqual(inspect(parser('@@'), ctx),
|
|
24
|
-
assert.deepStrictEqual(inspect(parser('@@a'), ctx),
|
|
25
|
-
assert.deepStrictEqual(inspect(parser('@@@a'), ctx),
|
|
26
|
-
assert.deepStrictEqual(inspect(parser('@#'), ctx),
|
|
27
|
-
assert.deepStrictEqual(inspect(parser('@#a'), ctx),
|
|
13
|
+
assert.deepStrictEqual(inspect(parser('@'), ctx), undefined);
|
|
14
|
+
assert.deepStrictEqual(inspect(parser('@+'), ctx), undefined);
|
|
15
|
+
assert.deepStrictEqual(inspect(parser('@_'), ctx), undefined);
|
|
16
|
+
assert.deepStrictEqual(inspect(parser('@-'), ctx), undefined);
|
|
17
|
+
assert.deepStrictEqual(inspect(parser('@.'), ctx), undefined);
|
|
18
|
+
assert.deepStrictEqual(inspect(parser('@0'), ctx), undefined);
|
|
19
|
+
assert.deepStrictEqual(inspect(parser('@a@'), ctx), undefined);
|
|
20
|
+
assert.deepStrictEqual(inspect(parser('@a@b'), ctx), undefined);
|
|
21
|
+
assert.deepStrictEqual(inspect(parser('@a@b@c'), ctx), undefined);
|
|
22
|
+
assert.deepStrictEqual(inspect(parser('@ab@'), ctx), undefined);
|
|
23
|
+
assert.deepStrictEqual(inspect(parser('@@'), ctx), undefined);
|
|
24
|
+
assert.deepStrictEqual(inspect(parser('@@a'), ctx), undefined);
|
|
25
|
+
assert.deepStrictEqual(inspect(parser('@@@a'), ctx), undefined);
|
|
26
|
+
assert.deepStrictEqual(inspect(parser('@#'), ctx), undefined);
|
|
27
|
+
assert.deepStrictEqual(inspect(parser('@#a'), ctx), undefined);
|
|
28
|
+
assert.deepStrictEqual(inspect(parser('@a.b:c'), ctx), undefined);
|
|
29
|
+
assert.deepStrictEqual(inspect(parser('@a.domain.com:b'), ctx), undefined);
|
|
30
|
+
assert.deepStrictEqual(inspect(parser('@http://host'), ctx), undefined);
|
|
28
31
|
assert.deepStrictEqual(inspect(parser(' @a'), ctx), undefined);
|
|
29
32
|
});
|
|
30
33
|
|
|
@@ -38,8 +41,6 @@ describe('Unit: parser/inline/autolink/account', () => {
|
|
|
38
41
|
assert.deepStrictEqual(inspect(parser('@a--b'), ctx), [['<a class="account" href="/@a">@a</a>'], '--b']);
|
|
39
42
|
assert.deepStrictEqual(inspect(parser('@a.'), ctx), [['<a class="account" href="/@a">@a</a>'], '.']);
|
|
40
43
|
assert.deepStrictEqual(inspect(parser('@a.domain.com'), ctx), [['<a class="account" href="/@a.domain.com">@a.domain.com</a>'], '']);
|
|
41
|
-
assert.deepStrictEqual(inspect(parser('@http://host'), ctx), [['@http'], '://host']);
|
|
42
|
-
assert.deepStrictEqual(inspect(parser('@ttp://host'), ctx), [ [ '@ttp' ], '://host' ]);
|
|
43
44
|
assert.deepStrictEqual(inspect(parser('@domain/a'), ctx), [['<a class="account" href="https://domain/@a" target="_blank">@domain/a</a>'], '']);
|
|
44
45
|
assert.deepStrictEqual(inspect(parser('@domain.com/a'), ctx), [['<a class="account" href="https://domain.com/@a" target="_blank">@domain.com/a</a>'], '']);
|
|
45
46
|
});
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { AutolinkParser } from '../../inline';
|
|
2
2
|
import { State, Backtrack } from '../../context';
|
|
3
3
|
import { List, Data } from '../../../combinator/data/parser';
|
|
4
|
-
import { union,
|
|
4
|
+
import { union, state, constraint, rewrite, surround, convert, fmap, lazy } from '../../../combinator';
|
|
5
5
|
import { unsafelink } from '../link';
|
|
6
6
|
import { str } from '../../source';
|
|
7
7
|
import { define } from 'typed-dom/dom';
|
|
@@ -9,24 +9,18 @@ import { define } from 'typed-dom/dom';
|
|
|
9
9
|
// https://example/@user must be a user page or a redirect page going there.
|
|
10
10
|
|
|
11
11
|
export const account: AutolinkParser.AccountParser = lazy(() => rewrite(
|
|
12
|
-
|
|
12
|
+
surround(
|
|
13
13
|
/(?<![0-9a-z])@/yi,
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
]),
|
|
18
|
-
false,
|
|
14
|
+
str(/[0-9a-z](?:(?:[0-9a-z]|-(?=[0-9a-z])){0,61}[0-9a-z])?(?:\.[0-9a-z](?:(?:[0-9a-z]|-(?=[0-9a-z])){0,61}[0-9a-z])?)*\//yi),
|
|
15
|
+
str(/[a-z][0-9a-z]*(?:[-.][0-9a-z]+)*(?![-.]?[0-9a-z@#]|>>|:\S)/yi),
|
|
16
|
+
true, undefined, undefined,
|
|
19
17
|
[3 | Backtrack.autolink]),
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
source
|
|
23
|
-
`
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
false),
|
|
30
|
-
([{ value }]) => new List([new Data(define(value, { class: 'account' }))])))),
|
|
31
|
-
({ context: { source } }) => new List([new Data(source)]),
|
|
32
|
-
])));
|
|
18
|
+
constraint(State.autolink, state(State.autolink, fmap(convert(
|
|
19
|
+
source =>
|
|
20
|
+
`[${source}]{ ${source.includes('/')
|
|
21
|
+
? `https://${source.slice(1).replace('/', '/@')}`
|
|
22
|
+
: `/${source}`
|
|
23
|
+
} }`,
|
|
24
|
+
union([unsafelink]),
|
|
25
|
+
false),
|
|
26
|
+
([{ value }]) => new List([new Data(define(value, { class: 'account' }))]))))));
|
|
@@ -15,10 +15,11 @@ describe('Unit: parser/inline/autolink/anchor', () => {
|
|
|
15
15
|
assert.deepStrictEqual(inspect(parser('>>-0'), ctx), undefined);
|
|
16
16
|
assert.deepStrictEqual(inspect(parser('>>01#'), ctx), undefined);
|
|
17
17
|
assert.deepStrictEqual(inspect(parser('>>01@'), ctx), undefined);
|
|
18
|
+
assert.deepStrictEqual(inspect(parser('>>0-1:2'), ctx), undefined);
|
|
18
19
|
assert.deepStrictEqual(inspect(parser('>>https://host'), ctx), undefined);
|
|
19
20
|
assert.deepStrictEqual(inspect(parser('>>tel:1234567890'), ctx), undefined);
|
|
20
21
|
assert.deepStrictEqual(inspect(parser('>>>'), ctx), undefined);
|
|
21
|
-
assert.deepStrictEqual(inspect(parser('a>>0'), ctx),
|
|
22
|
+
assert.deepStrictEqual(inspect(parser('a>>0'), ctx), undefined);
|
|
22
23
|
assert.deepStrictEqual(inspect(parser(' >>0'), ctx), undefined);
|
|
23
24
|
});
|
|
24
25
|
|
|
@@ -19,18 +19,15 @@ import { define } from 'typed-dom/dom';
|
|
|
19
19
|
export const anchor: AutolinkParser.AnchorParser = lazy(() => rewrite(
|
|
20
20
|
open(
|
|
21
21
|
/(?<![0-9a-z])>>/yi,
|
|
22
|
-
str(/(?:[a-z][0-9a-z]*(?:-[0-9a-z]+)*\/)?[0-9a-z]+(?:-[0-9a-z]+)*(
|
|
22
|
+
str(/(?:[a-z][0-9a-z]*(?:-[0-9a-z]+)*\/)?[0-9a-z]+(?:-[0-9a-z]+)*(?!-?[0-9a-z@#]|>>|:\S)/yi),
|
|
23
23
|
false,
|
|
24
24
|
[3 | Backtrack.autolink]),
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
source
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
([{ value }]) => new List([new Data(define(value, { class: 'anchor' }))])))),
|
|
35
|
-
({ context: { source } }) => new List([new Data(source)]),
|
|
36
|
-
])));
|
|
25
|
+
constraint(State.autolink, state(State.autolink, fmap(convert(
|
|
26
|
+
source =>
|
|
27
|
+
`[${source}]{ ${source.includes('/')
|
|
28
|
+
? `/@${source.slice(2).replace('/', '/timeline?at=')}`
|
|
29
|
+
: `?at=${source.slice(2)}`
|
|
30
|
+
} }`,
|
|
31
|
+
union([unsafelink]),
|
|
32
|
+
false),
|
|
33
|
+
([{ value }]) => new List([new Data(define(value, { class: 'anchor' }))]))))));
|
|
@@ -10,12 +10,12 @@ describe('Unit: parser/inline/autolink/channel', () => {
|
|
|
10
10
|
|
|
11
11
|
it('invalid', () => {
|
|
12
12
|
assert.deepStrictEqual(inspect(parser(''), ctx), undefined);
|
|
13
|
-
assert.deepStrictEqual(inspect(parser('@a@'), ctx),
|
|
14
|
-
assert.deepStrictEqual(inspect(parser('@a@b'), ctx),
|
|
15
|
-
assert.deepStrictEqual(inspect(parser('@a#'), ctx),
|
|
16
|
-
assert.deepStrictEqual(inspect(parser('@a#1'), ctx),
|
|
17
|
-
assert.deepStrictEqual(inspect(parser('@a#b@'), ctx),
|
|
18
|
-
assert.deepStrictEqual(inspect(parser('@a#1@b'), ctx),
|
|
13
|
+
assert.deepStrictEqual(inspect(parser('@a@'), ctx), undefined);
|
|
14
|
+
assert.deepStrictEqual(inspect(parser('@a@b'), ctx), undefined);
|
|
15
|
+
assert.deepStrictEqual(inspect(parser('@a#'), ctx), undefined);
|
|
16
|
+
assert.deepStrictEqual(inspect(parser('@a#1'), ctx), undefined);
|
|
17
|
+
assert.deepStrictEqual(inspect(parser('@a#b@'), ctx), undefined);
|
|
18
|
+
assert.deepStrictEqual(inspect(parser('@a#1@b'), ctx), undefined);
|
|
19
19
|
assert.deepStrictEqual(inspect(parser(' @a#b'), ctx), undefined);
|
|
20
20
|
});
|
|
21
21
|
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { AutolinkParser } from '../../inline';
|
|
2
2
|
import { State, Backtrack } from '../../context';
|
|
3
3
|
import { List, Data } from '../../../combinator/data/parser';
|
|
4
|
-
import { union,
|
|
4
|
+
import { union, sequence, some, state, constraint, verify, rewrite, surround, convert, fmap, lazy } from '../../../combinator';
|
|
5
5
|
import { unsafelink } from '../link';
|
|
6
6
|
import { emoji } from './hashtag';
|
|
7
7
|
import { str } from '../../source';
|
|
@@ -11,38 +11,34 @@ import { define } from 'typed-dom/dom';
|
|
|
11
11
|
|
|
12
12
|
export const channel: AutolinkParser.ChannelParser = lazy(() => rewrite(
|
|
13
13
|
sequence([
|
|
14
|
-
|
|
14
|
+
surround(
|
|
15
15
|
/(?<![0-9a-z])@/yi,
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
]),
|
|
20
|
-
false,
|
|
16
|
+
str(/[0-9a-z](?:(?:[0-9a-z]|-(?=[0-9a-z])){0,61}[0-9a-z])?(?:\.[0-9a-z](?:(?:[0-9a-z]|-(?=[0-9a-z])){0,61}[0-9a-z])?)*\//yi),
|
|
17
|
+
str(/[a-z][0-9a-z]*(?:[-.][0-9a-z]+)*(?![-.]?[0-9a-z@]|>>|:\S)/yi),
|
|
18
|
+
true, undefined, undefined,
|
|
21
19
|
[3 | Backtrack.autolink]),
|
|
22
|
-
some(
|
|
20
|
+
some(verify(surround(
|
|
23
21
|
'#',
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
([
|
|
29
|
-
|
|
30
|
-
|
|
22
|
+
str(new RegExp([
|
|
23
|
+
/(?!['_])(?:[^\p{C}\p{S}\p{P}\s]|emoji|'(?=[0-9A-Za-z])|_(?=[^\p{C}\p{S}\p{P}\s]|emoji))+/yu.source,
|
|
24
|
+
].join('').replace(/emoji/g, emoji), 'yu')),
|
|
25
|
+
str(new RegExp([
|
|
26
|
+
/(?![0-9a-z@]|>>|:\S|[^\p{C}\p{S}\p{P}\s]|emoji)/yu.source,
|
|
27
|
+
].join('').replace(/emoji/g, emoji), 'yu')),
|
|
28
|
+
false, undefined, undefined,
|
|
29
|
+
[3 | Backtrack.autolink]),
|
|
30
|
+
([{ value }]) => !/^[0-9]{1,4}$|^[0-9]{5}/.test(value as string))),
|
|
31
31
|
]),
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
source
|
|
35
|
-
`
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
return new List([new Data(define(el, { class: 'channel', href: url }, src))]);
|
|
46
|
-
}))),
|
|
47
|
-
({ context: { source } }) => new List([new Data(source)]),
|
|
48
|
-
])));
|
|
32
|
+
constraint(State.autolink, state(State.autolink, fmap(convert(
|
|
33
|
+
source =>
|
|
34
|
+
`[${source}]{ ${source.includes('/')
|
|
35
|
+
? `https://${source.slice(1, source.indexOf('#')).replace('/', '/@')}`
|
|
36
|
+
: `/${source.slice(0, source.indexOf('#'))}`
|
|
37
|
+
} }`,
|
|
38
|
+
union([unsafelink]),
|
|
39
|
+
false),
|
|
40
|
+
([{ value: el }], { source, position, range = 0 }) => {
|
|
41
|
+
const src = source.slice(position - range, position);
|
|
42
|
+
const url = `${el.getAttribute('href')}?ch=${src.slice(src.indexOf('#') + 1).replace(/#/g, '+')}`;
|
|
43
|
+
return new List([new Data(define(el, { class: 'channel', href: url }, src))]);
|
|
44
|
+
})))));
|
|
@@ -10,25 +10,25 @@ describe('Unit: parser/inline/autolink/email', () => {
|
|
|
10
10
|
|
|
11
11
|
it('invalid', () => {
|
|
12
12
|
assert.deepStrictEqual(inspect(parser(''), ctx), undefined);
|
|
13
|
-
assert.deepStrictEqual(inspect(parser('a@'), ctx),
|
|
14
|
-
assert.deepStrictEqual(inspect(parser('a@+'), ctx),
|
|
15
|
-
assert.deepStrictEqual(inspect(parser('a@_'), ctx),
|
|
16
|
-
assert.deepStrictEqual(inspect(parser('a@-'), ctx),
|
|
17
|
-
assert.deepStrictEqual(inspect(parser('a@.'), ctx),
|
|
18
|
-
assert.deepStrictEqual(inspect(parser('a@b@'), ctx),
|
|
19
|
-
assert.deepStrictEqual(inspect(parser('a@bc@'), ctx),
|
|
20
|
-
assert.deepStrictEqual(inspect(parser('a@b@c'), ctx),
|
|
21
|
-
assert.deepStrictEqual(inspect(parser('a@b#'), ctx),
|
|
22
|
-
assert.deepStrictEqual(inspect(parser('a@b#1'), ctx),
|
|
23
|
-
assert.deepStrictEqual(inspect(parser('a@@'), ctx),
|
|
24
|
-
assert.deepStrictEqual(inspect(parser('a@@b'), ctx),
|
|
25
|
-
assert.deepStrictEqual(inspect(parser('a+@b'), ctx),
|
|
26
|
-
assert.deepStrictEqual(inspect(parser('a__b@c'), ctx),
|
|
27
|
-
assert.deepStrictEqual(inspect(parser('a..b@c'), ctx),
|
|
28
|
-
assert.deepStrictEqual(inspect(parser('a++b@c'), ctx),
|
|
29
|
-
assert.deepStrictEqual(inspect(parser('a@
|
|
30
|
-
assert.deepStrictEqual(inspect(parser('a@
|
|
31
|
-
assert.deepStrictEqual(inspect(parser(`a@${'b'.repeat(64)}`), ctx),
|
|
13
|
+
assert.deepStrictEqual(inspect(parser('a@'), ctx), undefined);
|
|
14
|
+
assert.deepStrictEqual(inspect(parser('a@+'), ctx), undefined);
|
|
15
|
+
assert.deepStrictEqual(inspect(parser('a@_'), ctx), undefined);
|
|
16
|
+
assert.deepStrictEqual(inspect(parser('a@-'), ctx), undefined);
|
|
17
|
+
assert.deepStrictEqual(inspect(parser('a@.'), ctx), undefined);
|
|
18
|
+
assert.deepStrictEqual(inspect(parser('a@b@'), ctx), undefined);
|
|
19
|
+
assert.deepStrictEqual(inspect(parser('a@bc@'), ctx), undefined);
|
|
20
|
+
assert.deepStrictEqual(inspect(parser('a@b@c'), ctx), undefined);
|
|
21
|
+
assert.deepStrictEqual(inspect(parser('a@b#'), ctx), undefined);
|
|
22
|
+
assert.deepStrictEqual(inspect(parser('a@b#1'), ctx), undefined);
|
|
23
|
+
assert.deepStrictEqual(inspect(parser('a@@'), ctx), undefined);
|
|
24
|
+
assert.deepStrictEqual(inspect(parser('a@@b'), ctx), undefined);
|
|
25
|
+
assert.deepStrictEqual(inspect(parser('a+@b'), ctx), undefined);
|
|
26
|
+
assert.deepStrictEqual(inspect(parser('a__b@c'), ctx), undefined);
|
|
27
|
+
assert.deepStrictEqual(inspect(parser('a..b@c'), ctx), undefined);
|
|
28
|
+
assert.deepStrictEqual(inspect(parser('a++b@c'), ctx), undefined);
|
|
29
|
+
assert.deepStrictEqual(inspect(parser('a@b.c:d'), ctx), undefined);
|
|
30
|
+
assert.deepStrictEqual(inspect(parser('a@http://host'), ctx), undefined);
|
|
31
|
+
assert.deepStrictEqual(inspect(parser(`a@${'b'.repeat(64)}`), ctx), undefined);
|
|
32
32
|
assert.deepStrictEqual(inspect(parser(' a@b'), ctx), undefined);
|
|
33
33
|
});
|
|
34
34
|
|
|
@@ -8,14 +8,14 @@ import { html } from 'typed-dom/dom';
|
|
|
8
8
|
// https://html.spec.whatwg.org/multipage/input.html
|
|
9
9
|
|
|
10
10
|
export const email: AutolinkParser.EmailParser = rewrite(
|
|
11
|
-
open(/(?<![0-9a-z][_.+-]
|
|
11
|
+
open(/(?<![0-9a-z][_.+-]?|[@#])(?=[0-9a-z])/yi,
|
|
12
12
|
verify(
|
|
13
|
-
str(/[0-9a-z](?:[_.+-](?=[0-9a-z])|[0-9a-z]){0,255}@[0-9a-z](?:(?:[0-9a-z]|-(?=[0-9a-z])){0,61}[0-9a-z])?(?:\.[0-9a-z](?:(?:[0-9a-z]|-(?=[0-9a-z])){0,61}[0-9a-z])?)*(?![0-9a-z@#]|>>|:\S)/yi),
|
|
13
|
+
str(/[0-9a-z](?:[_.+-](?=[0-9a-z])|[0-9a-z]){0,255}@[0-9a-z](?:(?:[0-9a-z]|-(?=[0-9a-z])){0,61}[0-9a-z])?(?:\.[0-9a-z](?:(?:[0-9a-z]|-(?=[0-9a-z])){0,61}[0-9a-z])?)*(?![.-]?[0-9a-z@#]|>>|:\S)/yi),
|
|
14
14
|
([{ value }]) => value.length <= 255),
|
|
15
15
|
false,
|
|
16
16
|
[3 | Backtrack.autolink]),
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
({ context: { source } }) =>
|
|
20
|
-
|
|
21
|
-
|
|
17
|
+
constraint(State.autolink, state(State.autolink,
|
|
18
|
+
union([
|
|
19
|
+
({ context: { source } }) =>
|
|
20
|
+
new List([new Data(html('a', { class: 'email', href: `mailto:${source}` }, source))])
|
|
21
|
+
]))));
|
|
@@ -10,27 +10,27 @@ describe('Unit: parser/inline/autolink/hashnum', () => {
|
|
|
10
10
|
|
|
11
11
|
it('invalid', () => {
|
|
12
12
|
assert.deepStrictEqual(inspect(parser(''), ctx), undefined);
|
|
13
|
-
assert.deepStrictEqual(inspect(parser('#'), ctx),
|
|
14
|
-
assert.deepStrictEqual(inspect(parser('# '), ctx),
|
|
15
|
-
assert.deepStrictEqual(inspect(parser('#1#'), ctx),
|
|
16
|
-
assert.deepStrictEqual(inspect(parser('#1#2'), ctx),
|
|
17
|
-
assert.deepStrictEqual(inspect(parser('#1#2#3'), ctx),
|
|
18
|
-
assert.deepStrictEqual(inspect(parser('#1@2'), ctx),
|
|
19
|
-
assert.deepStrictEqual(inspect(parser('#\\'), ctx),
|
|
20
|
-
assert.deepStrictEqual(inspect(parser('#\\ '), ctx),
|
|
21
|
-
assert.deepStrictEqual(inspect(parser('#\\\n'), ctx),
|
|
22
|
-
assert.deepStrictEqual(inspect(parser('##'), ctx),
|
|
23
|
-
assert.deepStrictEqual(inspect(parser('##1'), ctx),
|
|
24
|
-
assert.deepStrictEqual(inspect(parser('###1'), ctx),
|
|
25
|
-
assert.deepStrictEqual(inspect(parser('#{}'), ctx),
|
|
26
|
-
assert.deepStrictEqual(inspect(parser('#{{}'), ctx),
|
|
27
|
-
assert.deepStrictEqual(inspect(parser('#{}}'), ctx),
|
|
28
|
-
assert.deepStrictEqual(inspect(parser('#{#}'), ctx),
|
|
29
|
-
assert.deepStrictEqual(inspect(parser('#{1}'), ctx),
|
|
30
|
-
assert.deepStrictEqual(inspect(parser('
|
|
13
|
+
assert.deepStrictEqual(inspect(parser('#'), ctx), undefined);
|
|
14
|
+
assert.deepStrictEqual(inspect(parser('# '), ctx), undefined);
|
|
15
|
+
assert.deepStrictEqual(inspect(parser('#1#'), ctx), undefined);
|
|
16
|
+
assert.deepStrictEqual(inspect(parser('#1#2'), ctx), undefined);
|
|
17
|
+
assert.deepStrictEqual(inspect(parser('#1#2#3'), ctx), undefined);
|
|
18
|
+
assert.deepStrictEqual(inspect(parser('#1@2'), ctx), undefined);
|
|
19
|
+
assert.deepStrictEqual(inspect(parser('#\\'), ctx), undefined);
|
|
20
|
+
assert.deepStrictEqual(inspect(parser('#\\ '), ctx), undefined);
|
|
21
|
+
assert.deepStrictEqual(inspect(parser('#\\\n'), ctx), undefined);
|
|
22
|
+
assert.deepStrictEqual(inspect(parser('##'), ctx), undefined);
|
|
23
|
+
assert.deepStrictEqual(inspect(parser('##1'), ctx), undefined);
|
|
24
|
+
assert.deepStrictEqual(inspect(parser('###1'), ctx), undefined);
|
|
25
|
+
assert.deepStrictEqual(inspect(parser('#{}'), ctx), undefined);
|
|
26
|
+
assert.deepStrictEqual(inspect(parser('#{{}'), ctx), undefined);
|
|
27
|
+
assert.deepStrictEqual(inspect(parser('#{}}'), ctx), undefined);
|
|
28
|
+
assert.deepStrictEqual(inspect(parser('#{#}'), ctx), undefined);
|
|
29
|
+
assert.deepStrictEqual(inspect(parser('#{1}'), ctx), undefined);
|
|
30
|
+
assert.deepStrictEqual(inspect(parser(`#${'1'.repeat(10)}`), ctx), undefined);
|
|
31
|
+
assert.deepStrictEqual(inspect(parser(`#${'1'.repeat(10)}a`), ctx), undefined);
|
|
32
|
+
assert.deepStrictEqual(inspect(parser('# '), ctx), undefined);
|
|
31
33
|
assert.deepStrictEqual(inspect(parser(' #1'), ctx), undefined);
|
|
32
|
-
assert.deepStrictEqual(inspect(parser(`#${'1'.repeat(10)}`), ctx), [[`#${'1'.repeat(10)}`], '']);
|
|
33
|
-
assert.deepStrictEqual(inspect(parser(`#${'1'.repeat(10)}a`), ctx), [[`#${'1'.repeat(10)}a`], '']);
|
|
34
34
|
});
|
|
35
35
|
|
|
36
36
|
it('valid', () => {
|
|
@@ -17,11 +17,9 @@ export const hashnum: AutolinkParser.HashnumParser = lazy(() => rewrite(
|
|
|
17
17
|
].join('').replace(/emoji/g, emoji), 'yu')),
|
|
18
18
|
false,
|
|
19
19
|
[1 | Backtrack.autolink]),
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
({ context: { source } }) => new List([new Data(source)]),
|
|
27
|
-
])));
|
|
20
|
+
constraint(State.autolink, state(State.autolink, fmap(convert(
|
|
21
|
+
source => `[${source}]{ ${source.slice(1)} }`,
|
|
22
|
+
union([unsafelink]),
|
|
23
|
+
false),
|
|
24
|
+
([{ value }]) => new List([new Data(define(value, { class: 'hashnum', href: null }))])))),
|
|
25
|
+
));
|
|
@@ -10,33 +10,33 @@ describe('Unit: parser/inline/autolink/hashtag', () => {
|
|
|
10
10
|
|
|
11
11
|
it('invalid', () => {
|
|
12
12
|
assert.deepStrictEqual(inspect(parser(''), ctx), undefined);
|
|
13
|
-
assert.deepStrictEqual(inspect(parser('#'), ctx),
|
|
14
|
-
assert.deepStrictEqual(inspect(parser('# '), ctx),
|
|
15
|
-
assert.deepStrictEqual(inspect(parser('#a#'), ctx),
|
|
16
|
-
assert.deepStrictEqual(inspect(parser('#a#b'), ctx),
|
|
17
|
-
assert.deepStrictEqual(inspect(parser('#a#b#c'), ctx),
|
|
18
|
-
assert.deepStrictEqual(inspect(parser('#a@b'), ctx),
|
|
19
|
-
assert.deepStrictEqual(inspect(parser('#@'), ctx),
|
|
20
|
-
assert.deepStrictEqual(inspect(parser('#@a'), ctx),
|
|
21
|
-
assert.deepStrictEqual(inspect(parser('#\\'), ctx),
|
|
22
|
-
assert.deepStrictEqual(inspect(parser('#\\ '), ctx),
|
|
23
|
-
assert.deepStrictEqual(inspect(parser('#\\\n'), ctx),
|
|
24
|
-
assert.deepStrictEqual(inspect(parser('##'), ctx),
|
|
25
|
-
assert.deepStrictEqual(inspect(parser('##a'), ctx),
|
|
26
|
-
assert.deepStrictEqual(inspect(parser('###a'), ctx),
|
|
27
|
-
assert.deepStrictEqual(inspect(parser(`#'`), ctx),
|
|
28
|
-
assert.deepStrictEqual(inspect(parser(`#'0`), ctx),
|
|
29
|
-
assert.deepStrictEqual(inspect(parser(`#'00`), ctx),
|
|
30
|
-
assert.deepStrictEqual(inspect(parser('#_'), ctx),
|
|
31
|
-
assert.deepStrictEqual(inspect(parser('#_a'), ctx),
|
|
32
|
-
assert.deepStrictEqual(inspect(parser('#(a)'), ctx),
|
|
33
|
-
assert.deepStrictEqual(inspect(parser('#{}'), ctx),
|
|
34
|
-
assert.deepStrictEqual(inspect(parser('#{{}'), ctx),
|
|
35
|
-
assert.deepStrictEqual(inspect(parser('#{}}'), ctx),
|
|
36
|
-
assert.deepStrictEqual(inspect(parser('#{#}'), ctx),
|
|
37
|
-
assert.deepStrictEqual(inspect(parser('#{a}'), ctx),
|
|
38
|
-
assert.deepStrictEqual(inspect(parser('#12345a'), ctx),
|
|
39
|
-
assert.deepStrictEqual(inspect(parser('# '), ctx),
|
|
13
|
+
assert.deepStrictEqual(inspect(parser('#'), ctx), undefined);
|
|
14
|
+
assert.deepStrictEqual(inspect(parser('# '), ctx), undefined);
|
|
15
|
+
assert.deepStrictEqual(inspect(parser('#a#'), ctx), undefined);
|
|
16
|
+
assert.deepStrictEqual(inspect(parser('#a#b'), ctx), undefined);
|
|
17
|
+
assert.deepStrictEqual(inspect(parser('#a#b#c'), ctx), undefined);
|
|
18
|
+
assert.deepStrictEqual(inspect(parser('#a@b'), ctx), undefined);
|
|
19
|
+
assert.deepStrictEqual(inspect(parser('#@'), ctx), undefined);
|
|
20
|
+
assert.deepStrictEqual(inspect(parser('#@a'), ctx), undefined);
|
|
21
|
+
assert.deepStrictEqual(inspect(parser('#\\'), ctx), undefined);
|
|
22
|
+
assert.deepStrictEqual(inspect(parser('#\\ '), ctx), undefined);
|
|
23
|
+
assert.deepStrictEqual(inspect(parser('#\\\n'), ctx), undefined);
|
|
24
|
+
assert.deepStrictEqual(inspect(parser('##'), ctx), undefined);
|
|
25
|
+
assert.deepStrictEqual(inspect(parser('##a'), ctx), undefined);
|
|
26
|
+
assert.deepStrictEqual(inspect(parser('###a'), ctx), undefined);
|
|
27
|
+
assert.deepStrictEqual(inspect(parser(`#'`), ctx), undefined);
|
|
28
|
+
assert.deepStrictEqual(inspect(parser(`#'0`), ctx), undefined);
|
|
29
|
+
assert.deepStrictEqual(inspect(parser(`#'00`), ctx), undefined);
|
|
30
|
+
assert.deepStrictEqual(inspect(parser('#_'), ctx), undefined);
|
|
31
|
+
assert.deepStrictEqual(inspect(parser('#_a'), ctx), undefined);
|
|
32
|
+
assert.deepStrictEqual(inspect(parser('#(a)'), ctx), undefined);
|
|
33
|
+
assert.deepStrictEqual(inspect(parser('#{}'), ctx), undefined);
|
|
34
|
+
assert.deepStrictEqual(inspect(parser('#{{}'), ctx), undefined);
|
|
35
|
+
assert.deepStrictEqual(inspect(parser('#{}}'), ctx), undefined);
|
|
36
|
+
assert.deepStrictEqual(inspect(parser('#{#}'), ctx), undefined);
|
|
37
|
+
assert.deepStrictEqual(inspect(parser('#{a}'), ctx), undefined);
|
|
38
|
+
assert.deepStrictEqual(inspect(parser('#12345a'), ctx), undefined);
|
|
39
|
+
assert.deepStrictEqual(inspect(parser('# '), ctx), undefined);
|
|
40
40
|
assert.deepStrictEqual(inspect(parser(' #a'), ctx), undefined);
|
|
41
41
|
});
|
|
42
42
|
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { AutolinkParser } from '../../inline';
|
|
2
2
|
import { State, Backtrack } from '../../context';
|
|
3
3
|
import { List, Data } from '../../../combinator/data/parser';
|
|
4
|
-
import { union, state, constraint, verify, rewrite,
|
|
4
|
+
import { union, state, constraint, verify, rewrite, surround, convert, fmap, lazy } from '../../../combinator';
|
|
5
5
|
import { unsafelink } from '../link';
|
|
6
6
|
import { str } from '../../source';
|
|
7
7
|
import { define } from 'typed-dom/dom';
|
|
@@ -12,22 +12,21 @@ import { define } from 'typed-dom/dom';
|
|
|
12
12
|
export const emoji = String.raw`\p{Emoji_Modifier_Base}\p{Emoji_Modifier}?|\p{Emoji_Presentation}|\p{Emoji}\uFE0F`;
|
|
13
13
|
|
|
14
14
|
export const hashtag: AutolinkParser.HashtagParser = lazy(() => rewrite(
|
|
15
|
-
|
|
15
|
+
verify(surround(
|
|
16
16
|
new RegExp([
|
|
17
17
|
/(?<![^\p{C}\p{S}\p{P}\s]|emoji)#/yiu.source,
|
|
18
18
|
].join('').replace(/emoji/g, emoji), 'yu'),
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
([
|
|
24
|
-
|
|
19
|
+
str(new RegExp([
|
|
20
|
+
/(?!['_])(?:[^\p{C}\p{S}\p{P}\s]|emoji|'(?=[0-9A-Za-z])|_(?=[^\p{C}\p{S}\p{P}\s]|emoji))+/yu.source,
|
|
21
|
+
].join('').replace(/emoji/g, emoji), 'yu')),
|
|
22
|
+
str(new RegExp([
|
|
23
|
+
/(?![0-9a-z@#]|>>|:\S|[^\p{C}\p{S}\p{P}\s]|emoji)/yu.source,
|
|
24
|
+
].join('').replace(/emoji/g, emoji), 'yu')),
|
|
25
|
+
false, undefined, undefined,
|
|
25
26
|
[3 | Backtrack.autolink]),
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
({ context: { source } }) => new List([new Data(source)]),
|
|
33
|
-
])));
|
|
27
|
+
([{ value }]) => !/^[0-9]{1,4}$|^[0-9]{5}/.test(value)),
|
|
28
|
+
constraint(State.autolink, state(State.autolink, fmap(convert(
|
|
29
|
+
source => `[${source}]{ ${`/hashtags/${source.slice(1)}`} }`,
|
|
30
|
+
union([unsafelink]),
|
|
31
|
+
false),
|
|
32
|
+
([{ value }]) => new List([new Data(define(value, { class: 'hashtag' }))]))))));
|
|
@@ -10,12 +10,12 @@ describe('Unit: parser/inline/autolink/url', () => {
|
|
|
10
10
|
|
|
11
11
|
it('invalid', () => {
|
|
12
12
|
assert.deepStrictEqual(inspect(parser(''), ctx), undefined);
|
|
13
|
-
assert.deepStrictEqual(inspect(parser('
|
|
14
|
-
assert.deepStrictEqual(inspect(parser('
|
|
15
|
-
assert.deepStrictEqual(inspect(parser(' http://'), ctx),
|
|
16
|
-
assert.deepStrictEqual(inspect(parser(' http://['), ctx),
|
|
17
|
-
assert.deepStrictEqual(inspect(parser(' http://]'), ctx),
|
|
18
|
-
assert.deepStrictEqual(inspect(parser(' Http://host'), ctx),
|
|
13
|
+
assert.deepStrictEqual(inspect(parser(' '), ctx), undefined);
|
|
14
|
+
assert.deepStrictEqual(inspect(parser(' http'), ctx), undefined);
|
|
15
|
+
assert.deepStrictEqual(inspect(parser(' http://'), ctx), undefined);
|
|
16
|
+
assert.deepStrictEqual(inspect(parser(' http://['), ctx), undefined);
|
|
17
|
+
assert.deepStrictEqual(inspect(parser(' http://]'), ctx), undefined);
|
|
18
|
+
assert.deepStrictEqual(inspect(parser(' Http://host'), ctx), undefined);
|
|
19
19
|
assert.deepStrictEqual(inspect(parser(' http://[::ffff:0:0%1]'), ctx), [['<a class="invalid">http://[::ffff:0:0%1]</a>'], '']);
|
|
20
20
|
assert.deepStrictEqual(inspect(parser(' http://[::ffff:0:0/96]'), ctx), [['<a class="invalid">http://[::ffff:0:0/96]</a>'], '']);
|
|
21
21
|
});
|
|
@@ -1,13 +1,14 @@
|
|
|
1
1
|
import { AutolinkParser } from '../../inline';
|
|
2
2
|
import { State, Recursion, Backtrack } from '../../context';
|
|
3
|
-
import { List
|
|
3
|
+
import { List } from '../../../combinator/data/parser';
|
|
4
4
|
import { union, tails, some, recursion, precedence, state, constraint, verify, focus, rewrite, convert, surround, open, lazy } from '../../../combinator';
|
|
5
|
+
import { inline } from '../../inline';
|
|
5
6
|
import { unsafelink } from '../link';
|
|
6
7
|
import { unescsource, str } from '../../source';
|
|
7
8
|
|
|
8
9
|
export const url: AutolinkParser.UrlParser = lazy(() => rewrite(
|
|
9
10
|
open(
|
|
10
|
-
/(?<![0-9A-Za-z][.+-]
|
|
11
|
+
/(?<![0-9A-Za-z][.+-]?|[@#])https?:\/\/(?=[\x21-\x7E])/y,
|
|
11
12
|
precedence(0, some(union([
|
|
12
13
|
some(unescsource, /(?<![-+*=~^_,.;:!?]|\/{3})(?:[-+*=~^_,.;:!?]|\/{3,}(?!\/))*(?=[\\$"`\[\](){}<>()[]{}|]|[^\x21-\x7E]|$)/y),
|
|
13
14
|
precedence(1, verify(bracket, ns => ns.length > 0)),
|
|
@@ -19,7 +20,7 @@ export const url: AutolinkParser.UrlParser = lazy(() => rewrite(
|
|
|
19
20
|
url => `{ ${url} }`,
|
|
20
21
|
unsafelink,
|
|
21
22
|
false))),
|
|
22
|
-
(
|
|
23
|
+
open(str(/[^:]+/y), some(inline)),
|
|
23
24
|
])));
|
|
24
25
|
|
|
25
26
|
export const lineurl: AutolinkParser.UrlParser.LineUrlParser = lazy(() => focus(
|
|
@@ -31,7 +32,7 @@ export const lineurl: AutolinkParser.UrlParser.LineUrlParser = lazy(() => focus(
|
|
|
31
32
|
url => `{ ${url} }`,
|
|
32
33
|
unsafelink,
|
|
33
34
|
false))),
|
|
34
|
-
(
|
|
35
|
+
open(str(/[^:]+/y), some(inline)),
|
|
35
36
|
]),
|
|
36
37
|
])));
|
|
37
38
|
|
|
@@ -8,14 +8,13 @@ import { account } from './autolink/account';
|
|
|
8
8
|
import { hashtag, emoji } from './autolink/hashtag';
|
|
9
9
|
import { hashnum } from './autolink/hashnum';
|
|
10
10
|
import { anchor } from './autolink/anchor';
|
|
11
|
-
import { str } from '../source';
|
|
12
11
|
|
|
13
12
|
export const autolink: AutolinkParser = lazy(() =>
|
|
14
13
|
validate(new RegExp([
|
|
15
14
|
/(?<![0-9a-z])@/yi.source,
|
|
16
15
|
/(?<![^\p{C}\p{S}\p{P}\s]|emoji)#/yiu.source,
|
|
17
16
|
/(?<![0-9a-z])>>/yi.source,
|
|
18
|
-
/(?<![0-9a-z][.+-]
|
|
17
|
+
/(?<![0-9a-z][.+-]?|[@#])!?[0-9a-z]/yi.source,
|
|
19
18
|
].join('|').replace(/emoji/g, emoji), 'yiu'),
|
|
20
19
|
state(~State.autolink,
|
|
21
20
|
union([
|
|
@@ -23,14 +22,14 @@ export const autolink: AutolinkParser = lazy(() =>
|
|
|
23
22
|
url,
|
|
24
23
|
email,
|
|
25
24
|
// Escape unmatched email-like strings.
|
|
26
|
-
str(/[0-9a-z]+(?:[_.+-][0-9a-z]+[:@]?|:|@(?=@))*/yi),
|
|
25
|
+
//str(/[0-9a-z]+(?:[_.+-][0-9a-z]+[:@]?|:|@(?=@))*/yi),
|
|
27
26
|
channel,
|
|
28
27
|
account,
|
|
29
28
|
// Escape unmatched account-like strings.
|
|
30
|
-
str(/@+(?:[0-9a-z]+(?:[_.+-][0-9a-z]+)*)?/yi),
|
|
29
|
+
//str(/@+(?:[0-9a-z]+(?:[_.+-][0-9a-z]+)*)?/yi),
|
|
31
30
|
hashtag,
|
|
32
31
|
hashnum,
|
|
33
32
|
// Escape unmatched hashtag-like strings.
|
|
34
|
-
str(new RegExp(/#+(?:(?:[^\p{C}\p{S}\p{P}\s]|emoji)+(?:['_.+-](?:[^\p{C}\p{S}\p{P}\s]|emoji)+)*)?/yu.source.replace(/emoji/g, emoji), 'yu')),
|
|
33
|
+
//str(new RegExp(/#+(?:(?:[^\p{C}\p{S}\p{P}\s]|emoji)+(?:['_.+-](?:[^\p{C}\p{S}\p{P}\s]|emoji)+)*)?/yu.source.replace(/emoji/g, emoji), 'yu')),
|
|
35
34
|
anchor,
|
|
36
35
|
]))));
|