securemark 0.295.1 → 0.295.2

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 (169) hide show
  1. package/CHANGELOG.md +4 -0
  2. package/design.md +4 -3
  3. package/dist/index.js +514 -459
  4. package/markdown.d.ts +13 -28
  5. package/package.json +1 -1
  6. package/src/combinator/control/constraint/block.test.ts +6 -8
  7. package/src/combinator/control/constraint/contract.ts +7 -7
  8. package/src/combinator/control/constraint/line.test.ts +7 -9
  9. package/src/combinator/control/constraint/line.ts +0 -1
  10. package/src/combinator/control/manipulation/clear.ts +2 -2
  11. package/src/combinator/control/manipulation/convert.ts +3 -3
  12. package/src/combinator/control/manipulation/duplicate.ts +4 -4
  13. package/src/combinator/control/manipulation/fallback.ts +2 -2
  14. package/src/combinator/control/manipulation/fence.ts +3 -3
  15. package/src/combinator/control/manipulation/indent.test.ts +20 -22
  16. package/src/combinator/control/manipulation/indent.ts +2 -2
  17. package/src/combinator/control/manipulation/recovery.ts +3 -3
  18. package/src/combinator/control/manipulation/reverse.ts +2 -2
  19. package/src/combinator/control/manipulation/scope.ts +2 -4
  20. package/src/combinator/control/manipulation/surround.ts +32 -32
  21. package/src/combinator/control/monad/bind.ts +6 -6
  22. package/src/combinator/control/monad/fmap.ts +6 -6
  23. package/src/combinator/data/data.ts +2 -2
  24. package/src/combinator/data/{parser/context/delimiter.ts → delimiter.ts} +4 -4
  25. package/src/combinator/data/parser/context.test.ts +12 -11
  26. package/src/combinator/data/parser/context.ts +13 -14
  27. package/src/combinator/data/parser/inits.ts +5 -5
  28. package/src/combinator/data/parser/sequence.test.ts +12 -13
  29. package/src/combinator/data/parser/sequence.ts +5 -5
  30. package/src/combinator/data/parser/some.test.ts +15 -16
  31. package/src/combinator/data/parser/some.ts +5 -6
  32. package/src/combinator/data/parser/subsequence.test.ts +16 -17
  33. package/src/combinator/data/parser/subsequence.ts +3 -3
  34. package/src/combinator/data/parser/tails.ts +3 -3
  35. package/src/combinator/data/parser/union.test.ts +12 -13
  36. package/src/combinator/data/parser/union.ts +3 -3
  37. package/src/combinator/data/parser.ts +55 -32
  38. package/src/debug.test.ts +5 -3
  39. package/src/parser/api/bind.ts +8 -6
  40. package/src/parser/api/header.ts +4 -4
  41. package/src/parser/api/normalize.ts +2 -1
  42. package/src/parser/api/parse.test.ts +7 -6
  43. package/src/parser/api/parse.ts +9 -8
  44. package/src/parser/autolink.test.ts +18 -18
  45. package/src/parser/block/blockquote.test.ts +79 -79
  46. package/src/parser/block/blockquote.ts +5 -5
  47. package/src/parser/block/codeblock.test.ts +57 -57
  48. package/src/parser/block/codeblock.ts +3 -3
  49. package/src/parser/block/dlist.test.ts +57 -57
  50. package/src/parser/block/dlist.ts +6 -6
  51. package/src/parser/block/extension/aside.test.ts +9 -9
  52. package/src/parser/block/extension/aside.ts +5 -5
  53. package/src/parser/block/extension/example.test.ts +19 -19
  54. package/src/parser/block/extension/example.ts +6 -6
  55. package/src/parser/block/extension/fig.test.ts +36 -36
  56. package/src/parser/block/extension/figbase.test.ts +16 -16
  57. package/src/parser/block/extension/figbase.ts +2 -2
  58. package/src/parser/block/extension/figure.test.ts +63 -63
  59. package/src/parser/block/extension/figure.ts +3 -3
  60. package/src/parser/block/extension/message.test.ts +14 -14
  61. package/src/parser/block/extension/message.ts +5 -5
  62. package/src/parser/block/extension/placeholder.test.ts +13 -13
  63. package/src/parser/block/extension/placeholder.ts +2 -2
  64. package/src/parser/block/extension/table.test.ts +76 -76
  65. package/src/parser/block/extension/table.ts +14 -14
  66. package/src/parser/block/extension.test.ts +24 -24
  67. package/src/parser/block/heading.test.ts +59 -59
  68. package/src/parser/block/heading.ts +7 -7
  69. package/src/parser/block/ilist.test.ts +8 -12
  70. package/src/parser/block/ilist.ts +6 -6
  71. package/src/parser/block/mathblock.test.ts +32 -32
  72. package/src/parser/block/mathblock.ts +3 -3
  73. package/src/parser/block/mediablock.ts +3 -3
  74. package/src/parser/block/olist.test.ts +103 -103
  75. package/src/parser/block/olist.ts +5 -5
  76. package/src/parser/block/pagebreak.test.ts +16 -16
  77. package/src/parser/block/pagebreak.ts +2 -2
  78. package/src/parser/block/paragraph.test.ts +58 -58
  79. package/src/parser/block/paragraph.ts +2 -2
  80. package/src/parser/block/reply/cite.test.ts +40 -40
  81. package/src/parser/block/reply/cite.ts +6 -6
  82. package/src/parser/block/reply/quote.test.ts +51 -51
  83. package/src/parser/block/reply/quote.ts +3 -3
  84. package/src/parser/block/reply.test.ts +20 -20
  85. package/src/parser/block/reply.ts +3 -3
  86. package/src/parser/block/sidefence.test.ts +48 -48
  87. package/src/parser/block/sidefence.ts +4 -4
  88. package/src/parser/block/table.test.ts +50 -50
  89. package/src/parser/block/table.ts +12 -12
  90. package/src/parser/block/ulist.test.ts +53 -53
  91. package/src/parser/block/ulist.ts +6 -6
  92. package/src/parser/block.ts +6 -4
  93. package/src/parser/context.ts +39 -0
  94. package/src/parser/header.test.ts +23 -23
  95. package/src/parser/header.ts +5 -5
  96. package/src/parser/inline/annotation.test.ts +43 -43
  97. package/src/parser/inline/annotation.ts +14 -4
  98. package/src/parser/inline/autolink/account.test.ts +33 -33
  99. package/src/parser/inline/autolink/account.ts +9 -9
  100. package/src/parser/inline/autolink/anchor.test.ts +22 -22
  101. package/src/parser/inline/autolink/anchor.ts +4 -4
  102. package/src/parser/inline/autolink/channel.test.ts +15 -15
  103. package/src/parser/inline/autolink/email.test.ts +37 -37
  104. package/src/parser/inline/autolink/email.ts +2 -2
  105. package/src/parser/inline/autolink/hashnum.test.ts +33 -33
  106. package/src/parser/inline/autolink/hashnum.ts +6 -5
  107. package/src/parser/inline/autolink/hashtag.test.ts +60 -60
  108. package/src/parser/inline/autolink/hashtag.ts +4 -4
  109. package/src/parser/inline/autolink/url.test.ts +75 -75
  110. package/src/parser/inline/autolink/url.ts +4 -4
  111. package/src/parser/inline/bracket.test.ts +70 -70
  112. package/src/parser/inline/bracket.ts +35 -32
  113. package/src/parser/inline/code.test.ts +31 -31
  114. package/src/parser/inline/code.ts +4 -4
  115. package/src/parser/inline/deletion.test.ts +28 -28
  116. package/src/parser/inline/deletion.ts +4 -4
  117. package/src/parser/inline/emphasis.test.ts +40 -40
  118. package/src/parser/inline/emphasis.ts +3 -3
  119. package/src/parser/inline/emstrong.test.ts +101 -101
  120. package/src/parser/inline/emstrong.ts +23 -23
  121. package/src/parser/inline/extension/index.test.ts +92 -92
  122. package/src/parser/inline/extension/index.ts +5 -5
  123. package/src/parser/inline/extension/indexee.ts +5 -5
  124. package/src/parser/inline/extension/indexer.test.ts +24 -24
  125. package/src/parser/inline/extension/indexer.ts +2 -2
  126. package/src/parser/inline/extension/label.test.ts +33 -33
  127. package/src/parser/inline/extension/label.ts +2 -2
  128. package/src/parser/inline/extension/placeholder.test.ts +43 -43
  129. package/src/parser/inline/extension/placeholder.ts +4 -4
  130. package/src/parser/inline/html.test.ts +108 -108
  131. package/src/parser/inline/html.ts +10 -10
  132. package/src/parser/inline/htmlentity.test.ts +38 -38
  133. package/src/parser/inline/htmlentity.ts +5 -5
  134. package/src/parser/inline/insertion.test.ts +28 -28
  135. package/src/parser/inline/insertion.ts +4 -4
  136. package/src/parser/inline/italic.test.ts +55 -55
  137. package/src/parser/inline/italic.ts +4 -4
  138. package/src/parser/inline/link.test.ts +186 -187
  139. package/src/parser/inline/link.ts +16 -17
  140. package/src/parser/inline/mark.test.ts +31 -31
  141. package/src/parser/inline/mark.ts +5 -5
  142. package/src/parser/inline/math.test.ts +132 -132
  143. package/src/parser/inline/math.ts +2 -2
  144. package/src/parser/inline/media.test.ts +91 -91
  145. package/src/parser/inline/media.ts +15 -15
  146. package/src/parser/inline/reference.test.ts +109 -109
  147. package/src/parser/inline/reference.ts +15 -54
  148. package/src/parser/inline/remark.test.ts +50 -50
  149. package/src/parser/inline/remark.ts +5 -5
  150. package/src/parser/inline/ruby.test.ts +45 -45
  151. package/src/parser/inline/ruby.ts +17 -17
  152. package/src/parser/inline/shortmedia.test.ts +10 -10
  153. package/src/parser/inline/strong.test.ts +37 -37
  154. package/src/parser/inline/strong.ts +3 -3
  155. package/src/parser/inline/template.test.ts +23 -23
  156. package/src/parser/inline/template.ts +5 -5
  157. package/src/parser/inline.test.ts +224 -223
  158. package/src/parser/segment.ts +2 -2
  159. package/src/parser/source/escapable.test.ts +24 -24
  160. package/src/parser/source/escapable.ts +8 -8
  161. package/src/parser/source/line.test.ts +18 -18
  162. package/src/parser/source/str.ts +2 -2
  163. package/src/parser/source/text.test.ts +85 -85
  164. package/src/parser/source/text.ts +5 -5
  165. package/src/parser/source/unescapable.test.ts +24 -24
  166. package/src/parser/source/unescapable.ts +5 -5
  167. package/src/parser/util.ts +10 -11
  168. package/src/parser/visibility.ts +8 -9
  169. package/src/util/quote.ts +2 -1
@@ -1,34 +1,68 @@
1
1
  import { List } from './data';
2
- import { Delimiters } from './parser/context/delimiter';
2
+ import { Delimiters } from './delimiter';
3
3
 
4
- export type Parser<N = unknown, C extends Ctx = Ctx, D extends Parser<unknown, C>[] = any>
4
+ export type Parser<N = unknown, C extends Context = Context, D extends Parser<unknown, C>[] = any>
5
5
  = (input: Input<C>) => Result<N, C, D>;
6
- export interface Input<C extends Ctx = Ctx> {
6
+ export namespace Parser {
7
+ export type Node<P extends Parser> = P extends Parser<infer N> ? N : never;
8
+ export type SubParsers<P extends Parser> = P extends Parser<unknown, any, infer D> ? D : never;
9
+ export type Context<P extends Parser> = P extends Parser<unknown, infer C> ? C : never;
10
+ export type SubNode<P extends Parser> = ExtractSubNode<SubParsers<P>>;
11
+ export type IntermediateParser<P extends Parser> = Parser<SubNode<P>, Context<P>, SubParsers<P>>;
12
+ type ExtractSubNode<D extends Parser[]> = ExtractSubParser<D> extends infer N ? N extends Parser<infer U> ? U : never : never;
13
+ type ExtractSubParser<D extends Parser[]> = D extends (infer P)[] ? P extends Parser ? P : never : never;
14
+ }
15
+ export interface Input<C extends Context = Context> {
7
16
  readonly context: C;
8
17
  }
9
- export type Result<N, C extends Ctx = Ctx, D extends Parser<unknown, C>[] = any>
10
- = List<Data<N>, C, D>
18
+ export type Result<N, C extends Context = Context, D extends Parser<unknown, C>[] = any>
19
+ = List<Node<N>, C, D>
11
20
  | undefined;
12
21
  export { List };
13
- export class Data<N> implements List.Node {
22
+ export class Node<N> implements List.Node {
14
23
  constructor(public value: N) {
15
24
  }
16
25
  public next?: this = undefined;
17
26
  public prev?: this = undefined;
18
27
  }
19
- export interface Ctx extends CtxOptions {
20
- source: string;
21
- position: number;
22
- }
23
- export interface CtxOptions {
24
- readonly resources?: {
28
+ export class Context {
29
+ constructor(
30
+ {
31
+ source,
32
+ position,
33
+ resources,
34
+ delimiters,
35
+ precedence,
36
+ state,
37
+ linebreak,
38
+ range,
39
+ offset,
40
+ backtracks,
41
+ }: Options = {},
42
+ ) {
43
+ this.source = source ?? '';
44
+ this.position = position ?? 0;
45
+ this.resources = resources;
46
+ this.precedence = precedence ?? 0;
47
+ this.delimiters = delimiters ?? new Delimiters();
48
+ this.state = state ?? 0;
49
+ this.linebreak = linebreak ?? 0;
50
+ this.range = range ?? 0;
51
+ this.offset = offset ?? 0;
52
+ this.backtracks = backtracks ?? {};
53
+ }
54
+ public source: string;
55
+ public position: number;
56
+ public readonly resources?: {
25
57
  clock: number;
26
58
  recursions: number[];
27
59
  };
28
- offset?: number;
29
- precedence?: number;
30
- delimiters?: Delimiters;
31
- state?: number;
60
+ public precedence: number;
61
+ public delimiters: Delimiters;
62
+ public state: number;
63
+ public linebreak: number;
64
+ public range: number;
65
+ public offset: number;
32
66
  // Objectの内部実装を利用する。
33
67
  // 探索木を直接使用する場合は探索速度が重要で挿入は相対的に少なく削除は不要かつ不確実であるため
34
68
  // AVL木が適当と思われる。
@@ -61,36 +95,25 @@ export interface CtxOptions {
61
95
  // 1段落数百文字あたり平均2、3か所以下が妥当な頻度でありこの場合の最大追加データサイズは
62
96
  // 入力内の最大セグメントサイズの10%前後である。
63
97
  //
64
- backtracks?: Record<number, number>;
65
- linebreak?: number;
66
- range?: number;
98
+ public backtracks: Record<number, number>;
67
99
  }
68
- export type Node<P extends Parser> = P extends Parser<infer N> ? N : never;
69
- export type SubParsers<P extends Parser> = P extends Parser<unknown, Ctx, infer D> ? D : never;
70
- export type Context<P extends Parser> = P extends Parser<unknown, infer C> ? C : never;
71
- export type SubNode<P extends Parser> = ExtractSubNode<SubParsers<P>>;
72
- export type IntermediateParser<P extends Parser> = Parser<SubNode<P>, Context<P>, SubParsers<P>>;
73
- type ExtractSubNode<D extends Parser[]> = ExtractSubParser<D> extends infer N ? N extends Parser<infer U> ? U : never : never;
74
- type ExtractSubParser<D extends Parser[]> = D extends (infer P)[] ? P extends Parser ? P : never : never;
100
+ export type Options = Partial<Context>;
75
101
 
76
- export function input<C extends CtxOptions>(source: string, context: C): Input<C & Ctx> {
77
- // @ts-expect-error
102
+ export function input<C extends Context>(source: string, context: C): Input<C> {
78
103
  context.source = source;
79
- // @ts-expect-error
80
104
  context.position = 0;
81
105
  return {
82
- // @ts-expect-error
83
106
  context,
84
107
  };
85
108
  }
86
109
 
87
- export function subinput<C extends Ctx>(source: string, context: C): Input<C> {
110
+ export function subinput<C extends Context>(source: string, context: C): Input<C> {
88
111
  return {
89
112
  context: {
90
113
  ...context,
91
114
  source,
92
115
  position: 0,
93
- offset: undefined,
116
+ offset: 0,
94
117
  backtracks: {},
95
118
  }
96
119
  };
package/src/debug.test.ts CHANGED
@@ -1,8 +1,10 @@
1
- import { Result, Ctx } from './combinator/data/parser';
1
+ import { Parser, Input } from './combinator/data/parser';
2
2
  import { html, define } from 'typed-dom/dom';
3
3
  import { querySelectorWith, querySelectorAllWith } from 'typed-dom/query';
4
4
 
5
- export function inspect(result: Result<DocumentFragment | HTMLElement | string>, ctx: Ctx, until: number | string = Infinity): [string[], string] | undefined {
5
+ export function inspect(parser: Parser<DocumentFragment | HTMLElement | string>, input: Input, until: number | string = Infinity): [string[], string] | undefined {
6
+ const { context } = input;
7
+ const result = parser(input);
6
8
  return result && [
7
9
  result.foldl<string[]>((acc, { value: node }) => {
8
10
  assert(node);
@@ -34,7 +36,7 @@ export function inspect(result: Result<DocumentFragment | HTMLElement | string>,
34
36
  }
35
37
  return acc.push(normalize(node.outerHTML.slice(0, until))), acc;
36
38
  }, []),
37
- ctx.source.slice(ctx.position),
39
+ context.source.slice(context.position),
38
40
  ];
39
41
  }
40
42
 
@@ -1,8 +1,7 @@
1
1
  import { ParserSettings, Progress } from '../../..';
2
- import { MarkdownParser } from '../../../markdown';
2
+ import { Context } from '../context';
3
3
  import { input } from '../../combinator/data/parser';
4
4
  import { segment } from '../segment';
5
- import { header } from '../header';
6
5
  import { block } from '../block';
7
6
  import { normalize } from './normalize';
8
7
  import { headers } from './header';
@@ -19,13 +18,12 @@ export function bind(target: DocumentFragment | HTMLElement | ShadowRoot, settin
19
18
  nearest: (position: number) => HTMLElement | undefined;
20
19
  index: (block: HTMLElement) => number;
21
20
  } {
22
- const context: MarkdownParser.Options = {
21
+ const context = new Context({
23
22
  ...settings,
24
23
  host: settings.host ?? new ReadonlyURL(location.pathname, location.origin),
25
- };
24
+ });
26
25
  assert(!context.offset);
27
26
  assert(!context.precedence);
28
- assert(!context.delimiters);
29
27
  assert(!context.state);
30
28
  if (context.id?.match(/[^0-9a-z/-]/i)) throw new Error('Invalid ID: ID must be alphanumeric');
31
29
  if (context.host?.origin === 'null') throw new Error(`Invalid host: ${context.host.href}`);
@@ -72,11 +70,15 @@ export function bind(target: DocumentFragment | HTMLElement | ShadowRoot, settin
72
70
  assert(head + last <= targetSegments.length);
73
71
  const base = next(head);
74
72
  let index = head;
73
+ // @ts-expect-error
74
+ context.header = true;
75
75
  for (; index < sourceSegments.length - last; ++index) {
76
76
  assert(rev === revision);
77
77
  const seg = sourceSegments[index];
78
- const es = (header(input(seg, { header: index === 0 } as MarkdownParser.Options)) || block(input(seg, context)))
78
+ const es = block(input(seg, context))
79
79
  ?.foldl<HTMLElement[]>((acc, { value }) => void acc.push(value) || acc, []) ?? [];
80
+ // @ts-expect-error
81
+ context.header = false;
80
82
  blocks.splice(index, 0, [seg, es, url]);
81
83
  if (es.length === 0) continue;
82
84
  // All deletion processes always run after all addition processes have done.
@@ -1,4 +1,4 @@
1
- import { input } from '../../combinator/data/parser';
1
+ import { Context } from '../context';
2
2
  import { header as h } from '../header';
3
3
 
4
4
  export function header(source: string): string {
@@ -12,10 +12,10 @@ export function headers(source: string): string[] {
12
12
  }
13
13
 
14
14
  function parse(source: string): [HTMLElement, number] | [] {
15
- const i = input(source, {});
16
- const result = h(i);
15
+ const context = new Context({ source });
16
+ const result = h({ context });
17
17
  const el = result?.head?.value;
18
18
  return el?.tagName === 'ASIDE'
19
- ? [el, i.context.position]
19
+ ? [el, context.position]
20
20
  : [];
21
21
  }
@@ -1,4 +1,5 @@
1
1
  import { input } from '../../combinator/data/parser';
2
+ import { Context } from '../context';
2
3
  import { unsafehtmlentity } from '../inline/htmlentity';
3
4
 
4
5
  const UNICODE_REPLACEMENT_CHARACTER = '\uFFFD';
@@ -68,7 +69,7 @@ const unreadableEscapeHTMLEntityNames = invisibleHTMLEntityNames.filter(name =>
68
69
  'zwnj',
69
70
  ].includes(name));
70
71
  const unreadableEscapeCharacters = unreadableEscapeHTMLEntityNames
71
- .map(name => unsafehtmlentity(input(`&${name};`, {}))!.head!.value);
72
+ .map(name => unsafehtmlentity(input(`&${name};`, new Context()))!.head!.value);
72
73
  assert(unreadableEscapeCharacters.length === unreadableEscapeHTMLEntityNames.length);
73
74
  assert(unreadableEscapeCharacters.every(c => c.length === 1));
74
75
  const unreadableEscapeCharacter = new RegExp(`[${unreadableEscapeCharacters.join('')}]`, 'g');
@@ -1,4 +1,5 @@
1
1
  import { parse } from './parse';
2
+ import { Context } from '../context';
2
3
  import { html } from 'typed-dom/dom';
3
4
 
4
5
  describe('Unit: parser/api/parse', () => {
@@ -361,20 +362,20 @@ describe('Unit: parser/api/parse', () => {
361
362
 
362
363
  it('backtrack', function () {
363
364
  this.timeout(5000);
364
- // 最悪計算量での実行速度はCommonMarkの公式JS実装の32nに対して3倍遅い程度。
365
- // 5n = annotation/reference + link + url/math + ruby + text
366
- const source = `((([[[[#$[${'.'.repeat(19998)}`;
365
+ // 最悪計算量での実行速度はCommonMarkの公式JS実装の32nに対して50-400%程度。
366
+ // 6n = annotation + reference + link + url/math + ruby + text
367
+ const source = `((([[[[#$[${'.'.repeat(16665)}`;
367
368
  assert.deepStrictEqual(
368
- [...parse(source, {}, { resources: { clock: 100000, recursions: [100] } }).children]
369
+ [...parse(source, {}, new Context({ resources: { clock: 100000, recursions: [100] } })).children]
369
370
  .map(el => el.tagName),
370
371
  ['P']);
371
372
  });
372
373
 
373
374
  it('backtrack error', function () {
374
375
  this.timeout(5000);
375
- const source = `((([[[[#$[${'.'.repeat(19998 + 1)}`;
376
+ const source = `((([[[[#$[${'.'.repeat(16665 + 1)}`;
376
377
  assert.deepStrictEqual(
377
- [...parse(source, {}, { resources: { clock: 100000, recursions: [100] } }).children]
378
+ [...parse(source, {}, new Context({ resources: { clock: 100000, recursions: [100] } })).children]
378
379
  .map(el => el.tagName),
379
380
  ['H1', 'PRE']);
380
381
  });
@@ -1,8 +1,7 @@
1
1
  import { ParserOptions } from '../../..';
2
- import { MarkdownParser } from '../../../markdown';
3
2
  import { input } from '../../combinator/data/parser';
3
+ import { Context } from '../context';
4
4
  import { segment } from '../segment';
5
- import { header } from '../header';
6
5
  import { block } from '../block';
7
6
  import { normalize } from './normalize';
8
7
  import { headers } from './header';
@@ -15,28 +14,30 @@ interface Options extends ParserOptions {
15
14
  readonly test?: boolean;
16
15
  }
17
16
 
18
- export function parse(source: string, options: Options = {}, context?: MarkdownParser.Options): DocumentFragment {
17
+ export function parse(source: string, options: Options = {}, context?: Context): DocumentFragment {
19
18
  const url = headers(source).find(field => field.toLowerCase().startsWith('url:'))?.slice(4).trim() ?? '';
20
19
  source = !context ? normalize(source) : source;
21
- context = {
20
+ context = new Context({
22
21
  host: options.host ?? context?.host ?? new ReadonlyURL(location.pathname, location.origin),
23
22
  url: url ? new ReadonlyURL(url as ':') : context?.url,
24
23
  id: options.id ?? context?.id,
25
24
  caches: context?.caches,
26
25
  resources: context?.resources,
27
- };
26
+ });
28
27
  assert(!context.offset);
29
28
  assert(!context.precedence);
30
- assert(!context.delimiters);
31
29
  assert(!context.state);
32
30
  if (context.id?.match(/[^0-9a-z/-]/i)) throw new Error('Invalid ID: ID must be alphanumeric');
33
31
  if (context.host?.origin === 'null') throw new Error(`Invalid host: ${context.host.href}`);
34
32
  const node = frag();
35
- let index = 0;
33
+ // @ts-expect-error
34
+ context.header = true;
36
35
  for (const seg of segment(source)) {
37
36
  node.append(
38
- ...(header(input(seg, { header: index++ === 0 } as MarkdownParser.Context)) || block(input(seg, context)))
37
+ ...block(input(seg, context))
39
38
  ?.foldl<HTMLElement[]>((acc, { value }) => void acc.push(value) || acc, []) ?? []);
39
+ // @ts-expect-error
40
+ context.header = false;
40
41
  }
41
42
  assert(options.id !== '' || !node.querySelector('[id], .index[href], .label[href], .annotation > a[href], .reference > a[href]'));
42
43
  if (options.test) return node;
@@ -1,29 +1,29 @@
1
1
  import { autolink } from './autolink';
2
2
  import { input } from '../combinator/data/parser';
3
+ import { Context } from './context';
3
4
  import { inspect } from '../debug.test';
4
5
 
5
6
  describe('Unit: parser/autolink', () => {
6
7
  describe('autolink', () => {
7
- const parser = (source: string) => autolink(input(source, ctx));
8
- const { context: ctx } = input('', {});
8
+ const parser = autolink;
9
9
 
10
10
  it('basic', () => {
11
- assert.deepStrictEqual(inspect(parser('http://host)'), ctx), [['<a class="url" href="http://host)" target="_blank">http://host)</a>'], '']);
12
- assert.deepStrictEqual(inspect(parser('http://host\\'), ctx), [['<a class="url" href="http://host\\" target="_blank">http://host\\</a>'], '']);
13
- assert.deepStrictEqual(inspect(parser('!http://host)'), ctx), [['!', '<a class="url" href="http://host)" target="_blank">http://host)</a>'], '']);
14
- assert.deepStrictEqual(inspect(parser('!http://host\\'), ctx), [['!', '<a class="url" href="http://host\\" target="_blank">http://host\\</a>'], '']);
15
- assert.deepStrictEqual(inspect(parser('#a'), ctx), [['<a class="hashtag" href="/hashtags/a">#a</a>'], '']);
16
- assert.deepStrictEqual(inspect(parser('@a#b'), ctx), [['<a class="channel" href="/@a?ch=b">@a#b</a>'], '']);
17
- assert.deepStrictEqual(inspect(parser('\\\n'), ctx), [['\\', '<br>'], '']);
18
- assert.deepStrictEqual(inspect(parser('a#b'), ctx), [['a', '#b'], '']);
19
- assert.deepStrictEqual(inspect(parser('0a#b'), ctx), [['0a', '#b'], '']);
20
- assert.deepStrictEqual(inspect(parser('あ#b'), ctx), [['あ', '#b'], '']);
21
- assert.deepStrictEqual(inspect(parser('あい#b'), ctx), [['あい', '#b'], '']);
22
- assert.deepStrictEqual(inspect(parser('0aあ#b'), ctx), [['0a', 'あ', '#b'], '']);
23
- assert.deepStrictEqual(inspect(parser('0aあい#b'), ctx), [['0a', 'あい', '#b'], '']);
24
- assert.deepStrictEqual(inspect(parser('a\n#b'), ctx), [['a', '<br>', '<a class="hashtag" href="/hashtags/b">#b</a>'], '']);
25
- assert.deepStrictEqual(inspect(parser('a\\\n#b'), ctx), [['a', '\\', '<br>', '<a class="hashtag" href="/hashtags/b">#b</a>'], '']);
26
- assert.deepStrictEqual(inspect(parser('0a>>b'), ctx), [['0a', '>', '>b'], '']);
11
+ assert.deepStrictEqual(inspect(parser, input('http://host)', new Context())), [['<a class="url" href="http://host)" target="_blank">http://host)</a>'], '']);
12
+ assert.deepStrictEqual(inspect(parser, input('http://host\\', new Context())), [['<a class="url" href="http://host\\" target="_blank">http://host\\</a>'], '']);
13
+ assert.deepStrictEqual(inspect(parser, input('!http://host)', new Context())), [['!', '<a class="url" href="http://host)" target="_blank">http://host)</a>'], '']);
14
+ assert.deepStrictEqual(inspect(parser, input('!http://host\\', new Context())), [['!', '<a class="url" href="http://host\\" target="_blank">http://host\\</a>'], '']);
15
+ assert.deepStrictEqual(inspect(parser, input('#a', new Context())), [['<a class="hashtag" href="/hashtags/a">#a</a>'], '']);
16
+ assert.deepStrictEqual(inspect(parser, input('@a#b', new Context())), [['<a class="channel" href="/@a?ch=b">@a#b</a>'], '']);
17
+ assert.deepStrictEqual(inspect(parser, input('\\\n', new Context())), [['\\', '<br>'], '']);
18
+ assert.deepStrictEqual(inspect(parser, input('a#b', new Context())), [['a', '#b'], '']);
19
+ assert.deepStrictEqual(inspect(parser, input('0a#b', new Context())), [['0a', '#b'], '']);
20
+ assert.deepStrictEqual(inspect(parser, input('あ#b', new Context())), [['あ', '#b'], '']);
21
+ assert.deepStrictEqual(inspect(parser, input('あい#b', new Context())), [['あい', '#b'], '']);
22
+ assert.deepStrictEqual(inspect(parser, input('0aあ#b', new Context())), [['0a', 'あ', '#b'], '']);
23
+ assert.deepStrictEqual(inspect(parser, input('0aあい#b', new Context())), [['0a', 'あい', '#b'], '']);
24
+ assert.deepStrictEqual(inspect(parser, input('a\n#b', new Context())), [['a', '<br>', '<a class="hashtag" href="/hashtags/b">#b</a>'], '']);
25
+ assert.deepStrictEqual(inspect(parser, input('a\\\n#b', new Context())), [['a', '\\', '<br>', '<a class="hashtag" href="/hashtags/b">#b</a>'], '']);
26
+ assert.deepStrictEqual(inspect(parser, input('0a>>b', new Context())), [['0a', '>', '>b'], '']);
27
27
  });
28
28
 
29
29
  });