Updating Markdown libraries to latest

This commit is contained in:
Nicholas Mayne
2014-07-19 19:28:49 +01:00
parent e0eff15fc5
commit 4d7d79f320
8 changed files with 203 additions and 63 deletions

View File

@@ -1,10 +1,11 @@
"use strict";
var Markdown; var Markdown;
if (typeof exports === "object" && typeof require === "function") // we're in a CommonJS (e.g. Node.js) module if (typeof exports === "object" && typeof require === "function") // we're in a CommonJS (e.g. Node.js) module
Markdown = exports; Markdown = exports;
else else
Markdown = {}; Markdown = {};
// The following text is included for historical reasons, but should // The following text is included for historical reasons, but should
// be taken with a pinch of salt; it's not all true anymore. // be taken with a pinch of salt; it's not all true anymore.
@@ -92,7 +93,7 @@ else
// caused an exception (and hence stopped the rendering) when the user entered // caused an exception (and hence stopped the rendering) when the user entered
// e.g. [push] or [__proto__]. Adding a prefix to the actual key prevents this // e.g. [push] or [__proto__]. Adding a prefix to the actual key prevents this
// (since no builtin property starts with "s_"). See // (since no builtin property starts with "s_"). See
// http://meta.stackoverflow.com/questions/64655/strange-wmd-bug // http://meta.stackexchange.com/questions/64655/strange-wmd-bug
// (granted, switching from Array() to Object() alone would have left only __proto__ // (granted, switching from Array() to Object() alone would have left only __proto__
// to be a problem) // to be a problem)
function SaveHash() { } function SaveHash() { }
@@ -105,7 +106,7 @@ else
} }
}; };
Markdown.Converter = function () { Markdown.Converter = function (OPTIONS) {
var pluginHooks = this.hooks = new HookCollection(); var pluginHooks = this.hooks = new HookCollection();
// given a URL that was encountered by itself (without markup), should return the link text that's to be given to this link // given a URL that was encountered by itself (without markup), should return the link text that's to be given to this link
@@ -142,6 +143,91 @@ else
// Used to track when we're inside an ordered or unordered list // Used to track when we're inside an ordered or unordered list
// (see _ProcessListItems() for details): // (see _ProcessListItems() for details):
var g_list_level; var g_list_level;
OPTIONS = OPTIONS || {};
var asciify = identity, deasciify = identity;
if (OPTIONS.nonAsciiLetters) {
/* In JavaScript regular expressions, \w only denotes [a-zA-Z0-9_].
* That's why there's inconsistent handling e.g. with intra-word bolding
* of Japanese words. That's why we do the following if OPTIONS.nonAsciiLetters
* is true:
*
* Before doing bold and italics, we find every instance
* of a unicode word character in the Markdown source that is not
* matched by \w, and the letter "Q". We take the character's code point
* and encode it in base 51, using the "digits"
*
* A, B, ..., P, R, ..., Y, Z, a, b, ..., y, z
*
* delimiting it with "Q" on both sides. For example, the source
*
* > In Chinese, the smurfs are called 藍精靈, meaning "blue spirits".
*
* turns into
*
* > In Chinese, the smurfs are called QNIhQQMOIQQOuUQ, meaning "blue spirits".
*
* Since everything that is a letter in Unicode is now a letter (or
* several letters) in ASCII, \w and \b should always do the right thing.
*
* After the bold/italic conversion, we decode again; since "Q" was encoded
* alongside all non-ascii characters (as "QBfQ"), and the conversion
* will not generate "Q", the only instances of that letter should be our
* encoded characters. And since the conversion will not break words, the
* "Q...Q" should all still be in one piece.
*
* We're using "Q" as the delimiter because it's probably one of the
* rarest characters, and also because I can't think of any special behavior
* that would ever be triggered by this letter (to use a silly example, if we
* delimited with "H" on the left and "P" on the right, then "Ψ" would be
* encoded as "HTTP", which may cause special behavior). The latter would not
* actually be a huge issue for bold/italic, but may be if we later use it
* in other places as well.
* */
(function () {
var lettersThatJavaScriptDoesNotKnowAndQ = /[Q\u00aa\u00b5\u00ba\u00c0-\u00d6\u00d8-\u00f6\u00f8-\u02c1\u02c6-\u02d1\u02e0-\u02e4\u02ec\u02ee\u0370-\u0374\u0376-\u0377\u037a-\u037d\u0386\u0388-\u038a\u038c\u038e-\u03a1\u03a3-\u03f5\u03f7-\u0481\u048a-\u0523\u0531-\u0556\u0559\u0561-\u0587\u05d0-\u05ea\u05f0-\u05f2\u0621-\u064a\u0660-\u0669\u066e-\u066f\u0671-\u06d3\u06d5\u06e5-\u06e6\u06ee-\u06fc\u06ff\u0710\u0712-\u072f\u074d-\u07a5\u07b1\u07c0-\u07ea\u07f4-\u07f5\u07fa\u0904-\u0939\u093d\u0950\u0958-\u0961\u0966-\u096f\u0971-\u0972\u097b-\u097f\u0985-\u098c\u098f-\u0990\u0993-\u09a8\u09aa-\u09b0\u09b2\u09b6-\u09b9\u09bd\u09ce\u09dc-\u09dd\u09df-\u09e1\u09e6-\u09f1\u0a05-\u0a0a\u0a0f-\u0a10\u0a13-\u0a28\u0a2a-\u0a30\u0a32-\u0a33\u0a35-\u0a36\u0a38-\u0a39\u0a59-\u0a5c\u0a5e\u0a66-\u0a6f\u0a72-\u0a74\u0a85-\u0a8d\u0a8f-\u0a91\u0a93-\u0aa8\u0aaa-\u0ab0\u0ab2-\u0ab3\u0ab5-\u0ab9\u0abd\u0ad0\u0ae0-\u0ae1\u0ae6-\u0aef\u0b05-\u0b0c\u0b0f-\u0b10\u0b13-\u0b28\u0b2a-\u0b30\u0b32-\u0b33\u0b35-\u0b39\u0b3d\u0b5c-\u0b5d\u0b5f-\u0b61\u0b66-\u0b6f\u0b71\u0b83\u0b85-\u0b8a\u0b8e-\u0b90\u0b92-\u0b95\u0b99-\u0b9a\u0b9c\u0b9e-\u0b9f\u0ba3-\u0ba4\u0ba8-\u0baa\u0bae-\u0bb9\u0bd0\u0be6-\u0bef\u0c05-\u0c0c\u0c0e-\u0c10\u0c12-\u0c28\u0c2a-\u0c33\u0c35-\u0c39\u0c3d\u0c58-\u0c59\u0c60-\u0c61\u0c66-\u0c6f\u0c85-\u0c8c\u0c8e-\u0c90\u0c92-\u0ca8\u0caa-\u0cb3\u0cb5-\u0cb9\u0cbd\u0cde\u0ce0-\u0ce1\u0ce6-\u0cef\u0d05-\u0d0c\u0d0e-\u0d10\u0d12-\u0d28\u0d2a-\u0d39\u0d3d\u0d60-\u0d61\u0d66-\u0d6f\u0d7a-\u0d7f\u0d85-\u0d96\u0d9a-\u0db1\u0db3-\u0dbb\u0dbd\u0dc0-\u0dc6\u0e01-\u0e30\u0e32-\u0e33\u0e40-\u0e46\u0e50-\u0e59\u0e81-\u0e82\u0e84\u0e87-\u0e88\u0e8a\u0e8d\u0e94-\u0e97\u0e99-\u0e9f\u0ea1-\u0ea3\u0ea5\u0ea7\u0eaa-\u0eab\u0ead-\u0eb0\u0eb2-\u0eb3\u0ebd\u0ec0-\u0ec4\u0ec6\u0ed0-\u0ed9\u0edc-\u0edd\u0f00\u0f20-\u0f29\u0f40-\u0f47\u0f49-\u0f6c\u0f88-\u0f8b\u1000-\u102a\u103f-\u1049\u1050-\u1055\u105a-\u105d\u1061\u1065-\u1066\u106e-\u1070\u1075-\u1081\u108e\u1090-\u1099\u10a0-\u10c5\u10d0-\u10fa\u10fc\u1100-\u1159\u115f-\u11a2\u11a8-\u11f9\u1200-\u1248\u124a-\u124d\u1250-\u1256\u1258\u125a-\u125d\u1260-\u1288\u128a-\u128d\u1290-\u12b0\u12b2-\u12b5\u12b8-\u12be\u12c0\u12c2-\u12c5\u12c8-\u12d6\u12d8-\u1310\u1312-\u1315\u1318-\u135a\u1380-\u138f\u13a0-\u13f4\u1401-\u166c\u166f-\u1676\u1681-\u169a\u16a0-\u16ea\u1700-\u170c\u170e-\u1711\u1720-\u1731\u1740-\u1751\u1760-\u176c\u176e-\u1770\u1780-\u17b3\u17d7\u17dc\u17e0-\u17e9\u1810-\u1819\u1820-\u1877\u1880-\u18a8\u18aa\u1900-\u191c\u1946-\u196d\u1970-\u1974\u1980-\u19a9\u19c1-\u19c7\u19d0-\u19d9\u1a00-\u1a16\u1b05-\u1b33\u1b45-\u1b4b\u1b50-\u1b59\u1b83-\u1ba0\u1bae-\u1bb9\u1c00-\u1c23\u1c40-\u1c49\u1c4d-\u1c7d\u1d00-\u1dbf\u1e00-\u1f15\u1f18-\u1f1d\u1f20-\u1f45\u1f48-\u1f4d\u1f50-\u1f57\u1f59\u1f5b\u1f5d\u1f5f-\u1f7d\u1f80-\u1fb4\u1fb6-\u1fbc\u1fbe\u1fc2-\u1fc4\u1fc6-\u1fcc\u1fd0-\u1fd3\u1fd6-\u1fdb\u1fe0-\u1fec\u1ff2-\u1ff4\u1ff6-\u1ffc\u203f-\u2040\u2054\u2071\u207f\u2090-\u2094\u2102\u2107\u210a-\u2113\u2115\u2119-\u211d\u2124\u2126\u2128\u212a-\u212d\u212f-\u2139\u213c-\u213f\u2145-\u2149\u214e\u2183-\u2184\u2c00-\u2c2e\u2c30-\u2c5e\u2c60-\u2c6f\u2c71-\u2c7d\u2c80-\u2ce4\u2d00-\u2d25\u2d30-\u2d65\u2d6f\u2d80-\u2d96\u2da0-\u2da6\u2da8-\u2dae\u2db0-\u2db6\u2db8-\u2dbe\u2dc0-\u2dc6\u2dc8-\u2dce\u2dd0-\u2dd6\u2dd8-\u2dde\u2e2f\u3005-\u3006\u3031-\u3035\u303b-\u303c\u3041-\u3096\u309d-\u309f\u30a1-\u30fa\u30fc-\u30ff\u3105-\u312d\u3131-\u318e\u31a0-\u31b7\u31f0-\u31ff\u3400-\u4db5\u4e00-\u9fc3\ua000-\ua48c\ua500-\ua60c\ua610-\ua62b\ua640-\ua65f\ua662-\ua66e\ua67f-\ua697\ua717-\ua71f\ua722-\ua788\ua78b-\ua78c\ua7fb-\ua801\ua803-\ua805\ua807-\ua80a\ua80c-\ua822\ua840-\ua873\ua882-\ua8b3\ua8d0-\ua8d9\ua900-\ua925\ua930-\ua946\uaa00-\uaa28\uaa40-\uaa42\uaa44-\uaa4b\uaa50-\uaa59\uac00-\ud7a3\uf900-\ufa2d\ufa30-\ufa6a\ufa70-\ufad9\ufb00-\ufb06\ufb13-\ufb17\ufb1d\ufb1f-\ufb28\ufb2a-\ufb36\ufb38-\ufb3c\ufb3e\ufb40-\ufb41\ufb43-\ufb44\ufb46-\ufbb1\ufbd3-\ufd3d\ufd50-\ufd8f\ufd92-\ufdc7\ufdf0-\ufdfb\ufe33-\ufe34\ufe4d-\ufe4f\ufe70-\ufe74\ufe76-\ufefc\uff10-\uff19\uff21-\uff3a\uff3f\uff41-\uff5a\uff66-\uffbe\uffc2-\uffc7\uffca-\uffcf\uffd2-\uffd7\uffda-\uffdc]/g;
var cp_Q = "Q".charCodeAt(0);
var cp_A = "A".charCodeAt(0);
var cp_Z = "Z".charCodeAt(0);
var dist_Za = "a".charCodeAt(0) - cp_Z - 1;
asciify = function(text) {
return text.replace(lettersThatJavaScriptDoesNotKnowAndQ, function (m) {
var c = m.charCodeAt(0);
var s = "";
var v;
while (c > 0) {
v = (c % 51) + cp_A;
if (v >= cp_Q)
v++;
if (v > cp_Z)
v += dist_Za;
s = String.fromCharCode(v) + s;
c = c / 51 | 0;
}
return "Q" + s + "Q";
})
};
deasciify = function(text) {
return text.replace(/Q([A-PR-Za-z]{1,3})Q/g, function (m, s) {
var c = 0;
var v;
for (var i = 0; i < s.length; i++) {
v = s.charCodeAt(i);
if (v > cp_Z)
v -= dist_Za;
if (v > cp_Q)
v--;
v -= cp_A;
c = (c * 51) + v;
}
return String.fromCharCode(c);
})
}
})();
}
this.makeHtml = function (text) { this.makeHtml = function (text) {
@@ -227,7 +313,7 @@ else
/* /*
text = text.replace(/ text = text.replace(/
^[ ]{0,3}\[(.+)\]: // id = $1 attacklab: g_tab_width - 1 ^[ ]{0,3}\[([^\[\]]+)\]: // id = $1 attacklab: g_tab_width - 1
[ \t]* [ \t]*
\n? // maybe *one* newline \n? // maybe *one* newline
[ \t]* [ \t]*
@@ -248,7 +334,7 @@ else
/gm, function(){...}); /gm, function(){...});
*/ */
text = text.replace(/^[ ]{0,3}\[(.+)\]:[ \t]*\n?[ \t]*<?(\S+?)>?(?=\s|$)[ \t]*\n?[ \t]*((\n*)["(](.+?)[")][ \t]*)?(?:\n+)/gm, text = text.replace(/^[ ]{0,3}\[([^\[\]]+)\]:[ \t]*\n?[ \t]*<?(\S+?)>?(?=\s|$)[ \t]*\n?[ \t]*((\n*)["(](.+?)[")][ \t]*)?(?:\n+)/gm,
function (wholeMatch, m1, m2, m3, m4, m5) { function (wholeMatch, m1, m2, m3, m4, m5) {
m1 = m1.toLowerCase(); m1 = m1.toLowerCase();
g_urls.set(m1, _EncodeAmpsAndAngles(m2)); // Link IDs are case-insensitive g_urls.set(m1, _EncodeAmpsAndAngles(m2)); // Link IDs are case-insensitive
@@ -307,7 +393,7 @@ else
) // attacklab: there are sentinel newlines at end of document ) // attacklab: there are sentinel newlines at end of document
/gm,function(){...}}; /gm,function(){...}};
*/ */
text = text.replace(/^(<(p|div|h[1-6]|blockquote|pre|table|dl|ol|ul|script|noscript|form|fieldset|iframe|math|ins|del)\b[^\r]*?\n<\/\2>[ \t]*(?=\n+))/gm, hashElement); text = text.replace(/^(<(p|div|h[1-6]|blockquote|pre|table|dl|ol|ul|script|noscript|form|fieldset|iframe|math|ins|del)\b[^\r]*?\n<\/\2>[ \t]*(?=\n+))/gm, hashMatch);
// //
// Now match more liberally, simply from `\n<tag>` to `</tag>\n` // Now match more liberally, simply from `\n<tag>` to `</tag>\n`
@@ -327,7 +413,7 @@ else
) // attacklab: there are sentinel newlines at end of document ) // attacklab: there are sentinel newlines at end of document
/gm,function(){...}}; /gm,function(){...}};
*/ */
text = text.replace(/^(<(p|div|h[1-6]|blockquote|pre|table|dl|ol|ul|script|noscript|form|fieldset|iframe|math)\b[^\r]*?.*<\/\2>[ \t]*(?=\n+)\n)/gm, hashElement); text = text.replace(/^(<(p|div|h[1-6]|blockquote|pre|table|dl|ol|ul|script|noscript|form|fieldset|iframe|math)\b[^\r]*?.*<\/\2>[ \t]*(?=\n+)\n)/gm, hashMatch);
// Special case just for <hr />. It was easier to make a special case than // Special case just for <hr />. It was easier to make a special case than
// to make the other regex more complicated. // to make the other regex more complicated.
@@ -344,9 +430,9 @@ else
[ \t]* [ \t]*
(?=\n{2,}) // followed by a blank line (?=\n{2,}) // followed by a blank line
) )
/g,hashElement); /g,hashMatch);
*/ */
text = text.replace(/\n[ ]{0,3}((<(hr)\b([^<>])*?\/?>)[ \t]*(?=\n{2,}))/g, hashElement); text = text.replace(/\n[ ]{0,3}((<(hr)\b([^<>])*?\/?>)[ \t]*(?=\n{2,}))/g, hashMatch);
// Special case for standalone HTML comments: // Special case for standalone HTML comments:
@@ -356,14 +442,14 @@ else
[ ]{0,3} // attacklab: g_tab_width - 1 [ ]{0,3} // attacklab: g_tab_width - 1
( // save in $1 ( // save in $1
<! <!
(--(?:|(?:[^>-]|-[^>])(?:[^-]|-[^-])*)--) // see http://www.w3.org/TR/html-markup/syntax.html#comments and http://meta.stackoverflow.com/q/95256 (--(?:|(?:[^>-]|-[^>])(?:[^-]|-[^-])*)--) // see http://www.w3.org/TR/html-markup/syntax.html#comments and http://meta.stackexchange.com/q/95256
> >
[ \t]* [ \t]*
(?=\n{2,}) // followed by a blank line (?=\n{2,}) // followed by a blank line
) )
/g,hashElement); /g,hashMatch);
*/ */
text = text.replace(/\n\n[ ]{0,3}(<!(--(?:|(?:[^>-]|-[^>])(?:[^-]|-[^-])*)--)>[ \t]*(?=\n{2,}))/g, hashElement); text = text.replace(/\n\n[ ]{0,3}(<!(--(?:|(?:[^>-]|-[^>])(?:[^-]|-[^-])*)--)>[ \t]*(?=\n{2,}))/g, hashMatch);
// PHP and ASP-style processor instructions (<?...?> and <%...%>) // PHP and ASP-style processor instructions (<?...?> and <%...%>)
@@ -382,26 +468,21 @@ else
[ \t]* [ \t]*
(?=\n{2,}) // followed by a blank line (?=\n{2,}) // followed by a blank line
) )
/g,hashElement); /g,hashMatch);
*/ */
text = text.replace(/(?:\n\n)([ ]{0,3}(?:<([?%])[^\r]*?\2>)[ \t]*(?=\n{2,}))/g, hashElement); text = text.replace(/(?:\n\n)([ ]{0,3}(?:<([?%])[^\r]*?\2>)[ \t]*(?=\n{2,}))/g, hashMatch);
return text; return text;
} }
function hashElement(wholeMatch, m1) { function hashBlock(text) {
var blockText = m1; text = text.replace(/(^\n+|\n+$)/g, "");
// Undo double lines
blockText = blockText.replace(/^\n+/, "");
// strip trailing blank lines
blockText = blockText.replace(/\n+$/g, "");
// Replace the element text with a marker ("~KxK" where x is its key) // Replace the element text with a marker ("~KxK" where x is its key)
blockText = "\n\n~K" + (g_html_blocks.push(blockText) - 1) + "K\n\n"; return "\n\n~K" + (g_html_blocks.push(text) - 1) + "K\n\n";
}
return blockText; function hashMatch(wholeMatch, m1) {
return hashBlock(m1);
} }
var blockGamutHookCallback = function (t) { return _RunBlockGamut(t); } var blockGamutHookCallback = function (t) { return _RunBlockGamut(t); }
@@ -488,7 +569,7 @@ else
text = text.replace(regex, function (wholeMatch) { text = text.replace(regex, function (wholeMatch) {
var tag = wholeMatch.replace(/(.)<\/?code>(?=.)/g, "$1`"); var tag = wholeMatch.replace(/(.)<\/?code>(?=.)/g, "$1`");
tag = escapeCharacters(tag, wholeMatch.charAt(1) == "!" ? "\\`*_/" : "\\`*_"); // also escape slashes in comments to prevent autolinking there -- http://meta.stackoverflow.com/questions/95987 tag = escapeCharacters(tag, wholeMatch.charAt(1) == "!" ? "\\`*_/" : "\\`*_"); // also escape slashes in comments to prevent autolinking there -- http://meta.stackexchange.com/questions/95987
return tag; return tag;
}); });
@@ -997,11 +1078,6 @@ else
return text; return text;
} }
function hashBlock(text) {
text = text.replace(/(^\n+|\n+$)/g, "");
return "\n\n~K" + (g_html_blocks.push(text) - 1) + "K\n\n";
}
function _DoCodeSpans(text) { function _DoCodeSpans(text) {
// //
// * Backtick quotes are used for <code></code> spans. // * Backtick quotes are used for <code></code> spans.
@@ -1030,8 +1106,9 @@ else
/* /*
text = text.replace(/ text = text.replace(/
(^|[^\\]) // Character before opening ` can't be a backslash (^|[^\\`]) // Character before opening ` can't be a backslash or backtick
(`+) // $2 = Opening run of ` (`+) // $2 = Opening run of `
(?!`) // and no more backticks -- match the full run
( // $3 = The code block ( // $3 = The code block
[^\r]*? [^\r]*?
[^`] // attacklab: work around lack of lookbehind [^`] // attacklab: work around lack of lookbehind
@@ -1041,7 +1118,7 @@ else
/gm, function(){...}); /gm, function(){...});
*/ */
text = text.replace(/(^|[^\\])(`+)([^\r]*?[^`])\2(?!`)/gm, text = text.replace(/(^|[^\\`])(`+)(?!`)([^\r]*?[^`])\2(?!`)/gm,
function (wholeMatch, m1, m2, m3, m4) { function (wholeMatch, m1, m2, m3, m4) {
var c = m3; var c = m3;
c = c.replace(/^([ \t]*)/g, ""); // leading whitespace c = c.replace(/^([ \t]*)/g, ""); // leading whitespace
@@ -1087,14 +1164,38 @@ else
function _DoItalicsAndBold(text) { function _DoItalicsAndBold(text) {
text = asciify(text);
// <strong> must go first: // <strong> must go first:
text = text.replace(/([\W_]|^)(\*\*|__)(?=\S)([^\r]*?\S[\*_]*)\2([\W_]|$)/g,
"$1<strong>$3</strong>$4"); // (^|[\W_]) Start with a non-letter or beginning of string. Store in \1.
// (?:(?!\1)|(?=^)) Either the next character is *not* the same as the previous,
// or we started at the end of the string (in which case the previous
// group had zero width, so we're still there). Because the next
// character is the marker, this means that if there are e.g. multiple
// underscores in a row, we can only match the left-most ones (which
// prevents foo___bar__ from getting bolded)
// (\*|_) The marker character itself, asterisk or underscore. Store in \2.
// \2 The marker again, since bold needs two.
// (?=\S) The first bolded character cannot be a space.
// ([^\r]*?\S) The actual bolded string. At least one character, and it cannot *end*
// with a space either. Note that like in many other places, [^\r] is
// just a workaround for JS' lack of single-line regexes; it's equivalent
// to a . in an /s regex, because the string cannot contain any \r (they
// are removed in the normalizing step).
// \2\2 The marker character, twice -- end of bold.
// (?!\2) Not followed by another marker character (ensuring that we match the
// rightmost two in a longer row)...
// (?=[\W_]|$) ...but by any other non-word character or the end of string.
text = text.replace(/(^|[\W_])(?:(?!\1)|(?=^))(\*|_)\2(?=\S)([^\r]*?\S)\2\2(?!\2)(?=[\W_]|$)/g,
"$1<strong>$3</strong>");
text = text.replace(/([\W_]|^)(\*|_)(?=\S)([^\r\*_]*?\S)\2([\W_]|$)/g, // This is almost identical to the <strong> regex, except 1) there's obviously just one marker
"$1<em>$3</em>$4"); // character, and 2) the italicized string cannot contain the marker character.
text = text.replace(/(^|[\W_])(?:(?!\1)|(?=^))(\*|_)(?=\S)((?:(?!\2)[^\r])*?\S)\2(?!\2)(?=[\W_]|$)/g,
"$1<em>$3</em>");
return text; return deasciify(text);
} }
function _DoBlockQuotes(text) { function _DoBlockQuotes(text) {
@@ -1286,7 +1387,13 @@ else
// autolink anything like <http://example.com> // autolink anything like <http://example.com>
var replacer = function (wholematch, m1) { return "<a href=\"" + m1 + "\">" + pluginHooks.plainLinkText(m1) + "</a>"; }
var replacer = function (wholematch, m1) {
var url = encodeProblemUrlChars(m1);
url = escapeCharacters(url, "*_");
return "<a href=\"" + url + "\">" + pluginHooks.plainLinkText(m1) + "</a>";
};
text = text.replace(/<((https?|ftp):[^'">\s]+)>/gi, replacer); text = text.replace(/<((https?|ftp):[^'">\s]+)>/gi, replacer);
// Email addresses: <address@domain.foo> // Email addresses: <address@domain.foo>
@@ -1409,4 +1516,4 @@ else
}; // end of the Markdown.Converter constructor }; // end of the Markdown.Converter constructor
})(); })();

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@@ -232,7 +232,7 @@
var regexText; var regexText;
var replacementText; var replacementText;
// chrome bug ... documented at: http://meta.stackoverflow.com/questions/63307/blockquote-glitch-in-editor-in-chrome-6-and-7/65985#65985 // chrome bug ... documented at: http://meta.stackexchange.com/questions/63307/blockquote-glitch-in-editor-in-chrome-6-and-7/65985#65985
if (navigator.userAgent.match(/Chrome/)) { if (navigator.userAgent.match(/Chrome/)) {
"X".match(/()./); "X".match(/()./);
} }
@@ -1079,7 +1079,9 @@
var checkEscape = function (key) { var checkEscape = function (key) {
var code = (key.charCode || key.keyCode); var code = (key.charCode || key.keyCode);
if (code === 27) { if (code === 27) {
if (key.stopPropagation) key.stopPropagation();
close(true); close(true);
return false;
} }
}; };
@@ -1087,7 +1089,7 @@
// isCancel is true if we don't care about the input text. // isCancel is true if we don't care about the input text.
// isCancel is false if we are going to keep the text. // isCancel is false if we are going to keep the text.
var close = function (isCancel) { var close = function (isCancel) {
util.removeEvent(doc.body, "keydown", checkEscape); util.removeEvent(doc.body, "keyup", checkEscape);
var text = input.value; var text = input.value;
if (isCancel) { if (isCancel) {
@@ -1171,7 +1173,7 @@
form.appendChild(okButton); form.appendChild(okButton);
form.appendChild(cancelButton); form.appendChild(cancelButton);
util.addEvent(doc.body, "keydown", checkEscape); util.addEvent(doc.body, "keyup", checkEscape);
dialog.style.top = "50%"; dialog.style.top = "50%";
dialog.style.left = "50%"; dialog.style.left = "50%";
dialog.style.display = "block"; dialog.style.display = "block";
@@ -1686,14 +1688,39 @@
// sure the URL and the optinal title are "nice". // sure the URL and the optinal title are "nice".
function properlyEncoded(linkdef) { function properlyEncoded(linkdef) {
return linkdef.replace(/^\s*(.*?)(?:\s+"(.+)")?\s*$/, function (wholematch, link, title) { return linkdef.replace(/^\s*(.*?)(?:\s+"(.+)")?\s*$/, function (wholematch, link, title) {
link = link.replace(/\?.*$/, function (querypart) {
return querypart.replace(/\+/g, " "); // in the query string, a plus and a space are identical var inQueryString = false;
});
link = decodeURIComponent(link); // unencode first, to prevent double encoding // The last alternative, `[^\w\d-./]`, is just a shortcut that lets us skip
link = encodeURI(link).replace(/'/g, '%27').replace(/\(/g, '%28').replace(/\)/g, '%29'); // the most common characters in URLs. Replacing it with `.` would not change
link = link.replace(/\?.*$/, function (querypart) { // the result, because encodeURI returns those characters unchanged, but it
return querypart.replace(/\+/g, "%2b"); // since we replaced plus with spaces in the query part, all pluses that now appear where originally encoded // would mean lots of unnecessary replacement calls
}); link = link.replace(/%(?:[\da-fA-F]{2})|\?|\+|[^\w\d-./]/g, function (match) {
// Valid percent encoding. Could just return it as is, but we follow RFC3986
// Section 2.1 which says "For consistency, URI producers and normalizers
// should use uppercase hexadecimal digits for all percent-encodings."
// Note that we also handle (illegal) stand-alone percent characters by
// replacing them with "%25"
if (match.length === 3 && match.charAt(0) == "%") {
return match.toUpperCase();
}
switch (match) {
case "?":
inQueryString = true;
return "?";
break;
// In the query string, a plus and a space are identical -- normalize.
// Not strictly necessary, but identical behavior to the previous version
// of this function.
case "+":
if (inQueryString)
return "%20";
break;
}
return encodeURI(match);
})
if (title) { if (title) {
title = title.trim ? title.trim() : title.replace(/^\s*/, "").replace(/\s*$/, ""); title = title.trim ? title.trim() : title.replace(/^\s*/, "").replace(/\s*$/, "");
title = title.replace(/"/g, "quot;").replace(/\(/g, "&#40;").replace(/\)/g, "&#41;").replace(/</g, "&lt;").replace(/>/g, "&gt;"); title = title.replace(/"/g, "quot;").replace(/\(/g, "&#40;").replace(/\)/g, "&#41;").replace(/</g, "&lt;").replace(/>/g, "&gt;");
@@ -1874,7 +1901,7 @@
// //
// Since this is essentially a backwards-moving regex, it's susceptible to // Since this is essentially a backwards-moving regex, it's susceptible to
// catstrophic backtracking and can cause the browser to hang; // catstrophic backtracking and can cause the browser to hang;
// see e.g. http://meta.stackoverflow.com/questions/9807. // see e.g. http://meta.stackexchange.com/questions/9807.
// //
// Hence we replaced this by a simple state machine that just goes through the // Hence we replaced this by a simple state machine that just goes through the
// lines and checks for a), b), and c). // lines and checks for a), b), and c).

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@@ -1,2 +1,4 @@
(function(){function i(n){return n.replace(/<[^>]*>?/gi,e)}function e(n){return n.match(r)||n.match(u)||n.match(f)?n:""}function o(n){var i,t;if(n=="")return"";var s=/<\/?\w+[^>]*(\s|$|>)/g,r=n.toLowerCase().match(s),f=(r||[]).length;if(f==0)return n;var e,h,u,o=[],c=[],l=!1;for(t=0;t<f;t++)if(e=r[t].replace(/<\/?(\w+).*/,"$1"),!o[t]&&!("<p><img><br><li><hr>".search("<"+e+">")>-1)){if(h=r[t],u=-1,!/^<\//.test(h))for(i=t+1;i<f;i++)if(!o[i]&&r[i]=="<\/"+e+">"){u=i;break}u==-1?l=c[t]=!0:o[u]=!0}return l?(t=0,n.replace(s,function(n){var i=c[t]?"":n;return t++,i})):n}var n,t;typeof exports=="object"&&typeof require=="function"?(n=exports,t=require("./Markdown.Converter").Converter):(n=window.Markdown,t=n.Converter),n.getSanitizingConverter=function(){var n=new t;return n.hooks.chain("postConversion",i),n.hooks.chain("postConversion",o),n};var r=/^(<\/?(b|blockquote|code|del|dd|dl|dt|em|h1|h2|h3|i|kbd|li|ol|p|pre|s|sup|sub|strong|strike|ul)>|<(br|hr)\s?\/?>)$/i,u=/^(<a\shref="((https?|ftp):\/\/|\/)[-A-Za-z0-9+&@#\/%?=~_|!:,.;\(\)]+"(\stitle="[^"<>]+")?\s?>|<\/a>)$/i,f=/^(<img\ssrc="(https?:\/\/|\/)[-A-Za-z0-9+&@#\/%?=~_|!:,.;\(\)]+"(\swidth="\d{1,3}")?(\sheight="\d{1,3}")?(\salt="[^"<>]*")?(\stitle="[^"<>]*")?\s?\/?>)$/i})(); (function(){function i(n){return n.replace(/<[^>]*>?/gi,e)}function e(n){return n.match(r)||n.match(u)||n.match(f)?n:""}function o(n){var i,t;if(n=="")return"";var s=/<\/?\w+[^>]*(\s|$|>)/g,r=n.toLowerCase().match(s),f=(r||[]).length;if(f==0)return n;var e,h,u,o=[],c=[],l=!1;for(t=0;t<f;t++)if(e=r[t].replace(/<\/?(\w+).*/,"$1"),!o[t]&&!("<p><img><br><li><hr>".search("<"+e+">")>-1)){if(h=r[t],u=-1,!/^<\//.test(h))for(i=t+1;i<f;i++)if(!o[i]&&r[i]=="<\/"+e+">"){u=i;break}u==-1?l=c[t]=!0:o[u]=!0}return l?(t=0,n.replace(s,function(n){var i=c[t]?"":n;return t++,i})):n}var n,t;typeof exports=="object"&&typeof require=="function"?(n=exports,t=require("./Markdown.Converter").Converter):(n=window.Markdown,t=n.Converter);n.getSanitizingConverter=function(){var n=new t;return n.hooks.chain("postConversion",i),n.hooks.chain("postConversion",o),n};var r=/^(<\/?(b|blockquote|code|del|dd|dl|dt|em|h1|h2|h3|i|kbd|li|ol|p|pre|s|sup|sub|strong|strike|ul)>|<(br|hr)\s?\/?>)$/i,u=/^(<a\shref="((https?|ftp):\/\/|\/)[-A-Za-z0-9+&@#\/%?=~_|!:,.;\(\)]+"(\stitle="[^"<>]+")?\s?>|<\/a>)$/i,f=/^(<img\ssrc="(https?:\/\/|\/)[-A-Za-z0-9+&@#\/%?=~_|!:,.;\(\)]+"(\swidth="\d{1,3}")?(\sheight="\d{1,3}")?(\salt="[^"<>]*")?(\stitle="[^"<>]*")?\s?\/?>)$/i})();
//@ sourceMappingURL=Markdown.Sanitizer.min.js.map /*
//# sourceMappingURL=Markdown.Sanitizer.min.js.map
*/

View File

@@ -2,7 +2,7 @@
"version":3, "version":3,
"file":"Markdown.Sanitizer.min.js", "file":"Markdown.Sanitizer.min.js",
"lineCount":1, "lineCount":1,
"mappings":"CAAC,QAAS,CAAA,CAAG,CAiBTA,SAASA,CAAY,CAACC,CAAD,CAAO,CACxB,OAAOA,CAAIC,QAAQ,CAAC,YAAY,CAAEC,CAAf,CADK,CAY5BA,SAASA,CAAW,CAACC,CAAD,CAAM,CACtB,OAAIA,CAAGC,MAAM,CAACC,CAAD,CAAsB,EAAGF,CAAGC,MAAM,CAACE,CAAD,CAAU,EAAGH,CAAGC,MAAM,CAACG,CAAD,C,CAC1DJ,C,CAEA,EAJW,CAe1BK,SAASA,CAAW,CAACR,CAAD,CAAO,CAuBlB,IAaYS,EAmBbC,C,CArDJ,GAAIV,CAAK,EAAG,GACR,MAAO,EAAE,CAEb,IAAIW,EAAK,wBAGLC,EAAOZ,CAAIa,YAAY,CAAA,CAAET,MAAM,CAACO,CAAD,EAG/BG,EAAW,CAACF,CAAK,EAAG,CAAA,CAAT,CAAYG,OANK,CAOhC,GAAID,CAAS,EAAG,EACZ,OAAOd,CAAI,CAEf,IAAIgB,EAASb,EAETC,EACAa,EAAY,CAAA,EACZC,EAAY,CAAA,EACZC,EAAe,CAAA,CALH,CAQhB,IAAST,CAAK,CAAE,CAAC,CAAEA,CAAK,CAAEI,CAAQ,CAAEJ,CAAI,EAAxC,CAII,GAHAM,CAAQ,CAAEJ,CAAK,CAAAF,CAAA,CAAKT,QAAQ,CAAC,aAAa,CAAE,IAAhB,CAAqB,CAG7C,CAAAgB,CAAU,CAAAP,CAAA,CAAM,EAAG,EAXT,sBAWoBU,OAAO,CAAC,GAAI,CAAEJ,CAAQ,CAAE,GAAjB,CAAsB,CAAE,IAC7D,CAKJ,GAHAb,CAAI,CAAES,CAAK,CAAAF,CAAA,CAAK,CAChBN,CAAM,CAAE,EAAE,CAEN,CAAC,MAAMiB,KAAK,CAAClB,CAAD,EAGZ,IAASM,CAAK,CAAEC,CAAK,CAAE,CAAC,CAAED,CAAK,CAAEK,CAAQ,CAAEL,CAAI,EAA/C,CACI,GAAI,CAACQ,CAAU,CAAAR,CAAA,CAAM,EAAGG,CAAK,CAAAH,CAAA,CAAM,EAAG,KAAK,CAAEO,CAAQ,CAAE,IAAK,CACxDZ,CAAM,CAAEK,CAAI,CACZ,KAFwD,CAOhEL,CAAM,EAAG,EAAb,CACIe,CAAa,CAAED,CAAU,CAAAR,CAAA,CAAM,CAAE,CAAA,CADrC,CAGIO,CAAU,CAAAb,CAAA,CAAO,CAAE,CAAA,CAnBnB,CAiCR,OAXKe,C,EA3BIT,CAgCA,CAAE,C,CACJV,CAAIC,QAAQ,CAACU,CAAE,CAAE,QAAS,CAACP,CAAD,CAAQ,CACrC,IAAIkB,EAAMJ,CAAU,CAAAR,CAAA,CAAM,CAAE,EAAG,CAAEN,CAAK,CAEtC,OADAM,CAAI,EAAE,CACCY,CAH8B,CAAtB,E,CALRtB,CAnDY,CA3C3B,IAAIuB,EAAQC,CAAS,CACjB,OAAOC,OAAQ,EAAI,QAAS,EAAG,OAAOC,OAAQ,EAAI,UAAtD,EACIH,CAAO,CAAEE,OAAO,CAChBD,CAAU,CAAEE,OAAO,CAAC,sBAAD,CAAwBF,WAF/C,EAIID,CAAO,CAAEI,MAAMC,SAAS,CACxBJ,CAAU,CAAED,CAAMC,W,CAGtBD,CAAMM,uBAAwB,CAAEC,QAAS,CAAA,CAAG,CACxC,IAAIC,EAAY,IAAIP,CAAW,CAG/B,OAFAO,CAASC,MAAMC,MAAM,CAAC,gBAAgB,CAAElC,CAAnB,CAAgC,CACrDgC,CAASC,MAAMC,MAAM,CAAC,gBAAgB,CAAEzB,CAAnB,CAA+B,CAC7CuB,CAJiC,C,CAY5C,IAAI1B,EAAsB,sHAEtBC,EAAU,yGAGVC,EAAY,2JA3BP,EA2GX,CAAA,CAAE", "mappings":"CAAC,QAAS,CAAA,CAAG,CAiBTA,SAASA,CAAY,CAACC,CAAD,CAAO,CACxB,OAAOA,CAAIC,QAAQ,CAAa,YAAA,CAAEC,CAAf,CADK,CAY5BA,SAASA,CAAW,CAACC,CAAD,CAAM,CACtB,OAAIA,CAAGC,MAAM,CAACC,CAAD,CAAsB,EAAGF,CAAGC,MAAM,CAACE,CAAD,CAAU,EAAGH,CAAGC,MAAM,CAACG,CAAD,CAAjE,CACOJ,CADP,CAGO,EAJW,CAe1BK,SAASA,CAAW,CAACR,CAAD,CAAO,CAuBlB,IAaYS,EAmBbC,C,CArDJ,GAAIV,CAAK,EAAG,GACR,MAAO,EAAE,CAEb,IAAIW,EAA4B,wBAG5BC,EAAOZ,CAAIa,YAAY,CAAA,CAAET,MAAM,CAACO,CAAD,EAG/BG,EAAW,CAACF,CAAK,EAAG,CAAA,CAAT,CAAYG,OANK,CAOhC,GAAID,CAAS,EAAG,EACZ,OAAOd,CAAI,CAEf,IAAIgB,EAASb,EAETC,EACAa,EAAY,CAAA,EACZC,EAAY,CAAA,EACZC,EAAe,CAAA,CALH,CAQhB,IAAST,CAAK,CAAE,CAAC,CAAEA,CAAK,CAAEI,CAAQ,CAAEJ,CAAI,EAAxC,CAII,GAHAM,CAAQ,CAAEJ,CAAK,CAAAF,CAAA,CAAKT,QAAQ,CAAc,aAAA,CAAE,IAAhB,CAAqB,CAG7C,CAAAgB,CAAU,CAAAP,CAAA,CAAM,EAAG,EAXT,sBAWoBU,OAAO,CAAC,GAAI,CAAEJ,CAAQ,CAAE,GAAjB,CAAsB,CAAE,IAC7D,CAKJ,GAHAb,CAAI,CAAES,CAAK,CAAAF,CAAA,CAAK,CAChBN,CAAM,CAAE,EAAE,CAEN,CAAO,MAAAiB,KAAK,CAAClB,CAAD,EAGZ,IAASM,CAAK,CAAEC,CAAK,CAAE,CAAC,CAAED,CAAK,CAAEK,CAAQ,CAAEL,CAAI,EAA/C,CACI,GAAI,CAACQ,CAAU,CAAAR,CAAA,CAAM,EAAGG,CAAK,CAAAH,CAAA,CAAM,EAAG,KAAK,CAAEO,CAAQ,CAAE,IAAK,CACxDZ,CAAM,CAAEK,CAAI,CACZ,KAFwD,CAOhEL,CAAM,EAAG,EAAb,CACIe,CAAa,CAAED,CAAU,CAAAR,CAAA,CAAM,CAAE,CAAA,CADrC,CAGIO,CAAU,CAAAb,CAAA,CAAO,CAAE,CAAA,CAnBnB,CAiCR,OAXKe,CAAD,EAKAT,CAAK,CAAE,C,CACJV,CAAIC,QAAQ,CAACU,CAAE,CAAE,QAAS,CAACP,CAAD,CAAQ,CACrC,IAAIkB,EAAMJ,CAAU,CAAAR,CAAA,CAAM,CAAE,EAAG,CAAEN,CAAK,CAEtC,OADAM,CAAI,EAAE,CACCY,CAH8B,CAAtB,EANf,CACOtB,CAnDY,CA3C3B,IAAIuB,EAAQC,CAAS,CACjB,OAAOC,OAAQ,EAAI,QAAS,EAAG,OAAOC,OAAQ,EAAI,UAAtD,EACIH,CAAO,CAAEE,OAAO,CAChBD,CAAU,CAAEE,OAAO,CAAC,sBAAD,CAAwBF,WAF/C,EAIID,CAAO,CAAEI,MAAMC,SAAS,CACxBJ,CAAU,CAAED,CAAMC,W,CAGtBD,CAAMM,uBAAwB,CAAEC,QAAS,CAAA,CAAG,CACxC,IAAIC,EAAY,IAAIP,CAAW,CAG/B,OAFAO,CAASC,MAAMC,MAAM,CAAC,gBAAgB,CAAElC,CAAnB,CAAgC,CACrDgC,CAASC,MAAMC,MAAM,CAAC,gBAAgB,CAAEzB,CAAnB,CAA+B,CAC7CuB,CAJiC,C,CAY5C,IAAI1B,EAA2I,sHAE3IC,EAAkH,yGAGlHC,EAAuK,2JA3BlK,EA2GX,CAAA,CAAE",
"sources":["Markdown.Sanitizer.js"], "sources":["Markdown.Sanitizer.js"],
"names":["sanitizeHtml","html","replace","sanitizeTag","tag","match","basic_tag_whitelist","a_white","img_white","balanceTags","ntag","ctag","re","tags","toLowerCase","tagcount","length","tagname","tagpaired","tagremove","needsRemoval","search","test","res","output","Converter","exports","require","window","Markdown","getSanitizingConverter","output.getSanitizingConverter","converter","hooks","chain"] "names":["sanitizeHtml","html","replace","sanitizeTag","tag","match","basic_tag_whitelist","a_white","img_white","balanceTags","ntag","ctag","re","tags","toLowerCase","tagcount","length","tagname","tagpaired","tagremove","needsRemoval","search","test","res","output","Converter","exports","require","window","Markdown","getSanitizingConverter","output.getSanitizingConverter","converter","hooks","chain"]
} }