securemark 0.294.11 → 0.295.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (37) hide show
  1. package/CHANGELOG.md +8 -0
  2. package/design.md +5 -5
  3. package/dist/index.js +119 -119
  4. package/package.json +1 -1
  5. package/src/combinator/control/constraint/block.ts +1 -1
  6. package/src/combinator/control/constraint/contract.ts +5 -6
  7. package/src/combinator/control/constraint/line.ts +1 -2
  8. package/src/combinator/control/manipulation/convert.ts +1 -1
  9. package/src/combinator/control/manipulation/fallback.ts +1 -1
  10. package/src/combinator/control/manipulation/indent.ts +2 -2
  11. package/src/combinator/control/manipulation/lazy.ts +1 -1
  12. package/src/combinator/control/manipulation/match.ts +2 -5
  13. package/src/combinator/control/manipulation/recovery.ts +1 -1
  14. package/src/combinator/control/manipulation/reverse.ts +1 -1
  15. package/src/combinator/control/manipulation/scope.ts +3 -7
  16. package/src/combinator/control/manipulation/surround.ts +45 -56
  17. package/src/combinator/control/monad/bind.ts +7 -12
  18. package/src/combinator/control/monad/fmap.ts +4 -4
  19. package/src/combinator/data/parser/context.ts +12 -12
  20. package/src/combinator/data/parser/inits.ts +3 -6
  21. package/src/combinator/data/parser/sequence.ts +3 -6
  22. package/src/combinator/data/parser/some.ts +2 -2
  23. package/src/combinator/data/parser/subsequence.ts +1 -1
  24. package/src/combinator/data/parser/tails.ts +1 -1
  25. package/src/combinator/data/parser/union.ts +1 -1
  26. package/src/combinator/data/parser.ts +10 -9
  27. package/src/parser/context.ts +6 -6
  28. package/src/parser/inline/annotation.ts +1 -1
  29. package/src/parser/inline/autolink/account.ts +1 -1
  30. package/src/parser/inline/autolink/url.ts +4 -5
  31. package/src/parser/inline/bracket.ts +27 -18
  32. package/src/parser/inline/extension/indexee.ts +1 -1
  33. package/src/parser/inline/link.ts +3 -3
  34. package/src/parser/inline/media.ts +1 -1
  35. package/src/parser/inline/reference.ts +9 -9
  36. package/src/parser/inline/ruby.ts +2 -2
  37. package/src/parser/visibility.ts +2 -2
@@ -1,6 +1,6 @@
1
1
  import { Parser, Ctx, Node, Context, SubParsers, SubNode } from '../parser';
2
2
 
3
- export function union<P extends Parser<unknown>>(parsers: SubParsers<P>): SubNode<P> extends Node<P> ? P : Parser<SubNode<P>, Context<P>, SubParsers<P>>;
3
+ export function union<P extends Parser>(parsers: SubParsers<P>): SubNode<P> extends Node<P> ? P : Parser<SubNode<P>, Context<P>, SubParsers<P>>;
4
4
  export function union<N, D extends Parser<N>[]>(parsers: D): Parser<N, Ctx, D> {
5
5
  assert(parsers.every(f => f));
6
6
  switch (parsers.length) {
@@ -1,7 +1,7 @@
1
1
  import { List } from './data';
2
2
  import { Delimiters } from './parser/context/delimiter';
3
3
 
4
- export type Parser<N, C extends Ctx = Ctx, D extends Parser<unknown, C>[] = any>
4
+ export type Parser<N = unknown, C extends Ctx = Ctx, D extends Parser<unknown, C>[] = any>
5
5
  = (input: Input<C>) => Result<N, C, D>;
6
6
  export interface Input<C extends Ctx = Ctx> {
7
7
  readonly context: C;
@@ -35,6 +35,7 @@ export interface CtxOptions {
35
35
  // 最大セグメントサイズ10KB内で探索コストが平均実行性能を圧迫するほど大きくなるとは考えにくいが
36
36
  // 探索コストを減らすにはバックトラック位置数が規定数を超えた場合一定区間ごとに探索木を分割する方法が考えられる。
37
37
  // 10KBの入力すべてを保持する探索木を1024文字ごとに分割するために必要なテーブルサイズは64bit*98=784byteとなる。
38
+ // 128文字ごとでもテーブルサイズは入力全体の1%未満であるため無視でき16文字ごとでさえ6.25%に過ぎない。
38
39
  // 探索木のポインタによるオーバーヘッドを考慮すれば一定サイズ以上ではテーブルのほうが効率的となる。
39
40
  // 区間別テーブルは固定サイズであるためプールして再使用できる。
40
41
  // 従って分割時のデータ構造は区間ごとに探索木を動的に生成しデータ数に応じてテーブルに移行するのが最も効率的である。
@@ -64,13 +65,13 @@ export interface CtxOptions {
64
65
  linebreak?: number;
65
66
  range?: number;
66
67
  }
67
- export type Node<P extends Parser<unknown>> = P extends Parser<infer N> ? N : never;
68
- export type SubParsers<P extends Parser<unknown>> = P extends Parser<unknown, Ctx, infer D> ? D : never;
69
- export type Context<P extends Parser<unknown>> = P extends Parser<unknown, infer C> ? C : never;
70
- export type SubNode<P extends Parser<unknown>> = ExtractSubNode<SubParsers<P>>;
71
- export type IntermediateParser<P extends Parser<unknown>> = Parser<SubNode<P>, Context<P>, SubParsers<P>>;
72
- type ExtractSubNode<D extends Parser<unknown>[]> = ExtractSubParser<D> extends infer N ? N extends Parser<infer U> ? U : never : never;
73
- type ExtractSubParser<D extends Parser<unknown>[]> = D extends (infer P)[] ? P extends Parser<unknown> ? P : never : never;
68
+ export type Node<P extends Parser> = P extends Parser<infer N> ? N : never;
69
+ export type SubParsers<P extends Parser> = P extends Parser<unknown, Ctx, infer D> ? D : never;
70
+ export type Context<P extends Parser> = P extends Parser<unknown, infer C> ? C : never;
71
+ export type SubNode<P extends Parser> = ExtractSubNode<SubParsers<P>>;
72
+ export type IntermediateParser<P extends Parser> = Parser<SubNode<P>, Context<P>, SubParsers<P>>;
73
+ type ExtractSubNode<D extends Parser[]> = ExtractSubParser<D> extends infer N ? N extends Parser<infer U> ? U : never : never;
74
+ type ExtractSubParser<D extends Parser[]> = D extends (infer P)[] ? P extends Parser ? P : never : never;
74
75
 
75
76
  export function input<C extends CtxOptions>(source: string, context: C): Input<C & Ctx> {
76
77
  // @ts-expect-error
@@ -95,7 +96,7 @@ export function subinput<C extends Ctx>(source: string, context: C): Input<C> {
95
96
  };
96
97
  }
97
98
 
98
- export function failsafe<P extends Parser<unknown>>(parser: P): P;
99
+ export function failsafe<P extends Parser>(parser: P): P;
99
100
  export function failsafe<N>(parser: Parser<N>): Parser<N> {
100
101
  assert(parser);
101
102
  return input => {
@@ -29,14 +29,14 @@ export const enum Recursion {
29
29
 
30
30
  export const enum Backtrack {
31
31
  // 構文
32
- doublebracket = 1 << 6,
33
- link = 1 << 5,
34
- ruby = 1 << 4,
32
+ doublebracket = 1 << 7,
33
+ link = 1 << 6,
34
+ ruby = 1 << 5,
35
35
  // 特殊構造
36
- escapable = 1 << 3,
37
- unescapable = 1 << 2,
36
+ escapable = 1 << 4,
37
+ unescapable = 1 << 3,
38
38
  // 共通構造
39
- common = 0 << 2,
39
+ common = 1 << 2,
40
40
  }
41
41
 
42
42
  export const enum Command {
@@ -13,7 +13,7 @@ export const annotation: AnnotationParser = lazy(() => constraint(State.annotati
13
13
  trimBlankStart(some(union([inline]), ')', [[')', 1]])))),
14
14
  '))',
15
15
  false,
16
- [1 | Backtrack.common, 3 | Backtrack.doublebracket],
16
+ [2, 1 | Backtrack.common, 3 | Backtrack.doublebracket],
17
17
  ([, ns], context) =>
18
18
  context.linebreak === 0
19
19
  ? new List([new Data(html('sup', { class: 'annotation' }, [html('span', defrag(unwrap(trimBlankNodeEnd(ns))))]))])
@@ -47,7 +47,7 @@ export const account: AutolinkParser.AccountParser = lazy(() => constraint(State
47
47
  ([[{ value: host }, { value: account }]], context) => {
48
48
  if (context.source[context.position] === '#') {
49
49
  assert(context.source[context.position - context.range!] === '@');
50
- return void setBacktrack(context, [2 | Backtrack.unescapable], context.position - context.range!);
50
+ return void setBacktrack(context, 2 | Backtrack.unescapable, context.position - context.range!);
51
51
  }
52
52
  return new List([
53
53
  new Data(define(
@@ -27,19 +27,18 @@ export const lineurl: AutolinkParser.UrlParser.LineUrlParser = lazy(() => focus(
27
27
  str('!'),
28
28
  union([
29
29
  constraint(State.autolink, state(State.autolink, ({ context }) => {
30
- const { source, position, range = 0 } = context;
31
- context.position -= position > 0 && source[position - 1] === '!' ? 1 : 0;
32
- context.position += range;
30
+ const { source, position } = context;
31
+ context.position -= source[0] === '!' ? 1 : 0;
33
32
  return new List([
34
33
  new Data(parse(
35
34
  new List(),
36
- new List([new Data(source.slice(position, context.position))]),
35
+ new List([new Data(source.slice(position))]),
37
36
  context))
38
37
  ]);
39
38
  })),
40
39
  str(/[^:]+/y),
41
40
  ]),
42
- ]), false));
41
+ ])));
43
42
 
44
43
  const bracket: AutolinkParser.UrlParser.BracketParser = lazy(() => union([
45
44
  surround(str('('), recursion(Recursion.terminal, some(union([bracket, unescsource]), ')')), str(')'),
@@ -38,22 +38,32 @@ const p1 = lazy(() => surround(
38
38
  str('('),
39
39
  precedence(1, recursion(Recursion.bracket, some(inline, ')', [[')', 1]]))),
40
40
  str(')'),
41
- true,
42
- [2 | Backtrack.common],
43
- ([as, bs = new List(), cs], { source, position, range = 0 }) => {
41
+ true, [],
42
+ ([as, bs = new List(), cs], context) => {
43
+ const { source, position, range = 0 } = context;
44
+ const head = position - range;
45
+ if (context.linebreak !== 0 || source[position - 2] !== ')' || source[head + 1] !== '(') {
46
+ setBacktrack(context, 2 | Backtrack.doublebracket, head);
47
+ }
44
48
  const str = source.slice(position - range + 1, position - 1);
45
49
  return indexA.test(str)
46
50
  ? new List([new Data(as.head!.value), new Data(str), new Data(cs.head!.value)])
47
51
  : new List([new Data(html('span', { class: 'paren' }, defrag(unwrap(as.import(bs as List<Data<string>>).import(cs)))))]);
48
52
  },
49
- ([as, bs = new List()]) => as.import(bs as List<Data<string>>)));
53
+ ([as, bs = new List()], context) => {
54
+ const { source, position, range = 0 } = context;
55
+ const head = position - range;
56
+ if (context.linebreak !== 0 || source[head + 1] !== '(') {
57
+ setBacktrack(context, 2 | Backtrack.doublebracket, head);
58
+ }
59
+ return as.import(bs as List<Data<string>>);
60
+ }));
50
61
 
51
62
  const p2 = lazy(() => surround(
52
63
  str('('),
53
64
  precedence(1, recursion(Recursion.bracket, some(inline, ')', [[')', 1]]))),
54
65
  str(')'),
55
- true,
56
- [2 | Backtrack.common],
66
+ true, [],
57
67
  ([as, bs = [], cs], { source, position, range = 0 }) => {
58
68
  const str = source.slice(position - range + 1, position - 1);
59
69
  return indexF.test(str)
@@ -72,20 +82,23 @@ const s1 = lazy(() => surround(
72
82
  if (context.state! & State.link) {
73
83
  const { source, position, range = 0 } = context;
74
84
  const head = position - range;
85
+ if (context.linebreak !== 0 || source[position - 2] !== ']' || source[head + 1] !== '[') {
86
+ setBacktrack(context, 2 | Backtrack.doublebracket, head);
87
+ }
75
88
  if (context.linebreak !== 0) {
76
- setBacktrack(context, [2 | Backtrack.link, 2 | Backtrack.ruby], head);
89
+ setBacktrack(context, 2 | Backtrack.doublebracket | Backtrack.link | Backtrack.ruby, head);
77
90
  }
78
91
  else if (source[position] !== '{') {
79
- setBacktrack(context, [2 | Backtrack.link], head);
92
+ setBacktrack(context, 2 | Backtrack.link, head);
80
93
  }
81
94
  else {
82
95
  context.state! ^= State.link;
83
- const result = !isBacktrack(context, [1 | Backtrack.link])
96
+ const result = !isBacktrack(context, 1 | Backtrack.link)
84
97
  ? textlink({ context })
85
98
  : undefined;
86
99
  context.position = position;
87
100
  if (!result) {
88
- setBacktrack(context, [2 | Backtrack.link], head);
101
+ setBacktrack(context, 2 | Backtrack.link, head);
89
102
  }
90
103
  context.state! ^= State.link;
91
104
  context.range = range;
@@ -99,8 +112,7 @@ const s2 = lazy(() => surround(
99
112
  str('['),
100
113
  precedence(1, recursion(Recursion.bracket, some(inline, ']', [[']', 1]]))),
101
114
  str(']'),
102
- true,
103
- [2 | Backtrack.common],
115
+ true, [],
104
116
  undefined,
105
117
  ([as, bs = new List()]) => as.import(bs as List<Data<string>>)));
106
118
 
@@ -108,8 +120,7 @@ const c1 = lazy(() => surround(
108
120
  str('{'),
109
121
  precedence(1, recursion(Recursion.bracket, some(inline, '}', [['}', 1]]))),
110
122
  str('}'),
111
- true,
112
- [2 | Backtrack.common],
123
+ true, [],
113
124
  undefined,
114
125
  ([as, bs = new List()]) => as.import(bs as List<Data<string>>)));
115
126
 
@@ -117,8 +128,7 @@ const c2 = lazy(() => surround(
117
128
  str('{'),
118
129
  precedence(1, recursion(Recursion.bracket, some(inline, '}', [['}', 1]]))),
119
130
  str('}'),
120
- true,
121
- [2 | Backtrack.common],
131
+ true, [],
122
132
  undefined,
123
133
  ([as, bs = new List()]) => as.import(bs as List<Data<string>>)));
124
134
 
@@ -127,7 +137,6 @@ const d1 = lazy(() => surround(
127
137
  // 改行の優先度を構文ごとに変える場合シグネチャの優先度対応が必要
128
138
  precedence(2, recursion(Recursion.bracket, some(inline, /["\n]/y, [['"', 2], ['\n', 3]]))),
129
139
  str('"'),
130
- true,
131
- [2 | Backtrack.common],
140
+ true, [],
132
141
  undefined,
133
142
  ([as, bs = new List()]) => as.import(bs as List<Data<string>>)));
@@ -3,7 +3,7 @@ import { Parser, List, Data } from '../../../combinator/data/parser';
3
3
  import { fmap } from '../../../combinator';
4
4
  import { define } from 'typed-dom/dom';
5
5
 
6
- export function indexee<P extends Parser<unknown, MarkdownParser.Context>>(parser: P): P;
6
+ export function indexee<P extends Parser<HTMLElement, MarkdownParser.Context>>(parser: P): P;
7
7
  export function indexee(parser: Parser<HTMLElement, MarkdownParser.Context>): Parser<HTMLElement> {
8
8
  return fmap(parser, (ns, { id }) =>
9
9
  ns.length === 1
@@ -24,11 +24,11 @@ export const textlink: LinkParser.TextLinkParser = lazy(() => constraint(State.l
24
24
  trimBlankStart(some(union([inline]), ']', [[']', 1]])),
25
25
  ']',
26
26
  true,
27
- [3 | Backtrack.common, 3 | Backtrack.link, 2 | Backtrack.ruby],
27
+ [3 | Backtrack.common | Backtrack.link, 2 | Backtrack.ruby],
28
28
  ([, ns = new List()], context) => {
29
29
  if (context.linebreak !== 0) {
30
30
  const head = context.position - context.range!;
31
- return void setBacktrack(context, [2 | Backtrack.link, 2 | Backtrack.ruby], head);
31
+ return void setBacktrack(context, 2 | Backtrack.link | Backtrack.ruby, head);
32
32
  }
33
33
  return ns.push(new Data(Command.Separator)) && ns;
34
34
  })),
@@ -48,7 +48,7 @@ export const textlink: LinkParser.TextLinkParser = lazy(() => constraint(State.l
48
48
  content.pop();
49
49
  if (params === undefined) {
50
50
  const head = context.position - context.range!;
51
- return void setBacktrack(context, [2 | Backtrack.link], head);
51
+ return void setBacktrack(context, 2 | Backtrack.link, head);
52
52
  }
53
53
  }
54
54
  else {
@@ -34,7 +34,7 @@ export const media: MediaParser = lazy(() => constraint(State.media, open(
34
34
  ([, ns = new List()], context) => {
35
35
  if (context.linebreak !== 0) {
36
36
  const head = context.position - context.range!;
37
- return void setBacktrack(context, [2 | Backtrack.link, 2 | Backtrack.ruby], head);
37
+ return void setBacktrack(context, 2 | Backtrack.link | Backtrack.ruby, head);
38
38
  }
39
39
  return ns;
40
40
  })),
@@ -18,7 +18,7 @@ export const reference: ReferenceParser = lazy(() => constraint(State.reference,
18
18
  ]))),
19
19
  ']]',
20
20
  false,
21
- [1 | Backtrack.common, 3 | Backtrack.doublebracket],
21
+ [2, 1 | Backtrack.common, 3 | Backtrack.doublebracket],
22
22
  ([, ns], context) => {
23
23
  const { position, range = 0, linebreak = 0 } = context;
24
24
  if (linebreak === 0) {
@@ -26,7 +26,7 @@ export const reference: ReferenceParser = lazy(() => constraint(State.reference,
26
26
  }
27
27
  else {
28
28
  const head = position - range;
29
- setBacktrack(context, [2 | Backtrack.link], head, 2);
29
+ setBacktrack(context, 2 | Backtrack.link, head, 2);
30
30
  }
31
31
  },
32
32
  ([as, bs], context) => {
@@ -34,10 +34,10 @@ export const reference: ReferenceParser = lazy(() => constraint(State.reference,
34
34
  const { source, position, range = 0, linebreak = 0, state = 0 } = context;
35
35
  const head = position - range;
36
36
  if (source[position] !== ']') {
37
- setBacktrack(context, [2 | Backtrack.common], head, 2);
37
+ setBacktrack(context, 2 | Backtrack.common, head, 2);
38
38
  }
39
39
  else if (linebreak !== 0) {
40
- setBacktrack(context, [2 | Backtrack.link, 2 | Backtrack.ruby], head, 2);
40
+ setBacktrack(context, 2 | Backtrack.link | Backtrack.ruby, head, 2);
41
41
  }
42
42
  else {
43
43
  assert(source[position] === ']');
@@ -47,22 +47,22 @@ export const reference: ReferenceParser = lazy(() => constraint(State.reference,
47
47
  context.position += 1;
48
48
  let result: ReturnType<typeof textlink>;
49
49
  if (source[context.position] !== '{') {
50
- setBacktrack(context, [2 | Backtrack.link], head + 1);
50
+ setBacktrack(context, 2 | Backtrack.link, head + 1);
51
51
  result = new List();
52
52
  }
53
53
  else {
54
- result = !isBacktrack(context, [1 | Backtrack.link])
54
+ result = !isBacktrack(context, 1 | Backtrack.link)
55
55
  ? textlink({ context })
56
56
  : undefined;
57
57
  context.range = range;
58
58
  if (!result) {
59
- setBacktrack(context, [2 | Backtrack.link], head + 1);
59
+ setBacktrack(context, 2 | Backtrack.link, head + 1);
60
60
  result = new List();
61
61
  }
62
62
  }
63
63
  assert(result);
64
64
  if (context.position === source.length) {
65
- setBacktrack(context, [2 | Backtrack.link], head);
65
+ setBacktrack(context, 2 | Backtrack.link, head);
66
66
  }
67
67
  else {
68
68
  assert(state ^ State.link);
@@ -74,7 +74,7 @@ export const reference: ReferenceParser = lazy(() => constraint(State.reference,
74
74
  ([, cs = new List(), ds]) =>
75
75
  cs.import(ds),
76
76
  ([, cs = new List()]) => {
77
- setBacktrack(context, [2 | Backtrack.link], head);
77
+ setBacktrack(context, 2 | Backtrack.link, head);
78
78
  return cs;
79
79
  })
80
80
  ({ context });
@@ -21,12 +21,12 @@ export const ruby: RubyParser = lazy(() => bind(
21
21
  dup(surround(
22
22
  '(', text, ')',
23
23
  false,
24
- [1 | Backtrack.common, 3 | Backtrack.ruby])),
24
+ [3 | Backtrack.ruby])),
25
25
  ]),
26
26
  ([{ value: texts }, { value: rubies = undefined } = {}], context) => {
27
27
  if (rubies === undefined) {
28
28
  const head = context.position - context.range!;
29
- return void setBacktrack(context, [2 | Backtrack.ruby], head);
29
+ return void setBacktrack(context, 2 | Backtrack.ruby, head);
30
30
  }
31
31
  switch (true) {
32
32
  case texts.length >= rubies.length:
@@ -50,7 +50,7 @@ export function blankWith(starts: '' | '\n', delimiter?: string | RegExp): RegEx
50
50
  // return isTightStart({ source: source.replace(blank.start, ''), context }, except);
51
51
  //}, ({ source }, except = '') => `${source}${Command.Separator}${except}`);
52
52
 
53
- export function tightStart<P extends Parser<unknown>>(parser: P, except?: string): P;
53
+ export function tightStart<P extends Parser>(parser: P, except?: string): P;
54
54
  export function tightStart<N>(parser: Parser<N>, except?: string): Parser<N> {
55
55
  return input =>
56
56
  isTightStart(input, except)
@@ -140,7 +140,7 @@ export function trimBlank<P extends Parser<HTMLElement | string>>(parser: P): P;
140
140
  export function trimBlank<N extends HTMLElement | string>(parser: Parser<N>): Parser<N> {
141
141
  return trimBlankStart(trimBlankEnd(parser));
142
142
  }
143
- export function trimBlankStart<P extends Parser<unknown>>(parser: P): P;
143
+ export function trimBlankStart<P extends Parser>(parser: P): P;
144
144
  export function trimBlankStart<N>(parser: Parser<N>): Parser<N> {
145
145
  return failsafe(input => {
146
146
  const { context } = input;