uri-js-rails 1.7.4 → 1.10.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/README.md +1 -1
- data/lib/uri-js-rails/version.rb +1 -1
- data/vendor/assets/javascripts/URI.js +455 -238
- data/vendor/assets/javascripts/jquery.URI.js +117 -87
- metadata +7 -9
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 2a7679fe260f287fbf4cd1b2e7343099c24d65db
|
4
|
+
data.tar.gz: 840a0a784bea3cf14f18bf2e713413d68f855b01
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 6096b252b722dd13466b81cbea3f59a386ddac30d7c7d478ee1d1a1df0bb5ad16b55829673bb765ac2f16dae1636f15202fa066d03b2db678f9a942d0f780ecc
|
7
|
+
data.tar.gz: bfecfe90b7073d03073724c1f9eae3dbb5f8f9b5b68bc555c2eafdd8a49f29536e54f8843483724b829001d35e38038a0a3c7e519321a9b4563d7f2d8ee1edd3
|
data/README.md
CHANGED
data/lib/uri-js-rails/version.rb
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
/*!
|
2
2
|
* URI.js - Mutating URLs
|
3
3
|
*
|
4
|
-
* Version: 1.
|
4
|
+
* Version: 1.10.2
|
5
5
|
*
|
6
6
|
* Author: Rodney Rehm
|
7
7
|
* Web: http://medialize.github.com/URI.js/
|
@@ -11,53 +11,64 @@
|
|
11
11
|
* GPL v3 http://opensource.org/licenses/GPL-3.0
|
12
12
|
*
|
13
13
|
*/
|
14
|
+
(function (root, factory) {
|
15
|
+
// https://github.com/umdjs/umd/blob/master/returnExports.js
|
16
|
+
if (typeof exports === 'object') {
|
17
|
+
// Node
|
18
|
+
module.exports = factory(require('./punycode'), require('./IPv6'), require('./SecondLevelDomains'));
|
19
|
+
} else if (typeof define === 'function' && define.amd) {
|
20
|
+
// AMD. Register as an anonymous module.
|
21
|
+
define(['./punycode', './IPv6', './SecondLevelDomains'], factory);
|
22
|
+
} else {
|
23
|
+
// Browser globals (root is window)
|
24
|
+
root.URI = factory(root.punycode, root.IPv6, root.SecondLevelDomains);
|
25
|
+
}
|
26
|
+
}(this, function (punycode, IPv6, SLD) {
|
27
|
+
"use strict";
|
14
28
|
|
15
|
-
|
29
|
+
function URI(url, base) {
|
30
|
+
// Allow instantiation without the 'new' keyword
|
31
|
+
if (!(this instanceof URI)) {
|
32
|
+
return new URI(url, base);
|
33
|
+
}
|
16
34
|
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
IPv6 = _load_module('IPv6'),
|
23
|
-
SLD = _load_module('SecondLevelDomains'),
|
24
|
-
URI = function(url, base) {
|
25
|
-
// Allow instantiation without the 'new' keyword
|
26
|
-
if (!(this instanceof URI)) {
|
27
|
-
return new URI(url, base);
|
28
|
-
}
|
29
|
-
|
30
|
-
if (url === undefined) {
|
31
|
-
if (typeof location !== 'undefined') {
|
32
|
-
url = location.href + "";
|
33
|
-
} else {
|
34
|
-
url = "";
|
35
|
-
}
|
35
|
+
if (url === undefined) {
|
36
|
+
if (typeof location !== 'undefined') {
|
37
|
+
url = location.href + "";
|
38
|
+
} else {
|
39
|
+
url = "";
|
36
40
|
}
|
41
|
+
}
|
37
42
|
|
38
|
-
|
43
|
+
this.href(url);
|
39
44
|
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
45
|
+
// resolve to base according to http://dvcs.w3.org/hg/url/raw-file/tip/Overview.html#constructor
|
46
|
+
if (base !== undefined) {
|
47
|
+
return this.absoluteTo(base);
|
48
|
+
}
|
44
49
|
|
45
|
-
|
46
|
-
|
47
|
-
|
50
|
+
return this;
|
51
|
+
};
|
52
|
+
|
53
|
+
var p = URI.prototype;
|
54
|
+
var hasOwn = Object.prototype.hasOwnProperty;
|
48
55
|
|
49
56
|
function escapeRegEx(string) {
|
50
57
|
// https://github.com/medialize/URI.js/commit/85ac21783c11f8ccab06106dba9735a31a86924d#commitcomment-821963
|
51
58
|
return string.replace(/([.*+?^=!:${}()|[\]\/\\])/g, '\\$1');
|
52
59
|
}
|
53
60
|
|
61
|
+
function getType(value) {
|
62
|
+
return String(Object.prototype.toString.call(value)).slice(8, -1);
|
63
|
+
}
|
64
|
+
|
54
65
|
function isArray(obj) {
|
55
|
-
return
|
66
|
+
return getType(obj) === "Array";
|
56
67
|
}
|
57
68
|
|
58
69
|
function filterArrayValues(data, value) {
|
59
|
-
var lookup = {}
|
60
|
-
|
70
|
+
var lookup = {};
|
71
|
+
var i, length;
|
61
72
|
|
62
73
|
if (isArray(value)) {
|
63
74
|
for (i = 0, length = value.length; i < length; i++) {
|
@@ -78,6 +89,74 @@ function filterArrayValues(data, value) {
|
|
78
89
|
return data;
|
79
90
|
}
|
80
91
|
|
92
|
+
function arrayContains(list, value) {
|
93
|
+
var i, length;
|
94
|
+
|
95
|
+
// value may be string, number, array, regexp
|
96
|
+
if (isArray(value)) {
|
97
|
+
// Note: this can be optimized to O(n) (instead of current O(m * n))
|
98
|
+
for (i = 0, length = value.length; i < length; i++) {
|
99
|
+
if (!arrayContains(list, value[i])) {
|
100
|
+
return false;
|
101
|
+
}
|
102
|
+
}
|
103
|
+
|
104
|
+
return true;
|
105
|
+
}
|
106
|
+
|
107
|
+
var _type = getType(value);
|
108
|
+
for (i = 0, length = list.length; i < length; i++) {
|
109
|
+
if (_type === 'RegExp') {
|
110
|
+
if (typeof list[i] === 'string' && list[i].match(value)) {
|
111
|
+
return true;
|
112
|
+
}
|
113
|
+
} else if (list[i] === value) {
|
114
|
+
return true;
|
115
|
+
}
|
116
|
+
}
|
117
|
+
|
118
|
+
return false;
|
119
|
+
}
|
120
|
+
|
121
|
+
function arraysEqual(one, two) {
|
122
|
+
if (!isArray(one) || !isArray(two)) {
|
123
|
+
return false;
|
124
|
+
}
|
125
|
+
|
126
|
+
// arrays can't be equal if they have different amount of content
|
127
|
+
if (one.length !== two.length) {
|
128
|
+
return false;
|
129
|
+
}
|
130
|
+
|
131
|
+
one.sort();
|
132
|
+
two.sort();
|
133
|
+
|
134
|
+
for (var i = 0, l = one.length; i < l; i++) {
|
135
|
+
if (one[i] !== two[i]) {
|
136
|
+
return false;
|
137
|
+
}
|
138
|
+
}
|
139
|
+
|
140
|
+
return true;
|
141
|
+
}
|
142
|
+
|
143
|
+
URI._parts = function() {
|
144
|
+
return {
|
145
|
+
protocol: null,
|
146
|
+
username: null,
|
147
|
+
password: null,
|
148
|
+
hostname: null,
|
149
|
+
urn: null,
|
150
|
+
port: null,
|
151
|
+
path: null,
|
152
|
+
query: null,
|
153
|
+
fragment: null,
|
154
|
+
// state
|
155
|
+
duplicateQueryParameters: URI.duplicateQueryParameters
|
156
|
+
};
|
157
|
+
};
|
158
|
+
// state: allow duplicate query parameters (a=1&a=1)
|
159
|
+
URI.duplicateQueryParameters = false;
|
81
160
|
// static properties
|
82
161
|
URI.protocol_expression = /^[a-z][a-z0-9-+-]*$/i;
|
83
162
|
URI.idn_expression = /[^a-z0-9\.-]/i;
|
@@ -87,7 +166,7 @@ URI.ip4_expression = /^\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}$/;
|
|
87
166
|
// credits to Rich Brown
|
88
167
|
// source: http://forums.intermapper.com/viewtopic.php?p=1096#1096
|
89
168
|
// specification: http://www.ietf.org/rfc/rfc4291.txt
|
90
|
-
URI.ip6_expression = /^\s*((([0-9A-Fa-f]{1,4}:){7}([0-9A-Fa-f]{1,4}|:))|(([0-9A-Fa-f]{1,4}:){6}(:[0-9A-Fa-f]{1,4}|((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3})|:))|(([0-9A-Fa-f]{1,4}:){5}(((:[0-9A-Fa-f]{1,4}){1,2})|:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3})|:))|(([0-9A-Fa-f]{1,4}:){4}(((:[0-9A-Fa-f]{1,4}){1,3})|((:[0-9A-Fa-f]{1,4})?:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){3}(((:[0-9A-Fa-f]{1,4}){1,4})|((:[0-9A-Fa-f]{1,4}){0,2}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){2}(((:[0-9A-Fa-f]{1,4}){1,5})|((:[0-9A-Fa-f]{1,4}){0,3}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){1}(((:[0-9A-Fa-f]{1,4}){1,6})|((:[0-9A-Fa-f]{1,4}){0,4}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(:(((:[0-9A-Fa-f]{1,4}){1,7})|((:[0-9A-Fa-f]{1,4}){0,5}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:)))(%.+)?\s
|
169
|
+
URI.ip6_expression = /^\s*((([0-9A-Fa-f]{1,4}:){7}([0-9A-Fa-f]{1,4}|:))|(([0-9A-Fa-f]{1,4}:){6}(:[0-9A-Fa-f]{1,4}|((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3})|:))|(([0-9A-Fa-f]{1,4}:){5}(((:[0-9A-Fa-f]{1,4}){1,2})|:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3})|:))|(([0-9A-Fa-f]{1,4}:){4}(((:[0-9A-Fa-f]{1,4}){1,3})|((:[0-9A-Fa-f]{1,4})?:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){3}(((:[0-9A-Fa-f]{1,4}){1,4})|((:[0-9A-Fa-f]{1,4}){0,2}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){2}(((:[0-9A-Fa-f]{1,4}){1,5})|((:[0-9A-Fa-f]{1,4}){0,3}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){1}(((:[0-9A-Fa-f]{1,4}){1,6})|((:[0-9A-Fa-f]{1,4}){0,4}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(:(((:[0-9A-Fa-f]{1,4}){1,7})|((:[0-9A-Fa-f]{1,4}){0,5}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:)))(%.+)?\s*$/;
|
91
170
|
// gruber revised expression - http://rodneyrehm.de/t/url-regex.html
|
92
171
|
URI.find_uri_expression = /\b((?:[a-z][\w-]+:(?:\/{1,3}|[a-z0-9%])|www\d{0,3}[.]|[a-z0-9.\-]+[.][a-z]{2,4}\/)(?:[^\s()<>]+|\(([^\s()<>]+|(\([^\s()<>]+\)))*\))+(?:\(([^\s()<>]+|(\([^\s()<>]+\)))*\)|[^\s`!()\[\]{};:'".,<>?«»“”‘’]))/ig;
|
93
172
|
// http://www.iana.org/assignments/uri-schemes.html
|
@@ -95,7 +174,10 @@ URI.find_uri_expression = /\b((?:[a-z][\w-]+:(?:\/{1,3}|[a-z0-9%])|www\d{0,3}[.]
|
|
95
174
|
URI.defaultPorts = {
|
96
175
|
http: "80",
|
97
176
|
https: "443",
|
98
|
-
ftp: "21"
|
177
|
+
ftp: "21",
|
178
|
+
gopher: "70",
|
179
|
+
ws: "80",
|
180
|
+
wss: "443"
|
99
181
|
};
|
100
182
|
// allowed hostname characters according to RFC 3986
|
101
183
|
// ALPHA DIGIT "-" "." "_" "~" "!" "$" "&" "'" "(" ")" "*" "+" "," ";" "=" %encoded
|
@@ -198,15 +280,15 @@ URI.decodePath = function(string) {
|
|
198
280
|
return segments.join('/');
|
199
281
|
};
|
200
282
|
// generate encode/decode path functions
|
201
|
-
var _parts = {'encode':'encode', 'decode':'decode'}
|
202
|
-
|
203
|
-
|
204
|
-
|
205
|
-
|
206
|
-
|
207
|
-
|
208
|
-
};
|
283
|
+
var _parts = {'encode':'encode', 'decode':'decode'};
|
284
|
+
var _part;
|
285
|
+
var generateAccessor = function(_group, _part) {
|
286
|
+
return function(string) {
|
287
|
+
return URI[_part](string + "").replace(URI.characters[_group][_part].expression, function(c) {
|
288
|
+
return URI.characters[_group][_part].map[c];
|
289
|
+
});
|
209
290
|
};
|
291
|
+
};
|
210
292
|
|
211
293
|
for (_part in _parts) {
|
212
294
|
URI[_part + "PathSegment"] = generateAccessor("pathname", _parts[_part]);
|
@@ -214,8 +296,11 @@ for (_part in _parts) {
|
|
214
296
|
|
215
297
|
URI.encodeReserved = generateAccessor("reserved", "encode");
|
216
298
|
|
217
|
-
URI.parse = function(string) {
|
218
|
-
var pos, t
|
299
|
+
URI.parse = function(string, parts) {
|
300
|
+
var pos, t;
|
301
|
+
if (!parts) {
|
302
|
+
parts = {};
|
303
|
+
}
|
219
304
|
// [protocol"://"[username[":"password]"@"]hostname[":"port]"/"?][path]["?"querystring]["#"fragment]
|
220
305
|
|
221
306
|
// extract fragment
|
@@ -248,6 +333,9 @@ URI.parse = function(string) {
|
|
248
333
|
if (parts.protocol && !parts.protocol.match(URI.protocol_expression)) {
|
249
334
|
// : may be within the path
|
250
335
|
parts.protocol = undefined;
|
336
|
+
} else if (parts.protocol === 'file') {
|
337
|
+
// the file scheme: does not contain an authority
|
338
|
+
string = string.substring(pos + 3);
|
251
339
|
} else if (string.substring(pos + 1, pos + 3) === '//') {
|
252
340
|
string = string.substring(pos + 3);
|
253
341
|
|
@@ -268,18 +356,19 @@ URI.parse = function(string) {
|
|
268
356
|
};
|
269
357
|
URI.parseHost = function(string, parts) {
|
270
358
|
// extract host:port
|
271
|
-
var pos = string.indexOf('/')
|
272
|
-
|
359
|
+
var pos = string.indexOf('/');
|
360
|
+
var bracketPos;
|
361
|
+
var t;
|
273
362
|
|
274
363
|
if (pos === -1) {
|
275
364
|
pos = string.length;
|
276
365
|
}
|
277
366
|
|
278
|
-
if (string
|
367
|
+
if (string.charAt(0) === "[") {
|
279
368
|
// IPv6 host - http://tools.ietf.org/html/draft-ietf-6man-text-addr-representation-04#section-6
|
280
369
|
// I claim most client software breaks on IPv6 anyways. To simplify things, URI only accepts
|
281
370
|
// IPv6+port in the format [2001:db8::1]:80 (for the time being)
|
282
|
-
|
371
|
+
bracketPos = string.indexOf(']');
|
283
372
|
parts.hostname = string.substring(1, bracketPos) || null;
|
284
373
|
parts.port = string.substring(bracketPos+2, pos) || null;
|
285
374
|
} else if (string.indexOf(':') !== string.lastIndexOf(':')) {
|
@@ -293,7 +382,7 @@ URI.parseHost = function(string, parts) {
|
|
293
382
|
parts.port = t[1] || null;
|
294
383
|
}
|
295
384
|
|
296
|
-
if (parts.hostname && string.substring(pos)
|
385
|
+
if (parts.hostname && string.substring(pos).charAt(0) !== '/') {
|
297
386
|
pos++;
|
298
387
|
string = "/" + string;
|
299
388
|
}
|
@@ -306,15 +395,16 @@ URI.parseAuthority = function(string, parts) {
|
|
306
395
|
};
|
307
396
|
URI.parseUserinfo = function(string, parts) {
|
308
397
|
// extract username:password
|
309
|
-
var pos = string.indexOf('@')
|
310
|
-
|
311
|
-
|
398
|
+
var pos = string.indexOf('@');
|
399
|
+
var firstSlash = string.indexOf('/');
|
400
|
+
var t;
|
312
401
|
|
313
402
|
// authority@ must come before /path
|
314
403
|
if (pos > -1 && (firstSlash === -1 || pos < firstSlash)) {
|
315
404
|
t = string.substring(0, pos).split(':');
|
316
405
|
parts.username = t[0] ? URI.decode(t[0]) : null;
|
317
|
-
|
406
|
+
t.shift();
|
407
|
+
parts.password = t[0] ? URI.decode(t.join(':')) : null;
|
318
408
|
string = string.substring(pos + 1);
|
319
409
|
} else {
|
320
410
|
parts.username = null;
|
@@ -335,15 +425,16 @@ URI.parseQuery = function(string) {
|
|
335
425
|
return {};
|
336
426
|
}
|
337
427
|
|
338
|
-
var items = {}
|
339
|
-
|
340
|
-
|
428
|
+
var items = {};
|
429
|
+
var splits = string.split('&');
|
430
|
+
var length = splits.length;
|
431
|
+
var v, name, value;
|
341
432
|
|
342
433
|
for (var i = 0; i < length; i++) {
|
343
|
-
|
344
|
-
|
345
|
-
|
346
|
-
|
434
|
+
v = splits[i].split('=');
|
435
|
+
name = URI.decodeQuery(v.shift());
|
436
|
+
// no "=" is null according to http://dvcs.w3.org/hg/url/raw-file/tip/Overview.html#collect-url-parameters
|
437
|
+
value = v.length ? URI.decodeQuery(v.join('=')) : null;
|
347
438
|
|
348
439
|
if (items[name]) {
|
349
440
|
if (typeof items[name] === "string") {
|
@@ -360,7 +451,7 @@ URI.parseQuery = function(string) {
|
|
360
451
|
};
|
361
452
|
|
362
453
|
URI.build = function(parts) {
|
363
|
-
var t =
|
454
|
+
var t = "";
|
364
455
|
|
365
456
|
if (parts.protocol) {
|
366
457
|
t += parts.protocol + ":";
|
@@ -373,27 +464,27 @@ URI.build = function(parts) {
|
|
373
464
|
t += (URI.buildAuthority(parts) || '');
|
374
465
|
|
375
466
|
if (typeof parts.path === "string") {
|
376
|
-
if (parts.path
|
467
|
+
if (parts.path.charAt(0) !== '/' && typeof parts.hostname === "string") {
|
377
468
|
t += '/';
|
378
469
|
}
|
379
470
|
|
380
471
|
t += parts.path;
|
381
472
|
}
|
382
473
|
|
383
|
-
if (typeof parts.query === "string") {
|
474
|
+
if (typeof parts.query === "string" && parts.query) {
|
384
475
|
t += '?' + parts.query;
|
385
476
|
}
|
386
477
|
|
387
|
-
if (typeof parts.fragment === "string") {
|
478
|
+
if (typeof parts.fragment === "string" && parts.fragment) {
|
388
479
|
t += '#' + parts.fragment;
|
389
480
|
}
|
390
481
|
return t;
|
391
482
|
};
|
392
483
|
URI.buildHost = function(parts) {
|
393
|
-
var t =
|
484
|
+
var t = "";
|
394
485
|
|
395
486
|
if (!parts.hostname) {
|
396
|
-
return
|
487
|
+
return "";
|
397
488
|
} else if (URI.ip6_expression.test(parts.hostname)) {
|
398
489
|
if (parts.port) {
|
399
490
|
t += "[" + parts.hostname + "]:" + parts.port;
|
@@ -415,7 +506,7 @@ URI.buildAuthority = function(parts) {
|
|
415
506
|
return URI.buildUserinfo(parts) + URI.buildHost(parts);
|
416
507
|
};
|
417
508
|
URI.buildUserinfo = function(parts) {
|
418
|
-
var t =
|
509
|
+
var t = "";
|
419
510
|
|
420
511
|
if (parts.username) {
|
421
512
|
t += URI.encode(parts.username);
|
@@ -437,11 +528,12 @@ URI.buildQuery = function(data, duplicates) {
|
|
437
528
|
// see http://www.w3.org/TR/REC-html40/interact/forms.html#form-content-type
|
438
529
|
|
439
530
|
var t = "";
|
440
|
-
|
441
|
-
|
531
|
+
var unique, key, i, length;
|
532
|
+
for (key in data) {
|
533
|
+
if (hasOwn.call(data, key) && key) {
|
442
534
|
if (isArray(data[key])) {
|
443
|
-
|
444
|
-
for (
|
535
|
+
unique = {};
|
536
|
+
for (i = 0, length = data[key].length; i < length; i++) {
|
445
537
|
if (data[key][i] !== undefined && unique[data[key][i] + ""] === undefined) {
|
446
538
|
t += "&" + URI.buildQueryParameter(key, data[key][i]);
|
447
539
|
if (duplicates !== true) {
|
@@ -466,7 +558,7 @@ URI.buildQueryParameter = function(name, value) {
|
|
466
558
|
URI.addQuery = function(data, name, value) {
|
467
559
|
if (typeof name === "object") {
|
468
560
|
for (var key in name) {
|
469
|
-
if (
|
561
|
+
if (hasOwn.call(name, key)) {
|
470
562
|
URI.addQuery(data, key, name[key]);
|
471
563
|
}
|
472
564
|
}
|
@@ -488,13 +580,15 @@ URI.addQuery = function(data, name, value) {
|
|
488
580
|
}
|
489
581
|
};
|
490
582
|
URI.removeQuery = function(data, name, value) {
|
583
|
+
var i, length, key;
|
584
|
+
|
491
585
|
if (isArray(name)) {
|
492
|
-
for (
|
586
|
+
for (i = 0, length = name.length; i < length; i++) {
|
493
587
|
data[name[i]] = undefined;
|
494
588
|
}
|
495
589
|
} else if (typeof name === "object") {
|
496
|
-
for (
|
497
|
-
if (
|
590
|
+
for (key in name) {
|
591
|
+
if (hasOwn.call(name, key)) {
|
498
592
|
URI.removeQuery(data, key, name[key]);
|
499
593
|
}
|
500
594
|
}
|
@@ -512,25 +606,92 @@ URI.removeQuery = function(data, name, value) {
|
|
512
606
|
throw new TypeError("URI.addQuery() accepts an object, string as the first parameter");
|
513
607
|
}
|
514
608
|
};
|
609
|
+
URI.hasQuery = function(data, name, value, withinArray) {
|
610
|
+
if (typeof name === "object") {
|
611
|
+
for (var key in name) {
|
612
|
+
if (hasOwn.call(name, key)) {
|
613
|
+
if (!URI.hasQuery(data, key, name[key])) {
|
614
|
+
return false;
|
615
|
+
}
|
616
|
+
}
|
617
|
+
}
|
618
|
+
|
619
|
+
return true;
|
620
|
+
} else if (typeof name !== "string") {
|
621
|
+
throw new TypeError("URI.hasQuery() accepts an object, string as the name parameter");
|
622
|
+
}
|
623
|
+
|
624
|
+
switch (getType(value)) {
|
625
|
+
case 'Undefined':
|
626
|
+
// true if exists (but may be empty)
|
627
|
+
return name in data; // data[name] !== undefined;
|
628
|
+
|
629
|
+
case 'Boolean':
|
630
|
+
// true if exists and non-empty
|
631
|
+
var _booly = Boolean(isArray(data[name]) ? data[name].length : data[name]);
|
632
|
+
return value === _booly;
|
633
|
+
|
634
|
+
case 'Function':
|
635
|
+
// allow complex comparison
|
636
|
+
return !!value(data[name], name, data);
|
637
|
+
|
638
|
+
case 'Array':
|
639
|
+
if (!isArray(data[name])) {
|
640
|
+
return false;
|
641
|
+
}
|
642
|
+
|
643
|
+
var op = withinArray ? arrayContains : arraysEqual;
|
644
|
+
return op(data[name], value);
|
645
|
+
|
646
|
+
case 'RegExp':
|
647
|
+
if (!isArray(data[name])) {
|
648
|
+
return Boolean(data[name] && data[name].match(value));
|
649
|
+
}
|
650
|
+
|
651
|
+
if (!withinArray) {
|
652
|
+
return false;
|
653
|
+
}
|
654
|
+
|
655
|
+
return arrayContains(data[name], value);
|
656
|
+
|
657
|
+
case 'Number':
|
658
|
+
value = String(value);
|
659
|
+
// omit break;
|
660
|
+
case 'String':
|
661
|
+
if (!isArray(data[name])) {
|
662
|
+
return data[name] === value;
|
663
|
+
}
|
664
|
+
|
665
|
+
if (!withinArray) {
|
666
|
+
return false;
|
667
|
+
}
|
668
|
+
|
669
|
+
return arrayContains(data[name], value);
|
670
|
+
|
671
|
+
default:
|
672
|
+
throw new TypeError("URI.hasQuery() accepts undefined, boolean, string, number, RegExp, Function as the value parameter");
|
673
|
+
}
|
674
|
+
};
|
675
|
+
|
515
676
|
|
516
677
|
URI.commonPath = function(one, two) {
|
517
|
-
var length = Math.min(one.length, two.length)
|
518
|
-
|
678
|
+
var length = Math.min(one.length, two.length);
|
679
|
+
var pos;
|
519
680
|
|
520
681
|
// find first non-matching character
|
521
682
|
for (pos = 0; pos < length; pos++) {
|
522
|
-
if (one
|
683
|
+
if (one.charAt(pos) !== two.charAt(pos)) {
|
523
684
|
pos--;
|
524
685
|
break;
|
525
686
|
}
|
526
687
|
}
|
527
688
|
|
528
689
|
if (pos < 1) {
|
529
|
-
return one
|
690
|
+
return one.charAt(0) === two.charAt(0) && one.charAt(0) === '/' ? '/' : '';
|
530
691
|
}
|
531
|
-
|
692
|
+
|
532
693
|
// revert to last /
|
533
|
-
if (one
|
694
|
+
if (one.charAt(pos) !== '/' || two.charAt(pos) !== '/') {
|
534
695
|
pos = one.substring(0, pos).lastIndexOf('/');
|
535
696
|
}
|
536
697
|
|
@@ -577,12 +738,9 @@ p.clone = function() {
|
|
577
738
|
return new URI(this);
|
578
739
|
};
|
579
740
|
|
580
|
-
p.toString = function() {
|
741
|
+
p.valueOf = p.toString = function() {
|
581
742
|
return this.build(false)._string;
|
582
743
|
};
|
583
|
-
p.valueOf = function() {
|
584
|
-
return this.toString();
|
585
|
-
};
|
586
744
|
|
587
745
|
// generate simple accessors
|
588
746
|
_parts = {protocol: 'protocol', username: 'username', password: 'password', hostname: 'hostname', port: 'port'};
|
@@ -598,7 +756,7 @@ generateAccessor = function(_part){
|
|
598
756
|
};
|
599
757
|
};
|
600
758
|
|
601
|
-
for (_part in _parts) {
|
759
|
+
for (_part in _parts) {
|
602
760
|
p[_part] = generateAccessor(_parts[_part]);
|
603
761
|
}
|
604
762
|
|
@@ -611,7 +769,7 @@ generateAccessor = function(_part, _key){
|
|
611
769
|
} else {
|
612
770
|
if (v !== null) {
|
613
771
|
v = v + "";
|
614
|
-
if (v
|
772
|
+
if (v.charAt(0) === _key) {
|
615
773
|
v = v.substring(1);
|
616
774
|
}
|
617
775
|
}
|
@@ -652,54 +810,57 @@ p.pathname = function(v, build) {
|
|
652
810
|
};
|
653
811
|
p.path = p.pathname;
|
654
812
|
p.href = function(href, build) {
|
813
|
+
var key;
|
814
|
+
|
655
815
|
if (href === undefined) {
|
656
816
|
return this.toString();
|
657
|
-
}
|
658
|
-
|
659
|
-
|
660
|
-
|
661
|
-
|
662
|
-
|
663
|
-
|
664
|
-
|
665
|
-
|
666
|
-
|
667
|
-
|
668
|
-
|
669
|
-
|
670
|
-
|
671
|
-
|
672
|
-
|
673
|
-
|
674
|
-
|
675
|
-
|
676
|
-
|
677
|
-
|
678
|
-
|
679
|
-
|
680
|
-
|
681
|
-
|
682
|
-
|
817
|
+
}
|
818
|
+
|
819
|
+
this._string = "";
|
820
|
+
this._parts = URI._parts();
|
821
|
+
|
822
|
+
var _URI = href instanceof URI;
|
823
|
+
var _object = typeof href === "object" && (href.hostname || href.path);
|
824
|
+
|
825
|
+
|
826
|
+
// window.location is reported to be an object, but it's not the sort
|
827
|
+
// of object we're looking for:
|
828
|
+
// * location.protocol ends with a colon
|
829
|
+
// * location.query != object.search
|
830
|
+
// * location.hash != object.fragment
|
831
|
+
// simply serializing the unknown object should do the trick
|
832
|
+
// (for location, not for everything...)
|
833
|
+
if (!_URI && _object && href.pathname !== undefined) {
|
834
|
+
href = href.toString();
|
835
|
+
}
|
836
|
+
|
837
|
+
if (typeof href === "string") {
|
838
|
+
this._parts = URI.parse(href, this._parts);
|
839
|
+
} else if (_URI || _object) {
|
840
|
+
var src = _URI ? href._parts : href;
|
841
|
+
for (key in src) {
|
842
|
+
if (hasOwn.call(this._parts, key)) {
|
843
|
+
this._parts[key] = src[key];
|
683
844
|
}
|
684
|
-
} else {
|
685
|
-
throw new TypeError("invalid input");
|
686
845
|
}
|
687
|
-
|
688
|
-
|
689
|
-
return this;
|
846
|
+
} else {
|
847
|
+
throw new TypeError("invalid input");
|
690
848
|
}
|
849
|
+
|
850
|
+
this.build(!build);
|
851
|
+
return this;
|
691
852
|
};
|
692
853
|
|
693
854
|
// identification accessors
|
694
855
|
p.is = function(what) {
|
695
|
-
var ip = false
|
696
|
-
|
697
|
-
|
698
|
-
|
699
|
-
|
700
|
-
|
701
|
-
|
702
|
-
|
856
|
+
var ip = false;
|
857
|
+
var ip4 = false;
|
858
|
+
var ip6 = false;
|
859
|
+
var name = false;
|
860
|
+
var sld = false;
|
861
|
+
var idn = false;
|
862
|
+
var punycode = false;
|
863
|
+
var relative = !this._parts.urn;
|
703
864
|
|
704
865
|
if (this._parts.hostname) {
|
705
866
|
relative = false;
|
@@ -757,9 +918,9 @@ p.is = function(what) {
|
|
757
918
|
};
|
758
919
|
|
759
920
|
// component specific input validation
|
760
|
-
var _protocol = p.protocol
|
761
|
-
|
762
|
-
|
921
|
+
var _protocol = p.protocol;
|
922
|
+
var _port = p.port;
|
923
|
+
var _hostname = p.hostname;
|
763
924
|
|
764
925
|
p.protocol = function(v, build) {
|
765
926
|
if (v !== undefined) {
|
@@ -787,7 +948,7 @@ p.port = function(v, build) {
|
|
787
948
|
|
788
949
|
if (v) {
|
789
950
|
v += "";
|
790
|
-
if (v
|
951
|
+
if (v.charAt(0) === ":") {
|
791
952
|
v = v.substring(1);
|
792
953
|
}
|
793
954
|
|
@@ -811,7 +972,7 @@ p.hostname = function(v, build) {
|
|
811
972
|
return _hostname.call(this, v, build);
|
812
973
|
};
|
813
974
|
|
814
|
-
//
|
975
|
+
// compound accessors
|
815
976
|
p.host = function(v, build) {
|
816
977
|
if (this._parts.urn) {
|
817
978
|
return v === undefined ? '' : this;
|
@@ -860,6 +1021,20 @@ p.userinfo = function(v, build) {
|
|
860
1021
|
return this;
|
861
1022
|
}
|
862
1023
|
};
|
1024
|
+
p.resource = function(v, build) {
|
1025
|
+
var parts;
|
1026
|
+
|
1027
|
+
if (v === undefined) {
|
1028
|
+
return this.path() + this.search() + this.hash();
|
1029
|
+
}
|
1030
|
+
|
1031
|
+
parts = URI.parse(v);
|
1032
|
+
this._parts.path = parts.path;
|
1033
|
+
this._parts.query = parts.query;
|
1034
|
+
this._parts.fragment = parts.fragment;
|
1035
|
+
this.build(!build);
|
1036
|
+
return this;
|
1037
|
+
};
|
863
1038
|
|
864
1039
|
// fraction accessors
|
865
1040
|
p.subdomain = function(v, build) {
|
@@ -877,11 +1052,11 @@ p.subdomain = function(v, build) {
|
|
877
1052
|
var end = this._parts.hostname.length - this.domain().length - 1;
|
878
1053
|
return this._parts.hostname.substring(0, end) || "";
|
879
1054
|
} else {
|
880
|
-
var e = this._parts.hostname.length - this.domain().length
|
881
|
-
|
882
|
-
|
1055
|
+
var e = this._parts.hostname.length - this.domain().length;
|
1056
|
+
var sub = this._parts.hostname.substring(0, e);
|
1057
|
+
var replace = new RegExp('^' + escapeRegEx(sub));
|
883
1058
|
|
884
|
-
if (v && v
|
1059
|
+
if (v && v.charAt(v.length - 1) !== '.') {
|
885
1060
|
v += ".";
|
886
1061
|
}
|
887
1062
|
|
@@ -954,8 +1129,8 @@ p.tld = function(v, build) {
|
|
954
1129
|
return "";
|
955
1130
|
}
|
956
1131
|
|
957
|
-
var pos = this._parts.hostname.lastIndexOf('.')
|
958
|
-
|
1132
|
+
var pos = this._parts.hostname.lastIndexOf('.');
|
1133
|
+
var tld = this._parts.hostname.substring(pos + 1);
|
959
1134
|
|
960
1135
|
if (build !== true && SLD && SLD.list[tld.toLowerCase()]) {
|
961
1136
|
return SLD.get(this._parts.hostname) || tld;
|
@@ -964,6 +1139,7 @@ p.tld = function(v, build) {
|
|
964
1139
|
return tld;
|
965
1140
|
} else {
|
966
1141
|
var replace;
|
1142
|
+
|
967
1143
|
if (!v) {
|
968
1144
|
throw new TypeError("cannot set TLD empty");
|
969
1145
|
} else if (v.match(/[^a-zA-Z0-9-]/)) {
|
@@ -998,15 +1174,15 @@ p.directory = function(v, build) {
|
|
998
1174
|
return '/';
|
999
1175
|
}
|
1000
1176
|
|
1001
|
-
var end = this._parts.path.length - this.filename().length - 1
|
1002
|
-
|
1177
|
+
var end = this._parts.path.length - this.filename().length - 1;
|
1178
|
+
var res = this._parts.path.substring(0, end) || (this._parts.hostname ? "/" : "");
|
1003
1179
|
|
1004
1180
|
return v ? URI.decodePath(res) : res;
|
1005
1181
|
|
1006
1182
|
} else {
|
1007
|
-
var e = this._parts.path.length - this.filename().length
|
1008
|
-
|
1009
|
-
|
1183
|
+
var e = this._parts.path.length - this.filename().length;
|
1184
|
+
var directory = this._parts.path.substring(0, e);
|
1185
|
+
var replace = new RegExp('^' + escapeRegEx(directory));
|
1010
1186
|
|
1011
1187
|
// fully qualifier directories begin with a slash
|
1012
1188
|
if (!this.is('relative')) {
|
@@ -1014,13 +1190,13 @@ p.directory = function(v, build) {
|
|
1014
1190
|
v = '/';
|
1015
1191
|
}
|
1016
1192
|
|
1017
|
-
if (v
|
1193
|
+
if (v.charAt(0) !== '/') {
|
1018
1194
|
v = "/" + v;
|
1019
1195
|
}
|
1020
1196
|
}
|
1021
1197
|
|
1022
1198
|
// directories always end with a slash
|
1023
|
-
if (v && v
|
1199
|
+
if (v && v.charAt(v.length - 1) !== '/') {
|
1024
1200
|
v += '/';
|
1025
1201
|
}
|
1026
1202
|
|
@@ -1040,13 +1216,14 @@ p.filename = function(v, build) {
|
|
1040
1216
|
return "";
|
1041
1217
|
}
|
1042
1218
|
|
1043
|
-
var pos = this._parts.path.lastIndexOf('/')
|
1044
|
-
|
1219
|
+
var pos = this._parts.path.lastIndexOf('/');
|
1220
|
+
var res = this._parts.path.substring(pos+1);
|
1045
1221
|
|
1046
1222
|
return v ? URI.decodePathSegment(res) : res;
|
1047
1223
|
} else {
|
1048
1224
|
var mutatedDirectory = false;
|
1049
|
-
|
1225
|
+
|
1226
|
+
if (v.charAt(0) === '/') {
|
1050
1227
|
v = v.substring(1);
|
1051
1228
|
}
|
1052
1229
|
|
@@ -1077,9 +1254,9 @@ p.suffix = function(v, build) {
|
|
1077
1254
|
return "";
|
1078
1255
|
}
|
1079
1256
|
|
1080
|
-
var filename = this.filename()
|
1081
|
-
|
1082
|
-
|
1257
|
+
var filename = this.filename();
|
1258
|
+
var pos = filename.lastIndexOf('.');
|
1259
|
+
var s, res;
|
1083
1260
|
|
1084
1261
|
if (pos === -1) {
|
1085
1262
|
return "";
|
@@ -1090,12 +1267,12 @@ p.suffix = function(v, build) {
|
|
1090
1267
|
res = (/^[a-z0-9%]+$/i).test(s) ? s : "";
|
1091
1268
|
return v ? URI.decodePathSegment(res) : res;
|
1092
1269
|
} else {
|
1093
|
-
if (v
|
1270
|
+
if (v.charAt(0) === '.') {
|
1094
1271
|
v = v.substring(1);
|
1095
1272
|
}
|
1096
1273
|
|
1097
|
-
var suffix = this.suffix()
|
1098
|
-
|
1274
|
+
var suffix = this.suffix();
|
1275
|
+
var replace;
|
1099
1276
|
|
1100
1277
|
if (!suffix) {
|
1101
1278
|
if (!v) {
|
@@ -1119,10 +1296,10 @@ p.suffix = function(v, build) {
|
|
1119
1296
|
}
|
1120
1297
|
};
|
1121
1298
|
p.segment = function(segment, v, build) {
|
1122
|
-
var separator = this._parts.urn ? ':' : '/'
|
1123
|
-
|
1124
|
-
|
1125
|
-
|
1299
|
+
var separator = this._parts.urn ? ':' : '/';
|
1300
|
+
var path = this.path();
|
1301
|
+
var absolute = path.substring(0, 1) === '/';
|
1302
|
+
var segments = path.split(separator);
|
1126
1303
|
|
1127
1304
|
if (typeof segment !== 'number') {
|
1128
1305
|
build = v;
|
@@ -1179,18 +1356,47 @@ var q = p.query;
|
|
1179
1356
|
p.query = function(v, build) {
|
1180
1357
|
if (v === true) {
|
1181
1358
|
return URI.parseQuery(this._parts.query);
|
1359
|
+
} else if (typeof v === "function") {
|
1360
|
+
var data = URI.parseQuery(this._parts.query);
|
1361
|
+
var result = v.call(this, data);
|
1362
|
+
this._parts.query = URI.buildQuery(result || data, this._parts.duplicateQueryParameters);
|
1363
|
+
this.build(!build);
|
1364
|
+
return this;
|
1182
1365
|
} else if (v !== undefined && typeof v !== "string") {
|
1183
|
-
this._parts.query = URI.buildQuery(v);
|
1366
|
+
this._parts.query = URI.buildQuery(v, this._parts.duplicateQueryParameters);
|
1184
1367
|
this.build(!build);
|
1185
1368
|
return this;
|
1186
1369
|
} else {
|
1187
1370
|
return q.call(this, v, build);
|
1188
1371
|
}
|
1189
1372
|
};
|
1373
|
+
p.setQuery = function(name, value, build) {
|
1374
|
+
var data = URI.parseQuery(this._parts.query);
|
1375
|
+
|
1376
|
+
if (typeof name === "object") {
|
1377
|
+
for (var key in name) {
|
1378
|
+
if (hasOwn.call(name, key)) {
|
1379
|
+
data[key] = name[key];
|
1380
|
+
}
|
1381
|
+
}
|
1382
|
+
} else if (typeof name === "string") {
|
1383
|
+
data[name] = value !== undefined ? value : null;
|
1384
|
+
} else {
|
1385
|
+
throw new TypeError("URI.addQuery() accepts an object, string as the name parameter");
|
1386
|
+
}
|
1387
|
+
|
1388
|
+
this._parts.query = URI.buildQuery(data, this._parts.duplicateQueryParameters);
|
1389
|
+
if (typeof name !== "string") {
|
1390
|
+
build = value;
|
1391
|
+
}
|
1392
|
+
|
1393
|
+
this.build(!build);
|
1394
|
+
return this;
|
1395
|
+
};
|
1190
1396
|
p.addQuery = function(name, value, build) {
|
1191
1397
|
var data = URI.parseQuery(this._parts.query);
|
1192
|
-
URI.addQuery(data, name, value);
|
1193
|
-
this._parts.query = URI.buildQuery(data);
|
1398
|
+
URI.addQuery(data, name, value === undefined ? null : value);
|
1399
|
+
this._parts.query = URI.buildQuery(data, this._parts.duplicateQueryParameters);
|
1194
1400
|
if (typeof name !== "string") {
|
1195
1401
|
build = value;
|
1196
1402
|
}
|
@@ -1201,7 +1407,7 @@ p.addQuery = function(name, value, build) {
|
|
1201
1407
|
p.removeQuery = function(name, value, build) {
|
1202
1408
|
var data = URI.parseQuery(this._parts.query);
|
1203
1409
|
URI.removeQuery(data, name, value);
|
1204
|
-
this._parts.query = URI.buildQuery(data);
|
1410
|
+
this._parts.query = URI.buildQuery(data, this._parts.duplicateQueryParameters);
|
1205
1411
|
if (typeof name !== "string") {
|
1206
1412
|
build = value;
|
1207
1413
|
}
|
@@ -1209,8 +1415,14 @@ p.removeQuery = function(name, value, build) {
|
|
1209
1415
|
this.build(!build);
|
1210
1416
|
return this;
|
1211
1417
|
};
|
1418
|
+
p.hasQuery = function(name, value, withinArray) {
|
1419
|
+
var data = URI.parseQuery(this._parts.query);
|
1420
|
+
return URI.hasQuery(data, name, value, withinArray);
|
1421
|
+
};
|
1422
|
+
p.setSearch = p.setQuery;
|
1212
1423
|
p.addSearch = p.addQuery;
|
1213
1424
|
p.removeSearch = p.removeQuery;
|
1425
|
+
p.hasSearch = p.hasQuery;
|
1214
1426
|
|
1215
1427
|
// sanitizing URLs
|
1216
1428
|
p.normalize = function() {
|
@@ -1271,14 +1483,14 @@ p.normalizePath = function(build) {
|
|
1271
1483
|
return this;
|
1272
1484
|
}
|
1273
1485
|
|
1274
|
-
var _was_relative
|
1275
|
-
|
1276
|
-
|
1277
|
-
|
1486
|
+
var _was_relative;
|
1487
|
+
var _was_relative_prefix;
|
1488
|
+
var _path = this._parts.path;
|
1489
|
+
var _parent, _pos;
|
1278
1490
|
|
1279
1491
|
// handle relative paths
|
1280
|
-
if (_path
|
1281
|
-
if (_path
|
1492
|
+
if (_path.charAt(0) !== '/') {
|
1493
|
+
if (_path.charAt(0) === '.') {
|
1282
1494
|
_was_relative_prefix = _path.substring(0, _path.indexOf('/'));
|
1283
1495
|
}
|
1284
1496
|
_was_relative = true;
|
@@ -1306,11 +1518,7 @@ p.normalizePath = function(build) {
|
|
1306
1518
|
}
|
1307
1519
|
// revert to relative
|
1308
1520
|
if (_was_relative && this.is('relative')) {
|
1309
|
-
|
1310
|
-
_path = _was_relative_prefix + _path;
|
1311
|
-
} else {
|
1312
|
-
_path = _path.substring(1);
|
1313
|
-
}
|
1521
|
+
_path = _path.substring(1);
|
1314
1522
|
}
|
1315
1523
|
|
1316
1524
|
_path = URI.recodePath(_path);
|
@@ -1345,8 +1553,8 @@ p.normalizeHash = p.normalizeFragment;
|
|
1345
1553
|
|
1346
1554
|
p.iso8859 = function() {
|
1347
1555
|
// expect unicode input, iso8859 output
|
1348
|
-
var e = URI.encode
|
1349
|
-
|
1556
|
+
var e = URI.encode;
|
1557
|
+
var d = URI.decode;
|
1350
1558
|
|
1351
1559
|
URI.encode = escape;
|
1352
1560
|
URI.decode = decodeURIComponent;
|
@@ -1358,8 +1566,8 @@ p.iso8859 = function() {
|
|
1358
1566
|
|
1359
1567
|
p.unicode = function() {
|
1360
1568
|
// expect iso8859 input, unicode output
|
1361
|
-
var e = URI.encode
|
1362
|
-
|
1569
|
+
var e = URI.encode;
|
1570
|
+
var d = URI.decode;
|
1363
1571
|
|
1364
1572
|
URI.encode = strictEncodeURIComponent;
|
1365
1573
|
URI.decode = unescape;
|
@@ -1389,7 +1597,7 @@ p.readable = function() {
|
|
1389
1597
|
}
|
1390
1598
|
}
|
1391
1599
|
|
1392
|
-
if (uri._parts.hostname && uri._parts.path && uri._parts.path
|
1600
|
+
if (uri._parts.hostname && uri._parts.path && uri._parts.path.charAt(0) !== '/') {
|
1393
1601
|
t += '/';
|
1394
1602
|
}
|
1395
1603
|
|
@@ -1415,21 +1623,25 @@ p.readable = function() {
|
|
1415
1623
|
|
1416
1624
|
// resolving relative and absolute URLs
|
1417
1625
|
p.absoluteTo = function(base) {
|
1418
|
-
var resolved = this.clone()
|
1419
|
-
|
1420
|
-
|
1626
|
+
var resolved = this.clone();
|
1627
|
+
var properties = ['protocol', 'username', 'password', 'hostname', 'port'];
|
1628
|
+
var basedir, i, p;
|
1421
1629
|
|
1422
1630
|
if (this._parts.urn) {
|
1423
1631
|
throw new Error('URNs do not have any generally defined hierachical components');
|
1424
1632
|
}
|
1425
1633
|
|
1426
|
-
if (this._parts.hostname) {
|
1427
|
-
return resolved;
|
1428
|
-
}
|
1429
|
-
|
1430
1634
|
if (!(base instanceof URI)) {
|
1431
1635
|
base = new URI(base);
|
1432
1636
|
}
|
1637
|
+
|
1638
|
+
if (!resolved._parts.protocol) {
|
1639
|
+
resolved._parts.protocol = base._parts.protocol;
|
1640
|
+
}
|
1641
|
+
|
1642
|
+
if (this._parts.hostname) {
|
1643
|
+
return resolved;
|
1644
|
+
}
|
1433
1645
|
|
1434
1646
|
for (i = 0, p; p = properties[i]; i++) {
|
1435
1647
|
resolved._parts[p] = base._parts[p];
|
@@ -1442,7 +1654,7 @@ p.absoluteTo = function(base) {
|
|
1442
1654
|
}
|
1443
1655
|
}
|
1444
1656
|
|
1445
|
-
if (resolved.path()
|
1657
|
+
if (resolved.path().charAt(0) !== '/') {
|
1446
1658
|
basedir = base.directory();
|
1447
1659
|
resolved._parts.path = (basedir ? (basedir + '/') : '') + resolved._parts.path;
|
1448
1660
|
resolved.normalizePath();
|
@@ -1452,12 +1664,11 @@ p.absoluteTo = function(base) {
|
|
1452
1664
|
return resolved;
|
1453
1665
|
};
|
1454
1666
|
p.relativeTo = function(base) {
|
1455
|
-
var relative = this.clone()
|
1456
|
-
|
1457
|
-
|
1458
|
-
_base;
|
1667
|
+
var relative = this.clone();
|
1668
|
+
var properties = ['protocol', 'username', 'password', 'hostname', 'port'];
|
1669
|
+
var common, _base, _this, _base_diff, _this_diff;
|
1459
1670
|
|
1460
|
-
if (
|
1671
|
+
if (relative._parts.urn) {
|
1461
1672
|
throw new Error('URNs do not have any generally defined hierachical components');
|
1462
1673
|
}
|
1463
1674
|
|
@@ -1465,49 +1676,69 @@ p.relativeTo = function(base) {
|
|
1465
1676
|
base = new URI(base);
|
1466
1677
|
}
|
1467
1678
|
|
1468
|
-
if (
|
1679
|
+
if (relative.path().charAt(0) !== '/' || base.path().charAt(0) !== '/') {
|
1469
1680
|
throw new Error('Cannot calculate common path from non-relative URLs');
|
1470
1681
|
}
|
1471
1682
|
|
1683
|
+
// determine common sub path
|
1472
1684
|
common = URI.commonPath(relative.path(), base.path());
|
1473
|
-
|
1474
|
-
|
1685
|
+
|
1686
|
+
// relative paths don't have authority
|
1475
1687
|
for (var i = 0, p; p = properties[i]; i++) {
|
1476
1688
|
relative._parts[p] = null;
|
1477
1689
|
}
|
1478
1690
|
|
1479
|
-
if
|
1691
|
+
// no relation if there's nothing in common
|
1692
|
+
if (common === '/') {
|
1480
1693
|
return relative;
|
1694
|
+
} else if (!common) {
|
1695
|
+
// there's absolutely nothing in common here
|
1696
|
+
return this.clone();
|
1481
1697
|
}
|
1698
|
+
|
1699
|
+
_base = base.directory();
|
1700
|
+
_this = relative.directory();
|
1482
1701
|
|
1702
|
+
// base and this are on the same level
|
1703
|
+
if (_base === _this) {
|
1704
|
+
relative._parts.path = relative.filename();
|
1705
|
+
return relative.build();
|
1706
|
+
}
|
1707
|
+
|
1708
|
+
_base_diff = _base.substring(common.length);
|
1709
|
+
_this_diff = _this.substring(common.length);
|
1710
|
+
|
1711
|
+
// this is a descendant of base
|
1483
1712
|
if (_base + '/' === common) {
|
1484
|
-
|
1485
|
-
|
1486
|
-
var parents = '../',
|
1487
|
-
_common = new RegExp('^' + escapeRegEx(common)),
|
1488
|
-
_parents = _base.replace(_common, '/').match(/\//g).length -1;
|
1489
|
-
|
1490
|
-
while (_parents--) {
|
1491
|
-
parents += '../';
|
1713
|
+
if (_this_diff) {
|
1714
|
+
_this_diff += '/';
|
1492
1715
|
}
|
1716
|
+
|
1717
|
+
relative._parts.path = _this_diff + relative.filename();
|
1718
|
+
return relative.build();
|
1719
|
+
}
|
1720
|
+
|
1721
|
+
// this is a descendant of base
|
1722
|
+
var parents = '../';
|
1723
|
+
var _common = new RegExp('^' + escapeRegEx(common));
|
1724
|
+
var _parents = _base.replace(_common, '/').match(/\//g).length -1;
|
1493
1725
|
|
1494
|
-
|
1726
|
+
while (_parents--) {
|
1727
|
+
parents += '../';
|
1495
1728
|
}
|
1496
1729
|
|
1497
|
-
relative.
|
1498
|
-
return relative;
|
1730
|
+
relative._parts.path = relative._parts.path.replace(_common, parents);
|
1731
|
+
return relative.build();
|
1499
1732
|
};
|
1500
1733
|
|
1501
1734
|
// comparing URIs
|
1502
1735
|
p.equals = function(uri) {
|
1503
|
-
var one = this.clone()
|
1504
|
-
|
1505
|
-
|
1506
|
-
|
1507
|
-
|
1508
|
-
|
1509
|
-
two_query,
|
1510
|
-
key;
|
1736
|
+
var one = this.clone();
|
1737
|
+
var two = new URI(uri);
|
1738
|
+
var one_map = {};
|
1739
|
+
var two_map = {};
|
1740
|
+
var checked = {};
|
1741
|
+
var one_query, two_query, key;
|
1511
1742
|
|
1512
1743
|
one.normalize();
|
1513
1744
|
two.normalize();
|
@@ -1537,29 +1768,13 @@ p.equals = function(uri) {
|
|
1537
1768
|
two_map = URI.parseQuery(two_query);
|
1538
1769
|
|
1539
1770
|
for (key in one_map) {
|
1540
|
-
if (
|
1771
|
+
if (hasOwn.call(one_map, key)) {
|
1541
1772
|
if (!isArray(one_map[key])) {
|
1542
1773
|
if (one_map[key] !== two_map[key]) {
|
1543
1774
|
return false;
|
1544
1775
|
}
|
1545
|
-
} else {
|
1546
|
-
|
1547
|
-
return false;
|
1548
|
-
}
|
1549
|
-
|
1550
|
-
// arrays can't be equal if they have different amount of content
|
1551
|
-
if (one_map[key].length !== two_map[key].length) {
|
1552
|
-
return false;
|
1553
|
-
}
|
1554
|
-
|
1555
|
-
one_map[key].sort();
|
1556
|
-
two_map[key].sort();
|
1557
|
-
|
1558
|
-
for (var i = 0, l = one_map[key].length; i < l; i++) {
|
1559
|
-
if (one_map[key][i] !== two_map[key][i]) {
|
1560
|
-
return false;
|
1561
|
-
}
|
1562
|
-
}
|
1776
|
+
} else if (!arraysEqual(one_map[key], two_map[key])) {
|
1777
|
+
return false;
|
1563
1778
|
}
|
1564
1779
|
|
1565
1780
|
checked[key] = true;
|
@@ -1567,7 +1782,7 @@ p.equals = function(uri) {
|
|
1567
1782
|
}
|
1568
1783
|
|
1569
1784
|
for (key in two_map) {
|
1570
|
-
if (
|
1785
|
+
if (hasOwn.call(two_map, key)) {
|
1571
1786
|
if (!checked[key]) {
|
1572
1787
|
// two contains a parameter not present in one
|
1573
1788
|
return false;
|
@@ -1578,9 +1793,11 @@ p.equals = function(uri) {
|
|
1578
1793
|
return true;
|
1579
1794
|
};
|
1580
1795
|
|
1581
|
-
|
1582
|
-
|
1583
|
-
|
1584
|
-
|
1796
|
+
// state
|
1797
|
+
p.duplicateQueryParameters = function(v) {
|
1798
|
+
this._parts.duplicateQueryParameters = !!v;
|
1799
|
+
return this;
|
1800
|
+
};
|
1585
1801
|
|
1586
|
-
|
1802
|
+
return URI;
|
1803
|
+
}));
|