securemark 0.299.4 → 0.300.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 (233) hide show
  1. package/CHANGELOG.md +8 -0
  2. package/design.md +0 -6
  3. package/dist/index.js +2847 -1993
  4. package/index.d.ts +2 -1
  5. package/markdown.d.ts +209 -183
  6. package/package.json +1 -1
  7. package/src/api/bind.test.ts +0 -22
  8. package/src/api/bind.ts +15 -10
  9. package/src/api/header.ts +8 -5
  10. package/src/api/parse.test.ts +118 -122
  11. package/src/api/parse.ts +13 -31
  12. package/src/api/run.ts +6 -0
  13. package/src/api.ts +1 -0
  14. package/src/combinator/control/inits.ts +35 -0
  15. package/src/combinator/control/sequence.test.ts +38 -0
  16. package/src/combinator/control/sequence.ts +19 -0
  17. package/src/combinator/control/some.test.ts +41 -0
  18. package/src/combinator/{data/parser → control}/some.ts +39 -26
  19. package/src/combinator/control/state.ts +33 -0
  20. package/src/combinator/control/subsequence.test.ts +47 -0
  21. package/src/combinator/control/subsequence.ts +16 -0
  22. package/src/combinator/control/tails.ts +8 -0
  23. package/src/combinator/control/union.test.ts +37 -0
  24. package/src/combinator/control/union.ts +31 -0
  25. package/src/combinator/{data/delimiter.ts → delimiter.ts} +40 -60
  26. package/src/combinator/effect/backtrack.ts +64 -0
  27. package/src/combinator/effect/clock.ts +10 -0
  28. package/src/combinator/effect/precedence.ts +50 -0
  29. package/src/combinator/effect/recursion.ts +30 -0
  30. package/src/combinator/effect/scope.ts +100 -0
  31. package/src/combinator/effect/state.ts +72 -0
  32. package/src/combinator/{data/list → parser}/list.ts +35 -10
  33. package/src/combinator/parser.ts +303 -0
  34. package/src/combinator/process/bind.ts +34 -0
  35. package/src/combinator/process/block.test.ts +20 -0
  36. package/src/combinator/process/block.ts +33 -0
  37. package/src/combinator/process/clear.ts +16 -0
  38. package/src/combinator/process/contract.ts +35 -0
  39. package/src/combinator/process/duplicate.ts +7 -0
  40. package/src/combinator/process/error.ts +13 -0
  41. package/src/combinator/{control/manipulation → process}/fallback.ts +3 -3
  42. package/src/combinator/process/fence.ts +59 -0
  43. package/src/combinator/process/fmap.ts +10 -0
  44. package/src/combinator/process/indent.test.ts +31 -0
  45. package/src/combinator/process/indent.ts +51 -0
  46. package/src/combinator/process/lazy.ts +8 -0
  47. package/src/combinator/process/line.test.ts +21 -0
  48. package/src/combinator/process/line.ts +55 -0
  49. package/src/combinator/process/match.ts +37 -0
  50. package/src/combinator/process/reverse.ts +7 -0
  51. package/src/combinator/process/scope.ts +102 -0
  52. package/src/combinator/process/surround.ts +273 -0
  53. package/src/combinator.ts +28 -24
  54. package/src/debug.test.ts +11 -8
  55. package/src/parser/autolink.test.ts +17 -18
  56. package/src/parser/block/blockquote.test.ts +78 -79
  57. package/src/parser/block/blockquote.ts +32 -25
  58. package/src/parser/block/codeblock.test.ts +54 -57
  59. package/src/parser/block/codeblock.ts +44 -26
  60. package/src/parser/block/dlist.test.ts +56 -57
  61. package/src/parser/block/dlist.ts +5 -5
  62. package/src/parser/block/extension/aside.test.ts +7 -9
  63. package/src/parser/block/extension/aside.ts +76 -47
  64. package/src/parser/block/extension/example.test.ts +16 -19
  65. package/src/parser/block/extension/example.ts +88 -48
  66. package/src/parser/block/extension/fig.test.ts +37 -36
  67. package/src/parser/block/extension/fig.ts +20 -25
  68. package/src/parser/block/extension/figbase.test.ts +18 -19
  69. package/src/parser/block/extension/figbase.ts +3 -3
  70. package/src/parser/block/extension/figure.test.ts +58 -63
  71. package/src/parser/block/extension/figure.ts +23 -21
  72. package/src/parser/block/extension/message.test.ts +12 -14
  73. package/src/parser/block/extension/message.ts +52 -39
  74. package/src/parser/block/extension/placeholder.test.ts +13 -13
  75. package/src/parser/block/extension/placeholder.ts +23 -21
  76. package/src/parser/block/extension/table.test.ts +69 -71
  77. package/src/parser/block/extension/table.ts +43 -31
  78. package/src/parser/block/extension.test.ts +24 -24
  79. package/src/parser/block/extension.ts +3 -3
  80. package/src/parser/block/heading.test.ts +58 -59
  81. package/src/parser/block/heading.ts +19 -18
  82. package/src/parser/block/ilist.test.ts +8 -8
  83. package/src/parser/block/ilist.ts +9 -7
  84. package/src/parser/block/mathblock.test.ts +29 -32
  85. package/src/parser/block/mathblock.ts +24 -23
  86. package/src/parser/block/mediablock.ts +7 -7
  87. package/src/parser/block/olist.test.ts +102 -103
  88. package/src/parser/block/olist.ts +11 -12
  89. package/src/parser/block/pagebreak.test.ts +15 -16
  90. package/src/parser/block/pagebreak.ts +5 -5
  91. package/src/parser/block/paragraph.test.ts +57 -58
  92. package/src/parser/block/paragraph.ts +1 -1
  93. package/src/parser/block/reply/cite.test.ts +39 -40
  94. package/src/parser/block/reply/cite.ts +5 -5
  95. package/src/parser/block/reply/quote.test.ts +50 -51
  96. package/src/parser/block/reply/quote.ts +8 -7
  97. package/src/parser/block/reply.test.ts +19 -20
  98. package/src/parser/block/reply.ts +2 -2
  99. package/src/parser/block/sidefence.test.ts +41 -48
  100. package/src/parser/block/sidefence.ts +17 -11
  101. package/src/parser/block/table.test.ts +48 -49
  102. package/src/parser/block/table.ts +10 -9
  103. package/src/parser/block/ulist.test.ts +52 -53
  104. package/src/parser/block/ulist.ts +9 -8
  105. package/src/parser/block.ts +63 -51
  106. package/src/parser/context.ts +40 -40
  107. package/src/parser/document.ts +48 -0
  108. package/src/parser/header.test.ts +19 -20
  109. package/src/parser/header.ts +31 -25
  110. package/src/parser/inline/annotation.test.ts +49 -50
  111. package/src/parser/inline/annotation.ts +14 -16
  112. package/src/parser/inline/autolink/account.test.ts +32 -33
  113. package/src/parser/inline/autolink/account.ts +18 -19
  114. package/src/parser/inline/autolink/anchor.test.ts +21 -22
  115. package/src/parser/inline/autolink/anchor.ts +7 -8
  116. package/src/parser/inline/autolink/channel.test.ts +14 -15
  117. package/src/parser/inline/autolink/email.test.ts +36 -37
  118. package/src/parser/inline/autolink/email.ts +6 -6
  119. package/src/parser/inline/autolink/hashnum.test.ts +32 -33
  120. package/src/parser/inline/autolink/hashnum.ts +7 -8
  121. package/src/parser/inline/autolink/hashtag.test.ts +59 -60
  122. package/src/parser/inline/autolink/hashtag.ts +8 -9
  123. package/src/parser/inline/autolink/url.test.ts +75 -76
  124. package/src/parser/inline/autolink/url.ts +17 -18
  125. package/src/parser/inline/autolink.ts +24 -11
  126. package/src/parser/inline/bracket.test.ts +73 -74
  127. package/src/parser/inline/bracket.ts +88 -63
  128. package/src/parser/inline/code.test.ts +30 -31
  129. package/src/parser/inline/code.ts +6 -6
  130. package/src/parser/inline/deletion.test.ts +27 -28
  131. package/src/parser/inline/deletion.ts +5 -5
  132. package/src/parser/inline/emphasis.test.ts +39 -40
  133. package/src/parser/inline/emphasis.ts +5 -5
  134. package/src/parser/inline/emstrong.test.ts +101 -102
  135. package/src/parser/inline/emstrong.ts +103 -85
  136. package/src/parser/inline/extension/index.test.ts +91 -92
  137. package/src/parser/inline/extension/index.ts +17 -13
  138. package/src/parser/inline/extension/indexee.ts +4 -4
  139. package/src/parser/inline/extension/indexer.test.ts +23 -24
  140. package/src/parser/inline/extension/indexer.ts +6 -5
  141. package/src/parser/inline/extension/label.test.ts +32 -33
  142. package/src/parser/inline/extension/label.ts +14 -5
  143. package/src/parser/inline/extension/placeholder.test.ts +42 -43
  144. package/src/parser/inline/extension/placeholder.ts +8 -9
  145. package/src/parser/inline/html.test.ts +109 -109
  146. package/src/parser/inline/html.ts +27 -27
  147. package/src/parser/inline/htmlentity.test.ts +37 -38
  148. package/src/parser/inline/htmlentity.ts +6 -7
  149. package/src/parser/inline/insertion.test.ts +27 -28
  150. package/src/parser/inline/insertion.ts +5 -5
  151. package/src/parser/inline/italic.test.ts +55 -56
  152. package/src/parser/inline/italic.ts +5 -5
  153. package/src/parser/inline/link.test.ts +186 -187
  154. package/src/parser/inline/link.ts +29 -30
  155. package/src/parser/inline/mark.test.ts +31 -32
  156. package/src/parser/inline/mark.ts +6 -6
  157. package/src/parser/inline/math.test.ts +140 -141
  158. package/src/parser/inline/math.ts +7 -8
  159. package/src/parser/inline/media.test.ts +92 -93
  160. package/src/parser/inline/media.ts +35 -41
  161. package/src/parser/inline/reference.test.ts +111 -112
  162. package/src/parser/inline/reference.ts +61 -32
  163. package/src/parser/inline/remark.test.ts +49 -50
  164. package/src/parser/inline/remark.ts +13 -13
  165. package/src/parser/inline/ruby.test.ts +49 -50
  166. package/src/parser/inline/ruby.ts +100 -52
  167. package/src/parser/inline/shortmedia.test.ts +9 -10
  168. package/src/parser/inline/shortmedia.ts +11 -9
  169. package/src/parser/inline/strong.test.ts +36 -37
  170. package/src/parser/inline/strong.ts +5 -5
  171. package/src/parser/inline/template.test.ts +22 -23
  172. package/src/parser/inline/template.ts +17 -20
  173. package/src/parser/inline.test.ts +225 -226
  174. package/src/parser/inline.ts +68 -34
  175. package/src/parser/parser.ts +51 -0
  176. package/src/parser/repeat.ts +118 -91
  177. package/src/parser/segment.test.ts +0 -11
  178. package/src/parser/segment.ts +25 -28
  179. package/src/parser/source/escapable.test.ts +23 -24
  180. package/src/parser/source/escapable.ts +19 -20
  181. package/src/parser/source/line.test.ts +17 -18
  182. package/src/parser/source/line.ts +19 -24
  183. package/src/parser/source/str.ts +17 -10
  184. package/src/parser/source/text.test.ts +88 -89
  185. package/src/parser/source/text.ts +32 -62
  186. package/src/parser/source/unescapable.test.ts +23 -24
  187. package/src/parser/source/unescapable.ts +15 -16
  188. package/src/parser/source/whitespace.ts +36 -0
  189. package/src/parser/source.ts +1 -0
  190. package/src/parser/util.ts +1 -1
  191. package/src/parser/visibility.ts +37 -15
  192. package/src/processor/figure.test.ts +20 -20
  193. package/src/processor/figure.ts +18 -10
  194. package/src/processor/note.test.ts +13 -13
  195. package/src/processor/note.ts +4 -2
  196. package/src/renderer/render/media/pdf.ts +2 -2
  197. package/src/renderer/render/media/twitter.ts +2 -2
  198. package/src/renderer/render/media.test.ts +12 -12
  199. package/src/renderer/render.test.ts +11 -11
  200. package/src/util/info.test.ts +2 -2
  201. package/src/util/quote.test.ts +3 -3
  202. package/src/util/quote.ts +6 -5
  203. package/src/util/toc.test.ts +12 -12
  204. package/src/combinator/control/constraint/block.test.ts +0 -20
  205. package/src/combinator/control/constraint/block.ts +0 -28
  206. package/src/combinator/control/constraint/contract.ts +0 -27
  207. package/src/combinator/control/constraint/line.test.ts +0 -21
  208. package/src/combinator/control/constraint/line.ts +0 -42
  209. package/src/combinator/control/manipulation/clear.ts +0 -5
  210. package/src/combinator/control/manipulation/convert.ts +0 -22
  211. package/src/combinator/control/manipulation/duplicate.ts +0 -7
  212. package/src/combinator/control/manipulation/fence.ts +0 -54
  213. package/src/combinator/control/manipulation/indent.test.ts +0 -31
  214. package/src/combinator/control/manipulation/indent.ts +0 -39
  215. package/src/combinator/control/manipulation/lazy.ts +0 -8
  216. package/src/combinator/control/manipulation/match.ts +0 -27
  217. package/src/combinator/control/manipulation/recovery.ts +0 -18
  218. package/src/combinator/control/manipulation/reverse.ts +0 -8
  219. package/src/combinator/control/manipulation/scope.ts +0 -61
  220. package/src/combinator/control/manipulation/surround.ts +0 -223
  221. package/src/combinator/control/monad/bind.ts +0 -26
  222. package/src/combinator/control/monad/fmap.ts +0 -10
  223. package/src/combinator/data/parser/context.ts +0 -96
  224. package/src/combinator/data/parser/inits.ts +0 -20
  225. package/src/combinator/data/parser/sequence.test.ts +0 -33
  226. package/src/combinator/data/parser/sequence.ts +0 -20
  227. package/src/combinator/data/parser/some.test.ts +0 -37
  228. package/src/combinator/data/parser/subsequence.test.ts +0 -41
  229. package/src/combinator/data/parser/subsequence.ts +0 -13
  230. package/src/combinator/data/parser/tails.ts +0 -8
  231. package/src/combinator/data/parser/union.test.ts +0 -33
  232. package/src/combinator/data/parser/union.ts +0 -18
  233. package/src/combinator/data/parser.ts +0 -144
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "securemark",
3
- "version": "0.299.4",
3
+ "version": "0.300.1",
4
4
  "description": "Secure markdown renderer working on browsers for user input data.",
5
5
  "private": false,
6
6
  "homepage": "https://github.com/falsandtru/securemark",
@@ -29,28 +29,6 @@ describe('Unit: api/bind', () => {
29
29
 
30
30
  const cfgs = { notes: { references: html('ol') } };
31
31
 
32
- it('huge input', () => {
33
- const iter = bind(html('div'), { ...cfgs, id: '' }).parse(`${'\n'.repeat(1e6 + 1)}`);
34
- assert.deepStrictEqual(
35
- inspect(iter),
36
- [
37
- '<h1 class="error">Error: Too large input over 1,000,000 bytes.</h1>',
38
- `<pre class="error" translate="no">${'\n'.repeat(997)}...</pre>`,
39
- ]);
40
- });
41
-
42
- it('huge segment', function () {
43
- this.timeout(10 * 1000);
44
-
45
- const iter = bind(html('div'), { ...cfgs, id: '' }).parse(`${'\n'.repeat(1e5 + 1)}`);
46
- assert.deepStrictEqual(
47
- inspect(iter, 3),
48
- [
49
- '<h1 class="error">Error: Too large segment over 100,000 bytes.</h1>',
50
- `<pre class="error" translate="no">${'\n'.repeat(997)}...</pre>`,
51
- ]);
52
- });
53
-
54
32
  it('empty', () => {
55
33
  const el = html('div');
56
34
  const update = bind(el, cfgs).parse;
package/src/api/bind.ts CHANGED
@@ -1,6 +1,6 @@
1
1
  import { ParserSettings, Progress } from '../..';
2
- import { Context, Options, Segment } from '../parser/context';
3
- import { input } from '../combinator/data/parser';
2
+ import { Input, Options, Segment } from '../parser/context';
3
+ import { Output, run } from '../combinator/parser';
4
4
  import { segment } from '../parser/segment';
5
5
  import { block } from '../parser/block';
6
6
  import { headers } from './header';
@@ -20,12 +20,13 @@ export function bind(target: DocumentFragment | HTMLElement | ShadowRoot, settin
20
20
  const options: Options = {
21
21
  ...settings,
22
22
  host: settings.host ?? new ReadonlyURL(location.pathname, location.origin),
23
+ header: true,
23
24
  };
24
25
  if (options.id?.match(/[^0-9a-z/-]/i)) throw new Error('Invalid ID: ID must be alphanumeric');
25
26
  if (options.host?.origin === 'null') throw new Error(`Invalid host: ${options.host.href}`);
26
27
  type Block = readonly [segment: string, blocks: readonly HTMLElement[], url: string];
27
28
  const blocks: Block[] = [];
28
- const adds: (readonly [HTMLElement, Node | null])[] = [];
29
+ const adds: (readonly [HTMLElement, global.Node | null])[] = [];
29
30
  const dels: (readonly [HTMLElement])[] = [];
30
31
  const bottom = target.firstChild;
31
32
  let revision: symbol | undefined;
@@ -43,7 +44,7 @@ export function bind(target: DocumentFragment | HTMLElement | ShadowRoot, settin
43
44
  const rev = revision = Symbol();
44
45
  const sourceSegments: string[] = [];
45
46
  const sourceSegmentAttrs: Segment[] = [];
46
- for (const [seg, attr] of segment(source, true)) {
47
+ for (const [seg, attr] of segment(source)) {
47
48
  sourceSegments.push(seg);
48
49
  sourceSegmentAttrs.push(attr);
49
50
  yield { type: 'segment', value: seg };
@@ -65,18 +66,22 @@ export function bind(target: DocumentFragment | HTMLElement | ShadowRoot, settin
65
66
  }
66
67
  assert(last <= targetSegments.length);
67
68
  assert(head + last <= targetSegments.length);
69
+ const output = new Output<HTMLElement>();
68
70
  const base = next(head);
69
71
  let index = head;
70
- // @ts-expect-error
71
72
  options.header = true;
72
73
  for (; index < sourceSegments.length - last; ++index) {
73
74
  assert(rev === revision);
74
75
  const seg = sourceSegments[index];
75
76
  options.segment = sourceSegmentAttrs[index] | Segment.write;
76
- const es = block(input(seg, new Context(options)))!
77
- .foldl<HTMLElement[]>((acc, { value }) => void acc.push(value) || acc, []);
78
- // @ts-expect-error
79
- options.header = false;
77
+ for (const _ of run(block, new Input(options, seg), output)) {
78
+ yield { type: 'break' };
79
+ }
80
+ assert(output.data.length === 1);
81
+ const es = output.pop()
82
+ .foldl<HTMLElement[]>((acc, { value }) => (acc.push(value), acc), []);
83
+ output.push();
84
+ options.header &&= false;
80
85
  blocks.length === index
81
86
  ? blocks.push([seg, es, url])
82
87
  : blocks.splice(index, 0, [seg, es, url]);
@@ -137,7 +142,7 @@ export function bind(target: DocumentFragment | HTMLElement | ShadowRoot, settin
137
142
  }
138
143
  }
139
144
 
140
- function next(index: number): Node | null {
145
+ function next(index: number): global.Node | null {
141
146
  assert(index >= 0);
142
147
  assert(index <= blocks.length);
143
148
  for (let i = index; i < blocks.length; ++i) {
package/src/api/header.ts CHANGED
@@ -1,4 +1,5 @@
1
- import { Context } from '../parser/context';
1
+ import { Input } from '../parser/context';
2
+ import { Output, run } from '../combinator/parser';
2
3
  import { header as h } from '../parser/header';
3
4
 
4
5
  export function header(source: string): string {
@@ -16,10 +17,12 @@ export function headers(source: string): string[] {
16
17
  }
17
18
 
18
19
  function parse(source: string): [HTMLElement, number] | [] {
19
- const context = new Context({ source });
20
- const result = h(context);
21
- const el = result?.head?.value;
20
+ const input = new Input({ source });
21
+ const output = new Output<HTMLElement>();
22
+ for (const _ of run(h,input, output));
23
+ assert(output.data.length === 1);
24
+ const el = output.peek().head?.value;
22
25
  return el?.tagName === 'ASIDE'
23
- ? [el, context.position]
26
+ ? [el, input.position]
24
27
  : [];
25
28
  }
@@ -1,104 +1,87 @@
1
+ import { run } from './run';
1
2
  import { parse } from './parse';
2
- import { Context } from '../parser/context';
3
+ import { Input } from '../parser/context';
3
4
  import { html } from 'typed-dom/dom';
4
5
  import { normalize } from '../debug.test';
5
6
 
6
7
  describe('Unit: api/parse', () => {
7
8
  describe('parse', () => {
8
- it('huge input', () => {
9
- assert.deepStrictEqual(
10
- [...parse(`${'\n'.repeat(1e6 + 1)}`, { id: '' }).children].map(el => el.outerHTML),
11
- [
12
- '<h1 class="error">Error: Too large input over 1,000,000 bytes.</h1>',
13
- `<pre class="error" translate="no">${'\n'.repeat(997)}...</pre>`,
14
- ]);
15
- });
16
-
17
- it('huge segment', () => {
18
- assert.deepStrictEqual(
19
- [...parse(`${'\n'.repeat(1e5 + 1)}`, { id: '' }).children].map(el => el.outerHTML),
20
- [
21
- '<h1 class="error">Error: Too large segment over 100,000 bytes.</h1>',
22
- `<pre class="error" translate="no">${'\n'.repeat(997)}...</pre>`,
23
- ]);
24
- });
25
-
26
9
  it('result', () => {
27
- assert(parse('') instanceof DocumentFragment);
10
+ assert(run(parse('')) instanceof DocumentFragment);
28
11
  });
29
12
 
30
13
  it('empty', () => {
31
14
  assert.deepStrictEqual(
32
- [...parse('').children].map(el => el.outerHTML),
33
- []);
15
+ [...run(parse('')).children].map(el => el.outerHTML),
16
+ ['<ol class="references"></ol>']);
34
17
  });
35
18
 
36
19
  it('invisible', () => {
37
20
  assert.deepStrictEqual(
38
- [...parse(' ').children].map(el => el.outerHTML),
39
- []);
21
+ [...run(parse(' ')).children].map(el => el.outerHTML),
22
+ ['<ol class="references"></ol>']);
40
23
  assert.deepStrictEqual(
41
- [...parse('\n').children].map(el => el.outerHTML),
42
- []);
24
+ [...run(parse('\n')).children].map(el => el.outerHTML),
25
+ ['<ol class="references"></ol>']);
43
26
  assert.deepStrictEqual(
44
- [...parse('\n\n').children].map(el => el.outerHTML),
45
- []);
27
+ [...run(parse('\n\n')).children].map(el => el.outerHTML),
28
+ ['<ol class="references"></ol>']);
46
29
  assert.deepStrictEqual(
47
- [...parse('\\').children].map(el => el.outerHTML),
48
- ['<p>\\</p>']);
30
+ [...run(parse('\\')).children].map(el => el.outerHTML),
31
+ ['<p>\\</p>', '<ol class="references"></ol>']);
49
32
  assert.deepStrictEqual(
50
- [...parse('\\\na').children].map(el => el.outerHTML),
51
- ['<p>\\<br>a</p>']);
33
+ [...run(parse('\\\na')).children].map(el => el.outerHTML),
34
+ ['<p>\\<br>a</p>', '<ol class="references"></ol>']);
52
35
  assert.deepStrictEqual(
53
- [...parse('&Tab;').children].map(el => el.outerHTML),
54
- ['<p>&amp;Tab;</p>']);
36
+ [...run(parse('&Tab;')).children].map(el => el.outerHTML),
37
+ ['<p>&amp;Tab;</p>', '<ol class="references"></ol>']);
55
38
  assert.deepStrictEqual(
56
- [...parse('&Tab;\na').children].map(el => el.outerHTML),
57
- ['<p>&amp;Tab;<br>a</p>']);
39
+ [...run(parse('&Tab;\na')).children].map(el => el.outerHTML),
40
+ ['<p>&amp;Tab;<br>a</p>', '<ol class="references"></ol>']);
58
41
  assert.deepStrictEqual(
59
- [...parse('<wbr>').children].map(el => el.outerHTML),
60
- ['<p>&lt;wbr&gt;</p>']);
42
+ [...run(parse('<wbr>')).children].map(el => el.outerHTML),
43
+ ['<p>&lt;wbr&gt;</p>', '<ol class="references"></ol>']);
61
44
  assert.deepStrictEqual(
62
- [...parse('<wbr>\na').children].map(el => el.outerHTML),
63
- ['<p>&lt;wbr&gt;<br>a</p>']);
45
+ [...run(parse('<wbr>\na')).children].map(el => el.outerHTML),
46
+ ['<p>&lt;wbr&gt;<br>a</p>', '<ol class="references"></ol>']);
64
47
  assert.deepStrictEqual(
65
- [...parse('[%\n<wbr>\n%]').children].map(el => el.outerHTML),
66
- ['<p><span class="remark"><input type="checkbox"><span>[%<br>&lt;wbr&gt;<br>%]</span></span></p>']);
48
+ [...run(parse('[%\n<wbr>\n%]')).children].map(el => el.outerHTML),
49
+ ['<p><span class="remark"><input type="checkbox"><span>[%<br>&lt;wbr&gt;<br>%]</span></span></p>', '<ol class="references"></ol>']);
67
50
  assert.deepStrictEqual(
68
- [...parse('[%\n<wbr>\n%]\na').children].map(el => el.outerHTML),
69
- ['<p><span class="remark"><input type="checkbox"><span>[%<br>&lt;wbr&gt;<br>%]</span></span><br>a</p>']);
51
+ [...run(parse('[%\n<wbr>\n%]\na')).children].map(el => el.outerHTML),
52
+ ['<p><span class="remark"><input type="checkbox"><span>[%<br>&lt;wbr&gt;<br>%]</span></span><br>a</p>', '<ol class="references"></ol>']);
70
53
  });
71
54
 
72
55
  it('linebreak', () => {
73
56
  assert.deepStrictEqual(
74
- [...parse('\\ ').children].map(el => el.outerHTML),
75
- ['<p>\\</p>']);
57
+ [...run(parse('\\ ')).children].map(el => el.outerHTML),
58
+ ['<p>\\</p>', '<ol class="references"></ol>']);
76
59
  assert.deepStrictEqual(
77
- [...parse('\\\n').children].map(el => el.outerHTML),
78
- ['<p>\\</p>']);
60
+ [...run(parse('\\\n')).children].map(el => el.outerHTML),
61
+ ['<p>\\</p>', '<ol class="references"></ol>']);
79
62
  assert.deepStrictEqual(
80
- [...parse('a\\ \nb').children].map(el => el.outerHTML),
81
- ['<p>a <br>b</p>']);
63
+ [...run(parse('a\\ \nb')).children].map(el => el.outerHTML),
64
+ ['<p>a <br>b</p>', '<ol class="references"></ol>']);
82
65
  assert.deepStrictEqual(
83
- [...parse('a\\\nb').children].map(el => el.outerHTML),
84
- ['<p>a<br>b</p>']);
66
+ [...run(parse('a\\\nb')).children].map(el => el.outerHTML),
67
+ ['<p>a<br>b</p>', '<ol class="references"></ol>']);
85
68
  assert.deepStrictEqual(
86
- [...parse('a\n\\ \nb').children].map(el => el.outerHTML),
87
- ['<p>a<br>\\<br>b</p>']);
69
+ [...run(parse('a\n\\ \nb')).children].map(el => el.outerHTML),
70
+ ['<p>a<br>\\<br>b</p>', '<ol class="references"></ol>']);
88
71
  assert.deepStrictEqual(
89
- [...parse('a\n\\\nb').children].map(el => el.outerHTML),
90
- ['<p>a<br>\\<br>b</p>']);
72
+ [...run(parse('a\n\\\nb')).children].map(el => el.outerHTML),
73
+ ['<p>a<br>\\<br>b</p>', '<ol class="references"></ol>']);
91
74
  });
92
75
 
93
76
  it('indent', () => {
94
77
  assert.deepStrictEqual(
95
- [...parse('\ta').children].map(el => el.outerHTML),
96
- ['<p>\ta</p>']);
78
+ [...run(parse('\ta')).children].map(el => el.outerHTML),
79
+ ['<p>\ta</p>', '<ol class="references"></ol>']);
97
80
  });
98
81
 
99
82
  it('url', () => {
100
83
  assert.deepStrictEqual(
101
- [...parse([
84
+ [...run(parse([
102
85
  [
103
86
  '---',
104
87
  'URL: https://source/x/y',
@@ -123,7 +106,7 @@ describe('Unit: api/parse', () => {
123
106
  '!{a}',
124
107
  '!{^/a}',
125
108
  '!{../../a}',
126
- ].join('\n\n'), { host: new URL(`${location.origin}/z`) }).children].map(el => el.outerHTML),
109
+ ].join('\n\n'), { host: new URL(`${location.origin}/z`) })).children].map(el => el.outerHTML),
127
110
  [
128
111
  '<aside class="header"><details open=""><summary>Header</summary><div class="field" data-name="url" data-value="https://source/x/y"><span class="field-name">URL</span>: <span class="field-value">https://source/x/y</span></div></details></aside>',
129
112
  '<p><a class="account" href="https://source/@a" target="_blank">@a</a></p>',
@@ -146,9 +129,10 @@ describe('Unit: api/parse', () => {
146
129
  '<div><a href="/z/a" target="_blank"><img class="media" data-src="/z/a" alt="^/a"></a></div>',
147
130
  '<div><a href="https://source/a" target="_blank"><img class="media" data-src="https://source/a" alt="../../a"></a></div>',
148
131
  '<ol class="annotations"><li id="annotation::def:a:1" data-marker="*1"><span>a</span><sup><a href="#annotation::ref:a:1">^1</a></sup></li></ol>',
132
+ '<ol class="references"></ol>',
149
133
  ]);
150
134
  assert.deepStrictEqual(
151
- [...parse([
135
+ [...run(parse([
152
136
  [
153
137
  '---',
154
138
  'URL: https://source/x/y',
@@ -156,14 +140,15 @@ describe('Unit: api/parse', () => {
156
140
  ].join('\n'),
157
141
  '{^/a}',
158
142
  '{./a}',
159
- ].join('\n\n'), { host: new URL(`${location.origin}/index.md`) }).children].map(el => el.outerHTML),
143
+ ].join('\n\n'), { host: new URL(`${location.origin}/index.md`) })).children].map(el => el.outerHTML),
160
144
  [
161
145
  '<aside class="header"><details open=""><summary>Header</summary><div class="field" data-name="url" data-value="https://source/x/y"><span class="field-name">URL</span>: <span class="field-value">https://source/x/y</span></div></details></aside>',
162
146
  '<p><a class="url" href="/a">^/a</a></p>',
163
147
  '<p><a class="url" href="https://source/x/a" target="_blank">./a</a></p>',
148
+ '<ol class="references"></ol>',
164
149
  ]);
165
150
  assert.deepStrictEqual(
166
- [...parse([
151
+ [...run(parse([
167
152
  [
168
153
  '---',
169
154
  `URL: ${location.origin}/x/y`,
@@ -171,17 +156,18 @@ describe('Unit: api/parse', () => {
171
156
  ].join('\n'),
172
157
  '{^/a}',
173
158
  '{./a}',
174
- ].join('\n\n'), { host: new URL(`${location.origin}/z`) }).children].map(el => el.outerHTML),
159
+ ].join('\n\n'), { host: new URL(`${location.origin}/z`) })).children].map(el => el.outerHTML),
175
160
  [
176
161
  `<aside class="header"><details open=""><summary>Header</summary><div class="field" data-name="url" data-value="${location.origin}/x/y"><span class="field-name">URL</span>: <span class="field-value">${location.origin}/x/y</span></div></details></aside>`,
177
162
  '<p><a class="url" href="/z/a">^/a</a></p>',
178
163
  '<p><a class="url" href="/x/a">./a</a></p>',
164
+ '<ol class="references"></ol>',
179
165
  ]);
180
166
  });
181
167
 
182
168
  it('separation', () => {
183
169
  assert.deepStrictEqual(
184
- [...parse([
170
+ [...run(parse([
185
171
  [
186
172
  '---',
187
173
  'URL: https://example/x',
@@ -202,19 +188,20 @@ describe('Unit: api/parse', () => {
202
188
  '~~~',
203
189
  ].join('\n'),
204
190
  '{#}',
205
- ].join('\n\n'), { host: new URL(`${location.origin}/z`) }).children].map(el => normalize(el.outerHTML)),
191
+ ].join('\n\n'), { host: new URL(`${location.origin}/z`) })).children].map(el => normalize(el.outerHTML)),
206
192
  [
207
193
  `<aside class="header"><details open=""><summary>Header</summary><div class="field" data-name="url" data-value="https://example/x"><span class="field-name">URL</span>: <span class="field-value">https://example/x</span></div></details></aside>`,
208
194
  '<pre class="invalid" translate="no">---\nURL: https://example/y\n---\n</pre>',
209
195
  '<aside class="example" data-type="markdown"><pre translate="no">---\nURL: https://example/y\n---\n\n{#}</pre><hr><section><aside class="header"><details open=""><summary>Header</summary><div class="field" data-name="url" data-value="https://example/y"><span class="field-name">URL</span>: <span class="field-value">https://example/y</span></div></details></aside><p><a class="url" href="https://example/y#" target="_blank">#</a></p><h2>References</h2><ol class="references"></ol></section></aside>',
210
196
  '<p><a class="url" href="https://example/x#" target="_blank">#</a></p>',
197
+ '<ol class="references"></ol>',
211
198
  ]);
212
199
  });
213
200
 
214
201
  it('note', () => {
215
202
  const notes = { references: html('ol') };
216
203
  assert.deepStrictEqual(
217
- [...parse('$-a\n$$\n$$\n\n(($-a[[^B]]))[[^B|$-a]]', { notes }).children].map(el => el.outerHTML),
204
+ [...run(parse('$-a\n$$\n$$\n\n(($-a[[^B]]))[[^B|$-a]]', { notes })).children].map(el => el.outerHTML),
218
205
  [
219
206
  '<figure data-type="math" data-label="$-a" data-group="$" data-number="1" id="label:$-a"><figcaption><span class="figindex">(1)</span><span class="figtext"></span></figcaption><div><div class="math" translate="no">$$\n$$</div></div></figure>',
220
207
  '<p><sup class="annotation" id="annotation::ref:[$-a][[^B]]:1" title="(1)[[^B]]"><a href="#annotation::def:[$-a][[^B]]:1">*1</a></sup><sup class="reference" data-abbr="B" id="reference::ref:B:2" title="(1)"><a href="#reference::def:B">[B]</a></sup></p>',
@@ -224,7 +211,7 @@ describe('Unit: api/parse', () => {
224
211
  notes.references.outerHTML,
225
212
  '<ol><li id="reference::def:B"><span><a class="label" data-label="$-a" href="#label:$-a">(1)</a></span><sup><a href="#reference::ref:B:1">^1</a><a href="#reference::ref:B:2" title="(1)">^2</a></sup></li></ol>');
226
213
  assert.deepStrictEqual(
227
- [...parse([
214
+ [...run(parse([
228
215
  '[[^A 1|b]]',
229
216
  '[[^A 1,|b]]',
230
217
  '[[^A 1, |b]]',
@@ -255,7 +242,7 @@ describe('Unit: api/parse', () => {
255
242
  '[[^A title 2020, 1|b]]',
256
243
  '[[^Constitution, art. 2|b]]',
257
244
  '[[^Constitution, art. 2, sec. 1|b]]',
258
- ].join('\n\n'), { notes }).children].map(el => el.outerHTML),
245
+ ].join('\n\n'), { notes })).children].map(el => el.outerHTML),
259
246
  [
260
247
  '<p><sup class="reference" data-abbr="A 1" id="reference::ref:A_1:1" title="b"><a href="#reference::def:A_1">[A 1]</a></sup></p>',
261
248
  '<p><sup class="reference" data-abbr="A 1," id="reference::ref:A_1:2" title="b"><a href="#reference::def:A_1">[A 1,]</a></sup></p>',
@@ -292,87 +279,96 @@ describe('Unit: api/parse', () => {
292
279
 
293
280
  it('normalize', () => {
294
281
  assert.deepStrictEqual(
295
- [...parse('a\\\r\nb').children].map(el => el.outerHTML),
296
- ['<p>a<br>b</p>']);
282
+ [...run(parse('a\\\r\nb')).children].map(el => el.outerHTML),
283
+ ['<p>a<br>b</p>', '<ol class="references"></ol>']);
297
284
  });
298
285
 
299
286
  it('recursion', () => {
300
287
  assert.deepStrictEqual(
301
- [...parse(`${'['.repeat(20)}0`).children].map(el => el.outerHTML),
302
- [`<p>${'['.repeat(20)}0</p>`]);
288
+ [...run(parse(`${'('.repeat(100)}0`)).children].map(el => el.tagName),
289
+ ['P', 'OL']);
303
290
  assert.deepStrictEqual(
304
- [...parse(`${'['.repeat(21)}0`).children].map(el => el.outerHTML.replace(/:\w+/, ':rnd')),
305
- [
306
- '<h1 id="error:rnd" class="error">Error: Too much recursion</h1>',
307
- `<pre class="error" translate="no">${'['.repeat(21)}0</pre>`,
308
- ]);
291
+ [...run(parse(`${'('.repeat(101)}0`)).children].map(el => el.tagName),
292
+ ['H1', 'PRE', 'OL']);
309
293
  assert.deepStrictEqual(
310
- [...parse(`${'('.repeat(20)}0`).children].map(el => el.tagName),
311
- ['P']);
294
+ [...run(parse(`${'['.repeat(100)}0`)).children].map(el => el.tagName),
295
+ ['P', 'OL']);
312
296
  assert.deepStrictEqual(
313
- [...parse(`${'('.repeat(21)}0`).children].map(el => el.tagName),
314
- ['H1', 'PRE']);
297
+ [...run(parse(`${'['.repeat(101)}0`)).children].map(el => el.tagName),
298
+ ['H1', 'PRE', 'OL']);
315
299
  assert.deepStrictEqual(
316
- [...parse(`${'(('.repeat(2)}0${'))'.repeat(2)}`).children].map(el => el.tagName),
300
+ [...run(parse(`${'{'.repeat(102)}0`)).children].map(el => el.tagName),
317
301
  ['P', 'OL']);
318
302
  assert.deepStrictEqual(
319
- [...parse(`${'(('.repeat(3)}0${'))'.repeat(3)}`).children].map(el => el.tagName),
320
- ['H1', 'PRE']);
303
+ [...run(parse(`${'{'.repeat(103)}0`)).children].map(el => el.tagName),
304
+ ['H1', 'PRE', 'OL']);
321
305
  assert.deepStrictEqual(
322
- [...parse(`(${'(('.repeat(2)}0${'))'.repeat(2)}`).children].map(el => el.tagName),
306
+ [...run(parse(`${'{ '.repeat(100)}0`)).children].map(el => el.tagName),
323
307
  ['P', 'OL']);
324
308
  assert.deepStrictEqual(
325
- [...parse(`(${'(('.repeat(3)}0${'))'.repeat(3)}`).children].map(el => el.tagName),
326
- ['H1', 'PRE']);
309
+ [...run(parse(`${'{ '.repeat(1000)}0`)).children].map(el => el.tagName),
310
+ ['P', 'OL']);
327
311
  assert.deepStrictEqual(
328
- [...parse(`${'(('.repeat(2)}0${'))'.repeat(2)}${'(('.repeat(2)}0${'))'.repeat(2)}`).children].map(el => el.tagName),
312
+ [...run(parse(`${'{ '.repeat(100)}0`)).children].map(el => el.tagName),
329
313
  ['P', 'OL']);
330
314
  assert.deepStrictEqual(
331
- [...parse(`${'(('.repeat(2)}0${'))'.repeat(2)}${'(('.repeat(3)}0${'))'.repeat(3)}`).children].map(el => el.tagName),
332
- ['H1', 'PRE']);
315
+ [...run(parse(`${'{ '.repeat(101)}0`)).children].map(el => el.tagName),
316
+ ['H1', 'PRE', 'OL']);
333
317
  assert.deepStrictEqual(
334
- [...parse(`${'(('.repeat(2)}0${'))'.repeat(2)}${'(('.repeat(9)}0${'))'.repeat(2)}`).children].map(el => el.tagName),
335
- ['P', 'OL']);
318
+ [...run(parse(`${'(('.repeat(2)}0${'))'.repeat(2)}`)).children].map(el => el.tagName),
319
+ ['P', 'OL', 'OL']);
320
+ assert.deepStrictEqual(
321
+ [...run(parse(`${'(('.repeat(3)}0${'))'.repeat(3)}`)).children].map(el => el.tagName),
322
+ ['H1', 'PRE', 'OL']);
323
+ assert.deepStrictEqual(
324
+ [...run(parse(`(${'(('.repeat(2)}0${'))'.repeat(2)}`)).children].map(el => el.tagName),
325
+ ['P', 'OL', 'OL']);
326
+ assert.deepStrictEqual(
327
+ [...run(parse(`(${'(('.repeat(3)}0${'))'.repeat(3)}`)).children].map(el => el.tagName),
328
+ ['H1', 'PRE', 'OL']);
329
+ assert.deepStrictEqual(
330
+ [...run(parse(`${'(('.repeat(2)}0${'))'.repeat(2)}${'(('.repeat(2)}0${'))'.repeat(2)}`)).children].map(el => el.tagName),
331
+ ['P', 'OL', 'OL']);
336
332
  assert.deepStrictEqual(
337
- [...parse(`${'(('.repeat(2)}0${'))'.repeat(2)}${'(('.repeat(9)}0${'))'.repeat(3)}`).children].map(el => el.tagName),
338
- ['H1', 'PRE']);
333
+ [...run(parse(`${'(('.repeat(2)}0${'))'.repeat(2)}${'(('.repeat(3)}0${'))'.repeat(3)}`)).children].map(el => el.tagName),
334
+ ['H1', 'PRE', 'OL']);
339
335
  assert.deepStrictEqual(
340
- [...parse(`${'(('.repeat(3)}0))((1))))))`).children].map(el => el.tagName),
341
- ['H1', 'PRE']);
336
+ [...run(parse(`${'(('.repeat(2)}0${'))'.repeat(2)}${'(('.repeat(9)}0${'))'.repeat(2)}`)).children].map(el => el.tagName),
337
+ ['P', 'OL', 'OL']);
338
+ assert.deepStrictEqual(
339
+ [...run(parse(`${'(('.repeat(2)}0${'))'.repeat(2)}${'(('.repeat(9)}0${'))'.repeat(3)}`)).children].map(el => el.tagName),
340
+ ['H1', 'PRE', 'OL']);
341
+ assert.deepStrictEqual(
342
+ [...run(parse(`${'(('.repeat(3)}0))((1))))))`)).children].map(el => el.tagName),
343
+ ['H1', 'PRE', 'OL']);
342
344
  });
343
345
 
344
346
  it('recovery', () => {
345
347
  assert.deepStrictEqual(
346
- [...parse(`${'['.repeat(20)}0\n\n[a]`).children].map(el => el.outerHTML),
347
- [
348
- `<p>${'['.repeat(20)}0</p>`,
349
- '<p>[a]</p>',
350
- ]);
351
- assert.deepStrictEqual(
352
- [...parse(`${'['.repeat(21)}0\n\n[a]`).children].map(el => el.outerHTML.replace(/:\w+/, ':rnd')),
348
+ [...run(parse(`${'('.repeat(101)}0\n\n*a*`)).children].map(el => el.outerHTML.replace(/:\w+/, ':rnd')),
353
349
  [
354
350
  '<h1 id="error:rnd" class="error">Error: Too much recursion</h1>',
355
- `<pre class="error" translate="no">${'['.repeat(21)}0\n</pre>`,
356
- '<p>[a]</p>',
351
+ `<pre class="error" translate="no">${'('.repeat(101)}0\n</pre>`,
352
+ '<p><em>a</em></p>',
353
+ '<ol class="references"></ol>',
357
354
  ]);
358
355
  });
359
356
 
360
- if (!navigator.userAgent.includes('Chrome')) return;
361
-
362
- it('creation', function () {
363
- this.timeout(10000);
357
+ it('creation', () => {
364
358
  assert.deepStrictEqual(
365
- [...parse('.'.repeat(100000)).children].map(el => el.outerHTML),
366
- [`<p>${'.'.repeat(100000)}</p>`]);
359
+ [...run(parse('.'.repeat(100000), {}, new Input({ resources: { clock: 100000, recursions: [100] } }))).children]
360
+ .map(el => el.outerHTML),
361
+ [`<p>${'.'.repeat(100000)}</p>`, '<ol class="references"></ol>']);
367
362
  });
368
363
 
369
- it.skip('creation error', function () {
370
- this.timeout(10000);
364
+ it('creation error', () => {
371
365
  assert.deepStrictEqual(
372
- [...parse('.'.repeat(100001)).children].map(el => el.outerHTML.replace(/:\w+/, ':rnd')),
366
+ [...run(parse('.'.repeat(100001), {}, new Input({ resources: { clock: 100000, recursions: [100] } }))).children]
367
+ .map(el => el.outerHTML.replace(/:\w+/, ':rnd')),
373
368
  [
374
369
  '<h1 id="error:rnd" class="error">Error: Too many creations</h1>',
375
370
  `<pre class="error" translate="no">${'.'.repeat(1000 - 3)}...</pre>`,
371
+ '<ol class="references"></ol>',
376
372
  ]);
377
373
  });
378
374
 
@@ -380,30 +376,30 @@ describe('Unit: api/parse', () => {
380
376
  // 最悪計算量での実行速度はCommonMarkの公式JS実装の32nに対して1-4倍程度。
381
377
  // 5n = reference + link + url/math + ruby + text
382
378
  assert.deepStrictEqual(
383
- [...parse(`((([[[[#$http://[${'.'.repeat(19992)}`, {}, new Context({ resources: { clock: 100000, recursions: [100] } })).children]
379
+ [...run(parse(`((([[[[#$http://[${'.'.repeat(19983)}`, {}, new Input({ resources: { clock: 100000, recursions: [100] } }))).children]
384
380
  .map(el => el.tagName),
385
- ['P']);
381
+ ['P', 'OL']);
386
382
  });
387
383
 
388
384
  it('backtrack 1 error', () => {
389
385
  assert.deepStrictEqual(
390
- [...parse(`((([[[[#$http://[${'.'.repeat(19992 + 1)}`, {}, new Context({ resources: { clock: 100000, recursions: [100] } })).children]
386
+ [...run(parse(`((([[[[#$http://[${'.'.repeat(19983 + 1)}`, {}, new Input({ resources: { clock: 100000, recursions: [100] } }))).children]
391
387
  .map(el => el.tagName),
392
- ['H1', 'PRE']);
388
+ ['H1', 'PRE', 'OL']);
393
389
  });
394
390
 
395
391
  it('backtrack 2', () => {
396
392
  assert.deepStrictEqual(
397
- [...parse(`((([[[[#$http://[${'.'.repeat(33324)}]]]`, {}, new Context({ resources: { clock: 100000, recursions: [100] } })).children]
393
+ [...run(parse(`((([[[[#$http://[${'.'.repeat(33313)}]]]`, {}, new Input({ resources: { clock: 100000, recursions: [100] } }))).children]
398
394
  .map(el => el.tagName),
399
395
  ['P', 'OL']);
400
396
  });
401
397
 
402
398
  it('backtrack 2 error', () => {
403
399
  assert.deepStrictEqual(
404
- [...parse(`((([[[[#$http://[${'.'.repeat(33324 + 1)}]]]`, {}, new Context({ resources: { clock: 100000, recursions: [100] } })).children]
400
+ [...run(parse(`((([[[[#$http://[${'.'.repeat(33313 + 1)}]]]`, {}, new Input({ resources: { clock: 100000, recursions: [100] } }))).children]
405
401
  .map(el => el.tagName),
406
- ['H1', 'PRE']);
402
+ ['H1', 'PRE', 'OL']);
407
403
  });
408
404
 
409
405
  });
package/src/api/parse.ts CHANGED
@@ -1,48 +1,30 @@
1
1
  import { ParserOptions } from '../..';
2
- import { input } from '../combinator/data/parser';
3
- import { Context, Options, Segment } from '../parser/context';
4
- import { segment } from '../parser/segment';
5
- import { block } from '../parser/block';
6
- import { headers } from './header';
7
- import { figure } from '../processor/figure';
8
- import { note } from '../processor/note';
2
+ import { Input, Options } from '../parser/context';
3
+ import { Output, run } from '../combinator/parser';
4
+ import { document } from '../parser/document';
9
5
  import { ReadonlyURL } from 'spica/url';
10
- import { frag } from 'typed-dom/dom';
11
6
 
12
7
  interface Opts extends ParserOptions {
13
8
  readonly local?: boolean;
14
9
  readonly test?: boolean;
15
10
  }
16
11
 
17
- export function parse(source: string, opts: Opts = {}, options?: Options): DocumentFragment {
18
- const url = headers(source).find(field => field.toLowerCase().startsWith('url:'))?.slice(4).trim() ?? '';
12
+ export function* parse(source: string, opts: Opts = {}, options?: Options): Generator<void, DocumentFragment, void> {
19
13
  options = {
20
14
  host: opts.host ?? options?.host ?? new ReadonlyURL(location.pathname, location.origin),
21
- url: url ? new ReadonlyURL(url as ':') : options?.url,
15
+ url: options?.url,
22
16
  id: opts.id ?? options?.id,
23
- local: opts.local ?? options?.local ?? false,
17
+ notes: opts.notes ?? options?.notes,
24
18
  caches: options?.caches,
25
19
  resources: options?.resources,
20
+ header: true,
21
+ test: opts.test,
26
22
  };
27
23
  if (options.id?.match(/[^0-9a-z/-]/i)) throw new Error('Invalid ID: ID must be alphanumeric');
28
24
  if (options.host?.origin === 'null') throw new Error(`Invalid host: ${options.host.href}`);
29
- const node = frag();
30
- // @ts-expect-error
31
- options.header = true;
32
- for (const [seg, attr] of segment(source, !options.local)) {
33
- options.segment = attr | Segment.write;
34
- const es = block(input(seg, new Context(options)))!
35
- .foldl<HTMLElement[]>((acc, { value }) => void acc.push(value) || acc, [])
36
- // @ts-expect-error
37
- options.header = false;
38
- if (es.length === 0) continue;
39
- node.append(...es);
40
- }
41
- assert(opts.id !== '' || !node.querySelector('[id], .index[href], .label[href], .annotation > a[href], .reference > a[href]'));
42
- if (opts.test) return node;
43
- for (const _ of figure(node, opts.notes, options));
44
- for (const _ of note(node, opts.notes, options));
45
- assert(opts.id !== '' || !node.querySelector('[id], .index[href], .label[href], .annotation > a[href], .reference > a[href]'));
46
- assert(opts.id !== '' || !opts.notes?.references.querySelector('[id], .index[href], .label[href]'));
47
- return node;
25
+ const output = new Output<DocumentFragment>();
26
+ for (const _ of run(document, new Input(options, source), output)) yield;
27
+ assert(output.data.length === 1);
28
+ assert(output.peek().length === 1);
29
+ return output.peek().head!.value;
48
30
  }
package/src/api/run.ts ADDED
@@ -0,0 +1,6 @@
1
+ export function run(parser: Iterator<void, DocumentFragment, void>): DocumentFragment {
2
+ for (;;) {
3
+ const { value, done } = parser.next();
4
+ if (done) return value;
5
+ }
6
+ }