securemark 0.293.5 → 0.294.1

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 (106) hide show
  1. package/CHANGELOG.md +8 -0
  2. package/dist/index.js +973 -617
  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 +4 -4
  7. package/src/combinator/control/constraint/line.test.ts +7 -7
  8. package/src/combinator/control/constraint/line.ts +2 -2
  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 -8
  15. package/src/combinator/control/manipulation/reverse.ts +2 -2
  16. package/src/combinator/control/manipulation/scope.ts +4 -7
  17. package/src/combinator/control/manipulation/surround.ts +16 -20
  18. package/src/combinator/control/monad/bind.ts +7 -8
  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 +8 -11
  24. package/src/combinator/data/parser/sequence.test.ts +3 -3
  25. package/src/combinator/data/parser/sequence.ts +8 -11
  26. package/src/combinator/data/parser/some.test.ts +3 -3
  27. package/src/combinator/data/parser/some.ts +7 -9
  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 +11 -20
  33. package/src/debug.test.ts +7 -6
  34. package/src/parser/api/bind.ts +8 -10
  35. package/src/parser/api/header.ts +2 -2
  36. package/src/parser/api/normalize.ts +2 -2
  37. package/src/parser/api/parse.ts +4 -2
  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 +24 -20
  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 +11 -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 +37 -28
  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/processor/note.ts +2 -2
  99. package/src/parser/segment.ts +5 -3
  100. package/src/parser/source/escapable.ts +9 -8
  101. package/src/parser/source/line.ts +9 -3
  102. package/src/parser/source/str.ts +3 -3
  103. package/src/parser/source/text.ts +9 -8
  104. package/src/parser/source/unescapable.ts +6 -5
  105. package/src/parser/util.ts +20 -15
  106. package/src/parser/visibility.ts +19 -20
@@ -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 } 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);
@@ -102,13 +111,13 @@ export const emstrong: EmStrongParser = lazy(() => validate('***',
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:
@@ -118,29 +127,29 @@ export const emstrong: EmStrongParser = lazy(() => validate('***',
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);
@@ -1,5 +1,6 @@
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, constraint, clear, surround, fmap } from '../../../combinator';
4
5
  import { str } from '../../source';
5
6
  import { html } from 'typed-dom/dom';
@@ -16,9 +17,12 @@ export const label: ExtensionParser.LabelParser = constraint(State.label, fmap(
16
17
  surround('[', body, ']', false, undefined, undefined, [1 | Backtrack.bracket, 1]),
17
18
  body,
18
19
  ]),
19
- ([text]) => [
20
- html('a', { class: 'label', 'data-label': text.slice(text[1] === '-' ? 0 : 1).toLowerCase() }, text),
21
- ]));
20
+ ([{ value }]) => new List([
21
+ new Data(html('a', {
22
+ class: 'label',
23
+ 'data-label': value.slice(value[1] === '-' ? 0 : 1).toLowerCase(),
24
+ }, value)),
25
+ ])));
22
26
 
23
27
  export function number(label: string, base: string): string {
24
28
  return isFixed(label)
@@ -1,11 +1,11 @@
1
1
  import { ExtensionParser } from '../../inline';
2
2
  import { Recursion, Backtrack } from '../../context';
3
+ import { List, Data } from '../../../combinator/data/parser';
3
4
  import { union, some, recursion, precedence, surround, lazy } from '../../../combinator';
4
5
  import { inline } from '../../inline';
5
6
  import { str } from '../../source';
6
7
  import { tightStart } from '../../visibility';
7
8
  import { invalid } from '../../util';
8
- import { unshift } from 'spica/array';
9
9
  import { html } from 'typed-dom/dom';
10
10
 
11
11
  // Don't use the symbols already used: !#$%@&*+~=|
@@ -18,13 +18,13 @@ export const placeholder: ExtensionParser.PlaceholderParser = lazy(() => surroun
18
18
  precedence(1, recursion(Recursion.inline,
19
19
  tightStart(some(union([inline]), ']', [[']', 1]])))),
20
20
  str(']'), false,
21
- (_, context) => [[
22
- html('span',
21
+ (_, context) => new List([
22
+ new Data(html('span',
23
23
  {
24
24
  class: 'invalid',
25
25
  ...invalid('extension', 'syntax', `Invalid start symbol or linebreak`),
26
26
  },
27
- context.source.slice(context.position - context.range!, context.position))
28
- ]],
29
- ([as, bs]) => bs && [unshift(as, bs)],
27
+ context.source.slice(context.position - context.range!, context.position)))
28
+ ]),
29
+ ([as, bs]) => bs && as.import(bs as List<Data<string>>),
30
30
  [3 | Backtrack.bracket]));
@@ -1,13 +1,12 @@
1
1
  import { HTMLParser } from '../inline';
2
2
  import { Recursion } from '../context';
3
- import { Ctx } from '../../combinator/data/parser';
3
+ import { List, Data, Ctx } from '../../combinator/data/parser';
4
4
  import { union, some, recursion, precedence, validate, surround, open, match, lazy } from '../../combinator';
5
5
  import { inline } from '../inline';
6
6
  import { str } from '../source';
7
7
  import { isLooseNodeStart, blankWith } from '../visibility';
8
- import { invalid } from '../util';
8
+ import { invalid, unwrap } from '../util';
9
9
  import { memoize } from 'spica/memoize';
10
- import { unshift, push } from 'spica/array';
11
10
  import { html as h, defrag } from 'typed-dom/dom';
12
11
 
13
12
  const tags: readonly string[] = ['wbr', 'bdo', 'bdi'];
@@ -28,10 +27,10 @@ export const html: HTMLParser = lazy(() => validate(/<[a-z]+(?=[ >])/yi,
28
27
  some(union([attribute])),
29
28
  open(str(/ ?/y), str('>'), true),
30
29
  true,
31
- ([as, bs = [], cs], context) =>
32
- [[elem(as[0].slice(1), false, push(unshift(as, bs), cs), [], [], context)]],
33
- ([as, bs = []], context) =>
34
- [[elem(as[0].slice(1), false, unshift(as, bs), [], [], context)]]),
30
+ ([as, bs = new List(), cs], context) =>
31
+ new List([new Data(elem(as.head!.value.slice(1), false, [...unwrap(as.import(bs).import(cs))], new List(), new List(), context))]),
32
+ ([as, bs = new List()], context) =>
33
+ new List([new Data(elem(as.head!.value.slice(1), false, [...unwrap(as.import(bs))], new List(), new List(), context))])),
35
34
  match(
36
35
  new RegExp(String.raw`<(${TAGS.join('|')})(?=[^\S\n]|>)`, 'y'),
37
36
  memoize(
@@ -40,8 +39,8 @@ export const html: HTMLParser = lazy(() => validate(/<[a-z]+(?=[ >])/yi,
40
39
  surround(
41
40
  str(`<${tag}`), some(attribute), open(str(/ ?/y), str('>'), true),
42
41
  true,
43
- ([as, bs = [], cs]) => [push(unshift(as, bs), cs)],
44
- ([as, bs = []]) => [unshift(as, bs)]),
42
+ ([as, bs = new List(), cs]) => as.import(bs).import(cs),
43
+ ([as, bs = new List()]) => as.import(bs)),
45
44
  // 不可視のHTML構造が可視構造を変化させるべきでない。
46
45
  // 可視のHTMLは優先度変更を検討する。
47
46
  // このため<>は将来的に共通構造を変化させる可能性があり
@@ -53,10 +52,10 @@ export const html: HTMLParser = lazy(() => validate(/<[a-z]+(?=[ >])/yi,
53
52
  ])))),
54
53
  str(`</${tag}>`),
55
54
  true,
56
- ([as, bs = [], cs], context) =>
57
- [[elem(tag, true, as, bs, cs, context)]],
58
- ([as, bs = []], context) =>
59
- [[elem(tag, true, as, bs, [], context)]]),
55
+ ([as, bs = new List(), cs], context) =>
56
+ new List([new Data(elem(tag, true, [...unwrap(as)], bs, cs, context))]),
57
+ ([as, bs = new List()], context) =>
58
+ new List([new Data(elem(tag, true, [...unwrap(as)], bs, new List(), context))])),
60
59
  ([, tag]) => tag,
61
60
  new Map())),
62
61
  surround(
@@ -65,10 +64,10 @@ export const html: HTMLParser = lazy(() => validate(/<[a-z]+(?=[ >])/yi,
65
64
  some(union([attribute])),
66
65
  open(str(/ ?/y), str('>'), true),
67
66
  true,
68
- ([as, bs = [], cs], context) =>
69
- [[elem(as[0].slice(1), false, push(unshift(as, bs), cs), [], [], context)]],
70
- ([as, bs = []], context) =>
71
- [[elem(as[0].slice(1), false, unshift(as, bs), [], [], context)]]),
67
+ ([as, bs = new List(), cs], context) =>
68
+ new List([new Data(elem(as.head!.value.slice(1), false, [...unwrap(as.import(bs).import(cs))], new List(), new List(), context))]),
69
+ ([as, bs = new List()], context) =>
70
+ new List([new Data(elem(as.head!.value.slice(1), false, [...unwrap(as.import(bs))], new List(), new List(), context))])),
72
71
  ])));
73
72
 
74
73
  export const attribute: HTMLParser.AttributeParser = union([
@@ -76,7 +75,7 @@ export const attribute: HTMLParser.AttributeParser = union([
76
75
  str(/ [^\s<>]+/y),
77
76
  ]);
78
77
 
79
- function elem(tag: string, content: boolean, as: string[], bs: (HTMLElement | string)[], cs: string[], context: Ctx): HTMLElement {
78
+ function elem(tag: string, content: boolean, as: readonly string[], bs: List<Data<HTMLElement | string>>, cs: List<Data<string>>, context: Ctx): HTMLElement {
80
79
  assert(as.length > 0);
81
80
  assert(as[0][0] === '<');
82
81
  if (!tags.includes(tag)) return ielem('tag', `Invalid HTML tag name "${tag}"`, context);
@@ -88,7 +87,7 @@ function elem(tag: string, content: boolean, as: string[], bs: (HTMLElement | st
88
87
  const [attrs] = attributes('html', attrspecs[tag], as.slice(1, as.at(-1) === '>' ? -1 : as.length));
89
88
  if (/(?<!\S)invalid(?!\S)/.test(attrs['class'] ?? '')) return ielem('attribute', 'Invalid HTML attribute', context)
90
89
  if (as.at(-1) !== '>') return ielem('tag', `Missing the closing symbol ">"`, context);
91
- return h(tag as 'span', attrs, defrag(bs));
90
+ return h(tag as 'span', attrs, defrag(unwrap(bs)));
92
91
  }
93
92
 
94
93
  function ielem(type: string, message: string, context: Ctx): HTMLElement {
@@ -105,7 +104,7 @@ const requiredAttributes = memoize(
105
104
  export function attributes(
106
105
  syntax: string,
107
106
  spec: Readonly<Record<string, readonly (string | undefined)[] | undefined>> | undefined,
108
- params: readonly string[],
107
+ params: Iterable<string>,
109
108
  ): [Record<string, string | undefined>, string[]] {
110
109
  assert(spec instanceof Object === false);
111
110
  assert(!spec?.['__proto__']);
@@ -113,17 +112,17 @@ export function attributes(
113
112
  const remains = [];
114
113
  let invalidation = false;
115
114
  const attrs: Record<string, string | undefined> = {};
116
- for (let i = 0; i < params.length; ++i) {
117
- const param = params[i].trimStart();
118
- if (param === '') continue;
119
- const name = param.split('=', 1)[0];
120
- const value = param !== name
121
- ? param.slice(name.length + 2, -1).replace(/\\(.?)/g, '$1')
115
+ for (const param of params) {
116
+ const attr = param.trimStart();
117
+ if (attr === '') continue;
118
+ const name = attr.split('=', 1)[0];
119
+ const value = attr !== name
120
+ ? attr.slice(name.length + 2, -1).replace(/\\(.?)/g, '$1')
122
121
  : undefined;
123
122
  invalidation ||= name === '' || !spec || name in attrs;
124
- if (name === '')continue;
123
+ if (name === '') continue;
125
124
  if (spec && name in spec && !spec[name]) {
126
- remains.push(params[i]);
125
+ remains.push(param);
127
126
  continue;
128
127
  }
129
128
  if (spec?.[name]?.includes(value) || spec?.[name]?.length === 0 && value !== undefined) {
@@ -1,4 +1,5 @@
1
1
  import { HTMLEntityParser, UnsafeHTMLEntityParser } from '../inline';
2
+ import { List, Data } from '../../combinator/data/parser';
2
3
  import { union, focus, fmap } from '../../combinator';
3
4
  import { invalid } from '../util';
4
5
  import { html } from 'typed-dom/dom';
@@ -10,20 +11,20 @@ export const unsafehtmlentity: UnsafeHTMLEntityParser = focus(
10
11
  const { source } = context;
11
12
  context.position += source.length;
12
13
  return source.length > 1 && source.at(-1) === ';'
13
- ? [[parser(source) ?? source]]
14
- : [[source]];
14
+ ? new List([new Data(parser(source) ?? source)])
15
+ : new List([new Data(source)]);
15
16
  });
16
17
 
17
18
  export const htmlentity: HTMLEntityParser = fmap(
18
19
  union([unsafehtmlentity]),
19
- ([text]) => [
20
- length === 1 || text.at(-1) !== ';'
21
- ? text
22
- : html('span', {
20
+ ([{ value }]) => new List([
21
+ length === 1 || value.at(-1) !== ';'
22
+ ? new Data(value)
23
+ : new Data(html('span', {
23
24
  class: 'invalid',
24
25
  ...invalid('htmlentity', 'syntax', 'Invalid HTML entity'),
25
- }, text)
26
- ]);
26
+ }, value))
27
+ ]));
27
28
 
28
29
  const parser = (el => (entity: string): string | undefined => {
29
30
  if (entity === '&NewLine;') return ' ';
@@ -1,10 +1,10 @@
1
1
  import { InsertionParser } 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 insertion: InsertionParser = lazy(() => validate('++',
@@ -16,6 +16,6 @@ export const insertion: InsertionParser = 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('ins', 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('ins', defrag(unwrap(nodes))))])))));
@@ -1,10 +1,10 @@
1
1
  import { ItalicParser } 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 { tightStart, 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
  // 可読性のため実際にはオブリーク体を指定する。
@@ -19,6 +19,6 @@ export const italic: ItalicParser = lazy(() => validate('///',
19
19
  open(some(inline, '/'), inline),
20
20
  ])))),
21
21
  '///', false,
22
- ([, bs], { buffer }) => [push(buffer!, bs)],
23
- ([, bs], { buffer }) => bs && [push(push(buffer!, bs), [Command.Cancel])]),
24
- nodes => [html('i', defrag(nodes))]))));
22
+ ([, bs], { buffer }) => buffer!.import(bs),
23
+ ([, bs], { buffer }) => bs && buffer!.import(bs).push(new Data(Command.Cancel)) && buffer!),
24
+ nodes => new List([new Data(html('i', defrag(unwrap(nodes))))])))));