securemark 0.242.0 → 0.243.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/markdown.d.ts CHANGED
@@ -87,6 +87,7 @@ export namespace MarkdownParser {
87
87
  BlockParser.CodeBlockParser,
88
88
  BlockParser.MathBlockParser,
89
89
  BlockParser.ExtensionParser,
90
+ BlockParser.SidefenceParser,
90
91
  BlockParser.BlockquoteParser,
91
92
  BlockParser.ReplyParser,
92
93
  BlockParser.ParagraphParser,
@@ -227,6 +228,22 @@ export namespace MarkdownParser {
227
228
  ]> {
228
229
  }
229
230
  }
231
+ export interface SidefenceParser extends
232
+ // | abc
233
+ Block<'sidefence'>,
234
+ Parser<HTMLQuoteElement, Context, [
235
+ SidefenceParser.SourceParser,
236
+ ]> {
237
+ }
238
+ export namespace SidefenceParser {
239
+ export interface SourceParser extends
240
+ Block<'sidefence/source'>,
241
+ Parser<HTMLQuoteElement, Context, [
242
+ SourceParser,
243
+ AutolinkParser,
244
+ ]> {
245
+ }
246
+ }
230
247
  export interface TableParser extends
231
248
  // |Head|
232
249
  // |:--:|
@@ -371,8 +388,8 @@ export namespace MarkdownParser {
371
388
  Parser<never, Context, [
372
389
  CodeBlockParser.SegmentParser,
373
390
  MathBlockParser.SegmentParser,
374
- BlockquoteParser.SegmentParser,
375
391
  TableParser.SegmentParser,
392
+ BlockquoteParser.SegmentParser,
376
393
  PlaceholderParser.SegmentParser,
377
394
  SourceParser.ContentLineParser,
378
395
  ]>,
@@ -401,8 +418,8 @@ export namespace MarkdownParser {
401
418
  Parser<never, Context, [
402
419
  CodeBlockParser.SegmentParser,
403
420
  MathBlockParser.SegmentParser,
404
- BlockquoteParser.SegmentParser,
405
421
  TableParser.SegmentParser,
422
+ BlockquoteParser.SegmentParser,
406
423
  PlaceholderParser.SegmentParser,
407
424
  SourceParser.ContentLineParser,
408
425
  ]>,
@@ -495,6 +512,7 @@ export namespace MarkdownParser {
495
512
  BlockParser.IndentBlockParser,
496
513
  BlockParser.CodeBlockParser,
497
514
  BlockParser.MathBlockParser,
515
+ BlockParser.SidefenceParser,
498
516
  BlockParser.BlockquoteParser,
499
517
  BlockParser.ParagraphParser,
500
518
  ]> {
package/package-lock.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "securemark",
3
- "version": "0.242.0",
3
+ "version": "0.243.2",
4
4
  "lockfileVersion": 1,
5
5
  "requires": true,
6
6
  "dependencies": {
@@ -1784,9 +1784,9 @@
1784
1784
  "dev": true
1785
1785
  },
1786
1786
  "cacache": {
1787
- "version": "16.0.6",
1788
- "resolved": "https://registry.npmjs.org/cacache/-/cacache-16.0.6.tgz",
1789
- "integrity": "sha512-9a/MLxGaw3LEGes0HaPez2RgZWDV6X0jrgChsuxfEh8xoDoYGxaGrkMe7Dlyjrb655tA/b8fX0qlUg6Ii5MBvw==",
1787
+ "version": "16.0.7",
1788
+ "resolved": "https://registry.npmjs.org/cacache/-/cacache-16.0.7.tgz",
1789
+ "integrity": "sha512-a4zfQpp5vm4Ipdvbj+ZrPonikRhm6WBEd4zT1Yc1DXsmAxrPgDwWBLF/u/wTVXSFPIgOJ1U3ghSa2Xm4s3h28w==",
1790
1790
  "dev": true,
1791
1791
  "requires": {
1792
1792
  "@npmcli/fs": "^2.1.0",
@@ -1962,9 +1962,9 @@
1962
1962
  "dev": true
1963
1963
  },
1964
1964
  "caniuse-lite": {
1965
- "version": "1.0.30001332",
1966
- "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001332.tgz",
1967
- "integrity": "sha512-10T30NYOEQtN6C11YGg411yebhvpnC6Z102+B95eAsN0oB6KUs01ivE8u+G6FMIRtIrVlYXhL+LUwQ3/hXwDWw==",
1965
+ "version": "1.0.30001334",
1966
+ "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001334.tgz",
1967
+ "integrity": "sha512-kbaCEBRRVSoeNs74sCuq92MJyGrMtjWVfhltoHUCW4t4pXFvGjUBrfo47weBRViHkiV3eBYyIsfl956NtHGazw==",
1968
1968
  "dev": true
1969
1969
  },
1970
1970
  "chalk": {
@@ -3075,9 +3075,9 @@
3075
3075
  "dev": true
3076
3076
  },
3077
3077
  "electron-to-chromium": {
3078
- "version": "1.4.123",
3079
- "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.123.tgz",
3080
- "integrity": "sha512-0pHGE53WkYoFbsgwYcVKEpWa6jbzlvkohIEA2CUoZ9b5KC+w/zlMiQHvW/4IBcOh7YoEFqRNavgTk02TBoUTUw==",
3078
+ "version": "1.4.124",
3079
+ "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.124.tgz",
3080
+ "integrity": "sha512-VhaE9VUYU6d2eIb+4xf83CATD+T+3bTzvxvlADkQE+c2hisiw3sZmvEDtsW704+Zky9WZGhBuQXijDVqSriQLA==",
3081
3081
  "dev": true
3082
3082
  },
3083
3083
  "elliptic": {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "securemark",
3
- "version": "0.242.0",
3
+ "version": "0.243.2",
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",
@@ -15,14 +15,8 @@ export const blockquote: BlockquoteParser = lazy(() => block(rewrite(segment, un
15
15
  ]))));
16
16
 
17
17
  const opener = /^(?=>>+(?:$|\s))/;
18
-
19
18
  const indent = block(open(opener, some(contentline, /^>(?:$|\s)/)), false);
20
-
21
- function unindent(source: string): string {
22
- return source
23
- .replace(/\n$/, '')
24
- .replace(/^>(?:$|\s|(?=>+(?:$|\s)))/mg, '');
25
- }
19
+ const unindent = (source: string) => source.replace(/(^|\n)>(?:[^\S\n]|(?=>*(?:$|\s)))|\n$/g, '$1');
26
20
 
27
21
  const source: BlockquoteParser.SourceParser = lazy(() => fmap(
28
22
  some(creator(union([
@@ -5,7 +5,7 @@ import { parse } from '../../api/parse';
5
5
  import { mathblock } from '../mathblock';
6
6
  import { html } from 'typed-dom/dom';
7
7
 
8
- const opener = /^(~{3,})(?:example\/(\S+)|(?!\S))([^\n]*)(?:$|\n)/;
8
+ const opener = /^(~{3,})(?:example\/(\S+))?(?!\S)([^\n]*)(?:$|\n)/;
9
9
 
10
10
  export const example: ExtensionParser.ExampleParser = creator(100, block(validate('~~~', fmap(
11
11
  fence(opener, 300),
@@ -1,12 +1,12 @@
1
1
  import { ExtensionParser } from '../../block';
2
- import { union, sequence, some, block, line, validate, rewrite, close, convert } from '../../../combinator';
2
+ import { union, sequence, some, block, line, validate, 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';
6
6
  import { segment as seg_code } from '../codeblock';
7
7
  import { segment as seg_math } from '../mathblock';
8
- import { segment as seg_blockquote } from '../blockquote';
9
8
  import { segment as seg_table } from './table';
9
+ import { segment as seg_blockquote } from '../blockquote';
10
10
  import { segment as seg_placeholder } from './placeholder';
11
11
 
12
12
  import FigParser = ExtensionParser.FigParser;
@@ -17,17 +17,18 @@ export const segment: FigParser.SegmentParser = block(validate(['[$', '$'],
17
17
  union([
18
18
  seg_code,
19
19
  seg_math,
20
- seg_blockquote,
21
20
  seg_table,
21
+ seg_blockquote,
22
22
  seg_placeholder,
23
23
  some(contentline),
24
24
  ]),
25
25
  ])));
26
26
 
27
- export const fig: FigParser = block(rewrite(segment, convert(
27
+ export const fig: FigParser = block(rewrite(segment, verify(convert(
28
28
  source => {
29
29
  const fence = (/^[^\n]*\n!?>+\s/.test(source) && source.match(/^~{3,}(?=[^\S\n]*$)/mg) || [])
30
30
  .reduce((max, fence) => fence > max ? fence : max, '~~') + '~';
31
31
  return `${fence}figure ${source}\n\n${fence}`;
32
32
  },
33
- union([figure]))));
33
+ union([figure])),
34
+ ([el]) => el.tagName === 'FIGURE')));
@@ -7,25 +7,24 @@ describe('Unit: parser/block/extension/figure', () => {
7
7
  const parser = (source: string) => some(figure)(source, {});
8
8
 
9
9
  it('invalid', () => {
10
- assert.deepStrictEqual(inspect(parser('~~~figure\n!https://host\n~~~')), undefined);
11
- assert.deepStrictEqual(inspect(parser('~~~figure $group-name]\n!https://host\n~~~')), [['<figure data-type="media" data-label="group-name" data-group="group" class="invalid"><figcaption><span class="figindex"></span></figcaption><div><a href="https://host" target="_blank"><img class="media" data-src="https://host" alt=""></a></div></figure>'], '']);
12
- assert.deepStrictEqual(inspect(parser('~~~figure [$group-name\n!https://host\n~~~')), undefined);
13
- assert.deepStrictEqual(inspect(parser('~~~figure [$group-name]\nhttps://host\n~~~')), undefined);
14
- assert.deepStrictEqual(inspect(parser('~~~figure [$group-name]\n!https://host\\\n~~~')), undefined);
15
- assert.deepStrictEqual(inspect(parser('~~~figure [$group-name]\n!https://host\n\\\n~~~')), undefined);
16
- assert.deepStrictEqual(inspect(parser('~~~figure [$group-name]\n!https://host\na\n~~~')), undefined);
17
- assert.deepStrictEqual(inspect(parser('~~~figure [$group-name]\n!https://host\n\n\n\n~~~')), undefined);
18
- assert.deepStrictEqual(inspect(parser('~~~figure [$group-name]\n !https://host\n~~~')), undefined);
19
- assert.deepStrictEqual(inspect(parser('~~~figure [$group-name]\n\n!https://host\n~~~')), undefined);
20
- assert.deepStrictEqual(inspect(parser('~~~figure [$group-name]\n!https://host\n~~~\n~~~')), undefined);
21
- assert.deepStrictEqual(inspect(parser('~~~figure [$group-name]\n!https://host\n~~~~')), undefined);
22
- assert.deepStrictEqual(inspect(parser('~~~~figure [$group-name]\n!https://host\n~~~')), undefined);
23
- assert.deepStrictEqual(inspect(parser('~~~figure [$group-name]a\nhttps://host\n~~~')), undefined);
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"><figcaption><span class="figindex"></span></figcaption><div><a href="https://host" target="_blank"><img class="media" data-src="https://host" alt=""></a></div></figure>'], '']);
25
- assert.deepStrictEqual(inspect(parser('~~~figure [$group-name] a\nhttps://host\n~~~')), undefined);
10
+ assert.deepStrictEqual(inspect(parser('~~~figure\n!https://host\n~~~')), [['<pre class="invalid" translate="no">~~~figure\n!https://host\n~~~</pre>'], '']);
11
+ assert.deepStrictEqual(inspect(parser('~~~figure $group-name]\n!https://host\n~~~')), [['<pre class="invalid" translate="no">~~~figure $group-name]\n!https://host\n~~~</pre>'], '']);
12
+ assert.deepStrictEqual(inspect(parser('~~~figure [$group-name\n!https://host\n~~~')), [['<pre class="invalid" translate="no">~~~figure [$group-name\n!https://host\n~~~</pre>'], '']);
13
+ assert.deepStrictEqual(inspect(parser('~~~figure [$group-name]\nhttps://host\n~~~')), [['<pre class="invalid" translate="no">~~~figure [$group-name]\nhttps://host\n~~~</pre>'], '']);
14
+ assert.deepStrictEqual(inspect(parser('~~~figure [$group-name]\n!https://host\\\n~~~')), [['<pre class="invalid" translate="no">~~~figure [$group-name]\n!https://host\\\n~~~</pre>'], '']);
15
+ assert.deepStrictEqual(inspect(parser('~~~figure [$group-name]\n!https://host\n\\\n~~~')), [['<pre class="invalid" translate="no">~~~figure [$group-name]\n!https://host\n\\\n~~~</pre>'], '']);
16
+ assert.deepStrictEqual(inspect(parser('~~~figure [$group-name]\n!https://host\na\n~~~')), [['<pre class="invalid" translate="no">~~~figure [$group-name]\n!https://host\na\n~~~</pre>'], '']);
17
+ assert.deepStrictEqual(inspect(parser('~~~figure [$group-name]\n!https://host\n\n\n\n~~~')), [['<pre class="invalid" translate="no">~~~figure [$group-name]\n!https://host\n\n\n\n~~~</pre>'], '']);
18
+ assert.deepStrictEqual(inspect(parser('~~~figure [$group-name]\n !https://host\n~~~')), [['<pre class="invalid" translate="no">~~~figure [$group-name]\n !https://host\n~~~</pre>'], '']);
19
+ assert.deepStrictEqual(inspect(parser('~~~figure [$group-name]\n!https://host\n~~~\n~~~')), [['<pre class="invalid" translate="no">~~~figure [$group-name]\n!https://host\n~~~\n~~~</pre>'], '']);
20
+ assert.deepStrictEqual(inspect(parser('~~~figure [$group-name]\n!https://host\n~~~~')), [['<pre class="invalid" translate="no">~~~figure [$group-name]\n!https://host\n~~~~</pre>'], '']);
21
+ assert.deepStrictEqual(inspect(parser('~~~~figure [$group-name]\n!https://host\n~~~')), [['<pre class="invalid" translate="no">~~~~figure [$group-name]\n!https://host\n~~~</pre>'], '']);
22
+ assert.deepStrictEqual(inspect(parser('~~~figure [$group-name]a\nhttps://host\n~~~')), [['<pre class="invalid" translate="no">~~~figure [$group-name]a\nhttps://host\n~~~</pre>'], '']);
23
+ assert.deepStrictEqual(inspect(parser('~~~figure [$group-name]a\n!https://host\n~~~')), [['<pre class="invalid" translate="no">~~~figure [$group-name]a\n!https://host\n~~~</pre>'], '']);
24
+ assert.deepStrictEqual(inspect(parser('~~~figure [$group-name] a\nhttps://host\n~~~')), [['<pre class="invalid" translate="no">~~~figure [$group-name] a\nhttps://host\n~~~</pre>'], '']);
26
25
  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"><figcaption><span class="figindex"></span></figcaption><div><a href="https://host" target="_blank"><img class="media" data-src="https://host" alt=""></a></div></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);
26
+ assert.deepStrictEqual(inspect(parser('~~~figure a[$group-name]\n!https://host\n~~~')), [['<pre class="invalid" translate="no">~~~figure a[$group-name]\n!https://host\n~~~</pre>'], '']);
27
+ assert.deepStrictEqual(inspect(parser('~~~figure a [$group-name]\n!https://host\n~~~')), [['<pre class="invalid" translate="no">~~~figure a [$group-name]\n!https://host\n~~~</pre>'], '']);
29
28
  assert.deepStrictEqual(inspect(parser('~~~ [$group-name]\n!https://host\n~~~')), undefined);
30
29
  assert.deepStrictEqual(inspect(parser('~~~ $group-name\n!https://host\n~~~')), undefined);
31
30
  assert.deepStrictEqual(inspect(parser(' ~~~figure [$group-name]\n!https://host\n~~~')), undefined);
@@ -33,7 +32,8 @@ describe('Unit: parser/block/extension/figure', () => {
33
32
  assert.deepStrictEqual(inspect(parser('~~~figure [$fig-name]\n> \n\n~~~')), [['<figure data-type="quote" data-label="fig-name" data-group="fig" class="invalid"><figcaption><span class="figindex"></span></figcaption><div><blockquote></blockquote></div></figure>'], '']);
34
33
  assert.deepStrictEqual(inspect(parser('~~~figure [$figure-name]\n> \n\n~~~')), [['<figure data-type="quote" data-label="figure-name" data-group="figure" class="invalid"><figcaption><span class="figindex"></span></figcaption><div><blockquote></blockquote></div></figure>'], '']);
35
34
  assert.deepStrictEqual(inspect(parser('~~~figure [$table-name]\n> \n\n~~~')), [['<figure data-type="quote" data-label="table-name" data-group="table" class="invalid"><figcaption><span class="figindex"></span></figcaption><div><blockquote></blockquote></div></figure>'], '']);
36
- assert(!parser('~~~figure [$group-name]\n```\n0' + '\n'.repeat(301) + '```\n~~~'));
35
+ assert.deepStrictEqual(inspect(parser(`~~~figure [$group-name]\n0${'\n'.repeat(301)}~~~`), '>'), [['<pre class="invalid" translate="no">'], '']);
36
+ assert.deepStrictEqual(inspect(parser(`~~~figure [$group-name]\n~~~\n0${'\n'.repeat(301)}~~~\n~~~`), '>'), [['<pre class="invalid" translate="no">'], '\n~~~\n~~~']);
37
37
  });
38
38
 
39
39
  it('valid', () => {
@@ -67,8 +67,8 @@ describe('Unit: parser/block/extension/figure', () => {
67
67
  assert.deepStrictEqual(inspect(parser('~~~figure [$-0.0]\n$$\n\n$$\n~~~')), [['<figure data-type="math" data-label="$-0.0" data-group="$" class="invalid"><figcaption><span class="figindex"></span></figcaption><div><div class="math" translate="no">$$\n\n$$</div></div></figure>'], '']);
68
68
  assert.deepStrictEqual(inspect(parser('~~~figure [$-name]\n!https://host\n~~~')), [['<figure data-type="media" data-label="$-name" data-group="$" class="invalid"><figcaption><span class="figindex"></span></figcaption><div><a href="https://host" target="_blank"><img class="media" data-src="https://host" alt=""></a></div></figure>'], '']);
69
69
  assert.deepStrictEqual(inspect(parser('~~~figure [$-name]\n$$\n\n$$\n\ncaption\n~~~')), [['<figure data-type="math" data-label="$-name" data-group="$" class="invalid"><figcaption><span class="figindex"></span>caption</figcaption><div><div class="math" translate="no">$$\n\n$$</div></div></figure>'], '']);
70
- assert(parser('~~~figure [$group-name]\n```\n0' + '\n'.repeat(300) + '```\n~~~'));
71
- assert(parser('~~~figure [$group-name]\n' + '>\n'.repeat(500) + '\n~~~'));
70
+ assert.deepStrictEqual(inspect(parser(`~~~figure [$group-name]\n${'>\n'.repeat(500)}\n~~~`), '>'), [['<figure data-type="quote" data-label="group-name" data-group="group">'], '']);
71
+ assert.deepStrictEqual(inspect(parser(`~~~figure [$group-name]\n~~~\n0${'\n'.repeat(300)}~~~\n~~~`), '>'), [['<figure data-type="example" data-label="group-name" data-group="group">'], '']);
72
72
  });
73
73
 
74
74
  });
@@ -1,8 +1,8 @@
1
1
  import { undefined } from 'spica/global';
2
2
  import { ExtensionParser } from '../../block';
3
- import { union, inits, sequence, some, block, line, rewrite, context, close, match, convert, trim, fmap } from '../../../combinator';
3
+ import { union, inits, sequence, some, block, line, fence, rewrite, context, close, match, convert, trim, fallback, fmap } from '../../../combinator';
4
4
  import { str, contentline, emptyline } from '../../source';
5
- import { label } from '../../inline/extension/label';
5
+ import { label, segment as seg_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';
@@ -23,36 +23,35 @@ import { unshift } from 'spica/array';
23
23
  import FigureParser = ExtensionParser.FigureParser;
24
24
 
25
25
  export const segment: FigureParser.SegmentParser = block(match(
26
- /^(~{3,})(?:figure[^\S\n]+)?(?=\[?\$[A-Za-z-][^\n]*\n)/,
26
+ /^(~{3,})(?:figure[^\S\n]|(?=\[?\$))/,
27
27
  memoize(
28
- ([, fence], closer = new RegExp(String.raw`^${fence}[^\S\n]*(?:$|\n)`)) =>
29
- close(
30
- sequence([
31
- contentline,
32
- inits([
33
- // All parsers which can include closing terms.
34
- union([
35
- seg_code,
36
- seg_math,
37
- seg_blockquote,
38
- seg_table,
39
- seg_placeholder,
40
- some(contentline, closer),
41
- ]),
28
+ ([, fence], closer = new RegExp(String.raw`^${fence}[^\S\n]*(?:$|\n)`)) => close(
29
+ sequence([
30
+ contentline,
31
+ inits([
32
+ // All parsers which can include closing terms.
33
+ union([
34
+ seg_code,
35
+ seg_math,
36
+ seg_table,
37
+ seg_blockquote,
38
+ seg_placeholder,
39
+ some(contentline, closer),
40
+ ]),
41
+ emptyline,
42
+ union([
42
43
  emptyline,
43
- union([
44
- emptyline,
45
- some(contentline, closer),
46
- ]),
44
+ some(contentline, closer),
47
45
  ]),
48
46
  ]),
49
- closer),
47
+ ]),
48
+ closer),
50
49
  ([, fence]) => fence.length, [])));
51
50
 
52
- export const figure: FigureParser = block(rewrite(segment, fmap(
53
- convert(source => source.slice(source.search(/[[$]/), source.trimEnd().lastIndexOf('\n')),
51
+ export const figure: FigureParser = block(fallback(rewrite(segment, fmap(
52
+ convert(source => source.slice(source.match(/^~+(?:figure[^\S\n]+)?/)![0].length, source.trimEnd().lastIndexOf('\n')),
54
53
  sequence([
55
- line(sequence([label, str(/^.*\n/)])),
54
+ line(sequence([label, str(/^(?=\s).*\n/)])),
56
55
  inits([
57
56
  block(union([
58
57
  ulist,
@@ -83,7 +82,33 @@ export const figure: FigureParser = block(rewrite(segment, fmap(
83
82
  defrag(caption))),
84
83
  html('div', [content]),
85
84
  ])
86
- ])));
85
+ ])),
86
+ fmap(
87
+ fence(/^(~{3,})(?:figure|\[?\$\S*)(?!\S)[^\n]*(?:$|\n)/, 300),
88
+ ([body, closer, opener, delim]: string[], _, context) => [
89
+ html('pre', {
90
+ class: 'invalid',
91
+ translate: 'no',
92
+ 'data-invalid-syntax': 'figure',
93
+ ...
94
+ !closer && {
95
+ 'data-invalid-type': 'fence',
96
+ 'data-invalid-message': `Missing the closing delimiter "${delim}"`,
97
+ } ||
98
+ !seg_label(opener.match(/^~+(?:figure[^\S\n]+)?(\[?\$\S+)/)?.[1] ?? '', context) && {
99
+ 'data-invalid-type': 'label',
100
+ 'data-invalid-message': 'Invalid label',
101
+ } ||
102
+ /^~+(?:figure[^\S\n]+)?(\[?\$\S+)[^\S\n]+\S/.test(opener) && {
103
+ 'data-invalid-type': 'argument',
104
+ 'data-invalid-message': 'Invalid argument',
105
+ } ||
106
+ {
107
+ 'data-invalid-type': 'content',
108
+ 'data-invalid-message': 'Invalid content',
109
+ },
110
+ }, `${opener}${body}${closer}`),
111
+ ])));
87
112
 
88
113
  function attributes(label: string, param: string, content: HTMLElement, caption: readonly HTMLElement[]): Record<string, string | undefined> {
89
114
  const group = label.split('-', 1)[0];
@@ -113,14 +138,14 @@ function attributes(label: string, param: string, content: HTMLElement, caption:
113
138
  assert(false);
114
139
  }
115
140
  const invalid =
116
- /^[^-]+-(?:[0-9]+\.)*0$/.test(label) && {
117
- 'data-invalid-type': 'label',
118
- 'data-invalid-message': 'The last part of the fixed label numbers must not be 0',
119
- } ||
120
141
  param.trimStart() !== '' && {
121
142
  'data-invalid-type': 'argument',
122
143
  'data-invalid-message': 'Invalid argument',
123
144
  } ||
145
+ /^[^-]+-(?:[0-9]+\.)*0$/.test(label) && {
146
+ 'data-invalid-type': 'label',
147
+ 'data-invalid-message': 'The last part of the fixed label numbers must not be 0',
148
+ } ||
124
149
  group === '$' && (type !== 'math' || caption.length > 0) && {
125
150
  'data-invalid-type': 'label',
126
151
  'data-invalid-message': '"$" label group must be used to math formulas with no caption',
@@ -10,6 +10,7 @@ import { table } from '../table';
10
10
  import { indentblock } from '../indentblock';
11
11
  import { codeblock } from '../codeblock';
12
12
  import { mathblock } from '../mathblock';
13
+ import { sidefence } from '../sidefence';
13
14
  import { blockquote } from '../blockquote';
14
15
  import { paragraph } from '../paragraph';
15
16
  import { html } from 'typed-dom/dom';
@@ -69,6 +70,7 @@ const content: MessageParser.ContentParser = union([
69
70
  indentblock,
70
71
  codeblock,
71
72
  mathblock,
73
+ sidefence,
72
74
  blockquote,
73
75
  paragraph,
74
76
  ]);
@@ -18,6 +18,6 @@ export const placeholder: ExtensionParser.PlaceholderParser = block(validate('~~
18
18
  translate: 'no',
19
19
  'data-invalid-syntax': 'extension',
20
20
  'data-invalid-type': !closer ? 'fence' : 'syntax',
21
- 'data-invalid-message': !closer ? `Missing the closing delimiter "${delim}"` : 'Invalid syntax',
22
- }, `${opener}${body}${closer}`)
21
+ 'data-invalid-message': !closer ? `Missing the closing delimiter "${delim}"` : 'Invalid extension name',
22
+ }, `${opener}${body}${closer}`),
23
23
  ])));
@@ -0,0 +1,66 @@
1
+ import { sidefence } from './sidefence';
2
+ import { some } from '../../combinator';
3
+ import { inspect } from '../../debug.test';
4
+
5
+ describe('Unit: parser/block/sidefence', () => {
6
+ describe('sidefence', () => {
7
+ const parser = (source: string) => some(sidefence)(source, {});
8
+
9
+ it('invalid', () => {
10
+ assert.deepStrictEqual(inspect(parser('')), undefined);
11
+ assert.deepStrictEqual(inspect(parser('\n')), undefined);
12
+ assert.deepStrictEqual(inspect(parser('|')), undefined);
13
+ assert.deepStrictEqual(inspect(parser('|a')), undefined);
14
+ assert.deepStrictEqual(inspect(parser('|\n')), undefined);
15
+ assert.deepStrictEqual(inspect(parser(' | ')), undefined);
16
+ assert.deepStrictEqual(inspect(parser('||')), undefined);
17
+ });
18
+
19
+ it('basic', () => {
20
+ assert.deepStrictEqual(inspect(parser('| ')), [['<blockquote class="invalid"></blockquote>'], '']);
21
+ assert.deepStrictEqual(inspect(parser('| \\')), [['<blockquote class="invalid"><pre>\\</pre></blockquote>'], '']);
22
+ assert.deepStrictEqual(inspect(parser('| \\\n')), [['<blockquote class="invalid"><pre>\\</pre></blockquote>'], '']);
23
+ assert.deepStrictEqual(inspect(parser('| a')), [['<blockquote class="invalid"><pre>a</pre></blockquote>'], '']);
24
+ assert.deepStrictEqual(inspect(parser('| a\n')), [['<blockquote class="invalid"><pre>a</pre></blockquote>'], '']);
25
+ assert.deepStrictEqual(inspect(parser('| a\nb')), undefined);
26
+ assert.deepStrictEqual(inspect(parser('| a\n b ')), undefined);
27
+ assert.deepStrictEqual(inspect(parser('| a\n|')), [['<blockquote class="invalid"><pre>a<br></pre></blockquote>'], '']);
28
+ assert.deepStrictEqual(inspect(parser('| a\n>>1')), undefined);
29
+ assert.deepStrictEqual(inspect(parser('| a\n| b ')), [['<blockquote class="invalid"><pre>a<br>b </pre></blockquote>'], '']);
30
+ assert.deepStrictEqual(inspect(parser('| a\n|\n')), [['<blockquote class="invalid"><pre>a<br></pre></blockquote>'], '']);
31
+ assert.deepStrictEqual(inspect(parser('| a\n|\nb')), undefined);
32
+ assert.deepStrictEqual(inspect(parser('| a\n|\n b ')), undefined);
33
+ assert.deepStrictEqual(inspect(parser('| a\n|\n|')), [['<blockquote class="invalid"><pre>a<br><br></pre></blockquote>'], '']);
34
+ assert.deepStrictEqual(inspect(parser('| a\n|\n>>1')), undefined);
35
+ assert.deepStrictEqual(inspect(parser('| a\n|\n| b ')), [['<blockquote class="invalid"><pre>a<br><br>b </pre></blockquote>'], '']);
36
+ assert.deepStrictEqual(inspect(parser('| a\\\nb')), undefined);
37
+ assert.deepStrictEqual(inspect(parser('| a ')), [['<blockquote class="invalid"><pre> a </pre></blockquote>'], '']);
38
+ assert.deepStrictEqual(inspect(parser('| \na')), undefined);
39
+ assert.deepStrictEqual(inspect(parser('|\na')), undefined);
40
+ assert.deepStrictEqual(inspect(parser('|\n a')), undefined);
41
+ assert.deepStrictEqual(inspect(parser('|\n|')), [['<blockquote class="invalid"><pre><br></pre></blockquote>'], '']);
42
+ assert.deepStrictEqual(inspect(parser('|\n| a')), [['<blockquote class="invalid"><pre><br>a</pre></blockquote>'], '']);
43
+ assert.deepStrictEqual(inspect(parser('| http://host')), [['<blockquote class="invalid"><pre><a href="http://host" target="_blank">http://host</a></pre></blockquote>'], '']);
44
+ assert.deepStrictEqual(inspect(parser('| !http://host')), [['<blockquote class="invalid"><pre>!<a href="http://host" target="_blank">http://host</a></pre></blockquote>'], '']);
45
+ assert.deepStrictEqual(inspect(parser('| #a')), [['<blockquote class="invalid"><pre><a href="/hashtags/a" class="hashtag">#a</a></pre></blockquote>'], '']);
46
+ assert.deepStrictEqual(inspect(parser('| @a#b')), [['<blockquote class="invalid"><pre><a href="/@a?ch=b" class="channel">@a#b</a></pre></blockquote>'], '']);
47
+ assert.deepStrictEqual(inspect(parser('| >>1\n| | b')), [['<blockquote class="invalid"><pre><a href="?at=1" class="anchor">&gt;&gt;1</a><br>| b</pre></blockquote>'], '']);
48
+ assert.deepStrictEqual(inspect(parser('| >>1\n| | b\n| c')), [['<blockquote class="invalid"><pre><a href="?at=1" class="anchor">&gt;&gt;1</a><br>| b<br>c</pre></blockquote>'], '']);
49
+ });
50
+
51
+ it('nest', () => {
52
+ assert.deepStrictEqual(inspect(parser('| a\n||')), [['<blockquote class="invalid"><pre>a</pre><blockquote></blockquote></blockquote>'], '']);
53
+ assert.deepStrictEqual(inspect(parser('| a\n|| b\n| c')), [['<blockquote class="invalid"><pre>a</pre><blockquote><pre>b</pre></blockquote><pre>c</pre></blockquote>'], '']);
54
+ assert.deepStrictEqual(inspect(parser('| a\n|| b\n|| c')), [['<blockquote class="invalid"><pre>a</pre><blockquote><pre>b<br>c</pre></blockquote></blockquote>'], '']);
55
+ assert.deepStrictEqual(inspect(parser('| a\n|| b\n||| c')), [['<blockquote class="invalid"><pre>a</pre><blockquote><pre>b</pre><blockquote><pre>c</pre></blockquote></blockquote></blockquote>'], '']);
56
+ assert.deepStrictEqual(inspect(parser('|| a')), [['<blockquote class="invalid"><blockquote><pre>a</pre></blockquote></blockquote>'], '']);
57
+ assert.deepStrictEqual(inspect(parser('|| a\n|')), [['<blockquote class="invalid"><blockquote><pre>a</pre></blockquote></blockquote>'], '']);
58
+ assert.deepStrictEqual(inspect(parser('|| a\n| b')), [['<blockquote class="invalid"><blockquote><pre>a</pre></blockquote><pre>b</pre></blockquote>'], '']);
59
+ assert.deepStrictEqual(inspect(parser('|| a\n||| b\n| c')), [['<blockquote class="invalid"><blockquote><pre>a</pre><blockquote><pre>b</pre></blockquote></blockquote><pre>c</pre></blockquote>'], '']);
60
+ assert.deepStrictEqual(inspect(parser('|| a\n| b\n||| c')), [['<blockquote class="invalid"><blockquote><pre>a</pre></blockquote><pre>b</pre><blockquote><blockquote><pre>c</pre></blockquote></blockquote></blockquote>'], '']);
61
+ assert.deepStrictEqual(inspect(parser('||| a\n|| b\n| c')), [['<blockquote class="invalid"><blockquote><blockquote><pre>a</pre></blockquote><pre>b</pre></blockquote><pre>c</pre></blockquote>'], '']);
62
+ });
63
+
64
+ });
65
+
66
+ });
@@ -0,0 +1,31 @@
1
+ import { SidefenceParser } from '../block';
2
+ import { union, some, block, focus, rewrite, creator, convert, lazy, fmap } from '../../combinator';
3
+ import { autolink } from '../autolink';
4
+ import { contentline } from '../source';
5
+ import { html, define, defrag } from 'typed-dom/dom';
6
+
7
+ export const sidefence: SidefenceParser = lazy(() => block(fmap(focus(
8
+ /^(?=\|+(?:[^\S\n]|\n\|))(?:\|+(?:[^\S\n][^\n]*)?(?:$|\n))+$/,
9
+ union([source])),
10
+ ([el]) => [
11
+ define(el, {
12
+ class: 'invalid',
13
+ 'data-invalid-syntax': 'sidefence',
14
+ 'data-invalid-type': 'syntax',
15
+ 'data-invalid-message': 'Reserved syntax',
16
+ }),
17
+ ])));
18
+
19
+ const opener = /^(?=\|\|+(?:$|\s))/;
20
+ const unindent = (source: string) => source.replace(/(^|\n)\|(?:[^\S\n]|(?=\|*(?:$|\s)))|\n$/g, '$1');
21
+
22
+ const source: SidefenceParser.SourceParser = lazy(() => fmap(
23
+ some(creator(union([
24
+ focus(
25
+ /^(?:\|\|+(?:[^\S\n][^\n]*)?(?:$|\n))+/,
26
+ convert(unindent, source)),
27
+ rewrite(
28
+ some(contentline, opener),
29
+ convert(unindent, fmap(some(autolink), ns => [html('pre', defrag(ns))]))),
30
+ ]))),
31
+ ns => [html('blockquote', ns)]));
@@ -29,9 +29,9 @@ const row = <P extends CellParser | AlignParser>(parser: P, optional: boolean):
29
29
  rewrite(contentline, source => [[
30
30
  html('tr', {
31
31
  class: 'invalid',
32
- 'data-invalid-syntax': 'tablerow',
32
+ 'data-invalid-syntax': 'table-row',
33
33
  'data-invalid-type': 'syntax',
34
- 'data-invalid-message': 'Invalid table row',
34
+ 'data-invalid-message': 'Missing the start symbol of the table row',
35
35
  }, [html('td', source.replace('\n', ''))])
36
36
  ], ''])));
37
37
 
@@ -13,6 +13,7 @@ import { indentblock } from './block/indentblock';
13
13
  import { codeblock } from './block/codeblock';
14
14
  import { mathblock } from './block/mathblock';
15
15
  import { extension } from './block/extension';
16
+ import { sidefence } from './block/sidefence';
16
17
  import { blockquote } from './block/blockquote';
17
18
  import { reply } from './block/reply';
18
19
  import { paragraph } from './block/paragraph';
@@ -31,6 +32,7 @@ export import IndentBlockParser = BlockParser.IndentBlockParser;
31
32
  export import CodeBlockParser = BlockParser.CodeBlockParser;
32
33
  export import MathBlockParser = BlockParser.MathBlockParser;
33
34
  export import ExtensionParser = BlockParser.ExtensionParser;
35
+ export import SidefenceParser = BlockParser.SidefenceParser;
34
36
  export import BlockquoteParser = BlockParser.BlockquoteParser;
35
37
  export import ReplyParser = BlockParser.ReplyParser;
36
38
  export import ParagraphParser = BlockParser.ParagraphParser;
@@ -50,6 +52,7 @@ export const block: BlockParser = creator(error(
50
52
  codeblock,
51
53
  mathblock,
52
54
  extension,
55
+ sidefence,
53
56
  blockquote,
54
57
  reply,
55
58
  paragraph
@@ -14,12 +14,12 @@ export const placeholder: ExtensionParser.PlaceholderParser = lazy(() => creator
14
14
  str(/^\[[:^]/),
15
15
  startTight(some(union([inline]), ']')),
16
16
  str(']'), false,
17
- ([, bs], rest) => [[
17
+ ([as, bs], rest) => [[
18
18
  html('span', {
19
19
  class: 'invalid',
20
20
  'data-invalid-syntax': 'extension',
21
21
  'data-invalid-type': 'syntax',
22
- 'data-invalid-message': 'Invalid symbol',
22
+ 'data-invalid-message': `Reserved start symbol "${as[0][1]}" cannot be used in "[]"`,
23
23
  }, defrag(bs)),
24
24
  ], rest],
25
25
  ([as, bs], rest) => [unshift(as, bs), rest]))));
@@ -93,22 +93,29 @@ describe('Unit: parser/inline/html', () => {
93
93
  assert.deepStrictEqual(inspect(parser('<small __proto__>a</small>')), undefined);
94
94
  assert.deepStrictEqual(inspect(parser('<small constructor>a</small>')), [['<span class="invalid">&lt;small constructor&gt;a&lt;/small&gt;</span>'], '']);
95
95
  assert.deepStrictEqual(inspect(parser('<small toString>a</small>')), undefined);
96
+ assert.deepStrictEqual(inspect(parser('<small X>a</small>')), undefined);
97
+ assert.deepStrictEqual(inspect(parser('<small x>a</small>')), [['<span class="invalid">&lt;small x&gt;a&lt;/small&gt;</span>'], '']);
96
98
  assert.deepStrictEqual(inspect(parser('<bdo>a</bdo>')), [['<span class="invalid">&lt;bdo&gt;a&lt;/bdo&gt;</span>'], '']);
97
99
  assert.deepStrictEqual(inspect(parser('<bdo >a</bdo>')), [['<span class="invalid">&lt;bdo &gt;a&lt;/bdo&gt;</span>'], '']);
98
100
  assert.deepStrictEqual(inspect(parser('<bdo __proto__>a</bdo>')), undefined);
99
101
  assert.deepStrictEqual(inspect(parser('<bdo constructor>a</bdo>')), [['<span class="invalid">&lt;bdo constructor&gt;a&lt;/bdo&gt;</span>'], '']);
100
102
  assert.deepStrictEqual(inspect(parser('<bdo toString>a</bdo>')), undefined);
103
+ assert.deepStrictEqual(inspect(parser('<bdo X>a</bdo>')), undefined);
104
+ assert.deepStrictEqual(inspect(parser('<bdo x>a</bdo>')), [['<span class="invalid">&lt;bdo x&gt;a&lt;/bdo&gt;</span>'], '']);
101
105
  assert.deepStrictEqual(inspect(parser('<bdo dir>a</bdo>')), [['<span class="invalid">&lt;bdo dir&gt;a&lt;/bdo&gt;</span>'], '']);
102
106
  assert.deepStrictEqual(inspect(parser('<bdo dir=>a</bdo>')), undefined);
103
107
  assert.deepStrictEqual(inspect(parser('<bdo dir=rtl>a</bdo>')), undefined);
104
108
  assert.deepStrictEqual(inspect(parser('<bdo dir=">a</bdo>')), undefined);
105
109
  assert.deepStrictEqual(inspect(parser('<bdo dir="">a</bdo>')), [['<span class="invalid">&lt;bdo dir=""&gt;a&lt;/bdo&gt;</span>'], '']);
106
110
  assert.deepStrictEqual(inspect(parser('<bdo dir="rtl" dir="rtl">a</bdo>')), [['<span class="invalid">&lt;bdo dir="rtl" dir="rtl"&gt;a&lt;/bdo&gt;</span>'], '']);
111
+ assert.deepStrictEqual(inspect(parser('<bdo diR="rtl">a</bdo>')), undefined);
107
112
  assert.deepStrictEqual(inspect(parser('<bdo dir="rtl">a</bdo>')), [['<bdo dir="rtl">a</bdo>'], '']);
108
113
  assert.deepStrictEqual(inspect(parser('<bdo dir="rtl" >a</bdo>')), [['<bdo dir="rtl">a</bdo>'], '']);
109
114
  assert.deepStrictEqual(inspect(parser('<bdo dir="rtl" >a</bdo>')), [['<bdo dir="rtl">a</bdo>'], '']);
110
115
  assert.deepStrictEqual(inspect(parser('<bdo dir="rtl">a</bdo>')), [['<bdo dir="rtl">a</bdo>'], '']);
111
116
  assert.deepStrictEqual(inspect(parser('<wbr constructor>')), [['<wbr class="invalid">'], '']);
117
+ assert.deepStrictEqual(inspect(parser('<wbr X>')), undefined);
118
+ assert.deepStrictEqual(inspect(parser('<wbr x>')), [['<wbr class="invalid">'], '']);
112
119
  });
113
120
 
114
121
  });