securemark 0.300.0 → 0.300.2
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 +237 -161
- package/index.d.ts +1 -1
- package/markdown.d.ts +3 -10
- package/package.json +1 -1
- package/src/api/bind.ts +6 -6
- package/src/api/parse.ts +2 -2
- package/src/combinator/control/inits.ts +13 -4
- package/src/combinator/control/sequence.ts +3 -1
- package/src/combinator/control/state.ts +1 -10
- package/src/combinator/control/union.ts +16 -3
- package/src/combinator/parser.ts +18 -8
- package/src/combinator/process/fence.ts +23 -33
- package/src/combinator/process/line.ts +1 -1
- package/src/combinator/process/surround.ts +2 -0
- package/src/parser/block/codeblock.test.ts +0 -2
- package/src/parser/block/codeblock.ts +4 -4
- package/src/parser/block/extension/aside.test.ts +0 -1
- package/src/parser/block/extension/aside.ts +2 -2
- package/src/parser/block/extension/example.test.ts +0 -2
- package/src/parser/block/extension/example.ts +2 -2
- package/src/parser/block/extension/fig.ts +5 -7
- package/src/parser/block/extension/figure.test.ts +0 -4
- package/src/parser/block/extension/figure.ts +6 -7
- package/src/parser/block/extension/message.test.ts +0 -1
- package/src/parser/block/extension/message.ts +2 -2
- package/src/parser/block/extension/placeholder.ts +4 -4
- package/src/parser/block/extension/table.test.ts +0 -1
- package/src/parser/block/extension/table.ts +2 -8
- package/src/parser/block/extension.ts +1 -2
- package/src/parser/block/mathblock.test.ts +0 -2
- package/src/parser/block/mathblock.ts +4 -4
- package/src/parser/context.ts +9 -12
- package/src/parser/document.ts +1 -1
- package/src/parser/inline/autolink/url.ts +4 -4
- package/src/parser/inline/math.ts +1 -1
- package/src/parser/inline/media.ts +4 -4
- package/src/parser/inline/ruby.ts +45 -8
- package/src/parser/inline/template.ts +4 -4
- package/src/parser/source/escapable.ts +0 -1
- package/src/parser/source/text.ts +14 -43
- package/src/parser/source/unescapable.ts +0 -1
- package/src/parser/source/whitespace.ts +36 -0
- package/src/parser/source.ts +1 -0
- package/src/parser/visibility.ts +2 -1
package/index.d.ts
CHANGED
|
@@ -44,7 +44,7 @@ export type Progress =
|
|
|
44
44
|
| { readonly type: 'block'; readonly value: HTMLElement; }
|
|
45
45
|
| { readonly type: 'figure'; readonly value: HTMLAnchorElement; }
|
|
46
46
|
| { readonly type: 'note'; readonly value: HTMLLIElement | HTMLElement; }
|
|
47
|
-
| { readonly type: 'break'; }
|
|
47
|
+
| { readonly type: 'break'; readonly value: 'segment' | 'block' | 'parser' | 'figure' | 'note'; }
|
|
48
48
|
| { readonly type: 'cancel'; };
|
|
49
49
|
|
|
50
50
|
export interface RenderingOptions {
|
package/markdown.d.ts
CHANGED
|
@@ -325,7 +325,6 @@ export namespace MarkdownParser {
|
|
|
325
325
|
Parser<string, Input, [
|
|
326
326
|
FigParser.SegmentParser,
|
|
327
327
|
FigureParser.SegmentParser,
|
|
328
|
-
TableParser.SegmentParser,
|
|
329
328
|
PlaceholderParser.SegmentParser,
|
|
330
329
|
]> {
|
|
331
330
|
}
|
|
@@ -350,8 +349,8 @@ export namespace MarkdownParser {
|
|
|
350
349
|
MathBlockParser,
|
|
351
350
|
ExampleParser,
|
|
352
351
|
TableParser,
|
|
353
|
-
BlockquoteParser,
|
|
354
352
|
PlaceholderParser,
|
|
353
|
+
BlockquoteParser,
|
|
355
354
|
InlineParser.MediaParser,
|
|
356
355
|
InlineParser.ShortMediaParser.LineShortMediaParser,
|
|
357
356
|
]>,
|
|
@@ -369,9 +368,8 @@ export namespace MarkdownParser {
|
|
|
369
368
|
Parser<never, Input, [
|
|
370
369
|
CodeBlockParser.SegmentParser,
|
|
371
370
|
MathBlockParser.SegmentParser,
|
|
372
|
-
TableParser.SegmentParser,
|
|
373
|
-
BlockquoteParser.SegmentParser,
|
|
374
371
|
PlaceholderParser.SegmentParser,
|
|
372
|
+
BlockquoteParser.SegmentParser,
|
|
375
373
|
SourceParser.ContentLineParser,
|
|
376
374
|
]>,
|
|
377
375
|
SourceParser.EmptyLineParser,
|
|
@@ -399,9 +397,8 @@ export namespace MarkdownParser {
|
|
|
399
397
|
Parser<never, Input, [
|
|
400
398
|
CodeBlockParser.SegmentParser,
|
|
401
399
|
MathBlockParser.SegmentParser,
|
|
402
|
-
TableParser.SegmentParser,
|
|
403
|
-
BlockquoteParser.SegmentParser,
|
|
404
400
|
PlaceholderParser.SegmentParser,
|
|
401
|
+
BlockquoteParser.SegmentParser,
|
|
405
402
|
SourceParser.ContentLineParser,
|
|
406
403
|
]>,
|
|
407
404
|
]> {
|
|
@@ -427,10 +424,6 @@ export namespace MarkdownParser {
|
|
|
427
424
|
]> {
|
|
428
425
|
}
|
|
429
426
|
export namespace TableParser {
|
|
430
|
-
export interface SegmentParser extends
|
|
431
|
-
Block<'extension/table/segment'>,
|
|
432
|
-
Parser<never, Input, []> {
|
|
433
|
-
}
|
|
434
427
|
export interface GridTableParser extends
|
|
435
428
|
Block<'extension/table/gridtable'>,
|
|
436
429
|
Parser<HTMLElement, Input, [
|
package/package.json
CHANGED
package/src/api/bind.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { ParserSettings, Progress } from '../..';
|
|
2
2
|
import { Input, Options, Segment } from '../parser/context';
|
|
3
|
-
import { Output,
|
|
3
|
+
import { Output, run } from '../combinator/parser';
|
|
4
4
|
import { segment } from '../parser/segment';
|
|
5
5
|
import { block } from '../parser/block';
|
|
6
6
|
import { headers } from './header';
|
|
@@ -74,8 +74,8 @@ export function bind(target: DocumentFragment | HTMLElement | ShadowRoot, settin
|
|
|
74
74
|
assert(rev === revision);
|
|
75
75
|
const seg = sourceSegments[index];
|
|
76
76
|
options.segment = sourceSegmentAttrs[index] | Segment.write;
|
|
77
|
-
for (const _ of run(block,
|
|
78
|
-
yield { type: 'break' };
|
|
77
|
+
for (const _ of run(block, new Input(options, seg), output)) {
|
|
78
|
+
yield { type: 'break', value: 'block' };
|
|
79
79
|
}
|
|
80
80
|
assert(output.data.length === 1);
|
|
81
81
|
const es = output.pop()
|
|
@@ -124,20 +124,20 @@ export function bind(target: DocumentFragment | HTMLElement | ShadowRoot, settin
|
|
|
124
124
|
yield { type: 'block', value: el };
|
|
125
125
|
if (rev !== revision) return yield { type: 'cancel' };
|
|
126
126
|
}
|
|
127
|
-
yield { type: 'break' };
|
|
127
|
+
yield { type: 'break', value: 'parser' };
|
|
128
128
|
if (rev !== revision) return yield { type: 'cancel' };
|
|
129
129
|
for (const el of figure(next(0)?.parentNode ?? target, settings.notes, options)) {
|
|
130
130
|
assert(rev === revision);
|
|
131
131
|
el
|
|
132
132
|
? yield { type: 'figure', value: el }
|
|
133
|
-
: yield { type: 'break' };
|
|
133
|
+
: yield { type: 'break', value: 'figure' };
|
|
134
134
|
if (rev !== revision) return yield { type: 'cancel' };
|
|
135
135
|
}
|
|
136
136
|
for (const el of note(next(0)?.parentNode ?? target, settings.notes, options, bottom)) {
|
|
137
137
|
assert(rev === revision);
|
|
138
138
|
el
|
|
139
139
|
? yield { type: 'note', value: el }
|
|
140
|
-
: yield { type: 'break' };
|
|
140
|
+
: yield { type: 'break', value: 'note' };
|
|
141
141
|
if (rev !== revision) return yield { type: 'cancel' };
|
|
142
142
|
}
|
|
143
143
|
}
|
package/src/api/parse.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { ParserOptions } from '../..';
|
|
2
|
-
import { Input, Options
|
|
2
|
+
import { Input, Options } from '../parser/context';
|
|
3
3
|
import { Output, run } from '../combinator/parser';
|
|
4
4
|
import { document } from '../parser/document';
|
|
5
5
|
import { ReadonlyURL } from 'spica/url';
|
|
@@ -23,7 +23,7 @@ export function* parse(source: string, opts: Opts = {}, options?: Options): Gene
|
|
|
23
23
|
if (options.id?.match(/[^0-9a-z/-]/i)) throw new Error('Invalid ID: ID must be alphanumeric');
|
|
24
24
|
if (options.host?.origin === 'null') throw new Error(`Invalid host: ${options.host.href}`);
|
|
25
25
|
const output = new Output<DocumentFragment>();
|
|
26
|
-
for (const _ of run(document,
|
|
26
|
+
for (const _ of run(document, new Input(options, source), output)) yield;
|
|
27
27
|
assert(output.data.length === 1);
|
|
28
28
|
assert(output.peek().length === 1);
|
|
29
29
|
return output.peek().head!.value;
|
|
@@ -1,16 +1,16 @@
|
|
|
1
|
-
import { Parser, SubParsers } from '../parser';
|
|
1
|
+
import { Parser, SubParsers, Result } from '../parser';
|
|
2
2
|
import { union } from './union';
|
|
3
3
|
import { sequence } from './sequence';
|
|
4
|
-
import { recovery } from './state';
|
|
5
4
|
|
|
6
5
|
export function inits<P extends Parser>(parsers: Parser.SubParsers<P>): P;
|
|
7
6
|
export function inits<T>(parsers: SubParsers<T>): Parser<T> {
|
|
8
7
|
assert(parsers.every(f => f));
|
|
9
8
|
switch (parsers.length) {
|
|
10
9
|
case 0:
|
|
10
|
+
assert(false);
|
|
11
11
|
return (_, output) => output.context;
|
|
12
12
|
case 1:
|
|
13
|
-
return
|
|
13
|
+
return parsers[0];
|
|
14
14
|
default:
|
|
15
15
|
return parsers.reduceRight((acc, parser, i) =>
|
|
16
16
|
sequence([
|
|
@@ -19,8 +19,17 @@ export function inits<T>(parsers: SubParsers<T>): Parser<T> {
|
|
|
19
19
|
? acc
|
|
20
20
|
: union([
|
|
21
21
|
acc,
|
|
22
|
-
recovery
|
|
22
|
+
recovery,
|
|
23
23
|
]),
|
|
24
24
|
]));
|
|
25
25
|
}
|
|
26
26
|
}
|
|
27
|
+
|
|
28
|
+
const recovery: Parser<never> = (_, output) => {
|
|
29
|
+
if (output.state) {
|
|
30
|
+
output.state = true;
|
|
31
|
+
// @ts-expect-error
|
|
32
|
+
output.context ??= Result.succ;
|
|
33
|
+
}
|
|
34
|
+
return output.context;
|
|
35
|
+
};
|
|
@@ -6,8 +6,10 @@ export function sequence<T>(parsers: SubParsers<T>): Parser<T> {
|
|
|
6
6
|
assert(parsers.every(f => f));
|
|
7
7
|
switch (parsers.length) {
|
|
8
8
|
case 0:
|
|
9
|
+
assert(false);
|
|
10
|
+
return (_, output) => output.context;
|
|
9
11
|
case 1:
|
|
10
|
-
return
|
|
12
|
+
return parsers[0];
|
|
11
13
|
default:
|
|
12
14
|
return parsers.reduceRight((acc, parser) => always([
|
|
13
15
|
parser,
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { Parser, SubParsers
|
|
1
|
+
import { Parser, SubParsers } from '../parser';
|
|
2
2
|
|
|
3
3
|
export function then<P extends Parser>(success: P, failure: P): P;
|
|
4
4
|
export function then<T>(success: Parser<T>, failure: Parser<T>): Parser<T> {
|
|
@@ -31,12 +31,3 @@ export function force<T>(parser: Parser<T>): Parser<T> {
|
|
|
31
31
|
? output.context
|
|
32
32
|
: parser(input, output);
|
|
33
33
|
}
|
|
34
|
-
|
|
35
|
-
export function recovery<P extends Parser>(parser?: P): P;
|
|
36
|
-
export function recovery<T>(parser: Parser<T> = () => Result.succ): Parser<T> {
|
|
37
|
-
return (input, output) => {
|
|
38
|
-
output.state = true;
|
|
39
|
-
output.context = Result.succ;
|
|
40
|
-
return parser(input, output);
|
|
41
|
-
};
|
|
42
|
-
}
|
|
@@ -1,14 +1,15 @@
|
|
|
1
|
-
import { Parser, SubParsers } from '../parser';
|
|
2
|
-
import { failure, always
|
|
1
|
+
import { Parser, SubParsers, Result } from '../parser';
|
|
2
|
+
import { failure, always } from './state';
|
|
3
3
|
|
|
4
4
|
export function union<P extends Parser>(parsers: Parser.SubParsers<P>): P;
|
|
5
5
|
export function union<T>(parsers: SubParsers<T>): Parser<T> {
|
|
6
6
|
assert(parsers.every(f => f));
|
|
7
7
|
switch (parsers.length) {
|
|
8
8
|
case 0:
|
|
9
|
+
assert(false);
|
|
9
10
|
return (_, output) => output.context;
|
|
10
11
|
case 1:
|
|
11
|
-
return
|
|
12
|
+
return parsers[0];
|
|
12
13
|
default:
|
|
13
14
|
return parsers.reduceRight((acc, parser) => always([
|
|
14
15
|
parser,
|
|
@@ -16,3 +17,15 @@ export function union<T>(parsers: SubParsers<T>): Parser<T> {
|
|
|
16
17
|
]));
|
|
17
18
|
}
|
|
18
19
|
}
|
|
20
|
+
|
|
21
|
+
function recovery<P extends Parser>(parser: P): P;
|
|
22
|
+
function recovery<T>(parser: Parser<T>): Parser<T> {
|
|
23
|
+
return (input, output) => {
|
|
24
|
+
if (!output.state) {
|
|
25
|
+
output.state = true;
|
|
26
|
+
// @ts-expect-error
|
|
27
|
+
output.context ??= Result.succ;
|
|
28
|
+
}
|
|
29
|
+
return parser(input, output);
|
|
30
|
+
};
|
|
31
|
+
}
|
package/src/combinator/parser.ts
CHANGED
|
@@ -140,7 +140,7 @@ export class Output<T> {
|
|
|
140
140
|
assert(data.length > 0);
|
|
141
141
|
}
|
|
142
142
|
public state: boolean = true;
|
|
143
|
-
public context: Result.Succ | Result.Fail = Result.succ;
|
|
143
|
+
public readonly context: Result.Succ | Result.Fail = Result.succ;
|
|
144
144
|
public error?: Error = undefined;
|
|
145
145
|
public peek(): List<Node<T>> {
|
|
146
146
|
assert(this.data.length > 0);
|
|
@@ -222,17 +222,24 @@ export function* run
|
|
|
222
222
|
time = Date.now();
|
|
223
223
|
}
|
|
224
224
|
if (output.state && output.error) {
|
|
225
|
-
output.state
|
|
226
|
-
|
|
225
|
+
if (output.state) {
|
|
226
|
+
output.state = false;
|
|
227
|
+
// @ts-expect-error
|
|
228
|
+
output.context = Result.fail;
|
|
229
|
+
}
|
|
227
230
|
}
|
|
228
231
|
const input = scope.peek();
|
|
229
232
|
//assert(input.position <= input.source.length);
|
|
230
|
-
const
|
|
233
|
+
const parser = queue.pop();
|
|
234
|
+
const result = parser(input, output);
|
|
231
235
|
|
|
232
236
|
if (result) {
|
|
233
237
|
//assert(result.every(f => f));
|
|
234
|
-
output.state
|
|
235
|
-
|
|
238
|
+
if (!output.state) {
|
|
239
|
+
output.state = true;
|
|
240
|
+
// @ts-expect-error
|
|
241
|
+
output.context ??= Result.succ;
|
|
242
|
+
}
|
|
236
243
|
if (result.length !== 0) {
|
|
237
244
|
if (queue.length !== 0) {
|
|
238
245
|
queue.memory = input.memory;
|
|
@@ -249,8 +256,11 @@ export function* run
|
|
|
249
256
|
if (result === Result.skip) {
|
|
250
257
|
queue.length = 0;
|
|
251
258
|
}
|
|
252
|
-
output.state
|
|
253
|
-
|
|
259
|
+
if (output.state) {
|
|
260
|
+
output.state = false;
|
|
261
|
+
// @ts-expect-error
|
|
262
|
+
output.context = Result.fail;
|
|
263
|
+
}
|
|
254
264
|
}
|
|
255
265
|
|
|
256
266
|
if (queue.length !== 0) continue;
|
|
@@ -2,15 +2,15 @@ import { Parser, SubParsers, Input, List, Node } from '../parser';
|
|
|
2
2
|
import { spend } from '../effect/clock';
|
|
3
3
|
import { firstline, isEmptyline } from './line';
|
|
4
4
|
|
|
5
|
-
export function fence<I extends Input, S extends SubParsers<never, I>>(opener: RegExp, write: boolean,
|
|
5
|
+
export function fence<I extends Input, S extends SubParsers<never, I>>(opener: RegExp, write: boolean, separation = true): Parser<string, I, S> {
|
|
6
6
|
assert(!opener.flags.match(/[gm]/) && opener.sticky && !opener.source.startsWith('^'));
|
|
7
7
|
return (input, output) => {
|
|
8
|
-
const { source
|
|
9
|
-
if (position === source.length) return;
|
|
10
|
-
opener.lastIndex = position;
|
|
8
|
+
const { source } = input;
|
|
9
|
+
if (input.position === source.length) return;
|
|
10
|
+
opener.lastIndex = input.position;
|
|
11
11
|
const matches = opener.exec(source);
|
|
12
12
|
if (!matches) return;
|
|
13
|
-
assert(matches[0] === firstline(source, position));
|
|
13
|
+
assert(matches[0] === firstline(source, input.position));
|
|
14
14
|
spend(input, output, matches[0].length);
|
|
15
15
|
const delim = matches[1];
|
|
16
16
|
assert(delim && delim === delim.trim());
|
|
@@ -23,37 +23,27 @@ export function fence<I extends Input, S extends SubParsers<never, I>>(opener: R
|
|
|
23
23
|
input.position -= matches[0].length;
|
|
24
24
|
return;
|
|
25
25
|
}
|
|
26
|
+
const { position } = input;
|
|
26
27
|
let body = '';
|
|
27
28
|
let closer = '';
|
|
28
|
-
|
|
29
|
-
for (
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
}
|
|
46
|
-
assert(!overflow);
|
|
47
|
-
overflow = line;
|
|
48
|
-
}
|
|
49
|
-
if (!overflow) {
|
|
50
|
-
body += line;
|
|
51
|
-
}
|
|
52
|
-
input.position += line.length;
|
|
29
|
+
assert(matches[0].endsWith('\n'));
|
|
30
|
+
for (input.position -= 1; ;) {
|
|
31
|
+
input.position = source.indexOf(`\n${delim}`, input.position) + 1 || source.length;
|
|
32
|
+
if (!isEmptyline(source, input.position + delim.length)) continue;
|
|
33
|
+
body = source.slice(position, input.position);
|
|
34
|
+
closer = firstline(source, input.position);
|
|
35
|
+
input.position += closer.length;
|
|
36
|
+
break;
|
|
37
|
+
}
|
|
38
|
+
if (separation) for (; !isEmptyline(source, input.position);) {
|
|
39
|
+
input.position = source.indexOf('\n', input.position) + 1 || source.length;
|
|
40
|
+
}
|
|
41
|
+
if (write) {
|
|
42
|
+
const overflow = source.slice(position + body.length + closer.length, input.position);
|
|
43
|
+
output.push(
|
|
44
|
+
new List([body, overflow, closer].map(str => new Node(str)))
|
|
45
|
+
.import(new List(matches.map(str => new Node(str)))));
|
|
53
46
|
}
|
|
54
|
-
write && output.push(
|
|
55
|
-
new List([body, overflow, closer].map(str => new Node(str)))
|
|
56
|
-
.import(new List(matches.map(str => new Node(str)))));
|
|
57
47
|
return output.context;
|
|
58
48
|
};
|
|
59
49
|
}
|
|
@@ -49,7 +49,7 @@ export function firstline(source: string, position: number): string {
|
|
|
49
49
|
const emptyline = /[^\S\r\n]*(?:$|\r?\n)/y;
|
|
50
50
|
export function isEmptyline(source: string, position: number): boolean {
|
|
51
51
|
emptyline.lastIndex = position;
|
|
52
|
-
return source.length
|
|
52
|
+
return position >= source.length
|
|
53
53
|
|| source[position] === '\n'
|
|
54
54
|
|| emptyline.test(source);
|
|
55
55
|
}
|
|
@@ -136,6 +136,7 @@ export function surround<T>(
|
|
|
136
136
|
const o = output.pop();
|
|
137
137
|
if (!g) return;
|
|
138
138
|
output.state = true;
|
|
139
|
+
// @ts-expect-error
|
|
139
140
|
output.context = Result.succ;
|
|
140
141
|
return g([o, state ? m : undefined], input, output);
|
|
141
142
|
}
|
|
@@ -156,6 +157,7 @@ export function surround<T>(
|
|
|
156
157
|
wbs && setBacktrack(input, wbs, position);
|
|
157
158
|
if (!g) return;
|
|
158
159
|
output.state = true;
|
|
160
|
+
// @ts-expect-error
|
|
159
161
|
output.context = Result.succ;
|
|
160
162
|
return g([o, state ? m : undefined], input, output);
|
|
161
163
|
}
|
|
@@ -22,7 +22,6 @@ describe('Unit: parser/block/codeblock', () => {
|
|
|
22
22
|
assert.deepStrictEqual(inspect(parser, input('```\n````')), [['<pre class="invalid" translate="no">```\n````</pre>'], '']);
|
|
23
23
|
assert.deepStrictEqual(inspect(parser, input('````\n```')), [['<pre class="invalid" translate="no">````\n```</pre>'], '']);
|
|
24
24
|
assert.deepStrictEqual(inspect(parser, input(' ```\n```')), undefined);
|
|
25
|
-
assert.deepStrictEqual(inspect(parser, input(`\`\`\`\n0${'\n'.repeat(301)}\`\`\``), '>'), [['<pre class="invalid" translate="no">'], '']);
|
|
26
25
|
});
|
|
27
26
|
|
|
28
27
|
it('basic', () => {
|
|
@@ -44,7 +43,6 @@ describe('Unit: parser/block/codeblock', () => {
|
|
|
44
43
|
assert.deepStrictEqual(inspect(parser, input('```\n!http://host)\n```')), [['<pre class="text">!<a class="url" href="http://host)" target="_blank">http://host)</a></pre>'], '']);
|
|
45
44
|
assert.deepStrictEqual(inspect(parser, input('```\n#a\n```')), [['<pre class="text"><a class="hashtag" href="/hashtags/a">#a</a></pre>'], '']);
|
|
46
45
|
assert.deepStrictEqual(inspect(parser, input('```\n@a#b\n```')), [['<pre class="text"><a class="channel" href="/@a?ch=b">@a#b</a></pre>'], '']);
|
|
47
|
-
assert.deepStrictEqual(inspect(parser, input(`\`\`\`\n0${'\n'.repeat(300)}\`\`\``), '>'), [['<pre class="text">'], '']);
|
|
48
46
|
});
|
|
49
47
|
|
|
50
48
|
it('attribute', () => {
|
|
@@ -9,13 +9,13 @@ const opener = /(`{3,})(?!`)([^\r\n]*)(?:$|\r?\n)/y;
|
|
|
9
9
|
const language = /^[0-9a-z]+(?:-[a-z][0-9a-z]*)*$/i;
|
|
10
10
|
|
|
11
11
|
export const segment: CodeBlockParser.SegmentParser = block(
|
|
12
|
-
fence(opener, false
|
|
12
|
+
fence(opener, false));
|
|
13
13
|
|
|
14
14
|
export const segment_: CodeBlockParser.SegmentParser = block(
|
|
15
|
-
fence(opener, false,
|
|
15
|
+
fence(opener, false, false), false);
|
|
16
16
|
|
|
17
17
|
export const codeblock: CodeBlockParser = block(inits([
|
|
18
|
-
fence(opener, true
|
|
18
|
+
fence(opener, true),
|
|
19
19
|
(input, output) => {
|
|
20
20
|
const [body, overflow, closer, opener, delim, param] = unwrap(output.pop()) as string[];
|
|
21
21
|
const params = param.match(/(?:\\.?|\S)+/g)?.reduce<{
|
|
@@ -64,7 +64,7 @@ export const codeblock: CodeBlockParser = block(inits([
|
|
|
64
64
|
? `Invalid trailing line after the closing delimiter "${delim}"`
|
|
65
65
|
: params.invalid!),
|
|
66
66
|
},
|
|
67
|
-
`${opener}${body}${
|
|
67
|
+
`${opener}${body}${closer}${overflow}`)));
|
|
68
68
|
return;
|
|
69
69
|
}
|
|
70
70
|
const src = body.slice(0, body.at(-2) === '\r' ? -2 : -1);
|
|
@@ -11,7 +11,6 @@ describe('Unit: parser/block/extension/aside', () => {
|
|
|
11
11
|
assert.deepStrictEqual(inspect(parser, input('~~~aside\n~~~')), [['<pre class="invalid" translate="no">~~~aside\n~~~</pre>'], '']);
|
|
12
12
|
assert.deepStrictEqual(inspect(parser, input('~~~aside\n# \n~~~')), [['<pre class="invalid" translate="no">~~~aside\n# \n~~~</pre>'], '']);
|
|
13
13
|
assert.deepStrictEqual(inspect(parser, input('~~~aside a\n# 0\n~~~')), [['<pre class="invalid" translate="no">~~~aside a\n# 0\n~~~</pre>'], '']);
|
|
14
|
-
assert.deepStrictEqual(inspect(parser, input(`~~~aside\n# 0${'\n'.repeat(301)}~~~`), '>'), [['<pre class="invalid" translate="no">'], '']);
|
|
15
14
|
});
|
|
16
15
|
|
|
17
16
|
it('valid', () => {
|
|
@@ -14,7 +14,7 @@ interface Memory {
|
|
|
14
14
|
}
|
|
15
15
|
|
|
16
16
|
export const aside: ExtensionParser.AsideParser = block(recursion(Recursion.block, inits([
|
|
17
|
-
fence(/(~{3,})aside(?!\S)([^\r\n]*)(?:$|\r?\n)/y, true
|
|
17
|
+
fence(/(~{3,})aside(?!\S)([^\r\n]*)(?:$|\r?\n)/y, true),
|
|
18
18
|
(input: Input<Memory>, output) => {
|
|
19
19
|
const [body, overflow, closer, opener, delim, param] = unwrap(output.pop()) as string[];
|
|
20
20
|
if (!closer || overflow || param.trimStart()) {
|
|
@@ -30,7 +30,7 @@ export const aside: ExtensionParser.AsideParser = block(recursion(Recursion.bloc
|
|
|
30
30
|
overflow ? `Invalid trailing line after the closing delimiter "${delim}"` :
|
|
31
31
|
'Invalid argument'),
|
|
32
32
|
},
|
|
33
|
-
`${opener}${body}${
|
|
33
|
+
`${opener}${body}${closer}${overflow}`)));
|
|
34
34
|
return;
|
|
35
35
|
}
|
|
36
36
|
input.memory = {
|
|
@@ -11,7 +11,6 @@ describe('Unit: parser/block/extension/example', () => {
|
|
|
11
11
|
assert.deepStrictEqual(inspect(parser, input('~~~example/\n~~~')), undefined);
|
|
12
12
|
assert.deepStrictEqual(inspect(parser, input('~~~example/a\n~~~')), [['<pre class="invalid" translate="no">~~~example/a\n~~~</pre>'], '']);
|
|
13
13
|
assert.deepStrictEqual(inspect(parser, input('~~~example/markdown a\n~~~')), [['<pre class="invalid" translate="no">~~~example/markdown a\n~~~</pre>'], '']);
|
|
14
|
-
assert.deepStrictEqual(inspect(parser, input(`~~~example/markdown\n0${'\n'.repeat(301)}~~~`), '>'), [['<pre class="invalid" translate="no">'], '']);
|
|
15
14
|
});
|
|
16
15
|
|
|
17
16
|
it('valid', () => {
|
|
@@ -27,7 +26,6 @@ describe('Unit: parser/block/extension/example', () => {
|
|
|
27
26
|
assert.deepStrictEqual(inspect(parser, input('~~~example/markdown\n((a))[[b]]\n~~~')), [['<aside class="example" data-type="markdown"><pre translate="no">((a))[[b]]</pre><hr><section><p><sup class="annotation local" id="annotation:random:ref:a:1" title="a"><a href="#annotation:random:def:a:1">*1</a></sup><sup class="reference local" id="reference:random:ref:b:1" title="b"><a href="#reference:random:def:b">[1]</a></sup></p><ol class="annotations"><li id="annotation:random:def:a:1" data-marker="*1"><span>a</span><sup><a href="#annotation:random:ref:a:1">^1</a></sup></li></ol><h2>References</h2><ol class="references"><li id="reference:random:def:b"><span>b</span><sup><a href="#reference:random:ref:b:1">^1</a></sup></li></ol></section></aside>'], '']);
|
|
28
27
|
assert.deepStrictEqual(inspect(parser, input('~~~~example/markdown\na\n~~~~')), [['<aside class="example" data-type="markdown"><pre translate="no">a</pre><hr><section><p>a</p><h2>References</h2><ol class="references"></ol></section></aside>'], '']);
|
|
29
28
|
assert.deepStrictEqual(inspect(parser, input('~~~example/math\na\n~~~')), [['<aside class="example" data-type="math"><pre translate="no">a</pre><hr><div class="math" translate="no">$$\na\n$$</div></aside>'], '']);
|
|
30
|
-
assert.deepStrictEqual(inspect(parser, input(`~~~example/math\n0${'\n'.repeat(100)}~~~`), '>'), [['<aside class="example" data-type="math">'], '']);
|
|
31
29
|
});
|
|
32
30
|
|
|
33
31
|
});
|
|
@@ -12,7 +12,7 @@ interface Memory {
|
|
|
12
12
|
}
|
|
13
13
|
|
|
14
14
|
export const example: ExtensionParser.ExampleParser = block(recursion(Recursion.block, inits([
|
|
15
|
-
fence(/(~{3,})(?:example\/(\S+))?(?!\S)([^\r\n]*)(?:$|\r?\n)/y, true
|
|
15
|
+
fence(/(~{3,})(?:example\/(\S+))?(?!\S)([^\r\n]*)(?:$|\r?\n)/y, true),
|
|
16
16
|
(input: Input<Memory>, output) => {
|
|
17
17
|
const [body, overflow, closer, opener, delim, type = 'markdown', param] = unwrap(output.pop()) as string[];
|
|
18
18
|
if (!closer || overflow || param.trimStart()) return output.append(
|
|
@@ -27,7 +27,7 @@ export const example: ExtensionParser.ExampleParser = block(recursion(Recursion.
|
|
|
27
27
|
overflow ? `Invalid trailing line after the closing delimiter "${delim}"` :
|
|
28
28
|
'Invalid argument'),
|
|
29
29
|
},
|
|
30
|
-
`${opener}${body}${
|
|
30
|
+
`${opener}${body}${closer}${overflow}`)));
|
|
31
31
|
switch (type) {
|
|
32
32
|
case 'markdown': {
|
|
33
33
|
input.memory = {
|
|
@@ -1,30 +1,28 @@
|
|
|
1
1
|
import { ExtensionParser } from '../../block';
|
|
2
2
|
import { Segment } from '../../context';
|
|
3
3
|
import { Result } from '../../../combinator/parser';
|
|
4
|
-
import { union, sequence, some, always,
|
|
4
|
+
import { union, sequence, some, always, block, line, rewrite, close } from '../../../combinator';
|
|
5
5
|
import { contentline } from '../../source';
|
|
6
6
|
import { figure } from './figure';
|
|
7
7
|
import { segment as seg_label } from '../../inline/extension/label';
|
|
8
8
|
import { segment as seg_code } from '../codeblock';
|
|
9
9
|
import { segment as seg_math } from '../mathblock';
|
|
10
|
-
import { segment as seg_table } from './table';
|
|
11
|
-
import { segment as seg_blockquote } from '../blockquote';
|
|
12
10
|
import { segment as seg_placeholder } from './placeholder';
|
|
11
|
+
import { segment as seg_blockquote } from '../blockquote';
|
|
13
12
|
|
|
14
13
|
import FigParser = ExtensionParser.FigParser;
|
|
15
14
|
|
|
16
|
-
export const segment: FigParser.SegmentParser =
|
|
15
|
+
export const segment: FigParser.SegmentParser = block(
|
|
17
16
|
sequence([
|
|
18
17
|
line(close(seg_label, /(?!\S)[^\r\n]*\r?\n/y), false),
|
|
19
18
|
union([
|
|
20
19
|
seg_code,
|
|
21
20
|
seg_math,
|
|
22
|
-
seg_table,
|
|
23
|
-
seg_blockquote,
|
|
24
21
|
seg_placeholder,
|
|
22
|
+
seg_blockquote,
|
|
25
23
|
some(contentline),
|
|
26
24
|
]),
|
|
27
|
-
]), true, Segment.fig)
|
|
25
|
+
]), true, Segment.fig);
|
|
28
26
|
|
|
29
27
|
export const fig: FigParser = block(rewrite(segment, always([
|
|
30
28
|
(input, output) => {
|
|
@@ -33,8 +33,6 @@ describe('Unit: parser/block/extension/figure', () => {
|
|
|
33
33
|
assert.deepStrictEqual(inspect(parser, input('~~~figure [$fig-name]\n> \n\n~~~')), [['<figure data-type="quote" data-label="fig-name" data-group="fig" class="invalid"><figcaption><span class="figindex"></span><span class="figtext"></span></figcaption><div><blockquote></blockquote></div></figure>'], '']);
|
|
34
34
|
assert.deepStrictEqual(inspect(parser, input('~~~figure [$figure-name]\n> \n\n~~~')), [['<figure data-type="quote" data-label="figure-name" data-group="figure" class="invalid"><figcaption><span class="figindex"></span><span class="figtext"></span></figcaption><div><blockquote></blockquote></div></figure>'], '']);
|
|
35
35
|
assert.deepStrictEqual(inspect(parser, input('~~~figure [$table-name]\n> \n\n~~~')), [['<figure data-type="quote" data-label="table-name" data-group="table" class="invalid"><figcaption><span class="figindex"></span><span class="figtext"></span></figcaption><div><blockquote></blockquote></div></figure>'], '']);
|
|
36
|
-
assert.deepStrictEqual(inspect(parser, input(`~~~figure [$group-name]\n0${'\n'.repeat(301)}~~~`), '>'), [['<pre class="invalid" translate="no">'], '']);
|
|
37
|
-
assert.deepStrictEqual(inspect(parser, input(`~~~figure [$group-name]\n~~~\n0${'\n'.repeat(301)}~~~\n~~~`), '>'), [['<pre class="invalid" translate="no">'], `${'\n'.repeat(300)}~~~\n~~~`]);
|
|
38
36
|
});
|
|
39
37
|
|
|
40
38
|
it('valid', () => {
|
|
@@ -70,8 +68,6 @@ describe('Unit: parser/block/extension/figure', () => {
|
|
|
70
68
|
assert.deepStrictEqual(inspect(parser, input('~~~figure [$-0.0]\n$$\n\n$$\n~~~')), [['<figure data-type="math" data-label="$-0.0" data-group="$" class="invalid"><figcaption><span class="figindex"></span><span class="figtext"></span></figcaption><div><div class="math" translate="no">$$\n\n$$</div></div></figure>'], '']);
|
|
71
69
|
assert.deepStrictEqual(inspect(parser, input('~~~figure [$-name]\n!https://host\n~~~')), [['<figure data-type="media" data-label="$-name" data-group="$" class="invalid"><figcaption><span class="figindex"></span><span class="figtext"></span></figcaption><div><a href="https://host" target="_blank"><img class="media" data-src="https://host" alt="https://host"></a></div></figure>'], '']);
|
|
72
70
|
assert.deepStrictEqual(inspect(parser, input('~~~figure [$-name]\n$$\n\n$$\n\ncaption\n~~~')), [['<figure data-type="math" data-label="$-name" data-group="$" class="invalid"><figcaption><span class="figindex"></span><span class="figtext">caption</span></figcaption><div><div class="math" translate="no">$$\n\n$$</div></div></figure>'], '']);
|
|
73
|
-
assert.deepStrictEqual(inspect(parser, input(`~~~figure [$group-name]\n${'> \n'.repeat(500)}\n~~~`), '>'), [['<figure data-type="quote" data-label="group-name" data-group="group">'], '']);
|
|
74
|
-
assert.deepStrictEqual(inspect(parser, input(`~~~figure [$group-name]\n~~~\n0${'\n'.repeat(300)}~~~\n~~~`), '>'), [['<figure data-type="example" data-label="group-name" data-group="group">'], '']);
|
|
75
71
|
});
|
|
76
72
|
|
|
77
73
|
});
|
|
@@ -10,9 +10,9 @@ import { table as styled_table } from '../table';
|
|
|
10
10
|
import { codeblock, segment_ as seg_code } from '../codeblock';
|
|
11
11
|
import { mathblock, segment_ as seg_math } from '../mathblock';
|
|
12
12
|
import { example } from './example';
|
|
13
|
-
import { table
|
|
14
|
-
import { blockquote, segment as seg_blockquote } from '../blockquote';
|
|
13
|
+
import { table } from './table';
|
|
15
14
|
import { placeholder, segment_ as seg_placeholder } from './placeholder';
|
|
15
|
+
import { blockquote, segment as seg_blockquote } from '../blockquote';
|
|
16
16
|
import { inline, media, lineshortmedia } from '../../inline';
|
|
17
17
|
import { visualize, trimBlank } from '../../visibility';
|
|
18
18
|
import { unwrap, invalid } from '../../util';
|
|
@@ -32,9 +32,8 @@ export const segment: FigureParser.SegmentParser = block(match(
|
|
|
32
32
|
union([
|
|
33
33
|
seg_code,
|
|
34
34
|
seg_math,
|
|
35
|
-
seg_table,
|
|
36
|
-
seg_blockquote,
|
|
37
35
|
seg_placeholder,
|
|
36
|
+
seg_blockquote,
|
|
38
37
|
some(contentline, closer),
|
|
39
38
|
]),
|
|
40
39
|
emptyline,
|
|
@@ -60,8 +59,8 @@ export const figure: FigureParser = block(fallback(rewrite(segment, fmap(
|
|
|
60
59
|
mathblock,
|
|
61
60
|
example,
|
|
62
61
|
table,
|
|
63
|
-
blockquote,
|
|
64
62
|
placeholder,
|
|
63
|
+
blockquote,
|
|
65
64
|
line(media, false),
|
|
66
65
|
line(lineshortmedia, false),
|
|
67
66
|
])),
|
|
@@ -84,7 +83,7 @@ export const figure: FigureParser = block(fallback(rewrite(segment, fmap(
|
|
|
84
83
|
]);
|
|
85
84
|
})),
|
|
86
85
|
inits([
|
|
87
|
-
fence(/(~{3,})(?:figure(?=$|[ \r\n])|\[?\$)[^\r\n]*(?:$|\r?\n)/y, true
|
|
86
|
+
fence(/(~{3,})(?:figure(?=$|[ \r\n])|\[?\$)[^\r\n]*(?:$|\r?\n)/y, true),
|
|
88
87
|
(_, output) => {
|
|
89
88
|
const [body, overflow, closer, opener, delim] = unwrap(output.pop()) as string[];
|
|
90
89
|
const violation =
|
|
@@ -115,7 +114,7 @@ export const figure: FigureParser = block(fallback(rewrite(segment, fmap(
|
|
|
115
114
|
translate: 'no',
|
|
116
115
|
...invalid('figure', violation[0], violation[1]),
|
|
117
116
|
},
|
|
118
|
-
`${opener}${body}${
|
|
117
|
+
`${opener}${body}${closer}${overflow}`)));
|
|
119
118
|
},
|
|
120
119
|
])));
|
|
121
120
|
|
|
@@ -12,7 +12,6 @@ describe('Unit: parser/block/extension/message', () => {
|
|
|
12
12
|
assert.deepStrictEqual(inspect(parser, input('~~~message/\n~~~')), undefined);
|
|
13
13
|
assert.deepStrictEqual(inspect(parser, input('~~~message/a\n~~~')), [['<pre class="invalid" translate="no">~~~message/a\n~~~</pre>'], '']);
|
|
14
14
|
assert.deepStrictEqual(inspect(parser, input('~~~message/note a\n~~~')), [['<pre class="invalid" translate="no">~~~message/note a\n~~~</pre>'], '']);
|
|
15
|
-
assert.deepStrictEqual(inspect(parser, input(`~~~message/note\n0${'\n'.repeat(301)}~~~`), '>'), [['<pre class="invalid" translate="no">'], '']);
|
|
16
15
|
});
|
|
17
16
|
|
|
18
17
|
it('valid', () => {
|
|
@@ -20,7 +20,7 @@ import { html } from 'typed-dom/dom';
|
|
|
20
20
|
import MessageParser = ExtensionParser.MessageParser;
|
|
21
21
|
|
|
22
22
|
export const message: MessageParser = block(inits([
|
|
23
|
-
fence(/(~{3,})message\/(\S+)(?!\S)([^\r\n]*)(?:$|\r?\n)/y, true
|
|
23
|
+
fence(/(~{3,})message\/(\S+)(?!\S)([^\r\n]*)(?:$|\r?\n)/y, true),
|
|
24
24
|
(input, output) => {
|
|
25
25
|
const [body, overflow, closer, opener, delim, type, param] = unwrap(output.pop()) as string[];
|
|
26
26
|
if (!closer || overflow || param.trimStart()) {
|
|
@@ -36,7 +36,7 @@ export const message: MessageParser = block(inits([
|
|
|
36
36
|
overflow ? `Invalid trailing line after the closing delimiter "${delim}"` :
|
|
37
37
|
'Invalid argument'),
|
|
38
38
|
},
|
|
39
|
-
`${opener}${body}${
|
|
39
|
+
`${opener}${body}${closer}${overflow}`)));
|
|
40
40
|
return;
|
|
41
41
|
}
|
|
42
42
|
switch (type) {
|