securemark 0.296.3 → 0.296.5

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.
@@ -1,19 +1,25 @@
1
- import { Parser, failsafe } from '../../data/parser';
1
+ import { Parser, List, Segment, failsafe } from '../../data/parser';
2
2
  import { isEmptyline } from './line';
3
3
 
4
- export function block<P extends Parser>(parser: P, separation?: boolean): P;
5
- export function block<N>(parser: Parser<N>, separation = true): Parser<N> {
4
+ export function block<P extends Parser>(parser: P, separation?: boolean, segment?: number): P;
5
+ export function block<N>(parser: Parser<N>, separation = true, segment = 0): Parser<N> {
6
6
  assert(parser);
7
7
  return failsafe(input => {
8
8
  const { context } = input;
9
9
  const { source, position } = context;
10
10
  if (position === source.length) return;
11
+ if (segment !== 0 && context.segment & Segment.write) {
12
+ if (context.segment !== (segment | Segment.write)) return;
13
+ context.position = source.length;
14
+ return new List();
15
+ }
11
16
  const result = parser(input);
12
17
  if (result === undefined) return;
13
18
  if (separation && !isEmptyline(source, context.position)) return;
14
19
  assert(context.position === source.length || source[context.position - 1] === '\n');
15
- return context.position === source.length || source[context.position - 1] === '\n'
16
- ? result
17
- : undefined;
20
+ if (segment !== 0 && context.segment & Segment.write ^ Segment.write) {
21
+ context.segment = segment;
22
+ }
23
+ return result;
18
24
  });
19
25
  }
@@ -1,7 +1,7 @@
1
1
  import { Parser, Input, Result, Context } from '../../data/parser';
2
2
 
3
- export function recover<P extends Parser>(parser: P, fallback: (input: Input<Parser.Context<P>>, reason: unknown) => Result<Parser.Node<P>>): P;
4
- export function recover<N>(parser: Parser<N>, fallback: (input: Input<Context>, reason: unknown) => Result<N>): Parser<N> {
3
+ export function recover<P extends Parser>(parser: P, catcher: (input: Input<Parser.Context<P>>, reason: unknown) => Result<Parser.Node<P>>): P;
4
+ export function recover<N>(parser: Parser<N>, catcher: (input: Input<Context>, reason: unknown) => Result<N>): Parser<N> {
5
5
  return input => {
6
6
  const { context } = input;
7
7
  const { source, position } = context;
@@ -12,7 +12,7 @@ export function recover<N>(parser: Parser<N>, fallback: (input: Input<Context>,
12
12
  assert(reason instanceof Error && reason.name === 'AssertionError' && !+console.error(reason) || 1);
13
13
  context.source = source;
14
14
  context.position = position;
15
- return fallback(input, reason);
15
+ return catcher(input, reason);
16
16
  }
17
17
  };
18
18
  }
@@ -33,6 +33,7 @@ export class Context {
33
33
  {
34
34
  source,
35
35
  position,
36
+ segment,
36
37
  resources,
37
38
  delimiters,
38
39
  precedence,
@@ -45,6 +46,7 @@ export class Context {
45
46
  ) {
46
47
  this.source = source ?? '';
47
48
  this.position = position ?? 0;
49
+ this.segment = segment ?? 0;
48
50
  this.resources = resources;
49
51
  this.precedence = precedence ?? 0;
50
52
  this.delimiters = delimiters ?? new Delimiters();
@@ -56,6 +58,7 @@ export class Context {
56
58
  }
57
59
  public source: string;
58
60
  public position: number;
61
+ public segment: number;
59
62
  public readonly resources?: {
60
63
  clock: number;
61
64
  recursions: number[];
@@ -103,6 +106,10 @@ export class Context {
103
106
  public backtracks: Record<number, number>;
104
107
  }
105
108
  export type Options = Partial<Context>;
109
+ export const enum Segment {
110
+ unknown = 0,
111
+ write = 1,
112
+ }
106
113
 
107
114
  export function input<C extends Context>(source: string, context: C): Input<C> {
108
115
  context.source = source;
@@ -1,5 +1,5 @@
1
1
  import { ParserSettings, Progress } from '../../..';
2
- import { Context } from '../context';
2
+ import { Context, Segment } from '../context';
3
3
  import { input } from '../../combinator/data/parser';
4
4
  import { segment } from '../segment';
5
5
  import { block } from '../block';
@@ -47,8 +47,10 @@ export function bind(target: DocumentFragment | HTMLElement | ShadowRoot, settin
47
47
  context.url = url ? new ReadonlyURL(url as ':') : undefined;
48
48
  const rev = revision = Symbol();
49
49
  const sourceSegments: string[] = [];
50
- for (const seg of segment(source)) {
50
+ const sourceSegmentAttrs: Segment[] = [];
51
+ for (const [seg, attr] of segment(source)) {
51
52
  sourceSegments.push(seg);
53
+ sourceSegmentAttrs.push(attr);
52
54
  yield { type: 'segment', value: seg };
53
55
  }
54
56
  const targetSegments = blocks.map(([seg]) => seg);
@@ -74,12 +76,15 @@ export function bind(target: DocumentFragment | HTMLElement | ShadowRoot, settin
74
76
  context.header = true;
75
77
  for (; index < sourceSegments.length - last; ++index) {
76
78
  assert(rev === revision);
77
- const seg = sourceSegments[index];
78
- const es = block(input(seg, new Context(context)))
79
+ const src = sourceSegments[index];
80
+ context.segment = sourceSegmentAttrs[index] | Segment.write;
81
+ const es = block(input(src, new Context(context)))
79
82
  ?.foldl<HTMLElement[]>((acc, { value }) => void acc.push(value) || acc, []) ?? [];
80
83
  // @ts-expect-error
81
84
  context.header = false;
82
- blocks.splice(index, 0, [seg, es, url]);
85
+ blocks.length === index
86
+ ? blocks.push([src, es, url])
87
+ : blocks.splice(index, 0, [src, es, url]);
83
88
  if (es.length === 0) continue;
84
89
  // All deletion processes always run after all addition processes have done.
85
90
  // Therefore any `base` node will never be unavailable by deletions until all the dependent `el` nodes are added.
@@ -1,6 +1,6 @@
1
1
  import { ParserOptions } from '../../..';
2
2
  import { input } from '../../combinator/data/parser';
3
- import { Context } from '../context';
3
+ import { Context, Segment } from '../context';
4
4
  import { segment } from '../segment';
5
5
  import { block } from '../block';
6
6
  import { normalize } from './normalize';
@@ -32,7 +32,8 @@ export function parse(source: string, options: Options = {}, context?: Context):
32
32
  const node = frag();
33
33
  // @ts-expect-error
34
34
  context.header = true;
35
- for (const seg of segment(source)) {
35
+ for (const [seg, attr] of segment(source)) {
36
+ context.segment = attr | Segment.write;
36
37
  node.append(
37
38
  ...block(input(seg, new Context(context)))
38
39
  ?.foldl<HTMLElement[]>((acc, { value }) => void acc.push(value) || acc, []) ?? []);
@@ -1,4 +1,5 @@
1
1
  import { ExtensionParser } from '../../block';
2
+ import { Segment } from '../../context';
2
3
  import { union, sequence, some, block, line, verify, rewrite, close, convert } from '../../../combinator';
3
4
  import { contentline } from '../../source';
4
5
  import { figure } from './figure';
@@ -23,7 +24,7 @@ export const segment: FigParser.SegmentParser = block(
23
24
  seg_placeholder,
24
25
  some(contentline),
25
26
  ]),
26
- ]));
27
+ ]), true, Segment.fig);
27
28
 
28
29
  export const fig: FigParser = block(rewrite(segment, verify(convert(
29
30
  (source, context) => {
@@ -33,6 +34,7 @@ export const fig: FigParser = block(rewrite(segment, verify(convert(
33
34
  const { position } = context;
34
35
  const result = parser({ context });
35
36
  context.position = position;
37
+ context.segment = Segment.figure | Segment.write;
36
38
  return result
37
39
  ? `${fence}figure ${source.replace(/^(.+\n.+\n)([\S\s]+?)\n?$/, '$1\n$2')}\n${fence}`
38
40
  : `${fence}figure ${source}\n\n${fence}`;
@@ -1,4 +1,5 @@
1
1
  import { ExtensionParser } from '../../block';
2
+ import { Segment } from '../../context';
2
3
  import { List, Node, subinput } from '../../../combinator/data/parser';
3
4
  import { union, inits, sequence, some, block, line, fence, rewrite, close, match, convert, fallback, fmap } from '../../../combinator';
4
5
  import { str, contentline, emptyline } from '../../source';
@@ -44,7 +45,7 @@ export const segment: FigureParser.SegmentParser = block(match(
44
45
  ]),
45
46
  ]),
46
47
  closer),
47
- ([, fence]) => fence.length - 1, [], 2 ** 4 - 1)));
48
+ ([, fence]) => fence.length - 1, [], 2 ** 4 - 1)), true, Segment.figure);
48
49
 
49
50
  export const figure: FigureParser = block(fallback(rewrite(segment, fmap(
50
51
  convert(source => source.slice(source.match(/^~+(?:\w+\s+)?/)![0].length, source.trimEnd().lastIndexOf('\n')),
@@ -57,7 +57,7 @@ export const message: MessageParser = block(fmap(
57
57
  'data-type': type,
58
58
  },
59
59
  [...segment(body)].reduce(
60
- (acc, seg) =>
60
+ (acc, [seg]) =>
61
61
  push(acc, unwrap(content(subinput(seg, context)))),
62
62
  [html('h1', title(type))])))
63
63
  ]);
@@ -30,9 +30,9 @@ describe('Unit: parser/block/extension', () => {
30
30
  assert(parser(input('~~~\na\n~~~', new Context())));
31
31
  assert(parser(input('~~~a\n~~~', new Context())));
32
32
  assert(parser(input('~~~a\nb\n~~~', new Context())));
33
- assert(parser(input('$-0', new Context())));
34
- assert(parser(input('$-0\n', new Context())));
35
- assert(parser(input('$-0\n\n', new Context())));
33
+ //assert(parser(input('$-0', new Context())));
34
+ //assert(parser(input('$-0\n', new Context())));
35
+ //assert(parser(input('$-0\n\n', new Context())));
36
36
  });
37
37
 
38
38
  });
@@ -1,7 +1,6 @@
1
1
  import { ExtensionParser } from '../block';
2
2
  import { union } from '../../combinator';
3
- import { figbase } from './extension/figbase';
4
- import { fig, segment as seg_fig } from './extension/fig';
3
+ import { segment as seg_fig } from './extension/fig';
5
4
  import { figure, segment as seg_figure } from './extension/figure';
6
5
  import { table, segment as seg_table } from './extension/table';
7
6
  import { message } from './extension/message';
@@ -17,8 +16,8 @@ export const segment: ExtensionParser.SegmentParser = union([
17
16
  ]);
18
17
 
19
18
  export const extension: ExtensionParser = union([
20
- figbase,
21
- fig,
19
+ //figbase,
20
+ //fig,
22
21
  figure,
23
22
  table,
24
23
  message,
@@ -1,9 +1,9 @@
1
1
  import { HeadingParser } from '../block';
2
- import { State } from '../context';
2
+ import { Segment, State } from '../context';
3
3
  import { List, Node } from '../../combinator/data/parser';
4
4
  import { union, some, state, block, line, focus, rewrite, open, fmap, firstline } from '../../combinator';
5
5
  import { inline, indexee, indexer, dataindex } from '../inline';
6
- import { str } from '../source';
6
+ import { str, strs } from '../source';
7
7
  import { visualize, trimBlank } from '../visibility';
8
8
  import { unwrap, invalid } from '../util';
9
9
  import { html, defrag } from 'typed-dom/dom';
@@ -20,14 +20,14 @@ export const segment: HeadingParser.SegmentParser = block(focus(
20
20
  context.position += line.length;
21
21
  }
22
22
  return acc;
23
- }, false));
23
+ }, false), true, Segment.heading);
24
24
 
25
25
  export const heading: HeadingParser = block(rewrite(segment,
26
26
  // その他の表示制御は各所のCSSで行う。
27
27
  state(State.annotation | State.reference | State.index | State.label | State.link,
28
28
  line(indexee(fmap(union([
29
29
  open(
30
- str(/##+/y),
30
+ strs('#', 2),
31
31
  visualize(trimBlank(some(union([indexer, inline])))), true),
32
32
  open(
33
33
  str('#'),
@@ -1,10 +1,10 @@
1
1
  import { MarkdownParser } from '../../markdown';
2
- import { Recursion, Command } from './context';
2
+ import { Segment, Recursion, Command } from './context';
3
3
  import { List, Node } from '../combinator/data/parser';
4
- import { union, reset, open, fallback, recover } from '../combinator';
4
+ import { union, reset, firstline, recover } from '../combinator';
5
5
  import { MAX_SEGMENT_SIZE } from './segment';
6
6
  import { header } from './header';
7
- import { emptyline } from './source';
7
+ import { emptysegment } from './source';
8
8
  import { pagebreak } from './block/pagebreak';
9
9
  import { heading } from './block/heading';
10
10
  import { ulist } from './block/ulist';
@@ -15,6 +15,9 @@ import { table } from './block/table';
15
15
  import { codeblock } from './block/codeblock';
16
16
  import { mathblock } from './block/mathblock';
17
17
  import { extension } from './block/extension';
18
+ import { figbase } from './block/extension/figbase';
19
+ import { fig } from './block/extension/fig';
20
+ import { figure } from './block/extension/figure';
18
21
  import { sidefence } from './block/sidefence';
19
22
  import { blockquote } from './block/blockquote';
20
23
  import { mediablock } from './block/mediablock';
@@ -57,12 +60,22 @@ export const block: BlockParser = reset(
57
60
  backtracks: {},
58
61
  },
59
62
  error(union([
60
- emptyline,
63
+ emptysegment,
61
64
  input => {
62
- const { context: { source, position } } = input;
65
+ const { context: { source, position, segment } } = input;
63
66
  if (position === source.length) return;
67
+ switch (segment ^ Segment.write) {
68
+ case Segment.heading:
69
+ return heading(input);
70
+ case Segment.fig:
71
+ return fig(input);
72
+ case Segment.figure:
73
+ return figure(input);
74
+ }
64
75
  const fst = source[position];
65
76
  switch (fst) {
77
+ case Command.Error:
78
+ throw new Error(firstline(source, position + 1).trimEnd());
66
79
  case '=':
67
80
  if (source.startsWith('===', position)) return pagebreak(input);
68
81
  break;
@@ -84,7 +97,7 @@ export const block: BlockParser = reset(
84
97
  case '[':
85
98
  switch (source[position + 1]) {
86
99
  case '$':
87
- return extension(input);
100
+ return figbase(input);
88
101
  case '!':
89
102
  return mediablock(input);
90
103
  }
@@ -95,11 +108,9 @@ export const block: BlockParser = reset(
95
108
  case '>':
96
109
  if (source[position + 1] === '>') return blockquote(input) || reply(input);
97
110
  return blockquote(input);
98
- case '#':
99
- return heading(input);
100
111
  case '$':
101
112
  if (source[position + 1] === '$') return mathblock(input);
102
- return extension(input);
113
+ return figbase(input);
103
114
  case '|':
104
115
  return table(input) || sidefence(input);
105
116
  case '(':
@@ -113,9 +124,8 @@ export const block: BlockParser = reset(
113
124
 
114
125
  function error(parser: BlockParser): BlockParser {
115
126
  const reg = new RegExp(String.raw`^${Command.Error}[^\n]*\n`)
116
- return recover<BlockParser>(fallback(
117
- open(Command.Error, ({ context: { source, position } }) => { throw new Error(source.slice(position).split('\n', 1)[0]); }),
118
- parser),
127
+ return recover<BlockParser>(
128
+ parser,
119
129
  ({ context: { source, position, id } }, reason) => new List([
120
130
  new Node(html('h1',
121
131
  {
@@ -7,6 +7,7 @@ export class Context extends Ctx {
7
7
  ) {
8
8
  super(options);
9
9
  const {
10
+ segment,
10
11
  buffer,
11
12
  sequential,
12
13
  header,
@@ -15,6 +16,7 @@ export class Context extends Ctx {
15
16
  id,
16
17
  caches,
17
18
  } = options;
19
+ this.segment = segment ?? Segment.unknown;
18
20
  this.buffer = buffer ?? new List();
19
21
  this.sequential = sequential ?? false;
20
22
  this.header = header ?? true;
@@ -23,6 +25,7 @@ export class Context extends Ctx {
23
25
  this.id = id;
24
26
  this.caches = caches;
25
27
  }
28
+ public override segment: Segment;
26
29
  public buffer: List<Node<(string | HTMLElement)>>;
27
30
  public sequential: boolean;
28
31
  public readonly header: boolean;
@@ -37,6 +40,16 @@ export class Context extends Ctx {
37
40
  }
38
41
  export type Options = Partial<Context>;
39
42
 
43
+ export const enum Segment {
44
+ unknown = 0,
45
+ write = 1,
46
+ nonempty = 0,
47
+ empty = 1 << 1,
48
+ heading = 3 << 1,
49
+ fig = 4 << 1,
50
+ figure = 5 << 1,
51
+ }
52
+
40
53
  export const enum State {
41
54
  annotation = 1 << 7,
42
55
  reference = 1 << 6,
@@ -13,7 +13,7 @@ import { define } from 'typed-dom/dom';
13
13
  export const account: AutolinkParser.AccountParser = lazy(() => constraint(State.autolink, state(State.autolink,
14
14
  surround(
15
15
  surround(
16
- /(?<![0-9a-z])@/yi,
16
+ /(?<![0-9a-z@#])@/yi,
17
17
  str(/[0-9a-z](?:[.-](?=[0-9a-z])|[0-9a-z]){0,254}\/|/yi),
18
18
  str(/[a-z][0-9a-z]*(?:[.-][0-9a-z]+)*(?![_.-]?[0-9a-z@]|>>|:\S)/yi),
19
19
  false,
@@ -18,7 +18,7 @@ import { define } from 'typed-dom/dom';
18
18
 
19
19
  export const anchor: AutolinkParser.AnchorParser = lazy(() => constraint(State.autolink, state(State.autolink,
20
20
  surround(
21
- /(?<![0-9a-z])>>/yi,
21
+ /(?<![0-9a-z@#])>>/yi,
22
22
  str(/[0-9a-z]+(?:-[0-9a-z]+)*(?![_.-]?[0-9a-z@#]|>>|:\S)/yi),
23
23
  '',
24
24
  false,
@@ -10,7 +10,7 @@ import { define } from 'typed-dom/dom';
10
10
  export const hashnum: AutolinkParser.HashnumParser = lazy(() => constraint(State.autolink, state(State.autolink,
11
11
  surround(
12
12
  new RegExp([
13
- /(?<![^\p{C}\p{S}\p{P}\s]|emoji)#/yu.source,
13
+ /(?<![^\p{C}\p{S}\p{P}\s]|emoji|[@#])#/yu.source,
14
14
  ].join('|').replace(/emoji/g, emoji.source), 'yu'),
15
15
  str(new RegExp([
16
16
  /[0-9]{1,9}(?![_.-]?[0-9a-z@#]|>>|:\S|[^\p{C}\p{S}\p{P}\s]|emoji)/yu.source,
@@ -14,7 +14,7 @@ export const emoji = /\p{Emoji_Modifier_Base}\p{Emoji_Modifier}?|\p{Emoji_Presen
14
14
  export const hashtag: AutolinkParser.HashtagParser = lazy(() => constraint(State.autolink, state(State.autolink,
15
15
  surround(
16
16
  new RegExp([
17
- /(?<![^\p{C}\p{S}\p{P}\s]|emoji)#/yu.source,
17
+ /(?<![^\p{C}\p{S}\p{P}\s]|emoji|[@#])#/yu.source,
18
18
  ].join('|').replace(/emoji/g, emoji.source), 'yu'),
19
19
  verify(
20
20
  str(new RegExp([
@@ -26,7 +26,7 @@ export const emstrong: EmStrongParser = lazy(() =>
26
26
  precedence(0, recursion(Recursion.inline, repeat('***', beforeNonblank, surround(
27
27
  '',
28
28
  some(union([some(inline, '*', afterNonblank)])),
29
- strs('*', 3),
29
+ strs('*', 1, 3),
30
30
  false, [],
31
31
  ([, bs, cs], context): Result<Parser.Node<EmStrongParser>, Parser.Context<EmStrongParser>> => {
32
32
  assert(cs.length === 1);
@@ -33,7 +33,7 @@ export function identity(
33
33
  if (index === '' && text.tagName === 'LI') return undefined;
34
34
  return index
35
35
  ? `${type}:${id ?? ''}:${index}`
36
- : identity(type, id, signature(text));
36
+ : identity(type, id, signature(text.cloneNode(true)));
37
37
  }
38
38
  text = text.trim();
39
39
  if (text === '') return undefined;
@@ -106,10 +106,10 @@ assert(baseR(~0 >>> 0, 36) === (~0 >>> 0).toString(36));
106
106
  assert(baseR(61, 62) === 'Z');
107
107
  assert(baseR(62, 62) === '10');
108
108
 
109
- export function signature(source: Element | DocumentFragment): string {
110
- assert(!navigator.userAgent.includes('Chrome') || !source.querySelector('br:not(:has(+ :is(ul, ol)))') || source.nodeName === 'MARK');
111
- const target = source.cloneNode(true) as typeof source;
112
- for (let es = target.querySelectorAll('code[data-src], .math[data-src], .label[data-label], .remark, rt, rp, br, .annotation, .reference, .checkbox, ul, ol'),
109
+ export function signature(target: Element | DocumentFragment): string {
110
+ assert(!target.parentNode);
111
+ assert(!target.querySelector('br:not(:has(+ :is(ul, ol)))') || target.nodeName === 'MARK');
112
+ for (let es = target.querySelectorAll('code[data-src], .math[data-src], .remark, rt, rp, br, .annotation, .reference, .checkbox, ul, ol, .label[data-label]'),
113
113
  len = es.length, i = 0; i < len; ++i) {
114
114
  const el = es[i];
115
115
  switch (el.tagName) {
@@ -144,9 +144,9 @@ export function signature(source: Element | DocumentFragment): string {
144
144
  return target.textContent!.trim();
145
145
  }
146
146
 
147
- export function text(source: Element | DocumentFragment): string {
148
- assert(!navigator.userAgent.includes('Chrome') || !source.querySelector('br:not(:has(+ :is(ul, ol)))'));
149
- const target = source.cloneNode(true) as typeof source;
147
+ export function text(target: Element | DocumentFragment): string {
148
+ assert(!target.parentNode);
149
+ assert(!target.querySelector('br:not(:has(+ :is(ul, ol)))'));
150
150
  for (let es = target.querySelectorAll('code[data-src], .math[data-src], .remark, rt, rp, br, .annotation, .reference, .checkbox, ul, ol'),
151
151
  len = es.length, i = 0; i < len; ++i) {
152
152
  const el = es[i];
@@ -19,7 +19,7 @@ export const mark: MarkParser = lazy(() =>
19
19
  (nodes, { id, state }, nest) => {
20
20
  const el = html('mark', defrag(unwrap(nodes)));
21
21
  if (state & State.linkers || nest) return new List([new Node(el)]);
22
- define(el, { id: identity('mark', id, signature(el)) });
22
+ define(el, { id: identity('mark', id, signature(el.cloneNode(true))) });
23
23
  return el.id
24
24
  ? new List([new Node(el), new Node(html('a', { href: `#${el.id}` }))])
25
25
  : new List([new Node(el)]);
@@ -228,7 +228,6 @@ describe('Unit: parser/inline', () => {
228
228
  assert.deepStrictEqual(inspect(parser, input('#a', new Context())), [['<a class="hashtag" href="/hashtags/a">#a</a>'], '']);
229
229
  assert.deepStrictEqual(inspect(parser, input('#http://host', new Context())), [['#', 'http', '://host'], '']);
230
230
  assert.deepStrictEqual(inspect(parser, input('#a\nb\n#c\n[#d]', new Context())), [['<a class="hashtag" href="/hashtags/a">#a</a>', '<br>', 'b', '<br>', '<a class="hashtag" href="/hashtags/c">#c</a>', '<br>', '<a class="index" href="#index::d">d</a>'], '']);
231
- assert.deepStrictEqual(inspect(parser, input('##a', new Context())), [['#', '<a class="hashtag" href="/hashtags/a">#a</a>'], '']);
232
231
  assert.deepStrictEqual(inspect(parser, input('_#a', new Context())), [['_', '<a class="hashtag" href="/hashtags/a">#a</a>'], '']);
233
232
  assert.deepStrictEqual(inspect(parser, input('_#a_', new Context())), [['_', '<a class="hashtag" href="/hashtags/a">#a</a>', '_'], '']);
234
233
  assert.deepStrictEqual(inspect(parser, input('_#a_b', new Context())), [['_', '<a class="hashtag" href="/hashtags/a_b">#a_b</a>'], '']);
@@ -255,18 +255,20 @@ describe('Unit: parser/processor/note', () => {
255
255
  ]).outerHTML,
256
256
  ]);
257
257
  assert.deepStrictEqual(
258
- note.outerHTML,
259
- html('ol', [
260
- html('li', { id: 'reference::def:a_b' }, [
261
- html('span', 'a b'),
262
- html('sup', [html('a', { href: '#reference::ref:a_b:1' }, '^1')]),
263
- ]),
264
- ]).outerHTML);
258
+ [note.outerHTML],
259
+ [
260
+ html('ol', [
261
+ html('li', { id: 'reference::def:a_b' }, [
262
+ html('span', 'a b'),
263
+ html('sup', [html('a', { href: '#reference::ref:a_b:1' }, '^1')]),
264
+ ]),
265
+ ]).outerHTML,
266
+ ]);
265
267
  }
266
268
  });
267
269
 
268
270
  it('abbr', () => {
269
- const target = parse('[[^A 1|b]][[^A 1]][[^A 1]]');
271
+ const target = parse('[[^A 1]][[^A 1|b]][[^A 1]]');
270
272
  const note = html('ol');
271
273
  for (let i = 0; i < 3; ++i) {
272
274
  [...reference(target, note)];
@@ -289,17 +291,19 @@ describe('Unit: parser/processor/note', () => {
289
291
  ]).outerHTML,
290
292
  ]);
291
293
  assert.deepStrictEqual(
292
- note.outerHTML,
293
- html('ol', [
294
- html('li', { id: 'reference::def:A_1' }, [
295
- html('span', 'b'),
296
- html('sup', [
297
- html('a', { href: '#reference::ref:A_1:1', title: 'b' }, '^1'),
298
- html('a', { href: '#reference::ref:A_1:2' }, '^2'),
299
- html('a', { href: '#reference::ref:A_1:3' }, '^3'),
300
- ])
301
- ]),
302
- ]).outerHTML);
294
+ [note.outerHTML],
295
+ [
296
+ html('ol', [
297
+ html('li', { id: 'reference::def:A_1' }, [
298
+ html('span', 'b'),
299
+ html('sup', [
300
+ html('a', { href: '#reference::ref:A_1:1' }, '^1'),
301
+ html('a', { href: '#reference::ref:A_1:2', title: 'b' }, '^2'),
302
+ html('a', { href: '#reference::ref:A_1:3' }, '^3'),
303
+ ])
304
+ ]),
305
+ ]).outerHTML,
306
+ ]);
303
307
  }
304
308
  });
305
309
 
@@ -336,16 +340,18 @@ describe('Unit: parser/processor/note', () => {
336
340
  ]).outerHTML,
337
341
  ]);
338
342
  assert.deepStrictEqual(
339
- note.outerHTML,
340
- html('ol', [
341
- html('li', { id: 'reference::def:B' }, [
342
- html('span', 'c'),
343
- html('sup', [
344
- html('a', { href: '#reference::ref:B:1', title: 'c' }, '^1'),
345
- html('a', { href: '#reference::ref:B:2' }, '^2'),
346
- ]),
347
- ]),
348
- ]).outerHTML);
343
+ [note.outerHTML],
344
+ [
345
+ html('ol', [
346
+ html('li', { id: 'reference::def:B' }, [
347
+ html('span', 'c'),
348
+ html('sup', [
349
+ html('a', { href: '#reference::ref:B:1', title: 'c' }, '^1'),
350
+ html('a', { href: '#reference::ref:B:2' }, '^2'),
351
+ ]),
352
+ ]),
353
+ ]).outerHTML,
354
+ ]);
349
355
  target.lastChild?.remove();
350
356
  }
351
357
  });