diff options
| author | Jez Ng | 2012-09-08 16:37:05 -0400 | 
|---|---|---|
| committer | Jez Ng | 2012-09-08 16:37:05 -0400 | 
| commit | adf8b7cc617279e50594477560ec7031e2ab68ea (patch) | |
| tree | f43660994fb29770bd38e4b11cc11d828ecc0615 /lib/utils.coffee | |
| parent | 3e5bba24ede4f9392ff666634a0a8f05e21a02d1 (diff) | |
| parent | e740ea52b646f1b7cd0ef13e15571b20adaa3bd8 (diff) | |
| download | vimium-adf8b7cc617279e50594477560ec7031e2ab68ea.tar.bz2 | |
Merge branch 'next-release'
Diffstat (limited to 'lib/utils.coffee')
| -rw-r--r-- | lib/utils.coffee | 137 | 
1 files changed, 59 insertions, 78 deletions
| diff --git a/lib/utils.coffee b/lib/utils.coffee index 598b631a..a2221ba4 100644 --- a/lib/utils.coffee +++ b/lib/utils.coffee @@ -1,6 +1,6 @@  Utils =    getCurrentVersion: -> -    # Chromium #15242 will make this XHR request to access the manifest unnecessary. +    # 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) @@ -25,10 +25,9 @@ Utils =    escapeHtml: (string) -> string.replace(/</g, "<").replace(/>/g, ">")    # Generates a unique ID -  createUniqueId: (-> +  createUniqueId: do ->      id = 0 -    return -> id += 1 -  )() +    -> id += 1    hasChromePrefix: (url) ->      chromePrefixes = [ 'about', 'view-source' ] @@ -38,84 +37,79 @@ Utils =    # Completes a partial URL (without scheme)    createFullUrl: (partialUrl) -> -    if (!/^[a-z]{3,}:\/\//.test(partialUrl)) +    unless /^[a-z]{3,}:\/\//.test partialUrl        "http://" + partialUrl      else        partialUrl -  # Tries to detect, whether :str is a valid URL. +  # Tries to detect if :str is a valid URL.    isUrl: (str) -> -    # more or less RFC compliant URL host part parsing. This should be sufficient -    # for our needs +    # 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 +      '^(?:([^:]+)(?::([^:]+))?@)?' + # user:password (optional) => \1, \2 +      '([^:]+|\\[[^\\]]+\\])'       + # host name (IPv6 addresses in square brackets allowed) => \3 +      '(?::(\\d+))?$'                 # port number (optional) => \4        ) -    # these are all official ASCII TLDs that are longer than 3 characters -    # (including the inofficial .onion TLD used by TOR) -    longTlds = [ 'arpa', 'asia', 'coop', 'info', 'jobs', 'local', 'mobi', 'museum', 'name', 'onion' ] - -    # are there more? -    specialHostNames = [ 'localhost' ] - -    # it starts with a scheme, so it's definitely an URL -    if (/^[a-z]{3,}:\/\//.test(str)) -      return true - -    # spaces => definitely not a valid URL -    if (str.indexOf(' ') >= 0) -      return false - -    # assuming that this is an URL, try to parse it 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]) -    if (!match) -      return false -    hostname = match[3] - -    # allow known special host names -    if (specialHostNames.indexOf(hostname) >= 0) -      return true - -    # allow IPv6 addresses (need to be wrapped in brackets, as required by RFC).  It is sufficient to check -    # for a colon here, as the regex wouldn't match colons in the host name unless it's an v6 address -    if (hostname.indexOf(':') >= 0) -      return true - -    # 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('.') -    lastPart = dottedParts[dottedParts.length-1] -    if (dottedParts.length > 1 && ((lastPart.length >= 2 && lastPart.length <= 3) || -        longTlds.indexOf(lastPart) >= 0)) -      return true - -    # also allow IPv4 addresses -    if (/^(\d{1,3}\.){3}\d{1,3}$/.test(hostname)) -      return true - -    # fallback: no URL +    # 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) -> -    # we need to escape explictely to encode characters like "+" correctly +    # Escape explicitly to encode characters like "+" correctly      "http://www.google.com/search?q=" + 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. +  # 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 then string + +    # Special-case about:[url] and view-source:[url] +    if Utils.hasChromePrefix string +      string +    else if Utils.isUrl string +      Utils.createFullUrl string      else -      if (Utils.isUrl(string)) then Utils.createFullUrl(string) else Utils.createSearchUrl(string) +      Utils.createSearchUrl string -# 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.prototype.curry = -> +# 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))) @@ -124,19 +118,7 @@ Array.copy = (array) -> Array.prototype.slice.call(array, 0)  String::startsWith = (str) -> @indexOf(str) == 0 -# A very simple method for defining a new class (constructor and methods) using a single hash. -# No support for inheritance is included because we really shouldn't need it. -# TODO(philc): remove this. -Class = -  extend: (properties) -> -    newClass = -> -      this.init.apply(this, arguments) if (this.init) -      null -    newClass.prototype = properties -    newClass.constructor = newClass -    newClass - -globalRoot = if window? then window else global +globalRoot = window ? global  globalRoot.extend = (hash1, hash2) ->    for key of hash2      hash1[key] = hash2[key] @@ -144,4 +126,3 @@ globalRoot.extend = (hash1, hash2) ->  root = exports ? window  root.Utils = Utils -root.Class = Class | 
