securemark 0.293.2 → 0.293.4

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 (45) hide show
  1. package/CHANGELOG.md +8 -0
  2. package/README.md +7 -10
  3. package/dist/index.js +349 -167
  4. package/package.json +1 -1
  5. package/src/combinator/control/manipulation/indent.test.ts +6 -1
  6. package/src/combinator/control/manipulation/indent.ts +1 -1
  7. package/src/combinator/control/manipulation/surround.ts +2 -1
  8. package/src/combinator/data/parser/context/delimiter.ts +7 -12
  9. package/src/combinator/data/parser/some.ts +4 -8
  10. package/src/combinator/data/parser.ts +0 -3
  11. package/src/parser/api/bind.ts +1 -1
  12. package/src/parser/api/parse.ts +1 -1
  13. package/src/parser/block/dlist.test.ts +1 -1
  14. package/src/parser/block/heading.test.ts +1 -0
  15. package/src/parser/block/olist.test.ts +9 -6
  16. package/src/parser/block/olist.ts +2 -2
  17. package/src/parser/block/ulist.test.ts +1 -0
  18. package/src/parser/block.ts +38 -36
  19. package/src/parser/inline/annotation.test.ts +1 -1
  20. package/src/parser/inline/bracket.test.ts +4 -2
  21. package/src/parser/inline/bracket.ts +114 -88
  22. package/src/parser/inline/emphasis.test.ts +1 -0
  23. package/src/parser/inline/html.test.ts +3 -3
  24. package/src/parser/inline/html.ts +32 -21
  25. package/src/parser/inline/italic.test.ts +1 -0
  26. package/src/parser/inline/link.test.ts +10 -8
  27. package/src/parser/inline/link.ts +18 -18
  28. package/src/parser/inline/mark.test.ts +1 -0
  29. package/src/parser/inline/math.ts +2 -2
  30. package/src/parser/inline/media.test.ts +6 -7
  31. package/src/parser/inline/media.ts +6 -5
  32. package/src/parser/inline/reference.test.ts +1 -1
  33. package/src/parser/inline/remark.test.ts +3 -1
  34. package/src/parser/inline/remark.ts +2 -2
  35. package/src/parser/inline/strong.test.ts +1 -0
  36. package/src/parser/inline/template.ts +1 -1
  37. package/src/parser/inline.test.ts +16 -16
  38. package/src/parser/inline.ts +46 -47
  39. package/src/parser/segment.ts +12 -12
  40. package/src/parser/source/escapable.test.ts +1 -0
  41. package/src/parser/source/escapable.ts +3 -9
  42. package/src/parser/source/text.test.ts +5 -4
  43. package/src/parser/source/text.ts +175 -24
  44. package/src/parser/source/unescapable.test.ts +1 -0
  45. package/src/parser/source/unescapable.ts +2 -3
@@ -67,7 +67,7 @@ describe('Unit: parser/inline/html', () => {
67
67
  assert.deepStrictEqual(inspect(parser('<wbr >'), ctx), [['<wbr>'], '']);
68
68
  assert.deepStrictEqual(inspect(parser('<wbr>a'), ctx), [['<wbr>'], 'a']);
69
69
  assert.deepStrictEqual(inspect(parser('<bdi >a</bdi>'), ctx), [['<bdi>a</bdi>'], '']);
70
- assert.deepStrictEqual(inspect(parser('<bdi >a</bdi>'), ctx), [['<bdi>a</bdi>'], '']);
70
+ assert.deepStrictEqual(inspect(parser('<bdi >a</bdi>'), ctx), [['<span class="invalid">&lt;bdi &gt;a&lt;/bdi&gt;</span>'], '']);
71
71
  assert.deepStrictEqual(inspect(parser('<bdi> a</bdi>'), ctx), [['<bdi> a</bdi>'], '']);
72
72
  assert.deepStrictEqual(inspect(parser('<bdi> a </bdi>'), ctx), [['<bdi> a </bdi>'], '']);
73
73
  assert.deepStrictEqual(inspect(parser('<bdi> a </bdi>'), ctx), [['<bdi> a </bdi>'], '']);
@@ -122,8 +122,8 @@ describe('Unit: parser/inline/html', () => {
122
122
  assert.deepStrictEqual(inspect(parser('<bdo diR="rtl">a</bdo>'), ctx), [['<span class="invalid">&lt;bdo diR="rtl"&gt;a&lt;/bdo&gt;</span>'], '']);
123
123
  assert.deepStrictEqual(inspect(parser('<bdo dir="rtl">a</bdo>'), ctx), [['<bdo dir="rtl">a</bdo>'], '']);
124
124
  assert.deepStrictEqual(inspect(parser('<bdo dir="rtl" >a</bdo>'), ctx), [['<bdo dir="rtl">a</bdo>'], '']);
125
- assert.deepStrictEqual(inspect(parser('<bdo dir="rtl" >a</bdo>'), ctx), [['<bdo dir="rtl">a</bdo>'], '']);
126
- assert.deepStrictEqual(inspect(parser('<bdo dir="rtl">a</bdo>'), ctx), [['<bdo dir="rtl">a</bdo>'], '']);
125
+ assert.deepStrictEqual(inspect(parser('<bdo dir="rtl" >a</bdo>'), ctx), [['<span class="invalid">&lt;bdo dir="rtl" &gt;a&lt;/bdo&gt;</span>'], '']);
126
+ assert.deepStrictEqual(inspect(parser('<bdo dir="rtl">a</bdo>'), ctx), [['<span class="invalid">&lt;bdo dir="rtl"&gt;a&lt;/bdo&gt;</span>'], '']);
127
127
  assert.deepStrictEqual(inspect(parser('<wbr\n>'), ctx), undefined);
128
128
  assert.deepStrictEqual(inspect(parser('<wbr \n>'), ctx), [['<span class="invalid">&lt;wbr </span>'], '\n>']);
129
129
  assert.deepStrictEqual(inspect(parser('<wbr constructor>'), ctx), [['<span class="invalid">&lt;wbr constructor&gt;</span>'], '']);
@@ -7,7 +7,7 @@ import { str } from '../source';
7
7
  import { isLooseNodeStart, blankWith } from '../visibility';
8
8
  import { invalid } from '../util';
9
9
  import { memoize } from 'spica/memoize';
10
- import { unshift, push, splice } from 'spica/array';
10
+ import { unshift, push } from 'spica/array';
11
11
  import { html as h, defrag } from 'typed-dom/dom';
12
12
 
13
13
  const tags: readonly string[] = ['wbr', 'bdo', 'bdi'];
@@ -20,13 +20,13 @@ const attrspecs = {
20
20
  Object.setPrototypeOf(attrspecs, null);
21
21
  Object.values(attrspecs).forEach(o => Object.setPrototypeOf(o, null));
22
22
 
23
- export const html: HTMLParser = lazy(() => validate(/<[a-z]+(?=[^\S\n]|>)/yi,
23
+ export const html: HTMLParser = lazy(() => validate(/<[a-z]+(?=[ >])/yi,
24
24
  union([
25
25
  surround(
26
26
  // https://html.spec.whatwg.org/multipage/syntax.html#void-elements
27
- str(/<(?:area|base|br|col|embed|hr|img|input|link|meta|source|track|wbr)(?=[^\S\n]|>)/yi),
27
+ str(/<(?:area|base|br|col|embed|hr|img|input|link|meta|source|track|wbr)(?=[ >])/yi),
28
28
  some(union([attribute])),
29
- open(str(/[^\S\n]*/y), str('>'), true),
29
+ open(str(/ ?/y), str('>'), true),
30
30
  true,
31
31
  ([as, bs = [], cs], context) =>
32
32
  [[elem(as[0].slice(1), false, push(unshift(as, bs), cs), [], [], context)]],
@@ -38,14 +38,18 @@ export const html: HTMLParser = lazy(() => validate(/<[a-z]+(?=[^\S\n]|>)/yi,
38
38
  ([, tag]) =>
39
39
  surround<HTMLParser.TagParser, string>(
40
40
  surround(
41
- str(`<${tag}`), some(attribute), open(str(/[^\S\n]*/y), str('>'), true),
41
+ str(`<${tag}`), some(attribute), open(str(/ ?/y), str('>'), true),
42
42
  true,
43
43
  ([as, bs = [], cs]) => [push(unshift(as, bs), cs)],
44
44
  ([as, bs = []]) => [unshift(as, bs)]),
45
- precedence(3, recursion(Recursion.inline,
45
+ // 不可視のHTML構造が可視構造を変化させるべきでない。
46
+ // 可視のHTMLは優先度変更を検討する。
47
+ // このため<>は将来的に共通構造を変化させる可能性があり
48
+ // 共通構造を変化させない非構造文字列としては依然としてエスケープを要する。
49
+ precedence(0, recursion(Recursion.inline,
46
50
  some(union([
47
- some(inline, blankWith('\n', `</${tag}>`), [[blankWith('\n', `</${tag}>`), 3]]),
48
- open('\n', some(inline, `</${tag}>`, [[`</${tag}>`, 3]]), true),
51
+ some(inline, blankWith('\n', `</${tag}>`)),
52
+ open('\n', some(inline, `</${tag}>`), true),
49
53
  ])))),
50
54
  str(`</${tag}>`),
51
55
  true,
@@ -57,9 +61,9 @@ export const html: HTMLParser = lazy(() => validate(/<[a-z]+(?=[^\S\n]|>)/yi,
57
61
  new Map())),
58
62
  surround(
59
63
  // https://html.spec.whatwg.org/multipage/syntax.html#void-elements
60
- str(/<[a-z]+(?=[^\S\n]|>)/yi),
64
+ str(/<[a-z]+(?=[ >])/yi),
61
65
  some(union([attribute])),
62
- open(str(/[^\S\n]*/y), str('>'), true),
66
+ open(str(/ ?/y), str('>'), true),
63
67
  true,
64
68
  ([as, bs = [], cs], context) =>
65
69
  [[elem(as[0].slice(1), false, push(unshift(as, bs), cs), [], [], context)]],
@@ -68,8 +72,8 @@ export const html: HTMLParser = lazy(() => validate(/<[a-z]+(?=[^\S\n]|>)/yi,
68
72
  ])));
69
73
 
70
74
  export const attribute: HTMLParser.AttributeParser = union([
71
- str(/[^\S\n]+[a-z]+(?:-[a-z]+)*(?:="(?:\\[^\n]|[^\\\n"])*")?(?=[^\S\n]|>)/yi),
72
- str(/[^\S\n]+[^\s<>]+/y),
75
+ str(/ [a-z]+(?:-[a-z]+)*(?:="(?:\\[^\n]|[^\\\n"])*")?(?=[ >])/yi),
76
+ str(/ [^\s<>]+/y),
73
77
  ]);
74
78
 
75
79
  function elem(tag: string, content: boolean, as: string[], bs: (HTMLElement | string)[], cs: string[], context: Ctx): HTMLElement {
@@ -81,7 +85,7 @@ function elem(tag: string, content: boolean, as: string[], bs: (HTMLElement | st
81
85
  if (bs.length === 0) return ielem('content', `Missing the content`, context);
82
86
  if (!isLooseNodeStart(bs)) return ielem('content', `Missing the visible content in the same line`, context);
83
87
  }
84
- const attrs = attributes('html', attrspecs[tag], as.slice(1, as.at(-1) === '>' ? -1 : as.length));
88
+ const [attrs] = attributes('html', attrspecs[tag], as.slice(1, as.at(-1) === '>' ? -1 : as.length));
85
89
  if (/(?<!\S)invalid(?!\S)/.test(attrs['class'] ?? '')) return ielem('attribute', 'Invalid HTML attribute', context)
86
90
  if (as.at(-1) !== '>') return ielem('tag', `Missing the closing symbol ">"`, context);
87
91
  return h(tag as 'span', attrs, defrag(bs));
@@ -101,11 +105,12 @@ const requiredAttributes = memoize(
101
105
  export function attributes(
102
106
  syntax: string,
103
107
  spec: Readonly<Record<string, readonly (string | undefined)[] | undefined>> | undefined,
104
- params: string[],
105
- ): Record<string, string | undefined> {
108
+ params: readonly string[],
109
+ ): [Record<string, string | undefined>, string[]] {
106
110
  assert(spec instanceof Object === false);
107
111
  assert(!spec?.['__proto__']);
108
112
  assert(!spec?.toString);
113
+ const remains = [];
109
114
  let invalidation = false;
110
115
  const attrs: Record<string, string | undefined> = {};
111
116
  for (let i = 0; i < params.length; ++i) {
@@ -116,19 +121,25 @@ export function attributes(
116
121
  ? param.slice(name.length + 2, -1).replace(/\\(.?)/g, '$1')
117
122
  : undefined;
118
123
  invalidation ||= name === '' || !spec || name in attrs;
119
- if (name === '' || spec && name in spec && !spec[name]) continue;
120
- spec?.[name]?.includes(value) || spec?.[name]?.length === 0 && value !== undefined
121
- ? attrs[name] = value ?? ''
122
- : invalidation ||= !!spec;
124
+ if (name === '')continue;
125
+ if (spec && name in spec && !spec[name]) {
126
+ remains.push(params[i]);
127
+ continue;
128
+ }
129
+ if (spec?.[name]?.includes(value) || spec?.[name]?.length === 0 && value !== undefined) {
130
+ attrs[name] = value ?? ''
131
+ }
132
+ else {
133
+ invalidation ||= !!spec;
134
+ }
123
135
  assert(!(name in {} && attrs.hasOwnProperty(name)));
124
- splice(params, i--, 1);
125
136
  }
126
137
  invalidation ||= !!spec && !requiredAttributes(spec).every(name => name in attrs);
127
138
  if (invalidation) {
128
139
  attrs['class'] = 'invalid';
129
140
  Object.assign(attrs, invalid(syntax, 'argument', 'Invalid argument'));
130
141
  }
131
- return attrs;
142
+ return [attrs, remains];
132
143
  }
133
144
 
134
145
  // https://developer.mozilla.org/en-US/docs/Web/HTML/Element
@@ -58,6 +58,7 @@ describe('Unit: parser/inline/italic', () => {
58
58
  assert.deepStrictEqual(inspect(parser('//////a//////'), ctx), [['<i><i>a</i></i>'], '']);
59
59
  assert.deepStrictEqual(inspect(parser('//////a///b///'), ctx), [['<i><i>a</i>b</i>'], '']);
60
60
  assert.deepStrictEqual(inspect(parser('///a ///b//////'), ctx), [['<i>a <i>b</i></i>'], '']);
61
+ assert.deepStrictEqual(inspect(parser('///- ///b//////'), ctx), [['<i>- <i>b</i></i>'], '']);
61
62
  assert.deepStrictEqual(inspect(parser('///a\\ ///b//////'), ctx), [['<i>a <i>b</i></i>'], '']);
62
63
  assert.deepStrictEqual(inspect(parser('///a //////b/////////'), ctx), [['<i>a <i><i>b</i></i></i>'], '']);
63
64
  assert.deepStrictEqual(inspect(parser('///a ///b///c///'), ctx), [['<i>a <i>b</i>c</i>'], '']);
@@ -63,8 +63,8 @@ describe('Unit: parser/inline/link', () => {
63
63
  assert.deepStrictEqual(inspect(parser('[]'), ctx), undefined);
64
64
  assert.deepStrictEqual(inspect(parser('[]{}'), ctx), undefined);
65
65
  assert.deepStrictEqual(inspect(parser('[]{ }'), ctx), [['<span class="invalid">[]{ }</span>'], '']);
66
- assert.deepStrictEqual(inspect(parser('[]{ }'), ctx), [['<span class="invalid">[]{ }</span>'], '']);
67
- assert.deepStrictEqual(inspect(parser('[]{ }'), ctx), [['<span class="invalid">[]{ }</span>'], '']);
66
+ assert.deepStrictEqual(inspect(parser('[]{ }'), ctx), undefined);
67
+ assert.deepStrictEqual(inspect(parser('[]{ }'), ctx), undefined);
68
68
  assert.deepStrictEqual(inspect(parser('[]{{}'), ctx), undefined);
69
69
  assert.deepStrictEqual(inspect(parser('[]{}}'), ctx), undefined);
70
70
  assert.deepStrictEqual(inspect(parser('[]{{}}'), ctx), undefined);
@@ -105,12 +105,11 @@ describe('Unit: parser/inline/link', () => {
105
105
  it('basic', () => {
106
106
  assert.deepStrictEqual(inspect(parser('[]{b}'), ctx), [['<a class="url" href="b">b</a>'], '']);
107
107
  assert.deepStrictEqual(inspect(parser('[]{b }'), ctx), [['<a class="url" href="b">b</a>'], '']);
108
- assert.deepStrictEqual(inspect(parser('[]{b }'), ctx), [['<a class="url" href="b">b</a>'], '']);
108
+ assert.deepStrictEqual(inspect(parser('[]{b }'), ctx), [['<span class="invalid">[]{b</span>'], ' }']);
109
109
  assert.deepStrictEqual(inspect(parser('[]{ b }'), ctx), [['<a class="url" href="b">b</a>'], '']);
110
- assert.deepStrictEqual(inspect(parser('[]{ b }'), ctx), [['<a class="url" href="b">b</a>'], '']);
111
- assert.deepStrictEqual(inspect(parser('[]{ b }'), ctx), [['<a class="url" href="b">b</a>'], '']);
112
- assert.deepStrictEqual(inspect(parser('[]{ b }'), ctx), [['<a class="url" href="b">b</a>'], '']);
113
- assert.deepStrictEqual(inspect(parser('[]{ b }'), ctx), [['<a class="url" href="b">b</a>'], '']);
110
+ assert.deepStrictEqual(inspect(parser('[]{ b }'), ctx), [['<span class="invalid">[]{ b</span>'], ' }']);
111
+ assert.deepStrictEqual(inspect(parser('[]{ b }'), ctx), undefined);
112
+ assert.deepStrictEqual(inspect(parser('[]{ b }'), ctx), undefined);
114
113
  assert.deepStrictEqual(inspect(parser('[]{"}'), ctx), [[`<a class="url" href="&quot;">"</a>`], '']);
115
114
  assert.deepStrictEqual(inspect(parser('[]{"}"}'), ctx), [[`<a class="url" href="&quot;">"</a>`], '"}']);
116
115
  assert.deepStrictEqual(inspect(parser('[]{\\}'), ctx), [[`<a class="url" href="\\">\\</a>`], '']);
@@ -209,7 +208,6 @@ describe('Unit: parser/inline/link', () => {
209
208
  assert.deepStrictEqual(inspect(parser('[]{/ aspect-ratio="4/3"}'), ctx), [['<a class="invalid" href="/">/</a>'], '']);
210
209
  assert.deepStrictEqual(inspect(parser('[]{/ 4:3}'), ctx), [['<a class="invalid" href="/">/</a>'], '']);
211
210
  assert.deepStrictEqual(inspect(parser('[]{/ =}'), ctx), [['<a class="invalid" href="/">/</a>'], '']);
212
- assert.deepStrictEqual(inspect(parser('[]{/ name}'), ctx), [['<a class="invalid" href="/">/</a>'], '']);
213
211
  assert.deepStrictEqual(inspect(parser('[]{/\nname}'), ctx), [['<span class="invalid">[]{/</span>'], '\nname}']);
214
212
  });
215
213
 
@@ -221,8 +219,12 @@ describe('Unit: parser/inline/link', () => {
221
219
  assert.deepStrictEqual(inspect(parser('[]{/ nofollow nofollow}'), ctx), [['<a class="invalid" href="/" rel="nofollow">/</a>'], '']);
222
220
  assert.deepStrictEqual(inspect(parser('[]{/ nofollow}'), ctx), [['<a class="url" href="/" rel="nofollow">/</a>'], '']);
223
221
  assert.deepStrictEqual(inspect(parser('[]{/ nofollow }'), ctx), [['<a class="url" href="/" rel="nofollow">/</a>'], '']);
222
+ assert.deepStrictEqual(inspect(parser('[]{/ nofollow }'), ctx), [['<span class="invalid">[]{/ nofollow</span>'], ' }']);
223
+ assert.deepStrictEqual(inspect(parser('[]{/ nofollow}'), ctx), [['<span class="invalid">[]{/</span>'], ' nofollow}']);
224
224
  assert.deepStrictEqual(inspect(parser('[]{ / nofollow}'), ctx), [['<a class="url" href="/" rel="nofollow">/</a>'], '']);
225
225
  assert.deepStrictEqual(inspect(parser('[]{ / nofollow }'), ctx), [['<a class="url" href="/" rel="nofollow">/</a>'], '']);
226
+ assert.deepStrictEqual(inspect(parser('[]{ / nofollow }'), ctx), [['<span class="invalid">[]{ / nofollow</span>'], ' }']);
227
+ assert.deepStrictEqual(inspect(parser('[]{ / nofollow}'), ctx), [['<span class="invalid">[]{ /</span>'], ' nofollow}']);
226
228
  assert.deepStrictEqual(inspect(parser('[]{http://host nofollow}'), ctx), [['<a class="url" href="http://host" target="_blank" rel="nofollow">http://host</a>'], '']);
227
229
  assert.deepStrictEqual(inspect(parser('[!http://host]{http://host nofollow}'), ctx), [['<a class="link" href="http://host" target="_blank" rel="nofollow"><img class="media" data-src="http://host" alt="http://host"></a>'], '']);
228
230
  });
@@ -35,7 +35,7 @@ export const textlink: LinkParser.TextLinkParser = lazy(() => constraint(State.l
35
35
  dup(surround(
36
36
  /{(?![{}])/y,
37
37
  inits([uri, some(option)]),
38
- /[^\S\n]*}/y,
38
+ / ?}/y,
39
39
  false,
40
40
  undefined,
41
41
  ([as, bs], context) => {
@@ -82,7 +82,7 @@ export const medialink: LinkParser.MediaLinkParser = lazy(() => constraint(State
82
82
  '[',
83
83
  union([media, shortmedia]),
84
84
  ']')),
85
- dup(surround(/{(?![{}])/y, inits([uri, some(option)]), /[^\S\n]*}/y)),
85
+ dup(surround(/{(?![{}])/y, inits([uri, some(option)]), / ?}/y)),
86
86
  ])),
87
87
  ([params, content = []]: [string[], (HTMLElement | string)[]], context) =>
88
88
  [[parse(defrag(content), params, context)]]))))));
@@ -94,20 +94,20 @@ export const unsafelink: LinkParser.UnsafeLinkParser = lazy(() =>
94
94
  '[',
95
95
  some(union([unescsource]), ']'),
96
96
  ']')),
97
- dup(surround(/{(?![{}])/y, inits([uri, some(option)]), /[^\S\n]*}/y)),
97
+ dup(surround(/{(?![{}])/y, inits([uri, some(option)]), / ?}/y)),
98
98
  ])),
99
99
  ([params, content = []], context) =>
100
100
  [[parse(defrag(content), params, context)]])));
101
101
 
102
102
  export const uri: LinkParser.ParameterParser.UriParser = union([
103
- open(/[^\S\n]+/y, str(/\S+/y)),
103
+ open(/ /y, str(/\S+/y)),
104
104
  str(/[^\s{}]+/y),
105
105
  ]);
106
106
 
107
107
  export const option: LinkParser.ParameterParser.OptionParser = union([
108
- fmap(str(/[^\S\n]+nofollow(?=[^\S\n]|})/y), () => [` rel="nofollow"`]),
109
- str(/[^\S\n]+[a-z]+(?:-[a-z]+)*(?:="(?:\\[^\n]|[^\\\n"])*")?(?=[^\S\n]|})/yi),
110
- str(/[^\S\n]+[^\s{}]+/y),
108
+ fmap(str(/ nofollow(?=[ }])/y), () => [` rel="nofollow"`]),
109
+ str(/ [a-z]+(?:-[a-z]+)*(?:="(?:\\[^\n]|[^\\\n"])*")?(?=[ }])/yi),
110
+ str(/ [^\s{}]+/y),
111
111
  ]);
112
112
 
113
113
  function parse(
@@ -135,7 +135,7 @@ function parse(
135
135
  context.host?.origin || location.origin);
136
136
  return el.classList.contains('invalid')
137
137
  ? el
138
- : define(el, attributes('link', optspec, params));
138
+ : define(el, attributes('link', optspec, params)[0]);
139
139
  }
140
140
 
141
141
  function elem(
@@ -155,11 +155,11 @@ function elem(
155
155
  case 'https:':
156
156
  assert(uri.host);
157
157
  switch (true) {
158
- case /[a-z][0-9]*:\/{0,2}\S/i.test(stringify(content)):
158
+ case /[0-9a-z]:\S/i.test(stringify(content)):
159
159
  type = 'content';
160
160
  message = 'URI must not be contained';
161
161
  break;
162
- case INSECURE_URI.slice(0, 2) === '^/'
162
+ case INSECURE_URI.startsWith('^/')
163
163
  && /\/\.\.?(?:\/|$)/.test(INSECURE_URI.slice(0, INSECURE_URI.search(/[?#]|$/))):
164
164
  type = 'argument';
165
165
  message = 'Dot-segments cannot be used in subresource paths';
@@ -223,7 +223,7 @@ export function resolve(uri: string, host: URL | Location, source: URL | Locatio
223
223
  assert(uri);
224
224
  assert(uri === uri.trim());
225
225
  switch (true) {
226
- case uri.slice(0, 2) === '^/':
226
+ case uri.startsWith('^/'):
227
227
  const last = host.pathname.slice(host.pathname.lastIndexOf('/') + 1);
228
228
  return last.includes('.') // isFile
229
229
  // Exclude ISO 6709.
@@ -232,7 +232,7 @@ export function resolve(uri: string, host: URL | Location, source: URL | Locatio
232
232
  : `${host.pathname.replace(/\/?$/, '/')}${uri.slice(2)}`;
233
233
  case host.origin === source.origin
234
234
  && host.pathname === source.pathname:
235
- case uri.slice(0, 2) === '//':
235
+ case uri.startsWith('//'):
236
236
  return uri;
237
237
  default:
238
238
  const target = new ReadonlyURL(uri, source.href);
@@ -243,13 +243,13 @@ export function resolve(uri: string, host: URL | Location, source: URL | Locatio
243
243
  }
244
244
 
245
245
  export function decode(uri: string): string {
246
- const origin = uri.match(/[a-z](?:[-.](?=[0-9a-z])|[0-9a-z])*:(?:\/{0,2}[^/?#\s]+|\/\/(?=[/]))/yi)?.[0] ?? '';
246
+ const head = /^[a-z]+(?:[.+-][0-9a-z]+)*:\/*[^/?#\s]+/i;
247
+ const origin = uri.match(head)?.[0] ?? '';
247
248
  try {
248
- let path = decodeURI(uri.slice(origin.length));
249
- if (!origin && /[a-z](?:[-.](?=[0-9a-z])|[0-9a-z])*:\/{0,2}\S/yi.test(path)) {
250
- path = uri.slice(origin.length);
251
- }
252
- uri = origin + path;
249
+ const path = decodeURI(uri.slice(origin.length));
250
+ uri = !origin && head.test(path)
251
+ ? uri.slice(origin.length)
252
+ : origin + path;
253
253
  }
254
254
  finally {
255
255
  return uri.replace(/\s+/g, encodeURI);
@@ -39,6 +39,7 @@ describe('Unit: parser/inline/mark', () => {
39
39
 
40
40
  it('nest', () => {
41
41
  assert.deepStrictEqual(inspect(parser('==a ==b===='), ctx), [['<mark id="mark::a_b">a <mark id="mark::b">b</mark><a href="#mark::b"></a></mark>', '<a href="#mark::a_b"></a>'], '']);
42
+ assert.deepStrictEqual(inspect(parser('==- ==b===='), ctx), [['<mark id="mark::-_b">- <mark id="mark::b">b</mark><a href="#mark::b"></a></mark>', '<a href="#mark::-_b"></a>'], '']);
42
43
  assert.deepStrictEqual(inspect(parser('==a\\ ==b===='), ctx), [['<mark id="mark::a_b">a <mark id="mark::b">b</mark><a href="#mark::b"></a></mark>', '<a href="#mark::a_b"></a>'], '']);
43
44
  assert.deepStrictEqual(inspect(parser('==a&Tab;==b===='), ctx), [['<mark id="mark::a_b=33Mw2l">a\t<mark id="mark::b">b</mark><a href="#mark::b"></a></mark>', '<a href="#mark::a_b=33Mw2l"></a>'], '']);
44
45
  assert.deepStrictEqual(inspect(parser('==a<wbr>==b===='), ctx), [['<mark id="mark::ab">a<wbr><mark id="mark::b">b</mark><a href="#mark::b"></a></mark>', '<a href="#mark::ab"></a>'], '']);
@@ -11,14 +11,14 @@ export const math: MathParser = lazy(() => rewrite(
11
11
  union([
12
12
  surround(
13
13
  /\$(?={)/y,
14
- precedence(5, bracket),
14
+ precedence(4, bracket),
15
15
  '$',
16
16
  false, undefined, undefined, [3 | Backtrack.bracket]),
17
17
  surround(
18
18
  /\$(?![\s{}])/y,
19
19
  precedence(2, some(union([
20
20
  some(escsource, /\s?\$|[`"{}\n]/y),
21
- precedence(5, bracket),
21
+ precedence(4, bracket),
22
22
  ]))),
23
23
  /\$(?![-0-9A-Za-z])/y,
24
24
  false, undefined, undefined, [3 | Backtrack.bracket]),
@@ -27,8 +27,8 @@ describe('Unit: parser/inline/media', () => {
27
27
  assert.deepStrictEqual(inspect(parser('![]'), ctx), undefined);
28
28
  assert.deepStrictEqual(inspect(parser('![]{}'), ctx), undefined);
29
29
  assert.deepStrictEqual(inspect(parser('![]{ }'), ctx), [['<span class="invalid">![]{ }</span>'], '']);
30
- assert.deepStrictEqual(inspect(parser('![]{ }'), ctx), [['<span class="invalid">![]{ }</span>'], '']);
31
- assert.deepStrictEqual(inspect(parser('![]{ }'), ctx), [['<span class="invalid">![]{ }</span>'], '']);
30
+ assert.deepStrictEqual(inspect(parser('![]{ }'), ctx), undefined);
31
+ assert.deepStrictEqual(inspect(parser('![]{ }'), ctx), undefined);
32
32
  assert.deepStrictEqual(inspect(parser('![]]{/}'), ctx), undefined);
33
33
  assert.deepStrictEqual(inspect(parser('![]{{}'), ctx), undefined);
34
34
  assert.deepStrictEqual(inspect(parser('![]{}}'), ctx), undefined);
@@ -66,12 +66,11 @@ describe('Unit: parser/inline/media', () => {
66
66
  it('basic', () => {
67
67
  assert.deepStrictEqual(inspect(parser('![]{b}'), ctx), [['<a href="b" target="_blank"><img class="media" data-src="b" alt="b"></a>'], '']);
68
68
  assert.deepStrictEqual(inspect(parser('![]{b }'), ctx), [['<a href="b" target="_blank"><img class="media" data-src="b" alt="b"></a>'], '']);
69
- assert.deepStrictEqual(inspect(parser('![]{b }'), ctx), [['<a href="b" target="_blank"><img class="media" data-src="b" alt="b"></a>'], '']);
69
+ assert.deepStrictEqual(inspect(parser('![]{b }'), ctx), [['<span class="invalid">![]{b</span>'], ' }']);
70
70
  assert.deepStrictEqual(inspect(parser('![]{ b }'), ctx), [['<a href="b" target="_blank"><img class="media" data-src="b" alt="b"></a>'], '']);
71
- assert.deepStrictEqual(inspect(parser('![]{ b }'), ctx), [['<a href="b" target="_blank"><img class="media" data-src="b" alt="b"></a>'], '']);
72
- assert.deepStrictEqual(inspect(parser('![]{ b }'), ctx), [['<a href="b" target="_blank"><img class="media" data-src="b" alt="b"></a>'], '']);
73
- assert.deepStrictEqual(inspect(parser('![]{ b }'), ctx), [['<a href="b" target="_blank"><img class="media" data-src="b" alt="b"></a>'], '']);
74
- assert.deepStrictEqual(inspect(parser('![]{ b }'), ctx), [['<a href="b" target="_blank"><img class="media" data-src="b" alt="b"></a>'], '']);
71
+ assert.deepStrictEqual(inspect(parser('![]{ b }'), ctx), [['<span class="invalid">![]{ b</span>'], ' }']);
72
+ assert.deepStrictEqual(inspect(parser('![]{ b }'), ctx), undefined);
73
+ assert.deepStrictEqual(inspect(parser('![]{ b }'), ctx), undefined);
75
74
  assert.deepStrictEqual(inspect(parser('![]{"}'), ctx), [['<a href="&quot;" target="_blank"><img class="media" data-src="&quot;" alt="&quot;"></a>'], '']);
76
75
  assert.deepStrictEqual(inspect(parser('![]{"}"}'), ctx), [['<a href="&quot;" target="_blank"><img class="media" data-src="&quot;" alt="&quot;"></a>'], '"}']);
77
76
  assert.deepStrictEqual(inspect(parser('![]{\\}'), ctx), [['<a href="\\" target="_blank"><img class="media" data-src="\\" alt="\\"></a>'], '']);
@@ -40,7 +40,7 @@ export const media: MediaParser = lazy(() => constraint(State.media, creation(10
40
40
  dup(surround(
41
41
  /{(?![{}])/y,
42
42
  inits([uri, some(option)]),
43
- /[^\S\n]*}/y,
43
+ / ?}/y,
44
44
  false,
45
45
  undefined,
46
46
  ([as, bs], context) => {
@@ -87,7 +87,8 @@ export const media: MediaParser = lazy(() => constraint(State.media, creation(10
87
87
  el.setAttribute('alt', text);
88
88
  if (!sanitize(el, uri)) return [[el]];
89
89
  assert(!el.matches('.invalid'));
90
- define(el, attributes('media', optspec, params));
90
+ const [attrs, linkparams] = attributes('media', optspec, params);
91
+ define(el, attrs);
91
92
  assert(el.matches('img') || !el.matches('.invalid'));
92
93
  // Awaiting the generic support for attr().
93
94
  if (el.hasAttribute('aspect-ratio')) {
@@ -103,7 +104,7 @@ export const media: MediaParser = lazy(() => constraint(State.media, creation(10
103
104
  context.position = position;
104
105
  return [define(link, { class: null, target: '_blank' }, [el])];
105
106
  })
106
- (subinput(`{ ${INSECURE_URI}${params.join('')} }`, context));
107
+ (subinput(`{ ${INSECURE_URI}${linkparams.join('')} }`, context));
107
108
  })))));
108
109
 
109
110
  const bracket: MediaParser.TextParser.BracketParser = lazy(() => recursion(Recursion.terminal, union([
@@ -119,9 +120,9 @@ const bracket: MediaParser.TextParser.BracketParser = lazy(() => recursion(Recur
119
120
 
120
121
  const option: MediaParser.ParameterParser.OptionParser = lazy(() => union([
121
122
  surround(
122
- open(/[^\S\n]+/y, str(/[1-9][0-9]*/y)),
123
+ open(/ /y, str(/[1-9][0-9]*/y)),
123
124
  str(/[x:]/y),
124
- str(/[1-9][0-9]*(?=[^\S\n]|})/y),
125
+ str(/[1-9][0-9]*(?=[ }])/y),
125
126
  false,
126
127
  ([[a], [b], [c]]) => [
127
128
  b === 'x'
@@ -17,7 +17,7 @@ describe('Unit: parser/inline/reference', () => {
17
17
  assert.deepStrictEqual(inspect(parser('[[]]]'), ctx), undefined);
18
18
  assert.deepStrictEqual(inspect(parser('[["]]'), ctx), undefined);
19
19
  assert.deepStrictEqual(inspect(parser('[[(]]'), ctx), undefined);
20
- assert.deepStrictEqual(inspect(parser('[[<bdi>]]'), ctx), undefined);
20
+ assert.deepStrictEqual(inspect(parser('[[[%]]'), ctx), undefined);
21
21
  assert.deepStrictEqual(inspect(parser('[[ ]]'), ctx), undefined);
22
22
  assert.deepStrictEqual(inspect(parser('[[ [a'), ctx), undefined);
23
23
  assert.deepStrictEqual(inspect(parser('[[\n]]'), ctx), undefined);
@@ -31,7 +31,7 @@ describe('Unit: parser/inline/remark', () => {
31
31
  assert.deepStrictEqual(inspect(parser('[%\\ a %]'), ctx), undefined);
32
32
  assert.deepStrictEqual(inspect(parser('[% a\\ %]'), ctx), [['[%', ' a', ' ', '%', ']'], '']);
33
33
  assert.deepStrictEqual(inspect(parser('[% a%]'), ctx), [['[%', ' a', '%', ']'], '']);
34
- assert.deepStrictEqual(inspect(parser('[% a %%]'), ctx), [['[%', ' a', ' ', '%', '%', ']'], '']);
34
+ assert.deepStrictEqual(inspect(parser('[% a %%]'), ctx), [['[%', ' a %', '%', ']'], '']);
35
35
  assert.deepStrictEqual(inspect(parser('[% [%% %]'), ctx), [['<span class="remark"><input type="checkbox"><span>[% <span class="invalid">[%%</span> %]</span></span>'], '']);
36
36
  assert.deepStrictEqual(inspect(parser('[%% [% %%]'), ctx), [['<span class="invalid">[%%</span>'], ' [% %%]']);
37
37
  assert.deepStrictEqual(inspect(parser('[%% a %]'), ctx), [['<span class="invalid">[%%</span>'], ' a %]']);
@@ -43,7 +43,9 @@ describe('Unit: parser/inline/remark', () => {
43
43
  assert.deepStrictEqual(inspect(parser('[% %]'), ctx), [['<span class="remark"><input type="checkbox"><span>[% %]</span></span>'], '']);
44
44
  assert.deepStrictEqual(inspect(parser('[% %]'), ctx), [['<span class="remark"><input type="checkbox"><span>[% %]</span></span>'], '']);
45
45
  assert.deepStrictEqual(inspect(parser('[% a %]'), ctx), [['<span class="remark"><input type="checkbox"><span>[% a %]</span></span>'], '']);
46
+ assert.deepStrictEqual(inspect(parser('[% - %]'), ctx), [['<span class="remark"><input type="checkbox"><span>[% - %]</span></span>'], '']);
46
47
  assert.deepStrictEqual(inspect(parser('[% a %]'), ctx), [['<span class="remark"><input type="checkbox"><span>[% a %]</span></span>'], '']);
48
+ assert.deepStrictEqual(inspect(parser('[% - %]'), ctx), [['<span class="remark"><input type="checkbox"><span>[% - %]</span></span>'], '']);
47
49
  assert.deepStrictEqual(inspect(parser('[% a b %]'), ctx), [['<span class="remark"><input type="checkbox"><span>[% a b %]</span></span>'], '']);
48
50
  assert.deepStrictEqual(inspect(parser('[% a\nb %]'), ctx), [['<span class="remark"><input type="checkbox"><span>[% a<br>b %]</span></span>'], '']);
49
51
  assert.deepStrictEqual(inspect(parser('[% a %] %]'), ctx), [['<span class="remark"><input type="checkbox"><span>[% a %]</span></span>'], ' %]']);
@@ -9,8 +9,8 @@ import { html, defrag } from 'typed-dom/dom';
9
9
 
10
10
  export const remark: RemarkParser = lazy(() => fallback(surround(
11
11
  str(/\[%(?=\s)/y),
12
- precedence(4, recursion(Recursion.inline,
13
- some(union([inline]), /\s%\]/y, [[/\s%\]/y, 4]]))),
12
+ precedence(3, recursion(Recursion.inline,
13
+ some(union([inline]), /\s%\]/y, [[/\s%\]/y, 3]]))),
14
14
  close(text, str(`%]`)), true,
15
15
  ([as, bs = [], cs]) => [[
16
16
  html('span', { class: 'remark' }, [
@@ -39,6 +39,7 @@ describe('Unit: parser/inline/strong', () => {
39
39
 
40
40
  it('nest', () => {
41
41
  assert.deepStrictEqual(inspect(parser('**a *b***'), ctx), [['<strong>a <em>b</em></strong>'], '']);
42
+ assert.deepStrictEqual(inspect(parser('**- *b***'), ctx), [['<strong>- <em>b</em></strong>'], '']);
42
43
  assert.deepStrictEqual(inspect(parser('**a **b****'), ctx), [['<strong>a <strong>b</strong></strong>'], '']);
43
44
  assert.deepStrictEqual(inspect(parser('**a&Tab;**b****'), ctx), [['<strong>a\t<strong>b</strong></strong>'], '']);
44
45
  assert.deepStrictEqual(inspect(parser('**a<wbr>**b****'), ctx), [['<strong>a<wbr><strong>b</strong></strong>'], '']);
@@ -34,7 +34,7 @@ const bracket: TemplateParser.BracketParser = lazy(() => union([
34
34
  undefined, () => [[]], [3 | Backtrack.escbracket]),
35
35
  surround(
36
36
  str('"'),
37
- precedence(2, recursion(Recursion.terminal, some(escsource, '"', [['"', 2, false]]))),
37
+ precedence(2, recursion(Recursion.terminal, some(escsource, /["\n]/y, [['"', 2], ['\n', 3]]))),
38
38
  str('"'),
39
39
  true,
40
40
  ([as, bs = [], cs], context) =>
@@ -22,7 +22,7 @@ describe('Unit: parser/inline', () => {
22
22
  it('nest', () => {
23
23
  assert.deepStrictEqual(inspect(parser('あ(A)'), ctx), [['あ', '(', 'A', ')'], '']);
24
24
  assert.deepStrictEqual(inspect(parser('あ(い)'), ctx), [['あ', '<span class="paren">(い)</span>'], '']);
25
- assert.deepStrictEqual(inspect(parser('* a*'), ctx), [['*', ' a', '*'], '']);
25
+ assert.deepStrictEqual(inspect(parser('* a*'), ctx), [['* a', '*'], '']);
26
26
  assert.deepStrictEqual(inspect(parser('** a**'), ctx), [['**', ' a', '**'], '']);
27
27
  assert.deepStrictEqual(inspect(parser('*** a***'), ctx), [['***', ' a', '***'], '']);
28
28
  assert.deepStrictEqual(inspect(parser('**** a****'), ctx), [['****', ' a', '****'], '']);
@@ -82,19 +82,19 @@ describe('Unit: parser/inline', () => {
82
82
  assert.deepStrictEqual(inspect(parser('*++ a ++*'), ctx), [['<em><ins> a </ins></em>'], '']);
83
83
  assert.deepStrictEqual(inspect(parser('*++ a ++*'), ctx), [['<em><ins> a </ins></em>'], '']);
84
84
  assert.deepStrictEqual(inspect(parser('*<bdi>`a`</bdi>*'), ctx), [['<em><bdi><code data-src="`a`">a</code></bdi></em>'], '']);
85
- assert.deepStrictEqual(inspect(parser('*a"\nb*'), ctx), [['*', 'a', '"', '<br>', 'b', '*'], '']);
85
+ assert.deepStrictEqual(inspect(parser('*a"\nb*'), ctx), [['<em>a"<br>b</em>'], '']);
86
86
  assert.deepStrictEqual(inspect(parser('*a"\n"("b*'), ctx), [['<em>a"<br>"("b</em>'], '']);
87
- assert.deepStrictEqual(inspect(parser('"*a\nb*'), ctx), [['"', '<em>a<br>b</em>'], '']);
88
- assert.deepStrictEqual(inspect(parser('"*a\n""b*'), ctx), [['"', '<em>a<br>""b</em>'], '']);
87
+ assert.deepStrictEqual(inspect(parser('"*a\nb*'), ctx), [['"', '*', 'a', '<br>', 'b', '*'], '']);
88
+ assert.deepStrictEqual(inspect(parser('"*a\n""b*'), ctx), [['"', '*', 'a', '<br>', '"', '"', 'b', '*'], '']);
89
89
  assert.deepStrictEqual(inspect(parser('"a\n"*b"c*'), ctx), [['"', 'a', '<br>', '"', '*', 'b', '"', 'c', '*'], '']);
90
- assert.deepStrictEqual(inspect(parser('"*a**b\nc**"("*'), ctx), [['"', '<em>a<strong>b<br>c</strong>"("</em>'], '']);
91
- assert.deepStrictEqual(inspect(parser('<bdi>a"\nb</bdi>'), ctx), [['<bdi>a"<br>b</bdi>'], '']);
92
- assert.deepStrictEqual(inspect(parser('"<bdi>"a\n""b</bdi>"'), ctx), [['"', '<bdi>"a<br>""b</bdi>', '"'], '']);
90
+ assert.deepStrictEqual(inspect(parser('"*a**b\nc**"("*'), ctx), [['"', '*', 'a', '**', 'b', '<br>', 'c', '**', '"', '(', '"', '*'], '']);
91
+ assert.deepStrictEqual(inspect(parser('[% a"\nb %]'), ctx), [['<span class="remark"><input type="checkbox"><span>[% a"<br>b %]</span></span>'], '']);
92
+ assert.deepStrictEqual(inspect(parser('"<bdi>"a\n""b</bdi>"'), ctx), [['"', '<span class="invalid">&lt;bdi&gt;</span>', '"', 'a', '<br>', '"', '"', 'b', '</bdi', '>', '"'], '']);
93
93
  assert.deepStrictEqual(inspect(parser('<bdi>*<bdi>a</bdi>*</bdi>'), ctx), [['<bdi><em><bdi>a</bdi></em></bdi>'], '']);
94
94
  assert.deepStrictEqual(inspect(parser('<bdi>((<bdi>((a))</bdi>))</bdi>'), ctx), [['<bdi><sup class="annotation"><span><bdi><span class="paren">((a))</span></bdi></span></sup></bdi>'], '']);
95
95
  assert.deepStrictEqual(inspect(parser('<bdi>[[<bdi>[[a]]</bdi>]]</bdi>'), ctx), [['<bdi><sup class="reference"><span><bdi>[[a]]</bdi></span></sup></bdi>'], '']);
96
- assert.deepStrictEqual(inspect(parser('<bdi>[#</bdi>]'), ctx), [['<bdi>[#</bdi>', ']'], '']);
97
- assert.deepStrictEqual(inspect(parser('"<bdi>("")</bdi>'), ctx), [['"', '<bdi><span class="paren">("")</span></bdi>'], '']);
96
+ assert.deepStrictEqual(inspect(parser('<bdi>[#</bdi>]'), ctx), [['<span class="invalid">&lt;bdi&gt;[#&lt;/bdi&gt;]</span>'], '']);
97
+ assert.deepStrictEqual(inspect(parser('"<bdi>("")</bdi>'), ctx), [['"', '<span class="invalid">&lt;bdi&gt;(</span>', '"', '"', ')', '</bdi', '>'], '']);
98
98
  assert.deepStrictEqual(inspect(parser('++\na\n++\n~~\nb\n~~\nc'), ctx), [['<ins><br>a</ins>', '<br>', '<del><br>b</del>', '<br>', 'c'], '']);
99
99
  assert.deepStrictEqual(inspect(parser('[@a]'), ctx), [['[', '<a class="account" href="/@a">@a</a>', ']'], '']);
100
100
  assert.deepStrictEqual(inspect(parser('[#1][#2]'), ctx), [['<a class="index" href="#index::1">1</a>', '<a class="index" href="#index::2">2</a>'], '']);
@@ -121,11 +121,11 @@ describe('Unit: parser/inline', () => {
121
121
  assert.deepStrictEqual(inspect(parser('{}'), ctx), [['{', '}'], '']);
122
122
  assert.deepStrictEqual(inspect(parser('{a}'), ctx), [['<a class="url" href="a">a</a>'], '']);
123
123
  assert.deepStrictEqual(inspect(parser('{{a}}'), ctx), [['<span class="template">{{a}}</span>'], '']);
124
- assert.deepStrictEqual(inspect(parser('\r!{}'), ctx), [['!', '{', '}'], '']);
125
- assert.deepStrictEqual(inspect(parser('\r!{a}'), ctx), [['!', '<a class="url" href="a">a</a>'], '']);
126
- assert.deepStrictEqual(inspect(parser('\r!{{a}}'), ctx), [['!', '<span class="template">{{a}}</span>'], '']);
127
- assert.deepStrictEqual(inspect(parser('\r!{{{a}}}'), ctx), [['!', '<span class="template">{{{a}}}</span>'], '']);
128
- assert.deepStrictEqual(inspect(parser('\r!!{a}'), ctx), [['!', '!', '<a class="url" href="a">a</a>'], '']);
124
+ assert.deepStrictEqual(inspect(parser('!{}'), ctx), [['!', '{', '}'], '']);
125
+ assert.deepStrictEqual(inspect(parser('!{a}'), ctx), [['!', '<a class="url" href="a">a</a>'], '']);
126
+ assert.deepStrictEqual(inspect(parser('!{{a}}'), ctx), [['!', '<span class="template">{{a}}</span>'], '']);
127
+ assert.deepStrictEqual(inspect(parser('!{{{a}}}'), ctx), [['!', '<span class="template">{{{a}}}</span>'], '']);
128
+ assert.deepStrictEqual(inspect(parser('!!{a}'), ctx), [['!', '!', '<a class="url" href="a">a</a>'], '']);
129
129
  assert.deepStrictEqual(inspect(parser('${a}'), ctx), [['$', '<a class="url" href="a">a</a>'], '']);
130
130
  assert.deepStrictEqual(inspect(parser('${{a}}'), ctx), [['$', '<span class="template">{{a}}</span>'], '']);
131
131
  assert.deepStrictEqual(inspect(parser('${{{a}}}'), ctx), [['$', '<span class="template">{{{a}}}</span>'], '']);
@@ -167,8 +167,8 @@ describe('Unit: parser/inline', () => {
167
167
  assert.deepStrictEqual(inspect(parser('"{{""}}'), ctx), [['"', '{', '{', '"', '"', '}', '}'], '']);
168
168
  assert.deepStrictEqual(inspect(parser('[#http://host/(<bdi>)]</bdi>'), ctx), [['<a class="index" href="#index::http://host/(&lt;bdi&gt;)">http://host/(&lt;bdi&gt;)</a>', '</bdi', '>'], '']);
169
169
  assert.deepStrictEqual(inspect(parser('[#@a/http://host/(<bdi>)]</bdi>'), ctx), [['<a class="index" href="#index::@a/http://host/(&lt;bdi&gt;)">@a/http://host/(&lt;bdi&gt;)</a>', '</bdi', '>'], '']);
170
- assert.deepStrictEqual(inspect(parser('[#a|<bdi>]</bdi>'), ctx), [['[', '<a class="hashtag" href="/hashtags/a">#a</a>', '|', '<bdi>]</bdi>'], '']);
171
- assert.deepStrictEqual(inspect(parser('[[#a|<bdi>]</bdi>'), ctx), [['[', '[', '<a class="hashtag" href="/hashtags/a">#a</a>', '|', '<bdi>]</bdi>'], '']);
170
+ assert.deepStrictEqual(inspect(parser('[#a|<bdi>]</bdi>'), ctx), [['<a class="index" href="#index::a|&lt;bdi&gt;">a|<span class="invalid">&lt;bdi&gt;</span></a>', '</bdi', '>'], '']);
171
+ assert.deepStrictEqual(inspect(parser('[[#a|<bdi>]</bdi>'), ctx), [['[', '<a class="index" href="#index::a|&lt;bdi&gt;">a|<span class="invalid">&lt;bdi&gt;</span></a>', '</bdi', '>'], '']);
172
172
  });
173
173
 
174
174
  it('uri', () => {