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.
Files changed (63) hide show
  1. package/CHANGELOG.md +8 -0
  2. package/dist/index.js +164 -144
  3. package/markdown.d.ts +3 -12
  4. package/package.json +3 -3
  5. package/src/combinator/control/manipulation/fence.ts +2 -0
  6. package/src/combinator/control/manipulation/indent.ts +1 -1
  7. package/src/combinator/control/manipulation/match.ts +11 -8
  8. package/src/parser/api/parse.test.ts +3 -3
  9. package/src/parser/block/blockquote.test.ts +3 -9
  10. package/src/parser/block/blockquote.ts +4 -4
  11. package/src/parser/block/dlist.ts +4 -4
  12. package/src/parser/block/extension/example.ts +1 -3
  13. package/src/parser/block/extension/fig.test.ts +0 -1
  14. package/src/parser/block/extension/fig.ts +6 -6
  15. package/src/parser/block/extension/figbase.ts +1 -1
  16. package/src/parser/block/extension/figure.test.ts +1 -1
  17. package/src/parser/block/extension/figure.ts +6 -6
  18. package/src/parser/block/extension/message.ts +1 -1
  19. package/src/parser/block/extension/table.ts +4 -4
  20. package/src/parser/block/heading.ts +4 -4
  21. package/src/parser/block/reply/cite.ts +2 -2
  22. package/src/parser/block/reply/quote.ts +2 -2
  23. package/src/parser/block/sidefence.test.ts +1 -3
  24. package/src/parser/block/sidefence.ts +4 -4
  25. package/src/parser/block/table.ts +2 -2
  26. package/src/parser/block.ts +1 -1
  27. package/src/parser/header.ts +3 -3
  28. package/src/parser/inline/autolink/account.test.ts +18 -17
  29. package/src/parser/inline/autolink/account.ts +14 -20
  30. package/src/parser/inline/autolink/anchor.test.ts +2 -1
  31. package/src/parser/inline/autolink/anchor.ts +10 -13
  32. package/src/parser/inline/autolink/channel.test.ts +6 -6
  33. package/src/parser/inline/autolink/channel.ts +28 -32
  34. package/src/parser/inline/autolink/email.test.ts +19 -19
  35. package/src/parser/inline/autolink/email.ts +7 -7
  36. package/src/parser/inline/autolink/hashnum.test.ts +20 -20
  37. package/src/parser/inline/autolink/hashnum.ts +6 -8
  38. package/src/parser/inline/autolink/hashtag.test.ts +27 -27
  39. package/src/parser/inline/autolink/hashtag.ts +15 -16
  40. package/src/parser/inline/autolink/url.test.ts +6 -6
  41. package/src/parser/inline/autolink/url.ts +5 -4
  42. package/src/parser/inline/autolink.ts +4 -5
  43. package/src/parser/inline/code.ts +12 -18
  44. package/src/parser/inline/deletion.test.ts +1 -1
  45. package/src/parser/inline/deletion.ts +3 -3
  46. package/src/parser/inline/emstrong.ts +3 -3
  47. package/src/parser/inline/extension/indexer.ts +1 -1
  48. package/src/parser/inline/html.test.ts +1 -0
  49. package/src/parser/inline/html.ts +1 -1
  50. package/src/parser/inline/insertion.test.ts +1 -1
  51. package/src/parser/inline/insertion.ts +3 -3
  52. package/src/parser/inline/italic.test.ts +2 -2
  53. package/src/parser/inline/italic.ts +3 -3
  54. package/src/parser/inline/link.test.ts +0 -1
  55. package/src/parser/inline/link.ts +3 -3
  56. package/src/parser/inline/mark.test.ts +1 -1
  57. package/src/parser/inline/mark.ts +3 -3
  58. package/src/parser/inline/remark.ts +3 -3
  59. package/src/parser/inline.test.ts +11 -11
  60. package/src/parser/inline.ts +2 -0
  61. package/src/parser/source/text.ts +8 -4
  62. package/src/parser/util.ts +1 -1
  63. 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), [['@0'], '']);
19
- assert.deepStrictEqual(inspect(parser('@a@'), ctx), [['@a'], '@']);
20
- assert.deepStrictEqual(inspect(parser('@a@b'), ctx), [['@a'], '@b']);
21
- assert.deepStrictEqual(inspect(parser('@a@b@c'), ctx), [['@a'], '@b@c']);
22
- assert.deepStrictEqual(inspect(parser('@ab@'), ctx), [['@ab'], '@']);
23
- assert.deepStrictEqual(inspect(parser('@@'), ctx), [['@@'], '']);
24
- assert.deepStrictEqual(inspect(parser('@@a'), ctx), [['@@a'], '']);
25
- assert.deepStrictEqual(inspect(parser('@@@a'), ctx), [['@@@a'], '']);
26
- assert.deepStrictEqual(inspect(parser('@#'), ctx), [['@', '#'], '']);
27
- assert.deepStrictEqual(inspect(parser('@#a'), ctx), [['@', '<a class="hashtag" href="/hashtags/a">#a</a>'], '']);
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, tails, state, constraint, rewrite, open, convert, fmap, lazy } from '../../../combinator';
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
- open(
12
+ surround(
13
13
  /(?<![0-9a-z])@/yi,
14
- tails([
15
- 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),
16
- str(/[a-z][0-9a-z]*(?:[-.][0-9a-z]+)*(?![0-9a-z@#]|>>|:\S)/yi),
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
- union([
21
- constraint(State.autolink, state(State.autolink, fmap(convert(
22
- source =>
23
- `[${source}]{ ${
24
- source.includes('/')
25
- ? `https://${source.slice(1).replace('/', '/@')}`
26
- : `/${source}`
27
- } }`,
28
- unsafelink,
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), [['a'], '>>0']);
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]+)*(?![0-9a-z@#]|>>|:\S)/yi),
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
- union([
26
- constraint(State.autolink, state(State.autolink, fmap(convert(
27
- source =>
28
- `[${source}]{ ${source.includes('/')
29
- ? `/@${source.slice(2).replace('/', '/timeline?at=')}`
30
- : `?at=${source.slice(2)}`
31
- } }`,
32
- unsafelink,
33
- false),
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), [['@a'], '@']);
14
- assert.deepStrictEqual(inspect(parser('@a@b'), ctx), [['@a'], '@b']);
15
- assert.deepStrictEqual(inspect(parser('@a#'), ctx), [['@a'], '#']);
16
- assert.deepStrictEqual(inspect(parser('@a#1'), ctx), [['@a'], '#1']);
17
- assert.deepStrictEqual(inspect(parser('@a#b@'), ctx), [['@a'], '#b@']);
18
- assert.deepStrictEqual(inspect(parser('@a#1@b'), ctx), [['@a'], '#1@b']);
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, tails, sequence, some, state, constraint, verify, rewrite, open, convert, fmap, lazy } from '../../../combinator';
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
- open(
14
+ surround(
15
15
  /(?<![0-9a-z])@/yi,
16
- tails([
17
- 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),
18
- str(/[a-z][0-9a-z]*(?:[-.][0-9a-z]+)*(?![0-9a-z@]|>>|:\S)/yi),
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(open(
20
+ some(verify(surround(
23
21
  '#',
24
- verify(
25
- str(new RegExp([
26
- /(?!['_])(?:[^\p{C}\p{S}\p{P}\s]|emoji|'(?=[0-9A-Za-z])|_(?=[^'\p{C}\p{S}\p{P}\s]|emoji))+(?![0-9a-z@]|>>|:\S|[^\p{C}\p{S}\p{P}\s]|emoji)/yu.source,
27
- ].join('').replace(/emoji/g, emoji), 'yu')),
28
- ([{ value }]) => !/^[0-9]{1,4}$|^[0-9]{5}/.test(value)),
29
- false,
30
- [3 | Backtrack.autolink])),
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
- union([
33
- constraint(State.autolink, state(State.autolink, fmap(convert(
34
- source =>
35
- `[${source}]{ ${
36
- source.includes('/')
37
- ? `https://${source.slice(1, source.indexOf('#')).replace('/', '/@')}`
38
- : `/${source.slice(0, source.indexOf('#'))}`
39
- } }`,
40
- unsafelink,
41
- false),
42
- ([{ value: el }], { source, position, range = 0 }) => {
43
- const src = source.slice(position - range, position);
44
- const url = `${el.getAttribute('href')}?ch=${src.slice(src.indexOf('#') + 1).replace(/#/g, '+')}`;
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), [['a'], '@']);
14
- assert.deepStrictEqual(inspect(parser('a@+'), ctx), [['a'], '@+']);
15
- assert.deepStrictEqual(inspect(parser('a@_'), ctx), [['a'], '@_']);
16
- assert.deepStrictEqual(inspect(parser('a@-'), ctx), [['a'], '@-']);
17
- assert.deepStrictEqual(inspect(parser('a@.'), ctx), [['a'], '@.']);
18
- assert.deepStrictEqual(inspect(parser('a@b@'), ctx), [['a'], '@b@']);
19
- assert.deepStrictEqual(inspect(parser('a@bc@'), ctx), [['a'], '@bc@']);
20
- assert.deepStrictEqual(inspect(parser('a@b@c'), ctx), [['a'], '@b@c']);
21
- assert.deepStrictEqual(inspect(parser('a@b#'), ctx), [['a'], '@b#']);
22
- assert.deepStrictEqual(inspect(parser('a@b#1'), ctx), [['a'], '@b#1']);
23
- assert.deepStrictEqual(inspect(parser('a@@'), ctx), [['a@', '@'], '']);
24
- assert.deepStrictEqual(inspect(parser('a@@b'), ctx), [['a@', '<a class="account" href="/@b">@b</a>'], '']);
25
- assert.deepStrictEqual(inspect(parser('a+@b'), ctx), [['a'], '+@b']);
26
- assert.deepStrictEqual(inspect(parser('a__b@c'), ctx), [['a'], '__b@c']);
27
- assert.deepStrictEqual(inspect(parser('a..b@c'), ctx), [['a'], '..b@c']);
28
- assert.deepStrictEqual(inspect(parser('a++b@c'), ctx), [['a'], '++b@c']);
29
- assert.deepStrictEqual(inspect(parser('a@http://host'), ctx), [['a'], '@http://host']);
30
- assert.deepStrictEqual(inspect(parser('a@ttp://host'), ctx), [['a'], '@ttp://host']);
31
- assert.deepStrictEqual(inspect(parser(`a@${'b'.repeat(64)}`), ctx), [['a'], `@${'b'.repeat(64)}`]);
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][_.+-]?)(?=[0-9a-z])/yi,
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
- union([
18
- constraint(State.autolink, state(State.autolink,
19
- ({ context: { source } }) => new List([new Data(html('a', { class: 'email', href: `mailto:${source}` }, source))]))),
20
- ({ context: { source } }) => new List([new Data(source)]),
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), [['#1'], '#']);
16
- assert.deepStrictEqual(inspect(parser('#1#2'), ctx), [['#1'], '#2']);
17
- assert.deepStrictEqual(inspect(parser('#1#2#3'), ctx), [['#1'], '#2#3']);
18
- assert.deepStrictEqual(inspect(parser('#1@2'), ctx), [['#1'], '@2']);
19
- assert.deepStrictEqual(inspect(parser('#\\'), ctx), [['#'], '\\']);
20
- assert.deepStrictEqual(inspect(parser('#\\ '), ctx), [['#'], '\\ ']);
21
- assert.deepStrictEqual(inspect(parser('#\\\n'), ctx), [['#'], '\\\n']);
22
- assert.deepStrictEqual(inspect(parser('##'), ctx), [['##'], '']);
23
- assert.deepStrictEqual(inspect(parser('##1'), ctx), [['##1'], '']);
24
- assert.deepStrictEqual(inspect(parser('###1'), ctx), [['###1'], '']);
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), [['#'], '{1}']);
30
- assert.deepStrictEqual(inspect(parser('# '), ctx), [['#'], ' ']);
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
- union([
21
- constraint(State.autolink, state(State.autolink, fmap(convert(
22
- source => `[${source}]{ ${source.slice(1)} }`,
23
- unsafelink,
24
- false),
25
- ([{ value }]) => new List([new Data(define(value, { class: 'hashnum', href: null }))])))),
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), [['#a'], '#']);
16
- assert.deepStrictEqual(inspect(parser('#a#b'), ctx), [['#a'], '#b']);
17
- assert.deepStrictEqual(inspect(parser('#a#b#c'), ctx), [['#a'], '#b#c']);
18
- assert.deepStrictEqual(inspect(parser('#a@b'), ctx), [['#a'], '@b']);
19
- assert.deepStrictEqual(inspect(parser('#@'), ctx), [['#', '@'], '']);
20
- assert.deepStrictEqual(inspect(parser('#@a'), ctx), [['#', '<a class="account" href="/@a">@a</a>'], '']);
21
- assert.deepStrictEqual(inspect(parser('#\\'), ctx), [['#'], '\\']);
22
- assert.deepStrictEqual(inspect(parser('#\\ '), ctx), [['#'], '\\ ']);
23
- assert.deepStrictEqual(inspect(parser('#\\\n'), ctx), [['#'], '\\\n']);
24
- assert.deepStrictEqual(inspect(parser('##'), ctx), [['##'], '']);
25
- assert.deepStrictEqual(inspect(parser('##a'), ctx), [['##a'], '']);
26
- assert.deepStrictEqual(inspect(parser('###a'), ctx), [['###a'], '']);
27
- assert.deepStrictEqual(inspect(parser(`#'`), ctx), [['#'], `'`]);
28
- assert.deepStrictEqual(inspect(parser(`#'0`), ctx), [[`#`], `'0`]);
29
- assert.deepStrictEqual(inspect(parser(`#'00`), ctx), [[`#`], `'00`]);
30
- assert.deepStrictEqual(inspect(parser('#_'), ctx), [['#'], '_']);
31
- assert.deepStrictEqual(inspect(parser('#_a'), ctx), [['#'], '_a']);
32
- assert.deepStrictEqual(inspect(parser('#(a)'), ctx), [['#'], '(a)']);
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), [['#'], '{a}']);
38
- assert.deepStrictEqual(inspect(parser('#12345a'), ctx), [['#12345a'], '']);
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, open, convert, fmap, lazy } from '../../../combinator';
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
- open(
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
- verify(
20
- str(new RegExp([
21
- /(?!['_])(?:[^\p{C}\p{S}\p{P}\s]|emoji|'(?=[0-9A-Za-z])|_(?=[^'\p{C}\p{S}\p{P}\s]|emoji))+(?![0-9a-z@#]|>>|:\S|[^\p{C}\p{S}\p{P}\s]|emoji)/yu.source,
22
- ].join('').replace(/emoji/g, emoji), 'yu')),
23
- ([{ value }]) => !/^[0-9]{1,4}$|^[0-9]{5}/.test(value)),
24
- false,
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
- union([
27
- constraint(State.autolink, state(State.autolink, fmap(convert(
28
- source => `[${source}]{ ${`/hashtags/${source.slice(1)}`} }`,
29
- unsafelink,
30
- false),
31
- ([{ value }]) => new List([new Data(define(value, { class: 'hashtag' }))])))),
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(' http'), ctx), [['http'], '']);
14
- assert.deepStrictEqual(inspect(parser(' ttp'), ctx), [['ttp'], '']);
15
- assert.deepStrictEqual(inspect(parser(' http://'), ctx), [['http:'], '//']);
16
- assert.deepStrictEqual(inspect(parser(' http://['), ctx), [['http:'], '//[']);
17
- assert.deepStrictEqual(inspect(parser(' http://]'), ctx), [['http:'], '//]']);
18
- assert.deepStrictEqual(inspect(parser(' Http://host'), ctx), [['Http:'], '//host']);
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, Data } from '../../../combinator/data/parser';
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][.+-]?)https?:\/\/(?=[\x21-\x7E])/y,
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
- ({ context: { source } }) => new List([new Data(source)]),
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
- ({ context: { source } }) => new List([new Data(source)]),
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][.+-]?)!?[0-9a-z]/yi.source,
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
  ]))));