securemark 0.258.9 → 0.259.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 (145) hide show
  1. package/CHANGELOG.md +12 -0
  2. package/design.md +6 -5
  3. package/dist/index.js +535 -278
  4. package/markdown.d.ts +4 -3
  5. package/package.json +1 -1
  6. package/src/combinator/control/constraint/block.test.ts +5 -5
  7. package/src/combinator/control/constraint/block.ts +3 -2
  8. package/src/combinator/control/constraint/contract.ts +7 -5
  9. package/src/combinator/control/constraint/line.test.ts +6 -6
  10. package/src/combinator/control/constraint/line.ts +6 -5
  11. package/src/combinator/control/manipulation/convert.ts +6 -5
  12. package/src/combinator/control/manipulation/fence.ts +2 -1
  13. package/src/combinator/control/manipulation/indent.test.ts +14 -14
  14. package/src/combinator/control/manipulation/indent.ts +5 -5
  15. package/src/combinator/control/manipulation/lazy.ts +2 -2
  16. package/src/combinator/control/manipulation/match.ts +3 -2
  17. package/src/combinator/control/manipulation/recovery.ts +6 -6
  18. package/src/combinator/control/manipulation/scope.ts +13 -10
  19. package/src/combinator/control/manipulation/surround.ts +9 -8
  20. package/src/combinator/control/manipulation/trim.test.ts +9 -9
  21. package/src/combinator/control/monad/bind.ts +3 -2
  22. package/src/combinator/data/parser/context/memo.ts +3 -4
  23. package/src/combinator/data/parser/context.test.ts +9 -9
  24. package/src/combinator/data/parser/context.ts +38 -34
  25. package/src/combinator/data/parser/inits.ts +3 -2
  26. package/src/combinator/data/parser/sequence.test.ts +10 -10
  27. package/src/combinator/data/parser/sequence.ts +3 -2
  28. package/src/combinator/data/parser/some.test.ts +13 -13
  29. package/src/combinator/data/parser/some.ts +3 -2
  30. package/src/combinator/data/parser/subsequence.test.ts +14 -14
  31. package/src/combinator/data/parser/union.test.ts +10 -10
  32. package/src/combinator/data/parser/union.ts +2 -2
  33. package/src/combinator/data/parser.ts +6 -1
  34. package/src/parser/api/bind.ts +3 -3
  35. package/src/parser/api/header.ts +1 -1
  36. package/src/parser/api/normalize.ts +1 -1
  37. package/src/parser/api/parse.ts +3 -3
  38. package/src/parser/autolink.test.ts +1 -1
  39. package/src/parser/autolink.ts +2 -2
  40. package/src/parser/block/blockquote.test.ts +1 -1
  41. package/src/parser/block/blockquote.ts +1 -1
  42. package/src/parser/block/codeblock.test.ts +1 -1
  43. package/src/parser/block/codeblock.ts +1 -1
  44. package/src/parser/block/dlist.test.ts +1 -1
  45. package/src/parser/block/extension/aside.test.ts +1 -1
  46. package/src/parser/block/extension/example.test.ts +1 -1
  47. package/src/parser/block/extension/example.ts +1 -1
  48. package/src/parser/block/extension/fig.test.ts +1 -1
  49. package/src/parser/block/extension/figbase.test.ts +1 -1
  50. package/src/parser/block/extension/figure.test.ts +1 -1
  51. package/src/parser/block/extension/figure.ts +1 -1
  52. package/src/parser/block/extension/message.test.ts +1 -1
  53. package/src/parser/block/extension/message.ts +1 -1
  54. package/src/parser/block/extension/placeholder.test.ts +1 -1
  55. package/src/parser/block/extension/table.test.ts +1 -1
  56. package/src/parser/block/extension/table.ts +1 -1
  57. package/src/parser/block/extension.test.ts +1 -1
  58. package/src/parser/block/heading.test.ts +3 -3
  59. package/src/parser/block/heading.ts +1 -1
  60. package/src/parser/block/horizontalrule.test.ts +1 -1
  61. package/src/parser/block/ilist.test.ts +1 -1
  62. package/src/parser/block/mathblock.test.ts +1 -1
  63. package/src/parser/block/olist.test.ts +1 -1
  64. package/src/parser/block/olist.ts +5 -5
  65. package/src/parser/block/paragraph.test.ts +1 -1
  66. package/src/parser/block/reply/cite.test.ts +4 -2
  67. package/src/parser/block/reply/cite.ts +2 -1
  68. package/src/parser/block/reply/quote.test.ts +1 -1
  69. package/src/parser/block/reply/quote.ts +2 -2
  70. package/src/parser/block/reply.test.ts +1 -1
  71. package/src/parser/block/sidefence.test.ts +1 -1
  72. package/src/parser/block/table.test.ts +1 -1
  73. package/src/parser/block/table.ts +1 -1
  74. package/src/parser/block/ulist.test.ts +1 -1
  75. package/src/parser/block/ulist.ts +1 -1
  76. package/src/parser/block.ts +2 -2
  77. package/src/parser/context.ts +15 -6
  78. package/src/parser/header.test.ts +1 -1
  79. package/src/parser/header.ts +3 -3
  80. package/src/parser/inline/annotation.test.ts +1 -1
  81. package/src/parser/inline/annotation.ts +3 -4
  82. package/src/parser/inline/autolink/account.test.ts +1 -1
  83. package/src/parser/inline/autolink/anchor.test.ts +1 -1
  84. package/src/parser/inline/autolink/channel.test.ts +1 -1
  85. package/src/parser/inline/autolink/email.test.ts +1 -1
  86. package/src/parser/inline/autolink/email.ts +1 -1
  87. package/src/parser/inline/autolink/hashnum.test.ts +1 -1
  88. package/src/parser/inline/autolink/hashtag.test.ts +1 -1
  89. package/src/parser/inline/autolink/url.test.ts +1 -1
  90. package/src/parser/inline/autolink.ts +1 -1
  91. package/src/parser/inline/bracket.test.ts +1 -1
  92. package/src/parser/inline/bracket.ts +8 -8
  93. package/src/parser/inline/code.test.ts +1 -1
  94. package/src/parser/inline/code.ts +2 -2
  95. package/src/parser/inline/comment.test.ts +1 -1
  96. package/src/parser/inline/comment.ts +2 -2
  97. package/src/parser/inline/deletion.test.ts +1 -1
  98. package/src/parser/inline/deletion.ts +2 -2
  99. package/src/parser/inline/emphasis.test.ts +1 -1
  100. package/src/parser/inline/emphasis.ts +2 -2
  101. package/src/parser/inline/emstrong.ts +4 -4
  102. package/src/parser/inline/escape.ts +3 -3
  103. package/src/parser/inline/extension/index.test.ts +1 -1
  104. package/src/parser/inline/extension/index.ts +3 -4
  105. package/src/parser/inline/extension/indexer.test.ts +1 -1
  106. package/src/parser/inline/extension/label.test.ts +1 -1
  107. package/src/parser/inline/extension/placeholder.test.ts +1 -1
  108. package/src/parser/inline/extension/placeholder.ts +2 -2
  109. package/src/parser/inline/html.test.ts +1 -1
  110. package/src/parser/inline/html.ts +2 -2
  111. package/src/parser/inline/htmlentity.test.ts +1 -1
  112. package/src/parser/inline/htmlentity.ts +1 -1
  113. package/src/parser/inline/insertion.test.ts +1 -1
  114. package/src/parser/inline/insertion.ts +2 -2
  115. package/src/parser/inline/link.test.ts +1 -1
  116. package/src/parser/inline/link.ts +14 -22
  117. package/src/parser/inline/mark.test.ts +1 -1
  118. package/src/parser/inline/mark.ts +2 -2
  119. package/src/parser/inline/math.test.ts +1 -1
  120. package/src/parser/inline/math.ts +1 -1
  121. package/src/parser/inline/media.test.ts +1 -1
  122. package/src/parser/inline/media.ts +3 -3
  123. package/src/parser/inline/reference.test.ts +1 -1
  124. package/src/parser/inline/reference.ts +3 -4
  125. package/src/parser/inline/ruby.test.ts +1 -1
  126. package/src/parser/inline/ruby.ts +5 -5
  127. package/src/parser/inline/shortmedia.test.ts +1 -1
  128. package/src/parser/inline/strong.test.ts +1 -1
  129. package/src/parser/inline/strong.ts +2 -2
  130. package/src/parser/inline/template.test.ts +1 -1
  131. package/src/parser/inline/template.ts +2 -2
  132. package/src/parser/inline.test.ts +1 -1
  133. package/src/parser/locale.test.ts +1 -1
  134. package/src/parser/segment.ts +1 -1
  135. package/src/parser/source/escapable.test.ts +1 -1
  136. package/src/parser/source/escapable.ts +1 -1
  137. package/src/parser/source/line.test.ts +1 -1
  138. package/src/parser/source/line.ts +2 -2
  139. package/src/parser/source/str.ts +4 -4
  140. package/src/parser/source/text.test.ts +1 -1
  141. package/src/parser/source/text.ts +4 -4
  142. package/src/parser/source/unescapable.test.ts +1 -1
  143. package/src/parser/source/unescapable.ts +1 -1
  144. package/src/parser/visibility.ts +13 -13
  145. package/src/util/quote.ts +1 -1
@@ -9,7 +9,7 @@ export function reset<T>(base: Ctx, parser: Parser<T>): Parser<T> {
9
9
  assert(Object.freeze(base));
10
10
  const changes = Object.entries(base);
11
11
  const values = Array(changes.length);
12
- return (source, context) =>
12
+ return ({ source, context }) =>
13
13
  apply(parser, source, ObjectCreate(context), changes, values);
14
14
  }
15
15
 
@@ -19,7 +19,7 @@ export function context<T>(base: Ctx, parser: Parser<T>): Parser<T> {
19
19
  assert(Object.freeze(base));
20
20
  const changes = Object.entries(base);
21
21
  const values = Array(changes.length);
22
- return (source, context) =>
22
+ return ({ source, context }) =>
23
23
  apply(parser, source, context, changes, values);
24
24
  }
25
25
 
@@ -41,7 +41,7 @@ function apply<T>(parser: Parser<T>, source: string, context: Ctx, changes: [str
41
41
  context[prop] = change[1];
42
42
  }
43
43
  }
44
- const result = parser(source, context);
44
+ const result = parser({ source, context });
45
45
  if (context) for (let i = 0; i < changes.length; ++i) {
46
46
  const change = changes[i];
47
47
  const prop = change[0];
@@ -56,47 +56,47 @@ function apply<T>(parser: Parser<T>, source: string, context: Ctx, changes: [str
56
56
  return result;
57
57
  }
58
58
 
59
- export function syntax<P extends Parser<unknown>>(syntax: number, precedence: number, cost: number, parser: P): P;
60
- export function syntax<T>(syntax: number, precedence: number, cost: number, parser?: Parser<T>): Parser<T> {
61
- return creation(cost, (source, context) => {
59
+ export function syntax<P extends Parser<unknown>>(syntax: number, precedence: number, cost: number, state: number, parser: P): P;
60
+ export function syntax<T>(syntax: number, prec: number, cost: number, state: number, parser?: Parser<T>): Parser<T> {
61
+ return creation(cost, precedence(prec, input => {
62
+ const { source, context } = input;
62
63
  if (source === '') return;
63
64
  const memo = context.memo ??= new Memo();
64
65
  context.memorable ??= ~0;
65
- const p = context.precedence;
66
- context.precedence = precedence;
67
- const position = source.length;
68
- const state = context.state ?? 0;
69
- const cache = syntax && memo.get(position, syntax, state);
66
+ context.offset ??= 0;
67
+ const position = source.length + context.offset!;
68
+ const st0 = context.state ?? 0;
69
+ const st1 = context.state = st0 | state;
70
+ const cache = syntax && memo.get(position, syntax, st1);
70
71
  const result: Result<T> = cache
71
72
  ? cache.length === 0
72
73
  ? undefined
73
74
  : [cache[0], source.slice(cache[1])]
74
- : parser!(source, context);
75
- if (syntax && state & context.memorable!) {
76
- cache ?? memo.set(position, syntax, state, eval(result), source.length - exec(result, '').length);
77
- assert.deepStrictEqual(cache && cache, cache && memo.get(position, syntax, state));
75
+ : parser!(input);
76
+ if (syntax && st0 & context.memorable!) {
77
+ cache ?? memo.set(position, syntax, st1, eval(result), source.length - exec(result, '').length);
78
+ assert.deepStrictEqual(cache && cache, cache && memo.get(position, syntax, st1));
78
79
  }
79
- if (result && !state && memo.length! >= position) {
80
- assert(!(state & context.memorable!));
81
- memo.clear(position);
80
+ if (result && !st0 && memo.length! >= position + 2) {
81
+ assert(!(st0 & context.memorable!));
82
+ memo.clear(position + 2);
82
83
  }
83
- context.precedence = p;
84
+ context.state = st0;
84
85
  return result;
85
- });
86
+ }));
86
87
  }
87
88
 
88
89
  export function creation<P extends Parser<unknown>>(parser: P): P;
89
90
  export function creation<P extends Parser<unknown>>(cost: number, parser: P): P;
90
91
  export function creation(cost: number | Parser<unknown>, parser?: Parser<unknown>): Parser<unknown> {
91
92
  if (typeof cost === 'function') return creation(1, cost);
92
- if (cost === 0) return parser!;
93
- assert(cost >= 0);
94
- return (source, context) => {
95
- const { resources = { clock: 1, recursion: 1 } } = context;
93
+ assert(cost > 0);
94
+ return input => {
95
+ const resources = input.context.resources ?? { clock: 1, recursion: 1 };
96
96
  if (resources.clock <= 0) throw new Error('Too many creations');
97
97
  if (resources.recursion <= 0) throw new Error('Too much recursion');
98
98
  --resources.recursion;
99
- const result = parser!(source, context);
99
+ const result = parser!(input);
100
100
  ++resources.recursion;
101
101
  if (result) {
102
102
  resources.clock -= cost;
@@ -107,10 +107,12 @@ export function creation(cost: number | Parser<unknown>, parser?: Parser<unknown
107
107
 
108
108
  export function precedence<P extends Parser<unknown>>(precedence: number, parser: P): P;
109
109
  export function precedence<T>(precedence: number, parser: Parser<T>): Parser<T> {
110
- return (source, context) => {
110
+ assert(precedence > 0);
111
+ return input => {
112
+ const { context } = input;
111
113
  const p = context.precedence;
112
114
  context.precedence = precedence;
113
- const result = parser(source, context);
115
+ const result = parser(input);
114
116
  context.precedence = p;
115
117
  return result;
116
118
  };
@@ -118,9 +120,9 @@ export function precedence<T>(precedence: number, parser: Parser<T>): Parser<T>
118
120
 
119
121
  export function guard<P extends Parser<unknown>>(f: (context: Context<P>) => boolean | number, parser: P): P;
120
122
  export function guard<T>(f: (context: Ctx) => boolean | number, parser: Parser<T>): Parser<T> {
121
- return (source, context) =>
122
- f(context)
123
- ? parser(source, context)
123
+ return input =>
124
+ f(input.context)
125
+ ? parser(input)
124
126
  : undefined;
125
127
  }
126
128
 
@@ -132,12 +134,13 @@ export function constraint<T>(state: number, positive: boolean | Parser<T>, pars
132
134
  positive = true;
133
135
  }
134
136
  assert(state);
135
- return (source, context) => {
137
+ return input => {
138
+ const { context } = input;
136
139
  const s = positive
137
140
  ? state & context.state!
138
141
  : state & ~context.state!;
139
142
  return s === state
140
- ? parser!(source, context)
143
+ ? parser!(input)
141
144
  : undefined;
142
145
  };
143
146
  }
@@ -150,12 +153,13 @@ export function state<T>(state: number, positive: boolean | Parser<T>, parser?:
150
153
  positive = true;
151
154
  }
152
155
  assert(state);
153
- return (source, context) => {
156
+ return input => {
157
+ const { context } = input;
154
158
  const s = context.state ?? 0;
155
159
  context.state = positive
156
160
  ? s | state
157
161
  : s & ~state;
158
- const result = parser!(source, context);
162
+ const result = parser!(input);
159
163
  context.state = s;
160
164
  return result;
161
165
  };
@@ -6,13 +6,14 @@ export function inits<P extends Parser<unknown>>(parsers: SubParsers<P>, resume?
6
6
  export function inits<T, D extends Parser<T>[]>(parsers: D, resume?: (nodes: T[], rest: string) => boolean): Parser<T, Ctx, D> {
7
7
  assert(parsers.every(f => f));
8
8
  if (parsers.length === 1) return parsers[0];
9
- return (source, context) => {
9
+ return input => {
10
+ const { source, context } = input;
10
11
  let rest = source;
11
12
  let nodes: T[] | undefined;
12
13
  for (let i = 0, len = parsers.length; i < len; ++i) {
13
14
  if (rest === '') break;
14
15
  if (context.delimiters?.match(rest, context.precedence)) break;
15
- const result = parsers[i](rest, context);
16
+ const result = parsers[i]({ source: rest, context });
16
17
  assert(check(rest, result));
17
18
  if (!result) break;
18
19
  nodes = nodes
@@ -4,12 +4,12 @@ import { inspect } from '../../../debug.test';
4
4
 
5
5
  describe('Unit: combinator/data/parser/sequence', () => {
6
6
  describe('sequence', () => {
7
- const a: Parser<string, never> = source => {
7
+ const a: Parser<string, never> = ({ source }) => {
8
8
  return source && source[0] === 'a'
9
9
  ? [['A'], source.slice(1)]
10
10
  : undefined;
11
11
  };
12
- const b: Parser<string, never> = source => {
12
+ const b: Parser<string, never> = ({ source }) => {
13
13
  return source && source[0] === 'b'
14
14
  ? [['B'], source.slice(1)]
15
15
  : undefined;
@@ -18,14 +18,14 @@ describe('Unit: combinator/data/parser/sequence', () => {
18
18
 
19
19
  it('basic', () => {
20
20
  const parser = ab;
21
- assert.deepStrictEqual(inspect(parser('', {})), undefined);
22
- assert.deepStrictEqual(inspect(parser('a', {})), undefined);
23
- assert.deepStrictEqual(inspect(parser('b', {})), undefined);
24
- assert.deepStrictEqual(inspect(parser('ab', {})), [['A', 'B'], '']);
25
- assert.deepStrictEqual(inspect(parser('ba', {})), undefined);
26
- assert.deepStrictEqual(inspect(parser('aab', {})), undefined);
27
- assert.deepStrictEqual(inspect(parser('abb', {})), [['A', 'B'], 'b']);
28
- assert.deepStrictEqual(inspect(parser('bba', {})), undefined);
21
+ assert.deepStrictEqual(inspect(parser({ source: '', context: {} })), undefined);
22
+ assert.deepStrictEqual(inspect(parser({ source: 'a', context: {} })), undefined);
23
+ assert.deepStrictEqual(inspect(parser({ source: 'b', context: {} })), undefined);
24
+ assert.deepStrictEqual(inspect(parser({ source: 'ab', context: {} })), [['A', 'B'], '']);
25
+ assert.deepStrictEqual(inspect(parser({ source: 'ba', context: {} })), undefined);
26
+ assert.deepStrictEqual(inspect(parser({ source: 'aab', context: {} })), undefined);
27
+ assert.deepStrictEqual(inspect(parser({ source: 'abb', context: {} })), [['A', 'B'], 'b']);
28
+ assert.deepStrictEqual(inspect(parser({ source: 'bba', context: {} })), undefined);
29
29
  });
30
30
 
31
31
  });
@@ -6,13 +6,14 @@ export function sequence<P extends Parser<unknown>>(parsers: SubParsers<P>, resu
6
6
  export function sequence<T, D extends Parser<T>[]>(parsers: D, resume?: (nodes: T[], rest: string) => boolean): Parser<T, Ctx, D> {
7
7
  assert(parsers.every(f => f));
8
8
  if (parsers.length === 1) return parsers[0];
9
- return (source, context) => {
9
+ return input => {
10
+ const { source, context } = input;
10
11
  let rest = source;
11
12
  let nodes: T[] | undefined;
12
13
  for (let i = 0, len = parsers.length; i < len; ++i) {
13
14
  if (rest === '') return;
14
15
  if (context.delimiters?.match(rest, context.precedence)) return;
15
- const result = parsers[i](rest, context);
16
+ const result = parsers[i]({ source: rest, context });
16
17
  assert(check(rest, result));
17
18
  if (!result) return;
18
19
  nodes = nodes
@@ -5,12 +5,12 @@ import { inspect } from '../../../debug.test';
5
5
 
6
6
  describe('Unit: combinator/data/parser/some', () => {
7
7
  describe('some', () => {
8
- const a: Parser<string, never> = source => {
8
+ const a: Parser<string, never> = ({ source }) => {
9
9
  return source && source[0] === 'a'
10
10
  ? [['A'], source.slice(1)]
11
11
  : undefined;
12
12
  };
13
- const b: Parser<string, never> = source => {
13
+ const b: Parser<string, never> = ({ source }) => {
14
14
  return source && source[0] === 'b'
15
15
  ? [['B'], source.slice(1)]
16
16
  : undefined;
@@ -19,17 +19,17 @@ describe('Unit: combinator/data/parser/some', () => {
19
19
 
20
20
  it('basic', () => {
21
21
  const parser = some(ab, /^aaa/);
22
- assert.deepStrictEqual(inspect(parser('', {})), undefined);
23
- assert.deepStrictEqual(inspect(parser('a', {})), [['A'], '']);
24
- assert.deepStrictEqual(inspect(parser('b', {})), [['B'], '']);
25
- assert.deepStrictEqual(inspect(parser('ab', {})), [['A', 'B'], '']);
26
- assert.deepStrictEqual(inspect(parser('ba', {})), [['B', 'A'], '']);
27
- assert.deepStrictEqual(inspect(parser('aab', {})), [['A', 'A', 'B'], '']);
28
- assert.deepStrictEqual(inspect(parser('bba', {})), [['B', 'B', 'A'], '']);
29
- assert.deepStrictEqual(inspect(parser('aaa', {})), undefined);
30
- assert.deepStrictEqual(inspect(parser('bbb', {})), [['B', 'B', 'B'], '']);
31
- assert.deepStrictEqual(inspect(parser('aaab', {})), undefined);
32
- assert.deepStrictEqual(inspect(parser('baaa', {})), [['B'], 'aaa']);
22
+ assert.deepStrictEqual(inspect(parser({ source: '', context: {} })), undefined);
23
+ assert.deepStrictEqual(inspect(parser({ source: 'a', context: {} })), [['A'], '']);
24
+ assert.deepStrictEqual(inspect(parser({ source: 'b', context: {} })), [['B'], '']);
25
+ assert.deepStrictEqual(inspect(parser({ source: 'ab', context: {} })), [['A', 'B'], '']);
26
+ assert.deepStrictEqual(inspect(parser({ source: 'ba', context: {} })), [['B', 'A'], '']);
27
+ assert.deepStrictEqual(inspect(parser({ source: 'aab', context: {} })), [['A', 'A', 'B'], '']);
28
+ assert.deepStrictEqual(inspect(parser({ source: 'bba', context: {} })), [['B', 'B', 'A'], '']);
29
+ assert.deepStrictEqual(inspect(parser({ source: 'aaa', context: {} })), undefined);
30
+ assert.deepStrictEqual(inspect(parser({ source: 'bbb', context: {} })), [['B', 'B', 'B'], '']);
31
+ assert.deepStrictEqual(inspect(parser({ source: 'aaab', context: {} })), undefined);
32
+ assert.deepStrictEqual(inspect(parser({ source: 'baaa', context: {} })), [['B'], 'aaa']);
33
33
  });
34
34
 
35
35
  });
@@ -16,7 +16,8 @@ export function some<T>(parser: Parser<T>, end?: string | RegExp | number, delim
16
16
  matcher: Delimiters.matcher(delimiter),
17
17
  precedence,
18
18
  }));
19
- return (source, context) => {
19
+ return input => {
20
+ const { source, context } = input;
20
21
  if (source === '') return;
21
22
  let rest = source;
22
23
  let nodes: T[] | undefined;
@@ -28,7 +29,7 @@ export function some<T>(parser: Parser<T>, end?: string | RegExp | number, delim
28
29
  if (rest === '') break;
29
30
  if (match(rest)) break;
30
31
  if (context.delimiters?.match(rest, context.precedence)) break;
31
- const result = parser(rest, context);
32
+ const result = parser({ source: rest, context });
32
33
  assert.doesNotThrow(() => limit < 0 && check(rest, result));
33
34
  if (!result) break;
34
35
  nodes = nodes
@@ -4,17 +4,17 @@ import { inspect } from '../../../debug.test';
4
4
 
5
5
  describe('Unit: combinator/data/parser/subsequence', () => {
6
6
  describe('subsequence', () => {
7
- const a: Parser<string, never> = source => {
7
+ const a: Parser<string, never> = ({ source }) => {
8
8
  return source && source[0] === 'a'
9
9
  ? [['A'], source.slice(1)]
10
10
  : undefined;
11
11
  };
12
- const b: Parser<string, never> = source => {
12
+ const b: Parser<string, never> = ({ source }) => {
13
13
  return source && source[0] === 'b'
14
14
  ? [['B'], source.slice(1)]
15
15
  : undefined;
16
16
  };
17
- const c: Parser<string, never> = source => {
17
+ const c: Parser<string, never> = ({ source }) => {
18
18
  return source && source[0] === 'c'
19
19
  ? [['C'], source.slice(1)]
20
20
  : undefined;
@@ -23,17 +23,17 @@ describe('Unit: combinator/data/parser/subsequence', () => {
23
23
 
24
24
  it('basic', () => {
25
25
  const parser = abc;
26
- assert.deepStrictEqual(inspect(parser('', {})), undefined);
27
- assert.deepStrictEqual(inspect(parser('a', {})), [['A'], '']);
28
- assert.deepStrictEqual(inspect(parser('b', {})), [['B'], '']);
29
- assert.deepStrictEqual(inspect(parser('c', {})), [['C'], '']);
30
- assert.deepStrictEqual(inspect(parser('ab', {})), [['A', 'B'], '']);
31
- assert.deepStrictEqual(inspect(parser('ba', {})), [['B'], 'a']);
32
- assert.deepStrictEqual(inspect(parser('aab', {})), [['A'], 'ab']);
33
- assert.deepStrictEqual(inspect(parser('abb', {})), [['A', 'B'], 'b']);
34
- assert.deepStrictEqual(inspect(parser('bba', {})), [['B'], 'ba']);
35
- assert.deepStrictEqual(inspect(parser('ac', {})), [['A', 'C'], '']);
36
- assert.deepStrictEqual(inspect(parser('bc', {})), [['B', 'C'], '']);
26
+ assert.deepStrictEqual(inspect(parser({ source: '', context: {} })), undefined);
27
+ assert.deepStrictEqual(inspect(parser({ source: 'a', context: {} })), [['A'], '']);
28
+ assert.deepStrictEqual(inspect(parser({ source: 'b', context: {} })), [['B'], '']);
29
+ assert.deepStrictEqual(inspect(parser({ source: 'c', context: {} })), [['C'], '']);
30
+ assert.deepStrictEqual(inspect(parser({ source: 'ab', context: {} })), [['A', 'B'], '']);
31
+ assert.deepStrictEqual(inspect(parser({ source: 'ba', context: {} })), [['B'], 'a']);
32
+ assert.deepStrictEqual(inspect(parser({ source: 'aab', context: {} })), [['A'], 'ab']);
33
+ assert.deepStrictEqual(inspect(parser({ source: 'abb', context: {} })), [['A', 'B'], 'b']);
34
+ assert.deepStrictEqual(inspect(parser({ source: 'bba', context: {} })), [['B'], 'ba']);
35
+ assert.deepStrictEqual(inspect(parser({ source: 'ac', context: {} })), [['A', 'C'], '']);
36
+ assert.deepStrictEqual(inspect(parser({ source: 'bc', context: {} })), [['B', 'C'], '']);
37
37
  });
38
38
 
39
39
  });
@@ -4,12 +4,12 @@ import { inspect } from '../../../debug.test';
4
4
 
5
5
  describe('Unit: combinator/data/parser/union', () => {
6
6
  describe('union', () => {
7
- const a: Parser<string, never> = source => {
7
+ const a: Parser<string, never> = ({ source }) => {
8
8
  return source && source[0] === 'a'
9
9
  ? [['A'], source.slice(1)]
10
10
  : undefined;
11
11
  };
12
- const b: Parser<string, never> = source => {
12
+ const b: Parser<string, never> = ({ source }) => {
13
13
  return source && source[0] === 'b'
14
14
  ? [['B'], source.slice(1)]
15
15
  : undefined;
@@ -18,14 +18,14 @@ describe('Unit: combinator/data/parser/union', () => {
18
18
 
19
19
  it('basic', () => {
20
20
  const parser = ab;
21
- assert.deepStrictEqual(inspect(parser('', {})), undefined);
22
- assert.deepStrictEqual(inspect(parser('a', {})), [['A'], '']);
23
- assert.deepStrictEqual(inspect(parser('b', {})), [['B'], '']);
24
- assert.deepStrictEqual(inspect(parser('ab', {})), [['A'], 'b']);
25
- assert.deepStrictEqual(inspect(parser('ba', {})), [['B'], 'a']);
26
- assert.deepStrictEqual(inspect(parser('aab', {})), [['A'], 'ab']);
27
- assert.deepStrictEqual(inspect(parser('abb', {})), [['A'], 'bb']);
28
- assert.deepStrictEqual(inspect(parser('bba', {})), [['B'], 'ba']);
21
+ assert.deepStrictEqual(inspect(parser({ source: '', context: {} })), undefined);
22
+ assert.deepStrictEqual(inspect(parser({ source: 'a', context: {} })), [['A'], '']);
23
+ assert.deepStrictEqual(inspect(parser({ source: 'b', context: {} })), [['B'], '']);
24
+ assert.deepStrictEqual(inspect(parser({ source: 'ab', context: {} })), [['A'], 'b']);
25
+ assert.deepStrictEqual(inspect(parser({ source: 'ba', context: {} })), [['B'], 'a']);
26
+ assert.deepStrictEqual(inspect(parser({ source: 'aab', context: {} })), [['A'], 'ab']);
27
+ assert.deepStrictEqual(inspect(parser({ source: 'abb', context: {} })), [['A'], 'bb']);
28
+ assert.deepStrictEqual(inspect(parser({ source: 'bba', context: {} })), [['B'], 'ba']);
29
29
  });
30
30
 
31
31
  });
@@ -12,9 +12,9 @@ export function union<T, D extends Parser<T>[]>(parsers: D): Parser<T, Ctx, D> {
12
12
  default:
13
13
  return Function('parsers', [
14
14
  '"use strict";',
15
- 'return (source, context) =>',
15
+ 'return (input, context) =>',
16
16
  '0',
17
- ...parsers.map((_, i) => `|| parsers[${i}](source, context)`),
17
+ ...parsers.map((_, i) => `|| parsers[${i}](input, context)`),
18
18
  ].join('\n'))(parsers);
19
19
  }
20
20
  }
@@ -2,7 +2,11 @@ import { Delimiters } from './parser/context/delimiter';
2
2
  import { Memo } from './parser/context/memo';
3
3
 
4
4
  export type Parser<T, C extends Ctx = Ctx, D extends Parser<unknown, C>[] = any>
5
- = (source: string, context: C) => Result<T, C, D>;
5
+ = (input: Input<C>) => Result<T, C, D>;
6
+ export interface Input<C extends Ctx = Ctx> {
7
+ readonly source: string;
8
+ readonly context: C;
9
+ }
6
10
  export type Result<T, C extends Ctx = Ctx, D extends Parser<unknown, C>[] = any>
7
11
  = readonly [T[], string, C, D]
8
12
  | readonly [T[], string]
@@ -12,6 +16,7 @@ export interface Ctx {
12
16
  clock: number;
13
17
  recursion: number;
14
18
  };
19
+ offset?: number;
15
20
  precedence?: number;
16
21
  delimiters?: Delimiters;
17
22
  state?: number;
@@ -5,7 +5,7 @@ import { eval } from '../../combinator/data/parser';
5
5
  import { segment, validate, MAX_INPUT_SIZE } from '../segment';
6
6
  import { header } from '../header';
7
7
  import { block } from '../block';
8
- import { backtrackable } from '../context';
8
+ import { State } from '../context';
9
9
  import { normalize } from './normalize';
10
10
  import { headers } from './header';
11
11
  import { figure } from '../processor/figure';
@@ -24,7 +24,7 @@ export function bind(target: DocumentFragment | HTMLElement | ShadowRoot, settin
24
24
  let context: MarkdownParser.Context = {
25
25
  ...settings,
26
26
  host: settings.host ?? new ReadonlyURL(location.pathname, location.origin),
27
- memorable: backtrackable,
27
+ memorable: State.backtrackable,
28
28
  };
29
29
  if (context.host?.origin === 'null') throw new Error(`Invalid host: ${context.host.href}`);
30
30
  assert(!settings.id);
@@ -77,7 +77,7 @@ export function bind(target: DocumentFragment | HTMLElement | ShadowRoot, settin
77
77
  for (; index < sourceSegments.length - last; ++index) {
78
78
  assert(rev === revision);
79
79
  const seg = sourceSegments[index];
80
- const es = eval(header(seg, { header: index === 0 }) || block(seg, context), []);
80
+ const es = eval(header({ source: seg, context: { header: index === 0 } }) || block({ source: seg, context }), []);
81
81
  blocks.splice(index, 0, [seg, es, url]);
82
82
  if (es.length === 0) continue;
83
83
  // All deletion processes always run after all addition processes have done.
@@ -12,7 +12,7 @@ export function headers(source: string): string[] {
12
12
  }
13
13
 
14
14
  function parse(source: string): [HTMLElement, string] | [] {
15
- const result = h(source, {});
15
+ const result = h({ source, context: {} });
16
16
  const [el] = eval(result, []);
17
17
  return el?.tagName === 'ASIDE'
18
18
  ? [el, exec(result!)]
@@ -60,7 +60,7 @@ export const invisibleHTMLEntityNames = [
60
60
  ] as const;
61
61
  const unreadableHTMLEntityNames: readonly string[] = invisibleHTMLEntityNames.slice(2);
62
62
  const unreadableEscapableCharacters = unreadableHTMLEntityNames
63
- .map(name => eval(unsafehtmlentity(`&${name};`, {}))![0]);
63
+ .map(name => eval(unsafehtmlentity({ source: `&${name};`, context: {} }))![0]);
64
64
  assert(unreadableEscapableCharacters.length === unreadableHTMLEntityNames.length);
65
65
  assert(unreadableEscapableCharacters.every(c => c.length === 1));
66
66
  const unreadableEscapableCharacter = new RegExp(`[${
@@ -5,7 +5,7 @@ import { eval } from '../../combinator/data/parser';
5
5
  import { segment, validate, MAX_SEGMENT_SIZE } from '../segment';
6
6
  import { header } from '../header';
7
7
  import { block } from '../block';
8
- import { backtrackable } from '../context';
8
+ import { State } from '../context';
9
9
  import { normalize } from './normalize';
10
10
  import { headers } from './header';
11
11
  import { figure } from '../processor/figure';
@@ -30,13 +30,13 @@ export function parse(source: string, opts: Options = {}, context?: MarkdownPars
30
30
  ...context?.resources && {
31
31
  resources: context.resources,
32
32
  },
33
- memorable: backtrackable,
33
+ memorable: State.backtrackable,
34
34
  };
35
35
  if (context.host?.origin === 'null') throw new Error(`Invalid host: ${context.host.href}`);
36
36
  const node = frag();
37
37
  let index = 0;
38
38
  for (const seg of segment(source)) {
39
- node.append(...eval(header(seg, { header: index++ === 0 }) || block(seg, context), []));
39
+ node.append(...eval(header({ source: seg, context: { header: index++ === 0 } }) || block({ source: seg, context }), []));
40
40
  }
41
41
  assert(opts.id !== '' || !node.querySelector('[id], .index[href], .label[href], .annotation > a[href], .reference > a[href]'));
42
42
  if (opts.test) return node;
@@ -4,7 +4,7 @@ import { inspect } from '../debug.test';
4
4
 
5
5
  describe('Unit: parser/autolink', () => {
6
6
  describe('autolink', () => {
7
- const parser = (source: string) => some(autolink)(source, {});
7
+ const parser = (source: string) => some(autolink)({ source, context: {} });
8
8
 
9
9
  it('basic', () => {
10
10
  assert.deepStrictEqual(inspect(parser(' http://host')), [[' ', '<a href="http://host" target="_blank">http://host</a>'], '']);
@@ -7,7 +7,7 @@ export import AutolinkParser = MarkdownParser.AutolinkParser;
7
7
 
8
8
  const delimiter = /[@#>0-9A-Za-z\n]|\S[#>]/;
9
9
 
10
- export const autolink: AutolinkParser = (source, context) => {
10
+ export const autolink: AutolinkParser = ({ source, context }) => {
11
11
  if (source === '') return;
12
12
  assert(source[0] !== '\x1B');
13
13
  const i = source.search(delimiter);
@@ -15,7 +15,7 @@ export const autolink: AutolinkParser = (source, context) => {
15
15
  case -1:
16
16
  return [[source], ''];
17
17
  case 0:
18
- return parser(source, context);
18
+ return parser({ source, context });
19
19
  default:
20
20
  return [[source.slice(0, i)], source.slice(i)];
21
21
  }
@@ -4,7 +4,7 @@ import { inspect } from '../../debug.test';
4
4
 
5
5
  describe('Unit: parser/block/blockquote', () => {
6
6
  describe('blockquote', () => {
7
- const parser = (source: string) => some(blockquote)(source, {});
7
+ const parser = (source: string) => some(blockquote)({ source, context: {} });
8
8
 
9
9
  it('invalid', () => {
10
10
  assert.deepStrictEqual(inspect(parser('')), undefined);
@@ -37,7 +37,7 @@ const markdown: BlockquoteParser.MarkdownParser = lazy(() => fmap(
37
37
  creation(99,
38
38
  rewrite(
39
39
  some(contentline, opener),
40
- convert(unindent, (source, context) => {
40
+ convert(unindent, ({ source, context }) => {
41
41
  const references = html('ol', { class: 'references' });
42
42
  const document = parse(source, {
43
43
  id: '',
@@ -4,7 +4,7 @@ import { inspect } from '../../debug.test';
4
4
 
5
5
  describe('Unit: parser/block/codeblock', () => {
6
6
  describe('codeblock', () => {
7
- const parser = (source: string) => some(codeblock)(source, {});
7
+ const parser = (source: string) => some(codeblock)({ source, context: {} });
8
8
 
9
9
  it('invalid', () => {
10
10
  assert.deepStrictEqual(inspect(parser('')), undefined);
@@ -70,6 +70,6 @@ export const codeblock: CodeBlockParser = block(validate('```', fmap(
70
70
  params.lang
71
71
  ? context.caches?.code?.get(`${params.lang ?? ''}\n${body.slice(0, -1)}`)?.cloneNode(true).childNodes ||
72
72
  body.slice(0, -1) || undefined
73
- : defrag(eval(some(autolink)(body.slice(0, -1), context), [])));
73
+ : defrag(eval(some(autolink)({ source: body.slice(0, -1), context }), [])));
74
74
  return [el];
75
75
  })));
@@ -4,7 +4,7 @@ import { inspect } from '../../debug.test';
4
4
 
5
5
  describe('Unit: parser/block/dlist', () => {
6
6
  describe('dlist', () => {
7
- const parser = (source: string) => some(dlist)(source, {});
7
+ const parser = (source: string) => some(dlist)({ source, context: {} });
8
8
 
9
9
  it('invalid', () => {
10
10
  assert.deepStrictEqual(inspect(parser('')), undefined);
@@ -4,7 +4,7 @@ import { inspect } from '../../../debug.test';
4
4
 
5
5
  describe('Unit: parser/block/extension/aside', () => {
6
6
  describe('aside', () => {
7
- const parser = (source: string) => some(aside)(source, {});
7
+ const parser = (source: string) => some(aside)({ source, context: {} });
8
8
 
9
9
  it('invalid', () => {
10
10
  assert.deepStrictEqual(inspect(parser('~~~aside\n~~~')), [['<pre class="invalid" translate="no">~~~aside\n~~~</pre>'], '']);
@@ -4,7 +4,7 @@ import { inspect } from '../../../debug.test';
4
4
 
5
5
  describe('Unit: parser/block/extension/example', () => {
6
6
  describe('example', () => {
7
- const parser = (source: string) => some(example)(source, {});
7
+ const parser = (source: string) => some(example)({ source, context: {} });
8
8
 
9
9
  it('invalid', () => {
10
10
  assert.deepStrictEqual(inspect(parser('~~~example/\n~~~')), undefined);
@@ -44,7 +44,7 @@ export const example: ExtensionParser.ExampleParser = block(validate('~~~', fmap
44
44
  html('aside', { class: 'example', 'data-type': 'math' }, [
45
45
  html('pre', { translate: 'no' }, body.slice(0, -1)),
46
46
  html('hr'),
47
- eval(mathblock(`$$\n${body}$$`, context), [])[0],
47
+ eval(mathblock({ source: `$$\n${body}$$`, context }), [])[0],
48
48
  ]),
49
49
  ];
50
50
  default:
@@ -4,7 +4,7 @@ import { inspect } from '../../../debug.test';
4
4
 
5
5
  describe('Unit: parser/block/extension/fig', () => {
6
6
  describe('fig', () => {
7
- const parser = (source: string) => some(fig)(source, {});
7
+ const parser = (source: string) => some(fig)({ source, context: {} });
8
8
 
9
9
  it('invalid', () => {
10
10
  assert.deepStrictEqual(inspect(parser('\n!https://host\n')), undefined);
@@ -4,7 +4,7 @@ import { inspect } from '../../../debug.test';
4
4
 
5
5
  describe('Unit: parser/block/extension/figbase', () => {
6
6
  describe('figbase', () => {
7
- const parser = (source: string) => some(figbase)(source, {});
7
+ const parser = (source: string) => some(figbase)({ source, context: {} });
8
8
 
9
9
  it('invalid', () => {
10
10
  assert.deepStrictEqual(inspect(parser('\n$-0')), undefined);