Last active
December 16, 2015 12:29
-
-
Save RWOverdijk/5434855 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
; | |
(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