[Pkg-javascript-commits] [node-url-parse] 01/04: Imported Upstream version 1.0.2

Thorsten Alteholz alteholz at moszumanska.debian.org
Sun Feb 7 13:11:18 UTC 2016


This is an automated email from the git hooks/post-receive script.

alteholz pushed a commit to branch master
in repository node-url-parse.

commit 272187206888d3f796e34a61c8ac422d51642f90
Author: Thorsten Alteholz <debian at alteholz.de>
Date:   Sun Feb 7 14:11:08 2016 +0100

    Imported Upstream version 1.0.2
---
 .npmignore   |   6 +
 .travis.yml  |  28 +++++
 LICENSE      |  22 ++++
 README.md    | 118 ++++++++++++++++++
 fuzzy.js     |  79 ++++++++++++
 index.js     | 232 ++++++++++++++++++++++++++++++++++++
 lolcation.js |  45 +++++++
 package.json |  63 ++++++++++
 test.js      | 384 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 9 files changed, 977 insertions(+)

diff --git a/.npmignore b/.npmignore
new file mode 100644
index 0000000..63c1316
--- /dev/null
+++ b/.npmignore
@@ -0,0 +1,6 @@
+node_modules
+coverage
+.tern-port
+browserified.js
+npm-debug.log
+dist
diff --git a/.travis.yml b/.travis.yml
new file mode 100644
index 0000000..22ebb02
--- /dev/null
+++ b/.travis.yml
@@ -0,0 +1,28 @@
+language: node_js
+node_js:
+  - "0.12"
+  - "0.11"
+  - "0.10"
+  - "0.9"
+  - "0.8"
+  - "iojs-v1.1"
+  - "iojs-v1.0"
+before_install:
+  - "npm install -g npm at 1.4.x"
+script:
+  - "npm run test-travis"
+after_script:
+  - "npm install coveralls at 2.11.x && cat coverage/lcov.info | coveralls"
+matrix:
+  fast_finish: true
+  allow_failures:
+    - node_js: "0.11"
+    - node_js: "0.9"
+    - node_js: "iojs-v1.1"
+    - node_js: "iojs-v1.0"
+notifications:
+  irc:
+    channels:
+      - "irc.freenode.org#unshift"
+    on_success: change
+    on_failure: change
diff --git a/LICENSE b/LICENSE
new file mode 100644
index 0000000..6dc9316
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,22 @@
+The MIT License (MIT)
+
+Copyright (c) 2015 Unshift.io, Arnout Kazemier,  the Contributors.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
+
diff --git a/README.md b/README.md
new file mode 100644
index 0000000..e0ead1f
--- /dev/null
+++ b/README.md
@@ -0,0 +1,118 @@
+# url-parse
+[![Made by unshift](https://img.shields.io/badge/made%20by-unshift-00ffcc.svg?style=flat-square)](http://unshift.io)[![Version npm](http://img.shields.io/npm/v/url-parse.svg?style=flat-square)](http://browsenpm.org/package/url-parse)[![Build Status](http://img.shields.io/travis/unshiftio/url-parse/master.svg?style=flat-square)](https://travis-ci.org/unshiftio/url-parse)[![Dependencies](https://img.shields.io/david/unshiftio/url-parse.svg?style=flat-square)](https://david-dm.org/unshiftio [...]
+
+The `url-parse` method exposes two different API interfaces. The `url` interface
+that you know from Node.js and the new `URL` interface that is available in the
+latest browsers.
+
+Since `0.1` we've moved away from using the DOM's `<a>` element for URL parsing
+and moving to a full Regular Expression solution. The main reason for this
+change is to make the URL parser available in different JavaScript environments
+as you don't always have access to the DOM like `Worker` environments. This
+module still have a really small foot print as this module's main intention is
+to be bundled with client-side code. The only problem however with a RegExp
+based solution is that it required a lot of lookups causing major problems in
+FireFox. So the last and the current solution was a pure string parsing
+solution which chops up the URL in smaller pieces.
+
+In addition to URL parsing we also expose the bundled `querystringify` module.
+
+## Installation
+
+This module is designed to be used using either browserify or node.js it's
+released in the public npm registry and can be installed using:
+
+```
+npm install url-parse
+```
+
+## Usage
+
+All examples assume that this library is bootstrapped using:
+
+```js
+'use strict';
+
+var URL = require('url-parse');
+```
+
+To parse an URL simply call the `URL` method with the URL that needs to be
+transformed in to an object.
+
+```js
+var url = new URL('https://github.com/foo/bar');
+```
+
+The `new` keyword is optional but it will save you an extra function invocation.
+In the example above we've demonstrated the URL interface, but as said in the
+module description we also support the node.js interface. So you could also use
+the library in this way:
+
+```js
+'use strict';
+
+var parse = require('url-parse')
+  , url = parse('https://github.com/foo/bar', true);
+```
+
+The returned `url` instance contains the following properties:
+
+- `protocol`: Without slashes `http:`.
+- `username`: Username of basic authentication.
+- `password`: Password of basic authentication.
+- `host`: Host name with port number.
+- `hostname`: Host name without port number.
+- `port`: Optional port number.
+- `pathname`: URL path.
+- `query`: Parsed object containing query string, unless parsing is set to false.
+- `hash`: Prefixed with `#`
+- `href`: The full URL.
+
+### URL.set(key, value)
+
+A simple helper function to change parts of the URL and propagating it through
+all properties. When you set a new `host` you want the same value to be applied
+to `port` if has a different port number, `hostname` so it has a correct name
+again and `href` so you have a complete URL.
+
+```js
+var parsed = parse('http://google.com/parse-things');
+
+parsed.set('hostname', 'yahoo.com');
+console.log(parsed.href); // http://yahoo.com/parse-things
+```
+
+It's aware of default ports so you cannot set a port 80 on an URL which has
+`http` as protocol.
+
+### URL.toString()
+
+The returned `url` object comes with a custom `toString` method which will
+generate a full URL again when called. The method accepts an extra function
+which will stringify the query string for you. If you don't supply a function we
+will use our default method.
+
+```js
+var location = url.toString(); // http://example.com/whatever/?qs=32
+```
+
+You would rarely need to use this method as the full URL is also available as
+`href` property. If you are using the `URL.set` method to make changes, this
+will automatically update.
+
+## Testing
+
+The testing of this module is done in 3 different ways:
+
+1. We have unit tests setup which run under Node.js using the normal `npm test`
+   command.
+2. Code coverage can be run manually using `npm run coverage`
+3. For browser testing we use `testling` to startup a test server. We do assume
+   that you `testling` installed globally, if not please run `npm install -g
+   testling` and after that `testling -u` in the root of this repository. When
+   you visit the outputted URL all unit tests that were written from the Node
+   can now be ran inside browsers.
+
+## License
+
+MIT
diff --git a/fuzzy.js b/fuzzy.js
new file mode 100644
index 0000000..b445753
--- /dev/null
+++ b/fuzzy.js
@@ -0,0 +1,79 @@
+'use strict';
+
+var URL = require('./')
+  , url = new URL('');
+
+/**
+ * A dictionary with all kind of different options that should generate a valid
+ * and parse-able URL.
+ *
+ * @type {Object}
+ * @api private
+ */
+var combinations = {};
+
+combinations.protocol = ['http:', 'https:', 'ws:', 'wss:', 'blob:'/*, ''*/];
+combinations.username = ['foo', 'bar'];
+combinations.password = combinations.username;
+combinations.hostname = ['example.com', 'www.example.com', 'travel.travel', 'sub.sub.sub.domain.nl', 'xn--n3h.com', 'localhost', '127.0.0.1', '255.255.255.255', /*'3ffe:6a88:85a3:08d3:1319:8a2e:0370:7344', '2001:2353::1428:57ab', '2001:2353:0::0:1428:57ab', '2001:2353:0:0:0:0:1428:57ab', '2001:2353:0000:0000:0000::1428:57ab', '2001:2353:0000:0000:0000:0000:1428:57ab', '2001:2353:02de::0e13', '2001:2353:2de::e13'*/];
+combinations.port = ['8080', '844', '3340'];
+combinations.pathname = ['/', '/bar', '/bar/', '/foo/bar', '/foo.bar/foo', '/fav.ico', '/@3rd-Eden', '/a/b/c/d/e/f/g/j/1/d/4/'];
+combinations.query = ['foo=bar', 'foo[]=bar&foo[]=foo', 'email=foo at bar.travel', 'q='];
+combinations.hash = ['name', 'moo-with-longer-name', '/what/about/slashes?querystring', '?querystring', '!/google/urls', 'use:foo@', 'http://'];
+
+/**
+ * Get a random item from the given array.
+ *
+ * @param {String} name Name of the array we want to have a random item returned.
+ * @returns {Mixed}
+ * @api private
+ */
+function get(name) {
+  var data = combinations[name];
+
+  return data[Math.floor(Math.random() * data.length)];
+}
+
+/**
+ * Return a random boolean.
+ *
+ * @returns {Boolean}
+ * @api private
+ */
+function yep() {
+  return !!Math.round(Math.random() * 1);
+}
+
+/**
+ * Generate the actual URL.
+ *
+ * @returns {Object} specification
+ * @api public
+ */
+module.exports = function generate() {
+  var spec = {}
+    , key;
+
+  spec.protocol = get('protocol');
+  spec.hostname = get('hostname');
+  spec.pathname = get('pathname');
+
+  if (yep()) spec.port = get('port');
+  if (yep()) spec.query = '?'+ get('query');
+  if (yep()) spec.hash = '#'+ get('hash');
+  if (yep()) {
+    spec.username = get('username');
+    spec.password = get('password');
+  }
+
+  for (key in combinations) {
+    url[key] = '';
+  }
+
+  for (key in spec) {
+    url[key] = spec[key];
+  }
+
+  spec.href = url.toString();
+  return spec;
+};
diff --git a/index.js b/index.js
new file mode 100644
index 0000000..92eaa4d
--- /dev/null
+++ b/index.js
@@ -0,0 +1,232 @@
+'use strict';
+
+var required = require('requires-port')
+  , lolcation = require('./lolcation')
+  , qs = require('querystringify')
+  , relativere = /^\/(?!\/)/;
+
+/**
+ * These are the parse instructions for the URL parsers, it informs the parser
+ * about:
+ *
+ * 0. The char it Needs to parse, if it's a string it should be done using
+ *    indexOf, RegExp using exec and NaN means set as current value.
+ * 1. The property we should set when parsing this value.
+ * 2. Indication if it's backwards or forward parsing, when set as number it's
+ *    the value of extra chars that should be split off.
+ * 3. Inherit from location if non existing in the parser.
+ * 4. `toLowerCase` the resulting value.
+ */
+var instructions = [
+  ['#', 'hash'],                        // Extract from the back.
+  ['?', 'query'],                       // Extract from the back.
+  ['//', 'protocol', 2, 1, 1],          // Extract from the front.
+  ['/', 'pathname'],                    // Extract from the back.
+  ['@', 'auth', 1],                     // Extract from the front.
+  [NaN, 'host', undefined, 1, 1],       // Set left over value.
+  [/\:(\d+)$/, 'port'],                 // RegExp the back.
+  [NaN, 'hostname', undefined, 1, 1]    // Set left over.
+];
+
+/**
+ * The actual URL instance. Instead of returning an object we've opted-in to
+ * create an actual constructor as it's much more memory efficient and
+ * faster and it pleases my CDO.
+ *
+ * @constructor
+ * @param {String} address URL we want to parse.
+ * @param {Boolean|function} parser Parser for the query string.
+ * @param {Object} location Location defaults for relative paths.
+ * @api public
+ */
+function URL(address, location, parser) {
+  if (!(this instanceof URL)) {
+    return new URL(address, location, parser);
+  }
+
+  var relative = relativere.test(address)
+    , parse, instruction, index, key
+    , type = typeof location
+    , url = this
+    , i = 0;
+
+  //
+  // The following if statements allows this module two have compatibility with
+  // 2 different API:
+  //
+  // 1. Node.js's `url.parse` api which accepts a URL, boolean as arguments
+  //    where the boolean indicates that the query string should also be parsed.
+  //
+  // 2. The `URL` interface of the browser which accepts a URL, object as
+  //    arguments. The supplied object will be used as default values / fall-back
+  //    for relative paths.
+  //
+  if ('object' !== type && 'string' !== type) {
+    parser = location;
+    location = null;
+  }
+
+  if (parser && 'function' !== typeof parser) {
+    parser = qs.parse;
+  }
+
+  location = lolcation(location);
+
+  for (; i < instructions.length; i++) {
+    instruction = instructions[i];
+    parse = instruction[0];
+    key = instruction[1];
+
+    if (parse !== parse) {
+      url[key] = address;
+    } else if ('string' === typeof parse) {
+      if (~(index = address.indexOf(parse))) {
+        if ('number' === typeof instruction[2]) {
+          url[key] = address.slice(0, index);
+          address = address.slice(index + instruction[2]);
+        } else {
+          url[key] = address.slice(index);
+          address = address.slice(0, index);
+        }
+      }
+    } else if (index = parse.exec(address)) {
+      url[key] = index[1];
+      address = address.slice(0, address.length - index[0].length);
+    }
+
+    url[key] = url[key] || (instruction[3] || ('port' === key && relative) ? location[key] || '' : '');
+
+    //
+    // Hostname, host and protocol should be lowercased so they can be used to
+    // create a proper `origin`.
+    //
+    if (instruction[4]) {
+      url[key] = url[key].toLowerCase();
+    }
+  }
+
+  //
+  // Also parse the supplied query string in to an object. If we're supplied
+  // with a custom parser as function use that instead of the default build-in
+  // parser.
+  //
+  if (parser) url.query = parser(url.query);
+
+  //
+  // We should not add port numbers if they are already the default port number
+  // for a given protocol. As the host also contains the port number we're going
+  // override it with the hostname which contains no port number.
+  //
+  if (!required(url.port, url.protocol)) {
+    url.host = url.hostname;
+    url.port = '';
+  }
+
+  //
+  // Parse down the `auth` for the username and password.
+  //
+  url.username = url.password = '';
+  if (url.auth) {
+    instruction = url.auth.split(':');
+    url.username = instruction[0] || '';
+    url.password = instruction[1] || '';
+  }
+
+  //
+  // The href is just the compiled result.
+  //
+  url.href = url.toString();
+}
+
+/**
+ * This is convenience method for changing properties in the URL instance to
+ * insure that they all propagate correctly.
+ *
+ * @param {String} prop Property we need to adjust.
+ * @param {Mixed} value The newly assigned value.
+ * @returns {URL}
+ * @api public
+ */
+URL.prototype.set = function set(part, value, fn) {
+  var url = this;
+
+  if ('query' === part) {
+    if ('string' === typeof value && value.length) {
+      value = (fn || qs.parse)(value);
+    }
+
+    url[part] = value;
+  } else if ('port' === part) {
+    url[part] = value;
+
+    if (!required(value, url.protocol)) {
+      url.host = url.hostname;
+      url[part] = '';
+    } else if (value) {
+      url.host = url.hostname +':'+ value;
+    }
+  } else if ('hostname' === part) {
+    url[part] = value;
+
+    if (url.port) value += ':'+ url.port;
+    url.host = value;
+  } else if ('host' === part) {
+    url[part] = value;
+
+    if (/\:\d+/.test(value)) {
+      value = value.split(':');
+      url.hostname = value[0];
+      url.port = value[1];
+    }
+  } else {
+    url[part] = value;
+  }
+
+  url.href = url.toString();
+  return url;
+};
+
+/**
+ * Transform the properties back in to a valid and full URL string.
+ *
+ * @param {Function} stringify Optional query stringify function.
+ * @returns {String}
+ * @api public
+ */
+URL.prototype.toString = function toString(stringify) {
+  if (!stringify || 'function' !== typeof stringify) stringify = qs.stringify;
+
+  var query
+    , url = this
+    , result = url.protocol +'//';
+
+  if (url.username) {
+    result += url.username;
+    if (url.password) result += ':'+ url.password;
+    result += '@';
+  }
+
+  result += url.hostname;
+  if (url.port) result += ':'+ url.port;
+
+  result += url.pathname;
+
+  if (url.query) {
+    if ('object' === typeof url.query) query = stringify(url.query);
+    else query = url.query;
+
+    result += (query.charAt(0) === '?' ? '' : '?') + query;
+  }
+
+  if (url.hash) result += url.hash;
+
+  return result;
+};
+
+//
+// Expose the URL parser and some additional properties that might be useful for
+// others.
+//
+URL.qs = qs;
+URL.location = lolcation;
+module.exports = URL;
diff --git a/lolcation.js b/lolcation.js
new file mode 100644
index 0000000..d251856
--- /dev/null
+++ b/lolcation.js
@@ -0,0 +1,45 @@
+'use strict';
+
+/**
+ * These properties should not be copied or inherited from. This is only needed
+ * for all non blob URL's as the a blob URL does not include a hash, only the
+ * origin.
+ *
+ * @type {Object}
+ * @private
+ */
+var ignore = { hash: 1, query: 1 }
+  , URL;
+
+/**
+ * The location object differs when your code is loaded through a normal page,
+ * Worker or through a worker using a blob. And with the blobble begins the
+ * trouble as the location object will contain the URL of the blob, not the
+ * location of the page where our code is loaded in. The actual origin is
+ * encoded in the `pathname` so we can thankfully generate a good "default"
+ * location from it so we can generate proper relative URL's again.
+ *
+ * @param {Object} loc Optional default location object.
+ * @returns {Object} lolcation object.
+ * @api public
+ */
+module.exports = function lolcation(loc) {
+  loc = loc || global.location || {};
+  URL = URL || require('./');
+
+  var finaldestination = {}
+    , type = typeof loc
+    , key;
+
+  if ('blob:' === loc.protocol) {
+    finaldestination = new URL(unescape(loc.pathname), {});
+  } else if ('string' === type) {
+    finaldestination = new URL(loc, {});
+    for (key in ignore) delete finaldestination[key];
+  } else if ('object' === type) for (key in loc) {
+    if (key in ignore) continue;
+    finaldestination[key] = loc[key];
+  }
+
+  return finaldestination;
+};
diff --git a/package.json b/package.json
new file mode 100644
index 0000000..dfef6e1
--- /dev/null
+++ b/package.json
@@ -0,0 +1,63 @@
+{
+  "name": "url-parse",
+  "version": "1.0.2",
+  "description": "Parse URL in node using the URL module and in the browser using the DOM",
+  "main": "index.js",
+  "scripts": {
+    "100%": "istanbul check-coverage --statements 100 --functions 100 --lines 100 --branches 100",
+    "test": "mocha test.js",
+    "watch": "mocha --watch test.js",
+    "coverage": "istanbul cover ./node_modules/.bin/_mocha -- test.js",
+    "test-travis": "istanbul cover node_modules/.bin/_mocha --report lcovonly -- test.js",
+    "browserify": "mkdir -p dist && browserify index.js -o dist/url-parse.js --standalone URLParse",
+    "phantomjs": "mochify --reporter spec --ui bdd ./test.js",
+    "testling": "testling -u"
+  },
+  "keywords": [
+    "URL",
+    "parser",
+    "uri",
+    "url",
+    "parse",
+    "query",
+    "string",
+    "querystring",
+    "stringify"
+  ],
+  "author": "Arnout Kazemier",
+  "license": "MIT",
+  "devDependencies": {
+    "assume": "1.1.x",
+    "browserify": "8.1.x",
+    "istanbul": "0.3.x",
+    "mocha": "2.1.x",
+    "mochify": "2.4.x",
+    "pre-commit": "1.0.x",
+    "testling": "1.7.x"
+  },
+  "testling": {
+    "files": "test.js",
+    "harness": "mocha-bdd",
+    "browsers": [
+      "ie/6..latest",
+      "chrome/22..latest",
+      "firefox/16..latest",
+      "safari/latest",
+      "opera/11.0..latest",
+      "iphone/6",
+      "ipad/6",
+      "android-browser/latest"
+    ]
+  },
+  "browser": {
+    "url": false
+  },
+  "repository": {
+    "type": "git",
+    "url": "https://github.com/unshiftio/url-parse"
+  },
+  "dependencies": {
+    "querystringify": "0.0.x",
+    "requires-port": "0.0.x"
+  }
+}
diff --git a/test.js b/test.js
new file mode 100644
index 0000000..477b3d8
--- /dev/null
+++ b/test.js
@@ -0,0 +1,384 @@
+describe('url-parse', function () {
+  'use strict';
+
+  var assume = require('assume')
+    , parse = require('./');
+
+  it('exposes parse as a function', function () {
+    assume(parse).is.a('function');
+  });
+
+  it('exposes the querystring module', function () {
+    assume(parse.qs).equals(require('querystringify'));
+  });
+
+  it('exposes the location function', function () {
+    assume(parse.location).equals(require('./lolcation'));
+  });
+
+  it('parsers the query string', function () {
+    var url = 'http://google.com/?foo=bar'
+      , data = parse(url, true);
+
+    assume(data.query).is.a('object');
+    assume(data.query.foo).equals('bar');
+  });
+
+  it('allows a custom function as parser', function () {
+    var url = 'http://google.com/?foo=bar'
+      , data = parse(url, function () { return '1337'; });
+
+    assume(data.query).equals('1337');
+  });
+
+  it('allows a custom stringify function', function () {
+    var url = 'http://google.com/?foo=bar'
+      , data = parse(url, true)
+      , str;
+
+    str = data.toString(function () { return 'lolcakes'; });
+    assume(str).equals('http://google.com/?lolcakes');
+  });
+
+  it('allows a custom location object', function () {
+    var url = '/foo?foo=bar'
+      , data = parse(url, parse('http://google.com'));
+
+    assume(data.href).equals('http://google.com/foo?foo=bar');
+  });
+
+  it('is blob: location aware', function () {
+    var blob = {"hash":"","search":"","pathname":"https%3A//gist.github.com/3f272586-6dac-4e29-92d0-f674f2dde618","port":"","hostname":"","host":"","protocol":"blob:","origin":"https://gist.github.com","href":"blob:https%3A//gist.github.com/3f272586-6dac-4e29-92d0-f674f2dde618"}
+      , url = '/unshiftio/url-parse'
+      , data = parse(url, blob);
+
+    assume(data.href).equals('https://gist.github.com/unshiftio/url-parse');
+  });
+
+  it('converts protocol to lowercase', function () {
+    var url = 'HTTP://example.com';
+
+    assume(parse(url).protocol).equals('http:');
+  });
+
+  it('can parse complex urls multiple times without errors', function () {
+    var url = 'https://www.mozilla.org/en-US/firefox/34.0/whatsnew/?oldversion=33.1';
+
+    for (var i = 0; i < 100; i++) {
+      parse(url);
+    }
+  });
+
+  it('converts hostname to lowercase', function () {
+    var url = 'HTTP://fOo.eXaMPle.com';
+
+    assume(parse(url).hostname).equals('foo.example.com');
+  });
+
+  it('does not lowercase the path', function () {
+    var url = 'HTTP://X.COM/Y/Z';
+
+    assume(parse(url).pathname).equals('/Y/Z');
+  });
+
+  it('removes default port numbers', function () {
+    var url = 'http://example.com:80'
+      , parsed = parse(url);
+
+    assume(parsed.port).equals('');
+    assume(parsed.host).equals('example.com');
+    assume(parsed.hostname).equals('example.com');
+    assume(parsed.href).equals('http://example.com');
+  });
+
+  it('understands an / as pathname', function () {
+    var url = 'http://example.com:80/'
+      , parsed = parse(url);
+
+    assume(parsed.port).equals('');
+    assume(parsed.username).equals('');
+    assume(parsed.password).equals('');
+    assume(parsed.pathname).equals('/');
+    assume(parsed.host).equals('example.com');
+    assume(parsed.hostname).equals('example.com');
+    assume(parsed.href).equals('http://example.com/');
+  });
+
+  it('does not care about spaces', function () {
+    var url = 'http://x.com/path?that\'s#all, folks'
+      , parsed = parse(url);
+
+    assume(parsed.port).equals('');
+    assume(parsed.username).equals('');
+    assume(parsed.password).equals('');
+    assume(parsed.pathname).equals('/path');
+    assume(parsed.hash).equal('#all, folks');
+    assume(parsed.query).equal('?that\'s');
+    assume(parsed.host).equals('x.com');
+    assume(parsed.hostname).equals('x.com');
+  });
+
+  it('accepts + in the url', function () {
+    var url = 'http://x.y.com+a/b/c'
+      , parsed = parse(url);
+
+    assume(parsed.protocol).equals('http:');
+    assume(parsed.host).equals('x.y.com+a');
+    assume(parsed.hostname).equals('x.y.com+a');
+    assume(parsed.pathname).equals('/b/c');
+  });
+
+  describe('ip', function () {
+    // coap://
+    //
+    it('parses ipv6', function () {
+      var url = 'http://[1080:0:0:0:8:800:200C:417A]:61616/foo/bar?q=z'
+        , parsed = parse(url);
+
+      assume(parsed.port).equals('61616');
+      assume(parsed.query).equals('?q=z');
+      assume(parsed.protocol).equals('http:');
+      assume(parsed.hostname).equals('[1080:0:0:0:8:800:200c:417a]');
+      assume(parsed.pathname).equals('/foo/bar');
+      assume(parsed.href).equals('http://[1080:0:0:0:8:800:200c:417a]:61616/foo/bar?q=z');
+    });
+
+    it('parses ipv6 with auth', function () {
+      var url = 'http://user:password@[3ffe:2a00:100:7031::1]:8080'
+        , parsed = parse(url);
+
+      assume(parsed.username).equals('user');
+      assume(parsed.password).equals('password');
+      assume(parsed.host).equals('[3ffe:2a00:100:7031::1]:8080');
+      assume(parsed.hostname).equals('[3ffe:2a00:100:7031::1]');
+      assume(parsed.href).equals(url);
+    });
+
+    it('parses ipv4', function () {
+      var url = 'http://222.148.142.13:61616/foo/bar?q=z'
+        , parsed = parse(url);
+
+      assume(parsed.port).equals('61616');
+      assume(parsed.query).equals('?q=z');
+      assume(parsed.protocol).equals('http:');
+      assume(parsed.hostname).equals('222.148.142.13');
+      assume(parsed.pathname).equals('/foo/bar');
+      assume(parsed.href).equals(url);
+    });
+  });
+
+  describe('auth', function () {
+    it('does not lowercase the USER:PASS', function () {
+      var url = 'HTTP://USER:PASS@EXAMPLE.COM'
+        , parsed = parse(url);
+
+      assume(parsed.username).equals('USER');
+      assume(parsed.password).equals('PASS');
+      assume(parsed.protocol).equals('http:');
+      assume(parsed.host).equals('example.com');
+      assume(parsed.hostname).equals('example.com');
+    });
+
+    it('accepts @ in pathnames', function () {
+      var url = 'http://mt0.google.com/vt/lyrs=m@114&hl=en&src=api&x=2&y=2&z=3&s='
+        , parsed = parse(url);
+
+      assume(parsed.pathname).equals('/vt/lyrs=m at 114&hl=en&src=api&x=2&y=2&z=3&s=');
+      assume(parsed.username).equals('');
+      assume(parsed.password).equals('');
+    });
+
+    it('does not require passwords for auth', function () {
+      var url = 'http://user@www.example.com/'
+        , parsed = parse(url);
+
+      assume(parsed.password).equals('');
+      assume(parsed.pathname).equals('/');
+      assume(parsed.username).equals('user');
+      assume(parsed.protocol).equals('http:');
+      assume(parsed.hostname).equals('www.example.com');
+      assume(parsed.href).equals(url);
+    });
+  });
+
+  it('accepts multiple ???', function () {
+    var url = 'http://mt0.google.com/vt/lyrs=m@114???&hl=en&src=api&x=2&y=2&z=3&s=';
+    assume(parse(url).query).equals('???&hl=en&src=api&x=2&y=2&z=3&s=');
+  });
+
+  it('accepts a string as source argument', function () {
+    var data = parse('/foo', 'http://sub.example.com/bar?foo=bar#hash');
+
+    assume(data.port).equals('');
+    assume(data.host).equals('sub.example.com');
+    assume(data.href).equals('http://sub.example.com/foo');
+  });
+
+  describe('inheritance', function () {
+    it('does not inherit port numbers for non relative urls', function () {
+      var data = parse('http://localhost', parse('http://sub.example.com:808/'));
+
+      assume(data.port).equals('');
+      assume(data.host).equals('localhost');
+      assume(data.href).equals('http://localhost');
+    });
+
+    it('does inherit port numbers from relative urls', function () {
+      var data = parse('/foo', parse('http://sub.example.com:808/'));
+
+      assume(data.port).equals('808');
+      assume(data.hostname).equals('sub.example.com');
+      assume(data.host).equals('sub.example.com:808');
+      assume(data.href).equals('http://sub.example.com:808/foo');
+    });
+
+    it('inherits protocol for relative protocols', function () {
+      var data = parse('//foo.com/foo', parse('http://sub.example.com:808/'));
+
+      assume(data.port).equals('');
+      assume(data.host).equals('foo.com');
+      assume(data.protocol).equals('http:');
+      assume(data.href).equals('http://foo.com/foo');
+    });
+
+    it('does not inherit pathnames from the source', function () {
+      var data = parse('http://localhost', parse('http://foo:bar@sub.example.com/bar?foo=bar#hash'));
+
+      assume(data.port).equals('');
+      assume(data.host).equals('localhost');
+      assume(data.href).equals('http://localhost');
+    });
+
+    it('does not inherit hashes and query strings from source object', function () {
+      var data = parse('/foo', parse('http://sub.example.com/bar?foo=bar#hash'));
+
+      assume(data.port).equals('');
+      assume(data.host).equals('sub.example.com');
+      assume(data.href).equals('http://sub.example.com/foo');
+    });
+
+    it('does not inherit auth from source object', function () {
+      var from = parse('http://foo:bar@sub.example.com')
+        , data = parse('/foo', from);
+
+      assume(data.port).equals('');
+      assume(data.username).equals('');
+      assume(data.password).equals('');
+      assume(data.host).equals('sub.example.com');
+      assume(data.href).equals('http://sub.example.com/foo');
+    });
+  });
+
+  describe('#set', function () {
+    it('correctly updates the host when setting port', function () {
+      var data = parse('http://google.com/foo');
+
+      assume(data.set('port', 8080)).equals(data);
+
+      assume(data.host).equals('google.com:8080');
+      assume(data.href).equals('http://google.com:8080/foo');
+    });
+
+    it('removes querystring and hash', function () {
+      var data = parse('https://thisanurl.com/?swag=yolo#representing');
+
+      data.set('query', '');
+      data.set('hash', '');
+
+      assume(data.href).equals('https://thisanurl.com/');
+    });
+
+    it('only sets port when its not default', function () {
+      var data = parse('http://google.com/foo');
+
+      assume(data.set('port', 80)).equals(data);
+
+      assume(data.host).equals('google.com');
+      assume(data.href).equals('http://google.com/foo');
+
+      assume(data.set('port', 443)).equals(data);
+      assume(data.host).equals('google.com:443');
+      assume(data.href).equals('http://google.com:443/foo');
+    });
+
+    it('updates query with object', function () {
+      var data = parse('http://google.com/?foo=bar');
+
+      assume(data.set('query', { bar: 'foo' })).equals(data);
+
+      assume(data.query.foo).equals(undefined);
+      assume(data.query.bar).equals('foo');
+
+      assume(data.href).equals('http://google.com/?bar=foo');
+    });
+
+    it('updates query with a string', function () {
+      var data = parse('http://google.com/?foo=bar');
+
+      assume(data.set('query', 'bar=foo')).equals(data);
+
+      assume(data.query.foo).equals(undefined);
+      assume(data.query.bar).equals('foo');
+
+      assume(data.href).equals('http://google.com/?bar=foo');
+
+      assume(data.set('query', '?baz=foo')).equals(data);
+
+      assume(data.query.bar).equals(undefined);
+      assume(data.query.baz).equals('foo');
+
+      assume(data.href).equals('http://google.com/?baz=foo');
+    });
+
+    it('updates the port when updating host', function () {
+      var data = parse('http://google.com/?foo=bar');
+
+      assume(data.set('host', 'yahoo.com:808')).equals(data);
+
+      assume(data.hostname).equals('yahoo.com');
+      assume(data.host).equals('yahoo.com:808');
+      assume(data.port).equals('808');
+
+      assume(data.href).equals('http://yahoo.com:808/?foo=bar');
+    });
+
+    it('updates the host when updating hostname', function () {
+      var data = parse('http://google.com:808/?foo=bar');
+
+      assume(data.set('hostname', 'yahoo.com')).equals(data);
+
+      assume(data.hostname).equals('yahoo.com');
+      assume(data.host).equals('yahoo.com:808');
+      assume(data.port).equals('808');
+
+      assume(data.href).equals('http://yahoo.com:808/?foo=bar');
+    });
+
+    it('updates other values', function () {
+      var data = parse('http://google.com/?foo=bar');
+
+      assume(data.set('protocol', 'https:')).equals(data);
+      assume(data.protocol).equals('https:');
+
+      assume(data.href).equals('https://google.com/?foo=bar');
+    });
+  });
+
+  describe('fuzzy', function () {
+    var fuzz = require('./fuzzy')
+      , times = 10;
+
+    for (var i = 0; i < times; i++) {
+      (function (spec) {
+        it('parses: '+ spec.href, function () {
+          var url = parse(spec.href)
+            , prop;
+
+          for (prop in spec) {
+            assume(url[prop]).equals(spec[prop]);
+          }
+        });
+      })(fuzz());
+    }
+  });
+});

-- 
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/pkg-javascript/node-url-parse.git



More information about the Pkg-javascript-commits mailing list