Skip to content
Fetching contributors…
Cannot retrieve contributors at this time
156 lines (125 sloc) 5.33 KB
Utils =
getCurrentVersion: ->
# Chromium #15242 will make this XHR request to access the manifest unnecessary
manifestRequest = new XMLHttpRequest()
manifestRequest.open("GET", chrome.extension.getURL("manifest.json"), false)
manifestRequest.send(null)
JSON.parse(manifestRequest.responseText).version
# Takes a dot-notation object string and call the function
# that it points to with the correct value for 'this'.
invokeCommandString: (str, argArray) ->
components = str.split('.')
obj = window
for component in components[0...-1]
obj = obj[component]
func = obj[components.pop()]
func.apply(obj, argArray)
# Creates a single DOM element from :html
createElementFromHtml: (html) ->
tmp = document.createElement("div")
tmp.innerHTML = html
tmp.firstChild
escapeHtml: (string) -> string.replace(/</g, "&lt;").replace(/>/g, "&gt;")
# Generates a unique ID
createUniqueId: do ->
id = 0
-> id += 1
hasChromePrefix: (url) ->
chromePrefixes = [ 'about', 'view-source', "chrome-extension" ]
for prefix in chromePrefixes
return true if url.startsWith prefix
false
# Completes a partial URL (without scheme)
createFullUrl: (partialUrl) ->
unless /^[a-z]{3,}:\/\//.test partialUrl
"http://" + partialUrl
else
partialUrl
# Tries to detect if :str is a valid URL.
isUrl: (str) ->
# Starts with a scheme: URL
return true if /^[a-z]{3,}:\/\//.test str
# Must not contain spaces
return false if ' ' in str
# More or less RFC compliant URL host part parsing. This should be sufficient for our needs
urlRegex = new RegExp(
'^(?:([^:]+)(?::([^:]+))?@)?' + # user:password (optional) => \1, \2
'([^:]+|\\[[^\\]]+\\])' + # host name (IPv6 addresses in square brackets allowed) => \3
'(?::(\\d+))?$' # port number (optional) => \4
)
# Official ASCII TLDs that are longer than 3 characters + inofficial .onion TLD used by TOR
longTlds = ['arpa', 'asia', 'coop', 'info', 'jobs', 'local', 'mobi', 'museum', 'name', 'onion']
specialHostNames = ['localhost']
# Try to parse the URL into its meaningful parts. If matching fails we're pretty sure that we don't have
# some kind of URL here.
match = urlRegex.exec (str.split '/')[0]
return false unless match
hostName = match[3]
# Allow known special host names
return true if hostName in specialHostNames
# Allow IPv6 addresses (need to be wrapped in brackets as required by RFC). It is sufficient to check for
# a colon, as the regex wouldn't match colons in the host name unless it's an v6 address
return true if ':' in hostName
# At this point we have to make a decision. As a heuristic, we check if the input has dots in it. If yes,
# and if the last part could be a TLD, treat it as an URL
dottedParts = hostName.split '.'
if dottedParts.length > 1
lastPart = dottedParts.pop()
return true if 2 <= lastPart.length <= 3 or lastPart in longTlds
# Allow IPv4 addresses
return true if /^(\d{1,3}\.){3}\d{1,3}$/.test hostName
# Fallback: no URL
return false
# Creates a search URL from the given :query.
createSearchUrl: (query) ->
# it would be better to pull the default search engine from chrome itself,
# but it is not clear if/how that is possible
Settings.get("searchUrl") + encodeURIComponent(query)
# Converts :string into a Google search if it's not already a URL. We don't bother with escaping characters
# as Chrome will do that for us.
convertToUrl: (string) ->
string = string.trim()
# Special-case about:[url] and view-source:[url]
if Utils.hasChromePrefix string
string
else if Utils.isUrl string
Utils.createFullUrl string
else
Utils.createSearchUrl string
# detects both literals and dynamically created strings
isString: (obj) -> typeof obj == 'string' or obj instanceof String
# Compares two version strings (e.g. "1.1" and "1.5") and returns
# -1 if versionA is < versionB, 0 if they're equal, and 1 if versionA is > versionB.
compareVersions: (versionA, versionB) ->
versionA = versionA.split(".")
versionB = versionB.split(".")
for i in [0...(Math.max(versionA.length, versionB.length))]
a = parseInt(versionA[i] || 0, 10)
b = parseInt(versionB[i] || 0, 10)
if (a < b)
return -1
else if (a > b)
return 1
0
# Zip two (or more) arrays:
# - Utils.zip([ [a,b], [1,2] ]) returns [ [a,1], [b,2] ]
# - Length of result is `arrays[0].length`.
# - Adapted from: http://stackoverflow.com/questions/4856717/javascript-equivalent-of-pythons-zip-function
zip: (arrays) ->
arrays[0].map (_,i) ->
arrays.map( (array) -> array[i] )
# This creates a new function out of an existing function, where the new function takes fewer arguments. This
# allows us to pass around functions instead of functions + a partial list of arguments.
Function::curry = ->
fixedArguments = Array.copy(arguments)
fn = this
-> fn.apply(this, fixedArguments.concat(Array.copy(arguments)))
Array.copy = (array) -> Array.prototype.slice.call(array, 0)
String::startsWith = (str) -> @indexOf(str) == 0
globalRoot = window ? global
globalRoot.extend = (hash1, hash2) ->
for key of hash2
hash1[key] = hash2[key]
hash1
root = exports ? window
root.Utils = Utils
Jump to Line
Something went wrong with that request. Please try again.