securemark 0.235.2 → 0.237.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 (58) hide show
  1. package/CHANGELOG.md +12 -0
  2. package/dist/securemark.js +200 -112
  3. package/karma.conf.js +1 -1
  4. package/markdown.d.ts +11 -10
  5. package/package-lock.json +111 -98
  6. package/package.json +3 -3
  7. package/src/debug.test.ts +3 -1
  8. package/src/parser/api/bind.ts +7 -3
  9. package/src/parser/api/parse.test.ts +3 -3
  10. package/src/parser/api/parse.ts +8 -11
  11. package/src/parser/block/blockquote.test.ts +1 -1
  12. package/src/parser/block/codeblock.ts +1 -1
  13. package/src/parser/block/dlist.ts +1 -3
  14. package/src/parser/block/extension/aside.test.ts +1 -1
  15. package/src/parser/block/extension/aside.ts +2 -2
  16. package/src/parser/block/extension/example.test.ts +2 -2
  17. package/src/parser/block/extension/example.ts +2 -2
  18. package/src/parser/block/extension/fig.test.ts +22 -20
  19. package/src/parser/block/extension/figure.test.ts +33 -31
  20. package/src/parser/block/extension/figure.ts +32 -3
  21. package/src/parser/block/extension/message.ts +2 -2
  22. package/src/parser/block/extension/placeholder.ts +1 -1
  23. package/src/parser/block/extension/table.ts +5 -5
  24. package/src/parser/block/extension.ts +1 -1
  25. package/src/parser/block/heading.ts +1 -3
  26. package/src/parser/block/ilist.ts +1 -1
  27. package/src/parser/block/mathblock.ts +1 -1
  28. package/src/parser/block/olist.test.ts +8 -0
  29. package/src/parser/block/olist.ts +7 -7
  30. package/src/parser/block/paragraph.test.ts +1 -1
  31. package/src/parser/block/reply/cite.test.ts +4 -0
  32. package/src/parser/block/reply/cite.ts +1 -0
  33. package/src/parser/block/reply/quote.ts +1 -1
  34. package/src/parser/block/table.ts +1 -1
  35. package/src/parser/block/ulist.test.ts +8 -0
  36. package/src/parser/block/ulist.ts +7 -7
  37. package/src/parser/header.ts +1 -1
  38. package/src/parser/inline/deletion.ts +1 -1
  39. package/src/parser/inline/emphasis.ts +1 -1
  40. package/src/parser/inline/emstrong.ts +3 -3
  41. package/src/parser/inline/extension/indexee.ts +8 -8
  42. package/src/parser/inline/extension/placeholder.ts +1 -1
  43. package/src/parser/inline/html.ts +7 -7
  44. package/src/parser/inline/htmlentity.test.ts +1 -1
  45. package/src/parser/inline/htmlentity.ts +18 -11
  46. package/src/parser/inline/insertion.ts +1 -1
  47. package/src/parser/inline/link.ts +4 -4
  48. package/src/parser/inline/mark.ts +1 -1
  49. package/src/parser/inline/math.ts +1 -1
  50. package/src/parser/inline/media.ts +3 -3
  51. package/src/parser/inline/reference.ts +1 -1
  52. package/src/parser/inline/ruby.ts +2 -2
  53. package/src/parser/inline/strong.ts +1 -1
  54. package/src/parser/inline.ts +2 -0
  55. package/src/parser/processor/figure.test.ts +33 -29
  56. package/src/parser/processor/figure.ts +25 -3
  57. package/src/parser/processor/footnote.ts +3 -3
  58. package/src/parser/util.ts +1 -1
@@ -26,7 +26,7 @@ export const quote: ReplyParser.QuoteParser = lazy(() => creator(block(fmap(vali
26
26
  class: 'quote invalid',
27
27
  'data-invalid-syntax': 'quote',
28
28
  'data-invalid-type': 'syntax',
29
- 'data-invalid-description': `Missing the whitespace after "${ns[0].split(/[^>]/, 1)[0]}".`,
29
+ 'data-invalid-message': `Missing the whitespace after "${ns[0].split(/[^>]/, 1)[0]}"`,
30
30
  },
31
31
  defrag(ns)),
32
32
  html('br'),
@@ -31,7 +31,7 @@ const row = <P extends CellParser | AlignParser>(parser: P, optional: boolean):
31
31
  class: 'invalid',
32
32
  'data-invalid-syntax': 'tablerow',
33
33
  'data-invalid-type': 'syntax',
34
- 'data-invalid-description': 'Invalid table row.',
34
+ 'data-invalid-message': 'Invalid table row',
35
35
  }, [html('td', source.replace('\n', ''))])
36
36
  ], ''])));
37
37
 
@@ -66,6 +66,14 @@ describe('Unit: parser/block/ulist', () => {
66
66
  assert.deepStrictEqual(inspect(parser('- [X] 1')), [['<ul class="checklist"><li><span class="checkbox">☑</span>1</li></ul>'], '']);
67
67
  });
68
68
 
69
+ it('indexer', () => {
70
+ assert.deepStrictEqual(inspect(parser('- [#a]')), [['<ul><li><a class="index" href="#index:a">a</a></li></ul>'], '']);
71
+ assert.deepStrictEqual(inspect(parser('- a [#b]')), [['<ul><li id="index:b">a<span class="indexer" data-index="b"></span></li></ul>'], '']);
72
+ assert.deepStrictEqual(inspect(parser('- [ ] [#a]')), [['<ul class="checklist"><li><span class="checkbox">☐</span><a class="index" href="#index:a">a</a></li></ul>'], '']);
73
+ assert.deepStrictEqual(inspect(parser('- [ ] a [#b]')), [['<ul class="checklist"><li id="index:b"><span class="checkbox">☐</span>a<span class="indexer" data-index="b"></span></li></ul>'], '']);
74
+ assert.deepStrictEqual(inspect(parser('- a [#b]\n - c [#d]')), [['<ul><li id="index:b">a<span class="indexer" data-index="b"></span><ul><li id="index:d">c<span class="indexer" data-index="d"></span></li></ul></li></ul>'], '']);
75
+ });
76
+
69
77
  });
70
78
 
71
79
  });
@@ -2,7 +2,7 @@ import { UListParser } from '../block';
2
2
  import { union, inits, subsequence, some, block, line, validate, indent, focus, rewrite, context, creator, open, trim, trimStart, fallback, lazy, fmap } from '../../combinator';
3
3
  import { olist_ } from './olist';
4
4
  import { ilist_ } from './ilist';
5
- import { inline } from '../inline';
5
+ import { inline, indexer, indexee } from '../inline';
6
6
  import { html, defrag } from 'typed-dom';
7
7
  import { unshift } from 'spica/array';
8
8
  import { contentline } from '../source';
@@ -15,13 +15,13 @@ export const ulist: UListParser = lazy(() => block(validate(
15
15
  export const ulist_: UListParser = lazy(() => block(fmap(validate(
16
16
  /^-(?=$|\s)/,
17
17
  some(creator(union([
18
- fmap(fallback(
18
+ indexee(fmap(fallback(
19
19
  inits([
20
- line(open(/^-(?:$|\s)/, trim(subsequence([checkbox, trimStart(some(inline))])), true)),
20
+ line(open(/^-(?:$|\s)/, trim(subsequence([checkbox, trimStart(some(union([indexer, inline])))])), true)),
21
21
  indent(union([ulist_, olist_, ilist_])),
22
22
  ]),
23
- iitem),
24
- ns => [html('li', defrag(fillFirstLine(ns)))]),
23
+ invalid),
24
+ ns => [html('li', defrag(fillFirstLine(ns)))]), true),
25
25
  ])))),
26
26
  es => [format(html('ul', es))])));
27
27
 
@@ -31,12 +31,12 @@ export const checkbox = focus(
31
31
  html('span', { class: 'checkbox' }, source[1].trimStart() ? '☑' : '☐'),
32
32
  ], '']);
33
33
 
34
- const iitem = rewrite(contentline, source => [[
34
+ const invalid = rewrite(contentline, source => [[
35
35
  html('span', {
36
36
  class: 'invalid',
37
37
  'data-invalid-syntax': 'listitem',
38
38
  'data-invalid-type': 'syntax',
39
- 'data-invalid-description': 'Fix the indent or the head of the list item.',
39
+ 'data-invalid-message': 'Fix the indent or the head of the list item',
40
40
  }, source.replace('\n', ''))
41
41
  ], '']);
42
42
 
@@ -31,7 +31,7 @@ export const header: MarkdownParser.HeaderParser = lazy(() => validate(
31
31
  translate: 'no',
32
32
  'data-invalid-syntax': 'header',
33
33
  'data-invalid-type': 'syntax',
34
- 'data-invalid-description': 'Invalid syntax.',
34
+ 'data-invalid-message': 'Invalid syntax',
35
35
  }, normalize(source)),
36
36
  ], ''],
37
37
  ]))),
@@ -9,7 +9,7 @@ import { unshift } from 'spica/array';
9
9
  export const deletion: DeletionParser = lazy(() => creator(surround(
10
10
  str('~~'),
11
11
  some(union([
12
- some(inline, blank(/\n?/, /~~/)),
12
+ some(inline, blank(/\n?/, '~~')),
13
13
  open(/^\n?/, some(inline, '~'), true),
14
14
  ])),
15
15
  str('~~'), false,
@@ -11,7 +11,7 @@ export const emphasis: EmphasisParser = lazy(() => creator(surround(
11
11
  str('*'),
12
12
  startTight(some(union([
13
13
  strong,
14
- some(inline, blank('', /\*/)),
14
+ some(inline, blank('', '*')),
15
15
  open(some(inline, '*'), inline),
16
16
  ])), '*'),
17
17
  str('*'), false,
@@ -10,19 +10,19 @@ import { html, defrag } from 'typed-dom';
10
10
  import { unshift } from 'spica/array';
11
11
 
12
12
  const substrong: IntermediateParser<StrongParser> = lazy(() => some(union([
13
- some(inline, blank('', /\*\*/)),
13
+ some(inline, blank('', '**')),
14
14
  open(some(inline, '*'), inline),
15
15
  ])));
16
16
  const subemphasis: IntermediateParser<EmphasisParser> = lazy(() => some(union([
17
17
  strong,
18
- some(inline, blank('', /\*/)),
18
+ some(inline, blank('', '*')),
19
19
  open(some(inline, '*'), inline),
20
20
  ])));
21
21
 
22
22
  export const emstrong: EmStrongParser = lazy(() => creator(surround(
23
23
  str('***'),
24
24
  startTight(some(union([
25
- some(inline, blank('', /\*/)),
25
+ some(inline, blank('', '*')),
26
26
  open(some(inline, '*'), inline),
27
27
  ]))),
28
28
  str(/^\*{1,3}/), false,
@@ -4,9 +4,9 @@ import { Parser } from '../../../combinator/data/parser';
4
4
  import { fmap } from '../../../combinator';
5
5
  import { define } from 'typed-dom';
6
6
 
7
- export function indexee<P extends Parser<unknown, MarkdownParser.Context>>(parser: P): P;
8
- export function indexee(parser: Parser<HTMLElement, MarkdownParser.Context>): Parser<HTMLElement> {
9
- return fmap(parser, ([el], _, { id }) => [define(el, { id: id !== '' && identity(text(el)) || undefined })]);
7
+ export function indexee<P extends Parser<unknown, MarkdownParser.Context>>(parser: P, optional?: boolean): P;
8
+ export function indexee(parser: Parser<HTMLElement, MarkdownParser.Context>, optional?: boolean): Parser<HTMLElement> {
9
+ return fmap(parser, ([el], _, { id }) => [define(el, { id: id !== '' && identity(text(el, optional)) || undefined })]);
10
10
  }
11
11
 
12
12
  export function identity(text: string): string {
@@ -18,13 +18,13 @@ assert(identity('0'.repeat(100)).slice(6) === '0'.repeat(100));
18
18
  assert(identity('0'.repeat(101)).slice(6) === '0'.repeat(97) + '...');
19
19
  assert(identity('0'.repeat(200)).slice(6) === '0'.repeat(97) + '...');
20
20
 
21
- export function text(source: HTMLElement | DocumentFragment): string {
21
+ export function text(source: HTMLElement | DocumentFragment, optional = false): string {
22
22
  assert(source instanceof DocumentFragment || !source.matches('.indexer'));
23
- assert(source.querySelectorAll('.indexer').length <= 1);
24
- assert(source.querySelector('.indexer') === source.querySelector(':scope > .indexer'));
25
- assert(!source.querySelector('.annotation, br'));
26
- const indexer = source.querySelector('.indexer');
23
+ assert(source.querySelectorAll(':scope > .indexer').length <= 1);
24
+ const indexer = source.querySelector(':scope > .indexer');
27
25
  if (indexer) return indexer.getAttribute('data-index')!;
26
+ if (optional) return '';
27
+ assert(!source.querySelector('.annotation, br'));
28
28
  const target = source.cloneNode(true) as typeof source;
29
29
  for (
30
30
  let es = target.querySelectorAll('code[data-src], .math[data-src], .comment, rt, rp, .reference'),
@@ -19,7 +19,7 @@ export const placeholder: ExtensionParser.PlaceholderParser = lazy(() => creator
19
19
  class: 'invalid',
20
20
  'data-invalid-syntax': 'extension',
21
21
  'data-invalid-type': 'syntax',
22
- 'data-invalid-description': 'Invalid symbol.',
22
+ 'data-invalid-message': 'Invalid symbol',
23
23
  }, defrag(bs)),
24
24
  ], rest],
25
25
  ([as, bs], rest) => [unshift(as, bs), rest]))));
@@ -116,38 +116,38 @@ function elem(tag: string, as: string[], bs: (HTMLElement | string)[], cs: strin
116
116
  assert(as[0][0] === '<' && as[as.length - 1].slice(-1) === '>');
117
117
  assert(bs.length === defrag(bs).length);
118
118
  assert(cs.length === 1);
119
- if (!tags.includes(tag)) return invalid('tag', `Invalid HTML tag <${tag}>.`, as, bs, cs);
119
+ if (!tags.includes(tag)) return invalid('tag', `Invalid HTML tag <${tag}>`, as, bs, cs);
120
120
  switch (tag) {
121
121
  case 'sup':
122
122
  case 'sub':
123
123
  switch (true) {
124
124
  case context.state?.in?.supsub:
125
- return invalid('nest', `<${tag}> HTML tag cannot be used in <sup> or <sub> HTML tag.`, as, bs, cs);
125
+ return invalid('nest', `<${tag}> HTML tag cannot be used in <sup> or <sub> HTML tag`, as, bs, cs);
126
126
  }
127
127
  break;
128
128
  case 'small':
129
129
  switch (true) {
130
130
  case context.state?.in?.supsub:
131
131
  case context.state?.in?.small:
132
- return invalid('nest', `<${tag}> HTML tag cannot be used in <sup>, <sub>, or <small> HTML tag.`, as, bs, cs);
132
+ return invalid('nest', `<${tag}> HTML tag cannot be used in <sup>, <sub>, or <small> HTML tag`, as, bs, cs);
133
133
  }
134
134
  break;
135
135
  }
136
136
  let attrs: Record<string, string | undefined> | undefined;
137
137
  switch (true) {
138
138
  case 'data-invalid-syntax' in (attrs = attributes('html', [], attrspec[tag], as.slice(1, -1) as string[])):
139
- return invalid('attribute', 'Invalid HTML attribute.', as, bs, cs);
139
+ return invalid('attribute', 'Invalid HTML attribute', as, bs, cs);
140
140
  default:
141
141
  assert(attrs);
142
142
  return h(tag as 'span', attrs, bs);
143
143
  }
144
144
  }
145
- function invalid(type: string, description: string, as: (HTMLElement | string)[], bs: (HTMLElement | string)[], cs: (HTMLElement | string)[]): HTMLElement {
145
+ function invalid(type: string, message: string, as: (HTMLElement | string)[], bs: (HTMLElement | string)[], cs: (HTMLElement | string)[]): HTMLElement {
146
146
  return h('span', {
147
147
  class: 'invalid',
148
148
  'data-invalid-syntax': 'html',
149
149
  'data-invalid-type': type,
150
- 'data-invalid-description': description,
150
+ 'data-invalid-message': message,
151
151
  }, defrag(push(unshift(as, bs), cs)));
152
152
  }
153
153
 
@@ -187,7 +187,7 @@ export function attributes(
187
187
  attrs['class'] = join(classes, ' ');
188
188
  attrs['data-invalid-syntax'] = syntax;
189
189
  attrs['data-invalid-type'] = 'argument';
190
- attrs['data-invalid-description'] = 'Invalid argument.';
190
+ attrs['data-invalid-message'] = 'Invalid argument';
191
191
  }
192
192
  return attrs;
193
193
  }
@@ -14,7 +14,6 @@ describe('Unit: parser/inline/htmlentity', () => {
14
14
  assert.deepStrictEqual(inspect(parser('& ;')), undefined);
15
15
  assert.deepStrictEqual(inspect(parser('&\n;')), undefined);
16
16
  assert.deepStrictEqual(inspect(parser('&a;')), [['<span class="invalid">&amp;a;</span>'], '']);
17
- assert.deepStrictEqual(inspect(parser('&NewLine;')), undefined);
18
17
  assert.deepStrictEqual(inspect(parser('&#;')), undefined);
19
18
  assert.deepStrictEqual(inspect(parser('&#g;')), undefined);
20
19
  assert.deepStrictEqual(inspect(parser('&#x;')), undefined);
@@ -36,6 +35,7 @@ describe('Unit: parser/inline/htmlentity', () => {
36
35
  });
37
36
 
38
37
  it('entity', () => {
38
+ assert.deepStrictEqual(inspect(parser('&NewLine;')), [[' '], '']);
39
39
  assert.deepStrictEqual(inspect(parser('&nbsp;')), [['\u00A0'], '']);
40
40
  assert.deepStrictEqual(inspect(parser('&amp;')), [['&'], '']);
41
41
  assert.deepStrictEqual(inspect(parser('&copy;')), [['©'], '']);
@@ -1,24 +1,31 @@
1
+ import { undefined } from 'spica/global';
1
2
  import { HTMLEntityParser, UnsafeHTMLEntityParser } from '../inline';
2
3
  import { union, validate, focus, creator, fmap } from '../../combinator';
3
4
  import { html } from 'typed-dom';
5
+ import { reduce } from 'spica/memoize';
4
6
 
5
7
  export const unsafehtmlentity: UnsafeHTMLEntityParser = creator(validate('&', focus(
6
- /^&(?!NewLine;)[0-9A-Za-z]+;/,
7
- (parser => entity => (
8
- parser.innerHTML = entity,
9
- entity = parser.textContent!,
10
- [[`${entity[0] !== '&' || entity.length === 1 ? '' : '\0'}${entity}`], '']
11
- ))(html('b')))));
8
+ /^&[0-9A-Za-z]+;/,
9
+ entity => [[parse(entity) ?? `\0${entity}`], ''])));
12
10
 
13
11
  export const htmlentity: HTMLEntityParser = fmap(
14
12
  union([unsafehtmlentity]),
15
- ([str]) => [
16
- str[0] === '\0'
13
+ ([test]) => [
14
+ test[0] === '\0'
17
15
  ? html('span', {
18
16
  class: 'invalid',
19
17
  'data-invalid-syntax': 'htmlentity',
20
18
  'data-invalid-type': 'syntax',
21
- 'data-invalid-description': 'Invalid HTML entity.',
22
- }, str.slice(1))
23
- : str,
19
+ 'data-invalid-message': 'Invalid HTML entity',
20
+ }, test.slice(1))
21
+ : test,
24
22
  ]);
23
+
24
+ const parse = reduce((el => (entity: string): string | undefined => {
25
+ if (entity === '&NewLine;') return ' ';
26
+ el.innerHTML = entity;
27
+ const text = el.textContent!;
28
+ return entity === text
29
+ ? undefined
30
+ : text;
31
+ })(html('b')));
@@ -9,7 +9,7 @@ import { unshift } from 'spica/array';
9
9
  export const insertion: InsertionParser = lazy(() => creator(surround(
10
10
  str('++'),
11
11
  some(union([
12
- some(inline, blank(/\n?/, /\+\+/)),
12
+ some(inline, blank(/\n?/, '++')),
13
13
  open(/^\n?/, some(inline, '+'), true),
14
14
  ])),
15
15
  str('++'), false,
@@ -103,7 +103,7 @@ function elem(
103
103
  origin: string,
104
104
  ): HTMLAnchorElement {
105
105
  let type: string;
106
- let description: string;
106
+ let message: string;
107
107
  switch (uri.protocol) {
108
108
  case 'http:':
109
109
  case 'https:':
@@ -111,7 +111,7 @@ function elem(
111
111
  if (INSECURE_URI.slice(0, 2) === '^/' &&
112
112
  /\/\.\.?(?:\/|$)/.test(INSECURE_URI.slice(0, INSECURE_URI.search(/[?#]|$/)))) {
113
113
  type = 'argument';
114
- description = 'Dot-segments cannot be used in subresource paths.';
114
+ message = 'Dot-segments cannot be used in subresource paths';
115
115
  break;
116
116
  }
117
117
  return html('a',
@@ -140,7 +140,7 @@ function elem(
140
140
  return html('a', { href: uri.source }, content);
141
141
  }
142
142
  type = 'content';
143
- description = 'Invalid phone number.';
143
+ message = 'Invalid phone number';
144
144
  break;
145
145
  }
146
146
  return html('a',
@@ -148,7 +148,7 @@ function elem(
148
148
  class: 'invalid',
149
149
  'data-invalid-syntax': 'link',
150
150
  'data-invalid-type': type ??= 'argument',
151
- 'data-invalid-description': description ??= 'Invalid protocol.',
151
+ 'data-invalid-message': message ??= 'Invalid protocol',
152
152
  },
153
153
  content.length === 0
154
154
  ? INSECURE_URI
@@ -9,7 +9,7 @@ import { unshift } from 'spica/array';
9
9
  export const mark: MarkParser = lazy(() => creator(surround(
10
10
  str('=='),
11
11
  startTight(some(union([
12
- some(inline, blank('', /==/)),
12
+ some(inline, blank('', '==')),
13
13
  open(some(inline, '='), inline),
14
14
  ]))),
15
15
  str('=='), false,
@@ -29,7 +29,7 @@ export const math: MathParser = lazy(() => creator(validate('$', rewrite(
29
29
  translate: 'no',
30
30
  'data-invalid-syntax': 'math',
31
31
  'data-invalid-type': 'content',
32
- 'data-invalid-description': `"${source.match(disallowedCommand)![0]}" command is disallowed.`,
32
+ 'data-invalid-message': `"${source.match(disallowedCommand)![0]}" command is disallowed`,
33
33
  },
34
34
  source)
35
35
  ], '']))));
@@ -81,7 +81,7 @@ function sanitize(target: HTMLElement, uri: ReadonlyURL, alt: string): boolean {
81
81
  class: void target.classList.add('invalid'),
82
82
  'data-invalid-syntax': 'media',
83
83
  'data-invalid-type': 'argument',
84
- 'data-invalid-description': 'Dot-segments cannot be used in media paths; use subresource paths instead.',
84
+ 'data-invalid-message': 'Dot-segments cannot be used in media paths; use subresource paths instead',
85
85
  });
86
86
  return false;
87
87
  }
@@ -91,7 +91,7 @@ function sanitize(target: HTMLElement, uri: ReadonlyURL, alt: string): boolean {
91
91
  class: void target.classList.add('invalid'),
92
92
  'data-invalid-syntax': 'media',
93
93
  'data-invalid-type': 'argument',
94
- 'data-invalid-description': 'Invalid protocol.',
94
+ 'data-invalid-message': 'Invalid protocol',
95
95
  });
96
96
  return false;
97
97
  }
@@ -100,7 +100,7 @@ function sanitize(target: HTMLElement, uri: ReadonlyURL, alt: string): boolean {
100
100
  class: void target.classList.add('invalid'),
101
101
  'data-invalid-syntax': 'media',
102
102
  'data-invalid-type': 'content',
103
- 'data-invalid-description': `Cannot use invalid HTML entitiy "${alt.match(/&[0-9A-Za-z]+;/)![0]}".`,
103
+ 'data-invalid-message': `Cannot use invalid HTML entitiy "${alt.match(/&[0-9A-Za-z]+;/)![0]}"`,
104
104
  alt: target.getAttribute('alt')?.replace(/\0/g, ''),
105
105
  });
106
106
  return false;
@@ -46,7 +46,7 @@ function attributes(ns: (string | HTMLElement)[]): Record<string, string | undef
46
46
  class: 'invalid',
47
47
  'data-invalid-syntax': 'reference',
48
48
  'data-invalid-type': 'syntax',
49
- 'data-invalid-description': 'Invalid abbr.',
49
+ 'data-invalid-message': 'Invalid abbr',
50
50
  }
51
51
  : { class: 'reference' };
52
52
  }
@@ -83,13 +83,13 @@ function attributes(texts: string[], rubies: string[]): Record<string, string> {
83
83
  let attrs: Record<string, string> | undefined;
84
84
  for (const ss of [texts, rubies]) {
85
85
  for (let i = 0; i < ss.length; ++i) {
86
- if (!ss[i].includes('\0')) continue;
86
+ if (ss[i].indexOf('\0') === -1) continue;
87
87
  ss[i] = ss[i].replace(/\0/g, '');
88
88
  attrs ??= {
89
89
  class: 'invalid',
90
90
  'data-invalid-syntax': 'ruby',
91
91
  'data-invalid-type': ss === texts ? 'content' : 'argument',
92
- 'data-invalid-description': 'Invalid HTML entity.',
92
+ 'data-invalid-message': 'Invalid HTML entity',
93
93
  };
94
94
  }
95
95
  }
@@ -9,7 +9,7 @@ import { unshift } from 'spica/array';
9
9
  export const strong: StrongParser = lazy(() => creator(surround(
10
10
  str('**'),
11
11
  startTight(some(union([
12
- some(inline, blank('', /\*\*/)),
12
+ some(inline, blank('', '**')),
13
13
  open(some(inline, '*'), inline),
14
14
  ])), '*'),
15
15
  str('**'), false,
@@ -75,5 +75,7 @@ export const inline: InlineParser = union([
75
75
  text
76
76
  ]);
77
77
 
78
+ export { indexee } from './inline/extension/indexee';
79
+ export { indexer } from './inline/extension/indexer';
78
80
  export { media } from './inline/media';
79
81
  export { shortmedia } from './inline/shortmedia';