securemark 0.249.1 → 0.252.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.
Files changed (37) hide show
  1. package/CHANGELOG.md +12 -0
  2. package/README.md +1 -1
  3. package/dist/index.js +120 -141
  4. package/markdown.d.ts +9 -19
  5. package/package.json +3 -3
  6. package/src/combinator/control/manipulation/indent.ts +15 -12
  7. package/src/combinator/control/manipulation/match.ts +2 -3
  8. package/src/parser/api/parse.test.ts +12 -6
  9. package/src/parser/block/blockquote.test.ts +2 -2
  10. package/src/parser/block/dlist.test.ts +2 -1
  11. package/src/parser/block/dlist.ts +4 -4
  12. package/src/parser/block/extension/figure.ts +5 -7
  13. package/src/parser/block/extension/message.ts +0 -2
  14. package/src/parser/block/heading.test.ts +1 -0
  15. package/src/parser/block/heading.ts +4 -4
  16. package/src/parser/block/olist.ts +7 -6
  17. package/src/parser/block/paragraph.test.ts +10 -10
  18. package/src/parser/block/paragraph.ts +2 -2
  19. package/src/parser/block/reply.ts +2 -2
  20. package/src/parser/block/ulist.ts +4 -3
  21. package/src/parser/block.ts +0 -3
  22. package/src/parser/inline/annotation.ts +2 -2
  23. package/src/parser/inline/code.ts +1 -1
  24. package/src/parser/inline/comment.test.ts +44 -44
  25. package/src/parser/inline/comment.ts +2 -2
  26. package/src/parser/inline/extension/index.test.ts +4 -4
  27. package/src/parser/inline/extension/index.ts +4 -5
  28. package/src/parser/inline/extension/placeholder.test.ts +4 -4
  29. package/src/parser/inline/html.ts +3 -3
  30. package/src/parser/inline/link.ts +2 -2
  31. package/src/parser/inline/reference.test.ts +3 -3
  32. package/src/parser/inline/reference.ts +6 -6
  33. package/src/parser/inline.test.ts +2 -2
  34. package/src/parser/source/str.ts +2 -2
  35. package/src/parser/util.ts +15 -11
  36. package/src/parser/block/indentblock.test.ts +0 -30
  37. package/src/parser/block/indentblock.ts +0 -13
package/markdown.d.ts CHANGED
@@ -77,7 +77,6 @@ export namespace MarkdownParser {
77
77
  BlockParser.IListParser,
78
78
  BlockParser.DListParser,
79
79
  BlockParser.TableParser,
80
- BlockParser.IndentBlockParser,
81
80
  BlockParser.CodeBlockParser,
82
81
  BlockParser.MathBlockParser,
83
82
  BlockParser.ExtensionParser,
@@ -283,13 +282,6 @@ export namespace MarkdownParser {
283
282
  }
284
283
  }
285
284
  }
286
- export interface IndentBlockParser extends
287
- // abc
288
- Block<'indentblock'>,
289
- Parser<HTMLPreElement, Context, [
290
- CodeBlockParser,
291
- ]> {
292
- }
293
285
  export interface CodeBlockParser extends
294
286
  // ```js index.js
295
287
  // abc
@@ -358,7 +350,6 @@ export namespace MarkdownParser {
358
350
  UListParser,
359
351
  OListParser,
360
352
  BlockParser.TableParser,
361
- IndentBlockParser,
362
353
  CodeBlockParser,
363
354
  MathBlockParser,
364
355
  ExampleParser,
@@ -503,7 +494,6 @@ export namespace MarkdownParser {
503
494
  BlockParser.OListParser,
504
495
  BlockParser.IListParser,
505
496
  BlockParser.TableParser,
506
- BlockParser.IndentBlockParser,
507
497
  BlockParser.CodeBlockParser,
508
498
  BlockParser.MathBlockParser,
509
499
  BlockParser.SidefenceParser,
@@ -668,13 +658,6 @@ export namespace MarkdownParser {
668
658
  }
669
659
  export namespace InlineParser {
670
660
  interface Inline<T extends string> extends Markdown<`inline/${T}`> { }
671
- export interface AnnotationParser extends
672
- // ((abc))
673
- Inline<'annotation'>,
674
- Parser<HTMLElement, Context, [
675
- InlineParser,
676
- ]> {
677
- }
678
661
  export interface EscapeParser extends
679
662
  // ****
680
663
  // +++
@@ -685,6 +668,13 @@ export namespace MarkdownParser {
685
668
  SourceParser.StrParser,
686
669
  ]> {
687
670
  }
671
+ export interface AnnotationParser extends
672
+ // ((abc))
673
+ Inline<'annotation'>,
674
+ Parser<HTMLElement, Context, [
675
+ InlineParser,
676
+ ]> {
677
+ }
688
678
  export interface ReferenceParser extends
689
679
  // [[abc]]
690
680
  // [[^abbr]]
@@ -692,7 +682,7 @@ export namespace MarkdownParser {
692
682
  Inline<'reference'>,
693
683
  Parser<HTMLElement, Context, [
694
684
  ReferenceParser.AbbrParser,
695
- SourceParser.StrParser,
685
+ InlineParser,
696
686
  InlineParser,
697
687
  ]> {
698
688
  }
@@ -736,7 +726,7 @@ export namespace MarkdownParser {
736
726
  }
737
727
  }
738
728
  export interface CommentParser extends
739
- // [# comment #]
729
+ // [% comment %]
740
730
  Inline<'comment'>,
741
731
  Parser<HTMLElement | string, Context, [
742
732
  InlineParser,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "securemark",
3
- "version": "0.249.1",
3
+ "version": "0.252.0",
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",
@@ -49,9 +49,9 @@
49
49
  "karma-mocha": "^2.0.1",
50
50
  "karma-power-assert": "^1.0.0",
51
51
  "mocha": "^10.0.0",
52
- "npm-check-updates": "^13.1.1",
52
+ "npm-check-updates": "^13.1.2",
53
53
  "semver": "^7.3.7",
54
- "spica": "0.0.564",
54
+ "spica": "0.0.567",
55
55
  "ts-loader": "^9.3.0",
56
56
  "typed-dom": "^0.0.298",
57
57
  "typescript": "4.7.3",
@@ -9,25 +9,28 @@ import { open } from './surround';
9
9
  import { memoize } from 'spica/memoize';
10
10
 
11
11
  export function indent<P extends Parser<unknown>>(parser: P, separation?: boolean): P;
12
- export function indent<T>(parser: Parser<T>, separation = false): Parser<T> {
12
+ export function indent<P extends Parser<unknown>>(opener: RegExp, parser: P, separation?: boolean): P;
13
+ export function indent<T>(opener: RegExp | Parser<T>, parser?: Parser<T> | boolean, separation = false): Parser<T> {
14
+ if (typeof opener === 'function') return indent(/^([ \t])\1*/, opener, parser as boolean);
13
15
  assert(parser);
14
16
  return bind(block(match(
15
- /^(?=(([ \t])\2*))/,
17
+ opener,
16
18
  memoize(
17
- ([, indent]) =>
18
- some(line(open(indent, source => [[unline(source)], '']))),
19
- ([, indent]) => indent.length * 2 + +(indent[0] === ' '), [])), separation),
20
- (nodes, rest, context) => {
21
- const result = parser(nodes.join('\n'), context);
19
+ ([indent]) =>
20
+ some(line(open(indent, source => [[source], '']))),
21
+ ([indent]) => indent.length * 2 + +(indent[0] === ' '), [])), separation),
22
+ (lines, rest, context) => {
23
+ assert(parser = parser as Parser<T>);
24
+ const result = parser(trimBlockEnd(lines.join('')), context);
22
25
  return result && exec(result) === ''
23
26
  ? [eval(result), rest]
24
27
  : undefined;
25
28
  });
26
29
  }
27
30
 
28
- function unline(line: string): string {
29
- return line === ''
30
- || line[line.length - 1] !== '\n'
31
- ? line
32
- : line.slice(0, -1);
31
+ function trimBlockEnd(block: string): string {
32
+ return block === ''
33
+ || block[block.length - 1] !== '\n'
34
+ ? block
35
+ : block.slice(0, -1);
33
36
  }
@@ -9,11 +9,10 @@ export function match<T>(pattern: RegExp, f: (matched: RegExpMatchArray) => Pars
9
9
  const param = source.match(pattern);
10
10
  if (!param) return;
11
11
  assert(source.startsWith(param[0]));
12
- const rest = source.slice(param[0].length);
13
- const result = f(param)(rest, context);
12
+ const result = f(param)(source, context);
14
13
  assert(check(source, result, false));
15
14
  if (!result) return;
16
- return exec(result).length < source.length && exec(result).length <= rest.length
15
+ return exec(result).length < source.length && exec(result).length <= source.length
17
16
  ? result
18
17
  : undefined;
19
18
  };
@@ -52,11 +52,11 @@ describe('Unit: parser/api/parse', () => {
52
52
  [...parse('<wbr>\na').children].map(el => el.outerHTML),
53
53
  ['<p>&lt;wbr&gt;<br>a</p>']);
54
54
  assert.deepStrictEqual(
55
- [...parse('[#\n<wbr>\n#]').children].map(el => el.outerHTML),
56
- ['<p><span class="comment"><input type="checkbox"><span>[#<br>&lt;wbr&gt;<br>#]</span></span></p>']);
55
+ [...parse('[%\n<wbr>\n%]').children].map(el => el.outerHTML),
56
+ ['<p><span class="comment"><input type="checkbox"><span>[%<br>&lt;wbr&gt;<br>%]</span></span></p>']);
57
57
  assert.deepStrictEqual(
58
- [...parse('[#\n<wbr>\n#]\na').children].map(el => el.outerHTML),
59
- ['<p><span class="comment"><input type="checkbox"><span>[#<br>&lt;wbr&gt;<br>#]</span></span><br>a</p>']);
58
+ [...parse('[%\n<wbr>\n%]\na').children].map(el => el.outerHTML),
59
+ ['<p><span class="comment"><input type="checkbox"><span>[%<br>&lt;wbr&gt;<br>%]</span></span><br>a</p>']);
60
60
  });
61
61
 
62
62
  it('linebreak', () => {
@@ -80,6 +80,12 @@ describe('Unit: parser/api/parse', () => {
80
80
  ['<p>a<br>\\<br>b</p>']);
81
81
  });
82
82
 
83
+ it('indent', () => {
84
+ assert.deepStrictEqual(
85
+ [...parse('\ta').children].map(el => el.outerHTML),
86
+ ['<p>\ta</p>']);
87
+ });
88
+
83
89
  it('url', () => {
84
90
  assert.deepStrictEqual(
85
91
  [...parse([
@@ -220,8 +226,8 @@ describe('Unit: parser/api/parse', () => {
220
226
 
221
227
  it('creation', () => {
222
228
  assert.deepStrictEqual(
223
- [...parse('"[# '.repeat(100)).children].map(el => el.outerHTML),
224
- [`<p>${'"[# '.repeat(100).trim()}</p>`]);
229
+ [...parse('"[% '.repeat(100)).children].map(el => el.outerHTML),
230
+ [`<p>${'"[% '.repeat(100).trim()}</p>`]);
225
231
  });
226
232
 
227
233
  it('recursion', () => {
@@ -72,7 +72,7 @@ describe('Unit: parser/block/blockquote', () => {
72
72
  assert.deepStrictEqual(inspect(parser('!> a\\\nb')), [['<blockquote><section><p>a<span class="linebreak"> </span>b</p><ol class="annotations"></ol><ol class="references"></ol></section></blockquote>'], '']);
73
73
  assert.deepStrictEqual(inspect(parser('!> *a\nb*')), [['<blockquote><section><p><em>a<br>b</em></p><ol class="annotations"></ol><ol class="references"></ol></section></blockquote>'], '']);
74
74
  assert.deepStrictEqual(inspect(parser('!> *a\n> b*')), [['<blockquote><section><p><em>a<br>b</em></p><ol class="annotations"></ol><ol class="references"></ol></section></blockquote>'], '']);
75
- assert.deepStrictEqual(inspect(parser('!> a \n b c ')), [['<blockquote><section><p>a<br> b c</p><ol class="annotations"></ol><ol class="references"></ol></section></blockquote>'], '']);
75
+ assert.deepStrictEqual(inspect(parser('!> a \n b c ')), [['<blockquote><section><p> a<br> b c</p><ol class="annotations"></ol><ol class="references"></ol></section></blockquote>'], '']);
76
76
  assert.deepStrictEqual(inspect(parser('!>> a')), [['<blockquote><blockquote><section><p>a</p><ol class="annotations"></ol><ol class="references"></ol></section></blockquote></blockquote>'], '']);
77
77
  assert.deepStrictEqual(inspect(parser('!>> a\n> b')), [['<blockquote><blockquote><section><p>a</p><ol class="annotations"></ol><ol class="references"></ol></section></blockquote><section><p>b</p><ol class="annotations"></ol><ol class="references"></ol></section></blockquote>'], '']);
78
78
  assert.deepStrictEqual(inspect(parser('!> - a')), [['<blockquote><section><ul><li>a</li></ul><ol class="annotations"></ol><ol class="references"></ol></section></blockquote>'], '']);
@@ -90,7 +90,7 @@ describe('Unit: parser/block/blockquote', () => {
90
90
  assert.deepStrictEqual(inspect(parser('!> \na')), [['<blockquote><section><p>a</p><ol class="annotations"></ol><ol class="references"></ol></section></blockquote>'], '']);
91
91
  assert.deepStrictEqual(inspect(parser('!>\n')), undefined);
92
92
  assert.deepStrictEqual(inspect(parser('!>\na')), [['<blockquote><section><p>a</p><ol class="annotations"></ol><ol class="references"></ol></section></blockquote>'], '']);
93
- assert.deepStrictEqual(inspect(parser('!>\n a')), [['<blockquote><section><p>a</p><ol class="annotations"></ol><ol class="references"></ol></section></blockquote>'], '']);
93
+ assert.deepStrictEqual(inspect(parser('!>\n a')), [['<blockquote><section><p> a</p><ol class="annotations"></ol><ol class="references"></ol></section></blockquote>'], '']);
94
94
  assert.deepStrictEqual(inspect(parser('!>\n>')), [['<blockquote><section><ol class="annotations"></ol><ol class="references"></ol></section></blockquote>'], '']);
95
95
  assert.deepStrictEqual(inspect(parser('!>\n> a')), [['<blockquote><section><p>a</p><ol class="annotations"></ol><ol class="references"></ol></section></blockquote>'], '']);
96
96
  assert.deepStrictEqual(inspect(parser('!>> ## a\n> ## a')), [['<blockquote><blockquote><section><h2>a</h2><ol class="annotations"></ol><ol class="references"></ol></section></blockquote><section><h2>a</h2><ol class="annotations"></ol><ol class="references"></ol></section></blockquote>'], '']);
@@ -33,6 +33,7 @@ describe('Unit: parser/block/dlist', () => {
33
33
  it('single', () => {
34
34
  assert.deepStrictEqual(inspect(parser('~ a')), [['<dl><dt id="index:a">a</dt><dd></dd></dl>'], '']);
35
35
  assert.deepStrictEqual(inspect(parser('~ \\')), [['<dl><dt id="index:\\">\\</dt><dd></dd></dl>'], '']);
36
+ assert.deepStrictEqual(inspect(parser('~ \\ a')), [['<dl><dt id="index:a">a</dt><dd></dd></dl>'], '']);
36
37
  assert.deepStrictEqual(inspect(parser('~ a\nb')), [['<dl><dt id="index:a">a</dt><dd>b</dd></dl>'], '']);
37
38
  assert.deepStrictEqual(inspect(parser('~ a\nb\n')), [['<dl><dt id="index:a">a</dt><dd>b</dd></dl>'], '']);
38
39
  assert.deepStrictEqual(inspect(parser('~ a\nb\nc')), [['<dl><dt id="index:a">a</dt><dd>b<br>c</dd></dl>'], '']);
@@ -57,7 +58,7 @@ describe('Unit: parser/block/dlist', () => {
57
58
 
58
59
  it('multiple', () => {
59
60
  assert.deepStrictEqual(inspect(parser('~ a\n: b\n~ c\n: d')), [['<dl><dt id="index:a">a</dt><dd>b</dd><dt id="index:c">c</dt><dd>d</dd></dl>'], '']);
60
- assert.deepStrictEqual(inspect(parser('~ a\n b\nc\n d')), [['<dl><dt id="index:a">a</dt><dd>b<br>c<br> d</dd></dl>'], '']);
61
+ assert.deepStrictEqual(inspect(parser('~ a\n b\nc\n d')), [['<dl><dt id="index:a">a</dt><dd> b<br>c<br> d</dd></dl>'], '']);
61
62
  assert.deepStrictEqual(inspect(parser('~ a\n: b\nc\n: d')), [['<dl><dt id="index:a">a</dt><dd>b<br>c</dd><dd>d</dd></dl>'], '']);
62
63
  assert.deepStrictEqual(inspect(parser('~ a\n: b\nc\n~ d\n: e')), [['<dl><dt id="index:a">a</dt><dd>b<br>c</dd><dt id="index:d">d</dt><dd>e</dd></dl>'], '']);
63
64
  assert.deepStrictEqual(inspect(parser('~ a\n: b\n~ c\n: d\n~ e\n: f')), [['<dl><dt id="index:a">a</dt><dd>b</dd><dt id="index:c">c</dt><dd>d</dd><dt id="index:e">e</dt><dd>f</dd></dl>'], '']);
@@ -1,9 +1,9 @@
1
1
  import { DListParser } from '../block';
2
- import { union, inits, some, block, line, validate, rewrite, context, creator, open, trim, lazy, fmap } from '../../combinator';
2
+ import { union, inits, some, block, line, validate, rewrite, context, creator, open, trimEnd, lazy, fmap } from '../../combinator';
3
3
  import { inline, indexee, indexer } from '../inline';
4
4
  import { anyline } from '../source';
5
5
  import { localize } from '../locale';
6
- import { visualize } from '../util';
6
+ import { visualize, trimBlank } from '../util';
7
7
  import { html, defrag } from 'typed-dom/dom';
8
8
  import { push } from 'spica/array';
9
9
 
@@ -25,7 +25,7 @@ export const dlist: DListParser = lazy(() => block(localize(fmap(validate(
25
25
 
26
26
  const term: DListParser.TermParser = creator(line(indexee(fmap(open(
27
27
  /^~[^\S\n]+(?=\S)/,
28
- trim(visualize(some(union([indexer, inline])))),
28
+ visualize(trimBlank(some(union([indexer, inline])))),
29
29
  true),
30
30
  ns => [html('dt', defrag(ns))]))));
31
31
 
@@ -33,7 +33,7 @@ const desc: DListParser.DescriptionParser = creator(block(fmap(open(
33
33
  /^:[^\S\n]+(?=\S)|/,
34
34
  rewrite(
35
35
  some(anyline, /^[~:][^\S\n]+\S/),
36
- trim(visualize(some(union([inline]))))),
36
+ visualize(trimEnd(some(union([inline]))))),
37
37
  true),
38
38
  ns => [html('dd', defrag(ns))]),
39
39
  false));
@@ -1,12 +1,11 @@
1
1
  import { undefined } from 'spica/global';
2
2
  import { ExtensionParser } from '../../block';
3
- import { union, inits, sequence, some, block, line, fence, rewrite, context, close, match, convert, trim, fallback, fmap } from '../../../combinator';
3
+ import { union, inits, sequence, some, block, line, fence, rewrite, context, close, match, convert, trimEnd, fallback, fmap } from '../../../combinator';
4
4
  import { str, contentline, emptyline } from '../../source';
5
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';
9
- import { indentblock } from '../indentblock';
10
9
  import { codeblock, segment_ as seg_code } from '../codeblock';
11
10
  import { mathblock, segment_ as seg_math } from '../mathblock';
12
11
  import { example } from './example';
@@ -15,7 +14,7 @@ import { blockquote, segment as seg_blockquote } from '../blockquote';
15
14
  import { placeholder, segment_ as seg_placeholder } from './placeholder';
16
15
  import { inline, media, shortmedia } from '../../inline';
17
16
  import { localize } from '../../locale';
18
- import { visualize } from '../../util';
17
+ import { visualize, trimBlank } from '../../util';
19
18
  import { html, defrag } from 'typed-dom/dom';
20
19
  import { memoize } from 'spica/memoize';
21
20
  import { unshift } from 'spica/array';
@@ -23,7 +22,7 @@ import { unshift } from 'spica/array';
23
22
  import FigureParser = ExtensionParser.FigureParser;
24
23
 
25
24
  export const segment: FigureParser.SegmentParser = block(match(
26
- /^(~{3,})(?:figure[^\S\n]|(?=\[?\$))/,
25
+ /^(~{3,})(?:figure[^\S\n])?(?=\[?\$)/,
27
26
  memoize(
28
27
  ([, fence], closer = new RegExp(String.raw`^${fence}[^\S\n]*(?:$|\n)`)) => close(
29
28
  sequence([
@@ -49,7 +48,7 @@ export const segment: FigureParser.SegmentParser = block(match(
49
48
  ([, fence]) => fence.length, [])));
50
49
 
51
50
  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')),
51
+ convert(source => source.slice(source.match(/^~+(?:\w+\s+)?/)![0].length, source.trimEnd().lastIndexOf('\n')),
53
52
  sequence([
54
53
  line(sequence([label, str(/^(?=\s).*\n/)])),
55
54
  inits([
@@ -57,7 +56,6 @@ export const figure: FigureParser = block(fallback(rewrite(segment, fmap(
57
56
  ulist,
58
57
  olist,
59
58
  styled_table,
60
- indentblock,
61
59
  codeblock,
62
60
  mathblock,
63
61
  example,
@@ -70,7 +68,7 @@ export const figure: FigureParser = block(fallback(rewrite(segment, fmap(
70
68
  emptyline,
71
69
  block(localize(
72
70
  context({ syntax: { inline: { media: false } } },
73
- trim(visualize(some(inline)))))),
71
+ visualize(trimBlank(trimEnd(some(inline))))))),
74
72
  ]),
75
73
  ])),
76
74
  ([label, param, content, ...caption]: [HTMLAnchorElement, string, ...HTMLElement[]]) => [
@@ -7,7 +7,6 @@ import { ulist } from '../ulist';
7
7
  import { olist } from '../olist';
8
8
  import { ilist } from '../ilist';
9
9
  import { table } from '../table';
10
- import { indentblock } from '../indentblock';
11
10
  import { codeblock } from '../codeblock';
12
11
  import { mathblock } from '../mathblock';
13
12
  import { sidefence } from '../sidefence';
@@ -71,7 +70,6 @@ const content: MessageParser.ContentParser = union([
71
70
  olist,
72
71
  ilist,
73
72
  table,
74
- indentblock,
75
73
  codeblock,
76
74
  mathblock,
77
75
  sidefence,
@@ -40,6 +40,7 @@ describe('Unit: parser/block/heading', () => {
40
40
  assert.deepStrictEqual(inspect(parser('# a\\')), [['<h1 id="index:a">a</h1>'], '']);
41
41
  assert.deepStrictEqual(inspect(parser('# a\\\n')), [['<h1 id="index:a">a</h1>'], '']);
42
42
  assert.deepStrictEqual(inspect(parser('# \\')), [['<h1 id="index:\\">\\</h1>'], '']);
43
+ assert.deepStrictEqual(inspect(parser('# \\ a')), [['<h1 id="index:a">a</h1>'], '']);
43
44
  assert.deepStrictEqual(inspect(parser('## \\')), [['<h2 id="index:\\">\\</h2>'], '']);
44
45
  assert.deepStrictEqual(inspect(parser('# @a')), [['<h1 id="index:@a">@a</h1>'], '']);
45
46
  assert.deepStrictEqual(inspect(parser('## @a')), [['<h2 id="index:@a"><a href="/@a" class="account">@a</a></h2>'], '']);
@@ -1,8 +1,8 @@
1
1
  import { HeadingParser } from '../block';
2
- import { union, some, block, line, validate, focus, rewrite, context, open, trim, fmap } from '../../combinator';
2
+ import { union, some, block, line, validate, focus, rewrite, context, open, fmap } from '../../combinator';
3
3
  import { inline, indexee, indexer } from '../inline';
4
4
  import { str } from '../source';
5
- import { visualize } from '../util';
5
+ import { visualize, trimBlank } from '../util';
6
6
  import { html, defrag } from 'typed-dom/dom';
7
7
 
8
8
  export const segment: HeadingParser.SegmentParser = block(validate('#', focus(
@@ -21,13 +21,13 @@ export const heading: HeadingParser = block(rewrite(segment,
21
21
  line(indexee(fmap(union([
22
22
  open(
23
23
  str(/^##+/),
24
- trim(visualize(some(union([indexer, inline])))), true),
24
+ visualize(trimBlank(some(union([indexer, inline])))), true),
25
25
  open(
26
26
  str('#'),
27
27
  context({ syntax: { inline: {
28
28
  autolink: false,
29
29
  }}},
30
- trim(visualize(some(union([indexer, inline]))))), true),
30
+ visualize(trimBlank(some(union([indexer, inline]))))), true),
31
31
  ]),
32
32
  ([h, ...ns]: [string, ...(HTMLElement | string)[]]) => [
33
33
  h.length <= 6
@@ -1,17 +1,18 @@
1
1
  import { undefined } from 'spica/global';
2
2
  import { OListParser } from '../block';
3
- import { union, inits, subsequence, some, block, line, validate, indent, focus, rewrite, context, creator, open, match, trim, trimStart, fallback, lazy, fmap } from '../../combinator';
3
+ import { union, inits, subsequence, some, block, line, validate, indent, focus, rewrite, context, creator, open, match, trim, fallback, lazy, fmap } from '../../combinator';
4
4
  import { checkbox, ulist_, fillFirstLine } from './ulist';
5
5
  import { ilist_ } from './ilist';
6
6
  import { inline, indexee, indexer } from '../inline';
7
7
  import { contentline } from '../source';
8
+ import { trimBlank } from '../util';
8
9
  import { html, define, defrag } from 'typed-dom/dom';
9
10
  import { memoize } from 'spica/memoize';
10
11
  import { shift } from 'spica/array';
11
12
 
12
13
  const openers = {
13
- '.': /^(?:[0-9]+|[a-z]+|[A-Z]+)(?:-(?!-)[0-9]*)*(?![^\S\n])\.?(?=$|\s)/,
14
- '(': /^\((?:[0-9]*|[a-z]*)(?![^)\n])\)?(?:-(?!-)[0-9]*)*(?=$|\s)/,
14
+ '.': /^([0-9]+|[a-z]+|[A-Z]+)(?:-(?!-)[0-9]*)*(?![^\S\n])\.?(?=$|\s)/,
15
+ '(': /^\(([0-9]*|[a-z]*)(?![^)\n])\)?(?:-(?!-)[0-9]*)*(?=$|\s)/,
15
16
  } as const;
16
17
 
17
18
  export const olist: OListParser = lazy(() => block(validate(
@@ -24,10 +25,10 @@ export const olist: OListParser = lazy(() => block(validate(
24
25
 
25
26
  export const olist_: OListParser = lazy(() => block(union([
26
27
  match(
27
- new RegExp(`^(?=${openers['.'].source.replace('?:', '')})`),
28
+ openers['.'],
28
29
  memoize(ms => list(type(ms[1]), '.'), ms => type(ms[1]).charCodeAt(0) || 0, [])),
29
30
  match(
30
- new RegExp(`^(?=${openers['('].source.replace('?:', '')})`),
31
+ openers['('],
31
32
  memoize(ms => list(type(ms[1]), '('), ms => type(ms[1]).charCodeAt(0) || 0, [])),
32
33
  ])));
33
34
 
@@ -35,7 +36,7 @@ const list = (type: string, form: string): OListParser.ListParser => fmap(
35
36
  some(creator(union([
36
37
  indexee(fmap(fallback(
37
38
  inits([
38
- line(open(heads[form], trim(subsequence([checkbox, trimStart(some(union([indexer, inline])))])), true)),
39
+ line(open(heads[form], trim(subsequence([checkbox, trimBlank(some(union([indexer, inline])))])), true)),
39
40
  indent(union([ulist_, olist_, ilist_])),
40
41
  ]),
41
42
  invalid),
@@ -33,7 +33,7 @@ describe('Unit: parser/block/paragraph', () => {
33
33
  assert.deepStrictEqual(inspect(parser('***a*b\n<wbr>**\nc')), [['<p>**<em>a</em>b<br><wbr>**<br>c</p>'], '']);
34
34
  assert.deepStrictEqual(inspect(parser('***a**b\n<wbr>*\nc')), [['<p>*<strong>a</strong>b<br><wbr>*<br>c</p>'], '']);
35
35
  assert.deepStrictEqual(inspect(parser('==a\n<wbr>==\nb')), [['<p>==a<br><wbr>==<br>b</p>'], '']);
36
- assert.deepStrictEqual(inspect(parser(' a')), [['<p>a</p>'], '']);
36
+ assert.deepStrictEqual(inspect(parser('\ta')), [['<p>\ta</p>'], '']);
37
37
  });
38
38
 
39
39
  it('anchor', () => {
@@ -50,18 +50,18 @@ describe('Unit: parser/block/paragraph', () => {
50
50
  assert.deepStrictEqual(inspect(parser('a\n>>1')), [['<p>a<br><a href="?at=1" class="anchor">&gt;&gt;1</a></p>'], '']);
51
51
  assert.deepStrictEqual(inspect(parser('a\n>>1\nb')), [['<p>a<br><a href="?at=1" class="anchor">&gt;&gt;1</a><br>b</p>'], '']);
52
52
  assert.deepStrictEqual(inspect(parser('a\n>> b\nc')), [['<p>a<br>&gt;&gt; b<br>c</p>'], '']);
53
- assert.deepStrictEqual(inspect(parser(' >>1')), [['<p><a href="?at=1" class="anchor">&gt;&gt;1</a></p>'], '']);
54
- assert.deepStrictEqual(inspect(parser(' >>>1')), [['<p>&gt;<a href="?at=1" class="anchor">&gt;&gt;1</a></p>'], '']);
53
+ assert.deepStrictEqual(inspect(parser('\t>>1')), [['<p>\t<a href="?at=1" class="anchor">&gt;&gt;1</a></p>'], '']);
54
+ assert.deepStrictEqual(inspect(parser('\t>>>1')), [['<p>\t&gt;<a href="?at=1" class="anchor">&gt;&gt;1</a></p>'], '']);
55
55
  });
56
56
 
57
57
  it('comment', () => {
58
- assert.deepStrictEqual(inspect(parser('[# a #]')), [['<p><span class="comment"><input type="checkbox"><span>[# a #]</span></span></p>'], '']);
59
- assert.deepStrictEqual(inspect(parser('[# a #]b')), [['<p><span class="comment"><input type="checkbox"><span>[# a #]</span></span>b</p>'], '']);
60
- assert.deepStrictEqual(inspect(parser('[# a #]\nb')), [['<p><span class="comment"><input type="checkbox"><span>[# a #]</span></span><br>b</p>'], '']);
61
- assert.deepStrictEqual(inspect(parser('[## a ##]')), [['<p><span class="comment"><input type="checkbox"><span>[## a ##]</span></span></p>'], '']);
62
- assert.deepStrictEqual(inspect(parser('[#\n<wbr>\n#]')), [['<p><span class="comment"><input type="checkbox"><span>[#<br>&lt;wbr&gt;<br>#]</span></span></p>'], '']);
63
- assert.deepStrictEqual(inspect(parser('[#\n<wbr>\n#]a')), [['<p><span class="comment"><input type="checkbox"><span>[#<br>&lt;wbr&gt;<br>#]</span></span>a</p>'], '']);
64
- assert.deepStrictEqual(inspect(parser('[#\n<wbr>\n#]\na')), [['<p><span class="comment"><input type="checkbox"><span>[#<br>&lt;wbr&gt;<br>#]</span></span><br>a</p>'], '']);
58
+ assert.deepStrictEqual(inspect(parser('[% a %]')), [['<p><span class="comment"><input type="checkbox"><span>[% a %]</span></span></p>'], '']);
59
+ assert.deepStrictEqual(inspect(parser('[% a %]b')), [['<p><span class="comment"><input type="checkbox"><span>[% a %]</span></span>b</p>'], '']);
60
+ assert.deepStrictEqual(inspect(parser('[% a %]\nb')), [['<p><span class="comment"><input type="checkbox"><span>[% a %]</span></span><br>b</p>'], '']);
61
+ assert.deepStrictEqual(inspect(parser('[%% a %%]')), [['<p><span class="comment"><input type="checkbox"><span>[%% a %%]</span></span></p>'], '']);
62
+ assert.deepStrictEqual(inspect(parser('[%\n<wbr>\n%]')), [['<p><span class="comment"><input type="checkbox"><span>[%<br>&lt;wbr&gt;<br>%]</span></span></p>'], '']);
63
+ assert.deepStrictEqual(inspect(parser('[%\n<wbr>\n%]a')), [['<p><span class="comment"><input type="checkbox"><span>[%<br>&lt;wbr&gt;<br>%]</span></span>a</p>'], '']);
64
+ assert.deepStrictEqual(inspect(parser('[%\n<wbr>\n%]\na')), [['<p><span class="comment"><input type="checkbox"><span>[%<br>&lt;wbr&gt;<br>%]</span></span><br>a</p>'], '']);
65
65
  });
66
66
 
67
67
  it('template', () => {
@@ -1,10 +1,10 @@
1
1
  import { ParagraphParser } from '../block';
2
- import { union, some, block, trim, fmap } from '../../combinator';
2
+ import { union, some, block, trimEnd, fmap } from '../../combinator';
3
3
  import { inline } from '../inline';
4
4
  import { localize } from '../locale';
5
5
  import { visualize } from '../util';
6
6
  import { html, defrag } from 'typed-dom/dom';
7
7
 
8
8
  export const paragraph: ParagraphParser = block(localize(fmap(
9
- trim(visualize(some(union([inline])))),
9
+ visualize(trimEnd(some(union([inline])))),
10
10
  ns => [html('p', defrag(ns))])));
@@ -1,5 +1,5 @@
1
1
  import { ReplyParser } from '../block';
2
- import { inits, subsequence, some, block, validate, rewrite, trim, fmap } from '../../combinator';
2
+ import { inits, subsequence, some, block, validate, rewrite, trimEnd, fmap } from '../../combinator';
3
3
  import { cite } from './reply/cite';
4
4
  import { quote, syntax as delimiter } from './reply/quote';
5
5
  import { inline } from '../inline';
@@ -26,7 +26,7 @@ export const reply: ReplyParser = block(validate('>', localize(fmap(
26
26
  some(quote),
27
27
  fmap(rewrite(
28
28
  some(anyline, delimiter),
29
- trim(visualize(some(inline)))),
29
+ visualize(trimEnd(some(inline)))),
30
30
  ns => push(ns, [html('br')])),
31
31
  ])),
32
32
  ]),
@@ -1,11 +1,12 @@
1
1
  import { UListParser } from '../block';
2
- import { union, inits, subsequence, some, block, line, validate, indent, focus, rewrite, context, creator, open, trim, trimStart, fallback, lazy, fmap } from '../../combinator';
2
+ import { union, inits, subsequence, some, block, line, validate, indent, focus, rewrite, context, creator, open, trim, fallback, lazy, fmap } from '../../combinator';
3
3
  import { olist_ } from './olist';
4
4
  import { ilist_ } from './ilist';
5
5
  import { inline, indexer, indexee } from '../inline';
6
+ import { contentline } from '../source';
7
+ import { trimBlank } from '../util';
6
8
  import { html, defrag } from 'typed-dom/dom';
7
9
  import { unshift } from 'spica/array';
8
- import { contentline } from '../source';
9
10
 
10
11
  export const ulist: UListParser = lazy(() => block(validate(
11
12
  /^-(?=[^\S\n]|\n[^\S\n]*\S)/,
@@ -17,7 +18,7 @@ export const ulist_: UListParser = lazy(() => block(fmap(validate(
17
18
  some(creator(union([
18
19
  indexee(fmap(fallback(
19
20
  inits([
20
- line(open(/^-(?:$|\s)/, trim(subsequence([checkbox, trimStart(some(union([indexer, inline])))])), true)),
21
+ line(open(/^-(?:$|\s)/, trim(subsequence([checkbox, trimBlank(some(union([indexer, inline])))])), true)),
21
22
  indent(union([ulist_, olist_, ilist_])),
22
23
  ]),
23
24
  invalid),
@@ -9,7 +9,6 @@ import { olist } from './block/olist';
9
9
  import { ilist } from './block/ilist';
10
10
  import { dlist } from './block/dlist';
11
11
  import { table } from './block/table';
12
- import { indentblock } from './block/indentblock';
13
12
  import { codeblock } from './block/codeblock';
14
13
  import { mathblock } from './block/mathblock';
15
14
  import { extension } from './block/extension';
@@ -28,7 +27,6 @@ export import OListParser = BlockParser.OListParser;
28
27
  export import IListParser = BlockParser.IListParser;
29
28
  export import DListParser = BlockParser.DListParser;
30
29
  export import TableParser = BlockParser.TableParser;
31
- export import IndentBlockParser = BlockParser.IndentBlockParser;
32
30
  export import CodeBlockParser = BlockParser.CodeBlockParser;
33
31
  export import MathBlockParser = BlockParser.MathBlockParser;
34
32
  export import ExtensionParser = BlockParser.ExtensionParser;
@@ -48,7 +46,6 @@ export const block: BlockParser = creator(error(
48
46
  ilist,
49
47
  dlist,
50
48
  table,
51
- indentblock,
52
49
  codeblock,
53
50
  mathblock,
54
51
  extension,
@@ -2,7 +2,7 @@ import { undefined } from 'spica/global';
2
2
  import { AnnotationParser } from '../inline';
3
3
  import { union, some, validate, guard, context, creator, surround, lazy, fmap } from '../../combinator';
4
4
  import { inline } from '../inline';
5
- import { trimBlankInline } from '../util';
5
+ import { trimBlank } from '../util';
6
6
  import { html, defrag } from 'typed-dom/dom';
7
7
 
8
8
  export const annotation: AnnotationParser = lazy(() => creator(validate('((', '))', '\n', fmap(surround(
@@ -19,6 +19,6 @@ export const annotation: AnnotationParser = lazy(() => creator(validate('((', ')
19
19
  //link: true,
20
20
  //autolink: true,
21
21
  }}, delimiters: undefined },
22
- trimBlankInline(some(union([inline]), ')', /^\\?\n/)))),
22
+ trimBlank(some(union([inline]), ')', /^\\?\n/)))),
23
23
  '))'),
24
24
  ns => [html('sup', { class: 'annotation' }, defrag(ns))]))));
@@ -5,7 +5,7 @@ import { html } from 'typed-dom/dom';
5
5
  export const code: CodeParser = creator(validate('`', match(
6
6
  /^(`+)(?!`)([^\n]*?[^`\n])\1(?!`)/,
7
7
  ([whole, , body]) => rest =>
8
- [[html('code', { 'data-src': whole }, format(body))], rest])));
8
+ [[html('code', { 'data-src': whole }, format(body))], rest.slice(whole.length)])));
9
9
 
10
10
  function format(text: string): string {
11
11
  assert(text.length > 0);