securemark 0.260.4 → 0.261.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 (53) hide show
  1. package/CHANGELOG.md +12 -0
  2. package/README.md +12 -12
  3. package/design.md +0 -4
  4. package/dist/index.js +268 -243
  5. package/markdown.d.ts +7 -23
  6. package/package.json +6 -6
  7. package/src/combinator/data/parser/context/memo.ts +4 -0
  8. package/src/combinator/data/parser/context.ts +25 -16
  9. package/src/combinator/data/parser.ts +0 -1
  10. package/src/parser/api/bind.ts +2 -1
  11. package/src/parser/api/parse.test.ts +1 -1
  12. package/src/parser/api/parse.ts +2 -1
  13. package/src/parser/block/blockquote.test.ts +2 -2
  14. package/src/parser/block/dlist.test.ts +1 -1
  15. package/src/parser/block/extension/example.test.ts +1 -1
  16. package/src/parser/block/extension/fig.test.ts +1 -1
  17. package/src/parser/block/heading.test.ts +2 -2
  18. package/src/parser/block/paragraph.test.ts +1 -4
  19. package/src/parser/block/reply/cite.test.ts +5 -0
  20. package/src/parser/block/reply/cite.ts +5 -4
  21. package/src/parser/context.ts +8 -7
  22. package/src/parser/inline/autolink/anchor.test.ts +1 -0
  23. package/src/parser/inline/autolink/email.test.ts +3 -0
  24. package/src/parser/inline/autolink/email.ts +1 -1
  25. package/src/parser/inline/autolink/hashnum.test.ts +1 -2
  26. package/src/parser/inline/autolink/hashnum.ts +1 -1
  27. package/src/parser/inline/autolink/hashtag.test.ts +15 -12
  28. package/src/parser/inline/autolink/hashtag.ts +3 -3
  29. package/src/parser/inline/autolink/url.test.ts +1 -1
  30. package/src/parser/inline/autolink/url.ts +1 -1
  31. package/src/parser/inline/autolink.ts +14 -5
  32. package/src/parser/inline/deletion.test.ts +2 -2
  33. package/src/parser/inline/emphasis.test.ts +26 -35
  34. package/src/parser/inline/emphasis.ts +5 -12
  35. package/src/parser/inline/escape.ts +1 -10
  36. package/src/parser/inline/extension/index.test.ts +2 -2
  37. package/src/parser/inline/extension/index.ts +1 -1
  38. package/src/parser/inline/insertion.test.ts +2 -2
  39. package/src/parser/inline/link.test.ts +1 -1
  40. package/src/parser/inline/link.ts +2 -2
  41. package/src/parser/inline/mark.test.ts +1 -1
  42. package/src/parser/inline/media.ts +2 -2
  43. package/src/parser/inline/ruby.ts +10 -6
  44. package/src/parser/inline/strong.test.ts +25 -32
  45. package/src/parser/inline/strong.ts +4 -8
  46. package/src/parser/inline/template.ts +1 -1
  47. package/src/parser/inline.test.ts +18 -91
  48. package/src/parser/inline.ts +0 -3
  49. package/src/parser/locale/ja.ts +1 -9
  50. package/src/parser/locale.test.ts +1 -1
  51. package/src/parser/source/text.test.ts +9 -4
  52. package/src/parser/source/text.ts +9 -16
  53. package/src/parser/inline/emstrong.ts +0 -62
@@ -1,5 +1,5 @@
1
1
  import { AutolinkParser } from '../inline';
2
- import { union, some, syntax, constraint, validate, fmap } from '../../combinator';
2
+ import { union, some, syntax, constraint, validate, focus, fmap } from '../../combinator';
3
3
  import { url } from './autolink/url';
4
4
  import { email } from './autolink/email';
5
5
  import { channel } from './autolink/channel';
@@ -14,22 +14,31 @@ import { stringify } from '../util';
14
14
  export const autolink: AutolinkParser = fmap(
15
15
  validate(/^(?:[@#>0-9a-z]|\S[#>])/i,
16
16
  constraint(State.autolink, false,
17
- syntax(Syntax.autolink, 1, 1, State.none,
17
+ syntax(Syntax.autolink, 1, 1, ~State.shortcut,
18
18
  some(union([
19
19
  url,
20
20
  email,
21
21
  // Escape unmatched email-like strings.
22
- str(/^[0-9a-z]+(?:[.+_-][0-9a-z]+)*(?:@(?:[0-9a-z]+(?:[.-][0-9a-z]+)*)?)*/i),
22
+ focus(
23
+ /^[0-9a-z](?:[_.+-](?=[0-9a-z])|[0-9a-z])*(?:@(?:[0-9a-z]+(?:[.-][0-9a-z]+)*)?)*/i,
24
+ ({ source }) => {
25
+ if (source.length > 255 || source.includes('@')) return [[source], ''];
26
+ const i = source.indexOf('_');
27
+ if (i === -1) return [[source], ''];
28
+ return [[source.slice(0, i)], source.slice(i)];
29
+ }),
23
30
  channel,
24
31
  account,
25
32
  // Escape unmatched account-like strings.
26
33
  str(/^@+[0-9a-z]*(?:-[0-9a-z]+)*/i),
27
34
  // Escape invalid leading characters.
28
- str(new RegExp(/^(?:[^\p{C}\p{S}\p{P}\s]|emoji|['_])(?=#)/u.source.replace('emoji', emoji), 'u')),
35
+ str(new RegExp(/^(?:[^\p{C}\p{S}\p{P}\s]|emoji)(?=#)/u.source.replace('emoji', emoji), 'u')),
29
36
  hashtag,
30
37
  hashnum,
31
38
  // Escape unmatched hashtag-like strings.
32
- str(new RegExp(/^#+(?:[^\p{C}\p{S}\p{P}\s]|emoji|['_])*/u.source.replace('emoji', emoji), 'u')),
39
+ str(new RegExp(/^#+(?:[^\p{C}\p{S}\p{P}\s]|emoji|')*/u.source.replace('emoji', emoji), 'u')),
40
+ // Escape invalid leading characters.
41
+ str(/^[0-9\p{Sc}](?=>)/u),
33
42
  anchor,
34
43
  ]))))),
35
44
  ns => ns.length === 1 ? ns : [stringify(ns)]);
@@ -37,8 +37,8 @@ describe('Unit: parser/inline/deletion', () => {
37
37
  });
38
38
 
39
39
  it('nest', () => {
40
- assert.deepStrictEqual(inspect(parser('~~*~~a~~*~~')), [['<del><em><del>a</del></em></del>'], '']);
41
- assert.deepStrictEqual(inspect(parser('~~*++a++*~~')), [['<del><em><ins>a</ins></em></del>'], '']);
40
+ assert.deepStrictEqual(inspect(parser('~~_~~a~~_~~')), [['<del><em><del>a</del></em></del>'], '']);
41
+ assert.deepStrictEqual(inspect(parser('~~_++a++_~~')), [['<del><em><ins>a</ins></em></del>'], '']);
42
42
  });
43
43
 
44
44
  });
@@ -7,47 +7,38 @@ describe('Unit: parser/inline/emphasis', () => {
7
7
  const parser = (source: string) => some(emphasis)({ source, context: {} });
8
8
 
9
9
  it('invalid', () => {
10
- assert.deepStrictEqual(inspect(parser('*')), undefined);
11
- assert.deepStrictEqual(inspect(parser('*a')), [['*', 'a'], '']);
12
- assert.deepStrictEqual(inspect(parser('*a *')), [['*', 'a'], ' *']);
13
- assert.deepStrictEqual(inspect(parser('*a *')), [['*', 'a', ' '], ' *']);
14
- assert.deepStrictEqual(inspect(parser('*a\n*')), [['*', 'a'], '\n*']);
15
- assert.deepStrictEqual(inspect(parser('*a\\ *')), [['*', 'a'], '\\ *']);
16
- assert.deepStrictEqual(inspect(parser('*a\\\n*')), [['*', 'a'], '\\\n*']);
17
- assert.deepStrictEqual(inspect(parser('*a**b')), [['*', 'a', '**', 'b'], '']);
18
- assert.deepStrictEqual(inspect(parser('*a**b*')), [['*', 'a', '**', 'b', '*'], '']);
19
- assert.deepStrictEqual(inspect(parser('* *')), undefined);
20
- assert.deepStrictEqual(inspect(parser('* a*')), undefined);
21
- assert.deepStrictEqual(inspect(parser('* a *')), undefined);
22
- assert.deepStrictEqual(inspect(parser('*\n*')), undefined);
23
- assert.deepStrictEqual(inspect(parser('*\na*')), undefined);
24
- assert.deepStrictEqual(inspect(parser('*\\ a*')), undefined);
25
- assert.deepStrictEqual(inspect(parser('*\\\na*')), undefined);
26
- assert.deepStrictEqual(inspect(parser('*<wbr>a*')), undefined);
27
- assert.deepStrictEqual(inspect(parser('**a**')), undefined);
28
- assert.deepStrictEqual(inspect(parser('***a***')), undefined);
29
- assert.deepStrictEqual(inspect(parser(' *a*')), undefined);
10
+ assert.deepStrictEqual(inspect(parser('_')), undefined);
11
+ assert.deepStrictEqual(inspect(parser('_a')), [['_', 'a'], '']);
12
+ assert.deepStrictEqual(inspect(parser('_a _')), [['_', 'a'], ' _']);
13
+ assert.deepStrictEqual(inspect(parser('_a _')), [['_', 'a', ' '], ' _']);
14
+ assert.deepStrictEqual(inspect(parser('_a\n_')), [['_', 'a'], '\n_']);
15
+ assert.deepStrictEqual(inspect(parser('_a\\ _')), [['_', 'a'], '\\ _']);
16
+ assert.deepStrictEqual(inspect(parser('_a\\\n_')), [['_', 'a'], '\\\n_']);
17
+ assert.deepStrictEqual(inspect(parser('_ _')), undefined);
18
+ assert.deepStrictEqual(inspect(parser('_ a_')), undefined);
19
+ assert.deepStrictEqual(inspect(parser('_ a _')), undefined);
20
+ assert.deepStrictEqual(inspect(parser('_\n_')), undefined);
21
+ assert.deepStrictEqual(inspect(parser('_\na_')), undefined);
22
+ assert.deepStrictEqual(inspect(parser('_\\ a_')), undefined);
23
+ assert.deepStrictEqual(inspect(parser('_\\\na_')), undefined);
24
+ assert.deepStrictEqual(inspect(parser('_<wbr>a_')), undefined);
25
+ assert.deepStrictEqual(inspect(parser(' _a_')), undefined);
30
26
  });
31
27
 
32
28
  it('basic', () => {
33
- assert.deepStrictEqual(inspect(parser('*a*')), [['<em>a</em>'], '']);
34
- assert.deepStrictEqual(inspect(parser('*ab*')), [['<em>ab</em>'], '']);
35
- assert.deepStrictEqual(inspect(parser('*a\nb*')), [['<em>a<br>b</em>'], '']);
36
- assert.deepStrictEqual(inspect(parser('*a\\\nb*')), [['<em>a<span class="linebreak"> </span>b</em>'], '']);
37
- assert.deepStrictEqual(inspect(parser('*a**')), [['<em>a</em>'], '*']);
29
+ assert.deepStrictEqual(inspect(parser('_a_')), [['<em>a</em>'], '']);
30
+ assert.deepStrictEqual(inspect(parser('_ab_')), [['<em>ab</em>'], '']);
31
+ assert.deepStrictEqual(inspect(parser('_a\nb_')), [['<em>a<br>b</em>'], '']);
32
+ assert.deepStrictEqual(inspect(parser('_a\\\nb_')), [['<em>a<span class="linebreak"> </span>b</em>'], '']);
38
33
  });
39
34
 
40
35
  it('nest', () => {
41
- assert.deepStrictEqual(inspect(parser('*a *b**')), [['<em>a <em>b</em></em>'], '']);
42
- assert.deepStrictEqual(inspect(parser('*a **b***')), [['<em>a <strong>b</strong></em>'], '']);
43
- assert.deepStrictEqual(inspect(parser('*a\\ *b**')), [['<em>a <em>b</em></em>'], '']);
44
- assert.deepStrictEqual(inspect(parser('*a&Tab;*b**')), [['<em>a\t<em>b</em></em>'], '']);
45
- assert.deepStrictEqual(inspect(parser('*a<wbr>*b**')), [['<em>a<wbr><em>b</em></em>'], '']);
46
- assert.deepStrictEqual(inspect(parser('*a**b**c*')), [['<em>a<strong>b</strong>c</em>'], '']);
47
- assert.deepStrictEqual(inspect(parser('*a**b**c*d')), [['<em>a<strong>b</strong>c</em>'], 'd']);
48
- assert.deepStrictEqual(inspect(parser('*`a`*')), [['<em><code data-src="`a`">a</code></em>'], '']);
49
- assert.deepStrictEqual(inspect(parser('*(*a*)*')), [['<em><span class="paren">(<em>a</em>)</span></em>'], '']);
50
- assert.deepStrictEqual(inspect(parser('*(**a**)*')), [['<em><span class="paren">(<strong>a</strong>)</span></em>'], '']);
36
+ assert.deepStrictEqual(inspect(parser('_a _b__')), [['<em>a <em>b</em></em>'], '']);
37
+ assert.deepStrictEqual(inspect(parser('_a *b*_')), [['<em>a <strong>b</strong></em>'], '']);
38
+ assert.deepStrictEqual(inspect(parser('_a\\ _b__')), [['<em>a <em>b</em></em>'], '']);
39
+ assert.deepStrictEqual(inspect(parser('_a&Tab;_b__')), [['<em>a\t<em>b</em></em>'], '']);
40
+ assert.deepStrictEqual(inspect(parser('_a<wbr>_b__')), [['<em>a<wbr><em>b</em></em>'], '']);
41
+ assert.deepStrictEqual(inspect(parser('_(_a_)_')), [['<em><span class="paren">(<em>a</em>)</span></em>'], '']);
51
42
  });
52
43
 
53
44
  });
@@ -1,8 +1,6 @@
1
1
  import { EmphasisParser } from '../inline';
2
2
  import { union, some, syntax, surround, open, lazy } from '../../combinator';
3
3
  import { inline } from '../inline';
4
- import { emstrong } from './emstrong';
5
- import { strong } from './strong';
6
4
  import { str } from '../source';
7
5
  import { Syntax, State } from '../context';
8
6
  import { startTight, blankWith } from '../visibility';
@@ -10,17 +8,12 @@ import { html, defrag } from 'typed-dom/dom';
10
8
  import { unshift } from 'spica/array';
11
9
 
12
10
  export const emphasis: EmphasisParser = lazy(() => surround(
13
- str('*'),
11
+ str('_'),
14
12
  syntax(Syntax.none, 1, 1, State.none,
15
13
  startTight(some(union([
16
- strong,
17
- some(inline, blankWith('*')),
18
- open(some(inline, '*'), union([
19
- emstrong,
20
- strong,
21
- emphasis,
22
- ])),
23
- ])), '*')),
24
- str('*'), false,
14
+ some(inline, blankWith('_')),
15
+ open(some(inline, '_'), emphasis),
16
+ ])), '_')),
17
+ str('_'), false,
25
18
  ([, bs], rest) => [[html('em', defrag(bs))], rest],
26
19
  ([as, bs], rest) => [unshift(as, bs), rest]));
@@ -6,20 +6,11 @@ import { str } from '../source';
6
6
  const repeat = str(/^(.)\1*/);
7
7
 
8
8
  export const escape: EscapeParser = union([({ source, context }) => {
9
- if (source.length < 3) return;
10
9
  switch (source[0]) {
11
- case '*':
12
- if (source.length < 4) return;
13
- assert(source[3]);
14
- return source[3] === source[0]
15
- && source[2] === source[0]
16
- && source[1] === source[0]
17
- ? repeat({ source, context })
18
- : undefined;
19
10
  case '+':
20
11
  case '~':
21
12
  case '=':
22
- assert(source[2]);
13
+ if (!source[2]) return;
23
14
  return source[2] === source[0]
24
15
  && source[1] === source[0]
25
16
  ? repeat({ source, context })
@@ -53,7 +53,7 @@ describe('Unit: parser/inline/extension/index', () => {
53
53
  assert.deepStrictEqual(inspect(parser('[#\\\\]')), [['<a class="index" href="#index:\\">\\</a>'], '']);
54
54
  assert.deepStrictEqual(inspect(parser('[#A]')), [['<a class="index" href="#index:A">A</a>'], '']);
55
55
  assert.deepStrictEqual(inspect(parser('[#==]')), [['<a class="index" href="#index:==">==</a>'], '']);
56
- assert.deepStrictEqual(inspect(parser('[#*A*]')), [['<a class="index" href="#index:A"><em>A</em></a>'], '']);
56
+ assert.deepStrictEqual(inspect(parser('[#_A_]')), [['<a class="index" href="#index:A"><em>A</em></a>'], '']);
57
57
  assert.deepStrictEqual(inspect(parser('[#`A`]')), [['<a class="index" href="#index:`A`"><code data-src="`A`">A</code></a>'], '']);
58
58
  assert.deepStrictEqual(inspect(parser('[#${A}$]')), [['<a class="index" href="#index:${A}$"><span class="math" translate="no" data-src="${A}$">${A}$</span></a>'], '']);
59
59
  assert.deepStrictEqual(inspect(parser('[#[A](a)]')), [['<a class="index" href="#index:A"><ruby>A<rp>(</rp><rt>a</rt><rp>)</rp></ruby></a>'], '']);
@@ -80,7 +80,7 @@ describe('Unit: parser/inline/extension/index', () => {
80
80
  assert.deepStrictEqual(inspect(parser('[#a|#b ]')), [['<a class="index" href="#index:b">a<span class="indexer" data-index="b"></span></a>'], '']);
81
81
  assert.deepStrictEqual(inspect(parser('[#a|#b ]')), [['<a class="index" href="#index:b">a<span class="indexer" data-index="b"></span></a>'], '']);
82
82
  assert.deepStrictEqual(inspect(parser('[#a|#\\b]')), [['<a class="index" href="#index:b">a<span class="indexer" data-index="b"></span></a>'], '']);
83
- assert.deepStrictEqual(inspect(parser('[#a|#*b*]')), [['<a class="index" href="#index:*b*">a<span class="indexer" data-index="*b*"></span></a>'], '']);
83
+ assert.deepStrictEqual(inspect(parser('[#a|#_b_]')), [['<a class="index" href="#index:_b_">a<span class="indexer" data-index="_b_"></span></a>'], '']);
84
84
  assert.deepStrictEqual(inspect(parser('[#a|#b c]')), [['<a class="index" href="#index:b_c">a<span class="indexer" data-index="b_c"></span></a>'], '']);
85
85
  assert.deepStrictEqual(inspect(parser('[#a|#b c]')), [['<a class="index" href="#index:b_c">a<span class="indexer" data-index="b_c"></span></a>'], '']);
86
86
  assert.deepStrictEqual(inspect(parser('[#a|#[]]')), [['<a class="index" href="#index:[]">a<span class="indexer" data-index="[]"></span></a>'], '']);
@@ -13,7 +13,7 @@ import IndexParser = ExtensionParser.IndexParser;
13
13
  export const index: IndexParser = lazy(() => validate('[#', fmap(indexee(surround(
14
14
  '[#',
15
15
  constraint(State.index, false,
16
- syntax(Syntax.index, 2, 1, State.linkable,
16
+ syntax(Syntax.index, 2, 1, State.linkers | State.media,
17
17
  startTight(
18
18
  open(stropt(/^\|?/), trimBlankEnd(some(union([
19
19
  signature,
@@ -37,8 +37,8 @@ describe('Unit: parser/inline/insertion', () => {
37
37
  });
38
38
 
39
39
  it('nest', () => {
40
- assert.deepStrictEqual(inspect(parser('++*++a++*++')), [['<ins><em><ins>a</ins></em></ins>'], '']);
41
- assert.deepStrictEqual(inspect(parser('++*~~a~~*++')), [['<ins><em><del>a</del></em></ins>'], '']);
40
+ assert.deepStrictEqual(inspect(parser('++_++a++_++')), [['<ins><em><ins>a</ins></em></ins>'], '']);
41
+ assert.deepStrictEqual(inspect(parser('++_~~a~~_++')), [['<ins><em><del>a</del></em></ins>'], '']);
42
42
  });
43
43
 
44
44
  });
@@ -170,7 +170,7 @@ describe('Unit: parser/inline/link', () => {
170
170
  assert.deepStrictEqual(inspect(parser('[((a))]{b}')), [['<a class="link" href="b"><span class="paren">((a))</span></a>'], '']);
171
171
  assert.deepStrictEqual(inspect(parser('[[[a]]]{b}')), [['<a class="link" href="b">[[a]]</a>'], '']);
172
172
  assert.deepStrictEqual(inspect(parser('[!http://host]{/}')), [['<a class="link" href="/" target="_blank"><img class="media" data-src="http://host" alt=""></a>'], '']);
173
- assert.deepStrictEqual(inspect(parser('[*a*]{b}')), [['<a class="link" href="b"><em>a</em></a>'], '']);
173
+ assert.deepStrictEqual(inspect(parser('[_a_]{b}')), [['<a class="link" href="b"><em>a</em></a>'], '']);
174
174
  });
175
175
 
176
176
  it('external', () => {
@@ -25,7 +25,7 @@ export const link: LinkParser = lazy(() => validate(['[', '{'], union([
25
25
 
26
26
  const textlink: LinkParser.TextLinkParser = lazy(() =>
27
27
  constraint(State.link, false,
28
- syntax(Syntax.link, 2, 10, State.linkable,
28
+ syntax(Syntax.link, 2, 10, State.linkers | State.media,
29
29
  bind(reverse(tails([
30
30
  dup(surround(
31
31
  '[',
@@ -41,7 +41,7 @@ const textlink: LinkParser.TextLinkParser = lazy(() =>
41
41
 
42
42
  const medialink: LinkParser.MediaLinkParser = lazy(() =>
43
43
  constraint(State.link | State.media, false,
44
- syntax(Syntax.link, 2, 10, State.linkable ^ State.media,
44
+ syntax(Syntax.link, 2, 10, State.linkers,
45
45
  bind(reverse(sequence([
46
46
  dup(surround(
47
47
  '[',
@@ -40,7 +40,7 @@ describe('Unit: parser/inline/mark', () => {
40
40
  assert.deepStrictEqual(inspect(parser('==a\\ ==b====')), [['<mark>a <mark>b</mark></mark>'], '']);
41
41
  assert.deepStrictEqual(inspect(parser('==a&Tab;==b====')), [['<mark>a\t<mark>b</mark></mark>'], '']);
42
42
  assert.deepStrictEqual(inspect(parser('==a<wbr>==b====')), [['<mark>a<wbr><mark>b</mark></mark>'], '']);
43
- assert.deepStrictEqual(inspect(parser('==*==a==*==')), [['<mark><em><mark>a</mark></em></mark>'], '']);
43
+ assert.deepStrictEqual(inspect(parser('==_==a==_==')), [['<mark><em><mark>a</mark></em></mark>'], '']);
44
44
  });
45
45
 
46
46
  });
@@ -21,7 +21,7 @@ Object.setPrototypeOf(optspec, null);
21
21
  export const media: MediaParser = lazy(() => validate(['![', '!{'], open(
22
22
  '!',
23
23
  constraint(State.media, false,
24
- syntax(Syntax.media, 2, 10, State.none,
24
+ syntax(Syntax.media, 2, 10, ~State.link,
25
25
  bind(verify(fmap(tails([
26
26
  dup(surround(
27
27
  '[',
@@ -55,7 +55,7 @@ export const media: MediaParser = lazy(() => validate(['![', '!{'], open(
55
55
  el.style.aspectRatio = el.getAttribute('aspect-ratio')!;
56
56
  }
57
57
  if (context.state! & State.link) return [[el], rest];
58
- if (cache && cache.tagName !== 'IMG') return creation(10, (..._) => [[el!], rest])({ source: '!', context });
58
+ if (cache && cache.tagName !== 'IMG') return creation(10, _ => [[el!], rest])({ source: '!', context });
59
59
  return fmap(
60
60
  unsafelink as MediaParser,
61
61
  ([link]) => [define(link, { class: null, target: '_blank' }, [el])])
@@ -1,20 +1,24 @@
1
1
  import { undefined } from 'spica/global';
2
2
  import { RubyParser } from '../inline';
3
3
  import { eval, exec } from '../../combinator/data/parser';
4
- import { sequence, syntax, creation, validate, verify, focus, surround, lazy, fmap } from '../../combinator';
4
+ import { sequence, syntax, creation, validate, verify, surround, lazy, fmap } from '../../combinator';
5
5
  import { unsafehtmlentity } from './htmlentity';
6
- import { text as txt } from '../source';
6
+ import { text as txt, str } from '../source';
7
7
  import { Syntax, State } from '../context';
8
8
  import { isStartTightNodes } from '../visibility';
9
9
  import { html, defrag } from 'typed-dom/dom';
10
10
  import { unshift, push } from 'spica/array';
11
11
 
12
- export const ruby: RubyParser = lazy(() => validate('[', syntax(Syntax.none, 2, 1, State.none, fmap(verify(
12
+ export const ruby: RubyParser = lazy(() => validate('[', syntax(Syntax.ruby, 2, 1, State.all, fmap(verify(fmap(
13
13
  sequence([
14
- surround('[', focus(/^(?:\\[^\n]|[^\\[\](){}"\n])+(?=]\()/, text), ']'),
15
- surround('(', focus(/^(?:\\[^\n]|[^\\[\](){}"\n])+(?=\))/, text), ')'),
14
+ surround('[', str(/^(?:\\[^\n]|[^\\[\](){}"\n])+/), ']'),
15
+ surround('(', str(/^(?:\\[^\n]|[^\\[\](){}"\n])+/), ')'),
16
16
  ]),
17
- ([texts]) => isStartTightNodes(texts)),
17
+ ([texts, rubies], _, context) => [
18
+ eval(text({ source: texts, context }), [])[0] ?? '',
19
+ eval(text({ source: rubies, context }), [])[0] ?? '',
20
+ ]),
21
+ ([texts, rubies]) => texts && rubies && isStartTightNodes(texts)),
18
22
  ([texts, rubies]) => {
19
23
  texts[texts.length - 1] === '' && texts.pop();
20
24
  switch (true) {
@@ -7,44 +7,37 @@ describe('Unit: parser/inline/strong', () => {
7
7
  const parser = (source: string) => some(strong)({ source, context: {} });
8
8
 
9
9
  it('invalid', () => {
10
- assert.deepStrictEqual(inspect(parser('**')), undefined);
11
- assert.deepStrictEqual(inspect(parser('**a')), [['**', 'a'], '']);
12
- assert.deepStrictEqual(inspect(parser('**a **')), [['**', 'a'], ' **']);
13
- assert.deepStrictEqual(inspect(parser('**a **')), [['**', 'a', ' '], ' **']);
14
- assert.deepStrictEqual(inspect(parser('**a\n**')), [['**', 'a'], '\n**']);
15
- assert.deepStrictEqual(inspect(parser('**a\\ **')), [['**', 'a'], '\\ **']);
16
- assert.deepStrictEqual(inspect(parser('**a\\\n**')), [['**', 'a'], '\\\n**']);
17
- assert.deepStrictEqual(inspect(parser('**a*')), [['**', 'a', '*'], '']);
18
- assert.deepStrictEqual(inspect(parser('**a*b**')), [['**', 'a', '<em>b</em>', '*'], '']);
19
- assert.deepStrictEqual(inspect(parser('** **')), undefined);
20
- assert.deepStrictEqual(inspect(parser('** a**')), undefined);
21
- assert.deepStrictEqual(inspect(parser('** a **')), undefined);
22
- assert.deepStrictEqual(inspect(parser('**\n**')), undefined);
23
- assert.deepStrictEqual(inspect(parser('**\na**')), undefined);
24
- assert.deepStrictEqual(inspect(parser('**\\ a**')), undefined);
25
- assert.deepStrictEqual(inspect(parser('**\\\na**')), undefined);
26
- assert.deepStrictEqual(inspect(parser('**<wbr>a**')), undefined);
27
- assert.deepStrictEqual(inspect(parser('***a***')), undefined);
28
- assert.deepStrictEqual(inspect(parser(' **a**')), undefined);
10
+ assert.deepStrictEqual(inspect(parser('*')), undefined);
11
+ assert.deepStrictEqual(inspect(parser('*a')), [['*', 'a'], '']);
12
+ assert.deepStrictEqual(inspect(parser('*a *')), [['*', 'a'], ' *']);
13
+ assert.deepStrictEqual(inspect(parser('*a *')), [['*', 'a', ' '], ' *']);
14
+ assert.deepStrictEqual(inspect(parser('*a\n*')), [['*', 'a'], '\n*']);
15
+ assert.deepStrictEqual(inspect(parser('*a\\ *')), [['*', 'a'], '\\ *']);
16
+ assert.deepStrictEqual(inspect(parser('*a\\\n*')), [['*', 'a'], '\\\n*']);
17
+ assert.deepStrictEqual(inspect(parser('* *')), undefined);
18
+ assert.deepStrictEqual(inspect(parser('* a*')), undefined);
19
+ assert.deepStrictEqual(inspect(parser('* a *')), undefined);
20
+ assert.deepStrictEqual(inspect(parser('*\n*')), undefined);
21
+ assert.deepStrictEqual(inspect(parser('*\na*')), undefined);
22
+ assert.deepStrictEqual(inspect(parser('*\\ a*')), undefined);
23
+ assert.deepStrictEqual(inspect(parser('*\\\na*')), undefined);
24
+ assert.deepStrictEqual(inspect(parser('*<wbr>a*')), undefined);
25
+ assert.deepStrictEqual(inspect(parser(' *a*')), undefined);
29
26
  });
30
27
 
31
28
  it('basic', () => {
32
- assert.deepStrictEqual(inspect(parser('**a**')), [['<strong>a</strong>'], '']);
33
- assert.deepStrictEqual(inspect(parser('**ab**')), [['<strong>ab</strong>'], '']);
34
- assert.deepStrictEqual(inspect(parser('**a\nb**')), [['<strong>a<br>b</strong>'], '']);
35
- assert.deepStrictEqual(inspect(parser('**a\\\nb**')), [['<strong>a<span class="linebreak"> </span>b</strong>'], '']);
29
+ assert.deepStrictEqual(inspect(parser('*a*')), [['<strong>a</strong>'], '']);
30
+ assert.deepStrictEqual(inspect(parser('*ab*')), [['<strong>ab</strong>'], '']);
31
+ assert.deepStrictEqual(inspect(parser('*a\nb*')), [['<strong>a<br>b</strong>'], '']);
32
+ assert.deepStrictEqual(inspect(parser('*a\\\nb*')), [['<strong>a<span class="linebreak"> </span>b</strong>'], '']);
36
33
  });
37
34
 
38
35
  it('nest', () => {
39
- assert.deepStrictEqual(inspect(parser('**a *b***')), [['<strong>a <em>b</em></strong>'], '']);
40
- assert.deepStrictEqual(inspect(parser('**a **b****')), [['<strong>a <strong>b</strong></strong>'], '']);
41
- assert.deepStrictEqual(inspect(parser('**a&Tab;**b****')), [['<strong>a\t<strong>b</strong></strong>'], '']);
42
- assert.deepStrictEqual(inspect(parser('**a<wbr>**b****')), [['<strong>a<wbr><strong>b</strong></strong>'], '']);
43
- assert.deepStrictEqual(inspect(parser('**a*b*c**')), [['<strong>a<em>b</em>c</strong>'], '']);
44
- assert.deepStrictEqual(inspect(parser('**a*b*c**d')), [['<strong>a<em>b</em>c</strong>'], 'd']);
45
- assert.deepStrictEqual(inspect(parser('**`a`**')), [['<strong><code data-src="`a`">a</code></strong>'], '']);
46
- assert.deepStrictEqual(inspect(parser('**(*a*)**')), [['<strong><span class="paren">(<em>a</em>)</span></strong>'], '']);
47
- assert.deepStrictEqual(inspect(parser('**(**a**)**')), [['<strong><span class="paren">(<strong>a</strong>)</span></strong>'], '']);
36
+ assert.deepStrictEqual(inspect(parser('*a _b_*')), [['<strong>a <em>b</em></strong>'], '']);
37
+ assert.deepStrictEqual(inspect(parser('*a *b**')), [['<strong>a <strong>b</strong></strong>'], '']);
38
+ assert.deepStrictEqual(inspect(parser('*a&Tab;*b**')), [['<strong>a\t<strong>b</strong></strong>'], '']);
39
+ assert.deepStrictEqual(inspect(parser('*a<wbr>*b**')), [['<strong>a<wbr><strong>b</strong></strong>'], '']);
40
+ assert.deepStrictEqual(inspect(parser('*(*a*)*')), [['<strong><span class="paren">(<strong>a</strong>)</span></strong>'], '']);
48
41
  });
49
42
 
50
43
  });
@@ -1,7 +1,6 @@
1
1
  import { StrongParser } from '../inline';
2
2
  import { union, some, syntax, surround, open, lazy } from '../../combinator';
3
3
  import { inline } from '../inline';
4
- import { emstrong } from './emstrong';
5
4
  import { str } from '../source';
6
5
  import { Syntax, State } from '../context';
7
6
  import { startTight, blankWith } from '../visibility';
@@ -9,15 +8,12 @@ import { html, defrag } from 'typed-dom/dom';
9
8
  import { unshift } from 'spica/array';
10
9
 
11
10
  export const strong: StrongParser = lazy(() => surround(
12
- str('**'),
11
+ str('*'),
13
12
  syntax(Syntax.none, 1, 1, State.none,
14
13
  startTight(some(union([
15
- some(inline, blankWith('**')),
16
- open(some(inline, '*'), union([
17
- emstrong,
18
- strong,
19
- ])),
14
+ some(inline, blankWith('*')),
15
+ open(some(inline, '*'), strong),
20
16
  ])), '*')),
21
- str('**'), false,
17
+ str('*'), false,
22
18
  ([, bs], rest) => [[html('strong', defrag(bs))], rest],
23
19
  ([as, bs], rest) => [unshift(as, bs), rest]));
@@ -7,7 +7,7 @@ import { html } from 'typed-dom/dom';
7
7
  import { unshift } from 'spica/array';
8
8
 
9
9
  export const template: TemplateParser = lazy(() => surround(
10
- '{{', syntax(Syntax.none, 2, 1, State.none, some(union([bracket, escsource]), '}')), '}}', true,
10
+ '{{', syntax(Syntax.none, 2, 1, State.all, some(union([bracket, escsource]), '}')), '}}', true,
11
11
  ([, ns = []], rest) => [[html('span', { class: 'template' }, `{{${ns.join('').replace(/\x1B/g, '')}}}`)], rest]));
12
12
 
13
13
  const bracket: TemplateParser.BracketParser = lazy(() => creation(union([