securemark 0.260.0 → 0.260.3
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 +12 -0
- package/design.md +4 -0
- package/dist/index.js +105 -97
- package/package.json +5 -5
- package/src/combinator/data/parser/context.ts +6 -4
- package/src/parser/api/parse.test.ts +13 -13
- package/src/parser/block/blockquote.ts +3 -3
- package/src/parser/block/dlist.ts +2 -2
- package/src/parser/block/extension/table.ts +3 -3
- package/src/parser/block/ilist.ts +1 -1
- package/src/parser/block/olist.ts +1 -1
- package/src/parser/block/reply/cite.ts +1 -1
- package/src/parser/block/reply/quote.ts +1 -1
- package/src/parser/block/sidefence.ts +1 -1
- package/src/parser/block/table.ts +4 -4
- package/src/parser/block/ulist.ts +2 -2
- package/src/parser/block.ts +1 -1
- package/src/parser/inline/annotation.test.ts +1 -1
- package/src/parser/inline/autolink/account.ts +2 -4
- package/src/parser/inline/autolink/anchor.ts +1 -1
- package/src/parser/inline/autolink/email.test.ts +1 -0
- package/src/parser/inline/autolink/email.ts +2 -2
- package/src/parser/inline/autolink/hashtag.ts +1 -1
- package/src/parser/inline/autolink/url.ts +3 -5
- package/src/parser/inline/autolink.ts +3 -3
- package/src/parser/inline/link.test.ts +55 -50
- package/src/parser/inline/link.ts +67 -49
- package/src/parser/inline/reference.test.ts +1 -1
- package/src/parser/inline/ruby.ts +1 -1
- package/src/parser/inline.test.ts +11 -11
- package/src/parser/source/escapable.ts +1 -1
- package/src/parser/source/str.ts +4 -4
- package/src/parser/source/text.ts +2 -3
- package/src/parser/source/unescapable.ts +1 -1
- package/src/renderer/render/media/twitter.ts +7 -1
|
@@ -36,12 +36,6 @@ const textlink: LinkParser.TextLinkParser = lazy(() =>
|
|
|
36
36
|
])),
|
|
37
37
|
([params, content = []]: [string[], (HTMLElement | string)[]], rest, context) => {
|
|
38
38
|
assert(!html('div', content).querySelector('a, .media, .annotation, .reference'));
|
|
39
|
-
if (content.length !== 0 && trimNode(content).length === 0) return;
|
|
40
|
-
for (let source = stringify(content); source;) {
|
|
41
|
-
const result = autolink({ source, context });
|
|
42
|
-
if (typeof eval(result, [])[0] === 'object') return;
|
|
43
|
-
source = exec(result, '');
|
|
44
|
-
}
|
|
45
39
|
return parse(content, params, rest, context);
|
|
46
40
|
}))));
|
|
47
41
|
|
|
@@ -91,42 +85,45 @@ function parse(
|
|
|
91
85
|
): Result<HTMLAnchorElement, MarkdownParser.Context> {
|
|
92
86
|
assert(params.length > 0);
|
|
93
87
|
assert(params.every(p => typeof p === 'string'));
|
|
88
|
+
if (content.length !== 0 && trimNode(content).length === 0) return;
|
|
89
|
+
content = defrag(content);
|
|
90
|
+
for (let source = stringify(content); source;) {
|
|
91
|
+
if (/^[a-z][0-9a-z]*(?:[-.][0-9a-z]+)*:\/\/[^/?#]/i.test(source)) return;
|
|
92
|
+
const result = autolink({ source, context });
|
|
93
|
+
if (typeof eval(result, [])[0] === 'object') return;
|
|
94
|
+
source = exec(result, '');
|
|
95
|
+
}
|
|
94
96
|
const INSECURE_URI = params.shift()!;
|
|
95
97
|
assert(INSECURE_URI === INSECURE_URI.trim());
|
|
96
98
|
assert(!INSECURE_URI.match(/\s/));
|
|
99
|
+
const uri = new ReadonlyURL(
|
|
100
|
+
resolve(INSECURE_URI, context.host ?? location, context.url ?? context.host ?? location),
|
|
101
|
+
context.host?.href || location.href);
|
|
102
|
+
switch (uri.protocol) {
|
|
103
|
+
case 'tel:': {
|
|
104
|
+
const tel = content.length === 0
|
|
105
|
+
? INSECURE_URI
|
|
106
|
+
: content[0];
|
|
107
|
+
const pattern = /^(?:tel:)?(?:\+(?!0))?\d+(?:-\d+)*$/i;
|
|
108
|
+
if (content.length <= 1 &&
|
|
109
|
+
typeof tel === 'string' &&
|
|
110
|
+
pattern.test(tel) &&
|
|
111
|
+
pattern.test(INSECURE_URI) &&
|
|
112
|
+
tel.replace(/[^+\d]/g, '') === INSECURE_URI.replace(/[^+\d]/g, '')) {
|
|
113
|
+
break;
|
|
114
|
+
}
|
|
115
|
+
return;
|
|
116
|
+
}
|
|
117
|
+
}
|
|
97
118
|
const el = elem(
|
|
98
119
|
INSECURE_URI,
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
resolve(INSECURE_URI, context.host ?? location, context.url ?? context.host ?? location),
|
|
102
|
-
context.host?.href || location.href),
|
|
120
|
+
content,
|
|
121
|
+
uri,
|
|
103
122
|
context.host?.origin || location.origin);
|
|
104
123
|
if (el.className === 'invalid') return [[el], rest];
|
|
105
124
|
return [[define(el, attributes('link', [], optspec, params))], rest];
|
|
106
125
|
}
|
|
107
126
|
|
|
108
|
-
export function resolve(uri: string, host: URL | Location, source: URL | Location): string {
|
|
109
|
-
assert(uri);
|
|
110
|
-
assert(uri === uri.trim());
|
|
111
|
-
switch (true) {
|
|
112
|
-
case uri.slice(0, 2) === '^/':
|
|
113
|
-
const last = host.pathname.slice(host.pathname.lastIndexOf('/') + 1);
|
|
114
|
-
return last.includes('.') // isFile
|
|
115
|
-
&& /^[0-9]*[A-Za-z][0-9A-Za-z]*$/.test(last.slice(last.lastIndexOf('.') + 1))
|
|
116
|
-
? `${host.pathname.slice(0, -last.length)}${uri.slice(2)}`
|
|
117
|
-
: `${host.pathname.replace(/\/?$/, '/')}${uri.slice(2)}`;
|
|
118
|
-
case host.origin === source.origin
|
|
119
|
-
&& host.pathname === source.pathname:
|
|
120
|
-
case uri.slice(0, 2) === '//':
|
|
121
|
-
return uri;
|
|
122
|
-
default:
|
|
123
|
-
const target = new ReadonlyURL(uri, source.href);
|
|
124
|
-
return target.origin === host.origin
|
|
125
|
-
? target.href.slice(target.origin.length)
|
|
126
|
-
: target.href;
|
|
127
|
-
}
|
|
128
|
-
}
|
|
129
|
-
|
|
130
127
|
function elem(
|
|
131
128
|
INSECURE_URI: string,
|
|
132
129
|
content: readonly (string | HTMLElement)[],
|
|
@@ -147,7 +144,7 @@ function elem(
|
|
|
147
144
|
}
|
|
148
145
|
return html('a',
|
|
149
146
|
{
|
|
150
|
-
class: 'link',
|
|
147
|
+
class: content.length === 0 ? 'url' : 'link',
|
|
151
148
|
href: uri.source,
|
|
152
149
|
target: undefined
|
|
153
150
|
|| uri.origin !== origin
|
|
@@ -159,21 +156,15 @@ function elem(
|
|
|
159
156
|
? decode(INSECURE_URI)
|
|
160
157
|
: content);
|
|
161
158
|
case 'tel:':
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
&& INSECURE_URI.replace(/[^+\d]/g, '') === content[0].replace(/[^+\d]/g, ''):
|
|
172
|
-
return html('a', { class: 'tel', href: uri.source }, content);
|
|
173
|
-
}
|
|
174
|
-
type = 'content';
|
|
175
|
-
message = 'Invalid phone number';
|
|
176
|
-
break;
|
|
159
|
+
assert(content.length <= 1);
|
|
160
|
+
return html('a',
|
|
161
|
+
{
|
|
162
|
+
class: 'tel',
|
|
163
|
+
href: uri.source,
|
|
164
|
+
},
|
|
165
|
+
content.length === 0
|
|
166
|
+
? [INSECURE_URI]
|
|
167
|
+
: content);
|
|
177
168
|
}
|
|
178
169
|
return html('a',
|
|
179
170
|
{
|
|
@@ -187,10 +178,37 @@ function elem(
|
|
|
187
178
|
: content);
|
|
188
179
|
}
|
|
189
180
|
|
|
181
|
+
export function resolve(uri: string, host: URL | Location, source: URL | Location): string {
|
|
182
|
+
assert(uri);
|
|
183
|
+
assert(uri === uri.trim());
|
|
184
|
+
switch (true) {
|
|
185
|
+
case uri.slice(0, 2) === '^/':
|
|
186
|
+
const last = host.pathname.slice(host.pathname.lastIndexOf('/') + 1);
|
|
187
|
+
return last.includes('.') // isFile
|
|
188
|
+
&& /^[0-9]*[a-z][0-9a-z]*$/i.test(last.slice(last.lastIndexOf('.') + 1))
|
|
189
|
+
? `${host.pathname.slice(0, -last.length)}${uri.slice(2)}`
|
|
190
|
+
: `${host.pathname.replace(/\/?$/, '/')}${uri.slice(2)}`;
|
|
191
|
+
case host.origin === source.origin
|
|
192
|
+
&& host.pathname === source.pathname:
|
|
193
|
+
case uri.slice(0, 2) === '//':
|
|
194
|
+
return uri;
|
|
195
|
+
default:
|
|
196
|
+
const target = new ReadonlyURL(uri, source.href);
|
|
197
|
+
return target.origin === host.origin
|
|
198
|
+
? target.href.slice(target.origin.length)
|
|
199
|
+
: target.href;
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
|
|
190
203
|
function decode(uri: string): string {
|
|
191
204
|
if (!uri.includes('%')) return uri;
|
|
205
|
+
const origin = uri.match(/^[a-z](?:[-.](?=\w)|[0-9a-z])*:\/\/[^/?#]*/i)?.[0] ?? '';
|
|
192
206
|
try {
|
|
193
|
-
|
|
207
|
+
let path = decodeURI(uri.slice(origin.length));
|
|
208
|
+
if (!origin && /^[a-z](?:[-.](?=\w)|[0-9a-z])*:\/\/[^/?#]/i.test(path)) {
|
|
209
|
+
path = uri.slice(origin.length);
|
|
210
|
+
}
|
|
211
|
+
uri = origin + path;
|
|
194
212
|
}
|
|
195
213
|
finally {
|
|
196
214
|
return uri.replace(/\s+/g, encodeURI);
|
|
@@ -46,7 +46,7 @@ describe('Unit: parser/inline/reference', () => {
|
|
|
46
46
|
assert.deepStrictEqual(inspect(parser('[[`a`]]')), [['<sup class="reference"><span><code data-src="`a`">a</code></span></sup>'], '']);
|
|
47
47
|
assert.deepStrictEqual(inspect(parser('[[@a]]')), [['<sup class="reference"><span><a class="account" href="/@a">@a</a></span></sup>'], '']);
|
|
48
48
|
assert.deepStrictEqual(inspect(parser('[[http://host]]')), [['<sup class="reference"><span><a class="url" href="http://host" target="_blank">http://host</a></span></sup>'], '']);
|
|
49
|
-
assert.deepStrictEqual(inspect(parser('[[![]{a}]]')), [['<sup class="reference"><span>!<a class="
|
|
49
|
+
assert.deepStrictEqual(inspect(parser('[[![]{a}]]')), [['<sup class="reference"><span>!<a class="url" href="a">a</a></span></sup>'], '']);
|
|
50
50
|
assert.deepStrictEqual(inspect(parser('[[[a]]]')), [['<sup class="reference"><span>[a]</span></sup>'], '']);
|
|
51
51
|
assert.deepStrictEqual(inspect(parser('[[[[a]]]]')), [['<sup class="reference"><span>[[a]]</span></sup>'], '']);
|
|
52
52
|
assert.deepStrictEqual(inspect(parser('[[((a))]]')), [['<sup class="reference"><span><span class="paren">((a))</span></span></sup>'], '']);
|
|
@@ -48,7 +48,7 @@ export const ruby: RubyParser = lazy(() => validate('[', syntax(Syntax.none, 2,
|
|
|
48
48
|
}
|
|
49
49
|
}))));
|
|
50
50
|
|
|
51
|
-
const text: RubyParser.TextParser = creation(({ source, context }) => {
|
|
51
|
+
const text: RubyParser.TextParser = creation(1, false, ({ source, context }) => {
|
|
52
52
|
const acc = [''];
|
|
53
53
|
while (source !== '') {
|
|
54
54
|
assert(source[0] !== '\n');
|
|
@@ -117,27 +117,27 @@ describe('Unit: parser/inline', () => {
|
|
|
117
117
|
assert.deepStrictEqual(inspect(parser('$$-1')), [['$', '<a class="label" data-label="$-1">$-1</a>'], '']);
|
|
118
118
|
assert.deepStrictEqual(inspect(parser('[[#a]]')), [['<sup class="reference"><span><a class="hashtag" href="/hashtags/a">#a</a></span></sup>'], '']);
|
|
119
119
|
assert.deepStrictEqual(inspect(parser('[[$-1]]')), [['<sup class="reference"><span><a class="label" data-label="$-1">$-1</a></span></sup>'], '']);
|
|
120
|
-
assert.deepStrictEqual(inspect(parser('[[#-1]]{b}')), [['<sup class="reference"><span>#-1</span></sup>', '<a class="
|
|
120
|
+
assert.deepStrictEqual(inspect(parser('[[#-1]]{b}')), [['<sup class="reference"><span>#-1</span></sup>', '<a class="url" href="b">b</a>'], '']);
|
|
121
121
|
assert.deepStrictEqual(inspect(parser('[[#-1]](b)')), [['<sup class="reference"><span>#-1</span></sup>', '(', 'b', ')'], '']);
|
|
122
122
|
assert.deepStrictEqual(inspect(parser('[[#-1]a]{b}')), [['<a class="link" href="b">[#-1]a</a>'], '']);
|
|
123
123
|
assert.deepStrictEqual(inspect(parser('[[#-1]a](b)')), [['[', '<a class="index" href="#index:-1">-1</a>', 'a', ']', '(', 'b', ')'], '']);
|
|
124
|
-
assert.deepStrictEqual(inspect(parser('[#a]{b}')), [['<a class="index" href="#index:a">a</a>', '<a class="
|
|
124
|
+
assert.deepStrictEqual(inspect(parser('[#a]{b}')), [['<a class="index" href="#index:a">a</a>', '<a class="url" href="b">b</a>'], '']);
|
|
125
125
|
assert.deepStrictEqual(inspect(parser('[@a]{b}')), [['<a class="link" href="b">@a</a>'], '']);
|
|
126
|
-
assert.deepStrictEqual(inspect(parser('[http://host]{http://evil}')), [['[', '<a class="url" href="http://host" target="_blank">http://host</a>', ']', '<a class="
|
|
127
|
-
assert.deepStrictEqual(inspect(parser('[http://host]{http://host}')), [['[', '<a class="url" href="http://host" target="_blank">http://host</a>', ']', '<a class="
|
|
126
|
+
assert.deepStrictEqual(inspect(parser('[http://host]{http://evil}')), [['[', '<a class="url" href="http://host" target="_blank">http://host</a>', ']', '<a class="url" href="http://evil" target="_blank">http://evil</a>'], '']);
|
|
127
|
+
assert.deepStrictEqual(inspect(parser('[http://host]{http://host}')), [['[', '<a class="url" href="http://host" target="_blank">http://host</a>', ']', '<a class="url" href="http://host" target="_blank">http://host</a>'], '']);
|
|
128
128
|
assert.deepStrictEqual(inspect(parser('[]{{a}}')), [['[', ']', '<span class="template">{{a}}</span>'], '']);
|
|
129
129
|
assert.deepStrictEqual(inspect(parser('![]{{a}}')), [['!', '[', ']', '<span class="template">{{a}}</span>'], '']);
|
|
130
|
-
assert.deepStrictEqual(inspect(parser('[\n]{a}')), [['[', '<br>', ']', '<a class="
|
|
131
|
-
assert.deepStrictEqual(inspect(parser('[\\\n]{a}')), [['[', '<span class="linebreak"> </span>', ']', '<a class="
|
|
130
|
+
assert.deepStrictEqual(inspect(parser('[\n]{a}')), [['[', '<br>', ']', '<a class="url" href="a">a</a>'], '']);
|
|
131
|
+
assert.deepStrictEqual(inspect(parser('[\\\n]{a}')), [['[', '<span class="linebreak"> </span>', ']', '<a class="url" href="a">a</a>'], '']);
|
|
132
132
|
assert.deepStrictEqual(inspect(parser('{}')), [['{', '}'], '']);
|
|
133
|
-
assert.deepStrictEqual(inspect(parser('{a}')), [['<a class="
|
|
133
|
+
assert.deepStrictEqual(inspect(parser('{a}')), [['<a class="url" href="a">a</a>'], '']);
|
|
134
134
|
assert.deepStrictEqual(inspect(parser('{{a}}')), [['<span class="template">{{a}}</span>'], '']);
|
|
135
135
|
assert.deepStrictEqual(inspect(parser('!{}')), [['!', '{', '}'], '']);
|
|
136
136
|
assert.deepStrictEqual(inspect(parser('!{a}')), [['<a href="a" target="_blank"><img class="media" data-src="a" alt=""></a>'], '']);
|
|
137
137
|
assert.deepStrictEqual(inspect(parser('!{{a}}')), [['!', '<span class="template">{{a}}</span>'], '']);
|
|
138
138
|
assert.deepStrictEqual(inspect(parser('!{{{a}}}')), [['!', '<span class="template">{{{a}}}</span>'], '']);
|
|
139
139
|
assert.deepStrictEqual(inspect(parser('!!{a}')), [['!', '<a href="a" target="_blank"><img class="media" data-src="a" alt=""></a>'], '']);
|
|
140
|
-
assert.deepStrictEqual(inspect(parser('${a}')), [['$', '<a class="
|
|
140
|
+
assert.deepStrictEqual(inspect(parser('${a}')), [['$', '<a class="url" href="a">a</a>'], '']);
|
|
141
141
|
assert.deepStrictEqual(inspect(parser('${{a}}')), [['$', '<span class="template">{{a}}</span>'], '']);
|
|
142
142
|
assert.deepStrictEqual(inspect(parser('${{{a}}}')), [['$', '<span class="template">{{{a}}}</span>'], '']);
|
|
143
143
|
assert.deepStrictEqual(inspect(parser('Di$ney Micro$oft')), [['Di', '$', 'ney', ' ', 'Micro', '$', 'oft'], '']);
|
|
@@ -152,14 +152,14 @@ describe('Unit: parser/inline', () => {
|
|
|
152
152
|
assert.deepStrictEqual(inspect(parser('[[[[a]]')), [['', '[', '', '[', '<sup class="reference"><span>a</span></sup>'], '']);
|
|
153
153
|
assert.deepStrictEqual(inspect(parser('[[[[a]]]]')), [['<sup class="reference"><span>[[a]]</span></sup>'], '']);
|
|
154
154
|
assert.deepStrictEqual(inspect(parser('[[[$-1]]]')), [['<sup class="reference"><span><a class="label" data-label="$-1">$-1</a></span></sup>'], '']);
|
|
155
|
-
assert.deepStrictEqual(inspect(parser('[[[]{a}]]')), [['<sup class="reference"><span><a class="
|
|
155
|
+
assert.deepStrictEqual(inspect(parser('[[[]{a}]]')), [['<sup class="reference"><span><a class="url" href="a">a</a></span></sup>'], '']);
|
|
156
156
|
assert.deepStrictEqual(inspect(parser('[[[a]{b}]]')), [['<sup class="reference"><span><a class="link" href="b">a</a></span></sup>'], '']);
|
|
157
157
|
assert.deepStrictEqual(inspect(parser('[(([a]{#}))]{#}')), [['<a class="link" href="#"><span class="paren">(<span class="paren">([a]{#})</span>)</span></a>'], '']);
|
|
158
158
|
assert.deepStrictEqual(inspect(parser('[[<bdi>]]')), [['<sup class="reference"><span><span class="invalid"><bdi></span></span></sup>'], '']);
|
|
159
159
|
assert.deepStrictEqual(inspect(parser('[[${]]}$')), [['', '[', '', '[', '<span class="math" translate="no" data-src="${]]}$">${]]}$</span>'], '']);
|
|
160
160
|
assert.deepStrictEqual(inspect(parser('"[[""]]')), [['"', '<sup class="reference"><span>""</span></sup>'], '']);
|
|
161
161
|
assert.deepStrictEqual(inspect(parser('[[a](b)]{c}')), [['<a class="link" href="c"><ruby>a<rp>(</rp><rt>b</rt><rp>)</rp></ruby></a>'], '']);
|
|
162
|
-
assert.deepStrictEqual(inspect(parser('[[[[[[[{a}')), [['', '[', '', '[', '', '[', '', '[', '', '[', '', '[', '', '[', '<a class="
|
|
162
|
+
assert.deepStrictEqual(inspect(parser('[[[[[[[{a}')), [['', '[', '', '[', '', '[', '', '[', '', '[', '', '[', '', '[', '<a class="url" href="a">a</a>'], '']);
|
|
163
163
|
assert.deepStrictEqual(inspect(parser('<http://host>')), [['<', '<a class="url" href="http://host" target="_blank">http://host</a>', '>'], '']);
|
|
164
164
|
assert.deepStrictEqual(inspect(parser('[~http://host')), [['', '[', '~', '<a class="url" href="http://host" target="_blank">http://host</a>'], '']);
|
|
165
165
|
assert.deepStrictEqual(inspect(parser('[~a@b')), [['', '[', '~', '<a class="email" href="mailto:a@b">a@b</a>'], '']);
|
|
@@ -167,7 +167,7 @@ describe('Unit: parser/inline', () => {
|
|
|
167
167
|
assert.deepStrictEqual(inspect(parser('[^http://host')), [['[^', '<a class="url" href="http://host" target="_blank">http://host</a>'], '']);
|
|
168
168
|
assert.deepStrictEqual(inspect(parser('[^a@b')), [['[^', '<a class="email" href="mailto:a@b">a@b</a>'], '']);
|
|
169
169
|
assert.deepStrictEqual(inspect(parser('[#a*b\nc*]')), [['[', '<a class="hashtag" href="/hashtags/a">#a</a>', '<em>b<br>c</em>', ']'], '']);
|
|
170
|
-
assert.deepStrictEqual(inspect(parser('[*a\nb*]{/}')), [['[', '<em>a<br>b</em>', ']', '<a class="
|
|
170
|
+
assert.deepStrictEqual(inspect(parser('[*a\nb*]{/}')), [['[', '<em>a<br>b</em>', ']', '<a class="url" href="/">/</a>'], '']);
|
|
171
171
|
assert.deepStrictEqual(inspect(parser('[*a\nb]*')), [['[', '*', 'a', '<br>', 'b', ']', '*'], '']);
|
|
172
172
|
assert.deepStrictEqual(inspect(parser('[*[a\nb*]')), [['', '[', '*', '[', 'a', '<br>', 'b', '*', ']'], '']);
|
|
173
173
|
assert.deepStrictEqual(inspect(parser('[[*a\nb*]]')), [['[', '[', '<em>a<br>b</em>', ']', ']'], '']);
|
|
@@ -4,7 +4,7 @@ import { nonWhitespace } from './text';
|
|
|
4
4
|
|
|
5
5
|
const delimiter = /[\s\x00-\x2F\x3A-\x40\x5B-\x60\x7B-\x7F]/;
|
|
6
6
|
|
|
7
|
-
export const escsource: EscapableSourceParser = creation(({ source }) => {
|
|
7
|
+
export const escsource: EscapableSourceParser = creation(1, false, ({ source }) => {
|
|
8
8
|
if (source === '') return;
|
|
9
9
|
const i = source.search(delimiter);
|
|
10
10
|
switch (i) {
|
package/src/parser/source/str.ts
CHANGED
|
@@ -7,13 +7,13 @@ export function str(pattern: string | RegExp): StrParser;
|
|
|
7
7
|
export function str(pattern: string | RegExp): Parser<string, Context<StrParser>, []> {
|
|
8
8
|
assert(pattern);
|
|
9
9
|
return typeof pattern === 'string'
|
|
10
|
-
? creation(({ source }) => {
|
|
10
|
+
? creation(1, false, ({ source }) => {
|
|
11
11
|
if (source === '') return;
|
|
12
12
|
return source.slice(0, pattern.length) === pattern
|
|
13
13
|
? [[pattern], source.slice(pattern.length)]
|
|
14
14
|
: undefined;
|
|
15
15
|
})
|
|
16
|
-
: creation(({ source }) => {
|
|
16
|
+
: creation(1, false, ({ source }) => {
|
|
17
17
|
if (source === '') return;
|
|
18
18
|
const m = source.match(pattern);
|
|
19
19
|
return m && m[0].length > 0
|
|
@@ -26,13 +26,13 @@ export function stropt(pattern: string | RegExp): StrParser;
|
|
|
26
26
|
export function stropt(pattern: string | RegExp): Parser<string, Context<StrParser>, []> {
|
|
27
27
|
assert(pattern);
|
|
28
28
|
return typeof pattern === 'string'
|
|
29
|
-
? creation(({ source }) => {
|
|
29
|
+
? creation(1, false, ({ source }) => {
|
|
30
30
|
if (source === '') return;
|
|
31
31
|
return source.slice(0, pattern.length) === pattern
|
|
32
32
|
? [[pattern], source.slice(pattern.length)]
|
|
33
33
|
: undefined;
|
|
34
34
|
})
|
|
35
|
-
: creation(({ source }) => {
|
|
35
|
+
: creation(1, false, ({ source }) => {
|
|
36
36
|
if (source === '') return;
|
|
37
37
|
const m = source.match(pattern);
|
|
38
38
|
return m
|
|
@@ -1,8 +1,7 @@
|
|
|
1
1
|
import { undefined } from 'spica/global';
|
|
2
2
|
import { TextParser, TxtParser, LinebreakParser } from '../source';
|
|
3
|
-
import { union,
|
|
3
|
+
import { union, creation, focus } from '../../combinator';
|
|
4
4
|
import { str } from './str';
|
|
5
|
-
import { Syntax, State } from '../context';
|
|
6
5
|
import { html } from 'typed-dom/dom';
|
|
7
6
|
|
|
8
7
|
export const delimiter = /[\s\x00-\x7F]|\S[#>]|[()、。!?][^\S\n]*(?=\\\n)/;
|
|
@@ -10,7 +9,7 @@ export const nonWhitespace = /[\S\n]|$/;
|
|
|
10
9
|
export const nonAlphanumeric = /[^0-9A-Za-z]|\S[#>]|$/;
|
|
11
10
|
const repeat = str(/^(.)\1*/);
|
|
12
11
|
|
|
13
|
-
export const text: TextParser =
|
|
12
|
+
export const text: TextParser = creation(1, false, ({ source, context }) => {
|
|
14
13
|
if (source === '') return;
|
|
15
14
|
const i = source.search(delimiter);
|
|
16
15
|
switch (i) {
|
|
@@ -2,7 +2,7 @@ import { UnescapableSourceParser } from '../source';
|
|
|
2
2
|
import { creation } from '../../combinator';
|
|
3
3
|
import { delimiter, nonWhitespace, nonAlphanumeric, isAlphanumeric } from './text';
|
|
4
4
|
|
|
5
|
-
export const unescsource: UnescapableSourceParser = creation(({ source }) => {
|
|
5
|
+
export const unescsource: UnescapableSourceParser = creation(1, false, ({ source }) => {
|
|
6
6
|
assert(source[0] !== '\x1B');
|
|
7
7
|
if (source === '') return;
|
|
8
8
|
const i = source.search(delimiter);
|
|
@@ -37,7 +37,13 @@ export function twitter(source: HTMLImageElement, url: URL): HTMLElement | undef
|
|
|
37
37
|
},
|
|
38
38
|
error({ status, statusText }) {
|
|
39
39
|
assert(Number.isSafeInteger(status));
|
|
40
|
-
define(el, [
|
|
40
|
+
define(el, [
|
|
41
|
+
define(parse(`{ ${source.getAttribute('data-src')} }`).querySelector('a')!, {
|
|
42
|
+
class: null,
|
|
43
|
+
target: '_blank',
|
|
44
|
+
}),
|
|
45
|
+
h('pre', `${status}\n${statusText}`),
|
|
46
|
+
]);
|
|
41
47
|
},
|
|
42
48
|
});
|
|
43
49
|
return el;
|