marked 1.0.0 → 1.2.0
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/lib/marked.esm.js +408 -115
- package/lib/marked.js +470 -136
- package/marked.min.js +1 -1
- package/package.json +17 -12
- package/src/Lexer.js +48 -7
- package/src/Parser.js +9 -1
- package/src/Renderer.js +1 -1
- package/src/Slugger.js +26 -10
- package/src/Tokenizer.js +110 -37
- package/src/defaults.js +1 -0
- package/src/marked.js +122 -41
- package/src/rules.js +91 -18
package/src/Tokenizer.js
CHANGED
|
@@ -9,6 +9,7 @@ const {
|
|
|
9
9
|
function outputLink(cap, link, raw) {
|
|
10
10
|
const href = link.href;
|
|
11
11
|
const title = link.title ? escape(link.title) : null;
|
|
12
|
+
const text = cap[1].replace(/\\([\[\]])/g, '$1');
|
|
12
13
|
|
|
13
14
|
if (cap[0].charAt(0) !== '!') {
|
|
14
15
|
return {
|
|
@@ -16,19 +17,47 @@ function outputLink(cap, link, raw) {
|
|
|
16
17
|
raw,
|
|
17
18
|
href,
|
|
18
19
|
title,
|
|
19
|
-
text
|
|
20
|
+
text
|
|
20
21
|
};
|
|
21
22
|
} else {
|
|
22
23
|
return {
|
|
23
24
|
type: 'image',
|
|
24
25
|
raw,
|
|
25
|
-
text: escape(cap[1]),
|
|
26
26
|
href,
|
|
27
|
-
title
|
|
27
|
+
title,
|
|
28
|
+
text: escape(text)
|
|
28
29
|
};
|
|
29
30
|
}
|
|
30
31
|
}
|
|
31
32
|
|
|
33
|
+
function indentCodeCompensation(raw, text) {
|
|
34
|
+
const matchIndentToCode = raw.match(/^(\s+)(?:```)/);
|
|
35
|
+
|
|
36
|
+
if (matchIndentToCode === null) {
|
|
37
|
+
return text;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
const indentToCode = matchIndentToCode[1];
|
|
41
|
+
|
|
42
|
+
return text
|
|
43
|
+
.split('\n')
|
|
44
|
+
.map(node => {
|
|
45
|
+
const matchIndentInNode = node.match(/^\s+/);
|
|
46
|
+
if (matchIndentInNode === null) {
|
|
47
|
+
return node;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
const [indentInNode] = matchIndentInNode;
|
|
51
|
+
|
|
52
|
+
if (indentInNode.length >= indentToCode.length) {
|
|
53
|
+
return node.slice(indentToCode.length);
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
return node;
|
|
57
|
+
})
|
|
58
|
+
.join('\n');
|
|
59
|
+
}
|
|
60
|
+
|
|
32
61
|
/**
|
|
33
62
|
* Tokenizer
|
|
34
63
|
*/
|
|
@@ -56,32 +85,35 @@ module.exports = class Tokenizer {
|
|
|
56
85
|
const lastToken = tokens[tokens.length - 1];
|
|
57
86
|
// An indented code block cannot interrupt a paragraph.
|
|
58
87
|
if (lastToken && lastToken.type === 'paragraph') {
|
|
59
|
-
tokens.pop();
|
|
60
|
-
lastToken.text += '\n' + cap[0].trimRight();
|
|
61
|
-
lastToken.raw += '\n' + cap[0];
|
|
62
|
-
return lastToken;
|
|
63
|
-
} else {
|
|
64
|
-
const text = cap[0].replace(/^ {4}/gm, '');
|
|
65
88
|
return {
|
|
66
|
-
type: 'code',
|
|
67
89
|
raw: cap[0],
|
|
68
|
-
|
|
69
|
-
text: !this.options.pedantic
|
|
70
|
-
? rtrim(text, '\n')
|
|
71
|
-
: text
|
|
90
|
+
text: cap[0].trimRight()
|
|
72
91
|
};
|
|
73
92
|
}
|
|
93
|
+
|
|
94
|
+
const text = cap[0].replace(/^ {4}/gm, '');
|
|
95
|
+
return {
|
|
96
|
+
type: 'code',
|
|
97
|
+
raw: cap[0],
|
|
98
|
+
codeBlockStyle: 'indented',
|
|
99
|
+
text: !this.options.pedantic
|
|
100
|
+
? rtrim(text, '\n')
|
|
101
|
+
: text
|
|
102
|
+
};
|
|
74
103
|
}
|
|
75
104
|
}
|
|
76
105
|
|
|
77
106
|
fences(src) {
|
|
78
107
|
const cap = this.rules.block.fences.exec(src);
|
|
79
108
|
if (cap) {
|
|
109
|
+
const raw = cap[0];
|
|
110
|
+
const text = indentCodeCompensation(raw, cap[3] || '');
|
|
111
|
+
|
|
80
112
|
return {
|
|
81
113
|
type: 'code',
|
|
82
|
-
raw
|
|
114
|
+
raw,
|
|
83
115
|
lang: cap[2] ? cap[2].trim() : cap[2],
|
|
84
|
-
text
|
|
116
|
+
text
|
|
85
117
|
};
|
|
86
118
|
}
|
|
87
119
|
}
|
|
@@ -163,12 +195,13 @@ module.exports = class Tokenizer {
|
|
|
163
195
|
let raw = cap[0];
|
|
164
196
|
const bull = cap[2];
|
|
165
197
|
const isordered = bull.length > 1;
|
|
198
|
+
const isparen = bull[bull.length - 1] === ')';
|
|
166
199
|
|
|
167
200
|
const list = {
|
|
168
201
|
type: 'list',
|
|
169
202
|
raw,
|
|
170
203
|
ordered: isordered,
|
|
171
|
-
start: isordered ? +bull : '',
|
|
204
|
+
start: isordered ? +bull.slice(0, -1) : '',
|
|
172
205
|
loose: false,
|
|
173
206
|
items: []
|
|
174
207
|
};
|
|
@@ -193,7 +226,7 @@ module.exports = class Tokenizer {
|
|
|
193
226
|
// Remove the list item's bullet
|
|
194
227
|
// so it is seen as the next token.
|
|
195
228
|
space = item.length;
|
|
196
|
-
item = item.replace(/^ *([*+-]|\d
|
|
229
|
+
item = item.replace(/^ *([*+-]|\d+[.)]) */, '');
|
|
197
230
|
|
|
198
231
|
// Outdent whatever the
|
|
199
232
|
// list item contains. Hacky.
|
|
@@ -208,7 +241,7 @@ module.exports = class Tokenizer {
|
|
|
208
241
|
// Backpedal if it does not belong in this list.
|
|
209
242
|
if (i !== l - 1) {
|
|
210
243
|
b = this.rules.block.bullet.exec(itemMatch[i + 1])[0];
|
|
211
|
-
if (
|
|
244
|
+
if (isordered ? b.length === 1 || (!isparen && b[b.length - 1] === ')')
|
|
212
245
|
: (b.length > 1 || (this.options.smartLists && b !== bull))) {
|
|
213
246
|
addBack = itemMatch.slice(i + 1).join('\n');
|
|
214
247
|
list.raw = list.raw.substring(0, list.raw.length - addBack.length);
|
|
@@ -238,6 +271,7 @@ module.exports = class Tokenizer {
|
|
|
238
271
|
}
|
|
239
272
|
|
|
240
273
|
list.items.push({
|
|
274
|
+
type: 'list_item',
|
|
241
275
|
raw,
|
|
242
276
|
task: istask,
|
|
243
277
|
checked: ischecked,
|
|
@@ -343,9 +377,17 @@ module.exports = class Tokenizer {
|
|
|
343
377
|
}
|
|
344
378
|
}
|
|
345
379
|
|
|
346
|
-
text(src) {
|
|
380
|
+
text(src, tokens) {
|
|
347
381
|
const cap = this.rules.block.text.exec(src);
|
|
348
382
|
if (cap) {
|
|
383
|
+
const lastToken = tokens[tokens.length - 1];
|
|
384
|
+
if (lastToken && lastToken.type === 'text') {
|
|
385
|
+
return {
|
|
386
|
+
raw: cap[0],
|
|
387
|
+
text: cap[0]
|
|
388
|
+
};
|
|
389
|
+
}
|
|
390
|
+
|
|
349
391
|
return {
|
|
350
392
|
type: 'text',
|
|
351
393
|
raw: cap[0],
|
|
@@ -448,35 +490,66 @@ module.exports = class Tokenizer {
|
|
|
448
490
|
}
|
|
449
491
|
}
|
|
450
492
|
|
|
451
|
-
strong(src) {
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
493
|
+
strong(src, maskedSrc, prevChar = '') {
|
|
494
|
+
let match = this.rules.inline.strong.start.exec(src);
|
|
495
|
+
|
|
496
|
+
if (match && (!match[1] || (match[1] && (prevChar === '' || this.rules.inline.punctuation.exec(prevChar))))) {
|
|
497
|
+
maskedSrc = maskedSrc.slice(-1 * src.length);
|
|
498
|
+
const endReg = match[0] === '**' ? this.rules.inline.strong.endAst : this.rules.inline.strong.endUnd;
|
|
499
|
+
|
|
500
|
+
endReg.lastIndex = 0;
|
|
501
|
+
|
|
502
|
+
let cap;
|
|
503
|
+
while ((match = endReg.exec(maskedSrc)) != null) {
|
|
504
|
+
cap = this.rules.inline.strong.middle.exec(maskedSrc.slice(0, match.index + 3));
|
|
505
|
+
if (cap) {
|
|
506
|
+
return {
|
|
507
|
+
type: 'strong',
|
|
508
|
+
raw: src.slice(0, cap[0].length),
|
|
509
|
+
text: src.slice(2, cap[0].length - 2)
|
|
510
|
+
};
|
|
511
|
+
}
|
|
512
|
+
}
|
|
459
513
|
}
|
|
460
514
|
}
|
|
461
515
|
|
|
462
|
-
em(src) {
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
516
|
+
em(src, maskedSrc, prevChar = '') {
|
|
517
|
+
let match = this.rules.inline.em.start.exec(src);
|
|
518
|
+
|
|
519
|
+
if (match && (!match[1] || (match[1] && (prevChar === '' || this.rules.inline.punctuation.exec(prevChar))))) {
|
|
520
|
+
maskedSrc = maskedSrc.slice(-1 * src.length);
|
|
521
|
+
const endReg = match[0] === '*' ? this.rules.inline.em.endAst : this.rules.inline.em.endUnd;
|
|
522
|
+
|
|
523
|
+
endReg.lastIndex = 0;
|
|
524
|
+
|
|
525
|
+
let cap;
|
|
526
|
+
while ((match = endReg.exec(maskedSrc)) != null) {
|
|
527
|
+
cap = this.rules.inline.em.middle.exec(maskedSrc.slice(0, match.index + 2));
|
|
528
|
+
if (cap) {
|
|
529
|
+
return {
|
|
530
|
+
type: 'em',
|
|
531
|
+
raw: src.slice(0, cap[0].length),
|
|
532
|
+
text: src.slice(1, cap[0].length - 1)
|
|
533
|
+
};
|
|
534
|
+
}
|
|
535
|
+
}
|
|
470
536
|
}
|
|
471
537
|
}
|
|
472
538
|
|
|
473
539
|
codespan(src) {
|
|
474
540
|
const cap = this.rules.inline.code.exec(src);
|
|
475
541
|
if (cap) {
|
|
542
|
+
let text = cap[2].replace(/\n/g, ' ');
|
|
543
|
+
const hasNonSpaceChars = /[^ ]/.test(text);
|
|
544
|
+
const hasSpaceCharsOnBothEnds = text.startsWith(' ') && text.endsWith(' ');
|
|
545
|
+
if (hasNonSpaceChars && hasSpaceCharsOnBothEnds) {
|
|
546
|
+
text = text.substring(1, text.length - 1);
|
|
547
|
+
}
|
|
548
|
+
text = escape(text, true);
|
|
476
549
|
return {
|
|
477
550
|
type: 'codespan',
|
|
478
551
|
raw: cap[0],
|
|
479
|
-
text
|
|
552
|
+
text
|
|
480
553
|
};
|
|
481
554
|
}
|
|
482
555
|
}
|
package/src/defaults.js
CHANGED
package/src/marked.js
CHANGED
|
@@ -28,18 +28,17 @@ function marked(src, opt, callback) {
|
|
|
28
28
|
+ Object.prototype.toString.call(src) + ', string expected');
|
|
29
29
|
}
|
|
30
30
|
|
|
31
|
-
if (
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
}
|
|
31
|
+
if (typeof opt === 'function') {
|
|
32
|
+
callback = opt;
|
|
33
|
+
opt = null;
|
|
34
|
+
}
|
|
36
35
|
|
|
37
|
-
|
|
38
|
-
|
|
36
|
+
opt = merge({}, marked.defaults, opt || {});
|
|
37
|
+
checkSanitizeDeprecation(opt);
|
|
38
|
+
|
|
39
|
+
if (callback) {
|
|
39
40
|
const highlight = opt.highlight;
|
|
40
|
-
let tokens
|
|
41
|
-
pending,
|
|
42
|
-
i = 0;
|
|
41
|
+
let tokens;
|
|
43
42
|
|
|
44
43
|
try {
|
|
45
44
|
tokens = Lexer.lex(src, opt);
|
|
@@ -47,20 +46,15 @@ function marked(src, opt, callback) {
|
|
|
47
46
|
return callback(e);
|
|
48
47
|
}
|
|
49
48
|
|
|
50
|
-
pending = tokens.length;
|
|
51
|
-
|
|
52
49
|
const done = function(err) {
|
|
53
|
-
if (err) {
|
|
54
|
-
opt.highlight = highlight;
|
|
55
|
-
return callback(err);
|
|
56
|
-
}
|
|
57
|
-
|
|
58
50
|
let out;
|
|
59
51
|
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
52
|
+
if (!err) {
|
|
53
|
+
try {
|
|
54
|
+
out = Parser.parse(tokens, opt);
|
|
55
|
+
} catch (e) {
|
|
56
|
+
err = e;
|
|
57
|
+
}
|
|
64
58
|
}
|
|
65
59
|
|
|
66
60
|
opt.highlight = highlight;
|
|
@@ -76,34 +70,47 @@ function marked(src, opt, callback) {
|
|
|
76
70
|
|
|
77
71
|
delete opt.highlight;
|
|
78
72
|
|
|
79
|
-
if (!
|
|
73
|
+
if (!tokens.length) return done();
|
|
80
74
|
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
75
|
+
let pending = 0;
|
|
76
|
+
marked.walkTokens(tokens, function(token) {
|
|
77
|
+
if (token.type === 'code') {
|
|
78
|
+
pending++;
|
|
79
|
+
setTimeout(() => {
|
|
80
|
+
highlight(token.text, token.lang, function(err, code) {
|
|
81
|
+
if (err) {
|
|
82
|
+
return done(err);
|
|
83
|
+
}
|
|
84
|
+
if (code != null && code !== token.text) {
|
|
85
|
+
token.text = code;
|
|
86
|
+
token.escaped = true;
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
pending--;
|
|
90
|
+
if (pending === 0) {
|
|
91
|
+
done();
|
|
92
|
+
}
|
|
93
|
+
});
|
|
94
|
+
}, 0);
|
|
95
|
+
}
|
|
96
|
+
});
|
|
97
|
+
|
|
98
|
+
if (pending === 0) {
|
|
99
|
+
done();
|
|
96
100
|
}
|
|
97
101
|
|
|
98
102
|
return;
|
|
99
103
|
}
|
|
104
|
+
|
|
100
105
|
try {
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
106
|
+
const tokens = Lexer.lex(src, opt);
|
|
107
|
+
if (opt.walkTokens) {
|
|
108
|
+
marked.walkTokens(tokens, opt.walkTokens);
|
|
109
|
+
}
|
|
110
|
+
return Parser.parse(tokens, opt);
|
|
104
111
|
} catch (e) {
|
|
105
112
|
e.message += '\nPlease report this to https://github.com/markedjs/marked.';
|
|
106
|
-
if (
|
|
113
|
+
if (opt.silent) {
|
|
107
114
|
return '<p>An error occurred:</p><pre>'
|
|
108
115
|
+ escape(e.message + '', true)
|
|
109
116
|
+ '</pre>';
|
|
@@ -161,9 +168,83 @@ marked.use = function(extension) {
|
|
|
161
168
|
}
|
|
162
169
|
opts.tokenizer = tokenizer;
|
|
163
170
|
}
|
|
171
|
+
if (extension.walkTokens) {
|
|
172
|
+
const walkTokens = marked.defaults.walkTokens;
|
|
173
|
+
opts.walkTokens = (token) => {
|
|
174
|
+
extension.walkTokens(token);
|
|
175
|
+
if (walkTokens) {
|
|
176
|
+
walkTokens(token);
|
|
177
|
+
}
|
|
178
|
+
};
|
|
179
|
+
}
|
|
164
180
|
marked.setOptions(opts);
|
|
165
181
|
};
|
|
166
182
|
|
|
183
|
+
/**
|
|
184
|
+
* Run callback for every token
|
|
185
|
+
*/
|
|
186
|
+
|
|
187
|
+
marked.walkTokens = function(tokens, callback) {
|
|
188
|
+
for (const token of tokens) {
|
|
189
|
+
callback(token);
|
|
190
|
+
switch (token.type) {
|
|
191
|
+
case 'table': {
|
|
192
|
+
for (const cell of token.tokens.header) {
|
|
193
|
+
marked.walkTokens(cell, callback);
|
|
194
|
+
}
|
|
195
|
+
for (const row of token.tokens.cells) {
|
|
196
|
+
for (const cell of row) {
|
|
197
|
+
marked.walkTokens(cell, callback);
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
break;
|
|
201
|
+
}
|
|
202
|
+
case 'list': {
|
|
203
|
+
marked.walkTokens(token.items, callback);
|
|
204
|
+
break;
|
|
205
|
+
}
|
|
206
|
+
default: {
|
|
207
|
+
if (token.tokens) {
|
|
208
|
+
marked.walkTokens(token.tokens, callback);
|
|
209
|
+
}
|
|
210
|
+
}
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
};
|
|
214
|
+
|
|
215
|
+
/**
|
|
216
|
+
* Parse Inline
|
|
217
|
+
*/
|
|
218
|
+
marked.parseInline = function(src, opt) {
|
|
219
|
+
// throw error in case of non string input
|
|
220
|
+
if (typeof src === 'undefined' || src === null) {
|
|
221
|
+
throw new Error('marked.parseInline(): input parameter is undefined or null');
|
|
222
|
+
}
|
|
223
|
+
if (typeof src !== 'string') {
|
|
224
|
+
throw new Error('marked.parseInline(): input parameter is of type '
|
|
225
|
+
+ Object.prototype.toString.call(src) + ', string expected');
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
opt = merge({}, marked.defaults, opt || {});
|
|
229
|
+
checkSanitizeDeprecation(opt);
|
|
230
|
+
|
|
231
|
+
try {
|
|
232
|
+
const tokens = Lexer.lexInline(src, opt);
|
|
233
|
+
if (opt.walkTokens) {
|
|
234
|
+
marked.walkTokens(tokens, opt.walkTokens);
|
|
235
|
+
}
|
|
236
|
+
return Parser.parseInline(tokens, opt);
|
|
237
|
+
} catch (e) {
|
|
238
|
+
e.message += '\nPlease report this to https://github.com/markedjs/marked.';
|
|
239
|
+
if (opt.silent) {
|
|
240
|
+
return '<p>An error occurred:</p><pre>'
|
|
241
|
+
+ escape(e.message + '', true)
|
|
242
|
+
+ '</pre>';
|
|
243
|
+
}
|
|
244
|
+
throw e;
|
|
245
|
+
}
|
|
246
|
+
};
|
|
247
|
+
|
|
167
248
|
/**
|
|
168
249
|
* Expose
|
|
169
250
|
*/
|
package/src/rules.js
CHANGED
|
@@ -18,9 +18,9 @@ const block = {
|
|
|
18
18
|
html: '^ {0,3}(?:' // optional indentation
|
|
19
19
|
+ '<(script|pre|style)[\\s>][\\s\\S]*?(?:</\\1>[^\\n]*\\n+|$)' // (1)
|
|
20
20
|
+ '|comment[^\\n]*(\\n+|$)' // (2)
|
|
21
|
-
+ '|<\\?[\\s\\S]
|
|
22
|
-
+ '|<![A-Z][\\s\\S]
|
|
23
|
-
+ '|<!\\[CDATA\\[[\\s\\S]
|
|
21
|
+
+ '|<\\?[\\s\\S]*?(?:\\?>\\n*|$)' // (3)
|
|
22
|
+
+ '|<![A-Z][\\s\\S]*?(?:>\\n*|$)' // (4)
|
|
23
|
+
+ '|<!\\[CDATA\\[[\\s\\S]*?(?:\\]\\]>\\n*|$)' // (5)
|
|
24
24
|
+ '|</?(tag)(?: +|\\n|/?>)[\\s\\S]*?(?:\\n{2,}|$)' // (6)
|
|
25
25
|
+ '|<(?!script|pre|style)([a-z][\\w-]*)(?:attribute)*? */?>(?=[ \\t]*(?:\\n|$))[\\s\\S]*?(?:\\n{2,}|$)' // (7) open tag
|
|
26
26
|
+ '|</(?!script|pre|style)[a-z][\\w-]*\\s*>(?=[ \\t]*(?:\\n|$))[\\s\\S]*?(?:\\n{2,}|$)' // (7) closing tag
|
|
@@ -42,7 +42,7 @@ block.def = edit(block.def)
|
|
|
42
42
|
.replace('title', block._title)
|
|
43
43
|
.getRegex();
|
|
44
44
|
|
|
45
|
-
block.bullet = /(?:[*+-]|\d{1,9}
|
|
45
|
+
block.bullet = /(?:[*+-]|\d{1,9}[.)])/;
|
|
46
46
|
block.item = /^( *)(bull) ?[^\n]*(?:\n(?!\1bull ?)[^\n]*)*/;
|
|
47
47
|
block.item = edit(block.item, 'gm')
|
|
48
48
|
.replace(/bull/g, block.bullet)
|
|
@@ -60,7 +60,7 @@ block._tag = 'address|article|aside|base|basefont|blockquote|body|caption'
|
|
|
60
60
|
+ '|legend|li|link|main|menu|menuitem|meta|nav|noframes|ol|optgroup|option'
|
|
61
61
|
+ '|p|param|section|source|summary|table|tbody|td|tfoot|th|thead|title|tr'
|
|
62
62
|
+ '|track|ul';
|
|
63
|
-
block._comment = /<!--(?!-?>)[\s\S]
|
|
63
|
+
block._comment = /<!--(?!-?>)[\s\S]*?(?:-->|$)/;
|
|
64
64
|
block.html = edit(block.html, 'i')
|
|
65
65
|
.replace('comment', block._comment)
|
|
66
66
|
.replace('tag', block._tag)
|
|
@@ -94,10 +94,10 @@ block.normal = merge({}, block);
|
|
|
94
94
|
|
|
95
95
|
block.gfm = merge({}, block.normal, {
|
|
96
96
|
nptable: '^ *([^|\\n ].*\\|.*)\\n' // Header
|
|
97
|
-
+ '
|
|
97
|
+
+ ' {0,3}([-:]+ *\\|[-| :]*)' // Align
|
|
98
98
|
+ '(?:\\n((?:(?!\\n|hr|heading|blockquote|code|fences|list|html).*(?:\\n|$))*)\\n*|$)', // Cells
|
|
99
99
|
table: '^ *\\|(.+)\\n' // Header
|
|
100
|
-
+ '
|
|
100
|
+
+ ' {0,3}\\|?( *[-:]+[-| :]*)' // Align
|
|
101
101
|
+ '(?:\\n *((?:(?!\\n|hr|heading|blockquote|code|fences|list|html).*(?:\\n|$))*)\\n*|$)' // Cells
|
|
102
102
|
});
|
|
103
103
|
|
|
@@ -168,18 +168,76 @@ const inline = {
|
|
|
168
168
|
link: /^!?\[(label)\]\(\s*(href)(?:\s+(title))?\s*\)/,
|
|
169
169
|
reflink: /^!?\[(label)\]\[(?!\s*\])((?:\\[\[\]]?|[^\[\]\\])+)\]/,
|
|
170
170
|
nolink: /^!?\[(?!\s*\])((?:\[[^\[\]]*\]|\\[\[\]]|[^\[\]])*)\](?:\[\])?/,
|
|
171
|
-
|
|
172
|
-
|
|
171
|
+
reflinkSearch: 'reflink|nolink(?!\\()',
|
|
172
|
+
strong: {
|
|
173
|
+
start: /^(?:(\*\*(?=[*punctuation]))|\*\*)(?![\s])|__/, // (1) returns if starts w/ punctuation
|
|
174
|
+
middle: /^\*\*(?:(?:(?!overlapSkip)(?:[^*]|\\\*)|overlapSkip)|\*(?:(?!overlapSkip)(?:[^*]|\\\*)|overlapSkip)*?\*)+?\*\*$|^__(?![\s])((?:(?:(?!overlapSkip)(?:[^_]|\\_)|overlapSkip)|_(?:(?!overlapSkip)(?:[^_]|\\_)|overlapSkip)*?_)+?)__$/,
|
|
175
|
+
endAst: /[^punctuation\s]\*\*(?!\*)|[punctuation]\*\*(?!\*)(?:(?=[punctuation_\s]|$))/, // last char can't be punct, or final * must also be followed by punct (or endline)
|
|
176
|
+
endUnd: /[^\s]__(?!_)(?:(?=[punctuation*\s])|$)/ // last char can't be a space, and final _ must preceed punct or \s (or endline)
|
|
177
|
+
},
|
|
178
|
+
em: {
|
|
179
|
+
start: /^(?:(\*(?=[punctuation]))|\*)(?![*\s])|_/, // (1) returns if starts w/ punctuation
|
|
180
|
+
middle: /^\*(?:(?:(?!overlapSkip)(?:[^*]|\\\*)|overlapSkip)|\*(?:(?!overlapSkip)(?:[^*]|\\\*)|overlapSkip)*?\*)+?\*$|^_(?![_\s])(?:(?:(?!overlapSkip)(?:[^_]|\\_)|overlapSkip)|_(?:(?!overlapSkip)(?:[^_]|\\_)|overlapSkip)*?_)+?_$/,
|
|
181
|
+
endAst: /[^punctuation\s]\*(?!\*)|[punctuation]\*(?!\*)(?:(?=[punctuation_\s]|$))/, // last char can't be punct, or final * must also be followed by punct (or endline)
|
|
182
|
+
endUnd: /[^\s]_(?!_)(?:(?=[punctuation*\s])|$)/ // last char can't be a space, and final _ must preceed punct or \s (or endline)
|
|
183
|
+
},
|
|
173
184
|
code: /^(`+)([^`]|[^`][\s\S]*?[^`])\1(?!`)/,
|
|
174
185
|
br: /^( {2,}|\\)\n(?!\s*$)/,
|
|
175
186
|
del: noopTest,
|
|
176
|
-
text: /^(`+|[^`])(?:[\s\S]*?(?:(?=[\\<!\[`*]|\b_|$)|[^ ](?= {2,}\n))
|
|
187
|
+
text: /^(`+|[^`])(?:(?= {2,}\n)|[\s\S]*?(?:(?=[\\<!\[`*]|\b_|$)|[^ ](?= {2,}\n)))/,
|
|
188
|
+
punctuation: /^([\s*punctuation])/
|
|
177
189
|
};
|
|
178
190
|
|
|
179
191
|
// list of punctuation marks from common mark spec
|
|
180
|
-
// without
|
|
181
|
-
inline._punctuation = '!"#$%&\'()
|
|
182
|
-
inline.
|
|
192
|
+
// without * and _ to workaround cases with double emphasis
|
|
193
|
+
inline._punctuation = '!"#$%&\'()+\\-.,/:;<=>?@\\[\\]`^{|}~';
|
|
194
|
+
inline.punctuation = edit(inline.punctuation).replace(/punctuation/g, inline._punctuation).getRegex();
|
|
195
|
+
|
|
196
|
+
// sequences em should skip over [title](link), `code`, <html>
|
|
197
|
+
inline._blockSkip = '\\[[^\\]]*?\\]\\([^\\)]*?\\)|`[^`]*?`|<[^>]*?>';
|
|
198
|
+
inline._overlapSkip = '__[^_]*?__|\\*\\*\\[^\\*\\]*?\\*\\*';
|
|
199
|
+
|
|
200
|
+
inline._comment = edit(block._comment).replace('(?:-->|$)', '-->').getRegex();
|
|
201
|
+
|
|
202
|
+
inline.em.start = edit(inline.em.start)
|
|
203
|
+
.replace(/punctuation/g, inline._punctuation)
|
|
204
|
+
.getRegex();
|
|
205
|
+
|
|
206
|
+
inline.em.middle = edit(inline.em.middle)
|
|
207
|
+
.replace(/punctuation/g, inline._punctuation)
|
|
208
|
+
.replace(/overlapSkip/g, inline._overlapSkip)
|
|
209
|
+
.getRegex();
|
|
210
|
+
|
|
211
|
+
inline.em.endAst = edit(inline.em.endAst, 'g')
|
|
212
|
+
.replace(/punctuation/g, inline._punctuation)
|
|
213
|
+
.getRegex();
|
|
214
|
+
|
|
215
|
+
inline.em.endUnd = edit(inline.em.endUnd, 'g')
|
|
216
|
+
.replace(/punctuation/g, inline._punctuation)
|
|
217
|
+
.getRegex();
|
|
218
|
+
|
|
219
|
+
inline.strong.start = edit(inline.strong.start)
|
|
220
|
+
.replace(/punctuation/g, inline._punctuation)
|
|
221
|
+
.getRegex();
|
|
222
|
+
|
|
223
|
+
inline.strong.middle = edit(inline.strong.middle)
|
|
224
|
+
.replace(/punctuation/g, inline._punctuation)
|
|
225
|
+
.replace(/overlapSkip/g, inline._overlapSkip)
|
|
226
|
+
.getRegex();
|
|
227
|
+
|
|
228
|
+
inline.strong.endAst = edit(inline.strong.endAst, 'g')
|
|
229
|
+
.replace(/punctuation/g, inline._punctuation)
|
|
230
|
+
.getRegex();
|
|
231
|
+
|
|
232
|
+
inline.strong.endUnd = edit(inline.strong.endUnd, 'g')
|
|
233
|
+
.replace(/punctuation/g, inline._punctuation)
|
|
234
|
+
.getRegex();
|
|
235
|
+
|
|
236
|
+
inline.blockSkip = edit(inline._blockSkip, 'g')
|
|
237
|
+
.getRegex();
|
|
238
|
+
|
|
239
|
+
inline.overlapSkip = edit(inline._overlapSkip, 'g')
|
|
240
|
+
.getRegex();
|
|
183
241
|
|
|
184
242
|
inline._escapes = /\\([!"#$%&'()*+,\-./:;<=>?@\[\]\\^_`{|}~])/g;
|
|
185
243
|
|
|
@@ -193,11 +251,11 @@ inline.autolink = edit(inline.autolink)
|
|
|
193
251
|
inline._attribute = /\s+[a-zA-Z:_][\w.:-]*(?:\s*=\s*"[^"]*"|\s*=\s*'[^']*'|\s*=\s*[^\s"'=<>`]+)?/;
|
|
194
252
|
|
|
195
253
|
inline.tag = edit(inline.tag)
|
|
196
|
-
.replace('comment',
|
|
254
|
+
.replace('comment', inline._comment)
|
|
197
255
|
.replace('attribute', inline._attribute)
|
|
198
256
|
.getRegex();
|
|
199
257
|
|
|
200
|
-
inline._label = /(?:\[[^\[\]]*\]|\\.|`[^`]*`|[^\[\]\\`])*?/;
|
|
258
|
+
inline._label = /(?:\[(?:\\.|[^\[\]\\])*\]|\\.|`[^`]*`|[^\[\]\\`])*?/;
|
|
201
259
|
inline._href = /<(?:\\[<>]?|[^\s<>\\])*>|[^\s\x00-\x1f]*/;
|
|
202
260
|
inline._title = /"(?:\\"?|[^"\\])*"|'(?:\\'?|[^'\\])*'|\((?:\\\)?|[^)\\])*\)/;
|
|
203
261
|
|
|
@@ -211,6 +269,11 @@ inline.reflink = edit(inline.reflink)
|
|
|
211
269
|
.replace('label', inline._label)
|
|
212
270
|
.getRegex();
|
|
213
271
|
|
|
272
|
+
inline.reflinkSearch = edit(inline.reflinkSearch, 'g')
|
|
273
|
+
.replace('reflink', inline.reflink)
|
|
274
|
+
.replace('nolink', inline.nolink)
|
|
275
|
+
.getRegex();
|
|
276
|
+
|
|
214
277
|
/**
|
|
215
278
|
* Normal Inline Grammar
|
|
216
279
|
*/
|
|
@@ -222,8 +285,18 @@ inline.normal = merge({}, inline);
|
|
|
222
285
|
*/
|
|
223
286
|
|
|
224
287
|
inline.pedantic = merge({}, inline.normal, {
|
|
225
|
-
strong:
|
|
226
|
-
|
|
288
|
+
strong: {
|
|
289
|
+
start: /^__|\*\*/,
|
|
290
|
+
middle: /^__(?=\S)([\s\S]*?\S)__(?!_)|^\*\*(?=\S)([\s\S]*?\S)\*\*(?!\*)/,
|
|
291
|
+
endAst: /\*\*(?!\*)/g,
|
|
292
|
+
endUnd: /__(?!_)/g
|
|
293
|
+
},
|
|
294
|
+
em: {
|
|
295
|
+
start: /^_|\*/,
|
|
296
|
+
middle: /^()\*(?=\S)([\s\S]*?\S)\*(?!\*)|^_(?=\S)([\s\S]*?\S)_(?!_)/,
|
|
297
|
+
endAst: /\*(?!\*)/g,
|
|
298
|
+
endUnd: /_(?!_)/g
|
|
299
|
+
},
|
|
227
300
|
link: edit(/^!?\[(label)\]\((.*?)\)/)
|
|
228
301
|
.replace('label', inline._label)
|
|
229
302
|
.getRegex(),
|
|
@@ -242,7 +315,7 @@ inline.gfm = merge({}, inline.normal, {
|
|
|
242
315
|
url: /^((?:ftp|https?):\/\/|www\.)(?:[a-zA-Z0-9\-]+\.?)+[^\s<]*|^email/,
|
|
243
316
|
_backpedal: /(?:[^?!.,:;*_~()&]+|\([^)]*\)|&(?![a-zA-Z0-9]+;$)|[?!.,:;*_~)]+(?!$))+/,
|
|
244
317
|
del: /^~+(?=\S)([\s\S]*?\S)~+/,
|
|
245
|
-
text: /^(`+|[^`])(?:[\s\S]*?(?:(?=[\\<!\[`*~]|\b_|https?:\/\/|ftp:\/\/|www\.|$)|[^ ](?= {2,}\n)|[^a-zA-Z0-9.!#$%&'*+\/=?_`{\|}~-](?=[a-zA-Z0-9.!#$%&'*+\/=?_`{\|}~-]+@))|(?=
|
|
318
|
+
text: /^(`+|[^`])(?:(?= {2,}\n)|[\s\S]*?(?:(?=[\\<!\[`*~]|\b_|https?:\/\/|ftp:\/\/|www\.|$)|[^ ](?= {2,}\n)|[^a-zA-Z0-9.!#$%&'*+\/=?_`{\|}~-](?=[a-zA-Z0-9.!#$%&'*+\/=?_`{\|}~-]+@))|(?=[a-zA-Z0-9.!#$%&'*+\/=?_`{\|}~-]+@))/
|
|
246
319
|
});
|
|
247
320
|
|
|
248
321
|
inline.gfm.url = edit(inline.gfm.url, 'i')
|