Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/phabricator
Path: blob/master/webroot/rsrc/externals/javelin/lib/URI.js
12242 views
1
/**
2
* @provides javelin-uri
3
* @requires javelin-install
4
* javelin-util
5
* javelin-stratcom
6
*
7
* @javelin-installs JX.$U
8
*
9
* @javelin
10
*/
11
12
/**
13
* Handy convenience function that returns a @{class:JX.URI} instance. This
14
* allows you to write things like:
15
*
16
* JX.$U('http://zombo.com/').getDomain();
17
*
18
* @param string Unparsed URI.
19
* @return @{class:JX.URI} JX.URI instance.
20
*/
21
JX.$U = function(uri) {
22
return new JX.URI(uri);
23
};
24
25
/**
26
* Convert a string URI into a maleable object.
27
*
28
* var uri = new JX.URI('http://www.example.com/asdf.php?a=b&c=d#anchor123');
29
* uri.getProtocol(); // http
30
* uri.getDomain(); // www.example.com
31
* uri.getPath(); // /asdf.php
32
* uri.getQueryParams(); // {a: 'b', c: 'd'}
33
* uri.getFragment(); // anchor123
34
*
35
* ...and back into a string:
36
*
37
* uri.setFragment('clowntown');
38
* uri.toString() // http://www.example.com/asdf.php?a=b&c=d#clowntown
39
*/
40
JX.install('URI', {
41
statics : {
42
_uriPattern : /(?:([^:\/?#]+):)?(?:\/\/([^:\/?#]*)(?::(\d*))?)?([^?#]*)(?:\?([^#]*))?(?:#(.*))?/,
43
44
/**
45
* Convert a Javascript object into an HTTP query string.
46
*
47
* @param Object Map of query keys to values.
48
* @return String HTTP query string, like 'cow=quack&duck=moo'.
49
*/
50
_defaultQuerySerializer : function(obj) {
51
var kv_pairs = [];
52
for (var key in obj) {
53
if (obj[key] !== null) {
54
var value = encodeURIComponent(obj[key]);
55
kv_pairs.push(encodeURIComponent(key) + (value ? '=' + value : ''));
56
}
57
}
58
59
return kv_pairs.join('&');
60
},
61
62
_decode : function(str) {
63
return decodeURIComponent(str.replace(/\+/g, ' '));
64
}
65
},
66
67
/**
68
* Construct a URI
69
*
70
* Accepts either absolute or relative URIs. Relative URIs may have protocol
71
* and domain properties set to undefined
72
*
73
* @param string absolute or relative URI
74
*/
75
construct : function(uri) {
76
// need to set the default value here rather than in the properties map,
77
// or else we get some crazy global state breakage
78
this.setQueryParams({});
79
80
if (uri) {
81
// parse the url
82
var result = JX.URI._uriPattern.exec(uri);
83
84
// fallback to undefined because IE has weird behavior otherwise
85
this.setProtocol(result[1] || undefined);
86
this.setDomain(result[2] || undefined);
87
this.setPort(result[3] || undefined);
88
var path = result[4];
89
var query = result[5];
90
this.setFragment(result[6] || undefined);
91
92
// parse the path
93
this.setPath(path.charAt(0) == '/' ? path : '/' + path);
94
95
// parse the query data
96
if (query && query.length) {
97
var dict = {};
98
var parts = query.split('&');
99
for (var ii = 0; ii < parts.length; ii++) {
100
var part = parts[ii];
101
if (!part.length) {
102
continue;
103
}
104
var pieces = part.split('=');
105
var name = pieces[0];
106
if (!name.length) {
107
continue;
108
}
109
var value = pieces.slice(1).join('=') || '';
110
dict[JX.URI._decode(name)] = JX.URI._decode(value);
111
}
112
this.setQueryParams(dict);
113
}
114
}
115
},
116
117
properties : {
118
protocol: undefined,
119
port: undefined,
120
path: undefined,
121
queryParams: undefined,
122
fragment: undefined,
123
querySerializer: undefined
124
},
125
126
members : {
127
_domain: undefined,
128
129
/**
130
* Append and override query data values
131
* Remove a query key by setting it undefined
132
*
133
* @param map
134
* @return @{JX.URI} self
135
*/
136
addQueryParams : function(map) {
137
JX.copy(this.getQueryParams(), map);
138
return this;
139
},
140
141
/**
142
* Set a specific query parameter
143
* Remove a query key by setting it undefined
144
*
145
* @param string
146
* @param wild
147
* @return @{JX.URI} self
148
*/
149
setQueryParam : function(key, value) {
150
var map = {};
151
map[key] = value;
152
return this.addQueryParams(map);
153
},
154
155
/**
156
* Set the domain
157
*
158
* This function checks the domain name to ensure that it is safe for
159
* browser consumption.
160
*/
161
setDomain : function(domain) {
162
var re = new RegExp(
163
// For the bottom 128 code points, we use a strict whitelist of
164
// characters that are allowed by all browsers: -.0-9:A-Z[]_a-z
165
'[\\x00-\\x2c\\x2f\\x3b-\\x40\\x5c\\x5e\\x60\\x7b-\\x7f' +
166
// In IE, these chararacters cause problems when entity-encoded.
167
'\\uFDD0-\\uFDEF\\uFFF0-\\uFFFF' +
168
// In Safari, these characters terminate the hostname.
169
'\\u2047\\u2048\\uFE56\\uFE5F\\uFF03\\uFF0F\\uFF1F]');
170
if (re.test(domain)) {
171
JX.$E('JX.URI.setDomain(...): invalid domain specified.');
172
}
173
this._domain = domain;
174
return this;
175
},
176
177
getDomain : function() {
178
return this._domain;
179
},
180
181
getRelativeURI: function() {
182
return JX.$U(this.toString())
183
.setProtocol(null)
184
.setPort(null)
185
.setDomain(null)
186
.toString();
187
},
188
189
toString : function() {
190
if (__DEV__) {
191
if (this.getPath() && this.getPath().charAt(0) != '/') {
192
JX.$E(
193
'JX.URI.toString(): ' +
194
'Path does not begin with a "/" which means this URI will likely' +
195
'be malformed. Ensure any string passed to .setPath() leads "/"');
196
}
197
}
198
var str = '';
199
if (this.getProtocol()) {
200
str += this.getProtocol() + '://';
201
}
202
str += this.getDomain() || '';
203
204
if (this.getPort()) {
205
str += ':' + this.getPort();
206
}
207
208
// If there is a domain or a protocol, we need to provide '/' for the
209
// path. If we don't have either and also don't have a path, we can omit
210
// it to produce a partial URI without path information which begins
211
// with "?", "#", or is empty.
212
str += this.getPath() || (str ? '/' : '');
213
214
str += this._getQueryString();
215
if (this.getFragment()) {
216
str += '#' + this.getFragment();
217
}
218
return str;
219
},
220
221
_getQueryString : function() {
222
var str = (
223
this.getQuerySerializer() || JX.URI._defaultQuerySerializer
224
)(this.getQueryParams());
225
return str ? '?' + str : '';
226
},
227
228
/**
229
* Redirect the browser to another page by changing the window location. If
230
* the URI is empty, reloads the current page.
231
*
232
* You can install a Stratcom listener for the 'go' event if you need to log
233
* or prevent redirects.
234
*
235
* @return void
236
*/
237
go : function() {
238
var uri = this.toString();
239
if (JX.Stratcom.invoke('go', null, {uri: uri}).getPrevented()) {
240
return;
241
}
242
if (!uri) {
243
// window.location.reload clears cache in Firefox.
244
uri = window.location.pathname + (window.location.query || '');
245
}
246
window.location = uri;
247
}
248
249
}
250
});
251
252