UNPKG

28.5 kBJavaScriptView Raw
1'use strict';
2
3function merge(obj) {
4 var arguments$1 = arguments;
5
6 var i = 1;
7 var target;
8 var key;
9
10 for (; i < arguments.length; i++) {
11 target = arguments$1[i];
12 for (key in target) {
13 if (Object.prototype.hasOwnProperty.call(target, key)) {
14 obj[key] = target[key];
15 }
16 }
17 }
18
19 return obj
20}
21
22function noop() {}
23noop.exec = noop;
24
25function escape$1(html, encode) {
26 return html
27 .replace(encode ? /&/g : /&(?!#?\w+;)/g, '&amp;')
28 .replace(/</g, '&lt;')
29 .replace(/>/g, '&gt;')
30 .replace(/"/g, '&quot;')
31 .replace(/'/g, '&#39;')
32}
33
34function unescape(html) {
35 // explicitly match decimal, hex, and named HTML entities
36 return html.replace(/&(#(?:\d+)|(?:#x[0-9A-Fa-f]+)|(?:\w+));?/g, function (_, n) {
37 n = n.toLowerCase();
38 if (n === 'colon') { return ':' }
39 if (n.charAt(0) === '#') {
40 return n.charAt(1) === 'x' ?
41 String.fromCharCode(parseInt(n.substring(2), 16)) :
42 String.fromCharCode(Number(n.substring(1)))
43 }
44 return ''
45 })
46}
47
48function replace(regex, opt) {
49 regex = regex.source;
50 opt = opt || '';
51 return function self(name, val) {
52 if (!name) { return new RegExp(regex, opt) }
53 val = val.source || val;
54 val = val.replace(/(^|[^\[])\^/g, '$1');
55 regex = regex.replace(name, val);
56 return self
57 }
58}
59
60function slugify(input) {
61 return input
62 // remove html tags
63 .replace(/<(?:.|\n)*?>/gm, '')
64 .replace(/[!\"#$%&'\(\)\*\+,\/:;<=>\?\@\[\\\]\^`\{\|\}~]/g, '') // eslint-disable-line no-useless-escape
65 // Replace dots and spaces with a sepeator
66 .replace(/(\s|\.)/g, '-')
67 // Convert 2 or more sepeators into just one sepeator
68 .replace(/-{2,}/g, '-')
69 // Make the whole thing lowercase
70 .toLowerCase()
71}
72
73var Renderer = function Renderer(options) {
74 this.options = options || {};
75 this._headings = [];
76};
77
78Renderer.prototype.code = function code (code$1, lang, escaped) {
79 if (this.options.highlight) {
80 var out = this.options.highlight(code$1, lang);
81 if (out !== null && out !== code$1) {
82 escaped = true;
83 code$1 = out;
84 }
85 }
86
87 if (!lang) {
88 return ("<pre><code>" + (escaped ? code$1 : escape$1(code$1, true)) + "\n</code></pre>")
89 }
90
91 return ("<pre><code class=\"" + (this.options.langPrefix) + (escape$1(lang, true)) + "\">" + (escaped ? code$1 : escape$1(code$1, true)) + "\n</code></pre>\n")
92};
93
94Renderer.prototype.blockquote = function blockquote (quote) {
95 return ("<blockquote>\n" + quote + "</blockquote>\n")
96};
97
98Renderer.prototype.html = function html (html$1) {
99 return html$1
100};
101
102Renderer.prototype.heading = function heading (text, level, raw) {
103 var slug = slugify(raw);
104 var count = this._headings.filter(function (h) { return h === raw; }).length;
105 if (count > 0) {
106 slug += "-" + count;
107 }
108 this._headings.push(raw);
109 return ("<h" + level + " id=\"" + (this.options.headerPrefix) + slug + "\">" + text + "</h" + level + ">\n")
110};
111
112Renderer.prototype.hr = function hr () {
113 return this.options.xhtml ? '<hr/>\n' : '<hr>\n'
114};
115
116Renderer.prototype.list = function list (body, ordered, taskList) {
117 var type = ordered ? 'ol' : 'ul';
118 var classNames = taskList ? ' class="task-list"' : '';
119 return ("<" + type + classNames + ">\n" + body + "</" + type + ">\n")
120};
121
122Renderer.prototype.listitem = function listitem (text, checked) {
123 if (checked === undefined) {
124 return ("<li>" + text + "</li>\n")
125 }
126
127 return '<li class="task-list-item">' +
128 '<input type="checkbox" class="task-list-item-checkbox"' +
129 (checked ? ' checked' : '') +
130 '> ' +
131 text +
132 '</li>\n'
133};
134
135Renderer.prototype.paragraph = function paragraph (text) {
136 return ("<p>" + text + "</p>\n")
137};
138
139Renderer.prototype.table = function table (header, body) {
140 return ("<table>\n<thead>\n" + header + "</thead>\n<tbody>\n" + body + "</tbody>\n</table>\n")
141};
142
143Renderer.prototype.tablerow = function tablerow (content) {
144 return ("<tr>\n" + content + "</tr>\n")
145};
146
147Renderer.prototype.tablecell = function tablecell (content, flags) {
148 var type = flags.header ? 'th' : 'td';
149 var tag = flags.align ?
150 ("<" + type + " style=\"text-align:" + (flags.align) + "\">") :
151 ("<" + type + ">");
152 return ((tag + content) + "</" + type + ">\n")
153};
154
155// span level renderer
156Renderer.prototype.strong = function strong (text) {
157 return ("<strong>" + text + "</strong>")
158};
159
160Renderer.prototype.em = function em (text) {
161 return ("<em>" + text + "</em>")
162};
163
164Renderer.prototype.codespan = function codespan (text) {
165 return ("<code>" + text + "</code>")
166};
167
168Renderer.prototype.br = function br () {
169 return this.options.xhtml ? '<br/>' : '<br>'
170};
171
172Renderer.prototype.del = function del (text) {
173 return ("<del>" + text + "</del>")
174};
175
176Renderer.prototype.link = function link (href, title, text) {
177 if (this.options.sanitize) {
178 var prot;
179 try {
180 prot = decodeURIComponent(unescape(href))
181 .replace(/[^\w:]/g, '')
182 .toLowerCase();
183 } catch (err) {
184 return ''
185 }
186 if (prot.indexOf('javascript:') === 0 || prot.indexOf('vbscript:') === 0 || prot.indexOf('data:') === 0) { // eslint-disable-line no-script-url
187 return ''
188 }
189 }
190 var out = "<a href=\"" + href + "\"";
191 if (title) {
192 out += " title=\"" + title + "\"";
193 }
194 out += ">" + text + "</a>";
195 return out
196};
197
198Renderer.prototype.image = function image (href, title, text) {
199 var out = "<img src=\"" + href + "\" alt=\"" + text + "\"";
200 if (title) {
201 out += " title=\"" + title + "\"";
202 }
203 out += this.options.xhtml ? '/>' : '>';
204 return out
205};
206
207Renderer.prototype.text = function text (text$1) {
208 return text$1
209};
210
211var defaultOptions = {
212 gfm: true,
213 tables: true,
214 taskLists: true,
215 breaks: false,
216 pedantic: false,
217 sanitize: false,
218 sanitizer: null,
219 mangle: true,
220 smartLists: false,
221 silent: false,
222 highlight: null,
223 langPrefix: 'lang-',
224 smartypants: false,
225 headerPrefix: '',
226 renderer: new Renderer(),
227 xhtml: false
228};
229
230/**
231 * Inline-Level Grammar
232 */
233
234var inline = {
235 escape: /^\\([\\`*{}[\]()#+\-.!_>])/,
236 autolink: /^<([^ >]+(@|:\/)[^ >]+)>/,
237 url: noop,
238 tag: /^<!--[\s\S]*?-->|^<\/?\w+(?:"[^"]*"|'[^']*'|[^'">])*?>/,
239 link: /^!?\[(inside)\]\(href\)/,
240 reflink: /^!?\[(inside)\]\s*\[([^\]]*)\]/,
241 nolink: /^!?\[((?:\[[^\]]*\]|[^[\]])*)\]/,
242 strong: /^__([\s\S]+?)__(?!_)|^\*\*([\s\S]+?)\*\*(?!\*)/,
243 em: /^\b_((?:[^_]|__)+?)_\b|^\*((?:\*\*|[\s\S])+?)\*(?!\*)/,
244 code: /^(`+)\s*([\s\S]*?[^`])\s*\1(?!`)/,
245 br: /^ {2,}\n(?!\s*$)/,
246 del: noop,
247 text: /^[\s\S]+?(?=[\\<![_*`]| {2,}\n|$)/
248};
249
250inline._inside = /(?:\[[^\]]*\]|[^[\]]|\](?=[^[]*\]))*/;
251inline._href = /\s*<?([\s\S]*?)>?(?:\s+['"]([\s\S]*?)['"])?\s*/;
252
253inline.link = replace(inline.link)
254 ('inside', inline._inside)
255 ('href', inline._href)
256 ();
257
258inline.reflink = replace(inline.reflink)
259 ('inside', inline._inside)
260 ();
261
262/**
263 * Normal Inline Grammar
264 */
265
266inline.normal = merge ({}, inline);
267
268/**
269 * Pedantic Inline Grammar
270 */
271
272inline.pedantic = merge ({}, inline.normal, {
273 strong: /^__(?=\S)([\s\S]*?\S)__(?!_)|^\*\*(?=\S)([\s\S]*?\S)\*\*(?!\*)/,
274 em: /^_(?=\S)([\s\S]*?\S)_(?!_)|^\*(?=\S)([\s\S]*?\S)\*(?!\*)/
275});
276
277/**
278 * GFM Inline Grammar
279 */
280
281inline.gfm = merge ({}, inline.normal, {
282 escape: replace(inline.escape) ('])', '~|])') (),
283 url: /^(https?:\/\/[^\s<]+[^<.,:;"')\]\s])/,
284 del: /^~~(?=\S)([\s\S]*?\S)~~/,
285 text: replace(inline.text)
286 (']|', '~]|')
287 ('|', '|https?://|')
288 ()
289});
290
291/**
292 * GFM + Line Breaks Inline Grammar
293 */
294
295inline.breaks = merge ({}, inline.gfm, {
296 br: replace(inline.br) ('{2,}', '*') (),
297 text: replace(inline.gfm.text) ('{2,}', '*') ()
298});
299
300var InlineLexer = function InlineLexer(links, options) {
301 if ( options === void 0 ) options = defaultOptions;
302
303 this.options = options;
304 this.links = links;
305 this.renderer = this.options.renderer || new Renderer();
306 this.renderer.options = this.options;
307
308 if (!this.links) {
309 throw new Error('Tokens array requires a `links` property.')
310 }
311
312 if (this.options.gfm) {
313 if (this.options.breaks) {
314 this.rules = inline.breaks;
315 } else {
316 this.rules = inline.gfm;
317 }
318 } else if (this.options.pedantic) {
319 this.rules = inline.pedantic;
320 } else {
321 this.rules = inline.normal;
322 }
323};
324
325InlineLexer.output = function output (src, links, options) {
326 return new InlineLexer(links, options).output(src)
327};
328
329InlineLexer.prototype.output = function output (src) {
330 var this$1 = this;
331
332 var out = '';
333 var link;
334 var text;
335 var href;
336 var cap;
337
338 while (src) {
339 // escape
340 if (cap = this$1.rules.escape.exec(src)) {
341 src = src.substring(cap[0].length);
342 out += cap[1];
343 continue
344 }
345
346 // autolink
347 if (cap = this$1.rules.autolink.exec(src)) {
348 src = src.substring(cap[0].length);
349 if (cap[2] === '@') {
350 text = cap[1].charAt(6) === ':' ?
351 this$1.mangle(cap[1].substring(7)) :
352 this$1.mangle(cap[1]);
353 href = this$1.mangle('mailto:') + text;
354 } else {
355 text = escape$1(cap[1]);
356 href = text;
357 }
358 out += this$1.renderer.link(href, null, text);
359 continue
360 }
361
362 // url (gfm)
363 if (!this$1.inLink && (cap = this$1.rules.url.exec(src))) {
364 src = src.substring(cap[0].length);
365 text = escape$1(cap[1]);
366 href = text;
367 out += this$1.renderer.link(href, null, text);
368 continue
369 }
370
371 // tag
372 if (cap = this$1.rules.tag.exec(src)) {
373 if (!this$1.inLink && /^<a /i.test(cap[0])) {
374 this$1.inLink = true;
375 } else if (this$1.inLink && /^<\/a>/i.test(cap[0])) {
376 this$1.inLink = false;
377 }
378 src = src.substring(cap[0].length);
379 out += this$1.options.sanitize ?
380 this$1.options.sanitizer ?
381 this$1.options.sanitizer(cap[0]) :
382 escape$1(cap[0]) :
383 cap[0];
384 continue
385 }
386
387 // link
388 if (cap = this$1.rules.link.exec(src)) {
389 src = src.substring(cap[0].length);
390 this$1.inLink = true;
391 out += this$1.outputLink(cap, {
392 href: cap[2],
393 title: cap[3]
394 });
395 this$1.inLink = false;
396 continue
397 }
398
399 // reflink, nolink
400 if ((cap = this$1.rules.reflink.exec(src)) ||
401 (cap = this$1.rules.nolink.exec(src))) {
402 src = src.substring(cap[0].length);
403 link = (cap[2] || cap[1]).replace(/\s+/g, ' ');
404 link = this$1.links[link.toLowerCase()];
405 if (!link || !link.href) {
406 out += cap[0].charAt(0);
407 src = cap[0].substring(1) + src;
408 continue
409 }
410 this$1.inLink = true;
411 out += this$1.outputLink(cap, link);
412 this$1.inLink = false;
413 continue
414 }
415
416 // strong
417 if (cap = this$1.rules.strong.exec(src)) {
418 src = src.substring(cap[0].length);
419 out += this$1.renderer.strong(this$1.output(cap[2] || cap[1]));
420 continue
421 }
422
423 // em
424 if (cap = this$1.rules.em.exec(src)) {
425 src = src.substring(cap[0].length);
426 out += this$1.renderer.em(this$1.output(cap[2] || cap[1]));
427 continue
428 }
429
430 // code
431 if (cap = this$1.rules.code.exec(src)) {
432 src = src.substring(cap[0].length);
433 out += this$1.renderer.codespan(escape$1(cap[2], true));
434 continue
435 }
436
437 // br
438 if (cap = this$1.rules.br.exec(src)) {
439 src = src.substring(cap[0].length);
440 out += this$1.renderer.br();
441 continue
442 }
443
444 // del (gfm)
445 if (cap = this$1.rules.del.exec(src)) {
446 src = src.substring(cap[0].length);
447 out += this$1.renderer.del(this$1.output(cap[1]));
448 continue
449 }
450
451 // text
452 if (cap = this$1.rules.text.exec(src)) {
453 src = src.substring(cap[0].length);
454 out += this$1.renderer.text(escape$1(this$1.smartypants(cap[0])));
455 continue
456 }
457
458 if (src) {
459 throw new Error('Infinite loop on byte: ' + src.charCodeAt(0))
460 }
461 }
462
463 return out
464};
465
466InlineLexer.prototype.outputLink = function outputLink (cap, link) {
467 var href = escape$1(link.href);
468 var title = link.title ? escape$1(link.title) : null;
469
470 return cap[0].charAt(0) === '!' ?
471 this.renderer.image(href, title, escape$1(cap[1])) :
472 this.renderer.link(href, title, this.output(cap[1]))
473};
474
475InlineLexer.prototype.smartypants = function smartypants (text) {
476 if (!this.options.smartypants) { return text }
477 return text
478 // em-dashes
479 .replace(/---/g, '\u2014')
480 // en-dashes
481 .replace(/--/g, '\u2013')
482 // opening singles
483 .replace(/(^|[-\u2014/(\[{"\s])'/g, '$1\u2018')
484 // closing singles & apostrophes
485 .replace(/'/g, '\u2019')
486 // opening doubles
487 .replace(/(^|[-\u2014/(\[{\u2018\s])"/g, '$1\u201c')
488 // closing doubles
489 .replace(/"/g, '\u201d')
490 // ellipses
491 .replace(/\.{3}/g, '\u2026')
492};
493
494InlineLexer.prototype.mangle = function mangle (text) {
495 if (!this.options.mangle) { return text }
496 var out = '';
497 var i = 0;
498 var ch;
499
500 for (; i < text.length; i++) {
501 ch = text.charCodeAt(i);
502 if (Math.random() > 0.5) {
503 ch = 'x' + ch.toString(16);
504 }
505 out += '&#' + ch + ';';
506 }
507
508 return out
509};
510
511InlineLexer.rules = inline;
512
513/**
514 * Parsing & Compiling
515 */
516
517var Parser = function Parser(options) {
518 if ( options === void 0 ) options = defaultOptions;
519
520 this.tokens = [];
521 this.token = null;
522 this.options = options;
523 this.options.renderer = this.options.renderer || new Renderer();
524 this.renderer = this.options.renderer;
525 this.renderer.options = this.options;
526};
527
528Parser.parse = function parse (src, options, renderer) {
529 return new Parser(options, renderer).parse(src)
530};
531
532/**
533 * Parse Loop
534 */
535
536Parser.prototype.parse = function parse (src) {
537 var this$1 = this;
538
539 this.inline = new InlineLexer(src.links, this.options, this.renderer);
540 this.tokens = src.reverse();
541
542 var out = '';
543 while (this.next()) {
544 out += this$1.tok();
545 }
546
547 // Remove cached headings
548 this.renderer._headings = [];
549 return out
550};
551
552/**
553 * Next Token
554 */
555
556Parser.prototype.next = function next () {
557 this.token = this.tokens.pop();
558 return this.token
559};
560
561/**
562 * Preview Next Token
563 */
564
565Parser.prototype.peek = function peek () {
566 return this.tokens[this.tokens.length - 1] || 0
567};
568
569/**
570 * Parse Text Tokens
571 */
572
573Parser.prototype.parseText = function parseText () {
574 var this$1 = this;
575
576 var body = this.token.text;
577
578 while (this.peek().type === 'text') {
579 body += "\n" + (this$1.next().text);
580 }
581
582 return this.inline.output(body)
583};
584
585/**
586 * Parse Current Token
587 */
588
589Parser.prototype.tok = function tok () {
590 var this$1 = this;
591
592 switch (this.token.type) {
593 case 'space': {
594 return ''
595 }
596 case 'hr': {
597 return this.renderer.hr()
598 }
599 case 'heading': {
600 return this.renderer.heading(
601 this.inline.output(this.token.text),
602 this.token.depth,
603 this.token.text)
604 }
605 case 'code': {
606 return this.renderer.code(this.token.text,
607 this.token.lang,
608 this.token.escaped)
609 }
610 case 'table': {
611 var header = '';
612 var body = '';
613 var i;
614 var row;
615 var cell;
616 var j;
617
618 // header
619 cell = '';
620 for (i = 0; i < this.token.header.length; i++) {
621 cell += this$1.renderer.tablecell(
622 this$1.inline.output(this$1.token.header[i]),
623 { header: true, align: this$1.token.align[i] }
624 );
625 }
626 header += this.renderer.tablerow(cell);
627
628 for (i = 0; i < this.token.cells.length; i++) {
629 row = this$1.token.cells[i];
630
631 cell = '';
632 for (j = 0; j < row.length; j++) {
633 cell += this$1.renderer.tablecell(
634 this$1.inline.output(row[j]),
635 { header: false, align: this$1.token.align[j] }
636 );
637 }
638
639 body += this$1.renderer.tablerow(cell);
640 }
641 return this.renderer.table(header, body)
642 }
643 case 'blockquote_start': {
644 var body$1 = '';
645
646 while (this.next().type !== 'blockquote_end') {
647 body$1 += this$1.tok();
648 }
649
650 return this.renderer.blockquote(body$1)
651 }
652 case 'list_start': {
653 var body$2 = '';
654 var taskList = false;
655 var ordered = this.token.ordered;
656
657 while (this.next().type !== 'list_end') {
658 if (this$1.token.checked !== undefined) {
659 taskList = true;
660 }
661 body$2 += this$1.tok();
662 }
663
664 return this.renderer.list(body$2, ordered, taskList)
665 }
666 case 'list_item_start': {
667 var body$3 = '';
668 var checked = this.token.checked;
669
670 while (this.next().type !== 'list_item_end') {
671 body$3 += this$1.token.type === 'text' ?
672 this$1.parseText() :
673 this$1.tok();
674 }
675
676 return this.renderer.listitem(body$3, checked)
677 }
678 case 'loose_item_start': {
679 var body$4 = '';
680 var checked$1 = this.token.checked;
681
682 while (this.next().type !== 'list_item_end') {
683 body$4 += this$1.tok();
684 }
685
686 return this.renderer.listitem(body$4, checked$1)
687 }
688 case 'html': {
689 var html = !this.token.pre && !this.options.pedantic ?
690 this.inline.output(this.token.text) :
691 this.token.text;
692 return this.renderer.html(html)
693 }
694 case 'paragraph': {
695 return this.renderer.paragraph(this.inline.output(this.token.text))
696 }
697 case 'text': {
698 return this.renderer.paragraph(this.parseText())
699 }
700 default: {
701 throw new Error('Unknow type')
702 }
703 }
704};
705
706var block = {
707 newline: /^\n+/,
708 code: /^( {4}[^\n]+\n*)+/,
709 fences: noop,
710 hr: /^( *[-*_]){3,} *(?:\n+|$)/,
711 heading: /^ *(#{1,6}) *([^\n]+?) *#* *(?:\n+|$)/,
712 nptable: noop,
713 lheading: /^([^\n]+)\n *(=|-){2,} *(?:\n+|$)/,
714 blockquote: /^( *>[^\n]+(\n(?!def)[^\n]+)*\n*)+/,
715 list: /^( *)(bull) [\s\S]+?(?:hr|def|\n{2,}(?! )(?!\1bull )\n*|\s*$)/,
716 html: /^ *(?:comment *(?:\n|\s*$)|closed *(?:\n{2,}|\s*$)|closing *(?:\n{2,}|\s*$))/,
717 def: /^ *\[([^\]]+)\]: *<?([^\s>]+)>?(?: +["(]([^\n]+)[")])? *(?:\n+|$)/,
718 table: noop,
719 paragraph: /^((?:[^\n]+\n?(?!hr|heading|lheading|blockquote|tag|def))+)\n*/,
720 text: /^[^\n]+/
721};
722
723block.bullet = /(?:[*+-]|\d+\.)/;
724block.item = /^( *)(bull) [^\n]*(?:\n(?!\1bull )[^\n]*)*/;
725block.item = replace(block.item, 'gm')
726 (/bull/g, block.bullet)
727 ();
728
729block.list = replace(block.list)
730 (/bull/g, block.bullet)
731 ('hr', '\\n+(?=\\1?(?:[-*_] *){3,}(?:\\n+|$))')
732 ('def', '\\n+(?=' + block.def.source + ')')
733 ();
734
735block.blockquote = replace(block.blockquote)
736 ('def', block.def)
737 ();
738
739block._tag = '(?!(?:' +
740 'a|em|strong|small|s|cite|q|dfn|abbr|data|time|code' +
741 '|var|samp|kbd|sub|sup|i|b|u|mark|ruby|rt|rp|bdi|bdo' +
742 '|span|br|wbr|ins|del|img)\\b)\\w+(?!:/|[^\\w\\s@]*@)\\b';
743
744block.html = replace(block.html)
745 ('comment', /<!--[\s\S]*?-->/)
746 ('closed', /<(tag)[\s\S]+?<\/\1>/)
747 ('closing', /<tag(?:"[^"]*"|'[^']*'|[^'">])*?>/)
748 (/tag/g, block._tag)
749 ();
750
751block.paragraph = replace(block.paragraph)
752 ('hr', block.hr)
753 ('heading', block.heading)
754 ('lheading', block.lheading)
755 ('blockquote', block.blockquote)
756 ('tag', '<' + block._tag)
757 ('def', block.def)
758 ();
759
760/**
761 * Normal Block Grammar
762 */
763
764block.normal = merge({}, block);
765
766/**
767 * GFM Block Grammar
768 */
769
770block.gfm = merge({}, block.normal, {
771 fences: /^ *(`{3,}|~{3,})[ \.]*(\S+)? *\n([\s\S]*?)\s*\1 *(?:\n+|$)/,
772 paragraph: /^/,
773 heading: /^ *(#{1,6}) +([^\n]+?) *#* *(?:\n+|$)/,
774 checkbox: /^\[([ x])\] +/
775});
776
777block.gfm.paragraph = replace(block.paragraph)
778 ('(?!', '(?!' +
779 block.gfm.fences.source.replace('\\1', '\\2') + '|' +
780 block.list.source.replace('\\1', '\\3') + '|')
781 ();
782
783/**
784 * GFM + Tables Block Grammar
785 */
786
787block.tables = merge({}, block.gfm, {
788 nptable: /^ *(\S.*\|.*)\n *([-:]+ *\|[-| :]*)\n((?:.*\|.*(?:\n|$))*)\n*/,
789 table: /^ *\|(.+)\n *\|( *[-:]+[-| :]*)\n((?: *\|.*(?:\n|$))*)\n*/
790});
791
792var Lexer = function Lexer(options) {
793 if ( options === void 0 ) options = defaultOptions;
794
795 this.tokens = [];
796 this.tokens.links = {};
797 this.options = options;
798
799 if (this.options.gfm) {
800 if (this.options.table) {
801 this.rules = block.table;
802 } else {
803 this.rules = block.gfm;
804 }
805 } else {
806 this.rules = block.normal;
807 }
808};
809
810Lexer.lex = function lex (src, options) {
811 return new Lexer(options).lex(src)
812};
813
814Lexer.prototype.lex = function lex (src) {
815 src = src
816 .replace(/\r\n|\r/g, '\n')
817 .replace(/\t/g, ' ')
818 .replace(/\u00a0/g, ' ')
819 .replace(/\u2424/g, '\n');
820
821 return this.token(src, true)
822};
823
824Lexer.prototype.token = function token (src, top, bq) {
825 var this$1 = this;
826
827 src = src.replace(/^ +$/gm, '');
828
829 var next;
830 var loose;
831 var cap;
832 var bull;
833 var b;
834 var item;
835 var space;
836 var i;
837 var l;
838 var checked;
839
840 while (src) {
841 // newline
842 if (cap = this$1.rules.newline.exec(src)) {
843 src = src.substring(cap[0].length);
844 if (cap[0].length > 1) {
845 this$1.tokens.push({
846 type: 'space'
847 });
848 }
849 }
850
851 // code
852 if (cap = this$1.rules.code.exec(src)) {
853 src = src.substring(cap[0].length);
854 cap = cap[0].replace(/^ {4}/gm, '');
855 this$1.tokens.push({
856 type: 'code',
857 text: this$1.options.pedantic ?
858 cap :
859 cap.replace(/\n+$/, '')
860 });
861 continue
862 }
863
864 // fences (gfm)
865 if (cap = this$1.rules.fences.exec(src)) {
866 src = src.substring(cap[0].length);
867 this$1.tokens.push({
868 type: 'code',
869 lang: cap[2],
870 text: cap[3] || ''
871 });
872 continue
873 }
874
875 // heading
876 if (cap = this$1.rules.heading.exec(src)) {
877 src = src.substring(cap[0].length);
878 this$1.tokens.push({
879 type: 'heading',
880 depth: cap[1].length,
881 text: cap[2]
882 });
883 continue
884 }
885
886 // table no leading pipe (gfm)
887 if (top && (cap = this$1.rules.nptable.exec(src))) {
888 src = src.substring(cap[0].length);
889
890 item = {
891 type: 'table',
892 header: cap[1].replace(/^ *| *\| *$/g, '').split(/ *\| */),
893 align: cap[2].replace(/^ *|\| *$/g, '').split(/ *\| */),
894 cells: cap[3].replace(/\n$/, '').split('\n')
895 };
896
897 for (i = 0; i < item.align.length; i++) {
898 if (/^ *-+: *$/.test(item.align[i])) {
899 item.align[i] = 'right';
900 } else if (/^ *:-+: *$/.test(item.align[i])) {
901 item.align[i] = 'center';
902 } else if (/^ *:-+ *$/.test(item.align[i])) {
903 item.align[i] = 'left';
904 } else {
905 item.align[i] = null;
906 }
907 }
908
909 for (i = 0; i < item.cells.length; i++) {
910 item.cells[i] = item.cells[i].split(/ *\| */);
911 }
912
913 this$1.tokens.push(item);
914
915 continue
916 }
917
918 // lheading
919 if (cap = this$1.rules.lheading.exec(src)) {
920 src = src.substring(cap[0].length);
921 this$1.tokens.push({
922 type: 'heading',
923 depth: cap[2] === '=' ? 1 : 2,
924 text: cap[1]
925 });
926 continue
927 }
928
929 // hr
930 if (cap = this$1.rules.hr.exec(src)) {
931 src = src.substring(cap[0].length);
932 this$1.tokens.push({
933 type: 'hr'
934 });
935 continue
936 }
937
938 // blockquote
939 if (cap = this$1.rules.blockquote.exec(src)) {
940 src = src.substring(cap[0].length);
941
942 this$1.tokens.push({
943 type: 'blockquote_start'
944 });
945
946 cap = cap[0].replace(/^ *> ?/gm, '');
947
948 // Pass `top` to keep the current
949 // "toplevel" state. This is exactly
950 // how markdown.pl works.
951 this$1.token(cap, top, true);
952
953 this$1.tokens.push({
954 type: 'blockquote_end'
955 });
956
957 continue
958 }
959
960 // list
961 if (cap = this$1.rules.list.exec(src)) {
962 src = src.substring(cap[0].length);
963 bull = cap[2];
964
965 this$1.tokens.push({
966 type: 'list_start',
967 ordered: bull.length > 1
968 });
969
970 // Get each top-level item.
971 cap = cap[0].match(this$1.rules.item);
972
973 next = false;
974 l = cap.length;
975 i = 0;
976
977 for (; i < l; i++) {
978 item = cap[i];
979
980 // Remove the list item's bullet
981 // so it is seen as the next token.
982 space = item.length;
983 item = item.replace(/^ *([*+-]|\d+\.) +/, '');
984
985 if (this$1.options.gfm && this$1.options.taskLists) {
986 checked = this$1.rules.checkbox.exec(item);
987
988 if (checked) {
989 checked = checked[1] === 'x';
990 item = item.replace(this$1.rules.checkbox, '');
991 } else {
992 checked = undefined;
993 }
994 }
995
996 // Outdent whatever the
997 // list item contains. Hacky.
998 if (item.indexOf('\n ') !== -1) {
999 space -= item.length;
1000 item = this$1.options.pedantic ?
1001 item.replace(/^ {1,4}/gm, '') :
1002 item.replace(new RegExp('^ {1,' + space + '}', 'gm'), '');
1003 }
1004
1005 // Determine whether the next list item belongs here.
1006 // Backpedal if it does not belong in this list.
1007 if (this$1.options.smartLists && i !== l - 1) {
1008 b = this$1.rules.bullet.exec(cap[i + 1])[0];
1009 if (bull !== b && !(bull.length > 1 && b.length > 1)) {
1010 src = cap.slice(i + 1).join('\n') + src;
1011 i = l - 1;
1012 }
1013 }
1014
1015 // Determine whether item is loose or not.
1016 // Use: /(^|\n)(?! )[^\n]+\n\n(?!\s*$)/
1017 // for discount behavior.
1018 loose = next || /\n\n(?!\s*$)/.test(item);
1019 if (i !== l - 1) {
1020 next = item.charAt(item.length - 1) === '\n';
1021 if (!loose) { loose = next; }
1022 }
1023
1024 this$1.tokens.push({
1025 checked: checked,
1026 type: loose ?
1027 'loose_item_start' :
1028 'list_item_start'
1029 });
1030
1031 // Recurse.
1032 this$1.token(item, false, bq);
1033
1034 this$1.tokens.push({
1035 type: 'list_item_end'
1036 });
1037 }
1038
1039 this$1.tokens.push({
1040 type: 'list_end'
1041 });
1042
1043 continue
1044 }
1045
1046 // html
1047 if (cap = this$1.rules.html.exec(src)) {
1048 src = src.substring(cap[0].length);
1049 this$1.tokens.push({
1050 type: this$1.options.sanitize ?
1051 'paragraph' :
1052 'html',
1053 pre: !this$1.options.sanitizer &&
1054 (cap[1] === 'pre' || cap[1] === 'script' || cap[1] === 'style'),
1055 text: cap[0]
1056 });
1057 continue
1058 }
1059
1060 // def
1061 if ((!bq && top) && (cap = this$1.rules.def.exec(src))) {
1062 src = src.substring(cap[0].length);
1063 this$1.tokens.links[cap[1].toLowerCase()] = {
1064 href: cap[2],
1065 title: cap[3]
1066 };
1067 continue
1068 }
1069
1070 // table (gfm)
1071 if (top && (cap = this$1.rules.table.exec(src))) {
1072 src = src.substring(cap[0].length);
1073
1074 item = {
1075 type: 'table',
1076 header: cap[1].replace(/^ *| *\| *$/g, '').split(/ *\| */),
1077 align: cap[2].replace(/^ *|\| *$/g, '').split(/ *\| */),
1078 cells: cap[3].replace(/(?: *\| *)?\n$/, '').split('\n')
1079 };
1080
1081 for (i = 0; i < item.align.length; i++) {
1082 if (/^ *-+: *$/.test(item.align[i])) {
1083 item.align[i] = 'right';
1084 } else if (/^ *:-+: *$/.test(item.align[i])) {
1085 item.align[i] = 'center';
1086 } else if (/^ *:-+ *$/.test(item.align[i])) {
1087 item.align[i] = 'left';
1088 } else {
1089 item.align[i] = null;
1090 }
1091 }
1092
1093 for (i = 0; i < item.cells.length; i++) {
1094 item.cells[i] = item.cells[i]
1095 .replace(/^ *\| *| *\| *$/g, '')
1096 .split(/ *\| */);
1097 }
1098
1099 this$1.tokens.push(item);
1100
1101 continue
1102 }
1103
1104 // top-level paragraph
1105 if (top && (cap = this$1.rules.paragraph.exec(src))) {
1106 src = src.substring(cap[0].length);
1107 this$1.tokens.push({
1108 type: 'paragraph',
1109 text: cap[1].charAt(cap[1].length - 1) === '\n' ?
1110 cap[1].slice(0, -1) :
1111 cap[1]
1112 });
1113 continue
1114 }
1115
1116 // text
1117 if (cap = this$1.rules.text.exec(src)) {
1118 // Top-level should never reach here.
1119 src = src.substring(cap[0].length);
1120 this$1.tokens.push({
1121 type: 'text',
1122 text: cap[0]
1123 });
1124 continue
1125 }
1126
1127 if (src) {
1128 throw new
1129 Error('Infinite loop on byte: ' + src.charCodeAt(0))
1130 }
1131 }
1132
1133 return this.tokens
1134};
1135
1136Lexer.rules = block;
1137
1138function marked3(src, opt) {
1139 try {
1140 if (opt) { opt = merge({}, defaultOptions, opt); }
1141 return Parser.parse(Lexer.lex(src, opt), opt)
1142 } catch (err) {
1143 err.message += '\nPlease report this to https://github.com/egoist/marked3.';
1144 if ((opt || defaultOptions).silent) {
1145 return '<p>An error occured:</p><pre>' +
1146 escape(String(err.message), true) +
1147 '</pre>'
1148 }
1149 throw err
1150 }
1151}
1152
1153marked3.Renderer = Renderer;
1154marked3.Parser = Parser;
1155marked3.Lexer = Lexer;
1156marked3.InlineLexer = InlineLexer;
1157
1158module.exports = marked3;