#key - Parsing Markdown in Under 100 Lines of Javascript
if (typeof markdown === 'undefined') var markdown = {
parse: function (s) {
    var r = s, ii, pre1 = [], pre2 = [];

    // detect newline format
    var newline = r.indexOf('\r\n') != -1 ? '\r\n' : r.indexOf('\n') != -1 ? '\n' : ''
    
    // store CONSTANT "{ unformatted blocks": not defined !} and 
 pre-formatted blocks 
r = r.replace(/CONSTANT "{": not defined !}/g, function (x) { pre1.push(x.substring(3, x.length - 3)); return 'CONSTANT "{": not defined !}'; }); r = r.replace(new RegExp('
([\\s\\S]*?)
', 'gi'), function (x) { pre2.push(x.substring(5, x.length - 6)); return '
'; });
    
    // h1 - h4 and hr
    r = r.replace(/^==== (.*)=*/gm, '

$1

'); r = r.replace(/^=== (.*)=*/gm, '

$1

'); r = r.replace(/^== (.*)=*/gm, '

$1

'); r = r.replace(/^= (.*)=*/gm, '

$1

'); r = r.replace(/^[-*][-*][-*]+/gm, '
'); // bold, italics, and code formatting r = r.replace(/\*\*(.*?)\*\*/g, '$1'); r = r.replace(new RegExp('//(((?!https?://).)*?)//', 'g'), '$1'); r = r.replace(/``(.*?)``/g, '$1'); // unordered lists r = r.replace(/^\*\*\*\* (.*)/gm, '
        • $1
'); r = r.replace(/^\*\*\* (.*)/gm, '
      • $1
'); r = r.replace(/^\*\* (.*)/gm, '
    • $1
'); r = r.replace(/^\* (.*)/gm, '
  • $1
'); for (ii = 0; ii < 3; ii++) r = r.replace(new RegExp('' + newline + '
    ', 'g'), newline); // ordered lists r = r.replace(/^#### (.*)/gm, '
          1. $1
    '); r = r.replace(/^### (.*)/gm, '
        1. $1
    '); r = r.replace(/^## (.*)/gm, '
      1. $1
    '); r = r.replace(/^# (.*)/gm, '
    1. $1
    '); for (ii = 0; ii < 3; ii++) r = r.replace(new RegExp('' + newline + '
      ', 'g'), newline); // links r = r.replace(/\[\[(http:[^\]|]*?)\]\]/g, '$1'); r = r.replace(/\[\[(http:[^|]*?)\|(.*?)\]\]/g, '$2'); r = r.replace(/\[\[([^\]|]*?)\]\]/g, '$1'); r = r.replace(/\[\[([^|]*?)\|(.*?)\]\]/g, '$2'); // images r = r.replace(/{{([^\]|]*?)}}/g, ''); r = r.replace(/{{([^|]*?)\|(.*?)}}/g, '$2'); // video r = r.replace(/<<(.*?)>>/g, ''); // hard linebreak if there are 2 or more spaces at the end of a line r = r.replace(new RegExp(' + ' + newline, 'g'), '
      ' + newline); // split on double-newlines, then add paragraph tags when the first tag isn't a block level element if (newline != '') for (var p = r.split(newline + newline), i = 0; i < p.length; i++) { var blockLevel = false; if (p[i].length >= 1 && p[i].charAt(0) == '<') { // check if the first tag is a block-level element var firstSpace = p[i].indexOf(' '), firstCloseTag = p[i].indexOf('>'); var endIndex = firstSpace > -1 && firstCloseTag > -1 ? Math.min(firstSpace, firstCloseTag) : firstSpace > -1 ? firstSpace : firstCloseTag; var tag = p[i].substring(1, endIndex).toLowerCase(); for (var j = 0; j < blockLevelElements.length; j++) if (blockLevelElements[j] == tag) blockLevel = true; } else if (p[i].length >= 1 && p[i].charAt(0) == '|') { // format the paragraph as a table blockLevel = true; p[i] = p[i].replace(/ \|= /g, '').replace(/\|= /g, '').replace(/ \|=/g, ''); p[i] = p[i].replace(/ \| /g, '').replace(/\| /g, '').replace(/ \|/g, ''); p[i] = '' + p[i] + '
      '; } else if (p[i].length >= 2 && p[i].charAt(0) == '>' && p[i].charAt(1) == ' ') { // format the paragraph as a blockquote blockLevel = true; p[i] = '
      ' + p[i].replace(/^> /gm, '') + '
      '; } if (!blockLevel) p[i] = '

      ' + p[i] + '

      '; } // reassemble the paragraphs if (newline != '') r = p.join(newline + newline); // restore the preformatted and unformatted blocks r = r.replace(new RegExp('
      ', 'g'), function (match) { return '
      ' + pre2.shift() + '
      '; }); r = r.replace(/CONSTANT "{": not defined !}/g, function (match) { return pre1.shift(); }); return r; } }; // markdown.parse(myText) /* = Heading 1 == Heading 2 === Heading 3 ==== Heading 4 **bold** //italic// * Bullet list * Second item ** Sub item # Numbered list # Second item ## Sub item [[link]] CONSTANT "image": not defined ! <