PageSourceSearch

https://tinywow.com/v3/js/plugins/showdown/showdown.min.js

js tinywow.com collected 2026-09-24 10:05:07 UTC 159,693 bytes, 5,157 lines download raw bytes

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(/&quot;/g, '"')
734    .replace(/&lt;/g, '<')
735    .replace(/&gt;/g, '>')
736    .replace(/&amp;/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&zwj;\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&zwj;\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&zwj;\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&zwj;\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&zwj;\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&zwj;\u2764\ufe0f&zwj;\ud83d\udc68',
1272  'couple_with_heart_woman_woman':'\ud83d\udc69&zwj;\u2764\ufe0f&zwj;\ud83d\udc69',
1273  'couplekiss_man_man':'\ud83d\udc68&zwj;\u2764\ufe0f&zwj;\ud83d\udc8b&zwj;\ud83d\udc68',
1274  'couplekiss_man_woman':'\ud83d\udc8f',
1275  'couplekiss_woman_woman':'\ud83d\udc69&zwj;\u2764\ufe0f&zwj;\ud83d\udc8b&zwj;\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&zwj;\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&zwj;\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&zwj;\ud83d\udc66',
1375  'family_man_boy_boy':'\ud83d\udc68&zwj;\ud83d\udc66&zwj;\ud83d\udc66',
1376  'family_man_girl':'\ud83d\udc68&zwj;\ud83d\udc67',
1377  'family_man_girl_boy':'\ud83d\udc68&zwj;\ud83d\udc67&zwj;\ud83d\udc66',
1378  'family_man_girl_girl':'\ud83d\udc68&zwj;\ud83d\udc67&zwj;\ud83d\udc67',
1379  'family_man_man_boy':'\ud83d\udc68&zwj;\ud83d\udc68&zwj;\ud83d\udc66',
1380  'family_man_man_boy_boy':'\ud83d\udc68&zwj;\ud83d\udc68&zwj;\ud83d\udc66&zwj;\ud83d\udc66',
1381  'family_man_man_girl':'\ud83d\udc68&zwj;\ud83d\udc68&zwj;\ud83d\udc67',
1382  'family_man_man_girl_boy':'\ud83d\udc68&zwj;\ud83d\udc68&zwj;\ud83d\udc67&zwj;\ud83d\udc66',
1383  'family_man_man_girl_girl':'\ud83d\udc68&zwj;\ud83d\udc68&zwj;\ud83d\udc67&zwj;\ud83d\udc67',
1384  'family_man_woman_boy_boy':'\ud83d\udc68&zwj;\ud83d\udc69&zwj;\ud83d\udc66&zwj;\ud83d\udc66',
1385  'family_man_woman_girl':'\ud83d\udc68&zwj;\ud83d\udc69&zwj;\ud83d\udc67',
1386  'family_man_woman_girl_boy':'\ud83d\udc68&zwj;\ud83d\udc69&zwj;\ud83d\udc67&zwj;\ud83d\udc66',
1387  'family_man_woman_girl_girl':'\ud83d\udc68&zwj;\ud83d\udc69&zwj;\ud83d\udc67&zwj;\ud83d\udc67',
1388  'family_woman_boy':'\ud83d\udc69&zwj;\ud83d\udc66',
1389  'family_woman_boy_boy':'\ud83d\udc69&zwj;\ud83d\udc66&zwj;\ud83d\udc66',
1390  'family_woman_girl':'\ud83d\udc69&zwj;\ud83d\udc67',
1391  'family_woman_girl_boy':'\ud83d\udc69&zwj;\ud83d\udc67&zwj;\ud83d\udc66',
1392  'family_woman_girl_girl':'\ud83d\udc69&zwj;\ud83d\udc67&zwj;\ud83d\udc67',
1393  'family_woman_woman_boy':'\ud83d\udc69&zwj;\ud83d\udc69&zwj;\ud83d\udc66',
1394  'family_woman_woman_boy_boy':'\ud83d\udc69&zwj;\ud83d\udc69&zwj;\ud83d\udc66&zwj;\ud83d\udc66',
1395  'family_woman_woman_girl':'\ud83d\udc69&zwj;\ud83d\udc69&zwj;\ud83d\udc67',
1396  'family_woman_woman_girl_boy':'\ud83d\udc69&zwj;\ud83d\udc69&zwj;\ud83d\udc67&zwj;\ud83d\udc66',
1397  'family_woman_woman_girl_girl':'\ud83d\udc69&zwj;\ud83d\udc69&zwj;\ud83d\udc67&zwj;\ud83d\udc67',
1398  'fast_forward':'\u23e9',
1399  'fax':'\ud83d\udce0',
1400  'fearful':'\ud83d\ude28',
1401  'feet':'\ud83d\udc3e',
1402  'female_detective':'\ud83d\udd75\ufe0f&zwj;\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&zwj;\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&zwj;\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&zwj;\u2640\ufe0f',
1480  'guitar':'\ud83c\udfb8',
1481  'gun':'\ud83d\udd2b',
1482  'haircut_woman':'\ud83d\udc87',
1483  'haircut_man':'\ud83d\udc87&zwj;\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&zwj;\ud83c\udfa8',
1616  'man_astronaut':'\ud83d\udc68&zwj;\ud83d\ude80',
1617  'man_cartwheeling':'\ud83e\udd38&zwj;\u2642\ufe0f',
1618  'man_cook':'\ud83d\udc68&zwj;\ud83c\udf73',
1619  'man_dancing':'\ud83d\udd7a',
1620  'man_facepalming':'\ud83e\udd26&zwj;\u2642\ufe0f',
1621  'man_factory_worker':'\ud83d\udc68&zwj;\ud83c\udfed',
1622  'man_farmer':'\ud83d\udc68&zwj;\ud83c\udf3e',
1623  'man_firefighter':'\ud83d\udc68&zwj;\ud83d\ude92',
1624  'man_health_worker':'\ud83d\udc68&zwj;\u2695\ufe0f',
1625  'man_in_tuxedo':'\ud83e\udd35',
1626  'man_judge':'\ud83d\udc68&zwj;\u2696\ufe0f',
1627  'man_juggling':'\ud83e\udd39&zwj;\u2642\ufe0f',
1628  'man_mechanic':'\ud83d\udc68&zwj;\ud83d\udd27',
1629  'man_office_worker':'\ud83d\udc68&zwj;\ud83d\udcbc',
1630  'man_pilot':'\ud83d\udc68&zwj;\u2708\ufe0f',
1631  'man_playing_handball':'\ud83e\udd3e&zwj;\u2642\ufe0f',
1632  'man_playing_water_polo':'\ud83e\udd3d&zwj;\u2642\ufe0f',
1633  'man_scientist':'\ud83d\udc68&zwj;\ud83d\udd2c',
1634  'man_shrugging':'\ud83e\udd37&zwj;\u2642\ufe0f',
1635  'man_singer':'\ud83d\udc68&zwj;\ud83c\udfa4',
1636  'man_student':'\ud83d\udc68&zwj;\ud83c\udf93',
1637  'man_teacher':'\ud83d\udc68&zwj;\ud83c\udfeb',
1638  'man_technologist':'\ud83d\udc68&zwj;\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&zwj;\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&zwj;\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&zwj;\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&zwj;\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&zwj;\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&zwj;\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&zwj;\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&zwj;\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&zwj;\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&zwj;\u2640\ufe0f',
1886  'rugby_football':'\ud83c\udfc9',
1887  'running_man':'\ud83c\udfc3',
1888  'running_shirt_with_sash':'\ud83c\udfbd',
1889  'running_woman':'\ud83c\udfc3&zwj;\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&zwj;\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&zwj;\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&zwj;\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&zwj;\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&zwj;\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&zwj;\ud83c\udfa8',
2142  'woman_astronaut':'\ud83d\udc69&zwj;\ud83d\ude80',
2143  'woman_cartwheeling':'\ud83e\udd38&zwj;\u2640\ufe0f',
2144  'woman_cook':'\ud83d\udc69&zwj;\ud83c\udf73',
2145  'woman_facepalming':'\ud83e\udd26&zwj;\u2640\ufe0f',
2146  'woman_factory_worker':'\ud83d\udc69&zwj;\ud83c\udfed',
2147  'woman_farmer':'\ud83d\udc69&zwj;\ud83c\udf3e',
2148  'woman_firefighter':'\ud83d\udc69&zwj;\ud83d\ude92',
2149  'woman_health_worker':'\ud83d\udc69&zwj;\u2695\ufe0f',
2150  'woman_judge':'\ud83d\udc69&zwj;\u2696\ufe0f',
2151  'woman_juggling':'\ud83e\udd39&zwj;\u2640\ufe0f',
2152  'woman_mechanic':'\ud83d\udc69&zwj;\ud83d\udd27',
2153  'woman_office_worker':'\ud83d\udc69&zwj;\ud83d\udcbc',
2154  'woman_pilot':'\ud83d\udc69&zwj;\u2708\ufe0f',
2155  'woman_playing_handball':'\ud83e\udd3e&zwj;\u2640\ufe0f',
2156  'woman_playing_water_polo':'\ud83e\udd3d&zwj;\u2640\ufe0f',
2157  'woman_scientist':'\ud83d\udc69&zwj;\ud83d\udd2c',
2158  'woman_shrugging':'\ud83e\udd37&zwj;\u2640\ufe0f',
2159  'woman_singer':'\ud83d\udc69&zwj;\ud83c\udfa4',
2160  'woman_student':'\ud83d\udc69&zwj;\ud83c\udf93',
2161  'woman_teacher':'\ud83d\udc69&zwj;\ud83c\udfeb',
2162  'woman_technologist':'\ud83d\udc69&zwj;\ud83d\udcbb',
2163  'woman_with_turban':'\ud83d\udc73&zwj;\u2640\ufe0f',
2164  'womans_clothes':'\ud83d\udc5a',
2165  'womans_hat':'\ud83d\udc52',
2166  'women_wrestling':'\ud83e\udd3c&zwj;\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, '&nbsp;');
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, '&quot;');
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, '&amp;');
3283
3284  // Encode naked <'s
3285  text = text.replace(/<(?![a-z\/?$!])/gi, '&lt;');
3286
3287  // Encode <
3288  text = text.replace(/</g, '&lt;');
3289
3290  // Encode >
3291  text = text.replace(/>/g, '&gt;');
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, '&amp;')
3333  // Do the angle bracket song and dance:
3334    .replace(/</g, '&lt;')
3335    .replace(/>/g, '&gt;')
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 '&lt;' + inside + '&gt;';
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(/&amp;/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(/&amp;/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, '&quot;')
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, '&quot;')
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:  ![alt text](url =<width>x<height> "optional title")
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, '&amp;')
4193      // double quotes
4194      .replace(/"/g, '&quot;');
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, '&quot;');
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 += '![' + node.getAttribute('alt') + '](';
4735    txt += '<' + node.getAttribute('src') + '>';
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.