securemark 0.294.0 → 0.294.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 (35) hide show
  1. package/CHANGELOG.md +4 -0
  2. package/dist/index.js +164 -119
  3. package/package.json +2 -2
  4. package/src/combinator/control/constraint/contract.ts +2 -2
  5. package/src/combinator/control/constraint/line.ts +2 -2
  6. package/src/combinator/control/manipulation/indent.ts +3 -7
  7. package/src/combinator/control/manipulation/scope.ts +4 -6
  8. package/src/combinator/control/manipulation/surround.ts +5 -8
  9. package/src/combinator/control/monad/bind.ts +2 -3
  10. package/src/combinator/data/data.ts +2 -2
  11. package/src/combinator/data/parser/context.test.ts +4 -4
  12. package/src/combinator/data/parser/inits.ts +4 -6
  13. package/src/combinator/data/parser/sequence.ts +4 -6
  14. package/src/combinator/data/parser/some.ts +5 -7
  15. package/src/combinator/data/parser.ts +3 -21
  16. package/src/debug.test.ts +2 -2
  17. package/src/parser/api/bind.ts +5 -5
  18. package/src/parser/api/header.ts +2 -2
  19. package/src/parser/api/normalize.ts +2 -2
  20. package/src/parser/api/parse.ts +2 -2
  21. package/src/parser/block/codeblock.ts +2 -2
  22. package/src/parser/block/extension/example.ts +2 -2
  23. package/src/parser/block/extension/figure.ts +1 -1
  24. package/src/parser/block/extension/message.ts +2 -2
  25. package/src/parser/block/extension/table.ts +2 -2
  26. package/src/parser/block.ts +4 -0
  27. package/src/parser/inline/emstrong.ts +5 -5
  28. package/src/parser/inline/reference.ts +2 -2
  29. package/src/parser/inline/ruby.ts +4 -4
  30. package/src/parser/processor/note.ts +2 -2
  31. package/src/parser/segment.ts +4 -4
  32. package/src/parser/source/line.ts +5 -0
  33. package/src/parser/source/str.ts +1 -1
  34. package/src/parser/util.ts +5 -5
  35. package/src/parser/visibility.ts +2 -2
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "securemark",
3
- "version": "0.294.0",
3
+ "version": "0.294.1",
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",
@@ -28,7 +28,7 @@
28
28
  "LICENSE"
29
29
  ],
30
30
  "dependencies": {
31
- "spica": "0.0.807"
31
+ "spica": "0.0.809"
32
32
  },
33
33
  "devDependencies": {
34
34
  "@types/dompurify": "3.0.5",
@@ -1,4 +1,4 @@
1
- import { Parser, Input, List, Data, Ctx, Node, Context, eval, failsafe } from '../../data/parser';
1
+ import { Parser, Input, List, Data, Ctx, Node, Context, failsafe } from '../../data/parser';
2
2
  import { matcher } from '../../../combinator';
3
3
 
4
4
  //export function contract<P extends Parser<unknown>>(patterns: string | RegExp | (string | RegExp)[], parser: P, cond: (nodes: readonly Data<P>[], rest: string) => boolean): P;
@@ -37,7 +37,7 @@ export function verify<N>(parser: Parser<N>, cond: (nodes: List<Data<N>>, contex
37
37
  if (position === source.length) return;
38
38
  const result = parser(input);
39
39
  assert(context.position > position || !result);
40
- if (result && !cond(eval(result), context)) return;
40
+ if (result && !cond(result, context)) return;
41
41
  return result;
42
42
  });
43
43
  }
@@ -1,4 +1,4 @@
1
- import { Parser, input, eval, failsafe } from '../../data/parser';
1
+ import { Parser, input, failsafe } from '../../data/parser';
2
2
 
3
3
  export function line<P extends Parser<unknown>>(parser: P): P;
4
4
  export function line<N>(parser: Parser<N>): Parser<N> {
@@ -18,7 +18,7 @@ export function line<N>(parser: Parser<N>): Parser<N> {
18
18
  if (result === undefined) return;
19
19
  if (!isBlank(source.slice(context.position, position + line.length))) return;
20
20
  context.position = position + line.length;
21
- return eval(result);
21
+ return result;
22
22
  });
23
23
  }
24
24
 
@@ -1,4 +1,4 @@
1
- import { Parser, List, Data, subinput, eval, failsafe } from '../../data/parser';
1
+ import { Parser, List, Data, subinput, failsafe } from '../../data/parser';
2
2
  import { some } from '../../data/parser/some';
3
3
  import { block } from '../constraint/block';
4
4
  import { line } from '../constraint/line';
@@ -26,14 +26,10 @@ export function indent<N>(opener: RegExp | Parser<N>, parser: Parser<N> | boolea
26
26
  context.position = source.length;
27
27
  return new List([new Data(source.slice(position))]);
28
28
  }))),
29
- ([indent]) => indent.length * 2 + +(indent[0] === ' '), {})), separation),
29
+ ([indent]) => indent.length <= 16 ? indent.length * 2 + +(indent[0] === ' ') : -1, [])), separation),
30
30
  (lines, context) => {
31
31
  assert(parser = parser as Parser<N>);
32
- const result = parser(subinput(trimBlockEnd(lines.foldl((acc, node) => acc + node.value, '')), context));
33
- assert(result);
34
- return result
35
- ? eval(result)
36
- : undefined;
32
+ return parser(subinput(trimBlockEnd(lines.foldl((acc, node) => acc + node.value, '')), context));
37
33
  }));
38
34
  }
39
35
 
@@ -1,4 +1,4 @@
1
- import { Parser, Context, input, eval, failsafe } from '../../data/parser';
1
+ import { Parser, Context, input, failsafe } from '../../data/parser';
2
2
  import { matcher } from '../../../combinator';
3
3
 
4
4
  export function focus<P extends Parser<unknown>>(scope: string | RegExp, parser: P): P;
@@ -8,7 +8,7 @@ export function focus<N>(scope: string | RegExp, parser: Parser<N>): Parser<N> {
8
8
  return failsafe(({ context }) => {
9
9
  const { source, position } = context;
10
10
  if (position === source.length) return;
11
- const src = eval(match({ context }))?.head?.value ?? '';
11
+ const src = match({ context })?.head?.value ?? '';
12
12
  assert(source.startsWith(src, position));
13
13
  if (src === '') return;
14
14
  context.range = src.length;
@@ -20,8 +20,7 @@ export function focus<N>(scope: string | RegExp, parser: Parser<N>): Parser<N> {
20
20
  assert(context.position > position || !result);
21
21
  context.source = source;
22
22
  context.offset -= position;
23
- if (result === undefined) return;
24
- return eval(result);
23
+ return result;
25
24
  });
26
25
  }
27
26
 
@@ -47,7 +46,6 @@ export function rewrite<N>(scope: Parser<unknown>, parser: Parser<N>): Parser<N>
47
46
  assert(context.position > position || !res2);
48
47
  context.source = source;
49
48
  context.offset -= position;
50
- if (res2 === undefined) return;
51
- return eval(res2);
49
+ return res2;
52
50
  });
53
51
  }
@@ -1,4 +1,4 @@
1
- import { Parser, Result, List, Data, Ctx, Node, Context, SubParsers, SubNode, IntermediateParser, eval, failsafe } from '../../data/parser';
1
+ import { Parser, Result, List, Data, Ctx, Node, Context, SubParsers, SubNode, IntermediateParser, failsafe } from '../../data/parser';
2
2
  import { matcher, clear } from '../../../combinator';
3
3
 
4
4
  export function surround<P extends Parser<unknown>, S = string>(
@@ -52,29 +52,26 @@ export function surround<N>(
52
52
  if (position === source.length) return;
53
53
  const { linebreak } = context;
54
54
  context.linebreak = 0;
55
- const resultO = opener(input);
55
+ const nodesO = opener(input);
56
56
  assert(context.position >= position);
57
- const nodesO = eval(resultO);
58
57
  if (!nodesO) {
59
58
  return void revert(context, linebreak);
60
59
  }
61
60
  if (isBacktrack(context, backtracks, position, context.position - position || 1)) {
62
61
  return void revert(context, linebreak);
63
62
  }
64
- const resultM = context.position < source.length ? parser(input) : undefined;
63
+ const nodesM = context.position < source.length ? parser(input) : undefined;
65
64
  assert(context.position >= position);
66
65
  context.range = context.position - position;
67
- const nodesM = eval(resultM);
68
- if (!resultM && !optional) {
66
+ if (!nodesM && !optional) {
69
67
  setBacktrack(context, backtracks, position);
70
68
  const result = g?.([nodesO, nodesM], context);
71
69
  revert(context, linebreak);
72
70
  return result;
73
71
  }
74
- const resultC = resultM || optional ? closer(input) : undefined;
72
+ const nodesC = nodesM || optional ? closer(input) : undefined;
75
73
  assert(context.position >= position);
76
74
  context.range = context.position - position;
77
- const nodesC = eval(resultC);
78
75
  if (!nodesC) {
79
76
  setBacktrack(context, backtracks, position);
80
77
  const result = g?.([nodesO, nodesM], context);
@@ -1,4 +1,4 @@
1
- import { Parser, Result, List, Data, Ctx, Node, Context, SubParsers, SubNode, IntermediateParser, eval, failsafe } from '../../data/parser';
1
+ import { Parser, Result, List, Data, Ctx, Node, Context, SubParsers, SubNode, IntermediateParser, failsafe } from '../../data/parser';
2
2
 
3
3
  export function bind<P extends Parser<unknown>>(parser: IntermediateParser<P>, f: (nodes: List<Data<SubNode<P>>>, context: Context<P>) => Result<Node<P>, Context<P>, SubParsers<P>>): P;
4
4
  export function bind<P extends Parser<unknown>>(parser: P, f: (nodes: List<Data<Node<P>>>, context: Context<P>) => Result<Node<P>, Context<P>, SubParsers<P>>): P;
@@ -14,9 +14,8 @@ export function bind<N, U>(parser: Parser<N>, f: (nodes: List<Data<N>>, context:
14
14
  assert(context.position > position || !res1);
15
15
  if (res1 === undefined) return;
16
16
  context.range = context.position - position;
17
- const res2 = f(eval(res1), context);
17
+ const res2 = f(res1, context);
18
18
  assert(context.position > position || !res2);
19
- if (res2 === undefined) return;
20
19
  return context.position > position
21
20
  ? res2
22
21
  : undefined;
@@ -1,6 +1,6 @@
1
- // Memory-efficient flexible list.
1
+ import { CtxOptions, Parser } from './parser';
2
2
 
3
- export class List<N extends List.Node = List.Node> {
3
+ export class List<N extends List.Node = List.Node, C extends CtxOptions = CtxOptions, D extends Parser<unknown, C>[] = any> {
4
4
  constructor(nodes?: ArrayLike<N>) {
5
5
  if (nodes === undefined) return;
6
6
  for (let i = 0; i < nodes.length; ++i) {
@@ -1,4 +1,4 @@
1
- import { Parser, List, Data, Ctx, CtxOptions, input, eval } from '../parser';
1
+ import { Parser, List, Data, Ctx, CtxOptions, input } from '../parser';
2
2
  import { some } from './some';
3
3
  import { reset, context, creation } from './context';
4
4
  import { unwrap } from '../../../parser/util';
@@ -18,7 +18,7 @@ describe('Unit: combinator/data/parser/context', () => {
18
18
  it('root', () => {
19
19
  const base: Context = { resources: { clock: 3, recursions: [1] } };
20
20
  const ctx: Context = {};
21
- assert.deepStrictEqual([...unwrap(eval(reset(base, parser)(input('123', ctx)))!)], [3, 2, 1]);
21
+ assert.deepStrictEqual([...unwrap(reset(base, parser)(input('123', ctx))!)], [3, 2, 1]);
22
22
  assert(base.resources?.clock === 3);
23
23
  assert(ctx.resources?.clock === undefined);
24
24
  assert.throws(() => reset(base, parser)(input('1234', ctx)));
@@ -28,7 +28,7 @@ describe('Unit: combinator/data/parser/context', () => {
28
28
  it('node', () => {
29
29
  const base: Context = { resources: { clock: 3, recursions: [1] } };
30
30
  const ctx: Context = { resources: { clock: 2, recursions: [1] } };
31
- assert.deepStrictEqual([...unwrap(eval(reset(base, parser)(input('1', ctx)))!)], [2]);
31
+ assert.deepStrictEqual([...unwrap(reset(base, parser)(input('1', ctx))!)], [2]);
32
32
  assert(base.resources?.clock === 3);
33
33
  assert(ctx.resources?.clock === 1);
34
34
  assert.throws(() => reset(base, parser)(input('12', ctx)));
@@ -47,7 +47,7 @@ describe('Unit: combinator/data/parser/context', () => {
47
47
  it('', () => {
48
48
  const base: Context = { status: true };
49
49
  const ctx: Context = { resources: { clock: 2, recursions: [1] } };
50
- assert.deepStrictEqual([...unwrap(eval(context(base, parser)(input('1', ctx)))!)], [true]);
50
+ assert.deepStrictEqual([...unwrap(context(base, parser)(input('1', ctx))!)], [true]);
51
51
  assert(base.resources?.clock === undefined);
52
52
  assert(ctx.resources?.clock === 1);
53
53
  assert(ctx.status === undefined);
@@ -1,4 +1,4 @@
1
- import { Parser, List, Data, CtxOptions, Node, Context, SubParsers, SubNode, eval, Ctx } from '../parser';
1
+ import { Parser, List, Data, CtxOptions, Node, Context, SubParsers, SubNode, Ctx } from '../parser';
2
2
 
3
3
  export function inits<P extends Parser<unknown, Ctx>>(parsers: SubParsers<P>, resume?: (nodes: List<Data<SubNode<P>>>) => boolean): SubNode<P> extends Node<P> ? P : Parser<SubNode<P>, Context<P>, SubParsers<P>>;
4
4
  export function inits<N, D extends Parser<N>[]>(parsers: D, resume?: (nodes: List<Data<N>>) => boolean): Parser<N, CtxOptions, D> {
@@ -13,13 +13,11 @@ export function inits<N, D extends Parser<N>[]>(parsers: D, resume?: (nodes: Lis
13
13
  if (context.delimiters?.match(input)) break;
14
14
  const result = parsers[i](input);
15
15
  if (result === undefined) break;
16
- nodes = nodes
17
- ? nodes.import(eval(result))
18
- : eval(result);
19
- if (resume?.(eval(result)) === false) break;
16
+ nodes = nodes?.import(result) ?? result;
17
+ if (resume?.(result) === false) break;
20
18
  }
21
19
  assert(context.position >= position);
22
- return nodes && context.position > position
20
+ return context.position > position
23
21
  ? nodes
24
22
  : undefined;
25
23
  };
@@ -1,4 +1,4 @@
1
- import { Parser, List, Data, CtxOptions, Node, Context, SubParsers, SubNode, eval } from '../parser';
1
+ import { Parser, List, Data, CtxOptions, Node, Context, SubParsers, SubNode } from '../parser';
2
2
 
3
3
  export function sequence<P extends Parser<unknown>>(parsers: SubParsers<P>, resume?: (nodes: List<Data<SubNode<P>>>) => boolean): SubNode<P> extends Node<P> ? P : Parser<SubNode<P>, Context<P>, SubParsers<P>>;
4
4
  export function sequence<N, D extends Parser<N>[]>(parsers: D, resume?: (nodes: List<Data<N>>) => boolean): Parser<N, CtxOptions, D> {
@@ -13,13 +13,11 @@ export function sequence<N, D extends Parser<N>[]>(parsers: D, resume?: (nodes:
13
13
  if (context.delimiters?.match(input)) return;
14
14
  const result = parsers[i](input);
15
15
  if (result === undefined) return;
16
- nodes = nodes
17
- ? nodes.import(eval(result))
18
- : eval(result);
19
- if (resume?.(eval(result)) === false) return;
16
+ nodes = nodes?.import(result) ?? result;
17
+ if (resume?.(result) === false) return;
20
18
  }
21
19
  assert(context.position >= position);
22
- return nodes && context.position > position
20
+ return context.position > position
23
21
  ? nodes
24
22
  : undefined;
25
23
  };
@@ -1,4 +1,4 @@
1
- import { Parser, List, Data, eval } from '../parser';
1
+ import { Parser, List, Data } from '../parser';
2
2
  import { Delimiters } from './context/delimiter';
3
3
 
4
4
  type DelimiterOption = readonly [delimiter: string | RegExp, precedence: number];
@@ -23,22 +23,20 @@ export function some<N>(parser: Parser<N>, end?: string | RegExp | number, delim
23
23
  context.delimiters ??= new Delimiters();
24
24
  context.delimiters.push(delims);
25
25
  }
26
- while (true) {
27
- if (context.position === source.length) break;
26
+ // whileは数倍遅い
27
+ for (; context.position < source.length;) {
28
28
  if (match(input)) break;
29
29
  if (context.delimiters?.match(input)) break;
30
30
  const result = parser(input);
31
31
  if (result === undefined) break;
32
- nodes = nodes
33
- ? nodes.import(eval(result))
34
- : eval(result);
32
+ nodes = nodes?.import(result) ?? result;
35
33
  if (limit >= 0 && context.position - position > limit) break;
36
34
  }
37
35
  if (delims.length > 0) {
38
36
  context.delimiters!.pop(delims.length);
39
37
  }
40
38
  assert(context.position >= position);
41
- return nodes && context.position > position
39
+ return context.position > position
42
40
  ? nodes
43
41
  : undefined;
44
42
  };
@@ -7,8 +7,7 @@ export interface Input<C extends CtxOptions = CtxOptions> {
7
7
  readonly context: C & Ctx;
8
8
  }
9
9
  export type Result<N, C extends CtxOptions = CtxOptions, D extends Parser<unknown, C>[] = any>
10
- = readonly [never, C, D]
11
- | List<Data<N>>
10
+ = List<Data<N>, C, D>
12
11
  | undefined;
13
12
  export { List };
14
13
  export class Data<N> implements List.Node {
@@ -78,28 +77,11 @@ export function clean<C extends Ctx>(context: C): C {
78
77
  return context;
79
78
  }
80
79
 
81
- export { eval_ as eval };
82
- function eval_<N>(result: NonNullable<Result<N>>, default_?: List<Data<N>>): List<Data<N>>;
83
- function eval_<N>(result: Result<N>, default_: List<Data<N>>): List<Data<N>>;
84
- function eval_<N>(result: Result<N>, default_?: undefined): List<Data<N>> | undefined;
85
- function eval_<N>(result: Result<N>, default_?: List<Data<N>>): List<Data<N>> | undefined {
86
- assert(!Array.isArray(result));
87
- return result
88
- ? result as List<Data<N>>
89
- : default_;
90
- }
91
-
92
80
  export function failsafe<P extends Parser<unknown>>(parser: P): P;
93
81
  export function failsafe<N>(parser: Parser<N>): Parser<N> {
94
82
  assert(parser);
95
83
  return input => {
96
- const { context } = input;
97
- const { source, position } = context;
98
- const result = parser(input);
99
- if (result === undefined) {
100
- context.source = source;
101
- context.position = position;
102
- }
103
- return result;
84
+ const position = input.context.position;
85
+ return parser(input) ?? (input.context.position = position, undefined);
104
86
  };
105
87
  }
package/src/debug.test.ts CHANGED
@@ -1,10 +1,10 @@
1
- import { Result, Ctx, eval } from './combinator/data/parser';
1
+ import { Result, Ctx } from './combinator/data/parser';
2
2
  import { html, define } from 'typed-dom/dom';
3
3
  import { querySelectorWith, querySelectorAllWith } from 'typed-dom/query';
4
4
 
5
5
  export function inspect(result: Result<DocumentFragment | HTMLElement | string>, ctx: Ctx, until: number | string = Infinity): [string[], string] | undefined {
6
6
  return result && [
7
- eval(result).foldl<string[]>((acc, { value: node }) => {
7
+ result.foldl<string[]>((acc, { value: node }) => {
8
8
  assert(node);
9
9
  if (typeof node === 'string') return acc.push(node), acc;
10
10
  if (node instanceof DocumentFragment) return acc.push(html('div', [node]).innerHTML), acc;
@@ -1,6 +1,6 @@
1
1
  import { ParserSettings, Progress } from '../../..';
2
2
  import { MarkdownParser } from '../../../markdown';
3
- import { input, eval } from '../../combinator/data/parser';
3
+ import { input } from '../../combinator/data/parser';
4
4
  import { segment } from '../segment';
5
5
  import { header } from '../header';
6
6
  import { block } from '../block';
@@ -75,7 +75,7 @@ export function bind(target: DocumentFragment | HTMLElement | ShadowRoot, settin
75
75
  for (; index < sourceSegments.length - last; ++index) {
76
76
  assert(rev === revision);
77
77
  const seg = sourceSegments[index];
78
- const es = eval(header(input(seg, { header: index === 0 } as MarkdownParser.Options)) || block(input(seg, context)))
78
+ const es = (header(input(seg, { header: index === 0 } as MarkdownParser.Options)) || block(input(seg, context)))
79
79
  ?.foldl<HTMLElement[]>((acc, { value }) => void acc.push(value) || acc, []) ?? [];
80
80
  blocks.splice(index, 0, [seg, es, url]);
81
81
  if (es.length === 0) continue;
@@ -83,7 +83,7 @@ export function bind(target: DocumentFragment | HTMLElement | ShadowRoot, settin
83
83
  // Therefore any `base` node will never be unavailable by deletions until all the dependent `el` nodes are added.
84
84
  push(adds, es.map(el => [el, base] as const));
85
85
  adds.reverse();
86
- while (adds.length > 0) {
86
+ for (; adds.length > 0;) {
87
87
  assert(rev === revision);
88
88
  const [el, base] = adds.pop()!;
89
89
  target.insertBefore(el, base);
@@ -100,7 +100,7 @@ export function bind(target: DocumentFragment | HTMLElement | ShadowRoot, settin
100
100
  }
101
101
  assert(blocks.length === sourceSegments.length);
102
102
  adds.reverse();
103
- while (adds.length > 0) {
103
+ for (; adds.length > 0;) {
104
104
  assert(rev === revision);
105
105
  const [el, base] = adds.pop()!;
106
106
  target.insertBefore(el, base);
@@ -109,7 +109,7 @@ export function bind(target: DocumentFragment | HTMLElement | ShadowRoot, settin
109
109
  if (rev !== revision) return yield { type: 'cancel' };
110
110
  }
111
111
  dels.reverse();
112
- while (dels.length > 0) {
112
+ for (; dels.length > 0;) {
113
113
  assert(rev === revision);
114
114
  const [el] = dels.pop()!;
115
115
  el.parentNode?.removeChild(el);
@@ -1,4 +1,4 @@
1
- import { input, eval } from '../../combinator/data/parser';
1
+ import { input } from '../../combinator/data/parser';
2
2
  import { header as h } from '../header';
3
3
 
4
4
  export function header(source: string): string {
@@ -14,7 +14,7 @@ export function headers(source: string): string[] {
14
14
  function parse(source: string): [HTMLElement, number] | [] {
15
15
  const i = input(source, {});
16
16
  const result = h(i);
17
- const el = eval(result)?.head?.value;
17
+ const el = result?.head?.value;
18
18
  return el?.tagName === 'ASIDE'
19
19
  ? [el, i.context.position]
20
20
  : [];
@@ -1,4 +1,4 @@
1
- import { input, eval } from '../../combinator/data/parser';
1
+ import { input } from '../../combinator/data/parser';
2
2
  import { unsafehtmlentity } from '../inline/htmlentity';
3
3
 
4
4
  const UNICODE_REPLACEMENT_CHARACTER = '\uFFFD';
@@ -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(input(`&${name};`, {})))!.head!.value);
63
+ .map(name => unsafehtmlentity(input(`&${name};`, {}))!.head!.value);
64
64
  assert(unreadableEscapableCharacters.length === unreadableHTMLEntityNames.length);
65
65
  assert(unreadableEscapableCharacters.every(c => c.length === 1));
66
66
  const unreadableEscapableCharacter = new RegExp(`[${unreadableEscapableCharacters.join('')}]`, 'g');
@@ -1,6 +1,6 @@
1
1
  import { ParserOptions } from '../../..';
2
2
  import { MarkdownParser } from '../../../markdown';
3
- import { input, eval } from '../../combinator/data/parser';
3
+ import { input } from '../../combinator/data/parser';
4
4
  import { segment } from '../segment';
5
5
  import { header } from '../header';
6
6
  import { block } from '../block';
@@ -35,7 +35,7 @@ export function parse(source: string, opts: Options = {}, context?: MarkdownPars
35
35
  let index = 0;
36
36
  for (const seg of segment(source)) {
37
37
  node.append(
38
- ...eval(header(input(seg, { header: index++ === 0 } as MarkdownParser.Context)) || block(input(seg, context)))
38
+ ...(header(input(seg, { header: index++ === 0 } as MarkdownParser.Context)) || block(input(seg, context)))
39
39
  ?.foldl<HTMLElement[]>((acc, { value }) => void acc.push(value) || acc, []) ?? []);
40
40
  }
41
41
  assert(opts.id !== '' || !node.querySelector('[id], .index[href], .label[href], .annotation > a[href], .reference > a[href]'));
@@ -1,5 +1,5 @@
1
1
  import { CodeBlockParser } from '../block';
2
- import { List, Data, subinput, eval } from '../../combinator/data/parser';
2
+ import { List, Data, subinput } from '../../combinator/data/parser';
3
3
  import { block, fence, clear, fmap } from '../../combinator';
4
4
  import { autolink } from '../autolink';
5
5
  import { unwrap, invalid } from '../util';
@@ -73,6 +73,6 @@ export const codeblock: CodeBlockParser = block(fmap(
73
73
  params.lang
74
74
  ? context.caches?.code?.get(`${params.lang ?? ''}\n${body.slice(0, -1)}`)?.cloneNode(true).childNodes ||
75
75
  body.slice(0, -1) || undefined
76
- : defrag(unwrap(eval(autolink(subinput(body.slice(0, -1), context)), new List()))));
76
+ : defrag(unwrap(autolink(subinput(body.slice(0, -1), context)))));
77
77
  return new List([new Data(el)]);
78
78
  }));
@@ -1,6 +1,6 @@
1
1
  import { ExtensionParser } from '../../block';
2
2
  import { Recursion } from '../../context';
3
- import { List, Data, subinput, eval } from '../../../combinator/data/parser';
3
+ import { List, Data, 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 } from '../../util';
@@ -49,7 +49,7 @@ export const example: ExtensionParser.ExampleParser = recursion(Recursion.block,
49
49
  new Data(html('aside', { class: 'example', 'data-type': 'math' }, [
50
50
  html('pre', { translate: 'no' }, body.slice(0, -1)),
51
51
  html('hr'),
52
- eval(mathblock(subinput(`$$\n${body}$$`, context)))!.head!.value,
52
+ mathblock(subinput(`$$\n${body}$$`, context))!.head!.value,
53
53
  ])),
54
54
  ]);
55
55
  default:
@@ -44,7 +44,7 @@ export const segment: FigureParser.SegmentParser = block(match(
44
44
  ]),
45
45
  ]),
46
46
  closer),
47
- ([, fence]) => fence.length, {})));
47
+ ([, fence]) => fence.length <= 16 ? fence.length : -1, [])));
48
48
 
49
49
  export const figure: FigureParser = block(fallback(rewrite(segment, fmap(
50
50
  convert(source => source.slice(source.match(/^~+(?:\w+\s+)?/)![0].length, source.trimEnd().lastIndexOf('\n')),
@@ -1,5 +1,5 @@
1
1
  import { ExtensionParser } from '../../block';
2
- import { List, Data, subinput, eval } from '../../../combinator/data/parser';
2
+ import { List, Data, subinput } from '../../../combinator/data/parser';
3
3
  import { union, block, fence, fmap } from '../../../combinator';
4
4
  import { segment } from '../../segment';
5
5
  import { emptyline } from '../../source';
@@ -58,7 +58,7 @@ export const message: MessageParser = block(fmap(
58
58
  },
59
59
  [...segment(body)].reduce(
60
60
  (acc, seg) =>
61
- push(acc, unwrap(eval(content(subinput(seg, context)))!)),
61
+ push(acc, unwrap(content(subinput(seg, context)))),
62
62
  [html('h1', title(type))])))
63
63
  ]);
64
64
  }));
@@ -1,6 +1,6 @@
1
1
  import { max, min } from 'spica/alias';
2
2
  import { ExtensionParser } from '../../block';
3
- import { List, Data, subinput, eval } from '../../../combinator/data/parser';
3
+ import { List, Data, subinput } from '../../../combinator/data/parser';
4
4
  import { union, subsequence, inits, some, block, line, validate, fence, rewrite, clear, surround, open, convert, dup, lazy, fmap } from '../../../combinator';
5
5
  import { inline, medialink, media, lineshortmedia } from '../../inline';
6
6
  import { str, anyline, emptyline, contentline } from '../../source';
@@ -42,7 +42,7 @@ export const table: TableParser = block(fmap(
42
42
  switch (type) {
43
43
  case 'grid':
44
44
  case undefined:
45
- return (eval(parser(subinput(body, context))) ?? new List([new Data(html('table'))]))
45
+ return (parser(subinput(body, context)) ?? new List([new Data(html('table'))]))
46
46
  .foldl(
47
47
  (acc, { value }) => acc.push(new Data(define(value, { 'data-type': type }))) && acc,
48
48
  new List());
@@ -61,6 +61,10 @@ export const block: BlockParser = reset(
61
61
  if (position === source.length) return;
62
62
  const fst = source[position];
63
63
  switch (fst) {
64
+ case '\n':
65
+ assert(source.trim() === '');
66
+ input.context.position = source.length;
67
+ return new List();
64
68
  case '=':
65
69
  if (source.startsWith('===', position)) return pagebreak(input);
66
70
  break;
@@ -1,6 +1,6 @@
1
1
  import { EmStrongParser, EmphasisParser, StrongParser } from '../inline';
2
2
  import { Recursion, Command } from '../context';
3
- import { Result, List, Data, Node, Context, IntermediateParser, eval } from '../../combinator/data/parser';
3
+ import { Result, List, Data, Node, Context, IntermediateParser } from '../../combinator/data/parser';
4
4
  import { union, some, recursion, precedence, validate, surround, open, lazy, bind } from '../../combinator';
5
5
  import { inline } from '../inline';
6
6
  import { strong } from './strong';
@@ -105,7 +105,7 @@ export const emstrong: EmStrongParser = lazy(() => validate('***',
105
105
  case 0:
106
106
  break;
107
107
  case 1:
108
- nodes = eval(bind<EmphasisParser>(
108
+ nodes = bind<EmphasisParser>(
109
109
  subemphasis,
110
110
  ds => {
111
111
  const { source } = context;
@@ -117,11 +117,11 @@ export const emstrong: EmStrongParser = lazy(() => validate('***',
117
117
  return prepend('*', nodes.import(ds));
118
118
  }
119
119
  })
120
- ({ context })) ?? prepend('*', nodes);
120
+ ({ context }) ?? prepend('*', nodes);
121
121
  prefix -= 1;
122
122
  break;
123
123
  case 2:
124
- nodes = eval(bind<StrongParser>(
124
+ nodes = bind<StrongParser>(
125
125
  substrong,
126
126
  ds => {
127
127
  const { source } = context;
@@ -133,7 +133,7 @@ export const emstrong: EmStrongParser = lazy(() => validate('***',
133
133
  return prepend('**', nodes.import(ds));
134
134
  }
135
135
  })
136
- ({ context })) ?? prepend('**', nodes);
136
+ ({ context }) ?? prepend('**', nodes);
137
137
  prefix -= 2;
138
138
  break;
139
139
  }
@@ -1,6 +1,6 @@
1
1
  import { ReferenceParser } from '../inline';
2
2
  import { State, Backtrack, Command } from '../context';
3
- import { List, Data, eval } from '../../combinator/data/parser';
3
+ import { List, Data } from '../../combinator/data/parser';
4
4
  import { union, subsequence, some, precedence, state, constraint, surround, isBacktrack, setBacktrack, lazy } from '../../combinator';
5
5
  import { inline } from '../inline';
6
6
  import { textlink } from './link';
@@ -78,7 +78,7 @@ export const reference: ReferenceParser = lazy(() => constraint(State.reference,
78
78
  })
79
79
  ({ context });
80
80
  if (state & State.annotation && next) {
81
- return (as as List<Data<string | HTMLElement>>).import(bs).import(eval(result!)).import(eval(next));
81
+ return (as as List<Data<string | HTMLElement>>).import(bs).import(result).import(next);
82
82
  }
83
83
  }
84
84
  context.position = position;
@@ -1,6 +1,6 @@
1
1
  import { RubyParser } from '../inline';
2
2
  import { Backtrack } from '../context';
3
- import { List, Data, eval } from '../../combinator/data/parser';
3
+ import { List, Data } from '../../combinator/data/parser';
4
4
  import { inits, surround, setBacktrack, dup, lazy, bind } from '../../combinator';
5
5
  import { unsafehtmlentity } from './htmlentity';
6
6
  import { txt } from '../source';
@@ -76,7 +76,7 @@ const text: RubyParser.TextParser = input => {
76
76
  case '&': {
77
77
  const result = unsafehtmlentity(input) ?? txt(input)!;
78
78
  assert(result);
79
- acc.last!.value += eval(result).head!.value;
79
+ acc.last!.value += result.head!.value;
80
80
  continue;
81
81
  }
82
82
  default: {
@@ -88,7 +88,7 @@ const text: RubyParser.TextParser = input => {
88
88
  }
89
89
  const result = txt(input)!;
90
90
  assert(result);
91
- acc.last!.value += eval(result).head?.value ?? '';
91
+ acc.last!.value += result.head?.value ?? '';
92
92
  continue;
93
93
  }
94
94
  }
@@ -103,7 +103,7 @@ const text: RubyParser.TextParser = input => {
103
103
  function* zip<N extends List.Node>(a: List<N>, b: List<N>): Iterable<[N | undefined, N | undefined]> {
104
104
  const ia = a[Symbol.iterator]();
105
105
  const ib = b[Symbol.iterator]();
106
- while (true) {
106
+ for (; ;) {
107
107
  const ra = ia.next();
108
108
  const rb = ib.next();
109
109
  if (ra.done) break;
@@ -191,7 +191,7 @@ function* proc(defs: Map<string, HTMLLIElement>, note: HTMLOListElement): Genera
191
191
  for (const [key, def] of defs) {
192
192
  defs.delete(key);
193
193
  ++count;
194
- while (length > size) {
194
+ for (; length > size;) {
195
195
  const node = children[count - 1] as HTMLLIElement;
196
196
  if (equal(node, def)) continue I;
197
197
  yield note.removeChild(node);
@@ -207,7 +207,7 @@ function* proc(defs: Map<string, HTMLLIElement>, note: HTMLOListElement): Genera
207
207
  ++length;
208
208
  assert(children.length === length);
209
209
  }
210
- while (length > size) {
210
+ for (; length > size;) {
211
211
  yield note.removeChild(children[size] as HTMLLIElement);
212
212
  --length;
213
213
  assert(children.length === length);