securemark 0.258.2 → 0.258.3

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 (53) hide show
  1. package/CHANGELOG.md +4 -0
  2. package/dist/index.js +137 -143
  3. package/package.json +1 -1
  4. package/src/combinator/data/parser/context/memo.ts +6 -3
  5. package/src/combinator/data/parser/context.test.ts +3 -3
  6. package/src/combinator/data/parser/context.ts +15 -21
  7. package/src/combinator/data/parser/some.ts +4 -2
  8. package/src/combinator/data/parser.ts +1 -1
  9. package/src/parser/api/bind.ts +1 -1
  10. package/src/parser/api/parse.test.ts +4 -4
  11. package/src/parser/api/parse.ts +1 -1
  12. package/src/parser/block/blockquote.ts +4 -4
  13. package/src/parser/block/dlist.ts +3 -3
  14. package/src/parser/block/extension/table.ts +4 -4
  15. package/src/parser/block/ilist.ts +2 -2
  16. package/src/parser/block/olist.ts +2 -2
  17. package/src/parser/block/reply/cite.ts +2 -2
  18. package/src/parser/block/reply/quote.ts +2 -2
  19. package/src/parser/block/sidefence.ts +2 -2
  20. package/src/parser/block/table.ts +5 -5
  21. package/src/parser/block/ulist.ts +2 -2
  22. package/src/parser/block.ts +2 -2
  23. package/src/parser/context.ts +1 -1
  24. package/src/parser/inline/annotation.ts +6 -5
  25. package/src/parser/inline/autolink/email.ts +2 -2
  26. package/src/parser/inline/autolink/url.ts +2 -2
  27. package/src/parser/inline/autolink.ts +2 -2
  28. package/src/parser/inline/bracket.ts +8 -8
  29. package/src/parser/inline/code.ts +2 -2
  30. package/src/parser/inline/comment.ts +2 -2
  31. package/src/parser/inline/deletion.ts +5 -4
  32. package/src/parser/inline/emphasis.ts +5 -4
  33. package/src/parser/inline/emstrong.ts +5 -4
  34. package/src/parser/inline/extension/index.ts +8 -7
  35. package/src/parser/inline/extension/indexer.ts +2 -2
  36. package/src/parser/inline/extension/label.ts +2 -2
  37. package/src/parser/inline/extension/placeholder.ts +5 -4
  38. package/src/parser/inline/html.ts +2 -2
  39. package/src/parser/inline/htmlentity.ts +2 -2
  40. package/src/parser/inline/insertion.ts +5 -4
  41. package/src/parser/inline/link.ts +10 -8
  42. package/src/parser/inline/mark.ts +5 -4
  43. package/src/parser/inline/math.ts +3 -3
  44. package/src/parser/inline/media.ts +7 -6
  45. package/src/parser/inline/reference.ts +7 -6
  46. package/src/parser/inline/ruby.ts +4 -4
  47. package/src/parser/inline/strong.ts +5 -4
  48. package/src/parser/inline/template.ts +6 -6
  49. package/src/parser/inline.test.ts +2 -0
  50. package/src/parser/source/escapable.ts +2 -2
  51. package/src/parser/source/str.ts +5 -5
  52. package/src/parser/source/text.ts +2 -2
  53. package/src/parser/source/unescapable.ts +2 -2
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "securemark",
3
- "version": "0.258.2",
3
+ "version": "0.258.3",
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,5 +1,5 @@
1
1
  export class Memo {
2
- private memory: Record<string, readonly [any[], number] | readonly []>[/* pos */] = [];
2
+ private readonly memory: Record<string, readonly [any[], number] | readonly []>[/* pos */] = [];
3
3
  public get length(): number {
4
4
  return this.memory.length;
5
5
  }
@@ -10,7 +10,10 @@ export class Memo {
10
10
  state: number,
11
11
  ): readonly [any[], number] | readonly [] | undefined {
12
12
  //console.log('get', position + this.offset, syntax, state, this.memory[position + this.offset - 1]?.[`${syntax}:${state}`]);;
13
- return this.memory[position + this.offset - 1]?.[`${syntax}:${state}`];
13
+ const cache = this.memory[position + this.offset - 1]?.[`${syntax}:${state}`];
14
+ return cache?.length === 2
15
+ ? [cache[0].slice(), cache[1]]
16
+ : cache;
14
17
  }
15
18
  public set(
16
19
  position: number,
@@ -24,7 +27,7 @@ export class Memo {
24
27
  record[`${syntax}:${state}`] = nodes
25
28
  ? [nodes.slice(), offset]
26
29
  : [];
27
- //console.log('set', position + this.offset, syntax, state);
30
+ //console.log('set', position + this.offset, syntax, state, record[`${syntax}:${state}`]);
28
31
  }
29
32
  public clear(position: number): void {
30
33
  const memory = this.memory;
@@ -1,7 +1,7 @@
1
1
  import { Parser, Ctx } from '../parser';
2
2
  import { some } from './some';
3
3
  import { reset, context } from './context';
4
- import { creator } from './context';
4
+ import { creation } from './context';
5
5
 
6
6
  describe('Unit: combinator/data/parser/context', () => {
7
7
  interface Context extends Ctx {
@@ -9,7 +9,7 @@ describe('Unit: combinator/data/parser/context', () => {
9
9
  }
10
10
 
11
11
  describe('reset', () => {
12
- const parser: Parser<number> = some(creator(
12
+ const parser: Parser<number> = some(creation(
13
13
  (s, context) => [[context.resources?.budget ?? NaN], s.slice(1)]));
14
14
 
15
15
  it('root', () => {
@@ -36,7 +36,7 @@ describe('Unit: combinator/data/parser/context', () => {
36
36
  });
37
37
 
38
38
  describe('context', () => {
39
- const parser: Parser<boolean, Context> = some(creator(
39
+ const parser: Parser<boolean, Context> = some(creation(
40
40
  (s, context) => [[context.status!], s.slice(1)]));
41
41
 
42
42
  it('', () => {
@@ -56,17 +56,12 @@ 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, parser: P): P;
60
59
  export function syntax<P extends Parser<unknown>>(syntax: number, precedence: number, cost: number, parser: P): P;
61
- export function syntax<T>(syntax: number, precedence: number, cost: number | Parser<T>, parser?: Parser<T>): Parser<T> {
62
- if (typeof cost === 'function') {
63
- parser = cost;
64
- cost = 1;
65
- }
60
+ export function syntax<T>(syntax: number, precedence: number, cost: number, parser?: Parser<T>): Parser<T> {
66
61
  return (source, context) => {
67
62
  if (source === '') return;
68
- context.backtrackable ??= ~0;
69
- const state = context.state ??= 0;
63
+ const memo = context.memo ??= new Memo();
64
+ context.memorable ??= ~0;
70
65
  const p = context.precedence;
71
66
  context.precedence = precedence;
72
67
  const { resources = { budget: 1, recursion: 1 } } = context;
@@ -74,7 +69,8 @@ export function syntax<T>(syntax: number, precedence: number, cost: number | Par
74
69
  if (resources.recursion <= 0) throw new Error('Too much recursion');
75
70
  --resources.recursion;
76
71
  const pos = source.length;
77
- const cache = syntax && context.memo?.get(pos, syntax, state);
72
+ const state = context.state ?? 0;
73
+ const cache = syntax && memo.get(pos, syntax, state);
78
74
  const result: Result<T> = cache
79
75
  ? cache.length === 0
80
76
  ? undefined
@@ -82,18 +78,16 @@ export function syntax<T>(syntax: number, precedence: number, cost: number | Par
82
78
  : parser!(source, context);
83
79
  ++resources.recursion;
84
80
  if (result && !cache) {
85
- assert(cost = cost as number);
86
81
  resources.budget -= cost;
87
82
  }
88
83
  if (syntax) {
89
- if (state & context.backtrackable) {
90
- context.memo ??= new Memo();
91
- cache ?? context.memo.set(pos, syntax, state, eval(result), source.length - exec(result, '').length);
92
- assert.deepStrictEqual(cache && cache, cache && context.memo.get(pos, syntax, state));
84
+ if (state & context.memorable!) {
85
+ cache ?? memo.set(pos, syntax, state, eval(result), source.length - exec(result, '').length);
86
+ assert.deepStrictEqual(cache && cache, cache && memo.get(pos, syntax, state));
93
87
  }
94
- else if (result && context.memo?.length! >= pos) {
95
- assert(!(state & context.backtrackable));
96
- context.memo!.clear(pos);
88
+ else if (result && memo.length! >= pos) {
89
+ assert(!(state & context.memorable!));
90
+ memo.clear(pos);
97
91
  }
98
92
  }
99
93
  context.precedence = p;
@@ -101,10 +95,10 @@ export function syntax<T>(syntax: number, precedence: number, cost: number | Par
101
95
  };
102
96
  }
103
97
 
104
- export function creator<P extends Parser<unknown>>(parser: P): P;
105
- export function creator<P extends Parser<unknown>>(cost: number, parser: P): P;
106
- export function creator(cost: number | Parser<unknown>, parser?: Parser<unknown>): Parser<unknown> {
107
- if (typeof cost === 'function') return creator(1, cost);
98
+ export function creation<P extends Parser<unknown>>(parser: P): P;
99
+ export function creation<P extends Parser<unknown>>(cost: number, parser: P): P;
100
+ export function creation(cost: number | Parser<unknown>, parser?: Parser<unknown>): Parser<unknown> {
101
+ if (typeof cost === 'function') return creation(1, cost);
108
102
  assert(cost >= 0);
109
103
  return (source, context) => {
110
104
  const { resources = { budget: 1, recursion: 1 } } = context;
@@ -1,7 +1,7 @@
1
1
  import { undefined } from 'spica/global';
2
2
  import { Parser, eval, exec, check } from '../parser';
3
3
  import { Delimiters } from './context/delimiter';
4
- import { push } from 'spica/array';
4
+ import { unshift, push } from 'spica/array';
5
5
 
6
6
  type DelimiterOption = readonly [delimiter: string | RegExp, precedence: number];
7
7
 
@@ -32,7 +32,9 @@ export function some<T>(parser: Parser<T>, end?: string | RegExp | number, delim
32
32
  assert.doesNotThrow(() => limit < 0 && check(rest, result));
33
33
  if (!result) break;
34
34
  nodes = nodes
35
- ? push(nodes, eval(result))
35
+ ? nodes.length < eval(result).length
36
+ ? unshift(nodes, eval(result))
37
+ : push(nodes, eval(result))
36
38
  : eval(result);
37
39
  rest = exec(result);
38
40
  if (limit >= 0 && source.length - rest.length > limit) break;
@@ -15,7 +15,7 @@ export interface Ctx {
15
15
  precedence?: number;
16
16
  delimiters?: Delimiters;
17
17
  state?: number;
18
- backtrackable?: number;
18
+ memorable?: number;
19
19
  memo?: Memo;
20
20
  }
21
21
  export type Tree<P extends Parser<unknown>> = P extends Parser<infer T> ? T : never;
@@ -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
- backtrackable,
27
+ memorable: backtrackable,
28
28
  };
29
29
  if (context.host?.origin === 'null') throw new Error(`Invalid host: ${context.host.href}`);
30
30
  assert(!settings.id);
@@ -247,19 +247,19 @@ describe('Unit: parser/api/parse', () => {
247
247
  [...parse('('.repeat(20)).children].map(el => el.outerHTML),
248
248
  [`<p>${'('.repeat(20)}</p>`]);
249
249
  assert.deepStrictEqual(
250
- [...parse('('.repeat(21)).children].map(el => el.outerHTML.replace(/:\w+/, ':rnd')),
250
+ [...parse('('.repeat(22)).children].map(el => el.outerHTML.replace(/:\w+/, ':rnd')),
251
251
  [
252
252
  '<h1 id="error:rnd" class="error">Error: Too much recursion</h1>',
253
- `<pre class="error" translate="no">${'('.repeat(21)}</pre>`,
253
+ `<pre class="error" translate="no">${'('.repeat(22)}</pre>`,
254
254
  ]);
255
255
  assert.deepStrictEqual(
256
256
  [...parse('['.repeat(20)).children].map(el => el.outerHTML),
257
257
  [`<p>${'['.repeat(20)}</p>`]);
258
258
  assert.deepStrictEqual(
259
- [...parse('['.repeat(21)).children].map(el => el.outerHTML.replace(/:\w+/, ':rnd')),
259
+ [...parse('['.repeat(22)).children].map(el => el.outerHTML.replace(/:\w+/, ':rnd')),
260
260
  [
261
261
  '<h1 id="error:rnd" class="error">Error: Too much recursion</h1>',
262
- `<pre class="error" translate="no">${'['.repeat(21)}</pre>`,
262
+ `<pre class="error" translate="no">${'['.repeat(22)}</pre>`,
263
263
  ]);
264
264
  assert.deepStrictEqual(
265
265
  [...parse('['.repeat(17) + '\na').children].map(el => el.outerHTML),
@@ -30,7 +30,7 @@ export function parse(source: string, opts: Options = {}, context?: MarkdownPars
30
30
  ...context?.resources && {
31
31
  resources: context.resources,
32
32
  },
33
- backtrackable,
33
+ memorable: backtrackable,
34
34
  };
35
35
  if (context.host?.origin === 'null') throw new Error(`Invalid host: ${context.host.href}`);
36
36
  const node = frag();
@@ -1,5 +1,5 @@
1
1
  import { BlockquoteParser } from '../block';
2
- import { union, some, creator, block, validate, rewrite, open, convert, lazy, fmap } from '../../combinator';
2
+ import { union, some, creation, block, validate, rewrite, open, convert, lazy, fmap } from '../../combinator';
3
3
  import { autolink } from '../autolink';
4
4
  import { contentline } from '../source';
5
5
  import { parse } from '../api/parse';
@@ -19,7 +19,7 @@ const indent = block(open(opener, some(contentline, /^>(?:$|\s)/)), false);
19
19
  const unindent = (source: string) => source.replace(/(^|\n)>(?:[^\S\n]|(?=>*(?:$|\s)))|\n$/g, '$1');
20
20
 
21
21
  const source: BlockquoteParser.SourceParser = lazy(() => fmap(
22
- some(creator(union([
22
+ some(creation(union([
23
23
  rewrite(
24
24
  indent,
25
25
  convert(unindent, source)),
@@ -30,11 +30,11 @@ const source: BlockquoteParser.SourceParser = lazy(() => fmap(
30
30
  ns => [html('blockquote', ns)]));
31
31
 
32
32
  const markdown: BlockquoteParser.MarkdownParser = lazy(() => fmap(
33
- some(creator(union([
33
+ some(creation(union([
34
34
  rewrite(
35
35
  indent,
36
36
  convert(unindent, markdown)),
37
- creator(99,
37
+ creation(99,
38
38
  rewrite(
39
39
  some(contentline, opener),
40
40
  convert(unindent, (source, context) => {
@@ -1,5 +1,5 @@
1
1
  import { DListParser } from '../block';
2
- import { union, inits, some, creator, state, block, line, validate, rewrite, open, trimEnd, lazy, fmap } from '../../combinator';
2
+ import { union, inits, some, creation, state, block, line, validate, rewrite, open, trimEnd, lazy, fmap } from '../../combinator';
3
3
  import { inline, indexee, indexer } from '../inline';
4
4
  import { anyline } from '../source';
5
5
  import { State } from '../context';
@@ -17,13 +17,13 @@ export const dlist: DListParser = lazy(() => block(localize(fmap(validate(
17
17
  ]))),
18
18
  es => [html('dl', fillTrailingDescription(es))]))));
19
19
 
20
- const term: DListParser.TermParser = creator(line(indexee(fmap(open(
20
+ const term: DListParser.TermParser = creation(line(indexee(fmap(open(
21
21
  /^~[^\S\n]+(?=\S)/,
22
22
  visualize(trimBlank(some(union([indexer, inline])))),
23
23
  true),
24
24
  ns => [html('dt', defrag(ns))]))));
25
25
 
26
- const desc: DListParser.DescriptionParser = creator(block(fmap(open(
26
+ const desc: DListParser.DescriptionParser = creation(block(fmap(open(
27
27
  /^:[^\S\n]+(?=\S)|/,
28
28
  rewrite(
29
29
  some(anyline, /^[~:][^\S\n]+\S/),
@@ -2,7 +2,7 @@ import { undefined, BigInt, Array } from 'spica/global';
2
2
  import { max, min, isArray } from 'spica/alias';
3
3
  import { ExtensionParser } from '../../block';
4
4
  import { Tree, eval } from '../../../combinator/data/parser';
5
- import { union, subsequence, inits, some, creator, block, line, validate, fence, rewrite, open, clear, convert, trim, dup, lazy, fmap } from '../../../combinator';
5
+ import { union, subsequence, inits, some, creation, block, line, validate, fence, rewrite, open, clear, convert, trim, dup, lazy, fmap } from '../../../combinator';
6
6
  import { inline } from '../../inline';
7
7
  import { str, anyline, emptyline, contentline } from '../../source';
8
8
  import { localize } from '../../locale';
@@ -79,7 +79,7 @@ const align: AlignParser = line(fmap(
79
79
 
80
80
  const delimiter = /^[-=<>]+(?:\/[-=^v]*)?(?=[^\S\n]*\n)|^[#:](?:(?!:\D|0)\d*:(?!0)\d*)?!*(?=\s)/;
81
81
 
82
- const head: CellParser.HeadParser = creator(block(fmap(open(
82
+ const head: CellParser.HeadParser = creation(block(fmap(open(
83
83
  str(/^#(?:(?!:\D|0)\d*:(?!0)\d*)?!*(?=\s)/),
84
84
  rewrite(
85
85
  inits([
@@ -91,7 +91,7 @@ const head: CellParser.HeadParser = creator(block(fmap(open(
91
91
  ns => [html('th', attributes(ns.shift()! as string), defrag(ns))]),
92
92
  false));
93
93
 
94
- const data: CellParser.DataParser = creator(block(fmap(open(
94
+ const data: CellParser.DataParser = creation(block(fmap(open(
95
95
  str(/^:(?:(?!:\D|0)\d*:(?!0)\d*)?!*(?=\s)/),
96
96
  rewrite(
97
97
  inits([
@@ -103,7 +103,7 @@ const data: CellParser.DataParser = creator(block(fmap(open(
103
103
  ns => [html('td', attributes(ns.shift()! as string), defrag(ns))]),
104
104
  false));
105
105
 
106
- const dataline: CellParser.DatalineParser = creator(line(
106
+ const dataline: CellParser.DatalineParser = creation(line(
107
107
  rewrite(
108
108
  contentline,
109
109
  union([
@@ -1,5 +1,5 @@
1
1
  import { IListParser } from '../block';
2
- import { union, inits, some, creator, state, block, line, validate, indent, open, fallback, lazy, fmap } from '../../combinator';
2
+ import { union, inits, some, creation, state, block, line, validate, indent, open, fallback, lazy, fmap } from '../../combinator';
3
3
  import { ulist_, fillFirstLine } from './ulist';
4
4
  import { olist_, invalid } from './olist';
5
5
  import { inline } from '../inline';
@@ -13,7 +13,7 @@ export const ilist: IListParser = lazy(() => block(validate(
13
13
 
14
14
  export const ilist_: IListParser = lazy(() => block(fmap(validate(
15
15
  /^[-+*](?:$|\s)/,
16
- some(creator(union([
16
+ some(creation(union([
17
17
  fmap(fallback(
18
18
  inits([
19
19
  line(open(/^[-+*](?:$|\s)/, some(inline), true)),
@@ -1,6 +1,6 @@
1
1
  import { undefined } from 'spica/global';
2
2
  import { OListParser } from '../block';
3
- import { union, inits, subsequence, some, creator, state, block, line, validate, indent, focus, rewrite, open, match, fallback, lazy, fmap } from '../../combinator';
3
+ import { union, inits, subsequence, some, creation, state, block, line, validate, indent, focus, rewrite, open, match, fallback, lazy, fmap } from '../../combinator';
4
4
  import { checkbox, ulist_, fillFirstLine } from './ulist';
5
5
  import { ilist_ } from './ilist';
6
6
  import { inline, indexee, indexer } from '../inline';
@@ -36,7 +36,7 @@ export const olist_: OListParser = lazy(() => block(union([
36
36
  ])));
37
37
 
38
38
  const list = (type: string, form: string): OListParser.ListParser => fmap(
39
- some(creator(union([
39
+ some(creation(union([
40
40
  indexee(fmap(fallback(
41
41
  inits([
42
42
  line(open(heads[form], subsequence([checkbox, trimBlank(some(union([indexer, inline])))]), true)),
@@ -1,10 +1,10 @@
1
1
  import { ReplyParser } from '../../block';
2
- import { union, tails, creator, line, validate, focus, reverse, fmap } from '../../../combinator';
2
+ import { union, tails, creation, line, validate, focus, reverse, fmap } from '../../../combinator';
3
3
  import { anchor } from '../../inline/autolink/anchor';
4
4
  import { str } from '../../source';
5
5
  import { html, define, defrag } from 'typed-dom/dom';
6
6
 
7
- export const cite: ReplyParser.CiteParser = creator(line(fmap(validate(
7
+ export const cite: ReplyParser.CiteParser = creation(line(fmap(validate(
8
8
  '>>',
9
9
  reverse(tails([
10
10
  str(/^>*(?=>>[^>\s]+[^\S\n]*(?:$|\n))/),
@@ -1,6 +1,6 @@
1
1
  import { ReplyParser } from '../../block';
2
2
  import { eval } from '../../../combinator/data/parser';
3
- import { union, some, creator, block, line, validate, rewrite, lazy, fmap } from '../../../combinator';
3
+ import { union, some, creation, block, line, validate, rewrite, lazy, fmap } from '../../../combinator';
4
4
  import { math } from '../../inline/math';
5
5
  import { str, anyline } from '../../source';
6
6
  import { autolink } from '../../autolink';
@@ -8,7 +8,7 @@ import { html, defrag } from 'typed-dom/dom';
8
8
 
9
9
  export const syntax = /^>+(?=[^\S\n])|^>(?=[^\s>])|^>+(?=[^\s>])(?![0-9a-z]+(?:-[0-9a-z]+)*(?![0-9A-Za-z@#:]))/;
10
10
 
11
- export const quote: ReplyParser.QuoteParser = lazy(() => creator(block(fmap(validate(
11
+ export const quote: ReplyParser.QuoteParser = lazy(() => creation(block(fmap(validate(
12
12
  '>',
13
13
  union([
14
14
  rewrite(
@@ -1,5 +1,5 @@
1
1
  import { SidefenceParser } from '../block';
2
- import { union, some, creator, block, focus, rewrite, convert, lazy, fmap } from '../../combinator';
2
+ import { union, some, creation, block, focus, rewrite, convert, lazy, fmap } from '../../combinator';
3
3
  import { autolink } from '../autolink';
4
4
  import { contentline } from '../source';
5
5
  import { html, define, defrag } from 'typed-dom/dom';
@@ -20,7 +20,7 @@ const opener = /^(?=\|\|+(?:$|\s))/;
20
20
  const unindent = (source: string) => source.replace(/(^|\n)\|(?:[^\S\n]|(?=\|*(?:$|\s)))|\n$/g, '$1');
21
21
 
22
22
  const source: SidefenceParser.SourceParser = lazy(() => fmap(
23
- some(creator(union([
23
+ some(creation(union([
24
24
  focus(
25
25
  /^(?:\|\|+(?:[^\S\n][^\n]*)?(?:$|\n))+/,
26
26
  convert(unindent, source)),
@@ -1,5 +1,5 @@
1
1
  import { TableParser } from '../block';
2
- import { union, sequence, some, creator, block, line, validate, focus, rewrite, surround, open, fallback, lazy, fmap } from '../../combinator';
2
+ import { union, sequence, some, creation, block, line, validate, focus, rewrite, surround, open, fallback, lazy, fmap } from '../../combinator';
3
3
  import { inline } from '../inline';
4
4
  import { contentline } from '../source';
5
5
  import { trimNode } from '../visibility';
@@ -25,7 +25,7 @@ export const table: TableParser = lazy(() => block(fmap(validate(
25
25
  ]),
26
26
  ])));
27
27
 
28
- const row = <P extends CellParser | AlignParser>(parser: P, optional: boolean): RowParser<P> => creator(fallback(fmap(
28
+ const row = <P extends CellParser | AlignParser>(parser: P, optional: boolean): RowParser<P> => creation(fallback(fmap(
29
29
  line(surround(/^(?=\|)/, some(union([parser])), /^[|\\]?\s*$/, optional)),
30
30
  es => [html('tr', es)]),
31
31
  rewrite(contentline, source => [[
@@ -37,7 +37,7 @@ const row = <P extends CellParser | AlignParser>(parser: P, optional: boolean):
37
37
  }, [html('td', source.replace('\n', ''))])
38
38
  ], ''])));
39
39
 
40
- const align: AlignParser = creator(fmap(open(
40
+ const align: AlignParser = creation(fmap(open(
41
41
  '|',
42
42
  union([
43
43
  focus(/^:-+:/, () => [['center'], '']),
@@ -52,11 +52,11 @@ const cell: CellParser = surround(
52
52
  some(union([inline]), /^\|/, [[/^[|\\]?\s*$/, 9]]),
53
53
  /^[^|]*/, true);
54
54
 
55
- const head: CellParser.HeadParser = creator(fmap(
55
+ const head: CellParser.HeadParser = creation(fmap(
56
56
  cell,
57
57
  ns => [html('th', trimNode(defrag(ns)))]));
58
58
 
59
- const data: CellParser.DataParser = creator(fmap(
59
+ const data: CellParser.DataParser = creation(fmap(
60
60
  cell,
61
61
  ns => [html('td', trimNode(defrag(ns)))]));
62
62
 
@@ -1,5 +1,5 @@
1
1
  import { UListParser } from '../block';
2
- import { union, inits, subsequence, some, creator, state, block, line, validate, indent, focus, open, fallback, lazy, fmap } from '../../combinator';
2
+ import { union, inits, subsequence, some, creation, state, block, line, validate, indent, focus, open, fallback, lazy, fmap } from '../../combinator';
3
3
  import { olist_, invalid } from './olist';
4
4
  import { ilist_ } from './ilist';
5
5
  import { inline, indexer, indexee } from '../inline';
@@ -15,7 +15,7 @@ export const ulist: UListParser = lazy(() => block(validate(
15
15
 
16
16
  export const ulist_: UListParser = lazy(() => block(fmap(validate(
17
17
  /^-(?=$|\s)/,
18
- some(creator(union([
18
+ some(creation(union([
19
19
  indexee(fmap(fallback(
20
20
  inits([
21
21
  line(open(/^-(?:$|\s)/, subsequence([checkbox, trimBlank(some(union([indexer, inline])))]), true)),
@@ -1,6 +1,6 @@
1
1
  import { undefined } from 'spica/global';
2
2
  import { MarkdownParser } from '../../markdown';
3
- import { union, reset, creator, open, fallback, recover } from '../combinator';
3
+ import { union, reset, creation, open, fallback, recover } from '../combinator';
4
4
  import { emptyline } from './source';
5
5
  import { horizontalrule } from './block/horizontalrule';
6
6
  import { heading } from './block/heading';
@@ -35,7 +35,7 @@ export import BlockquoteParser = BlockParser.BlockquoteParser;
35
35
  export import ReplyParser = BlockParser.ReplyParser;
36
36
  export import ParagraphParser = BlockParser.ParagraphParser;
37
37
 
38
- export const block: BlockParser = creator(error(
38
+ export const block: BlockParser = creation(error(
39
39
  reset({ resources: { budget: 50 * 1000, recursion: 20 } },
40
40
  union([
41
41
  emptyline,
@@ -1,4 +1,4 @@
1
- export const enum Rule {
1
+ export const enum Syntax {
2
2
  reference = 1 << 12,
3
3
  comment = 1 << 11,
4
4
  index = 1 << 10,
@@ -1,20 +1,21 @@
1
1
  import { undefined } from 'spica/global';
2
2
  import { AnnotationParser } from '../inline';
3
- import { union, some, guard, context, syntax, state, validate, surround, lazy } from '../../combinator';
3
+ import { union, some, guard, context, syntax, state, surround, lazy } from '../../combinator';
4
4
  import { inline } from '../inline';
5
5
  import { optimize } from './link';
6
- import { Rule, State } from '../context';
6
+ import { Syntax, State } from '../context';
7
7
  import { startLoose, trimNode } from '../visibility';
8
8
  import { html, defrag } from 'typed-dom/dom';
9
9
 
10
- export const annotation: AnnotationParser = lazy(() => validate('((', syntax(Rule.annotation, 6, surround(
10
+ export const annotation: AnnotationParser = lazy(() => surround(
11
11
  '((',
12
12
  guard(context => ~context.state! & State.annotation,
13
+ syntax(Syntax.annotation, 6, 1,
13
14
  state(State.annotation | State.media,
14
15
  startLoose(
15
16
  context({ delimiters: undefined },
16
- some(union([inline]), ')', [[/^\\?\n/, 9], [')', 2], ['))', 6]])), ')'))),
17
+ some(union([inline]), ')', [[/^\\?\n/, 9], [')', 2], ['))', 6]])), ')')))),
17
18
  '))',
18
19
  false,
19
20
  ([, ns], rest) => [[html('sup', { class: 'annotation' }, [html('span', trimNode(defrag(ns)))])], rest],
20
- ([, ns, rest], next) => next[0] === ')' ? undefined : optimize('((', ns, rest, next)))));
21
+ ([, ns, rest], next) => next[0] === ')' ? undefined : optimize('((', ns, rest, next)));
@@ -1,11 +1,11 @@
1
1
  import { AutolinkParser } from '../../inline';
2
- import { creator, verify, rewrite } from '../../../combinator';
2
+ import { creation, verify, rewrite } from '../../../combinator';
3
3
  import { str } from '../../source';
4
4
  import { html } from 'typed-dom/dom';
5
5
 
6
6
  // https://html.spec.whatwg.org/multipage/input.html
7
7
 
8
- export const email: AutolinkParser.EmailParser = creator(rewrite(verify(
8
+ export const email: AutolinkParser.EmailParser = creation(rewrite(verify(
9
9
  str(/^[0-9A-Za-z]+(?:[.+_-][0-9A-Za-z]+)*@[0-9A-Za-z](?:(?:[0-9A-Za-z]|-(?=\w)){0,61}[0-9A-Za-z])?(?:\.[0-9A-Za-z](?:(?:[0-9A-Za-z]|-(?=\w)){0,61}[0-9A-Za-z])?)*(?![0-9A-Za-z])/),
10
10
  ([source]) => source.indexOf('@') <= 64 && source.length <= 255),
11
11
  source => [[html('a', { class: 'email', href: `mailto:${source}` }, source)], '']));
@@ -1,5 +1,5 @@
1
1
  import { AutolinkParser } from '../../inline';
2
- import { union, some, creator, precedence, validate, focus, rewrite, convert, surround, open, lazy } from '../../../combinator';
2
+ import { union, some, creation, precedence, validate, focus, rewrite, convert, surround, open, lazy } from '../../../combinator';
3
3
  import { textlink } from '../link';
4
4
  import { unescsource } from '../../source';
5
5
 
@@ -13,7 +13,7 @@ export const url: AutolinkParser.UrlParser = lazy(() => validate(['http://', 'ht
13
13
  url => `{ ${url} }`,
14
14
  union([textlink])))));
15
15
 
16
- const bracket: AutolinkParser.UrlParser.BracketParser = lazy(() => creator(precedence(2, union([
16
+ const bracket: AutolinkParser.UrlParser.BracketParser = lazy(() => creation(precedence(2, union([
17
17
  surround('(', some(union([bracket, unescsource]), ')'), ')', true),
18
18
  surround('[', some(union([bracket, unescsource]), ']'), ']', true),
19
19
  surround('{', some(union([bracket, unescsource]), '}'), '}', true),
@@ -8,13 +8,13 @@ import { hashtag, emoji } from './autolink/hashtag';
8
8
  import { hashnum } from './autolink/hashnum';
9
9
  import { anchor } from './autolink/anchor';
10
10
  import { str } from '../source';
11
- import { Rule, State } from '../context';
11
+ import { Syntax, State } from '../context';
12
12
  import { stringify } from '../util';
13
13
 
14
14
  export const autolink: AutolinkParser = fmap(
15
15
  validate(/^(?:[@#>0-9A-Za-z]|\S#)/,
16
16
  guard(context => ~context.state! & State.autolink,
17
- syntax(Rule.autolink, 1,
17
+ syntax(Syntax.autolink, 1, 1,
18
18
  some(union([
19
19
  url,
20
20
  email,
@@ -3,29 +3,29 @@ import { BracketParser } from '../inline';
3
3
  import { union, some, syntax, surround, lazy } from '../../combinator';
4
4
  import { inline } from '../inline';
5
5
  import { str } from '../source';
6
- import { Rule } from '../context';
6
+ import { Syntax } from '../context';
7
7
  import { html, defrag } from 'typed-dom/dom';
8
8
  import { unshift, push } from 'spica/array';
9
9
 
10
10
  const index = /^[0-9A-Za-z]+(?:(?:[.-]|, )[0-9A-Za-z]+)*/;
11
11
 
12
12
  export const bracket: BracketParser = lazy(() => union([
13
- surround(str('('), syntax(Rule.none, 2, str(index)), str(')')),
14
- surround(str('('), syntax(Rule.bracket, 2, some(inline, ')', [[')', 2]])), str(')'), true,
13
+ surround(str('('), syntax(Syntax.none, 2, 1, str(index)), str(')')),
14
+ surround(str('('), syntax(Syntax.bracket, 2, 1, some(inline, ')', [[')', 2]])), str(')'), true,
15
15
  ([as, bs = [], cs], rest) => [[html('span', { class: 'paren' }, defrag(push(unshift(as, bs), cs)))], rest],
16
16
  ([as, bs = []], rest) => [unshift([''], unshift(as, bs)), rest]),
17
- surround(str('('), syntax(Rule.none, 2, str(new RegExp(index.source.replace(', ', '[,、]').replace(/[09AZaz.]|\-(?!\w)/g, c => c.trimStart() && String.fromCharCode(c.charCodeAt(0) + 0xFEE0))))), str(')')),
18
- surround(str('('), syntax(Rule.bracket, 2, some(inline, ')', [[')', 2]])), str(')'), true,
17
+ surround(str('('), syntax(Syntax.none, 2, 1, str(new RegExp(index.source.replace(', ', '[,、]').replace(/[09AZaz.]|\-(?!\w)/g, c => c.trimStart() && String.fromCharCode(c.charCodeAt(0) + 0xFEE0))))), str(')')),
18
+ surround(str('('), syntax(Syntax.bracket, 2, 1, some(inline, ')', [[')', 2]])), str(')'), true,
19
19
  ([as, bs = [], cs], rest) => [[html('span', { class: 'paren' }, defrag(push(unshift(as, bs), cs)))], rest],
20
20
  ([as, bs = []], rest) => [unshift(as, bs), rest]),
21
- surround(str('['), syntax(Rule.bracket, 2, some(inline, ']', [[']', 2]])), str(']'), true,
21
+ surround(str('['), syntax(Syntax.bracket, 2, 1, some(inline, ']', [[']', 2]])), str(']'), true,
22
22
  undefined,
23
23
  ([as, bs = []], rest) => [unshift([''], unshift(as, bs)), rest]),
24
- surround(str('{'), syntax(Rule.bracket, 2, some(inline, '}', [['}', 2]])), str('}'), true,
24
+ surround(str('{'), syntax(Syntax.bracket, 2, 1, some(inline, '}', [['}', 2]])), str('}'), true,
25
25
  undefined,
26
26
  ([as, bs = []], rest) => [unshift(as, bs), rest]),
27
27
  // Control media blinking in editing rather than control confusion of pairs of quote marks.
28
- surround(str('"'), syntax(Rule.quote, 8, some(inline, '"', [['"', 8]])), str('"'), true,
28
+ surround(str('"'), syntax(Syntax.quote, 8, 1, some(inline, '"', [['"', 8]])), str('"'), true,
29
29
  undefined,
30
30
  ([as, bs = []], rest) => [unshift(as, bs), rest]),
31
31
  ]));
@@ -1,8 +1,8 @@
1
1
  import { CodeParser } from '../inline';
2
- import { creator, validate, match } from '../../combinator';
2
+ import { creation, validate, match } from '../../combinator';
3
3
  import { html } from 'typed-dom/dom';
4
4
 
5
- export const code: CodeParser = creator(validate('`', match(
5
+ export const code: CodeParser = creation(validate('`', match(
6
6
  /^(`+)(?!`)([^\n]*?[^`\n])\1(?!`)/,
7
7
  ([whole, , body]) => rest =>
8
8
  [[html('code', { 'data-src': whole }, format(body))], rest.slice(whole.length)])));
@@ -2,12 +2,12 @@ import { CommentParser } from '../inline';
2
2
  import { union, some, syntax, validate, surround, open, close, match, lazy } from '../../combinator';
3
3
  import { inline } from '../inline';
4
4
  import { text, str } from '../source';
5
- import { Rule } from '../context';
5
+ import { Syntax } from '../context';
6
6
  import { html, defrag } from 'typed-dom/dom';
7
7
  import { memoize } from 'spica/memoize';
8
8
  import { unshift, push } from 'spica/array';
9
9
 
10
- export const comment: CommentParser = lazy(() => validate('[%', syntax(Rule.none, 4, match(
10
+ export const comment: CommentParser = lazy(() => validate('[%', syntax(Syntax.none, 4, 1, match(
11
11
  /^\[(%+)\s/,
12
12
  memoize(
13
13
  ([, fence]) =>