securemark 0.293.3 → 0.293.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.
Files changed (36) hide show
  1. package/CHANGELOG.md +8 -0
  2. package/dist/index.js +125 -141
  3. package/package.json +1 -1
  4. package/src/combinator/control/manipulation/surround.ts +2 -2
  5. package/src/combinator/data/parser/context.test.ts +10 -9
  6. package/src/combinator/data/parser/context.ts +2 -1
  7. package/src/combinator/data/parser.ts +0 -3
  8. package/src/parser/api/bind.ts +3 -3
  9. package/src/parser/api/normalize.ts +1 -3
  10. package/src/parser/api/parse.ts +1 -1
  11. package/src/parser/block/dlist.test.ts +1 -1
  12. package/src/parser/block/heading.test.ts +1 -0
  13. package/src/parser/block/olist.test.ts +1 -0
  14. package/src/parser/block/reply/quote.ts +6 -6
  15. package/src/parser/block/reply.ts +3 -2
  16. package/src/parser/block/ulist.test.ts +1 -0
  17. package/src/parser/header.test.ts +3 -1
  18. package/src/parser/header.ts +2 -2
  19. package/src/parser/inline/emphasis.test.ts +1 -0
  20. package/src/parser/inline/html.test.ts +3 -3
  21. package/src/parser/inline/html.ts +9 -9
  22. package/src/parser/inline/italic.test.ts +1 -0
  23. package/src/parser/inline/link.test.ts +10 -8
  24. package/src/parser/inline/link.ts +17 -17
  25. package/src/parser/inline/mark.test.ts +1 -0
  26. package/src/parser/inline/media.test.ts +6 -7
  27. package/src/parser/inline/media.ts +3 -3
  28. package/src/parser/inline/remark.test.ts +3 -1
  29. package/src/parser/inline/strong.test.ts +1 -0
  30. package/src/parser/source/escapable.test.ts +1 -0
  31. package/src/parser/source/escapable.ts +3 -11
  32. package/src/parser/source/text.test.ts +5 -4
  33. package/src/parser/source/text.ts +90 -94
  34. package/src/parser/source/unescapable.test.ts +1 -0
  35. package/src/parser/source/unescapable.ts +5 -8
  36. package/src/parser/util.ts +0 -19
@@ -1,5 +1,4 @@
1
1
  import { Delimiters } from './parser/context/delimiter';
2
- import { MarkdownParser } from '../../../markdown';
3
2
 
4
3
  export type Parser<N, C extends CtxOptions = CtxOptions, D extends Parser<unknown, C>[] = any>
5
4
  = (input: Input<C & Ctx>) => Result<N, C, D>;
@@ -38,8 +37,6 @@ export type IntermediateParser<P extends Parser<unknown>> = Parser<SubNode<P>, C
38
37
  type ExtractSubNode<D extends Parser<unknown>[]> = ExtractSubParser<D> extends infer N ? N extends Parser<infer U> ? U : never : never;
39
38
  type ExtractSubParser<D extends Parser<unknown>[]> = D extends (infer P)[] ? P extends Parser<unknown> ? P : never : never;
40
39
 
41
- export function input(source: string, context: CtxOptions): Input<Ctx>;
42
- export function input(source: string, context: MarkdownParser.Options): Input<MarkdownParser.Context>;
43
40
  export function input(source: string, context: CtxOptions): Input<Ctx> {
44
41
  // @ts-expect-error
45
42
  context.source = source;
@@ -1,7 +1,7 @@
1
1
  import { ParserSettings, Progress } from '../../..';
2
2
  import { MarkdownParser } from '../../../markdown';
3
3
  import { input, eval } from '../../combinator/data/parser';
4
- import { segment, validate, MAX_INPUT_SIZE } from '../segment';
4
+ import { segment } from '../segment';
5
5
  import { header } from '../header';
6
6
  import { block } from '../block';
7
7
  import { normalize } from './normalize';
@@ -44,7 +44,7 @@ export function bind(target: DocumentFragment | HTMLElement | ShadowRoot, settin
44
44
  function* parse(source: string): Generator<Progress, undefined, undefined> {
45
45
  if (settings.chunk && revision) throw new Error('Chunks cannot be updated');
46
46
  const url = headers(source).find(field => field.toLowerCase().startsWith('url:'))?.slice(4).trim() ?? '';
47
- source = normalize(validate(source, MAX_INPUT_SIZE) ? source : source.slice(0, MAX_INPUT_SIZE + 1));
47
+ source = normalize(source);
48
48
  // Change the object identity.
49
49
  context = {
50
50
  ...context,
@@ -78,7 +78,7 @@ export function bind(target: DocumentFragment | HTMLElement | ShadowRoot, settin
78
78
  for (; index < sourceSegments.length - last; ++index) {
79
79
  assert(rev === revision);
80
80
  const seg = sourceSegments[index];
81
- const es = eval(header(input(seg, { header: index === 0 })) || block(input(seg, context)), []);
81
+ const es = eval(header(input(seg, { header: index === 0 } as MarkdownParser.Context)) || block(input(seg, context)), []);
82
82
  blocks.splice(index, 0, [seg, es, url]);
83
83
  if (es.length === 0) continue;
84
84
  // All deletion processes always run after all addition processes have done.
@@ -63,9 +63,7 @@ const unreadableEscapableCharacters = unreadableHTMLEntityNames
63
63
  .map(name => eval(unsafehtmlentity(input(`&${name};`, {})))![0]);
64
64
  assert(unreadableEscapableCharacters.length === unreadableHTMLEntityNames.length);
65
65
  assert(unreadableEscapableCharacters.every(c => c.length === 1));
66
- const unreadableEscapableCharacter = new RegExp(`[${
67
- [...new Set<string>(unreadableEscapableCharacters)].join('')
68
- }]`, 'g');
66
+ const unreadableEscapableCharacter = new RegExp(`[${unreadableEscapableCharacters.join('')}]`, 'g');
69
67
  assert(!unreadableEscapableCharacter.source.includes('&'));
70
68
 
71
69
  // https://www.pandanoir.info/entry/2018/03/11/193000
@@ -34,7 +34,7 @@ export function parse(source: string, opts: Options = {}, context?: MarkdownPars
34
34
  const node = frag();
35
35
  let index = 0;
36
36
  for (const seg of segment(source)) {
37
- node.append(...eval(header(input(seg, { header: index++ === 0 })) || block(input(seg, context)), []));
37
+ node.append(...eval(header(input(seg, { header: index++ === 0 } as MarkdownParser.Context)) || block(input(seg, context)), []));
38
38
  }
39
39
  assert(opts.id !== '' || !node.querySelector('[id], .index[href], .label[href], .annotation > a[href], .reference > a[href]'));
40
40
  if (opts.test) return node;
@@ -69,7 +69,7 @@ describe('Unit: parser/block/dlist', () => {
69
69
  it('indexer', () => {
70
70
  assert.deepStrictEqual(inspect(parser('~ a [|b]'), ctx), [['<dl><dt id="index::b">a<span class="indexer" data-index="b"></span></dt><dd></dd></dl>'], '']);
71
71
  assert.deepStrictEqual(inspect(parser('~ a [|b]\\'), ctx), [['<dl><dt id="index::a_[|b]">a <span class="invalid">[|b]</span></dt><dd></dd></dl>'], '']);
72
- assert.deepStrictEqual(inspect(parser('~ A'), ctx), [['<dl><dt id="index::A">A</dt><dd></dd></dl>'], '']);
72
+ assert.deepStrictEqual(inspect(parser('~ - [|b]'), ctx), [['<dl><dt id="index::b">-<span class="indexer" data-index="b"></span></dt><dd></dd></dl>'], '']);
73
73
  assert.deepStrictEqual(inspect(parser('~ *A*'), ctx), [['<dl><dt id="index::A"><em>A</em></dt><dd></dd></dl>'], '']);
74
74
  assert.deepStrictEqual(inspect(parser('~ `A`'), ctx), [['<dl><dt id="index::`A`"><code data-src="`A`">A</code></dt><dd></dd></dl>'], '']);
75
75
  assert.deepStrictEqual(inspect(parser('~ ${A}$'), ctx), [['<dl><dt id="index::${A}$"><span class="math" translate="no" data-src="${A}$">${A}$</span></dt><dd></dd></dl>'], '']);
@@ -79,6 +79,7 @@ describe('Unit: parser/block/heading', () => {
79
79
  assert.deepStrictEqual(inspect(parser('# a [|b] [|c]'), ctx), [['<h1 id="index::c">a <span class="invalid">[|b]</span><span class="indexer" data-index="c"></span></h1>'], '']);
80
80
  assert.deepStrictEqual(inspect(parser('# a [|b] \n'), ctx), [['<h1 id="index::b">a<span class="indexer" data-index="b"></span></h1>'], '']);
81
81
  assert.deepStrictEqual(inspect(parser('# a \\[|b]'), ctx), [['<h1 id="index::a_[|b]">a [|b]</h1>'], '']);
82
+ assert.deepStrictEqual(inspect(parser('# - [|b]'), ctx), [['<h1 id="index::b">-<span class="indexer" data-index="b"></span></h1>'], '']);
82
83
  assert.deepStrictEqual(inspect(parser('## a [|b] [|c]'), ctx), [['<h2 id="index::c">a <span class="invalid">[|b]</span><span class="indexer" data-index="c"></span></h2>'], '']);
83
84
  });
84
85
 
@@ -138,6 +138,7 @@ describe('Unit: parser/block/olist', () => {
138
138
  assert.deepStrictEqual(inspect(parser('1. [|a]'), ctx), [['<ol><li id="index::[|a]"><span class="invalid">[|a]</span></li></ol>'], '']);
139
139
  assert.deepStrictEqual(inspect(parser('1. a [|]'), ctx), [['<ol><li>a<span class="indexer" data-index=""></span></li></ol>'], '']);
140
140
  assert.deepStrictEqual(inspect(parser('1. a [|b]'), ctx), [['<ol><li id="index::b">a<span class="indexer" data-index="b"></span></li></ol>'], '']);
141
+ assert.deepStrictEqual(inspect(parser('1. - [|]'), ctx), [['<ol><li>-<span class="indexer" data-index=""></span></li></ol>'], '']);
141
142
  assert.deepStrictEqual(inspect(parser('1. [ ] [|a]'), ctx), [['<ol class="checklist"><li id="index::[|a]"><span class="checkbox">☐</span><span class="invalid">[|a]</span></li></ol>'], '']);
142
143
  assert.deepStrictEqual(inspect(parser('1. [ ] a [|b]'), ctx), [['<ol class="checklist"><li id="index::b"><span class="checkbox">☐</span>a<span class="indexer" data-index="b"></span></li></ol>'], '']);
143
144
  assert.deepStrictEqual(inspect(parser('1. a [|]\n 1. c [|d]'), ctx), [['<ol><li>a<span class="indexer" data-index=""></span><ol><li id="index::d">c<span class="indexer" data-index="d"></span></li></ol></li></ol>'], '']);
@@ -3,7 +3,6 @@ import { union, some, block, validate, rewrite, convert, lazy, fmap } from '../.
3
3
  import { math } from '../../inline/math';
4
4
  import { autolink } from '../../inline/autolink';
5
5
  import { linebreak, unescsource, anyline } from '../../source';
6
- import { linearize } from '../../util';
7
6
  import { html, defrag } from 'typed-dom/dom';
8
7
 
9
8
  export const syntax = />+[^\S\n]/y;
@@ -11,7 +10,8 @@ export const syntax = />+[^\S\n]/y;
11
10
  export const quote: ReplyParser.QuoteParser = lazy(() => block(fmap(
12
11
  rewrite(
13
12
  some(validate(syntax, anyline)),
14
- linearize(convert(
13
+ convert(
14
+ // TODO: インデント数を渡してインデント数前の行頭確認を行う実装に置き換える
15
15
  source => source.replace(/(?<=^>+[^\S\n])/mg, '\r'),
16
16
  some(union([
17
17
  // quote補助関数が残した数式をパースする。
@@ -20,9 +20,9 @@ export const quote: ReplyParser.QuoteParser = lazy(() => block(fmap(
20
20
  linebreak,
21
21
  unescsource,
22
22
  ])),
23
- false), -1)),
24
- (ns: [string, ...(string | HTMLElement)[]]) => [
23
+ false)),
24
+ (ns: [string, ...(string | HTMLElement)[]], { source, position }) => [
25
+ source[position - 1] === '\n' ? ns.pop() as HTMLBRElement : html('br'),
25
26
  html('span', { class: 'quote' }, defrag(ns)),
26
- html('br'),
27
- ]),
27
+ ].reverse()),
28
28
  false));
@@ -4,8 +4,8 @@ import { cite, syntax as csyntax } from './reply/cite';
4
4
  import { quote, syntax as qsyntax } from './reply/quote';
5
5
  import { inline } from '../inline';
6
6
  import { anyline } from '../source';
7
- import { linearize } from '../util';
8
7
  import { visualize, trimBlankNodeEnd } from '../visibility';
8
+ import { push } from 'spica/array';
9
9
  import { html, defrag } from 'typed-dom/dom';
10
10
 
11
11
  const delimiter = new RegExp(`${csyntax.source}|${qsyntax.source}`, 'y');
@@ -16,6 +16,7 @@ export const reply: ReplyParser = block(validate(csyntax, fmap(
16
16
  quote,
17
17
  rewrite(
18
18
  some(anyline, delimiter),
19
- visualize(linearize(some(inline), 1))),
19
+ visualize(fmap(some(inline), (ns, { source, position }) =>
20
+ source[position - 1] === '\n' ? ns : push(ns, [html('br')])))),
20
21
  ])),
21
22
  ns => [html('p', trimBlankNodeEnd(defrag(ns)))])));
@@ -75,6 +75,7 @@ describe('Unit: parser/block/ulist', () => {
75
75
  assert.deepStrictEqual(inspect(parser('- [|a]'), ctx), [['<ul><li id="index::[|a]"><span class="invalid">[|a]</span></li></ul>'], '']);
76
76
  assert.deepStrictEqual(inspect(parser('- a [|]'), ctx), [['<ul><li>a<span class="indexer" data-index=""></span></li></ul>'], '']);
77
77
  assert.deepStrictEqual(inspect(parser('- a [|b]'), ctx), [['<ul><li id="index::b">a<span class="indexer" data-index="b"></span></li></ul>'], '']);
78
+ assert.deepStrictEqual(inspect(parser('- - [|b]'), ctx), [['<ul><li id="index::b">-<span class="indexer" data-index="b"></span></li></ul>'], '']);
78
79
  assert.deepStrictEqual(inspect(parser('- [ ] [|a]'), ctx), [['<ul class="checklist"><li id="index::[|a]"><span class="checkbox">☐</span><span class="invalid">[|a]</span></li></ul>'], '']);
79
80
  assert.deepStrictEqual(inspect(parser('- [ ] a [|b]'), ctx), [['<ul class="checklist"><li id="index::b"><span class="checkbox">☐</span>a<span class="indexer" data-index="b"></span></li></ul>'], '']);
80
81
  assert.deepStrictEqual(inspect(parser('- a [|]\n - c [|d]'), ctx), [['<ul><li>a<span class="indexer" data-index=""></span><ul><li id="index::d">c<span class="indexer" data-index="d"></span></li></ul></li></ul>'], '']);
@@ -21,7 +21,8 @@ describe('Unit: parser/header', () => {
21
21
  assert.deepStrictEqual(inspect(parser('---\n\n---'), ctx), undefined);
22
22
  assert.deepStrictEqual(inspect(parser('---\n \n---'), ctx), undefined);
23
23
  assert.deepStrictEqual(inspect(parser('---\n-\n---'), ctx), [['<pre class="invalid" translate="no">---\n-\n---</pre>'], '']);
24
- assert.deepStrictEqual(inspect(parser('----\na: b\n----'), ctx), [['<pre class="invalid" translate="no">----\na: b\n----</pre>'], '']);
24
+ assert.deepStrictEqual(inspect(parser('---\na: b\n----'), ctx), [['<pre class="invalid" translate="no">---\na: b\n----</pre>'], '']);
25
+ assert.deepStrictEqual(inspect(parser('----\na: b\n---'), ctx), [['<pre class="invalid" translate="no">----\na: b\n---</pre>'], '']);
25
26
  assert.deepStrictEqual(inspect(parser(`---\n${'a: b\n'.repeat(101)}---`), ctx), [[`<pre class="invalid" translate="no">---\n${'a: b\n'.repeat(101)}---</pre>`], '']);
26
27
  });
27
28
 
@@ -30,6 +31,7 @@ describe('Unit: parser/header', () => {
30
31
  assert.deepStrictEqual(inspect(parser('---\na: b\n---\n'), ctx), [['<aside class="header"><details open=""><summary>Header</summary><span class="field" data-name="a" data-value="b"><span class="field-name">a</span>: <span class="field-value">b</span>\n</span></details></aside>'], '']);
31
32
  assert.deepStrictEqual(inspect(parser('---\na: b\nC: D e\n---\n'), ctx), [['<aside class="header"><details open=""><summary>Header</summary><span class="field" data-name="a" data-value="b"><span class="field-name">a</span>: <span class="field-value">b</span>\n</span><span class="field" data-name="c" data-value="D e"><span class="field-name">C</span>: <span class="field-value">D e</span>\n</span></details></aside>'], '']);
32
33
  assert.deepStrictEqual(inspect(parser('--- \r\na: b \r\n--- \r\n \r\n \r\na'), ctx), [['<aside class="header"><details open=""><summary>Header</summary><span class="field" data-name="a" data-value="b"><span class="field-name">a</span>: <span class="field-value">b</span>\n</span></details></aside>'], ' \r\na']);
34
+ assert.deepStrictEqual(inspect(parser('----\na: b\n----'), ctx), [['<aside class="header"><details open=""><summary>Header</summary><span class="field" data-name="a" data-value="b"><span class="field-name">a</span>: <span class="field-value">b</span>\n</span></details></aside>'], '']);
33
35
  });
34
36
 
35
37
  });
@@ -7,7 +7,7 @@ import { normalize } from './api/normalize';
7
7
  import { html, defrag } from 'typed-dom/dom';
8
8
 
9
9
  export const header: MarkdownParser.HeaderParser = lazy(() => validate(
10
- /---+[^\S\v\f\r\n]*\r?\n[^\S\n]*(?=\S)/y,
10
+ /---+[^\S\v\f\r\n]*\r?\n(?=\S)/y,
11
11
  inits([
12
12
  rewrite(
13
13
  ({ context }) => {
@@ -23,7 +23,7 @@ export const header: MarkdownParser.HeaderParser = lazy(() => validate(
23
23
  block(
24
24
  union([
25
25
  validate(({ context }) => context.header ?? true,
26
- focus(/---[^\S\v\f\r\n]*\r?\n(?:[A-Za-z][0-9A-Za-z]*(?:-[A-Za-z][0-9A-Za-z]*)*:[ \t]+\S[^\v\f\r\n]*\r?\n){1,100}---[^\S\v\f\r\n]*(?:$|\r?\n)/y,
26
+ focus(/(---+)[^\S\v\f\r\n]*\r?\n(?:[A-Za-z][0-9A-Za-z]*(?:-[A-Za-z][0-9A-Za-z]*)*:[ \t]+\S[^\v\f\r\n]*\r?\n){1,100}\1[^\S\v\f\r\n]*(?:$|\r?\n)/y,
27
27
  convert(source =>
28
28
  normalize(source.slice(source.indexOf('\n') + 1, source.trimEnd().lastIndexOf('\n'))).replace(/(\S)\s+$/mg, '$1'),
29
29
  fmap(
@@ -40,6 +40,7 @@ describe('Unit: parser/inline/emphasis', () => {
40
40
 
41
41
  it('nest', () => {
42
42
  assert.deepStrictEqual(inspect(parser('*a *b**'), ctx), [['<em>a <em>b</em></em>'], '']);
43
+ assert.deepStrictEqual(inspect(parser('*- *b**'), ctx), [['<em>- <em>b</em></em>'], '']);
43
44
  assert.deepStrictEqual(inspect(parser('*a **b***'), ctx), [['<em>a <strong>b</strong></em>'], '']);
44
45
  assert.deepStrictEqual(inspect(parser('*a\\ *b**'), ctx), [['<em>a <em>b</em></em>'], '']);
45
46
  assert.deepStrictEqual(inspect(parser('*a&Tab;*b**'), ctx), [['<em>a\t<em>b</em></em>'], '']);
@@ -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>'], '']);
@@ -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,14 @@ 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
45
  // 不可視のHTML構造が可視構造を変化させるべきでない。
46
46
  // 可視のHTMLは優先度変更を検討する。
47
47
  // このため<>は将来的に共通構造を変化させる可能性があり
48
- // 共通構造を変更させない非構造文字列としては依然としてエスケープを要する。
48
+ // 共通構造を変化させない非構造文字列としては依然としてエスケープを要する。
49
49
  precedence(0, recursion(Recursion.inline,
50
50
  some(union([
51
51
  some(inline, blankWith('\n', `</${tag}>`)),
@@ -61,9 +61,9 @@ export const html: HTMLParser = lazy(() => validate(/<[a-z]+(?=[^\S\n]|>)/yi,
61
61
  new Map())),
62
62
  surround(
63
63
  // https://html.spec.whatwg.org/multipage/syntax.html#void-elements
64
- str(/<[a-z]+(?=[^\S\n]|>)/yi),
64
+ str(/<[a-z]+(?=[ >])/yi),
65
65
  some(union([attribute])),
66
- open(str(/[^\S\n]*/y), str('>'), true),
66
+ open(str(/ ?/y), str('>'), true),
67
67
  true,
68
68
  ([as, bs = [], cs], context) =>
69
69
  [[elem(as[0].slice(1), false, push(unshift(as, bs), cs), [], [], context)]],
@@ -72,8 +72,8 @@ export const html: HTMLParser = lazy(() => validate(/<[a-z]+(?=[^\S\n]|>)/yi,
72
72
  ])));
73
73
 
74
74
  export const attribute: HTMLParser.AttributeParser = union([
75
- str(/[^\S\n]+[a-z]+(?:-[a-z]+)*(?:="(?:\\[^\n]|[^\\\n"])*")?(?=[^\S\n]|>)/yi),
76
- str(/[^\S\n]+[^\s<>]+/y),
75
+ str(/ [a-z]+(?:-[a-z]+)*(?:="(?:\\[^\n]|[^\\\n"])*")?(?=[ >])/yi),
76
+ str(/ [^\s<>]+/y),
77
77
  ]);
78
78
 
79
79
  function elem(tag: string, content: boolean, as: string[], bs: (HTMLElement | string)[], cs: string[], context: Ctx): HTMLElement {
@@ -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(
@@ -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>'], '']);
@@ -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) => {
@@ -120,9 +120,9 @@ const bracket: MediaParser.TextParser.BracketParser = lazy(() => recursion(Recur
120
120
 
121
121
  const option: MediaParser.ParameterParser.OptionParser = lazy(() => union([
122
122
  surround(
123
- open(/[^\S\n]+/y, str(/[1-9][0-9]*/y)),
123
+ open(/ /y, str(/[1-9][0-9]*/y)),
124
124
  str(/[x:]/y),
125
- str(/[1-9][0-9]*(?=[^\S\n]|})/y),
125
+ str(/[1-9][0-9]*(?=[ }])/y),
126
126
  false,
127
127
  ([[a], [b], [c]]) => [
128
128
  b === 'x'
@@ -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>'], ' %]']);
@@ -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>'], '']);
@@ -15,6 +15,7 @@ describe('Unit: parser/source/escsource', () => {
15
15
  it('basic', () => {
16
16
  assert.deepStrictEqual(inspect(parser('a'), ctx), [['a'], '']);
17
17
  assert.deepStrictEqual(inspect(parser('ab'), ctx), [['ab'], '']);
18
+ assert.deepStrictEqual(inspect(parser('a b c'), ctx), [['a b c'], '']);
18
19
  assert.deepStrictEqual(inspect(parser('09あいAZaz'), ctx), [['09あいAZaz'], '']);
19
20
  });
20
21
 
@@ -1,10 +1,10 @@
1
1
  import { EscapableSourceParser } from '../source';
2
2
  import { Command } from '../context';
3
3
  import { consume } from '../../combinator';
4
- import { nonWhitespace, isBlank, next } from './text';
4
+ import { next } from './text';
5
5
  import { html } from 'typed-dom/dom';
6
6
 
7
- const delimiter = /(?=[\\$"`\[\](){}\r\n]|\s(?:\$)|:\/\/)/g;
7
+ const delimiter = /(?=[\\$"`\[\](){}\r\n]|\s\$|:\/\/)/g;
8
8
 
9
9
  export const escsource: EscapableSourceParser = ({ context }) => {
10
10
  const { source, position } = context;
@@ -38,15 +38,7 @@ export const escsource: EscapableSourceParser = ({ context }) => {
38
38
  default:
39
39
  assert(char !== '\n');
40
40
  if (context.sequential) return [[char]];
41
- nonWhitespace.lastIndex = position + 1;
42
- const b = isBlank(source, position);
43
- let i = b
44
- ? source[position + 1] === '\n'
45
- ? position + 1
46
- : nonWhitespace.test(source)
47
- ? nonWhitespace.lastIndex - 1
48
- : source.length
49
- : next(source, position, delimiter);
41
+ let i = next(source, position, delimiter);
50
42
  assert(i > position);
51
43
  i -= position;
52
44
  consume(i - 1, context);