uri-js-rails 1.7.4 → 1.10.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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
|
+
}));
|