securemark 0.293.1 → 0.293.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 +8 -0
- package/README.md +7 -10
- package/dist/index.js +329 -150
- package/package.json +1 -1
- package/src/combinator/control/manipulation/indent.test.ts +6 -1
- package/src/combinator/control/manipulation/indent.ts +1 -1
- package/src/combinator/control/manipulation/scope.ts +3 -4
- package/src/combinator/control/manipulation/surround.ts +2 -1
- package/src/combinator/data/parser/context/delimiter.ts +7 -12
- package/src/combinator/data/parser/some.ts +4 -8
- package/src/parser/api/parse.test.ts +2 -2
- package/src/parser/block/olist.test.ts +8 -6
- package/src/parser/block/olist.ts +2 -2
- package/src/parser/block/sidefence.ts +2 -2
- package/src/parser/block/table.ts +2 -2
- package/src/parser/block.ts +38 -36
- package/src/parser/inline/annotation.test.ts +1 -1
- package/src/parser/inline/autolink/url.test.ts +5 -5
- package/src/parser/inline/bracket.test.ts +6 -4
- package/src/parser/inline/bracket.ts +114 -88
- package/src/parser/inline/html.ts +24 -13
- package/src/parser/inline/italic.test.ts +9 -9
- package/src/parser/inline/link.ts +1 -1
- package/src/parser/inline/mark.test.ts +5 -5
- package/src/parser/inline/math.ts +2 -2
- package/src/parser/inline/media.ts +3 -2
- package/src/parser/inline/reference.test.ts +1 -1
- package/src/parser/inline/remark.ts +2 -2
- package/src/parser/inline/template.ts +1 -1
- package/src/parser/inline.test.ts +24 -23
- package/src/parser/inline.ts +46 -47
- package/src/parser/segment.ts +12 -12
- package/src/parser/source/escapable.test.ts +1 -1
- package/src/parser/source/escapable.ts +7 -4
- package/src/parser/source/text.ts +162 -25
- package/src/parser/source/unescapable.ts +5 -3
package/src/parser/inline.ts
CHANGED
|
@@ -53,70 +53,69 @@ export const inline: InlineParser = lazy(() => union([
|
|
|
53
53
|
input => {
|
|
54
54
|
const { context: { source, position } } = input;
|
|
55
55
|
if (position === source.length) return;
|
|
56
|
-
switch (source.slice(position, position + 2)) {
|
|
57
|
-
case '((':
|
|
58
|
-
return annotation(input)
|
|
59
|
-
|| bracket(input);
|
|
60
|
-
case '[[':
|
|
61
|
-
return reference(input)
|
|
62
|
-
|| textlink(input)
|
|
63
|
-
|| bracket(input);
|
|
64
|
-
case '{{':
|
|
65
|
-
return template(input)
|
|
66
|
-
|| bracket(input);
|
|
67
|
-
case '[%':
|
|
68
|
-
return remark(input)
|
|
69
|
-
|| textlink(input)
|
|
70
|
-
|| bracket(input);
|
|
71
|
-
case '[#':
|
|
72
|
-
case '[$':
|
|
73
|
-
case '[:':
|
|
74
|
-
case '[^':
|
|
75
|
-
case '[|':
|
|
76
|
-
return extension(input)
|
|
77
|
-
|| textlink(input)
|
|
78
|
-
|| bracket(input);
|
|
79
|
-
case '${':
|
|
80
|
-
return math(input);
|
|
81
|
-
case '++':
|
|
82
|
-
return insertion(input);
|
|
83
|
-
case '~~':
|
|
84
|
-
return deletion(input);
|
|
85
|
-
case '==':
|
|
86
|
-
return mark(input);
|
|
87
|
-
case '//':
|
|
88
|
-
return italic(input);
|
|
89
|
-
case '**':
|
|
90
|
-
return emstrong(input)
|
|
91
|
-
|| strong(input)
|
|
92
|
-
|| stars(input);
|
|
93
|
-
}
|
|
94
56
|
switch (source[position]) {
|
|
57
|
+
case '(':
|
|
58
|
+
if (source[position + 1] === '(') return annotation(input) || bracket(input);
|
|
59
|
+
return bracket(input);
|
|
95
60
|
case '[':
|
|
61
|
+
switch (source[position + 1]) {
|
|
62
|
+
case '[':
|
|
63
|
+
return reference(input)
|
|
64
|
+
|| textlink(input)
|
|
65
|
+
|| bracket(input);
|
|
66
|
+
case '%':
|
|
67
|
+
return remark(input)
|
|
68
|
+
|| textlink(input)
|
|
69
|
+
|| bracket(input);
|
|
70
|
+
case '#':
|
|
71
|
+
case '$':
|
|
72
|
+
case ':':
|
|
73
|
+
case '^':
|
|
74
|
+
case '|':
|
|
75
|
+
return extension(input)
|
|
76
|
+
|| textlink(input)
|
|
77
|
+
|| bracket(input);
|
|
78
|
+
}
|
|
96
79
|
return textlink(input)
|
|
97
80
|
|| ruby(input)
|
|
98
81
|
|| bracket(input);
|
|
99
82
|
case '{':
|
|
83
|
+
if (source[position + 1] === '{') return template(input) || bracket(input);
|
|
100
84
|
return textlink(input)
|
|
101
85
|
|| bracket(input);
|
|
86
|
+
case '"':
|
|
87
|
+
case '(':
|
|
88
|
+
case '[':
|
|
89
|
+
case '{':
|
|
90
|
+
return bracket(input);
|
|
102
91
|
case '<':
|
|
103
92
|
return html(input);
|
|
104
93
|
case '$':
|
|
94
|
+
if (source[position + 1] === '{') return math(input);
|
|
105
95
|
return extension(input)
|
|
106
96
|
|| math(input);
|
|
97
|
+
case '+':
|
|
98
|
+
if (source[position + 1] === '+') return insertion(input);
|
|
99
|
+
break;
|
|
100
|
+
case '~':
|
|
101
|
+
if (source[position + 1] === '~') return deletion(input);
|
|
102
|
+
break;
|
|
103
|
+
case '=':
|
|
104
|
+
if (source[position + 1] === '=') return mark(input);
|
|
105
|
+
break;
|
|
106
|
+
case '/':
|
|
107
|
+
if (source[position + 1] === '/' && source[position + 2] === '/') return italic(input);
|
|
108
|
+
break;
|
|
109
|
+
case '*':
|
|
110
|
+
return source[position + 1] === '*'
|
|
111
|
+
? source[position + 2] === '*'
|
|
112
|
+
? emstrong(input) || stars(input)
|
|
113
|
+
: strong(input) || stars(input)
|
|
114
|
+
: emphasis(input);
|
|
107
115
|
case '`':
|
|
108
116
|
return code(input);
|
|
109
|
-
case '*':
|
|
110
|
-
return emphasis(input)
|
|
111
|
-
|| stars(input);
|
|
112
117
|
case '&':
|
|
113
118
|
return htmlentity(input);
|
|
114
|
-
case '(':
|
|
115
|
-
case '(':
|
|
116
|
-
case '[':
|
|
117
|
-
case '{':
|
|
118
|
-
case '"':
|
|
119
|
-
return bracket(input);
|
|
120
119
|
}
|
|
121
120
|
},
|
|
122
121
|
autolink,
|
package/src/parser/segment.ts
CHANGED
|
@@ -17,19 +17,19 @@ const parser: SegmentParser = union([
|
|
|
17
17
|
input => {
|
|
18
18
|
const { context: { source, position } } = input;
|
|
19
19
|
if (position === source.length) return;
|
|
20
|
-
switch (source.slice(position, position + 3)) {
|
|
21
|
-
case '~~~':
|
|
22
|
-
return extension(input);
|
|
23
|
-
case '```':
|
|
24
|
-
return codeblock(input);
|
|
25
|
-
}
|
|
26
|
-
switch (source.slice(position, position + 2)) {
|
|
27
|
-
case '$$':
|
|
28
|
-
return mathblock(input);
|
|
29
|
-
case '[$':
|
|
30
|
-
return extension(input);
|
|
31
|
-
}
|
|
32
20
|
switch (source[position]) {
|
|
21
|
+
case '`':
|
|
22
|
+
if (source.startsWith('```', position)) return codeblock(input);
|
|
23
|
+
break;
|
|
24
|
+
case '~':
|
|
25
|
+
if (source.startsWith('~~~', position)) return extension(input);
|
|
26
|
+
break;
|
|
27
|
+
case '$':
|
|
28
|
+
if (source[position + 1] === '$') return mathblock(input);
|
|
29
|
+
break;
|
|
30
|
+
case '[':
|
|
31
|
+
if (source[position + 1] === '$') return extension(input);
|
|
32
|
+
break;
|
|
33
33
|
case '#':
|
|
34
34
|
return heading(input);
|
|
35
35
|
case '$':
|
|
@@ -15,7 +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('09あいAZaz'), ctx), [['09
|
|
18
|
+
assert.deepStrictEqual(inspect(parser('09あいAZaz'), ctx), [['09あいAZaz'], '']);
|
|
19
19
|
});
|
|
20
20
|
|
|
21
21
|
it('space', () => {
|
|
@@ -2,9 +2,10 @@ import { EscapableSourceParser } from '../source';
|
|
|
2
2
|
import { Command } from '../context';
|
|
3
3
|
import { consume } from '../../combinator';
|
|
4
4
|
import { nonWhitespace, isBlank, next } from './text';
|
|
5
|
-
import { delimiter } from './unescapable';
|
|
6
5
|
import { html } from 'typed-dom/dom';
|
|
7
6
|
|
|
7
|
+
const delimiter = /(?=[\\$"`\[\](){}\r\n]|\s(?:\$)|:\/\/)/g;
|
|
8
|
+
|
|
8
9
|
export const escsource: EscapableSourceParser = ({ context }) => {
|
|
9
10
|
const { source, position } = context;
|
|
10
11
|
if (position === source.length) return;
|
|
@@ -40,9 +41,11 @@ export const escsource: EscapableSourceParser = ({ context }) => {
|
|
|
40
41
|
nonWhitespace.lastIndex = position + 1;
|
|
41
42
|
const b = isBlank(source, position);
|
|
42
43
|
let i = b
|
|
43
|
-
?
|
|
44
|
-
?
|
|
45
|
-
: source
|
|
44
|
+
? source[position + 1] === '\n'
|
|
45
|
+
? position + 1
|
|
46
|
+
: nonWhitespace.test(source)
|
|
47
|
+
? nonWhitespace.lastIndex - 1
|
|
48
|
+
: source.length
|
|
46
49
|
: next(source, position, delimiter);
|
|
47
50
|
assert(i > position);
|
|
48
51
|
i -= position;
|
|
@@ -3,7 +3,7 @@ import { Command } from '../context';
|
|
|
3
3
|
import { union, consume, focus } from '../../combinator';
|
|
4
4
|
import { html } from 'typed-dom/dom';
|
|
5
5
|
|
|
6
|
-
|
|
6
|
+
//const delimiter = /(?=[\\!@#$&"`\[\](){}<>()[]{}*%|\r\n]|([+~=])\1|\/{3}|\s(?:\\?(?:$|\s)|[$%])|:\/\/)/g;
|
|
7
7
|
export const nonWhitespace = /[\S\r\n]/g;
|
|
8
8
|
|
|
9
9
|
export const text: TextParser = input => {
|
|
@@ -40,10 +40,12 @@ export const text: TextParser = input => {
|
|
|
40
40
|
nonWhitespace.lastIndex = position + 1;
|
|
41
41
|
const b = isBlank(source, position);
|
|
42
42
|
let i = b
|
|
43
|
-
?
|
|
44
|
-
?
|
|
45
|
-
: source
|
|
46
|
-
|
|
43
|
+
? source[position + 1] === '\n'
|
|
44
|
+
? position + 1
|
|
45
|
+
: nonWhitespace.test(source)
|
|
46
|
+
? nonWhitespace.lastIndex - 1
|
|
47
|
+
: source.length
|
|
48
|
+
: next(source, position);
|
|
47
49
|
assert(i > position);
|
|
48
50
|
const lineend = 0
|
|
49
51
|
|| b && i === source.length
|
|
@@ -70,10 +72,16 @@ export const linebreak: LinebreakParser = focus(/[\r\n]/y, union([
|
|
|
70
72
|
text,
|
|
71
73
|
])) as LinebreakParser;
|
|
72
74
|
|
|
73
|
-
export function next(source: string, position: number, delimiter
|
|
74
|
-
|
|
75
|
-
delimiter
|
|
76
|
-
|
|
75
|
+
export function next(source: string, position: number, delimiter?: RegExp): number {
|
|
76
|
+
let index: number;
|
|
77
|
+
if (delimiter) {
|
|
78
|
+
delimiter.lastIndex = position + 1;
|
|
79
|
+
delimiter.test(source);
|
|
80
|
+
index = delimiter.lastIndex;
|
|
81
|
+
}
|
|
82
|
+
else {
|
|
83
|
+
index = seek(source, position);
|
|
84
|
+
}
|
|
77
85
|
if (index === 0) return source.length;
|
|
78
86
|
assert(index > position);
|
|
79
87
|
const char = source[index];
|
|
@@ -85,16 +93,6 @@ export function next(source: string, position: number, delimiter: RegExp): numbe
|
|
|
85
93
|
index = backToEmailHead(source, position, index);
|
|
86
94
|
break;
|
|
87
95
|
}
|
|
88
|
-
if (index > position + 1) switch (char) {
|
|
89
|
-
case '*':
|
|
90
|
-
case '+':
|
|
91
|
-
case '~':
|
|
92
|
-
case '=':
|
|
93
|
-
case '/':
|
|
94
|
-
case '%':
|
|
95
|
-
case '|':
|
|
96
|
-
index -= /\s/.test(source[index - 1]) ? 1 : 0;
|
|
97
|
-
}
|
|
98
96
|
assert(index > position);
|
|
99
97
|
return index;
|
|
100
98
|
}
|
|
@@ -154,15 +152,154 @@ export function backToEmailHead(source: string, position: number, index: number)
|
|
|
154
152
|
return index + offset;
|
|
155
153
|
}
|
|
156
154
|
|
|
157
|
-
|
|
158
|
-
export function isBlank(source: string, position: number): boolean {
|
|
159
|
-
blank.lastIndex = position;
|
|
160
|
-
return blank.test(source);
|
|
161
|
-
}
|
|
162
|
-
export function isAlphanumeric(char: string): boolean {
|
|
155
|
+
function isAlphanumeric(char: string): boolean {
|
|
163
156
|
assert(char.length === 1);
|
|
164
157
|
if (char < '0' || '\x7F' < char) return false;
|
|
165
158
|
return '0' <= char && char <= '9'
|
|
166
159
|
|| 'a' <= char && char <= 'z'
|
|
167
160
|
|| 'A' <= char && char <= 'Z';
|
|
168
161
|
}
|
|
162
|
+
|
|
163
|
+
//const dict = new class {
|
|
164
|
+
// constructor() {
|
|
165
|
+
// [
|
|
166
|
+
// '\\',
|
|
167
|
+
// '!',
|
|
168
|
+
// '@',
|
|
169
|
+
// '#',
|
|
170
|
+
// '$',
|
|
171
|
+
// '&',
|
|
172
|
+
// '"',
|
|
173
|
+
// '`',
|
|
174
|
+
// '[',
|
|
175
|
+
// ']',
|
|
176
|
+
// '(',
|
|
177
|
+
// ')',
|
|
178
|
+
// '{',
|
|
179
|
+
// '}',
|
|
180
|
+
// '<',
|
|
181
|
+
// '>',
|
|
182
|
+
// '(',
|
|
183
|
+
// ')',
|
|
184
|
+
// '[',
|
|
185
|
+
// ']',
|
|
186
|
+
// '{',
|
|
187
|
+
// '}',
|
|
188
|
+
// '*',
|
|
189
|
+
// '%',
|
|
190
|
+
// '|',
|
|
191
|
+
// '\r',
|
|
192
|
+
// '\n',
|
|
193
|
+
// ].forEach(c =>
|
|
194
|
+
// this[c.charCodeAt(0)] = undefined);
|
|
195
|
+
// }
|
|
196
|
+
//};
|
|
197
|
+
|
|
198
|
+
const delimiter = /\s(?:\\?(?:$|\s)|[$%])/y;
|
|
199
|
+
|
|
200
|
+
function seek(source: string, position: number): number {
|
|
201
|
+
for (let i = position + 1; i < source.length; ++i) {
|
|
202
|
+
const fst = source[i];
|
|
203
|
+
//if (fst.charCodeAt(0) in dict) return i;
|
|
204
|
+
switch (fst) {
|
|
205
|
+
case '\\':
|
|
206
|
+
case '!':
|
|
207
|
+
case '@':
|
|
208
|
+
case '#':
|
|
209
|
+
case '$':
|
|
210
|
+
case '&':
|
|
211
|
+
case '"':
|
|
212
|
+
case '`':
|
|
213
|
+
case '[':
|
|
214
|
+
case ']':
|
|
215
|
+
case '(':
|
|
216
|
+
case ')':
|
|
217
|
+
case '{':
|
|
218
|
+
case '}':
|
|
219
|
+
case '<':
|
|
220
|
+
case '>':
|
|
221
|
+
case '(':
|
|
222
|
+
case ')':
|
|
223
|
+
case '[':
|
|
224
|
+
case ']':
|
|
225
|
+
case '{':
|
|
226
|
+
case '}':
|
|
227
|
+
case '*':
|
|
228
|
+
case '%':
|
|
229
|
+
case '|':
|
|
230
|
+
case '\r':
|
|
231
|
+
case '\n':
|
|
232
|
+
return i;
|
|
233
|
+
case '+':
|
|
234
|
+
case '~':
|
|
235
|
+
case '=':
|
|
236
|
+
if (source[i + 1] === fst) return i;
|
|
237
|
+
continue;
|
|
238
|
+
case '/':
|
|
239
|
+
if (source[i + 1] === fst && source[i + 2] === fst) return i;
|
|
240
|
+
continue;
|
|
241
|
+
case ':':
|
|
242
|
+
if (source[i + 1] === '/' && source[i + 2] === '/') return i;
|
|
243
|
+
continue;
|
|
244
|
+
//case ' ':
|
|
245
|
+
//case '\t':
|
|
246
|
+
//case ' ':
|
|
247
|
+
// if (i + 1 === source.length) return i;
|
|
248
|
+
// switch (source[i + 1]) {
|
|
249
|
+
// case ' ':
|
|
250
|
+
// case '\t':
|
|
251
|
+
// case '\r':
|
|
252
|
+
// case '\n':
|
|
253
|
+
// case ' ':
|
|
254
|
+
// case '$':
|
|
255
|
+
// case '%':
|
|
256
|
+
// return i;
|
|
257
|
+
// case '\\':
|
|
258
|
+
// if (i + 2 === source.length) return i;
|
|
259
|
+
// switch (source[i + 2]) {
|
|
260
|
+
// case ' ':
|
|
261
|
+
// case '\t':
|
|
262
|
+
// case '\r':
|
|
263
|
+
// case '\n':
|
|
264
|
+
// case ' ':
|
|
265
|
+
// return i;
|
|
266
|
+
// }
|
|
267
|
+
// }
|
|
268
|
+
// continue;
|
|
269
|
+
default:
|
|
270
|
+
delimiter.lastIndex = i;
|
|
271
|
+
if (delimiter.test(source)) return i;
|
|
272
|
+
continue;
|
|
273
|
+
}
|
|
274
|
+
assert(false);
|
|
275
|
+
}
|
|
276
|
+
return source.length;
|
|
277
|
+
}
|
|
278
|
+
|
|
279
|
+
const blank = /\s(?:$|\s|\\\n)/y;
|
|
280
|
+
export function isBlank(source: string, position: number): boolean {
|
|
281
|
+
blank.lastIndex = position;
|
|
282
|
+
return blank.test(source);
|
|
283
|
+
assert(position < source.length);
|
|
284
|
+
if (!isWhitespace(source[position])) return false;
|
|
285
|
+
if (position + 1 === source.length) return true;
|
|
286
|
+
const snd = source[position + 1];
|
|
287
|
+
if (isWhitespace(snd)) return true;
|
|
288
|
+
if (position + 2 === source.length) return false;
|
|
289
|
+
if (snd === '\\' && source[position + 2] === '\n') return true;
|
|
290
|
+
return false;
|
|
291
|
+
}
|
|
292
|
+
const whitespace = /\s/;
|
|
293
|
+
export function isWhitespace(char: string): boolean {
|
|
294
|
+
whitespace;
|
|
295
|
+
switch (char) {
|
|
296
|
+
case ' ':
|
|
297
|
+
case '\t':
|
|
298
|
+
case '\r':
|
|
299
|
+
case '\n':
|
|
300
|
+
case ' ':
|
|
301
|
+
return true
|
|
302
|
+
default:
|
|
303
|
+
return false;
|
|
304
|
+
}
|
|
305
|
+
}
|
|
@@ -30,9 +30,11 @@ export const unescsource: UnescapableSourceParser = ({ context }) => {
|
|
|
30
30
|
nonWhitespace.lastIndex = position + 1;
|
|
31
31
|
const b = isBlank(source, position);
|
|
32
32
|
let i = b
|
|
33
|
-
?
|
|
34
|
-
?
|
|
35
|
-
: source
|
|
33
|
+
? source[position + 1] === '\n'
|
|
34
|
+
? position + 1
|
|
35
|
+
: nonWhitespace.test(source)
|
|
36
|
+
? nonWhitespace.lastIndex - 1
|
|
37
|
+
: source.length
|
|
36
38
|
: next(source, position, delimiter);
|
|
37
39
|
assert(i > position);
|
|
38
40
|
i -= position;
|