securemark 0.295.1 → 0.295.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 +4 -0
- package/design.md +4 -3
- package/dist/index.js +514 -459
- package/markdown.d.ts +13 -28
- package/package.json +1 -1
- package/src/combinator/control/constraint/block.test.ts +6 -8
- package/src/combinator/control/constraint/contract.ts +7 -7
- package/src/combinator/control/constraint/line.test.ts +7 -9
- package/src/combinator/control/constraint/line.ts +0 -1
- package/src/combinator/control/manipulation/clear.ts +2 -2
- package/src/combinator/control/manipulation/convert.ts +3 -3
- package/src/combinator/control/manipulation/duplicate.ts +4 -4
- package/src/combinator/control/manipulation/fallback.ts +2 -2
- package/src/combinator/control/manipulation/fence.ts +3 -3
- package/src/combinator/control/manipulation/indent.test.ts +20 -22
- package/src/combinator/control/manipulation/indent.ts +2 -2
- package/src/combinator/control/manipulation/recovery.ts +3 -3
- package/src/combinator/control/manipulation/reverse.ts +2 -2
- package/src/combinator/control/manipulation/scope.ts +2 -4
- package/src/combinator/control/manipulation/surround.ts +32 -32
- package/src/combinator/control/monad/bind.ts +6 -6
- package/src/combinator/control/monad/fmap.ts +6 -6
- package/src/combinator/data/data.ts +2 -2
- package/src/combinator/data/{parser/context/delimiter.ts → delimiter.ts} +4 -4
- package/src/combinator/data/parser/context.test.ts +12 -11
- package/src/combinator/data/parser/context.ts +13 -14
- package/src/combinator/data/parser/inits.ts +5 -5
- package/src/combinator/data/parser/sequence.test.ts +12 -13
- package/src/combinator/data/parser/sequence.ts +5 -5
- package/src/combinator/data/parser/some.test.ts +15 -16
- package/src/combinator/data/parser/some.ts +5 -6
- package/src/combinator/data/parser/subsequence.test.ts +16 -17
- package/src/combinator/data/parser/subsequence.ts +3 -3
- package/src/combinator/data/parser/tails.ts +3 -3
- package/src/combinator/data/parser/union.test.ts +12 -13
- package/src/combinator/data/parser/union.ts +3 -3
- package/src/combinator/data/parser.ts +55 -32
- package/src/debug.test.ts +5 -3
- package/src/parser/api/bind.ts +8 -6
- package/src/parser/api/header.ts +4 -4
- package/src/parser/api/normalize.ts +2 -1
- package/src/parser/api/parse.test.ts +7 -6
- package/src/parser/api/parse.ts +9 -8
- package/src/parser/autolink.test.ts +18 -18
- package/src/parser/block/blockquote.test.ts +79 -79
- package/src/parser/block/blockquote.ts +5 -5
- package/src/parser/block/codeblock.test.ts +57 -57
- package/src/parser/block/codeblock.ts +3 -3
- package/src/parser/block/dlist.test.ts +57 -57
- package/src/parser/block/dlist.ts +6 -6
- package/src/parser/block/extension/aside.test.ts +9 -9
- package/src/parser/block/extension/aside.ts +5 -5
- package/src/parser/block/extension/example.test.ts +19 -19
- package/src/parser/block/extension/example.ts +6 -6
- package/src/parser/block/extension/fig.test.ts +36 -36
- package/src/parser/block/extension/figbase.test.ts +16 -16
- package/src/parser/block/extension/figbase.ts +2 -2
- package/src/parser/block/extension/figure.test.ts +63 -63
- package/src/parser/block/extension/figure.ts +3 -3
- package/src/parser/block/extension/message.test.ts +14 -14
- package/src/parser/block/extension/message.ts +5 -5
- package/src/parser/block/extension/placeholder.test.ts +13 -13
- package/src/parser/block/extension/placeholder.ts +2 -2
- package/src/parser/block/extension/table.test.ts +76 -76
- package/src/parser/block/extension/table.ts +14 -14
- package/src/parser/block/extension.test.ts +24 -24
- package/src/parser/block/heading.test.ts +59 -59
- package/src/parser/block/heading.ts +7 -7
- package/src/parser/block/ilist.test.ts +8 -12
- package/src/parser/block/ilist.ts +6 -6
- package/src/parser/block/mathblock.test.ts +32 -32
- package/src/parser/block/mathblock.ts +3 -3
- package/src/parser/block/mediablock.ts +3 -3
- package/src/parser/block/olist.test.ts +103 -103
- package/src/parser/block/olist.ts +5 -5
- package/src/parser/block/pagebreak.test.ts +16 -16
- package/src/parser/block/pagebreak.ts +2 -2
- package/src/parser/block/paragraph.test.ts +58 -58
- package/src/parser/block/paragraph.ts +2 -2
- package/src/parser/block/reply/cite.test.ts +40 -40
- package/src/parser/block/reply/cite.ts +6 -6
- package/src/parser/block/reply/quote.test.ts +51 -51
- package/src/parser/block/reply/quote.ts +3 -3
- package/src/parser/block/reply.test.ts +20 -20
- package/src/parser/block/reply.ts +3 -3
- package/src/parser/block/sidefence.test.ts +48 -48
- package/src/parser/block/sidefence.ts +4 -4
- package/src/parser/block/table.test.ts +50 -50
- package/src/parser/block/table.ts +12 -12
- package/src/parser/block/ulist.test.ts +53 -53
- package/src/parser/block/ulist.ts +6 -6
- package/src/parser/block.ts +6 -4
- package/src/parser/context.ts +39 -0
- package/src/parser/header.test.ts +23 -23
- package/src/parser/header.ts +5 -5
- package/src/parser/inline/annotation.test.ts +43 -43
- package/src/parser/inline/annotation.ts +14 -4
- package/src/parser/inline/autolink/account.test.ts +33 -33
- package/src/parser/inline/autolink/account.ts +9 -9
- package/src/parser/inline/autolink/anchor.test.ts +22 -22
- package/src/parser/inline/autolink/anchor.ts +4 -4
- package/src/parser/inline/autolink/channel.test.ts +15 -15
- package/src/parser/inline/autolink/email.test.ts +37 -37
- package/src/parser/inline/autolink/email.ts +2 -2
- package/src/parser/inline/autolink/hashnum.test.ts +33 -33
- package/src/parser/inline/autolink/hashnum.ts +6 -5
- package/src/parser/inline/autolink/hashtag.test.ts +60 -60
- package/src/parser/inline/autolink/hashtag.ts +4 -4
- package/src/parser/inline/autolink/url.test.ts +75 -75
- package/src/parser/inline/autolink/url.ts +4 -4
- package/src/parser/inline/bracket.test.ts +70 -70
- package/src/parser/inline/bracket.ts +35 -32
- package/src/parser/inline/code.test.ts +31 -31
- package/src/parser/inline/code.ts +4 -4
- package/src/parser/inline/deletion.test.ts +28 -28
- package/src/parser/inline/deletion.ts +4 -4
- package/src/parser/inline/emphasis.test.ts +40 -40
- package/src/parser/inline/emphasis.ts +3 -3
- package/src/parser/inline/emstrong.test.ts +101 -101
- package/src/parser/inline/emstrong.ts +23 -23
- package/src/parser/inline/extension/index.test.ts +92 -92
- package/src/parser/inline/extension/index.ts +5 -5
- package/src/parser/inline/extension/indexee.ts +5 -5
- package/src/parser/inline/extension/indexer.test.ts +24 -24
- package/src/parser/inline/extension/indexer.ts +2 -2
- package/src/parser/inline/extension/label.test.ts +33 -33
- package/src/parser/inline/extension/label.ts +2 -2
- package/src/parser/inline/extension/placeholder.test.ts +43 -43
- package/src/parser/inline/extension/placeholder.ts +4 -4
- package/src/parser/inline/html.test.ts +108 -108
- package/src/parser/inline/html.ts +10 -10
- package/src/parser/inline/htmlentity.test.ts +38 -38
- package/src/parser/inline/htmlentity.ts +5 -5
- package/src/parser/inline/insertion.test.ts +28 -28
- package/src/parser/inline/insertion.ts +4 -4
- package/src/parser/inline/italic.test.ts +55 -55
- package/src/parser/inline/italic.ts +4 -4
- package/src/parser/inline/link.test.ts +186 -187
- package/src/parser/inline/link.ts +16 -17
- package/src/parser/inline/mark.test.ts +31 -31
- package/src/parser/inline/mark.ts +5 -5
- package/src/parser/inline/math.test.ts +132 -132
- package/src/parser/inline/math.ts +2 -2
- package/src/parser/inline/media.test.ts +91 -91
- package/src/parser/inline/media.ts +15 -15
- package/src/parser/inline/reference.test.ts +109 -109
- package/src/parser/inline/reference.ts +15 -54
- package/src/parser/inline/remark.test.ts +50 -50
- package/src/parser/inline/remark.ts +5 -5
- package/src/parser/inline/ruby.test.ts +45 -45
- package/src/parser/inline/ruby.ts +17 -17
- package/src/parser/inline/shortmedia.test.ts +10 -10
- package/src/parser/inline/strong.test.ts +37 -37
- package/src/parser/inline/strong.ts +3 -3
- package/src/parser/inline/template.test.ts +23 -23
- package/src/parser/inline/template.ts +5 -5
- package/src/parser/inline.test.ts +224 -223
- package/src/parser/segment.ts +2 -2
- package/src/parser/source/escapable.test.ts +24 -24
- package/src/parser/source/escapable.ts +8 -8
- package/src/parser/source/line.test.ts +18 -18
- package/src/parser/source/str.ts +2 -2
- package/src/parser/source/text.test.ts +85 -85
- package/src/parser/source/text.ts +5 -5
- package/src/parser/source/unescapable.test.ts +24 -24
- package/src/parser/source/unescapable.ts +5 -5
- package/src/parser/util.ts +10 -11
- package/src/parser/visibility.ts +8 -9
- package/src/util/quote.ts +2 -1
|
@@ -1,34 +1,68 @@
|
|
|
1
1
|
import { List } from './data';
|
|
2
|
-
import { Delimiters } from './
|
|
2
|
+
import { Delimiters } from './delimiter';
|
|
3
3
|
|
|
4
|
-
export type Parser<N = unknown, C extends
|
|
4
|
+
export type Parser<N = unknown, C extends Context = Context, D extends Parser<unknown, C>[] = any>
|
|
5
5
|
= (input: Input<C>) => Result<N, C, D>;
|
|
6
|
-
export
|
|
6
|
+
export namespace Parser {
|
|
7
|
+
export type Node<P extends Parser> = P extends Parser<infer N> ? N : never;
|
|
8
|
+
export type SubParsers<P extends Parser> = P extends Parser<unknown, any, infer D> ? D : never;
|
|
9
|
+
export type Context<P extends Parser> = P extends Parser<unknown, infer C> ? C : never;
|
|
10
|
+
export type SubNode<P extends Parser> = ExtractSubNode<SubParsers<P>>;
|
|
11
|
+
export type IntermediateParser<P extends Parser> = Parser<SubNode<P>, Context<P>, SubParsers<P>>;
|
|
12
|
+
type ExtractSubNode<D extends Parser[]> = ExtractSubParser<D> extends infer N ? N extends Parser<infer U> ? U : never : never;
|
|
13
|
+
type ExtractSubParser<D extends Parser[]> = D extends (infer P)[] ? P extends Parser ? P : never : never;
|
|
14
|
+
}
|
|
15
|
+
export interface Input<C extends Context = Context> {
|
|
7
16
|
readonly context: C;
|
|
8
17
|
}
|
|
9
|
-
export type Result<N, C extends
|
|
10
|
-
= List<
|
|
18
|
+
export type Result<N, C extends Context = Context, D extends Parser<unknown, C>[] = any>
|
|
19
|
+
= List<Node<N>, C, D>
|
|
11
20
|
| undefined;
|
|
12
21
|
export { List };
|
|
13
|
-
export class
|
|
22
|
+
export class Node<N> implements List.Node {
|
|
14
23
|
constructor(public value: N) {
|
|
15
24
|
}
|
|
16
25
|
public next?: this = undefined;
|
|
17
26
|
public prev?: this = undefined;
|
|
18
27
|
}
|
|
19
|
-
export
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
28
|
+
export class Context {
|
|
29
|
+
constructor(
|
|
30
|
+
{
|
|
31
|
+
source,
|
|
32
|
+
position,
|
|
33
|
+
resources,
|
|
34
|
+
delimiters,
|
|
35
|
+
precedence,
|
|
36
|
+
state,
|
|
37
|
+
linebreak,
|
|
38
|
+
range,
|
|
39
|
+
offset,
|
|
40
|
+
backtracks,
|
|
41
|
+
}: Options = {},
|
|
42
|
+
) {
|
|
43
|
+
this.source = source ?? '';
|
|
44
|
+
this.position = position ?? 0;
|
|
45
|
+
this.resources = resources;
|
|
46
|
+
this.precedence = precedence ?? 0;
|
|
47
|
+
this.delimiters = delimiters ?? new Delimiters();
|
|
48
|
+
this.state = state ?? 0;
|
|
49
|
+
this.linebreak = linebreak ?? 0;
|
|
50
|
+
this.range = range ?? 0;
|
|
51
|
+
this.offset = offset ?? 0;
|
|
52
|
+
this.backtracks = backtracks ?? {};
|
|
53
|
+
}
|
|
54
|
+
public source: string;
|
|
55
|
+
public position: number;
|
|
56
|
+
public readonly resources?: {
|
|
25
57
|
clock: number;
|
|
26
58
|
recursions: number[];
|
|
27
59
|
};
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
60
|
+
public precedence: number;
|
|
61
|
+
public delimiters: Delimiters;
|
|
62
|
+
public state: number;
|
|
63
|
+
public linebreak: number;
|
|
64
|
+
public range: number;
|
|
65
|
+
public offset: number;
|
|
32
66
|
// Objectの内部実装を利用する。
|
|
33
67
|
// 探索木を直接使用する場合は探索速度が重要で挿入は相対的に少なく削除は不要かつ不確実であるため
|
|
34
68
|
// AVL木が適当と思われる。
|
|
@@ -61,36 +95,25 @@ export interface CtxOptions {
|
|
|
61
95
|
// 1段落数百文字あたり平均2、3か所以下が妥当な頻度でありこの場合の最大追加データサイズは
|
|
62
96
|
// 入力内の最大セグメントサイズの10%前後である。
|
|
63
97
|
//
|
|
64
|
-
backtracks
|
|
65
|
-
linebreak?: number;
|
|
66
|
-
range?: number;
|
|
98
|
+
public backtracks: Record<number, number>;
|
|
67
99
|
}
|
|
68
|
-
export type
|
|
69
|
-
export type SubParsers<P extends Parser> = P extends Parser<unknown, Ctx, infer D> ? D : never;
|
|
70
|
-
export type Context<P extends Parser> = P extends Parser<unknown, infer C> ? C : never;
|
|
71
|
-
export type SubNode<P extends Parser> = ExtractSubNode<SubParsers<P>>;
|
|
72
|
-
export type IntermediateParser<P extends Parser> = Parser<SubNode<P>, Context<P>, SubParsers<P>>;
|
|
73
|
-
type ExtractSubNode<D extends Parser[]> = ExtractSubParser<D> extends infer N ? N extends Parser<infer U> ? U : never : never;
|
|
74
|
-
type ExtractSubParser<D extends Parser[]> = D extends (infer P)[] ? P extends Parser ? P : never : never;
|
|
100
|
+
export type Options = Partial<Context>;
|
|
75
101
|
|
|
76
|
-
export function input<C extends
|
|
77
|
-
// @ts-expect-error
|
|
102
|
+
export function input<C extends Context>(source: string, context: C): Input<C> {
|
|
78
103
|
context.source = source;
|
|
79
|
-
// @ts-expect-error
|
|
80
104
|
context.position = 0;
|
|
81
105
|
return {
|
|
82
|
-
// @ts-expect-error
|
|
83
106
|
context,
|
|
84
107
|
};
|
|
85
108
|
}
|
|
86
109
|
|
|
87
|
-
export function subinput<C extends
|
|
110
|
+
export function subinput<C extends Context>(source: string, context: C): Input<C> {
|
|
88
111
|
return {
|
|
89
112
|
context: {
|
|
90
113
|
...context,
|
|
91
114
|
source,
|
|
92
115
|
position: 0,
|
|
93
|
-
offset:
|
|
116
|
+
offset: 0,
|
|
94
117
|
backtracks: {},
|
|
95
118
|
}
|
|
96
119
|
};
|
package/src/debug.test.ts
CHANGED
|
@@ -1,8 +1,10 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { Parser, Input } 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
|
-
export function inspect(
|
|
5
|
+
export function inspect(parser: Parser<DocumentFragment | HTMLElement | string>, input: Input, until: number | string = Infinity): [string[], string] | undefined {
|
|
6
|
+
const { context } = input;
|
|
7
|
+
const result = parser(input);
|
|
6
8
|
return result && [
|
|
7
9
|
result.foldl<string[]>((acc, { value: node }) => {
|
|
8
10
|
assert(node);
|
|
@@ -34,7 +36,7 @@ export function inspect(result: Result<DocumentFragment | HTMLElement | string>,
|
|
|
34
36
|
}
|
|
35
37
|
return acc.push(normalize(node.outerHTML.slice(0, until))), acc;
|
|
36
38
|
}, []),
|
|
37
|
-
|
|
39
|
+
context.source.slice(context.position),
|
|
38
40
|
];
|
|
39
41
|
}
|
|
40
42
|
|
package/src/parser/api/bind.ts
CHANGED
|
@@ -1,8 +1,7 @@
|
|
|
1
1
|
import { ParserSettings, Progress } from '../../..';
|
|
2
|
-
import {
|
|
2
|
+
import { Context } from '../context';
|
|
3
3
|
import { input } from '../../combinator/data/parser';
|
|
4
4
|
import { segment } from '../segment';
|
|
5
|
-
import { header } from '../header';
|
|
6
5
|
import { block } from '../block';
|
|
7
6
|
import { normalize } from './normalize';
|
|
8
7
|
import { headers } from './header';
|
|
@@ -19,13 +18,12 @@ export function bind(target: DocumentFragment | HTMLElement | ShadowRoot, settin
|
|
|
19
18
|
nearest: (position: number) => HTMLElement | undefined;
|
|
20
19
|
index: (block: HTMLElement) => number;
|
|
21
20
|
} {
|
|
22
|
-
const context
|
|
21
|
+
const context = new Context({
|
|
23
22
|
...settings,
|
|
24
23
|
host: settings.host ?? new ReadonlyURL(location.pathname, location.origin),
|
|
25
|
-
};
|
|
24
|
+
});
|
|
26
25
|
assert(!context.offset);
|
|
27
26
|
assert(!context.precedence);
|
|
28
|
-
assert(!context.delimiters);
|
|
29
27
|
assert(!context.state);
|
|
30
28
|
if (context.id?.match(/[^0-9a-z/-]/i)) throw new Error('Invalid ID: ID must be alphanumeric');
|
|
31
29
|
if (context.host?.origin === 'null') throw new Error(`Invalid host: ${context.host.href}`);
|
|
@@ -72,11 +70,15 @@ export function bind(target: DocumentFragment | HTMLElement | ShadowRoot, settin
|
|
|
72
70
|
assert(head + last <= targetSegments.length);
|
|
73
71
|
const base = next(head);
|
|
74
72
|
let index = head;
|
|
73
|
+
// @ts-expect-error
|
|
74
|
+
context.header = true;
|
|
75
75
|
for (; index < sourceSegments.length - last; ++index) {
|
|
76
76
|
assert(rev === revision);
|
|
77
77
|
const seg = sourceSegments[index];
|
|
78
|
-
const es =
|
|
78
|
+
const es = block(input(seg, context))
|
|
79
79
|
?.foldl<HTMLElement[]>((acc, { value }) => void acc.push(value) || acc, []) ?? [];
|
|
80
|
+
// @ts-expect-error
|
|
81
|
+
context.header = false;
|
|
80
82
|
blocks.splice(index, 0, [seg, es, url]);
|
|
81
83
|
if (es.length === 0) continue;
|
|
82
84
|
// All deletion processes always run after all addition processes have done.
|
package/src/parser/api/header.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { Context } from '../context';
|
|
2
2
|
import { header as h } from '../header';
|
|
3
3
|
|
|
4
4
|
export function header(source: string): string {
|
|
@@ -12,10 +12,10 @@ export function headers(source: string): string[] {
|
|
|
12
12
|
}
|
|
13
13
|
|
|
14
14
|
function parse(source: string): [HTMLElement, number] | [] {
|
|
15
|
-
const
|
|
16
|
-
const result = h(
|
|
15
|
+
const context = new Context({ source });
|
|
16
|
+
const result = h({ context });
|
|
17
17
|
const el = result?.head?.value;
|
|
18
18
|
return el?.tagName === 'ASIDE'
|
|
19
|
-
? [el,
|
|
19
|
+
? [el, context.position]
|
|
20
20
|
: [];
|
|
21
21
|
}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { input } from '../../combinator/data/parser';
|
|
2
|
+
import { Context } from '../context';
|
|
2
3
|
import { unsafehtmlentity } from '../inline/htmlentity';
|
|
3
4
|
|
|
4
5
|
const UNICODE_REPLACEMENT_CHARACTER = '\uFFFD';
|
|
@@ -68,7 +69,7 @@ const unreadableEscapeHTMLEntityNames = invisibleHTMLEntityNames.filter(name =>
|
|
|
68
69
|
'zwnj',
|
|
69
70
|
].includes(name));
|
|
70
71
|
const unreadableEscapeCharacters = unreadableEscapeHTMLEntityNames
|
|
71
|
-
.map(name => unsafehtmlentity(input(`&${name};`,
|
|
72
|
+
.map(name => unsafehtmlentity(input(`&${name};`, new Context()))!.head!.value);
|
|
72
73
|
assert(unreadableEscapeCharacters.length === unreadableEscapeHTMLEntityNames.length);
|
|
73
74
|
assert(unreadableEscapeCharacters.every(c => c.length === 1));
|
|
74
75
|
const unreadableEscapeCharacter = new RegExp(`[${unreadableEscapeCharacters.join('')}]`, 'g');
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { parse } from './parse';
|
|
2
|
+
import { Context } from '../context';
|
|
2
3
|
import { html } from 'typed-dom/dom';
|
|
3
4
|
|
|
4
5
|
describe('Unit: parser/api/parse', () => {
|
|
@@ -361,20 +362,20 @@ describe('Unit: parser/api/parse', () => {
|
|
|
361
362
|
|
|
362
363
|
it('backtrack', function () {
|
|
363
364
|
this.timeout(5000);
|
|
364
|
-
// 最悪計算量での実行速度はCommonMarkの公式JS実装の32nに対して
|
|
365
|
-
//
|
|
366
|
-
const source = `((([[[[#$[${'.'.repeat(
|
|
365
|
+
// 最悪計算量での実行速度はCommonMarkの公式JS実装の32nに対して50-400%程度。
|
|
366
|
+
// 6n = annotation + reference + link + url/math + ruby + text
|
|
367
|
+
const source = `((([[[[#$[${'.'.repeat(16665)}`;
|
|
367
368
|
assert.deepStrictEqual(
|
|
368
|
-
[...parse(source, {}, { resources: { clock: 100000, recursions: [100] } }).children]
|
|
369
|
+
[...parse(source, {}, new Context({ resources: { clock: 100000, recursions: [100] } })).children]
|
|
369
370
|
.map(el => el.tagName),
|
|
370
371
|
['P']);
|
|
371
372
|
});
|
|
372
373
|
|
|
373
374
|
it('backtrack error', function () {
|
|
374
375
|
this.timeout(5000);
|
|
375
|
-
const source = `((([[[[#$[${'.'.repeat(
|
|
376
|
+
const source = `((([[[[#$[${'.'.repeat(16665 + 1)}`;
|
|
376
377
|
assert.deepStrictEqual(
|
|
377
|
-
[...parse(source, {}, { resources: { clock: 100000, recursions: [100] } }).children]
|
|
378
|
+
[...parse(source, {}, new Context({ resources: { clock: 100000, recursions: [100] } })).children]
|
|
378
379
|
.map(el => el.tagName),
|
|
379
380
|
['H1', 'PRE']);
|
|
380
381
|
});
|
package/src/parser/api/parse.ts
CHANGED
|
@@ -1,8 +1,7 @@
|
|
|
1
1
|
import { ParserOptions } from '../../..';
|
|
2
|
-
import { MarkdownParser } from '../../../markdown';
|
|
3
2
|
import { input } from '../../combinator/data/parser';
|
|
3
|
+
import { Context } from '../context';
|
|
4
4
|
import { segment } from '../segment';
|
|
5
|
-
import { header } from '../header';
|
|
6
5
|
import { block } from '../block';
|
|
7
6
|
import { normalize } from './normalize';
|
|
8
7
|
import { headers } from './header';
|
|
@@ -15,28 +14,30 @@ interface Options extends ParserOptions {
|
|
|
15
14
|
readonly test?: boolean;
|
|
16
15
|
}
|
|
17
16
|
|
|
18
|
-
export function parse(source: string, options: Options = {}, context?:
|
|
17
|
+
export function parse(source: string, options: Options = {}, context?: Context): DocumentFragment {
|
|
19
18
|
const url = headers(source).find(field => field.toLowerCase().startsWith('url:'))?.slice(4).trim() ?? '';
|
|
20
19
|
source = !context ? normalize(source) : source;
|
|
21
|
-
context = {
|
|
20
|
+
context = new Context({
|
|
22
21
|
host: options.host ?? context?.host ?? new ReadonlyURL(location.pathname, location.origin),
|
|
23
22
|
url: url ? new ReadonlyURL(url as ':') : context?.url,
|
|
24
23
|
id: options.id ?? context?.id,
|
|
25
24
|
caches: context?.caches,
|
|
26
25
|
resources: context?.resources,
|
|
27
|
-
};
|
|
26
|
+
});
|
|
28
27
|
assert(!context.offset);
|
|
29
28
|
assert(!context.precedence);
|
|
30
|
-
assert(!context.delimiters);
|
|
31
29
|
assert(!context.state);
|
|
32
30
|
if (context.id?.match(/[^0-9a-z/-]/i)) throw new Error('Invalid ID: ID must be alphanumeric');
|
|
33
31
|
if (context.host?.origin === 'null') throw new Error(`Invalid host: ${context.host.href}`);
|
|
34
32
|
const node = frag();
|
|
35
|
-
|
|
33
|
+
// @ts-expect-error
|
|
34
|
+
context.header = true;
|
|
36
35
|
for (const seg of segment(source)) {
|
|
37
36
|
node.append(
|
|
38
|
-
...
|
|
37
|
+
...block(input(seg, context))
|
|
39
38
|
?.foldl<HTMLElement[]>((acc, { value }) => void acc.push(value) || acc, []) ?? []);
|
|
39
|
+
// @ts-expect-error
|
|
40
|
+
context.header = false;
|
|
40
41
|
}
|
|
41
42
|
assert(options.id !== '' || !node.querySelector('[id], .index[href], .label[href], .annotation > a[href], .reference > a[href]'));
|
|
42
43
|
if (options.test) return node;
|
|
@@ -1,29 +1,29 @@
|
|
|
1
1
|
import { autolink } from './autolink';
|
|
2
2
|
import { input } from '../combinator/data/parser';
|
|
3
|
+
import { Context } from './context';
|
|
3
4
|
import { inspect } from '../debug.test';
|
|
4
5
|
|
|
5
6
|
describe('Unit: parser/autolink', () => {
|
|
6
7
|
describe('autolink', () => {
|
|
7
|
-
const parser =
|
|
8
|
-
const { context: ctx } = input('', {});
|
|
8
|
+
const parser = autolink;
|
|
9
9
|
|
|
10
10
|
it('basic', () => {
|
|
11
|
-
assert.deepStrictEqual(inspect(parser('http://host)'
|
|
12
|
-
assert.deepStrictEqual(inspect(parser('http://host\\'
|
|
13
|
-
assert.deepStrictEqual(inspect(parser('!http://host)'
|
|
14
|
-
assert.deepStrictEqual(inspect(parser('!http://host\\'
|
|
15
|
-
assert.deepStrictEqual(inspect(parser('#a'
|
|
16
|
-
assert.deepStrictEqual(inspect(parser('@a#b'
|
|
17
|
-
assert.deepStrictEqual(inspect(parser('\\\n'
|
|
18
|
-
assert.deepStrictEqual(inspect(parser('a#b'
|
|
19
|
-
assert.deepStrictEqual(inspect(parser('0a#b'
|
|
20
|
-
assert.deepStrictEqual(inspect(parser('あ#b'
|
|
21
|
-
assert.deepStrictEqual(inspect(parser('あい#b'
|
|
22
|
-
assert.deepStrictEqual(inspect(parser('0aあ#b'
|
|
23
|
-
assert.deepStrictEqual(inspect(parser('0aあい#b'
|
|
24
|
-
assert.deepStrictEqual(inspect(parser('a\n#b'
|
|
25
|
-
assert.deepStrictEqual(inspect(parser('a\\\n#b'
|
|
26
|
-
assert.deepStrictEqual(inspect(parser('0a>>b'
|
|
11
|
+
assert.deepStrictEqual(inspect(parser, input('http://host)', new Context())), [['<a class="url" href="http://host)" target="_blank">http://host)</a>'], '']);
|
|
12
|
+
assert.deepStrictEqual(inspect(parser, input('http://host\\', new Context())), [['<a class="url" href="http://host\\" target="_blank">http://host\\</a>'], '']);
|
|
13
|
+
assert.deepStrictEqual(inspect(parser, input('!http://host)', new Context())), [['!', '<a class="url" href="http://host)" target="_blank">http://host)</a>'], '']);
|
|
14
|
+
assert.deepStrictEqual(inspect(parser, input('!http://host\\', new Context())), [['!', '<a class="url" href="http://host\\" target="_blank">http://host\\</a>'], '']);
|
|
15
|
+
assert.deepStrictEqual(inspect(parser, input('#a', new Context())), [['<a class="hashtag" href="/hashtags/a">#a</a>'], '']);
|
|
16
|
+
assert.deepStrictEqual(inspect(parser, input('@a#b', new Context())), [['<a class="channel" href="/@a?ch=b">@a#b</a>'], '']);
|
|
17
|
+
assert.deepStrictEqual(inspect(parser, input('\\\n', new Context())), [['\\', '<br>'], '']);
|
|
18
|
+
assert.deepStrictEqual(inspect(parser, input('a#b', new Context())), [['a', '#b'], '']);
|
|
19
|
+
assert.deepStrictEqual(inspect(parser, input('0a#b', new Context())), [['0a', '#b'], '']);
|
|
20
|
+
assert.deepStrictEqual(inspect(parser, input('あ#b', new Context())), [['あ', '#b'], '']);
|
|
21
|
+
assert.deepStrictEqual(inspect(parser, input('あい#b', new Context())), [['あい', '#b'], '']);
|
|
22
|
+
assert.deepStrictEqual(inspect(parser, input('0aあ#b', new Context())), [['0a', 'あ', '#b'], '']);
|
|
23
|
+
assert.deepStrictEqual(inspect(parser, input('0aあい#b', new Context())), [['0a', 'あい', '#b'], '']);
|
|
24
|
+
assert.deepStrictEqual(inspect(parser, input('a\n#b', new Context())), [['a', '<br>', '<a class="hashtag" href="/hashtags/b">#b</a>'], '']);
|
|
25
|
+
assert.deepStrictEqual(inspect(parser, input('a\\\n#b', new Context())), [['a', '\\', '<br>', '<a class="hashtag" href="/hashtags/b">#b</a>'], '']);
|
|
26
|
+
assert.deepStrictEqual(inspect(parser, input('0a>>b', new Context())), [['0a', '>', '>b'], '']);
|
|
27
27
|
});
|
|
28
28
|
|
|
29
29
|
});
|