securemark 0.237.0 → 0.238.0
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 +12 -0
- package/dist/securemark.js +179 -102
- package/markdown.d.ts +1 -1
- package/package-lock.json +16 -16
- package/package.json +1 -1
- package/src/debug.test.ts +1 -1
- package/src/parser/block/codeblock.test.ts +5 -2
- package/src/parser/block/codeblock.ts +43 -25
- package/src/parser/block/extension/aside.ts +1 -1
- package/src/parser/block/extension/example.ts +1 -1
- package/src/parser/block/extension/fig.test.ts +1 -1
- package/src/parser/block/extension/fig.ts +1 -1
- package/src/parser/block/extension/figure.test.ts +2 -0
- package/src/parser/block/extension/figure.ts +22 -25
- package/src/parser/block/extension/message.ts +1 -1
- package/src/parser/block/extension/placeholder.ts +1 -1
- package/src/parser/block/extension/table.ts +1 -1
- package/src/parser/block/heading.test.ts +1 -1
- package/src/parser/block/heading.ts +10 -4
- package/src/parser/block/mathblock.ts +1 -1
- package/src/parser/block.ts +2 -2
- package/src/parser/inline/comment.ts +1 -1
- package/src/parser/inline/extension/index.test.ts +19 -13
- package/src/parser/inline/extension/index.ts +4 -3
- package/src/parser/inline/htmlentity.ts +2 -2
- package/src/parser/inline/media.ts +2 -2
- package/src/parser/inline/ruby.ts +2 -2
- package/src/parser/processor/figure.test.ts +44 -18
- package/src/parser/processor/figure.ts +68 -24
- package/src/parser/processor/footnote.ts +1 -1
- package/src/parser/segment.test.ts +2 -2
- package/src/parser/segment.ts +2 -2
- package/src/parser/source/str.ts +23 -4
- package/src/parser/source/text.ts +3 -0
- package/src/parser/source.ts +1 -1
- package/src/parser/util.ts +2 -2
- package/src/util/quote.ts +1 -0
package/markdown.d.ts
CHANGED
|
@@ -388,7 +388,7 @@ export namespace MarkdownParser {
|
|
|
388
388
|
export interface SegmentParser extends
|
|
389
389
|
Block<'extension/figure/segment'>,
|
|
390
390
|
Parser<never, Context, [
|
|
391
|
-
|
|
391
|
+
SourceParser.ContentLineParser,
|
|
392
392
|
Parser<never, Context, [
|
|
393
393
|
Parser<never, Context, [
|
|
394
394
|
CodeBlockParser.SegmentParser,
|
package/package-lock.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "securemark",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.238.0",
|
|
4
4
|
"lockfileVersion": 1,
|
|
5
5
|
"requires": true,
|
|
6
6
|
"dependencies": {
|
|
@@ -1923,9 +1923,9 @@
|
|
|
1923
1923
|
"dev": true
|
|
1924
1924
|
},
|
|
1925
1925
|
"caniuse-lite": {
|
|
1926
|
-
"version": "1.0.
|
|
1927
|
-
"resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.
|
|
1928
|
-
"integrity": "sha512
|
|
1926
|
+
"version": "1.0.30001325",
|
|
1927
|
+
"resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001325.tgz",
|
|
1928
|
+
"integrity": "sha512-sB1bZHjseSjDtijV1Hb7PB2Zd58Kyx+n/9EotvZ4Qcz2K3d0lWB8dB4nb8wN/TsOGFq3UuAm0zQZNQ4SoR7TrQ==",
|
|
1929
1929
|
"dev": true
|
|
1930
1930
|
},
|
|
1931
1931
|
"chalk": {
|
|
@@ -4915,9 +4915,9 @@
|
|
|
4915
4915
|
}
|
|
4916
4916
|
},
|
|
4917
4917
|
"graceful-fs": {
|
|
4918
|
-
"version": "4.2.
|
|
4919
|
-
"resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.
|
|
4920
|
-
"integrity": "sha512-
|
|
4918
|
+
"version": "4.2.10",
|
|
4919
|
+
"resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.10.tgz",
|
|
4920
|
+
"integrity": "sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA==",
|
|
4921
4921
|
"dev": true
|
|
4922
4922
|
},
|
|
4923
4923
|
"growl": {
|
|
@@ -8018,15 +8018,15 @@
|
|
|
8018
8018
|
}
|
|
8019
8019
|
},
|
|
8020
8020
|
"npm-check-updates": {
|
|
8021
|
-
"version": "12.5.
|
|
8022
|
-
"resolved": "https://registry.npmjs.org/npm-check-updates/-/npm-check-updates-12.5.
|
|
8023
|
-
"integrity": "sha512-
|
|
8021
|
+
"version": "12.5.7",
|
|
8022
|
+
"resolved": "https://registry.npmjs.org/npm-check-updates/-/npm-check-updates-12.5.7.tgz",
|
|
8023
|
+
"integrity": "sha512-WDkqPBevmgphV1UH3FImsDEpTAq2UFvnMZC3GdXPknE2VL701kfKylnae8IA9ZeYfm/uU0249N9gjMXqA/9y3w==",
|
|
8024
8024
|
"dev": true,
|
|
8025
8025
|
"requires": {
|
|
8026
8026
|
"chalk": "^4.1.2",
|
|
8027
8027
|
"cint": "^8.2.1",
|
|
8028
8028
|
"cli-table": "^0.3.11",
|
|
8029
|
-
"commander": "^9.
|
|
8029
|
+
"commander": "^9.1.0",
|
|
8030
8030
|
"fast-memoize": "^2.5.2",
|
|
8031
8031
|
"find-up": "5.0.0",
|
|
8032
8032
|
"fp-and-or": "^0.1.3",
|
|
@@ -8039,11 +8039,11 @@
|
|
|
8039
8039
|
"lodash": "^4.17.21",
|
|
8040
8040
|
"minimatch": "^5.0.1",
|
|
8041
8041
|
"p-map": "^4.0.0",
|
|
8042
|
-
"pacote": "^13.0.
|
|
8042
|
+
"pacote": "^13.0.5",
|
|
8043
8043
|
"parse-github-url": "^1.0.2",
|
|
8044
8044
|
"progress": "^2.0.3",
|
|
8045
8045
|
"prompts": "^2.4.2",
|
|
8046
|
-
"rc-config-loader": "^4.
|
|
8046
|
+
"rc-config-loader": "^4.1.0",
|
|
8047
8047
|
"remote-git-tags": "^3.0.0",
|
|
8048
8048
|
"rimraf": "^3.0.2",
|
|
8049
8049
|
"semver": "^7.3.5",
|
|
@@ -9124,9 +9124,9 @@
|
|
|
9124
9124
|
}
|
|
9125
9125
|
},
|
|
9126
9126
|
"rc-config-loader": {
|
|
9127
|
-
"version": "4.
|
|
9128
|
-
"resolved": "https://registry.npmjs.org/rc-config-loader/-/rc-config-loader-4.
|
|
9129
|
-
"integrity": "sha512
|
|
9127
|
+
"version": "4.1.0",
|
|
9128
|
+
"resolved": "https://registry.npmjs.org/rc-config-loader/-/rc-config-loader-4.1.0.tgz",
|
|
9129
|
+
"integrity": "sha512-aW+kX4qy0CiM9L4fG4Us3oEOpIrOrXzWykAn+xldD07Y9PXWjTH744oHbv0Kc9ZwWaylw3jMjxaf14RgStrNrA==",
|
|
9130
9130
|
"dev": true,
|
|
9131
9131
|
"requires": {
|
|
9132
9132
|
"debug": "^4.1.1",
|
package/package.json
CHANGED
package/src/debug.test.ts
CHANGED
|
@@ -19,7 +19,7 @@ export function inspect(result: Result<HTMLElement | string>, until: number | st
|
|
|
19
19
|
? until
|
|
20
20
|
: ~(~node.outerHTML.indexOf(until) || -Infinity) + until.length;
|
|
21
21
|
const el = html('div');
|
|
22
|
-
assert(!node.outerHTML.match(/[\
|
|
22
|
+
assert(!node.outerHTML.match(/[\x00-\x08\x0B-\x1F\x7F]/));
|
|
23
23
|
el.innerHTML = node.outerHTML.slice(0, until);
|
|
24
24
|
if (node.outerHTML.length <= until) {
|
|
25
25
|
assert(node.outerHTML === el.innerHTML);
|
|
@@ -47,7 +47,7 @@ describe('Unit: parser/block/codeblock', () => {
|
|
|
47
47
|
it('attribute', () => {
|
|
48
48
|
assert.deepStrictEqual(inspect(parser('```0\n```')), [['<pre class="code language-0" translate="no" data-lang="0"></pre>'], '']);
|
|
49
49
|
assert.deepStrictEqual(inspect(parser('```a\n```')), [['<pre class="code language-a" translate="no" data-lang="a"></pre>'], '']);
|
|
50
|
-
assert.deepStrictEqual(inspect(parser('```A\n```')), [['<pre class="
|
|
50
|
+
assert.deepStrictEqual(inspect(parser('```A\n```')), [['<pre class="code language-a" translate="no" data-lang="a"></pre>'], '']);
|
|
51
51
|
assert.deepStrictEqual(inspect(parser('```a-b\n```')), [['<pre class="code language-a-b" translate="no" data-lang="a-b"></pre>'], '']);
|
|
52
52
|
assert.deepStrictEqual(inspect(parser('```a-b0\n```')), [['<pre class="code language-a-b0" translate="no" data-lang="a-b0"></pre>'], '']);
|
|
53
53
|
assert.deepStrictEqual(inspect(parser('```a--b\n```')), [['<pre class="text" translate="no" data-path="a--b"></pre>'], '']);
|
|
@@ -62,7 +62,10 @@ describe('Unit: parser/block/codeblock', () => {
|
|
|
62
62
|
assert.deepStrictEqual(inspect(parser('```.b\n```')), [['<pre class="text" translate="no" data-path=".b"></pre>'], '']);
|
|
63
63
|
assert.deepStrictEqual(inspect(parser('```b.c\n```')), [['<pre class="code language-c" translate="no" data-lang="c" data-path="b.c"></pre>'], '']);
|
|
64
64
|
assert.deepStrictEqual(inspect(parser('```a b.c\n```')), [['<pre class="code language-a" translate="no" data-lang="a" data-path="b.c"></pre>'], '']);
|
|
65
|
-
assert.deepStrictEqual(inspect(parser('```
|
|
65
|
+
assert.deepStrictEqual(inspect(parser('```a 1\n```')), [['<pre class="code language-a" translate="no" data-lang="a" data-line="1"></pre>'], '']);
|
|
66
|
+
assert.deepStrictEqual(inspect(parser('``` 1\n```')), [['<pre class="text" translate="no" data-line="1"></pre>'], '']);
|
|
67
|
+
assert.deepStrictEqual(inspect(parser('``` 1,2-3\n```')), [['<pre class="text" translate="no" data-line="1,2-3"></pre>'], '']);
|
|
68
|
+
assert.deepStrictEqual(inspect(parser('``` 1 b.c\n```')), [['<pre class="code language-c" translate="no" data-lang="c" data-line="1" data-path="b.c"></pre>'], '']);
|
|
66
69
|
});
|
|
67
70
|
|
|
68
71
|
});
|
|
@@ -3,12 +3,10 @@ import { CodeBlockParser } from '../block';
|
|
|
3
3
|
import { eval } from '../../combinator/data/parser';
|
|
4
4
|
import { some, block, validate, fence, clear, fmap } from '../../combinator';
|
|
5
5
|
import { autolink } from '../autolink';
|
|
6
|
-
import { escsource } from '../source';
|
|
7
6
|
import { html, defrag } from 'typed-dom';
|
|
8
|
-
import { join } from 'spica/array';
|
|
9
7
|
|
|
10
|
-
const opener = /^(`{3,})(?!`)(
|
|
11
|
-
const language = /^[0-9a-z]+(?:-[a-z][0-9a-z]*)
|
|
8
|
+
const opener = /^(`{3,})(?!`)([^\n]*)(?:$|\n)/;
|
|
9
|
+
const language = /^[0-9a-z]+(?:-[a-z][0-9a-z]*)*$/i;
|
|
12
10
|
|
|
13
11
|
export const segment: CodeBlockParser.SegmentParser = block(validate('```',
|
|
14
12
|
clear(fence(opener, 300))));
|
|
@@ -19,35 +17,55 @@ export const segment_: CodeBlockParser.SegmentParser = block(validate('```',
|
|
|
19
17
|
export const codeblock: CodeBlockParser = block(validate('```', fmap(
|
|
20
18
|
fence(opener, 300),
|
|
21
19
|
// Bug: Type mismatch between outer and inner.
|
|
22
|
-
([body, closer, opener, delim,
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
20
|
+
([body, closer, opener, delim, param]: string[], _, context) => {
|
|
21
|
+
const params = param.match(/(?:\\.?|\S)+/g)?.reduce<{
|
|
22
|
+
lang?: string;
|
|
23
|
+
path?: string;
|
|
24
|
+
line?: string;
|
|
25
|
+
invalid?: string;
|
|
26
|
+
}>((params, value, i) => {
|
|
27
|
+
let name: string;
|
|
28
|
+
switch (true) {
|
|
29
|
+
case i === 0
|
|
30
|
+
&& value[0] === param[0]
|
|
31
|
+
&& language.test(value):
|
|
32
|
+
name = 'lang';
|
|
33
|
+
value = value.toLowerCase();
|
|
34
|
+
break;
|
|
35
|
+
case /^\d+(?:[,-]\d+)*$/.test(value):
|
|
36
|
+
name = 'line';
|
|
37
|
+
break;
|
|
38
|
+
default:
|
|
39
|
+
name = 'path';
|
|
40
|
+
if (!params.lang) {
|
|
41
|
+
const file = value.split('/').pop() ?? '';
|
|
42
|
+
params.lang = file && file.includes('.', 1)
|
|
43
|
+
? file.split('.').pop()?.match(language)?.[0].toLowerCase()
|
|
44
|
+
: params.lang;
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
name in params
|
|
48
|
+
? params.invalid = `Duplicate ${name} value`
|
|
49
|
+
: params[name] = value;
|
|
50
|
+
return params;
|
|
51
|
+
}, {}) ?? {};
|
|
52
|
+
if (!closer || params.invalid) return [html('pre', {
|
|
29
53
|
class: 'invalid',
|
|
30
54
|
translate: 'no',
|
|
31
55
|
'data-invalid-syntax': 'codeblock',
|
|
32
|
-
'data-invalid-type': !closer ? '
|
|
33
|
-
'data-invalid-message': !closer ? `Missing the closing delimiter "${delim}"` :
|
|
56
|
+
'data-invalid-type': !closer ? 'fence' : 'argument',
|
|
57
|
+
'data-invalid-message': !closer ? `Missing the closing delimiter "${delim}"` : params.invalid,
|
|
34
58
|
}, `${opener}${body}${closer}`)];
|
|
35
|
-
const file = path.split('/').pop() ?? '';
|
|
36
|
-
const ext = file && file.includes('.', 1)
|
|
37
|
-
? file.split('.').pop()!
|
|
38
|
-
: '';
|
|
39
|
-
lang = language.test(lang || ext)
|
|
40
|
-
? lang || ext
|
|
41
|
-
: lang && 'invalid';
|
|
42
59
|
const el = html('pre',
|
|
43
60
|
{
|
|
44
|
-
class: lang ? `code language-${lang}` : 'text',
|
|
61
|
+
class: params.lang ? `code language-${params.lang}` : 'text',
|
|
45
62
|
translate: 'no',
|
|
46
|
-
'data-lang': lang || undefined,
|
|
47
|
-
'data-
|
|
63
|
+
'data-lang': params.lang || undefined,
|
|
64
|
+
'data-line': params.line || undefined,
|
|
65
|
+
'data-path': params.path || undefined,
|
|
48
66
|
},
|
|
49
|
-
lang
|
|
50
|
-
? context.caches?.code?.get(`${lang}\n${body.slice(0, -1)}`)?.cloneNode(true).childNodes ||
|
|
67
|
+
params.lang
|
|
68
|
+
? context.caches?.code?.get(`${params.lang ?? ''}\n${body.slice(0, -1)}`)?.cloneNode(true).childNodes ||
|
|
51
69
|
body.slice(0, -1) || undefined
|
|
52
70
|
: defrag(eval(some(autolink)(body.slice(0, -1), context), [])));
|
|
53
71
|
return [el];
|
|
@@ -12,7 +12,7 @@ export const aside: ExtensionParser.AsideParser = creator(100, block(validate('~
|
|
|
12
12
|
class: 'invalid',
|
|
13
13
|
translate: 'no',
|
|
14
14
|
'data-invalid-syntax': 'aside',
|
|
15
|
-
'data-invalid-type': !closer ? '
|
|
15
|
+
'data-invalid-type': !closer ? 'fence' : 'argument',
|
|
16
16
|
'data-invalid-message': !closer ? `Missing the closing delimiter "${delim}"` : 'Invalid argument',
|
|
17
17
|
}, `${opener}${body}${closer}`)];
|
|
18
18
|
const annotations = html('ol', { class: 'annotations' });
|
|
@@ -15,7 +15,7 @@ export const example: ExtensionParser.ExampleParser = creator(100, block(validat
|
|
|
15
15
|
class: 'invalid',
|
|
16
16
|
translate: 'no',
|
|
17
17
|
'data-invalid-syntax': 'example',
|
|
18
|
-
'data-invalid-type': !closer ? '
|
|
18
|
+
'data-invalid-type': !closer ? 'fence' : 'argument',
|
|
19
19
|
'data-invalid-message': !closer ? `Missing the closing delimiter "${delim}"` : 'Invalid argument',
|
|
20
20
|
}, `${opener}${body}${closer}`)];
|
|
21
21
|
switch (type) {
|
|
@@ -14,7 +14,7 @@ describe('Unit: parser/block/extension/fig', () => {
|
|
|
14
14
|
assert.deepStrictEqual(inspect(parser('[$group-name]\n !https://host')), undefined);
|
|
15
15
|
assert.deepStrictEqual(inspect(parser('[$group-name]\n\n!https://host')), undefined);
|
|
16
16
|
assert.deepStrictEqual(inspect(parser('[$group-name]a\nhttps://host')), undefined);
|
|
17
|
-
assert.deepStrictEqual(inspect(parser('[$group-name]a\n!https://host')),
|
|
17
|
+
assert.deepStrictEqual(inspect(parser('[$group-name]a\n!https://host')), undefined);
|
|
18
18
|
assert.deepStrictEqual(inspect(parser('[$group-name] a\nhttps://host')), undefined);
|
|
19
19
|
assert.deepStrictEqual(inspect(parser('[$group-name] a\n!https://host')), [['<figure data-type="media" data-label="group-name" data-group="group" class="invalid"><div><a href="https://host" target="_blank"><img class="media" data-src="https://host" alt=""></a></div><figcaption><span class="figindex"></span></figcaption></figure>'], '']);
|
|
20
20
|
assert.deepStrictEqual(inspect(parser('$-a\n$-b')), undefined);
|
|
@@ -24,6 +24,8 @@ describe('Unit: parser/block/extension/figure', () => {
|
|
|
24
24
|
assert.deepStrictEqual(inspect(parser('~~~figure [$group-name]a\n!https://host\n~~~')), [['<figure data-type="media" data-label="group-name" data-group="group" class="invalid"><div><a href="https://host" target="_blank"><img class="media" data-src="https://host" alt=""></a></div><figcaption><span class="figindex"></span></figcaption></figure>'], '']);
|
|
25
25
|
assert.deepStrictEqual(inspect(parser('~~~figure [$group-name] a\nhttps://host\n~~~')), undefined);
|
|
26
26
|
assert.deepStrictEqual(inspect(parser('~~~figure [$group-name] a\n!https://host\n~~~')), [['<figure data-type="media" data-label="group-name" data-group="group" class="invalid"><div><a href="https://host" target="_blank"><img class="media" data-src="https://host" alt=""></a></div><figcaption><span class="figindex"></span></figcaption></figure>'], '']);
|
|
27
|
+
assert.deepStrictEqual(inspect(parser('~~~figure a[$group-name]\n!https://host\n~~~')), undefined);
|
|
28
|
+
assert.deepStrictEqual(inspect(parser('~~~figure a [$group-name]\n!https://host\n~~~')), undefined);
|
|
27
29
|
assert.deepStrictEqual(inspect(parser('~~~ [$group-name]\n!https://host\n~~~')), undefined);
|
|
28
30
|
assert.deepStrictEqual(inspect(parser('~~~ $group-name\n!https://host\n~~~')), undefined);
|
|
29
31
|
assert.deepStrictEqual(inspect(parser(' ~~~figure [$group-name]\n!https://host\n~~~')), undefined);
|
|
@@ -2,7 +2,7 @@ import { undefined } from 'spica/global';
|
|
|
2
2
|
import { ExtensionParser } from '../../block';
|
|
3
3
|
import { union, inits, sequence, some, block, line, rewrite, context, close, match, convert, trim, fmap } from '../../../combinator';
|
|
4
4
|
import { str, contentline, emptyline } from '../../source';
|
|
5
|
-
import { label
|
|
5
|
+
import { label } from '../../inline/extension/label';
|
|
6
6
|
import { ulist } from '../ulist';
|
|
7
7
|
import { olist } from '../olist';
|
|
8
8
|
import { table as styled_table } from '../table';
|
|
@@ -22,12 +22,12 @@ import { unshift } from 'spica/array';
|
|
|
22
22
|
import FigureParser = ExtensionParser.FigureParser;
|
|
23
23
|
|
|
24
24
|
export const segment: FigureParser.SegmentParser = block(match(
|
|
25
|
-
/^(~{3,})(?:figure[^\S\n]+)?(?=\[?\$[A-Za-z-][^\n]*\n
|
|
25
|
+
/^(~{3,})(?:figure[^\S\n]+)?(?=\[?\$[A-Za-z-][^\n]*\n)/,
|
|
26
26
|
memoize(
|
|
27
27
|
([, fence], closer = new RegExp(String.raw`^${fence}[^\S\n]*(?:$|\n)`)) =>
|
|
28
28
|
close(
|
|
29
29
|
sequence([
|
|
30
|
-
|
|
30
|
+
contentline,
|
|
31
31
|
inits([
|
|
32
32
|
// All parsers which can include closing terms.
|
|
33
33
|
union([
|
|
@@ -85,10 +85,6 @@ export const figure: FigureParser = block(rewrite(segment, fmap(
|
|
|
85
85
|
|
|
86
86
|
function attributes(label: string, param: string, content: HTMLElement, caption: readonly HTMLElement[]): Record<string, string | undefined> {
|
|
87
87
|
const group = label.split('-', 1)[0];
|
|
88
|
-
const invalidLabel = /^[^-]+-(?:[0-9]+\.)*0$/.test(label);
|
|
89
|
-
const invalidParam = param.trimStart() !== '';
|
|
90
|
-
const invalidContent = group === '$' && (!content.classList.contains('math') || caption.length > 0);
|
|
91
|
-
const invalid = invalidLabel || invalidParam || invalidContent || undefined;
|
|
92
88
|
let type: string = content.className.split(/\s/)[0];
|
|
93
89
|
switch (type || content.tagName) {
|
|
94
90
|
case 'UL':
|
|
@@ -113,27 +109,28 @@ function attributes(label: string, param: string, content: HTMLElement, caption:
|
|
|
113
109
|
default:
|
|
114
110
|
assert(false);
|
|
115
111
|
}
|
|
112
|
+
const invalid =
|
|
113
|
+
/^[^-]+-(?:[0-9]+\.)*0$/.test(label) && {
|
|
114
|
+
'data-invalid-type': 'label',
|
|
115
|
+
'data-invalid-message': 'The last part of the fixed label numbers must not be 0',
|
|
116
|
+
} ||
|
|
117
|
+
param.trimStart() !== '' && {
|
|
118
|
+
'data-invalid-type': 'argument',
|
|
119
|
+
'data-invalid-message': 'Invalid argument',
|
|
120
|
+
} ||
|
|
121
|
+
group === '$' && (!content.classList.contains('math') || caption.length > 0) && {
|
|
122
|
+
'data-invalid-type': 'content',
|
|
123
|
+
'data-invalid-message': 'A figure labeled to define a formula number can contain only a math formula and no caption',
|
|
124
|
+
} ||
|
|
125
|
+
undefined;
|
|
116
126
|
return {
|
|
117
127
|
'data-type': type,
|
|
118
128
|
'data-label': label,
|
|
119
129
|
'data-group': group,
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
'data-invalid-message': 'The last part of the fixed label numbers must not be 0',
|
|
126
|
-
} ||
|
|
127
|
-
invalidParam && {
|
|
128
|
-
'data-invalid-syntax': 'figure',
|
|
129
|
-
'data-invalid-type': 'argument',
|
|
130
|
-
'data-invalid-message': 'Invalid argument',
|
|
131
|
-
} ||
|
|
132
|
-
invalidContent && {
|
|
133
|
-
'data-invalid-syntax': 'figure',
|
|
134
|
-
'data-invalid-type': 'content',
|
|
135
|
-
'data-invalid-message': 'A figure labeled to define a formula number can contain only a math formula and no caption',
|
|
136
|
-
} ||
|
|
137
|
-
undefined,
|
|
130
|
+
...invalid && {
|
|
131
|
+
class: 'invalid',
|
|
132
|
+
'data-invalid-syntax': 'figure',
|
|
133
|
+
...invalid,
|
|
134
|
+
},
|
|
138
135
|
};
|
|
139
136
|
}
|
|
@@ -24,7 +24,7 @@ export const message: MessageParser = block(validate('~~~', fmap(
|
|
|
24
24
|
class: 'invalid',
|
|
25
25
|
translate: 'no',
|
|
26
26
|
'data-invalid-syntax': 'message',
|
|
27
|
-
'data-invalid-type': !closer ? '
|
|
27
|
+
'data-invalid-type': !closer ? 'fence' : 'argument',
|
|
28
28
|
'data-invalid-message': !closer ? `Missing the closing delimiter "${delim}"` : 'Invalid argument',
|
|
29
29
|
}, `${opener}${body}${closer}`)];
|
|
30
30
|
switch (type) {
|
|
@@ -17,7 +17,7 @@ export const placeholder: ExtensionParser.PlaceholderParser = block(validate('~~
|
|
|
17
17
|
class: 'invalid',
|
|
18
18
|
translate: 'no',
|
|
19
19
|
'data-invalid-syntax': 'extension',
|
|
20
|
-
'data-invalid-type': !closer ? '
|
|
20
|
+
'data-invalid-type': !closer ? 'fence' : 'syntax',
|
|
21
21
|
'data-invalid-message': !closer ? `Missing the closing delimiter "${delim}"` : 'Invalid syntax',
|
|
22
22
|
}, `${opener}${body}${closer}`)
|
|
23
23
|
])));
|
|
@@ -31,7 +31,7 @@ export const table: TableParser = block(validate('~~~', recover(fmap(
|
|
|
31
31
|
class: 'invalid',
|
|
32
32
|
translate: 'no',
|
|
33
33
|
'data-invalid-syntax': 'table',
|
|
34
|
-
'data-invalid-type': !closer ? '
|
|
34
|
+
'data-invalid-type': !closer ? 'fence' : 'argument',
|
|
35
35
|
'data-invalid-message': !closer ? `Missing the closing delimiter "${delim}"` : 'Invalid argument',
|
|
36
36
|
}, `${opener}${body}${closer}`)];
|
|
37
37
|
return eval(parser(body, context)) ?? [html('table')];
|
|
@@ -27,7 +27,7 @@ describe('Unit: parser/block/heading', () => {
|
|
|
27
27
|
assert.deepStrictEqual(inspect(parser('# a\nb')), undefined);
|
|
28
28
|
assert.deepStrictEqual(inspect(parser('# *a\nb*')), undefined);
|
|
29
29
|
assert.deepStrictEqual(inspect(parser('# a\n#b')), undefined);
|
|
30
|
-
assert.deepStrictEqual(inspect(parser('####### a')),
|
|
30
|
+
assert.deepStrictEqual(inspect(parser('####### a')), [['<h6 class="invalid" id="index:a">a</h6>'], '']);
|
|
31
31
|
assert.deepStrictEqual(inspect(parser(' # a')), undefined);
|
|
32
32
|
});
|
|
33
33
|
|
|
@@ -4,10 +4,9 @@ import { inline, indexee, indexer } from '../inline';
|
|
|
4
4
|
import { str } from '../source';
|
|
5
5
|
import { visualize } from '../util';
|
|
6
6
|
import { html, defrag } from 'typed-dom';
|
|
7
|
-
import { shift } from 'spica/array';
|
|
8
7
|
|
|
9
8
|
export const segment: HeadingParser.SegmentParser = block(validate('#', focus(
|
|
10
|
-
|
|
9
|
+
/^#+[^\S\n]+\S[^\n]*(?:\n#+(?!\S)[^\n]*)*(?:$|\n)/,
|
|
11
10
|
some(line(source => [[source], ''])))));
|
|
12
11
|
|
|
13
12
|
export const heading: HeadingParser = block(rewrite(segment,
|
|
@@ -30,6 +29,13 @@ export const heading: HeadingParser = block(rewrite(segment,
|
|
|
30
29
|
}}},
|
|
31
30
|
trim(visualize(some(union([indexer, inline]))))), true),
|
|
32
31
|
]),
|
|
33
|
-
(ns: [string, ...(HTMLElement | string)[]]) => [
|
|
34
|
-
|
|
32
|
+
([h, ...ns]: [string, ...(HTMLElement | string)[]]) => [
|
|
33
|
+
h.length <= 6
|
|
34
|
+
? html(`h${h.length as 1}`, defrag(ns))
|
|
35
|
+
: html(`h6`, {
|
|
36
|
+
class: 'invalid',
|
|
37
|
+
'data-invalid-syntax': 'heading',
|
|
38
|
+
'data-invalid-type': 'syntax',
|
|
39
|
+
'data-invalid-message': 'Heading level must be up to 6',
|
|
40
|
+
}, defrag(ns))
|
|
35
41
|
]))))));
|
|
@@ -22,7 +22,7 @@ export const mathblock: MathBlockParser = block(validate('$$', fmap(
|
|
|
22
22
|
class: 'invalid',
|
|
23
23
|
translate: 'no',
|
|
24
24
|
'data-invalid-syntax': 'mathblock',
|
|
25
|
-
'data-invalid-type': delim.length > 2 ? 'syntax' : !closer ? '
|
|
25
|
+
'data-invalid-type': delim.length > 2 ? 'syntax' : !closer ? 'fence' : 'argument',
|
|
26
26
|
'data-invalid-message': delim.length > 2 ? 'Invalid syntax' : !closer ? `Missing the closing delimiter "${delim}"` : 'Invalid argument',
|
|
27
27
|
}, `${opener}${body}${closer}`),
|
|
28
28
|
])));
|
package/src/parser/block.ts
CHANGED
|
@@ -54,7 +54,7 @@ export const block: BlockParser = creator(error(
|
|
|
54
54
|
|
|
55
55
|
function error(parser: BlockParser): BlockParser {
|
|
56
56
|
return recover<BlockParser>(fallback(
|
|
57
|
-
open('\
|
|
57
|
+
open('\x07', source => { throw new Error(source.split('\n', 1)[0]); }),
|
|
58
58
|
parser),
|
|
59
59
|
(source, { id }, reason) => [[
|
|
60
60
|
html('h1',
|
|
@@ -71,7 +71,7 @@ function error(parser: BlockParser): BlockParser {
|
|
|
71
71
|
translate: 'no',
|
|
72
72
|
},
|
|
73
73
|
source
|
|
74
|
-
.replace(/^\
|
|
74
|
+
.replace(/^\x07.*\n/, '')
|
|
75
75
|
.slice(0, 1001)
|
|
76
76
|
.replace(/^(.{997}).{4}$/s, '$1...') || undefined),
|
|
77
77
|
], '']);
|
|
@@ -42,6 +42,7 @@ describe('Unit: parser/inline/extension/index', () => {
|
|
|
42
42
|
assert.deepStrictEqual(inspect(parser('[#a ]')), [['<a class="index" href="#index:a">a</a>'], '']);
|
|
43
43
|
assert.deepStrictEqual(inspect(parser('[#a b]')), [['<a class="index" href="#index:a_b">a b</a>'], '']);
|
|
44
44
|
assert.deepStrictEqual(inspect(parser('[#a b]')), [['<a class="index" href="#index:a_b">a b</a>'], '']);
|
|
45
|
+
assert.deepStrictEqual(inspect(parser('[#a \\ ]')), [['<a class="index" href="#index:a">a</a>'], '']);
|
|
45
46
|
assert.deepStrictEqual(inspect(parser('[#a ]')), [['<a class="index" href="#index:a">a</a>'], '']);
|
|
46
47
|
assert.deepStrictEqual(inspect(parser('[#a <wbr>]')), [['<a class="index" href="#index:a">a</a>'], '']);
|
|
47
48
|
assert.deepStrictEqual(inspect(parser('[#a [# b #]]')), [['<a class="index" href="#index:a">a <span class="comment"><input type="checkbox"><span>[# b #]</span></span></a>'], '']);
|
|
@@ -70,21 +71,26 @@ describe('Unit: parser/inline/extension/index', () => {
|
|
|
70
71
|
assert.deepStrictEqual(inspect(parser('[#|]')), [['<a class="index" href="#index:|">|</a>'], '']);
|
|
71
72
|
assert.deepStrictEqual(inspect(parser('[#|#]')), [['<a class="index" href="#index:|#">|#</a>'], '']);
|
|
72
73
|
assert.deepStrictEqual(inspect(parser('[#|#b]')), [['<a class="index" href="#index:|#b">|#b</a>'], '']);
|
|
73
|
-
assert.deepStrictEqual(inspect(parser('[#a
|
|
74
|
-
assert.deepStrictEqual(inspect(parser('[#a
|
|
75
|
-
assert.deepStrictEqual(inspect(parser('[#a
|
|
76
|
-
assert.deepStrictEqual(inspect(parser('[#a
|
|
77
|
-
assert.deepStrictEqual(inspect(parser('[#a
|
|
74
|
+
assert.deepStrictEqual(inspect(parser('[#a|]')), [['<a class="index" href="#index:a|">a|</a>'], '']);
|
|
75
|
+
assert.deepStrictEqual(inspect(parser('[#a|#]')), [['<a class="index" href="#index:a|#">a|#</a>'], '']);
|
|
76
|
+
assert.deepStrictEqual(inspect(parser('[#a|# ]')), [['<a class="index" href="#index:a|#">a|#</a>'], '']);
|
|
77
|
+
assert.deepStrictEqual(inspect(parser('[#a|#\\ ]')), [['<a class="index" href="#index:a|#">a|#</a>'], '']);
|
|
78
|
+
assert.deepStrictEqual(inspect(parser('[#a|#b]')), [['<a class="index" href="#index:b">a<span class="indexer" data-index="b"></span></a>'], '']);
|
|
79
|
+
assert.deepStrictEqual(inspect(parser('[#a|#b ]')), [['<a class="index" href="#index:b">a<span class="indexer" data-index="b"></span></a>'], '']);
|
|
80
|
+
assert.deepStrictEqual(inspect(parser('[#a|#b ]')), [['<a class="index" href="#index:b">a<span class="indexer" data-index="b"></span></a>'], '']);
|
|
81
|
+
assert.deepStrictEqual(inspect(parser('[#a|#\\b]')), [['<a class="index" href="#index:b">a<span class="indexer" data-index="b"></span></a>'], '']);
|
|
82
|
+
assert.deepStrictEqual(inspect(parser('[#a|#*b*]')), [['<a class="index" href="#index:*b*">a<span class="indexer" data-index="*b*"></span></a>'], '']);
|
|
83
|
+
assert.deepStrictEqual(inspect(parser('[#a|#b c]')), [['<a class="index" href="#index:b_c">a<span class="indexer" data-index="b_c"></span></a>'], '']);
|
|
84
|
+
assert.deepStrictEqual(inspect(parser('[#a|#b c]')), [['<a class="index" href="#index:b_c">a<span class="indexer" data-index="b_c"></span></a>'], '']);
|
|
85
|
+
assert.deepStrictEqual(inspect(parser('[#a|#[]]')), [['<a class="index" href="#index:[]">a<span class="indexer" data-index="[]"></span></a>'], '']);
|
|
86
|
+
assert.deepStrictEqual(inspect(parser('[#a|#©]')), [['<a class="index" href="#index:&copy;">a<span class="indexer" data-index="&copy;"></span></a>'], '']);
|
|
78
87
|
assert.deepStrictEqual(inspect(parser('[#a |#b]')), [['<a class="index" href="#index:b">a<span class="indexer" data-index="b"></span></a>'], '']);
|
|
79
|
-
assert.deepStrictEqual(inspect(parser('[#a |#b ]')), [['<a class="index" href="#index:b">a<span class="indexer" data-index="b"></span></a>'], '']);
|
|
80
|
-
assert.deepStrictEqual(inspect(parser('[#a |#b ]')), [['<a class="index" href="#index:b">a<span class="indexer" data-index="b"></span></a>'], '']);
|
|
81
|
-
assert.deepStrictEqual(inspect(parser('[#a |#\\b]')), [['<a class="index" href="#index:b">a<span class="indexer" data-index="b"></span></a>'], '']);
|
|
82
|
-
assert.deepStrictEqual(inspect(parser('[#a |#*b*]')), [['<a class="index" href="#index:*b*">a<span class="indexer" data-index="*b*"></span></a>'], '']);
|
|
83
|
-
assert.deepStrictEqual(inspect(parser('[#a |#b c]')), [['<a class="index" href="#index:b_c">a<span class="indexer" data-index="b_c"></span></a>'], '']);
|
|
84
|
-
assert.deepStrictEqual(inspect(parser('[#a |#b c]')), [['<a class="index" href="#index:b_c">a<span class="indexer" data-index="b_c"></span></a>'], '']);
|
|
85
|
-
assert.deepStrictEqual(inspect(parser('[#a |#[]]')), [['<a class="index" href="#index:[]">a<span class="indexer" data-index="[]"></span></a>'], '']);
|
|
86
|
-
assert.deepStrictEqual(inspect(parser('[#a |#©]')), [['<a class="index" href="#index:&copy;">a<span class="indexer" data-index="&copy;"></span></a>'], '']);
|
|
87
88
|
assert.deepStrictEqual(inspect(parser('[#a |#b]')), [['<a class="index" href="#index:b">a<span class="indexer" data-index="b"></span></a>'], '']);
|
|
89
|
+
assert.deepStrictEqual(inspect(parser('[#a \\ |#b]')), [['<a class="index" href="#index:b">a<span class="indexer" data-index="b"></span></a>'], '']);
|
|
90
|
+
assert.deepStrictEqual(inspect(parser('[#a |#b]')), [['<a class="index" href="#index:b">a<span class="indexer" data-index="b"></span></a>'], '']);
|
|
91
|
+
assert.deepStrictEqual(inspect(parser('[#a <wbr>|#b]')), [['<a class="index" href="#index:b">a<span class="indexer" data-index="b"></span></a>'], '']);
|
|
92
|
+
assert.deepStrictEqual(inspect(parser('[#a [# b #]|#c]')), [['<a class="index" href="#index:c">a <span class="comment"><input type="checkbox"><span>[# b #]</span></span><span class="indexer" data-index="c"></span></a>'], '']);
|
|
93
|
+
assert.deepStrictEqual(inspect(parser('[#a\\ |#b]')), [['<a class="index" href="#index:b">a<span class="indexer" data-index="b"></span></a>'], '']);
|
|
88
94
|
});
|
|
89
95
|
|
|
90
96
|
});
|
|
@@ -3,7 +3,7 @@ import { ExtensionParser } from '../../inline';
|
|
|
3
3
|
import { union, some, validate, guard, context, creator, surround, open, lazy, fmap } from '../../../combinator';
|
|
4
4
|
import { inline } from '../../inline';
|
|
5
5
|
import { indexee, identity } from './indexee';
|
|
6
|
-
import { txt, str } from '../../source';
|
|
6
|
+
import { txt, str, stropt } from '../../source';
|
|
7
7
|
import { startTight, trimNodeEnd } from '../../util';
|
|
8
8
|
import { html, define, defrag } from 'typed-dom';
|
|
9
9
|
import { join } from 'spica/array';
|
|
@@ -23,10 +23,11 @@ export const index: IndexParser = lazy(() => creator(validate('[#', ']', '\n', f
|
|
|
23
23
|
media: false,
|
|
24
24
|
autolink: false,
|
|
25
25
|
}}},
|
|
26
|
+
open(stropt('|'),
|
|
26
27
|
some(union([
|
|
27
28
|
signature,
|
|
28
29
|
inline,
|
|
29
|
-
]), ']', /^\\?\n/)))),
|
|
30
|
+
]), ']', /^\\?\n/), true)))),
|
|
30
31
|
']'),
|
|
31
32
|
ns => [html('a', trimNodeEnd(defrag(ns)))])),
|
|
32
33
|
([el]: [HTMLAnchorElement]) => [
|
|
@@ -40,7 +41,7 @@ export const index: IndexParser = lazy(() => creator(validate('[#', ']', '\n', f
|
|
|
40
41
|
]))));
|
|
41
42
|
|
|
42
43
|
const signature: IndexParser.SignatureParser = lazy(() => creator(fmap(open(
|
|
43
|
-
|
|
44
|
+
'|#',
|
|
44
45
|
startTight(some(union([bracket, txt]), ']'))),
|
|
45
46
|
ns => [
|
|
46
47
|
html('span', { class: 'indexer', 'data-index': identity(join(ns)).slice(6) }),
|
|
@@ -6,12 +6,12 @@ import { reduce } from 'spica/memoize';
|
|
|
6
6
|
|
|
7
7
|
export const unsafehtmlentity: UnsafeHTMLEntityParser = creator(validate('&', focus(
|
|
8
8
|
/^&[0-9A-Za-z]+;/,
|
|
9
|
-
entity => [[parse(entity) ?? `\
|
|
9
|
+
entity => [[parse(entity) ?? `\x1B${entity}`], ''])));
|
|
10
10
|
|
|
11
11
|
export const htmlentity: HTMLEntityParser = fmap(
|
|
12
12
|
union([unsafehtmlentity]),
|
|
13
13
|
([test]) => [
|
|
14
|
-
test[0] === '\
|
|
14
|
+
test[0] === '\x1B'
|
|
15
15
|
? html('span', {
|
|
16
16
|
class: 'invalid',
|
|
17
17
|
'data-invalid-syntax': 'htmlentity',
|
|
@@ -95,13 +95,13 @@ function sanitize(target: HTMLElement, uri: ReadonlyURL, alt: string): boolean {
|
|
|
95
95
|
});
|
|
96
96
|
return false;
|
|
97
97
|
}
|
|
98
|
-
if (alt.includes('\
|
|
98
|
+
if (alt.includes('\x1B')) {
|
|
99
99
|
define(target, {
|
|
100
100
|
class: void target.classList.add('invalid'),
|
|
101
101
|
'data-invalid-syntax': 'media',
|
|
102
102
|
'data-invalid-type': 'content',
|
|
103
103
|
'data-invalid-message': `Cannot use invalid HTML entitiy "${alt.match(/&[0-9A-Za-z]+;/)![0]}"`,
|
|
104
|
-
alt: target.getAttribute('alt')?.replace(/\
|
|
104
|
+
alt: target.getAttribute('alt')?.replace(/\x1B/g, ''),
|
|
105
105
|
});
|
|
106
106
|
return false;
|
|
107
107
|
}
|
|
@@ -83,8 +83,8 @@ function attributes(texts: string[], rubies: string[]): Record<string, string> {
|
|
|
83
83
|
let attrs: Record<string, string> | undefined;
|
|
84
84
|
for (const ss of [texts, rubies]) {
|
|
85
85
|
for (let i = 0; i < ss.length; ++i) {
|
|
86
|
-
if (ss[i].indexOf('\
|
|
87
|
-
ss[i] = ss[i].replace(/\
|
|
86
|
+
if (ss[i].indexOf('\x1B') === -1) continue;
|
|
87
|
+
ss[i] = ss[i].replace(/\x1B/g, '');
|
|
88
88
|
attrs ??= {
|
|
89
89
|
class: 'invalid',
|
|
90
90
|
'data-invalid-syntax': 'ruby',
|