marked 1.1.0 → 1.1.1
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 +168 -49
- package/lib/marked.js +168 -63
- package/marked.min.js +1 -1
- package/package.json +12 -11
- package/src/Lexer.js +24 -3
- package/src/Tokenizer.js +48 -22
- package/src/marked.js +16 -14
- package/src/rules.js +81 -11
package/src/Lexer.js
CHANGED
|
@@ -319,9 +319,29 @@ module.exports = class Lexer {
|
|
|
319
319
|
/**
|
|
320
320
|
* Lexing/Compiling
|
|
321
321
|
*/
|
|
322
|
-
inlineTokens(src, tokens = [], inLink = false, inRawBlock = false) {
|
|
322
|
+
inlineTokens(src, tokens = [], inLink = false, inRawBlock = false, prevChar = '') {
|
|
323
323
|
let token;
|
|
324
324
|
|
|
325
|
+
// String with links masked to avoid interference with em and strong
|
|
326
|
+
let maskedSrc = src;
|
|
327
|
+
let match;
|
|
328
|
+
|
|
329
|
+
// Mask out reflinks
|
|
330
|
+
if (this.tokens.links) {
|
|
331
|
+
const links = Object.keys(this.tokens.links);
|
|
332
|
+
if (links.length > 0) {
|
|
333
|
+
while ((match = this.tokenizer.rules.inline.reflinkSearch.exec(maskedSrc)) != null) {
|
|
334
|
+
if (links.includes(match[0].slice(match[0].lastIndexOf('[') + 1, -1))) {
|
|
335
|
+
maskedSrc = maskedSrc.slice(0, match.index) + '[' + 'a'.repeat(match[0].length - 2) + ']' + maskedSrc.slice(this.tokenizer.rules.inline.reflinkSearch.lastIndex);
|
|
336
|
+
}
|
|
337
|
+
}
|
|
338
|
+
}
|
|
339
|
+
}
|
|
340
|
+
// Mask out other blocks
|
|
341
|
+
while ((match = this.tokenizer.rules.inline.blockSkip.exec(maskedSrc)) != null) {
|
|
342
|
+
maskedSrc = maskedSrc.slice(0, match.index) + '[' + 'a'.repeat(match[0].length - 2) + ']' + maskedSrc.slice(this.tokenizer.rules.inline.blockSkip.lastIndex);
|
|
343
|
+
}
|
|
344
|
+
|
|
325
345
|
while (src) {
|
|
326
346
|
// escape
|
|
327
347
|
if (token = this.tokenizer.escape(src)) {
|
|
@@ -360,7 +380,7 @@ module.exports = class Lexer {
|
|
|
360
380
|
}
|
|
361
381
|
|
|
362
382
|
// strong
|
|
363
|
-
if (token = this.tokenizer.strong(src)) {
|
|
383
|
+
if (token = this.tokenizer.strong(src, maskedSrc, prevChar)) {
|
|
364
384
|
src = src.substring(token.raw.length);
|
|
365
385
|
token.tokens = this.inlineTokens(token.text, [], inLink, inRawBlock);
|
|
366
386
|
tokens.push(token);
|
|
@@ -368,7 +388,7 @@ module.exports = class Lexer {
|
|
|
368
388
|
}
|
|
369
389
|
|
|
370
390
|
// em
|
|
371
|
-
if (token = this.tokenizer.em(src)) {
|
|
391
|
+
if (token = this.tokenizer.em(src, maskedSrc, prevChar)) {
|
|
372
392
|
src = src.substring(token.raw.length);
|
|
373
393
|
token.tokens = this.inlineTokens(token.text, [], inLink, inRawBlock);
|
|
374
394
|
tokens.push(token);
|
|
@@ -414,6 +434,7 @@ module.exports = class Lexer {
|
|
|
414
434
|
// text
|
|
415
435
|
if (token = this.tokenizer.inlineText(src, inRawBlock, smartypants)) {
|
|
416
436
|
src = src.substring(token.raw.length);
|
|
437
|
+
prevChar = token.raw.slice(-1);
|
|
417
438
|
tokens.push(token);
|
|
418
439
|
continue;
|
|
419
440
|
}
|
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,15 +17,15 @@ 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
|
}
|
|
@@ -194,12 +195,13 @@ module.exports = class Tokenizer {
|
|
|
194
195
|
let raw = cap[0];
|
|
195
196
|
const bull = cap[2];
|
|
196
197
|
const isordered = bull.length > 1;
|
|
198
|
+
const isparen = bull[bull.length - 1] === ')';
|
|
197
199
|
|
|
198
200
|
const list = {
|
|
199
201
|
type: 'list',
|
|
200
202
|
raw,
|
|
201
203
|
ordered: isordered,
|
|
202
|
-
start: isordered ? +bull : '',
|
|
204
|
+
start: isordered ? +bull.slice(0, -1) : '',
|
|
203
205
|
loose: false,
|
|
204
206
|
items: []
|
|
205
207
|
};
|
|
@@ -224,7 +226,7 @@ module.exports = class Tokenizer {
|
|
|
224
226
|
// Remove the list item's bullet
|
|
225
227
|
// so it is seen as the next token.
|
|
226
228
|
space = item.length;
|
|
227
|
-
item = item.replace(/^ *([*+-]|\d
|
|
229
|
+
item = item.replace(/^ *([*+-]|\d+[.)]) */, '');
|
|
228
230
|
|
|
229
231
|
// Outdent whatever the
|
|
230
232
|
// list item contains. Hacky.
|
|
@@ -239,7 +241,7 @@ module.exports = class Tokenizer {
|
|
|
239
241
|
// Backpedal if it does not belong in this list.
|
|
240
242
|
if (i !== l - 1) {
|
|
241
243
|
b = this.rules.block.bullet.exec(itemMatch[i + 1])[0];
|
|
242
|
-
if (
|
|
244
|
+
if (isordered ? b.length === 1 || (!isparen && b[b.length - 1] === ')')
|
|
243
245
|
: (b.length > 1 || (this.options.smartLists && b !== bull))) {
|
|
244
246
|
addBack = itemMatch.slice(i + 1).join('\n');
|
|
245
247
|
list.raw = list.raw.substring(0, list.raw.length - addBack.length);
|
|
@@ -488,25 +490,49 @@ module.exports = class Tokenizer {
|
|
|
488
490
|
}
|
|
489
491
|
}
|
|
490
492
|
|
|
491
|
-
strong(src) {
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
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
|
+
}
|
|
499
513
|
}
|
|
500
514
|
}
|
|
501
515
|
|
|
502
|
-
em(src) {
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
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
|
+
}
|
|
510
536
|
}
|
|
511
537
|
}
|
|
512
538
|
|
package/src/marked.js
CHANGED
|
@@ -76,20 +76,22 @@ function marked(src, opt, callback) {
|
|
|
76
76
|
marked.walkTokens(tokens, function(token) {
|
|
77
77
|
if (token.type === 'code') {
|
|
78
78
|
pending++;
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
token.text
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
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);
|
|
93
95
|
}
|
|
94
96
|
});
|
|
95
97
|
|
package/src/rules.js
CHANGED
|
@@ -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)
|
|
@@ -168,19 +168,74 @@ 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))|(?= {2,}\n))
|
|
187
|
+
text: /^(`+|[^`])(?:[\s\S]*?(?:(?=[\\<!\[`*]|\b_|$)|[^ ](?= {2,}\n))|(?= {2,}\n))/,
|
|
188
|
+
punctuation: /^([\s*punctuation])/
|
|
177
189
|
};
|
|
178
190
|
|
|
179
191
|
// list of punctuation marks from common mark spec
|
|
180
|
-
// without
|
|
181
|
-
|
|
182
|
-
inline.
|
|
183
|
-
|
|
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.em.start = edit(inline.em.start)
|
|
201
|
+
.replace(/punctuation/g, inline._punctuation)
|
|
202
|
+
.getRegex();
|
|
203
|
+
|
|
204
|
+
inline.em.middle = edit(inline.em.middle)
|
|
205
|
+
.replace(/punctuation/g, inline._punctuation)
|
|
206
|
+
.replace(/overlapSkip/g, inline._overlapSkip)
|
|
207
|
+
.getRegex();
|
|
208
|
+
|
|
209
|
+
inline.em.endAst = edit(inline.em.endAst, 'g')
|
|
210
|
+
.replace(/punctuation/g, inline._punctuation)
|
|
211
|
+
.getRegex();
|
|
212
|
+
|
|
213
|
+
inline.em.endUnd = edit(inline.em.endUnd, 'g')
|
|
214
|
+
.replace(/punctuation/g, inline._punctuation)
|
|
215
|
+
.getRegex();
|
|
216
|
+
|
|
217
|
+
inline.strong.start = edit(inline.strong.start)
|
|
218
|
+
.replace(/punctuation/g, inline._punctuation)
|
|
219
|
+
.getRegex();
|
|
220
|
+
|
|
221
|
+
inline.strong.middle = edit(inline.strong.middle)
|
|
222
|
+
.replace(/punctuation/g, inline._punctuation)
|
|
223
|
+
.replace(/blockSkip/g, inline._blockSkip)
|
|
224
|
+
.getRegex();
|
|
225
|
+
|
|
226
|
+
inline.strong.endAst = edit(inline.strong.endAst, 'g')
|
|
227
|
+
.replace(/punctuation/g, inline._punctuation)
|
|
228
|
+
.getRegex();
|
|
229
|
+
|
|
230
|
+
inline.strong.endUnd = edit(inline.strong.endUnd, 'g')
|
|
231
|
+
.replace(/punctuation/g, inline._punctuation)
|
|
232
|
+
.getRegex();
|
|
233
|
+
|
|
234
|
+
inline.blockSkip = edit(inline._blockSkip, 'g')
|
|
235
|
+
.getRegex();
|
|
236
|
+
|
|
237
|
+
inline.overlapSkip = edit(inline._overlapSkip, 'g')
|
|
238
|
+
.getRegex();
|
|
184
239
|
|
|
185
240
|
inline._escapes = /\\([!"#$%&'()*+,\-./:;<=>?@\[\]\\^_`{|}~])/g;
|
|
186
241
|
|
|
@@ -198,7 +253,7 @@ inline.tag = edit(inline.tag)
|
|
|
198
253
|
.replace('attribute', inline._attribute)
|
|
199
254
|
.getRegex();
|
|
200
255
|
|
|
201
|
-
inline._label = /(?:\[[^\[\]]*\]|\\.|`[^`]*`|[^\[\]\\`])*?/;
|
|
256
|
+
inline._label = /(?:\[(?:\\.|[^\[\]\\])*\]|\\.|`[^`]*`|[^\[\]\\`])*?/;
|
|
202
257
|
inline._href = /<(?:\\[<>]?|[^\s<>\\])*>|[^\s\x00-\x1f]*/;
|
|
203
258
|
inline._title = /"(?:\\"?|[^"\\])*"|'(?:\\'?|[^'\\])*'|\((?:\\\)?|[^)\\])*\)/;
|
|
204
259
|
|
|
@@ -212,6 +267,11 @@ inline.reflink = edit(inline.reflink)
|
|
|
212
267
|
.replace('label', inline._label)
|
|
213
268
|
.getRegex();
|
|
214
269
|
|
|
270
|
+
inline.reflinkSearch = edit(inline.reflinkSearch, 'g')
|
|
271
|
+
.replace('reflink', inline.reflink)
|
|
272
|
+
.replace('nolink', inline.nolink)
|
|
273
|
+
.getRegex();
|
|
274
|
+
|
|
215
275
|
/**
|
|
216
276
|
* Normal Inline Grammar
|
|
217
277
|
*/
|
|
@@ -223,8 +283,18 @@ inline.normal = merge({}, inline);
|
|
|
223
283
|
*/
|
|
224
284
|
|
|
225
285
|
inline.pedantic = merge({}, inline.normal, {
|
|
226
|
-
strong:
|
|
227
|
-
|
|
286
|
+
strong: {
|
|
287
|
+
start: /^__|\*\*/,
|
|
288
|
+
middle: /^__(?=\S)([\s\S]*?\S)__(?!_)|^\*\*(?=\S)([\s\S]*?\S)\*\*(?!\*)/,
|
|
289
|
+
endAst: /\*\*(?!\*)/g,
|
|
290
|
+
endUnd: /__(?!_)/g
|
|
291
|
+
},
|
|
292
|
+
em: {
|
|
293
|
+
start: /^_|\*/,
|
|
294
|
+
middle: /^()\*(?=\S)([\s\S]*?\S)\*(?!\*)|^_(?=\S)([\s\S]*?\S)_(?!_)/,
|
|
295
|
+
endAst: /\*(?!\*)/g,
|
|
296
|
+
endUnd: /_(?!_)/g
|
|
297
|
+
},
|
|
228
298
|
link: edit(/^!?\[(label)\]\((.*?)\)/)
|
|
229
299
|
.replace('label', inline._label)
|
|
230
300
|
.getRegex(),
|