securemark 0.296.2 → 0.296.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/design.md +2 -3
- package/dist/index.js +128 -66
- package/markdown.d.ts +8 -4
- package/package.json +1 -1
- package/src/combinator/control/constraint/block.ts +12 -6
- package/src/combinator/control/manipulation/recovery.ts +3 -3
- package/src/combinator/control/manipulation/surround.ts +1 -1
- package/src/combinator/data/parser/context.test.ts +2 -2
- package/src/combinator/data/parser/context.ts +11 -2
- package/src/combinator/data/parser.ts +7 -0
- package/src/parser/api/bind.ts +15 -10
- package/src/parser/api/parse.ts +4 -3
- package/src/parser/block/extension/fig.ts +3 -1
- package/src/parser/block/extension/figure.ts +2 -1
- package/src/parser/block/extension/message.ts +1 -1
- package/src/parser/block/extension.test.ts +3 -3
- package/src/parser/block/extension.ts +3 -4
- package/src/parser/block/heading.ts +4 -4
- package/src/parser/block.ts +22 -12
- package/src/parser/context.ts +13 -0
- package/src/parser/inline/emstrong.ts +1 -1
- package/src/parser/segment.test.ts +73 -73
- package/src/parser/segment.ts +9 -11
- package/src/parser/source/line.ts +25 -6
- package/src/parser/source/str.ts +9 -10
- package/src/parser/source.ts +2 -1
|
@@ -1,19 +1,25 @@
|
|
|
1
|
-
import { Parser, failsafe } from '../../data/parser';
|
|
1
|
+
import { Parser, List, Segment, failsafe } from '../../data/parser';
|
|
2
2
|
import { isEmptyline } from './line';
|
|
3
3
|
|
|
4
|
-
export function block<P extends Parser>(parser: P, separation?: boolean): P;
|
|
5
|
-
export function block<N>(parser: Parser<N>, separation = true): Parser<N> {
|
|
4
|
+
export function block<P extends Parser>(parser: P, separation?: boolean, segment?: number): P;
|
|
5
|
+
export function block<N>(parser: Parser<N>, separation = true, segment = 0): Parser<N> {
|
|
6
6
|
assert(parser);
|
|
7
7
|
return failsafe(input => {
|
|
8
8
|
const { context } = input;
|
|
9
9
|
const { source, position } = context;
|
|
10
10
|
if (position === source.length) return;
|
|
11
|
+
if (segment !== 0 && context.segment & Segment.write) {
|
|
12
|
+
if (context.segment !== (segment | Segment.write)) return;
|
|
13
|
+
context.position = source.length;
|
|
14
|
+
return new List();
|
|
15
|
+
}
|
|
11
16
|
const result = parser(input);
|
|
12
17
|
if (result === undefined) return;
|
|
13
18
|
if (separation && !isEmptyline(source, context.position)) return;
|
|
14
19
|
assert(context.position === source.length || source[context.position - 1] === '\n');
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
20
|
+
if (segment !== 0 && context.segment & Segment.write ^ Segment.write) {
|
|
21
|
+
context.segment = segment;
|
|
22
|
+
}
|
|
23
|
+
return result;
|
|
18
24
|
});
|
|
19
25
|
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { Parser, Input, Result, Context } from '../../data/parser';
|
|
2
2
|
|
|
3
|
-
export function recover<P extends Parser>(parser: P,
|
|
4
|
-
export function recover<N>(parser: Parser<N>,
|
|
3
|
+
export function recover<P extends Parser>(parser: P, catcher: (input: Input<Parser.Context<P>>, reason: unknown) => Result<Parser.Node<P>>): P;
|
|
4
|
+
export function recover<N>(parser: Parser<N>, catcher: (input: Input<Context>, reason: unknown) => Result<N>): Parser<N> {
|
|
5
5
|
return input => {
|
|
6
6
|
const { context } = input;
|
|
7
7
|
const { source, position } = context;
|
|
@@ -12,7 +12,7 @@ export function recover<N>(parser: Parser<N>, fallback: (input: Input<Context>,
|
|
|
12
12
|
assert(reason instanceof Error && reason.name === 'AssertionError' && !+console.error(reason) || 1);
|
|
13
13
|
context.source = source;
|
|
14
14
|
context.position = position;
|
|
15
|
-
return
|
|
15
|
+
return catcher(input, reason);
|
|
16
16
|
}
|
|
17
17
|
};
|
|
18
18
|
}
|
|
@@ -103,7 +103,7 @@ export function surround<N>(
|
|
|
103
103
|
const result = g?.([nodesO, nodesM], context);
|
|
104
104
|
return result || void revert(context, linebreak);
|
|
105
105
|
}
|
|
106
|
-
const nodesC =
|
|
106
|
+
const nodesC = optional || nodesM ? closer(input) : undefined;
|
|
107
107
|
context.range = context.position - position;
|
|
108
108
|
if (nodesC === undefined) {
|
|
109
109
|
wbs && setBacktrack(context, wbs, position);
|
|
@@ -21,9 +21,9 @@ describe('Unit: combinator/data/parser/context', () => {
|
|
|
21
21
|
const ctx: Ctx = new Context();
|
|
22
22
|
assert.deepStrictEqual([...unwrap(reset(base, parser)(input('123', ctx))!)], [3, 2, 1]);
|
|
23
23
|
assert(base.resources?.clock === 3);
|
|
24
|
-
assert(ctx.resources?.clock ===
|
|
24
|
+
assert(ctx.resources?.clock === 0);
|
|
25
25
|
assert.throws(() => reset(base, parser)(input('1234', ctx)));
|
|
26
|
-
assert(ctx.resources?.clock ===
|
|
26
|
+
assert(ctx.resources?.clock === 0);
|
|
27
27
|
});
|
|
28
28
|
|
|
29
29
|
it('node', () => {
|
|
@@ -4,13 +4,22 @@ import { clone } from 'spica/assign';
|
|
|
4
4
|
|
|
5
5
|
export function reset<P extends Parser>(base: Options, parser: P): P;
|
|
6
6
|
export function reset<N>(base: Context, parser: Parser<N>): Parser<N> {
|
|
7
|
+
return input => {
|
|
8
|
+
const { context } = input;
|
|
9
|
+
// @ts-expect-error
|
|
10
|
+
context.resources ??= {
|
|
11
|
+
clock: base.resources?.clock,
|
|
12
|
+
recursions: base.resources?.recursions.slice(),
|
|
13
|
+
};
|
|
14
|
+
context.backtracks = {};
|
|
15
|
+
return parser(input);
|
|
16
|
+
};
|
|
7
17
|
assert(Object.getPrototypeOf(base) === Object.prototype);
|
|
8
18
|
assert(Object.freeze(base));
|
|
9
19
|
const changes = Object.entries(base);
|
|
10
20
|
const values = Array(changes.length);
|
|
11
21
|
return ({ context }) =>
|
|
12
|
-
|
|
13
|
-
apply(parser, { ...context }, changes, values, true);
|
|
22
|
+
apply(parser, context, changes, values, true);
|
|
14
23
|
}
|
|
15
24
|
|
|
16
25
|
export function context<P extends Parser>(base: Options, parser: P): P;
|
|
@@ -33,6 +33,7 @@ export class Context {
|
|
|
33
33
|
{
|
|
34
34
|
source,
|
|
35
35
|
position,
|
|
36
|
+
segment,
|
|
36
37
|
resources,
|
|
37
38
|
delimiters,
|
|
38
39
|
precedence,
|
|
@@ -45,6 +46,7 @@ export class Context {
|
|
|
45
46
|
) {
|
|
46
47
|
this.source = source ?? '';
|
|
47
48
|
this.position = position ?? 0;
|
|
49
|
+
this.segment = segment ?? 0;
|
|
48
50
|
this.resources = resources;
|
|
49
51
|
this.precedence = precedence ?? 0;
|
|
50
52
|
this.delimiters = delimiters ?? new Delimiters();
|
|
@@ -56,6 +58,7 @@ export class Context {
|
|
|
56
58
|
}
|
|
57
59
|
public source: string;
|
|
58
60
|
public position: number;
|
|
61
|
+
public segment: number;
|
|
59
62
|
public readonly resources?: {
|
|
60
63
|
clock: number;
|
|
61
64
|
recursions: number[];
|
|
@@ -103,6 +106,10 @@ export class Context {
|
|
|
103
106
|
public backtracks: Record<number, number>;
|
|
104
107
|
}
|
|
105
108
|
export type Options = Partial<Context>;
|
|
109
|
+
export const enum Segment {
|
|
110
|
+
unknown = 0,
|
|
111
|
+
write = 1,
|
|
112
|
+
}
|
|
106
113
|
|
|
107
114
|
export function input<C extends Context>(source: string, context: C): Input<C> {
|
|
108
115
|
context.source = source;
|
package/src/parser/api/bind.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { ParserSettings, Progress } from '../../..';
|
|
2
|
-
import { Context } from '../context';
|
|
2
|
+
import { Context, Segment } from '../context';
|
|
3
3
|
import { input } from '../../combinator/data/parser';
|
|
4
4
|
import { segment } from '../segment';
|
|
5
5
|
import { block } from '../block';
|
|
@@ -8,7 +8,7 @@ import { headers } from './header';
|
|
|
8
8
|
import { figure } from '../processor/figure';
|
|
9
9
|
import { note } from '../processor/note';
|
|
10
10
|
import { ReadonlyURL } from 'spica/url';
|
|
11
|
-
import {
|
|
11
|
+
import { splice } from 'spica/array';
|
|
12
12
|
|
|
13
13
|
interface Settings extends ParserSettings {
|
|
14
14
|
}
|
|
@@ -29,8 +29,8 @@ export function bind(target: DocumentFragment | HTMLElement | ShadowRoot, settin
|
|
|
29
29
|
if (context.host?.origin === 'null') throw new Error(`Invalid host: ${context.host.href}`);
|
|
30
30
|
type Block = readonly [segment: string, blocks: readonly HTMLElement[], url: string];
|
|
31
31
|
const blocks: Block[] = [];
|
|
32
|
-
const adds: [HTMLElement, Node | null][] = [];
|
|
33
|
-
const dels: [HTMLElement][] = [];
|
|
32
|
+
const adds: (readonly [HTMLElement, Node | null])[] = [];
|
|
33
|
+
const dels: (readonly [HTMLElement])[] = [];
|
|
34
34
|
const bottom = target.firstChild;
|
|
35
35
|
let revision: symbol | undefined;
|
|
36
36
|
return {
|
|
@@ -47,8 +47,10 @@ export function bind(target: DocumentFragment | HTMLElement | ShadowRoot, settin
|
|
|
47
47
|
context.url = url ? new ReadonlyURL(url as ':') : undefined;
|
|
48
48
|
const rev = revision = Symbol();
|
|
49
49
|
const sourceSegments: string[] = [];
|
|
50
|
-
|
|
50
|
+
const sourceSegmentAttrs: Segment[] = [];
|
|
51
|
+
for (const [seg, attr] of segment(source)) {
|
|
51
52
|
sourceSegments.push(seg);
|
|
53
|
+
sourceSegmentAttrs.push(attr);
|
|
52
54
|
yield { type: 'segment', value: seg };
|
|
53
55
|
}
|
|
54
56
|
const targetSegments = blocks.map(([seg]) => seg);
|
|
@@ -74,16 +76,19 @@ export function bind(target: DocumentFragment | HTMLElement | ShadowRoot, settin
|
|
|
74
76
|
context.header = true;
|
|
75
77
|
for (; index < sourceSegments.length - last; ++index) {
|
|
76
78
|
assert(rev === revision);
|
|
77
|
-
const
|
|
78
|
-
|
|
79
|
+
const src = sourceSegments[index];
|
|
80
|
+
context.segment = sourceSegmentAttrs[index] | Segment.write;
|
|
81
|
+
const es = block(input(src, new Context(context)))
|
|
79
82
|
?.foldl<HTMLElement[]>((acc, { value }) => void acc.push(value) || acc, []) ?? [];
|
|
80
83
|
// @ts-expect-error
|
|
81
84
|
context.header = false;
|
|
82
|
-
blocks.
|
|
85
|
+
blocks.length === index
|
|
86
|
+
? blocks.push([src, es, url])
|
|
87
|
+
: blocks.splice(index, 0, [src, es, url]);
|
|
83
88
|
if (es.length === 0) continue;
|
|
84
89
|
// All deletion processes always run after all addition processes have done.
|
|
85
90
|
// Therefore any `base` node will never be unavailable by deletions until all the dependent `el` nodes are added.
|
|
86
|
-
push(
|
|
91
|
+
adds.push(...es.map(el => [el, base] as const));
|
|
87
92
|
adds.reverse();
|
|
88
93
|
for (; adds.length > 0;) {
|
|
89
94
|
assert(rev === revision);
|
|
@@ -98,7 +103,7 @@ export function bind(target: DocumentFragment | HTMLElement | ShadowRoot, settin
|
|
|
98
103
|
assert(rev === revision);
|
|
99
104
|
const es = refuse[i][1];
|
|
100
105
|
if (es.length === 0) continue;
|
|
101
|
-
push(
|
|
106
|
+
dels.push(...es.map(el => [el] as const));
|
|
102
107
|
}
|
|
103
108
|
assert(blocks.length === sourceSegments.length);
|
|
104
109
|
adds.reverse();
|
package/src/parser/api/parse.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { ParserOptions } from '../../..';
|
|
2
2
|
import { input } from '../../combinator/data/parser';
|
|
3
|
-
import { Context } from '../context';
|
|
3
|
+
import { Context, Segment } from '../context';
|
|
4
4
|
import { segment } from '../segment';
|
|
5
5
|
import { block } from '../block';
|
|
6
6
|
import { normalize } from './normalize';
|
|
@@ -32,9 +32,10 @@ export function parse(source: string, options: Options = {}, context?: Context):
|
|
|
32
32
|
const node = frag();
|
|
33
33
|
// @ts-expect-error
|
|
34
34
|
context.header = true;
|
|
35
|
-
for (const seg of segment(source)) {
|
|
35
|
+
for (const [seg, attr] of segment(source)) {
|
|
36
|
+
context.segment = attr | Segment.write;
|
|
36
37
|
node.append(
|
|
37
|
-
...block(input(seg, context))
|
|
38
|
+
...block(input(seg, new Context(context)))
|
|
38
39
|
?.foldl<HTMLElement[]>((acc, { value }) => void acc.push(value) || acc, []) ?? []);
|
|
39
40
|
// @ts-expect-error
|
|
40
41
|
context.header = false;
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { ExtensionParser } from '../../block';
|
|
2
|
+
import { Segment } from '../../context';
|
|
2
3
|
import { union, sequence, some, block, line, verify, rewrite, close, convert } from '../../../combinator';
|
|
3
4
|
import { contentline } from '../../source';
|
|
4
5
|
import { figure } from './figure';
|
|
@@ -23,7 +24,7 @@ export const segment: FigParser.SegmentParser = block(
|
|
|
23
24
|
seg_placeholder,
|
|
24
25
|
some(contentline),
|
|
25
26
|
]),
|
|
26
|
-
]));
|
|
27
|
+
]), true, Segment.fig);
|
|
27
28
|
|
|
28
29
|
export const fig: FigParser = block(rewrite(segment, verify(convert(
|
|
29
30
|
(source, context) => {
|
|
@@ -33,6 +34,7 @@ export const fig: FigParser = block(rewrite(segment, verify(convert(
|
|
|
33
34
|
const { position } = context;
|
|
34
35
|
const result = parser({ context });
|
|
35
36
|
context.position = position;
|
|
37
|
+
context.segment = Segment.figure | Segment.write;
|
|
36
38
|
return result
|
|
37
39
|
? `${fence}figure ${source.replace(/^(.+\n.+\n)([\S\s]+?)\n?$/, '$1\n$2')}\n${fence}`
|
|
38
40
|
: `${fence}figure ${source}\n\n${fence}`;
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { ExtensionParser } from '../../block';
|
|
2
|
+
import { Segment } from '../../context';
|
|
2
3
|
import { List, Node, subinput } from '../../../combinator/data/parser';
|
|
3
4
|
import { union, inits, sequence, some, block, line, fence, rewrite, close, match, convert, fallback, fmap } from '../../../combinator';
|
|
4
5
|
import { str, contentline, emptyline } from '../../source';
|
|
@@ -44,7 +45,7 @@ export const segment: FigureParser.SegmentParser = block(match(
|
|
|
44
45
|
]),
|
|
45
46
|
]),
|
|
46
47
|
closer),
|
|
47
|
-
([, fence]) => fence.length - 1, [], 2 ** 4 - 1)));
|
|
48
|
+
([, fence]) => fence.length - 1, [], 2 ** 4 - 1)), true, Segment.figure);
|
|
48
49
|
|
|
49
50
|
export const figure: FigureParser = block(fallback(rewrite(segment, fmap(
|
|
50
51
|
convert(source => source.slice(source.match(/^~+(?:\w+\s+)?/)![0].length, source.trimEnd().lastIndexOf('\n')),
|
|
@@ -30,9 +30,9 @@ describe('Unit: parser/block/extension', () => {
|
|
|
30
30
|
assert(parser(input('~~~\na\n~~~', new Context())));
|
|
31
31
|
assert(parser(input('~~~a\n~~~', new Context())));
|
|
32
32
|
assert(parser(input('~~~a\nb\n~~~', new Context())));
|
|
33
|
-
assert(parser(input('$-0', new Context())));
|
|
34
|
-
assert(parser(input('$-0\n', new Context())));
|
|
35
|
-
assert(parser(input('$-0\n\n', new Context())));
|
|
33
|
+
//assert(parser(input('$-0', new Context())));
|
|
34
|
+
//assert(parser(input('$-0\n', new Context())));
|
|
35
|
+
//assert(parser(input('$-0\n\n', new Context())));
|
|
36
36
|
});
|
|
37
37
|
|
|
38
38
|
});
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import { ExtensionParser } from '../block';
|
|
2
2
|
import { union } from '../../combinator';
|
|
3
|
-
import {
|
|
4
|
-
import { fig, segment as seg_fig } from './extension/fig';
|
|
3
|
+
import { segment as seg_fig } from './extension/fig';
|
|
5
4
|
import { figure, segment as seg_figure } from './extension/figure';
|
|
6
5
|
import { table, segment as seg_table } from './extension/table';
|
|
7
6
|
import { message } from './extension/message';
|
|
@@ -17,8 +16,8 @@ export const segment: ExtensionParser.SegmentParser = union([
|
|
|
17
16
|
]);
|
|
18
17
|
|
|
19
18
|
export const extension: ExtensionParser = union([
|
|
20
|
-
figbase,
|
|
21
|
-
fig,
|
|
19
|
+
//figbase,
|
|
20
|
+
//fig,
|
|
22
21
|
figure,
|
|
23
22
|
table,
|
|
24
23
|
message,
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import { HeadingParser } from '../block';
|
|
2
|
-
import { State } from '../context';
|
|
2
|
+
import { Segment, State } from '../context';
|
|
3
3
|
import { List, Node } from '../../combinator/data/parser';
|
|
4
4
|
import { union, some, state, block, line, focus, rewrite, open, fmap, firstline } from '../../combinator';
|
|
5
5
|
import { inline, indexee, indexer, dataindex } from '../inline';
|
|
6
|
-
import { str } from '../source';
|
|
6
|
+
import { str, strs } from '../source';
|
|
7
7
|
import { visualize, trimBlank } from '../visibility';
|
|
8
8
|
import { unwrap, invalid } from '../util';
|
|
9
9
|
import { html, defrag } from 'typed-dom/dom';
|
|
@@ -20,14 +20,14 @@ export const segment: HeadingParser.SegmentParser = block(focus(
|
|
|
20
20
|
context.position += line.length;
|
|
21
21
|
}
|
|
22
22
|
return acc;
|
|
23
|
-
}, false));
|
|
23
|
+
}, false), true, Segment.heading);
|
|
24
24
|
|
|
25
25
|
export const heading: HeadingParser = block(rewrite(segment,
|
|
26
26
|
// その他の表示制御は各所のCSSで行う。
|
|
27
27
|
state(State.annotation | State.reference | State.index | State.label | State.link,
|
|
28
28
|
line(indexee(fmap(union([
|
|
29
29
|
open(
|
|
30
|
-
|
|
30
|
+
strs('#', 2),
|
|
31
31
|
visualize(trimBlank(some(union([indexer, inline])))), true),
|
|
32
32
|
open(
|
|
33
33
|
str('#'),
|
package/src/parser/block.ts
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import { MarkdownParser } from '../../markdown';
|
|
2
|
-
import { Recursion, Command } from './context';
|
|
2
|
+
import { Segment, Recursion, Command } from './context';
|
|
3
3
|
import { List, Node } from '../combinator/data/parser';
|
|
4
|
-
import { union, reset,
|
|
4
|
+
import { union, reset, firstline, recover } from '../combinator';
|
|
5
5
|
import { MAX_SEGMENT_SIZE } from './segment';
|
|
6
6
|
import { header } from './header';
|
|
7
|
-
import {
|
|
7
|
+
import { emptysegment } from './source';
|
|
8
8
|
import { pagebreak } from './block/pagebreak';
|
|
9
9
|
import { heading } from './block/heading';
|
|
10
10
|
import { ulist } from './block/ulist';
|
|
@@ -15,6 +15,9 @@ import { table } from './block/table';
|
|
|
15
15
|
import { codeblock } from './block/codeblock';
|
|
16
16
|
import { mathblock } from './block/mathblock';
|
|
17
17
|
import { extension } from './block/extension';
|
|
18
|
+
import { figbase } from './block/extension/figbase';
|
|
19
|
+
import { fig } from './block/extension/fig';
|
|
20
|
+
import { figure } from './block/extension/figure';
|
|
18
21
|
import { sidefence } from './block/sidefence';
|
|
19
22
|
import { blockquote } from './block/blockquote';
|
|
20
23
|
import { mediablock } from './block/mediablock';
|
|
@@ -57,12 +60,22 @@ export const block: BlockParser = reset(
|
|
|
57
60
|
backtracks: {},
|
|
58
61
|
},
|
|
59
62
|
error(union([
|
|
60
|
-
|
|
63
|
+
emptysegment,
|
|
61
64
|
input => {
|
|
62
|
-
const { context: { source, position } } = input;
|
|
65
|
+
const { context: { source, position, segment } } = input;
|
|
63
66
|
if (position === source.length) return;
|
|
67
|
+
switch (segment ^ Segment.write) {
|
|
68
|
+
case Segment.heading:
|
|
69
|
+
return heading(input);
|
|
70
|
+
case Segment.fig:
|
|
71
|
+
return fig(input);
|
|
72
|
+
case Segment.figure:
|
|
73
|
+
return figure(input);
|
|
74
|
+
}
|
|
64
75
|
const fst = source[position];
|
|
65
76
|
switch (fst) {
|
|
77
|
+
case Command.Error:
|
|
78
|
+
throw new Error(firstline(source, position + 1).trimEnd());
|
|
66
79
|
case '=':
|
|
67
80
|
if (source.startsWith('===', position)) return pagebreak(input);
|
|
68
81
|
break;
|
|
@@ -84,7 +97,7 @@ export const block: BlockParser = reset(
|
|
|
84
97
|
case '[':
|
|
85
98
|
switch (source[position + 1]) {
|
|
86
99
|
case '$':
|
|
87
|
-
return
|
|
100
|
+
return figbase(input);
|
|
88
101
|
case '!':
|
|
89
102
|
return mediablock(input);
|
|
90
103
|
}
|
|
@@ -95,11 +108,9 @@ export const block: BlockParser = reset(
|
|
|
95
108
|
case '>':
|
|
96
109
|
if (source[position + 1] === '>') return blockquote(input) || reply(input);
|
|
97
110
|
return blockquote(input);
|
|
98
|
-
case '#':
|
|
99
|
-
return heading(input);
|
|
100
111
|
case '$':
|
|
101
112
|
if (source[position + 1] === '$') return mathblock(input);
|
|
102
|
-
return
|
|
113
|
+
return figbase(input);
|
|
103
114
|
case '|':
|
|
104
115
|
return table(input) || sidefence(input);
|
|
105
116
|
case '(':
|
|
@@ -113,9 +124,8 @@ export const block: BlockParser = reset(
|
|
|
113
124
|
|
|
114
125
|
function error(parser: BlockParser): BlockParser {
|
|
115
126
|
const reg = new RegExp(String.raw`^${Command.Error}[^\n]*\n`)
|
|
116
|
-
return recover<BlockParser>(
|
|
117
|
-
|
|
118
|
-
parser),
|
|
127
|
+
return recover<BlockParser>(
|
|
128
|
+
parser,
|
|
119
129
|
({ context: { source, position, id } }, reason) => new List([
|
|
120
130
|
new Node(html('h1',
|
|
121
131
|
{
|
package/src/parser/context.ts
CHANGED
|
@@ -7,6 +7,7 @@ export class Context extends Ctx {
|
|
|
7
7
|
) {
|
|
8
8
|
super(options);
|
|
9
9
|
const {
|
|
10
|
+
segment,
|
|
10
11
|
buffer,
|
|
11
12
|
sequential,
|
|
12
13
|
header,
|
|
@@ -15,6 +16,7 @@ export class Context extends Ctx {
|
|
|
15
16
|
id,
|
|
16
17
|
caches,
|
|
17
18
|
} = options;
|
|
19
|
+
this.segment = segment ?? Segment.unknown;
|
|
18
20
|
this.buffer = buffer ?? new List();
|
|
19
21
|
this.sequential = sequential ?? false;
|
|
20
22
|
this.header = header ?? true;
|
|
@@ -23,6 +25,7 @@ export class Context extends Ctx {
|
|
|
23
25
|
this.id = id;
|
|
24
26
|
this.caches = caches;
|
|
25
27
|
}
|
|
28
|
+
public override segment: Segment;
|
|
26
29
|
public buffer: List<Node<(string | HTMLElement)>>;
|
|
27
30
|
public sequential: boolean;
|
|
28
31
|
public readonly header: boolean;
|
|
@@ -37,6 +40,16 @@ export class Context extends Ctx {
|
|
|
37
40
|
}
|
|
38
41
|
export type Options = Partial<Context>;
|
|
39
42
|
|
|
43
|
+
export const enum Segment {
|
|
44
|
+
unknown = 0,
|
|
45
|
+
write = 1,
|
|
46
|
+
nonempty = 0,
|
|
47
|
+
empty = 1 << 1,
|
|
48
|
+
heading = 3 << 1,
|
|
49
|
+
fig = 4 << 1,
|
|
50
|
+
figure = 5 << 1,
|
|
51
|
+
}
|
|
52
|
+
|
|
40
53
|
export const enum State {
|
|
41
54
|
annotation = 1 << 7,
|
|
42
55
|
reference = 1 << 6,
|
|
@@ -26,7 +26,7 @@ export const emstrong: EmStrongParser = lazy(() =>
|
|
|
26
26
|
precedence(0, recursion(Recursion.inline, repeat('***', beforeNonblank, surround(
|
|
27
27
|
'',
|
|
28
28
|
some(union([some(inline, '*', afterNonblank)])),
|
|
29
|
-
strs('*', 3),
|
|
29
|
+
strs('*', 1, 3),
|
|
30
30
|
false, [],
|
|
31
31
|
([, bs, cs], context): Result<Parser.Node<EmStrongParser>, Parser.Context<EmStrongParser>> => {
|
|
32
32
|
assert(cs.length === 1);
|