securemark 0.297.7 → 0.298.1
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 +140 -288
- package/package.json +1 -1
- package/src/combinator/control/constraint/block.test.ts +4 -4
- package/src/combinator/control/constraint/block.ts +1 -1
- package/src/combinator/control/constraint/line.test.ts +5 -5
- package/src/combinator/control/constraint/line.ts +1 -1
- package/src/combinator/control/manipulation/convert.ts +1 -1
- package/src/combinator/control/manipulation/fence.ts +1 -1
- package/src/combinator/control/manipulation/indent.test.ts +1 -1
- package/src/combinator/control/manipulation/indent.ts +1 -1
- package/src/combinator/control/manipulation/match.ts +1 -1
- package/src/combinator/control/manipulation/recovery.ts +1 -1
- package/src/combinator/control/manipulation/scope.ts +6 -8
- package/src/combinator/control/manipulation/surround.ts +1 -1
- package/src/combinator/control/monad/bind.ts +1 -1
- package/src/combinator/data/delimiter.ts +5 -5
- package/src/combinator/data/parser/context.test.ts +2 -2
- package/src/combinator/data/parser/context.ts +10 -10
- package/src/combinator/data/parser/inits.ts +1 -1
- package/src/combinator/data/parser/sequence.test.ts +2 -2
- package/src/combinator/data/parser/sequence.ts +1 -1
- package/src/combinator/data/parser/some.test.ts +2 -2
- package/src/combinator/data/parser/some.ts +1 -1
- package/src/combinator/data/parser/subsequence.test.ts +3 -3
- package/src/combinator/data/parser/union.test.ts +2 -2
- package/src/combinator/data/parser.ts +10 -16
- package/src/debug.test.ts +3 -3
- package/src/parser/api/header.ts +1 -1
- package/src/parser/api/parse.test.ts +3 -2
- package/src/parser/api/parse.ts +2 -0
- package/src/parser/block/blockquote.test.ts +5 -5
- package/src/parser/block/blockquote.ts +4 -3
- package/src/parser/block/extension/aside.test.ts +3 -3
- package/src/parser/block/extension/aside.ts +3 -3
- package/src/parser/block/extension/example.test.ts +5 -5
- package/src/parser/block/extension/example.ts +3 -3
- package/src/parser/block/extension/fig.ts +1 -1
- package/src/parser/block/heading.ts +1 -1
- package/src/parser/block/ilist.ts +2 -2
- package/src/parser/block/mediablock.ts +1 -1
- package/src/parser/block/olist.ts +2 -2
- package/src/parser/block/reply/cite.ts +3 -3
- package/src/parser/block/table.ts +3 -3
- package/src/parser/block/ulist.ts +1 -1
- package/src/parser/block.ts +2 -2
- package/src/parser/context.ts +6 -3
- package/src/parser/header.ts +3 -3
- package/src/parser/inline/annotation.ts +1 -1
- package/src/parser/inline/autolink/url.test.ts +1 -1
- package/src/parser/inline/autolink/url.ts +2 -2
- package/src/parser/inline/autolink.ts +1 -1
- package/src/parser/inline/bracket.ts +2 -2
- package/src/parser/inline/emstrong.ts +4 -4
- package/src/parser/inline/extension/indexee.ts +17 -9
- package/src/parser/inline/math.ts +1 -1
- package/src/parser/inline/reference.ts +1 -1
- package/src/parser/inline/remark.ts +1 -1
- package/src/parser/inline/ruby.ts +1 -1
- package/src/parser/inline.ts +1 -1
- package/src/parser/processor/figure.test.ts +27 -27
- package/src/parser/processor/figure.ts +10 -4
- package/src/parser/processor/note.test.ts +17 -16
- package/src/parser/processor/note.ts +11 -5
- package/src/parser/segment.ts +2 -2
- package/src/parser/source/escapable.ts +1 -1
- package/src/parser/source/line.ts +4 -4
- package/src/parser/source/str.ts +1 -1
- package/src/parser/source/text.ts +1 -1
- package/src/parser/source/unescapable.ts +1 -1
- package/src/parser/util.ts +6 -1
- package/src/parser/visibility.ts +1 -1
- package/src/util/quote.ts +1 -1
- package/src/util/toc.ts +1 -1
|
@@ -16,9 +16,9 @@ describe('Unit: parser/block/extension/aside', () => {
|
|
|
16
16
|
});
|
|
17
17
|
|
|
18
18
|
it('valid', () => {
|
|
19
|
-
assert.deepStrictEqual(inspect(parser, input('~~~aside\n# 0\n~~~', new Context())), [['<aside id="index::0" class="aside"><h1>0</h1><h2>References</h2><ol class="references"></ol></aside>'], '']);
|
|
20
|
-
assert.deepStrictEqual(inspect(parser, input('~~~aside\n## 0\n~~~', new Context())), [['<aside id="index::0" class="aside"><h2>0</h2><h2>References</h2><ol class="references"></ol></aside>'], '']);
|
|
21
|
-
assert.deepStrictEqual(inspect(parser, input('~~~aside\n# 0\n\n$-0.0\n\n## 1\n\n$test-a\n> \n~~~', new Context())), [['<aside id="index::0" class="aside"><h1>0</h1><figure data-label="$-0.0" data-group="$" hidden="" data-number="0.0"></figure><h2>1</h2><figure data-type="quote" data-label="test-a" data-group="test" data-number="1.1"><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>'], '']);
|
|
19
|
+
assert.deepStrictEqual(inspect(parser, input('~~~aside\n# 0\n~~~', new Context())), [['<aside id="index::0" class="aside"><h1 id="index:random:0" class="local">0</h1><h2>References</h2><ol class="references"></ol></aside>'], '']);
|
|
20
|
+
assert.deepStrictEqual(inspect(parser, input('~~~aside\n## 0\n~~~', new Context())), [['<aside id="index::0" class="aside"><h2 id="index:random:0" class="local">0</h2><h2>References</h2><ol class="references"></ol></aside>'], '']);
|
|
21
|
+
assert.deepStrictEqual(inspect(parser, input('~~~aside\n# 0\n\n$-0.0\n\n## 1\n\n$test-a\n> \n~~~', new Context())), [['<aside id="index::0" class="aside"><h1 id="index:random:0" class="local">0</h1><figure data-label="$-0.0" data-group="$" hidden="" data-number="0.0"></figure><h2 id="index:random:1" class="local">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>'], '']);
|
|
22
22
|
});
|
|
23
23
|
|
|
24
24
|
});
|
|
@@ -3,7 +3,7 @@ import { Recursion } from '../../context';
|
|
|
3
3
|
import { List, Node } from '../../../combinator/data/parser';
|
|
4
4
|
import { recursion, block, fence, fmap } from '../../../combinator';
|
|
5
5
|
import { identity } from '../../inline/extension/indexee';
|
|
6
|
-
import { unwrap, invalid } from '../../util';
|
|
6
|
+
import { unwrap, invalid, randomID } from '../../util';
|
|
7
7
|
import { parse } from '../../api/parse';
|
|
8
8
|
import { html } from 'typed-dom/dom';
|
|
9
9
|
|
|
@@ -26,12 +26,12 @@ export const aside: ExtensionParser.AsideParser = block(recursion(Recursion.bloc
|
|
|
26
26
|
]);
|
|
27
27
|
const references = html('ol', { class: 'references' });
|
|
28
28
|
const document = parse(body.slice(0, -1), {
|
|
29
|
-
|
|
29
|
+
local: true,
|
|
30
|
+
id: context.id === '' ? '' : randomID(),
|
|
30
31
|
notes: {
|
|
31
32
|
references,
|
|
32
33
|
},
|
|
33
34
|
}, context);
|
|
34
|
-
assert(!document.querySelector('[id]'));
|
|
35
35
|
const heading = 'H1 H2 H3 H4 H5 H6'.split(' ').includes(document.firstElementChild?.tagName!) && document.firstElementChild as HTMLHeadingElement;
|
|
36
36
|
if (!heading) return new List([
|
|
37
37
|
new Node(html('pre', {
|
|
@@ -21,11 +21,11 @@ describe('Unit: parser/block/extension/example', () => {
|
|
|
21
21
|
assert.deepStrictEqual(inspect(parser, input('~~~example/markdown\n\n~~~', new Context())), [['<aside class="example" data-type="markdown"><pre translate="no"></pre><hr><section><h2>References</h2><ol class="references"></ol></section></aside>'], '']);
|
|
22
22
|
assert.deepStrictEqual(inspect(parser, input('~~~example/markdown\na\n~~~', new Context())), [['<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>'], '']);
|
|
23
23
|
assert.deepStrictEqual(inspect(parser, input('~~~example/markdown\n++a\nb++\n~~~', new Context())), [['<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>'], '']);
|
|
24
|
-
assert.deepStrictEqual(inspect(parser, input('~~~example/markdown\n$fig-a\n!https://host\n~~~', new Context())), [['<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"><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>'], '']);
|
|
25
|
-
assert.deepStrictEqual(inspect(parser, input('~~~example/markdown\n[$fig-a]\n!https://host\n~~~', new Context())), [['<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"><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>'], '']);
|
|
26
|
-
assert.deepStrictEqual(inspect(parser, input('~~~example/markdown\n## a\n~~~', new Context())), [['<aside class="example" data-type="markdown"><pre translate="no">## a</pre><hr><section><h2>a</h2><h2>References</h2><ol class="references"></ol></section></aside>'], '']);
|
|
27
|
-
assert.deepStrictEqual(inspect(parser, input('~~~example/markdown\n~ a\n~~~', new Context())), [['<aside class="example" data-type="markdown"><pre translate="no">~ a</pre><hr><section><dl><dt>a</dt><dd></dd></dl><h2>References</h2><ol class="references"></ol></section></aside>'], '']);
|
|
28
|
-
assert.deepStrictEqual(inspect(parser, input('~~~example/markdown\n((a))[[b]]\n~~~', new Context())), [['<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$fig-a\n!https://host\n~~~', new Context())), [['<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>'], '']);
|
|
25
|
+
assert.deepStrictEqual(inspect(parser, input('~~~example/markdown\n[$fig-a]\n!https://host\n~~~', new Context())), [['<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>'], '']);
|
|
26
|
+
assert.deepStrictEqual(inspect(parser, input('~~~example/markdown\n## a\n~~~', new Context())), [['<aside class="example" data-type="markdown"><pre translate="no">## a</pre><hr><section><h2 id="index:random:a" class="local">a</h2><h2>References</h2><ol class="references"></ol></section></aside>'], '']);
|
|
27
|
+
assert.deepStrictEqual(inspect(parser, input('~~~example/markdown\n~ a\n~~~', new Context())), [['<aside class="example" data-type="markdown"><pre translate="no">~ a</pre><hr><section><dl><dt id="index:random:a" class="local">a</dt><dd></dd></dl><h2>References</h2><ol class="references"></ol></section></aside>'], '']);
|
|
28
|
+
assert.deepStrictEqual(inspect(parser, input('~~~example/markdown\n((a))[[b]]\n~~~', new Context())), [['<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>'], '']);
|
|
29
29
|
assert.deepStrictEqual(inspect(parser, input('~~~~example/markdown\na\n~~~~', new Context())), [['<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>'], '']);
|
|
30
30
|
assert.deepStrictEqual(inspect(parser, input('~~~example/math\na\n~~~', new Context())), [['<aside class="example" data-type="math"><pre translate="no">a</pre><hr><div class="math" translate="no">$$\na\n$$</div></aside>'], '']);
|
|
31
31
|
assert.deepStrictEqual(inspect(parser, input(`~~~example/math\n0${'\n'.repeat(100)}~~~`, new Context()), '>'), [['<aside class="example" data-type="math">'], '']);
|
|
@@ -3,7 +3,7 @@ import { Recursion } from '../../context';
|
|
|
3
3
|
import { List, Node, subinput } from '../../../combinator/data/parser';
|
|
4
4
|
import { recursion, block, fence, fmap } from '../../../combinator';
|
|
5
5
|
import { mathblock } from '../mathblock';
|
|
6
|
-
import { unwrap, invalid } from '../../util';
|
|
6
|
+
import { unwrap, invalid, randomID } from '../../util';
|
|
7
7
|
import { parse } from '../../api/parse';
|
|
8
8
|
import { html } from 'typed-dom/dom';
|
|
9
9
|
|
|
@@ -28,12 +28,12 @@ export const example: ExtensionParser.ExampleParser = block(recursion(Recursion.
|
|
|
28
28
|
case 'markdown': {
|
|
29
29
|
const references = html('ol', { class: 'references' });
|
|
30
30
|
const document = parse(body.slice(0, -1), {
|
|
31
|
-
|
|
31
|
+
local: true,
|
|
32
|
+
id: context.id === '' ? '' : randomID(),
|
|
32
33
|
notes: {
|
|
33
34
|
references,
|
|
34
35
|
},
|
|
35
36
|
}, context);
|
|
36
|
-
assert(!document.querySelector('[id]'));
|
|
37
37
|
return new List([
|
|
38
38
|
new Node(html('aside', { class: 'example', 'data-type': 'markdown' }, [
|
|
39
39
|
html('pre', { translate: 'no' }, body.slice(0, -1)),
|
|
@@ -32,7 +32,7 @@ export const fig: FigParser = block(rewrite(segment, verify(convert(
|
|
|
32
32
|
const fence = (/^[^\n]*\n!?>+ /.test(source) && source.match(/^~{3,}(?=[^\S\n]*$)/gm) as string[] || [])
|
|
33
33
|
.reduce((max, fence) => fence > max ? fence : max, '~~') + '~';
|
|
34
34
|
const { position } = context;
|
|
35
|
-
const result = parser(
|
|
35
|
+
const result = parser(context);
|
|
36
36
|
context.position = position;
|
|
37
37
|
context.segment = Segment.figure | Segment.write;
|
|
38
38
|
return result
|
|
@@ -11,7 +11,7 @@ import { html, defrag } from 'typed-dom/dom';
|
|
|
11
11
|
export const segment: HeadingParser.SegmentParser = block(focus(
|
|
12
12
|
/#+ +\S[^\n]*(?:\n#+(?=$|[ \n])[^\n]*)*(?:$|\n)/y,
|
|
13
13
|
input => {
|
|
14
|
-
const
|
|
14
|
+
const context = input;
|
|
15
15
|
const { source, range } = context;
|
|
16
16
|
const acc = new List<Node<string>>();
|
|
17
17
|
for (const len = context.position + range; context.position < len;) {
|
|
@@ -34,8 +34,8 @@ export const ilist_: IListParser = lazy(() => block(fmap(validate(
|
|
|
34
34
|
]))));
|
|
35
35
|
|
|
36
36
|
export const ilistitem = rewrite(
|
|
37
|
-
inits([contentline, indent<Parser<string>>(({
|
|
38
|
-
({
|
|
37
|
+
inits([contentline, indent<Parser<string>>(({ source }) => new List([new Node(source)]))]),
|
|
38
|
+
({ source }) => new List([
|
|
39
39
|
new Node(''),
|
|
40
40
|
new Node(html('span', {
|
|
41
41
|
class: 'invalid',
|
|
@@ -16,7 +16,7 @@ export const mediablock: MediaBlockParser = block(fmap(
|
|
|
16
16
|
medialink,
|
|
17
17
|
media,
|
|
18
18
|
lineshortmedia,
|
|
19
|
-
]), ({
|
|
19
|
+
]), ({ source }) => new List([
|
|
20
20
|
new Node(html('span', {
|
|
21
21
|
class: 'invalid',
|
|
22
22
|
...invalid('mediablock', 'syntax', 'Not media syntax'),
|
|
@@ -53,12 +53,12 @@ const list = (type: string, form: string): OListParser.ListParser => fmap(
|
|
|
53
53
|
const heads = {
|
|
54
54
|
'.': focus(
|
|
55
55
|
openers['.'],
|
|
56
|
-
({
|
|
56
|
+
({ source }) => new List([
|
|
57
57
|
new Node(source.trimEnd().split('.', 1)[0] + '.')
|
|
58
58
|
])),
|
|
59
59
|
'(': focus(
|
|
60
60
|
openers['('],
|
|
61
|
-
({
|
|
61
|
+
({ source }) => new List([
|
|
62
62
|
new Node(source.trimEnd().replace(/^\($/, '(1)').replace(/^\((\w+)$/, '($1)'))
|
|
63
63
|
])),
|
|
64
64
|
} as const;
|
|
@@ -16,9 +16,9 @@ export const cite: ReplyParser.CiteParser = line(fmap(
|
|
|
16
16
|
line(anchor),
|
|
17
17
|
// Subject page representation.
|
|
18
18
|
// リンクの実装は後で検討
|
|
19
|
-
focus(/>>#\S*(?=\s*$)/y, ({
|
|
20
|
-
focus(/>>https?:\/\/\S+(?=\s*$)/y, ({
|
|
21
|
-
focus(/>>\S+(?=\s*$)/y, ({
|
|
19
|
+
focus(/>>#\S*(?=\s*$)/y, ({ source }) => new List([new Node(html('a', { class: 'anchor' }, source))])),
|
|
20
|
+
focus(/>>https?:\/\/\S+(?=\s*$)/y, ({ source }) => new List([new Node(html('a', { class: 'anchor', href: source.slice(2).trimEnd(), target: '_blank' }, source))])),
|
|
21
|
+
focus(/>>\S+(?=\s*$)/y, ({ source }) => new List([new Node(source)])),
|
|
22
22
|
])),
|
|
23
23
|
nodes => {
|
|
24
24
|
const quotes = nodes.head!.value as string;
|
|
@@ -30,7 +30,7 @@ export const table: TableParser = lazy(() => block(fmap(validate(
|
|
|
30
30
|
const row = <P extends CellParser | AlignParser>(parser: P, optional: boolean): RowParser<P> => fallback(fmap(
|
|
31
31
|
line(surround(/(?=\|)/y, some(union([parser])), /\|?\s*$/y, optional)),
|
|
32
32
|
ns => new List([new Node(html('tr', unwrap(ns)))])),
|
|
33
|
-
rewrite(contentline, ({
|
|
33
|
+
rewrite(contentline, ({ source }) => new List([
|
|
34
34
|
new Node(html('tr', {
|
|
35
35
|
class: 'invalid',
|
|
36
36
|
...invalid('table-row', 'syntax', 'Missing the start symbol of the table row'),
|
|
@@ -40,9 +40,9 @@ const row = <P extends CellParser | AlignParser>(parser: P, optional: boolean):
|
|
|
40
40
|
const align: AlignParser = fmap(open(
|
|
41
41
|
'|',
|
|
42
42
|
union([
|
|
43
|
-
focus(/:-+:?/y, ({
|
|
43
|
+
focus(/:-+:?/y, ({ source, position, range }) =>
|
|
44
44
|
new List([new Node(source[position + range - 1] === ':' ? 'center' : 'start')]), false),
|
|
45
|
-
focus(/-+:?/y, ({
|
|
45
|
+
focus(/-+:?/y, ({ source, position, range }) =>
|
|
46
46
|
new List([new Node(source[position + range - 1] === ':' ? 'end' : '')]), false),
|
|
47
47
|
])),
|
|
48
48
|
ns => new List([new Node(html('td', defrag(unwrap(ns))))]));
|
|
@@ -31,7 +31,7 @@ export const ulist_: UListParser = lazy(() => block(fmap(validate(
|
|
|
31
31
|
|
|
32
32
|
export const checkbox = focus(
|
|
33
33
|
/\[[xX ]\](?=$|[ \n])/y,
|
|
34
|
-
({
|
|
34
|
+
({ source, position }) => new List([
|
|
35
35
|
new Node(html('span', { class: 'checkbox' }, source[position + 1].trimStart() ? '☑' : '☐')),
|
|
36
36
|
]), false);
|
|
37
37
|
|
package/src/parser/block.ts
CHANGED
|
@@ -63,7 +63,7 @@ export const block: BlockParser = reset(
|
|
|
63
63
|
error(union([
|
|
64
64
|
emptysegment,
|
|
65
65
|
input => {
|
|
66
|
-
const {
|
|
66
|
+
const { source, position, segment } = input;
|
|
67
67
|
if (position === source.length) return;
|
|
68
68
|
switch (segment ^ Segment.write) {
|
|
69
69
|
case Segment.heading:
|
|
@@ -127,7 +127,7 @@ function error(parser: BlockParser): BlockParser {
|
|
|
127
127
|
const reg = new RegExp(String.raw`^${Command.Error}[^\n]*\n`)
|
|
128
128
|
return recover<BlockParser>(
|
|
129
129
|
parser,
|
|
130
|
-
({
|
|
130
|
+
({ source, position, id }, reason) => new List([
|
|
131
131
|
new Node(html('h1',
|
|
132
132
|
{
|
|
133
133
|
id: id !== '' ? `error:${rnd0Z(8)}` : undefined,
|
package/src/parser/context.ts
CHANGED
|
@@ -8,8 +8,9 @@ export class Context extends Ctx {
|
|
|
8
8
|
super(options);
|
|
9
9
|
const {
|
|
10
10
|
segment,
|
|
11
|
-
|
|
11
|
+
local,
|
|
12
12
|
sequential,
|
|
13
|
+
buffer,
|
|
13
14
|
header,
|
|
14
15
|
host,
|
|
15
16
|
url,
|
|
@@ -17,8 +18,9 @@ export class Context extends Ctx {
|
|
|
17
18
|
caches,
|
|
18
19
|
} = options;
|
|
19
20
|
this.segment = segment ?? Segment.unknown;
|
|
20
|
-
this.
|
|
21
|
+
this.local = local ?? false;
|
|
21
22
|
this.sequential = sequential ?? false;
|
|
23
|
+
this.buffer = buffer ?? new List();
|
|
22
24
|
this.header = header ?? true;
|
|
23
25
|
this.host = host;
|
|
24
26
|
this.url = url;
|
|
@@ -26,8 +28,9 @@ export class Context extends Ctx {
|
|
|
26
28
|
this.caches = caches;
|
|
27
29
|
}
|
|
28
30
|
public override segment: Segment;
|
|
29
|
-
public
|
|
31
|
+
public local: boolean;
|
|
30
32
|
public sequential: boolean;
|
|
33
|
+
public buffer: List<Node<(string | HTMLElement)>>;
|
|
31
34
|
public recursion = new RecursionCounter('annotation', 2);
|
|
32
35
|
public readonly header: boolean;
|
|
33
36
|
public readonly host?: URL;
|
package/src/parser/header.ts
CHANGED
|
@@ -11,7 +11,7 @@ export const header: MarkdownParser.HeaderParser = lazy(() => validate(
|
|
|
11
11
|
inits([
|
|
12
12
|
block(
|
|
13
13
|
union([
|
|
14
|
-
validate(
|
|
14
|
+
validate(context => context.header,
|
|
15
15
|
focus(/(---+)[^\S\n]*\n(?:[a-z][0-9a-z]*(?:-[0-9a-z]+)*:[ \t]+\S[^\n]*\n){1,100}\1[^\S\n]*(?:$|\n)/yi,
|
|
16
16
|
convert(source =>
|
|
17
17
|
normalize(source.slice(source.indexOf('\n') + 1, source.trimEnd().lastIndexOf('\n'))),
|
|
@@ -24,7 +24,7 @@ export const header: MarkdownParser.HeaderParser = lazy(() => validate(
|
|
|
24
24
|
defrag(unwrap(ns.unshift(new Node(html('summary', 'Header'))) && ns))),
|
|
25
25
|
])),
|
|
26
26
|
]))))),
|
|
27
|
-
|
|
27
|
+
context => {
|
|
28
28
|
const { source, position } = context;
|
|
29
29
|
context.position += source.length;
|
|
30
30
|
return new List([
|
|
@@ -39,7 +39,7 @@ export const header: MarkdownParser.HeaderParser = lazy(() => validate(
|
|
|
39
39
|
clear(str(/[^\S\n]*\n/y)),
|
|
40
40
|
])));
|
|
41
41
|
|
|
42
|
-
const field: MarkdownParser.HeaderParser.FieldParser = line(({
|
|
42
|
+
const field: MarkdownParser.HeaderParser.FieldParser = line(({ source, position }) => {
|
|
43
43
|
const name = source.slice(position, source.indexOf(':', position));
|
|
44
44
|
const value = source.slice(position + name.length + 1).trim();
|
|
45
45
|
return new List([
|
|
@@ -82,7 +82,7 @@ export const annotation: AnnotationParser = lazy(() => constraint(State.annotati
|
|
|
82
82
|
? new List([new Node(html('span', { class: 'paren' }, defrag(unwrap(bs))))])
|
|
83
83
|
: new List([new Node(html('span', { class: 'bracket' }, defrag(unwrap(bs))))]);
|
|
84
84
|
bs.unshift(new Node('('));
|
|
85
|
-
const cs = parser(
|
|
85
|
+
const cs = parser(context);
|
|
86
86
|
if (source[context.position] === ')') {
|
|
87
87
|
cs && bs.import(cs);
|
|
88
88
|
bs.push(new Node(')'));
|
|
@@ -6,7 +6,7 @@ import { inspect } from '../../../debug.test';
|
|
|
6
6
|
|
|
7
7
|
describe('Unit: parser/inline/autolink/url', () => {
|
|
8
8
|
describe('url', () => {
|
|
9
|
-
const parser = (input: Input<Context>) => some(autolink)((++input.
|
|
9
|
+
const parser = (input: Input<Context>) => some(autolink)((++input.position, input));
|
|
10
10
|
|
|
11
11
|
it('invalid', () => {
|
|
12
12
|
assert.deepStrictEqual(inspect(parser, input('', new Context())), undefined);
|
|
@@ -16,7 +16,7 @@ export const url: AutolinkParser.UrlParser = lazy(() => rewrite(
|
|
|
16
16
|
false,
|
|
17
17
|
[3 | Backtrack.unescapable]),
|
|
18
18
|
union([
|
|
19
|
-
constraint(State.autolink, state(State.autolink,
|
|
19
|
+
constraint(State.autolink, state(State.autolink, context =>
|
|
20
20
|
new List([new Node(parse(new List(), new List([new Node(context.source)]), context))]))),
|
|
21
21
|
open(str(/[^:]+/y), some(inline)),
|
|
22
22
|
])));
|
|
@@ -26,7 +26,7 @@ export const lineurl: AutolinkParser.UrlParser.LineUrlParser = lazy(() => focus(
|
|
|
26
26
|
tails([
|
|
27
27
|
str('!'),
|
|
28
28
|
union([
|
|
29
|
-
constraint(State.autolink, state(State.autolink,
|
|
29
|
+
constraint(State.autolink, state(State.autolink, context => {
|
|
30
30
|
const { source, position } = context;
|
|
31
31
|
context.position -= source[0] === '!' ? 1 : 0;
|
|
32
32
|
return new List([
|
|
@@ -12,7 +12,7 @@ import { isAlphanumeric } from '../source/text';
|
|
|
12
12
|
export const autolink: AutolinkParser = lazy(() =>
|
|
13
13
|
state(~State.autolink,
|
|
14
14
|
input => {
|
|
15
|
-
const {
|
|
15
|
+
const { source, position } = input;
|
|
16
16
|
if (position === source.length) return;
|
|
17
17
|
const fst = source[position];
|
|
18
18
|
switch (fst) {
|
|
@@ -14,7 +14,7 @@ const indexF = new RegExp(indexA.source.replace(', ', '[,、]')
|
|
|
14
14
|
|
|
15
15
|
export const bracket: BracketParser = lazy(() => union([
|
|
16
16
|
input => {
|
|
17
|
-
const {
|
|
17
|
+
const { source, position } = input;
|
|
18
18
|
switch (source[position]) {
|
|
19
19
|
case '(':
|
|
20
20
|
return p1(input);
|
|
@@ -92,7 +92,7 @@ const s1 = lazy(() => surround(
|
|
|
92
92
|
setBacktrack(context, 2 | Backtrack.link, head);
|
|
93
93
|
}
|
|
94
94
|
else {
|
|
95
|
-
if (!isBacktrack(context, 1 | Backtrack.link) && !textlink(
|
|
95
|
+
if (!isBacktrack(context, 1 | Backtrack.link) && !textlink(context)) {
|
|
96
96
|
setBacktrack(context, 2 | Backtrack.link, head);
|
|
97
97
|
}
|
|
98
98
|
context.position = position;
|
|
@@ -52,7 +52,7 @@ export const emstrong: EmStrongParser = lazy(() =>
|
|
|
52
52
|
return prepend('*', buffer);
|
|
53
53
|
}
|
|
54
54
|
})
|
|
55
|
-
(
|
|
55
|
+
(context) ?? prepend('*', buffer.import(new List([new Node(html('strong', defrag(unwrap(bs)))), new Node(Command.Separator)])));
|
|
56
56
|
case '*':
|
|
57
57
|
return bind<StrongParser>(
|
|
58
58
|
substrong,
|
|
@@ -71,7 +71,7 @@ export const emstrong: EmStrongParser = lazy(() =>
|
|
|
71
71
|
return prepend('**', buffer);
|
|
72
72
|
}
|
|
73
73
|
})
|
|
74
|
-
(
|
|
74
|
+
(context) ?? prepend('**', buffer.import(new List([new Node(html('em', defrag(unwrap(bs)))), new Node(Command.Separator)])));
|
|
75
75
|
}
|
|
76
76
|
assert(false);
|
|
77
77
|
},
|
|
@@ -112,7 +112,7 @@ export const emstrong: EmStrongParser = lazy(() =>
|
|
|
112
112
|
return prepend('*', nodes.import(ds));
|
|
113
113
|
}
|
|
114
114
|
})
|
|
115
|
-
(
|
|
115
|
+
(context) ?? prepend('*', nodes);
|
|
116
116
|
prefix -= 1;
|
|
117
117
|
break;
|
|
118
118
|
case 2:
|
|
@@ -128,7 +128,7 @@ export const emstrong: EmStrongParser = lazy(() =>
|
|
|
128
128
|
return prepend('**', nodes.import(ds));
|
|
129
129
|
}
|
|
130
130
|
})
|
|
131
|
-
(
|
|
131
|
+
(context) ?? prepend('**', nodes);
|
|
132
132
|
prefix -= 2;
|
|
133
133
|
break;
|
|
134
134
|
}
|
|
@@ -5,23 +5,28 @@ import { define } from 'typed-dom/dom';
|
|
|
5
5
|
|
|
6
6
|
export function indexee<P extends Parser<HTMLElement, Context>>(parser: P): P;
|
|
7
7
|
export function indexee(parser: Parser<HTMLElement, Context>): Parser<HTMLElement> {
|
|
8
|
-
return fmap(parser, (ns, { id }) =>
|
|
8
|
+
return fmap(parser, (ns, { id, local }) =>
|
|
9
9
|
ns.length === 1
|
|
10
|
-
? new List([new Node(define(ns.head!.value, {
|
|
10
|
+
? new List([new Node(define(ns.head!.value, {
|
|
11
|
+
id: identity('index', id, ns.head!.value),
|
|
12
|
+
class: local ? `${ns.head!.value.className} local`.trimStart() : undefined,
|
|
13
|
+
'data-index': null
|
|
14
|
+
}))])
|
|
11
15
|
: ns);
|
|
12
16
|
}
|
|
13
17
|
|
|
14
|
-
const MAX = 60;
|
|
15
|
-
const ELLIPSIS = '...';
|
|
16
|
-
const PART = (MAX - ELLIPSIS.length) / 2 | 0;
|
|
17
|
-
const REM = MAX - PART * 2 - ELLIPSIS.length;
|
|
18
|
-
assert(PART * 2 + REM + ELLIPSIS.length === MAX);
|
|
19
18
|
const table = [
|
|
20
19
|
...[...Array(36)].map((_, i) => i.toString(36)),
|
|
21
20
|
...[...Array(36)].map((_, i) => i.toString(36).toUpperCase()).slice(-26),
|
|
22
21
|
'-', '=',
|
|
23
22
|
].join('');
|
|
24
23
|
assert(table.length === 64);
|
|
24
|
+
const MAX = 64 - '='.length - Math.ceil(Math.log(~0 >>> 0) / Math.log(table.length));
|
|
25
|
+
assert(MAX === 57);
|
|
26
|
+
const ELLIPSIS = '...';
|
|
27
|
+
const PART = (MAX - ELLIPSIS.length) / 2 | 0;
|
|
28
|
+
const REM = MAX - PART * 2 - ELLIPSIS.length;
|
|
29
|
+
assert(PART * 2 + REM + ELLIPSIS.length === MAX);
|
|
25
30
|
export function identity(
|
|
26
31
|
type: 'index' | 'mark' | '',
|
|
27
32
|
id: string | undefined,
|
|
@@ -68,10 +73,10 @@ assert.deepStrictEqual(
|
|
|
68
73
|
`${'0'.repeat(MAX - 1)}1`);
|
|
69
74
|
assert.deepStrictEqual(
|
|
70
75
|
identity('index', undefined, `0${'1'.repeat(MAX / 2)}${'2'.repeat(MAX / 2)}3`)!.slice(7),
|
|
71
|
-
`0${'1'.repeat(PART + REM - 1)}${ELLIPSIS}${'2'.repeat(PART - 1)}3=
|
|
76
|
+
`0${'1'.repeat(PART + REM - 1)}${ELLIPSIS}${'2'.repeat(PART - 1)}3=E0deO`);
|
|
72
77
|
assert.deepStrictEqual(
|
|
73
78
|
identity('index', undefined, `0${'1'.repeat(MAX * 2)}${'2'.repeat(MAX * 2)}3`)!.slice(7),
|
|
74
|
-
`0${'1'.repeat(PART + REM - 1)}${ELLIPSIS}${'2'.repeat(PART - 1)}3=
|
|
79
|
+
`0${'1'.repeat(PART + REM - 1)}${ELLIPSIS}${'2'.repeat(PART - 1)}3=2RHwOS`);
|
|
75
80
|
function hash(source: string): string {
|
|
76
81
|
let x = 0;
|
|
77
82
|
for (let i = 0; i < source.length; ++i) {
|
|
@@ -88,6 +93,8 @@ assert(hash('\x00') !== '0');
|
|
|
88
93
|
assert(hash('\x01') !== '0');
|
|
89
94
|
assert(hash('\x00') !== hash(String.fromCharCode(1 << 15)));
|
|
90
95
|
// 62も64も最大6桁
|
|
96
|
+
assert(Math.ceil(Math.log(~0 >>> 0) / Math.log(62)) === 6);
|
|
97
|
+
assert(Math.ceil(Math.log(~0 >>> 0) / Math.log(64)) === 6);
|
|
91
98
|
function baseR(n: number, r: number): string {
|
|
92
99
|
assert(n >= 0);
|
|
93
100
|
assert(Math.floor(n) === n);
|
|
@@ -104,6 +111,7 @@ function baseR(n: number, r: number): string {
|
|
|
104
111
|
}
|
|
105
112
|
assert(baseR(0, 36) === (0).toString(36));
|
|
106
113
|
assert(baseR(~0 >>> 0, 36) === (~0 >>> 0).toString(36));
|
|
114
|
+
assert(baseR(0, 62) === '0');
|
|
107
115
|
assert(baseR(61, 62) === 'Z');
|
|
108
116
|
assert(baseR(62, 62) === '10');
|
|
109
117
|
|
|
@@ -26,7 +26,7 @@ export const math: MathParser = lazy(() => rewrite(
|
|
|
26
26
|
false,
|
|
27
27
|
[3 | Backtrack.escapable]),
|
|
28
28
|
]),
|
|
29
|
-
({
|
|
29
|
+
({ source, caches: { math: cache } = {} }) => new List([
|
|
30
30
|
new Node(cache?.get(source)?.cloneNode(true) ||
|
|
31
31
|
html('span',
|
|
32
32
|
!forbiddenCommand.test(source)
|
|
@@ -45,7 +45,7 @@ export const reference: ReferenceParser = lazy(() => constraint(State.reference,
|
|
|
45
45
|
assert(~context.state & State.link);
|
|
46
46
|
context.position += 1;
|
|
47
47
|
assert(!isBacktrack(context, 1 | Backtrack.link));
|
|
48
|
-
if (!textlink(
|
|
48
|
+
if (!textlink(context)) {
|
|
49
49
|
setBacktrack(context, 2 | Backtrack.link, head + 1);
|
|
50
50
|
}
|
|
51
51
|
context.position = position;
|
|
@@ -20,6 +20,6 @@ export const remark: RemarkParser = lazy(() => fallback(surround(
|
|
|
20
20
|
])),
|
|
21
21
|
]),
|
|
22
22
|
([as, bs]) => bs && as.import(bs as List<Node<string>>)),
|
|
23
|
-
focus(/\[%+(?=[ \n])/y, ({
|
|
23
|
+
focus(/\[%+(?=[ \n])/y, ({ source }) => new List([
|
|
24
24
|
new Node(html('span', { class: 'invalid', ...invalid('remark', 'syntax', 'Invalid start symbol') }, source))
|
|
25
25
|
]))));
|
|
@@ -65,7 +65,7 @@ export const ruby: RubyParser = lazy(() => bind(
|
|
|
65
65
|
const delimiter = /[$"`\[\](){}<>()[]{}|]|\\?\n/y;
|
|
66
66
|
|
|
67
67
|
const text: RubyParser.TextParser = input => {
|
|
68
|
-
const
|
|
68
|
+
const context = input;
|
|
69
69
|
const { source } = context;
|
|
70
70
|
const acc = new List([new Node('')]);
|
|
71
71
|
let state = false;
|
package/src/parser/inline.ts
CHANGED
|
@@ -52,7 +52,7 @@ const stars = strs('*');
|
|
|
52
52
|
|
|
53
53
|
export const inline: InlineParser = lazy(() => union([
|
|
54
54
|
input => {
|
|
55
|
-
const {
|
|
55
|
+
const { source, position } = input;
|
|
56
56
|
if (position === source.length) return;
|
|
57
57
|
switch (source[position]) {
|
|
58
58
|
case '(':
|