securemark 0.293.0 → 0.293.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.
Files changed (66) hide show
  1. package/CHANGELOG.md +8 -0
  2. package/dist/index.js +254 -193
  3. package/markdown.d.ts +13 -21
  4. package/package.json +1 -1
  5. package/src/combinator/control/manipulation/scope.ts +3 -4
  6. package/src/combinator/data/parser/context.ts +5 -5
  7. package/src/combinator.ts +0 -1
  8. package/src/parser/api/parse.test.ts +2 -2
  9. package/src/parser/autolink.test.ts +7 -7
  10. package/src/parser/block/blockquote.ts +2 -2
  11. package/src/parser/block/codeblock.ts +7 -7
  12. package/src/parser/block/dlist.ts +1 -2
  13. package/src/parser/block/extension/aside.ts +3 -3
  14. package/src/parser/block/extension/example.ts +3 -3
  15. package/src/parser/block/extension/fig.ts +2 -2
  16. package/src/parser/block/extension/figure.test.ts +1 -1
  17. package/src/parser/block/extension/figure.ts +2 -2
  18. package/src/parser/block/extension/message.ts +3 -3
  19. package/src/parser/block/extension/placeholder.ts +7 -7
  20. package/src/parser/block/extension/table.ts +26 -16
  21. package/src/parser/block/extension.ts +3 -3
  22. package/src/parser/block/ilist.ts +3 -3
  23. package/src/parser/block/mathblock.ts +7 -7
  24. package/src/parser/block/mediablock.ts +6 -6
  25. package/src/parser/block/olist.ts +3 -3
  26. package/src/parser/block/paragraph.test.ts +1 -2
  27. package/src/parser/block/paragraph.ts +1 -2
  28. package/src/parser/block/reply/cite.ts +3 -5
  29. package/src/parser/block/reply/quote.ts +2 -3
  30. package/src/parser/block/sidefence.ts +2 -2
  31. package/src/parser/block/table.ts +5 -5
  32. package/src/parser/block/ulist.ts +2 -3
  33. package/src/parser/block.ts +2 -2
  34. package/src/parser/context.ts +4 -4
  35. package/src/parser/inline/annotation.ts +1 -1
  36. package/src/parser/inline/autolink/url.test.ts +7 -7
  37. package/src/parser/inline/autolink/url.ts +1 -2
  38. package/src/parser/inline/autolink.ts +1 -1
  39. package/src/parser/inline/bracket.test.ts +2 -2
  40. package/src/parser/inline/extension/index.ts +5 -4
  41. package/src/parser/inline/extension/indexer.test.ts +0 -1
  42. package/src/parser/inline/extension/indexer.ts +1 -1
  43. package/src/parser/inline/html.ts +7 -6
  44. package/src/parser/inline/htmlentity.ts +3 -3
  45. package/src/parser/inline/italic.test.ts +11 -11
  46. package/src/parser/inline/link.ts +1 -6
  47. package/src/parser/inline/mark.test.ts +5 -5
  48. package/src/parser/inline/math.ts +3 -3
  49. package/src/parser/inline/media.ts +3 -8
  50. package/src/parser/inline/reference.ts +1 -1
  51. package/src/parser/inline/remark.test.ts +14 -18
  52. package/src/parser/inline/remark.ts +17 -19
  53. package/src/parser/inline/ruby.ts +3 -3
  54. package/src/parser/inline/shortmedia.ts +1 -1
  55. package/src/parser/inline.test.ts +25 -24
  56. package/src/parser/inline.ts +21 -9
  57. package/src/parser/segment.ts +23 -5
  58. package/src/parser/source/escapable.test.ts +1 -1
  59. package/src/parser/source/escapable.ts +4 -12
  60. package/src/parser/source/text.test.ts +40 -40
  61. package/src/parser/source/text.ts +77 -24
  62. package/src/parser/source/unescapable.test.ts +3 -3
  63. package/src/parser/source/unescapable.ts +4 -12
  64. package/src/parser/visibility.ts +32 -32
  65. package/src/combinator/control/manipulation/trim.test.ts +0 -23
  66. package/src/combinator/control/manipulation/trim.ts +0 -17
@@ -23,7 +23,7 @@ describe('Unit: parser/block/paragraph', () => {
23
23
  assert.deepStrictEqual(inspect(parser('a\\\n'), ctx), [['<p>a</p>'], '']);
24
24
  assert.deepStrictEqual(inspect(parser('a\\\nb'), ctx), [['<p>a<br>b</p>'], '']);
25
25
  assert.deepStrictEqual(inspect(parser('a&NewLine;b'), ctx), [['<p>a b</p>'], '']);
26
- assert.deepStrictEqual(inspect(parser('&Tab;&NewLine;'), ctx), [['<p>&amp;Tab;&amp;NewLine;</p>'], '']);
26
+ assert.deepStrictEqual(inspect(parser('&Tab;&NewLine;'), ctx), [['<p>&amp;NewLine;</p>'], '']);
27
27
  assert.deepStrictEqual(inspect(parser('<wbr>'), ctx), [['<p>&lt;wbr&gt;</p>'], '']);
28
28
  assert.deepStrictEqual(inspect(parser('<wbr>\n'), ctx), [['<p>&lt;wbr&gt;</p>'], '']);
29
29
  assert.deepStrictEqual(inspect(parser('<wbr>\na'), ctx), [['<p>&lt;wbr&gt;<br>a</p>'], '']);
@@ -67,7 +67,6 @@ describe('Unit: parser/block/paragraph', () => {
67
67
  assert.deepStrictEqual(inspect(parser('[% a %]'), ctx), [['<p><span class="remark"><input type="checkbox"><span>[% a %]</span></span></p>'], '']);
68
68
  assert.deepStrictEqual(inspect(parser('[% a %]b'), ctx), [['<p><span class="remark"><input type="checkbox"><span>[% a %]</span></span>b</p>'], '']);
69
69
  assert.deepStrictEqual(inspect(parser('[% a %]\nb'), ctx), [['<p><span class="remark"><input type="checkbox"><span>[% a %]</span></span><br>b</p>'], '']);
70
- assert.deepStrictEqual(inspect(parser('[%% a %%]'), ctx), [['<p><span class="remark"><input type="checkbox"><span>[%% a %%]</span></span></p>'], '']);
71
70
  assert.deepStrictEqual(inspect(parser('[%\n<wbr>\n%]'), ctx), [['<p><span class="remark"><input type="checkbox"><span>[%<br>&lt;wbr&gt;<br>%]</span></span></p>'], '']);
72
71
  assert.deepStrictEqual(inspect(parser('[%\n<wbr>\n%]a'), ctx), [['<p><span class="remark"><input type="checkbox"><span>[%<br>&lt;wbr&gt;<br>%]</span></span>a</p>'], '']);
73
72
  assert.deepStrictEqual(inspect(parser('[%\n<wbr>\n%]\na'), ctx), [['<p><span class="remark"><input type="checkbox"><span>[%<br>&lt;wbr&gt;<br>%]</span></span><br>a</p>'], '']);
@@ -1,10 +1,9 @@
1
1
  import { ParagraphParser } from '../block';
2
2
  import { union, some, block, fmap } from '../../combinator';
3
3
  import { inline } from '../inline';
4
- import { linearize } from '../util';
5
4
  import { visualize, trimBlankEnd } from '../visibility';
6
5
  import { html, defrag } from 'typed-dom/dom';
7
6
 
8
7
  export const paragraph: ParagraphParser = block(fmap(
9
- visualize(trimBlankEnd(linearize(some(union([inline])), -1))),
8
+ visualize(trimBlankEnd(some(union([inline])))),
10
9
  ns => [html('p', defrag(ns))]));
@@ -1,5 +1,5 @@
1
1
  import { ReplyParser } from '../../block';
2
- import { union, line, validate, focus, open, fmap } from '../../../combinator';
2
+ import { union, line, focus, open, fmap } from '../../../combinator';
3
3
  import { anchor } from '../../inline/autolink/anchor';
4
4
  import { str } from '../../source';
5
5
  import { invalid } from '../../util';
@@ -7,8 +7,7 @@ import { html, define, defrag } from 'typed-dom/dom';
7
7
 
8
8
  export const syntax = />*(?=>>[^>\s]\S*[^\S\n]*(?:$|\n))/y;
9
9
 
10
- export const cite: ReplyParser.CiteParser = line(fmap(validate(
11
- '>>',
10
+ export const cite: ReplyParser.CiteParser = line(fmap(
12
11
  open(
13
12
  str(syntax),
14
13
  union([
@@ -18,8 +17,7 @@ export const cite: ReplyParser.CiteParser = line(fmap(validate(
18
17
  focus(/>>#\S*(?=\s*$)/y, ({ context: { source } }) => [[html('a', { class: 'anchor' }, source)]]),
19
18
  focus(/>>https?:\/\/\S+(?=\s*$)/y, ({ context: { source } }) => [[html('a', { class: 'anchor', href: source.slice(2).trimEnd(), target: '_blank' }, source)]]),
20
19
  focus(/>>.+(?=\s*$)/y, ({ context: { source } }) => [[source]]),
21
- ]),
22
- )),
20
+ ])),
23
21
  ([quotes, node]: [string, HTMLElement | string]) => [
24
22
  html('span',
25
23
  typeof node === 'object'
@@ -8,8 +8,7 @@ import { html, defrag } from 'typed-dom/dom';
8
8
 
9
9
  export const syntax = />+[^\S\n]/y;
10
10
 
11
- export const quote: ReplyParser.QuoteParser = lazy(() => block(fmap(validate(
12
- '>',
11
+ export const quote: ReplyParser.QuoteParser = lazy(() => block(fmap(
13
12
  rewrite(
14
13
  some(validate(syntax, anyline)),
15
14
  linearize(convert(
@@ -21,7 +20,7 @@ export const quote: ReplyParser.QuoteParser = lazy(() => block(fmap(validate(
21
20
  linebreak,
22
21
  unescsource,
23
22
  ])),
24
- false), -1))),
23
+ false), -1)),
25
24
  (ns: [string, ...(string | HTMLElement)[]]) => [
26
25
  html('span', { class: 'quote' }, defrag(ns)),
27
26
  html('br'),
@@ -8,7 +8,7 @@ import { html, define, defrag } from 'typed-dom/dom';
8
8
 
9
9
  export const sidefence: SidefenceParser = lazy(() => block(fmap(focus(
10
10
  /(?=\|+(?:[^\S\n]|\n\|))(?:\|+(?:[^\S\n][^\n]*)?(?:$|\n))+$/y,
11
- union([source]), false),
11
+ union([source])),
12
12
  ([el]) => [
13
13
  define(el, {
14
14
  class: 'invalid',
@@ -23,7 +23,7 @@ const source: SidefenceParser.SourceParser = lazy(() => fmap(
23
23
  some(recursion(Recursion.block, union([
24
24
  focus(
25
25
  /(?:\|\|+(?:[^\S\n][^\n]*)?(?:$|\n))+/y,
26
- convert(unindent, source, false, true), false),
26
+ convert(unindent, source, false, true)),
27
27
  rewrite(
28
28
  some(contentline, opener),
29
29
  convert(unindent, fmap(autolink, ns => [html('pre', defrag(ns))]), false, true)),
@@ -1,5 +1,5 @@
1
1
  import { TableParser } from '../block';
2
- import { union, sequence, some, block, line, validate, focus, rewrite, surround, open, close, trimStart, fallback, lazy, fmap } from '../../combinator';
2
+ import { union, sequence, some, block, line, validate, focus, rewrite, surround, open, close, fallback, lazy, fmap } from '../../combinator';
3
3
  import { inline, media, medialink, shortmedia } from '../inline';
4
4
  import { contentline } from '../source';
5
5
  import { trimBlank } from '../visibility';
@@ -40,20 +40,20 @@ const align: AlignParser = fmap(open(
40
40
  '|',
41
41
  union([
42
42
  focus(/:-+:?/y, ({ context: { source } }) =>
43
- [[source.at(-1) === ':' ? 'center' : 'start']], false),
43
+ [[source.at(-1) === ':' ? 'center' : 'start']]),
44
44
  focus(/-+:?/y, ({ context: { source } }) =>
45
- [[source.at(-1) === ':' ? 'end' : '']], false),
45
+ [[source.at(-1) === ':' ? 'end' : '']]),
46
46
  ])),
47
47
  ns => [html('td', defrag(ns))]);
48
48
 
49
49
  const cell: CellParser = surround(
50
50
  /\|\s*(?=\S)/y,
51
- trimStart(union([
51
+ union([
52
52
  close(medialink, /\s*(?=\||$)/y),
53
53
  close(media, /\s*(?=\||$)/y),
54
54
  close(shortmedia, /\s*(?=\||$)/y),
55
55
  trimBlank(some(inline, /\|/y, [[/[|\\]?\s*$/y, 9]])),
56
- ])),
56
+ ]),
57
57
  /[^|]*/y, true);
58
58
 
59
59
  const head: CellParser.HeadParser = fmap(
@@ -1,10 +1,9 @@
1
1
  import { UListParser } from '../block';
2
2
  import { Recursion } from '../context';
3
- import { union, inits, subsequence, some, recursion, block, line, validate, indent, focus, open, trim, fallback, lazy, fmap } from '../../combinator';
3
+ import { union, inits, subsequence, some, recursion, block, line, validate, indent, focus, open, fallback, lazy, fmap } from '../../combinator';
4
4
  import { olist_ } from './olist';
5
5
  import { ilist_, ilistitem } from './ilist';
6
6
  import { inline, indexer, indexee, dataindex } from '../inline';
7
- import { linearize } from '../util';
8
7
  import { visualize, trimBlank } from '../visibility';
9
8
  import { unshift } from 'spica/array';
10
9
  import { html, defrag } from 'typed-dom/dom';
@@ -20,7 +19,7 @@ export const ulist_: UListParser = lazy(() => block(fmap(validate(
20
19
  inits([
21
20
  line(open(/-(?:$|[ \n])/y, subsequence([
22
21
  checkbox,
23
- trim(visualize(linearize(trimBlank(some(union([indexer, inline]))), - 1))),
22
+ visualize(trimBlank(some(union([indexer, inline])))),
24
23
  ]), true)),
25
24
  indent(union([ulist_, olist_, ilist_])),
26
25
  ]),
@@ -63,6 +63,8 @@ export const block: BlockParser = reset(
63
63
  return pagebreak(input);
64
64
  case '~~~':
65
65
  return extension(input);
66
+ case '```':
67
+ return codeblock(input);
66
68
  }
67
69
  switch (source.slice(position, position + 2)) {
68
70
  case '$$':
@@ -91,8 +93,6 @@ export const block: BlockParser = reset(
91
93
  case '|':
92
94
  return table(input)
93
95
  || sidefence(input);
94
- case '`':
95
- return codeblock(input);
96
96
  case '$':
97
97
  return extension(input);
98
98
  case '>':
@@ -28,10 +28,10 @@ export const enum Recursion {
28
28
  }
29
29
 
30
30
  export const enum Backtrack {
31
- link = 1 << 6,
32
- ruby = 1 << 5,
33
- doublebracket = 1 << 4,
34
- bracket = 1 << 3,
31
+ bracket = 1 << 6,
32
+ doublebracket = 1 << 5,
33
+ link = 1 << 4,
34
+ ruby = 1 << 3,
35
35
  escbracket = 1 << 2,
36
36
  autolink = 0 << 2,
37
37
  }
@@ -16,4 +16,4 @@ export const annotation: AnnotationParser = lazy(() => constraint(State.annotati
16
16
  ? [[html('sup', { class: 'annotation' }, [html('span', defrag(trimBlankNodeEnd(ns)))])]]
17
17
  : undefined,
18
18
  undefined,
19
- [3 | Backtrack.doublebracket, 1 | Backtrack.bracket])));
19
+ [1 | Backtrack.bracket, 3 | Backtrack.doublebracket])));
@@ -10,12 +10,12 @@ describe('Unit: parser/inline/autolink/url', () => {
10
10
 
11
11
  it('invalid', () => {
12
12
  assert.deepStrictEqual(inspect(parser(''), ctx), undefined);
13
- assert.deepStrictEqual(inspect(parser(' http'), ctx), [[' ', 'http'], '']);
14
- assert.deepStrictEqual(inspect(parser(' ttp'), ctx), [[' ', 'ttp'], '']);
15
- assert.deepStrictEqual(inspect(parser(' http://'), ctx), [[' ', 'http', ':', '/', '/'], '']);
16
- assert.deepStrictEqual(inspect(parser(' http://['), ctx), [[' ', 'http', ':', '/', '/', '['], '']);
17
- assert.deepStrictEqual(inspect(parser(' http://]'), ctx), [[' ', 'http', ':', '/', '/', ']'], '']);
18
- assert.deepStrictEqual(inspect(parser(' Http://host'), ctx), [[' ', 'Http', ':', '/', '/', 'host'], '']);
13
+ assert.deepStrictEqual(inspect(parser(' http'), ctx), [[' http'], '']);
14
+ assert.deepStrictEqual(inspect(parser(' ttp'), ctx), [[' ttp'], '']);
15
+ assert.deepStrictEqual(inspect(parser(' http://'), ctx), [[' ', 'http:', '//'], '']);
16
+ assert.deepStrictEqual(inspect(parser(' http://['), ctx), [[' ', 'http:', '//', '['], '']);
17
+ assert.deepStrictEqual(inspect(parser(' http://]'), ctx), [[' ', 'http:', '//', ']'], '']);
18
+ assert.deepStrictEqual(inspect(parser(' Http://host'), ctx), [[' ', 'Http:', '//host'], '']);
19
19
  assert.deepStrictEqual(inspect(parser(' http://[::ffff:0:0%1]'), ctx), [[' ', '<a class="invalid">http://[::ffff:0:0%1]</a>'], '']);
20
20
  assert.deepStrictEqual(inspect(parser(' http://[::ffff:0:0/96]'), ctx), [[' ', '<a class="invalid">http://[::ffff:0:0/96]</a>'], '']);
21
21
  });
@@ -59,7 +59,7 @@ describe('Unit: parser/inline/autolink/url', () => {
59
59
  assert.deepStrictEqual(inspect(parser(' http://host^'), ctx), [[' ', '<a class="url" href="http://host" target="_blank">http://host</a>', '^'], '']);
60
60
  assert.deepStrictEqual(inspect(parser(' http://host_'), ctx), [[' ', '<a class="url" href="http://host" target="_blank">http://host</a>', '_'], '']);
61
61
  assert.deepStrictEqual(inspect(parser(' http://host/'), ctx), [[' ', '<a class="url" href="http://host/" target="_blank">http://host/</a>'], '']);
62
- assert.deepStrictEqual(inspect(parser(' http://host//'), ctx), [[' ', '<a class="url" href="http://host" target="_blank">http://host</a>', '/', '/'], '']);
62
+ assert.deepStrictEqual(inspect(parser(' http://host//'), ctx), [[' ', '<a class="url" href="http://host" target="_blank">http://host</a>', '//'], '']);
63
63
  assert.deepStrictEqual(inspect(parser(` http://host'`), ctx), [[' ', '<a class="url" href="http://host\'" target="_blank">http://host\'</a>'], '']);
64
64
  assert.deepStrictEqual(inspect(parser(' http://host"'), ctx), [[' ', '<a class="url" href="http://host" target="_blank">http://host</a>', '"'], '']);
65
65
  assert.deepStrictEqual(inspect(parser(' http://host`'), ctx), [[' ', '<a class="url" href="http://host" target="_blank">http://host</a>', '`'], '']);
@@ -9,8 +9,7 @@ export const url: AutolinkParser.UrlParser = lazy(() => rewrite(
9
9
  /(?<![0-9a-z][.+-]?)https?:\/\/(?=[\x21-\x7E])/y,
10
10
  precedence(1, some(union([
11
11
  verify(bracket, ns => ns.length > 0),
12
- // 再帰に注意
13
- some(unescsource, /[-+*=~^_/,.;:!?]{2}|[-+*=~^_,.;:!?]?(?=[\\"`|\[\](){}<>]|[^\x21-\x7E]|$)/y),
12
+ some(unescsource, /([-+*=~^_/])\1|[,.;:!?]{2}|[-+*=~^_,.;:!?]?(?=[\\"`\[\](){}<>()[]{}|]|[^\x21-\x7E]|$)/y),
14
13
  ]), undefined, [[/[^\x21-\x7E]|\$/y, 9]])),
15
14
  false,
16
15
  [3 | Backtrack.autolink]),
@@ -23,7 +23,7 @@ export const autolink: AutolinkParser = lazy(() =>
23
23
  url,
24
24
  email,
25
25
  // Escape unmatched email-like strings.
26
- str(/[0-9a-z]+(?:[_.+-][0-9a-z]+@?|@(?=@))*/yi),
26
+ str(/[0-9a-z]+(?:[_.+-][0-9a-z]+[:@]?|:|@(?=@))*/yi),
27
27
  channel,
28
28
  account,
29
29
  // Escape unmatched account-like strings.
@@ -60,7 +60,7 @@ describe('Unit: parser/inline/bracket', () => {
60
60
  assert.deepStrictEqual(inspect(parser('[]'), ctx), [['[', ']'], '']);
61
61
  assert.deepStrictEqual(inspect(parser('[a'), ctx), [['[', 'a'], '']);
62
62
  assert.deepStrictEqual(inspect(parser('[a]'), ctx), [['[', 'a', ']'], '']);
63
- assert.deepStrictEqual(inspect(parser('[==]'), ctx), [['[', '=', '=', ']'], '']);
63
+ assert.deepStrictEqual(inspect(parser('[==]'), ctx), [['[', '==', ']'], '']);
64
64
  assert.deepStrictEqual(inspect(parser('[$]$'), ctx), [['[', '<span class="math" translate="no" data-src="$]$">$]$</span>'], '']);
65
65
  assert.deepStrictEqual(inspect(parser(']'), ctx), undefined);
66
66
  });
@@ -70,7 +70,7 @@ describe('Unit: parser/inline/bracket', () => {
70
70
  assert.deepStrictEqual(inspect(parser('{}'), ctx), [['{', '}'], '']);
71
71
  assert.deepStrictEqual(inspect(parser('{a'), ctx), [['{', 'a'], '']);
72
72
  assert.deepStrictEqual(inspect(parser('{a}'), ctx), [['{', 'a', '}'], '']);
73
- assert.deepStrictEqual(inspect(parser('{==}'), ctx), [['{', '=', '=', '}'], '']);
73
+ assert.deepStrictEqual(inspect(parser('{==}'), ctx), [['{', '==', '}'], '']);
74
74
  assert.deepStrictEqual(inspect(parser('}'), ctx), undefined);
75
75
  });
76
76
 
@@ -49,17 +49,18 @@ export const signature: IndexParser.SignatureParser = lazy(() => validate('|', s
49
49
  str(/\|(?!\\?\s)/y),
50
50
  some(union([
51
51
  unsafehtmlentity,
52
- some(txt, /(?:[&$[\](){}<>"`]|\\?\n)/y),
52
+ some(txt, /(?:[$"`\[\](){}<>()[]{}])/y),
53
53
  ]), ']'),
54
54
  /(?=])/y,
55
55
  false,
56
- ([, ns]) => {
56
+ ([, ns], context) => {
57
57
  const index = identity('index', undefined, ns.join(''))?.slice(7);
58
- return index
58
+ return index && context.linebreak === 0
59
59
  ? [[html('span', { class: 'indexer', 'data-index': index })]]
60
60
  : undefined;
61
61
  },
62
- ([as, bs]) => bs && [unshift(as, bs)])));
62
+ ([as, bs]) => bs && [unshift(as, bs)],
63
+ [3 | Backtrack.bracket])));
63
64
 
64
65
  export function dataindex(ns: readonly (string | HTMLElement)[]): string | undefined {
65
66
  if (ns.length === 0) return;
@@ -34,7 +34,6 @@ describe('Unit: parser/inline/extension/indexer', () => {
34
34
  assert.deepStrictEqual(inspect(parser(' [|*A*]'), ctx), [['<span class="indexer" data-index="*A*"></span>'], '']);
35
35
  assert.deepStrictEqual(inspect(parser(' [|\\`A\\`]'), ctx), [['<span class="indexer" data-index="`A`"></span>'], '']);
36
36
  assert.deepStrictEqual(inspect(parser(' [|\\$\\{A\\}\\$]'), ctx), [['<span class="indexer" data-index="${A}$"></span>'], '']);
37
- assert.deepStrictEqual(inspect(parser(' [|a]'), ctx), [['<span class="indexer" data-index="a"></span>'], '']);
38
37
  });
39
38
 
40
39
  });
@@ -10,7 +10,7 @@ import { html } from 'typed-dom/dom';
10
10
  // 継続的編集において最も簡便となる。
11
11
 
12
12
  export const indexer: ExtensionParser.IndexerParser = surround(
13
- /\s+\[(?=\|\S)/y,
13
+ /\s\[(?=\|\S)/y,
14
14
  union([
15
15
  signature,
16
16
  focus(/\|(?=\])/y, () => [[html('span', { class: 'indexer', 'data-index': '' })]]),
@@ -10,7 +10,7 @@ import { memoize } from 'spica/memoize';
10
10
  import { unshift, push, splice } from 'spica/array';
11
11
  import { html as h, defrag } from 'typed-dom/dom';
12
12
 
13
- const tags = Object.freeze(['wbr', 'bdo', 'bdi']);
13
+ const tags: readonly string[] = ['wbr', 'bdo', 'bdi'];
14
14
  const attrspecs = {
15
15
  wbr: {},
16
16
  bdo: {
@@ -81,7 +81,7 @@ function elem(tag: string, content: boolean, as: string[], bs: (HTMLElement | st
81
81
  if (bs.length === 0) return ielem('content', `Missing the content`, context);
82
82
  if (!isLooseNodeStart(bs)) return ielem('content', `Missing the visible content in the same line`, context);
83
83
  }
84
- const attrs = attributes('html', attrspecs[tag], as.slice(1, as.at(-1) === '>' ? -2 : as.length));
84
+ const attrs = attributes('html', attrspecs[tag], as.slice(1, as.at(-1) === '>' ? -1 : as.length));
85
85
  if (/(?<!\S)invalid(?!\S)/.test(attrs['class'] ?? '')) return ielem('attribute', 'Invalid HTML attribute', context)
86
86
  if (as.at(-1) !== '>') return ielem('tag', `Missing the closing symbol ">"`, context);
87
87
  return h(tag as 'span', attrs, defrag(bs));
@@ -110,12 +110,13 @@ export function attributes(
110
110
  const attrs: Record<string, string | undefined> = {};
111
111
  for (let i = 0; i < params.length; ++i) {
112
112
  const param = params[i].trimStart();
113
+ if (param === '') continue;
113
114
  const name = param.split('=', 1)[0];
114
115
  const value = param !== name
115
116
  ? param.slice(name.length + 2, -1).replace(/\\(.?)/g, '$1')
116
117
  : undefined;
117
- invalidation ||= !spec || name in attrs;
118
- if (spec && name in spec && !spec[name]) continue;
118
+ invalidation ||= name === '' || !spec || name in attrs;
119
+ if (name === '' || spec && name in spec && !spec[name]) continue;
119
120
  spec?.[name]?.includes(value) || spec?.[name]?.length === 0 && value !== undefined
120
121
  ? attrs[name] = value ?? ''
121
122
  : invalidation ||= !!spec;
@@ -132,7 +133,7 @@ export function attributes(
132
133
 
133
134
  // https://developer.mozilla.org/en-US/docs/Web/HTML/Element
134
135
  // [...document.querySelectorAll('tbody > tr > td:first-child')].map(el => el.textContent.slice(1, -1))
135
- const TAGS = Object.freeze([
136
+ const TAGS: readonly string[] = [
136
137
  "html",
137
138
  "base",
138
139
  "head",
@@ -269,4 +270,4 @@ const TAGS = Object.freeze([
269
270
  "strike",
270
271
  "tt",
271
272
  "xmp",
272
- ]);
273
+ ];
@@ -1,9 +1,9 @@
1
1
  import { HTMLEntityParser, UnsafeHTMLEntityParser } from '../inline';
2
- import { union, validate, focus, fmap } from '../../combinator';
2
+ import { union, focus, fmap } from '../../combinator';
3
3
  import { invalid } from '../util';
4
4
  import { html } from 'typed-dom/dom';
5
5
 
6
- export const unsafehtmlentity: UnsafeHTMLEntityParser = validate('&', focus(
6
+ export const unsafehtmlentity: UnsafeHTMLEntityParser = focus(
7
7
  /&(?:[0-9A-Za-z]+;?)?/y,
8
8
  //({ source }) => [[parser(source) ?? `${Command.Error}${source}`], '']));
9
9
  ({ context }) => {
@@ -12,7 +12,7 @@ export const unsafehtmlentity: UnsafeHTMLEntityParser = validate('&', focus(
12
12
  return source.length > 1 && source.at(-1) === ';'
13
13
  ? [[parser(source) ?? source]]
14
14
  : [[source]];
15
- }));
15
+ });
16
16
 
17
17
  export const htmlentity: HTMLEntityParser = fmap(
18
18
  union([unsafehtmlentity]),
@@ -11,14 +11,14 @@ describe('Unit: parser/inline/italic', () => {
11
11
  it('invalid', () => {
12
12
  assert.deepStrictEqual(inspect(parser('///'), ctx), undefined);
13
13
  assert.deepStrictEqual(inspect(parser('///a'), ctx), [['///', 'a'], '']);
14
- assert.deepStrictEqual(inspect(parser('///a ///'), ctx), [['///', 'a', ' ', '/', '/', '/'], '']);
15
- assert.deepStrictEqual(inspect(parser('///a ///'), ctx), [['///', 'a', ' ', '/', '/', '/'], '']);
16
- assert.deepStrictEqual(inspect(parser('///a\n///'), ctx), [['///', 'a', '<br>', '/', '/', '/'], '']);
17
- assert.deepStrictEqual(inspect(parser('///a\\ ///'), ctx), [['///', 'a', ' ', '/', '/', '/'], '']);
18
- assert.deepStrictEqual(inspect(parser('///a\\\n///'), ctx), [['///', 'a', '<br>', '/', '/', '/'], '']);
19
- assert.deepStrictEqual(inspect(parser('///a/b'), ctx), [['///', 'a', '/', 'b'], '']);
20
- assert.deepStrictEqual(inspect(parser('///a//b'), ctx), [['///', 'a', '/', '/', 'b'], '']);
21
- assert.deepStrictEqual(inspect(parser('///a*b///'), ctx), [['///', 'a', '*', 'b', '/', '/', '/'], '']);
14
+ assert.deepStrictEqual(inspect(parser('///a ///'), ctx), [['///', 'a', ' ', '///'], '']);
15
+ assert.deepStrictEqual(inspect(parser('///a ///'), ctx), [['///', 'a', ' ', '///'], '']);
16
+ assert.deepStrictEqual(inspect(parser('///a\n///'), ctx), [['///', 'a', '<br>', '///'], '']);
17
+ assert.deepStrictEqual(inspect(parser('///a\\ ///'), ctx), [['///', 'a', ' ', '///'], '']);
18
+ assert.deepStrictEqual(inspect(parser('///a\\\n///'), ctx), [['///', 'a', '<br>', '///'], '']);
19
+ assert.deepStrictEqual(inspect(parser('///a/b'), ctx), [['///', 'a', '/b'], '']);
20
+ assert.deepStrictEqual(inspect(parser('///a//b'), ctx), [['///', 'a', '//b'], '']);
21
+ assert.deepStrictEqual(inspect(parser('///a*b///'), ctx), [['///', 'a', '*', 'b', '///'], '']);
22
22
  assert.deepStrictEqual(inspect(parser('/// ///'), ctx), undefined);
23
23
  assert.deepStrictEqual(inspect(parser('/// a///'), ctx), undefined);
24
24
  assert.deepStrictEqual(inspect(parser('/// a ///'), ctx), undefined);
@@ -52,9 +52,9 @@ describe('Unit: parser/inline/italic', () => {
52
52
  assert.deepStrictEqual(inspect(parser('//////a///'), ctx), [['///', '<i>a</i>'], '']);
53
53
  assert.deepStrictEqual(inspect(parser('//////a///b'), ctx), [['///', '<i>a</i>', 'b'], '']);
54
54
  assert.deepStrictEqual(inspect(parser('//////a////'), ctx), [['///', '<i>a</i>', '/'], '']);
55
- assert.deepStrictEqual(inspect(parser('//////a////b'), ctx), [['///', '<i>a</i>', '/', 'b'], '']);
56
- assert.deepStrictEqual(inspect(parser('//////a/////'), ctx), [['///', '<i>a</i>', '/', '/'], '']);
57
- assert.deepStrictEqual(inspect(parser('//////a/////b'), ctx), [['///', '<i>a</i>', '/', '/', 'b'], '']);
55
+ assert.deepStrictEqual(inspect(parser('//////a////b'), ctx), [['///', '<i>a</i>', '/b'], '']);
56
+ assert.deepStrictEqual(inspect(parser('//////a/////'), ctx), [['///', '<i>a</i>', '//'], '']);
57
+ assert.deepStrictEqual(inspect(parser('//////a/////b'), ctx), [['///', '<i>a</i>', '//b'], '']);
58
58
  assert.deepStrictEqual(inspect(parser('//////a//////'), ctx), [['<i><i>a</i></i>'], '']);
59
59
  assert.deepStrictEqual(inspect(parser('//////a///b///'), ctx), [['<i><i>a</i>b</i>'], '']);
60
60
  assert.deepStrictEqual(inspect(parser('///a ///b//////'), ctx), [['<i>a <i>b</i></i>'], '']);
@@ -29,7 +29,7 @@ export const textlink: LinkParser.TextLinkParser = lazy(() => constraint(State.l
29
29
  ? [push(ns, [Command.Separator])]
30
30
  : undefined,
31
31
  undefined,
32
- [3 | Backtrack.link, 2 | Backtrack.ruby, 3 | Backtrack.bracket])),
32
+ [3 | Backtrack.bracket, 3 | Backtrack.link, 2 | Backtrack.ruby])),
33
33
  // `{ `と`{`で個別にバックトラックが発生し+1nされる。
34
34
  // 自己再帰的にパースしてもオプションの不要なパースによる計算量の増加により相殺される。
35
35
  dup(surround(
@@ -87,11 +87,6 @@ export const medialink: LinkParser.MediaLinkParser = lazy(() => constraint(State
87
87
  ([params, content = []]: [string[], (HTMLElement | string)[]], context) =>
88
88
  [[parse(defrag(content), params, context)]]))))));
89
89
 
90
- export const linemedialink: LinkParser.LineMediaLinkParser = surround(
91
- /(?<=^|[\r\n])/y,
92
- union([medialink]),
93
- /(?=[^\S\n]*(?:$|\n))/y);
94
-
95
90
  export const unsafelink: LinkParser.UnsafeLinkParser = lazy(() =>
96
91
  creation(10,
97
92
  bind(reverse(tails([
@@ -14,11 +14,11 @@ describe('Unit: parser/inline/mark', () => {
14
14
  assert.deepStrictEqual(inspect(parser('=='), ctx), undefined);
15
15
  assert.deepStrictEqual(inspect(parser('==a'), ctx), [['==', 'a'], '']);
16
16
  assert.deepStrictEqual(inspect(parser('==a='), ctx), [['==', 'a', '='], '']);
17
- assert.deepStrictEqual(inspect(parser('==a =='), ctx), [['==', 'a', ' ', '=', '='], '']);
18
- assert.deepStrictEqual(inspect(parser('==a =='), ctx), [['==', 'a', ' ', '=', '='], '']);
19
- assert.deepStrictEqual(inspect(parser('==a\n=='), ctx), [['==', 'a', '<br>', '=', '='], '']);
20
- assert.deepStrictEqual(inspect(parser('==a\\ =='), ctx), [['==', 'a', ' ', '=', '='], '']);
21
- assert.deepStrictEqual(inspect(parser('==a\\\n=='), ctx), [['==', 'a', '<br>', '=', '='], '']);
17
+ assert.deepStrictEqual(inspect(parser('==a =='), ctx), [['==', 'a', ' ', '=='], '']);
18
+ assert.deepStrictEqual(inspect(parser('==a =='), ctx), [['==', 'a', ' ', '=='], '']);
19
+ assert.deepStrictEqual(inspect(parser('==a\n=='), ctx), [['==', 'a', '<br>', '=='], '']);
20
+ assert.deepStrictEqual(inspect(parser('==a\\ =='), ctx), [['==', 'a', ' ', '=='], '']);
21
+ assert.deepStrictEqual(inspect(parser('==a\\\n=='), ctx), [['==', 'a', '<br>', '=='], '']);
22
22
  assert.deepStrictEqual(inspect(parser('== =='), ctx), undefined);
23
23
  assert.deepStrictEqual(inspect(parser('== a=='), ctx), undefined);
24
24
  assert.deepStrictEqual(inspect(parser('== a =='), ctx), undefined);
@@ -1,13 +1,13 @@
1
1
  import { MathParser } from '../inline';
2
2
  import { Backtrack, Recursion } from '../context';
3
- import { union, some, recursion, precedence, validate, rewrite, surround, lazy } from '../../combinator';
3
+ import { union, some, recursion, precedence, rewrite, surround, lazy } from '../../combinator';
4
4
  import { escsource, str } from '../source';
5
5
  import { invalid } from '../util';
6
6
  import { html } from 'typed-dom/dom';
7
7
 
8
8
  const forbiddenCommand = /\\(?:begin|tiny|huge|large)(?![a-z])|:\/\//i;
9
9
 
10
- export const math: MathParser = lazy(() => validate('$', rewrite(
10
+ export const math: MathParser = lazy(() => rewrite(
11
11
  union([
12
12
  surround(
13
13
  /\$(?={)/y,
@@ -35,7 +35,7 @@ export const math: MathParser = lazy(() => validate('$', rewrite(
35
35
  `"${source.match(forbiddenCommand)![0]}" command is forbidden`),
36
36
  },
37
37
  source)
38
- ]])));
38
+ ]]));
39
39
 
40
40
  const bracket: MathParser.BracketParser = lazy(() => surround(
41
41
  str('{'),
@@ -1,7 +1,7 @@
1
1
  import { MediaParser } from '../inline';
2
2
  import { State, Recursion, Backtrack, Command } from '../context';
3
3
  import { subinput } from '../../combinator/data/parser';
4
- import { union, inits, tails, some, creation, recursion, precedence, constraint, validate, verify, surround, open, setBacktrack, dup, lazy, fmap, bind } from '../../combinator';
4
+ import { union, inits, tails, some, creation, recursion, precedence, constraint, verify, surround, open, setBacktrack, dup, lazy, fmap, bind } from '../../combinator';
5
5
  import { unsafelink, uri, option as linkoption, resolve, decode } from './link';
6
6
  import { attributes } from './html';
7
7
  import { unsafehtmlentity } from './htmlentity';
@@ -19,7 +19,7 @@ const optspec = {
19
19
  } as const;
20
20
  Object.setPrototypeOf(optspec, null);
21
21
 
22
- export const media: MediaParser = lazy(() => constraint(State.media, validate(/![[{]/y, creation(10, open(
22
+ export const media: MediaParser = lazy(() => constraint(State.media, creation(10, open(
23
23
  '!',
24
24
  bind(verify(fmap(tails([
25
25
  dup(surround(
@@ -104,12 +104,7 @@ export const media: MediaParser = lazy(() => constraint(State.media, validate(/!
104
104
  return [define(link, { class: null, target: '_blank' }, [el])];
105
105
  })
106
106
  (subinput(`{ ${INSECURE_URI}${params.join('')} }`, context));
107
- }))))));
108
-
109
- export const linemedia: MediaParser.LineMediaParser = surround(
110
- /(?<=^|[\r\n])/y,
111
- union([media]),
112
- /(?=[^\S\n]*(?:$|\n))/y);
107
+ })))));
113
108
 
114
109
  const bracket: MediaParser.TextParser.BracketParser = lazy(() => recursion(Recursion.terminal, union([
115
110
  surround(str('('), some(union([unsafehtmlentity, bracket, txt]), ')'), str(')'), true,
@@ -88,7 +88,7 @@ export const reference: ReferenceParser = lazy(() => constraint(State.reference,
88
88
  ? [unshift(as, bs)]
89
89
  : undefined;
90
90
  },
91
- [3 | Backtrack.doublebracket, 1 | Backtrack.bracket])));
91
+ [1 | Backtrack.bracket, 3 | Backtrack.doublebracket])));
92
92
 
93
93
  // Chicago-Style
94
94
  const abbr: ReferenceParser.AbbrParser = surround(
@@ -16,25 +16,25 @@ describe('Unit: parser/inline/remark', () => {
16
16
  assert.deepStrictEqual(inspect(parser('[%a%]'), ctx), undefined);
17
17
  assert.deepStrictEqual(inspect(parser('[%a b%]'), ctx), undefined);
18
18
  assert.deepStrictEqual(inspect(parser('[% '), ctx), [['[%'], '']);
19
- assert.deepStrictEqual(inspect(parser('[% \n a'), ctx), [['[%', '<br>', ' ', 'a'], '']);
19
+ assert.deepStrictEqual(inspect(parser('[% \n a'), ctx), [['[%', '<br>', ' a'], '']);
20
20
  assert.deepStrictEqual(inspect(parser('[%%]'), ctx), undefined);
21
21
  assert.deepStrictEqual(inspect(parser('[% [%'), ctx), [['[%', ' ', '[', '%'], '']);
22
22
  assert.deepStrictEqual(inspect(parser('[% [% '), ctx), [['[%', ' ', '[%'], '']);
23
- assert.deepStrictEqual(inspect(parser('[% [% a'), ctx), [['[%', ' ', '[%', ' ', 'a'], '']);
23
+ assert.deepStrictEqual(inspect(parser('[% [% a'), ctx), [['[%', ' ', '[%', ' a'], '']);
24
24
  assert.deepStrictEqual(inspect(parser('[% [% a %]'), ctx), [['[%', ' ', '<span class="remark"><input type="checkbox"><span>[% a %]</span></span>'], '']);
25
- assert.deepStrictEqual(inspect(parser('[% a[%'), ctx), [['[%', ' ', 'a', '[', '%'], '']);
26
- assert.deepStrictEqual(inspect(parser('[% a [%'), ctx), [['[%', ' ', 'a', ' ', '[', '%'], '']);
27
- assert.deepStrictEqual(inspect(parser('[% a [% '), ctx), [['[%', ' ', 'a', ' ', '[%'], '']);
28
- assert.deepStrictEqual(inspect(parser('[% a [% b'), ctx), [['[%', ' ', 'a', ' ', '[%', ' ', 'b'], '']);
29
- assert.deepStrictEqual(inspect(parser('[% a [%% b'), ctx), [['[%', ' ', 'a', ' ', '[%%', ' ', 'b'], '']);
30
- assert.deepStrictEqual(inspect(parser('[%% a [% b'), ctx), [['[%%', ' ', 'a', ' ', '[%', ' ', 'b'], '']);
25
+ assert.deepStrictEqual(inspect(parser('[% a[%'), ctx), [['[%', ' a', '[', '%'], '']);
26
+ assert.deepStrictEqual(inspect(parser('[% a [%'), ctx), [['[%', ' a ', '[', '%'], '']);
27
+ assert.deepStrictEqual(inspect(parser('[% a [% '), ctx), [['[%', ' a ', '[%'], '']);
28
+ assert.deepStrictEqual(inspect(parser('[% a [% b'), ctx), [['[%', ' a ', '[%', ' b'], '']);
29
+ assert.deepStrictEqual(inspect(parser('[% a [%% b'), ctx), [['[%', ' a ', '<span class="invalid">[%%</span>', ' b'], '']);
30
+ assert.deepStrictEqual(inspect(parser('[%% a [% b'), ctx), [['<span class="invalid">[%%</span>'], ' a [% b']);
31
31
  assert.deepStrictEqual(inspect(parser('[%\\ a %]'), ctx), undefined);
32
- assert.deepStrictEqual(inspect(parser('[% a\\ %]'), ctx), [['[%', ' ', 'a', ' ', '%', ']'], '']);
33
- assert.deepStrictEqual(inspect(parser('[% a%]'), ctx), [['[%', ' ', 'a', '%', ']'], '']);
34
- assert.deepStrictEqual(inspect(parser('[% a %%]'), ctx), [['[%', ' ', 'a', ' ', '%', '%', ']'], '']);
35
- assert.deepStrictEqual(inspect(parser('[% [%% %]'), ctx), [['[%', ' ', '[%%', ' ', '%', ']'], '']);
36
- assert.deepStrictEqual(inspect(parser('[%% [% %%]'), ctx), [['[%%', ' ', '[%', ' ', '%', '%', ']'], '']);
37
- assert.deepStrictEqual(inspect(parser('[%% a %]'), ctx), [['[%%', ' ', 'a', ' ', '%', ']'], '']);
32
+ assert.deepStrictEqual(inspect(parser('[% a\\ %]'), ctx), [['[%', ' a', ' ', '%', ']'], '']);
33
+ assert.deepStrictEqual(inspect(parser('[% a%]'), ctx), [['[%', ' a', '%', ']'], '']);
34
+ assert.deepStrictEqual(inspect(parser('[% a %%]'), ctx), [['[%', ' a', ' ', '%', '%', ']'], '']);
35
+ assert.deepStrictEqual(inspect(parser('[% [%% %]'), ctx), [['<span class="remark"><input type="checkbox"><span>[% <span class="invalid">[%%</span> %]</span></span>'], '']);
36
+ assert.deepStrictEqual(inspect(parser('[%% [% %%]'), ctx), [['<span class="invalid">[%%</span>'], ' [% %%]']);
37
+ assert.deepStrictEqual(inspect(parser('[%% a %]'), ctx), [['<span class="invalid">[%%</span>'], ' a %]']);
38
38
  assert.deepStrictEqual(inspect(parser(' [% a %]'), ctx), undefined);
39
39
  });
40
40
 
@@ -49,10 +49,6 @@ describe('Unit: parser/inline/remark', () => {
49
49
  assert.deepStrictEqual(inspect(parser('[% a %] %]'), ctx), [['<span class="remark"><input type="checkbox"><span>[% a %]</span></span>'], ' %]']);
50
50
  assert.deepStrictEqual(inspect(parser('[% %%] %]'), ctx), [['<span class="remark"><input type="checkbox"><span>[% %%] %]</span></span>'], '']);
51
51
  assert.deepStrictEqual(inspect(parser('[% [% a %] %]'), ctx), [['<span class="remark"><input type="checkbox"><span>[% <span class="remark"><input type="checkbox"><span>[% a %]</span></span> %]</span></span>'], '']);
52
- assert.deepStrictEqual(inspect(parser('[% [%% a %%] %]'), ctx), [['<span class="remark"><input type="checkbox"><span>[% <span class="remark"><input type="checkbox"><span>[%% a %%]</span></span> %]</span></span>'], '']);
53
- assert.deepStrictEqual(inspect(parser('[%% a %%]'), ctx), [['<span class="remark"><input type="checkbox"><span>[%% a %%]</span></span>'], '']);
54
- assert.deepStrictEqual(inspect(parser('[%% %] %%]'), ctx), [['<span class="remark"><input type="checkbox"><span>[%% %] %%]</span></span>'], '']);
55
- assert.deepStrictEqual(inspect(parser('[%% [% a %] %%]'), ctx), [['<span class="remark"><input type="checkbox"><span>[%% <span class="remark"><input type="checkbox"><span>[% a %]</span></span> %%]</span></span>'], '']);
56
52
  assert.deepStrictEqual(inspect(parser('[% a %]b'), ctx), [['<span class="remark"><input type="checkbox"><span>[% a %]</span></span>'], 'b']);
57
53
  assert.deepStrictEqual(inspect(parser('[%\na\n%]'), ctx), [['<span class="remark"><input type="checkbox"><span>[%<br>a<br>%]</span></span>'], '']);
58
54
  assert.deepStrictEqual(inspect(parser('[% &a; %]'), ctx), [['<span class="remark"><input type="checkbox"><span>[% <span class="invalid">&amp;a;</span> %]</span></span>'], '']);