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.
- package/CHANGELOG.md +8 -0
- package/dist/index.js +2102 -2185
- package/index.ts +2 -2
- package/package.json +1 -1
- package/src/{parser/api → api}/bind.test.ts +2 -2
- package/src/{parser/api → api}/bind.ts +5 -5
- package/src/{parser/api → api}/body.test.ts +1 -1
- package/src/{parser/api → api}/cache.ts +1 -1
- package/src/{parser/api → api}/header.test.ts +1 -1
- package/src/{parser/api → api}/header.ts +2 -2
- package/src/{parser/api → api}/normalize.test.ts +1 -1
- package/src/{parser/api → api}/parse.test.ts +3 -3
- package/src/{parser/api → api}/parse.ts +5 -5
- package/src/combinator/control/manipulation/fence.ts +2 -2
- package/src/combinator/control/manipulation/match.ts +2 -2
- package/src/combinator/data/delimiter.ts +3 -3
- package/src/combinator/data/{node.ts → list/list.ts} +4 -4
- package/src/combinator/data/parser/context.ts +12 -38
- package/src/combinator/data/parser/inits.ts +3 -3
- package/src/combinator/data/parser/sequence.ts +3 -3
- package/src/combinator/data/parser/some.ts +0 -1
- package/src/combinator/data/parser/subsequence.ts +3 -3
- package/src/combinator/data/parser/tails.ts +3 -3
- package/src/combinator/data/parser.ts +1 -1
- package/src/parser/block/blockquote.ts +3 -3
- package/src/parser/block/extension/aside.ts +1 -1
- package/src/parser/block/extension/example.ts +1 -1
- package/src/parser/block.ts +1 -1
- package/src/parser/context.ts +4 -5
- package/src/parser/inline/annotation.ts +1 -1
- package/src/parser/inline/deletion.ts +1 -1
- package/src/parser/inline/emstrong.ts +1 -1
- package/src/parser/inline/insertion.ts +1 -1
- package/src/parser/inline/italic.ts +1 -1
- package/src/parser/inline/link.ts +4 -4
- package/src/parser/inline/mark.ts +1 -1
- package/src/parser/inline/media.ts +3 -3
- package/src/parser/inline.ts +1 -1
- package/src/parser/node.ts +1 -1
- package/src/parser/repeat.ts +7 -19
- package/src/parser/source/escapable.ts +5 -5
- package/src/parser/source/text.ts +8 -9
- package/src/parser/source/unescapable.ts +6 -6
- package/src/parser/visibility.ts +1 -1
- package/src/{parser/processor → processor}/figure.test.ts +4 -4
- package/src/{parser/processor → processor}/figure.ts +2 -2
- package/src/{parser/processor → processor}/note.test.ts +3 -3
- package/src/{parser/processor → processor}/note.ts +2 -2
- package/src/renderer/render/media/pdf.ts +1 -1
- package/src/renderer/render/media/twitter.ts +1 -1
- package/src/renderer/render/media.test.ts +1 -2
- package/src/renderer/render.test.ts +1 -1
- package/src/util/info.test.ts +1 -1
- package/src/util/quote.test.ts +1 -1
- package/src/util/toc.test.ts +1 -1
- package/src/parser.ts +0 -1
- /package/src/{parser/api → api}/body.ts +0 -0
- /package/src/{parser/api → api}/normalize.ts +0 -0
- /package/src/{parser/api.ts → api.ts} +0 -0
package/index.ts
CHANGED
package/package.json
CHANGED
|
@@ -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:
|
|
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 '
|
|
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,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 '
|
|
4
|
+
import { normalize } from '../debug.test';
|
|
5
5
|
|
|
6
|
-
describe('Unit:
|
|
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 '
|
|
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 {
|
|
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
|
-
|
|
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 {
|
|
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 &&
|
|
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 {
|
|
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 &&
|
|
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 &&
|
|
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 '
|
|
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
|
|
138
|
-
|
|
139
|
-
|
|
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
|
-
|
|
11
|
+
spend(context, cost);
|
|
15
12
|
return result;
|
|
16
13
|
};
|
|
17
14
|
}
|
|
18
|
-
export function
|
|
19
|
-
const
|
|
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>(
|
|
26
|
-
export function recursion(
|
|
27
|
-
assert(
|
|
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
|
-
|
|
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
|
-
|
|
30
|
+
recur(recursions, index, -1);
|
|
38
31
|
return result;
|
|
39
32
|
};
|
|
40
33
|
}
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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,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,
|
|
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 '
|
|
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
|
-
|
|
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 '
|
|
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 '
|
|
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(
|
package/src/parser/block.ts
CHANGED
package/src/parser/context.ts
CHANGED
|
@@ -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(
|
|
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
|
|
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, ')',
|
|
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('~~', '', '~~',
|
|
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, '***',
|
|
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('++', '', '++',
|
|
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, '///',
|
|
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,
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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, '==',
|
|
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,
|
|
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
|
-
|
|
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
|
-
|
|
62
|
+
spend(context, 100);
|
|
63
63
|
if (params.last!.value === Command.Cancel) {
|
|
64
64
|
params.pop();
|
|
65
65
|
return new List([
|
package/src/parser/inline.ts
CHANGED
package/src/parser/node.ts
CHANGED