securemark 0.297.7 → 0.298.1

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 (74) hide show
  1. package/CHANGELOG.md +8 -0
  2. package/dist/index.js +140 -288
  3. package/package.json +1 -1
  4. package/src/combinator/control/constraint/block.test.ts +4 -4
  5. package/src/combinator/control/constraint/block.ts +1 -1
  6. package/src/combinator/control/constraint/line.test.ts +5 -5
  7. package/src/combinator/control/constraint/line.ts +1 -1
  8. package/src/combinator/control/manipulation/convert.ts +1 -1
  9. package/src/combinator/control/manipulation/fence.ts +1 -1
  10. package/src/combinator/control/manipulation/indent.test.ts +1 -1
  11. package/src/combinator/control/manipulation/indent.ts +1 -1
  12. package/src/combinator/control/manipulation/match.ts +1 -1
  13. package/src/combinator/control/manipulation/recovery.ts +1 -1
  14. package/src/combinator/control/manipulation/scope.ts +6 -8
  15. package/src/combinator/control/manipulation/surround.ts +1 -1
  16. package/src/combinator/control/monad/bind.ts +1 -1
  17. package/src/combinator/data/delimiter.ts +5 -5
  18. package/src/combinator/data/parser/context.test.ts +2 -2
  19. package/src/combinator/data/parser/context.ts +10 -10
  20. package/src/combinator/data/parser/inits.ts +1 -1
  21. package/src/combinator/data/parser/sequence.test.ts +2 -2
  22. package/src/combinator/data/parser/sequence.ts +1 -1
  23. package/src/combinator/data/parser/some.test.ts +2 -2
  24. package/src/combinator/data/parser/some.ts +1 -1
  25. package/src/combinator/data/parser/subsequence.test.ts +3 -3
  26. package/src/combinator/data/parser/union.test.ts +2 -2
  27. package/src/combinator/data/parser.ts +10 -16
  28. package/src/debug.test.ts +3 -3
  29. package/src/parser/api/header.ts +1 -1
  30. package/src/parser/api/parse.test.ts +3 -2
  31. package/src/parser/api/parse.ts +2 -0
  32. package/src/parser/block/blockquote.test.ts +5 -5
  33. package/src/parser/block/blockquote.ts +4 -3
  34. package/src/parser/block/extension/aside.test.ts +3 -3
  35. package/src/parser/block/extension/aside.ts +3 -3
  36. package/src/parser/block/extension/example.test.ts +5 -5
  37. package/src/parser/block/extension/example.ts +3 -3
  38. package/src/parser/block/extension/fig.ts +1 -1
  39. package/src/parser/block/heading.ts +1 -1
  40. package/src/parser/block/ilist.ts +2 -2
  41. package/src/parser/block/mediablock.ts +1 -1
  42. package/src/parser/block/olist.ts +2 -2
  43. package/src/parser/block/reply/cite.ts +3 -3
  44. package/src/parser/block/table.ts +3 -3
  45. package/src/parser/block/ulist.ts +1 -1
  46. package/src/parser/block.ts +2 -2
  47. package/src/parser/context.ts +6 -3
  48. package/src/parser/header.ts +3 -3
  49. package/src/parser/inline/annotation.ts +1 -1
  50. package/src/parser/inline/autolink/url.test.ts +1 -1
  51. package/src/parser/inline/autolink/url.ts +2 -2
  52. package/src/parser/inline/autolink.ts +1 -1
  53. package/src/parser/inline/bracket.ts +2 -2
  54. package/src/parser/inline/emstrong.ts +4 -4
  55. package/src/parser/inline/extension/indexee.ts +17 -9
  56. package/src/parser/inline/math.ts +1 -1
  57. package/src/parser/inline/reference.ts +1 -1
  58. package/src/parser/inline/remark.ts +1 -1
  59. package/src/parser/inline/ruby.ts +1 -1
  60. package/src/parser/inline.ts +1 -1
  61. package/src/parser/processor/figure.test.ts +27 -27
  62. package/src/parser/processor/figure.ts +10 -4
  63. package/src/parser/processor/note.test.ts +17 -16
  64. package/src/parser/processor/note.ts +11 -5
  65. package/src/parser/segment.ts +2 -2
  66. package/src/parser/source/escapable.ts +1 -1
  67. package/src/parser/source/line.ts +4 -4
  68. package/src/parser/source/str.ts +1 -1
  69. package/src/parser/source/text.ts +1 -1
  70. package/src/parser/source/unescapable.ts +1 -1
  71. package/src/parser/util.ts +6 -1
  72. package/src/parser/visibility.ts +1 -1
  73. package/src/util/quote.ts +1 -1
  74. package/src/util/toc.ts +1 -1
@@ -16,9 +16,9 @@ describe('Unit: parser/block/extension/aside', () => {
16
16
  });
17
17
 
18
18
  it('valid', () => {
19
- assert.deepStrictEqual(inspect(parser, input('~~~aside\n# 0\n~~~', new Context())), [['<aside id="index::0" class="aside"><h1>0</h1><h2>References</h2><ol class="references"></ol></aside>'], '']);
20
- assert.deepStrictEqual(inspect(parser, input('~~~aside\n## 0\n~~~', new Context())), [['<aside id="index::0" class="aside"><h2>0</h2><h2>References</h2><ol class="references"></ol></aside>'], '']);
21
- assert.deepStrictEqual(inspect(parser, input('~~~aside\n# 0\n\n$-0.0\n\n## 1\n\n$test-a\n> \n~~~', new Context())), [['<aside id="index::0" class="aside"><h1>0</h1><figure data-label="$-0.0" data-group="$" hidden="" data-number="0.0"></figure><h2>1</h2><figure data-type="quote" data-label="test-a" data-group="test" data-number="1.1"><figcaption><span class="figindex">Test 1.1. </span><span class="figtext"></span></figcaption><div><blockquote></blockquote></div></figure><h2>References</h2><ol class="references"></ol></aside>'], '']);
19
+ assert.deepStrictEqual(inspect(parser, input('~~~aside\n# 0\n~~~', new Context())), [['<aside id="index::0" class="aside"><h1 id="index:random:0" class="local">0</h1><h2>References</h2><ol class="references"></ol></aside>'], '']);
20
+ assert.deepStrictEqual(inspect(parser, input('~~~aside\n## 0\n~~~', new Context())), [['<aside id="index::0" class="aside"><h2 id="index:random:0" class="local">0</h2><h2>References</h2><ol class="references"></ol></aside>'], '']);
21
+ assert.deepStrictEqual(inspect(parser, input('~~~aside\n# 0\n\n$-0.0\n\n## 1\n\n$test-a\n> \n~~~', new Context())), [['<aside id="index::0" class="aside"><h1 id="index:random:0" class="local">0</h1><figure data-label="$-0.0" data-group="$" hidden="" data-number="0.0"></figure><h2 id="index:random:1" class="local">1</h2><figure data-type="quote" data-label="test-a" data-group="test" data-number="1.1" id="label:random:test-a"><figcaption><span class="figindex">Test 1.1. </span><span class="figtext"></span></figcaption><div><blockquote></blockquote></div></figure><h2>References</h2><ol class="references"></ol></aside>'], '']);
22
22
  });
23
23
 
24
24
  });
@@ -3,7 +3,7 @@ import { Recursion } from '../../context';
3
3
  import { List, Node } from '../../../combinator/data/parser';
4
4
  import { recursion, block, fence, fmap } from '../../../combinator';
5
5
  import { identity } from '../../inline/extension/indexee';
6
- import { unwrap, invalid } from '../../util';
6
+ import { unwrap, invalid, randomID } from '../../util';
7
7
  import { parse } from '../../api/parse';
8
8
  import { html } from 'typed-dom/dom';
9
9
 
@@ -26,12 +26,12 @@ export const aside: ExtensionParser.AsideParser = block(recursion(Recursion.bloc
26
26
  ]);
27
27
  const references = html('ol', { class: 'references' });
28
28
  const document = parse(body.slice(0, -1), {
29
- id: '',
29
+ local: true,
30
+ id: context.id === '' ? '' : randomID(),
30
31
  notes: {
31
32
  references,
32
33
  },
33
34
  }, context);
34
- assert(!document.querySelector('[id]'));
35
35
  const heading = 'H1 H2 H3 H4 H5 H6'.split(' ').includes(document.firstElementChild?.tagName!) && document.firstElementChild as HTMLHeadingElement;
36
36
  if (!heading) return new List([
37
37
  new Node(html('pre', {
@@ -21,11 +21,11 @@ describe('Unit: parser/block/extension/example', () => {
21
21
  assert.deepStrictEqual(inspect(parser, input('~~~example/markdown\n\n~~~', new Context())), [['<aside class="example" data-type="markdown"><pre translate="no"></pre><hr><section><h2>References</h2><ol class="references"></ol></section></aside>'], '']);
22
22
  assert.deepStrictEqual(inspect(parser, input('~~~example/markdown\na\n~~~', new Context())), [['<aside class="example" data-type="markdown"><pre translate="no">a</pre><hr><section><p>a</p><h2>References</h2><ol class="references"></ol></section></aside>'], '']);
23
23
  assert.deepStrictEqual(inspect(parser, input('~~~example/markdown\n++a\nb++\n~~~', new Context())), [['<aside class="example" data-type="markdown"><pre translate="no">++a\nb++</pre><hr><section><p><ins>a<br>b</ins></p><h2>References</h2><ol class="references"></ol></section></aside>'], '']);
24
- assert.deepStrictEqual(inspect(parser, input('~~~example/markdown\n$fig-a\n!https://host\n~~~', new Context())), [['<aside class="example" data-type="markdown"><pre translate="no">$fig-a\n!https://host</pre><hr><section><figure data-type="media" data-label="fig-a" data-group="fig" data-number="1"><figcaption><span class="figindex">Fig. 1. </span><span class="figtext"></span></figcaption><div><a href="https://host" target="_blank"><img class="media" data-src="https://host" alt="https://host"></a></div></figure><h2>References</h2><ol class="references"></ol></section></aside>'], '']);
25
- assert.deepStrictEqual(inspect(parser, input('~~~example/markdown\n[$fig-a]\n!https://host\n~~~', new Context())), [['<aside class="example" data-type="markdown"><pre translate="no">[$fig-a]\n!https://host</pre><hr><section><figure data-type="media" data-label="fig-a" data-group="fig" data-number="1"><figcaption><span class="figindex">Fig. 1. </span><span class="figtext"></span></figcaption><div><a href="https://host" target="_blank"><img class="media" data-src="https://host" alt="https://host"></a></div></figure><h2>References</h2><ol class="references"></ol></section></aside>'], '']);
26
- assert.deepStrictEqual(inspect(parser, input('~~~example/markdown\n## a\n~~~', new Context())), [['<aside class="example" data-type="markdown"><pre translate="no">## a</pre><hr><section><h2>a</h2><h2>References</h2><ol class="references"></ol></section></aside>'], '']);
27
- assert.deepStrictEqual(inspect(parser, input('~~~example/markdown\n~ a\n~~~', new Context())), [['<aside class="example" data-type="markdown"><pre translate="no">~ a</pre><hr><section><dl><dt>a</dt><dd></dd></dl><h2>References</h2><ol class="references"></ol></section></aside>'], '']);
28
- assert.deepStrictEqual(inspect(parser, input('~~~example/markdown\n((a))[[b]]\n~~~', new Context())), [['<aside class="example" data-type="markdown"><pre translate="no">((a))[[b]]</pre><hr><section><p><sup class="annotation disabled" title="a"><a>*1</a></sup><sup class="reference disabled" title="b"><a>[1]</a></sup></p><ol class="annotations"><li data-marker="*1"><span>a</span><sup><a>^1</a></sup></li></ol><h2>References</h2><ol class="references"><li><span>b</span><sup><a>^1</a></sup></li></ol></section></aside>'], '']);
24
+ assert.deepStrictEqual(inspect(parser, input('~~~example/markdown\n$fig-a\n!https://host\n~~~', new Context())), [['<aside class="example" data-type="markdown"><pre translate="no">$fig-a\n!https://host</pre><hr><section><figure data-type="media" data-label="fig-a" data-group="fig" data-number="1" id="label:random:fig-a"><figcaption><span class="figindex">Fig. 1. </span><span class="figtext"></span></figcaption><div><a href="https://host" target="_blank"><img class="media" data-src="https://host" alt="https://host"></a></div></figure><h2>References</h2><ol class="references"></ol></section></aside>'], '']);
25
+ assert.deepStrictEqual(inspect(parser, input('~~~example/markdown\n[$fig-a]\n!https://host\n~~~', new Context())), [['<aside class="example" data-type="markdown"><pre translate="no">[$fig-a]\n!https://host</pre><hr><section><figure data-type="media" data-label="fig-a" data-group="fig" data-number="1" id="label:random:fig-a"><figcaption><span class="figindex">Fig. 1. </span><span class="figtext"></span></figcaption><div><a href="https://host" target="_blank"><img class="media" data-src="https://host" alt="https://host"></a></div></figure><h2>References</h2><ol class="references"></ol></section></aside>'], '']);
26
+ assert.deepStrictEqual(inspect(parser, input('~~~example/markdown\n## a\n~~~', new Context())), [['<aside class="example" data-type="markdown"><pre translate="no">## a</pre><hr><section><h2 id="index:random:a" class="local">a</h2><h2>References</h2><ol class="references"></ol></section></aside>'], '']);
27
+ assert.deepStrictEqual(inspect(parser, input('~~~example/markdown\n~ a\n~~~', new Context())), [['<aside class="example" data-type="markdown"><pre translate="no">~ a</pre><hr><section><dl><dt id="index:random:a" class="local">a</dt><dd></dd></dl><h2>References</h2><ol class="references"></ol></section></aside>'], '']);
28
+ assert.deepStrictEqual(inspect(parser, input('~~~example/markdown\n((a))[[b]]\n~~~', new Context())), [['<aside class="example" data-type="markdown"><pre translate="no">((a))[[b]]</pre><hr><section><p><sup class="annotation local" id="annotation:random:ref:a:1" title="a"><a href="#annotation:random:def:a:1">*1</a></sup><sup class="reference local" id="reference:random:ref:b:1" title="b"><a href="#reference:random:def:b">[1]</a></sup></p><ol class="annotations"><li id="annotation:random:def:a:1" data-marker="*1"><span>a</span><sup><a href="#annotation:random:ref:a:1">^1</a></sup></li></ol><h2>References</h2><ol class="references"><li id="reference:random:def:b"><span>b</span><sup><a href="#reference:random:ref:b:1">^1</a></sup></li></ol></section></aside>'], '']);
29
29
  assert.deepStrictEqual(inspect(parser, input('~~~~example/markdown\na\n~~~~', new Context())), [['<aside class="example" data-type="markdown"><pre translate="no">a</pre><hr><section><p>a</p><h2>References</h2><ol class="references"></ol></section></aside>'], '']);
30
30
  assert.deepStrictEqual(inspect(parser, input('~~~example/math\na\n~~~', new Context())), [['<aside class="example" data-type="math"><pre translate="no">a</pre><hr><div class="math" translate="no">$$\na\n$$</div></aside>'], '']);
31
31
  assert.deepStrictEqual(inspect(parser, input(`~~~example/math\n0${'\n'.repeat(100)}~~~`, new Context()), '>'), [['<aside class="example" data-type="math">'], '']);
@@ -3,7 +3,7 @@ import { Recursion } from '../../context';
3
3
  import { List, Node, subinput } from '../../../combinator/data/parser';
4
4
  import { recursion, block, fence, fmap } from '../../../combinator';
5
5
  import { mathblock } from '../mathblock';
6
- import { unwrap, invalid } from '../../util';
6
+ import { unwrap, invalid, randomID } from '../../util';
7
7
  import { parse } from '../../api/parse';
8
8
  import { html } from 'typed-dom/dom';
9
9
 
@@ -28,12 +28,12 @@ export const example: ExtensionParser.ExampleParser = block(recursion(Recursion.
28
28
  case 'markdown': {
29
29
  const references = html('ol', { class: 'references' });
30
30
  const document = parse(body.slice(0, -1), {
31
- id: '',
31
+ local: true,
32
+ id: context.id === '' ? '' : randomID(),
32
33
  notes: {
33
34
  references,
34
35
  },
35
36
  }, context);
36
- assert(!document.querySelector('[id]'));
37
37
  return new List([
38
38
  new Node(html('aside', { class: 'example', 'data-type': 'markdown' }, [
39
39
  html('pre', { translate: 'no' }, body.slice(0, -1)),
@@ -32,7 +32,7 @@ export const fig: FigParser = block(rewrite(segment, verify(convert(
32
32
  const fence = (/^[^\n]*\n!?>+ /.test(source) && source.match(/^~{3,}(?=[^\S\n]*$)/gm) as string[] || [])
33
33
  .reduce((max, fence) => fence > max ? fence : max, '~~') + '~';
34
34
  const { position } = context;
35
- const result = parser({ context });
35
+ const result = parser(context);
36
36
  context.position = position;
37
37
  context.segment = Segment.figure | Segment.write;
38
38
  return result
@@ -11,7 +11,7 @@ import { html, defrag } from 'typed-dom/dom';
11
11
  export const segment: HeadingParser.SegmentParser = block(focus(
12
12
  /#+ +\S[^\n]*(?:\n#+(?=$|[ \n])[^\n]*)*(?:$|\n)/y,
13
13
  input => {
14
- const { context } = input;
14
+ const context = input;
15
15
  const { source, range } = context;
16
16
  const acc = new List<Node<string>>();
17
17
  for (const len = context.position + range; context.position < len;) {
@@ -34,8 +34,8 @@ export const ilist_: IListParser = lazy(() => block(fmap(validate(
34
34
  ]))));
35
35
 
36
36
  export const ilistitem = rewrite(
37
- inits([contentline, indent<Parser<string>>(({ context: { source } }) => new List([new Node(source)]))]),
38
- ({ context: { source } }) => new List([
37
+ inits([contentline, indent<Parser<string>>(({ source }) => new List([new Node(source)]))]),
38
+ ({ source }) => new List([
39
39
  new Node(''),
40
40
  new Node(html('span', {
41
41
  class: 'invalid',
@@ -16,7 +16,7 @@ export const mediablock: MediaBlockParser = block(fmap(
16
16
  medialink,
17
17
  media,
18
18
  lineshortmedia,
19
- ]), ({ context: { source } }) => new List([
19
+ ]), ({ source }) => new List([
20
20
  new Node(html('span', {
21
21
  class: 'invalid',
22
22
  ...invalid('mediablock', 'syntax', 'Not media syntax'),
@@ -53,12 +53,12 @@ const list = (type: string, form: string): OListParser.ListParser => fmap(
53
53
  const heads = {
54
54
  '.': focus(
55
55
  openers['.'],
56
- ({ context: { source } }) => new List([
56
+ ({ source }) => new List([
57
57
  new Node(source.trimEnd().split('.', 1)[0] + '.')
58
58
  ])),
59
59
  '(': focus(
60
60
  openers['('],
61
- ({ context: { source } }) => new List([
61
+ ({ source }) => new List([
62
62
  new Node(source.trimEnd().replace(/^\($/, '(1)').replace(/^\((\w+)$/, '($1)'))
63
63
  ])),
64
64
  } as const;
@@ -16,9 +16,9 @@ export const cite: ReplyParser.CiteParser = line(fmap(
16
16
  line(anchor),
17
17
  // Subject page representation.
18
18
  // リンクの実装は後で検討
19
- focus(/>>#\S*(?=\s*$)/y, ({ context: { source } }) => new List([new Node(html('a', { class: 'anchor' }, source))])),
20
- focus(/>>https?:\/\/\S+(?=\s*$)/y, ({ context: { source } }) => new List([new Node(html('a', { class: 'anchor', href: source.slice(2).trimEnd(), target: '_blank' }, source))])),
21
- focus(/>>\S+(?=\s*$)/y, ({ context: { source } }) => new List([new Node(source)])),
19
+ focus(/>>#\S*(?=\s*$)/y, ({ source }) => new List([new Node(html('a', { class: 'anchor' }, source))])),
20
+ focus(/>>https?:\/\/\S+(?=\s*$)/y, ({ source }) => new List([new Node(html('a', { class: 'anchor', href: source.slice(2).trimEnd(), target: '_blank' }, source))])),
21
+ focus(/>>\S+(?=\s*$)/y, ({ source }) => new List([new Node(source)])),
22
22
  ])),
23
23
  nodes => {
24
24
  const quotes = nodes.head!.value as string;
@@ -30,7 +30,7 @@ export const table: TableParser = lazy(() => block(fmap(validate(
30
30
  const row = <P extends CellParser | AlignParser>(parser: P, optional: boolean): RowParser<P> => fallback(fmap(
31
31
  line(surround(/(?=\|)/y, some(union([parser])), /\|?\s*$/y, optional)),
32
32
  ns => new List([new Node(html('tr', unwrap(ns)))])),
33
- rewrite(contentline, ({ context: { source } }) => new List([
33
+ rewrite(contentline, ({ source }) => new List([
34
34
  new Node(html('tr', {
35
35
  class: 'invalid',
36
36
  ...invalid('table-row', 'syntax', 'Missing the start symbol of the table row'),
@@ -40,9 +40,9 @@ const row = <P extends CellParser | AlignParser>(parser: P, optional: boolean):
40
40
  const align: AlignParser = fmap(open(
41
41
  '|',
42
42
  union([
43
- focus(/:-+:?/y, ({ context: { source, position, range } }) =>
43
+ focus(/:-+:?/y, ({ source, position, range }) =>
44
44
  new List([new Node(source[position + range - 1] === ':' ? 'center' : 'start')]), false),
45
- focus(/-+:?/y, ({ context: { source, position, range } }) =>
45
+ focus(/-+:?/y, ({ source, position, range }) =>
46
46
  new List([new Node(source[position + range - 1] === ':' ? 'end' : '')]), false),
47
47
  ])),
48
48
  ns => new List([new Node(html('td', defrag(unwrap(ns))))]));
@@ -31,7 +31,7 @@ export const ulist_: UListParser = lazy(() => block(fmap(validate(
31
31
 
32
32
  export const checkbox = focus(
33
33
  /\[[xX ]\](?=$|[ \n])/y,
34
- ({ context: { source, position } }) => new List([
34
+ ({ source, position }) => new List([
35
35
  new Node(html('span', { class: 'checkbox' }, source[position + 1].trimStart() ? '☑' : '☐')),
36
36
  ]), false);
37
37
 
@@ -63,7 +63,7 @@ export const block: BlockParser = reset(
63
63
  error(union([
64
64
  emptysegment,
65
65
  input => {
66
- const { context: { source, position, segment } } = input;
66
+ const { source, position, segment } = input;
67
67
  if (position === source.length) return;
68
68
  switch (segment ^ Segment.write) {
69
69
  case Segment.heading:
@@ -127,7 +127,7 @@ function error(parser: BlockParser): BlockParser {
127
127
  const reg = new RegExp(String.raw`^${Command.Error}[^\n]*\n`)
128
128
  return recover<BlockParser>(
129
129
  parser,
130
- ({ context: { source, position, id } }, reason) => new List([
130
+ ({ source, position, id }, reason) => new List([
131
131
  new Node(html('h1',
132
132
  {
133
133
  id: id !== '' ? `error:${rnd0Z(8)}` : undefined,
@@ -8,8 +8,9 @@ export class Context extends Ctx {
8
8
  super(options);
9
9
  const {
10
10
  segment,
11
- buffer,
11
+ local,
12
12
  sequential,
13
+ buffer,
13
14
  header,
14
15
  host,
15
16
  url,
@@ -17,8 +18,9 @@ export class Context extends Ctx {
17
18
  caches,
18
19
  } = options;
19
20
  this.segment = segment ?? Segment.unknown;
20
- this.buffer = buffer ?? new List();
21
+ this.local = local ?? false;
21
22
  this.sequential = sequential ?? false;
23
+ this.buffer = buffer ?? new List();
22
24
  this.header = header ?? true;
23
25
  this.host = host;
24
26
  this.url = url;
@@ -26,8 +28,9 @@ export class Context extends Ctx {
26
28
  this.caches = caches;
27
29
  }
28
30
  public override segment: Segment;
29
- public buffer: List<Node<(string | HTMLElement)>>;
31
+ public local: boolean;
30
32
  public sequential: boolean;
33
+ public buffer: List<Node<(string | HTMLElement)>>;
31
34
  public recursion = new RecursionCounter('annotation', 2);
32
35
  public readonly header: boolean;
33
36
  public readonly host?: URL;
@@ -11,7 +11,7 @@ export const header: MarkdownParser.HeaderParser = lazy(() => validate(
11
11
  inits([
12
12
  block(
13
13
  union([
14
- validate(({ context }) => context.header,
14
+ validate(context => context.header,
15
15
  focus(/(---+)[^\S\n]*\n(?:[a-z][0-9a-z]*(?:-[0-9a-z]+)*:[ \t]+\S[^\n]*\n){1,100}\1[^\S\n]*(?:$|\n)/yi,
16
16
  convert(source =>
17
17
  normalize(source.slice(source.indexOf('\n') + 1, source.trimEnd().lastIndexOf('\n'))),
@@ -24,7 +24,7 @@ export const header: MarkdownParser.HeaderParser = lazy(() => validate(
24
24
  defrag(unwrap(ns.unshift(new Node(html('summary', 'Header'))) && ns))),
25
25
  ])),
26
26
  ]))))),
27
- ({ context }) => {
27
+ context => {
28
28
  const { source, position } = context;
29
29
  context.position += source.length;
30
30
  return new List([
@@ -39,7 +39,7 @@ export const header: MarkdownParser.HeaderParser = lazy(() => validate(
39
39
  clear(str(/[^\S\n]*\n/y)),
40
40
  ])));
41
41
 
42
- const field: MarkdownParser.HeaderParser.FieldParser = line(({ context: { source, position } }) => {
42
+ const field: MarkdownParser.HeaderParser.FieldParser = line(({ source, position }) => {
43
43
  const name = source.slice(position, source.indexOf(':', position));
44
44
  const value = source.slice(position + name.length + 1).trim();
45
45
  return new List([
@@ -82,7 +82,7 @@ export const annotation: AnnotationParser = lazy(() => constraint(State.annotati
82
82
  ? new List([new Node(html('span', { class: 'paren' }, defrag(unwrap(bs))))])
83
83
  : new List([new Node(html('span', { class: 'bracket' }, defrag(unwrap(bs))))]);
84
84
  bs.unshift(new Node('('));
85
- const cs = parser({ context });
85
+ const cs = parser(context);
86
86
  if (source[context.position] === ')') {
87
87
  cs && bs.import(cs);
88
88
  bs.push(new Node(')'));
@@ -6,7 +6,7 @@ import { inspect } from '../../../debug.test';
6
6
 
7
7
  describe('Unit: parser/inline/autolink/url', () => {
8
8
  describe('url', () => {
9
- const parser = (input: Input<Context>) => some(autolink)((++input.context.position, input));
9
+ const parser = (input: Input<Context>) => some(autolink)((++input.position, input));
10
10
 
11
11
  it('invalid', () => {
12
12
  assert.deepStrictEqual(inspect(parser, input('', new Context())), undefined);
@@ -16,7 +16,7 @@ export const url: AutolinkParser.UrlParser = lazy(() => rewrite(
16
16
  false,
17
17
  [3 | Backtrack.unescapable]),
18
18
  union([
19
- constraint(State.autolink, state(State.autolink, ({ context }) =>
19
+ constraint(State.autolink, state(State.autolink, context =>
20
20
  new List([new Node(parse(new List(), new List([new Node(context.source)]), context))]))),
21
21
  open(str(/[^:]+/y), some(inline)),
22
22
  ])));
@@ -26,7 +26,7 @@ export const lineurl: AutolinkParser.UrlParser.LineUrlParser = lazy(() => focus(
26
26
  tails([
27
27
  str('!'),
28
28
  union([
29
- constraint(State.autolink, state(State.autolink, ({ context }) => {
29
+ constraint(State.autolink, state(State.autolink, context => {
30
30
  const { source, position } = context;
31
31
  context.position -= source[0] === '!' ? 1 : 0;
32
32
  return new List([
@@ -12,7 +12,7 @@ import { isAlphanumeric } from '../source/text';
12
12
  export const autolink: AutolinkParser = lazy(() =>
13
13
  state(~State.autolink,
14
14
  input => {
15
- const { context: { source, position } } = input;
15
+ const { source, position } = input;
16
16
  if (position === source.length) return;
17
17
  const fst = source[position];
18
18
  switch (fst) {
@@ -14,7 +14,7 @@ const indexF = new RegExp(indexA.source.replace(', ', '[,、]')
14
14
 
15
15
  export const bracket: BracketParser = lazy(() => union([
16
16
  input => {
17
- const { context: { source, position } } = input;
17
+ const { source, position } = input;
18
18
  switch (source[position]) {
19
19
  case '(':
20
20
  return p1(input);
@@ -92,7 +92,7 @@ const s1 = lazy(() => surround(
92
92
  setBacktrack(context, 2 | Backtrack.link, head);
93
93
  }
94
94
  else {
95
- if (!isBacktrack(context, 1 | Backtrack.link) && !textlink({ context })) {
95
+ if (!isBacktrack(context, 1 | Backtrack.link) && !textlink(context)) {
96
96
  setBacktrack(context, 2 | Backtrack.link, head);
97
97
  }
98
98
  context.position = position;
@@ -52,7 +52,7 @@ export const emstrong: EmStrongParser = lazy(() =>
52
52
  return prepend('*', buffer);
53
53
  }
54
54
  })
55
- ({ context }) ?? prepend('*', buffer.import(new List([new Node(html('strong', defrag(unwrap(bs)))), new Node(Command.Separator)])));
55
+ (context) ?? prepend('*', buffer.import(new List([new Node(html('strong', defrag(unwrap(bs)))), new Node(Command.Separator)])));
56
56
  case '*':
57
57
  return bind<StrongParser>(
58
58
  substrong,
@@ -71,7 +71,7 @@ export const emstrong: EmStrongParser = lazy(() =>
71
71
  return prepend('**', buffer);
72
72
  }
73
73
  })
74
- ({ context }) ?? prepend('**', buffer.import(new List([new Node(html('em', defrag(unwrap(bs)))), new Node(Command.Separator)])));
74
+ (context) ?? prepend('**', buffer.import(new List([new Node(html('em', defrag(unwrap(bs)))), new Node(Command.Separator)])));
75
75
  }
76
76
  assert(false);
77
77
  },
@@ -112,7 +112,7 @@ export const emstrong: EmStrongParser = lazy(() =>
112
112
  return prepend('*', nodes.import(ds));
113
113
  }
114
114
  })
115
- ({ context }) ?? prepend('*', nodes);
115
+ (context) ?? prepend('*', nodes);
116
116
  prefix -= 1;
117
117
  break;
118
118
  case 2:
@@ -128,7 +128,7 @@ export const emstrong: EmStrongParser = lazy(() =>
128
128
  return prepend('**', nodes.import(ds));
129
129
  }
130
130
  })
131
- ({ context }) ?? prepend('**', nodes);
131
+ (context) ?? prepend('**', nodes);
132
132
  prefix -= 2;
133
133
  break;
134
134
  }
@@ -5,23 +5,28 @@ import { define } from 'typed-dom/dom';
5
5
 
6
6
  export function indexee<P extends Parser<HTMLElement, Context>>(parser: P): P;
7
7
  export function indexee(parser: Parser<HTMLElement, Context>): Parser<HTMLElement> {
8
- return fmap(parser, (ns, { id }) =>
8
+ return fmap(parser, (ns, { id, local }) =>
9
9
  ns.length === 1
10
- ? new List([new Node(define(ns.head!.value, { id: identity('index', id, ns.head!.value), 'data-index': null }))])
10
+ ? new List([new Node(define(ns.head!.value, {
11
+ id: identity('index', id, ns.head!.value),
12
+ class: local ? `${ns.head!.value.className} local`.trimStart() : undefined,
13
+ 'data-index': null
14
+ }))])
11
15
  : ns);
12
16
  }
13
17
 
14
- const MAX = 60;
15
- const ELLIPSIS = '...';
16
- const PART = (MAX - ELLIPSIS.length) / 2 | 0;
17
- const REM = MAX - PART * 2 - ELLIPSIS.length;
18
- assert(PART * 2 + REM + ELLIPSIS.length === MAX);
19
18
  const table = [
20
19
  ...[...Array(36)].map((_, i) => i.toString(36)),
21
20
  ...[...Array(36)].map((_, i) => i.toString(36).toUpperCase()).slice(-26),
22
21
  '-', '=',
23
22
  ].join('');
24
23
  assert(table.length === 64);
24
+ const MAX = 64 - '='.length - Math.ceil(Math.log(~0 >>> 0) / Math.log(table.length));
25
+ assert(MAX === 57);
26
+ const ELLIPSIS = '...';
27
+ const PART = (MAX - ELLIPSIS.length) / 2 | 0;
28
+ const REM = MAX - PART * 2 - ELLIPSIS.length;
29
+ assert(PART * 2 + REM + ELLIPSIS.length === MAX);
25
30
  export function identity(
26
31
  type: 'index' | 'mark' | '',
27
32
  id: string | undefined,
@@ -68,10 +73,10 @@ assert.deepStrictEqual(
68
73
  `${'0'.repeat(MAX - 1)}1`);
69
74
  assert.deepStrictEqual(
70
75
  identity('index', undefined, `0${'1'.repeat(MAX / 2)}${'2'.repeat(MAX / 2)}3`)!.slice(7),
71
- `0${'1'.repeat(PART + REM - 1)}${ELLIPSIS}${'2'.repeat(PART - 1)}3=MYkmc`);
76
+ `0${'1'.repeat(PART + REM - 1)}${ELLIPSIS}${'2'.repeat(PART - 1)}3=E0deO`);
72
77
  assert.deepStrictEqual(
73
78
  identity('index', undefined, `0${'1'.repeat(MAX * 2)}${'2'.repeat(MAX * 2)}3`)!.slice(7),
74
- `0${'1'.repeat(PART + REM - 1)}${ELLIPSIS}${'2'.repeat(PART - 1)}3=3bF8VU`);
79
+ `0${'1'.repeat(PART + REM - 1)}${ELLIPSIS}${'2'.repeat(PART - 1)}3=2RHwOS`);
75
80
  function hash(source: string): string {
76
81
  let x = 0;
77
82
  for (let i = 0; i < source.length; ++i) {
@@ -88,6 +93,8 @@ assert(hash('\x00') !== '0');
88
93
  assert(hash('\x01') !== '0');
89
94
  assert(hash('\x00') !== hash(String.fromCharCode(1 << 15)));
90
95
  // 62も64も最大6桁
96
+ assert(Math.ceil(Math.log(~0 >>> 0) / Math.log(62)) === 6);
97
+ assert(Math.ceil(Math.log(~0 >>> 0) / Math.log(64)) === 6);
91
98
  function baseR(n: number, r: number): string {
92
99
  assert(n >= 0);
93
100
  assert(Math.floor(n) === n);
@@ -104,6 +111,7 @@ function baseR(n: number, r: number): string {
104
111
  }
105
112
  assert(baseR(0, 36) === (0).toString(36));
106
113
  assert(baseR(~0 >>> 0, 36) === (~0 >>> 0).toString(36));
114
+ assert(baseR(0, 62) === '0');
107
115
  assert(baseR(61, 62) === 'Z');
108
116
  assert(baseR(62, 62) === '10');
109
117
 
@@ -26,7 +26,7 @@ export const math: MathParser = lazy(() => rewrite(
26
26
  false,
27
27
  [3 | Backtrack.escapable]),
28
28
  ]),
29
- ({ context: { source, caches: { math: cache } = {} } }) => new List([
29
+ ({ source, caches: { math: cache } = {} }) => new List([
30
30
  new Node(cache?.get(source)?.cloneNode(true) ||
31
31
  html('span',
32
32
  !forbiddenCommand.test(source)
@@ -45,7 +45,7 @@ export const reference: ReferenceParser = lazy(() => constraint(State.reference,
45
45
  assert(~context.state & State.link);
46
46
  context.position += 1;
47
47
  assert(!isBacktrack(context, 1 | Backtrack.link));
48
- if (!textlink({ context })) {
48
+ if (!textlink(context)) {
49
49
  setBacktrack(context, 2 | Backtrack.link, head + 1);
50
50
  }
51
51
  context.position = position;
@@ -20,6 +20,6 @@ export const remark: RemarkParser = lazy(() => fallback(surround(
20
20
  ])),
21
21
  ]),
22
22
  ([as, bs]) => bs && as.import(bs as List<Node<string>>)),
23
- focus(/\[%+(?=[ \n])/y, ({ context: { source } }) => new List([
23
+ focus(/\[%+(?=[ \n])/y, ({ source }) => new List([
24
24
  new Node(html('span', { class: 'invalid', ...invalid('remark', 'syntax', 'Invalid start symbol') }, source))
25
25
  ]))));
@@ -65,7 +65,7 @@ export const ruby: RubyParser = lazy(() => bind(
65
65
  const delimiter = /[$"`\[\](){}<>()[]{}|]|\\?\n/y;
66
66
 
67
67
  const text: RubyParser.TextParser = input => {
68
- const { context } = input;
68
+ const context = input;
69
69
  const { source } = context;
70
70
  const acc = new List([new Node('')]);
71
71
  let state = false;
@@ -52,7 +52,7 @@ const stars = strs('*');
52
52
 
53
53
  export const inline: InlineParser = lazy(() => union([
54
54
  input => {
55
- const { context: { source, position } } = input;
55
+ const { source, position } = input;
56
56
  if (position === source.length) return;
57
57
  switch (source[position]) {
58
58
  case '(':