Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
;
(function () {
/**
* The TextScan object constructor.
*
* @constructor
*/
function TextScan() {
/**
* The string to replaces found matches with. Defaults to ***
*
* @type {String}
*/
var replacementString = '***';
/**
* The color used for highlighting
*
* @type {string}
*/
var highlightColor = 'F2B8B8';
/**
* Holds the currently matched text.
*
* @type {{replace: string, hasMatches: boolean}}
*/
var currentMatch = {
replace : '',
hasMatches : false
};
/**
* The available patterns. These are as follows:
* [name] [description]
* - long_number ; Matches long, consecutive numbers
* - phone_number ; Matches phone numbers.
* - email_address ; Matches email addresses in many formats.
* - url ; Matches URL patterns/
* - words ; Finds words, even when in disguise.
*
* @type {{long_number: {pattern: RegExp, enabled: boolean}, phone_number: {pattern: RegExp, enabled: boolean}, email_address: {pattern: RegExp, enabled: boolean}, url: {pattern: RegExp, enabled: boolean}, words: {enabled: boolean, pattern: Array}}}
*/
var patterns = {
long_number : {
pattern : /\d{8,}/,
enabled : true
},
phone_number : {
pattern : /([+-]?[\d]{1,}[\d\s]+|\([\d]+\))[-\d.\s]{8,}/gi,
enabled : true
},
email_address : {
pattern : /[\w._%+-]+(@|\[at\]|\(at\))[\w.-]+(\.|\[dot\]|\(dot\)|\(punt\)|\[punt\])[a-zA-Z]{2,4}/gi,
enabled : true
},
url : {
pattern : /((https?:\/{1,2})?[-\w.]{2,}(\.|\[dot\]|\(dot\)|\(punt\)|\[punt\])([a-zA-Z]{2}\.[a-zA-Z]{2,3}|[a-zA-Z]{2,4}).*?(?=$|[^\w\/-]))/gi,
enabled : true
},
words : {
pattern : [],
enabled : true
}
};
/**
* A mapping that maps regular characters to 1337 characters.
*
* @type {{o: string, g: string, b: Array, t: string, s: string, a: string, e: string, z: string, i: string, l: string}}
*/
var map1337 = {
o : '0',
g : '9',
b : ['8', '6'],
t : '7',
s : '5',
a : '4',
e : '3',
z : '2',
i : '1',
l : '1'
};
/**
* Check if given subject is an array.
*
* @param subject
* @returns {boolean}
*/
var isArray = function (subject) {
return Object.prototype.toString.call(subject) === '[object Array]';
};
/**
* Enable a filter by name.
*
* @param {String} filter
* @returns {TextScan}
*/
this.enableFilter = function (filter) {
if (typeof patterns[filter] === 'undefined') {
throw 'Invalid filter supplied.';
}
patterns[filter].enabled = true;
return this;
};
/**
* Add multiple filterWords.
*
* @param {{}} words
* @returns {TextScan}
*/
this.addFilterWords = function (words) {
if (!isArray(words)) {
throw 'Invalid type supplied for addFilterWords. Expected array.';
}
for (var i = 0; i < words.length; i++) {
this.addFilterWord(words[i]);
}
return this;
};
/**
* Add a word to filter out.
*
* @param {String} word
* @returns {TextScan}
*/
this.addFilterWord = function (word) {
var pattern = '',
any = '[^a-z0-9]?',
last = false,
character;
for (var i = 0; i < word.length; i++) {
last = i === (word.length - 1);
character = word.charAt(i);
if (typeof map1337[character] === 'undefined') {
pattern += (character + (!last ? any : ''));
continue;
}
if (typeof map1337[character] === 'string') {
pattern += ('((' + character + '|' + map1337[character] + ')' + (!last ? any : '') + ')');
continue;
}
pattern += '((' + character;
for (var m = 0; m < map1337[character].length; m++) {
pattern += '|' + map1337[character][m];
}
pattern += ')' + (!last ? any : '') + ')';
}
patterns.words.pattern.push(new RegExp(pattern, 'ig'));
return this;
};
/**
* Disable a filter by name.
*
* @param {String} filter
* @returns {TextScan}
*/
this.disableFilter = function (filter) {
if (typeof patterns[filter] === 'undefined') {
throw 'Invalid filter supplied.';
}
patterns[filter].enabled = false;
return this;
};
/**
* Enable multiple filters at once.
*
* @param {Array} filters
* @returns {TextScan}
* @see TextScan.enableFilter
*/
this.enableFilters = function (filters) {
if (!isArray(filters)) {
throw 'Invalid filters type supplied. Expected Array.';
}
for (var i = 0; i < filters.length; i++) {
this.enableFilter(filters[i]);
}
return this;
};
/**
* Set the string to replace matches in the filterString() method.
*
* @param {String} str
* @returns {TextScan}
*/
this.setReplacementString = function (str) {
if (typeof str !== 'string') {
throw 'Invalid replacementString type supplied. Expected string.';
}
replacementString = str;
return this;
};
/**
* @returns {String}
*/
this.getReplacementString = function () {
return replacementString;
};
/**
* Returns if text matched.
*
* @returns {Boolean}
*/
this.test = function () {
return currentMatch.hasMatches;
};
/**
* Prepare some text to be matched against.
*
* @param {String} str
* @param {Boolean} highlight
* @returns {TextScan}
*/
this.prepare = function (str, highlight) {
currentMatch.replace = this.filterString(str, highlight);
currentMatch.hasMatches = str !== currentMatch.replace;
return this;
};
/**
* Get the filtered text.
*
* @returns {TextScan}
*/
this.replace = function () {
return currentMatch.replace;
};
/**
* Filter the string.
*
* @param {String} str
* @param {Boolean} highlight
* @returns {String}}
*/
this.filterString = function (str, highlight) {
highlight = highlight || false;
var replace = function (str, pattern) {
if (!highlight) {
return str.replace(pattern, replacementString);
}
return str.replace(pattern, function (match) {
return '<span style="background: #' + highlightColor + ';">' + match + '</span>';
});
};
if (typeof str !== 'string') {
throw 'Invalid "str" type supplied in filterString. Expected string.';
}
for (var p in patterns) {
if (!patterns[p].enabled) {
continue;
}
if (patterns[p].pattern instanceof RegExp) {
str = replace(str, patterns[p].pattern);
continue;
}
if (!isArray(patterns[p].pattern)) {
throw 'Invalid pattern type supplied. Expected Array.';
}
for (var i = 0; i < patterns[p].pattern.length; i++) {
if (!patterns[p].pattern[i] instanceof RegExp) {
throw 'Expected valid RegExp.';
}
str = replace(str, patterns[p].pattern[i]);
}
}
return str;
};
}
/*
* Make sure TextScan is loadable through amd.
*/
if (typeof define === "function" && define.amd) {
define([], function () {
return TextScan;
});
return;
}
/*
* Make sure TextScan is accessible beyond our scope.
*/
window.TextScan = TextScan;
})();
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment