securemark 0.294.3 → 0.294.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 +164 -144
- package/markdown.d.ts +3 -12
- package/package.json +3 -3
- package/src/combinator/control/manipulation/fence.ts +2 -0
- package/src/combinator/control/manipulation/indent.ts +1 -1
- package/src/combinator/control/manipulation/match.ts +11 -8
- package/src/parser/api/parse.test.ts +3 -3
- package/src/parser/block/blockquote.test.ts +3 -9
- package/src/parser/block/blockquote.ts +4 -4
- package/src/parser/block/dlist.ts +4 -4
- package/src/parser/block/extension/example.ts +1 -3
- package/src/parser/block/extension/fig.test.ts +0 -1
- package/src/parser/block/extension/fig.ts +6 -6
- package/src/parser/block/extension/figbase.ts +1 -1
- package/src/parser/block/extension/figure.test.ts +1 -1
- package/src/parser/block/extension/figure.ts +6 -6
- package/src/parser/block/extension/message.ts +1 -1
- package/src/parser/block/extension/table.ts +4 -4
- package/src/parser/block/heading.ts +4 -4
- package/src/parser/block/reply/cite.ts +2 -2
- package/src/parser/block/reply/quote.ts +2 -2
- package/src/parser/block/sidefence.test.ts +1 -3
- package/src/parser/block/sidefence.ts +4 -4
- package/src/parser/block/table.ts +2 -2
- package/src/parser/block.ts +1 -1
- package/src/parser/header.ts +3 -3
- package/src/parser/inline/autolink/account.test.ts +18 -17
- package/src/parser/inline/autolink/account.ts +14 -20
- package/src/parser/inline/autolink/anchor.test.ts +2 -1
- package/src/parser/inline/autolink/anchor.ts +10 -13
- package/src/parser/inline/autolink/channel.test.ts +6 -6
- package/src/parser/inline/autolink/channel.ts +28 -32
- package/src/parser/inline/autolink/email.test.ts +19 -19
- package/src/parser/inline/autolink/email.ts +7 -7
- package/src/parser/inline/autolink/hashnum.test.ts +20 -20
- package/src/parser/inline/autolink/hashnum.ts +6 -8
- package/src/parser/inline/autolink/hashtag.test.ts +27 -27
- package/src/parser/inline/autolink/hashtag.ts +15 -16
- package/src/parser/inline/autolink/url.test.ts +6 -6
- package/src/parser/inline/autolink/url.ts +5 -4
- package/src/parser/inline/autolink.ts +4 -5
- package/src/parser/inline/code.ts +12 -18
- package/src/parser/inline/deletion.test.ts +1 -1
- package/src/parser/inline/deletion.ts +3 -3
- package/src/parser/inline/emstrong.ts +3 -3
- package/src/parser/inline/extension/indexer.ts +1 -1
- package/src/parser/inline/html.test.ts +1 -0
- package/src/parser/inline/html.ts +1 -1
- package/src/parser/inline/insertion.test.ts +1 -1
- package/src/parser/inline/insertion.ts +3 -3
- package/src/parser/inline/italic.test.ts +2 -2
- package/src/parser/inline/italic.ts +3 -3
- package/src/parser/inline/link.test.ts +0 -1
- package/src/parser/inline/link.ts +3 -3
- package/src/parser/inline/mark.test.ts +1 -1
- package/src/parser/inline/mark.ts +3 -3
- package/src/parser/inline/remark.ts +3 -3
- package/src/parser/inline.test.ts +11 -11
- package/src/parser/inline.ts +2 -0
- package/src/parser/source/text.ts +8 -4
- package/src/parser/util.ts +1 -1
- package/src/parser/visibility.ts +4 -6
package/markdown.d.ts
CHANGED
|
@@ -1096,13 +1096,10 @@ export namespace MarkdownParser {
|
|
|
1096
1096
|
AutolinkParser.UrlParser.LineUrlParser,
|
|
1097
1097
|
AutolinkParser.UrlParser,
|
|
1098
1098
|
AutolinkParser.EmailParser,
|
|
1099
|
-
SourceParser.StrParser,
|
|
1100
1099
|
AutolinkParser.ChannelParser,
|
|
1101
1100
|
AutolinkParser.AccountParser,
|
|
1102
|
-
SourceParser.StrParser,
|
|
1103
1101
|
AutolinkParser.HashtagParser,
|
|
1104
1102
|
AutolinkParser.HashnumParser,
|
|
1105
|
-
SourceParser.StrParser,
|
|
1106
1103
|
AutolinkParser.AnchorParser,
|
|
1107
1104
|
]> {
|
|
1108
1105
|
}
|
|
@@ -1110,9 +1107,9 @@ export namespace MarkdownParser {
|
|
|
1110
1107
|
export interface UrlParser extends
|
|
1111
1108
|
// https://host
|
|
1112
1109
|
Inline<'url'>,
|
|
1113
|
-
Parser<string |
|
|
1110
|
+
Parser<string | HTMLElement, Context, [
|
|
1114
1111
|
LinkParser.UnsafeLinkParser,
|
|
1115
|
-
|
|
1112
|
+
InlineParser,
|
|
1116
1113
|
]> {
|
|
1117
1114
|
}
|
|
1118
1115
|
export namespace UrlParser {
|
|
@@ -1122,7 +1119,7 @@ export namespace MarkdownParser {
|
|
|
1122
1119
|
SourceParser.StrParser,
|
|
1123
1120
|
Parser<string | HTMLElement, Context, [
|
|
1124
1121
|
InlineParser.LinkParser.UnsafeLinkParser,
|
|
1125
|
-
|
|
1122
|
+
InlineParser,
|
|
1126
1123
|
]>,
|
|
1127
1124
|
]> {
|
|
1128
1125
|
}
|
|
@@ -1150,7 +1147,6 @@ export namespace MarkdownParser {
|
|
|
1150
1147
|
Inline<'email'>,
|
|
1151
1148
|
Parser<string | HTMLAnchorElement, Context, [
|
|
1152
1149
|
Parser<HTMLAnchorElement, Context, []>,
|
|
1153
|
-
Parser<string, Context, []>,
|
|
1154
1150
|
]> {
|
|
1155
1151
|
}
|
|
1156
1152
|
export interface ChannelParser extends
|
|
@@ -1158,7 +1154,6 @@ export namespace MarkdownParser {
|
|
|
1158
1154
|
Inline<'channel'>,
|
|
1159
1155
|
Parser<string | HTMLAnchorElement, Context, [
|
|
1160
1156
|
LinkParser.UnsafeLinkParser,
|
|
1161
|
-
Parser<string, Context, []>,
|
|
1162
1157
|
]> {
|
|
1163
1158
|
}
|
|
1164
1159
|
export interface AccountParser extends
|
|
@@ -1166,7 +1161,6 @@ export namespace MarkdownParser {
|
|
|
1166
1161
|
Inline<'account'>,
|
|
1167
1162
|
Parser<string | HTMLAnchorElement, Context, [
|
|
1168
1163
|
LinkParser.UnsafeLinkParser,
|
|
1169
|
-
Parser<string, Context, []>,
|
|
1170
1164
|
]> {
|
|
1171
1165
|
}
|
|
1172
1166
|
export interface HashtagParser extends
|
|
@@ -1174,7 +1168,6 @@ export namespace MarkdownParser {
|
|
|
1174
1168
|
Inline<'hashtag'>,
|
|
1175
1169
|
Parser<string | HTMLAnchorElement, Context, [
|
|
1176
1170
|
LinkParser.UnsafeLinkParser,
|
|
1177
|
-
Parser<string, Context, []>,
|
|
1178
1171
|
]> {
|
|
1179
1172
|
}
|
|
1180
1173
|
export interface HashnumParser extends
|
|
@@ -1182,7 +1175,6 @@ export namespace MarkdownParser {
|
|
|
1182
1175
|
Inline<'hashnum'>,
|
|
1183
1176
|
Parser<string | HTMLAnchorElement, Context, [
|
|
1184
1177
|
LinkParser.UnsafeLinkParser,
|
|
1185
|
-
Parser<string, Context, []>,
|
|
1186
1178
|
]> {
|
|
1187
1179
|
}
|
|
1188
1180
|
export interface AnchorParser extends
|
|
@@ -1190,7 +1182,6 @@ export namespace MarkdownParser {
|
|
|
1190
1182
|
Inline<'anchor'>,
|
|
1191
1183
|
Parser<string | HTMLAnchorElement, Context, [
|
|
1192
1184
|
LinkParser.UnsafeLinkParser,
|
|
1193
|
-
Parser<string, Context, []>,
|
|
1194
1185
|
]> {
|
|
1195
1186
|
}
|
|
1196
1187
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "securemark",
|
|
3
|
-
"version": "0.294.
|
|
3
|
+
"version": "0.294.5",
|
|
4
4
|
"description": "Secure markdown renderer working on browsers for user input data.",
|
|
5
5
|
"private": false,
|
|
6
6
|
"homepage": "https://github.com/falsandtru/securemark",
|
|
@@ -28,7 +28,7 @@
|
|
|
28
28
|
"LICENSE"
|
|
29
29
|
],
|
|
30
30
|
"dependencies": {
|
|
31
|
-
"spica": "0.0.
|
|
31
|
+
"spica": "0.0.810"
|
|
32
32
|
},
|
|
33
33
|
"devDependencies": {
|
|
34
34
|
"@types/dompurify": "3.0.5",
|
|
@@ -42,7 +42,7 @@
|
|
|
42
42
|
"babel-plugin-unassert": "^3.2.0",
|
|
43
43
|
"concurrently": "^8.2.2",
|
|
44
44
|
"eslint": "^9.8.0",
|
|
45
|
-
"eslint-plugin-redos": "^4.
|
|
45
|
+
"eslint-plugin-redos": "^4.5.0",
|
|
46
46
|
"eslint-webpack-plugin": "^4.2.0",
|
|
47
47
|
"glob": "^11.0.0",
|
|
48
48
|
"karma": "^6.4.4",
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { Parser, List, Data, Ctx, failsafe } from '../../data/parser';
|
|
2
|
+
import { consume } from '../../../combinator';
|
|
2
3
|
import { firstline, isBlank } from '../constraint/line';
|
|
3
4
|
import { push } from 'spica/array';
|
|
4
5
|
|
|
@@ -12,6 +13,7 @@ export function fence<C extends Ctx, D extends Parser<unknown, C>[]>(opener: Reg
|
|
|
12
13
|
const matches = opener.exec(source);
|
|
13
14
|
if (!matches) return;
|
|
14
15
|
assert(matches[0] === firstline(source, position));
|
|
16
|
+
consume(matches[0].length, context);
|
|
15
17
|
const delim = matches[1];
|
|
16
18
|
assert(delim && delim === delim.trim());
|
|
17
19
|
if (matches[0].includes(delim, delim.length)) return;
|
|
@@ -26,7 +26,7 @@ export function indent<N>(opener: RegExp | Parser<N>, parser: Parser<N> | boolea
|
|
|
26
26
|
context.position = source.length;
|
|
27
27
|
return new List([new Data(source.slice(position))]);
|
|
28
28
|
}))),
|
|
29
|
-
([indent]) => indent.length
|
|
29
|
+
([indent]) => indent.length * 2 + -(indent[0] === ' '), [], 2 ** 4 - 1)), separation),
|
|
30
30
|
(lines, context) => {
|
|
31
31
|
assert(parser = parser as Parser<N>);
|
|
32
32
|
return parser(subinput(trimBlockEnd(lines.foldl((acc, node) => acc + node.value, '')), context));
|
|
@@ -1,20 +1,23 @@
|
|
|
1
1
|
import { Parser, failsafe } from '../../data/parser';
|
|
2
2
|
import { consume } from '../../../combinator';
|
|
3
3
|
|
|
4
|
-
export function match<P extends Parser<unknown>>(pattern: RegExp, f: (matched: RegExpMatchArray) => P
|
|
5
|
-
export function match<N>(pattern: RegExp, f: (matched: RegExpMatchArray) => Parser<N
|
|
4
|
+
export function match<P extends Parser<unknown>>(pattern: RegExp, f: (matched: RegExpMatchArray) => P): P;
|
|
5
|
+
export function match<N>(pattern: RegExp, f: (matched: RegExpMatchArray) => Parser<N>): Parser<N> {
|
|
6
6
|
assert(!pattern.flags.match(/[gm]/) && pattern.sticky && !pattern.source.startsWith('^'));
|
|
7
|
+
const count = typeof pattern === 'object'
|
|
8
|
+
? /[^^\\*+][*+]/.test(pattern.source)
|
|
9
|
+
: false;
|
|
7
10
|
return failsafe(input => {
|
|
8
11
|
const { context } = input;
|
|
9
12
|
const { source, position } = context;
|
|
10
13
|
if (position === source.length) return;
|
|
11
14
|
pattern.lastIndex = position;
|
|
12
|
-
const
|
|
13
|
-
if (!
|
|
14
|
-
assert(source.startsWith(
|
|
15
|
-
|
|
16
|
-
const result = f(
|
|
17
|
-
context.position += result && context.position === position ?
|
|
15
|
+
const params = pattern.exec(source);
|
|
16
|
+
if (!params) return;
|
|
17
|
+
assert(source.startsWith(params[0], position));
|
|
18
|
+
count && consume(params[0].length, context);
|
|
19
|
+
const result = f(params)(input);
|
|
20
|
+
context.position += result && context.position === position ? params[0].length : 0;
|
|
18
21
|
assert(context.position > position || !result);
|
|
19
22
|
return context.position > position
|
|
20
23
|
? result
|
|
@@ -361,9 +361,9 @@ describe('Unit: parser/api/parse', () => {
|
|
|
361
361
|
|
|
362
362
|
it('backtrack', function () {
|
|
363
363
|
this.timeout(5000);
|
|
364
|
-
// 最悪計算量での実行速度はCommonMarkの公式JS実装の32n
|
|
364
|
+
// 最悪計算量での実行速度はCommonMarkの公式JS実装の32nより速い。
|
|
365
365
|
// 5n = annotation/reference + link + url/math + ruby + text
|
|
366
|
-
const source =
|
|
366
|
+
const source = `((([[[[#$[${'.'.repeat(19997)}`;
|
|
367
367
|
assert.deepStrictEqual(
|
|
368
368
|
[...parse(source, {}, { resources: { clock: 100000, recursions: [100] } }).children]
|
|
369
369
|
.map(el => el.tagName),
|
|
@@ -372,7 +372,7 @@ describe('Unit: parser/api/parse', () => {
|
|
|
372
372
|
|
|
373
373
|
it('backtrack error', function () {
|
|
374
374
|
this.timeout(5000);
|
|
375
|
-
const source =
|
|
375
|
+
const source = `((([[[[#$[${'.'.repeat(19997 + 1)}`;
|
|
376
376
|
assert.deepStrictEqual(
|
|
377
377
|
[...parse(source, {}, { resources: { clock: 100000, recursions: [100] } }).children]
|
|
378
378
|
.map(el => el.tagName),
|
|
@@ -14,6 +14,9 @@ describe('Unit: parser/block/blockquote', () => {
|
|
|
14
14
|
assert.deepStrictEqual(inspect(parser('>'), ctx), undefined);
|
|
15
15
|
assert.deepStrictEqual(inspect(parser('>a'), ctx), undefined);
|
|
16
16
|
assert.deepStrictEqual(inspect(parser('>\n'), ctx), undefined);
|
|
17
|
+
assert.deepStrictEqual(inspect(parser('>\na'), ctx), undefined);
|
|
18
|
+
assert.deepStrictEqual(inspect(parser('!>\n'), ctx), undefined);
|
|
19
|
+
assert.deepStrictEqual(inspect(parser('!>\na'), ctx), undefined);
|
|
17
20
|
assert.deepStrictEqual(inspect(parser(' > '), ctx), undefined);
|
|
18
21
|
assert.deepStrictEqual(inspect(parser('>>'), ctx), undefined);
|
|
19
22
|
});
|
|
@@ -38,10 +41,6 @@ describe('Unit: parser/block/blockquote', () => {
|
|
|
38
41
|
assert.deepStrictEqual(inspect(parser('> a\\\nb'), ctx), [['<blockquote><pre>a\\<br>b</pre></blockquote>'], '']);
|
|
39
42
|
assert.deepStrictEqual(inspect(parser('> a '), ctx), [['<blockquote><pre> a </pre></blockquote>'], '']);
|
|
40
43
|
assert.deepStrictEqual(inspect(parser('> \na'), ctx), [['<blockquote><pre><br>a</pre></blockquote>'], '']);
|
|
41
|
-
assert.deepStrictEqual(inspect(parser('>\na'), ctx), [['<blockquote><pre><br>a</pre></blockquote>'], '']);
|
|
42
|
-
assert.deepStrictEqual(inspect(parser('>\n a'), ctx), [['<blockquote><pre><br> a</pre></blockquote>'], '']);
|
|
43
|
-
assert.deepStrictEqual(inspect(parser('>\n>'), ctx), [['<blockquote><pre><br></pre></blockquote>'], '']);
|
|
44
|
-
assert.deepStrictEqual(inspect(parser('>\n> a'), ctx), [['<blockquote><pre><br>a</pre></blockquote>'], '']);
|
|
45
44
|
assert.deepStrictEqual(inspect(parser('> http://host'), ctx), [['<blockquote><pre><a class="url" href="http://host" target="_blank">http://host</a></pre></blockquote>'], '']);
|
|
46
45
|
assert.deepStrictEqual(inspect(parser('> http://host)'), ctx), [['<blockquote><pre><a class="url" href="http://host)" target="_blank">http://host)</a></pre></blockquote>'], '']);
|
|
47
46
|
assert.deepStrictEqual(inspect(parser('> !http://host'), ctx), [['<blockquote><pre>!<a class="url" href="http://host" target="_blank">http://host</a></pre></blockquote>'], '']);
|
|
@@ -92,11 +91,6 @@ describe('Unit: parser/block/blockquote', () => {
|
|
|
92
91
|
assert.deepStrictEqual(inspect(parser('!>> > a\n> b'), ctx), [['<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>'], '']);
|
|
93
92
|
assert.deepStrictEqual(inspect(parser('!> !> a'), ctx), [['<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>'], '']);
|
|
94
93
|
assert.deepStrictEqual(inspect(parser('!> \na'), ctx), [['<blockquote><section><p>a</p><h2>References</h2><ol class="references"></ol></section></blockquote>'], '']);
|
|
95
|
-
assert.deepStrictEqual(inspect(parser('!>\n'), ctx), undefined);
|
|
96
|
-
assert.deepStrictEqual(inspect(parser('!>\na'), ctx), [['<blockquote><section><p>a</p><h2>References</h2><ol class="references"></ol></section></blockquote>'], '']);
|
|
97
|
-
assert.deepStrictEqual(inspect(parser('!>\n a'), ctx), [['<blockquote><section><p> a</p><h2>References</h2><ol class="references"></ol></section></blockquote>'], '']);
|
|
98
|
-
assert.deepStrictEqual(inspect(parser('!>\n>'), ctx), [['<blockquote><section><h2>References</h2><ol class="references"></ol></section></blockquote>'], '']);
|
|
99
|
-
assert.deepStrictEqual(inspect(parser('!>\n> a'), ctx), [['<blockquote><section><p>a</p><h2>References</h2><ol class="references"></ol></section></blockquote>'], '']);
|
|
100
94
|
assert.deepStrictEqual(inspect(parser('!>> ## a\n> ## a'), ctx), [['<blockquote><blockquote><section><h2>a</h2><h2>References</h2><ol class="references"></ol></section></blockquote><section><h2>a</h2><h2>References</h2><ol class="references"></ol></section></blockquote>'], '']);
|
|
101
95
|
assert.deepStrictEqual(inspect(parser('!>> ~ a\n> ~ a'), ctx), [['<blockquote><blockquote><section><dl><dt>a</dt><dd></dd></dl><h2>References</h2><ol class="references"></ol></section></blockquote><section><dl><dt>a</dt><dd></dd></dl><h2>References</h2><ol class="references"></ol></section></blockquote>'], '']);
|
|
102
96
|
assert.deepStrictEqual(inspect(parser('!>> ~~~figure $test-a\n>> > \n>>\n~~~\n> ~~~figure $test-a\n> > \n>\n[#a]\n~~~'), ctx), [['<blockquote><blockquote><section><figure data-type="quote" data-label="test-a" data-group="test" data-number="1"><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"><figcaption><span class="figindex">Test 1. </span><span class="figtext"><a class="index">a</a></span></figcaption><div><blockquote></blockquote></div></figure><h2>References</h2><ol class="references"></ol></section></blockquote>'], '']);
|
|
@@ -9,7 +9,7 @@ import { parse } from '../api/parse';
|
|
|
9
9
|
import { html, defrag } from 'typed-dom/dom';
|
|
10
10
|
|
|
11
11
|
export const segment: BlockquoteParser.SegmentParser = block(union([
|
|
12
|
-
validate(/!?>+
|
|
12
|
+
validate(/!?>+ /y, some(contentline)),
|
|
13
13
|
]));
|
|
14
14
|
|
|
15
15
|
export const blockquote: BlockquoteParser = lazy(() => block(rewrite(segment, union([
|
|
@@ -17,9 +17,9 @@ export const blockquote: BlockquoteParser = lazy(() => block(rewrite(segment, un
|
|
|
17
17
|
open(/!(?=>)/y, markdown),
|
|
18
18
|
]))));
|
|
19
19
|
|
|
20
|
-
const opener = /(?=>>+(
|
|
21
|
-
const indent = block(open(opener, some(contentline, />(
|
|
22
|
-
const unindent = (source: string) => source.replace(/(?<=^|\n)>(?:[
|
|
20
|
+
const opener = /(?=>>+(?:$|[ \n]))/y;
|
|
21
|
+
const indent = block(open(opener, some(contentline, />(?:$|[ \n])/y)), false);
|
|
22
|
+
const unindent = (source: string) => source.replace(/(?<=^|\n)>(?: |(?=>*(?:$|[ \n])))|\n$/g, '');
|
|
23
23
|
|
|
24
24
|
const source: BlockquoteParser.SourceParser = lazy(() => fmap(
|
|
25
25
|
some(recursion(Recursion.blockquote, union([
|
|
@@ -9,7 +9,7 @@ import { unwrap } from '../util';
|
|
|
9
9
|
import { html, defrag } from 'typed-dom/dom';
|
|
10
10
|
|
|
11
11
|
export const dlist: DListParser = lazy(() => block(fmap(validate(
|
|
12
|
-
/~
|
|
12
|
+
/~ +(?=\S)/y,
|
|
13
13
|
some(inits([
|
|
14
14
|
state(State.annotation | State.reference | State.index | State.label | State.link,
|
|
15
15
|
some(term)),
|
|
@@ -18,15 +18,15 @@ export const dlist: DListParser = lazy(() => block(fmap(validate(
|
|
|
18
18
|
ns => new List([new Data(html('dl', unwrap(fillTrailingDescription(ns))))]))));
|
|
19
19
|
|
|
20
20
|
const term: DListParser.TermParser = line(indexee(fmap(open(
|
|
21
|
-
/~
|
|
21
|
+
/~ +(?=\S)/y,
|
|
22
22
|
visualize(trimBlank(some(union([indexer, inline])))),
|
|
23
23
|
true),
|
|
24
24
|
ns => new List([new Data(html('dt', { 'data-index': dataindex(ns) }, defrag(unwrap(ns))))]))));
|
|
25
25
|
|
|
26
26
|
const desc: DListParser.DescriptionParser = block(fmap(open(
|
|
27
|
-
/:
|
|
27
|
+
/: +(?=\S)|/y,
|
|
28
28
|
rewrite(
|
|
29
|
-
some(anyline, /[~:]
|
|
29
|
+
some(anyline, /[~:] +(?=\S)/y),
|
|
30
30
|
visualize(trimBlankEnd(some(union([inline]))))),
|
|
31
31
|
true),
|
|
32
32
|
ns => new List([new Data(html('dd', defrag(unwrap(ns))))])),
|
|
@@ -7,10 +7,8 @@ import { unwrap, invalid } from '../../util';
|
|
|
7
7
|
import { parse } from '../../api/parse';
|
|
8
8
|
import { html } from 'typed-dom/dom';
|
|
9
9
|
|
|
10
|
-
const opener = /(~{3,})(?:example\/(\S+))?(?!\S)([^\n]*)(?:$|\n)/y;
|
|
11
|
-
|
|
12
10
|
export const example: ExtensionParser.ExampleParser = recursion(Recursion.block, block(fmap(
|
|
13
|
-
fence(
|
|
11
|
+
fence(/(~{3,})(?:example\/(\S+))?(?!\S)([^\n]*)(?:$|\n)/y, 300),
|
|
14
12
|
// Bug: Type mismatch between outer and inner.
|
|
15
13
|
(nodes: List<Data<string>>, context) => {
|
|
16
14
|
const [body, overflow, closer, opener, delim, type = 'markdown', param] = unwrap(nodes);
|
|
@@ -40,7 +40,6 @@ describe('Unit: parser/block/extension/fig', () => {
|
|
|
40
40
|
assert.deepStrictEqual(inspect(parser('[$group-name]\n~~~table\n~~~\n'), ctx), [['<figure data-type="table" data-label="group-name" data-group="group"><figcaption><span class="figindex"></span><span class="figtext"></span></figcaption><div><table></table></div></figure>'], '']);
|
|
41
41
|
assert.deepStrictEqual(inspect(parser('[$group-name]\n> '), ctx), [['<figure data-type="quote" data-label="group-name" data-group="group"><figcaption><span class="figindex"></span><span class="figtext"></span></figcaption><div><blockquote></blockquote></div></figure>'], '']);
|
|
42
42
|
assert.deepStrictEqual(inspect(parser('[$group-name]\n> \n'), ctx), [['<figure data-type="quote" data-label="group-name" data-group="group"><figcaption><span class="figindex"></span><span class="figtext"></span></figcaption><div><blockquote></blockquote></div></figure>'], '']);
|
|
43
|
-
assert.deepStrictEqual(inspect(parser('[$group-name]\n>\n~~~'), ctx), [['<figure data-type="quote" data-label="group-name" data-group="group"><figcaption><span class="figindex"></span><span class="figtext"></span></figcaption><div><blockquote><pre><br>~~~</pre></blockquote></div></figure>'], '']);
|
|
44
43
|
assert.deepStrictEqual(inspect(parser('[$group-name]\n!> *a*'), ctx), [['<figure data-type="quote" data-label="group-name" data-group="group"><figcaption><span class="figindex"></span><span class="figtext"></span></figcaption><div><blockquote><section><p><em>a</em></p><h2>References</h2><ol class="references"></ol></section></blockquote></div></figure>'], '']);
|
|
45
44
|
assert.deepStrictEqual(inspect(parser('[$group-name]\n![]{https://host}'), ctx), [['<figure data-type="media" data-label="group-name" data-group="group"><figcaption><span class="figindex"></span><span class="figtext"></span></figcaption><div><a href="https://host" target="_blank"><img class="media" data-src="https://host" alt="https://host"></a></div></figure>'], '']);
|
|
46
45
|
assert.deepStrictEqual(inspect(parser('[$group-name]\n![]{https://host}\n'), ctx), [['<figure data-type="media" data-label="group-name" data-group="group"><figcaption><span class="figindex"></span><span class="figtext"></span></figcaption><div><a href="https://host" target="_blank"><img class="media" data-src="https://host" alt="https://host"></a></div></figure>'], '']);
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { ExtensionParser } from '../../block';
|
|
2
|
-
import { union, sequence, some, block, line,
|
|
2
|
+
import { union, sequence, some, block, line, verify, rewrite, close, convert } from '../../../combinator';
|
|
3
3
|
import { contentline } from '../../source';
|
|
4
4
|
import { figure } from './figure';
|
|
5
5
|
import { segment as seg_label } from '../../inline/extension/label';
|
|
@@ -12,9 +12,9 @@ import { media, lineshortmedia } from '../../inline';
|
|
|
12
12
|
|
|
13
13
|
import FigParser = ExtensionParser.FigParser;
|
|
14
14
|
|
|
15
|
-
export const segment: FigParser.SegmentParser = block(
|
|
15
|
+
export const segment: FigParser.SegmentParser = block(
|
|
16
16
|
sequence([
|
|
17
|
-
line(close(seg_label, /(
|
|
17
|
+
line(close(seg_label, /(?!\S).*\n/y)),
|
|
18
18
|
union([
|
|
19
19
|
seg_code,
|
|
20
20
|
seg_math,
|
|
@@ -23,12 +23,12 @@ export const segment: FigParser.SegmentParser = block(validate(/\[?\$/y,
|
|
|
23
23
|
seg_placeholder,
|
|
24
24
|
some(contentline),
|
|
25
25
|
]),
|
|
26
|
-
]))
|
|
26
|
+
]));
|
|
27
27
|
|
|
28
28
|
export const fig: FigParser = block(rewrite(segment, verify(convert(
|
|
29
29
|
(source, context) => {
|
|
30
30
|
// Bug: TypeScript
|
|
31
|
-
const fence = (/^[^\n]*\n
|
|
31
|
+
const fence = (/^[^\n]*\n!?>+ /.test(source) && source.match(/^~{3,}(?=[^\S\n]*$)/mg) as string[] || [])
|
|
32
32
|
.reduce((max, fence) => fence > max ? fence : max, '~~') + '~';
|
|
33
33
|
return parser({ context })
|
|
34
34
|
? `${fence}figure ${source.replace(/^(.+\n.+\n)([\S\s]+?)\n?$/, '$1\n$2')}\n${fence}`
|
|
@@ -39,7 +39,7 @@ export const fig: FigParser = block(rewrite(segment, verify(convert(
|
|
|
39
39
|
([{ value: el }]) => el.tagName === 'FIGURE')));
|
|
40
40
|
|
|
41
41
|
const parser = sequence([
|
|
42
|
-
line(close(seg_label, /(
|
|
42
|
+
line(close(seg_label, /(?!\S).*\n/y)),
|
|
43
43
|
line(union([
|
|
44
44
|
media,
|
|
45
45
|
lineshortmedia,
|
|
@@ -5,7 +5,7 @@ import { label } from '../../inline/extension/label';
|
|
|
5
5
|
import { html } from 'typed-dom/dom';
|
|
6
6
|
|
|
7
7
|
export const figbase: ExtensionParser.FigbaseParser = block(fmap(
|
|
8
|
-
validate(/\[?\$-(?:[0-9]+\.)*0\]?
|
|
8
|
+
validate(/\[?\$-(?:[0-9]+\.)*0\]?(?:$|[ \n])/y,
|
|
9
9
|
line(union([label]))),
|
|
10
10
|
([{ value: el }]) => {
|
|
11
11
|
const label = el.getAttribute('data-label')!;
|
|
@@ -71,7 +71,7 @@ describe('Unit: parser/block/extension/figure', () => {
|
|
|
71
71
|
assert.deepStrictEqual(inspect(parser('~~~figure [$-0.0]\n$$\n\n$$\n~~~'), ctx), [['<figure data-type="math" data-label="$-0.0" data-group="$" class="invalid"><figcaption><span class="figindex"></span><span class="figtext"></span></figcaption><div><div class="math" translate="no">$$\n\n$$</div></div></figure>'], '']);
|
|
72
72
|
assert.deepStrictEqual(inspect(parser('~~~figure [$-name]\n!https://host\n~~~'), ctx), [['<figure data-type="media" data-label="$-name" data-group="$" class="invalid"><figcaption><span class="figindex"></span><span class="figtext"></span></figcaption><div><a href="https://host" target="_blank"><img class="media" data-src="https://host" alt="https://host"></a></div></figure>'], '']);
|
|
73
73
|
assert.deepStrictEqual(inspect(parser('~~~figure [$-name]\n$$\n\n$$\n\ncaption\n~~~'), ctx), [['<figure data-type="math" data-label="$-name" data-group="$" class="invalid"><figcaption><span class="figindex"></span><span class="figtext">caption</span></figcaption><div><div class="math" translate="no">$$\n\n$$</div></div></figure>'], '']);
|
|
74
|
-
assert.deepStrictEqual(inspect(parser(`~~~figure [$group-name]\n${'
|
|
74
|
+
assert.deepStrictEqual(inspect(parser(`~~~figure [$group-name]\n${'> \n'.repeat(500)}\n~~~`), ctx, '>'), [['<figure data-type="quote" data-label="group-name" data-group="group">'], '']);
|
|
75
75
|
assert.deepStrictEqual(inspect(parser(`~~~figure [$group-name]\n~~~\n0${'\n'.repeat(300)}~~~\n~~~`), ctx, '>'), [['<figure data-type="example" data-label="group-name" data-group="group">'], '']);
|
|
76
76
|
});
|
|
77
77
|
|
|
@@ -21,7 +21,7 @@ import { html, defrag } from 'typed-dom/dom';
|
|
|
21
21
|
import FigureParser = ExtensionParser.FigureParser;
|
|
22
22
|
|
|
23
23
|
export const segment: FigureParser.SegmentParser = block(match(
|
|
24
|
-
/(~{3,})(?:figure
|
|
24
|
+
/(~{3,})(?:figure )?(?=\[?\$)/y,
|
|
25
25
|
memoize(
|
|
26
26
|
([, fence], closer = new RegExp(String.raw`${fence}[^\S\n]*(?:$|\n)`, 'y')) => close(
|
|
27
27
|
sequence([
|
|
@@ -44,12 +44,12 @@ export const segment: FigureParser.SegmentParser = block(match(
|
|
|
44
44
|
]),
|
|
45
45
|
]),
|
|
46
46
|
closer),
|
|
47
|
-
([, fence]) => fence.length
|
|
47
|
+
([, fence]) => fence.length - 1, [], 2 ** 4 - 1)));
|
|
48
48
|
|
|
49
49
|
export const figure: FigureParser = block(fallback(rewrite(segment, fmap(
|
|
50
50
|
convert(source => source.slice(source.match(/^~+(?:\w+\s+)?/)![0].length, source.trimEnd().lastIndexOf('\n')),
|
|
51
51
|
sequence([
|
|
52
|
-
line(sequence([label, str(/(
|
|
52
|
+
line(sequence([label, str(/(?!\S).*\n/y)])),
|
|
53
53
|
inits([
|
|
54
54
|
block(union([
|
|
55
55
|
ulist,
|
|
@@ -83,7 +83,7 @@ export const figure: FigureParser = block(fallback(rewrite(segment, fmap(
|
|
|
83
83
|
]);
|
|
84
84
|
})),
|
|
85
85
|
fmap(
|
|
86
|
-
fence(/(~{3,})(?:figure|\[
|
|
86
|
+
fence(/(~{3,})(?:figure(?=$|[ \n])|\[?\$)[^\n]*(?:$|\n)/y, 300),
|
|
87
87
|
(nodes, context) => {
|
|
88
88
|
const [body, overflow, closer, opener, delim] = unwrap<string>(nodes);
|
|
89
89
|
const violation =
|
|
@@ -95,11 +95,11 @@ export const figure: FigureParser = block(fallback(rewrite(segment, fmap(
|
|
|
95
95
|
'fence',
|
|
96
96
|
`Invalid trailing line after the closing delimiter "${delim}"`,
|
|
97
97
|
] ||
|
|
98
|
-
!seg_label(subinput(opener.match(/^~+(?:figure
|
|
98
|
+
!seg_label(subinput(opener.match(/^~+(?:figure )?(\[?\$\S+)/)?.[1] ?? '', context)) && [
|
|
99
99
|
'label',
|
|
100
100
|
'Invalid label',
|
|
101
101
|
] ||
|
|
102
|
-
/^~+(?:figure
|
|
102
|
+
/^~+(?:figure )?(\[?\$\S+)[^\S\n]+\S/.test(opener) && [
|
|
103
103
|
'argument',
|
|
104
104
|
'Invalid argument',
|
|
105
105
|
] ||
|
|
@@ -20,7 +20,7 @@ import { html } from 'typed-dom/dom';
|
|
|
20
20
|
import MessageParser = ExtensionParser.MessageParser;
|
|
21
21
|
|
|
22
22
|
export const message: MessageParser = block(fmap(
|
|
23
|
-
fence(/(~{3,})message\/(\S+)([^\n]*)(?:$|\n)/y, 300),
|
|
23
|
+
fence(/(~{3,})message\/(\S+)(?!\S)([^\n]*)(?:$|\n)/y, 300),
|
|
24
24
|
// Bug: Type mismatch between outer and inner.
|
|
25
25
|
(nodes: List<Data<string>>, context) => {
|
|
26
26
|
const [body, overflow, closer, opener, delim, type, param] = unwrap(nodes);
|
|
@@ -83,10 +83,10 @@ const align: AlignParser = line(fmap(
|
|
|
83
83
|
union([str(alignment)]),
|
|
84
84
|
([{ value }]) => new List([new Data(value.split('/').map(s => s.split('')) as [string[], string[]?])])));
|
|
85
85
|
|
|
86
|
-
const delimiter = /[-=<>]+(?:\/[-=^v]*)?(?=[^\S\n]*\n)|[#:](?:(?!:\D|0)\d*:(?!0)\d*)?(?:!+[+]?)?(
|
|
86
|
+
const delimiter = /[-=<>]+(?:\/[-=^v]*)?(?=[^\S\n]*\n)|[#:](?:(?!:\D|0)\d*:(?!0)\d*)?(?:!+[+]?)?(?=[ \n])/y;
|
|
87
87
|
|
|
88
88
|
const head: CellParser.HeadParser = block(fmap(open(
|
|
89
|
-
str(/#(?:(?!:\D|0)\d*:(?!0)\d*)?(?:!+[+]?)?(
|
|
89
|
+
str(/#(?:(?!:\D|0)\d*:(?!0)\d*)?(?:!+[+]?)?(?=[ \n])/y),
|
|
90
90
|
rewrite(
|
|
91
91
|
inits([
|
|
92
92
|
anyline,
|
|
@@ -108,7 +108,7 @@ const head: CellParser.HeadParser = block(fmap(open(
|
|
|
108
108
|
false);
|
|
109
109
|
|
|
110
110
|
const data: CellParser.DataParser = block(fmap(open(
|
|
111
|
-
str(/:(?:(?!:\D|0)\d*:(?!0)\d*)?(?:!+[+]?)?(
|
|
111
|
+
str(/:(?:(?!:\D|0)\d*:(?!0)\d*)?(?:!+[+]?)?(?=[ \n])/y),
|
|
112
112
|
rewrite(
|
|
113
113
|
inits([
|
|
114
114
|
anyline,
|
|
@@ -133,7 +133,7 @@ const dataline: CellParser.DatalineParser = line(
|
|
|
133
133
|
rewrite(
|
|
134
134
|
contentline,
|
|
135
135
|
union([
|
|
136
|
-
validate(
|
|
136
|
+
validate(/!+ /y, convert(source => `:${source}`, data, false)),
|
|
137
137
|
convert(source => `: ${source}`, data, false),
|
|
138
138
|
])));
|
|
139
139
|
|
|
@@ -1,16 +1,16 @@
|
|
|
1
1
|
import { HeadingParser } from '../block';
|
|
2
2
|
import { State } from '../context';
|
|
3
3
|
import { List, Data } from '../../combinator/data/parser';
|
|
4
|
-
import { union, some, state, block, line,
|
|
4
|
+
import { union, some, state, block, line, focus, rewrite, open, fmap } from '../../combinator';
|
|
5
5
|
import { inline, indexee, indexer, dataindex } from '../inline';
|
|
6
6
|
import { str } from '../source';
|
|
7
7
|
import { visualize, trimBlank } from '../visibility';
|
|
8
8
|
import { unwrap, invalid } from '../util';
|
|
9
9
|
import { html, defrag } from 'typed-dom/dom';
|
|
10
10
|
|
|
11
|
-
export const segment: HeadingParser.SegmentParser = block(
|
|
12
|
-
/#+
|
|
13
|
-
some(line(({ context: { source } }) => new List([new Data(source)])))))
|
|
11
|
+
export const segment: HeadingParser.SegmentParser = block(focus(
|
|
12
|
+
/#+ +\S[^\n]*(?:\n#+(?=$|[ \n])[^\n]*)*(?:$|\n)/y,
|
|
13
|
+
some(line(({ context: { source } }) => new List([new Data(source)])))));
|
|
14
14
|
|
|
15
15
|
export const heading: HeadingParser = block(rewrite(segment,
|
|
16
16
|
// その他の表示制御は各所のCSSで行う。
|
|
@@ -12,12 +12,12 @@ export const cite: ReplyParser.CiteParser = line(fmap(
|
|
|
12
12
|
open(
|
|
13
13
|
str(syntax),
|
|
14
14
|
union([
|
|
15
|
-
anchor,
|
|
15
|
+
line(anchor),
|
|
16
16
|
// Subject page representation.
|
|
17
17
|
// リンクの実装は後で検討
|
|
18
18
|
focus(/>>#\S*(?=\s*$)/y, ({ context: { source } }) => new List([new Data(html('a', { class: 'anchor' }, source))])),
|
|
19
19
|
focus(/>>https?:\/\/\S+(?=\s*$)/y, ({ context: { source } }) => new List([new Data(html('a', { class: 'anchor', href: source.slice(2).trimEnd(), target: '_blank' }, source))])),
|
|
20
|
-
focus(
|
|
20
|
+
focus(/>>\S+(?=\s*$)/y, ({ context: { source } }) => new List([new Data(source)])),
|
|
21
21
|
])),
|
|
22
22
|
nodes => {
|
|
23
23
|
const quotes = nodes.head!.value as string;
|
|
@@ -7,14 +7,14 @@ import { linebreak, unescsource, anyline } from '../../source';
|
|
|
7
7
|
import { unwrap } from '../../util';
|
|
8
8
|
import { html, defrag } from 'typed-dom/dom';
|
|
9
9
|
|
|
10
|
-
export const syntax = />+
|
|
10
|
+
export const syntax = />+ /y;
|
|
11
11
|
|
|
12
12
|
export const quote: ReplyParser.QuoteParser = lazy(() => block(fmap(
|
|
13
13
|
rewrite(
|
|
14
14
|
some(validate(syntax, anyline)),
|
|
15
15
|
convert(
|
|
16
16
|
// TODO: インデント数を渡してインデント数前の行頭確認を行う実装に置き換える
|
|
17
|
-
source => source.replace(/(?<=^>+
|
|
17
|
+
source => source.replace(/(?<=^>+ )/mg, '\r'),
|
|
18
18
|
some(union([
|
|
19
19
|
// quote補助関数が残した数式をパースする。
|
|
20
20
|
math,
|
|
@@ -39,9 +39,7 @@ describe('Unit: parser/block/sidefence', () => {
|
|
|
39
39
|
assert.deepStrictEqual(inspect(parser('| a '), ctx), [['<blockquote class="invalid"><pre> a </pre></blockquote>'], '']);
|
|
40
40
|
assert.deepStrictEqual(inspect(parser('| \na'), ctx), undefined);
|
|
41
41
|
assert.deepStrictEqual(inspect(parser('|\na'), ctx), undefined);
|
|
42
|
-
assert.deepStrictEqual(inspect(parser('|\n a'), ctx), undefined);
|
|
43
|
-
assert.deepStrictEqual(inspect(parser('|\n|'), ctx), [['<blockquote class="invalid"><pre><br></pre></blockquote>'], '']);
|
|
44
|
-
assert.deepStrictEqual(inspect(parser('|\n| a'), ctx), [['<blockquote class="invalid"><pre><br>a</pre></blockquote>'], '']);
|
|
42
|
+
assert.deepStrictEqual(inspect(parser('|\n| a'), ctx), undefined);
|
|
45
43
|
assert.deepStrictEqual(inspect(parser('| http://host'), ctx), [['<blockquote class="invalid"><pre><a class="url" href="http://host" target="_blank">http://host</a></pre></blockquote>'], '']);
|
|
46
44
|
assert.deepStrictEqual(inspect(parser('| http://host)'), ctx), [['<blockquote class="invalid"><pre><a class="url" href="http://host)" target="_blank">http://host)</a></pre></blockquote>'], '']);
|
|
47
45
|
assert.deepStrictEqual(inspect(parser('| !http://host'), ctx), [['<blockquote class="invalid"><pre>!<a class="url" href="http://host" target="_blank">http://host</a></pre></blockquote>'], '']);
|
|
@@ -8,7 +8,7 @@ import { unwrap, invalid } from '../util';
|
|
|
8
8
|
import { html, define, defrag } from 'typed-dom/dom';
|
|
9
9
|
|
|
10
10
|
export const sidefence: SidefenceParser = lazy(() => block(fmap(focus(
|
|
11
|
-
|
|
11
|
+
/\|+ [^\n]*(?:\n\|+(?=$|[ \n])[^\n]*)*(?:$|\n)/y,
|
|
12
12
|
union([source])),
|
|
13
13
|
([{ value }]) => new List([
|
|
14
14
|
new Data(define(value, {
|
|
@@ -17,13 +17,13 @@ export const sidefence: SidefenceParser = lazy(() => block(fmap(focus(
|
|
|
17
17
|
})),
|
|
18
18
|
]))));
|
|
19
19
|
|
|
20
|
-
const opener = /(?=\|\|+(
|
|
21
|
-
const unindent = (source: string) => source.replace(/(?<=^|\n)\|(?:[
|
|
20
|
+
const opener = /(?=\|\|+(?:$|[ \n]))/y;
|
|
21
|
+
const unindent = (source: string) => source.replace(/(?<=^|\n)\|(?: |(?=\|*(?:$|[ \n])))|\n$/g, '');
|
|
22
22
|
|
|
23
23
|
const source: SidefenceParser.SourceParser = lazy(() => fmap(
|
|
24
24
|
some(recursion(Recursion.block, union([
|
|
25
25
|
focus(
|
|
26
|
-
/(?:\|\|+(
|
|
26
|
+
/(?:\|\|+(?=$|[ \n])[^\n]*(?:$|\n))+/y,
|
|
27
27
|
convert(unindent, source, false, true)),
|
|
28
28
|
rewrite(
|
|
29
29
|
some(contentline, opener),
|
|
@@ -28,7 +28,7 @@ export const table: TableParser = lazy(() => block(fmap(validate(
|
|
|
28
28
|
]))));
|
|
29
29
|
|
|
30
30
|
const row = <P extends CellParser | AlignParser>(parser: P, optional: boolean): RowParser<P> => fallback(fmap(
|
|
31
|
-
line(surround(/(?=\|)/y, some(union([parser])),
|
|
31
|
+
line(surround(/(?=\|)/y, some(union([parser])), /\|?\s*$/y, optional)),
|
|
32
32
|
ns => new List([new Data(html('tr', unwrap(ns)))])),
|
|
33
33
|
rewrite(contentline, ({ context: { source } }) => new List([
|
|
34
34
|
new Data(html('tr', {
|
|
@@ -53,7 +53,7 @@ const cell: CellParser = surround(
|
|
|
53
53
|
close(medialink, /\s*(?=\||$)/y),
|
|
54
54
|
close(media, /\s*(?=\||$)/y),
|
|
55
55
|
close(shortmedia, /\s*(?=\||$)/y),
|
|
56
|
-
trimBlank(some(inline, /\|/y, [[
|
|
56
|
+
trimBlank(some(inline, /\|/y, [[/\|?\s*$/y, 9]])),
|
|
57
57
|
]),
|
|
58
58
|
/[^|]*/y, true);
|
|
59
59
|
|
package/src/parser/block.ts
CHANGED
|
@@ -114,7 +114,7 @@ export const block: BlockParser = reset(
|
|
|
114
114
|
]) as any));
|
|
115
115
|
|
|
116
116
|
function error(parser: BlockParser): BlockParser {
|
|
117
|
-
const reg = new RegExp(String.raw`^${Command.Error}
|
|
117
|
+
const reg = new RegExp(String.raw`^${Command.Error}[^\n]*\n`)
|
|
118
118
|
return recover<BlockParser>(fallback(
|
|
119
119
|
open(Command.Error, ({ context: { source, position } }) => { throw new Error(source.slice(position).split('\n', 1)[0]); }),
|
|
120
120
|
parser),
|
package/src/parser/header.ts
CHANGED
|
@@ -8,7 +8,7 @@ import { normalize } from './api/normalize';
|
|
|
8
8
|
import { html, defrag } from 'typed-dom/dom';
|
|
9
9
|
|
|
10
10
|
export const header: MarkdownParser.HeaderParser = lazy(() => validate(
|
|
11
|
-
/---+
|
|
11
|
+
/---+ *\r?\n(?=\S)/y,
|
|
12
12
|
inits([
|
|
13
13
|
rewrite(
|
|
14
14
|
({ context }) => {
|
|
@@ -24,7 +24,7 @@ export const header: MarkdownParser.HeaderParser = lazy(() => validate(
|
|
|
24
24
|
block(
|
|
25
25
|
union([
|
|
26
26
|
validate(({ context }) => context.header ?? true,
|
|
27
|
-
focus(/(---+)
|
|
27
|
+
focus(/(---+) *\r?\n(?:[A-Za-z][0-9A-Za-z]*(?:-[0-9A-Za-z]+)*:[ \t]+\S[^\r\n]*\r?\n){1,100}\1 *(?:$|\r?\n)/y,
|
|
28
28
|
convert(source =>
|
|
29
29
|
normalize(source.slice(source.indexOf('\n') + 1, source.trimEnd().lastIndexOf('\n'))).replace(/(\S)\s+$/mg, '$1'),
|
|
30
30
|
fmap(
|
|
@@ -48,7 +48,7 @@ export const header: MarkdownParser.HeaderParser = lazy(() => validate(
|
|
|
48
48
|
]);
|
|
49
49
|
},
|
|
50
50
|
]))),
|
|
51
|
-
clear(str(/
|
|
51
|
+
clear(str(/ *\r?\n/y)),
|
|
52
52
|
])));
|
|
53
53
|
|
|
54
54
|
const field: MarkdownParser.HeaderParser.FieldParser = line(({ context: { source, position } }) => {
|