1;/*! showdown v 2.1.0 - 21-04-2022 */ 2(function(){
vendor: 82,686 bytes, lines 2-2787
2 3/** 4 * Created by Tivie on 13-07-2015. 5 */ 6 7function getDefaultOpts (simple) { 8 'use strict'; 9 10 var defaultOptions = { 11 omitExtraWLInCodeBlocks: { 12 defaultValue: false, 13 describe: 'Omit the default extra whiteline added to code blocks', 14 type: 'boolean' 15 }, 16 noHeaderId: { 17 defaultValue: false, 18 describe: 'Turn on/off generated header id', 19 type: 'boolean' 20 }, 21 prefixHeaderId: { 22 defaultValue: false, 23 describe: 'Add a prefix to the generated header ids. Passing a string will prefix that string to the header id. Setting to true will add a generic \'section-\' prefix', 24 type: 'string' 25 }, 26 rawPrefixHeaderId: { 27 defaultValue: false, 28 describe: 'Setting this option to true will prevent showdown from modifying the prefix. This might result in malformed IDs (if, for instance, the " char is used in the prefix)', 29 type: 'boolean' 30 }, 31 ghCompatibleHeaderId: { 32 defaultValue: false, 33 describe: 'Generate header ids compatible with github style (spaces are replaced with dashes, a bunch of non alphanumeric chars are removed)', 34 type: 'boolean' 35 }, 36 rawHeaderId: { 37 defaultValue: false, 38 describe: 'Remove only spaces, \' and " from generated header ids (including prefixes), replacing them with dashes (-). WARNING: This might result in malformed ids', 39 type: 'boolean' 40 }, 41 headerLevelStart: { 42 defaultValue: false, 43 describe: 'The header blocks level start', 44 type: 'integer' 45 }, 46 parseImgDimensions: { 47 defaultValue: false, 48 describe: 'Turn on/off image dimension parsing', 49 type: 'boolean' 50 }, 51 simplifiedAutoLink: { 52 defaultValue: false, 53 describe: 'Turn on/off GFM autolink style', 54 type: 'boolean' 55 }, 56 excludeTrailingPunctuationFromURLs: { 57 defaultValue: false, 58 describe: 'Excludes trailing punctuation from links generated with autoLinking', 59 type: 'boolean' 60 }, 61 literalMidWordUnderscores: { 62 defaultValue: false, 63 describe: 'Parse midword underscores as literal underscores', 64 type: 'boolean' 65 }, 66 literalMidWordAsterisks: { 67 defaultValue: false, 68 describe: 'Parse midword asterisks as literal asterisks', 69 type: 'boolean' 70 }, 71 strikethrough: { 72 defaultValue: false, 73 describe: 'Turn on/off strikethrough support', 74 type: 'boolean' 75 }, 76 tables: { 77 defaultValue: false, 78 describe: 'Turn on/off tables support', 79 type: 'boolean' 80 }, 81 tablesHeaderId: { 82 defaultValue: false, 83 describe: 'Add an id to table headers', 84 type: 'boolean' 85 }, 86 ghCodeBlocks: { 87 defaultValue: true, 88 describe: 'Turn on/off GFM fenced code blocks support', 89 type: 'boolean' 90 }, 91 tasklists: { 92 defaultValue: false, 93 describe: 'Turn on/off GFM tasklist support', 94 type: 'boolean' 95 }, 96 smoothLivePreview: { 97 defaultValue: false, 98 describe: 'Prevents weird effects in live previews due to incomplete input', 99 type: 'boolean' 100 }, 101 smartIndentationFix: { 102 defaultValue: false, 103 describe: 'Tries to smartly fix indentation in es6 strings', 104 type: 'boolean' 105 }, 106 disableForced4SpacesIndentedSublists: { 107 defaultValue: false, 108 describe: 'Disables the requirement of indenting nested sublists by 4 spaces', 109 type: 'boolean' 110 }, 111 simpleLineBreaks: { 112 defaultValue: false, 113 describe: 'Parses simple line breaks as <br> (GFM Style)', 114 type: 'boolean' 115 }, 116 requireSpaceBeforeHeadingText: { 117 defaultValue: false, 118 describe: 'Makes adding a space between `#` and the header text mandatory (GFM Style)', 119 type: 'boolean' 120 }, 121 ghMentions: { 122 defaultValue: false, 123 describe: 'Enables github @mentions', 124 type: 'boolean' 125 }, 126 ghMentionsLink: { 127 defaultValue: 'https://github.com/{u}', 128 describe: 'Changes the link generated by @mentions. Only applies if ghMentions option is enabled.', 129 type: 'string' 130 }, 131 encodeEmails: { 132 defaultValue: true, 133 describe: 'Encode e-mail addresses through the use of Character Entities, transforming ASCII e-mail addresses into its equivalent decimal entities', 134 type: 'boolean' 135 }, 136 openLinksInNewWindow: { 137 defaultValue: false, 138 describe: 'Open all links in new windows', 139 type: 'boolean' 140 }, 141 backslashEscapesHTMLTags: { 142 defaultValue: false, 143 describe: 'Support for HTML Tag escaping. ex: \<div>foo\</div>', 144 type: 'boolean' 145 }, 146 emoji: { 147 defaultValue: false, 148 describe: 'Enable emoji support. Ex: `this is a :smile: emoji`', 149 type: 'boolean' 150 }, 151 underline: { 152 defaultValue: false, 153 describe: 'Enable support for underline. Syntax is double or triple underscores: `__underline word__`. With this option enabled, underscores no longer parses into `<em>` and `<strong>`', 154 type: 'boolean' 155 }, 156 ellipsis: { 157 defaultValue: true, 158 describe: 'Replaces three dots with the ellipsis unicode character', 159 type: 'boolean' 160 }, 161 completeHTMLDocument: { 162 defaultValue: false, 163 describe: 'Outputs a complete html document, including `<html>`, `<head>` and `<body>` tags', 164 type: 'boolean' 165 }, 166 metadata: { 167 defaultValue: false, 168 describe: 'Enable support for document metadata (defined at the top of the document between `«««` and `»»»` or between `---` and `---`).', 169 type: 'boolean' 170 }, 171 splitAdjacentBlockquotes: { 172 defaultValue: false, 173 describe: 'Split adjacent blockquote blocks', 174 type: 'boolean' 175 } 176 }; 177 if (simple === false) { 178 return JSON.parse(JSON.stringify(defaultOptions)); 179 } 180 var ret = {}; 181 for (var opt in defaultOptions) { 182 if (defaultOptions.hasOwnProperty(opt)) { 183 ret[opt] = defaultOptions[opt].defaultValue; 184 } 185 } 186 return ret; 187} 188 189function allOptionsOn () { 190 'use strict'; 191 var options = getDefaultOpts(true), 192 ret = {}; 193 for (var opt in options) { 194 if (options.hasOwnProperty(opt)) { 195 ret[opt] = true; 196 } 197 } 198 return ret; 199} 200 201/** 202 * Created by Tivie on 06-01-2015. 203 */ 204 205// Private properties 206var showdown = {}, 207 parsers = {}, 208 extensions = {}, 209 globalOptions = getDefaultOpts(true), 210 setFlavor = 'vanilla', 211 flavor = { 212 github: { 213 omitExtraWLInCodeBlocks: true, 214 simplifiedAutoLink: true, 215 excludeTrailingPunctuationFromURLs: true, 216 literalMidWordUnderscores: true, 217 strikethrough: true, 218 tables: true, 219 tablesHeaderId: true, 220 ghCodeBlocks: true, 221 tasklists: true, 222 disableForced4SpacesIndentedSublists: true, 223 simpleLineBreaks: true, 224 requireSpaceBeforeHeadingText: true, 225 ghCompatibleHeaderId: true, 226 ghMentions: true, 227 backslashEscapesHTMLTags: true, 228 emoji: true, 229 splitAdjacentBlockquotes: true 230 }, 231 original: { 232 noHeaderId: true, 233 ghCodeBlocks: false 234 }, 235 ghost: { 236 omitExtraWLInCodeBlocks: true, 237 parseImgDimensions: true, 238 simplifiedAutoLink: true, 239 excludeTrailingPunctuationFromURLs: true, 240 literalMidWordUnderscores: true, 241 strikethrough: true, 242 tables: true, 243 tablesHeaderId: true, 244 ghCodeBlocks: true, 245 tasklists: true, 246 smoothLivePreview: true, 247 simpleLineBreaks: true, 248 requireSpaceBeforeHeadingText: true, 249 ghMentions: false, 250 encodeEmails: true 251 }, 252 vanilla: getDefaultOpts(true), 253 allOn: allOptionsOn() 254 }; 255 256/** 257 * helper namespace 258 * @type {{}} 259 */ 260showdown.helper = {}; 261 262/** 263 * TODO LEGACY SUPPORT CODE 264 * @type {{}} 265 */ 266showdown.extensions = {}; 267 268/** 269 * Set a global option 270 * @static 271 * @param {string} key 272 * @param {*} value 273 * @returns {showdown} 274 */ 275showdown.setOption = function (key, value) { 276 'use strict'; 277 globalOptions[key] = value; 278 return this; 279}; 280 281/** 282 * Get a global option 283 * @static 284 * @param {string} key 285 * @returns {*} 286 */ 287showdown.getOption = function (key) { 288 'use strict'; 289 return globalOptions[key]; 290}; 291 292/** 293 * Get the global options 294 * @static 295 * @returns {{}} 296 */ 297showdown.getOptions = function () { 298 'use strict'; 299 return globalOptions; 300}; 301 302/** 303 * Reset global options to the default values 304 * @static 305 */ 306showdown.resetOptions = function () { 307 'use strict'; 308 globalOptions = getDefaultOpts(true); 309}; 310 311/** 312 * Set the flavor showdown should use as default 313 * @param {string} name 314 */ 315showdown.setFlavor = function (name) { 316 'use strict'; 317 if (!flavor.hasOwnProperty(name)) { 318 throw Error(name + ' flavor was not found'); 319 } 320 showdown.resetOptions(); 321 var preset = flavor[name]; 322 setFlavor = name; 323 for (var option in preset) { 324 if (preset.hasOwnProperty(option)) { 325 globalOptions[option] = preset[option]; 326 } 327 } 328}; 329 330/** 331 * Get the currently set flavor 332 * @returns {string} 333 */ 334showdown.getFlavor = function () { 335 'use strict'; 336 return setFlavor; 337}; 338 339/** 340 * Get the options of a specified flavor. Returns undefined if the flavor was not found 341 * @param {string} name Name of the flavor 342 * @returns {{}|undefined} 343 */ 344showdown.getFlavorOptions = function (name) { 345 'use strict'; 346 if (flavor.hasOwnProperty(name)) { 347 return flavor[name]; 348 } 349}; 350 351/** 352 * Get the default options 353 * @static 354 * @param {boolean} [simple=true] 355 * @returns {{}} 356 */ 357showdown.getDefaultOptions = function (simple) { 358 'use strict'; 359 return getDefaultOpts(simple); 360}; 361 362/** 363 * Get or set a subParser 364 * 365 * subParser(name) - Get a registered subParser 366 * subParser(name, func) - Register a subParser 367 * @static 368 * @param {string} name 369 * @param {function} [func] 370 * @returns {*} 371 */ 372showdown.subParser = function (name, func) { 373 'use strict'; 374 if (showdown.helper.isString(name)) { 375 if (typeof func !== 'undefined') { 376 parsers[name] = func; 377 } else { 378 if (parsers.hasOwnProperty(name)) { 379 return parsers[name]; 380 } else { 381 throw Error('SubParser named ' + name + ' not registered!'); 382 } 383 } 384 } 385}; 386 387/** 388 * Gets or registers an extension 389 * @static 390 * @param {string} name 391 * @param {object|object[]|function=} ext 392 * @returns {*} 393 */ 394showdown.extension = function (name, ext) { 395 'use strict'; 396 397 if (!showdown.helper.isString(name)) { 398 throw Error('Extension \'name\' must be a string'); 399 } 400 401 name = showdown.helper.stdExtName(name); 402 403 // Getter 404 if (showdown.helper.isUndefined(ext)) { 405 if (!extensions.hasOwnProperty(name)) { 406 throw Error('Extension named ' + name + ' is not registered!'); 407 } 408 return extensions[name]; 409 410 // Setter 411 } else { 412 // Expand extension if it's wrapped in a function 413 if (typeof ext === 'function') { 414 ext = ext(); 415 } 416 417 // Ensure extension is an array 418 if (!showdown.helper.isArray(ext)) { 419 ext = [ext]; 420 } 421 422 var validExtension = validate(ext, name); 423 424 if (validExtension.valid) { 425 extensions[name] = ext; 426 } else { 427 throw Error(validExtension.error); 428 } 429 } 430}; 431 432/** 433 * Gets all extensions registered 434 * @returns {{}} 435 */ 436showdown.getAllExtensions = function () { 437 'use strict'; 438 return extensions; 439}; 440 441/** 442 * Remove an extension 443 * @param {string} name 444 */ 445showdown.removeExtension = function (name) { 446 'use strict'; 447 delete extensions[name]; 448}; 449 450/** 451 * Removes all extensions 452 */ 453showdown.resetExtensions = function () { 454 'use strict'; 455 extensions = {}; 456}; 457 458/** 459 * Validate extension 460 * @param {array} extension 461 * @param {string} name 462 * @returns {{valid: boolean, error: string}} 463 */ 464function validate (extension, name) { 465 'use strict'; 466 467 var errMsg = (name) ? 'Error in ' + name + ' extension->' : 'Error in unnamed extension', 468 ret = { 469 valid: true, 470 error: '' 471 }; 472 473 if (!showdown.helper.isArray(extension)) { 474 extension = [extension]; 475 } 476 477 for (var i = 0; i < extension.length; ++i) { 478 var baseMsg = errMsg + ' sub-extension ' + i + ': ', 479 ext = extension[i]; 480 if (typeof ext !== 'object') { 481 ret.valid = false; 482 ret.error = baseMsg + 'must be an object, but ' + typeof ext + ' given'; 483 return ret; 484 } 485 486 if (!showdown.helper.isString(ext.type)) { 487 ret.valid = false; 488 ret.error = baseMsg + 'property "type" must be a string, but ' + typeof ext.type + ' given'; 489 return ret; 490 } 491 492 var type = ext.type = ext.type.toLowerCase(); 493 494 // normalize extension type 495 if (type === 'language') { 496 type = ext.type = 'lang'; 497 } 498 499 if (type === 'html') { 500 type = ext.type = 'output'; 501 } 502 503 if (type !== 'lang' && type !== 'output' && type !== 'listener') { 504 ret.valid = false; 505 ret.error = baseMsg + 'type ' + type + ' is not recognized. Valid values: "lang/language", "output/html" or "listener"'; 506 return ret; 507 } 508 509 if (type === 'listener') { 510 if (showdown.helper.isUndefined(ext.listeners)) { 511 ret.valid = false; 512 ret.error = baseMsg + '. Extensions of type "listener" must have a property called "listeners"'; 513 return ret; 514 } 515 } else { 516 if (showdown.helper.isUndefined(ext.filter) && showdown.helper.isUndefined(ext.regex)) { 517 ret.valid = false; 518 ret.error = baseMsg + type + ' extensions must define either a "regex" property or a "filter" method'; 519 return ret; 520 } 521 } 522 523 if (ext.listeners) { 524 if (typeof ext.listeners !== 'object') { 525 ret.valid = false; 526 ret.error = baseMsg + '"listeners" property must be an object but ' + typeof ext.listeners + ' given'; 527 return ret; 528 } 529 for (var ln in ext.listeners) { 530 if (ext.listeners.hasOwnProperty(ln)) { 531 if (typeof ext.listeners[ln] !== 'function') { 532 ret.valid = false; 533 ret.error = baseMsg + '"listeners" property must be an hash of [event name]: [callback]. listeners.' + ln + 534 ' must be a function but ' + typeof ext.listeners[ln] + ' given'; 535 return ret; 536 } 537 } 538 } 539 } 540 541 if (ext.filter) { 542 if (typeof ext.filter !== 'function') { 543 ret.valid = false; 544 ret.error = baseMsg + '"filter" must be a function, but ' + typeof ext.filter + ' given'; 545 return ret; 546 } 547 } else if (ext.regex) { 548 if (showdown.helper.isString(ext.regex)) { 549 ext.regex = new RegExp(ext.regex, 'g'); 550 } 551 if (!(ext.regex instanceof RegExp)) { 552 ret.valid = false; 553 ret.error = baseMsg + '"regex" property must either be a string or a RegExp object, but ' + typeof ext.regex + ' given'; 554 return ret; 555 } 556 if (showdown.helper.isUndefined(ext.replace)) { 557 ret.valid = false; 558 ret.error = baseMsg + '"regex" extensions must implement a replace string or function'; 559 return ret; 560 } 561 } 562 } 563 return ret; 564} 565 566/** 567 * Validate extension 568 * @param {object} ext 569 * @returns {boolean} 570 */ 571showdown.validateExtension = function (ext) { 572 'use strict'; 573 574 var validateExtension = validate(ext, null); 575 if (!validateExtension.valid) { 576 console.warn(validateExtension.error); 577 return false; 578 } 579 return true; 580}; 581 582/** 583 * showdownjs helper functions 584 */ 585 586if (!showdown.hasOwnProperty('helper')) { 587 showdown.helper = {}; 588} 589 590/** 591 * Check if var is string 592 * @static 593 * @param {string} a 594 * @returns {boolean} 595 */ 596showdown.helper.isString = function (a) { 597 'use strict'; 598 return (typeof a === 'string' || a instanceof String); 599}; 600 601/** 602 * Check if var is a function 603 * @static 604 * @param {*} a 605 * @returns {boolean} 606 */ 607showdown.helper.isFunction = function (a) { 608 'use strict'; 609 var getType = {}; 610 return a && getType.toString.call(a) === '[object Function]'; 611}; 612 613/** 614 * isArray helper function 615 * @static 616 * @param {*} a 617 * @returns {boolean} 618 */ 619showdown.helper.isArray = function (a) { 620 'use strict'; 621 return Array.isArray(a); 622}; 623 624/** 625 * Check if value is undefined 626 * @static 627 * @param {*} value The value to check. 628 * @returns {boolean} Returns `true` if `value` is `undefined`, else `false`. 629 */ 630showdown.helper.isUndefined = function (value) { 631 'use strict'; 632 return typeof value === 'undefined'; 633}; 634 635/** 636 * ForEach helper function 637 * Iterates over Arrays and Objects (own properties only) 638 * @static 639 * @param {*} obj 640 * @param {function} callback Accepts 3 params: 1. value, 2. key, 3. the original array/object 641 */ 642showdown.helper.forEach = function (obj, callback) { 643 'use strict'; 644 // check if obj is defined 645 if (showdown.helper.isUndefined(obj)) { 646 throw new Error('obj param is required'); 647 } 648 649 if (showdown.helper.isUndefined(callback)) { 650 throw new Error('callback param is required'); 651 } 652 653 if (!showdown.helper.isFunction(callback)) { 654 throw new Error('callback param must be a function/closure'); 655 } 656 657 if (typeof obj.forEach === 'function') { 658 obj.forEach(callback); 659 } else if (showdown.helper.isArray(obj)) { 660 for (var i = 0; i < obj.length; i++) { 661 callback(obj[i], i, obj); 662 } 663 } else if (typeof (obj) === 'object') { 664 for (var prop in obj) { 665 if (obj.hasOwnProperty(prop)) { 666 callback(obj[prop], prop, obj); 667 } 668 } 669 } else { 670 throw new Error('obj does not seem to be an array or an iterable object'); 671 } 672}; 673 674/** 675 * Standardidize extension name 676 * @static 677 * @param {string} s extension name 678 * @returns {string} 679 */ 680showdown.helper.stdExtName = function (s) { 681 'use strict'; 682 return s.replace(/[_?*+\/\\.^-]/g, '').replace(/\s/g, '').toLowerCase(); 683}; 684 685function escapeCharactersCallback (wholeMatch, m1) { 686 'use strict'; 687 var charCodeToEscape = m1.charCodeAt(0); 688 return '¨E' + charCodeToEscape + 'E'; 689} 690 691/** 692 * Callback used to escape characters when passing through String.replace 693 * @static 694 * @param {string} wholeMatch 695 * @param {string} m1 696 * @returns {string} 697 */ 698showdown.helper.escapeCharactersCallback = escapeCharactersCallback; 699 700/** 701 * Escape characters in a string 702 * @static 703 * @param {string} text 704 * @param {string} charsToEscape 705 * @param {boolean} afterBackslash 706 * @returns {XML|string|void|*} 707 */ 708showdown.helper.escapeCharacters = function (text, charsToEscape, afterBackslash) { 709 'use strict'; 710 // First we have to escape the escape characters so that 711 // we can build a character class out of them 712 var regexString = '([' + charsToEscape.replace(/([\[\]\\])/g, '\\$1') + '])'; 713 714 if (afterBackslash) { 715 regexString = '\\\\' + regexString; 716 } 717 718 var regex = new RegExp(regexString, 'g'); 719 text = text.replace(regex, escapeCharactersCallback); 720 721 return text; 722}; 723 724/** 725 * Unescape HTML entities 726 * @param txt 727 * @returns {string} 728 */ 729showdown.helper.unescapeHTMLEntities = function (txt) { 730 'use strict'; 731 732 return txt 733 .replace(/"/g, '"') 734 .replace(/</g, '<') 735 .replace(/>/g, '>') 736 .replace(/&/g, '&'); 737}; 738 739var rgxFindMatchPos = function (str, left, right, flags) { 740 'use strict'; 741 var f = flags || '', 742 g = f.indexOf('g') > -1, 743 x = new RegExp(left + '|' + right, 'g' + f.replace(/g/g, '')), 744 l = new RegExp(left, f.replace(/g/g, '')), 745 pos = [], 746 t, s, m, start, end; 747 748 do { 749 t = 0; 750 while ((m = x.exec(str))) { 751 if (l.test(m[0])) { 752 if (!(t++)) { 753 s = x.lastIndex; 754 start = s - m[0].length; 755 } 756 } else if (t) { 757 if (!--t) { 758 end = m.index + m[0].length; 759 var obj = { 760 left: {start: start, end: s}, 761 match: {start: s, end: m.index}, 762 right: {start: m.index, end: end}, 763 wholeMatch: {start: start, end: end} 764 }; 765 pos.push(obj); 766 if (!g) { 767 return pos; 768 } 769 } 770 } 771 } 772 } while (t && (x.lastIndex = s)); 773 774 return pos; 775}; 776 777/** 778 * matchRecursiveRegExp 779 * 780 * (c) 2007 Steven Levithan <stevenlevithan.com> 781 * MIT License 782 * 783 * Accepts a string to search, a left and right format delimiter 784 * as regex patterns, and optional regex flags. Returns an array 785 * of matches, allowing nested instances of left/right delimiters. 786 * Use the "g" flag to return all matches, otherwise only the 787 * first is returned. Be careful to ensure that the left and 788 * right format delimiters produce mutually exclusive matches. 789 * Backreferences are not supported within the right delimiter 790 * due to how it is internally combined with the left delimiter. 791 * When matching strings whose format delimiters are unbalanced 792 * to the left or right, the output is intentionally as a 793 * conventional regex library with recursion support would 794 * produce, e.g. "<<x>" and "<x>>" both produce ["x"] when using 795 * "<" and ">" as the delimiters (both strings contain a single, 796 * balanced instance of "<x>"). 797 * 798 * examples: 799 * matchRecursiveRegExp("test", "\\(", "\\)") 800 * returns: [] 801 * matchRecursiveRegExp("<t<<e>><s>>t<>", "<", ">", "g") 802 * returns: ["t<<e>><s>", ""] 803 * matchRecursiveRegExp("<div id=\"x\">test</div>", "<div\\b[^>]*>", "</div>", "gi") 804 * returns: ["test"] 805 */ 806showdown.helper.matchRecursiveRegExp = function (str, left, right, flags) { 807 'use strict'; 808 809 var matchPos = rgxFindMatchPos (str, left, right, flags), 810 results = []; 811 812 for (var i = 0; i < matchPos.length; ++i) { 813 results.push([ 814 str.slice(matchPos[i].wholeMatch.start, matchPos[i].wholeMatch.end), 815 str.slice(matchPos[i].match.start, matchPos[i].match.end), 816 str.slice(matchPos[i].left.start, matchPos[i].left.end), 817 str.slice(matchPos[i].right.start, matchPos[i].right.end) 818 ]); 819 } 820 return results; 821}; 822 823/** 824 * 825 * @param {string} str 826 * @param {string|function} replacement 827 * @param {string} left 828 * @param {string} right 829 * @param {string} flags 830 * @returns {string} 831 */ 832showdown.helper.replaceRecursiveRegExp = function (str, replacement, left, right, flags) { 833 'use strict'; 834 835 if (!showdown.helper.isFunction(replacement)) { 836 var repStr = replacement; 837 replacement = function () { 838 return repStr; 839 }; 840 } 841 842 var matchPos = rgxFindMatchPos(str, left, right, flags), 843 finalStr = str, 844 lng = matchPos.length; 845 846 if (lng > 0) { 847 var bits = []; 848 if (matchPos[0].wholeMatch.start !== 0) { 849 bits.push(str.slice(0, matchPos[0].wholeMatch.start)); 850 } 851 for (var i = 0; i < lng; ++i) { 852 bits.push( 853 replacement( 854 str.slice(matchPos[i].wholeMatch.start, matchPos[i].wholeMatch.end), 855 str.slice(matchPos[i].match.start, matchPos[i].match.end), 856 str.slice(matchPos[i].left.start, matchPos[i].left.end), 857 str.slice(matchPos[i].right.start, matchPos[i].right.end) 858 ) 859 ); 860 if (i < lng - 1) { 861 bits.push(str.slice(matchPos[i].wholeMatch.end, matchPos[i + 1].wholeMatch.start)); 862 } 863 } 864 if (matchPos[lng - 1].wholeMatch.end < str.length) { 865 bits.push(str.slice(matchPos[lng - 1].wholeMatch.end)); 866 } 867 finalStr = bits.join(''); 868 } 869 return finalStr; 870}; 871 872/** 873 * Returns the index within the passed String object of the first occurrence of the specified regex, 874 * starting the search at fromIndex. Returns -1 if the value is not found. 875 * 876 * @param {string} str string to search 877 * @param {RegExp} regex Regular expression to search 878 * @param {int} [fromIndex = 0] Index to start the search 879 * @returns {Number} 880 * @throws InvalidArgumentError 881 */ 882showdown.helper.regexIndexOf = function (str, regex, fromIndex) { 883 'use strict'; 884 if (!showdown.helper.isString(str)) { 885 throw 'InvalidArgumentError: first parameter of showdown.helper.regexIndexOf function must be a string'; 886 } 887 if (regex instanceof RegExp === false) { 888 throw 'InvalidArgumentError: second parameter of showdown.helper.regexIndexOf function must be an instance of RegExp'; 889 } 890 var indexOf = str.substring(fromIndex || 0).search(regex); 891 return (indexOf >= 0) ? (indexOf + (fromIndex || 0)) : indexOf; 892}; 893 894/** 895 * Splits the passed string object at the defined index, and returns an array composed of the two substrings 896 * @param {string} str string to split 897 * @param {int} index index to split string at 898 * @returns {[string,string]} 899 * @throws InvalidArgumentError 900 */ 901showdown.helper.splitAtIndex = function (str, index) { 902 'use strict'; 903 if (!showdown.helper.isString(str)) { 904 throw 'InvalidArgumentError: first parameter of showdown.helper.regexIndexOf function must be a string'; 905 } 906 return [str.substring(0, index), str.substring(index)]; 907}; 908 909/** 910 * Obfuscate an e-mail address through the use of Character Entities, 911 * transforming ASCII characters into their equivalent decimal or hex entities. 912 * 913 * Since it has a random component, subsequent calls to this function produce different results 914 * 915 * @param {string} mail 916 * @returns {string} 917 */ 918showdown.helper.encodeEmailAddress = function (mail) { 919 'use strict'; 920 var encode = [ 921 function (ch) { 922 return '&#' + ch.charCodeAt(0) + ';'; 923 }, 924 function (ch) { 925 return '&#x' + ch.charCodeAt(0).toString(16) + ';'; 926 }, 927 function (ch) { 928 return ch; 929 } 930 ]; 931 932 mail = mail.replace(/./g, function (ch) { 933 if (ch === '@') { 934 // this *must* be encoded. I insist. 935 ch = encode[Math.floor(Math.random() * 2)](ch); 936 } else { 937 var r = Math.random(); 938 // roughly 10% raw, 45% hex, 45% dec 939 ch = ( 940 r > 0.9 ? encode[2](ch) : r > 0.45 ? encode[1](ch) : encode[0](ch) 941 ); 942 } 943 return ch; 944 }); 945 946 return mail; 947}; 948 949/** 950 * 951 * @param str 952 * @param targetLength 953 * @param padString 954 * @returns {string} 955 */ 956showdown.helper.padEnd = function padEnd (str, targetLength, padString) { 957 'use strict'; 958 /*jshint bitwise: false*/ 959 // eslint-disable-next-line space-infix-ops 960 targetLength = targetLength>>0; //floor if number or convert non-number to 0; 961 /*jshint bitwise: true*/ 962 padString = String(padString || ' '); 963 if (str.length > targetLength) { 964 return String(str); 965 } else { 966 targetLength = targetLength - str.length; 967 if (targetLength > padString.length) { 968 padString += padString.repeat(targetLength / padString.length); //append to original to ensure we are longer than needed 969 } 970 return String(str) + padString.slice(0,targetLength); 971 } 972}; 973 974/** 975 * POLYFILLS 976 */ 977// use this instead of builtin is undefined for IE8 compatibility 978if (typeof (console) === 'undefined') { 979 console = { 980 warn: function (msg) { 981 'use strict'; 982 alert(msg); 983 }, 984 log: function (msg) { 985 'use strict'; 986 alert(msg); 987 }, 988 error: function (msg) { 989 'use strict'; 990 throw msg; 991 } 992 }; 993} 994 995/** 996 * Common regexes. 997 * We declare some common regexes to improve performance 998 */ 999showdown.helper.regexes = { 1000 asteriskDashAndColon: /([*_:~])/g 1001}; 1002 1003/** 1004 * EMOJIS LIST 1005 */ 1006showdown.helper.emojis = { 1007 '+1':'\ud83d\udc4d', 1008 '-1':'\ud83d\udc4e', 1009 '100':'\ud83d\udcaf', 1010 '1234':'\ud83d\udd22', 1011 '1st_place_medal':'\ud83e\udd47', 1012 '2nd_place_medal':'\ud83e\udd48', 1013 '3rd_place_medal':'\ud83e\udd49', 1014 '8ball':'\ud83c\udfb1', 1015 'a':'\ud83c\udd70\ufe0f', 1016 'ab':'\ud83c\udd8e', 1017 'abc':'\ud83d\udd24', 1018 'abcd':'\ud83d\udd21', 1019 'accept':'\ud83c\ude51', 1020 'aerial_tramway':'\ud83d\udea1', 1021 'airplane':'\u2708\ufe0f', 1022 'alarm_clock':'\u23f0', 1023 'alembic':'\u2697\ufe0f', 1024 'alien':'\ud83d\udc7d', 1025 'ambulance':'\ud83d\ude91', 1026 'amphora':'\ud83c\udffa', 1027 'anchor':'\u2693\ufe0f', 1028 'angel':'\ud83d\udc7c', 1029 'anger':'\ud83d\udca2', 1030 'angry':'\ud83d\ude20', 1031 'anguished':'\ud83d\ude27', 1032 'ant':'\ud83d\udc1c', 1033 'apple':'\ud83c\udf4e', 1034 'aquarius':'\u2652\ufe0f', 1035 'aries':'\u2648\ufe0f', 1036 'arrow_backward':'\u25c0\ufe0f', 1037 'arrow_double_down':'\u23ec', 1038 'arrow_double_up':'\u23eb', 1039 'arrow_down':'\u2b07\ufe0f', 1040 'arrow_down_small':'\ud83d\udd3d', 1041 'arrow_forward':'\u25b6\ufe0f', 1042 'arrow_heading_down':'\u2935\ufe0f', 1043 'arrow_heading_up':'\u2934\ufe0f', 1044 'arrow_left':'\u2b05\ufe0f', 1045 'arrow_lower_left':'\u2199\ufe0f', 1046 'arrow_lower_right':'\u2198\ufe0f', 1047 'arrow_right':'\u27a1\ufe0f', 1048 'arrow_right_hook':'\u21aa\ufe0f', 1049 'arrow_up':'\u2b06\ufe0f', 1050 'arrow_up_down':'\u2195\ufe0f', 1051 'arrow_up_small':'\ud83d\udd3c', 1052 'arrow_upper_left':'\u2196\ufe0f', 1053 'arrow_upper_right':'\u2197\ufe0f', 1054 'arrows_clockwise':'\ud83d\udd03', 1055 'arrows_counterclockwise':'\ud83d\udd04', 1056 'art':'\ud83c\udfa8', 1057 'articulated_lorry':'\ud83d\ude9b', 1058 'artificial_satellite':'\ud83d\udef0', 1059 'astonished':'\ud83d\ude32', 1060 'athletic_shoe':'\ud83d\udc5f', 1061 'atm':'\ud83c\udfe7', 1062 'atom_symbol':'\u269b\ufe0f', 1063 'avocado':'\ud83e\udd51', 1064 'b':'\ud83c\udd71\ufe0f', 1065 'baby':'\ud83d\udc76', 1066 'baby_bottle':'\ud83c\udf7c', 1067 'baby_chick':'\ud83d\udc24', 1068 'baby_symbol':'\ud83d\udebc', 1069 'back':'\ud83d\udd19', 1070 'bacon':'\ud83e\udd53', 1071 'badminton':'\ud83c\udff8', 1072 'baggage_claim':'\ud83d\udec4', 1073 'baguette_bread':'\ud83e\udd56', 1074 'balance_scale':'\u2696\ufe0f', 1075 'balloon':'\ud83c\udf88', 1076 'ballot_box':'\ud83d\uddf3', 1077 'ballot_box_with_check':'\u2611\ufe0f', 1078 'bamboo':'\ud83c\udf8d', 1079 'banana':'\ud83c\udf4c', 1080 'bangbang':'\u203c\ufe0f', 1081 'bank':'\ud83c\udfe6', 1082 'bar_chart':'\ud83d\udcca', 1083 'barber':'\ud83d\udc88', 1084 'baseball':'\u26be\ufe0f', 1085 'basketball':'\ud83c\udfc0', 1086 'basketball_man':'\u26f9\ufe0f', 1087 'basketball_woman':'\u26f9\ufe0f‍\u2640\ufe0f', 1088 'bat':'\ud83e\udd87', 1089 'bath':'\ud83d\udec0', 1090 'bathtub':'\ud83d\udec1', 1091 'battery':'\ud83d\udd0b', 1092 'beach_umbrella':'\ud83c\udfd6', 1093 'bear':'\ud83d\udc3b', 1094 'bed':'\ud83d\udecf', 1095 'bee':'\ud83d\udc1d', 1096 'beer':'\ud83c\udf7a', 1097 'beers':'\ud83c\udf7b', 1098 'beetle':'\ud83d\udc1e', 1099 'beginner':'\ud83d\udd30', 1100 'bell':'\ud83d\udd14', 1101 'bellhop_bell':'\ud83d\udece', 1102 'bento':'\ud83c\udf71', 1103 'biking_man':'\ud83d\udeb4', 1104 'bike':'\ud83d\udeb2', 1105 'biking_woman':'\ud83d\udeb4‍\u2640\ufe0f', 1106 'bikini':'\ud83d\udc59', 1107 'biohazard':'\u2623\ufe0f', 1108 'bird':'\ud83d\udc26', 1109 'birthday':'\ud83c\udf82', 1110 'black_circle':'\u26ab\ufe0f', 1111 'black_flag':'\ud83c\udff4', 1112 'black_heart':'\ud83d\udda4', 1113 'black_joker':'\ud83c\udccf', 1114 'black_large_square':'\u2b1b\ufe0f', 1115 'black_medium_small_square':'\u25fe\ufe0f', 1116 'black_medium_square':'\u25fc\ufe0f', 1117 'black_nib':'\u2712\ufe0f', 1118 'black_small_square':'\u25aa\ufe0f', 1119 'black_square_button':'\ud83d\udd32', 1120 'blonde_man':'\ud83d\udc71', 1121 'blonde_woman':'\ud83d\udc71‍\u2640\ufe0f', 1122 'blossom':'\ud83c\udf3c', 1123 'blowfish':'\ud83d\udc21', 1124 'blue_book':'\ud83d\udcd8', 1125 'blue_car':'\ud83d\ude99', 1126 'blue_heart':'\ud83d\udc99', 1127 'blush':'\ud83d\ude0a', 1128 'boar':'\ud83d\udc17', 1129 'boat':'\u26f5\ufe0f', 1130 'bomb':'\ud83d\udca3', 1131 'book':'\ud83d\udcd6', 1132 'bookmark':'\ud83d\udd16', 1133 'bookmark_tabs':'\ud83d\udcd1', 1134 'books':'\ud83d\udcda', 1135 'boom':'\ud83d\udca5', 1136 'boot':'\ud83d\udc62', 1137 'bouquet':'\ud83d\udc90', 1138 'bowing_man':'\ud83d\ude47', 1139 'bow_and_arrow':'\ud83c\udff9', 1140 'bowing_woman':'\ud83d\ude47‍\u2640\ufe0f', 1141 'bowling':'\ud83c\udfb3', 1142 'boxing_glove':'\ud83e\udd4a', 1143 'boy':'\ud83d\udc66', 1144 'bread':'\ud83c\udf5e', 1145 'bride_with_veil':'\ud83d\udc70', 1146 'bridge_at_night':'\ud83c\udf09', 1147 'briefcase':'\ud83d\udcbc', 1148 'broken_heart':'\ud83d\udc94', 1149 'bug':'\ud83d\udc1b', 1150 'building_construction':'\ud83c\udfd7', 1151 'bulb':'\ud83d\udca1', 1152 'bullettrain_front':'\ud83d\ude85', 1153 'bullettrain_side':'\ud83d\ude84', 1154 'burrito':'\ud83c\udf2f', 1155 'bus':'\ud83d\ude8c', 1156 'business_suit_levitating':'\ud83d\udd74', 1157 'busstop':'\ud83d\ude8f', 1158 'bust_in_silhouette':'\ud83d\udc64', 1159 'busts_in_silhouette':'\ud83d\udc65', 1160 'butterfly':'\ud83e\udd8b', 1161 'cactus':'\ud83c\udf35', 1162 'cake':'\ud83c\udf70', 1163 'calendar':'\ud83d\udcc6', 1164 'call_me_hand':'\ud83e\udd19', 1165 'calling':'\ud83d\udcf2', 1166 'camel':'\ud83d\udc2b', 1167 'camera':'\ud83d\udcf7', 1168 'camera_flash':'\ud83d\udcf8', 1169 'camping':'\ud83c\udfd5', 1170 'cancer':'\u264b\ufe0f', 1171 'candle':'\ud83d\udd6f', 1172 'candy':'\ud83c\udf6c', 1173 'canoe':'\ud83d\udef6', 1174 'capital_abcd':'\ud83d\udd20', 1175 'capricorn':'\u2651\ufe0f', 1176 'car':'\ud83d\ude97', 1177 'card_file_box':'\ud83d\uddc3', 1178 'card_index':'\ud83d\udcc7', 1179 'card_index_dividers':'\ud83d\uddc2', 1180 'carousel_horse':'\ud83c\udfa0', 1181 'carrot':'\ud83e\udd55', 1182 'cat':'\ud83d\udc31', 1183 'cat2':'\ud83d\udc08', 1184 'cd':'\ud83d\udcbf', 1185 'chains':'\u26d3', 1186 'champagne':'\ud83c\udf7e', 1187 'chart':'\ud83d\udcb9', 1188 'chart_with_downwards_trend':'\ud83d\udcc9', 1189 'chart_with_upwards_trend':'\ud83d\udcc8', 1190 'checkered_flag':'\ud83c\udfc1', 1191 'cheese':'\ud83e\uddc0', 1192 'cherries':'\ud83c\udf52', 1193 'cherry_blossom':'\ud83c\udf38', 1194 'chestnut':'\ud83c\udf30', 1195 'chicken':'\ud83d\udc14', 1196 'children_crossing':'\ud83d\udeb8', 1197 'chipmunk':'\ud83d\udc3f', 1198 'chocolate_bar':'\ud83c\udf6b', 1199 'christmas_tree':'\ud83c\udf84', 1200 'church':'\u26ea\ufe0f', 1201 'cinema':'\ud83c\udfa6', 1202 'circus_tent':'\ud83c\udfaa', 1203 'city_sunrise':'\ud83c\udf07', 1204 'city_sunset':'\ud83c\udf06', 1205 'cityscape':'\ud83c\udfd9', 1206 'cl':'\ud83c\udd91', 1207 'clamp':'\ud83d\udddc', 1208 'clap':'\ud83d\udc4f', 1209 'clapper':'\ud83c\udfac', 1210 'classical_building':'\ud83c\udfdb', 1211 'clinking_glasses':'\ud83e\udd42', 1212 'clipboard':'\ud83d\udccb', 1213 'clock1':'\ud83d\udd50', 1214 'clock10':'\ud83d\udd59', 1215 'clock1030':'\ud83d\udd65', 1216 'clock11':'\ud83d\udd5a', 1217 'clock1130':'\ud83d\udd66', 1218 'clock12':'\ud83d\udd5b', 1219 'clock1230':'\ud83d\udd67', 1220 'clock130':'\ud83d\udd5c', 1221 'clock2':'\ud83d\udd51', 1222 'clock230':'\ud83d\udd5d', 1223 'clock3':'\ud83d\udd52', 1224 'clock330':'\ud83d\udd5e', 1225 'clock4':'\ud83d\udd53', 1226 'clock430':'\ud83d\udd5f', 1227 'clock5':'\ud83d\udd54', 1228 'clock530':'\ud83d\udd60', 1229 'clock6':'\ud83d\udd55', 1230 'clock630':'\ud83d\udd61', 1231 'clock7':'\ud83d\udd56', 1232 'clock730':'\ud83d\udd62', 1233 'clock8':'\ud83d\udd57', 1234 'clock830':'\ud83d\udd63', 1235 'clock9':'\ud83d\udd58', 1236 'clock930':'\ud83d\udd64', 1237 'closed_book':'\ud83d\udcd5', 1238 'closed_lock_with_key':'\ud83d\udd10', 1239 'closed_umbrella':'\ud83c\udf02', 1240 'cloud':'\u2601\ufe0f', 1241 'cloud_with_lightning':'\ud83c\udf29', 1242 'cloud_with_lightning_and_rain':'\u26c8', 1243 'cloud_with_rain':'\ud83c\udf27', 1244 'cloud_with_snow':'\ud83c\udf28', 1245 'clown_face':'\ud83e\udd21', 1246 'clubs':'\u2663\ufe0f', 1247 'cocktail':'\ud83c\udf78', 1248 'coffee':'\u2615\ufe0f', 1249 'coffin':'\u26b0\ufe0f', 1250 'cold_sweat':'\ud83d\ude30', 1251 'comet':'\u2604\ufe0f', 1252 'computer':'\ud83d\udcbb', 1253 'computer_mouse':'\ud83d\uddb1', 1254 'confetti_ball':'\ud83c\udf8a', 1255 'confounded':'\ud83d\ude16', 1256 'confused':'\ud83d\ude15', 1257 'congratulations':'\u3297\ufe0f', 1258 'construction':'\ud83d\udea7', 1259 'construction_worker_man':'\ud83d\udc77', 1260 'construction_worker_woman':'\ud83d\udc77‍\u2640\ufe0f', 1261 'control_knobs':'\ud83c\udf9b', 1262 'convenience_store':'\ud83c\udfea', 1263 'cookie':'\ud83c\udf6a', 1264 'cool':'\ud83c\udd92', 1265 'policeman':'\ud83d\udc6e', 1266 'copyright':'\u00a9\ufe0f', 1267 'corn':'\ud83c\udf3d', 1268 'couch_and_lamp':'\ud83d\udecb', 1269 'couple':'\ud83d\udc6b', 1270 'couple_with_heart_woman_man':'\ud83d\udc91', 1271 'couple_with_heart_man_man':'\ud83d\udc68‍\u2764\ufe0f‍\ud83d\udc68', 1272 'couple_with_heart_woman_woman':'\ud83d\udc69‍\u2764\ufe0f‍\ud83d\udc69', 1273 'couplekiss_man_man':'\ud83d\udc68‍\u2764\ufe0f‍\ud83d\udc8b‍\ud83d\udc68', 1274 'couplekiss_man_woman':'\ud83d\udc8f', 1275 'couplekiss_woman_woman':'\ud83d\udc69‍\u2764\ufe0f‍\ud83d\udc8b‍\ud83d\udc69', 1276 'cow':'\ud83d\udc2e', 1277 'cow2':'\ud83d\udc04', 1278 'cowboy_hat_face':'\ud83e\udd20', 1279 'crab':'\ud83e\udd80', 1280 'crayon':'\ud83d\udd8d', 1281 'credit_card':'\ud83d\udcb3', 1282 'crescent_moon':'\ud83c\udf19', 1283 'cricket':'\ud83c\udfcf', 1284 'crocodile':'\ud83d\udc0a', 1285 'croissant':'\ud83e\udd50', 1286 'crossed_fingers':'\ud83e\udd1e', 1287 'crossed_flags':'\ud83c\udf8c', 1288 'crossed_swords':'\u2694\ufe0f', 1289 'crown':'\ud83d\udc51', 1290 'cry':'\ud83d\ude22', 1291 'crying_cat_face':'\ud83d\ude3f', 1292 'crystal_ball':'\ud83d\udd2e', 1293 'cucumber':'\ud83e\udd52', 1294 'cupid':'\ud83d\udc98', 1295 'curly_loop':'\u27b0', 1296 'currency_exchange':'\ud83d\udcb1', 1297 'curry':'\ud83c\udf5b', 1298 'custard':'\ud83c\udf6e', 1299 'customs':'\ud83d\udec3', 1300 'cyclone':'\ud83c\udf00', 1301 'dagger':'\ud83d\udde1', 1302 'dancer':'\ud83d\udc83', 1303 'dancing_women':'\ud83d\udc6f', 1304 'dancing_men':'\ud83d\udc6f‍\u2642\ufe0f', 1305 'dango':'\ud83c\udf61', 1306 'dark_sunglasses':'\ud83d\udd76', 1307 'dart':'\ud83c\udfaf', 1308 'dash':'\ud83d\udca8', 1309 'date':'\ud83d\udcc5', 1310 'deciduous_tree':'\ud83c\udf33', 1311 'deer':'\ud83e\udd8c', 1312 'department_store':'\ud83c\udfec', 1313 'derelict_house':'\ud83c\udfda', 1314 'desert':'\ud83c\udfdc', 1315 'desert_island':'\ud83c\udfdd', 1316 'desktop_computer':'\ud83d\udda5', 1317 'male_detective':'\ud83d\udd75\ufe0f', 1318 'diamond_shape_with_a_dot_inside':'\ud83d\udca0', 1319 'diamonds':'\u2666\ufe0f', 1320 'disappointed':'\ud83d\ude1e', 1321 'disappointed_relieved':'\ud83d\ude25', 1322 'dizzy':'\ud83d\udcab', 1323 'dizzy_face':'\ud83d\ude35', 1324 'do_not_litter':'\ud83d\udeaf', 1325 'dog':'\ud83d\udc36', 1326 'dog2':'\ud83d\udc15', 1327 'dollar':'\ud83d\udcb5', 1328 'dolls':'\ud83c\udf8e', 1329 'dolphin':'\ud83d\udc2c', 1330 'door':'\ud83d\udeaa', 1331 'doughnut':'\ud83c\udf69', 1332 'dove':'\ud83d\udd4a', 1333 'dragon':'\ud83d\udc09', 1334 'dragon_face':'\ud83d\udc32', 1335 'dress':'\ud83d\udc57', 1336 'dromedary_camel':'\ud83d\udc2a', 1337 'drooling_face':'\ud83e\udd24', 1338 'droplet':'\ud83d\udca7', 1339 'drum':'\ud83e\udd41', 1340 'duck':'\ud83e\udd86', 1341 'dvd':'\ud83d\udcc0', 1342 'e-mail':'\ud83d\udce7', 1343 'eagle':'\ud83e\udd85', 1344 'ear':'\ud83d\udc42', 1345 'ear_of_rice':'\ud83c\udf3e', 1346 'earth_africa':'\ud83c\udf0d', 1347 'earth_americas':'\ud83c\udf0e', 1348 'earth_asia':'\ud83c\udf0f', 1349 'egg':'\ud83e\udd5a', 1350 'eggplant':'\ud83c\udf46', 1351 'eight_pointed_black_star':'\u2734\ufe0f', 1352 'eight_spoked_asterisk':'\u2733\ufe0f', 1353 'electric_plug':'\ud83d\udd0c', 1354 'elephant':'\ud83d\udc18', 1355 'email':'\u2709\ufe0f', 1356 'end':'\ud83d\udd1a', 1357 'envelope_with_arrow':'\ud83d\udce9', 1358 'euro':'\ud83d\udcb6', 1359 'european_castle':'\ud83c\udff0', 1360 'european_post_office':'\ud83c\udfe4', 1361 'evergreen_tree':'\ud83c\udf32', 1362 'exclamation':'\u2757\ufe0f', 1363 'expressionless':'\ud83d\ude11', 1364 'eye':'\ud83d\udc41', 1365 'eye_speech_bubble':'\ud83d\udc41‍\ud83d\udde8', 1366 'eyeglasses':'\ud83d\udc53', 1367 'eyes':'\ud83d\udc40', 1368 'face_with_head_bandage':'\ud83e\udd15', 1369 'face_with_thermometer':'\ud83e\udd12', 1370 'fist_oncoming':'\ud83d\udc4a', 1371 'factory':'\ud83c\udfed', 1372 'fallen_leaf':'\ud83c\udf42', 1373 'family_man_woman_boy':'\ud83d\udc6a', 1374 'family_man_boy':'\ud83d\udc68‍\ud83d\udc66', 1375 'family_man_boy_boy':'\ud83d\udc68‍\ud83d\udc66‍\ud83d\udc66', 1376 'family_man_girl':'\ud83d\udc68‍\ud83d\udc67', 1377 'family_man_girl_boy':'\ud83d\udc68‍\ud83d\udc67‍\ud83d\udc66', 1378 'family_man_girl_girl':'\ud83d\udc68‍\ud83d\udc67‍\ud83d\udc67', 1379 'family_man_man_boy':'\ud83d\udc68‍\ud83d\udc68‍\ud83d\udc66', 1380 'family_man_man_boy_boy':'\ud83d\udc68‍\ud83d\udc68‍\ud83d\udc66‍\ud83d\udc66', 1381 'family_man_man_girl':'\ud83d\udc68‍\ud83d\udc68‍\ud83d\udc67', 1382 'family_man_man_girl_boy':'\ud83d\udc68‍\ud83d\udc68‍\ud83d\udc67‍\ud83d\udc66', 1383 'family_man_man_girl_girl':'\ud83d\udc68‍\ud83d\udc68‍\ud83d\udc67‍\ud83d\udc67', 1384 'family_man_woman_boy_boy':'\ud83d\udc68‍\ud83d\udc69‍\ud83d\udc66‍\ud83d\udc66', 1385 'family_man_woman_girl':'\ud83d\udc68‍\ud83d\udc69‍\ud83d\udc67', 1386 'family_man_woman_girl_boy':'\ud83d\udc68‍\ud83d\udc69‍\ud83d\udc67‍\ud83d\udc66', 1387 'family_man_woman_girl_girl':'\ud83d\udc68‍\ud83d\udc69‍\ud83d\udc67‍\ud83d\udc67', 1388 'family_woman_boy':'\ud83d\udc69‍\ud83d\udc66', 1389 'family_woman_boy_boy':'\ud83d\udc69‍\ud83d\udc66‍\ud83d\udc66', 1390 'family_woman_girl':'\ud83d\udc69‍\ud83d\udc67', 1391 'family_woman_girl_boy':'\ud83d\udc69‍\ud83d\udc67‍\ud83d\udc66', 1392 'family_woman_girl_girl':'\ud83d\udc69‍\ud83d\udc67‍\ud83d\udc67', 1393 'family_woman_woman_boy':'\ud83d\udc69‍\ud83d\udc69‍\ud83d\udc66', 1394 'family_woman_woman_boy_boy':'\ud83d\udc69‍\ud83d\udc69‍\ud83d\udc66‍\ud83d\udc66', 1395 'family_woman_woman_girl':'\ud83d\udc69‍\ud83d\udc69‍\ud83d\udc67', 1396 'family_woman_woman_girl_boy':'\ud83d\udc69‍\ud83d\udc69‍\ud83d\udc67‍\ud83d\udc66', 1397 'family_woman_woman_girl_girl':'\ud83d\udc69‍\ud83d\udc69‍\ud83d\udc67‍\ud83d\udc67', 1398 'fast_forward':'\u23e9', 1399 'fax':'\ud83d\udce0', 1400 'fearful':'\ud83d\ude28', 1401 'feet':'\ud83d\udc3e', 1402 'female_detective':'\ud83d\udd75\ufe0f‍\u2640\ufe0f', 1403 'ferris_wheel':'\ud83c\udfa1', 1404 'ferry':'\u26f4', 1405 'field_hockey':'\ud83c\udfd1', 1406 'file_cabinet':'\ud83d\uddc4', 1407 'file_folder':'\ud83d\udcc1', 1408 'film_projector':'\ud83d\udcfd', 1409 'film_strip':'\ud83c\udf9e', 1410 'fire':'\ud83d\udd25', 1411 'fire_engine':'\ud83d\ude92', 1412 'fireworks':'\ud83c\udf86', 1413 'first_quarter_moon':'\ud83c\udf13', 1414 'first_quarter_moon_with_face':'\ud83c\udf1b', 1415 'fish':'\ud83d\udc1f', 1416 'fish_cake':'\ud83c\udf65', 1417 'fishing_pole_and_fish':'\ud83c\udfa3', 1418 'fist_raised':'\u270a', 1419 'fist_left':'\ud83e\udd1b', 1420 'fist_right':'\ud83e\udd1c', 1421 'flags':'\ud83c\udf8f', 1422 'flashlight':'\ud83d\udd26', 1423 'fleur_de_lis':'\u269c\ufe0f', 1424 'flight_arrival':'\ud83d\udeec', 1425 'flight_departure':'\ud83d\udeeb', 1426 'floppy_disk':'\ud83d\udcbe', 1427 'flower_playing_cards':'\ud83c\udfb4', 1428 'flushed':'\ud83d\ude33', 1429 'fog':'\ud83c\udf2b', 1430 'foggy':'\ud83c\udf01', 1431 'football':'\ud83c\udfc8', 1432 'footprints':'\ud83d\udc63', 1433 'fork_and_knife':'\ud83c\udf74', 1434 'fountain':'\u26f2\ufe0f', 1435 'fountain_pen':'\ud83d\udd8b', 1436 'four_leaf_clover':'\ud83c\udf40', 1437 'fox_face':'\ud83e\udd8a', 1438 'framed_picture':'\ud83d\uddbc', 1439 'free':'\ud83c\udd93', 1440 'fried_egg':'\ud83c\udf73', 1441 'fried_shrimp':'\ud83c\udf64', 1442 'fries':'\ud83c\udf5f', 1443 'frog':'\ud83d\udc38', 1444 'frowning':'\ud83d\ude26', 1445 'frowning_face':'\u2639\ufe0f', 1446 'frowning_man':'\ud83d\ude4d‍\u2642\ufe0f', 1447 'frowning_woman':'\ud83d\ude4d', 1448 'middle_finger':'\ud83d\udd95', 1449 'fuelpump':'\u26fd\ufe0f', 1450 'full_moon':'\ud83c\udf15', 1451 'full_moon_with_face':'\ud83c\udf1d', 1452 'funeral_urn':'\u26b1\ufe0f', 1453 'game_die':'\ud83c\udfb2', 1454 'gear':'\u2699\ufe0f', 1455 'gem':'\ud83d\udc8e', 1456 'gemini':'\u264a\ufe0f', 1457 'ghost':'\ud83d\udc7b', 1458 'gift':'\ud83c\udf81', 1459 'gift_heart':'\ud83d\udc9d', 1460 'girl':'\ud83d\udc67', 1461 'globe_with_meridians':'\ud83c\udf10', 1462 'goal_net':'\ud83e\udd45', 1463 'goat':'\ud83d\udc10', 1464 'golf':'\u26f3\ufe0f', 1465 'golfing_man':'\ud83c\udfcc\ufe0f', 1466 'golfing_woman':'\ud83c\udfcc\ufe0f‍\u2640\ufe0f', 1467 'gorilla':'\ud83e\udd8d', 1468 'grapes':'\ud83c\udf47', 1469 'green_apple':'\ud83c\udf4f', 1470 'green_book':'\ud83d\udcd7', 1471 'green_heart':'\ud83d\udc9a', 1472 'green_salad':'\ud83e\udd57', 1473 'grey_exclamation':'\u2755', 1474 'grey_question':'\u2754', 1475 'grimacing':'\ud83d\ude2c', 1476 'grin':'\ud83d\ude01', 1477 'grinning':'\ud83d\ude00', 1478 'guardsman':'\ud83d\udc82', 1479 'guardswoman':'\ud83d\udc82‍\u2640\ufe0f', 1480 'guitar':'\ud83c\udfb8', 1481 'gun':'\ud83d\udd2b', 1482 'haircut_woman':'\ud83d\udc87', 1483 'haircut_man':'\ud83d\udc87‍\u2642\ufe0f', 1484 'hamburger':'\ud83c\udf54', 1485 'hammer':'\ud83d\udd28', 1486 'hammer_and_pick':'\u2692', 1487 'hammer_and_wrench':'\ud83d\udee0', 1488 'hamster':'\ud83d\udc39', 1489 'hand':'\u270b', 1490 'handbag':'\ud83d\udc5c', 1491 'handshake':'\ud83e\udd1d', 1492 'hankey':'\ud83d\udca9', 1493 'hatched_chick':'\ud83d\udc25', 1494 'hatching_chick':'\ud83d\udc23', 1495 'headphones':'\ud83c\udfa7', 1496 'hear_no_evil':'\ud83d\ude49', 1497 'heart':'\u2764\ufe0f', 1498 'heart_decoration':'\ud83d\udc9f', 1499 'heart_eyes':'\ud83d\ude0d', 1500 'heart_eyes_cat':'\ud83d\ude3b', 1501 'heartbeat':'\ud83d\udc93', 1502 'heartpulse':'\ud83d\udc97', 1503 'hearts':'\u2665\ufe0f', 1504 'heavy_check_mark':'\u2714\ufe0f', 1505 'heavy_division_sign':'\u2797', 1506 'heavy_dollar_sign':'\ud83d\udcb2', 1507 'heavy_heart_exclamation':'\u2763\ufe0f', 1508 'heavy_minus_sign':'\u2796', 1509 'heavy_multiplication_x':'\u2716\ufe0f', 1510 'heavy_plus_sign':'\u2795', 1511 'helicopter':'\ud83d\ude81', 1512 'herb':'\ud83c\udf3f', 1513 'hibiscus':'\ud83c\udf3a', 1514 'high_brightness':'\ud83d\udd06', 1515 'high_heel':'\ud83d\udc60', 1516 'hocho':'\ud83d\udd2a', 1517 'hole':'\ud83d\udd73', 1518 'honey_pot':'\ud83c\udf6f', 1519 'horse':'\ud83d\udc34', 1520 'horse_racing':'\ud83c\udfc7', 1521 'hospital':'\ud83c\udfe5', 1522 'hot_pepper':'\ud83c\udf36', 1523 'hotdog':'\ud83c\udf2d', 1524 'hotel':'\ud83c\udfe8', 1525 'hotsprings':'\u2668\ufe0f', 1526 'hourglass':'\u231b\ufe0f', 1527 'hourglass_flowing_sand':'\u23f3', 1528 'house':'\ud83c\udfe0', 1529 'house_with_garden':'\ud83c\udfe1', 1530 'houses':'\ud83c\udfd8', 1531 'hugs':'\ud83e\udd17', 1532 'hushed':'\ud83d\ude2f', 1533 'ice_cream':'\ud83c\udf68', 1534 'ice_hockey':'\ud83c\udfd2', 1535 'ice_skate':'\u26f8', 1536 'icecream':'\ud83c\udf66', 1537 'id':'\ud83c\udd94', 1538 'ideograph_advantage':'\ud83c\ude50', 1539 'imp':'\ud83d\udc7f', 1540 'inbox_tray':'\ud83d\udce5', 1541 'incoming_envelope':'\ud83d\udce8', 1542 'tipping_hand_woman':'\ud83d\udc81', 1543 'information_source':'\u2139\ufe0f', 1544 'innocent':'\ud83d\ude07', 1545 'interrobang':'\u2049\ufe0f', 1546 'iphone':'\ud83d\udcf1', 1547 'izakaya_lantern':'\ud83c\udfee', 1548 'jack_o_lantern':'\ud83c\udf83', 1549 'japan':'\ud83d\uddfe', 1550 'japanese_castle':'\ud83c\udfef', 1551 'japanese_goblin':'\ud83d\udc7a', 1552 'japanese_ogre':'\ud83d\udc79', 1553 'jeans':'\ud83d\udc56', 1554 'joy':'\ud83d\ude02', 1555 'joy_cat':'\ud83d\ude39', 1556 'joystick':'\ud83d\udd79', 1557 'kaaba':'\ud83d\udd4b', 1558 'key':'\ud83d\udd11', 1559 'keyboard':'\u2328\ufe0f', 1560 'keycap_ten':'\ud83d\udd1f', 1561 'kick_scooter':'\ud83d\udef4', 1562 'kimono':'\ud83d\udc58', 1563 'kiss':'\ud83d\udc8b', 1564 'kissing':'\ud83d\ude17', 1565 'kissing_cat':'\ud83d\ude3d', 1566 'kissing_closed_eyes':'\ud83d\ude1a', 1567 'kissing_heart':'\ud83d\ude18', 1568 'kissing_smiling_eyes':'\ud83d\ude19', 1569 'kiwi_fruit':'\ud83e\udd5d', 1570 'koala':'\ud83d\udc28', 1571 'koko':'\ud83c\ude01', 1572 'label':'\ud83c\udff7', 1573 'large_blue_circle':'\ud83d\udd35', 1574 'large_blue_diamond':'\ud83d\udd37', 1575 'large_orange_diamond':'\ud83d\udd36', 1576 'last_quarter_moon':'\ud83c\udf17', 1577 'last_quarter_moon_with_face':'\ud83c\udf1c', 1578 'latin_cross':'\u271d\ufe0f', 1579 'laughing':'\ud83d\ude06', 1580 'leaves':'\ud83c\udf43', 1581 'ledger':'\ud83d\udcd2', 1582 'left_luggage':'\ud83d\udec5', 1583 'left_right_arrow':'\u2194\ufe0f', 1584 'leftwards_arrow_with_hook':'\u21a9\ufe0f', 1585 'lemon':'\ud83c\udf4b', 1586 'leo':'\u264c\ufe0f', 1587 'leopard':'\ud83d\udc06', 1588 'level_slider':'\ud83c\udf9a', 1589 'libra':'\u264e\ufe0f', 1590 'light_rail':'\ud83d\ude88', 1591 'link':'\ud83d\udd17', 1592 'lion':'\ud83e\udd81', 1593 'lips':'\ud83d\udc44', 1594 'lipstick':'\ud83d\udc84', 1595 'lizard':'\ud83e\udd8e', 1596 'lock':'\ud83d\udd12', 1597 'lock_with_ink_pen':'\ud83d\udd0f', 1598 'lollipop':'\ud83c\udf6d', 1599 'loop':'\u27bf', 1600 'loud_sound':'\ud83d\udd0a', 1601 'loudspeaker':'\ud83d\udce2', 1602 'love_hotel':'\ud83c\udfe9', 1603 'love_letter':'\ud83d\udc8c', 1604 'low_brightness':'\ud83d\udd05', 1605 'lying_face':'\ud83e\udd25', 1606 'm':'\u24c2\ufe0f', 1607 'mag':'\ud83d\udd0d', 1608 'mag_right':'\ud83d\udd0e', 1609 'mahjong':'\ud83c\udc04\ufe0f', 1610 'mailbox':'\ud83d\udceb', 1611 'mailbox_closed':'\ud83d\udcea', 1612 'mailbox_with_mail':'\ud83d\udcec', 1613 'mailbox_with_no_mail':'\ud83d\udced', 1614 'man':'\ud83d\udc68', 1615 'man_artist':'\ud83d\udc68‍\ud83c\udfa8', 1616 'man_astronaut':'\ud83d\udc68‍\ud83d\ude80', 1617 'man_cartwheeling':'\ud83e\udd38‍\u2642\ufe0f', 1618 'man_cook':'\ud83d\udc68‍\ud83c\udf73', 1619 'man_dancing':'\ud83d\udd7a', 1620 'man_facepalming':'\ud83e\udd26‍\u2642\ufe0f', 1621 'man_factory_worker':'\ud83d\udc68‍\ud83c\udfed', 1622 'man_farmer':'\ud83d\udc68‍\ud83c\udf3e', 1623 'man_firefighter':'\ud83d\udc68‍\ud83d\ude92', 1624 'man_health_worker':'\ud83d\udc68‍\u2695\ufe0f', 1625 'man_in_tuxedo':'\ud83e\udd35', 1626 'man_judge':'\ud83d\udc68‍\u2696\ufe0f', 1627 'man_juggling':'\ud83e\udd39‍\u2642\ufe0f', 1628 'man_mechanic':'\ud83d\udc68‍\ud83d\udd27', 1629 'man_office_worker':'\ud83d\udc68‍\ud83d\udcbc', 1630 'man_pilot':'\ud83d\udc68‍\u2708\ufe0f', 1631 'man_playing_handball':'\ud83e\udd3e‍\u2642\ufe0f', 1632 'man_playing_water_polo':'\ud83e\udd3d‍\u2642\ufe0f', 1633 'man_scientist':'\ud83d\udc68‍\ud83d\udd2c', 1634 'man_shrugging':'\ud83e\udd37‍\u2642\ufe0f', 1635 'man_singer':'\ud83d\udc68‍\ud83c\udfa4', 1636 'man_student':'\ud83d\udc68‍\ud83c\udf93', 1637 'man_teacher':'\ud83d\udc68‍\ud83c\udfeb', 1638 'man_technologist':'\ud83d\udc68‍\ud83d\udcbb', 1639 'man_with_gua_pi_mao':'\ud83d\udc72', 1640 'man_with_turban':'\ud83d\udc73', 1641 'tangerine':'\ud83c\udf4a', 1642 'mans_shoe':'\ud83d\udc5e', 1643 'mantelpiece_clock':'\ud83d\udd70', 1644 'maple_leaf':'\ud83c\udf41', 1645 'martial_arts_uniform':'\ud83e\udd4b', 1646 'mask':'\ud83d\ude37', 1647 'massage_woman':'\ud83d\udc86', 1648 'massage_man':'\ud83d\udc86‍\u2642\ufe0f', 1649 'meat_on_bone':'\ud83c\udf56', 1650 'medal_military':'\ud83c\udf96', 1651 'medal_sports':'\ud83c\udfc5', 1652 'mega':'\ud83d\udce3', 1653 'melon':'\ud83c\udf48', 1654 'memo':'\ud83d\udcdd', 1655 'men_wrestling':'\ud83e\udd3c‍\u2642\ufe0f', 1656 'menorah':'\ud83d\udd4e', 1657 'mens':'\ud83d\udeb9', 1658 'metal':'\ud83e\udd18', 1659 'metro':'\ud83d\ude87', 1660 'microphone':'\ud83c\udfa4', 1661 'microscope':'\ud83d\udd2c', 1662 'milk_glass':'\ud83e\udd5b', 1663 'milky_way':'\ud83c\udf0c', 1664 'minibus':'\ud83d\ude90', 1665 'minidisc':'\ud83d\udcbd', 1666 'mobile_phone_off':'\ud83d\udcf4', 1667 'money_mouth_face':'\ud83e\udd11', 1668 'money_with_wings':'\ud83d\udcb8', 1669 'moneybag':'\ud83d\udcb0', 1670 'monkey':'\ud83d\udc12', 1671 'monkey_face':'\ud83d\udc35', 1672 'monorail':'\ud83d\ude9d', 1673 'moon':'\ud83c\udf14', 1674 'mortar_board':'\ud83c\udf93', 1675 'mosque':'\ud83d\udd4c', 1676 'motor_boat':'\ud83d\udee5', 1677 'motor_scooter':'\ud83d\udef5', 1678 'motorcycle':'\ud83c\udfcd', 1679 'motorway':'\ud83d\udee3', 1680 'mount_fuji':'\ud83d\uddfb', 1681 'mountain':'\u26f0', 1682 'mountain_biking_man':'\ud83d\udeb5', 1683 'mountain_biking_woman':'\ud83d\udeb5‍\u2640\ufe0f', 1684 'mountain_cableway':'\ud83d\udea0', 1685 'mountain_railway':'\ud83d\ude9e', 1686 'mountain_snow':'\ud83c\udfd4', 1687 'mouse':'\ud83d\udc2d', 1688 'mouse2':'\ud83d\udc01', 1689 'movie_camera':'\ud83c\udfa5', 1690 'moyai':'\ud83d\uddff', 1691 'mrs_claus':'\ud83e\udd36', 1692 'muscle':'\ud83d\udcaa', 1693 'mushroom':'\ud83c\udf44', 1694 'musical_keyboard':'\ud83c\udfb9', 1695 'musical_note':'\ud83c\udfb5', 1696 'musical_score':'\ud83c\udfbc', 1697 'mute':'\ud83d\udd07', 1698 'nail_care':'\ud83d\udc85', 1699 'name_badge':'\ud83d\udcdb', 1700 'national_park':'\ud83c\udfde', 1701 'nauseated_face':'\ud83e\udd22', 1702 'necktie':'\ud83d\udc54', 1703 'negative_squared_cross_mark':'\u274e', 1704 'nerd_face':'\ud83e\udd13', 1705 'neutral_face':'\ud83d\ude10', 1706 'new':'\ud83c\udd95', 1707 'new_moon':'\ud83c\udf11', 1708 'new_moon_with_face':'\ud83c\udf1a', 1709 'newspaper':'\ud83d\udcf0', 1710 'newspaper_roll':'\ud83d\uddde', 1711 'next_track_button':'\u23ed', 1712 'ng':'\ud83c\udd96', 1713 'no_good_man':'\ud83d\ude45‍\u2642\ufe0f', 1714 'no_good_woman':'\ud83d\ude45', 1715 'night_with_stars':'\ud83c\udf03', 1716 'no_bell':'\ud83d\udd15', 1717 'no_bicycles':'\ud83d\udeb3', 1718 'no_entry':'\u26d4\ufe0f', 1719 'no_entry_sign':'\ud83d\udeab', 1720 'no_mobile_phones':'\ud83d\udcf5', 1721 'no_mouth':'\ud83d\ude36', 1722 'no_pedestrians':'\ud83d\udeb7', 1723 'no_smoking':'\ud83d\udead', 1724 'non-potable_water':'\ud83d\udeb1', 1725 'nose':'\ud83d\udc43', 1726 'notebook':'\ud83d\udcd3', 1727 'notebook_with_decorative_cover':'\ud83d\udcd4', 1728 'notes':'\ud83c\udfb6', 1729 'nut_and_bolt':'\ud83d\udd29', 1730 'o':'\u2b55\ufe0f', 1731 'o2':'\ud83c\udd7e\ufe0f', 1732 'ocean':'\ud83c\udf0a', 1733 'octopus':'\ud83d\udc19', 1734 'oden':'\ud83c\udf62', 1735 'office':'\ud83c\udfe2', 1736 'oil_drum':'\ud83d\udee2', 1737 'ok':'\ud83c\udd97', 1738 'ok_hand':'\ud83d\udc4c', 1739 'ok_man':'\ud83d\ude46‍\u2642\ufe0f', 1740 'ok_woman':'\ud83d\ude46', 1741 'old_key':'\ud83d\udddd', 1742 'older_man':'\ud83d\udc74', 1743 'older_woman':'\ud83d\udc75', 1744 'om':'\ud83d\udd49', 1745 'on':'\ud83d\udd1b', 1746 'oncoming_automobile':'\ud83d\ude98', 1747 'oncoming_bus':'\ud83d\ude8d', 1748 'oncoming_police_car':'\ud83d\ude94', 1749 'oncoming_taxi':'\ud83d\ude96', 1750 'open_file_folder':'\ud83d\udcc2', 1751 'open_hands':'\ud83d\udc50', 1752 'open_mouth':'\ud83d\ude2e', 1753 'open_umbrella':'\u2602\ufe0f', 1754 'ophiuchus':'\u26ce', 1755 'orange_book':'\ud83d\udcd9', 1756 'orthodox_cross':'\u2626\ufe0f', 1757 'outbox_tray':'\ud83d\udce4', 1758 'owl':'\ud83e\udd89', 1759 'ox':'\ud83d\udc02', 1760 'package':'\ud83d\udce6', 1761 'page_facing_up':'\ud83d\udcc4', 1762 'page_with_curl':'\ud83d\udcc3', 1763 'pager':'\ud83d\udcdf', 1764 'paintbrush':'\ud83d\udd8c', 1765 'palm_tree':'\ud83c\udf34', 1766 'pancakes':'\ud83e\udd5e', 1767 'panda_face':'\ud83d\udc3c', 1768 'paperclip':'\ud83d\udcce', 1769 'paperclips':'\ud83d\udd87', 1770 'parasol_on_ground':'\u26f1', 1771 'parking':'\ud83c\udd7f\ufe0f', 1772 'part_alternation_mark':'\u303d\ufe0f', 1773 'partly_sunny':'\u26c5\ufe0f', 1774 'passenger_ship':'\ud83d\udef3', 1775 'passport_control':'\ud83d\udec2', 1776 'pause_button':'\u23f8', 1777 'peace_symbol':'\u262e\ufe0f', 1778 'peach':'\ud83c\udf51', 1779 'peanuts':'\ud83e\udd5c', 1780 'pear':'\ud83c\udf50', 1781 'pen':'\ud83d\udd8a', 1782 'pencil2':'\u270f\ufe0f', 1783 'penguin':'\ud83d\udc27', 1784 'pensive':'\ud83d\ude14', 1785 'performing_arts':'\ud83c\udfad', 1786 'persevere':'\ud83d\ude23', 1787 'person_fencing':'\ud83e\udd3a', 1788 'pouting_woman':'\ud83d\ude4e', 1789 'phone':'\u260e\ufe0f', 1790 'pick':'\u26cf', 1791 'pig':'\ud83d\udc37', 1792 'pig2':'\ud83d\udc16', 1793 'pig_nose':'\ud83d\udc3d', 1794 'pill':'\ud83d\udc8a', 1795 'pineapple':'\ud83c\udf4d', 1796 'ping_pong':'\ud83c\udfd3', 1797 'pisces':'\u2653\ufe0f', 1798 'pizza':'\ud83c\udf55', 1799 'place_of_worship':'\ud83d\uded0', 1800 'plate_with_cutlery':'\ud83c\udf7d', 1801 'play_or_pause_button':'\u23ef', 1802 'point_down':'\ud83d\udc47', 1803 'point_left':'\ud83d\udc48', 1804 'point_right':'\ud83d\udc49', 1805 'point_up':'\u261d\ufe0f', 1806 'point_up_2':'\ud83d\udc46', 1807 'police_car':'\ud83d\ude93', 1808 'policewoman':'\ud83d\udc6e‍\u2640\ufe0f', 1809 'poodle':'\ud83d\udc29', 1810 'popcorn':'\ud83c\udf7f', 1811 'post_office':'\ud83c\udfe3', 1812 'postal_horn':'\ud83d\udcef', 1813 'postbox':'\ud83d\udcee', 1814 'potable_water':'\ud83d\udeb0', 1815 'potato':'\ud83e\udd54', 1816 'pouch':'\ud83d\udc5d', 1817 'poultry_leg':'\ud83c\udf57', 1818 'pound':'\ud83d\udcb7', 1819 'rage':'\ud83d\ude21', 1820 'pouting_cat':'\ud83d\ude3e', 1821 'pouting_man':'\ud83d\ude4e‍\u2642\ufe0f', 1822 'pray':'\ud83d\ude4f', 1823 'prayer_beads':'\ud83d\udcff', 1824 'pregnant_woman':'\ud83e\udd30', 1825 'previous_track_button':'\u23ee', 1826 'prince':'\ud83e\udd34', 1827 'princess':'\ud83d\udc78', 1828 'printer':'\ud83d\udda8', 1829 'purple_heart':'\ud83d\udc9c', 1830 'purse':'\ud83d\udc5b', 1831 'pushpin':'\ud83d\udccc', 1832 'put_litter_in_its_place':'\ud83d\udeae', 1833 'question':'\u2753', 1834 'rabbit':'\ud83d\udc30', 1835 'rabbit2':'\ud83d\udc07', 1836 'racehorse':'\ud83d\udc0e', 1837 'racing_car':'\ud83c\udfce', 1838 'radio':'\ud83d\udcfb', 1839 'radio_button':'\ud83d\udd18', 1840 'radioactive':'\u2622\ufe0f', 1841 'railway_car':'\ud83d\ude83', 1842 'railway_track':'\ud83d\udee4', 1843 'rainbow':'\ud83c\udf08', 1844 'rainbow_flag':'\ud83c\udff3\ufe0f‍\ud83c\udf08', 1845 'raised_back_of_hand':'\ud83e\udd1a', 1846 'raised_hand_with_fingers_splayed':'\ud83d\udd90', 1847 'raised_hands':'\ud83d\ude4c', 1848 'raising_hand_woman':'\ud83d\ude4b', 1849 'raising_hand_man':'\ud83d\ude4b‍\u2642\ufe0f', 1850 'ram':'\ud83d\udc0f', 1851 'ramen':'\ud83c\udf5c', 1852 'rat':'\ud83d\udc00', 1853 'record_button':'\u23fa', 1854 'recycle':'\u267b\ufe0f', 1855 'red_circle':'\ud83d\udd34', 1856 'registered':'\u00ae\ufe0f', 1857 'relaxed':'\u263a\ufe0f', 1858 'relieved':'\ud83d\ude0c', 1859 'reminder_ribbon':'\ud83c\udf97', 1860 'repeat':'\ud83d\udd01', 1861 'repeat_one':'\ud83d\udd02', 1862 'rescue_worker_helmet':'\u26d1', 1863 'restroom':'\ud83d\udebb', 1864 'revolving_hearts':'\ud83d\udc9e', 1865 'rewind':'\u23ea', 1866 'rhinoceros':'\ud83e\udd8f', 1867 'ribbon':'\ud83c\udf80', 1868 'rice':'\ud83c\udf5a', 1869 'rice_ball':'\ud83c\udf59', 1870 'rice_cracker':'\ud83c\udf58', 1871 'rice_scene':'\ud83c\udf91', 1872 'right_anger_bubble':'\ud83d\uddef', 1873 'ring':'\ud83d\udc8d', 1874 'robot':'\ud83e\udd16', 1875 'rocket':'\ud83d\ude80', 1876 'rofl':'\ud83e\udd23', 1877 'roll_eyes':'\ud83d\ude44', 1878 'roller_coaster':'\ud83c\udfa2', 1879 'rooster':'\ud83d\udc13', 1880 'rose':'\ud83c\udf39', 1881 'rosette':'\ud83c\udff5', 1882 'rotating_light':'\ud83d\udea8', 1883 'round_pushpin':'\ud83d\udccd', 1884 'rowing_man':'\ud83d\udea3', 1885 'rowing_woman':'\ud83d\udea3‍\u2640\ufe0f', 1886 'rugby_football':'\ud83c\udfc9', 1887 'running_man':'\ud83c\udfc3', 1888 'running_shirt_with_sash':'\ud83c\udfbd', 1889 'running_woman':'\ud83c\udfc3‍\u2640\ufe0f', 1890 'sa':'\ud83c\ude02\ufe0f', 1891 'sagittarius':'\u2650\ufe0f', 1892 'sake':'\ud83c\udf76', 1893 'sandal':'\ud83d\udc61', 1894 'santa':'\ud83c\udf85', 1895 'satellite':'\ud83d\udce1', 1896 'saxophone':'\ud83c\udfb7', 1897 'school':'\ud83c\udfeb', 1898 'school_satchel':'\ud83c\udf92', 1899 'scissors':'\u2702\ufe0f', 1900 'scorpion':'\ud83e\udd82', 1901 'scorpius':'\u264f\ufe0f', 1902 'scream':'\ud83d\ude31', 1903 'scream_cat':'\ud83d\ude40', 1904 'scroll':'\ud83d\udcdc', 1905 'seat':'\ud83d\udcba', 1906 'secret':'\u3299\ufe0f', 1907 'see_no_evil':'\ud83d\ude48', 1908 'seedling':'\ud83c\udf31', 1909 'selfie':'\ud83e\udd33', 1910 'shallow_pan_of_food':'\ud83e\udd58', 1911 'shamrock':'\u2618\ufe0f', 1912 'shark':'\ud83e\udd88', 1913 'shaved_ice':'\ud83c\udf67', 1914 'sheep':'\ud83d\udc11', 1915 'shell':'\ud83d\udc1a', 1916 'shield':'\ud83d\udee1', 1917 'shinto_shrine':'\u26e9', 1918 'ship':'\ud83d\udea2', 1919 'shirt':'\ud83d\udc55', 1920 'shopping':'\ud83d\udecd', 1921 'shopping_cart':'\ud83d\uded2', 1922 'shower':'\ud83d\udebf', 1923 'shrimp':'\ud83e\udd90', 1924 'signal_strength':'\ud83d\udcf6', 1925 'six_pointed_star':'\ud83d\udd2f', 1926 'ski':'\ud83c\udfbf', 1927 'skier':'\u26f7', 1928 'skull':'\ud83d\udc80', 1929 'skull_and_crossbones':'\u2620\ufe0f', 1930 'sleeping':'\ud83d\ude34', 1931 'sleeping_bed':'\ud83d\udecc', 1932 'sleepy':'\ud83d\ude2a', 1933 'slightly_frowning_face':'\ud83d\ude41', 1934 'slightly_smiling_face':'\ud83d\ude42', 1935 'slot_machine':'\ud83c\udfb0', 1936 'small_airplane':'\ud83d\udee9', 1937 'small_blue_diamond':'\ud83d\udd39', 1938 'small_orange_diamond':'\ud83d\udd38', 1939 'small_red_triangle':'\ud83d\udd3a', 1940 'small_red_triangle_down':'\ud83d\udd3b', 1941 'smile':'\ud83d\ude04', 1942 'smile_cat':'\ud83d\ude38', 1943 'smiley':'\ud83d\ude03', 1944 'smiley_cat':'\ud83d\ude3a', 1945 'smiling_imp':'\ud83d\ude08', 1946 'smirk':'\ud83d\ude0f', 1947 'smirk_cat':'\ud83d\ude3c', 1948 'smoking':'\ud83d\udeac', 1949 'snail':'\ud83d\udc0c', 1950 'snake':'\ud83d\udc0d', 1951 'sneezing_face':'\ud83e\udd27', 1952 'snowboarder':'\ud83c\udfc2', 1953 'snowflake':'\u2744\ufe0f', 1954 'snowman':'\u26c4\ufe0f', 1955 'snowman_with_snow':'\u2603\ufe0f', 1956 'sob':'\ud83d\ude2d', 1957 'soccer':'\u26bd\ufe0f', 1958 'soon':'\ud83d\udd1c', 1959 'sos':'\ud83c\udd98', 1960 'sound':'\ud83d\udd09', 1961 'space_invader':'\ud83d\udc7e', 1962 'spades':'\u2660\ufe0f', 1963 'spaghetti':'\ud83c\udf5d', 1964 'sparkle':'\u2747\ufe0f', 1965 'sparkler':'\ud83c\udf87', 1966 'sparkles':'\u2728', 1967 'sparkling_heart':'\ud83d\udc96', 1968 'speak_no_evil':'\ud83d\ude4a', 1969 'speaker':'\ud83d\udd08', 1970 'speaking_head':'\ud83d\udde3', 1971 'speech_balloon':'\ud83d\udcac', 1972 'speedboat':'\ud83d\udea4', 1973 'spider':'\ud83d\udd77', 1974 'spider_web':'\ud83d\udd78', 1975 'spiral_calendar':'\ud83d\uddd3', 1976 'spiral_notepad':'\ud83d\uddd2', 1977 'spoon':'\ud83e\udd44', 1978 'squid':'\ud83e\udd91', 1979 'stadium':'\ud83c\udfdf', 1980 'star':'\u2b50\ufe0f', 1981 'star2':'\ud83c\udf1f', 1982 'star_and_crescent':'\u262a\ufe0f', 1983 'star_of_david':'\u2721\ufe0f', 1984 'stars':'\ud83c\udf20', 1985 'station':'\ud83d\ude89', 1986 'statue_of_liberty':'\ud83d\uddfd', 1987 'steam_locomotive':'\ud83d\ude82', 1988 'stew':'\ud83c\udf72', 1989 'stop_button':'\u23f9', 1990 'stop_sign':'\ud83d\uded1', 1991 'stopwatch':'\u23f1', 1992 'straight_ruler':'\ud83d\udccf', 1993 'strawberry':'\ud83c\udf53', 1994 'stuck_out_tongue':'\ud83d\ude1b', 1995 'stuck_out_tongue_closed_eyes':'\ud83d\ude1d', 1996 'stuck_out_tongue_winking_eye':'\ud83d\ude1c', 1997 'studio_microphone':'\ud83c\udf99', 1998 'stuffed_flatbread':'\ud83e\udd59', 1999 'sun_behind_large_cloud':'\ud83c\udf25', 2000 'sun_behind_rain_cloud':'\ud83c\udf26', 2001 'sun_behind_small_cloud':'\ud83c\udf24', 2002 'sun_with_face':'\ud83c\udf1e', 2003 'sunflower':'\ud83c\udf3b', 2004 'sunglasses':'\ud83d\ude0e', 2005 'sunny':'\u2600\ufe0f', 2006 'sunrise':'\ud83c\udf05', 2007 'sunrise_over_mountains':'\ud83c\udf04', 2008 'surfing_man':'\ud83c\udfc4', 2009 'surfing_woman':'\ud83c\udfc4‍\u2640\ufe0f', 2010 'sushi':'\ud83c\udf63', 2011 'suspension_railway':'\ud83d\ude9f', 2012 'sweat':'\ud83d\ude13', 2013 'sweat_drops':'\ud83d\udca6', 2014 'sweat_smile':'\ud83d\ude05', 2015 'sweet_potato':'\ud83c\udf60', 2016 'swimming_man':'\ud83c\udfca', 2017 'swimming_woman':'\ud83c\udfca‍\u2640\ufe0f', 2018 'symbols':'\ud83d\udd23', 2019 'synagogue':'\ud83d\udd4d', 2020 'syringe':'\ud83d\udc89', 2021 'taco':'\ud83c\udf2e', 2022 'tada':'\ud83c\udf89', 2023 'tanabata_tree':'\ud83c\udf8b', 2024 'taurus':'\u2649\ufe0f', 2025 'taxi':'\ud83d\ude95', 2026 'tea':'\ud83c\udf75', 2027 'telephone_receiver':'\ud83d\udcde', 2028 'telescope':'\ud83d\udd2d', 2029 'tennis':'\ud83c\udfbe', 2030 'tent':'\u26fa\ufe0f', 2031 'thermometer':'\ud83c\udf21', 2032 'thinking':'\ud83e\udd14', 2033 'thought_balloon':'\ud83d\udcad', 2034 'ticket':'\ud83c\udfab', 2035 'tickets':'\ud83c\udf9f', 2036 'tiger':'\ud83d\udc2f', 2037 'tiger2':'\ud83d\udc05', 2038 'timer_clock':'\u23f2', 2039 'tipping_hand_man':'\ud83d\udc81‍\u2642\ufe0f', 2040 'tired_face':'\ud83d\ude2b', 2041 'tm':'\u2122\ufe0f', 2042 'toilet':'\ud83d\udebd', 2043 'tokyo_tower':'\ud83d\uddfc', 2044 'tomato':'\ud83c\udf45', 2045 'tongue':'\ud83d\udc45', 2046 'top':'\ud83d\udd1d', 2047 'tophat':'\ud83c\udfa9', 2048 'tornado':'\ud83c\udf2a', 2049 'trackball':'\ud83d\uddb2', 2050 'tractor':'\ud83d\ude9c', 2051 'traffic_light':'\ud83d\udea5', 2052 'train':'\ud83d\ude8b', 2053 'train2':'\ud83d\ude86', 2054 'tram':'\ud83d\ude8a', 2055 'triangular_flag_on_post':'\ud83d\udea9', 2056 'triangular_ruler':'\ud83d\udcd0', 2057 'trident':'\ud83d\udd31', 2058 'triumph':'\ud83d\ude24', 2059 'trolleybus':'\ud83d\ude8e', 2060 'trophy':'\ud83c\udfc6', 2061 'tropical_drink':'\ud83c\udf79', 2062 'tropical_fish':'\ud83d\udc20', 2063 'truck':'\ud83d\ude9a', 2064 'trumpet':'\ud83c\udfba', 2065 'tulip':'\ud83c\udf37', 2066 'tumbler_glass':'\ud83e\udd43', 2067 'turkey':'\ud83e\udd83', 2068 'turtle':'\ud83d\udc22', 2069 'tv':'\ud83d\udcfa', 2070 'twisted_rightwards_arrows':'\ud83d\udd00', 2071 'two_hearts':'\ud83d\udc95', 2072 'two_men_holding_hands':'\ud83d\udc6c', 2073 'two_women_holding_hands':'\ud83d\udc6d', 2074 'u5272':'\ud83c\ude39', 2075 'u5408':'\ud83c\ude34', 2076 'u55b6':'\ud83c\ude3a', 2077 'u6307':'\ud83c\ude2f\ufe0f', 2078 'u6708':'\ud83c\ude37\ufe0f', 2079 'u6709':'\ud83c\ude36', 2080 'u6e80':'\ud83c\ude35', 2081 'u7121':'\ud83c\ude1a\ufe0f', 2082 'u7533':'\ud83c\ude38', 2083 'u7981':'\ud83c\ude32', 2084 'u7a7a':'\ud83c\ude33', 2085 'umbrella':'\u2614\ufe0f', 2086 'unamused':'\ud83d\ude12', 2087 'underage':'\ud83d\udd1e', 2088 'unicorn':'\ud83e\udd84', 2089 'unlock':'\ud83d\udd13', 2090 'up':'\ud83c\udd99', 2091 'upside_down_face':'\ud83d\ude43', 2092 'v':'\u270c\ufe0f', 2093 'vertical_traffic_light':'\ud83d\udea6', 2094 'vhs':'\ud83d\udcfc', 2095 'vibration_mode':'\ud83d\udcf3', 2096 'video_camera':'\ud83d\udcf9', 2097 'video_game':'\ud83c\udfae', 2098 'violin':'\ud83c\udfbb', 2099 'virgo':'\u264d\ufe0f', 2100 'volcano':'\ud83c\udf0b', 2101 'volleyball':'\ud83c\udfd0', 2102 'vs':'\ud83c\udd9a', 2103 'vulcan_salute':'\ud83d\udd96', 2104 'walking_man':'\ud83d\udeb6', 2105 'walking_woman':'\ud83d\udeb6‍\u2640\ufe0f', 2106 'waning_crescent_moon':'\ud83c\udf18', 2107 'waning_gibbous_moon':'\ud83c\udf16', 2108 'warning':'\u26a0\ufe0f', 2109 'wastebasket':'\ud83d\uddd1', 2110 'watch':'\u231a\ufe0f', 2111 'water_buffalo':'\ud83d\udc03', 2112 'watermelon':'\ud83c\udf49', 2113 'wave':'\ud83d\udc4b', 2114 'wavy_dash':'\u3030\ufe0f', 2115 'waxing_crescent_moon':'\ud83c\udf12', 2116 'wc':'\ud83d\udebe', 2117 'weary':'\ud83d\ude29', 2118 'wedding':'\ud83d\udc92', 2119 'weight_lifting_man':'\ud83c\udfcb\ufe0f', 2120 'weight_lifting_woman':'\ud83c\udfcb\ufe0f‍\u2640\ufe0f', 2121 'whale':'\ud83d\udc33', 2122 'whale2':'\ud83d\udc0b', 2123 'wheel_of_dharma':'\u2638\ufe0f', 2124 'wheelchair':'\u267f\ufe0f', 2125 'white_check_mark':'\u2705', 2126 'white_circle':'\u26aa\ufe0f', 2127 'white_flag':'\ud83c\udff3\ufe0f', 2128 'white_flower':'\ud83d\udcae', 2129 'white_large_square':'\u2b1c\ufe0f', 2130 'white_medium_small_square':'\u25fd\ufe0f', 2131 'white_medium_square':'\u25fb\ufe0f', 2132 'white_small_square':'\u25ab\ufe0f', 2133 'white_square_button':'\ud83d\udd33', 2134 'wilted_flower':'\ud83e\udd40', 2135 'wind_chime':'\ud83c\udf90', 2136 'wind_face':'\ud83c\udf2c', 2137 'wine_glass':'\ud83c\udf77', 2138 'wink':'\ud83d\ude09', 2139 'wolf':'\ud83d\udc3a', 2140 'woman':'\ud83d\udc69', 2141 'woman_artist':'\ud83d\udc69‍\ud83c\udfa8', 2142 'woman_astronaut':'\ud83d\udc69‍\ud83d\ude80', 2143 'woman_cartwheeling':'\ud83e\udd38‍\u2640\ufe0f', 2144 'woman_cook':'\ud83d\udc69‍\ud83c\udf73', 2145 'woman_facepalming':'\ud83e\udd26‍\u2640\ufe0f', 2146 'woman_factory_worker':'\ud83d\udc69‍\ud83c\udfed', 2147 'woman_farmer':'\ud83d\udc69‍\ud83c\udf3e', 2148 'woman_firefighter':'\ud83d\udc69‍\ud83d\ude92', 2149 'woman_health_worker':'\ud83d\udc69‍\u2695\ufe0f', 2150 'woman_judge':'\ud83d\udc69‍\u2696\ufe0f', 2151 'woman_juggling':'\ud83e\udd39‍\u2640\ufe0f', 2152 'woman_mechanic':'\ud83d\udc69‍\ud83d\udd27', 2153 'woman_office_worker':'\ud83d\udc69‍\ud83d\udcbc', 2154 'woman_pilot':'\ud83d\udc69‍\u2708\ufe0f', 2155 'woman_playing_handball':'\ud83e\udd3e‍\u2640\ufe0f', 2156 'woman_playing_water_polo':'\ud83e\udd3d‍\u2640\ufe0f', 2157 'woman_scientist':'\ud83d\udc69‍\ud83d\udd2c', 2158 'woman_shrugging':'\ud83e\udd37‍\u2640\ufe0f', 2159 'woman_singer':'\ud83d\udc69‍\ud83c\udfa4', 2160 'woman_student':'\ud83d\udc69‍\ud83c\udf93', 2161 'woman_teacher':'\ud83d\udc69‍\ud83c\udfeb', 2162 'woman_technologist':'\ud83d\udc69‍\ud83d\udcbb', 2163 'woman_with_turban':'\ud83d\udc73‍\u2640\ufe0f', 2164 'womans_clothes':'\ud83d\udc5a', 2165 'womans_hat':'\ud83d\udc52', 2166 'women_wrestling':'\ud83e\udd3c‍\u2640\ufe0f', 2167 'womens':'\ud83d\udeba', 2168 'world_map':'\ud83d\uddfa', 2169 'worried':'\ud83d\ude1f', 2170 'wrench':'\ud83d\udd27', 2171 'writing_hand':'\u270d\ufe0f', 2172 'x':'\u274c', 2173 'yellow_heart':'\ud83d\udc9b', 2174 'yen':'\ud83d\udcb4', 2175 'yin_yang':'\u262f\ufe0f', 2176 'yum':'\ud83d\ude0b', 2177 'zap':'\u26a1\ufe0f', 2178 'zipper_mouth_face':'\ud83e\udd10', 2179 'zzz':'\ud83d\udca4', 2180 2181 /* special emojis :P */ 2182 'octocat': '<img alt=":octocat:" height="20" width="20" align="absmiddle" src="https://assets-cdn.github.com/images/icons/emoji/octocat.png">', 2183 'showdown': '<span style="font-family: \'Anonymous Pro\', monospace; text-decoration: underline; text-decoration-style: dashed; text-decoration-color: #3e8b8a;text-underline-position: under;">S</span>' 2184}; 2185 2186/** 2187 * Created by Estevao on 31-05-2015. 2188 */ 2189 2190/** 2191 * Showdown Converter class 2192 * @class 2193 * @param {object} [converterOptions] 2194 * @returns {Converter} 2195 */ 2196showdown.Converter = function (converterOptions) { 2197 'use strict'; 2198 2199 var 2200 /** 2201 * Options used by this converter 2202 * @private 2203 * @type {{}} 2204 */ 2205 options = {}, 2206 2207 /** 2208 * Language extensions used by this converter 2209 * @private 2210 * @type {Array} 2211 */ 2212 langExtensions = [], 2213 2214 /** 2215 * Output modifiers extensions used by this converter 2216 * @private 2217 * @type {Array} 2218 */ 2219 outputModifiers = [], 2220 2221 /** 2222 * Event listeners 2223 * @private 2224 * @type {{}} 2225 */ 2226 listeners = {}, 2227 2228 /** 2229 * The flavor set in this converter 2230 */ 2231 setConvFlavor = setFlavor, 2232 2233 /** 2234 * Metadata of the document 2235 * @type {{parsed: {}, raw: string, format: string}} 2236 */ 2237 metadata = { 2238 parsed: {}, 2239 raw: '', 2240 format: '' 2241 }; 2242 2243 _constructor(); 2244 2245 /** 2246 * Converter constructor 2247 * @private 2248 */ 2249 function _constructor () { 2250 converterOptions = converterOptions || {}; 2251 2252 for (var gOpt in globalOptions) { 2253 if (globalOptions.hasOwnProperty(gOpt)) { 2254 options[gOpt] = globalOptions[gOpt]; 2255 } 2256 } 2257 2258 // Merge options 2259 if (typeof converterOptions === 'object') { 2260 for (var opt in converterOptions) { 2261 if (converterOptions.hasOwnProperty(opt)) { 2262 options[opt] = converterOptions[opt]; 2263 } 2264 } 2265 } else { 2266 throw Error('Converter expects the passed parameter to be an object, but ' + typeof converterOptions + 2267 ' was passed instead.'); 2268 } 2269 2270 if (options.extensions) { 2271 showdown.helper.forEach(options.extensions, _parseExtension); 2272 } 2273 } 2274 2275 /** 2276 * Parse extension 2277 * @param {*} ext 2278 * @param {string} [name=''] 2279 * @private 2280 */ 2281 function _parseExtension (ext, name) { 2282 2283 name = name || null; 2284 // If it's a string, the extension was previously loaded 2285 if (showdown.helper.isString(ext)) { 2286 ext = showdown.helper.stdExtName(ext); 2287 name = ext; 2288 2289 // LEGACY_SUPPORT CODE 2290 if (showdown.extensions[ext]) { 2291 console.warn('DEPRECATION WARNING: ' + ext + ' is an old extension that uses a deprecated loading method.' + 2292 'Please inform the developer that the extension should be updated!'); 2293 legacyExtensionLoading(showdown.extensions[ext], ext); 2294 return; 2295 // END LEGACY SUPPORT CODE 2296 2297 } else if (!showdown.helper.isUndefined(extensions[ext])) { 2298 ext = extensions[ext]; 2299 2300 } else { 2301 throw Error('Extension "' + ext + '" could not be loaded. It was either not found or is not a valid extension.'); 2302 } 2303 } 2304 2305 if (typeof ext === 'function') { 2306 ext = ext(); 2307 } 2308 2309 if (!showdown.helper.isArray(ext)) { 2310 ext = [ext]; 2311 } 2312 2313 var validExt = validate(ext, name); 2314 if (!validExt.valid) { 2315 throw Error(validExt.error); 2316 } 2317 2318 for (var i = 0; i < ext.length; ++i) { 2319 switch (ext[i].type) { 2320 2321 case 'lang': 2322 langExtensions.push(ext[i]); 2323 break; 2324 2325 case 'output': 2326 outputModifiers.push(ext[i]); 2327 break; 2328 } 2329 if (ext[i].hasOwnProperty('listeners')) { 2330 for (var ln in ext[i].listeners) { 2331 if (ext[i].listeners.hasOwnProperty(ln)) { 2332 listen(ln, ext[i].listeners[ln]); 2333 } 2334 } 2335 } 2336 } 2337 2338 } 2339 2340 /** 2341 * LEGACY_SUPPORT 2342 * @param {*} ext 2343 * @param {string} name 2344 */ 2345 function legacyExtensionLoading (ext, name) { 2346 if (typeof ext === 'function') { 2347 ext = ext(new showdown.Converter()); 2348 } 2349 if (!showdown.helper.isArray(ext)) { 2350 ext = [ext]; 2351 } 2352 var valid = validate(ext, name); 2353 2354 if (!valid.valid) { 2355 throw Error(valid.error); 2356 } 2357 2358 for (var i = 0; i < ext.length; ++i) { 2359 switch (ext[i].type) { 2360 case 'lang': 2361 langExtensions.push(ext[i]); 2362 break; 2363 case 'output': 2364 outputModifiers.push(ext[i]); 2365 break; 2366 default:// should never reach here 2367 throw Error('Extension loader error: Type unrecognized!!!'); 2368 } 2369 } 2370 } 2371 2372 /** 2373 * Listen to an event 2374 * @param {string} name 2375 * @param {function} callback 2376 */ 2377 function listen (name, callback) { 2378 if (!showdown.helper.isString(name)) { 2379 throw Error('Invalid argument in converter.listen() method: name must be a string, but ' + typeof name + ' given'); 2380 } 2381 2382 if (typeof callback !== 'function') { 2383 throw Error('Invalid argument in converter.listen() method: callback must be a function, but ' + typeof callback + ' given'); 2384 } 2385 2386 if (!listeners.hasOwnProperty(name)) { 2387 listeners[name] = []; 2388 } 2389 listeners[name].push(callback); 2390 } 2391 2392 function rTrimInputText (text) { 2393 var rsp = text.match(/^\s*/)[0].length, 2394 rgx = new RegExp('^\\s{0,' + rsp + '}', 'gm'); 2395 return text.replace(rgx, ''); 2396 } 2397 2398 /** 2399 * Dispatch an event 2400 * @private 2401 * @param {string} evtName Event name 2402 * @param {string} text Text 2403 * @param {{}} options Converter Options 2404 * @param {{}} globals 2405 * @returns {string} 2406 */ 2407 this._dispatch = function dispatch (evtName, text, options, globals) { 2408 if (listeners.hasOwnProperty(evtName)) { 2409 for (var ei = 0; ei < listeners[evtName].length; ++ei) { 2410 var nText = listeners[evtName][ei](evtName, text, this, options, globals); 2411 if (nText && typeof nText !== 'undefined') { 2412 text = nText; 2413 } 2414 } 2415 } 2416 return text; 2417 }; 2418 2419 /** 2420 * Listen to an event 2421 * @param {string} name 2422 * @param {function} callback 2423 * @returns {showdown.Converter} 2424 */ 2425 this.listen = function (name, callback) { 2426 listen(name, callback); 2427 return this; 2428 }; 2429 2430 /** 2431 * Converts a markdown string into HTML 2432 * @param {string} text 2433 * @returns {*} 2434 */ 2435 this.makeHtml = function (text) { 2436 //check if text is not falsy 2437 if (!text) { 2438 return text; 2439 } 2440 2441 var globals = { 2442 gHtmlBlocks: [], 2443 gHtmlMdBlocks: [], 2444 gHtmlSpans: [], 2445 gUrls: {}, 2446 gTitles: {}, 2447 gDimensions: {}, 2448 gListLevel: 0, 2449 hashLinkCounts: {}, 2450 langExtensions: langExtensions, 2451 outputModifiers: outputModifiers, 2452 converter: this, 2453 ghCodeBlocks: [], 2454 metadata: { 2455 parsed: {}, 2456 raw: '', 2457 format: '' 2458 } 2459 }; 2460 2461 // This lets us use ¨ trema as an escape char to avoid md5 hashes 2462 // The choice of character is arbitrary; anything that isn't 2463 // magic in Markdown will work. 2464 text = text.replace(/¨/g, '¨T'); 2465 2466 // Replace $ with ¨D 2467 // RegExp interprets $ as a special character 2468 // when it's in a replacement string 2469 text = text.replace(/\$/g, '¨D'); 2470 2471 // Standardize line endings 2472 text = text.replace(/\r\n/g, '\n'); // DOS to Unix 2473 text = text.replace(/\r/g, '\n'); // Mac to Unix 2474 2475 // Stardardize line spaces 2476 text = text.replace(/\u00A0/g, ' '); 2477 2478 if (options.smartIndentationFix) { 2479 text = rTrimInputText(text); 2480 } 2481 2482 // Make sure text begins and ends with a couple of newlines: 2483 text = '\n\n' + text + '\n\n'; 2484 2485 // detab 2486 text = showdown.subParser('detab')(text, options, globals); 2487 2488 /** 2489 * Strip any lines consisting only of spaces and tabs. 2490 * This makes subsequent regexs easier to write, because we can 2491 * match consecutive blank lines with /\n+/ instead of something 2492 * contorted like /[ \t]*\n+/ 2493 */ 2494 text = text.replace(/^[ \t]+$/mg, ''); 2495 2496 //run languageExtensions 2497 showdown.helper.forEach(langExtensions, function (ext) { 2498 text = showdown.subParser('runExtension')(ext, text, options, globals); 2499 }); 2500 2501 // run the sub parsers 2502 text = showdown.subParser('metadata')(text, options, globals); 2503 text = showdown.subParser('hashPreCodeTags')(text, options, globals); 2504 text = showdown.subParser('githubCodeBlocks')(text, options, globals); 2505 text = showdown.subParser('hashHTMLBlocks')(text, options, globals); 2506 text = showdown.subParser('hashCodeTags')(text, options, globals); 2507 text = showdown.subParser('stripLinkDefinitions')(text, options, globals); 2508 text = showdown.subParser('blockGamut')(text, options, globals); 2509 text = showdown.subParser('unhashHTMLSpans')(text, options, globals); 2510 text = showdown.subParser('unescapeSpecialChars')(text, options, globals); 2511 2512 // attacklab: Restore dollar signs 2513 text = text.replace(/¨D/g, '$$'); 2514 2515 // attacklab: Restore tremas 2516 text = text.replace(/¨T/g, '¨'); 2517 2518 // render a complete html document instead of a partial if the option is enabled 2519 text = showdown.subParser('completeHTMLDocument')(text, options, globals); 2520 2521 // Run output modifiers 2522 showdown.helper.forEach(outputModifiers, function (ext) { 2523 text = showdown.subParser('runExtension')(ext, text, options, globals); 2524 }); 2525 2526 // update metadata 2527 metadata = globals.metadata; 2528 return text; 2529 }; 2530 2531 /** 2532 * Converts an HTML string into a markdown string 2533 * @param src 2534 * @param [HTMLParser] A WHATWG DOM and HTML parser, such as JSDOM. If none is supplied, window.document will be used. 2535 * @returns {string} 2536 */ 2537 this.makeMarkdown = this.makeMd = function (src, HTMLParser) { 2538 2539 // replace \r\n with \n 2540 src = src.replace(/\r\n/g, '\n'); 2541 src = src.replace(/\r/g, '\n'); // old macs 2542 2543 // due to an edge case, we need to find this: > < 2544 // to prevent removing of non silent white spaces 2545 // ex: <em>this is</em> <strong>sparta</strong> 2546 src = src.replace(/>[ \t]+</, '>¨NBSP;<'); 2547 2548 if (!HTMLParser) { 2549 if (window && window.document) { 2550 HTMLParser = window.document; 2551 } else { 2552 throw new Error('HTMLParser is undefined. If in a webworker or nodejs environment, you need to provide a WHATWG DOM and HTML such as JSDOM'); 2553 } 2554 } 2555 2556 var doc = HTMLParser.createElement('div'); 2557 doc.innerHTML = src; 2558 2559 var globals = { 2560 preList: substitutePreCodeTags(doc) 2561 }; 2562 2563 // remove all newlines and collapse spaces 2564 clean(doc); 2565 2566 // some stuff, like accidental reference links must now be escaped 2567 // TODO 2568 // doc.innerHTML = doc.innerHTML.replace(/\[[\S\t ]]/); 2569 2570 var nodes = doc.childNodes, 2571 mdDoc = ''; 2572 2573 for (var i = 0; i < nodes.length; i++) { 2574 mdDoc += showdown.subParser('makeMarkdown.node')(nodes[i], globals); 2575 } 2576 2577 function clean (node) { 2578 for (var n = 0; n < node.childNodes.length; ++n) { 2579 var child = node.childNodes[n]; 2580 if (child.nodeType === 3) { 2581 if (!/\S/.test(child.nodeValue) && !/^[ ]+$/.test(child.nodeValue)) { 2582 node.removeChild(child); 2583 --n; 2584 } else { 2585 child.nodeValue = child.nodeValue.split('\n').join(' '); 2586 child.nodeValue = child.nodeValue.replace(/(\s)+/g, '$1'); 2587 } 2588 } else if (child.nodeType === 1) { 2589 clean(child); 2590 } 2591 } 2592 } 2593 2594 // find all pre tags and replace contents with placeholder 2595 // we need this so that we can remove all indentation from html 2596 // to ease up parsing 2597 function substitutePreCodeTags (doc) { 2598 2599 var pres = doc.querySelectorAll('pre'), 2600 presPH = []; 2601 2602 for (var i = 0; i < pres.length; ++i) { 2603 2604 if (pres[i].childElementCount === 1 && pres[i].firstChild.tagName.toLowerCase() === 'code') { 2605 var content = pres[i].firstChild.innerHTML.trim(), 2606 language = pres[i].firstChild.getAttribute('data-language') || ''; 2607 2608 // if data-language attribute is not defined, then we look for class language-* 2609 if (language === '') { 2610 var classes = pres[i].firstChild.className.split(' '); 2611 for (var c = 0; c < classes.length; ++c) { 2612 var matches = classes[c].match(/^language-(.+)$/); 2613 if (matches !== null) { 2614 language = matches[1]; 2615 break; 2616 } 2617 } 2618 } 2619 2620 // unescape html entities in content 2621 content = showdown.helper.unescapeHTMLEntities(content); 2622 2623 presPH.push(content); 2624 pres[i].outerHTML = '<precode language="' + language + '" precodenum="' + i.toString() + '"></precode>'; 2625 } else { 2626 presPH.push(pres[i].innerHTML); 2627 pres[i].innerHTML = ''; 2628 pres[i].setAttribute('prenum', i.toString()); 2629 } 2630 } 2631 return presPH; 2632 } 2633 2634 return mdDoc; 2635 }; 2636 2637 /** 2638 * Set an option of this Converter instance 2639 * @param {string} key 2640 * @param {*} value 2641 */ 2642 this.setOption = function (key, value) { 2643 options[key] = value; 2644 }; 2645 2646 /** 2647 * Get the option of this Converter instance 2648 * @param {string} key 2649 * @returns {*} 2650 */ 2651 this.getOption = function (key) { 2652 return options[key]; 2653 }; 2654 2655 /** 2656 * Get the options of this Converter instance 2657 * @returns {{}} 2658 */ 2659 this.getOptions = function () { 2660 return options; 2661 }; 2662 2663 /** 2664 * Add extension to THIS converter 2665 * @param {{}} extension 2666 * @param {string} [name=null] 2667 */ 2668 this.addExtension = function (extension, name) { 2669 name = name || null; 2670 _parseExtension(extension, name); 2671 }; 2672 2673 /** 2674 * Use a global registered extension with THIS converter 2675 * @param {string} extensionName Name of the previously registered extension 2676 */ 2677 this.useExtension = function (extensionName) { 2678 _parseExtension(extensionName); 2679 }; 2680 2681 /** 2682 * Set the flavor THIS converter should use 2683 * @param {string} name 2684 */ 2685 this.setFlavor = function (name) { 2686 if (!flavor.hasOwnProperty(name)) { 2687 throw Error(name + ' flavor was not found'); 2688 } 2689 var preset = flavor[name]; 2690 setConvFlavor = name; 2691 for (var option in preset) { 2692 if (preset.hasOwnProperty(option)) { 2693 options[option] = preset[option]; 2694 } 2695 } 2696 }; 2697 2698 /** 2699 * Get the currently set flavor of this converter 2700 * @returns {string} 2701 */ 2702 this.getFlavor = function () { 2703 return setConvFlavor; 2704 }; 2705 2706 /** 2707 * Remove an extension from THIS converter. 2708 * Note: This is a costly operation. It's better to initialize a new converter 2709 * and specify the extensions you wish to use 2710 * @param {Array} extension 2711 */ 2712 this.removeExtension = function (extension) { 2713 if (!showdown.helper.isArray(extension)) { 2714 extension = [extension]; 2715 } 2716 for (var a = 0; a < extension.length; ++a) { 2717 var ext = extension[a]; 2718 for (var i = 0; i < langExtensions.length; ++i) { 2719 if (langExtensions[i] === ext) { 2720 langExtensions.splice(i, 1); 2721 } 2722 } 2723 for (var ii = 0; ii < outputModifiers.length; ++ii) { 2724 if (outputModifiers[ii] === ext) { 2725 outputModifiers.splice(ii, 1); 2726 } 2727 } 2728 } 2729 }; 2730 2731 /** 2732 * Get all extension of THIS converter 2733 * @returns {{language: Array, output: Array}} 2734 */ 2735 this.getAllExtensions = function () { 2736 return { 2737 language: langExtensions, 2738 output: outputModifiers 2739 }; 2740 }; 2741 2742 /** 2743 * Get the metadata of the previously parsed document 2744 * @param raw 2745 * @returns {string|{}} 2746 */ 2747 this.getMetadata = function (raw) { 2748 if (raw) { 2749 return metadata.raw; 2750 } else { 2751 return metadata.parsed; 2752 } 2753 }; 2754 2755 /** 2756 * Get the metadata format of the previously parsed document 2757 * @returns {string} 2758 */ 2759 this.getMetadataFormat = function () { 2760 return metadata.format; 2761 }; 2762 2763 /** 2764 * Private: set a single key, value metadata pair 2765 * @param {string} key 2766 * @param {string} value 2767 */ 2768 this._setMetadataPair = function (key, value) { 2769 metadata.parsed[key] = value; 2770 }; 2771 2772 /** 2773 * Private: set metadata format 2774 * @param {string} format 2775 */ 2776 this._setMetadataFormat = function (format) { 2777 metadata.format = format; 2778 }; 2779 2780 /** 2781 * Private: set metadata raw text 2782 * @param {string} raw 2783 */ 2784 this._setMetadataRaw = function (raw) { 2785 metadata.raw = raw; 2786 }; 2787};
vendor: 51,121 bytes, lines 2788-4276
2788 2789/** 2790 * Turn Markdown link shortcuts into XHTML <a> tags. 2791 */ 2792showdown.subParser('anchors', function (text, options, globals) { 2793 'use strict'; 2794 2795 text = globals.converter._dispatch('anchors.before', text, options, globals); 2796 2797 var writeAnchorTag = function (wholeMatch, linkText, linkId, url, m5, m6, title) { 2798 if (showdown.helper.isUndefined(title)) { 2799 title = ''; 2800 } 2801 linkId = linkId.toLowerCase(); 2802 2803 // Special case for explicit empty url 2804 if (wholeMatch.search(/\(<?\s*>? ?(['"].*['"])?\)$/m) > -1) { 2805 url = ''; 2806 } else if (!url) { 2807 if (!linkId) { 2808 // lower-case and turn embedded newlines into spaces 2809 linkId = linkText.toLowerCase().replace(/ ?\n/g, ' '); 2810 } 2811 url = '#' + linkId; 2812 2813 if (!showdown.helper.isUndefined(globals.gUrls[linkId])) { 2814 url = globals.gUrls[linkId]; 2815 if (!showdown.helper.isUndefined(globals.gTitles[linkId])) { 2816 title = globals.gTitles[linkId]; 2817 } 2818 } else { 2819 return wholeMatch; 2820 } 2821 } 2822 2823 //url = showdown.helper.escapeCharacters(url, '*_', false); // replaced line to improve performance 2824 url = url.replace(showdown.helper.regexes.asteriskDashAndColon, showdown.helper.escapeCharactersCallback); 2825 2826 var result = '<a href="' + url + '"'; 2827 2828 if (title !== '' && title !== null) { 2829 title = title.replace(/"/g, '"'); 2830 //title = showdown.helper.escapeCharacters(title, '*_', false); // replaced line to improve performance 2831 title = title.replace(showdown.helper.regexes.asteriskDashAndColon, showdown.helper.escapeCharactersCallback); 2832 result += ' title="' + title + '"'; 2833 } 2834 2835 // optionLinksInNewWindow only applies 2836 // to external links. Hash links (#) open in same page 2837 if (options.openLinksInNewWindow && !/^#/.test(url)) { 2838 // escaped _ 2839 result += ' rel="noopener noreferrer" target="¨E95Eblank"'; 2840 } 2841 2842 result += '>' + linkText + '</a>'; 2843 2844 return result; 2845 }; 2846 2847 // First, handle reference-style links: [link text] [id] 2848 text = text.replace(/\[((?:\[[^\]]*]|[^\[\]])*)] ?(?:\n *)?\[(.*?)]()()()()/g, writeAnchorTag); 2849 2850 // Next, inline-style links: [link text](url "optional title") 2851 // cases with crazy urls like ./image/cat1).png 2852 text = text.replace(/\[((?:\[[^\]]*]|[^\[\]])*)]()[ \t]*\([ \t]?<([^>]*)>(?:[ \t]*((["'])([^"]*?)\5))?[ \t]?\)/g, 2853 writeAnchorTag); 2854 2855 // normal cases 2856 text = text.replace(/\[((?:\[[^\]]*]|[^\[\]])*)]()[ \t]*\([ \t]?<?([\S]+?(?:\([\S]*?\)[\S]*?)?)>?(?:[ \t]*((["'])([^"]*?)\5))?[ \t]?\)/g, 2857 writeAnchorTag); 2858 2859 // handle reference-style shortcuts: [link text] 2860 // These must come last in case you've also got [link test][1] 2861 // or [link test](/foo) 2862 text = text.replace(/\[([^\[\]]+)]()()()()()/g, writeAnchorTag); 2863 2864 // Lastly handle GithubMentions if option is enabled 2865 if (options.ghMentions) { 2866 text = text.replace(/(^|\s)(\\)?(@([a-z\d]+(?:[a-z\d.-]+?[a-z\d]+)*))/gmi, function (wm, st, escape, mentions, username) { 2867 if (escape === '\\') { 2868 return st + mentions; 2869 } 2870 2871 //check if options.ghMentionsLink is a string 2872 if (!showdown.helper.isString(options.ghMentionsLink)) { 2873 throw new Error('ghMentionsLink option must be a string'); 2874 } 2875 var lnk = options.ghMentionsLink.replace(/\{u}/g, username), 2876 target = ''; 2877 if (options.openLinksInNewWindow) { 2878 target = ' rel="noopener noreferrer" target="¨E95Eblank"'; 2879 } 2880 return st + '<a href="' + lnk + '"' + target + '>' + mentions + '</a>'; 2881 }); 2882 } 2883 2884 text = globals.converter._dispatch('anchors.after', text, options, globals); 2885 return text; 2886}); 2887 2888// url allowed chars [a-z\d_.~:/?#[]@!$&'()*+,;=-] 2889 2890var simpleURLRegex = /([*~_]+|\b)(((https?|ftp|dict):\/\/|www\.)[^'">\s]+?\.[^'">\s]+?)()(\1)?(?=\s|$)(?!["<>])/gi, 2891 simpleURLRegex2 = /([*~_]+|\b)(((https?|ftp|dict):\/\/|www\.)[^'">\s]+\.[^'">\s]+?)([.!?,()\[\]])?(\1)?(?=\s|$)(?!["<>])/gi, 2892 delimUrlRegex = /()<(((https?|ftp|dict):\/\/|www\.)[^'">\s]+)()>()/gi, 2893 simpleMailRegex = /(^|\s)(?:mailto:)?([A-Za-z0-9!#$%&'*+-/=?^_`{|}~.]+@[-a-z0-9]+(\.[-a-z0-9]+)*\.[a-z]+)(?=$|\s)/gmi, 2894 delimMailRegex = /<()(?:mailto:)?([-.\w]+@[-a-z0-9]+(\.[-a-z0-9]+)*\.[a-z]+)>/gi, 2895 2896 replaceLink = function (options) { 2897 'use strict'; 2898 return function (wm, leadingMagicChars, link, m2, m3, trailingPunctuation, trailingMagicChars) { 2899 link = link.replace(showdown.helper.regexes.asteriskDashAndColon, showdown.helper.escapeCharactersCallback); 2900 var lnkTxt = link, 2901 append = '', 2902 target = '', 2903 lmc = leadingMagicChars || '', 2904 tmc = trailingMagicChars || ''; 2905 if (/^www\./i.test(link)) { 2906 link = link.replace(/^www\./i, 'http://www.'); 2907 } 2908 if (options.excludeTrailingPunctuationFromURLs && trailingPunctuation) { 2909 append = trailingPunctuation; 2910 } 2911 if (options.openLinksInNewWindow) { 2912 target = ' rel="noopener noreferrer" target="¨E95Eblank"'; 2913 } 2914 return lmc + '<a href="' + link + '"' + target + '>' + lnkTxt + '</a>' + append + tmc; 2915 }; 2916 }, 2917 2918 replaceMail = function (options, globals) { 2919 'use strict'; 2920 return function (wholeMatch, b, mail) { 2921 var href = 'mailto:'; 2922 b = b || ''; 2923 mail = showdown.subParser('unescapeSpecialChars')(mail, options, globals); 2924 if (options.encodeEmails) { 2925 href = showdown.helper.encodeEmailAddress(href + mail); 2926 mail = showdown.helper.encodeEmailAddress(mail); 2927 } else { 2928 href = href + mail; 2929 } 2930 return b + '<a href="' + href + '">' + mail + '</a>'; 2931 }; 2932 }; 2933 2934showdown.subParser('autoLinks', function (text, options, globals) { 2935 'use strict'; 2936 2937 text = globals.converter._dispatch('autoLinks.before', text, options, globals); 2938 2939 text = text.replace(delimUrlRegex, replaceLink(options)); 2940 text = text.replace(delimMailRegex, replaceMail(options, globals)); 2941 2942 text = globals.converter._dispatch('autoLinks.after', text, options, globals); 2943 2944 return text; 2945}); 2946 2947showdown.subParser('simplifiedAutoLinks', function (text, options, globals) { 2948 'use strict'; 2949 2950 if (!options.simplifiedAutoLink) { 2951 return text; 2952 } 2953 2954 text = globals.converter._dispatch('simplifiedAutoLinks.before', text, options, globals); 2955 2956 if (options.excludeTrailingPunctuationFromURLs) { 2957 text = text.replace(simpleURLRegex2, replaceLink(options)); 2958 } else { 2959 text = text.replace(simpleURLRegex, replaceLink(options)); 2960 } 2961 text = text.replace(simpleMailRegex, replaceMail(options, globals)); 2962 2963 text = globals.converter._dispatch('simplifiedAutoLinks.after', text, options, globals); 2964 2965 return text; 2966}); 2967 2968/** 2969 * These are all the transformations that form block-level 2970 * tags like paragraphs, headers, and list items. 2971 */ 2972showdown.subParser('blockGamut', function (text, options, globals) { 2973 'use strict'; 2974 2975 text = globals.converter._dispatch('blockGamut.before', text, options, globals); 2976 2977 // we parse blockquotes first so that we can have headings and hrs 2978 // inside blockquotes 2979 text = showdown.subParser('blockQuotes')(text, options, globals); 2980 text = showdown.subParser('headers')(text, options, globals); 2981 2982 // Do Horizontal Rules: 2983 text = showdown.subParser('horizontalRule')(text, options, globals); 2984 2985 text = showdown.subParser('lists')(text, options, globals); 2986 text = showdown.subParser('codeBlocks')(text, options, globals); 2987 text = showdown.subParser('tables')(text, options, globals); 2988 2989 // We already ran _HashHTMLBlocks() before, in Markdown(), but that 2990 // was to escape raw HTML in the original Markdown source. This time, 2991 // we're escaping the markup we've just created, so that we don't wrap 2992 // <p> tags around block-level tags. 2993 text = showdown.subParser('hashHTMLBlocks')(text, options, globals); 2994 text = showdown.subParser('paragraphs')(text, options, globals); 2995 2996 text = globals.converter._dispatch('blockGamut.after', text, options, globals); 2997 2998 return text; 2999}); 3000 3001showdown.subParser('blockQuotes', function (text, options, globals) { 3002 'use strict'; 3003 3004 text = globals.converter._dispatch('blockQuotes.before', text, options, globals); 3005 3006 // add a couple extra lines after the text and endtext mark 3007 text = text + '\n\n'; 3008 3009 var rgx = /(^ {0,3}>[ \t]?.+\n(.+\n)*\n*)+/gm; 3010 3011 if (options.splitAdjacentBlockquotes) { 3012 rgx = /^ {0,3}>[\s\S]*?(?:\n\n)/gm; 3013 } 3014 3015 text = text.replace(rgx, function (bq) { 3016 // attacklab: hack around Konqueror 3.5.4 bug: 3017 // "----------bug".replace(/^-/g,"") == "bug" 3018 bq = bq.replace(/^[ \t]*>[ \t]?/gm, ''); // trim one level of quoting 3019 3020 // attacklab: clean up hack 3021 bq = bq.replace(/¨0/g, ''); 3022 3023 bq = bq.replace(/^[ \t]+$/gm, ''); // trim whitespace-only lines 3024 bq = showdown.subParser('githubCodeBlocks')(bq, options, globals); 3025 bq = showdown.subParser('blockGamut')(bq, options, globals); // recurse 3026 3027 bq = bq.replace(/(^|\n)/g, '$1 '); 3028 // These leading spaces screw with <pre> content, so we need to fix that: 3029 bq = bq.replace(/(\s*<pre>[^\r]+?<\/pre>)/gm, function (wholeMatch, m1) { 3030 var pre = m1; 3031 // attacklab: hack around Konqueror 3.5.4 bug: 3032 pre = pre.replace(/^ /mg, '¨0'); 3033 pre = pre.replace(/¨0/g, ''); 3034 return pre; 3035 }); 3036 3037 return showdown.subParser('hashBlock')('<blockquote>\n' + bq + '\n</blockquote>', options, globals); 3038 }); 3039 3040 text = globals.converter._dispatch('blockQuotes.after', text, options, globals); 3041 return text; 3042}); 3043 3044/** 3045 * Process Markdown `<pre><code>` blocks. 3046 */ 3047showdown.subParser('codeBlocks', function (text, options, globals) { 3048 'use strict'; 3049 3050 text = globals.converter._dispatch('codeBlocks.before', text, options, globals); 3051 3052 // sentinel workarounds for lack of \A and \Z, safari\khtml bug 3053 text += '¨0'; 3054 3055 var pattern = /(?:\n\n|^)((?:(?:[ ]{4}|\t).*\n+)+)(\n*[ ]{0,3}[^ \t\n]|(?=¨0))/g; 3056 text = text.replace(pattern, function (wholeMatch, m1, m2) { 3057 var codeblock = m1, 3058 nextChar = m2, 3059 end = '\n'; 3060 3061 codeblock = showdown.subParser('outdent')(codeblock, options, globals); 3062 codeblock = showdown.subParser('encodeCode')(codeblock, options, globals); 3063 codeblock = showdown.subParser('detab')(codeblock, options, globals); 3064 codeblock = codeblock.replace(/^\n+/g, ''); // trim leading newlines 3065 codeblock = codeblock.replace(/\n+$/g, ''); // trim trailing newlines 3066 3067 if (options.omitExtraWLInCodeBlocks) { 3068 end = ''; 3069 } 3070 3071 codeblock = '<pre><code>' + codeblock + end + '</code></pre>'; 3072 3073 return showdown.subParser('hashBlock')(codeblock, options, globals) + nextChar; 3074 }); 3075 3076 // strip sentinel 3077 text = text.replace(/¨0/, ''); 3078 3079 text = globals.converter._dispatch('codeBlocks.after', text, options, globals); 3080 return text; 3081}); 3082 3083/** 3084 * 3085 * * Backtick quotes are used for <code></code> spans. 3086 * 3087 * * You can use multiple backticks as the delimiters if you want to 3088 * include literal backticks in the code span. So, this input: 3089 * 3090 * Just type ``foo `bar` baz`` at the prompt. 3091 * 3092 * Will translate to: 3093 * 3094 * <p>Just type <code>foo `bar` baz</code> at the prompt.</p> 3095 * 3096 * There's no arbitrary limit to the number of backticks you 3097 * can use as delimters. If you need three consecutive backticks 3098 * in your code, use four for delimiters, etc. 3099 * 3100 * * You can use spaces to get literal backticks at the edges: 3101 * 3102 * ... type `` `bar` `` ... 3103 * 3104 * Turns to: 3105 * 3106 * ... type <code>`bar`</code> ... 3107 */ 3108showdown.subParser('codeSpans', function (text, options, globals) { 3109 'use strict'; 3110 3111 text = globals.converter._dispatch('codeSpans.before', text, options, globals); 3112 3113 if (typeof (text) === 'undefined') { 3114 text = ''; 3115 } 3116 text = text.replace(/(^|[^\\])(`+)([^\r]*?[^`])\2(?!`)/gm, 3117 function (wholeMatch, m1, m2, m3) { 3118 var c = m3; 3119 c = c.replace(/^([ \t]*)/g, ''); // leading whitespace 3120 c = c.replace(/[ \t]*$/g, ''); // trailing whitespace 3121 c = showdown.subParser('encodeCode')(c, options, globals); 3122 c = m1 + '<code>' + c + '</code>'; 3123 c = showdown.subParser('hashHTMLSpans')(c, options, globals); 3124 return c; 3125 } 3126 ); 3127 3128 text = globals.converter._dispatch('codeSpans.after', text, options, globals); 3129 return text; 3130}); 3131 3132/** 3133 * Create a full HTML document from the processed markdown 3134 */ 3135showdown.subParser('completeHTMLDocument', function (text, options, globals) { 3136 'use strict'; 3137 3138 if (!options.completeHTMLDocument) { 3139 return text; 3140 } 3141 3142 text = globals.converter._dispatch('completeHTMLDocument.before', text, options, globals); 3143 3144 var doctype = 'html', 3145 doctypeParsed = '<!DOCTYPE HTML>\n', 3146 title = '', 3147 charset = '<meta charset="utf-8">\n', 3148 lang = '', 3149 metadata = ''; 3150 3151 if (typeof globals.metadata.parsed.doctype !== 'undefined') { 3152 doctypeParsed = '<!DOCTYPE ' + globals.metadata.parsed.doctype + '>\n'; 3153 doctype = globals.metadata.parsed.doctype.toString().toLowerCase(); 3154 if (doctype === 'html' || doctype === 'html5') { 3155 charset = '<meta charset="utf-8">'; 3156 } 3157 } 3158 3159 for (var meta in globals.metadata.parsed) { 3160 if (globals.metadata.parsed.hasOwnProperty(meta)) { 3161 switch (meta.toLowerCase()) { 3162 case 'doctype': 3163 break; 3164 3165 case 'title': 3166 title = '<title>' + globals.metadata.parsed.title + '</title>\n'; 3167 break; 3168 3169 case 'charset': 3170 if (doctype === 'html' || doctype === 'html5') { 3171 charset = '<meta charset="' + globals.metadata.parsed.charset + '">\n'; 3172 } else { 3173 charset = '<meta name="charset" content="' + globals.metadata.parsed.charset + '">\n'; 3174 } 3175 break; 3176 3177 case 'language': 3178 case 'lang': 3179 lang = ' lang="' + globals.metadata.parsed[meta] + '"'; 3180 metadata += '<meta name="' + meta + '" content="' + globals.metadata.parsed[meta] + '">\n'; 3181 break; 3182 3183 default: 3184 metadata += '<meta name="' + meta + '" content="' + globals.metadata.parsed[meta] + '">\n'; 3185 } 3186 } 3187 } 3188 3189 text = doctypeParsed + '<html' + lang + '>\n<head>\n' + title + charset + metadata + '</head>\n<body>\n' + text.trim() + '\n</body>\n</html>'; 3190 3191 text = globals.converter._dispatch('completeHTMLDocument.after', text, options, globals); 3192 return text; 3193}); 3194 3195/** 3196 * Convert all tabs to spaces 3197 */ 3198showdown.subParser('detab', function (text, options, globals) { 3199 'use strict'; 3200 text = globals.converter._dispatch('detab.before', text, options, globals); 3201 3202 // expand first n-1 tabs 3203 text = text.replace(/\t(?=\t)/g, ' '); // g_tab_width 3204 3205 // replace the nth with two sentinels 3206 text = text.replace(/\t/g, '¨A¨B'); 3207 3208 // use the sentinel to anchor our regex so it doesn't explode 3209 text = text.replace(/¨B(.+?)¨A/g, function (wholeMatch, m1) { 3210 var leadingText = m1, 3211 numSpaces = 4 - leadingText.length % 4; // g_tab_width 3212 3213 // there *must* be a better way to do this: 3214 for (var i = 0; i < numSpaces; i++) { 3215 leadingText += ' '; 3216 } 3217 3218 return leadingText; 3219 }); 3220 3221 // clean up sentinels 3222 text = text.replace(/¨A/g, ' '); // g_tab_width 3223 text = text.replace(/¨B/g, ''); 3224 3225 text = globals.converter._dispatch('detab.after', text, options, globals); 3226 return text; 3227}); 3228 3229showdown.subParser('ellipsis', function (text, options, globals) { 3230 'use strict'; 3231 3232 if (!options.ellipsis) { 3233 return text; 3234 } 3235 3236 text = globals.converter._dispatch('ellipsis.before', text, options, globals); 3237 3238 text = text.replace(/\.\.\./g, 'â¦'); 3239 3240 text = globals.converter._dispatch('ellipsis.after', text, options, globals); 3241 3242 return text; 3243}); 3244 3245/** 3246 * Turn emoji codes into emojis 3247 * 3248 * List of supported emojis: https://github.com/showdownjs/showdown/wiki/Emojis 3249 */ 3250showdown.subParser('emoji', function (text, options, globals) { 3251 'use strict'; 3252 3253 if (!options.emoji) { 3254 return text; 3255 } 3256 3257 text = globals.converter._dispatch('emoji.before', text, options, globals); 3258 3259 var emojiRgx = /:([\S]+?):/g; 3260 3261 text = text.replace(emojiRgx, function (wm, emojiCode) { 3262 if (showdown.helper.emojis.hasOwnProperty(emojiCode)) { 3263 return showdown.helper.emojis[emojiCode]; 3264 } 3265 return wm; 3266 }); 3267 3268 text = globals.converter._dispatch('emoji.after', text, options, globals); 3269 3270 return text; 3271}); 3272 3273/** 3274 * Smart processing for ampersands and angle brackets that need to be encoded. 3275 */ 3276showdown.subParser('encodeAmpsAndAngles', function (text, options, globals) { 3277 'use strict'; 3278 text = globals.converter._dispatch('encodeAmpsAndAngles.before', text, options, globals); 3279 3280 // Ampersand-encoding based entirely on Nat Irons's Amputator MT plugin: 3281 // http://bumppo.net/projects/amputator/ 3282 text = text.replace(/&(?!#?[xX]?(?:[0-9a-fA-F]+|\w+);)/g, '&'); 3283 3284 // Encode naked <'s 3285 text = text.replace(/<(?![a-z\/?$!])/gi, '<'); 3286 3287 // Encode < 3288 text = text.replace(/</g, '<'); 3289 3290 // Encode > 3291 text = text.replace(/>/g, '>'); 3292 3293 text = globals.converter._dispatch('encodeAmpsAndAngles.after', text, options, globals); 3294 return text; 3295}); 3296 3297/** 3298 * Returns the string, with after processing the following backslash escape sequences. 3299 * 3300 * attacklab: The polite way to do this is with the new escapeCharacters() function: 3301 * 3302 * text = escapeCharacters(text,"\\",true); 3303 * text = escapeCharacters(text,"`*_{}[]()>#+-.!",true); 3304 * 3305 * ...but we're sidestepping its use of the (slow) RegExp constructor 3306 * as an optimization for Firefox. This function gets called a LOT. 3307 */ 3308showdown.subParser('encodeBackslashEscapes', function (text, options, globals) { 3309 'use strict'; 3310 text = globals.converter._dispatch('encodeBackslashEscapes.before', text, options, globals); 3311 3312 text = text.replace(/\\(\\)/g, showdown.helper.escapeCharactersCallback); 3313 text = text.replace(/\\([`*_{}\[\]()>#+.!~=|:-])/g, showdown.helper.escapeCharactersCallback); 3314 3315 text = globals.converter._dispatch('encodeBackslashEscapes.after', text, options, globals); 3316 return text; 3317}); 3318 3319/** 3320 * Encode/escape certain characters inside Markdown code runs. 3321 * The point is that in code, these characters are literals, 3322 * and lose their special Markdown meanings. 3323 */ 3324showdown.subParser('encodeCode', function (text, options, globals) { 3325 'use strict'; 3326 3327 text = globals.converter._dispatch('encodeCode.before', text, options, globals); 3328 3329 // Encode all ampersands; HTML entities are not 3330 // entities within a Markdown code span. 3331 text = text 3332 .replace(/&/g, '&') 3333 // Do the angle bracket song and dance: 3334 .replace(/</g, '<') 3335 .replace(/>/g, '>') 3336 // Now, escape characters that are magic in Markdown: 3337 .replace(/([*_{}\[\]\\=~-])/g, showdown.helper.escapeCharactersCallback); 3338 3339 text = globals.converter._dispatch('encodeCode.after', text, options, globals); 3340 return text; 3341}); 3342 3343/** 3344 * Within tags -- meaning between < and > -- encode [\ ` * _ ~ =] so they 3345 * don't conflict with their use in Markdown for code, italics and strong. 3346 */ 3347showdown.subParser('escapeSpecialCharsWithinTagAttributes', function (text, options, globals) { 3348 'use strict'; 3349 text = globals.converter._dispatch('escapeSpecialCharsWithinTagAttributes.before', text, options, globals); 3350 3351 // Build a regex to find HTML tags. 3352 var tags = /<\/?[a-z\d_:-]+(?:[\s]+[\s\S]+?)?>/gi, 3353 comments = /<!(--(?:(?:[^>-]|-[^>])(?:[^-]|-[^-])*)--)>/gi; 3354 3355 text = text.replace(tags, function (wholeMatch) { 3356 return wholeMatch 3357 .replace(/(.)<\/?code>(?=.)/g, '$1`') 3358 .replace(/([\\`*_~=|])/g, showdown.helper.escapeCharactersCallback); 3359 }); 3360 3361 text = text.replace(comments, function (wholeMatch) { 3362 return wholeMatch 3363 .replace(/([\\`*_~=|])/g, showdown.helper.escapeCharactersCallback); 3364 }); 3365 3366 text = globals.converter._dispatch('escapeSpecialCharsWithinTagAttributes.after', text, options, globals); 3367 return text; 3368}); 3369 3370/** 3371 * Handle github codeblocks prior to running HashHTML so that 3372 * HTML contained within the codeblock gets escaped properly 3373 * Example: 3374 * ```ruby 3375 * def hello_world(x) 3376 * puts "Hello, #{x}" 3377 * end 3378 * ``` 3379 */ 3380showdown.subParser('githubCodeBlocks', function (text, options, globals) { 3381 'use strict'; 3382 3383 // early exit if option is not enabled 3384 if (!options.ghCodeBlocks) { 3385 return text; 3386 } 3387 3388 text = globals.converter._dispatch('githubCodeBlocks.before', text, options, globals); 3389 3390 text += '¨0'; 3391 3392 text = text.replace(/(?:^|\n)(?: {0,3})(```+|~~~+)(?: *)([^\s`~]*)\n([\s\S]*?)\n(?: {0,3})\1/g, function (wholeMatch, delim, language, codeblock) { 3393 var end = (options.omitExtraWLInCodeBlocks) ? '' : '\n'; 3394 3395 // First parse the github code block 3396 codeblock = showdown.subParser('encodeCode')(codeblock, options, globals); 3397 codeblock = showdown.subParser('detab')(codeblock, options, globals); 3398 codeblock = codeblock.replace(/^\n+/g, ''); // trim leading newlines 3399 codeblock = codeblock.replace(/\n+$/g, ''); // trim trailing whitespace 3400 3401 codeblock = '<pre><code' + (language ? ' class="' + language + ' language-' + language + '"' : '') + '>' + codeblock + end + '</code></pre>'; 3402 3403 codeblock = showdown.subParser('hashBlock')(codeblock, options, globals); 3404 3405 // Since GHCodeblocks can be false positives, we need to 3406 // store the primitive text and the parsed text in a global var, 3407 // and then return a token 3408 return '\n\n¨G' + (globals.ghCodeBlocks.push({text: wholeMatch, codeblock: codeblock}) - 1) + 'G\n\n'; 3409 }); 3410 3411 // attacklab: strip sentinel 3412 text = text.replace(/¨0/, ''); 3413 3414 return globals.converter._dispatch('githubCodeBlocks.after', text, options, globals); 3415}); 3416 3417showdown.subParser('hashBlock', function (text, options, globals) { 3418 'use strict'; 3419 text = globals.converter._dispatch('hashBlock.before', text, options, globals); 3420 text = text.replace(/(^\n+|\n+$)/g, ''); 3421 text = '\n\n¨K' + (globals.gHtmlBlocks.push(text) - 1) + 'K\n\n'; 3422 text = globals.converter._dispatch('hashBlock.after', text, options, globals); 3423 return text; 3424}); 3425 3426/** 3427 * Hash and escape <code> elements that should not be parsed as markdown 3428 */ 3429showdown.subParser('hashCodeTags', function (text, options, globals) { 3430 'use strict'; 3431 text = globals.converter._dispatch('hashCodeTags.before', text, options, globals); 3432 3433 var repFunc = function (wholeMatch, match, left, right) { 3434 var codeblock = left + showdown.subParser('encodeCode')(match, options, globals) + right; 3435 return '¨C' + (globals.gHtmlSpans.push(codeblock) - 1) + 'C'; 3436 }; 3437 3438 // Hash naked <code> 3439 text = showdown.helper.replaceRecursiveRegExp(text, repFunc, '<code\\b[^>]*>', '</code>', 'gim'); 3440 3441 text = globals.converter._dispatch('hashCodeTags.after', text, options, globals); 3442 return text; 3443}); 3444 3445showdown.subParser('hashElement', function (text, options, globals) { 3446 'use strict'; 3447 3448 return function (wholeMatch, m1) { 3449 var blockText = m1; 3450 3451 // Undo double lines 3452 blockText = blockText.replace(/\n\n/g, '\n'); 3453 blockText = blockText.replace(/^\n/, ''); 3454 3455 // strip trailing blank lines 3456 blockText = blockText.replace(/\n+$/g, ''); 3457 3458 // Replace the element text with a marker ("¨KxK" where x is its key) 3459 blockText = '\n\n¨K' + (globals.gHtmlBlocks.push(blockText) - 1) + 'K\n\n'; 3460 3461 return blockText; 3462 }; 3463}); 3464 3465showdown.subParser('hashHTMLBlocks', function (text, options, globals) { 3466 'use strict'; 3467 text = globals.converter._dispatch('hashHTMLBlocks.before', text, options, globals); 3468 3469 var blockTags = [ 3470 'pre', 3471 'div', 3472 'h1', 3473 'h2', 3474 'h3', 3475 'h4', 3476 'h5', 3477 'h6', 3478 'blockquote', 3479 'table', 3480 'dl', 3481 'ol', 3482 'ul', 3483 'script', 3484 'noscript', 3485 'form', 3486 'fieldset', 3487 'iframe', 3488 'math', 3489 'style', 3490 'section', 3491 'header', 3492 'footer', 3493 'nav', 3494 'article', 3495 'aside', 3496 'address', 3497 'audio', 3498 'canvas', 3499 'figure', 3500 'hgroup', 3501 'output', 3502 'video', 3503 'p' 3504 ], 3505 repFunc = function (wholeMatch, match, left, right) { 3506 var txt = wholeMatch; 3507 // check if this html element is marked as markdown 3508 // if so, it's contents should be parsed as markdown 3509 if (left.search(/\bmarkdown\b/) !== -1) { 3510 txt = left + globals.converter.makeHtml(match) + right; 3511 } 3512 return '\n\n¨K' + (globals.gHtmlBlocks.push(txt) - 1) + 'K\n\n'; 3513 }; 3514 3515 if (options.backslashEscapesHTMLTags) { 3516 // encode backslash escaped HTML tags 3517 text = text.replace(/\\<(\/?[^>]+?)>/g, function (wm, inside) { 3518 return '<' + inside + '>'; 3519 }); 3520 } 3521 3522 // hash HTML Blocks 3523 for (var i = 0; i < blockTags.length; ++i) { 3524 3525 var opTagPos, 3526 rgx1 = new RegExp('^ {0,3}(<' + blockTags[i] + '\\b[^>]*>)', 'im'), 3527 patLeft = '<' + blockTags[i] + '\\b[^>]*>', 3528 patRight = '</' + blockTags[i] + '>'; 3529 // 1. Look for the first position of the first opening HTML tag in the text 3530 while ((opTagPos = showdown.helper.regexIndexOf(text, rgx1)) !== -1) { 3531 3532 // if the HTML tag is \ escaped, we need to escape it and break 3533 3534 3535 //2. Split the text in that position 3536 var subTexts = showdown.helper.splitAtIndex(text, opTagPos), 3537 //3. Match recursively 3538 newSubText1 = showdown.helper.replaceRecursiveRegExp(subTexts[1], repFunc, patLeft, patRight, 'im'); 3539 3540 // prevent an infinite loop 3541 if (newSubText1 === subTexts[1]) { 3542 break; 3543 } 3544 text = subTexts[0].concat(newSubText1); 3545 } 3546 } 3547 // HR SPECIAL CASE 3548 text = text.replace(/(\n {0,3}(<(hr)\b([^<>])*?\/?>)[ \t]*(?=\n{2,}))/g, 3549 showdown.subParser('hashElement')(text, options, globals)); 3550 3551 // Special case for standalone HTML comments 3552 text = showdown.helper.replaceRecursiveRegExp(text, function (txt) { 3553 return '\n\n¨K' + (globals.gHtmlBlocks.push(txt) - 1) + 'K\n\n'; 3554 }, '^ {0,3}<!--', '-->', 'gm'); 3555 3556 // PHP and ASP-style processor instructions (<?...?> and <%...%>) 3557 text = text.replace(/(?:\n\n)( {0,3}(?:<([?%])[^\r]*?\2>)[ \t]*(?=\n{2,}))/g, 3558 showdown.subParser('hashElement')(text, options, globals)); 3559 3560 text = globals.converter._dispatch('hashHTMLBlocks.after', text, options, globals); 3561 return text; 3562}); 3563 3564/** 3565 * Hash span elements that should not be parsed as markdown 3566 */ 3567showdown.subParser('hashHTMLSpans', function (text, options, globals) { 3568 'use strict'; 3569 text = globals.converter._dispatch('hashHTMLSpans.before', text, options, globals); 3570 3571 function hashHTMLSpan (html) { 3572 return '¨C' + (globals.gHtmlSpans.push(html) - 1) + 'C'; 3573 } 3574 3575 // Hash Self Closing tags 3576 text = text.replace(/<[^>]+?\/>/gi, function (wm) { 3577 return hashHTMLSpan(wm); 3578 }); 3579 3580 // Hash tags without properties 3581 text = text.replace(/<([^>]+?)>[\s\S]*?<\/\1>/g, function (wm) { 3582 return hashHTMLSpan(wm); 3583 }); 3584 3585 // Hash tags with properties 3586 text = text.replace(/<([^>]+?)\s[^>]+?>[\s\S]*?<\/\1>/g, function (wm) { 3587 return hashHTMLSpan(wm); 3588 }); 3589 3590 // Hash self closing tags without /> 3591 text = text.replace(/<[^>]+?>/gi, function (wm) { 3592 return hashHTMLSpan(wm); 3593 }); 3594 3595 /*showdown.helper.matchRecursiveRegExp(text, '<code\\b[^>]*>', '</code>', 'gi');*/ 3596 3597 text = globals.converter._dispatch('hashHTMLSpans.after', text, options, globals); 3598 return text; 3599}); 3600 3601/** 3602 * Unhash HTML spans 3603 */ 3604showdown.subParser('unhashHTMLSpans', function (text, options, globals) { 3605 'use strict'; 3606 text = globals.converter._dispatch('unhashHTMLSpans.before', text, options, globals); 3607 3608 for (var i = 0; i < globals.gHtmlSpans.length; ++i) { 3609 var repText = globals.gHtmlSpans[i], 3610 // limiter to prevent infinite loop (assume 10 as limit for recurse) 3611 limit = 0; 3612 3613 while (/¨C(\d+)C/.test(repText)) { 3614 var num = RegExp.$1; 3615 repText = repText.replace('¨C' + num + 'C', globals.gHtmlSpans[num]); 3616 if (limit === 10) { 3617 console.error('maximum nesting of 10 spans reached!!!'); 3618 break; 3619 } 3620 ++limit; 3621 } 3622 text = text.replace('¨C' + i + 'C', repText); 3623 } 3624 3625 text = globals.converter._dispatch('unhashHTMLSpans.after', text, options, globals); 3626 return text; 3627}); 3628 3629/** 3630 * Hash and escape <pre><code> elements that should not be parsed as markdown 3631 */ 3632showdown.subParser('hashPreCodeTags', function (text, options, globals) { 3633 'use strict'; 3634 text = globals.converter._dispatch('hashPreCodeTags.before', text, options, globals); 3635 3636 var repFunc = function (wholeMatch, match, left, right) { 3637 // encode html entities 3638 var codeblock = left + showdown.subParser('encodeCode')(match, options, globals) + right; 3639 return '\n\n¨G' + (globals.ghCodeBlocks.push({text: wholeMatch, codeblock: codeblock}) - 1) + 'G\n\n'; 3640 }; 3641 3642 // Hash <pre><code> 3643 text = showdown.helper.replaceRecursiveRegExp(text, repFunc, '^ {0,3}<pre\\b[^>]*>\\s*<code\\b[^>]*>', '^ {0,3}</code>\\s*</pre>', 'gim'); 3644 3645 text = globals.converter._dispatch('hashPreCodeTags.after', text, options, globals); 3646 return text; 3647}); 3648 3649showdown.subParser('headers', function (text, options, globals) { 3650 'use strict'; 3651 3652 text = globals.converter._dispatch('headers.before', text, options, globals); 3653 3654 var headerLevelStart = (isNaN(parseInt(options.headerLevelStart))) ? 1 : parseInt(options.headerLevelStart), 3655 3656 // Set text-style headers: 3657 // Header 1 3658 // ======== 3659 // 3660 // Header 2 3661 // -------- 3662 // 3663 setextRegexH1 = (options.smoothLivePreview) ? /^(.+)[ \t]*\n={2,}[ \t]*\n+/gm : /^(.+)[ \t]*\n=+[ \t]*\n+/gm, 3664 setextRegexH2 = (options.smoothLivePreview) ? /^(.+)[ \t]*\n-{2,}[ \t]*\n+/gm : /^(.+)[ \t]*\n-+[ \t]*\n+/gm; 3665 3666 text = text.replace(setextRegexH1, function (wholeMatch, m1) { 3667 3668 var spanGamut = showdown.subParser('spanGamut')(m1, options, globals), 3669 hID = (options.noHeaderId) ? '' : ' id="' + headerId(m1) + '"', 3670 hLevel = headerLevelStart, 3671 hashBlock = '<h' + hLevel + hID + '>' + spanGamut + '</h' + hLevel + '>'; 3672 return showdown.subParser('hashBlock')(hashBlock, options, globals); 3673 }); 3674 3675 text = text.replace(setextRegexH2, function (matchFound, m1) { 3676 var spanGamut = showdown.subParser('spanGamut')(m1, options, globals), 3677 hID = (options.noHeaderId) ? '' : ' id="' + headerId(m1) + '"', 3678 hLevel = headerLevelStart + 1, 3679 hashBlock = '<h' + hLevel + hID + '>' + spanGamut + '</h' + hLevel + '>'; 3680 return showdown.subParser('hashBlock')(hashBlock, options, globals); 3681 }); 3682 3683 // atx-style headers: 3684 // # Header 1 3685 // ## Header 2 3686 // ## Header 2 with closing hashes ## 3687 // ... 3688 // ###### Header 6 3689 // 3690 var atxStyle = (options.requireSpaceBeforeHeadingText) ? /^(#{1,6})[ \t]+(.+?)[ \t]*#*\n+/gm : /^(#{1,6})[ \t]*(.+?)[ \t]*#*\n+/gm; 3691 3692 text = text.replace(atxStyle, function (wholeMatch, m1, m2) { 3693 var hText = m2; 3694 if (options.customizedHeaderId) { 3695 hText = m2.replace(/\s?\{([^{]+?)}\s*$/, ''); 3696 } 3697 3698 var span = showdown.subParser('spanGamut')(hText, options, globals), 3699 hID = (options.noHeaderId) ? '' : ' id="' + headerId(m2) + '"', 3700 hLevel = headerLevelStart - 1 + m1.length, 3701 header = '<h' + hLevel + hID + '>' + span + '</h' + hLevel + '>'; 3702 3703 return showdown.subParser('hashBlock')(header, options, globals); 3704 }); 3705 3706 function headerId (m) { 3707 var title, 3708 prefix; 3709 3710 // It is separate from other options to allow combining prefix and customized 3711 if (options.customizedHeaderId) { 3712 var match = m.match(/\{([^{]+?)}\s*$/); 3713 if (match && match[1]) { 3714 m = match[1]; 3715 } 3716 } 3717 3718 title = m; 3719 3720 // Prefix id to prevent causing inadvertent pre-existing style matches. 3721 if (showdown.helper.isString(options.prefixHeaderId)) { 3722 prefix = options.prefixHeaderId; 3723 } else if (options.prefixHeaderId === true) { 3724 prefix = 'section-'; 3725 } else { 3726 prefix = ''; 3727 } 3728 3729 if (!options.rawPrefixHeaderId) { 3730 title = prefix + title; 3731 } 3732 3733 if (options.ghCompatibleHeaderId) { 3734 title = title 3735 .replace(/ /g, '-') 3736 // replace previously escaped chars (&, ¨ and $) 3737 .replace(/&/g, '') 3738 .replace(/¨T/g, '') 3739 .replace(/¨D/g, '') 3740 // replace rest of the chars (&~$ are repeated as they might have been escaped) 3741 // borrowed from github's redcarpet (some they should produce similar results) 3742 .replace(/[&+$,\/:;=?@"#{}|^¨~\[\]`\\*)(%.!'<>]/g, '') 3743 .toLowerCase(); 3744 } else if (options.rawHeaderId) { 3745 title = title 3746 .replace(/ /g, '-') 3747 // replace previously escaped chars (&, ¨ and $) 3748 .replace(/&/g, '&') 3749 .replace(/¨T/g, '¨') 3750 .replace(/¨D/g, '$') 3751 // replace " and ' 3752 .replace(/["']/g, '-') 3753 .toLowerCase(); 3754 } else { 3755 title = title 3756 .replace(/[^\w]/g, '') 3757 .toLowerCase(); 3758 } 3759 3760 if (options.rawPrefixHeaderId) { 3761 title = prefix + title; 3762 } 3763 3764 if (globals.hashLinkCounts[title]) { 3765 title = title + '-' + (globals.hashLinkCounts[title]++); 3766 } else { 3767 globals.hashLinkCounts[title] = 1; 3768 } 3769 return title; 3770 } 3771 3772 text = globals.converter._dispatch('headers.after', text, options, globals); 3773 return text; 3774}); 3775 3776/** 3777 * Turn Markdown link shortcuts into XHTML <a> tags. 3778 */ 3779showdown.subParser('horizontalRule', function (text, options, globals) { 3780 'use strict'; 3781 text = globals.converter._dispatch('horizontalRule.before', text, options, globals); 3782 3783 var key = showdown.subParser('hashBlock')('<hr />', options, globals); 3784 text = text.replace(/^ {0,2}( ?-){3,}[ \t]*$/gm, key); 3785 text = text.replace(/^ {0,2}( ?\*){3,}[ \t]*$/gm, key); 3786 text = text.replace(/^ {0,2}( ?_){3,}[ \t]*$/gm, key); 3787 3788 text = globals.converter._dispatch('horizontalRule.after', text, options, globals); 3789 return text; 3790}); 3791 3792/** 3793 * Turn Markdown image shortcuts into <img> tags. 3794 */ 3795showdown.subParser('images', function (text, options, globals) { 3796 'use strict'; 3797 3798 text = globals.converter._dispatch('images.before', text, options, globals); 3799 3800 var inlineRegExp = /!\[([^\]]*?)][ \t]*()\([ \t]?<?([\S]+?(?:\([\S]*?\)[\S]*?)?)>?(?: =([*\d]+[A-Za-z%]{0,4})x([*\d]+[A-Za-z%]{0,4}))?[ \t]*(?:(["'])([^"]*?)\6)?[ \t]?\)/g, 3801 crazyRegExp = /!\[([^\]]*?)][ \t]*()\([ \t]?<([^>]*)>(?: =([*\d]+[A-Za-z%]{0,4})x([*\d]+[A-Za-z%]{0,4}))?[ \t]*(?:(?:(["'])([^"]*?)\6))?[ \t]?\)/g, 3802 base64RegExp = /!\[([^\]]*?)][ \t]*()\([ \t]?<?(data:.+?\/.+?;base64,[A-Za-z0-9+/=\n]+?)>?(?: =([*\d]+[A-Za-z%]{0,4})x([*\d]+[A-Za-z%]{0,4}))?[ \t]*(?:(["'])([^"]*?)\6)?[ \t]?\)/g, 3803 referenceRegExp = /!\[([^\]]*?)] ?(?:\n *)?\[([\s\S]*?)]()()()()()/g, 3804 refShortcutRegExp = /!\[([^\[\]]+)]()()()()()/g; 3805 3806 function writeImageTagBase64 (wholeMatch, altText, linkId, url, width, height, m5, title) { 3807 url = url.replace(/\s/g, ''); 3808 return writeImageTag (wholeMatch, altText, linkId, url, width, height, m5, title); 3809 } 3810 3811 function writeImageTag (wholeMatch, altText, linkId, url, width, height, m5, title) { 3812 3813 var gUrls = globals.gUrls, 3814 gTitles = globals.gTitles, 3815 gDims = globals.gDimensions; 3816 3817 linkId = linkId.toLowerCase(); 3818 3819 if (!title) { 3820 title = ''; 3821 } 3822 // Special case for explicit empty url 3823 if (wholeMatch.search(/\(<?\s*>? ?(['"].*['"])?\)$/m) > -1) { 3824 url = ''; 3825 3826 } else if (url === '' || url === null) { 3827 if (linkId === '' || linkId === null) { 3828 // lower-case and turn embedded newlines into spaces 3829 linkId = altText.toLowerCase().replace(/ ?\n/g, ' '); 3830 } 3831 url = '#' + linkId; 3832 3833 if (!showdown.helper.isUndefined(gUrls[linkId])) { 3834 url = gUrls[linkId]; 3835 if (!showdown.helper.isUndefined(gTitles[linkId])) { 3836 title = gTitles[linkId]; 3837 } 3838 if (!showdown.helper.isUndefined(gDims[linkId])) { 3839 width = gDims[linkId].width; 3840 height = gDims[linkId].height; 3841 } 3842 } else { 3843 return wholeMatch; 3844 } 3845 } 3846 3847 altText = altText 3848 .replace(/"/g, '"') 3849 //altText = showdown.helper.escapeCharacters(altText, '*_', false); 3850 .replace(showdown.helper.regexes.asteriskDashAndColon, showdown.helper.escapeCharactersCallback); 3851 //url = showdown.helper.escapeCharacters(url, '*_', false); 3852 url = url.replace(showdown.helper.regexes.asteriskDashAndColon, showdown.helper.escapeCharactersCallback); 3853 var result = '<img src="' + url + '" alt="' + altText + '"'; 3854 3855 if (title && showdown.helper.isString(title)) { 3856 title = title 3857 .replace(/"/g, '"') 3858 //title = showdown.helper.escapeCharacters(title, '*_', false); 3859 .replace(showdown.helper.regexes.asteriskDashAndColon, showdown.helper.escapeCharactersCallback); 3860 result += ' title="' + title + '"'; 3861 } 3862 3863 if (width && height) { 3864 width = (width === '*') ? 'auto' : width; 3865 height = (height === '*') ? 'auto' : height; 3866 3867 result += ' width="' + width + '"'; 3868 result += ' height="' + height + '"'; 3869 } 3870 3871 result += ' />'; 3872 3873 return result; 3874 } 3875 3876 // First, handle reference-style labeled images: ![alt text][id] 3877 text = text.replace(referenceRegExp, writeImageTag); 3878 3879 // Next, handle inline images:  3880 3881 // base64 encoded images 3882 text = text.replace(base64RegExp, writeImageTagBase64); 3883 3884 // cases with crazy urls like ./image/cat1).png 3885 text = text.replace(crazyRegExp, writeImageTag); 3886 3887 // normal cases 3888 text = text.replace(inlineRegExp, writeImageTag); 3889 3890 // handle reference-style shortcuts: ![img text] 3891 text = text.replace(refShortcutRegExp, writeImageTag); 3892 3893 text = globals.converter._dispatch('images.after', text, options, globals); 3894 return text; 3895}); 3896 3897showdown.subParser('italicsAndBold', function (text, options, globals) { 3898 'use strict'; 3899 3900 text = globals.converter._dispatch('italicsAndBold.before', text, options, globals); 3901 3902 // it's faster to have 3 separate regexes for each case than have just one 3903 // because of backtracing, in some cases, it could lead to an exponential effect 3904 // called "catastrophic backtrace". Ominous! 3905 3906 function parseInside (txt, left, right) { 3907 /* 3908 if (options.simplifiedAutoLink) { 3909 txt = showdown.subParser('simplifiedAutoLinks')(txt, options, globals); 3910 } 3911 */ 3912 return left + txt + right; 3913 } 3914 3915 // Parse underscores 3916 if (options.literalMidWordUnderscores) { 3917 text = text.replace(/\b___(\S[\s\S]*?)___\b/g, function (wm, txt) { 3918 return parseInside (txt, '<strong><em>', '</em></strong>'); 3919 }); 3920 text = text.replace(/\b__(\S[\s\S]*?)__\b/g, function (wm, txt) { 3921 return parseInside (txt, '<strong>', '</strong>'); 3922 }); 3923 text = text.replace(/\b_(\S[\s\S]*?)_\b/g, function (wm, txt) { 3924 return parseInside (txt, '<em>', '</em>'); 3925 }); 3926 } else { 3927 text = text.replace(/___(\S[\s\S]*?)___/g, function (wm, m) { 3928 return (/\S$/.test(m)) ? parseInside (m, '<strong><em>', '</em></strong>') : wm; 3929 }); 3930 text = text.replace(/__(\S[\s\S]*?)__/g, function (wm, m) { 3931 return (/\S$/.test(m)) ? parseInside (m, '<strong>', '</strong>') : wm; 3932 }); 3933 text = text.replace(/_([^\s_][\s\S]*?)_/g, function (wm, m) { 3934 // !/^_[^_]/.test(m) - test if it doesn't start with __ (since it seems redundant, we removed it) 3935 return (/\S$/.test(m)) ? parseInside (m, '<em>', '</em>') : wm; 3936 }); 3937 } 3938 3939 // Now parse asterisks 3940 if (options.literalMidWordAsterisks) { 3941 text = text.replace(/([^*]|^)\B\*\*\*(\S[\s\S]*?)\*\*\*\B(?!\*)/g, function (wm, lead, txt) { 3942 return parseInside (txt, lead + '<strong><em>', '</em></strong>'); 3943 }); 3944 text = text.replace(/([^*]|^)\B\*\*(\S[\s\S]*?)\*\*\B(?!\*)/g, function (wm, lead, txt) { 3945 return parseInside (txt, lead + '<strong>', '</strong>'); 3946 }); 3947 text = text.replace(/([^*]|^)\B\*(\S[\s\S]*?)\*\B(?!\*)/g, function (wm, lead, txt) { 3948 return parseInside (txt, lead + '<em>', '</em>'); 3949 }); 3950 } else { 3951 text = text.replace(/\*\*\*(\S[\s\S]*?)\*\*\*/g, function (wm, m) { 3952 return (/\S$/.test(m)) ? parseInside (m, '<strong><em>', '</em></strong>') : wm; 3953 }); 3954 text = text.replace(/\*\*(\S[\s\S]*?)\*\*/g, function (wm, m) { 3955 return (/\S$/.test(m)) ? parseInside (m, '<strong>', '</strong>') : wm; 3956 }); 3957 text = text.replace(/\*([^\s*][\s\S]*?)\*/g, function (wm, m) { 3958 // !/^\*[^*]/.test(m) - test if it doesn't start with ** (since it seems redundant, we removed it) 3959 return (/\S$/.test(m)) ? parseInside (m, '<em>', '</em>') : wm; 3960 }); 3961 } 3962 3963 3964 text = globals.converter._dispatch('italicsAndBold.after', text, options, globals); 3965 return text; 3966}); 3967 3968/** 3969 * Form HTML ordered (numbered) and unordered (bulleted) lists. 3970 */ 3971showdown.subParser('lists', function (text, options, globals) { 3972 'use strict'; 3973 3974 /** 3975 * Process the contents of a single ordered or unordered list, splitting it 3976 * into individual list items. 3977 * @param {string} listStr 3978 * @param {boolean} trimTrailing 3979 * @returns {string} 3980 */ 3981 function processListItems (listStr, trimTrailing) { 3982 // The $g_list_level global keeps track of when we're inside a list. 3983 // Each time we enter a list, we increment it; when we leave a list, 3984 // we decrement. If it's zero, we're not in a list anymore. 3985 // 3986 // We do this because when we're not inside a list, we want to treat 3987 // something like this: 3988 // 3989 // I recommend upgrading to version 3990 // 8. Oops, now this line is treated 3991 // as a sub-list. 3992 // 3993 // As a single paragraph, despite the fact that the second line starts 3994 // with a digit-period-space sequence. 3995 // 3996 // Whereas when we're inside a list (or sub-list), that line will be 3997 // treated as the start of a sub-list. What a kludge, huh? This is 3998 // an aspect of Markdown's syntax that's hard to parse perfectly 3999 // without resorting to mind-reading. Perhaps the solution is to 4000 // change the syntax rules such that sub-lists must start with a 4001 // starting cardinal number; e.g. "1." or "a.". 4002 globals.gListLevel++; 4003 4004 // trim trailing blank lines: 4005 listStr = listStr.replace(/\n{2,}$/, '\n'); 4006 4007 // attacklab: add sentinel to emulate \z 4008 listStr += '¨0'; 4009 4010 var rgx = /(\n)?(^ {0,3})([*+-]|\d+[.])[ \t]+((\[(x|X| )?])?[ \t]*[^\r]+?(\n{1,2}))(?=\n*(¨0| {0,3}([*+-]|\d+[.])[ \t]+))/gm, 4011 isParagraphed = (/\n[ \t]*\n(?!¨0)/.test(listStr)); 4012 4013 // Since version 1.5, nesting sublists requires 4 spaces (or 1 tab) indentation, 4014 // which is a syntax breaking change 4015 // activating this option reverts to old behavior 4016 if (options.disableForced4SpacesIndentedSublists) { 4017 rgx = /(\n)?(^ {0,3})([*+-]|\d+[.])[ \t]+((\[(x|X| )?])?[ \t]*[^\r]+?(\n{1,2}))(?=\n*(¨0|\2([*+-]|\d+[.])[ \t]+))/gm; 4018 } 4019 4020 listStr = listStr.replace(rgx, function (wholeMatch, m1, m2, m3, m4, taskbtn, checked) { 4021 checked = (checked && checked.trim() !== ''); 4022 4023 var item = showdown.subParser('outdent')(m4, options, globals), 4024 bulletStyle = ''; 4025 4026 // Support for github tasklists 4027 if (taskbtn && options.tasklists) { 4028 bulletStyle = ' class="task-list-item" style="list-style-type: none;"'; 4029 item = item.replace(/^[ \t]*\[(x|X| )?]/m, function () { 4030 var otp = '<input type="checkbox" disabled style="margin: 0px 0.35em 0.25em -1.6em; vertical-align: middle;"'; 4031 if (checked) { 4032 otp += ' checked'; 4033 } 4034 otp += '>'; 4035 return otp; 4036 }); 4037 } 4038 4039 // ISSUE #312 4040 // This input: - - - a 4041 // causes trouble to the parser, since it interprets it as: 4042 // <ul><li><li><li>a</li></li></li></ul> 4043 // instead of: 4044 // <ul><li>- - a</li></ul> 4045 // So, to prevent it, we will put a marker (¨A)in the beginning of the line 4046 // Kind of hackish/monkey patching, but seems more effective than overcomplicating the list parser 4047 item = item.replace(/^([-*+]|\d\.)[ \t]+[\S\n ]*/g, function (wm2) { 4048 return '¨A' + wm2; 4049 }); 4050 4051 // m1 - Leading line or 4052 // Has a double return (multi paragraph) or 4053 // Has sublist 4054 if (m1 || (item.search(/\n{2,}/) > -1)) { 4055 item = showdown.subParser('githubCodeBlocks')(item, options, globals); 4056 item = showdown.subParser('blockGamut')(item, options, globals); 4057 } else { 4058 // Recursion for sub-lists: 4059 item = showdown.subParser('lists')(item, options, globals); 4060 item = item.replace(/\n$/, ''); // chomp(item) 4061 item = showdown.subParser('hashHTMLBlocks')(item, options, globals); 4062 4063 // Colapse double linebreaks 4064 item = item.replace(/\n\n+/g, '\n\n'); 4065 if (isParagraphed) { 4066 item = showdown.subParser('paragraphs')(item, options, globals); 4067 } else { 4068 item = showdown.subParser('spanGamut')(item, options, globals); 4069 } 4070 } 4071 4072 // now we need to remove the marker (¨A) 4073 item = item.replace('¨A', ''); 4074 // we can finally wrap the line in list item tags 4075 item = '<li' + bulletStyle + '>' + item + '</li>\n'; 4076 4077 return item; 4078 }); 4079 4080 // attacklab: strip sentinel 4081 listStr = listStr.replace(/¨0/g, ''); 4082 4083 globals.gListLevel--; 4084 4085 if (trimTrailing) { 4086 listStr = listStr.replace(/\s+$/, ''); 4087 } 4088 4089 return listStr; 4090 } 4091 4092 function styleStartNumber (list, listType) { 4093 // check if ol and starts by a number different than 1 4094 if (listType === 'ol') { 4095 var res = list.match(/^ *(\d+)\./); 4096 if (res && res[1] !== '1') { 4097 return ' start="' + res[1] + '"'; 4098 } 4099 } 4100 return ''; 4101 } 4102 4103 /** 4104 * Check and parse consecutive lists (better fix for issue #142) 4105 * @param {string} list 4106 * @param {string} listType 4107 * @param {boolean} trimTrailing 4108 * @returns {string} 4109 */ 4110 function parseConsecutiveLists (list, listType, trimTrailing) { 4111 // check if we caught 2 or more consecutive lists by mistake 4112 // we use the counterRgx, meaning if listType is UL we look for OL and vice versa 4113 var olRgx = (options.disableForced4SpacesIndentedSublists) ? /^ ?\d+\.[ \t]/gm : /^ {0,3}\d+\.[ \t]/gm, 4114 ulRgx = (options.disableForced4SpacesIndentedSublists) ? /^ ?[*+-][ \t]/gm : /^ {0,3}[*+-][ \t]/gm, 4115 counterRxg = (listType === 'ul') ? olRgx : ulRgx, 4116 result = ''; 4117 4118 if (list.search(counterRxg) !== -1) { 4119 (function parseCL (txt) { 4120 var pos = txt.search(counterRxg), 4121 style = styleStartNumber(list, listType); 4122 if (pos !== -1) { 4123 // slice 4124 result += '\n\n<' + listType + style + '>\n' + processListItems(txt.slice(0, pos), !!trimTrailing) + '</' + listType + '>\n'; 4125 4126 // invert counterType and listType 4127 listType = (listType === 'ul') ? 'ol' : 'ul'; 4128 counterRxg = (listType === 'ul') ? olRgx : ulRgx; 4129 4130 //recurse 4131 parseCL(txt.slice(pos)); 4132 } else { 4133 result += '\n\n<' + listType + style + '>\n' + processListItems(txt, !!trimTrailing) + '</' + listType + '>\n'; 4134 } 4135 })(list); 4136 } else { 4137 var style = styleStartNumber(list, listType); 4138 result = '\n\n<' + listType + style + '>\n' + processListItems(list, !!trimTrailing) + '</' + listType + '>\n'; 4139 } 4140 4141 return result; 4142 } 4143 4144 /** Start of list parsing **/ 4145 text = globals.converter._dispatch('lists.before', text, options, globals); 4146 // add sentinel to hack around khtml/safari bug: 4147 // http://bugs.webkit.org/show_bug.cgi?id=11231 4148 text += '¨0'; 4149 4150 if (globals.gListLevel) { 4151 text = text.replace(/^(( {0,3}([*+-]|\d+[.])[ \t]+)[^\r]+?(¨0|\n{2,}(?=\S)(?![ \t]*(?:[*+-]|\d+[.])[ \t]+)))/gm, 4152 function (wholeMatch, list, m2) { 4153 var listType = (m2.search(/[*+-]/g) > -1) ? 'ul' : 'ol'; 4154 return parseConsecutiveLists(list, listType, true); 4155 } 4156 ); 4157 } else { 4158 text = text.replace(/(\n\n|^\n?)(( {0,3}([*+-]|\d+[.])[ \t]+)[^\r]+?(¨0|\n{2,}(?=\S)(?![ \t]*(?:[*+-]|\d+[.])[ \t]+)))/gm, 4159 function (wholeMatch, m1, list, m3) { 4160 var listType = (m3.search(/[*+-]/g) > -1) ? 'ul' : 'ol'; 4161 return parseConsecutiveLists(list, listType, false); 4162 } 4163 ); 4164 } 4165 4166 // strip sentinel 4167 text = text.replace(/¨0/, ''); 4168 text = globals.converter._dispatch('lists.after', text, options, globals); 4169 return text; 4170}); 4171 4172/** 4173 * Parse metadata at the top of the document 4174 */ 4175showdown.subParser('metadata', function (text, options, globals) { 4176 'use strict'; 4177 4178 if (!options.metadata) { 4179 return text; 4180 } 4181 4182 text = globals.converter._dispatch('metadata.before', text, options, globals); 4183 4184 function parseMetadataContents (content) { 4185 // raw is raw so it's not changed in any way 4186 globals.metadata.raw = content; 4187 4188 // escape chars forbidden in html attributes 4189 // double quotes 4190 content = content 4191 // ampersand first 4192 .replace(/&/g, '&') 4193 // double quotes 4194 .replace(/"/g, '"'); 4195 4196 content = content.replace(/\n {4}/g, ' '); 4197 content.replace(/^([\S ]+): +([\s\S]+?)$/gm, function (wm, key, value) { 4198 globals.metadata.parsed[key] = value; 4199 return ''; 4200 }); 4201 } 4202 4203 text = text.replace(/^\s*«««+(\S*?)\n([\s\S]+?)\n»»»+\n/, function (wholematch, format, content) { 4204 parseMetadataContents(content); 4205 return '¨M'; 4206 }); 4207 4208 text = text.replace(/^\s*---+(\S*?)\n([\s\S]+?)\n---+\n/, function (wholematch, format, content) { 4209 if (format) { 4210 globals.metadata.format = format; 4211 } 4212 parseMetadataContents(content); 4213 return '¨M'; 4214 }); 4215 4216 text = text.replace(/¨M/g, ''); 4217 4218 text = globals.converter._dispatch('metadata.after', text, options, globals); 4219 return text; 4220}); 4221 4222/** 4223 * Remove one level of line-leading tabs or spaces 4224 */ 4225showdown.subParser('outdent', function (text, options, globals) { 4226 'use strict'; 4227 text = globals.converter._dispatch('outdent.before', text, options, globals); 4228 4229 // attacklab: hack around Konqueror 3.5.4 bug: 4230 // "----------bug".replace(/^-/g,"") == "bug" 4231 text = text.replace(/^(\t|[ ]{1,4})/gm, '¨0'); // attacklab: g_tab_width 4232 4233 // attacklab: clean up hack 4234 text = text.replace(/¨0/g, ''); 4235 4236 text = globals.converter._dispatch('outdent.after', text, options, globals); 4237 return text; 4238}); 4239 4240/** 4241 * 4242 */ 4243showdown.subParser('paragraphs', function (text, options, globals) { 4244 'use strict'; 4245 4246 text = globals.converter._dispatch('paragraphs.before', text, options, globals); 4247 // Strip leading and trailing lines: 4248 text = text.replace(/^\n+/g, ''); 4249 text = text.replace(/\n+$/g, ''); 4250 4251 var grafs = text.split(/\n{2,}/g), 4252 grafsOut = [], 4253 end = grafs.length; // Wrap <p> tags 4254 4255 for (var i = 0; i < end; i++) { 4256 var str = grafs[i]; 4257 // if this is an HTML marker, copy it 4258 if (str.search(/¨(K|G)(\d+)\1/g) >= 0) { 4259 grafsOut.push(str); 4260 4261 // test for presence of characters to prevent empty lines being parsed 4262 // as paragraphs (resulting in undesired extra empty paragraphs) 4263 } else if (str.search(/\S/) >= 0) { 4264 str = showdown.subParser('spanGamut')(str, options, globals); 4265 str = str.replace(/^([ \t]*)/g, '<p>'); 4266 str += '</p>'; 4267 grafsOut.push(str); 4268 } 4269 } 4270 4271 /** Unhashify HTML blocks */ 4272 end = grafsOut.length; 4273 for (i = 0; i < end; i++) { 4274 var blockText = '', 4275 grafsOutIt = grafsOut[i], 4276 codeFlag = false;
4277 // if this is a marker for an html block... 4278 // use RegExp.test instead of string.search because of QML bug 4279 while (/¨(K|G)(\d+)\1/.test(grafsOutIt)) { 4280 var delim = RegExp.$1, 4281 num = RegExp.$2; 4282 4283 if (delim === 'K') { 4284 blockText = globals.gHtmlBlocks[num]; 4285 } else { 4286 // we need to check if ghBlock is a false positive 4287 if (codeFlag) { 4288 // use encoded version of all text 4289 blockText = showdown.subParser('encodeCode')(globals.ghCodeBlocks[num].text, options, globals); 4290 } else { 4291 blockText = globals.ghCodeBlocks[num].codeblock; 4292 } 4293 } 4294 blockText = blockText.replace(/\$/g, '$$$$'); // Escape any dollar signs 4295 4296 grafsOutIt = grafsOutIt.replace(/(\n\n)?¨(K|G)\d+\2(\n\n)?/, blockText); 4297 // Check if grafsOutIt is a pre->code 4298 if (/^<pre\b[^>]*>\s*<code\b[^>]*>/.test(grafsOutIt)) { 4299 codeFlag = true; 4300 } 4301 } 4302 grafsOut[i] = grafsOutIt; 4303 } 4304 text = grafsOut.join('\n'); 4305 // Strip leading and trailing lines: 4306 text = text.replace(/^\n+/g, ''); 4307 text = text.replace(/\n+$/g, ''); 4308 return globals.converter._dispatch('paragraphs.after', text, options, globals); 4309}); 4310 4311/** 4312 * Run extension 4313 */ 4314showdown.subParser('runExtension', function (ext, text, options, globals) { 4315 'use strict'; 4316 4317 if (ext.filter) { 4318 text = ext.filter(text, globals.converter, options); 4319 4320 } else if (ext.regex) { 4321 // TODO remove this when old extension loading mechanism is deprecated 4322 var re = ext.regex; 4323 if (!(re instanceof RegExp)) { 4324 re = new RegExp(re, 'g'); 4325 } 4326 text = text.replace(re, ext.replace); 4327 } 4328 4329 return text; 4330}); 4331 4332/** 4333 * These are all the transformations that occur *within* block-level 4334 * tags like paragraphs, headers, and list items. 4335 */ 4336showdown.subParser('spanGamut', function (text, options, globals) { 4337 'use strict'; 4338 4339 text = globals.converter._dispatch('spanGamut.before', text, options, globals); 4340 text = showdown.subParser('codeSpans')(text, options, globals); 4341 text = showdown.subParser('escapeSpecialCharsWithinTagAttributes')(text, options, globals); 4342 text = showdown.subParser('encodeBackslashEscapes')(text, options, globals); 4343 4344 // Process anchor and image tags. Images must come first, 4345 // because ![foo][f] looks like an anchor. 4346 text = showdown.subParser('images')(text, options, globals); 4347 text = showdown.subParser('anchors')(text, options, globals); 4348 4349 // Make links out of things like `<http://example.com/>` 4350 // Must come after anchors, because you can use < and > 4351 // delimiters in inline links like [this](<url>). 4352 text = showdown.subParser('autoLinks')(text, options, globals); 4353 text = showdown.subParser('simplifiedAutoLinks')(text, options, globals); 4354 text = showdown.subParser('emoji')(text, options, globals); 4355 text = showdown.subParser('underline')(text, options, globals); 4356 text = showdown.subParser('italicsAndBold')(text, options, globals); 4357 text = showdown.subParser('strikethrough')(text, options, globals); 4358 text = showdown.subParser('ellipsis')(text, options, globals); 4359 4360 // we need to hash HTML tags inside spans 4361 text = showdown.subParser('hashHTMLSpans')(text, options, globals); 4362 4363 // now we encode amps and angles 4364 text = showdown.subParser('encodeAmpsAndAngles')(text, options, globals); 4365 4366 // Do hard breaks 4367 if (options.simpleLineBreaks) { 4368 // GFM style hard breaks 4369 // only add line breaks if the text does not contain a block (special case for lists) 4370 if (!/\n\n¨K/.test(text)) { 4371 text = text.replace(/\n+/g, '<br />\n'); 4372 } 4373 } else { 4374 // Vanilla hard breaks 4375 text = text.replace(/ +\n/g, '<br />\n'); 4376 } 4377 4378 text = globals.converter._dispatch('spanGamut.after', text, options, globals); 4379 return text; 4380}); 4381 4382showdown.subParser('strikethrough', function (text, options, globals) { 4383 'use strict'; 4384 4385 function parseInside (txt) { 4386 if (options.simplifiedAutoLink) { 4387 txt = showdown.subParser('simplifiedAutoLinks')(txt, options, globals); 4388 } 4389 return '<del>' + txt + '</del>'; 4390 } 4391 4392 if (options.strikethrough) { 4393 text = globals.converter._dispatch('strikethrough.before', text, options, globals); 4394 text = text.replace(/(?:~){2}([\s\S]+?)(?:~){2}/g, function (wm, txt) { return parseInside(txt); }); 4395 text = globals.converter._dispatch('strikethrough.after', text, options, globals); 4396 } 4397 4398 return text; 4399}); 4400 4401/** 4402 * Strips link definitions from text, stores the URLs and titles in 4403 * hash references. 4404 * Link defs are in the form: ^[id]: url "optional title" 4405 */ 4406showdown.subParser('stripLinkDefinitions', function (text, options, globals) { 4407 'use strict'; 4408 4409 var regex = /^ {0,3}\[([^\]]+)]:[ \t]*\n?[ \t]*<?([^>\s]+)>?(?: =([*\d]+[A-Za-z%]{0,4})x([*\d]+[A-Za-z%]{0,4}))?[ \t]*\n?[ \t]*(?:(\n*)["|'(](.+?)["|')][ \t]*)?(?:\n+|(?=¨0))
vendor: 19,576 bytes, lines 4409-5108
4409/gm, 4410 base64Regex = /^ {0,3}\[([^\]]+)]:[ \t]*\n?[ \t]*<?(data:.+?\/.+?;base64,[A-Za-z0-9+/=\n]+?)>?(?: =([*\d]+[A-Za-z%]{0,4})x([*\d]+[A-Za-z%]{0,4}))?[ \t]*\n?[ \t]*(?:(\n*)["|'(](.+?)["|')][ \t]*)?(?:\n\n|(?=¨0)|(?=\n\[))/gm; 4411 4412 // attacklab: sentinel workarounds for lack of \A and \Z, safari\khtml bug 4413 text += '¨0'; 4414 4415 var replaceFunc = function (wholeMatch, linkId, url, width, height, blankLines, title) { 4416 4417 // if there aren't two instances of linkId it must not be a reference link so back out 4418 linkId = linkId.toLowerCase(); 4419 if (text.toLowerCase().split(linkId).length - 1 < 2) { 4420 return wholeMatch; 4421 } 4422 if (url.match(/^data:.+?\/.+?;base64,/)) { 4423 // remove newlines 4424 globals.gUrls[linkId] = url.replace(/\s/g, ''); 4425 } else { 4426 globals.gUrls[linkId] = showdown.subParser('encodeAmpsAndAngles')(url, options, globals); // Link IDs are case-insensitive 4427 } 4428 4429 if (blankLines) { 4430 // Oops, found blank lines, so it's not a title. 4431 // Put back the parenthetical statement we stole. 4432 return blankLines + title; 4433 4434 } else { 4435 if (title) { 4436 globals.gTitles[linkId] = title.replace(/"|'/g, '"'); 4437 } 4438 if (options.parseImgDimensions && width && height) { 4439 globals.gDimensions[linkId] = { 4440 width: width, 4441 height: height 4442 }; 4443 } 4444 } 4445 // Completely remove the definition from the text 4446 return ''; 4447 }; 4448 4449 // first we try to find base64 link references 4450 text = text.replace(base64Regex, replaceFunc); 4451 4452 text = text.replace(regex, replaceFunc); 4453 4454 // attacklab: strip sentinel 4455 text = text.replace(/¨0/, ''); 4456 4457 return text; 4458}); 4459 4460showdown.subParser('tables', function (text, options, globals) { 4461 'use strict'; 4462 4463 if (!options.tables) { 4464 return text; 4465 } 4466 4467 var tableRgx = /^ {0,3}\|?.+\|.+\n {0,3}\|?[ \t]*:?[ \t]*(?:[-=]){2,}[ \t]*:?[ \t]*\|[ \t]*:?[ \t]*(?:[-=]){2,}[\s\S]+?(?:\n\n|¨0)/gm, 4468 //singeColTblRgx = /^ {0,3}\|.+\|\n {0,3}\|[ \t]*:?[ \t]*(?:[-=]){2,}[ \t]*:?[ \t]*\|[ \t]*\n(?: {0,3}\|.+\|\n)+(?:\n\n|¨0)/gm; 4469 singeColTblRgx = /^ {0,3}\|.+\|[ \t]*\n {0,3}\|[ \t]*:?[ \t]*(?:[-=]){2,}[ \t]*:?[ \t]*\|[ \t]*\n( {0,3}\|.+\|[ \t]*\n)*(?:\n|¨0)/gm; 4470 4471 function parseStyles (sLine) { 4472 if (/^:[ \t]*--*$/.test(sLine)) { 4473 return ' style="text-align:left;"'; 4474 } else if (/^--*[ \t]*:[ \t]*$/.test(sLine)) { 4475 return ' style="text-align:right;"'; 4476 } else if (/^:[ \t]*--*[ \t]*:$/.test(sLine)) { 4477 return ' style="text-align:center;"'; 4478 } else { 4479 return ''; 4480 } 4481 } 4482 4483 function parseHeaders (header, style) { 4484 var id = ''; 4485 header = header.trim(); 4486 // support both tablesHeaderId and tableHeaderId due to error in documentation so we don't break backwards compatibility 4487 if (options.tablesHeaderId || options.tableHeaderId) { 4488 id = ' id="' + header.replace(/ /g, '_').toLowerCase() + '"'; 4489 } 4490 header = showdown.subParser('spanGamut')(header, options, globals); 4491 4492 return '<th' + id + style + '>' + header + '</th>\n'; 4493 } 4494 4495 function parseCells (cell, style) { 4496 var subText = showdown.subParser('spanGamut')(cell, options, globals); 4497 return '<td' + style + '>' + subText + '</td>\n'; 4498 } 4499 4500 function buildTable (headers, cells) { 4501 var tb = '<table>\n<thead>\n<tr>\n', 4502 tblLgn = headers.length; 4503 4504 for (var i = 0; i < tblLgn; ++i) { 4505 tb += headers[i]; 4506 } 4507 tb += '</tr>\n</thead>\n<tbody>\n'; 4508 4509 for (i = 0; i < cells.length; ++i) { 4510 tb += '<tr>\n'; 4511 for (var ii = 0; ii < tblLgn; ++ii) { 4512 tb += cells[i][ii]; 4513 } 4514 tb += '</tr>\n'; 4515 } 4516 tb += '</tbody>\n</table>\n'; 4517 return tb; 4518 } 4519 4520 function parseTable (rawTable) { 4521 var i, tableLines = rawTable.split('\n'); 4522 4523 for (i = 0; i < tableLines.length; ++i) { 4524 // strip wrong first and last column if wrapped tables are used 4525 if (/^ {0,3}\|/.test(tableLines[i])) { 4526 tableLines[i] = tableLines[i].replace(/^ {0,3}\|/, ''); 4527 } 4528 if (/\|[ \t]*$/.test(tableLines[i])) { 4529 tableLines[i] = tableLines[i].replace(/\|[ \t]*$/, ''); 4530 } 4531 // parse code spans first, but we only support one line code spans 4532 tableLines[i] = showdown.subParser('codeSpans')(tableLines[i], options, globals); 4533 } 4534 4535 var rawHeaders = tableLines[0].split('|').map(function (s) { return s.trim();}), 4536 rawStyles = tableLines[1].split('|').map(function (s) { return s.trim();}), 4537 rawCells = [], 4538 headers = [], 4539 styles = [], 4540 cells = []; 4541 4542 tableLines.shift(); 4543 tableLines.shift(); 4544 4545 for (i = 0; i < tableLines.length; ++i) { 4546 if (tableLines[i].trim() === '') { 4547 continue; 4548 } 4549 rawCells.push( 4550 tableLines[i] 4551 .split('|') 4552 .map(function (s) { 4553 return s.trim(); 4554 }) 4555 ); 4556 } 4557 4558 if (rawHeaders.length < rawStyles.length) { 4559 return rawTable; 4560 } 4561 4562 for (i = 0; i < rawStyles.length; ++i) { 4563 styles.push(parseStyles(rawStyles[i])); 4564 } 4565 4566 for (i = 0; i < rawHeaders.length; ++i) { 4567 if (showdown.helper.isUndefined(styles[i])) { 4568 styles[i] = ''; 4569 } 4570 headers.push(parseHeaders(rawHeaders[i], styles[i])); 4571 } 4572 4573 for (i = 0; i < rawCells.length; ++i) { 4574 var row = []; 4575 for (var ii = 0; ii < headers.length; ++ii) { 4576 if (showdown.helper.isUndefined(rawCells[i][ii])) { 4577 4578 } 4579 row.push(parseCells(rawCells[i][ii], styles[ii])); 4580 } 4581 cells.push(row); 4582 } 4583 4584 return buildTable(headers, cells); 4585 } 4586 4587 text = globals.converter._dispatch('tables.before', text, options, globals); 4588 4589 // find escaped pipe characters 4590 text = text.replace(/\\(\|)/g, showdown.helper.escapeCharactersCallback); 4591 4592 // parse multi column tables 4593 text = text.replace(tableRgx, parseTable); 4594 4595 // parse one column tables 4596 text = text.replace(singeColTblRgx, parseTable); 4597 4598 text = globals.converter._dispatch('tables.after', text, options, globals); 4599 4600 return text; 4601}); 4602 4603showdown.subParser('underline', function (text, options, globals) { 4604 'use strict'; 4605 4606 if (!options.underline) { 4607 return text; 4608 } 4609 4610 text = globals.converter._dispatch('underline.before', text, options, globals); 4611 4612 if (options.literalMidWordUnderscores) { 4613 text = text.replace(/\b___(\S[\s\S]*?)___\b/g, function (wm, txt) { 4614 return '<u>' + txt + '</u>'; 4615 }); 4616 text = text.replace(/\b__(\S[\s\S]*?)__\b/g, function (wm, txt) { 4617 return '<u>' + txt + '</u>'; 4618 }); 4619 } else { 4620 text = text.replace(/___(\S[\s\S]*?)___/g, function (wm, m) { 4621 return (/\S$/.test(m)) ? '<u>' + m + '</u>' : wm; 4622 }); 4623 text = text.replace(/__(\S[\s\S]*?)__/g, function (wm, m) { 4624 return (/\S$/.test(m)) ? '<u>' + m + '</u>' : wm; 4625 }); 4626 } 4627 4628 // escape remaining underscores to prevent them being parsed by italic and bold 4629 text = text.replace(/(_)/g, showdown.helper.escapeCharactersCallback); 4630 4631 text = globals.converter._dispatch('underline.after', text, options, globals); 4632 4633 return text; 4634}); 4635 4636/** 4637 * Swap back in all the special characters we've hidden. 4638 */ 4639showdown.subParser('unescapeSpecialChars', function (text, options, globals) { 4640 'use strict'; 4641 text = globals.converter._dispatch('unescapeSpecialChars.before', text, options, globals); 4642 4643 text = text.replace(/¨E(\d+)E/g, function (wholeMatch, m1) { 4644 var charCodeToReplace = parseInt(m1); 4645 return String.fromCharCode(charCodeToReplace); 4646 }); 4647 4648 text = globals.converter._dispatch('unescapeSpecialChars.after', text, options, globals); 4649 return text; 4650}); 4651 4652showdown.subParser('makeMarkdown.blockquote', function (node, globals) { 4653 'use strict'; 4654 4655 var txt = ''; 4656 if (node.hasChildNodes()) { 4657 var children = node.childNodes, 4658 childrenLength = children.length; 4659 4660 for (var i = 0; i < childrenLength; ++i) { 4661 var innerTxt = showdown.subParser('makeMarkdown.node')(children[i], globals); 4662 4663 if (innerTxt === '') { 4664 continue; 4665 } 4666 txt += innerTxt; 4667 } 4668 } 4669 // cleanup 4670 txt = txt.trim(); 4671 txt = '> ' + txt.split('\n').join('\n> '); 4672 return txt; 4673}); 4674 4675showdown.subParser('makeMarkdown.codeBlock', function (node, globals) { 4676 'use strict'; 4677 4678 var lang = node.getAttribute('language'), 4679 num = node.getAttribute('precodenum'); 4680 return '```' + lang + '\n' + globals.preList[num] + '\n```'; 4681}); 4682 4683showdown.subParser('makeMarkdown.codeSpan', function (node) { 4684 'use strict'; 4685 4686 return '`' + node.innerHTML + '`'; 4687}); 4688 4689showdown.subParser('makeMarkdown.emphasis', function (node, globals) { 4690 'use strict'; 4691 4692 var txt = ''; 4693 if (node.hasChildNodes()) { 4694 txt += '*'; 4695 var children = node.childNodes, 4696 childrenLength = children.length; 4697 for (var i = 0; i < childrenLength; ++i) { 4698 txt += showdown.subParser('makeMarkdown.node')(children[i], globals); 4699 } 4700 txt += '*'; 4701 } 4702 return txt; 4703}); 4704 4705showdown.subParser('makeMarkdown.header', function (node, globals, headerLevel) { 4706 'use strict'; 4707 4708 var headerMark = new Array(headerLevel + 1).join('#'), 4709 txt = ''; 4710 4711 if (node.hasChildNodes()) { 4712 txt = headerMark + ' '; 4713 var children = node.childNodes, 4714 childrenLength = children.length; 4715 4716 for (var i = 0; i < childrenLength; ++i) { 4717 txt += showdown.subParser('makeMarkdown.node')(children[i], globals); 4718 } 4719 } 4720 return txt; 4721}); 4722 4723showdown.subParser('makeMarkdown.hr', function () { 4724 'use strict'; 4725 4726 return '---'; 4727}); 4728 4729showdown.subParser('makeMarkdown.image', function (node) { 4730 'use strict'; 4731 4732 var txt = ''; 4733 if (node.hasAttribute('src')) { 4734 txt += ' + '>'; 4736 if (node.hasAttribute('width') && node.hasAttribute('height')) { 4737 txt += ' =' + node.getAttribute('width') + 'x' + node.getAttribute('height'); 4738 } 4739 4740 if (node.hasAttribute('title')) { 4741 txt += ' "' + node.getAttribute('title') + '"'; 4742 } 4743 txt += ')'; 4744 } 4745 return txt; 4746}); 4747 4748showdown.subParser('makeMarkdown.links', function (node, globals) { 4749 'use strict'; 4750 4751 var txt = ''; 4752 if (node.hasChildNodes() && node.hasAttribute('href')) { 4753 var children = node.childNodes, 4754 childrenLength = children.length; 4755 txt = '['; 4756 for (var i = 0; i < childrenLength; ++i) { 4757 txt += showdown.subParser('makeMarkdown.node')(children[i], globals); 4758 } 4759 txt += ']('; 4760 txt += '<' + node.getAttribute('href') + '>'; 4761 if (node.hasAttribute('title')) { 4762 txt += ' "' + node.getAttribute('title') + '"'; 4763 } 4764 txt += ')'; 4765 } 4766 return txt; 4767}); 4768 4769showdown.subParser('makeMarkdown.list', function (node, globals, type) { 4770 'use strict'; 4771 4772 var txt = ''; 4773 if (!node.hasChildNodes()) { 4774 return ''; 4775 } 4776 var listItems = node.childNodes, 4777 listItemsLenght = listItems.length, 4778 listNum = node.getAttribute('start') || 1; 4779 4780 for (var i = 0; i < listItemsLenght; ++i) { 4781 if (typeof listItems[i].tagName === 'undefined' || listItems[i].tagName.toLowerCase() !== 'li') { 4782 continue; 4783 } 4784 4785 // define the bullet to use in list 4786 var bullet = ''; 4787 if (type === 'ol') { 4788 bullet = listNum.toString() + '. '; 4789 } else { 4790 bullet = '- '; 4791 } 4792 4793 // parse list item 4794 txt += bullet + showdown.subParser('makeMarkdown.listItem')(listItems[i], globals); 4795 ++listNum; 4796 } 4797 4798 // add comment at the end to prevent consecutive lists to be parsed as one 4799 txt += '\n<!-- -->\n'; 4800 return txt.trim(); 4801}); 4802 4803showdown.subParser('makeMarkdown.listItem', function (node, globals) { 4804 'use strict'; 4805 4806 var listItemTxt = ''; 4807 4808 var children = node.childNodes, 4809 childrenLenght = children.length; 4810 4811 for (var i = 0; i < childrenLenght; ++i) { 4812 listItemTxt += showdown.subParser('makeMarkdown.node')(children[i], globals); 4813 } 4814 // if it's only one liner, we need to add a newline at the end 4815 if (!/\n$/.test(listItemTxt)) { 4816 listItemTxt += '\n'; 4817 } else { 4818 // it's multiparagraph, so we need to indent 4819 listItemTxt = listItemTxt 4820 .split('\n') 4821 .join('\n ') 4822 .replace(/^ {4}$/gm, '') 4823 .replace(/\n\n+/g, '\n\n'); 4824 } 4825 4826 return listItemTxt; 4827}); 4828 4829 4830 4831showdown.subParser('makeMarkdown.node', function (node, globals, spansOnly) { 4832 'use strict'; 4833 4834 spansOnly = spansOnly || false; 4835 4836 var txt = ''; 4837 4838 // edge case of text without wrapper paragraph 4839 if (node.nodeType === 3) { 4840 return showdown.subParser('makeMarkdown.txt')(node, globals); 4841 } 4842 4843 // HTML comment 4844 if (node.nodeType === 8) { 4845 return '<!--' + node.data + '-->\n\n'; 4846 } 4847 4848 // process only node elements 4849 if (node.nodeType !== 1) { 4850 return ''; 4851 } 4852 4853 var tagName = node.tagName.toLowerCase(); 4854 4855 switch (tagName) { 4856 4857 // 4858 // BLOCKS 4859 // 4860 case 'h1': 4861 if (!spansOnly) { txt = showdown.subParser('makeMarkdown.header')(node, globals, 1) + '\n\n'; } 4862 break; 4863 case 'h2': 4864 if (!spansOnly) { txt = showdown.subParser('makeMarkdown.header')(node, globals, 2) + '\n\n'; } 4865 break; 4866 case 'h3': 4867 if (!spansOnly) { txt = showdown.subParser('makeMarkdown.header')(node, globals, 3) + '\n\n'; } 4868 break; 4869 case 'h4': 4870 if (!spansOnly) { txt = showdown.subParser('makeMarkdown.header')(node, globals, 4) + '\n\n'; } 4871 break; 4872 case 'h5': 4873 if (!spansOnly) { txt = showdown.subParser('makeMarkdown.header')(node, globals, 5) + '\n\n'; } 4874 break; 4875 case 'h6': 4876 if (!spansOnly) { txt = showdown.subParser('makeMarkdown.header')(node, globals, 6) + '\n\n'; } 4877 break; 4878 4879 case 'p': 4880 if (!spansOnly) { txt = showdown.subParser('makeMarkdown.paragraph')(node, globals) + '\n\n'; } 4881 break; 4882 4883 case 'blockquote': 4884 if (!spansOnly) { txt = showdown.subParser('makeMarkdown.blockquote')(node, globals) + '\n\n'; } 4885 break; 4886 4887 case 'hr': 4888 if (!spansOnly) { txt = showdown.subParser('makeMarkdown.hr')(node, globals) + '\n\n'; } 4889 break; 4890 4891 case 'ol': 4892 if (!spansOnly) { txt = showdown.subParser('makeMarkdown.list')(node, globals, 'ol') + '\n\n'; } 4893 break; 4894 4895 case 'ul': 4896 if (!spansOnly) { txt = showdown.subParser('makeMarkdown.list')(node, globals, 'ul') + '\n\n'; } 4897 break; 4898 4899 case 'precode': 4900 if (!spansOnly) { txt = showdown.subParser('makeMarkdown.codeBlock')(node, globals) + '\n\n'; } 4901 break; 4902 4903 case 'pre': 4904 if (!spansOnly) { txt = showdown.subParser('makeMarkdown.pre')(node, globals) + '\n\n'; } 4905 break; 4906 4907 case 'table': 4908 if (!spansOnly) { txt = showdown.subParser('makeMarkdown.table')(node, globals) + '\n\n'; } 4909 break; 4910 4911 // 4912 // SPANS 4913 // 4914 case 'code': 4915 txt = showdown.subParser('makeMarkdown.codeSpan')(node, globals); 4916 break; 4917 4918 case 'em': 4919 case 'i': 4920 txt = showdown.subParser('makeMarkdown.emphasis')(node, globals); 4921 break; 4922 4923 case 'strong': 4924 case 'b': 4925 txt = showdown.subParser('makeMarkdown.strong')(node, globals); 4926 break; 4927 4928 case 'del': 4929 txt = showdown.subParser('makeMarkdown.strikethrough')(node, globals); 4930 break; 4931 4932 case 'a': 4933 txt = showdown.subParser('makeMarkdown.links')(node, globals); 4934 break; 4935 4936 case 'img': 4937 txt = showdown.subParser('makeMarkdown.image')(node, globals); 4938 break; 4939 4940 default: 4941 txt = node.outerHTML + '\n\n'; 4942 } 4943 4944 // common normalization 4945 // TODO eventually 4946 4947 return txt; 4948}); 4949 4950showdown.subParser('makeMarkdown.paragraph', function (node, globals) { 4951 'use strict'; 4952 4953 var txt = ''; 4954 if (node.hasChildNodes()) { 4955 var children = node.childNodes, 4956 childrenLength = children.length; 4957 for (var i = 0; i < childrenLength; ++i) { 4958 txt += showdown.subParser('makeMarkdown.node')(children[i], globals); 4959 } 4960 } 4961 4962 // some text normalization 4963 txt = txt.trim(); 4964 4965 return txt; 4966}); 4967 4968showdown.subParser('makeMarkdown.pre', function (node, globals) { 4969 'use strict'; 4970 4971 var num = node.getAttribute('prenum'); 4972 return '<pre>' + globals.preList[num] + '</pre>'; 4973}); 4974 4975showdown.subParser('makeMarkdown.strikethrough', function (node, globals) { 4976 'use strict'; 4977 4978 var txt = ''; 4979 if (node.hasChildNodes()) { 4980 txt += '~~'; 4981 var children = node.childNodes, 4982 childrenLength = children.length; 4983 for (var i = 0; i < childrenLength; ++i) { 4984 txt += showdown.subParser('makeMarkdown.node')(children[i], globals); 4985 } 4986 txt += '~~'; 4987 } 4988 return txt; 4989}); 4990 4991showdown.subParser('makeMarkdown.strong', function (node, globals) { 4992 'use strict'; 4993 4994 var txt = ''; 4995 if (node.hasChildNodes()) { 4996 txt += '**'; 4997 var children = node.childNodes, 4998 childrenLength = children.length; 4999 for (var i = 0; i < childrenLength; ++i) { 5000 txt += showdown.subParser('makeMarkdown.node')(children[i], globals); 5001 } 5002 txt += '**'; 5003 } 5004 return txt; 5005}); 5006 5007showdown.subParser('makeMarkdown.table', function (node, globals) { 5008 'use strict'; 5009 5010 var txt = '', 5011 tableArray = [[], []], 5012 headings = node.querySelectorAll('thead>tr>th'), 5013 rows = node.querySelectorAll('tbody>tr'), 5014 i, ii; 5015 for (i = 0; i < headings.length; ++i) { 5016 var headContent = showdown.subParser('makeMarkdown.tableCell')(headings[i], globals), 5017 allign = '---'; 5018 5019 if (headings[i].hasAttribute('style')) { 5020 var style = headings[i].getAttribute('style').toLowerCase().replace(/\s/g, ''); 5021 switch (style) { 5022 case 'text-align:left;': 5023 allign = ':---'; 5024 break; 5025 case 'text-align:right;': 5026 allign = '---:'; 5027 break; 5028 case 'text-align:center;': 5029 allign = ':---:'; 5030 break; 5031 } 5032 } 5033 tableArray[0][i] = headContent.trim(); 5034 tableArray[1][i] = allign; 5035 } 5036 5037 for (i = 0; i < rows.length; ++i) { 5038 var r = tableArray.push([]) - 1, 5039 cols = rows[i].getElementsByTagName('td'); 5040 5041 for (ii = 0; ii < headings.length; ++ii) { 5042 var cellContent = ' '; 5043 if (typeof cols[ii] !== 'undefined') { 5044 cellContent = showdown.subParser('makeMarkdown.tableCell')(cols[ii], globals); 5045 } 5046 tableArray[r].push(cellContent); 5047 } 5048 } 5049 5050 var cellSpacesCount = 3; 5051 for (i = 0; i < tableArray.length; ++i) { 5052 for (ii = 0; ii < tableArray[i].length; ++ii) { 5053 var strLen = tableArray[i][ii].length; 5054 if (strLen > cellSpacesCount) { 5055 cellSpacesCount = strLen; 5056 } 5057 } 5058 } 5059 5060 for (i = 0; i < tableArray.length; ++i) { 5061 for (ii = 0; ii < tableArray[i].length; ++ii) { 5062 if (i === 1) { 5063 if (tableArray[i][ii].slice(-1) === ':') { 5064 tableArray[i][ii] = showdown.helper.padEnd(tableArray[i][ii].slice(-1), cellSpacesCount - 1, '-') + ':'; 5065 } else { 5066 tableArray[i][ii] = showdown.helper.padEnd(tableArray[i][ii], cellSpacesCount, '-'); 5067 } 5068 } else { 5069 tableArray[i][ii] = showdown.helper.padEnd(tableArray[i][ii], cellSpacesCount); 5070 } 5071 } 5072 txt += '| ' + tableArray[i].join(' | ') + ' |\n'; 5073 } 5074 5075 return txt.trim(); 5076}); 5077 5078showdown.subParser('makeMarkdown.tableCell', function (node, globals) { 5079 'use strict'; 5080 5081 var txt = ''; 5082 if (!node.hasChildNodes()) { 5083 return ''; 5084 } 5085 var children = node.childNodes, 5086 childrenLength = children.length; 5087 5088 for (var i = 0; i < childrenLength; ++i) { 5089 txt += showdown.subParser('makeMarkdown.node')(children[i], globals, true); 5090 } 5091 return txt.trim(); 5092}); 5093 5094showdown.subParser('makeMarkdown.txt', function (node) { 5095 'use strict'; 5096 5097 var txt = node.nodeValue; 5098 5099 // multiple spaces are collapsed 5100 txt = txt.replace(/ +/g, ' '); 5101 5102 // replace the custom ¨NBSP; with a space 5103 txt = txt.replace(/¨NBSP;/g, ' '); 5104 5105 // ", <, > and & should replace escaped html entities 5106 txt = showdown.helper.unescapeHTMLEntities(txt); 5107 5108 // escape markdown magic characters
5109 // emphasis, strong and strikethrough - can appear everywhere 5110 // we also escape pipe (|) because of tables 5111 // and escape ` because of code blocks and spans 5112 txt = txt.replace(/([*_~|`])/g, '\\$1'); 5113 5114 // escape > because of blockquotes 5115 txt = txt.replace(/^(\s*)>/g, '\\$1>'); 5116 5117 // hash character, only troublesome at the beginning of a line because of headers 5118 txt = txt.replace(/^#/gm, '\\#'); 5119 5120 // horizontal rules 5121 txt = txt.replace(/^(\s*)([-=]{3,})(\s*)$/, '$1\\$2$3'); 5122 5123 // dot, because of ordered lists, only troublesome at the beginning of a line when preceded by an integer 5124 txt = txt.replace(/^( {0,3}\d+)\./gm, '$1\\.'); 5125 5126 // +, * and -, at the beginning of a line becomes a list, so we need to escape them also (asterisk was already escaped) 5127 txt = txt.replace(/^( {0,3})([+-])/gm, '$1\\$2'); 5128 5129 // images and links, ] followed by ( is problematic, so we escape it 5130 txt = txt.replace(/]([\s]*)\(/g, '\\]$1\\('); 5131 5132 // reference URIs must also be escaped 5133 txt = txt.replace(/^ {0,3}\[([\S \t]*?)]:/gm, '\\[$1]:'); 5134 5135 return txt; 5136}); 5137 5138var root = this; 5139 5140// AMD Loader 5141if (typeof define === 'function' && define.amd) { 5142 define(function () { 5143 'use strict'; 5144 return showdown; 5145 }); 5146 5147// CommonJS/nodeJS Loader 5148} else if (typeof module !== 'undefined' && module.exports) { 5149 module.exports = showdown; 5150 5151// Regular Browser loader 5152} else { 5153 root.showdown = showdown; 5154} 5155}).call(this); 5156 5157//# sourceMappingURL=showdown.js.map
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.