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.
- package/CHANGELOG.md +8 -0
- package/dist/index.js +125 -141
- package/package.json +1 -1
- package/src/combinator/control/manipulation/surround.ts +2 -2
- package/src/combinator/data/parser/context.test.ts +10 -9
- package/src/combinator/data/parser/context.ts +2 -1
- package/src/combinator/data/parser.ts +0 -3
- package/src/parser/api/bind.ts +3 -3
- package/src/parser/api/normalize.ts +1 -3
- package/src/parser/api/parse.ts +1 -1
- package/src/parser/block/dlist.test.ts +1 -1
- package/src/parser/block/heading.test.ts +1 -0
- package/src/parser/block/olist.test.ts +1 -0
- package/src/parser/block/reply/quote.ts +6 -6
- package/src/parser/block/reply.ts +3 -2
- package/src/parser/block/ulist.test.ts +1 -0
- package/src/parser/header.test.ts +3 -1
- package/src/parser/header.ts +2 -2
- package/src/parser/inline/emphasis.test.ts +1 -0
- package/src/parser/inline/html.test.ts +3 -3
- package/src/parser/inline/html.ts +9 -9
- package/src/parser/inline/italic.test.ts +1 -0
- package/src/parser/inline/link.test.ts +10 -8
- package/src/parser/inline/link.ts +17 -17
- package/src/parser/inline/mark.test.ts +1 -0
- package/src/parser/inline/media.test.ts +6 -7
- package/src/parser/inline/media.ts +3 -3
- package/src/parser/inline/remark.test.ts +3 -1
- package/src/parser/inline/strong.test.ts +1 -0
- package/src/parser/source/escapable.test.ts +1 -0
- package/src/parser/source/escapable.ts +3 -11
- package/src/parser/source/text.test.ts +5 -4
- package/src/parser/source/text.ts +90 -94
- package/src/parser/source/unescapable.test.ts +1 -0
- package/src/parser/source/unescapable.ts +5 -8
- 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;
|
package/src/parser/api/bind.ts
CHANGED
|
@@ -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
|
|
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(
|
|
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
|
package/src/parser/api/parse.ts
CHANGED
|
@@ -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('~
|
|
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
|
-
|
|
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)
|
|
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
|
-
|
|
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(
|
|
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('
|
|
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
|
});
|
package/src/parser/header.ts
CHANGED
|
@@ -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
|
|
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(
|
|
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	*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
|
|
70
|
+
assert.deepStrictEqual(inspect(parser('<bdi >a</bdi>'), ctx), [['<span class="invalid"><bdi >a</bdi></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"><bdo diR="rtl">a</bdo></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"
|
|
126
|
-
assert.deepStrictEqual(inspect(parser('<bdo dir="rtl">a</bdo>'), ctx), [['<bdo
|
|
125
|
+
assert.deepStrictEqual(inspect(parser('<bdo dir="rtl" >a</bdo>'), ctx), [['<span class="invalid"><bdo dir="rtl" >a</bdo></span>'], '']);
|
|
126
|
+
assert.deepStrictEqual(inspect(parser('<bdo dir="rtl">a</bdo>'), ctx), [['<span class="invalid"><bdo dir="rtl">a</bdo></span>'], '']);
|
|
127
127
|
assert.deepStrictEqual(inspect(parser('<wbr\n>'), ctx), undefined);
|
|
128
128
|
assert.deepStrictEqual(inspect(parser('<wbr \n>'), ctx), [['<span class="invalid"><wbr </span>'], '\n>']);
|
|
129
129
|
assert.deepStrictEqual(inspect(parser('<wbr constructor>'), ctx), [['<span class="invalid"><wbr constructor></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]+(?=[
|
|
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)(?=[
|
|
27
|
+
str(/<(?:area|base|br|col|embed|hr|img|input|link|meta|source|track|wbr)(?=[ >])/yi),
|
|
28
28
|
some(union([attribute])),
|
|
29
|
-
open(str(/
|
|
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(/
|
|
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]+(?=[
|
|
64
|
+
str(/<[a-z]+(?=[ >])/yi),
|
|
65
65
|
some(union([attribute])),
|
|
66
|
-
open(str(/
|
|
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(/[
|
|
76
|
-
str(/[^\
|
|
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),
|
|
67
|
-
assert.deepStrictEqual(inspect(parser('[]{ }'), ctx),
|
|
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), [['<
|
|
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), [['<
|
|
111
|
-
assert.deepStrictEqual(inspect(parser('[]{ b }'), ctx),
|
|
112
|
-
assert.deepStrictEqual(inspect(parser('[]{ b }'), ctx),
|
|
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=""">"</a>`], '']);
|
|
115
114
|
assert.deepStrictEqual(inspect(parser('[]{"}"}'), ctx), [[`<a class="url" href=""">"</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
|
-
/
|
|
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)]), /
|
|
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)]), /
|
|
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(/
|
|
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(/
|
|
109
|
-
str(/[
|
|
110
|
-
str(/[^\
|
|
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 /[
|
|
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.
|
|
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.
|
|
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.
|
|
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
|
|
246
|
+
const head = /^[a-z]+(?:[.+-][0-9a-z]+)*:\/*[^/?#\s]+/i;
|
|
247
|
+
const origin = uri.match(head)?.[0] ?? '';
|
|
247
248
|
try {
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
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	==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),
|
|
31
|
-
assert.deepStrictEqual(inspect(parser('![]{ }'), ctx),
|
|
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), [['<
|
|
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), [['<
|
|
72
|
-
assert.deepStrictEqual(inspect(parser('![]{ b }'), ctx),
|
|
73
|
-
assert.deepStrictEqual(inspect(parser('![]{ b }'), ctx),
|
|
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=""" target="_blank"><img class="media" data-src=""" alt="""></a>'], '']);
|
|
76
75
|
assert.deepStrictEqual(inspect(parser('![]{"}"}'), ctx), [['<a href=""" target="_blank"><img class="media" data-src=""" alt="""></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
|
-
/
|
|
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(/
|
|
123
|
+
open(/ /y, str(/[1-9][0-9]*/y)),
|
|
124
124
|
str(/[x:]/y),
|
|
125
|
-
str(/[1-9][0-9]*(?=[
|
|
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	**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 {
|
|
4
|
+
import { next } from './text';
|
|
5
5
|
import { html } from 'typed-dom/dom';
|
|
6
6
|
|
|
7
|
-
const delimiter = /(?=[\\$"`\[\](){}\r\n]|\s
|
|
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
|
-
|
|
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);
|