Just type foo `bar` baz
at the prompt.
`bar`
...
#
text = text.replace(/([\`]+)(.+?)(\1)/g, "$2
");
*/
r = /(`+)(.+?)\1(?!`)/g
text = text.replace(r, function(match, str1, str2) {
str2 = str2.replace(/^[ \t]*/g, "");
str2 = str2.replace(/[ \t]*$/g, "");
str2 = EncodeCode(str2);
return ""+str2+"
";
} );
return text;
}
function EncodeCode(c) {
c = c.replace(/\&/gm, '&');
c = c.replace(/\/gm, '>');
c = Houdini(c);
return c;
}
function RunSpanGamut(text) {
/* #
# These are all the transformations that occur *within* block-level
# tags like paragraphs, headers, and list items.
# */
text = DoCodeSpans(text);
// moved "do hard breaks" up here 'cos EscapeSpecialChars eats trailing spaces.
// don't *think* it breaks anything...
text = text.replace(/[ ]{2,}$\n/gm, "` blocks.
//#
// $m_tab_width hard coded?
r = "(?:\\n\\n|\\A)((?:(?:[ ]{"+md_tab_width+"}|\\t).*\\n+)+)((?=^[ ]{0,"+md_tab_width+"}\\S)|\$)";
i = new RegExp(r, "gm");
text = text.replace(i, function(match, str1) {
codeblock = str1;
codeblock = EncodeCode(Outdent(codeblock));
codeblock = Detab(codeblock);
codeblock = codeblock.replace(/\A\n+/gm, "");
codeblock = codeblock.replace(/\s+$/g, "");
result = "\n\n" + codeblock + "\n
\n\n";
return result;
} );
return text;
}
function DoBlockQuotes(text) {
text = text.replace(/((^[ \t]*>[ \t]?.+\n(.+\n)*\n*)+)/gm, function(match, str1) {
bq = str1;
bq = bq.replace(/^[ \t]*>[ \t]?/gm, ""); //# trim one level of quoting
bq = bq.replace(/^[ \t]+$/gm, ""); //# trim whitespace-only lines
bq = RunBlockGamut(bq); //# recurse
bq = bq.replace(/\n+$/, "");
bq = bq.replace(/^/gm, " ");
//# These leading spaces screw with content, so we need to fix that:
bq = bq.replace(/(\s*[\s\S]+?<\/pre>)/g, function(match, str1) {
pre = str1;
pre = pre.replace(/^ /mg, "");
return pre;
} );
return "\n"+bq+"\n
\n\n";
} );
return text;
}
function dechex($char) {
$char = $char.toString(16)
return $char;
}
function EncodeEmailAddress($addr) {
$matches = $addr.match(/([^\:])/g);
$r = Math.round(Math.random()*100);
$newaddr = "";
for (var $match in $matches) {
$newaddr += rencode($matches[$match]);
}
$m = ""
for ($i=0; $i<6; $i++) {
$m+=rencode("mailto".charAt($i));
}
$addr = ''+$newaddr+'';
return $addr;
}
function rencode($char) {
$r = Math.round(Math.random()*100);
// roughly 10% raw, 45% hex, 45% dec
// '@' *must* be encoded. I insist.
if ($r > 90 && $char != "@") { return $char; }
else if ($r < 45) { return ""+$char.charCodeAt(0).toString(16)+";"; }
else { return ""+$char.charCodeAt(0)+";"; }
}
function DoAutoLinks(text) {
text = text.replace(/<((https?|ftp):[^'">\s]+)>/gi, function(match, str1) {
str1 = antiEm(str1);
return ''+str1+'';
});
//# Email addresses:
text = text.replace(/<(?:mailto:)?([-.\w]+\@[-a-z0-9]+(\.[-a-z0-9]+)*\.[a-z]+)>/gmi, function(match, str1) {
return EncodeEmailAddress(UnescapeSpecialChars(str1));
} );
//text = Houdini(text); // hashify special characters.
return text;
}
function FormParagraphs(text) {
//#
//# Params:
//# text - string to process with html tags
//#
//# Strip leading and trailing lines:
text = text.replace(/\A\n+/mg, "");
text = text.replace(/\n+\z/mg, "");
grafs = text.split(/\n{2,}/mg);
//#
//# Wrap
tags.
//#
for (var i in grafs) {
if (!md_html_blocks[grafs[i]]) {
// don't process blocks (all wrapped in some , but let through -- another kludge for you to enjoy
if (grafs[i] && (grafs[i].match(/\S+/gm)) && !grafs[i].match(/^[<](?!((https?|ftp):[^'">\s]+)>|(?:mailto:)?([-.\w]+\@[-a-z0-9]+(\.[-a-z0-9]+)*\.[a-z]+)>)/mi)) {
grafs[i] = RunSpanGamut(grafs[i]);
grafs[i] = ""+grafs[i];
//grafs[i] = grafs[i].replace(/^([ \t]*)/mg, "
");
grafs[i] += "
";
}
}
}
//#
//# Unhashify HTML blocks
//#
for (var i in grafs) {
if (md_html_blocks[grafs[i]]) {
grafs[i] = md_html_blocks[grafs[i]];
}
}
return grafs.join("\n\n");
}
function RunBlockGamut(text) {
//
// These are all the transformations that form block-level
// tags like paragraphs, headers, and list items.
//
text = DoHeaders(text);
// Do Horizontal Rules:
text = text.replace(/^[ ]{0,2}([ ]?\*[ ]?){3,}[ \t]*$/gm, "\n
tags around block-level tags.
text = HashHTMLBlocks(text);
text = FormParagraphs(text);
return text;
}
function RunBlockQuoteGamut(text) {
// recursion doesn't work at present
text = DoHeaders(text);
text = text.replace(/^( ?\* ?){3,}$/m, "\n
[ \\t]*(?=(\\n+|\\Z)))";
reg = new RegExp(r, "gm");
text = text.replace(reg, function(match, str1, str2) {
key=fakemd5();
while (md_html_blocks[key]) {
key=fakemd5();
}
md_html_blocks[key] = str1;
return "\n\n"+key+"\n\n";
});
r = "(^<("+block_tags_b+")\\b(.*\\n)*?.*<\\/\\2>[ \\t]*(?=(\\n+|\\Z)))";
reg = new RegExp(r, "gm");
text = text.replace(reg, function(match, str1, str2) {
key=fakemd5();
while (md_html_blocks[key]) {
key=fakemd5();
}
md_html_blocks[key] = str1;
return "\n\n"+key+"\n\n";
});
//
// Special case for
. Since JS doesn't support lookbehind, mightn't work right.
r = "(?:(\\n\\n)|\\A\\n?)([ ]{0,"+less_than_tab+"}<(hr)\\b([^<>])*?\\/?>[ \\t]*(?=\\n{2,}|\\Z))";
reg = new RegExp(r, "gm");
text = text.replace(reg, function(match, str1, str2) {
key=fakemd5();
while (md_html_blocks[key]) {
key=fakemd5();
}
md_html_blocks[key] = str2;
return "\n\n"+key+"\n\n";
});
//
// Special case for standalone comments. Same as above -- no lookbehind, mightn't work right.
r = "(?:(\\n\\n)|\\A\\n?)([ ]{0,"+less_than_tab+"}(?:)[ \\t]*(?=\\n{2,}|\\Z))";
reg = new RegExp(r, "gm");
text = text.replace(reg, function(match, str1, str2) {
key=fakemd5();
while (md_html_blocks[key]) {
key=fakemd5();
}
md_html_blocks[key] = str2;
return "\n\n"+key+"\n\n";
});
return text;
}
function StripLinkDefinitions(text) {
r = "^[ ]{0,"+less_than_tab+"}\\[(.+)\\]:[ \\t]*\\n?[ \\t]*(\\S+)>?[ \\t]*\\n?[ \\t]*(?:[\"(](.+?)[\")][ \\t]*)?(?:\\n+|\\Z)";
reg = new RegExp(r, "gm");
text = text.replace(reg, function(match, str1, str2, str3) {
link_id = str1.toLowerCase();
md_urls[link_id] = EncodeAmpsAndAngles(str2);
if (str3) {
md_titles[link_id] = str3;
}
return "";
} );
return text;
}
function htmlentities(text) {
// Note: just uses the hex entities. Easier than a gigantic associative array.
$re = /(%([a-zA-Z0-9]{1,4}))/g
$escaped = escape(text);
$entitized = $escaped.replace($re, "$2;")
return $entitized;
}
function EncodeAmpsAndAngles(text) {
// Smart processing for ampersands and angle brackets that need to be encoded.
text = text.replace(/&(?!#?[xX]?(?:[0-9a-fA-F]+|\w+);)/g, "&");
text = text.replace(/<(?![a-z\/?\$!])/gi, "<");
return text;
}
function EscapeSpecialChars(text) {
tokens = TokenizeHTML(text);
text = '';
// $in_pre = 0; # Keep track of when we're inside or tags.
// $tags_to_skip = "!<(/?)(?:pre|code|kbd|script|math)[\s>]!";
for (var i in tokens) {
if (tokens[i].type == "tag") {
// Within tags, encode * and _ so they don't conflict
// with their use in Markdown for italics and strong.
// We're replacing each such character with its
// corresponding MD5 checksum value; this is likely
// overkill, but it should prevent us from colliding
// with the escape values by accident.
t = tokens[i].value;
t = antiEm(t);
text += t;
} else {
t = tokens[i].value;
t = EncodeBackslashEscapes(t);
text += t;
}
}
return text;
}
function TokenizeHTML(string) {
//
// Parameter: String containing HTML markup.
// Returns: An array of the tokens comprising the input
// string. Each token is either a tag (possibly with nested,
// tags contained therein, such as , or a
// actually, I have no idea if this version will work with nested tags like that -- haven't tested it
// run of text between tags. Each element of the array is a
// two-element array; the first is either 'tag' or 'text';
// the second is the actual value.
//
// Returns: An array of objects with "type" and "value".
//
//
// Regular expression derived from the _tokenize() subroutine in
// Brad Choate's MTRegex plugin.
//
//
function token(type, value) {
this.type = type;
this.value = value;
}
tokens = new Array();
r = /(?:)|(?:<\?[\s\S]*?\?>)|(?:<[a-z\/!$](?:[^<>]|(?:<[a-z\/!$](?:[^<>]|(?:<[a-z\/!$](?:[^<>]|(?:<[a-z\/!$](?:[^<>]|(?:<[a-z\/!$](?:[^<>]|(?:<[a-z\/!$](?:[^<>])*>))*>))*>))*>))*>))*>)/i
while (r.test(string)) {
txt = RegExp.leftContext;
tag = RegExp.lastMatch;
tokens.push(new token("text", txt));
tokens.push(new token("tag", tag));
string = string.replace(txt, "");
string = string.replace(tag, "");
}
// everything past the last tag
if (string != "") {
tokens.push(new token("text", string));
}
return tokens;
}