securemark 0.300.3 → 0.300.5
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 +230 -180
- package/index.d.ts +2 -2
- package/markdown.d.ts +36 -36
- package/package.json +1 -1
- package/src/api/bind.test.ts +3 -1
- package/src/api/bind.ts +6 -3
- package/src/api/header.ts +1 -1
- package/src/api/parse.ts +8 -2
- package/src/combinator/effect/backtrack.ts +19 -7
- package/src/combinator/parser/list.ts +13 -15
- package/src/combinator/parser.ts +3 -5
- package/src/debug.test.ts +3 -0
- package/src/parser/autolink.ts +2 -2
- package/src/parser/block/blockquote.test.ts +4 -4
- package/src/parser/block/blockquote.ts +2 -1
- package/src/parser/block/extension/aside.test.ts +3 -3
- package/src/parser/block/extension/aside.ts +2 -1
- package/src/parser/block/extension/example.test.ts +3 -3
- package/src/parser/block/extension/example.ts +3 -1
- package/src/parser/{header.test.ts → block/header.test.ts} +3 -3
- package/src/parser/{header.ts → block/header.ts} +7 -7
- package/src/parser/block/reply/cite.ts +2 -3
- package/src/parser/block/reply/quote.ts +1 -2
- package/src/parser/block/reply.ts +1 -2
- package/src/parser/block.ts +6 -5
- package/src/parser/context.ts +3 -1
- package/src/parser/document.ts +25 -22
- package/src/parser/inline/annotation.ts +11 -5
- package/src/parser/inline/extension/index.ts +1 -2
- package/src/parser/inline/extension/indexee.ts +1 -2
- package/src/parser/inline/extension/label.ts +10 -6
- package/src/parser/inline/html.ts +1 -2
- package/src/parser/inline/htmlentity.ts +5 -4
- package/src/parser/inline/media.ts +2 -3
- package/src/parser/inline/reference.ts +3 -3
- package/src/parser/inline.test.ts +1 -0
- package/src/parser/inline.ts +2 -2
- package/src/parser/node.ts +0 -5
- package/src/parser/repeat.ts +5 -1
- package/src/parser/segment.ts +2 -2
- package/src/parser/source/escapable.ts +5 -6
- package/src/parser/source/str.ts +3 -2
- package/src/parser/source/text.ts +3 -4
- package/src/parser/source/unescapable.ts +3 -4
- package/src/parser/source.ts +2 -2
- package/src/parser/util.ts +9 -0
- package/src/parser/visibility.ts +4 -5
- package/src/processor/figure.test.ts +35 -24
- package/src/processor/figure.ts +11 -27
- package/src/processor/note.test.ts +71 -25
- package/src/processor/note.ts +45 -35
- package/src/util/toc.ts +2 -3
package/index.d.ts
CHANGED
|
@@ -42,8 +42,8 @@ export interface ParserSettings {
|
|
|
42
42
|
export type Progress =
|
|
43
43
|
| { readonly type: 'segment'; readonly value: string; }
|
|
44
44
|
| { readonly type: 'block'; readonly value: HTMLElement; }
|
|
45
|
-
| { readonly type: 'figure';
|
|
46
|
-
| { readonly type: 'note'; readonly value:
|
|
45
|
+
| { readonly type: 'figure'; }
|
|
46
|
+
| { readonly type: 'note'; readonly value: HTMLOListElement; }
|
|
47
47
|
| { readonly type: 'break'; readonly value: 'segment' | 'block' | 'parser' | 'figure' | 'note'; }
|
|
48
48
|
| { readonly type: 'cancel'; };
|
|
49
49
|
|
package/markdown.d.ts
CHANGED
|
@@ -1,19 +1,18 @@
|
|
|
1
1
|
import { Parser, List, Node } from './src/combinator/parser';
|
|
2
2
|
import { Input } from './src/parser/context';
|
|
3
3
|
|
|
4
|
-
declare abstract class
|
|
4
|
+
declare abstract class Document<T> {
|
|
5
5
|
private parser?: T;
|
|
6
6
|
}
|
|
7
|
-
export interface
|
|
8
|
-
|
|
7
|
+
export interface DocumentParser extends
|
|
8
|
+
Document<'document'>,
|
|
9
9
|
Parser<DocumentFragment, Input, [
|
|
10
|
-
|
|
11
|
-
MarkdownParser.BlockParser,
|
|
10
|
+
DocumentParser.BlockParser,
|
|
12
11
|
]> {
|
|
13
12
|
}
|
|
14
|
-
export namespace
|
|
13
|
+
export namespace DocumentParser {
|
|
15
14
|
export interface SegmentParser extends
|
|
16
|
-
|
|
15
|
+
Document<'segment'>,
|
|
17
16
|
Parser<string, Input, [
|
|
18
17
|
SourceParser.EmptySegmentParser,
|
|
19
18
|
Parser<string, Input, [
|
|
@@ -25,39 +24,19 @@ export namespace MarkdownParser {
|
|
|
25
24
|
SourceParser.ContentLineParser,
|
|
26
25
|
]> {
|
|
27
26
|
}
|
|
28
|
-
export interface HeaderParser extends
|
|
29
|
-
// ---
|
|
30
|
-
// url: https://host/path
|
|
31
|
-
// ---
|
|
32
|
-
Markdown<'header'>,
|
|
33
|
-
Parser<HTMLElement | HTMLPreElement, Input, [
|
|
34
|
-
Parser<HTMLElement | HTMLPreElement, Input, [
|
|
35
|
-
Parser<HTMLElement, Input, [
|
|
36
|
-
HeaderParser.FieldParser,
|
|
37
|
-
]>,
|
|
38
|
-
Parser<HTMLPreElement, Input, []>,
|
|
39
|
-
]>,
|
|
40
|
-
Parser<never, Input, []>,
|
|
41
|
-
]> {
|
|
42
|
-
}
|
|
43
|
-
export namespace HeaderParser {
|
|
44
|
-
export interface FieldParser extends
|
|
45
|
-
Markdown<'header/field'>,
|
|
46
|
-
Parser<HTMLSpanElement, Input, []> {
|
|
47
|
-
}
|
|
48
|
-
}
|
|
49
27
|
export interface BlockParser extends
|
|
50
|
-
|
|
28
|
+
Document<'block'>,
|
|
51
29
|
Parser<HTMLElement, Input, [
|
|
52
30
|
SourceParser.EmptySegmentParser,
|
|
53
31
|
Parser<HTMLElement, Input, [
|
|
54
|
-
BlockParser.
|
|
32
|
+
BlockParser.HeaderParser,
|
|
55
33
|
BlockParser.HeadingParser,
|
|
56
34
|
BlockParser.UListParser,
|
|
57
35
|
BlockParser.OListParser,
|
|
58
36
|
BlockParser.IListParser,
|
|
59
37
|
BlockParser.DListParser,
|
|
60
38
|
BlockParser.TableParser,
|
|
39
|
+
BlockParser.PagebreakParser,
|
|
61
40
|
BlockParser.CodeBlockParser,
|
|
62
41
|
BlockParser.MathBlockParser,
|
|
63
42
|
BlockParser.ExtensionParser,
|
|
@@ -70,7 +49,28 @@ export namespace MarkdownParser {
|
|
|
70
49
|
]> {
|
|
71
50
|
}
|
|
72
51
|
export namespace BlockParser {
|
|
73
|
-
interface Block<T extends string> extends
|
|
52
|
+
interface Block<T extends string> extends Document<`block/${T}`> { }
|
|
53
|
+
export interface HeaderParser extends
|
|
54
|
+
// ---
|
|
55
|
+
// url: https://host/path
|
|
56
|
+
// ---
|
|
57
|
+
Block<'header'>,
|
|
58
|
+
Parser<HTMLElement | HTMLPreElement, Input, [
|
|
59
|
+
Parser<HTMLElement | HTMLPreElement, Input, [
|
|
60
|
+
Parser<HTMLElement, Input, [
|
|
61
|
+
HeaderParser.FieldParser,
|
|
62
|
+
]>,
|
|
63
|
+
Parser<HTMLPreElement, Input, []>,
|
|
64
|
+
]>,
|
|
65
|
+
Parser<never, Input, []>,
|
|
66
|
+
]> {
|
|
67
|
+
}
|
|
68
|
+
export namespace HeaderParser {
|
|
69
|
+
export interface FieldParser extends
|
|
70
|
+
Block<'header/field'>,
|
|
71
|
+
Parser<HTMLSpanElement, Input, []> {
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
74
|
export interface PagebreakParser extends
|
|
75
75
|
// ===
|
|
76
76
|
Block<'pagebreak'>,
|
|
@@ -520,7 +520,7 @@ export namespace MarkdownParser {
|
|
|
520
520
|
Parser<HTMLElement, Input, [
|
|
521
521
|
Parser<string, Input, []>,
|
|
522
522
|
Parser<HTMLElement, Input, []>,
|
|
523
|
-
|
|
523
|
+
DocumentParser,
|
|
524
524
|
Parser<HTMLElement, Input, []>,
|
|
525
525
|
]> {
|
|
526
526
|
}
|
|
@@ -635,7 +635,7 @@ export namespace MarkdownParser {
|
|
|
635
635
|
}
|
|
636
636
|
}
|
|
637
637
|
export interface InlineParser extends
|
|
638
|
-
|
|
638
|
+
Document<'inline'>,
|
|
639
639
|
Parser<HTMLElement | string, Input, [
|
|
640
640
|
Parser<HTMLElement | string, Input, [
|
|
641
641
|
InlineParser.AnnotationParser,
|
|
@@ -663,7 +663,7 @@ export namespace MarkdownParser {
|
|
|
663
663
|
]> {
|
|
664
664
|
}
|
|
665
665
|
export namespace InlineParser {
|
|
666
|
-
interface Inline<T extends string> extends
|
|
666
|
+
interface Inline<T extends string> extends Document<`inline/${T}`> { }
|
|
667
667
|
export interface AnnotationParser extends
|
|
668
668
|
// ((abc))
|
|
669
669
|
Inline<'annotation'>,
|
|
@@ -1173,14 +1173,14 @@ export namespace MarkdownParser {
|
|
|
1173
1173
|
}
|
|
1174
1174
|
}
|
|
1175
1175
|
export interface AutolinkParser extends
|
|
1176
|
-
|
|
1176
|
+
Document<'autolink'>,
|
|
1177
1177
|
Parser<string | HTMLElement, Input, [
|
|
1178
1178
|
InlineParser.AutolinkParser,
|
|
1179
1179
|
SourceParser.UnescapableSourceParser,
|
|
1180
1180
|
]> {
|
|
1181
1181
|
}
|
|
1182
1182
|
export namespace SourceParser {
|
|
1183
|
-
interface Source<T extends string> extends
|
|
1183
|
+
interface Source<T extends string> extends Document<`source/${T}`> { }
|
|
1184
1184
|
export interface TextParser extends
|
|
1185
1185
|
// abc
|
|
1186
1186
|
Source<'text'>,
|
package/package.json
CHANGED
package/src/api/bind.test.ts
CHANGED
package/src/api/bind.ts
CHANGED
|
@@ -126,14 +126,17 @@ export function bind(target: DocumentFragment | HTMLElement | ShadowRoot, settin
|
|
|
126
126
|
}
|
|
127
127
|
yield { type: 'break', value: 'parser' };
|
|
128
128
|
if (rev !== revision) return yield { type: 'cancel' };
|
|
129
|
-
for (const el of figure(next(0)?.parentNode ?? target, settings.notes, options)) {
|
|
129
|
+
for (const el of figure(next(0)?.parentNode ?? target, output.labels.pop()!, settings.notes, options)) {
|
|
130
130
|
assert(rev === revision);
|
|
131
131
|
el
|
|
132
|
-
? yield { type: 'figure'
|
|
132
|
+
? yield { type: 'figure' }
|
|
133
133
|
: yield { type: 'break', value: 'figure' };
|
|
134
134
|
if (rev !== revision) return yield { type: 'cancel' };
|
|
135
135
|
}
|
|
136
|
-
for (const el of note(next(0)?.parentNode ?? target,
|
|
136
|
+
for (const el of note(next(0)?.parentNode ?? target, {
|
|
137
|
+
annotations: output.annotations.pop()!,
|
|
138
|
+
references: output.references.pop()!,
|
|
139
|
+
}, settings.notes, options, bottom)) {
|
|
137
140
|
assert(rev === revision);
|
|
138
141
|
el
|
|
139
142
|
? yield { type: 'note', value: el }
|
package/src/api/header.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { Input } from '../parser/context';
|
|
2
2
|
import { Output, run } from '../combinator/parser';
|
|
3
|
-
import { header as h } from '../parser/header';
|
|
3
|
+
import { header as h } from '../parser/block/header';
|
|
4
4
|
|
|
5
5
|
export function header(source: string): string {
|
|
6
6
|
const [, pos = 0] = parse(source);
|
package/src/api/parse.ts
CHANGED
|
@@ -1,12 +1,15 @@
|
|
|
1
1
|
import { ParserOptions } from '../..';
|
|
2
2
|
import { Input, Options } from '../parser/context';
|
|
3
|
-
import { Output, run } from '../combinator/parser';
|
|
3
|
+
import { Output, List, Node, run } from '../combinator/parser';
|
|
4
4
|
import { document } from '../parser/document';
|
|
5
5
|
import { ReadonlyURL } from 'spica/url';
|
|
6
6
|
|
|
7
|
-
interface Opts extends ParserOptions {
|
|
7
|
+
export interface Opts extends ParserOptions {
|
|
8
8
|
readonly local?: boolean;
|
|
9
9
|
readonly test?: boolean;
|
|
10
|
+
readonly labels?: List<Node<HTMLAnchorElement>>;
|
|
11
|
+
readonly annotations?: List<Node<HTMLElement>>;
|
|
12
|
+
readonly references?: List<Node<HTMLElement>>;
|
|
10
13
|
}
|
|
11
14
|
|
|
12
15
|
export function* parse(source: string, opts: Opts = {}, options?: Options): Generator<void, DocumentFragment, void> {
|
|
@@ -23,6 +26,9 @@ export function* parse(source: string, opts: Opts = {}, options?: Options): Gene
|
|
|
23
26
|
if (options.id?.match(/[^0-9a-z/-]/i)) throw new Error('Invalid ID: ID must be alphanumeric');
|
|
24
27
|
if (options.host?.origin === 'null') throw new Error(`Invalid host: ${options.host.href}`);
|
|
25
28
|
const output = new Output<DocumentFragment>();
|
|
29
|
+
assert(output.labels[0] = opts.labels ?? output.labels[0]);
|
|
30
|
+
assert(output.annotations[0] = opts.annotations ?? output.annotations[0]);
|
|
31
|
+
assert(output.references[0] = opts.references ?? output.references[0]);
|
|
26
32
|
for (const _ of run(document, new Input(options, source), output)) yield;
|
|
27
33
|
assert(output.data.length === 1);
|
|
28
34
|
assert(output.peek().length === 1);
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { always } from '../control/state';
|
|
2
|
-
import { Parser, Input } from '../parser';
|
|
2
|
+
import { Parser, Input, Output, List } from '../parser';
|
|
3
3
|
import { Scope } from './scope';
|
|
4
4
|
|
|
5
5
|
interface Data {
|
|
@@ -30,8 +30,8 @@ export class Backtrack {
|
|
|
30
30
|
input.range = range;
|
|
31
31
|
input.linebreak = linebreak;
|
|
32
32
|
}
|
|
33
|
-
public handle(
|
|
34
|
-
state
|
|
33
|
+
public handle(output: Output<unknown>): void {
|
|
34
|
+
output.state
|
|
35
35
|
? this.unmemory()
|
|
36
36
|
: this.backtrack();
|
|
37
37
|
}
|
|
@@ -50,14 +50,26 @@ export function backtrack<T>(parser: Parser<T>): Parser<T> {
|
|
|
50
50
|
linebreak,
|
|
51
51
|
});
|
|
52
52
|
output.push();
|
|
53
|
+
output.labels.push(new List());
|
|
54
|
+
output.annotations.push(new List());
|
|
55
|
+
output.references.push(new List());
|
|
53
56
|
return output.context;
|
|
54
57
|
},
|
|
55
58
|
parser,
|
|
56
59
|
({ backtrack }, output) => {
|
|
57
|
-
output
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
60
|
+
backtrack.handle(output);
|
|
61
|
+
if (output.state) {
|
|
62
|
+
output.import(output.pop());
|
|
63
|
+
output.labels.at(-2)!.import(output.labels.pop()!);
|
|
64
|
+
output.annotations.at(-2)!.import(output.annotations.pop()!);
|
|
65
|
+
output.references.at(-2)!.import(output.references.pop()!);
|
|
66
|
+
}
|
|
67
|
+
else {
|
|
68
|
+
output.pop();
|
|
69
|
+
output.labels.pop();
|
|
70
|
+
output.annotations.pop();
|
|
71
|
+
output.references.pop();
|
|
72
|
+
}
|
|
61
73
|
return output.context;
|
|
62
74
|
},
|
|
63
75
|
]);
|
|
@@ -8,6 +8,9 @@ export class List<N extends List.Node = List.Node, I extends Input = Input, S ex
|
|
|
8
8
|
}
|
|
9
9
|
}
|
|
10
10
|
public length = 0;
|
|
11
|
+
public isEmpty(): boolean {
|
|
12
|
+
return this.head === undefined;
|
|
13
|
+
}
|
|
11
14
|
public head?: N = undefined;
|
|
12
15
|
public last?: N = undefined;
|
|
13
16
|
public get tail(): N | undefined {
|
|
@@ -93,18 +96,6 @@ export class List<N extends List.Node = List.Node, I extends Input = Input, S ex
|
|
|
93
96
|
list.clear();
|
|
94
97
|
return this;
|
|
95
98
|
}
|
|
96
|
-
public truncateBefore(node: N): void {
|
|
97
|
-
assert(node.next || node.prev || this.head === this.last);
|
|
98
|
-
if (node.prev === undefined) return;
|
|
99
|
-
this.delete(node.prev);
|
|
100
|
-
this.head = node;
|
|
101
|
-
}
|
|
102
|
-
public truncateAfter(node: N): void {
|
|
103
|
-
assert(node.next || node.prev || this.head === this.last);
|
|
104
|
-
if (node.next === undefined) return;
|
|
105
|
-
this.delete(node.next);
|
|
106
|
-
this.last = node;
|
|
107
|
-
}
|
|
108
99
|
public clear(): void {
|
|
109
100
|
this.length = 0;
|
|
110
101
|
this.head = this.last = undefined;
|
|
@@ -155,12 +146,19 @@ export namespace List {
|
|
|
155
146
|
prev?: this;
|
|
156
147
|
}
|
|
157
148
|
}
|
|
158
|
-
export class Node<
|
|
149
|
+
export class Node<T> implements List.Node {
|
|
159
150
|
constructor(
|
|
160
|
-
public value:
|
|
161
|
-
public
|
|
151
|
+
public value: T,
|
|
152
|
+
public position: number = 0,
|
|
153
|
+
public flags: Node.Flag = 0,
|
|
162
154
|
) {
|
|
163
155
|
}
|
|
164
156
|
public next?: this = undefined;
|
|
165
157
|
public prev?: this = undefined;
|
|
166
158
|
}
|
|
159
|
+
export namespace Node {
|
|
160
|
+
export const enum Flag {
|
|
161
|
+
none,
|
|
162
|
+
blank,
|
|
163
|
+
}
|
|
164
|
+
}
|
package/src/combinator/parser.ts
CHANGED
|
@@ -142,6 +142,9 @@ export class Output<T> {
|
|
|
142
142
|
public state: boolean = true;
|
|
143
143
|
public readonly context: Result.Succ | Result.Fail = Result.succ;
|
|
144
144
|
public error?: Error = undefined;
|
|
145
|
+
public readonly labels: List<Node<HTMLAnchorElement>>[] = [new List()];
|
|
146
|
+
public readonly annotations: List<Node<HTMLElement>>[] = [new List()];
|
|
147
|
+
public readonly references: List<Node<HTMLElement>>[] = [new List()];
|
|
145
148
|
public peek(): List<Node<T>> {
|
|
146
149
|
assert(this.data.length > 0);
|
|
147
150
|
return this.data.at(-1)!;
|
|
@@ -163,11 +166,6 @@ export class Output<T> {
|
|
|
163
166
|
this.data[this.data.length - 1] = list;
|
|
164
167
|
return Result.succ;
|
|
165
168
|
}
|
|
166
|
-
public flat(): Result.Succ | Result.Fail {
|
|
167
|
-
assert(this.data.length > 1);
|
|
168
|
-
this.import(this.data.pop()!);
|
|
169
|
-
return Result.succ;
|
|
170
|
-
}
|
|
171
169
|
public push(list: List<Node<T>> = new List()): void {
|
|
172
170
|
this.data.push(list);
|
|
173
171
|
}
|
package/src/debug.test.ts
CHANGED
|
@@ -6,6 +6,9 @@ export function inspect(parser: Parser<DocumentFragment | HTMLElement | string>,
|
|
|
6
6
|
const output = new Output<DocumentFragment | HTMLElement | string>();
|
|
7
7
|
for (const _ of run(parser, input, output));
|
|
8
8
|
assert.deepStrictEqual(output.data, [output.data[0]]);
|
|
9
|
+
assert(output.labels.length === 1);
|
|
10
|
+
assert(output.annotations.length === 1);
|
|
11
|
+
assert(output.references.length === 1);
|
|
9
12
|
assert(output.state || output.peek().length === 0);
|
|
10
13
|
assert(!output.error);
|
|
11
14
|
return !output.state ? undefined : [
|
package/src/parser/autolink.ts
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { DocumentParser } from '../../markdown';
|
|
2
2
|
import { union, some, lazy } from '../combinator';
|
|
3
3
|
import { autolink as autolink_ } from './inline/autolink';
|
|
4
4
|
import { unescsource } from './source';
|
|
5
5
|
|
|
6
|
-
export import AutolinkParser =
|
|
6
|
+
export import AutolinkParser = DocumentParser.AutolinkParser;
|
|
7
7
|
|
|
8
8
|
export const autolink: AutolinkParser = lazy(() =>
|
|
9
9
|
some(union([
|
|
@@ -77,7 +77,7 @@ describe('Unit: parser/block/blockquote', () => {
|
|
|
77
77
|
assert.deepStrictEqual(inspect(parser, input('!> a \n b c ')), [['<blockquote><section><p> a<br> b c</p><h2>References</h2><ol class="references"></ol></section></blockquote>'], '']);
|
|
78
78
|
assert.deepStrictEqual(inspect(parser, input('!>> a')), [['<blockquote><blockquote><section><p>a</p><h2>References</h2><ol class="references"></ol></section></blockquote></blockquote>'], '']);
|
|
79
79
|
assert.deepStrictEqual(inspect(parser, input('!>> a\n> b')), [['<blockquote><blockquote><section><p>a</p><h2>References</h2><ol class="references"></ol></section></blockquote><section><p>b</p><h2>References</h2><ol class="references"></ol></section></blockquote>'], '']);
|
|
80
|
-
assert.deepStrictEqual(inspect(parser, input('!> - a')), [['<blockquote><section><ul><li id="index:random:a"
|
|
80
|
+
assert.deepStrictEqual(inspect(parser, input('!> - a')), [['<blockquote><section><ul><li id="index:random:a">a</li></ul><h2>References</h2><ol class="references"></ol></section></blockquote>'], '']);
|
|
81
81
|
assert.deepStrictEqual(inspect(parser, input('!> ```\na\n```')), [['<blockquote><section><pre class="text">a</pre><h2>References</h2><ol class="references"></ol></section></blockquote>'], '']);
|
|
82
82
|
assert.deepStrictEqual(inspect(parser, input('!> ```\n> a\n```')), [['<blockquote><section><pre class="text">a</pre><h2>References</h2><ol class="references"></ol></section></blockquote>'], '']);
|
|
83
83
|
assert.deepStrictEqual(inspect(parser, input('!> ```\n> a\n> ```')), [['<blockquote><section><pre class="text">a</pre><h2>References</h2><ol class="references"></ol></section></blockquote>'], '']);
|
|
@@ -90,10 +90,10 @@ describe('Unit: parser/block/blockquote', () => {
|
|
|
90
90
|
assert.deepStrictEqual(inspect(parser, input('!>> > a\n> b')), [['<blockquote><blockquote><section><blockquote><pre>a</pre></blockquote><h2>References</h2><ol class="references"></ol></section></blockquote><section><p>b</p><h2>References</h2><ol class="references"></ol></section></blockquote>'], '']);
|
|
91
91
|
assert.deepStrictEqual(inspect(parser, input('!> !> a')), [['<blockquote><section><blockquote><section><p>a</p><h2>References</h2><ol class="references"></ol></section></blockquote><h2>References</h2><ol class="references"></ol></section></blockquote>'], '']);
|
|
92
92
|
assert.deepStrictEqual(inspect(parser, input('!> \na')), [['<blockquote><section><p>a</p><h2>References</h2><ol class="references"></ol></section></blockquote>'], '']);
|
|
93
|
-
assert.deepStrictEqual(inspect(parser, input('!>> ## a\n> ## a')), [['<blockquote><blockquote><section><h2 id="index:random:a"
|
|
94
|
-
assert.deepStrictEqual(inspect(parser, input('!>> ~ a\n> ~ a')), [['<blockquote><blockquote><section><dl><dt id="index:random:a"
|
|
93
|
+
assert.deepStrictEqual(inspect(parser, input('!>> ## a\n> ## a')), [['<blockquote><blockquote><section><h2 id="index:random:a">a</h2><h2>References</h2><ol class="references"></ol></section></blockquote><section><h2 id="index:random:a">a</h2><h2>References</h2><ol class="references"></ol></section></blockquote>'], '']);
|
|
94
|
+
assert.deepStrictEqual(inspect(parser, input('!>> ~ a\n> ~ a')), [['<blockquote><blockquote><section><dl><dt id="index:random:a">a</dt><dd></dd></dl><h2>References</h2><ol class="references"></ol></section></blockquote><section><dl><dt id="index:random:a">a</dt><dd></dd></dl><h2>References</h2><ol class="references"></ol></section></blockquote>'], '']);
|
|
95
95
|
assert.deepStrictEqual(inspect(parser, input('!>> ~~~figure $test-a\n>> > \n>>\n~~~\n> ~~~figure $test-a\n> > \n>\n[#a]\n~~~')), [['<blockquote><blockquote><section><figure data-type="quote" data-label="test-a" data-group="test" data-number="1" id="label:random:test-a"><figcaption><span class="figindex">Test 1. </span><span class="figtext"></span></figcaption><div><blockquote></blockquote></div></figure><h2>References</h2><ol class="references"></ol></section></blockquote><section><figure data-type="quote" data-label="test-a" data-group="test" data-number="1" id="label:random:test-a"><figcaption><span class="figindex">Test 1. </span><span class="figtext"><a class="index" href="#index:random:a">a</a></span></figcaption><div><blockquote></blockquote></div></figure><h2>References</h2><ol class="references"></ol></section></blockquote>'], '']);
|
|
96
|
-
assert.deepStrictEqual(inspect(parser, input('!>> ((a))\n> ((a))')), [['<blockquote><blockquote><section><p><sup class="annotation
|
|
96
|
+
assert.deepStrictEqual(inspect(parser, input('!>> ((a))\n> ((a))')), [['<blockquote><blockquote><section><p><sup class="annotation" id="annotation:random:ref:a:1" title="a"><a href="#annotation:random:def:a:1">*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"></ol></section></blockquote><section><p><sup class="annotation" id="annotation:random:ref:a:1" title="a"><a href="#annotation:random:def:a:1">*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"></ol></section></blockquote>'], '']);
|
|
97
97
|
});
|
|
98
98
|
|
|
99
99
|
});
|
|
@@ -54,7 +54,8 @@ const markdown: BlockquoteParser.MarkdownParser = lazy(() => fmap(
|
|
|
54
54
|
const doc = output.pop().head!.value;
|
|
55
55
|
if (!doc.firstChild) return output.context;
|
|
56
56
|
return output.append(new Node(html('section', [
|
|
57
|
-
|
|
57
|
+
// DocumentFragmentを追加すると異常に重くなるので避ける
|
|
58
|
+
...doc.children,
|
|
58
59
|
html('h2', 'References'),
|
|
59
60
|
notes!.references,
|
|
60
61
|
])));
|
|
@@ -14,9 +14,9 @@ describe('Unit: parser/block/extension/aside', () => {
|
|
|
14
14
|
});
|
|
15
15
|
|
|
16
16
|
it('valid', () => {
|
|
17
|
-
assert.deepStrictEqual(inspect(parser, input('~~~aside\n# 0\n~~~')), [['<aside id="index::0" class="aside"><h1 id="index:random:0"
|
|
18
|
-
assert.deepStrictEqual(inspect(parser, input('~~~aside\n## 0\n~~~')), [['<aside id="index::0" class="aside"><h2 id="index:random:0"
|
|
19
|
-
assert.deepStrictEqual(inspect(parser, input('~~~aside\n# 0\n\n$-0.0\n\n## 1\n\n$test-a\n> \n~~~')), [['<aside id="index::0" class="aside"><h1 id="index:random:0"
|
|
17
|
+
assert.deepStrictEqual(inspect(parser, input('~~~aside\n# 0\n~~~')), [['<aside id="index::0" class="aside"><h1 id="index:random:0">0</h1><h2>References</h2><ol class="references"></ol></aside>'], '']);
|
|
18
|
+
assert.deepStrictEqual(inspect(parser, input('~~~aside\n## 0\n~~~')), [['<aside id="index::0" class="aside"><h2 id="index:random:0">0</h2><h2>References</h2><ol class="references"></ol></aside>'], '']);
|
|
19
|
+
assert.deepStrictEqual(inspect(parser, input('~~~aside\n# 0\n\n$-0.0\n\n## 1\n\n$test-a\n> \n~~~')), [['<aside id="index::0" class="aside"><h1 id="index:random:0">0</h1><figure data-label="$-0.0" data-group="$" hidden="" data-number="0.0"></figure><h2 id="index:random:1">1</h2><figure data-type="quote" data-label="test-a" data-group="test" data-number="1.1" id="label:random:test-a"><figcaption><span class="figindex">Test 1.1. </span><span class="figtext"></span></figcaption><div><blockquote></blockquote></div></figure><h2>References</h2><ol class="references"></ol></aside>'], '']);
|
|
20
20
|
});
|
|
21
21
|
|
|
22
22
|
});
|
|
@@ -21,9 +21,9 @@ describe('Unit: parser/block/extension/example', () => {
|
|
|
21
21
|
assert.deepStrictEqual(inspect(parser, input('~~~example/markdown\n++a\nb++\n~~~')), [['<aside class="example" data-type="markdown"><pre translate="no">++a\nb++</pre><hr><section><p><ins>a<br>b</ins></p><h2>References</h2><ol class="references"></ol></section></aside>'], '']);
|
|
22
22
|
assert.deepStrictEqual(inspect(parser, input('~~~example/markdown\n$fig-a\n!https://host\n~~~')), [['<aside class="example" data-type="markdown"><pre translate="no">$fig-a\n!https://host</pre><hr><section><figure data-type="media" data-label="fig-a" data-group="fig" data-number="1" id="label:random:fig-a"><figcaption><span class="figindex">Fig. 1. </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><h2>References</h2><ol class="references"></ol></section></aside>'], '']);
|
|
23
23
|
assert.deepStrictEqual(inspect(parser, input('~~~example/markdown\n[$fig-a]\n!https://host\n~~~')), [['<aside class="example" data-type="markdown"><pre translate="no">[$fig-a]\n!https://host</pre><hr><section><figure data-type="media" data-label="fig-a" data-group="fig" data-number="1" id="label:random:fig-a"><figcaption><span class="figindex">Fig. 1. </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><h2>References</h2><ol class="references"></ol></section></aside>'], '']);
|
|
24
|
-
assert.deepStrictEqual(inspect(parser, input('~~~example/markdown\n## a\n~~~')), [['<aside class="example" data-type="markdown"><pre translate="no">## a</pre><hr><section><h2 id="index:random:a"
|
|
25
|
-
assert.deepStrictEqual(inspect(parser, input('~~~example/markdown\n~ a\n~~~')), [['<aside class="example" data-type="markdown"><pre translate="no">~ a</pre><hr><section><dl><dt id="index:random:a"
|
|
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
|
|
24
|
+
assert.deepStrictEqual(inspect(parser, input('~~~example/markdown\n## a\n~~~')), [['<aside class="example" data-type="markdown"><pre translate="no">## a</pre><hr><section><h2 id="index:random:a">a</h2><h2>References</h2><ol class="references"></ol></section></aside>'], '']);
|
|
25
|
+
assert.deepStrictEqual(inspect(parser, input('~~~example/markdown\n~ a\n~~~')), [['<aside class="example" data-type="markdown"><pre translate="no">~ a</pre><hr><section><dl><dt id="index:random:a">a</dt><dd></dd></dl><h2>References</h2><ol class="references"></ol></section></aside>'], '']);
|
|
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" id="annotation:random:ref:a:1" title="a"><a href="#annotation:random:def:a:1">*1</a></sup><sup class="reference" 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>'], '']);
|
|
27
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>'], '']);
|
|
28
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>'], '']);
|
|
29
29
|
});
|
|
@@ -66,6 +66,7 @@ const contMD: Result<DocumentFragment | HTMLElement, Input<Memory>> = [
|
|
|
66
66
|
(input, output) => {
|
|
67
67
|
const { notes } = input;
|
|
68
68
|
input = input.scope.pop();
|
|
69
|
+
const doc = output.pop().head!.value;
|
|
69
70
|
return output.append(
|
|
70
71
|
new Node(html('aside',
|
|
71
72
|
{ class: 'example', 'data-type': 'markdown' },
|
|
@@ -73,7 +74,8 @@ const contMD: Result<DocumentFragment | HTMLElement, Input<Memory>> = [
|
|
|
73
74
|
html('pre', { translate: 'no' }, input.memory.body.slice(0, input.memory.body.at(-2) === '\r' ? -2 : -1)),
|
|
74
75
|
html('hr'),
|
|
75
76
|
html('section', [
|
|
76
|
-
|
|
77
|
+
// DocumentFragmentを追加すると異常に重くなるので避ける
|
|
78
|
+
...doc.children,
|
|
77
79
|
html('h2', 'References'),
|
|
78
80
|
notes!.references,
|
|
79
81
|
]),
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { header } from './header';
|
|
2
|
-
import { input } from '
|
|
3
|
-
import { inspect } from '
|
|
2
|
+
import { input } from '../context';
|
|
3
|
+
import { inspect } from '../../debug.test';
|
|
4
4
|
|
|
5
|
-
describe('Unit: parser/header', () => {
|
|
5
|
+
describe('Unit: parser/block/header', () => {
|
|
6
6
|
describe('header', () => {
|
|
7
7
|
const parser = header;
|
|
8
8
|
|
|
@@ -1,12 +1,12 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { List, Node } from '
|
|
3
|
-
import { union, inits, some, scope, block, line, validate, focus, clear, lazy, fmap } from '
|
|
4
|
-
import { str } from '
|
|
5
|
-
import { unwrap, invalid } from '
|
|
1
|
+
import { HeaderParser } from '../block';
|
|
2
|
+
import { List, Node } from '../../combinator/parser';
|
|
3
|
+
import { union, inits, some, scope, block, line, validate, focus, clear, lazy, fmap } from '../../combinator';
|
|
4
|
+
import { str } from '../source';
|
|
5
|
+
import { unwrap, invalid } from '../util';
|
|
6
6
|
import { ReadonlyURL } from 'spica/url';
|
|
7
7
|
import { html, defrag } from 'typed-dom/dom';
|
|
8
8
|
|
|
9
|
-
export const header:
|
|
9
|
+
export const header: HeaderParser = lazy(() => validate(
|
|
10
10
|
/---+[^\S\r\n]*\r?\n(?=\S)/y,
|
|
11
11
|
inits([
|
|
12
12
|
block(
|
|
@@ -40,7 +40,7 @@ export const header: MarkdownParser.HeaderParser = lazy(() => validate(
|
|
|
40
40
|
clear(str(/[^\S\r\n]*\r?\n/y)),
|
|
41
41
|
])));
|
|
42
42
|
|
|
43
|
-
const field:
|
|
43
|
+
const field: HeaderParser.FieldParser = line((input, output) => {
|
|
44
44
|
const { source, position } = input;
|
|
45
45
|
const name = source.slice(position, source.indexOf(':', position));
|
|
46
46
|
const value = source.slice(position + name.length + 1).trim();
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import { ReplyParser } from '../../block';
|
|
2
2
|
import { List, Node } from '../../../combinator/parser';
|
|
3
|
-
import { Flag } from '../../node';
|
|
4
3
|
import { union, line, focus, open, fmap } from '../../../combinator';
|
|
5
4
|
import { anchor } from '../../inline/autolink/anchor';
|
|
6
5
|
import { str } from '../../source';
|
|
@@ -20,7 +19,7 @@ export const cite: ReplyParser.CiteParser = line(fmap(
|
|
|
20
19
|
focus(/>>https?:\/\/\S+(?=\s*$)/y, ({ source }, output) => output.append(new Node(html('a', { class: 'anchor', href: source.slice(2).trimEnd(), target: '_blank' }, source)))),
|
|
21
20
|
focus(/>>\S+(?=\s*$)/y, ({ source }, output) => output.append(new Node(source))),
|
|
22
21
|
])),
|
|
23
|
-
nodes => {
|
|
22
|
+
(nodes, { position }) => {
|
|
24
23
|
const quotes = nodes.head!.value as string;
|
|
25
24
|
const node = nodes.last!.value;
|
|
26
25
|
return new List([
|
|
@@ -34,6 +33,6 @@ export const cite: ReplyParser.CiteParser = line(fmap(
|
|
|
34
33
|
? define(node, { 'data-depth': `${quotes.length + 1}` }, node.innerText.slice(1))
|
|
35
34
|
: node.slice(1),
|
|
36
35
|
]))),
|
|
37
|
-
new Node(html('br'), Flag.blank),
|
|
36
|
+
new Node(html('br'), position, Node.Flag.blank),
|
|
38
37
|
]);
|
|
39
38
|
}));
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import { ReplyParser } from '../../block';
|
|
2
2
|
import { List, Node } from '../../../combinator/parser';
|
|
3
|
-
import { Flag } from '../../node';
|
|
4
3
|
import { union, some, scope, block, validate, rewrite, fmap } from '../../../combinator';
|
|
5
4
|
import { math } from '../../inline/math';
|
|
6
5
|
import { autolink } from '../../inline/autolink';
|
|
@@ -23,7 +22,7 @@ export const quote: ReplyParser.QuoteParser = block(fmap(
|
|
|
23
22
|
])),
|
|
24
23
|
true)),
|
|
25
24
|
(ns, { source, position }) => new List([
|
|
26
|
-
new Node(source[position - 1] === '\n' ? ns.pop()!.value as HTMLBRElement : html('br'), Flag.blank),
|
|
25
|
+
new Node(source[position - 1] === '\n' ? ns.pop()!.value as HTMLBRElement : html('br'), position, Node.Flag.blank),
|
|
27
26
|
new Node(html('span', { class: 'quote' }, defrag(unwrap(ns)))),
|
|
28
27
|
].reverse())),
|
|
29
28
|
false);
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import { ReplyParser } from '../block';
|
|
2
2
|
import { List, Node } from '../../combinator/parser';
|
|
3
|
-
import { Flag } from '../node';
|
|
4
3
|
import { union, some, block, validate, rewrite, fmap } from '../../combinator';
|
|
5
4
|
import { cite, syntax as csyntax } from './reply/cite';
|
|
6
5
|
import { quote, syntax as qsyntax } from './reply/quote';
|
|
@@ -21,6 +20,6 @@ export const reply: ReplyParser = block(validate(csyntax, fmap(
|
|
|
21
20
|
visualize(fmap(some(inline), (ns, { source, position }) =>
|
|
22
21
|
source[position - 1] === '\n'
|
|
23
22
|
? ns
|
|
24
|
-
: ns.push(new Node(html('br'), Flag.blank)))))
|
|
23
|
+
: ns.push(new Node(html('br'), position, Node.Flag.blank)))))
|
|
25
24
|
])),
|
|
26
25
|
ns => new List([new Node(html('p', defrag(unwrap(trimBlankNodeEnd(ns)))))]))));
|