securemark 0.299.2 → 0.299.4

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 (59) hide show
  1. package/CHANGELOG.md +8 -0
  2. package/dist/index.js +2102 -2185
  3. package/index.ts +2 -2
  4. package/package.json +1 -1
  5. package/src/{parser/api → api}/bind.test.ts +2 -2
  6. package/src/{parser/api → api}/bind.ts +5 -5
  7. package/src/{parser/api → api}/body.test.ts +1 -1
  8. package/src/{parser/api → api}/cache.ts +1 -1
  9. package/src/{parser/api → api}/header.test.ts +1 -1
  10. package/src/{parser/api → api}/header.ts +2 -2
  11. package/src/{parser/api → api}/normalize.test.ts +1 -1
  12. package/src/{parser/api → api}/parse.test.ts +3 -3
  13. package/src/{parser/api → api}/parse.ts +5 -5
  14. package/src/combinator/control/manipulation/fence.ts +2 -2
  15. package/src/combinator/control/manipulation/match.ts +2 -2
  16. package/src/combinator/data/delimiter.ts +3 -3
  17. package/src/combinator/data/{node.ts → list/list.ts} +4 -4
  18. package/src/combinator/data/parser/context.ts +12 -38
  19. package/src/combinator/data/parser/inits.ts +3 -3
  20. package/src/combinator/data/parser/sequence.ts +3 -3
  21. package/src/combinator/data/parser/some.ts +0 -1
  22. package/src/combinator/data/parser/subsequence.ts +3 -3
  23. package/src/combinator/data/parser/tails.ts +3 -3
  24. package/src/combinator/data/parser.ts +1 -1
  25. package/src/parser/block/blockquote.ts +3 -3
  26. package/src/parser/block/extension/aside.ts +1 -1
  27. package/src/parser/block/extension/example.ts +1 -1
  28. package/src/parser/block.ts +1 -1
  29. package/src/parser/context.ts +4 -5
  30. package/src/parser/inline/annotation.ts +1 -1
  31. package/src/parser/inline/deletion.ts +1 -1
  32. package/src/parser/inline/emstrong.ts +1 -1
  33. package/src/parser/inline/insertion.ts +1 -1
  34. package/src/parser/inline/italic.ts +1 -1
  35. package/src/parser/inline/link.ts +4 -4
  36. package/src/parser/inline/mark.ts +1 -1
  37. package/src/parser/inline/media.ts +3 -3
  38. package/src/parser/inline.ts +1 -1
  39. package/src/parser/node.ts +1 -1
  40. package/src/parser/repeat.ts +7 -19
  41. package/src/parser/source/escapable.ts +5 -5
  42. package/src/parser/source/text.ts +8 -9
  43. package/src/parser/source/unescapable.ts +6 -6
  44. package/src/parser/visibility.ts +1 -1
  45. package/src/{parser/processor → processor}/figure.test.ts +4 -4
  46. package/src/{parser/processor → processor}/figure.ts +2 -2
  47. package/src/{parser/processor → processor}/note.test.ts +3 -3
  48. package/src/{parser/processor → processor}/note.ts +2 -2
  49. package/src/renderer/render/media/pdf.ts +1 -1
  50. package/src/renderer/render/media/twitter.ts +1 -1
  51. package/src/renderer/render/media.test.ts +1 -2
  52. package/src/renderer/render.test.ts +1 -1
  53. package/src/util/info.test.ts +1 -1
  54. package/src/util/quote.test.ts +1 -1
  55. package/src/util/toc.test.ts +1 -1
  56. package/src/parser.ts +0 -1
  57. /package/src/{parser/api → api}/body.ts +0 -0
  58. /package/src/{parser/api → api}/normalize.ts +0 -0
  59. /package/src/{parser/api.ts → api.ts} +0 -0
package/index.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  import 'spica/global';
2
2
 
3
- export * from './src/parser';
4
- export * from './src/util';
3
+ export * from './src/api';
5
4
  export * from './src/renderer';
5
+ export * from './src/util';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "securemark",
3
- "version": "0.299.2",
3
+ "version": "0.299.4",
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",
@@ -1,8 +1,8 @@
1
- import { Progress } from '../../..';
1
+ import { Progress } from '../..';
2
2
  import { bind } from './bind';
3
3
  import { frag, html } from 'typed-dom/dom';
4
4
 
5
- describe('Unit: parser/api/bind', () => {
5
+ describe('Unit: api/bind', () => {
6
6
  describe('bind', () => {
7
7
  function inspect(iter: IterableIterator<Progress>, count = Infinity) {
8
8
  const acc: (string | undefined)[] = [];
@@ -1,8 +1,8 @@
1
- import { ParserSettings, Progress } from '../../..';
2
- import { Context, Options, Segment } from '../context';
3
- import { input } from '../../combinator/data/parser';
4
- import { segment } from '../segment';
5
- import { block } from '../block';
1
+ import { ParserSettings, Progress } from '../..';
2
+ import { Context, Options, Segment } from '../parser/context';
3
+ import { input } from '../combinator/data/parser';
4
+ import { segment } from '../parser/segment';
5
+ import { block } from '../parser/block';
6
6
  import { headers } from './header';
7
7
  import { figure } from '../processor/figure';
8
8
  import { note } from '../processor/note';
@@ -1,6 +1,6 @@
1
1
  import { body } from './body';
2
2
 
3
- describe('Unit: parser/api/body', () => {
3
+ describe('Unit: api/body', () => {
4
4
  describe('body', () => {
5
5
  it('basic', () => {
6
6
  assert.deepStrictEqual(body(''), '');
@@ -1,4 +1,4 @@
1
- import { Caches } from '../../..';
1
+ import { Caches } from '../..';
2
2
  import { TClock } from 'spica/tclock';
3
3
  import { TLRU } from 'spica/tlru';
4
4
 
@@ -1,6 +1,6 @@
1
1
  import { headers } from './header';
2
2
 
3
- describe('Unit: parser/api/header', () => {
3
+ describe('Unit: api/header', () => {
4
4
  describe('headers', () => {
5
5
  it('basic', () => {
6
6
  assert.deepStrictEqual(headers(''), []);
@@ -1,5 +1,5 @@
1
- import { Context } from '../context';
2
- import { header as h } from '../header';
1
+ import { Context } from '../parser/context';
2
+ import { header as h } from '../parser/header';
3
3
 
4
4
  export function header(source: string): string {
5
5
  const [, pos = 0] = parse(source);
@@ -1,6 +1,6 @@
1
1
  import { normalize, escape } from './normalize';
2
2
 
3
- describe('Unit: parser/normalize', () => {
3
+ describe('Unit: normalize', () => {
4
4
  describe('normalize', () => {
5
5
  it('controls', () => {
6
6
  assert(normalize('\r') === '\n');
@@ -1,9 +1,9 @@
1
1
  import { parse } from './parse';
2
- import { Context } from '../context';
2
+ import { Context } from '../parser/context';
3
3
  import { html } from 'typed-dom/dom';
4
- import { normalize } from '../../debug.test';
4
+ import { normalize } from '../debug.test';
5
5
 
6
- describe('Unit: parser/api/parse', () => {
6
+ describe('Unit: api/parse', () => {
7
7
  describe('parse', () => {
8
8
  it('huge input', () => {
9
9
  assert.deepStrictEqual(
@@ -1,8 +1,8 @@
1
- import { ParserOptions } from '../../..';
2
- import { input } from '../../combinator/data/parser';
3
- import { Context, Options, Segment } from '../context';
4
- import { segment } from '../segment';
5
- import { block } from '../block';
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
6
  import { headers } from './header';
7
7
  import { figure } from '../processor/figure';
8
8
  import { note } from '../processor/note';
@@ -1,5 +1,5 @@
1
1
  import { Parser, List, Node, Context, failsafe } from '../../data/parser';
2
- import { consume } from '../../../combinator';
2
+ import { spend } from '../../../combinator';
3
3
  import { firstline, isEmptyline } from '../constraint/line';
4
4
  import { push } from 'spica/array';
5
5
 
@@ -13,7 +13,7 @@ export function fence<C extends Context, D extends Parser<unknown, C>[]>(opener:
13
13
  const matches = opener.exec(source);
14
14
  if (!matches) return;
15
15
  assert(matches[0] === firstline(source, position));
16
- consume(matches[0].length, context);
16
+ spend(context, matches[0].length);
17
17
  const delim = matches[1];
18
18
  assert(delim && delim === delim.trim());
19
19
  if (matches[0].includes(delim, delim.length)) return;
@@ -1,5 +1,5 @@
1
1
  import { Parser } from '../../data/parser';
2
- import { consume } from '../../../combinator';
2
+ import { spend } from '../../../combinator';
3
3
 
4
4
  export function match<P extends Parser>(pattern: RegExp, f: (matched: RegExpMatchArray) => P): P;
5
5
  export function match<N>(pattern: RegExp, f: (matched: RegExpMatchArray) => Parser<N>): Parser<N> {
@@ -15,7 +15,7 @@ export function match<N>(pattern: RegExp, f: (matched: RegExpMatchArray) => Pars
15
15
  const params = pattern.exec(source);
16
16
  if (!params) return;
17
17
  assert(source.startsWith(params[0], position));
18
- count && consume(params[0].length, context);
18
+ count && spend(context, params[0].length);
19
19
  const result = f(params)(input);
20
20
  context.position += result
21
21
  ? context.position === position
@@ -1,5 +1,5 @@
1
1
  import { Parser, Input, List, Node, Context } from './parser';
2
- import { consume } from './parser/context';
2
+ import { spend } from './parser/context';
3
3
 
4
4
  interface Delimiter {
5
5
  readonly memory: Delimiter[];
@@ -199,7 +199,7 @@ export function matcher(pattern: string | RegExp, advance: boolean, after?: Pars
199
199
  pos = position;
200
200
  if (index === -1) return;
201
201
  const src = source.slice(position, index);
202
- count && !hit && consume(src.length, context);
202
+ count && !hit && spend(context, src.length);
203
203
  if (advance) {
204
204
  context.position = index;
205
205
  }
@@ -250,7 +250,7 @@ export function tester(pattern: string | RegExp, advance: boolean, after?: Parse
250
250
  pos = position;
251
251
  if (index === -1) return;
252
252
  const len = index - position;
253
- count && !hit && consume(len, context);
253
+ count && !hit && spend(context, len);
254
254
  if (advance) {
255
255
  context.position = index;
256
256
  }
@@ -1,4 +1,4 @@
1
- import { Parser, Context } from './parser';
1
+ import { Parser, Context } from '../parser';
2
2
 
3
3
  export class List<N extends List.Node = List.Node, C extends Context = Context, D extends Parser<unknown, C>[] = any> {
4
4
  constructor(nodes?: ArrayLike<N>) {
@@ -134,8 +134,8 @@ export class List<N extends List.Node = List.Node, C extends Context = Context,
134
134
  }
135
135
  }
136
136
  export namespace List {
137
- export class Node {
138
- public next?: this = undefined;
139
- public prev?: this = undefined;
137
+ export interface Node {
138
+ next?: this;
139
+ prev?: this;
140
140
  }
141
141
  }
@@ -6,61 +6,35 @@ export function creation(cost: number, parser: Parser): Parser {
6
6
  assert(cost >= 0);
7
7
  return input => {
8
8
  const context = input;
9
- const resources = context.resources ?? { clock: cost || 1, recursions: [1] };
10
- const { recursions } = resources;
11
- assert(recursions.length > 0);
12
9
  const result = parser(input);
13
10
  if (result === undefined) return;
14
- consume(cost, context);
11
+ spend(context, cost);
15
12
  return result;
16
13
  };
17
14
  }
18
- export function consume(cost: number, context: Context): void {
19
- const { resources } = context;
20
- if (!resources) return;
15
+ export function spend(context: Context, cost: number): void {
16
+ const resources = context.resources ?? { clock: cost || 1, recursions: [1] };
21
17
  if (resources.clock < cost) throw new Error('Too many creations');
22
18
  resources.clock -= cost;
23
19
  }
24
20
 
25
- export function recursion<P extends Parser>(recursion: number, parser: P): P;
26
- export function recursion(recursion: number, parser: Parser): Parser {
27
- assert(recursion >= 0);
21
+ export function recursion<P extends Parser>(index: number, parser: P): P;
22
+ export function recursion(index: number, parser: Parser): Parser {
23
+ assert(index >= 0);
28
24
  return input => {
29
25
  const context = input;
30
26
  const resources = context.resources ?? { clock: 1, recursions: [1] };
31
27
  const { recursions } = resources;
32
- assert(recursions.length > 0);
33
- const rec = min(recursion, recursions.length - 1);
34
- if (rec >= 0 && recursions[rec] < 1) throw new Error('Too much recursion');
35
- rec >= 0 && --recursions[rec];
28
+ recur(recursions, index, 1);
36
29
  const result = parser(input);
37
- rec >= 0 && ++recursions[rec];
30
+ recur(recursions, index, -1);
38
31
  return result;
39
32
  };
40
33
  }
41
-
42
- export function recursions<P extends Parser>(recursions: readonly number[], parser: P): P;
43
- export function recursions(rs: readonly number[], parser: Parser): Parser {
44
- assert(rs.every(r => r >= 0));
45
- return input => {
46
- const context = input;
47
- const resources = context.resources ?? { clock: 1, recursions: [4] };
48
- const { recursions } = resources;
49
- assert(recursions.length > 0);
50
- for (const recursion of rs) {
51
- const rec = min(recursion, recursions.length - 1);
52
- if (rec === -1) continue;
53
- if (recursions[rec] < 1) throw new Error('Too much recursion');
54
- --recursions[rec];
55
- }
56
- const result = parser(input);
57
- for (const recursion of rs) {
58
- const rec = min(recursion, recursions.length - 1);
59
- if (rec === -1) continue;
60
- ++recursions[rec];
61
- }
62
- return result;
63
- };
34
+ export function recur(recursions: number[], index: number, size: number, force: boolean = false): void {
35
+ index = min(index, recursions.length && recursions.length - 1);
36
+ if (recursions[index] < size - +force) throw new Error('Too much recursion');
37
+ recursions[index] -= size;
64
38
  }
65
39
 
66
40
  export function precedence<P extends Parser>(precedence: number, parser: P): P;
@@ -1,7 +1,7 @@
1
1
  import { Parser, List, Node, Context } from '../parser';
2
2
 
3
- export function inits<P extends Parser>(parsers: Parser.SubParsers<P>): Parser.SubNode<P> extends Parser.Node<P> ? P : Parser<Parser.SubNode<P>, Parser.Context<P>, Parser.SubParsers<P>>;
4
- export function inits<N, D extends Parser<N>[]>(parsers: D): Parser<N, Context, D> {
3
+ export function inits<P extends Parser>(parsers: Parser.SubParsers<P>, delimitation?: boolean): Parser.SubNode<P> extends Parser.Node<P> ? P : Parser<Parser.SubNode<P>, Parser.Context<P>, Parser.SubParsers<P>>;
4
+ export function inits<N, D extends Parser<N>[]>(parsers: D, delimitation = false): Parser<N, Context, D> {
5
5
  assert(parsers.every(f => f));
6
6
  if (parsers.length === 1) return parsers[0];
7
7
  return input => {
@@ -10,7 +10,7 @@ export function inits<N, D extends Parser<N>[]>(parsers: D): Parser<N, Context,
10
10
  let nodes: List<Node<N>> | undefined;
11
11
  for (let len = parsers.length, i = 0; i < len; ++i) {
12
12
  if (context.position === source.length) break;
13
- if (context.delimiters.test(input)) break;
13
+ if (delimitation && context.delimiters.test(input)) break;
14
14
  const result = parsers[i](input);
15
15
  if (result === undefined) break;
16
16
  nodes = nodes?.import(result) ?? result;
@@ -1,7 +1,7 @@
1
1
  import { Parser, List, Node, Context, failsafe } from '../parser';
2
2
 
3
- export function sequence<P extends Parser>(parsers: Parser.SubParsers<P>): Parser.SubNode<P> extends Parser.Node<P> ? P : Parser<Parser.SubNode<P>, Parser.Context<P>, Parser.SubParsers<P>>;
4
- export function sequence<N, D extends Parser<N>[]>(parsers: D): Parser<N, Context, D> {
3
+ export function sequence<P extends Parser>(parsers: Parser.SubParsers<P>, delimitation?: boolean): Parser.SubNode<P> extends Parser.Node<P> ? P : Parser<Parser.SubNode<P>, Parser.Context<P>, Parser.SubParsers<P>>;
4
+ export function sequence<N, D extends Parser<N>[]>(parsers: D, delimitation = false): Parser<N, Context, D> {
5
5
  assert(parsers.every(f => f));
6
6
  if (parsers.length === 1) return parsers[0];
7
7
  return failsafe(input => {
@@ -10,7 +10,7 @@ export function sequence<N, D extends Parser<N>[]>(parsers: D): Parser<N, Contex
10
10
  let nodes: List<Node<N>> | undefined;
11
11
  for (let len = parsers.length, i = 0; i < len; ++i) {
12
12
  if (context.position === source.length) return;
13
- if (context.delimiters.test(input)) return;
13
+ if (delimitation && context.delimiters.test(input)) return;
14
14
  const result = parsers[i](input);
15
15
  if (result === undefined) return;
16
16
  nodes = nodes?.import(result) ?? result;
@@ -38,7 +38,6 @@ export function some<N>(parser: Parser<N>, delimiter?: number | string | RegExp
38
38
  return input => {
39
39
  const context = input;
40
40
  const { source, position } = context;
41
- //assert(context.backtracks ??= {});
42
41
  let nodes: List<Node<N>> | undefined;
43
42
  delims && context.delimiters.push(delims);
44
43
  // whileは数倍遅い
@@ -2,12 +2,12 @@ import { Parser, Context } from '../parser';
2
2
  import { union } from './union';
3
3
  import { inits } from './inits';
4
4
 
5
- export function subsequence<P extends Parser>(parsers: Parser.SubParsers<P>): Parser.SubNode<P> extends Parser.Node<P> ? P : Parser<Parser.SubNode<P>, Parser.Context<P>, Parser.SubParsers<P>>;
6
- export function subsequence<N, D extends Parser<N>[]>(parsers: D): Parser<N, Context, D> {
5
+ export function subsequence<P extends Parser>(parsers: Parser.SubParsers<P>, delimitation?: boolean): Parser.SubNode<P> extends Parser.Node<P> ? P : Parser<Parser.SubNode<P>, Parser.Context<P>, Parser.SubParsers<P>>;
6
+ export function subsequence<N, D extends Parser<N>[]>(parsers: D, delimitation = false): Parser<N, Context, D> {
7
7
  assert(parsers.every(f => f));
8
8
  return union(
9
9
  parsers.map((_, i) =>
10
10
  i + 1 < parsers.length
11
- ? inits([parsers[i], subsequence(parsers.slice(i + 1))])
11
+ ? inits([parsers[i], subsequence(parsers.slice(i + 1), delimitation)], delimitation)
12
12
  : parsers[i]) as D);
13
13
  }
@@ -2,7 +2,7 @@ import { Parser, Context } from '../parser';
2
2
  import { union } from './union';
3
3
  import { sequence } from './sequence';
4
4
 
5
- export function tails<P extends Parser>(parsers: Parser.SubParsers<P>): Parser.SubNode<P> extends Parser.Node<P> ? P : Parser<Parser.SubNode<P>, Parser.Context<P>, Parser.SubParsers<P>>;
6
- export function tails<N, D extends Parser<N>[]>(parsers: D): Parser<N, Context, D> {
7
- return union(parsers.map((_, i) => sequence(parsers.slice(i))) as D);
5
+ export function tails<P extends Parser>(parsers: Parser.SubParsers<P>, delimitation?: boolean): Parser.SubNode<P> extends Parser.Node<P> ? P : Parser<Parser.SubNode<P>, Parser.Context<P>, Parser.SubParsers<P>>;
6
+ export function tails<N, D extends Parser<N>[]>(parsers: D, delimitation?: boolean): Parser<N, Context, D> {
7
+ return union(parsers.map((_, i) => sequence(parsers.slice(i), delimitation)) as D);
8
8
  }
@@ -1,4 +1,4 @@
1
- import { List } from './node';
1
+ import { List } from './list/list';
2
2
  import { Delimiters } from './delimiter';
3
3
 
4
4
  export type Parser<N = unknown, C extends Context = Context, D extends Parser<unknown, C>[] = any>
@@ -1,11 +1,11 @@
1
1
  import { BlockquoteParser } from '../block';
2
2
  import { Recursion } from '../context';
3
3
  import { List, Node } from '../../combinator/data/parser';
4
- import { union, some, consume, recursion, block, validate, rewrite, open, convert, lazy, fmap } from '../../combinator';
4
+ import { union, some, spend, recursion, block, validate, rewrite, open, convert, lazy, fmap } from '../../combinator';
5
5
  import { autolink } from '../autolink';
6
6
  import { contentline } from '../source';
7
7
  import { unwrap, randomID } from '../util';
8
- import { parse } from '../api/parse';
8
+ import { parse } from '../../api/parse';
9
9
  import { html, defrag } from 'typed-dom/dom';
10
10
 
11
11
  export const segment: BlockquoteParser.SegmentParser = block(union([
@@ -40,7 +40,7 @@ const markdown: BlockquoteParser.MarkdownParser = lazy(() => fmap(
40
40
  rewrite(
41
41
  some(contentline, opener),
42
42
  convert(unindent, context => {
43
- consume(10, context);
43
+ spend(context, 10);
44
44
  const { source } = context;
45
45
  const references = html('ol', { class: 'references' });
46
46
  const document = parse(source, {
@@ -4,7 +4,7 @@ import { List, Node } from '../../../combinator/data/parser';
4
4
  import { recursion, block, fence, fmap } from '../../../combinator';
5
5
  import { identity } from '../../inline/extension/indexee';
6
6
  import { unwrap, invalid, randomID } from '../../util';
7
- import { parse } from '../../api/parse';
7
+ import { parse } from '../../../api/parse';
8
8
  import { html } from 'typed-dom/dom';
9
9
 
10
10
  export const aside: ExtensionParser.AsideParser = block(recursion(Recursion.block, fmap(
@@ -4,7 +4,7 @@ import { List, Node, subinput } from '../../../combinator/data/parser';
4
4
  import { recursion, block, fence, fmap } from '../../../combinator';
5
5
  import { mathblock } from '../mathblock';
6
6
  import { unwrap, invalid, randomID } from '../../util';
7
- import { parse } from '../../api/parse';
7
+ import { parse } from '../../../api/parse';
8
8
  import { html } from 'typed-dom/dom';
9
9
 
10
10
  export const example: ExtensionParser.ExampleParser = block(recursion(Recursion.block, fmap(
@@ -99,7 +99,7 @@ export const block: BlockParser = error(union([
99
99
  case '(':
100
100
  return olist(input);
101
101
  default:
102
- if ('0' <= char && char <= '9') return olist(input);
102
+ if (char <= '9' && '0' <= char) return olist(input);
103
103
  }
104
104
  },
105
105
  paragraph
@@ -20,7 +20,7 @@ export class Context extends Ctx {
20
20
  id,
21
21
  caches,
22
22
  } = options;
23
- this.resources ??= {
23
+ this.resources = options.resources ?? {
24
24
  // バックトラックのせいで文字数制限を受けないようにする。
25
25
  clock: MAX_SEGMENT_SIZE * (5 + 1),
26
26
  recursions: [
@@ -42,7 +42,7 @@ export class Context extends Ctx {
42
42
  this.id = id;
43
43
  this.caches = caches;
44
44
  }
45
- public override readonly resources?: {
45
+ public override readonly resources: {
46
46
  clock: number;
47
47
  recursions: number[];
48
48
  };
@@ -50,7 +50,7 @@ export class Context extends Ctx {
50
50
  public local: boolean;
51
51
  public sequential: boolean;
52
52
  public buffer: List<Node<(string | HTMLElement)>>;
53
- public recursion = new RecursionCounter('annotation', 2);
53
+ public recursion = new RecursionCounter(2);
54
54
  public readonly header: boolean;
55
55
  public readonly host?: URL;
56
56
  public readonly url?: URL;
@@ -65,7 +65,6 @@ export type Options = Partial<Context>;
65
65
 
66
66
  class RecursionCounter {
67
67
  constructor(
68
- private readonly syntax: string,
69
68
  private readonly limit: number,
70
69
  ) {
71
70
  }
@@ -75,7 +74,7 @@ class RecursionCounter {
75
74
  const { stack } = this
76
75
  for (; this.index > 0 && stack[this.index - 1] <= depth; --this.index);
77
76
  // 内側から数えるので無効化処理できずエラーを投げるしかない。
78
- if (this.index === this.limit) throw new Error(`Too much ${this.syntax} recursion`);
77
+ if (this.index === this.limit) throw new Error(`Too much recursion`);
79
78
  stack[this.index] = depth;
80
79
  ++this.index;
81
80
  }
@@ -25,7 +25,7 @@ import { html, defrag } from 'typed-dom/dom';
25
25
  // 常に非常に非効率な処理を行い常時低速化するより三重以上の注釈を禁止して効率性を維持するのが妥当である。
26
26
  const MAX_DEPTH = 20;
27
27
  export const annotation: AnnotationParser = lazy(() => constraint(State.annotation,
28
- repeat('(', beforeNonblank, ')', [Recursion.bracket], precedence(1, surround(
28
+ repeat('(', beforeNonblank, ')', Recursion.bracket, precedence(1, surround(
29
29
  '',
30
30
  some(union([inline]), ')', [[')', 1]]),
31
31
  ')',
@@ -9,7 +9,7 @@ import { unwrap } from '../util';
9
9
  import { html, defrag } from 'typed-dom/dom';
10
10
 
11
11
  export const deletion: DeletionParser = lazy(() =>
12
- repeat('~~', '', '~~', [Recursion.inline], precedence(0, surround(
12
+ repeat('~~', '', '~~', Recursion.inline, precedence(0, surround(
13
13
  '',
14
14
  some(union([
15
15
  some(inline, blankWith('\n', '~~')),
@@ -24,7 +24,7 @@ const subemphasis: Parser.IntermediateParser<EmphasisParser> = lazy(() => some(u
24
24
  // 可能な限り早く閉じるよう解析しなければならない。
25
25
  // このため終端記号の後ろを見て終端を中止し同じ構文を再帰的に適用してはならない。
26
26
  export const emstrong: EmStrongParser = lazy(() =>
27
- repeat('***', beforeNonblank, '***', [Recursion.inline], precedence(0, surround(
27
+ repeat('***', beforeNonblank, '***', Recursion.inline, precedence(0, surround(
28
28
  '',
29
29
  some(union([some(inline, '*', afterNonblank)])),
30
30
  strs('*', 1, 3),
@@ -9,7 +9,7 @@ import { unwrap } from '../util';
9
9
  import { html, defrag } from 'typed-dom/dom';
10
10
 
11
11
  export const insertion: InsertionParser = lazy(() =>
12
- repeat('++', '', '++', [Recursion.inline], precedence(0, surround(
12
+ repeat('++', '', '++', Recursion.inline, precedence(0, surround(
13
13
  '',
14
14
  some(union([
15
15
  some(inline, blankWith('\n', '++')),
@@ -12,7 +12,7 @@ import { html, defrag } from 'typed-dom/dom';
12
12
  // 斜体は単語に使うとかえって見づらく読み飛ばしやすくなるため使わないべきであり
13
13
  // ある程度の長さのある文に使うのが望ましい。
14
14
  export const italic: ItalicParser = lazy(() =>
15
- repeat('///', beforeNonblank, '///', [Recursion.inline], precedence(0, surround(
15
+ repeat('///', beforeNonblank, '///', Recursion.inline, precedence(0, surround(
16
16
  '',
17
17
  some(union([inline]), '///', afterNonblank),
18
18
  '///',
@@ -1,7 +1,7 @@
1
1
  import { LinkParser } from '../inline';
2
2
  import { Context, State, Backtrack, Command } from '../context';
3
3
  import { List, Node } from '../../combinator/data/parser';
4
- import { union, inits, sequence, subsequence, some, consume, precedence, state, constraint, surround, open, setBacktrack, dup, lazy, fmap, bind } from '../../combinator';
4
+ import { union, inits, sequence, subsequence, some, spend, precedence, state, constraint, surround, open, setBacktrack, dup, lazy, fmap, bind } from '../../combinator';
5
5
  import { inline, media, shortmedia } from '../inline';
6
6
  import { attributes } from './html';
7
7
  import { str } from '../source';
@@ -35,7 +35,7 @@ export const textlink: LinkParser.TextLinkParser = lazy(() => bind(
35
35
  // 自己再帰的にパースしてもオプションの不要なパースによる計算量の増加により相殺される。
36
36
  dup(surround(
37
37
  /{(?![{}])/y,
38
- precedence(9, inits([uri, some(option)])),
38
+ inits([uri, some(option)]),
39
39
  / ?}/y,
40
40
  false, [],
41
41
  undefined,
@@ -83,7 +83,7 @@ export const medialink: LinkParser.MediaLinkParser = lazy(() => constraint(State
83
83
  ']')),
84
84
  dup(surround(
85
85
  /{(?![{}])/y,
86
- precedence(9, inits([uri, some(option)])),
86
+ inits([uri, some(option)]),
87
87
  / ?}/y)),
88
88
  ]),
89
89
  ([{ value: content }, { value: params }], context) =>
@@ -109,7 +109,7 @@ export function parse(
109
109
  const INSECURE_URI = params.shift()!.value;
110
110
  assert(INSECURE_URI === INSECURE_URI.trim());
111
111
  assert(!INSECURE_URI.match(/\s/));
112
- consume(10, context);
112
+ spend(context, 10);
113
113
  let uri: ReadonlyURL | undefined;
114
114
  try{
115
115
  uri = new ReadonlyURL(
@@ -10,7 +10,7 @@ import { unwrap } from '../util';
10
10
  import { html, define, defrag } from 'typed-dom/dom';
11
11
 
12
12
  export const mark: MarkParser = lazy(() =>
13
- repeat('==', beforeNonblank, '==', [Recursion.inline], precedence(0, surround(
13
+ repeat('==', beforeNonblank, '==', Recursion.inline, precedence(0, surround(
14
14
  '',
15
15
  state(State.mark, some(union([inline]), '==', afterNonblank)),
16
16
  '==',
@@ -2,7 +2,7 @@ import { MediaParser } from '../inline';
2
2
  import { State, Recursion, Backtrack, Command } from '../context';
3
3
  import { List, Node } from '../../combinator/data/parser';
4
4
  import { Flag } from '../node';
5
- import { union, inits, tails, some, consume, recursion, precedence, constraint, surround, open, setBacktrack, dup, lazy, fmap, bind } from '../../combinator';
5
+ import { union, inits, tails, some, spend, recursion, precedence, constraint, surround, open, setBacktrack, dup, lazy, fmap, bind } from '../../combinator';
6
6
  import { uri, option as linkoption, resolve, decode, parse } from './link';
7
7
  import { attributes } from './html';
8
8
  import { unsafehtmlentity } from './htmlentity';
@@ -41,7 +41,7 @@ export const media: MediaParser = lazy(() => constraint(State.media, open(
41
41
  })),
42
42
  dup(surround(
43
43
  /{(?![{}])/y,
44
- precedence(9, inits([uri, some(option)])),
44
+ inits([uri, some(option)]),
45
45
  / ?}/y,
46
46
  false, [],
47
47
  undefined,
@@ -59,7 +59,7 @@ export const media: MediaParser = lazy(() => constraint(State.media, open(
59
59
  text = text.trim();
60
60
  if (text === '' || text[0] !== tmp[0]) return;
61
61
  }
62
- consume(100, context);
62
+ spend(context, 100);
63
63
  if (params.last!.value === Command.Cancel) {
64
64
  params.pop();
65
65
  return new List([
@@ -135,5 +135,5 @@ export { shortmedia, lineshortmedia } from './inline/shortmedia';
135
135
 
136
136
  function isAlphabet(char: string): boolean {
137
137
  assert(char.length === 1);
138
- return 'a' <= char && char <= 'z';
138
+ return char <= 'z' && 'a' <= char;
139
139
  }
@@ -1,4 +1,4 @@
1
- import { invisibleBlankHTMLEntityNames } from './api/normalize';
1
+ import { invisibleBlankHTMLEntityNames } from '../api/normalize';
2
2
 
3
3
  export const enum Flag {
4
4
  none,