Comparing version 1.3.0-beta.1 to 1.3.0
{ | ||
"name": "jsUri", | ||
"version": "1.2.2", | ||
"version": "1.3.0", | ||
"main": "./Uri.js", | ||
@@ -5,0 +5,0 @@ "dependencies": { |
{ | ||
"name": "jsuri", | ||
"description": "Uri and query string manipulation", | ||
"version": "1.3.0-beta.1", | ||
"version": "1.3.0", | ||
"author": "Derek Watson <watson@dcw.ca> (http://dcw.ca)", | ||
@@ -35,3 +35,3 @@ "contributors": [ | ||
"mocha": "~1.14.0", | ||
"chai": "~1.8.1" | ||
"chai": "~1.9.2" | ||
}, | ||
@@ -41,3 +41,23 @@ "optionalDependencies": {}, | ||
"node": "*" | ||
}, | ||
"jshintConfig": { | ||
"boss": true, | ||
"node": true, | ||
"smarttabs": true, | ||
"undef": true, | ||
"unused": true, | ||
"onecase": true, | ||
"lastsemic": true, | ||
"indent": 2, | ||
"newcap" : true, | ||
"noempty" : true, | ||
"nonew" : true, | ||
"nomen" : true, | ||
"sub" : false, | ||
"trailing" : true, | ||
"white" : false | ||
}, | ||
"spm": { | ||
"main": "Uri.js" | ||
} | ||
} |
146
README.md
@@ -0,98 +1,124 @@ | ||
# jsUri | ||
URI parsing and manipulation for node.js and the browser. | ||
[![Build Status](https://travis-ci.org/derek-watson/jsUri.png)](https://travis-ci.org/derek-watson/jsUri) | ||
# jsUri | ||
[![NPM](https://nodei.co/npm/jsuri.png)](https://nodei.co/npm/jsuri/) | ||
Uri parsing and manipulation for node.js and the browser. | ||
[![spm package](http://spmjs.io/badge/jsuri)](http://spmjs.io/package/jsuri) | ||
var uri = new Uri('http://user:pass@www.test.com:81/index.html?q=books#fragment') | ||
Pass any URL into the constructor: | ||
Use property methods to get at the various parts | ||
```js | ||
var uri = new Uri('http://user:pass@www.test.com:81/index.html?q=books#fragment') | ||
``` | ||
uri.protocol() // http | ||
uri.userInfo() // user:pass | ||
uri.host() // www.test.com | ||
uri.port() // 81 | ||
uri.path() // /index.html | ||
uri.query() // q=books | ||
uri.anchor() // fragment | ||
Use property methods to get at the various parts: | ||
Property methods accept an optional value to set | ||
```js | ||
uri.protocol() // http | ||
uri.userInfo() // user:pass | ||
uri.host() // www.test.com | ||
uri.port() // 81 | ||
uri.path() // /index.html | ||
uri.query() // q=books | ||
uri.anchor() // fragment | ||
``` | ||
uri.protocol('https') | ||
uri.toString() // https://user:pass@www.test.com:81/index.html?q=books#fragment | ||
Property methods accept an optional value to set: | ||
uri.host('mydomain.com') | ||
uri.toString() // https://user:pass@www.mydomain.com:81/index.html?q=books#fragment | ||
```js | ||
uri.protocol('https') | ||
uri.toString() // https://user:pass@www.test.com:81/index.html?q=books#fragment | ||
Chainable setter methods help you compose strings | ||
uri.host('mydomain.com') | ||
uri.toString() // https://user:pass@mydomain.com:81/index.html?q=books#fragment | ||
``` | ||
new Uri() | ||
.setPath('/archives/1979/') | ||
.setQuery('?page=1') // /archives/1979?page=1 | ||
Chainable setter methods help you compose strings: | ||
new Uri() | ||
.setPath('/index.html') | ||
.setAnchor('content') | ||
.setHost('www.test.com') | ||
.setPort(8080) | ||
.setUserInfo('username:password') | ||
.setProtocol('https') | ||
.setQuery('this=that&some=thing') // https://username:password@www.test.com:8080/index.html?this=that&some=thing#content | ||
```js | ||
new Uri() | ||
.setPath('/archives/1979/') | ||
.setQuery('?page=1') // /archives/1979?page=1 | ||
new Uri('http://www.test.com') | ||
.setHost('www.yahoo.com') | ||
.setProtocol('https') // https://www.yahoo.com | ||
new Uri() | ||
.setPath('/index.html') | ||
.setAnchor('content') | ||
.setHost('www.test.com') | ||
.setPort(8080) | ||
.setUserInfo('username:password') | ||
.setProtocol('https') | ||
.setQuery('this=that&some=thing') // https://username:password@www.test.com:8080/index.html?this=that&some=thing#content | ||
new Uri('http://www.test.com') | ||
.setHost('www.yahoo.com') | ||
.setProtocol('https') // https://www.yahoo.com | ||
``` | ||
## Query param methods | ||
Returns the first query param value for the key | ||
Returns the first query param value for the key: | ||
new Uri('?cat=1&cat=2&cat=3').getQueryParamValue('cat') // 1 | ||
```js | ||
new Uri('?cat=1&cat=2&cat=3').getQueryParamValue('cat') // 1 | ||
``` | ||
Returns all query param values for the given key | ||
Returns all query param values for the given key: | ||
new Uri('?cat=1&cat=2&cat=3').getQueryParamValues('cat') // [1, 2, 3] | ||
```js | ||
new Uri('?cat=1&cat=2&cat=3').getQueryParamValues('cat') // [1, 2, 3] | ||
``` | ||
Internally, query key/value pairs are stored as a series of two-value arrays in the Query object | ||
Internally, query key/value pairs are stored as a series of two-value arrays in the Query object: | ||
new Uri('?a=b&c=d').query().params // [ ['a', 'b'], ['c', 'd']] | ||
```js | ||
new Uri('?a=b&c=d').query().params // [ ['a', 'b'], ['c', 'd']] | ||
``` | ||
Add query param values | ||
Add query param values: | ||
new Uri().addQueryParam('q', 'books') // ?q=books | ||
```js | ||
new Uri().addQueryParam('q', 'books') // ?q=books | ||
new Uri('http://www.github.com') | ||
.addQueryParam('testing', '123') | ||
.addQueryParam('one', 1) // http://www.github.com/?testing=123&one=1 | ||
new Uri('http://www.github.com') | ||
.addQueryParam('testing', '123') | ||
.addQueryParam('one', 1) // http://www.github.com/?testing=123&one=1 | ||
// insert param at index 0 | ||
new Uri('?b=2&c=3&d=4').addQueryParam('a', '1', 0) // ?a=1&b=2&c=3&d=4 | ||
// insert param at index 0 | ||
new Uri('?b=2&c=3&d=4').addQueryParam('a', '1', 0) // ?a=1&b=2&c=3&d=4 | ||
``` | ||
Replace every query string parameter named `key` with `newVal` | ||
Replace every query string parameter named `key` with `newVal`: | ||
new Uri().replaceQueryParam('page', 2) // ?page=2 | ||
```js | ||
new Uri().replaceQueryParam('page', 2) // ?page=2 | ||
new Uri('?a=1&b=2&c=3') | ||
.replaceQueryParam('a', 'eh') // ?a=eh&b=2&c=3 | ||
new Uri('?a=1&b=2&c=3') | ||
.replaceQueryParam('a', 'eh') // ?a=eh&b=2&c=3 | ||
new Uri('?a=1&b=2&c=3&c=4&c=5&c=6') | ||
.replaceQueryParam('c', 'five', '5') // ?a=1&b=2&c=3&c=4&c=five&c=6 | ||
new Uri('?a=1&b=2&c=3&c=4&c=5&c=6') | ||
.replaceQueryParam('c', 'five', '5') // ?a=1&b=2&c=3&c=4&c=five&c=6 | ||
``` | ||
Removes instances of query parameters named `key`: | ||
Removes instances of query parameters named `key` | ||
```js | ||
new Uri('?a=1&b=2&c=3') | ||
.deleteQueryParam('a') // ?b=2&c=3 | ||
new Uri('?a=1&b=2&c=3') | ||
.deleteQueryParam('a') // ?b=2&c=3 | ||
new Uri('test.com?a=1&b=2&c=3&a=eh') | ||
.deleteQueryParam('a', 'eh') // test.com/?a=1&b=2&c=3 | ||
``` | ||
new Uri('test.com?a=1&b=2&c=3&a=eh') | ||
.deleteQueryParam('a', 'eh') // test.com/?a=1&b=2&c=3 | ||
Create an identical URI object with no shared state: | ||
Create an identical uri object with no shared state | ||
```js | ||
var baseUri = new Uri('http://localhost/') | ||
var baseUri = new Uri('http://localhost/') | ||
baseUri.clone().setProtocol('https') // https://localhost/ | ||
baseUri // http://localhost/ | ||
``` | ||
baseUri.clone().setProtocol('https') // https://localhost/ | ||
baseUri // http://localhost/ | ||
This project incorporates the [parseUri](http://blog.stevenlevithan.com/archives/parseuri) regular expression by Steven Levithan. |
@@ -211,2 +211,14 @@ var expect = require('chai').expect | ||
}) | ||
it('preserves the format of file uris', function() { | ||
var str = 'file://c:/parent/child.ext' | ||
var uri = new Uri(str) | ||
expect(uri.toString()).to.equal(str) | ||
}) | ||
it('correctly composes url encoded urls', function() { | ||
var originalQuery = '?k=%40v' | ||
var parsed = new Uri('http://example.com' + originalQuery) | ||
expect(parsed.query()).to.equal(originalQuery) | ||
}) | ||
}) |
@@ -40,2 +40,10 @@ var expect = require('chai').expect | ||
}) | ||
it('should correctly parse the uri if an @ sign is present after the host part of the url', function(){ | ||
q = new Uri('http://github.com/username?email=user@example.com&11=eleven') | ||
expect(q.host()).to.equal('github.com') | ||
expect(q.path()).to.equal('/username') | ||
expect(q.getQueryParamValue('email')).to.equal('user@example.com') | ||
expect(q.getQueryParamValue('11')).to.equal('eleven') | ||
}) | ||
}) | ||
@@ -107,2 +115,7 @@ | ||
it('should not do anything if passed no params', function() { | ||
q = new Uri('?a=1&b=2&c=3').addQueryParam() | ||
expect(q.toString()).to.equal('?a=1&b=2&c=3') | ||
}) | ||
it('should be able to directly replace a query param', function() { | ||
@@ -113,2 +126,12 @@ q = new Uri('?a=1&b=2&c=3').replaceQueryParam('a', 'eh') | ||
it('should remove an extra question mark', function() { | ||
q = new Uri('??a=1&b=2&c=3').replaceQueryParam('a', 4) | ||
expect(q.toString()).to.equal('?a=4&b=2&c=3') | ||
}) | ||
it('should remove a param without a key', function() { | ||
q = new Uri('?=1&b=2&c=3').replaceQueryParam('a', 4) | ||
expect(q.toString()).to.equal('?b=2&c=3&a=4') | ||
}) | ||
it('should be able to replace a query param value that does not exist', function() { | ||
@@ -119,2 +142,27 @@ q = new Uri().replaceQueryParam('page', 2) | ||
it('should be able to replace a nonexistent query param value when others exist', function() { | ||
q = new Uri('?a=1').replaceQueryParam('page', 2) | ||
expect(q.toString()).to.equal('?a=1&page=2') | ||
}) | ||
it('should be able to replace only a query param value with a specified value', function() { | ||
q = new Uri('?page=1&page=2').replaceQueryParam('page', 3, 1) | ||
expect(q.toString()).to.equal('?page=3&page=2') | ||
}) | ||
it('should be able to replace only a query param value with a specified string value', function() { | ||
q = new Uri('?a=one&a=two').replaceQueryParam('a', 'three', 'one') | ||
expect(q.toString()).to.equal('?a=three&a=two') | ||
}) | ||
it('should be able to replace a param value with a specified value that does not exist', function() { | ||
q = new Uri('?page=4&page=2').replaceQueryParam('page', 3, 1) | ||
expect(q.toString()).to.equal('?page=4&page=2') | ||
}) | ||
it('should replace a param value with an empty value if not provided a value', function() { | ||
q = new Uri('?page=4&page=2').replaceQueryParam('page') | ||
expect(q.toString()).to.equal('?page=') | ||
}) | ||
it('should be able to handle multiple values for the same key', function() { | ||
@@ -137,2 +185,12 @@ q = new Uri().addQueryParam('a', 1) | ||
}) | ||
it('should not add a trailing slash if one is already present', function () { | ||
q = new Uri('stuff/').addTrailingSlash(); | ||
expect(q.toString()).to.equal('stuff/') | ||
}) | ||
it('should add a trailing slash to an empty uri', function () { | ||
q = new Uri().addTrailingSlash(); | ||
expect(q.toString()).to.equal('/') | ||
}) | ||
}) | ||
@@ -139,0 +197,0 @@ |
62
Uri.js
@@ -23,3 +23,3 @@ /*! | ||
query_separator: /[&;]/, | ||
uri_parser: /^(?:(?![^:@]+:[^:@\/]*@)([^:\/?#.]+):)?(?:\/\/)?((?:(([^:@]*)(?::([^:@]*))?)?@)?([^:\/?#]*)(?::(\d*))?)(((\/(?:[^?#](?![^?#\/]*\.[^?#\/.]+(?:[?#]|$)))*\/?)?([^?#\/]*))(?:\?([^#]*))?(?:#(.*))?)/ | ||
uri_parser: /^(?:(?![^:@]+:[^:@\/]*@)([^:\/?#.]+):)?(?:\/\/)?((?:(([^:@\/]*)(?::([^:@]*))?)?@)?([^:\/?#]*)(?::(\d*))?)(((\/(?:[^?#](?![^?#\/]*\.[^?#\/.]+(?:[?#]|$)))*\/?)?([^?#\/]*))(?:\?([^#]*))?(?:#(.*))?)/ | ||
}; | ||
@@ -32,6 +32,30 @@ | ||
if (!Array.prototype.forEach) { | ||
Array.prototype.forEach = function(fn, scope) { | ||
for (var i = 0, len = this.length; i < len; ++i) { | ||
fn.call(scope || this, this[i], i, this); | ||
Array.prototype.forEach = function(callback, thisArg) { | ||
var T, k; | ||
if (this == null) { | ||
throw new TypeError(' this is null or not defined'); | ||
} | ||
var O = Object(this); | ||
var len = O.length >>> 0; | ||
if (typeof callback !== "function") { | ||
throw new TypeError(callback + ' is not a function'); | ||
} | ||
if (arguments.length > 1) { | ||
T = thisArg; | ||
} | ||
k = 0; | ||
while (k < len) { | ||
var kValue; | ||
if (k in O) { | ||
kValue = O[k]; | ||
callback.call(T, kValue, k, O); | ||
} | ||
k++; | ||
} | ||
}; | ||
@@ -90,3 +114,3 @@ } | ||
for (i = 0; i < ps.length; i++) { | ||
for (i = 0, l = ps.length; i < l; i++) { | ||
p = ps[i]; | ||
@@ -157,3 +181,3 @@ n = p.indexOf('='); | ||
for (i = 0; i < this.queryPairs.length; i++) { | ||
for (i = 0, l = this.queryPairs.length; i < l; i++) { | ||
param = this.queryPairs[i]; | ||
@@ -183,3 +207,3 @@ if (s.length > 0) { | ||
var param, i; | ||
for (i = 0; i < this.queryPairs.length; i++) { | ||
for (i = 0, l = this.queryPairs.length; i < l; i++) { | ||
param = this.queryPairs[i]; | ||
@@ -199,3 +223,3 @@ if (key === param[0]) { | ||
var arr = [], i, param; | ||
for (i = 0; i < this.queryPairs.length; i++) { | ||
for (i = 0, l = this.queryPairs.length; i < l; i++) { | ||
param = this.queryPairs[i]; | ||
@@ -218,3 +242,3 @@ if (key === param[0]) { | ||
for (i = 0; i < this.queryPairs.length; i++) { | ||
for (i = 0, l = this.queryPairs.length; i < l; i++) { | ||
@@ -260,6 +284,6 @@ param = this.queryPairs[i]; | ||
Uri.prototype.replaceQueryParam = function (key, newVal, oldVal) { | ||
var index = -1, i, param; | ||
var index = -1, len = this.queryPairs.length, i, param; | ||
if (arguments.length === 3) { | ||
for (i = 0; i < this.queryPairs.length; i++) { | ||
for (i = 0; i < len; i++) { | ||
param = this.queryPairs[i]; | ||
@@ -271,5 +295,7 @@ if (decode(param[0]) === decode(key) && decodeURIComponent(param[1]) === decode(oldVal)) { | ||
} | ||
this.deleteQueryParam(key, oldVal).addQueryParam(key, newVal, index); | ||
if (index >= 0) { | ||
this.deleteQueryParam(key, decode(oldVal)).addQueryParam(key, newVal, index); | ||
} | ||
} else { | ||
for (i = 0; i < this.queryPairs.length; i++) { | ||
for (i = 0; i < len; i++) { | ||
param = this.queryPairs[i]; | ||
@@ -328,2 +354,6 @@ if (decode(param[0]) === decode(key)) { | ||
if (s == 'file://') { | ||
return s + this.uriParts.authority; | ||
} | ||
if (this.userInfo() && this.host()) { | ||
@@ -350,10 +380,10 @@ s += this.userInfo(); | ||
Uri.prototype.addTrailingSlash = function() { | ||
var path = this.path() || '' | ||
var path = this.path() || ''; | ||
if (path.substr(-1) !== '/') { | ||
this.path(path + '/') | ||
this.path(path + '/'); | ||
} | ||
return this; | ||
} | ||
}; | ||
@@ -360,0 +390,0 @@ /** |
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
No v1
QualityPackage is not semver >=1. This means it is not stable and does not support ^ ranges.
Found 1 instance in 1 package
41062
904
0
125
0
12