From 7031222822f3e5389f8ad594c54cf9e8e3f18b33 Mon Sep 17 00:00:00 2001 From: Jake Eaton Date: Mon, 27 Feb 2017 18:27:53 -0500 Subject: [PATCH] never override builtin prototypes --- background_scripts/actions.js | 12 +-- background_scripts/bookmarks.js | 9 +- background_scripts/options.js | 4 +- background_scripts/popup.js | 4 +- content_scripts/command.js | 25 +++--- content_scripts/complete.js | 58 +++++++------ content_scripts/hints.js | 8 +- content_scripts/mappings.js | 8 +- content_scripts/messenger.js | 2 +- content_scripts/search.js | 6 +- content_scripts/utils.js | 140 +++++++++++++++----------------- pages/options.js | 4 +- 12 files changed, 136 insertions(+), 144 deletions(-) diff --git a/background_scripts/actions.js b/background_scripts/actions.js index 48d45c09..24e76c32 100644 --- a/background_scripts/actions.js +++ b/background_scripts/actions.js @@ -173,7 +173,7 @@ Actions = (function() { _.openLinksWindow = function(o) { var urls = o.request.urls; if (!o.request.noconvert) { - urls = urls.map(function(e) { return e.convertLink(); }); + urls = urls.map(function(e) { return Utils.toSearchURL(e); }); } for (var i = 0; i < o.request.repeats; i++) { chrome.windows.create({ @@ -417,17 +417,17 @@ Actions = (function() { return; } paste = paste.split('\n').filter(function(e) { return e.trim(); }); - if (paste.length && paste[0].convertLink(o.request.engineUrl) !== paste[0]) { + if (paste.length && Utils.toSearchURL(paste[0], o.request.engineUrl) !== paste[0]) { paste = paste.join('\n'); openTab({ - url: paste.convertLink(o.request.engineUrl), + url: Utils.toSearchURL(paste, o.request.engineUrl), index: getTabOrderIndex(o.sender.tab) }); } else { for (var i = 0; i < o.request.repeats; ++i) { for (var j = 0, l = paste.length; j < l; ++j) { openTab({ - url: paste[j].convertLink(o.request.engineUrl), + url: Utils.toSearchURL(paste[j], o.request.engineUrl), index: getTabOrderIndex(o.sender.tab) }); } @@ -442,7 +442,7 @@ Actions = (function() { } paste = paste.split('\n')[0]; chrome.tabs.update({ - url: paste.convertLink(o.request.engineUrl) + url: Utils.toSearchURL(paste, o.request.engineUrl) }); }; @@ -941,7 +941,7 @@ Actions = (function() { o.request.repeats = Math.max(~~o.request.repeats, 1); if (o.request.url && !o.request.noconvert) { - o.url = o.request.url.convertLink(); + o.url = Utils.toSearchURL(o.request.url); } else if (o.request.url) { o.url = o.request.url; } else { diff --git a/background_scripts/bookmarks.js b/background_scripts/bookmarks.js index 88b92572..0ead7905 100644 --- a/background_scripts/bookmarks.js +++ b/background_scripts/bookmarks.js @@ -16,15 +16,14 @@ Bookmarks.containsFolder = function(path, directory) { }; Bookmarks.getFolderLinks = function(path, callback) { - path = path.split('/').compress(); + path = Utils.compressArray(path.split('/')); chrome.bookmarks.getTree(function(tree) { var dir = tree[0]; while (dir = Bookmarks.containsFolder(path[0], dir)) { path = path.slice(1); if (!path || !path.length) { - callback(dir.children.map(function(e) { - return e.url; - }).compress()); + var links = dir.children.map(function(e) { return e.url; }); + callback(Utils.compressArray(links)); } } }); @@ -40,7 +39,7 @@ Bookmarks.getPath = function(marks, path, callback, initialPath) { if (typeof path !== 'string' || path[0] !== '/') { return false; } - path = path.split(/\//).compress(); + path = Utils.compressArray(path.split(/\//)); marks.forEach(function(item) { if (item.title === path[0]) { folder = item; diff --git a/background_scripts/options.js b/background_scripts/options.js index b8d4b9a5..af540f08 100644 --- a/background_scripts/options.js +++ b/background_scripts/options.js @@ -125,7 +125,7 @@ Options.getAllSettings = function(request, sender, callback) { }; Options.updateBlacklistsMappings = function() { - var rc = settings.RC.split(/\n+/).compress(), + var rc = Utils.compressArray(settings.RC.split(/\n+/)), i, index, line; if (settings.BLACKLISTS) { settings.blacklists = settings.BLACKLISTS.split(/\n+/); @@ -137,7 +137,7 @@ Options.updateBlacklistsMappings = function() { index = i; } } - settings.blacklists = settings.blacklists.unique(); + settings.blacklists = Utils.uniqueElements(settings.blacklists); if (settings.blacklists.length) { line = 'let blacklists = ' + JSON.stringify(settings.blacklists); if (index) { diff --git a/background_scripts/popup.js b/background_scripts/popup.js index d3aecd33..edb6447c 100644 --- a/background_scripts/popup.js +++ b/background_scripts/popup.js @@ -5,7 +5,7 @@ var Popup = { Popup.getBlacklisted = function(callback) { if (typeof callback === 'object') callback = callback.callback; - var blacklists = settings.blacklists.compress(); + var blacklists = Utils.compressArray(settings.blacklists); this.getActiveTab(function(tab) { var url = tab.url; for (var i = 0, l = blacklists.length; i < l; ++i) { @@ -83,7 +83,7 @@ Popup.toggleEnabled = function(obj) { }; Popup.toggleBlacklisted = function() { - var blacklists = settings.blacklists.compress(); + var blacklists = Utils.compressArray(settings.blacklists); this.getActiveTab(function(tab) { var url = tab.url; var foundMatch = false; diff --git a/content_scripts/command.js b/content_scripts/command.js index b07a74cf..77c4a5eb 100644 --- a/content_scripts/command.js +++ b/content_scripts/command.js @@ -292,7 +292,7 @@ Command.callCompletionFunction = (function() { var searchCompletion = function(value) { self.deleteCompletions('engines,bookmarks,complete,chrome,search'); - search = search.split(/ +/).compress(); + search = Utils.compressArray(search.split(/ +/)); if ((search.length < 2 && value.slice(-1) !== ' ') || (!Complete.engineEnabled(search[0]) && !Complete.hasAlias(search[0]))) { self.completions.engines = Complete.getMatchingEngines(search.join(' ')).map(function(name) { @@ -500,7 +500,7 @@ Command.execute = function(value, repeats) { commandMode = false; - var split = value.split(/\s+/g).compress(); + var split = Utils.compressArray(value.split(/\s+/g)); if (this.customCommands.hasOwnProperty(split[0])) { this.execute(this.customCommands[split[0]] + ' ' + split.slice(1).join(' '), 1); return; @@ -547,7 +547,7 @@ Command.execute = function(value, repeats) { value = value.replace(/[&$*!=?|]+$/, function(e) { return e.replace(/[^=?]/g, ''); }); - if (Complete.engineEnabled(value.split(/\s+/g).compress()[1])) + if (Complete.engineEnabled(Utils.compressArray(value.split(/\s+/g))[1])) value = value.replace(/[=?]+$/, ''); this.history.index = {}; @@ -732,7 +732,7 @@ Command.execute = function(value, repeats) { if (Number.isNaN(+sessionId) && this.completionResults.length) sessionId = this.completionResults[0][3]; RUNTIME('restoreChromeSession', { - sessionId: sessionId.trimAround() + sessionId: Utils.trim(sessionId) }); } @@ -784,7 +784,7 @@ Command.execute = function(value, repeats) { } if (/^delsession/.test(value)) { - value = value.replace(/^\S+(\s+)?/, '').trimAround(); + value = Utils.trim(value.replace(/^\S+(\s+)?/, '')); if (value === '') { Status.setMessage('argument required', 1, 'error'); return; @@ -800,7 +800,7 @@ Command.execute = function(value, repeats) { } if (/^mksession/.test(value)) { - value = value.replace(/^\S+(\s+)?/, '').trimAround(); + value = Utils.trim(value.replace(/^\S+(\s+)?/, '')); if (value === '') { Status.setMessage('session name required', 1, 'error'); return; @@ -820,7 +820,7 @@ Command.execute = function(value, repeats) { } if (/^session/.test(value)) { - value = value.replace(/^\S+(\s+)?/, '').trimAround(); + value = Utils.trim(value.replace(/^\S+(\s+)?/, '')); if (value === '') { Status.setMessage('session name required', 1, 'error'); return; @@ -1142,11 +1142,10 @@ Command.updateSettings = function(config) { if (config.locale) { Complete.setLocale(config.locale); } - if (config.hintcharacters && - config.hintcharacters.split('').unique().length > 1) { - settings.hintcharacters = config.hintcharacters - .split('').unique().join(''); - } + + var chars = Utils.uniqueElements((config.hintcharacters || '').split('')); + settings.hintcharacters = chars.join(''); + if (config !== settings) { for (key in config) { if (key.toUpperCase() !== key && settings.hasOwnProperty(key)) { @@ -1265,7 +1264,7 @@ Command.configureSettings = function(_settings) { Command.blacklisted = false; var isBlacklisted = false; for (var i = 0, l = blacklists.length; i < l; i++) { - blacklist = blacklists[i].trimAround().split(/\s+/g); + blacklist = Utils.split(blacklists[i], /\s+/); if (!blacklist.length) { continue; } diff --git a/content_scripts/complete.js b/content_scripts/complete.js index 15ab283a..0adf9c9d 100644 --- a/content_scripts/complete.js +++ b/content_scripts/complete.js @@ -45,16 +45,15 @@ var Complete = { activeEngines: [], convertToLink: function(input, isURL, isLink) { - input = input.replace(/@%/g, document.URL) - .split(/\s+/) - .compress() - .slice(1); + input = input.replace(/@%/g, document.URL).split(/\s+/); + input = Utils.compressArray(input).slice(1); + if (input.length === 0) return ''; input[0] = this.getAlias(input[0]) || input[0]; if (!this.hasEngine(input[0])) { - if (!isLink && (isURL || input.join(' ').validURL())) { + if (!isLink && (isURL || Utils.isValidURL(input.join(' ')))) { input = input.join(' '); return (!/^[a-zA-Z\-]+:/.test(input) ? 'http://' : '') + input; @@ -74,9 +73,9 @@ var Complete = { engine.formatRequest(input.slice(1).join(' ')) : encodeURIComponent(input.slice(1).join(' ')); - if (suffix.validURL()) - return suffix.convertLink(); - return prefix.embedString(suffix); + if (Utils.isValidURL(suffix)) + return Utils.toSearchURL(suffix); + return Utils.format(prefix, suffix); }, setLocale: function(locale) { @@ -146,7 +145,7 @@ Complete.engines = { apiUrl: 'https://www.google.com/complete/search?client=chrome-omni&gs_ri=chrome-ext&oit=1&cp=1&pgcl=7&q=%s', queryApi: function(query, callback) { httpRequest({ - url: this.apiUrl.embedString(query), + url: Utils.format(this.apiUrl, query), json: true }, function(response) { var data = response[1].map(function(e, i) { @@ -171,7 +170,7 @@ Complete.engines = { }, queryApi: function(query, callback) { httpRequest({ - url: this.apiUrl.embedString(query), + url: Utils.format(this.apiUrl, query), json: true }, function(response) { callback(response[1]); @@ -185,7 +184,7 @@ Complete.engines = { apiUrl: 'https://www.google.com/s?tbm=map&fp=1&gs_ri=maps&source=hp&suggest=p&authuser=0&hl=en&pf=p&tch=1&ech=2&q=%s', queryApi: function(query, callback) { httpRequest({ - url: this.apiUrl.embedString(query), + url: Utils.format(this.apiUrl, query), json: false }, function(response) { var data = JSON.parse(JSON.parse(JSON.stringify(response.replace(/\/\*[^\*]+\*\//g, '')))).d; @@ -209,7 +208,7 @@ Complete.engines = { apiUrl: 'http://www.google.com/complete/search?client=img&hl=en&gs_rn=43&gs_ri=img&ds=i&cp=1&gs_id=8&q=%s', queryApi: function(query, callback) { httpRequest({ - url: this.apiUrl.embedString(query), + url: Utils.format(this.apiUrl, query), json: false }, function(response) { var data = JSON.parse(JSON.parse(JSON.stringify(response.replace(/\/\*[^\*]+\*\//g, '')))).d; @@ -233,7 +232,7 @@ Complete.engines = { apiUrl: 'http://www.google.com/trends/entitiesQuery?tn=10&q=%s', queryApi: function(query, callback) { httpRequest({ - url: this.apiUrl.embedString(encodeURIComponent(query)), + url: Utils.format(this.apiUrl, encodeURIComponent(query)), json: true }, function(response) { callback(response.entityList.map(function(e) { @@ -249,7 +248,7 @@ Complete.engines = { apiUrl: 'https://www.google.com/finance/match?matchtype=matchall&q=%s', queryApi: function(query, callback) { httpRequest({ - url: this.apiUrl.embedString(encodeURIComponent(query)), + url: Utils.format(this.apiUrl, encodeURIComponent(query)), json: true }, function(response) { callback(response.matches.map(function(e) { @@ -265,7 +264,7 @@ Complete.engines = { apiUrl: 'https://completion.amazon.com/search/complete?method=completion&search-alias=aps&client=amazon-search-ui&mkt=1&q=%s', queryApi: function(query, callback) { httpRequest({ - url: this.apiUrl.embedString(encodeURIComponent(query)), + url: Utils.format(this.apiUrl, encodeURIComponent(query)), json: true }, function(response) { callback(response[1]); @@ -279,7 +278,7 @@ Complete.engines = { apiUrl: 'https://search.yahoo.com/sugg/gossip/gossip-us-ura/?output=sd1&appid=search.yahoo.com&nresults=20&command=%s', queryApi: function(query, callback) { httpRequest({ - url: this.apiUrl.embedString(encodeURIComponent(query)), + url: Utils.format(this.apiUrl, encodeURIComponent(query)), json: true }, function(response) { var _ret = []; @@ -299,7 +298,7 @@ Complete.engines = { apiUrl: 'https://search.yahoo.com/sugg/ss/gossip-us_ss-vertical_ss/?output=sd1&pubid=1307&appid=yanswer&command=%s&nresults=20', queryApi: function(query, callback) { httpRequest({ - url: this.apiUrl.embedString(encodeURIComponent(query)), + url: Utils.format(this.apiUrl, encodeURIComponent(query)), json: true }, function(response) { callback(response.r.map(function(e) { @@ -318,7 +317,7 @@ Complete.engines = { }, queryApi: function(query, callback) { httpRequest({ - url: this.apiUrl.embedString(query), + url: Utils.format(this.apiUrl, query), json: true }, function(response) { callback(response[1].map(function(e) { @@ -334,7 +333,7 @@ Complete.engines = { apiUrl: 'https://autosug.ebay.com/autosug?kwd=%s', queryApi: function(query, callback) { httpRequest({ - url: this.apiUrl.embedString(encodeURIComponent(query)), + url: Utils.format(this.apiUrl, encodeURIComponent(query)), json: false }, function(response) { var _ret = JSON.parse(response.replace(/^[^\(]+\(|\)$/g, '')); @@ -354,7 +353,7 @@ Complete.engines = { apiUrl: 'https://clients1.google.com/complete/search?client=youtube&hl=en&gl=us&gs_rn=23&gs_ri=youtube&ds=yt&cp=2&gs_id=d&q=%s', queryApi: function(query, callback) { httpRequest({ - url: this.apiUrl.embedString(query), + url: Utils.format(this.apiUrl, query), json: false }, function(response) { var _ret = JSON.parse(response.replace(/^[^\(]+\(|\)$/g, '')); @@ -374,7 +373,7 @@ Complete.engines = { }, queryApi: function(query, callback) { httpRequest({ - url: this.apiUrl.embedString(encodeURIComponent(query)), + url: Utils.format(this.apiUrl, encodeURIComponent(query)), json: true }, function(response) { callback(response.results.map(function(e) { @@ -390,7 +389,7 @@ Complete.engines = { apiUrl: 'http://www.merriam-webster.com/autocomplete?query=%s', queryApi: function(query, callback) { httpRequest({ - url: this.apiUrl.embedString(encodeURIComponent(query)), + url: Utils.format(this.apiUrl, encodeURIComponent(query)), json: true }, function(response) { callback(response.suggestions.map(function(e) { @@ -409,7 +408,7 @@ Complete.engines = { }, queryApi: function(query, callback) { httpRequest({ - url: this.apiUrl.embedString(encodeURIComponent(query)), + url: Utils.format(this.apiUrl, encodeURIComponent(query)), json: true }, function(response) { callback(response[1].map(function(e) { @@ -425,12 +424,11 @@ Complete.engines = { apiUrl: 'https://duckduckgo.com/ac/?q=%s', queryApi: function(query, callback) { httpRequest({ - url: this.apiUrl.embedString(encodeURIComponent(query)), + url: Utils.format(this.apiUrl, encodeURIComponent(query)), json: true }, function(response) { - callback(response.map(function(e) { - return e.phrase; - }).compress()); + response = response.map(function(e) { return e.phrase; }); + callback(Utils.compressArray(response)); }); } }, @@ -441,7 +439,7 @@ Complete.engines = { apiUrl: 'http://api.urbandictionary.com/v0/autocomplete?term=%s', queryApi: function(query, callback) { httpRequest({ - url: this.apiUrl.embedString(encodeURIComponent(query)), + url: Utils.format(this.apiUrl, encodeURIComponent(query)), json: true }, function(response) { callback(response.slice(1).map(function(e) { @@ -481,7 +479,7 @@ Complete.engines = { apiUrl: 'https://www.themoviedb.org/search/remote/multi?query=%s&language=en', queryApi: function(query, callback) { httpRequest({ - url: this.apiUrl.embedString(encodeURIComponent(query)), + url: Utils.format(this.apiUrl, encodeURIComponent(query)), json: true, }, function(response) { callback(response.map(function(e) { @@ -511,7 +509,7 @@ Complete.engines = { apiUrl: 'http://suggestion.baidu.com/su?json=1&cb=&wd=', queryApi: function(query, callback) { httpRequest({ - url: this.apiUrl.embedString(encodeURIComponent(query)), + url: Utils.format(this.apiUrl, encodeURIComponent(query)), }, function(response) { response = JSON.parse(response.slice(1, -2)); callback(response.s); diff --git a/content_scripts/hints.js b/content_scripts/hints.js index 77081bb8..40cfb90c 100644 --- a/content_scripts/hints.js +++ b/content_scripts/hints.js @@ -25,13 +25,15 @@ Hints.matchPatternFilters = { }; Hints.matchPatterns = function(pattern) { + var direction = pattern === settings.nextmatchpattern ? 'next' : 'prev'; var applicableFilters = Object.keys(this.matchPatternFilters) .filter(function(key) { return matchLocation(document.URL, key); }).map(function(key) { - return this.matchPatternFilters[key][ - pattern === settings.nextmatchpattern ? 'next' : 'prev']; - }.bind(this)).compress(); + return Hints.matchPatternFilters[key][direction]; + }); + applicableFilters = Utils.compressArray(applicableFilters); + var link = null; for (var i = 0; i < applicableFilters.length; i++) { link = findFirstOf(document.querySelectorAll(applicableFilters[i]), diff --git a/content_scripts/mappings.js b/content_scripts/mappings.js index 7c72d493..9313963b 100644 --- a/content_scripts/mappings.js +++ b/content_scripts/mappings.js @@ -846,7 +846,7 @@ Mappings.splitMapping = function(string) { }; Mappings.parseLine = function(line) { - var map = line.split(/ +/).compress(); + var map = Utils.compressArray(line.split(/ +/)); if (map.length) { switch (map[0]) { case 'unmapAll': @@ -885,7 +885,7 @@ Mappings.parseLine = function(line) { return; case 'call': waitForLoad(function() { - map = map.slice(1).join(' ').trimAround(); + map = Utils.trim(map.slice(1).join(' ')); if (map[0] === ':') { Command.execute(map.slice(1).replace(//i, ''), 1); } else if (Mappings.actions[map]) { @@ -912,8 +912,8 @@ Mappings.parseCustom = function(config) { insertMappings.insert(Mappings.splitMapping(e[0]), e[1]); }); var ignore = false; // ignore 'site DOMAIN {...}' blocks - config = config.split('\n').compress().forEach(function(e) { - var kw = e.split(' ').compress(); + Utils.split(config, '\n').forEach(function(e) { + var kw = Utils.split(e, ' '); if (kw.length === 3 && kw[0] === 'site' && kw[2] === '{') { ignore = true; } diff --git a/content_scripts/messenger.js b/content_scripts/messenger.js index 14848611..183a7608 100644 --- a/content_scripts/messenger.js +++ b/content_scripts/messenger.js @@ -151,7 +151,7 @@ port.onMessage.addListener(function(response) { break; case 'parseRC': if (response.config.MAPPINGS) { - response.config.MAPPINGS.split('\n').compress().forEach(Mappings.parseLine); + Utils.split(response.config.MAPPINGS, '\n').forEach(Mappings.parseLine); delete response.config.MAPPINGS; } Command.updateSettings(response.config); diff --git a/content_scripts/search.js b/content_scripts/search.js index 56eb2769..2217cd8f 100644 --- a/content_scripts/search.js +++ b/content_scripts/search.js @@ -75,11 +75,11 @@ Search.nextResult = function(reverse) { Command.input.value = Command.input.value.match(/^\S+ /)[0] + Command.completionResults[this.index][1]; break; case 'search': - var value = Command.input.value.split(/\s+/).compress(); + var value = Utils.split(Command.input.value, /\s+/); var repl = ''; if (Command.customCommands.hasOwnProperty(value[0])) { value = [value[0]]; - repl = Command.customCommands[value[0]].split(/\s+/).compress().slice(2).join(' '); + repl = Utils.split(Command.customCommands[value[0]], /\s+/).slice(2).join(' '); } var inputValue, searchValue; if (Command.completionResults[this.index].length === 3) { @@ -90,7 +90,7 @@ Search.nextResult = function(reverse) { searchValue = Command.completionResults[this.index][1]; } if (searchValue.indexOf(repl) === 0) - searchValue = searchValue.replace(repl, '').trimAround(); + searchValue = Utils.trim(searchValue.replace(repl, '')); Command.input.value = inputValue + searchValue; break; case 'windows': diff --git a/content_scripts/utils.js b/content_scripts/utils.js index efa0b09e..ceac29d5 100644 --- a/content_scripts/utils.js +++ b/content_scripts/utils.js @@ -4,15 +4,73 @@ var Utils = { trueModulo: function(a, b) { return ((a % b) + b) % b; }, -}; + uniqueElements: function(array) { + var result = []; + for (var i = 0; i < array.length; i++) { + if (result.indexOf(array[i]) === -1) + result.push(array[i]); + } + return result; + }, + compressArray: function(array) { + var result = []; + // faster than using [].filter + for (var i = 0; i < array.length; i++) { + if (array[i]) + result.push(array[i]); + } + return result; + }, + // splits a string without leaving empty strings in the resultant array + split: function(string, pattern) { + return this.compressArray(string.split(pattern)); + }, + trim: function(string) { + return string.replace(/^(\s+)?(.*\S)?(\s+)?$/g, '$2'); + }, + format: function(string, value) { + var index = string.lastIndexOf('%s'); + if (index < 0) + return string + value; + return string.slice(0, index) + string.slice(index + 2); + }, + toSearchURL: function(query, engineUrl) { + if (Utils.isValidURL(query)) { + return (!/^[a-zA-Z\-]+:/.test(query) ? 'http://' : '') + query; + } + engineUrl = engineUrl || 'https://www.google.com/search?q='; + return Utils.format(engineUrl, encodeURIComponent(query)); + }, -var definePrototype = function(obj, name, fn) { - Object.defineProperty(obj.prototype, name, { - enumerable: false, - configurable: false, - writeable: false, - value: fn - }); + isValidURL: (function() { + var TLDs = ['abogado', 'ac', 'academy', 'accountants', 'active', 'actor', 'ad', 'adult', 'ae', 'aero', 'af', 'ag', 'agency', 'ai', 'airforce', 'al', 'allfinanz', 'alsace', 'am', 'amsterdam', 'an', 'android', 'ao', 'aq', 'aquarelle', 'ar', 'archi', 'army', 'arpa', 'as', 'asia', 'associates', 'at', 'attorney', 'au', 'auction', 'audio', 'autos', 'aw', 'ax', 'axa', 'az', 'ba', 'band', 'bank', 'bar', 'barclaycard', 'barclays', 'bargains', 'bayern', 'bb', 'bd', 'be', 'beer', 'berlin', 'best', 'bf', 'bg', 'bh', 'bi', 'bid', 'bike', 'bio', 'biz', 'bj', 'black', 'blackfriday', 'bloomberg', 'blue', 'bm', 'bmw', 'bn', 'bnpparibas', 'bo', 'boo', 'boutique', 'br', 'brussels', 'bs', 'bt', 'budapest', 'build', 'builders', 'business', 'buzz', 'bv', 'bw', 'by', 'bz', 'bzh', 'ca', 'cab', 'cal', 'camera', 'camp', 'cancerresearch', 'capetown', 'capital', 'caravan', 'cards', 'care', 'career', 'careers', 'cartier', 'casa', 'cash', 'cat', 'catering', 'cc', 'cd', 'center', 'ceo', 'cern', 'cf', 'cg', 'ch', 'channel', 'cheap', 'christmas', 'chrome', 'church', 'ci', 'citic', 'city', 'ck', 'cl', 'claims', 'cleaning', 'click', 'clinic', 'clothing', 'club', 'cm', 'cn', 'co', 'coach', 'codes', 'coffee', 'college', 'cologne', 'com', 'community', 'company', 'computer', 'condos', 'construction', 'consulting', 'contractors', 'cooking', 'cool', 'coop', 'country', 'cr', 'credit', 'creditcard', 'cricket', 'crs', 'cruises', 'cu', 'cuisinella', 'cv', 'cw', 'cx', 'cy', 'cymru', 'cz', 'dabur', 'dad', 'dance', 'dating', 'day', 'dclk', 'de', 'deals', 'degree', 'delivery', 'democrat', 'dental', 'dentist', 'desi', 'design', 'dev', 'diamonds', 'diet', 'digital', 'direct', 'directory', 'discount', 'dj', 'dk', 'dm', 'dnp', 'do', 'docs', 'domains', 'doosan', 'durban', 'dvag', 'dz', 'eat', 'ec', 'edu', 'education', 'ee', 'eg', 'email', 'emerck', 'energy', 'engineer', 'engineering', 'enterprises', 'equipment', 'er', 'es', 'esq', 'estate', 'et', 'eu', 'eurovision', 'eus', 'events', 'everbank', 'exchange', 'expert', 'exposed', 'fail', 'farm', 'fashion', 'feedback', 'fi', 'finance', 'financial', 'firmdale', 'fish', 'fishing', 'fit', 'fitness', 'fj', 'fk', 'flights', 'florist', 'flowers', 'flsmidth', 'fly', 'fm', 'fo', 'foo', 'forsale', 'foundation', 'fr', 'frl', 'frogans', 'fund', 'furniture', 'futbol', 'ga', 'gal', 'gallery', 'garden', 'gb', 'gbiz', 'gd', 'ge', 'gent', 'gf', 'gg', 'ggee', 'gh', 'gi', 'gift', 'gifts', 'gives', 'gl', 'glass', 'gle', 'global', 'globo', 'gm', 'gmail', 'gmo', 'gmx', 'gn', 'goog', 'google', 'gop', 'gov', 'gp', 'gq', 'gr', 'graphics', 'gratis', 'green', 'gripe', 'gs', 'gt', 'gu', 'guide', 'guitars', 'guru', 'gw', 'gy', 'hamburg', 'hangout', 'haus', 'healthcare', 'help', 'here', 'hermes', 'hiphop', 'hiv', 'hk', 'hm', 'hn', 'holdings', 'holiday', 'homes', 'horse', 'host', 'hosting', 'house', 'how', 'hr', 'ht', 'hu', 'ibm', 'id', 'ie', 'ifm', 'il', 'im', 'immo', 'immobilien', 'in', 'industries', 'info', 'ing', 'ink', 'institute', 'insure', 'int', 'international', 'investments', 'io', 'iq', 'ir', 'irish', 'is', 'it', 'iwc', 'jcb', 'je', 'jetzt', 'jm', 'jo', 'jobs', 'joburg', 'jp', 'juegos', 'kaufen', 'kddi', 'ke', 'kg', 'kh', 'ki', 'kim', 'kitchen', 'kiwi', 'km', 'kn', 'koeln', 'kp', 'kr', 'krd', 'kred', 'kw', 'ky', 'kyoto', 'kz', 'la', 'lacaixa', 'land', 'lat', 'latrobe', 'lawyer', 'lb', 'lc', 'lds', 'lease', 'legal', 'lgbt', 'li', 'lidl', 'life', 'lighting', 'limited', 'limo', 'link', 'lk', 'loans', 'london', 'lotte', 'lotto', 'lr', 'ls', 'lt', 'ltda', 'lu', 'luxe', 'luxury', 'lv', 'ly', 'ma', 'madrid', 'maison', 'management', 'mango', 'market', 'marketing', 'marriott', 'mc', 'md', 'me', 'media', 'meet', 'melbourne', 'meme', 'memorial', 'menu', 'mg', 'mh', 'miami', 'mil', 'mini', 'mk', 'ml', 'mm', 'mn', 'mo', 'mobi', 'moda', 'moe', 'monash', 'money', 'mormon', 'mortgage', 'moscow', 'motorcycles', 'mov', 'mp', 'mq', 'mr', 'ms', 'mt', 'mu', 'museum', 'mv', 'mw', 'mx', 'my', 'mz', 'na', 'nagoya', 'name', 'navy', 'nc', 'ne', 'net', 'network', 'neustar', 'new', 'nexus', 'nf', 'ng', 'ngo', 'nhk', 'ni', 'ninja', 'nl', 'no', 'np', 'nr', 'nra', 'nrw', 'nu', 'nyc', 'nz', 'okinawa', 'om', 'one', 'ong', 'onl', 'ooo', 'org', 'organic', 'osaka', 'otsuka', 'ovh', 'pa', 'paris', 'partners', 'parts', 'party', 'pe', 'pf', 'pg', 'ph', 'pharmacy', 'photo', 'photography', 'photos', 'physio', 'pics', 'pictures', 'pink', 'pizza', 'pk', 'pl', 'place', 'plumbing', 'pm', 'pn', 'pohl', 'poker', 'porn', 'post', 'pr', 'praxi', 'press', 'pro', 'prod', 'productions', 'prof', 'properties', 'property', 'ps', 'pt', 'pub', 'pw', 'py', 'qa', 'qpon', 'quebec', 're', 'realtor', 'recipes', 'red', 'rehab', 'reise', 'reisen', 'reit', 'ren', 'rentals', 'repair', 'report', 'republican', 'rest', 'restaurant', 'reviews', 'rich', 'rio', 'rip', 'ro', 'rocks', 'rodeo', 'rs', 'rsvp', 'ru', 'ruhr', 'rw', 'ryukyu', 'sa', 'saarland', 'sale', 'samsung', 'sarl', 'sb', 'sc', 'sca', 'scb', 'schmidt', 'schule', 'schwarz', 'science', 'scot', 'sd', 'se', 'services', 'sew', 'sexy', 'sg', 'sh', 'shiksha', 'shoes', 'shriram', 'si', 'singles', 'sj', 'sk', 'sky', 'sl', 'sm', 'sn', 'so', 'social', 'software', 'sohu', 'solar', 'solutions', 'soy', 'space', 'spiegel', 'sr', 'st', 'su', 'supplies', 'supply', 'support', 'surf', 'surgery', 'suzuki', 'sv', 'sx', 'sy', 'sydney', 'systems', 'sz', 'taipei', 'tatar', 'tattoo', 'tax', 'tc', 'td', 'technology', 'tel', 'temasek', 'tf', 'tg', 'th', 'tienda', 'tips', 'tires', 'tirol', 'tj', 'tk', 'tl', 'tm', 'tn', 'to', 'today', 'tokyo', 'tools', 'top', 'town', 'toys', 'tp', 'tr', 'trade', 'training', 'travel', 'trust', 'tt', 'tui', 'tv', 'tw', 'tz', 'ua', 'ug', 'uk', 'university', 'uno', 'uol', 'us', 'uy', 'uz', 'va', 'vacations', 'vc', 've', 'vegas', 'ventures', 'versicherung', 'vet', 'vg', 'vi', 'viajes', 'video', 'villas', 'vision', 'vlaanderen', 'vn', 'vodka', 'vote', 'voting', 'voto', 'voyage', 'vu', 'wales', 'wang', 'watch', 'webcam', 'website', 'wed', 'wedding', 'wf', 'whoswho', 'wien', 'wiki', 'williamhill', 'wme', 'work', 'works', 'world', 'ws', 'wtc', 'wtf', 'xn--1qqw23a', 'xn--3bst00m', 'xn--3ds443g', 'xn--3e0b707e', 'xn--45brj9c', 'xn--45q11c', 'xn--4gbrim', 'xn--55qw42g', 'xn--55qx5d', 'xn--6frz82g', 'xn--6qq986b3xl', 'xn--80adxhks', 'xn--80ao21a', 'xn--80asehdb', 'xn--80aswg', 'xn--90a3ac', 'xn--b4w605ferd', 'xn--c1avg', 'xn--cg4bki', 'xn--clchc0ea0b2g2a9gcd', 'xn--czr694b', 'xn--czrs0t', 'xn--czru2d', 'xn--d1acj3b', 'xn--d1alf', 'xn--fiq228c5hs', 'xn--fiq64b', 'xn--fiqs8s', 'xn--fiqz9s', 'xn--flw351e', 'xn--fpcrj9c3d', 'xn--fzc2c9e2c', 'xn--gecrj9c', 'xn--h2brj9c', 'xn--hxt814e', 'xn--i1b6b1a6a2e', 'xn--io0a7i', 'xn--j1amh', 'xn--j6w193g', 'xn--kprw13d', 'xn--kpry57d', 'xn--kput3i', 'xn--l1acc', 'xn--lgbbat1ad8j', 'xn--mgb9awbf', 'xn--mgba3a4f16a', 'xn--mgbaam7a8h', 'xn--mgbab2bd', 'xn--mgbayh7gpa', 'xn--mgbbh1a71e', 'xn--mgbc0a9azcg', 'xn--mgberp4a5d4ar', 'xn--mgbx4cd0ab', 'xn--ngbc5azd', 'xn--node', 'xn--nqv7f', 'xn--nqv7fs00ema', 'xn--o3cw4h', 'xn--ogbpf8fl', 'xn--p1acf', 'xn--p1ai', 'xn--pgbs0dh', 'xn--q9jyb4c', 'xn--qcka1pmc', 'xn--rhqv96g', 'xn--s9brj9c', 'xn--ses554g', 'xn--unup4y', 'xn--vermgensberater-ctb', 'xn--vermgensberatung-pwb', 'xn--vhquv', 'xn--wgbh1c', 'xn--wgbl6a', 'xn--xhq521b', 'xn--xkc2al3hye2a', 'xn--xkc2dl3a5ee0h', 'xn--yfro4i67o', 'xn--ygbi2ammx', 'xn--zfr164b', 'xxx', 'xyz', 'yachts', 'yandex', 'ye', 'yoga', 'yokohama', 'youtube', 'yt', 'za', 'zip', 'zm', 'zone', 'zuerich', 'zw']; + var PROTOCOLS = ['http:', 'https:', 'file:', 'ftp:', 'chrome:', 'chrome-extension:']; + return function(url) { + url = this.trim(url); + if (~url.indexOf(' ')) + return false; + if (~url.search(/^(about|file):[^:]/)) + return true; + var protocol = (url.match(/^([a-zA-Z\-]+:)[^:]/) || [''])[0].slice(0, -1); + var protocolMatch = PROTOCOLS.indexOf(protocol) !== -1; + if (protocolMatch) + url = url.replace(/^[a-zA-Z\-]+:\/*/, ''); + var hasPath = /.*[a-zA-Z].*\//.test(url); + url = url.replace(/(:[0-9]+)?([#\/].*|$)/g, '').split('.'); + if (protocolMatch && /^[a-zA-Z0-9@!]+$/.test(url)) + return true; + if (protocol && !protocolMatch && protocol !== 'localhost:') + return false; + var isIP = url.every(function(e) { // IP addresses + return /^[0-9]+$/.test(e) && +e >= 0 && +e < 256; + }); + if ((isIP && !protocol && url.length === 4) || (isIP && protocolMatch)) + return true; + return (url.every(function(e) { return /^[a-z0-9\-]+$/i.test(e); }) && + (url.length > 1 && TLDs.indexOf(url[url.length - 1]) !== -1)) || + (url.length === 1 && url[0] === 'localhost') || hasPath; + }; + })(), }; // ------------ Begin reverse image @@ -55,22 +113,6 @@ var googleReverseImage = function(url, source) { }; // ------------ End reverse image -definePrototype(Array, 'unique', function() { - var a = []; - for (var i = 0, l = this.length; i < l; ++i) { - if (a.indexOf(this[i]) === -1) { - a.push(this[i]); - } - } - return a; -}); - -definePrototype(Array, 'compress', function() { - return this.filter(function(e) { - return e; - }); -}); - Object.clone = function(node) { if (Array.isArray(node)) { return node.map(function(e) { @@ -103,54 +145,6 @@ Object.compare = function(a, b, keys) { return true; }; -definePrototype(String, 'trimAround', function() { - return this.replace(/^(\s+)?(.*\S)?(\s+)?$/g, '$2'); -}); - -definePrototype(String, 'validURL', (function() { - var TLDs = ['abogado', 'ac', 'academy', 'accountants', 'active', 'actor', 'ad', 'adult', 'ae', 'aero', 'af', 'ag', 'agency', 'ai', 'airforce', 'al', 'allfinanz', 'alsace', 'am', 'amsterdam', 'an', 'android', 'ao', 'aq', 'aquarelle', 'ar', 'archi', 'army', 'arpa', 'as', 'asia', 'associates', 'at', 'attorney', 'au', 'auction', 'audio', 'autos', 'aw', 'ax', 'axa', 'az', 'ba', 'band', 'bank', 'bar', 'barclaycard', 'barclays', 'bargains', 'bayern', 'bb', 'bd', 'be', 'beer', 'berlin', 'best', 'bf', 'bg', 'bh', 'bi', 'bid', 'bike', 'bio', 'biz', 'bj', 'black', 'blackfriday', 'bloomberg', 'blue', 'bm', 'bmw', 'bn', 'bnpparibas', 'bo', 'boo', 'boutique', 'br', 'brussels', 'bs', 'bt', 'budapest', 'build', 'builders', 'business', 'buzz', 'bv', 'bw', 'by', 'bz', 'bzh', 'ca', 'cab', 'cal', 'camera', 'camp', 'cancerresearch', 'capetown', 'capital', 'caravan', 'cards', 'care', 'career', 'careers', 'cartier', 'casa', 'cash', 'cat', 'catering', 'cc', 'cd', 'center', 'ceo', 'cern', 'cf', 'cg', 'ch', 'channel', 'cheap', 'christmas', 'chrome', 'church', 'ci', 'citic', 'city', 'ck', 'cl', 'claims', 'cleaning', 'click', 'clinic', 'clothing', 'club', 'cm', 'cn', 'co', 'coach', 'codes', 'coffee', 'college', 'cologne', 'com', 'community', 'company', 'computer', 'condos', 'construction', 'consulting', 'contractors', 'cooking', 'cool', 'coop', 'country', 'cr', 'credit', 'creditcard', 'cricket', 'crs', 'cruises', 'cu', 'cuisinella', 'cv', 'cw', 'cx', 'cy', 'cymru', 'cz', 'dabur', 'dad', 'dance', 'dating', 'day', 'dclk', 'de', 'deals', 'degree', 'delivery', 'democrat', 'dental', 'dentist', 'desi', 'design', 'dev', 'diamonds', 'diet', 'digital', 'direct', 'directory', 'discount', 'dj', 'dk', 'dm', 'dnp', 'do', 'docs', 'domains', 'doosan', 'durban', 'dvag', 'dz', 'eat', 'ec', 'edu', 'education', 'ee', 'eg', 'email', 'emerck', 'energy', 'engineer', 'engineering', 'enterprises', 'equipment', 'er', 'es', 'esq', 'estate', 'et', 'eu', 'eurovision', 'eus', 'events', 'everbank', 'exchange', 'expert', 'exposed', 'fail', 'farm', 'fashion', 'feedback', 'fi', 'finance', 'financial', 'firmdale', 'fish', 'fishing', 'fit', 'fitness', 'fj', 'fk', 'flights', 'florist', 'flowers', 'flsmidth', 'fly', 'fm', 'fo', 'foo', 'forsale', 'foundation', 'fr', 'frl', 'frogans', 'fund', 'furniture', 'futbol', 'ga', 'gal', 'gallery', 'garden', 'gb', 'gbiz', 'gd', 'ge', 'gent', 'gf', 'gg', 'ggee', 'gh', 'gi', 'gift', 'gifts', 'gives', 'gl', 'glass', 'gle', 'global', 'globo', 'gm', 'gmail', 'gmo', 'gmx', 'gn', 'goog', 'google', 'gop', 'gov', 'gp', 'gq', 'gr', 'graphics', 'gratis', 'green', 'gripe', 'gs', 'gt', 'gu', 'guide', 'guitars', 'guru', 'gw', 'gy', 'hamburg', 'hangout', 'haus', 'healthcare', 'help', 'here', 'hermes', 'hiphop', 'hiv', 'hk', 'hm', 'hn', 'holdings', 'holiday', 'homes', 'horse', 'host', 'hosting', 'house', 'how', 'hr', 'ht', 'hu', 'ibm', 'id', 'ie', 'ifm', 'il', 'im', 'immo', 'immobilien', 'in', 'industries', 'info', 'ing', 'ink', 'institute', 'insure', 'int', 'international', 'investments', 'io', 'iq', 'ir', 'irish', 'is', 'it', 'iwc', 'jcb', 'je', 'jetzt', 'jm', 'jo', 'jobs', 'joburg', 'jp', 'juegos', 'kaufen', 'kddi', 'ke', 'kg', 'kh', 'ki', 'kim', 'kitchen', 'kiwi', 'km', 'kn', 'koeln', 'kp', 'kr', 'krd', 'kred', 'kw', 'ky', 'kyoto', 'kz', 'la', 'lacaixa', 'land', 'lat', 'latrobe', 'lawyer', 'lb', 'lc', 'lds', 'lease', 'legal', 'lgbt', 'li', 'lidl', 'life', 'lighting', 'limited', 'limo', 'link', 'lk', 'loans', 'london', 'lotte', 'lotto', 'lr', 'ls', 'lt', 'ltda', 'lu', 'luxe', 'luxury', 'lv', 'ly', 'ma', 'madrid', 'maison', 'management', 'mango', 'market', 'marketing', 'marriott', 'mc', 'md', 'me', 'media', 'meet', 'melbourne', 'meme', 'memorial', 'menu', 'mg', 'mh', 'miami', 'mil', 'mini', 'mk', 'ml', 'mm', 'mn', 'mo', 'mobi', 'moda', 'moe', 'monash', 'money', 'mormon', 'mortgage', 'moscow', 'motorcycles', 'mov', 'mp', 'mq', 'mr', 'ms', 'mt', 'mu', 'museum', 'mv', 'mw', 'mx', 'my', 'mz', 'na', 'nagoya', 'name', 'navy', 'nc', 'ne', 'net', 'network', 'neustar', 'new', 'nexus', 'nf', 'ng', 'ngo', 'nhk', 'ni', 'ninja', 'nl', 'no', 'np', 'nr', 'nra', 'nrw', 'nu', 'nyc', 'nz', 'okinawa', 'om', 'one', 'ong', 'onl', 'ooo', 'org', 'organic', 'osaka', 'otsuka', 'ovh', 'pa', 'paris', 'partners', 'parts', 'party', 'pe', 'pf', 'pg', 'ph', 'pharmacy', 'photo', 'photography', 'photos', 'physio', 'pics', 'pictures', 'pink', 'pizza', 'pk', 'pl', 'place', 'plumbing', 'pm', 'pn', 'pohl', 'poker', 'porn', 'post', 'pr', 'praxi', 'press', 'pro', 'prod', 'productions', 'prof', 'properties', 'property', 'ps', 'pt', 'pub', 'pw', 'py', 'qa', 'qpon', 'quebec', 're', 'realtor', 'recipes', 'red', 'rehab', 'reise', 'reisen', 'reit', 'ren', 'rentals', 'repair', 'report', 'republican', 'rest', 'restaurant', 'reviews', 'rich', 'rio', 'rip', 'ro', 'rocks', 'rodeo', 'rs', 'rsvp', 'ru', 'ruhr', 'rw', 'ryukyu', 'sa', 'saarland', 'sale', 'samsung', 'sarl', 'sb', 'sc', 'sca', 'scb', 'schmidt', 'schule', 'schwarz', 'science', 'scot', 'sd', 'se', 'services', 'sew', 'sexy', 'sg', 'sh', 'shiksha', 'shoes', 'shriram', 'si', 'singles', 'sj', 'sk', 'sky', 'sl', 'sm', 'sn', 'so', 'social', 'software', 'sohu', 'solar', 'solutions', 'soy', 'space', 'spiegel', 'sr', 'st', 'su', 'supplies', 'supply', 'support', 'surf', 'surgery', 'suzuki', 'sv', 'sx', 'sy', 'sydney', 'systems', 'sz', 'taipei', 'tatar', 'tattoo', 'tax', 'tc', 'td', 'technology', 'tel', 'temasek', 'tf', 'tg', 'th', 'tienda', 'tips', 'tires', 'tirol', 'tj', 'tk', 'tl', 'tm', 'tn', 'to', 'today', 'tokyo', 'tools', 'top', 'town', 'toys', 'tp', 'tr', 'trade', 'training', 'travel', 'trust', 'tt', 'tui', 'tv', 'tw', 'tz', 'ua', 'ug', 'uk', 'university', 'uno', 'uol', 'us', 'uy', 'uz', 'va', 'vacations', 'vc', 've', 'vegas', 'ventures', 'versicherung', 'vet', 'vg', 'vi', 'viajes', 'video', 'villas', 'vision', 'vlaanderen', 'vn', 'vodka', 'vote', 'voting', 'voto', 'voyage', 'vu', 'wales', 'wang', 'watch', 'webcam', 'website', 'wed', 'wedding', 'wf', 'whoswho', 'wien', 'wiki', 'williamhill', 'wme', 'work', 'works', 'world', 'ws', 'wtc', 'wtf', 'xn--1qqw23a', 'xn--3bst00m', 'xn--3ds443g', 'xn--3e0b707e', 'xn--45brj9c', 'xn--45q11c', 'xn--4gbrim', 'xn--55qw42g', 'xn--55qx5d', 'xn--6frz82g', 'xn--6qq986b3xl', 'xn--80adxhks', 'xn--80ao21a', 'xn--80asehdb', 'xn--80aswg', 'xn--90a3ac', 'xn--b4w605ferd', 'xn--c1avg', 'xn--cg4bki', 'xn--clchc0ea0b2g2a9gcd', 'xn--czr694b', 'xn--czrs0t', 'xn--czru2d', 'xn--d1acj3b', 'xn--d1alf', 'xn--fiq228c5hs', 'xn--fiq64b', 'xn--fiqs8s', 'xn--fiqz9s', 'xn--flw351e', 'xn--fpcrj9c3d', 'xn--fzc2c9e2c', 'xn--gecrj9c', 'xn--h2brj9c', 'xn--hxt814e', 'xn--i1b6b1a6a2e', 'xn--io0a7i', 'xn--j1amh', 'xn--j6w193g', 'xn--kprw13d', 'xn--kpry57d', 'xn--kput3i', 'xn--l1acc', 'xn--lgbbat1ad8j', 'xn--mgb9awbf', 'xn--mgba3a4f16a', 'xn--mgbaam7a8h', 'xn--mgbab2bd', 'xn--mgbayh7gpa', 'xn--mgbbh1a71e', 'xn--mgbc0a9azcg', 'xn--mgberp4a5d4ar', 'xn--mgbx4cd0ab', 'xn--ngbc5azd', 'xn--node', 'xn--nqv7f', 'xn--nqv7fs00ema', 'xn--o3cw4h', 'xn--ogbpf8fl', 'xn--p1acf', 'xn--p1ai', 'xn--pgbs0dh', 'xn--q9jyb4c', 'xn--qcka1pmc', 'xn--rhqv96g', 'xn--s9brj9c', 'xn--ses554g', 'xn--unup4y', 'xn--vermgensberater-ctb', 'xn--vermgensberatung-pwb', 'xn--vhquv', 'xn--wgbh1c', 'xn--wgbl6a', 'xn--xhq521b', 'xn--xkc2al3hye2a', 'xn--xkc2dl3a5ee0h', 'xn--yfro4i67o', 'xn--ygbi2ammx', 'xn--zfr164b', 'xxx', 'xyz', 'yachts', 'yandex', 'ye', 'yoga', 'yokohama', 'youtube', 'yt', 'za', 'zip', 'zm', 'zone', 'zuerich', 'zw']; - var PROTOCOLS = ['http:', 'https:', 'file:', 'ftp:', 'chrome:', 'chrome-extension:']; - return function() { - var url = this.trimAround(); - if (~url.indexOf(' ')) - return false; - if (~url.search(/^(about|file):[^:]/)) - return true; - var protocol = (url.match(/^([a-zA-Z\-]+:)[^:]/) || [''])[0].slice(0, -1); - var protocolMatch = PROTOCOLS.indexOf(protocol) !== -1; - if (protocolMatch) - url = url.replace(/^[a-zA-Z\-]+:\/*/, ''); - var hasPath = /.*[a-zA-Z].*\//.test(url); - url = url.replace(/(:[0-9]+)?([#\/].*|$)/g, '').split('.'); - if (protocolMatch && /^[a-zA-Z0-9@!]+$/.test(url)) - return true; - if (protocol && !protocolMatch && protocol !== 'localhost:') - return false; - var isIP = url.every(function(e) { // IP addresses - return /^[0-9]+$/.test(e) && +e >= 0 && +e < 256; - }); - if ((isIP && !protocol && url.length === 4) || (isIP && protocolMatch)) - return true; - return (url.every(function(e) { return /^[a-z0-9\-]+$/i.test(e); }) && - (url.length > 1 && TLDs.indexOf(url[url.length - 1]) !== -1)) || - (url.length === 1 && url[0] === 'localhost') || hasPath; - }; -})()); - -definePrototype(String, 'embedString', function(string) { - if (this.indexOf('%s') === -1) - return this + string; - return this.split('%s').join(string); -}); - -definePrototype(String, 'convertLink', function(engineUrl) { - if (this.validURL()) { - return (!/^[a-zA-Z\-]+:/.test(this) ? 'http://' : '') + this; - } - engineUrl = engineUrl || 'https://www.google.com/search?q='; - return engineUrl.embedString(encodeURIComponent(this)); -}); - var matchLocation = function(url, pattern) { // Uses @match syntax // See https://code.google.com/p/chromium/codesearch#chromium/src/extensions/common/url_pattern.h&sq=package:chromium if (typeof pattern !== 'string' || !pattern.trim()) { @@ -226,7 +220,7 @@ var eachUntil = function(array, callback) { */ var searchArray = function(opt) { var split = /[\/?:.\-\s]+/; - var search = opt.search.toLowerCase().split(split).compress(); + var search = Utils.split(opt.search.toLowerCase(), split); var fn = opt.fn || function(item) { return item; }; var matches = []; eachUntil(opt.array, function(item) { diff --git a/pages/options.js b/pages/options.js index 9132fe80..b2d5c00e 100644 --- a/pages/options.js +++ b/pages/options.js @@ -65,13 +65,13 @@ Settings.editMode = function(e) { }; Settings.syncGist = function() { - var url = new URL(this.gistUrl.value.trimAround()); + var url = new URL(Utils.trim(this.gistUrl.value)); if (url.hostname === 'gist.github.com') { url.hostname = 'gist.githubusercontent.com'; url.pathname += '/raw'; } else if (url.hostname === 'github.com') { url.hostname = 'raw.githubusercontent.com'; - var path = url.pathname.split('/').compress(); + var path = Utils.split(url.pathname, '/'); if (path[2] === 'blob') path.splice(2, 1); url.pathname = path.join('/');