securemark 0.298.2 → 0.298.4

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 (50) hide show
  1. package/CHANGELOG.md +8 -0
  2. package/design.md +1 -5
  3. package/dist/index.js +153 -153
  4. package/package.json +1 -1
  5. package/src/combinator/control/constraint/line.ts +1 -1
  6. package/src/combinator/control/manipulation/match.ts +1 -1
  7. package/src/combinator/data/delimiter.ts +42 -37
  8. package/src/combinator/data/parser/context.ts +4 -2
  9. package/src/combinator/data/parser/inits.ts +1 -1
  10. package/src/combinator/data/parser/sequence.ts +1 -1
  11. package/src/combinator/data/parser/some.ts +4 -3
  12. package/src/parser/api/bind.ts +17 -22
  13. package/src/parser/api/header.ts +1 -1
  14. package/src/parser/api/parse.test.ts +7 -10
  15. package/src/parser/api/parse.ts +27 -31
  16. package/src/parser/block/codeblock.ts +1 -1
  17. package/src/parser/block/extension/fig.ts +1 -1
  18. package/src/parser/block/extension/figure.ts +1 -1
  19. package/src/parser/block/extension/message.ts +1 -1
  20. package/src/parser/block/extension/placeholder.ts +1 -1
  21. package/src/parser/block/extension/table.ts +1 -1
  22. package/src/parser/block/heading.test.ts +2 -2
  23. package/src/parser/block/heading.ts +1 -1
  24. package/src/parser/block/mathblock.ts +1 -1
  25. package/src/parser/block/table.test.ts +1 -1
  26. package/src/parser/block.ts +64 -82
  27. package/src/parser/context.ts +20 -0
  28. package/src/parser/header.test.ts +1 -0
  29. package/src/parser/header.ts +3 -3
  30. package/src/parser/inline/annotation.test.ts +19 -19
  31. package/src/parser/inline/annotation.ts +10 -7
  32. package/src/parser/inline/autolink.ts +3 -3
  33. package/src/parser/inline/bracket.test.ts +11 -11
  34. package/src/parser/inline/bracket.ts +7 -17
  35. package/src/parser/inline/emphasis.test.ts +2 -2
  36. package/src/parser/inline/emstrong.test.ts +3 -3
  37. package/src/parser/inline/extension/index.test.ts +1 -1
  38. package/src/parser/inline/html.test.ts +5 -1
  39. package/src/parser/inline/html.ts +61 -53
  40. package/src/parser/inline/italic.test.ts +1 -1
  41. package/src/parser/inline/link.test.ts +1 -1
  42. package/src/parser/inline/reference.test.ts +1 -1
  43. package/src/parser/inline/strong.test.ts +2 -2
  44. package/src/parser/inline.test.ts +14 -14
  45. package/src/parser/inline.ts +7 -1
  46. package/src/parser/processor/note.ts +1 -1
  47. package/src/parser/segment.ts +13 -15
  48. package/src/parser/source/escapable.ts +0 -1
  49. package/src/parser/source/line.ts +6 -4
  50. package/src/parser/source/text.ts +4 -5
@@ -1,8 +1,7 @@
1
1
  import { MarkdownParser } from '../../markdown';
2
- import { Segment, Recursion, Command } from './context';
2
+ import { Segment, Command } from './context';
3
3
  import { List, Node } from '../combinator/data/parser';
4
- import { union, reset, firstline, recover } from '../combinator';
5
- import { MAX_SEGMENT_SIZE } from './segment';
4
+ import { union, firstline, recover } from '../combinator';
6
5
  import { header } from './header';
7
6
  import { emptysegment } from './source';
8
7
  import { pagebreak } from './block/pagebreak';
@@ -43,88 +42,71 @@ export import MediaBlockParser = BlockParser.MediaBlockParser;
43
42
  export import ReplyParser = BlockParser.ReplyParser;
44
43
  export import ParagraphParser = BlockParser.ParagraphParser;
45
44
 
46
- export const block: BlockParser = reset(
47
- {
48
- resources: {
49
- // バックトラックのせいで文字数制限を受けないようにする。
50
- clock: MAX_SEGMENT_SIZE * 6 + 1,
51
- recursions: [
52
- 5 || Recursion.block,
53
- 20 || Recursion.blockquote,
54
- 40 || Recursion.listitem,
55
- 20 || Recursion.inline,
56
- 20 || Recursion.annotation,
57
- 20 || Recursion.bracket,
58
- 20 || Recursion.terminal,
59
- ],
60
- },
61
- backtracks: {},
45
+ export const block: BlockParser = error(union([
46
+ emptysegment,
47
+ input => {
48
+ const { source, position, segment } = input;
49
+ if (position === source.length) return;
50
+ switch (segment ^ Segment.write) {
51
+ case Segment.heading:
52
+ return heading(input);
53
+ case Segment.fig:
54
+ return fig(input);
55
+ case Segment.figure:
56
+ return figure(input);
57
+ }
58
+ const char = source[position];
59
+ switch (char) {
60
+ case Command.Error:
61
+ throw new Error(firstline(source, position + 1).trimEnd());
62
+ case '=':
63
+ if (source.startsWith('===', position)) return pagebreak(input);
64
+ break;
65
+ case '`':
66
+ if (source.startsWith('```', position)) return codeblock(input);
67
+ break;
68
+ case '~':
69
+ if (source.startsWith('~~~', position)) return extension(input);
70
+ if (source[position + 1] === ' ') return dlist(input);
71
+ break;
72
+ case '-':
73
+ if (source.startsWith('---', position)) return header(input);
74
+ if (source[position + 1] === ' ') return ulist(input) || ilist(input);
75
+ break;
76
+ case '+':
77
+ case '*':
78
+ if (source[position + 1] === ' ') return ilist(input);
79
+ break;
80
+ case '[':
81
+ switch (source[position + 1]) {
82
+ case '$':
83
+ return figbase(input);
84
+ case '!':
85
+ return mediablock(input);
86
+ }
87
+ break;
88
+ case '!':
89
+ if (source[position + 1] === '>') return blockquote(input);
90
+ return mediablock(input);
91
+ case '>':
92
+ if (source[position + 1] === '>') return blockquote(input) || reply(input);
93
+ return blockquote(input);
94
+ case '$':
95
+ if (source[position + 1] === '$') return mathblock(input);
96
+ return figbase(input);
97
+ case '|':
98
+ return table(input) || sidefence(input);
99
+ case '(':
100
+ return olist(input);
101
+ default:
102
+ if ('0' <= char && char <= '9') return olist(input);
103
+ }
62
104
  },
63
- error(union([
64
- emptysegment,
65
- input => {
66
- const { source, position, segment } = input;
67
- if (position === source.length) return;
68
- switch (segment ^ Segment.write) {
69
- case Segment.heading:
70
- return heading(input);
71
- case Segment.fig:
72
- return fig(input);
73
- case Segment.figure:
74
- return figure(input);
75
- }
76
- const fst = source[position];
77
- switch (fst) {
78
- case Command.Error:
79
- throw new Error(firstline(source, position + 1).trimEnd());
80
- case '=':
81
- if (source.startsWith('===', position)) return pagebreak(input);
82
- break;
83
- case '`':
84
- if (source.startsWith('```', position)) return codeblock(input);
85
- break;
86
- case '~':
87
- if (source.startsWith('~~~', position)) return extension(input);
88
- if (source[position + 1] === ' ') return dlist(input);
89
- break;
90
- case '-':
91
- if (source.startsWith('---', position)) return header(input);
92
- if (source[position + 1] === ' ') return ulist(input) || ilist(input);
93
- break;
94
- case '+':
95
- case '*':
96
- if (source[position + 1] === ' ') return ilist(input);
97
- break;
98
- case '[':
99
- switch (source[position + 1]) {
100
- case '$':
101
- return figbase(input);
102
- case '!':
103
- return mediablock(input);
104
- }
105
- break;
106
- case '!':
107
- if (source[position + 1] === '>') return blockquote(input);
108
- return mediablock(input);
109
- case '>':
110
- if (source[position + 1] === '>') return blockquote(input) || reply(input);
111
- return blockquote(input);
112
- case '$':
113
- if (source[position + 1] === '$') return mathblock(input);
114
- return figbase(input);
115
- case '|':
116
- return table(input) || sidefence(input);
117
- case '(':
118
- return olist(input);
119
- default:
120
- if ('0' <= fst && fst <= '9') return olist(input);
121
- }
122
- },
123
- paragraph
124
- ])));
105
+ paragraph
106
+ ]));
125
107
 
126
108
  function error(parser: BlockParser): BlockParser {
127
- const reg = new RegExp(String.raw`^${Command.Error}[^\n]*\n`)
109
+ const reg = new RegExp(String.raw`^${Command.Error}[^\r\n]*\r?\n`)
128
110
  return recover<BlockParser>(
129
111
  parser,
130
112
  ({ source, position, id }, reason) => new List([
@@ -1,6 +1,9 @@
1
1
  import { List, Node, Context as Ctx } from '../../src/combinator/data/parser';
2
2
  import { Dict } from 'spica/dict';
3
3
 
4
+ export const MAX_SEGMENT_SIZE = 100_000; // 100,000 bytes (Max value size of FDB)
5
+ export const MAX_INPUT_SIZE = MAX_SEGMENT_SIZE * 10;
6
+
4
7
  export class Context extends Ctx {
5
8
  constructor(
6
9
  options: Partial<Context> = {},
@@ -17,6 +20,19 @@ export class Context extends Ctx {
17
20
  id,
18
21
  caches,
19
22
  } = options;
23
+ this.resources ??= {
24
+ // バックトラックのせいで文字数制限を受けないようにする。
25
+ clock: MAX_SEGMENT_SIZE * (6 + 1),
26
+ recursions: [
27
+ 5 || Recursion.block,
28
+ 20 || Recursion.blockquote,
29
+ 40 || Recursion.listitem,
30
+ 20 || Recursion.inline,
31
+ 20 || Recursion.annotation,
32
+ 20 || Recursion.bracket,
33
+ 20 || Recursion.terminal,
34
+ ],
35
+ };
20
36
  this.segment = segment ?? Segment.unknown;
21
37
  this.local = local ?? false;
22
38
  this.sequential = sequential ?? false;
@@ -27,6 +43,10 @@ export class Context extends Ctx {
27
43
  this.id = id;
28
44
  this.caches = caches;
29
45
  }
46
+ public override readonly resources?: {
47
+ clock: number;
48
+ recursions: number[];
49
+ };
30
50
  public override segment: Segment;
31
51
  public local: boolean;
32
52
  public sequential: boolean;
@@ -27,6 +27,7 @@ describe('Unit: parser/header', () => {
27
27
  assert.deepStrictEqual(inspect(parser, input('---\na: b\n---', new Context())), [['<aside class="header"><details open=""><summary>Header</summary><span class="field" data-name="a" data-value="b"><span class="field-name">a</span>: <span class="field-value">b</span>\n</span></details></aside>'], '']);
28
28
  assert.deepStrictEqual(inspect(parser, input('---\na: b\n---\n', new Context())), [['<aside class="header"><details open=""><summary>Header</summary><span class="field" data-name="a" data-value="b"><span class="field-name">a</span>: <span class="field-value">b</span>\n</span></details></aside>'], '']);
29
29
  assert.deepStrictEqual(inspect(parser, input('---\na: b\nC: D e\n---\n', new Context())), [['<aside class="header"><details open=""><summary>Header</summary><span class="field" data-name="a" data-value="b"><span class="field-name">a</span>: <span class="field-value">b</span>\n</span><span class="field" data-name="c" data-value="D e"><span class="field-name">C</span>: <span class="field-value">D e</span>\n</span></details></aside>'], '']);
30
+ assert.deepStrictEqual(inspect(parser, input('---\r\na: b\r\nC: D e\r\n---\r\n', new Context())), [['<aside class="header"><details open=""><summary>Header</summary><span class="field" data-name="a" data-value="b"><span class="field-name">a</span>: <span class="field-value">b</span>\n</span><span class="field" data-name="c" data-value="D e"><span class="field-name">C</span>: <span class="field-value">D e</span>\n</span></details></aside>'], '']);
30
31
  assert.deepStrictEqual(inspect(parser, input('----\na: b\n----', new Context())), [['<aside class="header"><details open=""><summary>Header</summary><span class="field" data-name="a" data-value="b"><span class="field-name">a</span>: <span class="field-value">b</span>\n</span></details></aside>'], '']);
31
32
  });
32
33
 
@@ -7,12 +7,12 @@ import { normalize } from './api/normalize';
7
7
  import { html, defrag } from 'typed-dom/dom';
8
8
 
9
9
  export const header: MarkdownParser.HeaderParser = lazy(() => validate(
10
- /---+[^\S\n]*\n(?=\S)/y,
10
+ /---+[^\S\r\n]*\r?\n(?=\S)/y,
11
11
  inits([
12
12
  block(
13
13
  union([
14
14
  validate(context => context.header,
15
- focus(/(---+)[^\S\n]*\n(?:[a-z][0-9a-z]*(?:-[0-9a-z]+)*:[ \t]+\S[^\n]*\n){1,100}\1[^\S\n]*(?:$|\n)/yi,
15
+ focus(/(---+)[^\S\r\n]*\r?\n(?:[a-z][0-9a-z]*(?:-[0-9a-z]+)*:[ \t]+\S[^\r\n]*\r?\n){1,100}\1[^\S\r\n]*(?:$|\r?\n)/yi,
16
16
  convert(source =>
17
17
  normalize(source.slice(source.indexOf('\n') + 1, source.trimEnd().lastIndexOf('\n'))),
18
18
  fmap(
@@ -36,7 +36,7 @@ export const header: MarkdownParser.HeaderParser = lazy(() => validate(
36
36
  ]);
37
37
  },
38
38
  ])),
39
- clear(str(/[^\S\n]*\n/y)),
39
+ clear(str(/[^\S\r\n]*\r?\n/y)),
40
40
  ])));
41
41
 
42
42
  const field: MarkdownParser.HeaderParser.FieldParser = line(({ source, position }) => {
@@ -13,17 +13,17 @@ describe('Unit: parser/inline/annotation', () => {
13
13
  assert.deepStrictEqual(inspect(parser, input('(', new Context())), undefined);
14
14
  assert.deepStrictEqual(inspect(parser, input('()', new Context())), undefined);
15
15
  assert.deepStrictEqual(inspect(parser, input('((', new Context())), undefined);
16
- assert.deepStrictEqual(inspect(parser, input('(())', new Context())), [['<span class="bracket">(<span class="paren">()</span>)</span>'], '']);
17
- assert.deepStrictEqual(inspect(parser, input('(()))', new Context())), [['<span class="bracket">(<span class="paren">()</span>)</span>'], ')']);
18
- assert.deepStrictEqual(inspect(parser, input('(("))', new Context())), [['<span class="bracket">(<span class="bracket">("))</span></span>'], '']);
19
- assert.deepStrictEqual(inspect(parser, input('((a', new Context())), [['<span class="bracket">(<span class="paren">(a</span></span>'], '']);
20
- assert.deepStrictEqual(inspect(parser, input('((!', new Context())), [['<span class="bracket">(<span class="bracket">(!</span></span>'], '']);
21
- assert.deepStrictEqual(inspect(parser, input('((a)', new Context())), [['<span class="bracket">(<span class="paren">(a)</span></span>'], '']);
22
- assert.deepStrictEqual(inspect(parser, input('((!)', new Context())), [['<span class="bracket">(<span class="bracket">(!)</span></span>'], '']);
23
- assert.deepStrictEqual(inspect(parser, input('((a)b)', new Context())), [['<span class="bracket">(<span class="paren">(a)</span>b)</span>'], '']);
24
- assert.deepStrictEqual(inspect(parser, input('((!)b)', new Context())), [['<span class="bracket">(<span class="bracket">(!)</span>b)</span>'], '']);
25
- assert.deepStrictEqual(inspect(parser, input('(([))', new Context())), [['<span class="bracket">(<span class="bracket">([))</span></span>'], '']);
26
- assert.deepStrictEqual(inspect(parser, input('(([%))', new Context())), [['<span class="bracket">(<span class="bracket">([%))</span></span>'], '']);
16
+ assert.deepStrictEqual(inspect(parser, input('(())', new Context())), [['<span class="paren">(<span class="paren">()</span>)</span>'], '']);
17
+ assert.deepStrictEqual(inspect(parser, input('(()))', new Context())), [['<span class="paren">(<span class="paren">()</span>)</span>'], ')']);
18
+ assert.deepStrictEqual(inspect(parser, input('(("))', new Context())), [['<span class="paren">(<span class="paren">("))</span></span>'], '']);
19
+ assert.deepStrictEqual(inspect(parser, input('((a', new Context())), [['<span class="paren">(<span class="paren">(a</span></span>'], '']);
20
+ assert.deepStrictEqual(inspect(parser, input('((!', new Context())), [['<span class="paren">(<span class="paren">(!</span></span>'], '']);
21
+ assert.deepStrictEqual(inspect(parser, input('((a)', new Context())), [['<span class="paren">(<span class="paren">(a)</span></span>'], '']);
22
+ assert.deepStrictEqual(inspect(parser, input('((!)', new Context())), [['<span class="paren">(<span class="paren">(!)</span></span>'], '']);
23
+ assert.deepStrictEqual(inspect(parser, input('((a)b)', new Context())), [['<span class="paren">(<span class="paren">(a)</span>b)</span>'], '']);
24
+ assert.deepStrictEqual(inspect(parser, input('((!)b)', new Context())), [['<span class="paren">(<span class="paren">(!)</span>b)</span>'], '']);
25
+ assert.deepStrictEqual(inspect(parser, input('(([))', new Context())), [['<span class="paren">(<span class="paren">([))</span></span>'], '']);
26
+ assert.deepStrictEqual(inspect(parser, input('(([%))', new Context())), [['<span class="paren">(<span class="paren">([%))</span></span>'], '']);
27
27
  assert.deepStrictEqual(inspect(parser, input('(( ))', new Context())), undefined);
28
28
  assert.deepStrictEqual(inspect(parser, input('(( a))', new Context())), undefined);
29
29
  assert.deepStrictEqual(inspect(parser, input('(( a ))', new Context())), undefined);
@@ -37,13 +37,13 @@ describe('Unit: parser/inline/annotation', () => {
37
37
  assert.deepStrictEqual(inspect(parser, input('((a\nb))', new Context())), [['<span class="bracket">(<span class="bracket">(a<br>b)</span>)</span>'], '']);
38
38
  assert.deepStrictEqual(inspect(parser, input('((a\\\nb))', new Context())), [['<span class="bracket">(<span class="bracket">(a<br>b)</span>)</span>'], '']);
39
39
  assert.deepStrictEqual(inspect(parser, input('((*a\nb*))', new Context())), [['<span class="bracket">(<span class="bracket">(<em>a<br>b</em>)</span>)</span>'], '']);
40
- assert.deepStrictEqual(inspect(parser, input('((\\))', new Context())), [['<span class="bracket">(<span class="bracket">())</span></span>'], '']);
41
- assert.deepStrictEqual(inspect(parser, input('(((a))', new Context())), [['<span class="bracket">(<sup class="annotation"><span>a</span></sup></span>'], '']);
42
- assert.deepStrictEqual(inspect(parser, input('(((!))', new Context())), [['<span class="bracket">(<sup class="annotation"><span>!</span></sup></span>'], '']);
43
- assert.deepStrictEqual(inspect(parser, input('(((*a*))', new Context())), [['<span class="bracket">(<sup class="annotation"><span><em>a</em></span></sup></span>'], '']);
44
- assert.deepStrictEqual(inspect(parser, input('(((((a))))', new Context())), [['<span class="bracket">(<sup class="annotation"><span><sup class="annotation"><span>a</span></sup></span></sup></span>'], '']);
45
- assert.deepStrictEqual(inspect(parser, input('(((((!))))', new Context())), [['<span class="bracket">(<sup class="annotation"><span><sup class="annotation"><span>!</span></sup></span></sup></span>'], '']);
46
- assert.deepStrictEqual(inspect(parser, input('(((((*a*))))', new Context())), [['<span class="bracket">(<sup class="annotation"><span><sup class="annotation"><span><em>a</em></span></sup></span></sup></span>'], '']);
40
+ assert.deepStrictEqual(inspect(parser, input('((\\))', new Context())), [['<span class="paren">(<span class="paren">())</span></span>'], '']);
41
+ assert.deepStrictEqual(inspect(parser, input('(((a))', new Context())), [['<span class="paren">(<sup class="annotation"><span>a</span></sup></span>'], '']);
42
+ assert.deepStrictEqual(inspect(parser, input('(((!))', new Context())), [['<span class="paren">(<sup class="annotation"><span>!</span></sup></span>'], '']);
43
+ assert.deepStrictEqual(inspect(parser, input('(((*a*))', new Context())), [['<span class="paren">(<sup class="annotation"><span><em>a</em></span></sup></span>'], '']);
44
+ assert.deepStrictEqual(inspect(parser, input('(((((a))))', new Context())), [['<span class="paren">(<sup class="annotation"><span><sup class="annotation"><span>a</span></sup></span></sup></span>'], '']);
45
+ assert.deepStrictEqual(inspect(parser, input('(((((!))))', new Context())), [['<span class="paren">(<sup class="annotation"><span><sup class="annotation"><span>!</span></sup></span></sup></span>'], '']);
46
+ assert.deepStrictEqual(inspect(parser, input('(((((*a*))))', new Context())), [['<span class="paren">(<sup class="annotation"><span><sup class="annotation"><span><em>a</em></span></sup></span></sup></span>'], '']);
47
47
  assert.deepStrictEqual(inspect(parser, input(' ((a))', new Context())), undefined);
48
48
  });
49
49
 
@@ -61,7 +61,7 @@ describe('Unit: parser/inline/annotation', () => {
61
61
  assert.deepStrictEqual(inspect(parser, input('((@a))', new Context())), [['<sup class="annotation"><span><a class="account" href="/@a">@a</a></span></sup>'], '']);
62
62
  assert.deepStrictEqual(inspect(parser, input('((http://host))', new Context())), [['<sup class="annotation"><span><a class="url" href="http://host" target="_blank">http://host</a></span></sup>'], '']);
63
63
  assert.deepStrictEqual(inspect(parser, input('((![]{a}))', new Context())), [['<sup class="annotation"><span>!<a class="url" href="a">a</a></span></sup>'], '']);
64
- assert.deepStrictEqual(inspect(parser, input('((a(())))', new Context())), [['<sup class="annotation"><span>a<span class="bracket">(<span class="paren">()</span>)</span></span></sup>'], '']);
64
+ assert.deepStrictEqual(inspect(parser, input('((a(())))', new Context())), [['<sup class="annotation"><span>a<span class="paren">(<span class="paren">()</span>)</span></span></sup>'], '']);
65
65
  assert.deepStrictEqual(inspect(parser, input('((a[[]]))', new Context())), [['<sup class="annotation"><span>a[[]]</span></sup>'], '']);
66
66
  assert.deepStrictEqual(inspect(parser, input('(([[a] ]))', new Context())), [['<sup class="annotation"><span>[[a] ]</span></sup>'], '']);
67
67
  assert.deepStrictEqual(inspect(parser, input('(((a)))', new Context())), [['<sup class="annotation"><span><span class="paren">(a)</span></span></sup>'], '']);
@@ -3,7 +3,7 @@ import { State, Recursion } from '../context';
3
3
  import { List, Node } from '../../combinator/data/parser';
4
4
  import { union, some, recursions, precedence, constraint, surround, open, lazy } from '../../combinator';
5
5
  import { inline } from '../inline';
6
- import { bracketname, indexA } from './bracket';
6
+ import { bracketname } from './bracket';
7
7
  import { beforeNonblank, trimBlankNodeEnd } from '../visibility';
8
8
  import { unwrap } from '../util';
9
9
  import { html, defrag } from 'typed-dom/dom';
@@ -36,8 +36,8 @@ export const annotation: AnnotationParser = lazy(() => constraint(State.annotati
36
36
  ns.push(new Node(')'));
37
37
  return new List([
38
38
  new Node(html('span',
39
- { class: 'bracket' },
40
- ['(', html('span', { class: 'bracket' }, defrag(unwrap(ns))), ')']))
39
+ { class: bracketname(context, 1, 1) },
40
+ ['(', html('span', { class: bracketname(context, 2, 2) }, defrag(unwrap(ns))), ')']))
41
41
  ]);
42
42
  }
43
43
  const depth = MAX_DEPTH - (resources?.recursions[Recursion.annotation] ?? resources?.recursions.at(-1) ?? MAX_DEPTH);
@@ -71,7 +71,7 @@ export const annotation: AnnotationParser = lazy(() => constraint(State.annotati
71
71
  recursion.add(depth);
72
72
  return new List([
73
73
  new Node(html('span',
74
- { class: 'bracket' },
74
+ { class: 'paren' },
75
75
  ['(', html('sup', { class: 'annotation' }, [html('span', bs.head.value.childNodes)])]))
76
76
  ]);
77
77
  }
@@ -80,7 +80,7 @@ export const annotation: AnnotationParser = lazy(() => constraint(State.annotati
80
80
  recursion.add(depth);
81
81
  return new List([
82
82
  new Node(html('span',
83
- { class: 'bracket' },
83
+ { class: 'paren' },
84
84
  ['(', html('sup', { class: 'annotation' }, [html('span', [bs.head.value])])]))
85
85
  ]);
86
86
  }
@@ -94,7 +94,7 @@ export const annotation: AnnotationParser = lazy(() => constraint(State.annotati
94
94
  }
95
95
  bs = new List([
96
96
  new Node(html('span',
97
- { class: bracketname(context, indexA, 2, context.position - position) },
97
+ { class: bracketname(context, 2, context.position - position) },
98
98
  defrag(unwrap(bs))))
99
99
  ]);
100
100
  bs.unshift(new Node('('));
@@ -103,8 +103,11 @@ export const annotation: AnnotationParser = lazy(() => constraint(State.annotati
103
103
  cs && bs.import(cs);
104
104
  bs.push(new Node(')'));
105
105
  context.position += 1;
106
+ context.range += 1;
106
107
  }
107
- return new List([new Node(html('span', { class: 'bracket' }, defrag(unwrap(bs))))]);
108
+ return new List([new Node(html('span',
109
+ { class: bracketname(context, 1, context.position - position) },
110
+ defrag(unwrap(bs))))]);
108
111
  })));
109
112
 
110
113
  const parser = lazy(() => precedence(1, some(inline, ')', [[')', 1]])));
@@ -14,8 +14,8 @@ export const autolink: AutolinkParser = lazy(() =>
14
14
  input => {
15
15
  const { source, position } = input;
16
16
  if (position === source.length) return;
17
- const fst = source[position];
18
- switch (fst) {
17
+ const char = source[position];
18
+ switch (char) {
19
19
  case '@':
20
20
  return account(input);
21
21
  case '#':
@@ -41,6 +41,6 @@ export const autolink: AutolinkParser = lazy(() =>
41
41
  }
42
42
  return url(input) || email(input);
43
43
  default:
44
- if (isAlphanumeric(fst)) return email(input);
44
+ if (isAlphanumeric(char)) return email(input);
45
45
  }
46
46
  }));
@@ -23,30 +23,30 @@ describe('Unit: parser/inline/bracket', () => {
23
23
  assert.deepStrictEqual(inspect(parser, input('(1, 2)', new Context())), [['<span class="paren">(1, 2)</span>'], '']);
24
24
  assert.deepStrictEqual(inspect(parser, input('(1.1-1.2)', new Context())), [['<span class="paren">(1.1-1.2)</span>'], '']);
25
25
  assert.deepStrictEqual(inspect(parser, input('(1.1, 1.2)', new Context())), [['<span class="paren">(1.1, 1.2)</span>'], '']);
26
- assert.deepStrictEqual(inspect(parser, input('(1 2)', new Context())), [['<span class="bracket">(1 2)</span>'], '']);
26
+ assert.deepStrictEqual(inspect(parser, input('(1 2)', new Context())), [['<span class="paren">(1 2)</span>'], '']);
27
27
  assert.deepStrictEqual(inspect(parser, input('(1a)', new Context())), [['<span class="paren">(1a)</span>'], '']);
28
28
  assert.deepStrictEqual(inspect(parser, input('(a)', new Context())), [['<span class="paren">(a)</span>'], '']);
29
29
  assert.deepStrictEqual(inspect(parser, input('(a1)', new Context())), [['<span class="paren">(a1)</span>'], '']);
30
30
  assert.deepStrictEqual(inspect(parser, input('(a-1)', new Context())), [['<span class="paren">(a-1)</span>'], '']);
31
31
  assert.deepStrictEqual(inspect(parser, input('(a.1)', new Context())), [['<span class="paren">(a.1)</span>'], '']);
32
- assert.deepStrictEqual(inspect(parser, input('(a b)', new Context())), [['<span class="bracket">(a b)</span>'], '']);
32
+ assert.deepStrictEqual(inspect(parser, input('(a b)', new Context())), [['<span class="paren">(a b)</span>'], '']);
33
33
  assert.deepStrictEqual(inspect(parser, input('(word)', new Context())), [['<span class="paren">(word)</span>'], '']);
34
- assert.deepStrictEqual(inspect(parser, input('(word word)', new Context())), [['<span class="bracket">(word word)</span>'], '']);
34
+ assert.deepStrictEqual(inspect(parser, input('(word word)', new Context())), [['<span class="paren">(word word)</span>'], '']);
35
35
  assert.deepStrictEqual(inspect(parser, input('(word, word)', new Context())), [['<span class="paren">(word, word)</span>'], '']);
36
36
  assert.deepStrictEqual(inspect(parser, input('(A)', new Context())), [['<span class="paren">(A)</span>'], '']);
37
37
  assert.deepStrictEqual(inspect(parser, input('(Name)', new Context())), [['<span class="paren">(Name)</span>'], '']);
38
- assert.deepStrictEqual(inspect(parser, input('(Word word)', new Context())), [['<span class="bracket">(Word word)</span>'], '']);
39
- assert.deepStrictEqual(inspect(parser, input('(Word Word)', new Context())), [['<span class="bracket">(Word Word)</span>'], '']);
38
+ assert.deepStrictEqual(inspect(parser, input('(Word word)', new Context())), [['<span class="paren">(Word word)</span>'], '']);
39
+ assert.deepStrictEqual(inspect(parser, input('(Word Word)', new Context())), [['<span class="paren">(Word Word)</span>'], '']);
40
40
  assert.deepStrictEqual(inspect(parser, input('(Name, Name)', new Context())), [['<span class="paren">(Name, Name)</span>'], '']);
41
41
  assert.deepStrictEqual(inspect(parser, input('(ABBR)', new Context())), [['<span class="paren">(ABBR)</span>'], '']);
42
42
  assert.deepStrictEqual(inspect(parser, input('(ABBR, ABBR)', new Context())), [['<span class="paren">(ABBR, ABBR)</span>'], '']);
43
43
  assert.deepStrictEqual(inspect(parser, input(`(${'0'.repeat(16)})`, new Context())), [[`<span class="paren">(${'0'.repeat(16)})</span>`], '']);
44
44
  assert.deepStrictEqual(inspect(parser, input(`(${'0'.repeat(17)})`, new Context())), [[`<span class="bracket">(${'0'.repeat(17)})</span>`], '']);
45
- assert.deepStrictEqual(inspect(parser, input('(\\a)', new Context())), [['<span class="bracket">(a)</span>'], '']);
46
- assert.deepStrictEqual(inspect(parser, input('(==)', new Context())), [['<span class="bracket">(==)</span>'], '']);
47
- assert.deepStrictEqual(inspect(parser, input('(()', new Context())), [['<span class="bracket">(<span class="paren">()</span></span>'], '']);
45
+ assert.deepStrictEqual(inspect(parser, input('(\\a)', new Context())), [['<span class="paren">(a)</span>'], '']);
46
+ assert.deepStrictEqual(inspect(parser, input('(==)', new Context())), [['<span class="paren">(==)</span>'], '']);
47
+ assert.deepStrictEqual(inspect(parser, input('(()', new Context())), [['<span class="paren">(<span class="paren">()</span></span>'], '']);
48
48
  assert.deepStrictEqual(inspect(parser, input('("(\n))"(")', new Context())), [['<span class="bracket">("<span class="paren">(</span><br>)</span>'], ')"(")']);
49
- assert.deepStrictEqual(inspect(parser, input('($)$', new Context())), [['<span class="bracket">(<span class="math" translate="no" data-src="$)$">$)$</span></span>'], '']);
49
+ assert.deepStrictEqual(inspect(parser, input('($)$', new Context())), [['<span class="paren">(<span class="math" translate="no" data-src="$)$">$)$</span></span>'], '']);
50
50
  assert.deepStrictEqual(inspect(parser, input(')', new Context())), undefined);
51
51
  assert.deepStrictEqual(inspect(parser, input('(1,2)', new Context())), [['<span class="paren">(1,2)</span>'], '']);
52
52
  assert.deepStrictEqual(inspect(parser, input('(0-1)', new Context())), [['<span class="paren">(0-1)</span>'], '']);
@@ -85,8 +85,8 @@ describe('Unit: parser/inline/bracket', () => {
85
85
  assert.deepStrictEqual(inspect(parser, input('"a', new Context())), [['"', 'a'], '']);
86
86
  assert.deepStrictEqual(inspect(parser, input('"a"', new Context())), [['"', 'a', '"'], '']);
87
87
  assert.deepStrictEqual(inspect(parser, input('"(")"', new Context())), [['"', '<span class="paren">(</span>', '"'], ')"']);
88
- assert.deepStrictEqual(inspect(parser, input('"(("', new Context())), [['"', '<span class="bracket">(<span class="paren">(</span></span>', '"'], '']);
89
- assert.deepStrictEqual(inspect(parser, input('"(\\")"', new Context())), [['"', '<span class="bracket">(")</span>', '"'], '']);
88
+ assert.deepStrictEqual(inspect(parser, input('"(("', new Context())), [['"', '<span class="paren">(<span class="paren">(</span></span>', '"'], '']);
89
+ assert.deepStrictEqual(inspect(parser, input('"(\\")"', new Context())), [['"', '<span class="paren">(")</span>', '"'], '']);
90
90
  assert.deepStrictEqual(inspect(parser, input('"(\n)"(")', new Context())), [['"', '<span class="paren">(</span>'], '\n)"(")']);
91
91
  assert.deepStrictEqual(inspect(parser, input('"\n"', new Context())), [['"'], '\n"']);
92
92
  assert.deepStrictEqual(inspect(parser, input('"\n"(")', new Context())), [['"'], '\n"(")']);
@@ -8,19 +8,9 @@ import { str } from '../source';
8
8
  import { unwrap } from '../util';
9
9
  import { html, defrag } from 'typed-dom/dom';
10
10
 
11
- export const indexA = /[0-9A-Za-z]+(?:(?:[.-]|, )[0-9A-Za-z]+)*/y;
12
- const indexF = new RegExp(
13
- indexA.source.replace(', ', '[,、]')
14
- .replace(/[09AZaz.]|\-(?!\w)/g, c => String.fromCodePoint(c.codePointAt(0)! + 0xFEE0)),
15
- 'y');
16
- export function bracketname(context: Context, syntax: RegExp, opener: number, closer: number): string {
17
- const { source, position, range, linebreak } = context;
18
- syntax.lastIndex = position - range + opener;
19
- return range - opener - closer === 0
20
- || linebreak === 0
21
- && range - opener - closer <= 16
22
- && syntax.test(source)
23
- && syntax.lastIndex === position - closer
11
+ export function bracketname(context: Context, opener: number, closer: number): string {
12
+ const { range, linebreak } = context;
13
+ return range - opener - closer === 0 || linebreak === 0 && range - opener - closer <= 16
24
14
  ? 'paren'
25
15
  : 'bracket';
26
16
  }
@@ -54,12 +44,12 @@ const p1 = lazy(() => surround(
54
44
  true, [],
55
45
  ([as, bs = new List(), cs], context) => new List([
56
46
  new Node(html('span',
57
- { class: bracketname(context, indexA, 1, 1) },
47
+ { class: bracketname(context, 1, 1) },
58
48
  defrag(unwrap(as.import(bs as List<Node<string>>).import(cs)))))
59
49
  ]),
60
50
  ([as, bs = new List()], context) => new List([
61
51
  new Node(html('span',
62
- { class: bracketname(context, indexA, 1, 0) },
52
+ { class: bracketname(context, 1, 0) },
63
53
  defrag(unwrap(as.import(bs as List<Node<string>>)))))
64
54
  ])));
65
55
 
@@ -70,12 +60,12 @@ const p2 = lazy(() => surround(
70
60
  true, [],
71
61
  ([as, bs = new List(), cs], context) => new List([
72
62
  new Node(html('span',
73
- { class: bracketname(context, indexF, 1, 1) },
63
+ { class: bracketname(context, 1, 1) },
74
64
  defrag(unwrap(as.import(bs as List<Node<string>>).import(cs)))))
75
65
  ]),
76
66
  ([as, bs = new List()], context) => new List([
77
67
  new Node(html('span',
78
- { class: bracketname(context, indexF, 1, 0) },
68
+ { class: bracketname(context, 1, 0) },
79
69
  defrag(unwrap(as.import(bs as List<Node<string>>)))))
80
70
  ])));
81
71
 
@@ -51,8 +51,8 @@ describe('Unit: parser/inline/emphasis', () => {
51
51
  assert.deepStrictEqual(inspect(parser, input('*a**b**c*', new Context())), [['<em>a<strong>b</strong>c</em>'], '']);
52
52
  assert.deepStrictEqual(inspect(parser, input('*a**b**c*d', new Context())), [['<em>a<strong>b</strong>c</em>'], 'd']);
53
53
  assert.deepStrictEqual(inspect(parser, input('*`a`*', new Context())), [['<em><code data-src="`a`">a</code></em>'], '']);
54
- assert.deepStrictEqual(inspect(parser, input('*(*a*)*', new Context())), [['<em><span class="bracket">(<em>a</em>)</span></em>'], '']);
55
- assert.deepStrictEqual(inspect(parser, input('*(**a**)*', new Context())), [['<em><span class="bracket">(<strong>a</strong>)</span></em>'], '']);
54
+ assert.deepStrictEqual(inspect(parser, input('*(*a*)*', new Context())), [['<em><span class="paren">(<em>a</em>)</span></em>'], '']);
55
+ assert.deepStrictEqual(inspect(parser, input('*(**a**)*', new Context())), [['<em><span class="paren">(<strong>a</strong>)</span></em>'], '']);
56
56
  });
57
57
 
58
58
  });
@@ -37,9 +37,9 @@ describe('Unit: parser/inline/emstrong', () => {
37
37
 
38
38
  it('nest', () => {
39
39
  assert.deepStrictEqual(inspect(parser, input('***`a`***', new Context())), [['<em><strong><code data-src="`a`">a</code></strong></em>'], '']);
40
- assert.deepStrictEqual(inspect(parser, input('***(*a*)***', new Context())), [['<em><strong><span class="bracket">(<em>a</em>)</span></strong></em>'], '']);
41
- assert.deepStrictEqual(inspect(parser, input('***(**a**)***', new Context())), [['<em><strong><span class="bracket">(<strong>a</strong>)</span></strong></em>'], '']);
42
- assert.deepStrictEqual(inspect(parser, input('***(***a***)***', new Context())), [['<em><strong><span class="bracket">(<em><strong>a</strong></em>)</span></strong></em>'], '']);
40
+ assert.deepStrictEqual(inspect(parser, input('***(*a*)***', new Context())), [['<em><strong><span class="paren">(<em>a</em>)</span></strong></em>'], '']);
41
+ assert.deepStrictEqual(inspect(parser, input('***(**a**)***', new Context())), [['<em><strong><span class="paren">(<strong>a</strong>)</span></strong></em>'], '']);
42
+ assert.deepStrictEqual(inspect(parser, input('***(***a***)***', new Context())), [['<em><strong><span class="paren">(<em><strong>a</strong></em>)</span></strong></em>'], '']);
43
43
  assert.deepStrictEqual(inspect(parser, input('***a*', new Context())), [['**', '<em>a</em>'], '']);
44
44
  assert.deepStrictEqual(inspect(parser, input('***a*b', new Context())), [['**', '<em>a</em>', 'b'], '']);
45
45
  assert.deepStrictEqual(inspect(parser, input('***a*b*', new Context())), [['**', '<em>a</em>', 'b'], '*']);
@@ -72,7 +72,7 @@ describe('Unit: parser/inline/extension/index', () => {
72
72
  assert.deepStrictEqual(inspect(parser, input('[#!http://host]', new Context())), [['<a class="index" href="#index::!http://host">!http://host</a>'], '']);
73
73
  assert.deepStrictEqual(inspect(parser, input('[#[% %]]', new Context())), [['<a class="index"><span class="remark"><input type="checkbox"><span>[% %]</span></span></a>'], '']);
74
74
  assert.deepStrictEqual(inspect(parser, input('[#[% a %]]', new Context())), [['<a class="index"><span class="remark"><input type="checkbox"><span>[% a %]</span></span></a>'], '']);
75
- assert.deepStrictEqual(inspect(parser, input('[#a((b))]', new Context())), [['<a class="index" href="#index::a((b))">a<span class="bracket">(<span class="paren">(b)</span>)</span></a>'], '']);
75
+ assert.deepStrictEqual(inspect(parser, input('[#a((b))]', new Context())), [['<a class="index" href="#index::a((b))">a<span class="paren">(<span class="paren">(b)</span>)</span></a>'], '']);
76
76
  assert.deepStrictEqual(inspect(parser, input('[#a[[b]]]', new Context())), [['<a class="index" href="#index::a[[b]]">a[[b]]</a>'], '']);
77
77
  });
78
78
 
@@ -1,4 +1,4 @@
1
- import { html } from './html';
1
+ import { html, TAGS } from './html';
2
2
  import { some } from '../../combinator';
3
3
  import { input } from '../../combinator/data/parser';
4
4
  import { Context } from '../context';
@@ -8,6 +8,10 @@ describe('Unit: parser/inline/html', () => {
8
8
  describe('html', () => {
9
9
  const parser = some(html);
10
10
 
11
+ it('hash', () => {
12
+ assert(TAGS.every(tag => parser(input(`<${tag}>`, new Context()))));
13
+ });
14
+
11
15
  it('xss', () => {
12
16
  assert.deepStrictEqual(inspect(parser, input('<script>', new Context())), [['<span class="invalid">&lt;script&gt;</span>'], '']);
13
17
  assert.deepStrictEqual(inspect(parser, input('<script>alert()<script>', new Context())), [['<span class="invalid">&lt;script&gt;alert()&lt;script&gt;</span>'], '']);