securemark 0.293.5 → 0.294.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 (105) hide show
  1. package/CHANGELOG.md +4 -0
  2. package/dist/index.js +845 -534
  3. package/markdown.d.ts +13 -13
  4. package/package.json +3 -3
  5. package/src/combinator/control/constraint/block.test.ts +6 -6
  6. package/src/combinator/control/constraint/contract.ts +3 -3
  7. package/src/combinator/control/constraint/line.test.ts +7 -7
  8. package/src/combinator/control/constraint/line.ts +1 -1
  9. package/src/combinator/control/manipulation/clear.ts +2 -3
  10. package/src/combinator/control/manipulation/convert.ts +2 -2
  11. package/src/combinator/control/manipulation/duplicate.ts +4 -5
  12. package/src/combinator/control/manipulation/fence.ts +2 -2
  13. package/src/combinator/control/manipulation/indent.test.ts +2 -2
  14. package/src/combinator/control/manipulation/indent.ts +4 -4
  15. package/src/combinator/control/manipulation/reverse.ts +2 -2
  16. package/src/combinator/control/manipulation/scope.ts +3 -4
  17. package/src/combinator/control/manipulation/surround.ts +12 -13
  18. package/src/combinator/control/monad/bind.ts +6 -6
  19. package/src/combinator/control/monad/fmap.ts +7 -7
  20. package/src/combinator/data/data.ts +135 -0
  21. package/src/combinator/data/parser/context.test.ts +8 -8
  22. package/src/combinator/data/parser/context.ts +3 -3
  23. package/src/combinator/data/parser/inits.ts +6 -7
  24. package/src/combinator/data/parser/sequence.test.ts +3 -3
  25. package/src/combinator/data/parser/sequence.ts +6 -7
  26. package/src/combinator/data/parser/some.test.ts +3 -3
  27. package/src/combinator/data/parser/some.ts +4 -4
  28. package/src/combinator/data/parser/subsequence.test.ts +4 -4
  29. package/src/combinator/data/parser/subsequence.ts +3 -3
  30. package/src/combinator/data/parser/tails.ts +3 -3
  31. package/src/combinator/data/parser/union.test.ts +3 -3
  32. package/src/combinator/data/parser.ts +16 -7
  33. package/src/debug.test.ts +6 -5
  34. package/src/parser/api/bind.ts +4 -6
  35. package/src/parser/api/header.ts +1 -1
  36. package/src/parser/api/normalize.ts +1 -1
  37. package/src/parser/api/parse.ts +3 -1
  38. package/src/parser/block/blockquote.ts +6 -4
  39. package/src/parser/block/codeblock.ts +8 -7
  40. package/src/parser/block/dlist.ts +9 -8
  41. package/src/parser/block/extension/aside.ts +27 -21
  42. package/src/parser/block/extension/example.ts +29 -26
  43. package/src/parser/block/extension/fig.ts +1 -1
  44. package/src/parser/block/extension/figbase.ts +6 -5
  45. package/src/parser/block/extension/figure.ts +23 -19
  46. package/src/parser/block/extension/message.ts +35 -24
  47. package/src/parser/block/extension/placeholder.ts +17 -13
  48. package/src/parser/block/extension/table.ts +47 -40
  49. package/src/parser/block/heading.test.ts +3 -12
  50. package/src/parser/block/heading.ts +12 -8
  51. package/src/parser/block/ilist.ts +13 -12
  52. package/src/parser/block/mathblock.ts +21 -17
  53. package/src/parser/block/mediablock.ts +7 -5
  54. package/src/parser/block/olist.ts +15 -5
  55. package/src/parser/block/pagebreak.ts +2 -1
  56. package/src/parser/block/paragraph.ts +3 -1
  57. package/src/parser/block/reply/cite.ts +20 -15
  58. package/src/parser/block/reply/quote.ts +6 -4
  59. package/src/parser/block/reply.ts +6 -3
  60. package/src/parser/block/sidefence.ts +8 -7
  61. package/src/parser/block/table.ts +23 -22
  62. package/src/parser/block/ulist.ts +16 -12
  63. package/src/parser/block.ts +7 -6
  64. package/src/parser/header.ts +18 -18
  65. package/src/parser/inline/annotation.ts +3 -1
  66. package/src/parser/inline/autolink/account.ts +3 -2
  67. package/src/parser/inline/autolink/anchor.ts +3 -2
  68. package/src/parser/inline/autolink/channel.ts +5 -4
  69. package/src/parser/inline/autolink/email.ts +4 -3
  70. package/src/parser/inline/autolink/hashnum.ts +3 -2
  71. package/src/parser/inline/autolink/hashtag.ts +4 -3
  72. package/src/parser/inline/autolink/url.ts +7 -6
  73. package/src/parser/inline/bracket.ts +16 -15
  74. package/src/parser/inline/code.ts +5 -4
  75. package/src/parser/inline/deletion.ts +5 -5
  76. package/src/parser/inline/emphasis.ts +4 -3
  77. package/src/parser/inline/emstrong.test.ts +18 -18
  78. package/src/parser/inline/emstrong.ts +39 -30
  79. package/src/parser/inline/extension/index.ts +22 -19
  80. package/src/parser/inline/extension/indexee.ts +2 -2
  81. package/src/parser/inline/extension/indexer.ts +2 -1
  82. package/src/parser/inline/extension/label.ts +7 -3
  83. package/src/parser/inline/extension/placeholder.ts +6 -6
  84. package/src/parser/inline/html.ts +27 -28
  85. package/src/parser/inline/htmlentity.ts +9 -8
  86. package/src/parser/inline/insertion.ts +5 -5
  87. package/src/parser/inline/italic.ts +5 -5
  88. package/src/parser/inline/link.ts +36 -38
  89. package/src/parser/inline/mark.ts +7 -7
  90. package/src/parser/inline/math.ts +5 -4
  91. package/src/parser/inline/media.ts +33 -32
  92. package/src/parser/inline/reference.ts +19 -20
  93. package/src/parser/inline/remark.ts +11 -11
  94. package/src/parser/inline/ruby.ts +50 -53
  95. package/src/parser/inline/strong.ts +4 -3
  96. package/src/parser/inline/template.ts +16 -15
  97. package/src/parser/inline.test.ts +3 -3
  98. package/src/parser/segment.ts +3 -1
  99. package/src/parser/source/escapable.ts +9 -8
  100. package/src/parser/source/line.ts +4 -3
  101. package/src/parser/source/str.ts +2 -2
  102. package/src/parser/source/text.ts +9 -8
  103. package/src/parser/source/unescapable.ts +6 -5
  104. package/src/parser/util.ts +18 -13
  105. package/src/parser/visibility.ts +19 -20
@@ -1,5 +1,6 @@
1
1
  import { AutolinkParser } from '../../inline';
2
2
  import { State, Backtrack } from '../../context';
3
+ import { List, Data } from '../../../combinator/data/parser';
3
4
  import { union, state, constraint, rewrite, open, convert, fmap, lazy } from '../../../combinator';
4
5
  import { unsafelink } from '../link';
5
6
  import { emoji } from './hashtag';
@@ -21,6 +22,6 @@ export const hashnum: AutolinkParser.HashnumParser = lazy(() => rewrite(
21
22
  source => `[${source}]{ ${source.slice(1)} }`,
22
23
  unsafelink,
23
24
  false),
24
- ([el]) => [define(el, { class: 'hashnum', href: null })]))),
25
- ({ context: { source } }) => [[source]],
25
+ ([{ value }]) => new List([new Data(define(value, { class: 'hashnum', href: null }))])))),
26
+ ({ context: { source } }) => new List([new Data(source)]),
26
27
  ])));
@@ -1,5 +1,6 @@
1
1
  import { AutolinkParser } from '../../inline';
2
2
  import { State, Backtrack } from '../../context';
3
+ import { List, Data } from '../../../combinator/data/parser';
3
4
  import { union, state, constraint, verify, rewrite, open, convert, fmap, lazy } from '../../../combinator';
4
5
  import { unsafelink } from '../link';
5
6
  import { str } from '../../source';
@@ -19,7 +20,7 @@ export const hashtag: AutolinkParser.HashtagParser = lazy(() => rewrite(
19
20
  str(new RegExp([
20
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,
21
22
  ].join('').replace(/emoji/g, emoji), 'yu')),
22
- ([source]) => !/^[0-9]{1,4}$|^[0-9]{5}/.test(source)),
23
+ ([{ value }]) => !/^[0-9]{1,4}$|^[0-9]{5}/.test(value)),
23
24
  false,
24
25
  [3 | Backtrack.autolink]),
25
26
  union([
@@ -27,6 +28,6 @@ export const hashtag: AutolinkParser.HashtagParser = lazy(() => rewrite(
27
28
  source => `[${source}]{ ${`/hashtags/${source.slice(1)}`} }`,
28
29
  unsafelink,
29
30
  false),
30
- ([el]) => [define(el, { class: 'hashtag' })]))),
31
- ({ context: { source } }) => [[source]],
31
+ ([{ value }]) => new List([new Data(define(value, { class: 'hashtag' }))])))),
32
+ ({ context: { source } }) => new List([new Data(source)]),
32
33
  ])));
@@ -1,5 +1,6 @@
1
1
  import { AutolinkParser } from '../../inline';
2
2
  import { State, Recursion, Backtrack } from '../../context';
3
+ import { List, Data } from '../../../combinator/data/parser';
3
4
  import { union, tails, some, recursion, precedence, state, constraint, verify, focus, rewrite, convert, surround, open, lazy } from '../../../combinator';
4
5
  import { unsafelink } from '../link';
5
6
  import { unescsource, str } from '../../source';
@@ -18,7 +19,7 @@ export const url: AutolinkParser.UrlParser = lazy(() => rewrite(
18
19
  url => `{ ${url} }`,
19
20
  unsafelink,
20
21
  false))),
21
- ({ context: { source } }) => [[source]],
22
+ ({ context: { source } }) => new List([new Data(source)]),
22
23
  ])));
23
24
 
24
25
  export const lineurl: AutolinkParser.UrlParser.LineUrlParser = lazy(() => focus(
@@ -30,17 +31,17 @@ export const lineurl: AutolinkParser.UrlParser.LineUrlParser = lazy(() => focus(
30
31
  url => `{ ${url} }`,
31
32
  unsafelink,
32
33
  false))),
33
- ({ context: { source } }) => [[source]],
34
+ ({ context: { source } }) => new List([new Data(source)]),
34
35
  ]),
35
36
  ])));
36
37
 
37
38
  const bracket: AutolinkParser.UrlParser.BracketParser = lazy(() => union([
38
39
  surround(str('('), recursion(Recursion.terminal, some(union([bracket, unescsource]), ')')), str(')'), true,
39
- undefined, () => [[]], [3 | Backtrack.autolink]),
40
+ undefined, () => new List(), [3 | Backtrack.autolink]),
40
41
  surround(str('['), recursion(Recursion.terminal, some(union([bracket, unescsource]), ']')), str(']'), true,
41
- undefined, () => [[]], [3 | Backtrack.autolink]),
42
+ undefined, () => new List(), [3 | Backtrack.autolink]),
42
43
  surround(str('{'), recursion(Recursion.terminal, some(union([bracket, unescsource]), '}')), str('}'), true,
43
- undefined, () => [[]], [3 | Backtrack.autolink]),
44
+ undefined, () => new List(), [3 | Backtrack.autolink]),
44
45
  surround(str('"'), precedence(2, recursion(Recursion.terminal, some(unescsource, '"'))), str('"'), true,
45
- undefined, () => [[]], [3 | Backtrack.autolink]),
46
+ undefined, () => new List(), [3 | Backtrack.autolink]),
46
47
  ]));
@@ -1,10 +1,11 @@
1
1
  import { BracketParser } from '../inline';
2
2
  import { State, Recursion, Backtrack } from '../context';
3
+ import { List, Data } from '../../combinator/data/parser';
3
4
  import { union, some, recursion, precedence, surround, isBacktrack, setBacktrack, lazy } from '../../combinator';
4
5
  import { inline } from '../inline';
5
6
  import { textlink } from './link';
6
7
  import { str } from '../source';
7
- import { unshift, push } from 'spica/array';
8
+ import { unwrap } from '../util';
8
9
  import { html, defrag } from 'typed-dom/dom';
9
10
 
10
11
  const indexA = /^[0-9A-Za-z]+(?:(?:[.-]|, )[0-9A-Za-z]+)*$/;
@@ -38,13 +39,13 @@ const p1 = lazy(() => surround(
38
39
  precedence(1, recursion(Recursion.bracket, some(inline, ')', [[')', 1]]))),
39
40
  str(')'),
40
41
  true,
41
- ([as, bs = [], cs], { source, position, range = 0 }) => {
42
+ ([as, bs = new List(), cs], { source, position, range = 0 }) => {
42
43
  const str = source.slice(position - range + 1, position - 1);
43
44
  return indexA.test(str)
44
- ? [[as[0], str, cs[0]]]
45
- : [[html('span', { class: 'paren' }, defrag(push(unshift(as, bs), cs)))]];
45
+ ? new List([new Data(as.head!.value), new Data(str), new Data(cs.head!.value)])
46
+ : new List([new Data(html('span', { class: 'paren' }, defrag(unwrap(as.import(bs as List<Data<string>>).import(cs)))))]);
46
47
  },
47
- ([as, bs = []]) => [unshift(as, bs)],
48
+ ([as, bs = new List()]) => as.import(bs as List<Data<string>>),
48
49
  [2 | Backtrack.bracket]));
49
50
 
50
51
  const p2 = lazy(() => surround(
@@ -55,10 +56,10 @@ const p2 = lazy(() => surround(
55
56
  ([as, bs = [], cs], { source, position, range = 0 }) => {
56
57
  const str = source.slice(position - range + 1, position - 1);
57
58
  return indexF.test(str)
58
- ? [[as[0], str, cs[0]]]
59
- : [[html('span', { class: 'paren' }, defrag(push(unshift(as, bs), cs)))]];
59
+ ? new List([new Data(as.head!.value), new Data(str), new Data(cs.head!.value)])
60
+ : new List([new Data(html('span', { class: 'paren' }, defrag(unwrap(as.import(bs as List<Data<string>>).import(cs)))))]);
60
61
  },
61
- ([as, bs = []]) => [unshift(as, bs)],
62
+ ([as, bs = new List()]) => as.import(bs as List<Data<string>>),
62
63
  [2 | Backtrack.bracket]));
63
64
 
64
65
  const s1 = lazy(() => surround(
@@ -66,7 +67,7 @@ const s1 = lazy(() => surround(
66
67
  precedence(1, recursion(Recursion.bracket, some(inline, ']', [[']', 1]]))),
67
68
  str(']'),
68
69
  true,
69
- ([as, bs = [], cs], context) => {
70
+ ([as, bs = new List(), cs], context) => {
70
71
  if (context.state! & State.link) {
71
72
  const { source, position, range = 0 } = context;
72
73
  const head = position - range;
@@ -86,9 +87,9 @@ const s1 = lazy(() => surround(
86
87
  context.range = range;
87
88
  }
88
89
  }
89
- return [push(unshift(as, bs), cs)];
90
+ return as.import(bs as List<Data<string>>).import(cs);
90
91
  },
91
- ([as, bs = []]) => [unshift(as, bs)],
92
+ ([as, bs = new List()]) => as.import(bs as List<Data<string>>),
92
93
  [2 | Backtrack.bracket]));
93
94
 
94
95
  const s2 = lazy(() => surround(
@@ -97,7 +98,7 @@ const s2 = lazy(() => surround(
97
98
  str(']'),
98
99
  true,
99
100
  undefined,
100
- ([as, bs = []]) => [unshift(as, bs)],
101
+ ([as, bs = new List()]) => as.import(bs as List<Data<string>>),
101
102
  [2 | Backtrack.bracket]));
102
103
 
103
104
  const c1 = lazy(() => surround(
@@ -106,7 +107,7 @@ const c1 = lazy(() => surround(
106
107
  str('}'),
107
108
  true,
108
109
  undefined,
109
- ([as, bs = []]) => [unshift(as, bs)],
110
+ ([as, bs = new List()]) => as.import(bs as List<Data<string>>),
110
111
  [2 | Backtrack.bracket]));
111
112
 
112
113
  const c2 = lazy(() => surround(
@@ -115,7 +116,7 @@ const c2 = lazy(() => surround(
115
116
  str('}'),
116
117
  true,
117
118
  undefined,
118
- ([as, bs = []]) => [unshift(as, bs)],
119
+ ([as, bs = new List()]) => as.import(bs as List<Data<string>>),
119
120
  [2 | Backtrack.bracket]));
120
121
 
121
122
  const d1 = lazy(() => surround(
@@ -125,5 +126,5 @@ const d1 = lazy(() => surround(
125
126
  str('"'),
126
127
  true,
127
128
  undefined,
128
- ([as, bs = []]) => [unshift(as, bs)],
129
+ ([as, bs = new List()]) => as.import(bs as List<Data<string>>),
129
130
  [2 | Backtrack.bracket]));
@@ -1,4 +1,5 @@
1
1
  import { CodeParser } from '../inline';
2
+ import { List, Data } from '../../combinator/data/parser';
2
3
  import { open, match } from '../../combinator';
3
4
  import { Backtrack } from '../context';
4
5
  import { invalid } from '../util';
@@ -10,13 +11,13 @@ export const code: CodeParser = open(
10
11
  /(`+)(?!`)([^\n]*?)(?:((?<!`)\1(?!`))|(?=$|\n))/y,
11
12
  ([whole, opener, body, closer]) => () =>
12
13
  closer
13
- ? [[html('code', { 'data-src': whole }, format(body))]]
14
+ ? new List([new Data(html('code', { 'data-src': whole }, format(body)))])
14
15
  : body
15
- ? [[html('code', {
16
+ ? new List([new Data(html('code', {
16
17
  class: 'invalid',
17
18
  ...invalid('code', 'syntax', `Missing the closing symbol "${opener}"`)
18
- }, whole)]]
19
- : [[opener]],
19
+ }, whole))])
20
+ : new List([new Data(opener)]),
20
21
  true),
21
22
  false,
22
23
  [3 | Backtrack.bracket]);
@@ -1,10 +1,10 @@
1
1
  import { DeletionParser } from '../inline';
2
2
  import { Recursion, Command } from '../context';
3
+ import { List, Data } from '../../combinator/data/parser';
3
4
  import { union, some, recursion, precedence, validate, surround, open, lazy } from '../../combinator';
4
5
  import { inline } from '../inline';
5
6
  import { blankWith } from '../visibility';
6
- import { repeat } from '../util';
7
- import { push } from 'spica/array';
7
+ import { unwrap, repeat } from '../util';
8
8
  import { html, defrag } from 'typed-dom/dom';
9
9
 
10
10
  export const deletion: DeletionParser = lazy(() => validate('~~',
@@ -16,6 +16,6 @@ export const deletion: DeletionParser = lazy(() => validate('~~',
16
16
  open('\n', some(inline, '~'), true),
17
17
  ]))),
18
18
  '~~', false,
19
- ([, bs], { buffer }) => [push(buffer!, bs)],
20
- ([, bs], { buffer }) => bs && [push(push(buffer!, bs), [Command.Cancel])]),
21
- nodes => [html('del', defrag(nodes))]))));
19
+ ([, bs], { buffer }) => buffer!.import(bs),
20
+ ([, bs], { buffer }) => bs && buffer!.import(bs).push(new Data(Command.Cancel)) && buffer!),
21
+ nodes => new List([new Data(html('del', defrag(unwrap(nodes))))])))));
@@ -1,11 +1,12 @@
1
1
  import { EmphasisParser } from '../inline';
2
2
  import { Recursion } from '../context';
3
+ import { List, Data } from '../../combinator/data/parser';
3
4
  import { union, some, recursion, precedence, surround, open, lazy } from '../../combinator';
4
5
  import { inline } from '../inline';
5
6
  import { strong } from './strong';
6
7
  import { str } from '../source';
7
8
  import { tightStart, blankWith } from '../visibility';
8
- import { unshift } from 'spica/array';
9
+ import { unwrap } from '../util';
9
10
  import { html, defrag } from 'typed-dom/dom';
10
11
 
11
12
  export const emphasis: EmphasisParser = lazy(() => surround(
@@ -17,5 +18,5 @@ export const emphasis: EmphasisParser = lazy(() => surround(
17
18
  open(some(inline, '*'), inline),
18
19
  ]))))),
19
20
  str('*'), false,
20
- ([, bs]) => [[html('em', defrag(bs))]],
21
- ([as, bs]) => bs && [unshift(as, bs)]));
21
+ ([, bs]) => new List([new Data(html('em', defrag(unwrap(bs))))]),
22
+ ([as, bs]) => bs && as.import(bs as List<Data<string>>)));
@@ -10,12 +10,12 @@ describe('Unit: parser/inline/emstrong', () => {
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\n***'), ctx), [['***', 'a', '<br>', '***'], '']);
17
- assert.deepStrictEqual(inspect(parser('***a\\ ***'), ctx), [['***', 'a', ' ', '***'], '']);
18
- assert.deepStrictEqual(inspect(parser('***a\\\n***'), ctx), [['***', 'a', '<br>', '***'], '']);
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\n***'), ctx), [['***a', '<br>', '***'], '']);
17
+ assert.deepStrictEqual(inspect(parser('***a\\ ***'), ctx), [['***a', ' ', '***'], '']);
18
+ assert.deepStrictEqual(inspect(parser('***a\\\n***'), ctx), [['***a', '<br>', '***'], '']);
19
19
  assert.deepStrictEqual(inspect(parser('*** ***'), ctx), undefined);
20
20
  assert.deepStrictEqual(inspect(parser('*** a***'), ctx), undefined);
21
21
  assert.deepStrictEqual(inspect(parser('*** a ***'), ctx), undefined);
@@ -43,7 +43,7 @@ describe('Unit: parser/inline/emstrong', () => {
43
43
  assert.deepStrictEqual(inspect(parser('***a*'), ctx), [['**', '<em>a</em>'], '']);
44
44
  assert.deepStrictEqual(inspect(parser('***a*b'), ctx), [['**', '<em>a</em>', 'b'], '']);
45
45
  assert.deepStrictEqual(inspect(parser('***a*b*'), ctx), [['**', '<em>a</em>', 'b'], '*']);
46
- assert.deepStrictEqual(inspect(parser('***a*b*c'), ctx), [['**', '<em>a</em>', 'b*c'], '']);
46
+ assert.deepStrictEqual(inspect(parser('***a*b*c'), ctx), [['**', '<em>a</em>', 'b', '*', 'c'], '']);
47
47
  assert.deepStrictEqual(inspect(parser('***a*b*c*'), ctx), [['**', '<em>a</em>', 'b', '<em>c</em>'], '']);
48
48
  assert.deepStrictEqual(inspect(parser('***a*b*c**'), ctx), [['**', '<em>a</em>', 'b', '<em>c</em>'], '*']);
49
49
  assert.deepStrictEqual(inspect(parser('***a*b*c***'), ctx), [['<strong><em>a</em>b<em>c</em></strong>'], '']);
@@ -53,7 +53,7 @@ describe('Unit: parser/inline/emstrong', () => {
53
53
  assert.deepStrictEqual(inspect(parser('***a**b'), ctx), [['*', '<strong>a</strong>', 'b'], '']);
54
54
  assert.deepStrictEqual(inspect(parser('***a**b*'), ctx), [['<em><strong>a</strong>b</em>'], '']);
55
55
  assert.deepStrictEqual(inspect(parser('***a**b**'), ctx), [['<em><strong>a</strong>b</em>'], '*']);
56
- assert.deepStrictEqual(inspect(parser('***a**b**c'), ctx), [['*', '<strong>a</strong>', 'b**c'], '']);
56
+ assert.deepStrictEqual(inspect(parser('***a**b**c'), ctx), [['*', '<strong>a</strong>', 'b', '**', 'c'], '']);
57
57
  assert.deepStrictEqual(inspect(parser('***a**b**c*'), ctx), [['<em><strong>a</strong>b**c</em>'], '']);
58
58
  assert.deepStrictEqual(inspect(parser('***a**b**c**'), ctx), [['*', '<strong>a</strong>', 'b', '<strong>c</strong>'], '']);
59
59
  assert.deepStrictEqual(inspect(parser('***a**b**c***'), ctx), [['<em><strong>a</strong>b<strong>c</strong></em>'], '']);
@@ -66,8 +66,8 @@ describe('Unit: parser/inline/emstrong', () => {
66
66
  assert.deepStrictEqual(inspect(parser('***a*\\ **b****'), ctx), [['<strong><em>a</em> <strong>b</strong></strong>'], '']);
67
67
  assert.deepStrictEqual(inspect(parser('***a*&Tab;**b****'), ctx), [['<strong><em>a</em>\t<strong>b</strong></strong>'], '']);
68
68
  assert.deepStrictEqual(inspect(parser('***a*<wbr>**b****'), ctx), [['<strong><em>a</em><wbr><strong>b</strong></strong>'], '']);
69
- assert.deepStrictEqual(inspect(parser('***a*b **'), ctx), [['**', '<em>a</em>', 'b **'], '']);
70
- assert.deepStrictEqual(inspect(parser('***a*b\\ **'), ctx), [['**', '<em>a</em>', 'b **'], '']);
69
+ assert.deepStrictEqual(inspect(parser('***a*b **'), ctx), [['**', '<em>a</em>', 'b', ' ', '**'], '']);
70
+ assert.deepStrictEqual(inspect(parser('***a*b\\ **'), ctx), [['**', '<em>a</em>', 'b', ' ', '**'], '']);
71
71
  assert.deepStrictEqual(inspect(parser('***a**b*'), ctx), [['<em><strong>a</strong>b</em>'], '']);
72
72
  assert.deepStrictEqual(inspect(parser('***a**b*c'), ctx), [['<em><strong>a</strong>b</em>'], 'c']);
73
73
  assert.deepStrictEqual(inspect(parser('***a**b*c**'), ctx), [['<em><strong>a</strong>b</em>'], 'c**']);
@@ -77,8 +77,8 @@ describe('Unit: parser/inline/emstrong', () => {
77
77
  assert.deepStrictEqual(inspect(parser('***a**\\ *b**'), ctx), [['<em><strong>a</strong> <em>b</em></em>'], '']);
78
78
  assert.deepStrictEqual(inspect(parser('***a**&Tab;*b**'), ctx), [['<em><strong>a</strong>\t<em>b</em></em>'], '']);
79
79
  assert.deepStrictEqual(inspect(parser('***a**<wbr>*b**'), ctx), [['<em><strong>a</strong><wbr><em>b</em></em>'], '']);
80
- assert.deepStrictEqual(inspect(parser('***a**b *'), ctx), [['*', '<strong>a</strong>', 'b *'], '']);
81
- assert.deepStrictEqual(inspect(parser('***a**b\\ *'), ctx), [['*', '<strong>a</strong>', 'b *'], '']);
80
+ assert.deepStrictEqual(inspect(parser('***a**b *'), ctx), [['*', '<strong>a</strong>', 'b', ' ', '*'], '']);
81
+ assert.deepStrictEqual(inspect(parser('***a**b\\ *'), ctx), [['*', '<strong>a</strong>', 'b', ' ', '*'], '']);
82
82
  assert.deepStrictEqual(inspect(parser('***a*'), ctx), [['**', '<em>a</em>'], '']);
83
83
  assert.deepStrictEqual(inspect(parser('***a**'), ctx), [['*', '<strong>a</strong>'], '']);
84
84
  assert.deepStrictEqual(inspect(parser('***a***'), ctx), [['<em><strong>a</strong></em>'], '']);
@@ -108,12 +108,12 @@ describe('Unit: parser/inline/emstrong', () => {
108
108
  assert.deepStrictEqual(inspect(parser('******a*****b*'), ctx), [['<em><strong><em><strong>a</strong></em></strong>b</em>'], '']);
109
109
  assert.deepStrictEqual(inspect(parser('******a******'), ctx), [['<em><strong><em><strong>a</strong></em></strong></em>'], '']);
110
110
  assert.deepStrictEqual(inspect(parser('******a******b'), ctx), [['<em><strong><em><strong>a</strong></em></strong></em>'], 'b']);
111
- assert.deepStrictEqual(inspect(parser('******a*b'), ctx), [['***', '**', '<em>a</em>', 'b'], '']);
112
- assert.deepStrictEqual(inspect(parser('******a*b *'), ctx), [['***', '**', '<em>a</em>', 'b *'], '']);
113
- assert.deepStrictEqual(inspect(parser('******a*b **'), ctx), [['***', '**', '<em>a</em>', 'b **'], '']);
114
- assert.deepStrictEqual(inspect(parser('******a*b ***'), ctx), [['***', '**', '<em>a</em>', 'b ***'], '']);
115
- assert.deepStrictEqual(inspect(parser('******a*b ****'), ctx), [['***', '**', '<em>a</em>', 'b ****'], '']);
116
- assert.deepStrictEqual(inspect(parser('******a*b *****'), ctx), [['***', '**', '<em>a</em>', 'b *****'], '']);
111
+ assert.deepStrictEqual(inspect(parser('******a*b'), ctx), [['*****', '<em>a</em>', 'b'], '']);
112
+ assert.deepStrictEqual(inspect(parser('******a*b *'), ctx), [['*****', '<em>a</em>', 'b', ' ', '*'], '']);
113
+ assert.deepStrictEqual(inspect(parser('******a*b **'), ctx), [['*****', '<em>a</em>', 'b', ' ', '**'], '']);
114
+ assert.deepStrictEqual(inspect(parser('******a*b ***'), ctx), [['*****', '<em>a</em>', 'b', ' ', '***'], '']);
115
+ assert.deepStrictEqual(inspect(parser('******a*b ****'), ctx), [['*****', '<em>a</em>', 'b', ' ', '****'], '']);
116
+ assert.deepStrictEqual(inspect(parser('******a*b *****'), ctx), [['*****', '<em>a</em>', 'b', ' ', '*****'], '']);
117
117
  });
118
118
 
119
119
  });
@@ -1,14 +1,13 @@
1
1
  import { EmStrongParser, EmphasisParser, StrongParser } from '../inline';
2
2
  import { Recursion, Command } from '../context';
3
- import { Result, Node, Context, IntermediateParser } from '../../combinator/data/parser';
3
+ import { Result, List, Data, Node, Context, IntermediateParser, eval } from '../../combinator/data/parser';
4
4
  import { union, some, recursion, precedence, validate, surround, open, lazy, bind } from '../../combinator';
5
5
  import { inline } from '../inline';
6
6
  import { strong } from './strong';
7
7
  import { emphasis } from './emphasis';
8
8
  import { str } from '../source';
9
9
  import { tightStart, blankWith } from '../visibility';
10
- import { repeat } from '../util';
11
- import { unshift, push } from 'spica/array';
10
+ import { unwrap, repeat } from '../util';
12
11
  import { html, defrag } from 'typed-dom/dom';
13
12
 
14
13
  const substrong: IntermediateParser<StrongParser> = lazy(() => some(union([
@@ -36,10 +35,10 @@ export const emstrong: EmStrongParser = lazy(() => validate('***',
36
35
  str(/\*{1,3}/y), false,
37
36
  ([, bs, cs], context): Result<Node<EmStrongParser>, Context<EmStrongParser>> => {
38
37
  assert(cs.length === 1);
39
- const { buffer } = context;
40
- switch (cs[0]) {
38
+ const { buffer = new List() } = context;
39
+ switch (cs.head!.value) {
41
40
  case '***':
42
- return [bs];
41
+ return bs;
43
42
  case '**':
44
43
  return bind<EmphasisParser>(
45
44
  subemphasis,
@@ -47,13 +46,18 @@ export const emstrong: EmStrongParser = lazy(() => validate('***',
47
46
  const { source } = context;
48
47
  if (source.startsWith('*', context.position)) {
49
48
  context.position += 1;
50
- return [[html('em', push(push(buffer!, [html('strong', defrag(bs))]), defrag(ds))), Command.Separator]];
49
+ buffer.push(new Data(html('strong', defrag(unwrap(bs)))));
50
+ buffer.import(ds);
51
+ return new List([new Data(html('em', defrag(unwrap(buffer)))), new Data(Command.Separator)]);
51
52
  }
52
53
  else {
53
- return [prepend('*', push(push(push(buffer!, [html('strong', defrag(bs))]), defrag(ds)), [Command.Separator]))];
54
+ buffer.push(new Data(html('strong', defrag(unwrap(bs)))));
55
+ buffer.import(ds);
56
+ buffer.push(new Data(Command.Separator));
57
+ return prepend('*', buffer);
54
58
  }
55
59
  })
56
- ({ context }) ?? [prepend('*', push(push(buffer!, [html('strong', defrag(bs))]), [Command.Separator]))];
60
+ ({ context }) ?? prepend('*', buffer.import(new List([new Data(html('strong', defrag(unwrap(bs)))), new Data(Command.Separator)])));
57
61
  case '*':
58
62
  return bind<StrongParser>(
59
63
  substrong,
@@ -61,19 +65,24 @@ export const emstrong: EmStrongParser = lazy(() => validate('***',
61
65
  const { source } = context;
62
66
  if (source.startsWith('**', context.position)) {
63
67
  context.position += 2;
64
- return [[html('strong', push(push(buffer!, [html('em', defrag(bs))]), defrag(ds))), Command.Separator]];
68
+ buffer.push(new Data(html('em', defrag(unwrap(bs)))));
69
+ buffer.import(ds);
70
+ return new List([new Data(html('strong', defrag(unwrap(buffer)))), new Data(Command.Separator)]);
65
71
  }
66
72
  else {
67
- return [prepend('**', push(push(push(buffer!, [html('em', defrag(bs))]), defrag(ds)), [Command.Separator]))];
73
+ buffer.push(new Data(html('em', defrag(unwrap(bs)))));
74
+ buffer.import(ds);
75
+ buffer.push(new Data(Command.Separator));
76
+ return prepend('**', buffer);
68
77
  }
69
78
  })
70
- ({ context }) ?? [prepend('**', push(push(buffer!, [html('em', defrag(bs))]), [Command.Separator]))];
79
+ ({ context }) ?? prepend('**', buffer.import(new List([new Data(html('em', defrag(unwrap(bs)))), new Data(Command.Separator)])));
71
80
  }
72
81
  assert(false);
73
82
  },
74
- ([, bs], { buffer }) => bs && [push(push(buffer!, bs), [Command.Cancel])]),
83
+ ([, bs], { buffer }) => bs && buffer!.import(bs) && buffer!.push(new Data(Command.Cancel)) && buffer!),
75
84
  // 3以上の`*`に対してemの適用を保証する
76
- nodes => [html('em', [html('strong', defrag(nodes))])],
85
+ nodes => new List([new Data(html('em', [html('strong', defrag(unwrap(nodes)))]))]),
77
86
  (nodes, context, prefix, postfix, state) => {
78
87
  context.position += postfix;
79
88
  assert(postfix < 3);
@@ -82,10 +91,10 @@ export const emstrong: EmStrongParser = lazy(() => validate('***',
82
91
  case 0:
83
92
  break;
84
93
  case 1:
85
- nodes = [html('em', defrag(nodes))];
94
+ nodes = new List([new Data(html('em', defrag(unwrap(nodes))))]);
86
95
  break;
87
96
  case 2:
88
- nodes = [html('strong', defrag(nodes))];
97
+ nodes = new List([new Data(html('strong', defrag(unwrap(nodes))))]);
89
98
  break;
90
99
  default:
91
100
  assert(false);
@@ -96,51 +105,51 @@ export const emstrong: EmStrongParser = lazy(() => validate('***',
96
105
  case 0:
97
106
  break;
98
107
  case 1:
99
- nodes = bind<EmphasisParser>(
108
+ nodes = eval(bind<EmphasisParser>(
100
109
  subemphasis,
101
110
  ds => {
102
111
  const { source } = context;
103
112
  if (source.startsWith('*', context.position)) {
104
113
  context.position += 1;
105
- return [[html('em', push(nodes, defrag(ds)))]];
114
+ return new List([new Data(html('em', defrag(unwrap(nodes.import(ds)))))]);
106
115
  }
107
116
  else {
108
- return [prepend('*', push(nodes, defrag(ds)))];
117
+ return prepend('*', nodes.import(ds));
109
118
  }
110
119
  })
111
- ({ context })?.[0] ?? prepend('*', nodes);
120
+ ({ context })) ?? prepend('*', nodes);
112
121
  prefix -= 1;
113
122
  break;
114
123
  case 2:
115
- nodes = bind<StrongParser>(
124
+ nodes = eval(bind<StrongParser>(
116
125
  substrong,
117
126
  ds => {
118
127
  const { source } = context;
119
128
  if (source.startsWith('**', context.position)) {
120
129
  context.position += 2;
121
- return [[html('strong', push(nodes, defrag(ds)))]];
130
+ return new List([new Data(html('strong', defrag(unwrap(nodes.import(ds)))))]);
122
131
  }
123
132
  else {
124
- return [prepend('**', push(nodes, defrag(ds)))];
133
+ return prepend('**', nodes.import(ds));
125
134
  }
126
135
  })
127
- ({ context })?.[0] ?? prepend('**', nodes);
136
+ ({ context })) ?? prepend('**', nodes);
128
137
  prefix -= 2;
129
138
  break;
130
139
  }
131
140
  }
132
141
  if (prefix > postfix) {
133
- nodes = push(['*'.repeat(prefix - postfix)], nodes);
142
+ nodes = prepend('*'.repeat(prefix - postfix), nodes);
134
143
  }
135
- return [nodes];
144
+ return nodes;
136
145
  }))));
137
146
 
138
- function prepend<N>(prefix: string, nodes: N[]): N[] {
139
- if (typeof nodes[0] === 'string') {
140
- nodes[0] = prefix + nodes[0] as N;
147
+ function prepend<N>(prefix: string, nodes: List<Data<N>>): List<Data<N>> {
148
+ if (typeof nodes.head?.value === 'string') {
149
+ nodes.head.value = prefix + nodes.head.value as N;
141
150
  }
142
151
  else {
143
- unshift([prefix], nodes);
152
+ nodes.unshift(new Data(prefix as N));
144
153
  }
145
154
  return nodes;
146
155
  }
@@ -1,12 +1,13 @@
1
1
  import { ExtensionParser } from '../../inline';
2
2
  import { State, Backtrack } from '../../context';
3
+ import { List, Data } from '../../../combinator/data/parser';
3
4
  import { union, inits, some, precedence, state, constraint, validate, surround, lazy, fmap } from '../../../combinator';
4
5
  import { inline } from '../../inline';
5
6
  import { indexee, identity } from './indexee';
6
7
  import { unsafehtmlentity } from '../htmlentity';
7
8
  import { txt, str } from '../../source';
8
9
  import { tightStart, trimBlankNodeEnd } from '../../visibility';
9
- import { unshift } from 'spica/array';
10
+ import { unwrap } from '../../util';
10
11
  import { html, define, defrag } from 'typed-dom/dom';
11
12
 
12
13
  import IndexParser = ExtensionParser.IndexParser;
@@ -23,23 +24,23 @@ export const index: IndexParser = lazy(() => constraint(State.index, fmap(indexe
23
24
  false,
24
25
  ([, bs], context) =>
25
26
  context.linebreak === 0 && trimBlankNodeEnd(bs).length > 0
26
- ? [[html('a', { 'data-index': dataindex(bs) }, defrag(bs))]]
27
+ ? new List([new Data(html('a', { 'data-index': dataindex(bs) }, defrag(unwrap(bs))))])
27
28
  : undefined,
28
29
  undefined,
29
30
  [3 | Backtrack.bracket])),
30
31
  ns => {
31
32
  if (ns.length === 1) {
32
- const el = ns[0] as HTMLElement;
33
- return [
34
- define(el, {
33
+ const el = ns.head!.value as HTMLElement;
34
+ return new List([
35
+ new Data(define(el, {
35
36
  id: el.id ? null : undefined,
36
37
  class: 'index',
37
38
  href: el.id ? `#${el.id}` : undefined,
38
- })
39
- ];
39
+ }))
40
+ ]);
40
41
  }
41
42
  else {
42
- assert(ns.at(-1) === '');
43
+ assert(ns.last?.value === '');
43
44
  ns.pop();
44
45
  return ns;
45
46
  }
@@ -54,21 +55,23 @@ export const signature: IndexParser.SignatureParser = lazy(() => validate('|', s
54
55
  /(?=])/y,
55
56
  false,
56
57
  ([, ns], context) => {
57
- const index = identity('index', undefined, ns.join(''))?.slice(7);
58
+ const index = identity('index', undefined, ns.foldl((acc, { value }) => acc + value, ''))?.slice(7);
58
59
  return index && context.linebreak === 0
59
- ? [[html('span', { class: 'indexer', 'data-index': index })]]
60
+ ? new List([new Data(html('span', { class: 'indexer', 'data-index': index }))])
60
61
  : undefined;
61
62
  },
62
- ([as, bs]) => bs && [unshift(as, bs)],
63
+ ([as, bs]) => bs && as.import(bs),
63
64
  [3 | Backtrack.bracket])));
64
65
 
65
- export function dataindex(ns: readonly (string | HTMLElement)[]): string | undefined {
66
- if (ns.length === 0) return;
67
- for (let i = ns.length; i--;) {
68
- const node = ns[i];
69
- if (typeof node === 'string') return;
70
- if (i === ns.length - 1 && ['UL', 'OL'].includes(node.tagName)) continue;
71
- if (!node.classList.contains('indexer')) return;
72
- return node.getAttribute('data-index') ?? undefined;
66
+ export function dataindex(nodes: List<Data<string | HTMLElement>>): string | undefined {
67
+ let node = nodes.last;
68
+ if (typeof node?.value !== 'object') return;
69
+ switch (node.value.tagName) {
70
+ case 'UL':
71
+ case 'OL':
72
+ node = node.prev;
73
+ if (typeof node?.value !== 'object') return;
73
74
  }
75
+ if (!node.value.classList.contains('indexer')) return;
76
+ return node.value.getAttribute('data-index') ?? undefined;
74
77
  }
@@ -1,5 +1,5 @@
1
1
  import { MarkdownParser } from '../../../../markdown';
2
- import { Parser } from '../../../combinator/data/parser';
2
+ import { Parser, List, Data } from '../../../combinator/data/parser';
3
3
  import { fmap } from '../../../combinator';
4
4
  import { define } from 'typed-dom/dom';
5
5
 
@@ -7,7 +7,7 @@ export function indexee<P extends Parser<unknown, MarkdownParser.Context>>(parse
7
7
  export function indexee(parser: Parser<HTMLElement, MarkdownParser.Context>): Parser<HTMLElement> {
8
8
  return fmap(parser, (ns, { id }) =>
9
9
  ns.length === 1
10
- ? [define(ns[0], { id: identity('index', id, ns[0]), 'data-index': null })]
10
+ ? new List([new Data(define(ns.head!.value, { id: identity('index', id, ns.head!.value), 'data-index': null }))])
11
11
  : ns);
12
12
  }
13
13
 
@@ -1,4 +1,5 @@
1
1
  import { ExtensionParser } from '../../inline';
2
+ import { List, Data } from '../../../combinator/data/parser';
2
3
  import { union, focus, surround } from '../../../combinator';
3
4
  import { signature } from './index';
4
5
  import { html } from 'typed-dom/dom';
@@ -13,6 +14,6 @@ export const indexer: ExtensionParser.IndexerParser = surround(
13
14
  /\s\[(?=\|\S)/y,
14
15
  union([
15
16
  signature,
16
- focus(/\|(?=\])/y, () => [[html('span', { class: 'indexer', 'data-index': '' })]]),
17
+ focus(/\|(?=\])/y, () => new List([new Data(html('span', { class: 'indexer', 'data-index': '' }))])),
17
18
  ]),
18
19
  /\]\s*$/y);