mirror of
https://github.com/showdownjs/showdown.git
synced 2024-03-22 13:30:55 +08:00
Prior to version 1.6.1, emails would always be obfuscated through dec and hex encoding. This option makes it possible to disable this.
314 lines
7.9 KiB
JavaScript
314 lines
7.9 KiB
JavaScript
/**
|
|
* showdownjs helper functions
|
|
*/
|
|
|
|
if (!showdown.hasOwnProperty('helper')) {
|
|
showdown.helper = {};
|
|
}
|
|
|
|
/**
|
|
* Check if var is string
|
|
* @static
|
|
* @param {string} a
|
|
* @returns {boolean}
|
|
*/
|
|
showdown.helper.isString = function isString(a) {
|
|
'use strict';
|
|
return (typeof a === 'string' || a instanceof String);
|
|
};
|
|
|
|
/**
|
|
* Check if var is a function
|
|
* @static
|
|
* @param {string} a
|
|
* @returns {boolean}
|
|
*/
|
|
showdown.helper.isFunction = function isFunction(a) {
|
|
'use strict';
|
|
var getType = {};
|
|
return a && getType.toString.call(a) === '[object Function]';
|
|
};
|
|
|
|
/**
|
|
* ForEach helper function
|
|
* @static
|
|
* @param {*} obj
|
|
* @param {function} callback
|
|
*/
|
|
showdown.helper.forEach = function forEach(obj, callback) {
|
|
'use strict';
|
|
if (typeof obj.forEach === 'function') {
|
|
obj.forEach(callback);
|
|
} else {
|
|
for (var i = 0; i < obj.length; i++) {
|
|
callback(obj[i], i, obj);
|
|
}
|
|
}
|
|
};
|
|
|
|
/**
|
|
* isArray helper function
|
|
* @static
|
|
* @param {*} a
|
|
* @returns {boolean}
|
|
*/
|
|
showdown.helper.isArray = function isArray(a) {
|
|
'use strict';
|
|
return a.constructor === Array;
|
|
};
|
|
|
|
/**
|
|
* Check if value is undefined
|
|
* @static
|
|
* @param {*} value The value to check.
|
|
* @returns {boolean} Returns `true` if `value` is `undefined`, else `false`.
|
|
*/
|
|
showdown.helper.isUndefined = function isUndefined(value) {
|
|
'use strict';
|
|
return typeof value === 'undefined';
|
|
};
|
|
|
|
/**
|
|
* Standardidize extension name
|
|
* @static
|
|
* @param {string} s extension name
|
|
* @returns {string}
|
|
*/
|
|
showdown.helper.stdExtName = function (s) {
|
|
'use strict';
|
|
return s.replace(/[_-]||\s/g, '').toLowerCase();
|
|
};
|
|
|
|
function escapeCharactersCallback(wholeMatch, m1) {
|
|
'use strict';
|
|
var charCodeToEscape = m1.charCodeAt(0);
|
|
return '~E' + charCodeToEscape + 'E';
|
|
}
|
|
|
|
/**
|
|
* Callback used to escape characters when passing through String.replace
|
|
* @static
|
|
* @param {string} wholeMatch
|
|
* @param {string} m1
|
|
* @returns {string}
|
|
*/
|
|
showdown.helper.escapeCharactersCallback = escapeCharactersCallback;
|
|
|
|
/**
|
|
* Escape characters in a string
|
|
* @static
|
|
* @param {string} text
|
|
* @param {string} charsToEscape
|
|
* @param {boolean} afterBackslash
|
|
* @returns {XML|string|void|*}
|
|
*/
|
|
showdown.helper.escapeCharacters = function escapeCharacters(text, charsToEscape, afterBackslash) {
|
|
'use strict';
|
|
// First we have to escape the escape characters so that
|
|
// we can build a character class out of them
|
|
var regexString = '([' + charsToEscape.replace(/([\[\]\\])/g, '\\$1') + '])';
|
|
|
|
if (afterBackslash) {
|
|
regexString = '\\\\' + regexString;
|
|
}
|
|
|
|
var regex = new RegExp(regexString, 'g');
|
|
text = text.replace(regex, escapeCharactersCallback);
|
|
|
|
return text;
|
|
};
|
|
|
|
var rgxFindMatchPos = function (str, left, right, flags) {
|
|
'use strict';
|
|
var f = flags || '',
|
|
g = f.indexOf('g') > -1,
|
|
x = new RegExp(left + '|' + right, 'g' + f.replace(/g/g, '')),
|
|
l = new RegExp(left, f.replace(/g/g, '')),
|
|
pos = [],
|
|
t, s, m, start, end;
|
|
|
|
do {
|
|
t = 0;
|
|
while ((m = x.exec(str))) {
|
|
if (l.test(m[0])) {
|
|
if (!(t++)) {
|
|
s = x.lastIndex;
|
|
start = s - m[0].length;
|
|
}
|
|
} else if (t) {
|
|
if (!--t) {
|
|
end = m.index + m[0].length;
|
|
var obj = {
|
|
left: {start: start, end: s},
|
|
match: {start: s, end: m.index},
|
|
right: {start: m.index, end: end},
|
|
wholeMatch: {start: start, end: end}
|
|
};
|
|
pos.push(obj);
|
|
if (!g) {
|
|
return pos;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
} while (t && (x.lastIndex = s));
|
|
|
|
return pos;
|
|
};
|
|
|
|
/**
|
|
* matchRecursiveRegExp
|
|
*
|
|
* (c) 2007 Steven Levithan <stevenlevithan.com>
|
|
* MIT License
|
|
*
|
|
* Accepts a string to search, a left and right format delimiter
|
|
* as regex patterns, and optional regex flags. Returns an array
|
|
* of matches, allowing nested instances of left/right delimiters.
|
|
* Use the "g" flag to return all matches, otherwise only the
|
|
* first is returned. Be careful to ensure that the left and
|
|
* right format delimiters produce mutually exclusive matches.
|
|
* Backreferences are not supported within the right delimiter
|
|
* due to how it is internally combined with the left delimiter.
|
|
* When matching strings whose format delimiters are unbalanced
|
|
* to the left or right, the output is intentionally as a
|
|
* conventional regex library with recursion support would
|
|
* produce, e.g. "<<x>" and "<x>>" both produce ["x"] when using
|
|
* "<" and ">" as the delimiters (both strings contain a single,
|
|
* balanced instance of "<x>").
|
|
*
|
|
* examples:
|
|
* matchRecursiveRegExp("test", "\\(", "\\)")
|
|
* returns: []
|
|
* matchRecursiveRegExp("<t<<e>><s>>t<>", "<", ">", "g")
|
|
* returns: ["t<<e>><s>", ""]
|
|
* matchRecursiveRegExp("<div id=\"x\">test</div>", "<div\\b[^>]*>", "</div>", "gi")
|
|
* returns: ["test"]
|
|
*/
|
|
showdown.helper.matchRecursiveRegExp = function (str, left, right, flags) {
|
|
'use strict';
|
|
|
|
var matchPos = rgxFindMatchPos (str, left, right, flags),
|
|
results = [];
|
|
|
|
for (var i = 0; i < matchPos.length; ++i) {
|
|
results.push([
|
|
str.slice(matchPos[i].wholeMatch.start, matchPos[i].wholeMatch.end),
|
|
str.slice(matchPos[i].match.start, matchPos[i].match.end),
|
|
str.slice(matchPos[i].left.start, matchPos[i].left.end),
|
|
str.slice(matchPos[i].right.start, matchPos[i].right.end)
|
|
]);
|
|
}
|
|
return results;
|
|
};
|
|
|
|
/**
|
|
*
|
|
* @param {string} str
|
|
* @param {string|function} replacement
|
|
* @param {string} left
|
|
* @param {string} right
|
|
* @param {string} flags
|
|
* @returns {string}
|
|
*/
|
|
showdown.helper.replaceRecursiveRegExp = function (str, replacement, left, right, flags) {
|
|
'use strict';
|
|
|
|
if (!showdown.helper.isFunction(replacement)) {
|
|
var repStr = replacement;
|
|
replacement = function () {
|
|
return repStr;
|
|
};
|
|
}
|
|
|
|
var matchPos = rgxFindMatchPos(str, left, right, flags),
|
|
finalStr = str,
|
|
lng = matchPos.length;
|
|
|
|
if (lng > 0) {
|
|
var bits = [];
|
|
if (matchPos[0].wholeMatch.start !== 0) {
|
|
bits.push(str.slice(0, matchPos[0].wholeMatch.start));
|
|
}
|
|
for (var i = 0; i < lng; ++i) {
|
|
bits.push(
|
|
replacement(
|
|
str.slice(matchPos[i].wholeMatch.start, matchPos[i].wholeMatch.end),
|
|
str.slice(matchPos[i].match.start, matchPos[i].match.end),
|
|
str.slice(matchPos[i].left.start, matchPos[i].left.end),
|
|
str.slice(matchPos[i].right.start, matchPos[i].right.end)
|
|
)
|
|
);
|
|
if (i < lng - 1) {
|
|
bits.push(str.slice(matchPos[i].wholeMatch.end, matchPos[i + 1].wholeMatch.start));
|
|
}
|
|
}
|
|
if (matchPos[lng - 1].wholeMatch.end < str.length) {
|
|
bits.push(str.slice(matchPos[lng - 1].wholeMatch.end));
|
|
}
|
|
finalStr = bits.join('');
|
|
}
|
|
return finalStr;
|
|
};
|
|
|
|
/**
|
|
* Obfuscate an e-mail address through the use of Character Entities,
|
|
* transforming ASCII characters into their equivalent decimal or hex entities.
|
|
*
|
|
* Since it has a random component, subsequent calls to this function produce different results
|
|
*
|
|
* @param {string} mail
|
|
* @returns {string}
|
|
*/
|
|
showdown.helper.encodeEmailAddress = function (mail) {
|
|
'use strict';
|
|
var encode = [
|
|
function (ch) {
|
|
return '&#' + ch.charCodeAt(0) + ';';
|
|
},
|
|
function (ch) {
|
|
return '&#x' + ch.charCodeAt(0).toString(16) + ';';
|
|
},
|
|
function (ch) {
|
|
return ch;
|
|
}
|
|
];
|
|
|
|
mail = mail.replace(/./g, function (ch) {
|
|
if (ch === '@') {
|
|
// this *must* be encoded. I insist.
|
|
ch = encode[Math.floor(Math.random() * 2)](ch);
|
|
} else {
|
|
var r = Math.random();
|
|
// roughly 10% raw, 45% hex, 45% dec
|
|
ch = (
|
|
r > 0.9 ? encode[2](ch) : r > 0.45 ? encode[1](ch) : encode[0](ch)
|
|
);
|
|
}
|
|
return ch;
|
|
});
|
|
|
|
return mail;
|
|
};
|
|
|
|
/**
|
|
* POLYFILLS
|
|
*/
|
|
// use this instead of builtin is undefined for IE8 compatibility
|
|
if (typeof(console) === 'undefined') {
|
|
console = {
|
|
warn: function (msg) {
|
|
'use strict';
|
|
alert(msg);
|
|
},
|
|
log: function (msg) {
|
|
'use strict';
|
|
alert(msg);
|
|
},
|
|
error: function (msg) {
|
|
'use strict';
|
|
throw msg;
|
|
}
|
|
};
|
|
}
|