UNPKG

4.21 kBJavaScriptView Raw
1var nodeUrl = require('url');
2var querystring = require('querystring');
3var _ = require('underscore');
4
5var UrlGrey = function(url){
6 this.url = url;
7 this._parsed = null;
8};
9
10UrlGrey.prototype.parsed = function(){
11 if (!this._parsed){
12 this._parsed = nodeUrl.parse(this.url);
13 var p = this._parsed;
14 if (p.protocol){
15 p.protocol = p.protocol.slice(0,-1);
16 } else {
17 p.protocol = 'http';
18 }
19 if (p.hash){
20 p.hash = p.hash.substring(1);
21 }
22 p.username = '';
23 p.password = '';
24 if (!p.hostname){
25 p.hostname = 'localhost';
26 }
27 if (!p.port){
28 p.port = 80;
29 } else {
30 p.port = parseInt(p.port, 10);
31 }
32 if (p.auth){
33 var auth = p.auth.split(':');
34 p.username = auth[0];
35 p.password = auth[1];
36 }
37 }
38 return this._parsed;
39};
40
41UrlGrey.prototype.query = function(mergeObject){
42 var path;
43 if (mergeObject === false){
44 // clear the query entirely if the input === false
45 return this.queryString('');
46 }
47
48 var url = this.url;
49 if (!mergeObject){
50 var parsed = nodeUrl.parse(url);
51 if (!!parsed.search){
52 var qstr = parsed.search.substring(1);
53 return querystring.parse(qstr);
54 }
55 return {};
56 } else {
57 // read the object out
58 var oldQuery = querystring.parse(this.queryString());
59 _.each(mergeObject, function(v, k){
60 if (v === null){
61 delete oldQuery[k];
62 } else {
63 oldQuery[k] = v;
64 }
65 });
66 var newString = querystring.stringify(oldQuery, '&', '=');
67 return this.queryString(newString);
68 }
69};
70
71
72addPropertyGetterSetter('protocol');
73addPropertyGetterSetter('port');
74addPropertyGetterSetter('username');
75addPropertyGetterSetter('password');
76addPropertyGetterSetter('hostname');
77addPropertyGetterSetter('hash');
78// add a method called queryString that manipulates 'query'
79addPropertyGetterSetter('query', 'queryString');
80addPropertyGetterSetter('pathname', 'path');
81
82UrlGrey.prototype.path = function(){
83 var args = _.toArray(arguments);
84 if (args.length !== 0){
85 var obj = new UrlGrey(this.toString());
86 var str = _.flatten(args).join('/');
87 str = str.replace(/\/+/g, '/'); // remove double slashes
88 str = str.replace(/\/$/, ''); // remove all trailing slashes
89 if (str[0] !== '/'){ str = '/' + str; }
90 obj.parsed().pathname = str;
91 return obj;
92 }
93 return this.parsed().pathname;
94};
95
96
97UrlGrey.prototype.encode = function(str){
98 return querystring.escape(str);
99};
100
101UrlGrey.prototype.decode = function(str){
102 return querystring.unescape(str);
103};
104
105UrlGrey.prototype.parent = function(){
106 // read-only. (can't SET parent)
107 var pieces = this.path().split("/");
108 var popped = pieces.pop();
109 if (popped === ''){ // ignore trailing slash
110 pieces.pop();
111 }
112 return this.path(pieces.join("/"));
113};
114
115UrlGrey.prototype.child = function(suffix){
116 if (suffix){
117 suffix = encodeURIComponent(suffix);
118 return this.path(this.path(), suffix);
119 } else {
120 // if no suffix, return the child
121 var pieces = this.path().split("/");
122 var last = _.last(pieces);
123 if ((pieces.length > 1) && (last === '')){
124 // ignore trailing slashes
125 pieces.pop();
126 last = _.last(pieces);
127 }
128 return last;
129 }
130};
131
132UrlGrey.prototype.toJSON = function(){
133 return this.toString();
134};
135
136UrlGrey.prototype.toString = function(){
137 var p = this.parsed();
138 var userinfo = p.username + ':' + p.password;
139 var retval = this.protocol() + '://';
140 if (userinfo != ':'){
141 retval += userinfo + '@';
142 }
143 retval += p.hostname;
144 if (this.port() !== 80){
145 retval += ':' + this.port();
146 }
147 retval += this.path() === '/' ? '' : this.path();
148 var qs = this.queryString();
149 if (qs){
150 retval += '?' + qs;
151 }
152 if (p.hash){
153 retval += '#' + p.hash;
154 }
155 return retval;
156};
157
158module.exports = function(url){ return new UrlGrey(url); };
159
160function addPropertyGetterSetter(propertyName, methodName){
161 if (!methodName){
162 methodName = propertyName;
163 }
164 UrlGrey.prototype[methodName] = function(str){
165 if (!!str || str === ''){
166 var obj = new UrlGrey(this.toString());
167 obj.parsed()[propertyName] = str;
168 return obj;
169 }
170 return this.parsed()[propertyName];
171 };
172}