marked.esm.js (65751B)
1 /** 2 * marked - a markdown parser 3 * Copyright (c) 2011-2020, Christopher Jeffrey. (MIT Licensed) 4 * https://github.com/markedjs/marked 5 */ 6 7 /** 8 * DO NOT EDIT THIS FILE 9 * The code in this file is generated from files in ./src/ 10 */ 11 12 function createCommonjsModule(fn, module) { 13 return module = { exports: {} }, fn(module, module.exports), module.exports; 14 } 15 16 var defaults = createCommonjsModule(function (module) { 17 function getDefaults() { 18 return { 19 baseUrl: null, 20 breaks: false, 21 gfm: true, 22 headerIds: true, 23 headerPrefix: '', 24 highlight: null, 25 langPrefix: 'language-', 26 mangle: true, 27 pedantic: false, 28 renderer: null, 29 sanitize: false, 30 sanitizer: null, 31 silent: false, 32 smartLists: false, 33 smartypants: false, 34 tokenizer: null, 35 walkTokens: null, 36 xhtml: false 37 }; 38 } 39 40 function changeDefaults(newDefaults) { 41 module.exports.defaults = newDefaults; 42 } 43 44 module.exports = { 45 defaults: getDefaults(), 46 getDefaults, 47 changeDefaults 48 }; 49 }); 50 var defaults_1 = defaults.defaults; 51 var defaults_2 = defaults.getDefaults; 52 var defaults_3 = defaults.changeDefaults; 53 54 /** 55 * Helpers 56 */ 57 const escapeTest = /[&<>"']/; 58 const escapeReplace = /[&<>"']/g; 59 const escapeTestNoEncode = /[<>"']|&(?!#?\w+;)/; 60 const escapeReplaceNoEncode = /[<>"']|&(?!#?\w+;)/g; 61 const escapeReplacements = { 62 '&': '&', 63 '<': '<', 64 '>': '>', 65 '"': '"', 66 "'": ''' 67 }; 68 const getEscapeReplacement = (ch) => escapeReplacements[ch]; 69 function escape(html, encode) { 70 if (encode) { 71 if (escapeTest.test(html)) { 72 return html.replace(escapeReplace, getEscapeReplacement); 73 } 74 } else { 75 if (escapeTestNoEncode.test(html)) { 76 return html.replace(escapeReplaceNoEncode, getEscapeReplacement); 77 } 78 } 79 80 return html; 81 } 82 83 const unescapeTest = /&(#(?:\d+)|(?:#x[0-9A-Fa-f]+)|(?:\w+));?/ig; 84 85 function unescape(html) { 86 // explicitly match decimal, hex, and named HTML entities 87 return html.replace(unescapeTest, (_, n) => { 88 n = n.toLowerCase(); 89 if (n === 'colon') return ':'; 90 if (n.charAt(0) === '#') { 91 return n.charAt(1) === 'x' 92 ? String.fromCharCode(parseInt(n.substring(2), 16)) 93 : String.fromCharCode(+n.substring(1)); 94 } 95 return ''; 96 }); 97 } 98 99 const caret = /(^|[^\[])\^/g; 100 function edit(regex, opt) { 101 regex = regex.source || regex; 102 opt = opt || ''; 103 const obj = { 104 replace: (name, val) => { 105 val = val.source || val; 106 val = val.replace(caret, '$1'); 107 regex = regex.replace(name, val); 108 return obj; 109 }, 110 getRegex: () => { 111 return new RegExp(regex, opt); 112 } 113 }; 114 return obj; 115 } 116 117 const nonWordAndColonTest = /[^\w:]/g; 118 const originIndependentUrl = /^$|^[a-z][a-z0-9+.-]*:|^[?#]/i; 119 function cleanUrl(sanitize, base, href) { 120 if (sanitize) { 121 let prot; 122 try { 123 prot = decodeURIComponent(unescape(href)) 124 .replace(nonWordAndColonTest, '') 125 .toLowerCase(); 126 } catch (e) { 127 return null; 128 } 129 if (prot.indexOf('javascript:') === 0 || prot.indexOf('vbscript:') === 0 || prot.indexOf('data:') === 0) { 130 return null; 131 } 132 } 133 if (base && !originIndependentUrl.test(href)) { 134 href = resolveUrl(base, href); 135 } 136 try { 137 href = encodeURI(href).replace(/%25/g, '%'); 138 } catch (e) { 139 return null; 140 } 141 return href; 142 } 143 144 const baseUrls = {}; 145 const justDomain = /^[^:]+:\/*[^/]*$/; 146 const protocol = /^([^:]+:)[\s\S]*$/; 147 const domain = /^([^:]+:\/*[^/]*)[\s\S]*$/; 148 149 function resolveUrl(base, href) { 150 if (!baseUrls[' ' + base]) { 151 // we can ignore everything in base after the last slash of its path component, 152 // but we might need to add _that_ 153 // https://tools.ietf.org/html/rfc3986#section-3 154 if (justDomain.test(base)) { 155 baseUrls[' ' + base] = base + '/'; 156 } else { 157 baseUrls[' ' + base] = rtrim(base, '/', true); 158 } 159 } 160 base = baseUrls[' ' + base]; 161 const relativeBase = base.indexOf(':') === -1; 162 163 if (href.substring(0, 2) === '//') { 164 if (relativeBase) { 165 return href; 166 } 167 return base.replace(protocol, '$1') + href; 168 } else if (href.charAt(0) === '/') { 169 if (relativeBase) { 170 return href; 171 } 172 return base.replace(domain, '$1') + href; 173 } else { 174 return base + href; 175 } 176 } 177 178 const noopTest = { exec: function noopTest() {} }; 179 180 function merge(obj) { 181 let i = 1, 182 target, 183 key; 184 185 for (; i < arguments.length; i++) { 186 target = arguments[i]; 187 for (key in target) { 188 if (Object.prototype.hasOwnProperty.call(target, key)) { 189 obj[key] = target[key]; 190 } 191 } 192 } 193 194 return obj; 195 } 196 197 function splitCells(tableRow, count) { 198 // ensure that every cell-delimiting pipe has a space 199 // before it to distinguish it from an escaped pipe 200 const row = tableRow.replace(/\|/g, (match, offset, str) => { 201 let escaped = false, 202 curr = offset; 203 while (--curr >= 0 && str[curr] === '\\') escaped = !escaped; 204 if (escaped) { 205 // odd number of slashes means | is escaped 206 // so we leave it alone 207 return '|'; 208 } else { 209 // add space before unescaped | 210 return ' |'; 211 } 212 }), 213 cells = row.split(/ \|/); 214 let i = 0; 215 216 if (cells.length > count) { 217 cells.splice(count); 218 } else { 219 while (cells.length < count) cells.push(''); 220 } 221 222 for (; i < cells.length; i++) { 223 // leading or trailing whitespace is ignored per the gfm spec 224 cells[i] = cells[i].trim().replace(/\\\|/g, '|'); 225 } 226 return cells; 227 } 228 229 // Remove trailing 'c's. Equivalent to str.replace(/c*$/, ''). 230 // /c*$/ is vulnerable to REDOS. 231 // invert: Remove suffix of non-c chars instead. Default falsey. 232 function rtrim(str, c, invert) { 233 const l = str.length; 234 if (l === 0) { 235 return ''; 236 } 237 238 // Length of suffix matching the invert condition. 239 let suffLen = 0; 240 241 // Step left until we fail to match the invert condition. 242 while (suffLen < l) { 243 const currChar = str.charAt(l - suffLen - 1); 244 if (currChar === c && !invert) { 245 suffLen++; 246 } else if (currChar !== c && invert) { 247 suffLen++; 248 } else { 249 break; 250 } 251 } 252 253 return str.substr(0, l - suffLen); 254 } 255 256 function findClosingBracket(str, b) { 257 if (str.indexOf(b[1]) === -1) { 258 return -1; 259 } 260 const l = str.length; 261 let level = 0, 262 i = 0; 263 for (; i < l; i++) { 264 if (str[i] === '\\') { 265 i++; 266 } else if (str[i] === b[0]) { 267 level++; 268 } else if (str[i] === b[1]) { 269 level--; 270 if (level < 0) { 271 return i; 272 } 273 } 274 } 275 return -1; 276 } 277 278 function checkSanitizeDeprecation(opt) { 279 if (opt && opt.sanitize && !opt.silent) { 280 console.warn('marked(): sanitize and sanitizer parameters are deprecated since version 0.7.0, should not be used and will be removed in the future. Read more here: https://marked.js.org/#/USING_ADVANCED.md#options'); 281 } 282 } 283 284 var helpers = { 285 escape, 286 unescape, 287 edit, 288 cleanUrl, 289 resolveUrl, 290 noopTest, 291 merge, 292 splitCells, 293 rtrim, 294 findClosingBracket, 295 checkSanitizeDeprecation 296 }; 297 298 const { defaults: defaults$1 } = defaults; 299 const { 300 rtrim: rtrim$1, 301 splitCells: splitCells$1, 302 escape: escape$1, 303 findClosingBracket: findClosingBracket$1 304 } = helpers; 305 306 function outputLink(cap, link, raw) { 307 const href = link.href; 308 const title = link.title ? escape$1(link.title) : null; 309 const text = cap[1].replace(/\\([\[\]])/g, '$1'); 310 311 if (cap[0].charAt(0) !== '!') { 312 return { 313 type: 'link', 314 raw, 315 href, 316 title, 317 text 318 }; 319 } else { 320 return { 321 type: 'image', 322 raw, 323 href, 324 title, 325 text: escape$1(text) 326 }; 327 } 328 } 329 330 function indentCodeCompensation(raw, text) { 331 const matchIndentToCode = raw.match(/^(\s+)(?:```)/); 332 333 if (matchIndentToCode === null) { 334 return text; 335 } 336 337 const indentToCode = matchIndentToCode[1]; 338 339 return text 340 .split('\n') 341 .map(node => { 342 const matchIndentInNode = node.match(/^\s+/); 343 if (matchIndentInNode === null) { 344 return node; 345 } 346 347 const [indentInNode] = matchIndentInNode; 348 349 if (indentInNode.length >= indentToCode.length) { 350 return node.slice(indentToCode.length); 351 } 352 353 return node; 354 }) 355 .join('\n'); 356 } 357 358 /** 359 * Tokenizer 360 */ 361 var Tokenizer_1 = class Tokenizer { 362 constructor(options) { 363 this.options = options || defaults$1; 364 } 365 366 space(src) { 367 const cap = this.rules.block.newline.exec(src); 368 if (cap) { 369 if (cap[0].length > 1) { 370 return { 371 type: 'space', 372 raw: cap[0] 373 }; 374 } 375 return { raw: '\n' }; 376 } 377 } 378 379 code(src, tokens) { 380 const cap = this.rules.block.code.exec(src); 381 if (cap) { 382 const lastToken = tokens[tokens.length - 1]; 383 // An indented code block cannot interrupt a paragraph. 384 if (lastToken && lastToken.type === 'paragraph') { 385 return { 386 raw: cap[0], 387 text: cap[0].trimRight() 388 }; 389 } 390 391 const text = cap[0].replace(/^ {4}/gm, ''); 392 return { 393 type: 'code', 394 raw: cap[0], 395 codeBlockStyle: 'indented', 396 text: !this.options.pedantic 397 ? rtrim$1(text, '\n') 398 : text 399 }; 400 } 401 } 402 403 fences(src) { 404 const cap = this.rules.block.fences.exec(src); 405 if (cap) { 406 const raw = cap[0]; 407 const text = indentCodeCompensation(raw, cap[3] || ''); 408 409 return { 410 type: 'code', 411 raw, 412 lang: cap[2] ? cap[2].trim() : cap[2], 413 text 414 }; 415 } 416 } 417 418 heading(src) { 419 const cap = this.rules.block.heading.exec(src); 420 if (cap) { 421 return { 422 type: 'heading', 423 raw: cap[0], 424 depth: cap[1].length, 425 text: cap[2] 426 }; 427 } 428 } 429 430 nptable(src) { 431 const cap = this.rules.block.nptable.exec(src); 432 if (cap) { 433 const item = { 434 type: 'table', 435 header: splitCells$1(cap[1].replace(/^ *| *\| *$/g, '')), 436 align: cap[2].replace(/^ *|\| *$/g, '').split(/ *\| */), 437 cells: cap[3] ? cap[3].replace(/\n$/, '').split('\n') : [], 438 raw: cap[0] 439 }; 440 441 if (item.header.length === item.align.length) { 442 let l = item.align.length; 443 let i; 444 for (i = 0; i < l; i++) { 445 if (/^ *-+: *$/.test(item.align[i])) { 446 item.align[i] = 'right'; 447 } else if (/^ *:-+: *$/.test(item.align[i])) { 448 item.align[i] = 'center'; 449 } else if (/^ *:-+ *$/.test(item.align[i])) { 450 item.align[i] = 'left'; 451 } else { 452 item.align[i] = null; 453 } 454 } 455 456 l = item.cells.length; 457 for (i = 0; i < l; i++) { 458 item.cells[i] = splitCells$1(item.cells[i], item.header.length); 459 } 460 461 return item; 462 } 463 } 464 } 465 466 hr(src) { 467 const cap = this.rules.block.hr.exec(src); 468 if (cap) { 469 return { 470 type: 'hr', 471 raw: cap[0] 472 }; 473 } 474 } 475 476 blockquote(src) { 477 const cap = this.rules.block.blockquote.exec(src); 478 if (cap) { 479 const text = cap[0].replace(/^ *> ?/gm, ''); 480 481 return { 482 type: 'blockquote', 483 raw: cap[0], 484 text 485 }; 486 } 487 } 488 489 list(src) { 490 const cap = this.rules.block.list.exec(src); 491 if (cap) { 492 let raw = cap[0]; 493 const bull = cap[2]; 494 const isordered = bull.length > 1; 495 const isparen = bull[bull.length - 1] === ')'; 496 497 const list = { 498 type: 'list', 499 raw, 500 ordered: isordered, 501 start: isordered ? +bull.slice(0, -1) : '', 502 loose: false, 503 items: [] 504 }; 505 506 // Get each top-level item. 507 const itemMatch = cap[0].match(this.rules.block.item); 508 509 let next = false, 510 item, 511 space, 512 b, 513 addBack, 514 loose, 515 istask, 516 ischecked; 517 518 const l = itemMatch.length; 519 for (let i = 0; i < l; i++) { 520 item = itemMatch[i]; 521 raw = item; 522 523 // Remove the list item's bullet 524 // so it is seen as the next token. 525 space = item.length; 526 item = item.replace(/^ *([*+-]|\d+[.)]) */, ''); 527 528 // Outdent whatever the 529 // list item contains. Hacky. 530 if (~item.indexOf('\n ')) { 531 space -= item.length; 532 item = !this.options.pedantic 533 ? item.replace(new RegExp('^ {1,' + space + '}', 'gm'), '') 534 : item.replace(/^ {1,4}/gm, ''); 535 } 536 537 // Determine whether the next list item belongs here. 538 // Backpedal if it does not belong in this list. 539 if (i !== l - 1) { 540 b = this.rules.block.bullet.exec(itemMatch[i + 1])[0]; 541 if (isordered ? b.length === 1 || (!isparen && b[b.length - 1] === ')') 542 : (b.length > 1 || (this.options.smartLists && b !== bull))) { 543 addBack = itemMatch.slice(i + 1).join('\n'); 544 list.raw = list.raw.substring(0, list.raw.length - addBack.length); 545 i = l - 1; 546 } 547 } 548 549 // Determine whether item is loose or not. 550 // Use: /(^|\n)(?! )[^\n]+\n\n(?!\s*$)/ 551 // for discount behavior. 552 loose = next || /\n\n(?!\s*$)/.test(item); 553 if (i !== l - 1) { 554 next = item.charAt(item.length - 1) === '\n'; 555 if (!loose) loose = next; 556 } 557 558 if (loose) { 559 list.loose = true; 560 } 561 562 // Check for task list items 563 istask = /^\[[ xX]\] /.test(item); 564 ischecked = undefined; 565 if (istask) { 566 ischecked = item[1] !== ' '; 567 item = item.replace(/^\[[ xX]\] +/, ''); 568 } 569 570 list.items.push({ 571 type: 'list_item', 572 raw, 573 task: istask, 574 checked: ischecked, 575 loose: loose, 576 text: item 577 }); 578 } 579 580 return list; 581 } 582 } 583 584 html(src) { 585 const cap = this.rules.block.html.exec(src); 586 if (cap) { 587 return { 588 type: this.options.sanitize 589 ? 'paragraph' 590 : 'html', 591 raw: cap[0], 592 pre: !this.options.sanitizer 593 && (cap[1] === 'pre' || cap[1] === 'script' || cap[1] === 'style'), 594 text: this.options.sanitize ? (this.options.sanitizer ? this.options.sanitizer(cap[0]) : escape$1(cap[0])) : cap[0] 595 }; 596 } 597 } 598 599 def(src) { 600 const cap = this.rules.block.def.exec(src); 601 if (cap) { 602 if (cap[3]) cap[3] = cap[3].substring(1, cap[3].length - 1); 603 const tag = cap[1].toLowerCase().replace(/\s+/g, ' '); 604 return { 605 tag, 606 raw: cap[0], 607 href: cap[2], 608 title: cap[3] 609 }; 610 } 611 } 612 613 table(src) { 614 const cap = this.rules.block.table.exec(src); 615 if (cap) { 616 const item = { 617 type: 'table', 618 header: splitCells$1(cap[1].replace(/^ *| *\| *$/g, '')), 619 align: cap[2].replace(/^ *|\| *$/g, '').split(/ *\| */), 620 cells: cap[3] ? cap[3].replace(/\n$/, '').split('\n') : [] 621 }; 622 623 if (item.header.length === item.align.length) { 624 item.raw = cap[0]; 625 626 let l = item.align.length; 627 let i; 628 for (i = 0; i < l; i++) { 629 if (/^ *-+: *$/.test(item.align[i])) { 630 item.align[i] = 'right'; 631 } else if (/^ *:-+: *$/.test(item.align[i])) { 632 item.align[i] = 'center'; 633 } else if (/^ *:-+ *$/.test(item.align[i])) { 634 item.align[i] = 'left'; 635 } else { 636 item.align[i] = null; 637 } 638 } 639 640 l = item.cells.length; 641 for (i = 0; i < l; i++) { 642 item.cells[i] = splitCells$1( 643 item.cells[i].replace(/^ *\| *| *\| *$/g, ''), 644 item.header.length); 645 } 646 647 return item; 648 } 649 } 650 } 651 652 lheading(src) { 653 const cap = this.rules.block.lheading.exec(src); 654 if (cap) { 655 return { 656 type: 'heading', 657 raw: cap[0], 658 depth: cap[2].charAt(0) === '=' ? 1 : 2, 659 text: cap[1] 660 }; 661 } 662 } 663 664 paragraph(src) { 665 const cap = this.rules.block.paragraph.exec(src); 666 if (cap) { 667 return { 668 type: 'paragraph', 669 raw: cap[0], 670 text: cap[1].charAt(cap[1].length - 1) === '\n' 671 ? cap[1].slice(0, -1) 672 : cap[1] 673 }; 674 } 675 } 676 677 text(src, tokens) { 678 const cap = this.rules.block.text.exec(src); 679 if (cap) { 680 const lastToken = tokens[tokens.length - 1]; 681 if (lastToken && lastToken.type === 'text') { 682 return { 683 raw: cap[0], 684 text: cap[0] 685 }; 686 } 687 688 return { 689 type: 'text', 690 raw: cap[0], 691 text: cap[0] 692 }; 693 } 694 } 695 696 escape(src) { 697 const cap = this.rules.inline.escape.exec(src); 698 if (cap) { 699 return { 700 type: 'escape', 701 raw: cap[0], 702 text: escape$1(cap[1]) 703 }; 704 } 705 } 706 707 tag(src, inLink, inRawBlock) { 708 const cap = this.rules.inline.tag.exec(src); 709 if (cap) { 710 if (!inLink && /^<a /i.test(cap[0])) { 711 inLink = true; 712 } else if (inLink && /^<\/a>/i.test(cap[0])) { 713 inLink = false; 714 } 715 if (!inRawBlock && /^<(pre|code|kbd|script)(\s|>)/i.test(cap[0])) { 716 inRawBlock = true; 717 } else if (inRawBlock && /^<\/(pre|code|kbd|script)(\s|>)/i.test(cap[0])) { 718 inRawBlock = false; 719 } 720 721 return { 722 type: this.options.sanitize 723 ? 'text' 724 : 'html', 725 raw: cap[0], 726 inLink, 727 inRawBlock, 728 text: this.options.sanitize 729 ? (this.options.sanitizer 730 ? this.options.sanitizer(cap[0]) 731 : escape$1(cap[0])) 732 : cap[0] 733 }; 734 } 735 } 736 737 link(src) { 738 const cap = this.rules.inline.link.exec(src); 739 if (cap) { 740 const lastParenIndex = findClosingBracket$1(cap[2], '()'); 741 if (lastParenIndex > -1) { 742 const start = cap[0].indexOf('!') === 0 ? 5 : 4; 743 const linkLen = start + cap[1].length + lastParenIndex; 744 cap[2] = cap[2].substring(0, lastParenIndex); 745 cap[0] = cap[0].substring(0, linkLen).trim(); 746 cap[3] = ''; 747 } 748 let href = cap[2]; 749 let title = ''; 750 if (this.options.pedantic) { 751 const link = /^([^'"]*[^\s])\s+(['"])(.*)\2/.exec(href); 752 753 if (link) { 754 href = link[1]; 755 title = link[3]; 756 } else { 757 title = ''; 758 } 759 } else { 760 title = cap[3] ? cap[3].slice(1, -1) : ''; 761 } 762 href = href.trim().replace(/^<([\s\S]*)>$/, '$1'); 763 const token = outputLink(cap, { 764 href: href ? href.replace(this.rules.inline._escapes, '$1') : href, 765 title: title ? title.replace(this.rules.inline._escapes, '$1') : title 766 }, cap[0]); 767 return token; 768 } 769 } 770 771 reflink(src, links) { 772 let cap; 773 if ((cap = this.rules.inline.reflink.exec(src)) 774 || (cap = this.rules.inline.nolink.exec(src))) { 775 let link = (cap[2] || cap[1]).replace(/\s+/g, ' '); 776 link = links[link.toLowerCase()]; 777 if (!link || !link.href) { 778 const text = cap[0].charAt(0); 779 return { 780 type: 'text', 781 raw: text, 782 text 783 }; 784 } 785 const token = outputLink(cap, link, cap[0]); 786 return token; 787 } 788 } 789 790 strong(src, maskedSrc, prevChar = '') { 791 let match = this.rules.inline.strong.start.exec(src); 792 793 if (match && (!match[1] || (match[1] && (prevChar === '' || this.rules.inline.punctuation.exec(prevChar))))) { 794 maskedSrc = maskedSrc.slice(-1 * src.length); 795 const endReg = match[0] === '**' ? this.rules.inline.strong.endAst : this.rules.inline.strong.endUnd; 796 797 endReg.lastIndex = 0; 798 799 let cap; 800 while ((match = endReg.exec(maskedSrc)) != null) { 801 cap = this.rules.inline.strong.middle.exec(maskedSrc.slice(0, match.index + 3)); 802 if (cap) { 803 return { 804 type: 'strong', 805 raw: src.slice(0, cap[0].length), 806 text: src.slice(2, cap[0].length - 2) 807 }; 808 } 809 } 810 } 811 } 812 813 em(src, maskedSrc, prevChar = '') { 814 let match = this.rules.inline.em.start.exec(src); 815 816 if (match && (!match[1] || (match[1] && (prevChar === '' || this.rules.inline.punctuation.exec(prevChar))))) { 817 maskedSrc = maskedSrc.slice(-1 * src.length); 818 const endReg = match[0] === '*' ? this.rules.inline.em.endAst : this.rules.inline.em.endUnd; 819 820 endReg.lastIndex = 0; 821 822 let cap; 823 while ((match = endReg.exec(maskedSrc)) != null) { 824 cap = this.rules.inline.em.middle.exec(maskedSrc.slice(0, match.index + 2)); 825 if (cap) { 826 return { 827 type: 'em', 828 raw: src.slice(0, cap[0].length), 829 text: src.slice(1, cap[0].length - 1) 830 }; 831 } 832 } 833 } 834 } 835 836 codespan(src) { 837 const cap = this.rules.inline.code.exec(src); 838 if (cap) { 839 let text = cap[2].replace(/\n/g, ' '); 840 const hasNonSpaceChars = /[^ ]/.test(text); 841 const hasSpaceCharsOnBothEnds = text.startsWith(' ') && text.endsWith(' '); 842 if (hasNonSpaceChars && hasSpaceCharsOnBothEnds) { 843 text = text.substring(1, text.length - 1); 844 } 845 text = escape$1(text, true); 846 return { 847 type: 'codespan', 848 raw: cap[0], 849 text 850 }; 851 } 852 } 853 854 br(src) { 855 const cap = this.rules.inline.br.exec(src); 856 if (cap) { 857 return { 858 type: 'br', 859 raw: cap[0] 860 }; 861 } 862 } 863 864 del(src) { 865 const cap = this.rules.inline.del.exec(src); 866 if (cap) { 867 return { 868 type: 'del', 869 raw: cap[0], 870 text: cap[1] 871 }; 872 } 873 } 874 875 autolink(src, mangle) { 876 const cap = this.rules.inline.autolink.exec(src); 877 if (cap) { 878 let text, href; 879 if (cap[2] === '@') { 880 text = escape$1(this.options.mangle ? mangle(cap[1]) : cap[1]); 881 href = 'mailto:' + text; 882 } else { 883 text = escape$1(cap[1]); 884 href = text; 885 } 886 887 return { 888 type: 'link', 889 raw: cap[0], 890 text, 891 href, 892 tokens: [ 893 { 894 type: 'text', 895 raw: text, 896 text 897 } 898 ] 899 }; 900 } 901 } 902 903 url(src, mangle) { 904 let cap; 905 if (cap = this.rules.inline.url.exec(src)) { 906 let text, href; 907 if (cap[2] === '@') { 908 text = escape$1(this.options.mangle ? mangle(cap[0]) : cap[0]); 909 href = 'mailto:' + text; 910 } else { 911 // do extended autolink path validation 912 let prevCapZero; 913 do { 914 prevCapZero = cap[0]; 915 cap[0] = this.rules.inline._backpedal.exec(cap[0])[0]; 916 } while (prevCapZero !== cap[0]); 917 text = escape$1(cap[0]); 918 if (cap[1] === 'www.') { 919 href = 'http://' + text; 920 } else { 921 href = text; 922 } 923 } 924 return { 925 type: 'link', 926 raw: cap[0], 927 text, 928 href, 929 tokens: [ 930 { 931 type: 'text', 932 raw: text, 933 text 934 } 935 ] 936 }; 937 } 938 } 939 940 inlineText(src, inRawBlock, smartypants) { 941 const cap = this.rules.inline.text.exec(src); 942 if (cap) { 943 let text; 944 if (inRawBlock) { 945 text = this.options.sanitize ? (this.options.sanitizer ? this.options.sanitizer(cap[0]) : escape$1(cap[0])) : cap[0]; 946 } else { 947 text = escape$1(this.options.smartypants ? smartypants(cap[0]) : cap[0]); 948 } 949 return { 950 type: 'text', 951 raw: cap[0], 952 text 953 }; 954 } 955 } 956 }; 957 958 const { 959 noopTest: noopTest$1, 960 edit: edit$1, 961 merge: merge$1 962 } = helpers; 963 964 /** 965 * Block-Level Grammar 966 */ 967 const block = { 968 newline: /^\n+/, 969 code: /^( {4}[^\n]+\n*)+/, 970 fences: /^ {0,3}(`{3,}(?=[^`\n]*\n)|~{3,})([^\n]*)\n(?:|([\s\S]*?)\n)(?: {0,3}\1[~`]* *(?:\n+|$)|$)/, 971 hr: /^ {0,3}((?:- *){3,}|(?:_ *){3,}|(?:\* *){3,})(?:\n+|$)/, 972 heading: /^ {0,3}(#{1,6}) +([^\n]*?)(?: +#+)? *(?:\n+|$)/, 973 blockquote: /^( {0,3}> ?(paragraph|[^\n]*)(?:\n|$))+/, 974 list: /^( {0,3})(bull) [\s\S]+?(?:hr|def|\n{2,}(?! )(?!\1bull )\n*|\s*$)/, 975 html: '^ {0,3}(?:' // optional indentation 976 + '<(script|pre|style)[\\s>][\\s\\S]*?(?:</\\1>[^\\n]*\\n+|$)' // (1) 977 + '|comment[^\\n]*(\\n+|$)' // (2) 978 + '|<\\?[\\s\\S]*?(?:\\?>\\n*|$)' // (3) 979 + '|<![A-Z][\\s\\S]*?(?:>\\n*|$)' // (4) 980 + '|<!\\[CDATA\\[[\\s\\S]*?(?:\\]\\]>\\n*|$)' // (5) 981 + '|</?(tag)(?: +|\\n|/?>)[\\s\\S]*?(?:\\n{2,}|$)' // (6) 982 + '|<(?!script|pre|style)([a-z][\\w-]*)(?:attribute)*? */?>(?=[ \\t]*(?:\\n|$))[\\s\\S]*?(?:\\n{2,}|$)' // (7) open tag 983 + '|</(?!script|pre|style)[a-z][\\w-]*\\s*>(?=[ \\t]*(?:\\n|$))[\\s\\S]*?(?:\\n{2,}|$)' // (7) closing tag 984 + ')', 985 def: /^ {0,3}\[(label)\]: *\n? *<?([^\s>]+)>?(?:(?: +\n? *| *\n *)(title))? *(?:\n+|$)/, 986 nptable: noopTest$1, 987 table: noopTest$1, 988 lheading: /^([^\n]+)\n {0,3}(=+|-+) *(?:\n+|$)/, 989 // regex template, placeholders will be replaced according to different paragraph 990 // interruption rules of commonmark and the original markdown spec: 991 _paragraph: /^([^\n]+(?:\n(?!hr|heading|lheading|blockquote|fences|list|html)[^\n]+)*)/, 992 text: /^[^\n]+/ 993 }; 994 995 block._label = /(?!\s*\])(?:\\[\[\]]|[^\[\]])+/; 996 block._title = /(?:"(?:\\"?|[^"\\])*"|'[^'\n]*(?:\n[^'\n]+)*\n?'|\([^()]*\))/; 997 block.def = edit$1(block.def) 998 .replace('label', block._label) 999 .replace('title', block._title) 1000 .getRegex(); 1001 1002 block.bullet = /(?:[*+-]|\d{1,9}[.)])/; 1003 block.item = /^( *)(bull) ?[^\n]*(?:\n(?!\1bull ?)[^\n]*)*/; 1004 block.item = edit$1(block.item, 'gm') 1005 .replace(/bull/g, block.bullet) 1006 .getRegex(); 1007 1008 block.list = edit$1(block.list) 1009 .replace(/bull/g, block.bullet) 1010 .replace('hr', '\\n+(?=\\1?(?:(?:- *){3,}|(?:_ *){3,}|(?:\\* *){3,})(?:\\n+|$))') 1011 .replace('def', '\\n+(?=' + block.def.source + ')') 1012 .getRegex(); 1013 1014 block._tag = 'address|article|aside|base|basefont|blockquote|body|caption' 1015 + '|center|col|colgroup|dd|details|dialog|dir|div|dl|dt|fieldset|figcaption' 1016 + '|figure|footer|form|frame|frameset|h[1-6]|head|header|hr|html|iframe' 1017 + '|legend|li|link|main|menu|menuitem|meta|nav|noframes|ol|optgroup|option' 1018 + '|p|param|section|source|summary|table|tbody|td|tfoot|th|thead|title|tr' 1019 + '|track|ul'; 1020 block._comment = /<!--(?!-?>)[\s\S]*?(?:-->|$)/; 1021 block.html = edit$1(block.html, 'i') 1022 .replace('comment', block._comment) 1023 .replace('tag', block._tag) 1024 .replace('attribute', / +[a-zA-Z:_][\w.:-]*(?: *= *"[^"\n]*"| *= *'[^'\n]*'| *= *[^\s"'=<>`]+)?/) 1025 .getRegex(); 1026 1027 block.paragraph = edit$1(block._paragraph) 1028 .replace('hr', block.hr) 1029 .replace('heading', ' {0,3}#{1,6} ') 1030 .replace('|lheading', '') // setex headings don't interrupt commonmark paragraphs 1031 .replace('blockquote', ' {0,3}>') 1032 .replace('fences', ' {0,3}(?:`{3,}(?=[^`\\n]*\\n)|~{3,})[^\\n]*\\n') 1033 .replace('list', ' {0,3}(?:[*+-]|1[.)]) ') // only lists starting from 1 can interrupt 1034 .replace('html', '</?(?:tag)(?: +|\\n|/?>)|<(?:script|pre|style|!--)') 1035 .replace('tag', block._tag) // pars can be interrupted by type (6) html blocks 1036 .getRegex(); 1037 1038 block.blockquote = edit$1(block.blockquote) 1039 .replace('paragraph', block.paragraph) 1040 .getRegex(); 1041 1042 /** 1043 * Normal Block Grammar 1044 */ 1045 1046 block.normal = merge$1({}, block); 1047 1048 /** 1049 * GFM Block Grammar 1050 */ 1051 1052 block.gfm = merge$1({}, block.normal, { 1053 nptable: '^ *([^|\\n ].*\\|.*)\\n' // Header 1054 + ' {0,3}([-:]+ *\\|[-| :]*)' // Align 1055 + '(?:\\n((?:(?!\\n|hr|heading|blockquote|code|fences|list|html).*(?:\\n|$))*)\\n*|$)', // Cells 1056 table: '^ *\\|(.+)\\n' // Header 1057 + ' {0,3}\\|?( *[-:]+[-| :]*)' // Align 1058 + '(?:\\n *((?:(?!\\n|hr|heading|blockquote|code|fences|list|html).*(?:\\n|$))*)\\n*|$)' // Cells 1059 }); 1060 1061 block.gfm.nptable = edit$1(block.gfm.nptable) 1062 .replace('hr', block.hr) 1063 .replace('heading', ' {0,3}#{1,6} ') 1064 .replace('blockquote', ' {0,3}>') 1065 .replace('code', ' {4}[^\\n]') 1066 .replace('fences', ' {0,3}(?:`{3,}(?=[^`\\n]*\\n)|~{3,})[^\\n]*\\n') 1067 .replace('list', ' {0,3}(?:[*+-]|1[.)]) ') // only lists starting from 1 can interrupt 1068 .replace('html', '</?(?:tag)(?: +|\\n|/?>)|<(?:script|pre|style|!--)') 1069 .replace('tag', block._tag) // tables can be interrupted by type (6) html blocks 1070 .getRegex(); 1071 1072 block.gfm.table = edit$1(block.gfm.table) 1073 .replace('hr', block.hr) 1074 .replace('heading', ' {0,3}#{1,6} ') 1075 .replace('blockquote', ' {0,3}>') 1076 .replace('code', ' {4}[^\\n]') 1077 .replace('fences', ' {0,3}(?:`{3,}(?=[^`\\n]*\\n)|~{3,})[^\\n]*\\n') 1078 .replace('list', ' {0,3}(?:[*+-]|1[.)]) ') // only lists starting from 1 can interrupt 1079 .replace('html', '</?(?:tag)(?: +|\\n|/?>)|<(?:script|pre|style|!--)') 1080 .replace('tag', block._tag) // tables can be interrupted by type (6) html blocks 1081 .getRegex(); 1082 1083 /** 1084 * Pedantic grammar (original John Gruber's loose markdown specification) 1085 */ 1086 1087 block.pedantic = merge$1({}, block.normal, { 1088 html: edit$1( 1089 '^ *(?:comment *(?:\\n|\\s*$)' 1090 + '|<(tag)[\\s\\S]+?</\\1> *(?:\\n{2,}|\\s*$)' // closed tag 1091 + '|<tag(?:"[^"]*"|\'[^\']*\'|\\s[^\'"/>\\s]*)*?/?> *(?:\\n{2,}|\\s*$))') 1092 .replace('comment', block._comment) 1093 .replace(/tag/g, '(?!(?:' 1094 + 'a|em|strong|small|s|cite|q|dfn|abbr|data|time|code|var|samp|kbd|sub' 1095 + '|sup|i|b|u|mark|ruby|rt|rp|bdi|bdo|span|br|wbr|ins|del|img)' 1096 + '\\b)\\w+(?!:|[^\\w\\s@]*@)\\b') 1097 .getRegex(), 1098 def: /^ *\[([^\]]+)\]: *<?([^\s>]+)>?(?: +(["(][^\n]+[")]))? *(?:\n+|$)/, 1099 heading: /^ *(#{1,6}) *([^\n]+?) *(?:#+ *)?(?:\n+|$)/, 1100 fences: noopTest$1, // fences not supported 1101 paragraph: edit$1(block.normal._paragraph) 1102 .replace('hr', block.hr) 1103 .replace('heading', ' *#{1,6} *[^\n]') 1104 .replace('lheading', block.lheading) 1105 .replace('blockquote', ' {0,3}>') 1106 .replace('|fences', '') 1107 .replace('|list', '') 1108 .replace('|html', '') 1109 .getRegex() 1110 }); 1111 1112 /** 1113 * Inline-Level Grammar 1114 */ 1115 const inline = { 1116 escape: /^\\([!"#$%&'()*+,\-./:;<=>?@\[\]\\^_`{|}~])/, 1117 autolink: /^<(scheme:[^\s\x00-\x1f<>]*|email)>/, 1118 url: noopTest$1, 1119 tag: '^comment' 1120 + '|^</[a-zA-Z][\\w:-]*\\s*>' // self-closing tag 1121 + '|^<[a-zA-Z][\\w-]*(?:attribute)*?\\s*/?>' // open tag 1122 + '|^<\\?[\\s\\S]*?\\?>' // processing instruction, e.g. <?php ?> 1123 + '|^<![a-zA-Z]+\\s[\\s\\S]*?>' // declaration, e.g. <!DOCTYPE html> 1124 + '|^<!\\[CDATA\\[[\\s\\S]*?\\]\\]>', // CDATA section 1125 link: /^!?\[(label)\]\(\s*(href)(?:\s+(title))?\s*\)/, 1126 reflink: /^!?\[(label)\]\[(?!\s*\])((?:\\[\[\]]?|[^\[\]\\])+)\]/, 1127 nolink: /^!?\[(?!\s*\])((?:\[[^\[\]]*\]|\\[\[\]]|[^\[\]])*)\](?:\[\])?/, 1128 reflinkSearch: 'reflink|nolink(?!\\()', 1129 strong: { 1130 start: /^(?:(\*\*(?=[*punctuation]))|\*\*)(?![\s])|__/, // (1) returns if starts w/ punctuation 1131 middle: /^\*\*(?:(?:(?!overlapSkip)(?:[^*]|\\\*)|overlapSkip)|\*(?:(?!overlapSkip)(?:[^*]|\\\*)|overlapSkip)*?\*)+?\*\*$|^__(?![\s])((?:(?:(?!overlapSkip)(?:[^_]|\\_)|overlapSkip)|_(?:(?!overlapSkip)(?:[^_]|\\_)|overlapSkip)*?_)+?)__$/, 1132 endAst: /[^punctuation\s]\*\*(?!\*)|[punctuation]\*\*(?!\*)(?:(?=[punctuation_\s]|$))/, // last char can't be punct, or final * must also be followed by punct (or endline) 1133 endUnd: /[^\s]__(?!_)(?:(?=[punctuation*\s])|$)/ // last char can't be a space, and final _ must preceed punct or \s (or endline) 1134 }, 1135 em: { 1136 start: /^(?:(\*(?=[punctuation]))|\*)(?![*\s])|_/, // (1) returns if starts w/ punctuation 1137 middle: /^\*(?:(?:(?!overlapSkip)(?:[^*]|\\\*)|overlapSkip)|\*(?:(?!overlapSkip)(?:[^*]|\\\*)|overlapSkip)*?\*)+?\*$|^_(?![_\s])(?:(?:(?!overlapSkip)(?:[^_]|\\_)|overlapSkip)|_(?:(?!overlapSkip)(?:[^_]|\\_)|overlapSkip)*?_)+?_$/, 1138 endAst: /[^punctuation\s]\*(?!\*)|[punctuation]\*(?!\*)(?:(?=[punctuation_\s]|$))/, // last char can't be punct, or final * must also be followed by punct (or endline) 1139 endUnd: /[^\s]_(?!_)(?:(?=[punctuation*\s])|$)/ // last char can't be a space, and final _ must preceed punct or \s (or endline) 1140 }, 1141 code: /^(`+)([^`]|[^`][\s\S]*?[^`])\1(?!`)/, 1142 br: /^( {2,}|\\)\n(?!\s*$)/, 1143 del: noopTest$1, 1144 text: /^(`+|[^`])(?:(?= {2,}\n)|[\s\S]*?(?:(?=[\\<!\[`*]|\b_|$)|[^ ](?= {2,}\n)))/, 1145 punctuation: /^([\s*punctuation])/ 1146 }; 1147 1148 // list of punctuation marks from common mark spec 1149 // without * and _ to workaround cases with double emphasis 1150 inline._punctuation = '!"#$%&\'()+\\-.,/:;<=>?@\\[\\]`^{|}~'; 1151 inline.punctuation = edit$1(inline.punctuation).replace(/punctuation/g, inline._punctuation).getRegex(); 1152 1153 // sequences em should skip over [title](link), `code`, <html> 1154 inline._blockSkip = '\\[[^\\]]*?\\]\\([^\\)]*?\\)|`[^`]*?`|<[^>]*?>'; 1155 inline._overlapSkip = '__[^_]*?__|\\*\\*\\[^\\*\\]*?\\*\\*'; 1156 1157 inline._comment = edit$1(block._comment).replace('(?:-->|$)', '-->').getRegex(); 1158 1159 inline.em.start = edit$1(inline.em.start) 1160 .replace(/punctuation/g, inline._punctuation) 1161 .getRegex(); 1162 1163 inline.em.middle = edit$1(inline.em.middle) 1164 .replace(/punctuation/g, inline._punctuation) 1165 .replace(/overlapSkip/g, inline._overlapSkip) 1166 .getRegex(); 1167 1168 inline.em.endAst = edit$1(inline.em.endAst, 'g') 1169 .replace(/punctuation/g, inline._punctuation) 1170 .getRegex(); 1171 1172 inline.em.endUnd = edit$1(inline.em.endUnd, 'g') 1173 .replace(/punctuation/g, inline._punctuation) 1174 .getRegex(); 1175 1176 inline.strong.start = edit$1(inline.strong.start) 1177 .replace(/punctuation/g, inline._punctuation) 1178 .getRegex(); 1179 1180 inline.strong.middle = edit$1(inline.strong.middle) 1181 .replace(/punctuation/g, inline._punctuation) 1182 .replace(/overlapSkip/g, inline._overlapSkip) 1183 .getRegex(); 1184 1185 inline.strong.endAst = edit$1(inline.strong.endAst, 'g') 1186 .replace(/punctuation/g, inline._punctuation) 1187 .getRegex(); 1188 1189 inline.strong.endUnd = edit$1(inline.strong.endUnd, 'g') 1190 .replace(/punctuation/g, inline._punctuation) 1191 .getRegex(); 1192 1193 inline.blockSkip = edit$1(inline._blockSkip, 'g') 1194 .getRegex(); 1195 1196 inline.overlapSkip = edit$1(inline._overlapSkip, 'g') 1197 .getRegex(); 1198 1199 inline._escapes = /\\([!"#$%&'()*+,\-./:;<=>?@\[\]\\^_`{|}~])/g; 1200 1201 inline._scheme = /[a-zA-Z][a-zA-Z0-9+.-]{1,31}/; 1202 inline._email = /[a-zA-Z0-9.!#$%&'*+/=?^_`{|}~-]+(@)[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)+(?![-_])/; 1203 inline.autolink = edit$1(inline.autolink) 1204 .replace('scheme', inline._scheme) 1205 .replace('email', inline._email) 1206 .getRegex(); 1207 1208 inline._attribute = /\s+[a-zA-Z:_][\w.:-]*(?:\s*=\s*"[^"]*"|\s*=\s*'[^']*'|\s*=\s*[^\s"'=<>`]+)?/; 1209 1210 inline.tag = edit$1(inline.tag) 1211 .replace('comment', inline._comment) 1212 .replace('attribute', inline._attribute) 1213 .getRegex(); 1214 1215 inline._label = /(?:\[(?:\\.|[^\[\]\\])*\]|\\.|`[^`]*`|[^\[\]\\`])*?/; 1216 inline._href = /<(?:\\[<>]?|[^\s<>\\])*>|[^\s\x00-\x1f]*/; 1217 inline._title = /"(?:\\"?|[^"\\])*"|'(?:\\'?|[^'\\])*'|\((?:\\\)?|[^)\\])*\)/; 1218 1219 inline.link = edit$1(inline.link) 1220 .replace('label', inline._label) 1221 .replace('href', inline._href) 1222 .replace('title', inline._title) 1223 .getRegex(); 1224 1225 inline.reflink = edit$1(inline.reflink) 1226 .replace('label', inline._label) 1227 .getRegex(); 1228 1229 inline.reflinkSearch = edit$1(inline.reflinkSearch, 'g') 1230 .replace('reflink', inline.reflink) 1231 .replace('nolink', inline.nolink) 1232 .getRegex(); 1233 1234 /** 1235 * Normal Inline Grammar 1236 */ 1237 1238 inline.normal = merge$1({}, inline); 1239 1240 /** 1241 * Pedantic Inline Grammar 1242 */ 1243 1244 inline.pedantic = merge$1({}, inline.normal, { 1245 strong: { 1246 start: /^__|\*\*/, 1247 middle: /^__(?=\S)([\s\S]*?\S)__(?!_)|^\*\*(?=\S)([\s\S]*?\S)\*\*(?!\*)/, 1248 endAst: /\*\*(?!\*)/g, 1249 endUnd: /__(?!_)/g 1250 }, 1251 em: { 1252 start: /^_|\*/, 1253 middle: /^()\*(?=\S)([\s\S]*?\S)\*(?!\*)|^_(?=\S)([\s\S]*?\S)_(?!_)/, 1254 endAst: /\*(?!\*)/g, 1255 endUnd: /_(?!_)/g 1256 }, 1257 link: edit$1(/^!?\[(label)\]\((.*?)\)/) 1258 .replace('label', inline._label) 1259 .getRegex(), 1260 reflink: edit$1(/^!?\[(label)\]\s*\[([^\]]*)\]/) 1261 .replace('label', inline._label) 1262 .getRegex() 1263 }); 1264 1265 /** 1266 * GFM Inline Grammar 1267 */ 1268 1269 inline.gfm = merge$1({}, inline.normal, { 1270 escape: edit$1(inline.escape).replace('])', '~|])').getRegex(), 1271 _extended_email: /[A-Za-z0-9._+-]+(@)[a-zA-Z0-9-_]+(?:\.[a-zA-Z0-9-_]*[a-zA-Z0-9])+(?![-_])/, 1272 url: /^((?:ftp|https?):\/\/|www\.)(?:[a-zA-Z0-9\-]+\.?)+[^\s<]*|^email/, 1273 _backpedal: /(?:[^?!.,:;*_~()&]+|\([^)]*\)|&(?![a-zA-Z0-9]+;$)|[?!.,:;*_~)]+(?!$))+/, 1274 del: /^~+(?=\S)([\s\S]*?\S)~+/, 1275 text: /^(`+|[^`])(?:(?= {2,}\n)|[\s\S]*?(?:(?=[\\<!\[`*~]|\b_|https?:\/\/|ftp:\/\/|www\.|$)|[^ ](?= {2,}\n)|[^a-zA-Z0-9.!#$%&'*+\/=?_`{\|}~-](?=[a-zA-Z0-9.!#$%&'*+\/=?_`{\|}~-]+@))|(?=[a-zA-Z0-9.!#$%&'*+\/=?_`{\|}~-]+@))/ 1276 }); 1277 1278 inline.gfm.url = edit$1(inline.gfm.url, 'i') 1279 .replace('email', inline.gfm._extended_email) 1280 .getRegex(); 1281 /** 1282 * GFM + Line Breaks Inline Grammar 1283 */ 1284 1285 inline.breaks = merge$1({}, inline.gfm, { 1286 br: edit$1(inline.br).replace('{2,}', '*').getRegex(), 1287 text: edit$1(inline.gfm.text) 1288 .replace('\\b_', '\\b_| {2,}\\n') 1289 .replace(/\{2,\}/g, '*') 1290 .getRegex() 1291 }); 1292 1293 var rules = { 1294 block, 1295 inline 1296 }; 1297 1298 const { defaults: defaults$2 } = defaults; 1299 const { block: block$1, inline: inline$1 } = rules; 1300 1301 /** 1302 * smartypants text replacement 1303 */ 1304 function smartypants(text) { 1305 return text 1306 // em-dashes 1307 .replace(/---/g, '\u2014') 1308 // en-dashes 1309 .replace(/--/g, '\u2013') 1310 // opening singles 1311 .replace(/(^|[-\u2014/(\[{"\s])'/g, '$1\u2018') 1312 // closing singles & apostrophes 1313 .replace(/'/g, '\u2019') 1314 // opening doubles 1315 .replace(/(^|[-\u2014/(\[{\u2018\s])"/g, '$1\u201c') 1316 // closing doubles 1317 .replace(/"/g, '\u201d') 1318 // ellipses 1319 .replace(/\.{3}/g, '\u2026'); 1320 } 1321 1322 /** 1323 * mangle email addresses 1324 */ 1325 function mangle(text) { 1326 let out = '', 1327 i, 1328 ch; 1329 1330 const l = text.length; 1331 for (i = 0; i < l; i++) { 1332 ch = text.charCodeAt(i); 1333 if (Math.random() > 0.5) { 1334 ch = 'x' + ch.toString(16); 1335 } 1336 out += '&#' + ch + ';'; 1337 } 1338 1339 return out; 1340 } 1341 1342 /** 1343 * Block Lexer 1344 */ 1345 var Lexer_1 = class Lexer { 1346 constructor(options) { 1347 this.tokens = []; 1348 this.tokens.links = Object.create(null); 1349 this.options = options || defaults$2; 1350 this.options.tokenizer = this.options.tokenizer || new Tokenizer_1(); 1351 this.tokenizer = this.options.tokenizer; 1352 this.tokenizer.options = this.options; 1353 1354 const rules = { 1355 block: block$1.normal, 1356 inline: inline$1.normal 1357 }; 1358 1359 if (this.options.pedantic) { 1360 rules.block = block$1.pedantic; 1361 rules.inline = inline$1.pedantic; 1362 } else if (this.options.gfm) { 1363 rules.block = block$1.gfm; 1364 if (this.options.breaks) { 1365 rules.inline = inline$1.breaks; 1366 } else { 1367 rules.inline = inline$1.gfm; 1368 } 1369 } 1370 this.tokenizer.rules = rules; 1371 } 1372 1373 /** 1374 * Expose Rules 1375 */ 1376 static get rules() { 1377 return { 1378 block: block$1, 1379 inline: inline$1 1380 }; 1381 } 1382 1383 /** 1384 * Static Lex Method 1385 */ 1386 static lex(src, options) { 1387 const lexer = new Lexer(options); 1388 return lexer.lex(src); 1389 } 1390 1391 /** 1392 * Static Lex Inline Method 1393 */ 1394 static lexInline(src, options) { 1395 const lexer = new Lexer(options); 1396 return lexer.inlineTokens(src); 1397 } 1398 1399 /** 1400 * Preprocessing 1401 */ 1402 lex(src) { 1403 src = src 1404 .replace(/\r\n|\r/g, '\n') 1405 .replace(/\t/g, ' '); 1406 1407 this.blockTokens(src, this.tokens, true); 1408 1409 this.inline(this.tokens); 1410 1411 return this.tokens; 1412 } 1413 1414 /** 1415 * Lexing 1416 */ 1417 blockTokens(src, tokens = [], top = true) { 1418 src = src.replace(/^ +$/gm, ''); 1419 let token, i, l, lastToken; 1420 1421 while (src) { 1422 // newline 1423 if (token = this.tokenizer.space(src)) { 1424 src = src.substring(token.raw.length); 1425 if (token.type) { 1426 tokens.push(token); 1427 } 1428 continue; 1429 } 1430 1431 // code 1432 if (token = this.tokenizer.code(src, tokens)) { 1433 src = src.substring(token.raw.length); 1434 if (token.type) { 1435 tokens.push(token); 1436 } else { 1437 lastToken = tokens[tokens.length - 1]; 1438 lastToken.raw += '\n' + token.raw; 1439 lastToken.text += '\n' + token.text; 1440 } 1441 continue; 1442 } 1443 1444 // fences 1445 if (token = this.tokenizer.fences(src)) { 1446 src = src.substring(token.raw.length); 1447 tokens.push(token); 1448 continue; 1449 } 1450 1451 // heading 1452 if (token = this.tokenizer.heading(src)) { 1453 src = src.substring(token.raw.length); 1454 tokens.push(token); 1455 continue; 1456 } 1457 1458 // table no leading pipe (gfm) 1459 if (token = this.tokenizer.nptable(src)) { 1460 src = src.substring(token.raw.length); 1461 tokens.push(token); 1462 continue; 1463 } 1464 1465 // hr 1466 if (token = this.tokenizer.hr(src)) { 1467 src = src.substring(token.raw.length); 1468 tokens.push(token); 1469 continue; 1470 } 1471 1472 // blockquote 1473 if (token = this.tokenizer.blockquote(src)) { 1474 src = src.substring(token.raw.length); 1475 token.tokens = this.blockTokens(token.text, [], top); 1476 tokens.push(token); 1477 continue; 1478 } 1479 1480 // list 1481 if (token = this.tokenizer.list(src)) { 1482 src = src.substring(token.raw.length); 1483 l = token.items.length; 1484 for (i = 0; i < l; i++) { 1485 token.items[i].tokens = this.blockTokens(token.items[i].text, [], false); 1486 } 1487 tokens.push(token); 1488 continue; 1489 } 1490 1491 // html 1492 if (token = this.tokenizer.html(src)) { 1493 src = src.substring(token.raw.length); 1494 tokens.push(token); 1495 continue; 1496 } 1497 1498 // def 1499 if (top && (token = this.tokenizer.def(src))) { 1500 src = src.substring(token.raw.length); 1501 if (!this.tokens.links[token.tag]) { 1502 this.tokens.links[token.tag] = { 1503 href: token.href, 1504 title: token.title 1505 }; 1506 } 1507 continue; 1508 } 1509 1510 // table (gfm) 1511 if (token = this.tokenizer.table(src)) { 1512 src = src.substring(token.raw.length); 1513 tokens.push(token); 1514 continue; 1515 } 1516 1517 // lheading 1518 if (token = this.tokenizer.lheading(src)) { 1519 src = src.substring(token.raw.length); 1520 tokens.push(token); 1521 continue; 1522 } 1523 1524 // top-level paragraph 1525 if (top && (token = this.tokenizer.paragraph(src))) { 1526 src = src.substring(token.raw.length); 1527 tokens.push(token); 1528 continue; 1529 } 1530 1531 // text 1532 if (token = this.tokenizer.text(src, tokens)) { 1533 src = src.substring(token.raw.length); 1534 if (token.type) { 1535 tokens.push(token); 1536 } else { 1537 lastToken = tokens[tokens.length - 1]; 1538 lastToken.raw += '\n' + token.raw; 1539 lastToken.text += '\n' + token.text; 1540 } 1541 continue; 1542 } 1543 1544 if (src) { 1545 const errMsg = 'Infinite loop on byte: ' + src.charCodeAt(0); 1546 if (this.options.silent) { 1547 console.error(errMsg); 1548 break; 1549 } else { 1550 throw new Error(errMsg); 1551 } 1552 } 1553 } 1554 1555 return tokens; 1556 } 1557 1558 inline(tokens) { 1559 let i, 1560 j, 1561 k, 1562 l2, 1563 row, 1564 token; 1565 1566 const l = tokens.length; 1567 for (i = 0; i < l; i++) { 1568 token = tokens[i]; 1569 switch (token.type) { 1570 case 'paragraph': 1571 case 'text': 1572 case 'heading': { 1573 token.tokens = []; 1574 this.inlineTokens(token.text, token.tokens); 1575 break; 1576 } 1577 case 'table': { 1578 token.tokens = { 1579 header: [], 1580 cells: [] 1581 }; 1582 1583 // header 1584 l2 = token.header.length; 1585 for (j = 0; j < l2; j++) { 1586 token.tokens.header[j] = []; 1587 this.inlineTokens(token.header[j], token.tokens.header[j]); 1588 } 1589 1590 // cells 1591 l2 = token.cells.length; 1592 for (j = 0; j < l2; j++) { 1593 row = token.cells[j]; 1594 token.tokens.cells[j] = []; 1595 for (k = 0; k < row.length; k++) { 1596 token.tokens.cells[j][k] = []; 1597 this.inlineTokens(row[k], token.tokens.cells[j][k]); 1598 } 1599 } 1600 1601 break; 1602 } 1603 case 'blockquote': { 1604 this.inline(token.tokens); 1605 break; 1606 } 1607 case 'list': { 1608 l2 = token.items.length; 1609 for (j = 0; j < l2; j++) { 1610 this.inline(token.items[j].tokens); 1611 } 1612 break; 1613 } 1614 } 1615 } 1616 1617 return tokens; 1618 } 1619 1620 /** 1621 * Lexing/Compiling 1622 */ 1623 inlineTokens(src, tokens = [], inLink = false, inRawBlock = false, prevChar = '') { 1624 let token; 1625 1626 // String with links masked to avoid interference with em and strong 1627 let maskedSrc = src; 1628 let match; 1629 1630 // Mask out reflinks 1631 if (this.tokens.links) { 1632 const links = Object.keys(this.tokens.links); 1633 if (links.length > 0) { 1634 while ((match = this.tokenizer.rules.inline.reflinkSearch.exec(maskedSrc)) != null) { 1635 if (links.includes(match[0].slice(match[0].lastIndexOf('[') + 1, -1))) { 1636 maskedSrc = maskedSrc.slice(0, match.index) + '[' + 'a'.repeat(match[0].length - 2) + ']' + maskedSrc.slice(this.tokenizer.rules.inline.reflinkSearch.lastIndex); 1637 } 1638 } 1639 } 1640 } 1641 // Mask out other blocks 1642 while ((match = this.tokenizer.rules.inline.blockSkip.exec(maskedSrc)) != null) { 1643 maskedSrc = maskedSrc.slice(0, match.index) + '[' + 'a'.repeat(match[0].length - 2) + ']' + maskedSrc.slice(this.tokenizer.rules.inline.blockSkip.lastIndex); 1644 } 1645 1646 while (src) { 1647 // escape 1648 if (token = this.tokenizer.escape(src)) { 1649 src = src.substring(token.raw.length); 1650 tokens.push(token); 1651 continue; 1652 } 1653 1654 // tag 1655 if (token = this.tokenizer.tag(src, inLink, inRawBlock)) { 1656 src = src.substring(token.raw.length); 1657 inLink = token.inLink; 1658 inRawBlock = token.inRawBlock; 1659 tokens.push(token); 1660 continue; 1661 } 1662 1663 // link 1664 if (token = this.tokenizer.link(src)) { 1665 src = src.substring(token.raw.length); 1666 if (token.type === 'link') { 1667 token.tokens = this.inlineTokens(token.text, [], true, inRawBlock); 1668 } 1669 tokens.push(token); 1670 continue; 1671 } 1672 1673 // reflink, nolink 1674 if (token = this.tokenizer.reflink(src, this.tokens.links)) { 1675 src = src.substring(token.raw.length); 1676 if (token.type === 'link') { 1677 token.tokens = this.inlineTokens(token.text, [], true, inRawBlock); 1678 } 1679 tokens.push(token); 1680 continue; 1681 } 1682 1683 // strong 1684 if (token = this.tokenizer.strong(src, maskedSrc, prevChar)) { 1685 src = src.substring(token.raw.length); 1686 token.tokens = this.inlineTokens(token.text, [], inLink, inRawBlock); 1687 tokens.push(token); 1688 continue; 1689 } 1690 1691 // em 1692 if (token = this.tokenizer.em(src, maskedSrc, prevChar)) { 1693 src = src.substring(token.raw.length); 1694 token.tokens = this.inlineTokens(token.text, [], inLink, inRawBlock); 1695 tokens.push(token); 1696 continue; 1697 } 1698 1699 // code 1700 if (token = this.tokenizer.codespan(src)) { 1701 src = src.substring(token.raw.length); 1702 tokens.push(token); 1703 continue; 1704 } 1705 1706 // br 1707 if (token = this.tokenizer.br(src)) { 1708 src = src.substring(token.raw.length); 1709 tokens.push(token); 1710 continue; 1711 } 1712 1713 // del (gfm) 1714 if (token = this.tokenizer.del(src)) { 1715 src = src.substring(token.raw.length); 1716 token.tokens = this.inlineTokens(token.text, [], inLink, inRawBlock); 1717 tokens.push(token); 1718 continue; 1719 } 1720 1721 // autolink 1722 if (token = this.tokenizer.autolink(src, mangle)) { 1723 src = src.substring(token.raw.length); 1724 tokens.push(token); 1725 continue; 1726 } 1727 1728 // url (gfm) 1729 if (!inLink && (token = this.tokenizer.url(src, mangle))) { 1730 src = src.substring(token.raw.length); 1731 tokens.push(token); 1732 continue; 1733 } 1734 1735 // text 1736 if (token = this.tokenizer.inlineText(src, inRawBlock, smartypants)) { 1737 src = src.substring(token.raw.length); 1738 prevChar = token.raw.slice(-1); 1739 tokens.push(token); 1740 continue; 1741 } 1742 1743 if (src) { 1744 const errMsg = 'Infinite loop on byte: ' + src.charCodeAt(0); 1745 if (this.options.silent) { 1746 console.error(errMsg); 1747 break; 1748 } else { 1749 throw new Error(errMsg); 1750 } 1751 } 1752 } 1753 1754 return tokens; 1755 } 1756 }; 1757 1758 const { defaults: defaults$3 } = defaults; 1759 const { 1760 cleanUrl: cleanUrl$1, 1761 escape: escape$2 1762 } = helpers; 1763 1764 /** 1765 * Renderer 1766 */ 1767 var Renderer_1 = class Renderer { 1768 constructor(options) { 1769 this.options = options || defaults$3; 1770 } 1771 1772 code(code, infostring, escaped) { 1773 const lang = (infostring || '').match(/\S*/)[0]; 1774 if (this.options.highlight) { 1775 const out = this.options.highlight(code, lang); 1776 if (out != null && out !== code) { 1777 escaped = true; 1778 code = out; 1779 } 1780 } 1781 1782 if (!lang) { 1783 return '<pre><code>' 1784 + (escaped ? code : escape$2(code, true)) 1785 + '</code></pre>\n'; 1786 } 1787 1788 return '<pre><code class="' 1789 + this.options.langPrefix 1790 + escape$2(lang, true) 1791 + '">' 1792 + (escaped ? code : escape$2(code, true)) 1793 + '</code></pre>\n'; 1794 } 1795 1796 blockquote(quote) { 1797 return '<blockquote>\n' + quote + '</blockquote>\n'; 1798 } 1799 1800 html(html) { 1801 return html; 1802 } 1803 1804 heading(text, level, raw, slugger) { 1805 if (this.options.headerIds) { 1806 return '<h' 1807 + level 1808 + ' id="' 1809 + this.options.headerPrefix 1810 + slugger.slug(raw) 1811 + '">' 1812 + text 1813 + '</h' 1814 + level 1815 + '>\n'; 1816 } 1817 // ignore IDs 1818 return '<h' + level + '>' + text + '</h' + level + '>\n'; 1819 } 1820 1821 hr() { 1822 return this.options.xhtml ? '<hr/>\n' : '<hr>\n'; 1823 } 1824 1825 list(body, ordered, start) { 1826 const type = ordered ? 'ol' : 'ul', 1827 startatt = (ordered && start !== 1) ? (' start="' + start + '"') : ''; 1828 return '<' + type + startatt + '>\n' + body + '</' + type + '>\n'; 1829 } 1830 1831 listitem(text) { 1832 return '<li>' + text + '</li>\n'; 1833 } 1834 1835 checkbox(checked) { 1836 return '<input ' 1837 + (checked ? 'checked="" ' : '') 1838 + 'disabled="" type="checkbox"' 1839 + (this.options.xhtml ? ' /' : '') 1840 + '> '; 1841 } 1842 1843 paragraph(text) { 1844 return '<p>' + text + '</p>\n'; 1845 } 1846 1847 table(header, body) { 1848 if (body) body = '<tbody>' + body + '</tbody>'; 1849 1850 return '<table>\n' 1851 + '<thead>\n' 1852 + header 1853 + '</thead>\n' 1854 + body 1855 + '</table>\n'; 1856 } 1857 1858 tablerow(content) { 1859 return '<tr>\n' + content + '</tr>\n'; 1860 } 1861 1862 tablecell(content, flags) { 1863 const type = flags.header ? 'th' : 'td'; 1864 const tag = flags.align 1865 ? '<' + type + ' align="' + flags.align + '">' 1866 : '<' + type + '>'; 1867 return tag + content + '</' + type + '>\n'; 1868 } 1869 1870 // span level renderer 1871 strong(text) { 1872 return '<strong>' + text + '</strong>'; 1873 } 1874 1875 em(text) { 1876 return '<em>' + text + '</em>'; 1877 } 1878 1879 codespan(text) { 1880 return '<code>' + text + '</code>'; 1881 } 1882 1883 br() { 1884 return this.options.xhtml ? '<br/>' : '<br>'; 1885 } 1886 1887 del(text) { 1888 return '<del>' + text + '</del>'; 1889 } 1890 1891 link(href, title, text) { 1892 href = cleanUrl$1(this.options.sanitize, this.options.baseUrl, href); 1893 if (href === null) { 1894 return text; 1895 } 1896 let out = '<a href="' + escape$2(href) + '"'; 1897 if (title) { 1898 out += ' title="' + title + '"'; 1899 } 1900 out += '>' + text + '</a>'; 1901 return out; 1902 } 1903 1904 image(href, title, text) { 1905 href = cleanUrl$1(this.options.sanitize, this.options.baseUrl, href); 1906 if (href === null) { 1907 return text; 1908 } 1909 1910 let out = '<img src="' + href + '" alt="' + text + '"'; 1911 if (title) { 1912 out += ' title="' + title + '"'; 1913 } 1914 out += this.options.xhtml ? '/>' : '>'; 1915 return out; 1916 } 1917 1918 text(text) { 1919 return text; 1920 } 1921 }; 1922 1923 /** 1924 * TextRenderer 1925 * returns only the textual part of the token 1926 */ 1927 var TextRenderer_1 = class TextRenderer { 1928 // no need for block level renderers 1929 strong(text) { 1930 return text; 1931 } 1932 1933 em(text) { 1934 return text; 1935 } 1936 1937 codespan(text) { 1938 return text; 1939 } 1940 1941 del(text) { 1942 return text; 1943 } 1944 1945 html(text) { 1946 return text; 1947 } 1948 1949 text(text) { 1950 return text; 1951 } 1952 1953 link(href, title, text) { 1954 return '' + text; 1955 } 1956 1957 image(href, title, text) { 1958 return '' + text; 1959 } 1960 1961 br() { 1962 return ''; 1963 } 1964 }; 1965 1966 /** 1967 * Slugger generates header id 1968 */ 1969 var Slugger_1 = class Slugger { 1970 constructor() { 1971 this.seen = {}; 1972 } 1973 1974 serialize(value) { 1975 return value 1976 .toLowerCase() 1977 .trim() 1978 // remove html tags 1979 .replace(/<[!\/a-z].*?>/ig, '') 1980 // remove unwanted chars 1981 .replace(/[\u2000-\u206F\u2E00-\u2E7F\\'!"#$%&()*+,./:;<=>?@[\]^`{|}~]/g, '') 1982 .replace(/\s/g, '-'); 1983 } 1984 1985 /** 1986 * Finds the next safe (unique) slug to use 1987 */ 1988 getNextSafeSlug(originalSlug, isDryRun) { 1989 let slug = originalSlug; 1990 let occurenceAccumulator = 0; 1991 if (this.seen.hasOwnProperty(slug)) { 1992 occurenceAccumulator = this.seen[originalSlug]; 1993 do { 1994 occurenceAccumulator++; 1995 slug = originalSlug + '-' + occurenceAccumulator; 1996 } while (this.seen.hasOwnProperty(slug)); 1997 } 1998 if (!isDryRun) { 1999 this.seen[originalSlug] = occurenceAccumulator; 2000 this.seen[slug] = 0; 2001 } 2002 return slug; 2003 } 2004 2005 /** 2006 * Convert string to unique id 2007 * @param {object} options 2008 * @param {boolean} options.dryrun Generates the next unique slug without updating the internal accumulator. 2009 */ 2010 slug(value, options = {}) { 2011 const slug = this.serialize(value); 2012 return this.getNextSafeSlug(slug, options.dryrun); 2013 } 2014 }; 2015 2016 const { defaults: defaults$4 } = defaults; 2017 const { 2018 unescape: unescape$1 2019 } = helpers; 2020 2021 /** 2022 * Parsing & Compiling 2023 */ 2024 var Parser_1 = class Parser { 2025 constructor(options) { 2026 this.options = options || defaults$4; 2027 this.options.renderer = this.options.renderer || new Renderer_1(); 2028 this.renderer = this.options.renderer; 2029 this.renderer.options = this.options; 2030 this.textRenderer = new TextRenderer_1(); 2031 this.slugger = new Slugger_1(); 2032 } 2033 2034 /** 2035 * Static Parse Method 2036 */ 2037 static parse(tokens, options) { 2038 const parser = new Parser(options); 2039 return parser.parse(tokens); 2040 } 2041 2042 /** 2043 * Static Parse Inline Method 2044 */ 2045 static parseInline(tokens, options) { 2046 const parser = new Parser(options); 2047 return parser.parseInline(tokens); 2048 } 2049 2050 /** 2051 * Parse Loop 2052 */ 2053 parse(tokens, top = true) { 2054 let out = '', 2055 i, 2056 j, 2057 k, 2058 l2, 2059 l3, 2060 row, 2061 cell, 2062 header, 2063 body, 2064 token, 2065 ordered, 2066 start, 2067 loose, 2068 itemBody, 2069 item, 2070 checked, 2071 task, 2072 checkbox; 2073 2074 const l = tokens.length; 2075 for (i = 0; i < l; i++) { 2076 token = tokens[i]; 2077 switch (token.type) { 2078 case 'space': { 2079 continue; 2080 } 2081 case 'hr': { 2082 out += this.renderer.hr(); 2083 continue; 2084 } 2085 case 'heading': { 2086 out += this.renderer.heading( 2087 this.parseInline(token.tokens), 2088 token.depth, 2089 unescape$1(this.parseInline(token.tokens, this.textRenderer)), 2090 this.slugger); 2091 continue; 2092 } 2093 case 'code': { 2094 out += this.renderer.code(token.text, 2095 token.lang, 2096 token.escaped); 2097 continue; 2098 } 2099 case 'table': { 2100 header = ''; 2101 2102 // header 2103 cell = ''; 2104 l2 = token.header.length; 2105 for (j = 0; j < l2; j++) { 2106 cell += this.renderer.tablecell( 2107 this.parseInline(token.tokens.header[j]), 2108 { header: true, align: token.align[j] } 2109 ); 2110 } 2111 header += this.renderer.tablerow(cell); 2112 2113 body = ''; 2114 l2 = token.cells.length; 2115 for (j = 0; j < l2; j++) { 2116 row = token.tokens.cells[j]; 2117 2118 cell = ''; 2119 l3 = row.length; 2120 for (k = 0; k < l3; k++) { 2121 cell += this.renderer.tablecell( 2122 this.parseInline(row[k]), 2123 { header: false, align: token.align[k] } 2124 ); 2125 } 2126 2127 body += this.renderer.tablerow(cell); 2128 } 2129 out += this.renderer.table(header, body); 2130 continue; 2131 } 2132 case 'blockquote': { 2133 body = this.parse(token.tokens); 2134 out += this.renderer.blockquote(body); 2135 continue; 2136 } 2137 case 'list': { 2138 ordered = token.ordered; 2139 start = token.start; 2140 loose = token.loose; 2141 l2 = token.items.length; 2142 2143 body = ''; 2144 for (j = 0; j < l2; j++) { 2145 item = token.items[j]; 2146 checked = item.checked; 2147 task = item.task; 2148 2149 itemBody = ''; 2150 if (item.task) { 2151 checkbox = this.renderer.checkbox(checked); 2152 if (loose) { 2153 if (item.tokens.length > 0 && item.tokens[0].type === 'text') { 2154 item.tokens[0].text = checkbox + ' ' + item.tokens[0].text; 2155 if (item.tokens[0].tokens && item.tokens[0].tokens.length > 0 && item.tokens[0].tokens[0].type === 'text') { 2156 item.tokens[0].tokens[0].text = checkbox + ' ' + item.tokens[0].tokens[0].text; 2157 } 2158 } else { 2159 item.tokens.unshift({ 2160 type: 'text', 2161 text: checkbox 2162 }); 2163 } 2164 } else { 2165 itemBody += checkbox; 2166 } 2167 } 2168 2169 itemBody += this.parse(item.tokens, loose); 2170 body += this.renderer.listitem(itemBody, task, checked); 2171 } 2172 2173 out += this.renderer.list(body, ordered, start); 2174 continue; 2175 } 2176 case 'html': { 2177 // TODO parse inline content if parameter markdown=1 2178 out += this.renderer.html(token.text); 2179 continue; 2180 } 2181 case 'paragraph': { 2182 out += this.renderer.paragraph(this.parseInline(token.tokens)); 2183 continue; 2184 } 2185 case 'text': { 2186 body = token.tokens ? this.parseInline(token.tokens) : token.text; 2187 while (i + 1 < l && tokens[i + 1].type === 'text') { 2188 token = tokens[++i]; 2189 body += '\n' + (token.tokens ? this.parseInline(token.tokens) : token.text); 2190 } 2191 out += top ? this.renderer.paragraph(body) : body; 2192 continue; 2193 } 2194 default: { 2195 const errMsg = 'Token with "' + token.type + '" type was not found.'; 2196 if (this.options.silent) { 2197 console.error(errMsg); 2198 return; 2199 } else { 2200 throw new Error(errMsg); 2201 } 2202 } 2203 } 2204 } 2205 2206 return out; 2207 } 2208 2209 /** 2210 * Parse Inline Tokens 2211 */ 2212 parseInline(tokens, renderer) { 2213 renderer = renderer || this.renderer; 2214 let out = '', 2215 i, 2216 token; 2217 2218 const l = tokens.length; 2219 for (i = 0; i < l; i++) { 2220 token = tokens[i]; 2221 switch (token.type) { 2222 case 'escape': { 2223 out += renderer.text(token.text); 2224 break; 2225 } 2226 case 'html': { 2227 out += renderer.html(token.text); 2228 break; 2229 } 2230 case 'link': { 2231 out += renderer.link(token.href, token.title, this.parseInline(token.tokens, renderer)); 2232 break; 2233 } 2234 case 'image': { 2235 out += renderer.image(token.href, token.title, token.text); 2236 break; 2237 } 2238 case 'strong': { 2239 out += renderer.strong(this.parseInline(token.tokens, renderer)); 2240 break; 2241 } 2242 case 'em': { 2243 out += renderer.em(this.parseInline(token.tokens, renderer)); 2244 break; 2245 } 2246 case 'codespan': { 2247 out += renderer.codespan(token.text); 2248 break; 2249 } 2250 case 'br': { 2251 out += renderer.br(); 2252 break; 2253 } 2254 case 'del': { 2255 out += renderer.del(this.parseInline(token.tokens, renderer)); 2256 break; 2257 } 2258 case 'text': { 2259 out += renderer.text(token.text); 2260 break; 2261 } 2262 default: { 2263 const errMsg = 'Token with "' + token.type + '" type was not found.'; 2264 if (this.options.silent) { 2265 console.error(errMsg); 2266 return; 2267 } else { 2268 throw new Error(errMsg); 2269 } 2270 } 2271 } 2272 } 2273 return out; 2274 } 2275 }; 2276 2277 const { 2278 merge: merge$2, 2279 checkSanitizeDeprecation: checkSanitizeDeprecation$1, 2280 escape: escape$3 2281 } = helpers; 2282 const { 2283 getDefaults, 2284 changeDefaults, 2285 defaults: defaults$5 2286 } = defaults; 2287 2288 /** 2289 * Marked 2290 */ 2291 function marked(src, opt, callback) { 2292 // throw error in case of non string input 2293 if (typeof src === 'undefined' || src === null) { 2294 throw new Error('marked(): input parameter is undefined or null'); 2295 } 2296 if (typeof src !== 'string') { 2297 throw new Error('marked(): input parameter is of type ' 2298 + Object.prototype.toString.call(src) + ', string expected'); 2299 } 2300 2301 if (typeof opt === 'function') { 2302 callback = opt; 2303 opt = null; 2304 } 2305 2306 opt = merge$2({}, marked.defaults, opt || {}); 2307 checkSanitizeDeprecation$1(opt); 2308 2309 if (callback) { 2310 const highlight = opt.highlight; 2311 let tokens; 2312 2313 try { 2314 tokens = Lexer_1.lex(src, opt); 2315 } catch (e) { 2316 return callback(e); 2317 } 2318 2319 const done = function(err) { 2320 let out; 2321 2322 if (!err) { 2323 try { 2324 out = Parser_1.parse(tokens, opt); 2325 } catch (e) { 2326 err = e; 2327 } 2328 } 2329 2330 opt.highlight = highlight; 2331 2332 return err 2333 ? callback(err) 2334 : callback(null, out); 2335 }; 2336 2337 if (!highlight || highlight.length < 3) { 2338 return done(); 2339 } 2340 2341 delete opt.highlight; 2342 2343 if (!tokens.length) return done(); 2344 2345 let pending = 0; 2346 marked.walkTokens(tokens, function(token) { 2347 if (token.type === 'code') { 2348 pending++; 2349 setTimeout(() => { 2350 highlight(token.text, token.lang, function(err, code) { 2351 if (err) { 2352 return done(err); 2353 } 2354 if (code != null && code !== token.text) { 2355 token.text = code; 2356 token.escaped = true; 2357 } 2358 2359 pending--; 2360 if (pending === 0) { 2361 done(); 2362 } 2363 }); 2364 }, 0); 2365 } 2366 }); 2367 2368 if (pending === 0) { 2369 done(); 2370 } 2371 2372 return; 2373 } 2374 2375 try { 2376 const tokens = Lexer_1.lex(src, opt); 2377 if (opt.walkTokens) { 2378 marked.walkTokens(tokens, opt.walkTokens); 2379 } 2380 return Parser_1.parse(tokens, opt); 2381 } catch (e) { 2382 e.message += '\nPlease report this to https://github.com/markedjs/marked.'; 2383 if (opt.silent) { 2384 return '<p>An error occurred:</p><pre>' 2385 + escape$3(e.message + '', true) 2386 + '</pre>'; 2387 } 2388 throw e; 2389 } 2390 } 2391 2392 /** 2393 * Options 2394 */ 2395 2396 marked.options = 2397 marked.setOptions = function(opt) { 2398 merge$2(marked.defaults, opt); 2399 changeDefaults(marked.defaults); 2400 return marked; 2401 }; 2402 2403 marked.getDefaults = getDefaults; 2404 2405 marked.defaults = defaults$5; 2406 2407 /** 2408 * Use Extension 2409 */ 2410 2411 marked.use = function(extension) { 2412 const opts = merge$2({}, extension); 2413 if (extension.renderer) { 2414 const renderer = marked.defaults.renderer || new Renderer_1(); 2415 for (const prop in extension.renderer) { 2416 const prevRenderer = renderer[prop]; 2417 renderer[prop] = (...args) => { 2418 let ret = extension.renderer[prop].apply(renderer, args); 2419 if (ret === false) { 2420 ret = prevRenderer.apply(renderer, args); 2421 } 2422 return ret; 2423 }; 2424 } 2425 opts.renderer = renderer; 2426 } 2427 if (extension.tokenizer) { 2428 const tokenizer = marked.defaults.tokenizer || new Tokenizer_1(); 2429 for (const prop in extension.tokenizer) { 2430 const prevTokenizer = tokenizer[prop]; 2431 tokenizer[prop] = (...args) => { 2432 let ret = extension.tokenizer[prop].apply(tokenizer, args); 2433 if (ret === false) { 2434 ret = prevTokenizer.apply(tokenizer, args); 2435 } 2436 return ret; 2437 }; 2438 } 2439 opts.tokenizer = tokenizer; 2440 } 2441 if (extension.walkTokens) { 2442 const walkTokens = marked.defaults.walkTokens; 2443 opts.walkTokens = (token) => { 2444 extension.walkTokens(token); 2445 if (walkTokens) { 2446 walkTokens(token); 2447 } 2448 }; 2449 } 2450 marked.setOptions(opts); 2451 }; 2452 2453 /** 2454 * Run callback for every token 2455 */ 2456 2457 marked.walkTokens = function(tokens, callback) { 2458 for (const token of tokens) { 2459 callback(token); 2460 switch (token.type) { 2461 case 'table': { 2462 for (const cell of token.tokens.header) { 2463 marked.walkTokens(cell, callback); 2464 } 2465 for (const row of token.tokens.cells) { 2466 for (const cell of row) { 2467 marked.walkTokens(cell, callback); 2468 } 2469 } 2470 break; 2471 } 2472 case 'list': { 2473 marked.walkTokens(token.items, callback); 2474 break; 2475 } 2476 default: { 2477 if (token.tokens) { 2478 marked.walkTokens(token.tokens, callback); 2479 } 2480 } 2481 } 2482 } 2483 }; 2484 2485 /** 2486 * Parse Inline 2487 */ 2488 marked.parseInline = function(src, opt) { 2489 // throw error in case of non string input 2490 if (typeof src === 'undefined' || src === null) { 2491 throw new Error('marked.parseInline(): input parameter is undefined or null'); 2492 } 2493 if (typeof src !== 'string') { 2494 throw new Error('marked.parseInline(): input parameter is of type ' 2495 + Object.prototype.toString.call(src) + ', string expected'); 2496 } 2497 2498 opt = merge$2({}, marked.defaults, opt || {}); 2499 checkSanitizeDeprecation$1(opt); 2500 2501 try { 2502 const tokens = Lexer_1.lexInline(src, opt); 2503 if (opt.walkTokens) { 2504 marked.walkTokens(tokens, opt.walkTokens); 2505 } 2506 return Parser_1.parseInline(tokens, opt); 2507 } catch (e) { 2508 e.message += '\nPlease report this to https://github.com/markedjs/marked.'; 2509 if (opt.silent) { 2510 return '<p>An error occurred:</p><pre>' 2511 + escape$3(e.message + '', true) 2512 + '</pre>'; 2513 } 2514 throw e; 2515 } 2516 }; 2517 2518 /** 2519 * Expose 2520 */ 2521 2522 marked.Parser = Parser_1; 2523 marked.parser = Parser_1.parse; 2524 2525 marked.Renderer = Renderer_1; 2526 marked.TextRenderer = TextRenderer_1; 2527 2528 marked.Lexer = Lexer_1; 2529 marked.lexer = Lexer_1.lex; 2530 2531 marked.Tokenizer = Tokenizer_1; 2532 2533 marked.Slugger = Slugger_1; 2534 2535 marked.parse = marked; 2536 2537 var marked_1 = marked; 2538 2539 export default marked_1;