securemark 0.256.0 → 0.257.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.
Files changed (48) hide show
  1. package/CHANGELOG.md +6 -0
  2. package/dist/index.js +195 -143
  3. package/markdown.d.ts +18 -11
  4. package/package.json +1 -1
  5. package/src/combinator/control/manipulation/context.ts +13 -2
  6. package/src/combinator/control/manipulation/resource.ts +36 -2
  7. package/src/combinator/control/manipulation/surround.ts +6 -6
  8. package/src/combinator/data/parser/inits.ts +1 -1
  9. package/src/combinator/data/parser/sequence.ts +1 -1
  10. package/src/combinator/data/parser/some.ts +16 -38
  11. package/src/combinator/data/parser.ts +34 -18
  12. package/src/debug.test.ts +2 -2
  13. package/src/parser/api/bind.ts +9 -11
  14. package/src/parser/api/parse.test.ts +48 -11
  15. package/src/parser/block.ts +1 -1
  16. package/src/parser/inline/annotation.test.ts +6 -5
  17. package/src/parser/inline/annotation.ts +8 -5
  18. package/src/parser/inline/autolink/url.ts +6 -6
  19. package/src/parser/inline/bracket.test.ts +11 -7
  20. package/src/parser/inline/bracket.ts +10 -10
  21. package/src/parser/inline/comment.test.ts +4 -3
  22. package/src/parser/inline/comment.ts +4 -4
  23. package/src/parser/inline/deletion.ts +3 -3
  24. package/src/parser/inline/emphasis.ts +3 -3
  25. package/src/parser/inline/emstrong.ts +4 -5
  26. package/src/parser/inline/extension/index.test.ts +1 -0
  27. package/src/parser/inline/extension/index.ts +8 -7
  28. package/src/parser/inline/extension/indexer.ts +3 -5
  29. package/src/parser/inline/extension/label.ts +1 -1
  30. package/src/parser/inline/extension/placeholder.test.ts +1 -0
  31. package/src/parser/inline/extension/placeholder.ts +4 -4
  32. package/src/parser/inline/html.test.ts +2 -0
  33. package/src/parser/inline/html.ts +5 -5
  34. package/src/parser/inline/insertion.ts +3 -3
  35. package/src/parser/inline/link.test.ts +1 -0
  36. package/src/parser/inline/link.ts +6 -6
  37. package/src/parser/inline/mark.ts +3 -3
  38. package/src/parser/inline/math.test.ts +21 -14
  39. package/src/parser/inline/math.ts +4 -15
  40. package/src/parser/inline/media.test.ts +0 -2
  41. package/src/parser/inline/media.ts +6 -6
  42. package/src/parser/inline/reference.test.ts +5 -5
  43. package/src/parser/inline/reference.ts +18 -6
  44. package/src/parser/inline/ruby.ts +29 -27
  45. package/src/parser/inline/strong.ts +3 -3
  46. package/src/parser/inline/template.ts +4 -4
  47. package/src/parser/inline.test.ts +11 -8
  48. package/src/parser/util.ts +17 -1
@@ -7,11 +7,9 @@ describe('Unit: parser/inline/bracket', () => {
7
7
  const parser = (source: string) => some(bracket)(source, {});
8
8
 
9
9
  it('(', () => {
10
- assert.deepStrictEqual(inspect(parser('(')), [['('], '']);
10
+ assert.deepStrictEqual(inspect(parser('(')), [['', '('], '']);
11
11
  assert.deepStrictEqual(inspect(parser('()')), [['<span class="paren">()</span>'], '']);
12
- assert.deepStrictEqual(inspect(parser('(a')), [['(', 'a'], '']);
13
- assert.deepStrictEqual(inspect(parser('(\\a)')), [['<span class="paren">(a)</span>'], '']);
14
- assert.deepStrictEqual(inspect(parser(')')), undefined);
12
+ assert.deepStrictEqual(inspect(parser('(a')), [['', '(', 'a'], '']);
15
13
  assert.deepStrictEqual(inspect(parser('(0)')), [['(', '0', ')'], '']);
16
14
  assert.deepStrictEqual(inspect(parser('(1)')), [['(', '1', ')'], '']);
17
15
  assert.deepStrictEqual(inspect(parser('(10)')), [['(', '10', ')'], '']);
@@ -39,6 +37,9 @@ describe('Unit: parser/inline/bracket', () => {
39
37
  assert.deepStrictEqual(inspect(parser('(Name, Name)')), [['(', 'Name, Name', ')'], '']);
40
38
  assert.deepStrictEqual(inspect(parser('(ABBR)')), [['(', 'ABBR', ')'], '']);
41
39
  assert.deepStrictEqual(inspect(parser('(ABBR, ABBR)')), [['(', 'ABBR, ABBR', ')'], '']);
40
+ assert.deepStrictEqual(inspect(parser('(\\a)')), [['<span class="paren">(a)</span>'], '']);
41
+ assert.deepStrictEqual(inspect(parser('(==)')), [['<span class="paren">(==)</span>'], '']);
42
+ assert.deepStrictEqual(inspect(parser(')')), undefined);
42
43
  assert.deepStrictEqual(inspect(parser('(1,2)')), [['(', '1,2', ')'], '']);
43
44
  assert.deepStrictEqual(inspect(parser('(0-1)')), [['(', '0-1', ')'], '']);
44
45
  assert.deepStrictEqual(inspect(parser('(0.1)')), [['(', '0.1', ')'], '']);
@@ -49,10 +50,11 @@ describe('Unit: parser/inline/bracket', () => {
49
50
  });
50
51
 
51
52
  it('[', () => {
52
- assert.deepStrictEqual(inspect(parser('[')), [['['], '']);
53
+ assert.deepStrictEqual(inspect(parser('[')), [['', '['], '']);
53
54
  assert.deepStrictEqual(inspect(parser('[]')), [['[', ']'], '']);
54
- assert.deepStrictEqual(inspect(parser('[a')), [['[', 'a'], '']);
55
+ assert.deepStrictEqual(inspect(parser('[a')), [['', '[', 'a'], '']);
55
56
  assert.deepStrictEqual(inspect(parser('[a]')), [['[', 'a', ']'], '']);
57
+ assert.deepStrictEqual(inspect(parser('[==]')), [['[', '==', ']'], '']);
56
58
  assert.deepStrictEqual(inspect(parser(']')), undefined);
57
59
  });
58
60
 
@@ -61,6 +63,7 @@ describe('Unit: parser/inline/bracket', () => {
61
63
  assert.deepStrictEqual(inspect(parser('{}')), [['{', '}'], '']);
62
64
  assert.deepStrictEqual(inspect(parser('{a')), [['{', 'a'], '']);
63
65
  assert.deepStrictEqual(inspect(parser('{a}')), [['{', 'a', '}'], '']);
66
+ assert.deepStrictEqual(inspect(parser('{==}')), [['{', '==', '}'], '']);
64
67
  assert.deepStrictEqual(inspect(parser('}')), undefined);
65
68
  });
66
69
 
@@ -69,7 +72,8 @@ describe('Unit: parser/inline/bracket', () => {
69
72
  assert.deepStrictEqual(inspect(parser('""')), [['"', '"'], '']);
70
73
  assert.deepStrictEqual(inspect(parser('"a')), [['"', 'a'], '']);
71
74
  assert.deepStrictEqual(inspect(parser('"a"')), [['"', 'a', '"'], '']);
72
- assert.deepStrictEqual(inspect(parser('"(")"')), [['"', '(', '"'], ')"']);
75
+ assert.deepStrictEqual(inspect(parser('"(")"')), [['"', '', '(', '"'], ')"']);
76
+ assert.deepStrictEqual(inspect(parser('"(("')), [['"', '((', '"'], '']);
73
77
  assert.deepStrictEqual(inspect(parser('"(\\")"')), [['"', '<span class="paren">(")</span>', '"'], '']);
74
78
  assert.deepStrictEqual(inspect(parser('"(\n)"')), [['"', '<span class="paren">(<br>)</span>', '"'], '']);
75
79
  assert.deepStrictEqual(inspect(parser('"(\\\n)"')), [['"', '<span class="paren">(<span class="linebreak"> </span>)</span>', '"'], '']);
@@ -1,6 +1,6 @@
1
1
  import { undefined } from 'spica/global';
2
2
  import { BracketParser } from '../inline';
3
- import { union, some, creator, surround, lazy } from '../../combinator';
3
+ import { union, some, precedence, creator, surround, lazy } from '../../combinator';
4
4
  import { inline } from '../inline';
5
5
  import { str } from '../source';
6
6
  import { html, defrag } from 'typed-dom/dom';
@@ -9,22 +9,22 @@ import { unshift, push } from 'spica/array';
9
9
  const index = /^[0-9A-Za-z]+(?:(?:[.-]|, )[0-9A-Za-z]+)*/;
10
10
 
11
11
  export const bracket: BracketParser = lazy(() => creator(0, union([
12
- surround(str('('), str(index), str(')')),
13
- surround(str('('), some(inline, ')'), str(')'), true,
12
+ surround(str('('), precedence(3, str(index)), str(')')),
13
+ surround(str('('), precedence(3, some(inline, ')', [[')', 3]])), str(')'), true,
14
14
  ([as, bs = [], cs], rest) => [[html('span', { class: 'paren' }, defrag(push(unshift(as, bs), cs)))], rest],
15
- ([as, bs = []], rest) => [unshift(as, bs), rest]),
16
- surround(str('('), str(new RegExp(index.source.replace(', ', '[,、]').replace(/[09AZaz.]|\-(?!\w)/g, c => c.trimStart() && String.fromCharCode(c.charCodeAt(0) + 0xFEE0)))), str(')')),
17
- surround(str('('), some(inline, ')'), str(')'), true,
15
+ ([as, bs = []], rest) => [unshift([''], unshift(as, bs)), rest]),
16
+ surround(str('('), precedence(3, str(new RegExp(index.source.replace(', ', '[,、]').replace(/[09AZaz.]|\-(?!\w)/g, c => c.trimStart() && String.fromCharCode(c.charCodeAt(0) + 0xFEE0))))), str(')')),
17
+ surround(str('('), precedence(3, some(inline, ')', [[')', 3]])), str(')'), true,
18
18
  ([as, bs = [], cs], rest) => [[html('span', { class: 'paren' }, defrag(push(unshift(as, bs), cs)))], rest],
19
19
  ([as, bs = []], rest) => [unshift(as, bs), rest]),
20
- surround(str('['), some(inline, ']'), str(']'), true,
20
+ surround(str('['), precedence(3, some(inline, ']', [[']', 3]])), str(']'), true,
21
21
  undefined,
22
- ([as, bs = []], rest) => [unshift(as, bs), rest]),
23
- surround(str('{'), some(inline, '}'), str('}'), true,
22
+ ([as, bs = []], rest) => [unshift([''], unshift(as, bs)), rest]),
23
+ surround(str('{'), precedence(3, some(inline, '}', [['}', 3]])), str('}'), true,
24
24
  undefined,
25
25
  ([as, bs = []], rest) => [unshift(as, bs), rest]),
26
26
  // Control media blinking in editing rather than control confusion of pairs of quote marks.
27
- surround(str('"'), some(inline, '"', '"'), str('"'), true,
27
+ surround(str('"'), precedence(8, some(inline, '"', [['"', 8]])), str('"'), true,
28
28
  undefined,
29
29
  ([as, bs = []], rest) => [unshift(as, bs), rest]),
30
30
  ])));
@@ -16,12 +16,12 @@ describe('Unit: parser/inline/comment', () => {
16
16
  assert.deepStrictEqual(inspect(parser('[% ')), [['[%'], '']);
17
17
  assert.deepStrictEqual(inspect(parser('[% \n a')), [['[%', '<br>', ' ', 'a'], '']);
18
18
  assert.deepStrictEqual(inspect(parser('[%%]')), undefined);
19
- assert.deepStrictEqual(inspect(parser('[% [%')), [['[%', ' ', '[', '%'], '']);
19
+ assert.deepStrictEqual(inspect(parser('[% [%')), [['[%', ' ', '', '[', '%'], '']);
20
20
  assert.deepStrictEqual(inspect(parser('[% [% ')), [['[%', ' ', '[%'], '']);
21
21
  assert.deepStrictEqual(inspect(parser('[% [% a')), [['[%', ' ', '[%', ' ', 'a'], '']);
22
22
  assert.deepStrictEqual(inspect(parser('[% [% a %]')), [['[%', ' ', '<span class="comment"><input type="checkbox"><span>[% a %]</span></span>'], '']);
23
- assert.deepStrictEqual(inspect(parser('[% a[%')), [['[%', ' ', 'a', '[', '%'], '']);
24
- assert.deepStrictEqual(inspect(parser('[% a [%')), [['[%', ' ', 'a', ' ', '[', '%'], '']);
23
+ assert.deepStrictEqual(inspect(parser('[% a[%')), [['[%', ' ', 'a', '', '[', '%'], '']);
24
+ assert.deepStrictEqual(inspect(parser('[% a [%')), [['[%', ' ', 'a', ' ', '', '[', '%'], '']);
25
25
  assert.deepStrictEqual(inspect(parser('[% a [% ')), [['[%', ' ', 'a', ' ', '[%'], '']);
26
26
  assert.deepStrictEqual(inspect(parser('[% a [% b')), [['[%', ' ', 'a', ' ', '[%', ' ', 'b'], '']);
27
27
  assert.deepStrictEqual(inspect(parser('[% a [%% b')), [['[%', ' ', 'a', ' ', '[%%', ' ', 'b'], '']);
@@ -55,6 +55,7 @@ describe('Unit: parser/inline/comment', () => {
55
55
  assert.deepStrictEqual(inspect(parser('[% &a; %]')), [['<span class="comment"><input type="checkbox"><span>[% <span class="invalid">&amp;a;</span> %]</span></span>'], '']);
56
56
  assert.deepStrictEqual(inspect(parser('[% &copy; %]')), [['<span class="comment"><input type="checkbox"><span>[% © %]</span></span>'], '']);
57
57
  assert.deepStrictEqual(inspect(parser('[% &amp;copy; %]')), [['<span class="comment"><input type="checkbox"><span>[% &amp;copy; %]</span></span>'], '']);
58
+ assert.deepStrictEqual(inspect(parser('[% [ %]')), [['<span class="comment"><input type="checkbox"><span>[% [ %]</span></span>'], '']);
58
59
  assert.deepStrictEqual(inspect(parser('[% \\ a %]')), [['<span class="comment"><input type="checkbox"><span>[% a %]</span></span>'], '']);
59
60
  });
60
61
 
@@ -1,18 +1,18 @@
1
1
  import { CommentParser } from '../inline';
2
- import { union, some, validate, creator, surround, open, close, match, lazy } from '../../combinator';
2
+ import { union, some, validate, precedence, creator, surround, open, close, match, lazy } from '../../combinator';
3
3
  import { inline } from '../inline';
4
4
  import { text, str } from '../source';
5
5
  import { html, defrag } from 'typed-dom/dom';
6
6
  import { memoize } from 'spica/memoize';
7
7
  import { unshift, push } from 'spica/array';
8
8
 
9
- export const comment: CommentParser = lazy(() => creator(validate('[%', match(
9
+ export const comment: CommentParser = lazy(() => validate('[%', creator(precedence(4, match(
10
10
  /^\[(%+)\s/,
11
11
  memoize(
12
12
  ([, fence]) =>
13
13
  surround(
14
14
  open(str(`[${fence}`), some(text, new RegExp(String.raw`^\s+${fence}\]|^\S`)), true),
15
- some(union([inline]), new RegExp(String.raw`^\s+${fence}\]`)),
15
+ some(union([inline]), new RegExp(String.raw`^\s+${fence}\]`), [[new RegExp(String.raw`^\s+${fence}\]`), 4]]),
16
16
  close(some(text, /^\S/), str(`${fence}]`)), true,
17
17
  ([as, bs = [], cs], rest) => [[
18
18
  html('span', { class: 'comment' }, [
@@ -21,4 +21,4 @@ export const comment: CommentParser = lazy(() => creator(validate('[%', match(
21
21
  ]),
22
22
  ], rest],
23
23
  ([as, bs = []], rest) => [unshift(as, bs), rest]),
24
- ([, fence]) => fence.length, [])))));
24
+ ([, fence]) => fence.length, []))))));
@@ -1,12 +1,12 @@
1
1
  import { DeletionParser } from '../inline';
2
- import { union, some, creator, surround, open, lazy } from '../../combinator';
2
+ import { union, some, precedence, creator, surround, open, lazy } from '../../combinator';
3
3
  import { inline } from '../inline';
4
4
  import { str } from '../source';
5
5
  import { blankWith } from '../util';
6
6
  import { html, defrag } from 'typed-dom/dom';
7
7
  import { unshift } from 'spica/array';
8
8
 
9
- export const deletion: DeletionParser = lazy(() => creator(surround(
9
+ export const deletion: DeletionParser = lazy(() => creator(precedence(2, surround(
10
10
  str('~~'),
11
11
  some(union([
12
12
  some(inline, blankWith('\n', '~~')),
@@ -14,4 +14,4 @@ export const deletion: DeletionParser = lazy(() => creator(surround(
14
14
  ])),
15
15
  str('~~'), false,
16
16
  ([, bs], rest) => [[html('del', defrag(bs))], rest],
17
- ([as, bs], rest) => [unshift(as, bs), rest])));
17
+ ([as, bs], rest) => [unshift(as, bs), rest]))));
@@ -1,5 +1,5 @@
1
1
  import { EmphasisParser } from '../inline';
2
- import { union, some, creator, surround, open, lazy } from '../../combinator';
2
+ import { union, some, precedence, creator, surround, open, lazy } from '../../combinator';
3
3
  import { inline } from '../inline';
4
4
  import { emstrong } from './emstrong';
5
5
  import { strong } from './strong';
@@ -8,7 +8,7 @@ import { startTight, blankWith } from '../util';
8
8
  import { html, defrag } from 'typed-dom/dom';
9
9
  import { unshift } from 'spica/array';
10
10
 
11
- export const emphasis: EmphasisParser = lazy(() => creator(surround(
11
+ export const emphasis: EmphasisParser = lazy(() => creator(precedence(1, surround(
12
12
  str('*'),
13
13
  startTight(some(union([
14
14
  strong,
@@ -21,4 +21,4 @@ export const emphasis: EmphasisParser = lazy(() => creator(surround(
21
21
  ])), '*'),
22
22
  str('*'), false,
23
23
  ([, bs], rest) => [[html('em', defrag(bs))], rest],
24
- ([as, bs], rest) => [unshift(as, bs), rest])));
24
+ ([as, bs], rest) => [unshift(as, bs), rest]))));
@@ -1,7 +1,6 @@
1
- import { MarkdownParser } from '../../../markdown';
2
1
  import { EmStrongParser, EmphasisParser, StrongParser } from '../inline';
3
2
  import { Result, IntermediateParser } from '../../combinator/data/parser';
4
- import { union, some, creator, surround, open, lazy, bind } from '../../combinator';
3
+ import { union, some, precedence, creator, surround, open, lazy, bind } from '../../combinator';
5
4
  import { inline } from '../inline';
6
5
  import { strong } from './strong';
7
6
  import { emphasis } from './emphasis';
@@ -27,14 +26,14 @@ const subemphasis: IntermediateParser<EmphasisParser> = lazy(() => some(union([
27
26
  ])),
28
27
  ])));
29
28
 
30
- export const emstrong: EmStrongParser = lazy(() => creator(surround(
29
+ export const emstrong: EmStrongParser = lazy(() => creator(precedence(1, surround(
31
30
  str('***'),
32
31
  startTight(some(union([
33
32
  some(inline, blankWith('*')),
34
33
  open(some(inline, '*'), inline),
35
34
  ]))),
36
35
  str(/^\*{1,3}/), false,
37
- ([, bs, cs], rest, context): Result<HTMLElement | string, MarkdownParser.Context> => {
36
+ ([, bs, cs], rest, context): Result<HTMLElement | string, typeof context> => {
38
37
  assert(cs.length === 1);
39
38
  switch (cs[0]) {
40
39
  case '***':
@@ -58,4 +57,4 @@ export const emstrong: EmStrongParser = lazy(() => creator(surround(
58
57
  }
59
58
  assert(false);
60
59
  },
61
- ([as, bs], rest) => [unshift(as, bs), rest])));
60
+ ([as, bs], rest) => [unshift(as, bs), rest]))));
@@ -52,6 +52,7 @@ describe('Unit: parser/inline/extension/index', () => {
52
52
  assert.deepStrictEqual(inspect(parser('[#\\]]')), [['<a class="index" href="#index:]">]</a>'], '']);
53
53
  assert.deepStrictEqual(inspect(parser('[#\\\\]')), [['<a class="index" href="#index:\\">\\</a>'], '']);
54
54
  assert.deepStrictEqual(inspect(parser('[#A]')), [['<a class="index" href="#index:A">A</a>'], '']);
55
+ assert.deepStrictEqual(inspect(parser('[#==]')), [['<a class="index" href="#index:==">==</a>'], '']);
55
56
  assert.deepStrictEqual(inspect(parser('[#*A*]')), [['<a class="index" href="#index:A"><em>A</em></a>'], '']);
56
57
  assert.deepStrictEqual(inspect(parser('[#`A`]')), [['<a class="index" href="#index:`A`"><code data-src="`A`">A</code></a>'], '']);
57
58
  assert.deepStrictEqual(inspect(parser('[#${A}$]')), [['<a class="index" href="#index:${A}$"><span class="math" translate="no" data-src="${A}$">${A}$</span></a>'], '']);
@@ -1,6 +1,6 @@
1
1
  import { undefined } from 'spica/global';
2
2
  import { ExtensionParser } from '../../inline';
3
- import { union, some, validate, guard, context, creator, surround, open, lazy, fmap } from '../../../combinator';
3
+ import { union, some, validate, guard, context, precedence, creator, surround, open, lazy, fmap } from '../../../combinator';
4
4
  import { inline } from '../../inline';
5
5
  import { indexee, identity } from './indexee';
6
6
  import { txt, str, stropt } from '../../source';
@@ -9,7 +9,7 @@ import { html, define, defrag } from 'typed-dom/dom';
9
9
 
10
10
  import IndexParser = ExtensionParser.IndexParser;
11
11
 
12
- export const index: IndexParser = lazy(() => creator(validate('[#', fmap(indexee(fmap(surround(
12
+ export const index: IndexParser = lazy(() => validate('[#', creator(precedence(3, fmap(indexee(surround(
13
13
  '[#',
14
14
  guard(context => context.syntax?.inline?.index ?? true,
15
15
  startTight(
@@ -25,9 +25,10 @@ export const index: IndexParser = lazy(() => creator(validate('[#', fmap(indexee
25
25
  open(stropt(/^\|?/), trimBlankEnd(some(union([
26
26
  signature,
27
27
  inline,
28
- ]), ']', /^\\?\n/)), true)))),
29
- ']'),
30
- ns => [html('a', defrag(ns))])),
28
+ ]), ']', [[/^\\?\n/, 9], [']', 3]])), true)))),
29
+ ']',
30
+ false,
31
+ ([, ns], rest) => [[html('a', defrag(ns))], rest])),
31
32
  ([el]: [HTMLAnchorElement]) => [
32
33
  define(el,
33
34
  {
@@ -36,7 +37,7 @@ export const index: IndexParser = lazy(() => creator(validate('[#', fmap(indexee
36
37
  href: el.id ? `#${el.id}` : undefined,
37
38
  },
38
39
  el.childNodes),
39
- ]))));
40
+ ])))));
40
41
 
41
42
  const signature: IndexParser.SignatureParser = lazy(() => creator(fmap(open(
42
43
  '|#',
@@ -49,5 +50,5 @@ const bracket: IndexParser.SignatureParser.BracketParser = lazy(() => creator(un
49
50
  surround(str('('), some(union([bracket, txt]), ')'), str(')'), true),
50
51
  surround(str('['), some(union([bracket, txt]), ']'), str(']'), true),
51
52
  surround(str('{'), some(union([bracket, txt]), '}'), str('}'), true),
52
- surround(str('"'), some(txt, '"'), str('"'), true),
53
+ surround(str('"'), precedence(8, some(txt, '"')), str('"'), true),
53
54
  ])));
@@ -1,14 +1,12 @@
1
1
  import { ExtensionParser } from '../../inline';
2
- import { union, verify, focus, creator, context, surround, fmap } from '../../../combinator';
2
+ import { union, verify, focus, creator, surround, fmap } from '../../../combinator';
3
3
  import { index } from './index';
4
+ import { clean } from '../../util';
4
5
  import { html } from 'typed-dom/dom';
5
6
 
6
7
  export const indexer: ExtensionParser.IndexerParser = creator(fmap(verify(surround(
7
8
  /^\s+(?=\[#\S)/,
8
- context({ syntax: { inline: {
9
- index: true,
10
- }}},
11
- union([
9
+ clean(union([
12
10
  focus('[#]', () => [[html('a', { href: '#' })], '']),
13
11
  index,
14
12
  ])),
@@ -11,7 +11,7 @@ export const segment: ExtensionParser.LabelParser.SegmentParser = clear(validate
11
11
  body,
12
12
  ])));
13
13
 
14
- export const label: ExtensionParser.LabelParser = creator(validate(['[$', '$'], fmap(
14
+ export const label: ExtensionParser.LabelParser = validate(['[$', '$'], creator(fmap(
15
15
  guard(context => context.syntax?.inline?.label ?? true,
16
16
  union([
17
17
  surround('[', body, ']'),
@@ -45,6 +45,7 @@ describe('Unit: parser/inline/extension/placeholder', () => {
45
45
  assert.deepStrictEqual(inspect(parser('[^a\\ \\ ]')), [['<span class="invalid">a </span>'], '']);
46
46
  assert.deepStrictEqual(inspect(parser('[^a<wbr>]')), [['<span class="invalid">a<wbr></span>'], '']);
47
47
  assert.deepStrictEqual(inspect(parser('[^a<wbr><wbr>]')), [['<span class="invalid">a<wbr><wbr></span>'], '']);
48
+ assert.deepStrictEqual(inspect(parser('[^==]')), [['<span class="invalid">==</span>'], '']);
48
49
  assert.deepStrictEqual(inspect(parser('[^a[% b %]]')), [['<span class="invalid">a<span class="comment"><input type="checkbox"><span>[% b %]</span></span></span>'], '']);
49
50
  assert.deepStrictEqual(inspect(parser('[^a[% b %][% c %]]')), [['<span class="invalid">a<span class="comment"><input type="checkbox"><span>[% b %]</span></span><span class="comment"><input type="checkbox"><span>[% c %]</span></span></span>'], '']);
50
51
  assert.deepStrictEqual(inspect(parser('[^\\]]')), [['<span class="invalid">]</span>'], '']);
@@ -1,5 +1,5 @@
1
1
  import { ExtensionParser } from '../../inline';
2
- import { union, some, validate, creator, surround, lazy } from '../../../combinator';
2
+ import { union, some, validate, precedence, creator, surround, lazy } from '../../../combinator';
3
3
  import { inline } from '../../inline';
4
4
  import { str } from '../../source';
5
5
  import { startTight } from '../../util';
@@ -10,9 +10,9 @@ import { unshift } from 'spica/array';
10
10
 
11
11
  // All syntax surrounded by square brackets shouldn't contain line breaks.
12
12
 
13
- export const placeholder: ExtensionParser.PlaceholderParser = lazy(() => creator(validate(['[:', '[^'], surround(
13
+ export const placeholder: ExtensionParser.PlaceholderParser = lazy(() => validate(['[:', '[^'], creator(precedence(3, surround(
14
14
  str(/^\[[:^]/),
15
- startTight(some(union([inline]), ']', /^\\?\n/)),
15
+ startTight(some(union([inline]), ']', [[/^\\?\n/, 9], [']', 3]])),
16
16
  str(']'), false,
17
17
  ([as, bs], rest) => [[
18
18
  html('span', {
@@ -22,4 +22,4 @@ export const placeholder: ExtensionParser.PlaceholderParser = lazy(() => creator
22
22
  'data-invalid-message': `Reserved start symbol "${as[0][1]}" cannot be used in "[]"`,
23
23
  }, defrag(bs)),
24
24
  ], rest],
25
- ([as, bs], rest) => [unshift(as, bs), rest]))));
25
+ ([as, bs], rest) => [unshift(as, bs), rest])))));
@@ -25,6 +25,7 @@ describe('Unit: parser/inline/html', () => {
25
25
  assert.deepStrictEqual(inspect(parser('<a,b>')), undefined);
26
26
  assert.deepStrictEqual(inspect(parser('<a, b>')), undefined);
27
27
  assert.deepStrictEqual(inspect(parser('<T>')), undefined);
28
+ assert.deepStrictEqual(inspect(parser('<bdi>')), [['<span class="invalid">&lt;bdi&gt;</span>'], '']);
28
29
  assert.deepStrictEqual(inspect(parser('<bdi>z')), [['<span class="invalid">&lt;bdi&gt;z</span>'], '']);
29
30
  assert.deepStrictEqual(inspect(parser('<bdi></bdi>')), [['<span class="invalid">&lt;bdi&gt;&lt;/bdi&gt;</span>'], '']);
30
31
  assert.deepStrictEqual(inspect(parser('<bdi> </bdi>')), [['<span class="invalid">&lt;bdi&gt; &lt;/bdi&gt;</span>'], '']);
@@ -76,6 +77,7 @@ describe('Unit: parser/inline/html', () => {
76
77
  });
77
78
 
78
79
  it('nest', () => {
80
+ assert.deepStrictEqual(inspect(parser('<bdi>[% </bdi>')), [['<bdi>[% </bdi>'], '']);
79
81
  assert.deepStrictEqual(inspect(parser('<bdi><bdi>a</bdi></bdi>')), [['<bdi><bdi>a</bdi></bdi>'], '']);
80
82
  assert.deepStrictEqual(inspect(parser('<bdi>a<bdi>b</bdi>c</bdi>')), [['<bdi>a<bdi>b</bdi>c</bdi>'], '']);
81
83
  assert.deepStrictEqual(inspect(parser('<bdi>`a`</bdi>')), [['<bdi><code data-src="`a`">a</code></bdi>'], '']);
@@ -1,6 +1,6 @@
1
1
  import { undefined, Object } from 'spica/global';
2
2
  import { HTMLParser } from '../inline';
3
- import { union, subsequence, some, validate, focus, creator, surround, open, match, lazy } from '../../combinator';
3
+ import { union, subsequence, some, validate, focus, precedence, creator, surround, open, match, lazy } from '../../combinator';
4
4
  import { inline } from '../inline';
5
5
  import { str } from '../source';
6
6
  import { isStartLooseNodes, blankWith } from '../util';
@@ -18,7 +18,7 @@ const attrspecs = {
18
18
  Object.setPrototypeOf(attrspecs, null);
19
19
  Object.values(attrspecs).forEach(o => Object.setPrototypeOf(o, null));
20
20
 
21
- export const html: HTMLParser = lazy(() => creator(validate('<', validate(/^<[a-z]+(?=[^\S\n]|>)/, union([
21
+ export const html: HTMLParser = lazy(() => validate('<', validate(/^<[a-z]+(?=[^\S\n]|>)/, creator(precedence(5, union([
22
22
  focus(
23
23
  '<wbr>',
24
24
  () => [[h('wbr')], '']),
@@ -34,7 +34,7 @@ export const html: HTMLParser = lazy(() => creator(validate('<', validate(/^<[a-
34
34
  str(`<${tag}`), some(attribute), str(/^[^\S\n]*>/), true),
35
35
  subsequence([
36
36
  focus(/^[^\S\n]*\n/, some(inline)),
37
- some(open(/^\n?/, some(inline, blankWith('\n', `</${tag}>`)), true)),
37
+ some(open(/^\n?/, some(inline, blankWith('\n', `</${tag}>`), [[blankWith('\n', `</${tag}>`), 5]]), true)),
38
38
  ]),
39
39
  str(`</${tag}>`), true,
40
40
  ([as, bs = [], cs], rest) =>
@@ -50,7 +50,7 @@ export const html: HTMLParser = lazy(() => creator(validate('<', validate(/^<[a-
50
50
  str(`<${tag}`), some(attribute), str(/^[^\S\n]*>/), true),
51
51
  subsequence([
52
52
  focus(/^[^\S\n]*\n/, some(inline)),
53
- some(inline, `</${tag}>`),
53
+ some(inline, `</${tag}>`, [[`</${tag}>`, 5]]),
54
54
  ]),
55
55
  str(`</${tag}>`), true,
56
56
  ([as, bs = [], cs], rest) =>
@@ -59,7 +59,7 @@ export const html: HTMLParser = lazy(() => creator(validate('<', validate(/^<[a-
59
59
  [[elem(tag, as, bs, [])], rest]),
60
60
  ([, tag]) => tag,
61
61
  new Cache(10000))),
62
- ])))));
62
+ ]))))));
63
63
 
64
64
  export const attribute: HTMLParser.TagParser.AttributeParser = union([
65
65
  str(/^[^\S\n]+[a-z]+(?:-[a-z]+)*(?:="(?:\\[^\n]|[^\\\n"])*")?(?=[^\S\n]|>)/),
@@ -1,12 +1,12 @@
1
1
  import { InsertionParser } from '../inline';
2
- import { union, some, creator, surround, open, lazy } from '../../combinator';
2
+ import { union, some, precedence, creator, surround, open, lazy } from '../../combinator';
3
3
  import { inline } from '../inline';
4
4
  import { str } from '../source';
5
5
  import { blankWith } from '../util';
6
6
  import { html, defrag } from 'typed-dom/dom';
7
7
  import { unshift } from 'spica/array';
8
8
 
9
- export const insertion: InsertionParser = lazy(() => creator(surround(
9
+ export const insertion: InsertionParser = lazy(() => creator(precedence(2, surround(
10
10
  str('++'),
11
11
  some(union([
12
12
  some(inline, blankWith('\n', '++')),
@@ -14,4 +14,4 @@ export const insertion: InsertionParser = lazy(() => creator(surround(
14
14
  ])),
15
15
  str('++'), false,
16
16
  ([, bs], rest) => [[html('ins', defrag(bs))], rest],
17
- ([as, bs], rest) => [unshift(as, bs), rest])));
17
+ ([as, bs], rest) => [unshift(as, bs), rest]))));
@@ -151,6 +151,7 @@ describe('Unit: parser/inline/link', () => {
151
151
  });
152
152
 
153
153
  it('nest', () => {
154
+ assert.deepStrictEqual(inspect(parser('[*]{/}')), [['<a href="/">*</a>'], '']);
154
155
  assert.deepStrictEqual(inspect(parser('[\\[]{/}')), [['<a href="/">[</a>'], '']);
155
156
  assert.deepStrictEqual(inspect(parser('[\\]]{/}')), [['<a href="/">]</a>'], '']);
156
157
  assert.deepStrictEqual(inspect(parser('[[]{a}]{a}')), [['<a href="a">[]{a}</a>'], '']);
@@ -1,7 +1,7 @@
1
1
  import { undefined, location, encodeURI, decodeURI, Location } from 'spica/global';
2
2
  import { LinkParser } from '../inline';
3
3
  import { eval } from '../../combinator/data/parser';
4
- import { union, inits, tails, some, validate, guard, context, creator, surround, open, dup, reverse, lazy, fmap, bind } from '../../combinator';
4
+ import { union, inits, tails, some, validate, guard, context, precedence, creator, surround, open, dup, reverse, lazy, fmap, bind } from '../../combinator';
5
5
  import { inline, media, shortmedia } from '../inline';
6
6
  import { attributes } from './html';
7
7
  import { autolink } from '../autolink';
@@ -15,7 +15,7 @@ const optspec = {
15
15
  } as const;
16
16
  Object.setPrototypeOf(optspec, null);
17
17
 
18
- export const link: LinkParser = lazy(() => creator(10, validate(['[', '{'], bind(
18
+ export const link: LinkParser = lazy(() => validate(['[', '{'], creator(10, precedence(3, bind(
19
19
  guard(context => context.syntax?.inline?.link ?? true,
20
20
  reverse(tails([
21
21
  context({ syntax: { inline: {
@@ -36,7 +36,7 @@ export const link: LinkParser = lazy(() => creator(10, validate(['[', '{'], bind
36
36
  media: false,
37
37
  autolink: false,
38
38
  }}},
39
- trimBlankStart(some(inline, ']', /^\\?\n/))),
39
+ trimBlankStart(some(inline, ']', [[/^\\?\n/, 9], [']', 3]]))),
40
40
  ']',
41
41
  true),
42
42
  ]))),
@@ -60,7 +60,7 @@ export const link: LinkParser = lazy(() => creator(10, validate(['[', '{'], bind
60
60
  if (el.classList.contains('invalid')) return [[el], rest];
61
61
  assert(el.classList.length === 0);
62
62
  return [[define(el, attributes('link', [], optspec, params))], rest];
63
- }))));
63
+ })))));
64
64
 
65
65
  export const uri: LinkParser.ParameterParser.UriParser = union([
66
66
  open(/^[^\S\n]+/, str(/^\S+/)),
@@ -90,8 +90,8 @@ export function resolve(uri: string, host: URL | Location, source: URL | Locatio
90
90
  default:
91
91
  const target = new ReadonlyURL(uri, source.href);
92
92
  return target.origin === host.origin
93
- ? target.href.slice(target.origin.length)
94
- : target.href;
93
+ ? target.href.slice(target.origin.length)
94
+ : target.href;
95
95
  }
96
96
  }
97
97
 
@@ -1,12 +1,12 @@
1
1
  import { MarkParser } from '../inline';
2
- import { union, some, creator, surround, open, lazy } from '../../combinator';
2
+ import { union, some, precedence, creator, surround, open, lazy } from '../../combinator';
3
3
  import { inline } from '../inline';
4
4
  import { str } from '../source';
5
5
  import { startTight, blankWith } from '../util';
6
6
  import { html, defrag } from 'typed-dom/dom';
7
7
  import { unshift } from 'spica/array';
8
8
 
9
- export const mark: MarkParser = lazy(() => creator(surround(
9
+ export const mark: MarkParser = lazy(() => creator(precedence(2, surround(
10
10
  str('=='),
11
11
  startTight(some(union([
12
12
  some(inline, blankWith('==')),
@@ -14,4 +14,4 @@ export const mark: MarkParser = lazy(() => creator(surround(
14
14
  ]))),
15
15
  str('=='), false,
16
16
  ([, bs], rest) => [[html('mark', defrag(bs))], rest],
17
- ([as, bs], rest) => [unshift(as, bs), rest])));
17
+ ([as, bs], rest) => [unshift(as, bs), rest]))));
@@ -18,6 +18,12 @@ describe('Unit: parser/inline/math', () => {
18
18
  assert.deepStrictEqual(inspect(parser('$-a $-b')), undefined);
19
19
  assert.deepStrictEqual(inspect(parser('$-a\\ $-b')), undefined);
20
20
  assert.deepStrictEqual(inspect(parser('$a $')), undefined);
21
+ assert.deepStrictEqual(inspect(parser('$-a `$`')), undefined);
22
+ assert.deepStrictEqual(inspect(parser('$-a ``$``')), undefined);
23
+ // (``" + ``" + $-b") or (``"`` + "$-b")
24
+ assert.deepStrictEqual(inspect(parser('$-a ``"``"$-b"')), undefined);
25
+ // (``b`` + "c" + $-d) or (``b``"c" + $-d)
26
+ assert.deepStrictEqual(inspect(parser('$-a ``b``"c"$-d')), undefined);
21
27
  assert.deepStrictEqual(inspect(parser('$-a"$-b"')), undefined);
22
28
  assert.deepStrictEqual(inspect(parser('$-a\\"$-b\\"')), undefined);
23
29
  assert.deepStrictEqual(inspect(parser('$a"$')), undefined);
@@ -28,7 +34,6 @@ describe('Unit: parser/inline/math', () => {
28
34
  assert.deepStrictEqual(inspect(parser('$-a\\[$-b\\]')), undefined);
29
35
  assert.deepStrictEqual(inspect(parser('$a[$')), undefined);
30
36
  assert.deepStrictEqual(inspect(parser('$-a{$-b}')), undefined);
31
- assert.deepStrictEqual(inspect(parser('$-a\\{$-b\\}')), undefined);
32
37
  assert.deepStrictEqual(inspect(parser('$a{$')), undefined);
33
38
  assert.deepStrictEqual(inspect(parser('$a$b')), undefined);
34
39
  assert.deepStrictEqual(inspect(parser('$a$b$')), undefined);
@@ -38,13 +43,25 @@ describe('Unit: parser/inline/math', () => {
38
43
  assert.deepStrictEqual(inspect(parser('$\n$')), undefined);
39
44
  assert.deepStrictEqual(inspect(parser('$a\\$\nb$')), undefined);
40
45
  assert.deepStrictEqual(inspect(parser('$a\\$\\\nb$')), undefined);
41
- assert.deepStrictEqual(inspect(parser('$`"$')), undefined);
46
+ assert.deepStrictEqual(inspect(parser('$`$')), undefined);
47
+ assert.deepStrictEqual(inspect(parser('$`a"$')), undefined);
48
+ assert.deepStrictEqual(inspect(parser('$`a"b$')), undefined);
49
+ assert.deepStrictEqual(inspect(parser('$``$')), undefined);
50
+ assert.deepStrictEqual(inspect(parser('$``$"$')), undefined);
51
+ assert.deepStrictEqual(inspect(parser('$``a$')), undefined);
42
52
  assert.deepStrictEqual(inspect(parser('$``a"$0')), undefined);
53
+ assert.deepStrictEqual(inspect(parser('$``a""b$')), undefined);
43
54
  assert.deepStrictEqual(inspect(parser('$``a""$')), undefined);
55
+ assert.deepStrictEqual(inspect(parser('$```a"$')), undefined);
44
56
  assert.deepStrictEqual(inspect(parser('$```a""$')), undefined);
45
57
  assert.deepStrictEqual(inspect(parser('$``\n"$')), undefined);
46
58
  assert.deepStrictEqual(inspect(parser('$``a\\$\nb"$')), undefined);
47
59
  assert.deepStrictEqual(inspect(parser('$``a\\$\\\nb"$')), undefined);
60
+ assert.deepStrictEqual(inspect(parser('$``"$')), undefined);
61
+ assert.deepStrictEqual(inspect(parser('$``a"$')), undefined);
62
+ assert.deepStrictEqual(inspect(parser('$``\\"$')), undefined);
63
+ assert.deepStrictEqual(inspect(parser('$``a``b"c"$')), undefined);
64
+ assert.deepStrictEqual(inspect(parser('$````""$')), undefined);
48
65
  assert.deepStrictEqual(inspect(parser('$"$')), undefined);
49
66
  assert.deepStrictEqual(inspect(parser('$}$')), undefined);
50
67
  assert.deepStrictEqual(inspect(parser('${')), undefined);
@@ -104,18 +121,8 @@ describe('Unit: parser/inline/math', () => {
104
121
  assert.deepStrictEqual(inspect(parser('$f(x)$')), [['<span class="math" translate="no" data-src="$f(x)$">$f(x)$</span>'], '']);
105
122
  assert.deepStrictEqual(inspect(parser('$f: x \\to y$')), [['<span class="math" translate="no" data-src="$f: x \\to y$">$f: x \\to y$</span>'], '']);
106
123
  assert.deepStrictEqual(inspect(parser('$k$-space')), [['<span class="math" translate="no" data-src="$k$">$k$</span>'], '-space']);
107
- assert.deepStrictEqual(inspect(parser('$`$')), [['<span class="math" translate="no" data-src="$`$">$`$</span>'], '']);
108
- assert.deepStrictEqual(inspect(parser('$`"a$')), [['<span class="math" translate="no" data-src="$`&quot;a$">$`"a$</span>'], '']);
109
- assert.deepStrictEqual(inspect(parser('$``$')), [['<span class="math" translate="no" data-src="$``$">$``$</span>'], '']);
110
- assert.deepStrictEqual(inspect(parser('$``"$')), [['<span class="math" translate="no" data-src="$``&quot;$">$``"$</span>'], '']);
111
- assert.deepStrictEqual(inspect(parser('$``""a$')), [['<span class="math" translate="no" data-src="$``&quot;&quot;a$">$``""a$</span>'], '']);
112
- assert.deepStrictEqual(inspect(parser('$``a"$')), [['<span class="math" translate="no" data-src="$``a&quot;$">$``a"$</span>'], '']);
113
- assert.deepStrictEqual(inspect(parser('$``$"$')), [['<span class="math" translate="no" data-src="$``$">$``$</span>'], '"$']);
114
- assert.deepStrictEqual(inspect(parser('$``\\"$')), [['<span class="math" translate="no" data-src="$``\\&quot;$">$``\\"$</span>'], '']);
115
- assert.deepStrictEqual(inspect(parser('$``a``b"c"$')), [['<span class="math" translate="no" data-src="$``a``b&quot;c&quot;$">$``a``b"c"$</span>'], '']);
116
- assert.deepStrictEqual(inspect(parser('$```"$')), [['<span class="math" translate="no" data-src="$```&quot;$">$```"$</span>'], '']);
117
- assert.deepStrictEqual(inspect(parser('$````""$')), [['<span class="math" translate="no" data-src="$````&quot;&quot;$">$````""$</span>'], '']);
118
124
  assert.deepStrictEqual(inspect(parser('$a{b}$')), [['<span class="math" translate="no" data-src="$a{b}$">$a{b}$</span>'], '']);
125
+ assert.deepStrictEqual(inspect(parser('$a\\{$\\}')), [['<span class="math" translate="no" data-src="$a\\{$">$a\\{$</span>'], '\\}']);
119
126
  assert.deepStrictEqual(inspect(parser('${}$')), [['<span class="math" translate="no" data-src="${}$">${}$</span>'], '']);
120
127
  assert.deepStrictEqual(inspect(parser('${ }$')), [['<span class="math" translate="no" data-src="${ }$">${ }$</span>'], '']);
121
128
  assert.deepStrictEqual(inspect(parser('${a}$')), [['<span class="math" translate="no" data-src="${a}$">${a}$</span>'], '']);
@@ -127,7 +134,7 @@ describe('Unit: parser/inline/math', () => {
127
134
  assert.deepStrictEqual(inspect(parser('${a }$')), [['<span class="math" translate="no" data-src="${a }$">${a }$</span>'], '']);
128
135
  assert.deepStrictEqual(inspect(parser('${ a}$')), [['<span class="math" translate="no" data-src="${ a}$">${ a}$</span>'], '']);
129
136
  assert.deepStrictEqual(inspect(parser('${ a }$')), [['<span class="math" translate="no" data-src="${ a }$">${ a }$</span>'], '']);
130
- assert.deepStrictEqual(inspect(parser('${``a"}$')), [['<span class="math" translate="no" data-src="${``a&quot;}$">${``a"}$</span>'], '']);
137
+ assert.deepStrictEqual(inspect(parser('${``"}$')), [['<span class="math" translate="no" data-src="${``&quot;}$">${``"}$</span>'], '']);
131
138
  assert.deepStrictEqual(inspect(parser('${\\a}$')), [['<span class="math" translate="no" data-src="${\\a}$">${\\a}$</span>'], '']);
132
139
  assert.deepStrictEqual(inspect(parser('${\\$}$')), [['<span class="math" translate="no" data-src="${\\$}$">${\\$}$</span>'], '']);
133
140
  assert.deepStrictEqual(inspect(parser('${\\\\}$')), [['<span class="math" translate="no" data-src="${\\\\}$">${\\\\}$</span>'], '']);