1/* 2 * JQuery URL Parser plugin, v2.2.1 3 * Developed and maintanined by Mark Perkins, [email protected] 4 * Source repository: https://github.com/allmarkedup/jQuery-URL-Parser 5 * Licensed under an MIT-style license. See https://github.com/allmarkedup/jQuery-URL-Parser/blob/master/LICENSE for details. 6 */ 7 8;(function(factory) { 9 if (typeof define === 'function' && define.amd) { 10 // AMD available; use anonymous module 11 if ( typeof jQuery !== 'undefined' ) { 12 define(['jquery'], factory); 13 } else { 14 define([], factory); 15 } 16 } else { 17 // No AMD available; mutate global vars 18 if ( typeof jQuery !== 'undefined' ) { 19 factory(jQuery); 20 } else { 21 factory(); 22 } 23 } 24})(function($, undefined) { 25 26 var tag2attr = { 27 a : 'href', 28 img : 'src', 29 form : 'action', 30 base : 'href', 31 script : 'src', 32 iframe : 'src', 33 link : 'href' 34 }, 35 36 key = ['source', 'protocol', 'authority', 'userInfo', 'user', 'password', 'host', 'port', 'relative', 'path', 'directory', 'file', 'query', 'fragment'], // keys available to query 37 38 aliases = { 'anchor' : 'fragment' }, // aliases for backwards compatability 39 40 parser = { 41 strict : /^(?:([^:\/?#]+):)?(?:\/\/((?:(([^:@]*):?([^:@]*))?@)?([^:\/?#]*)(?::(\d*))?))?((((?:[^?#\/]*\/)*)([^?#]*))(?:\?([^#]*))?(?:#(.*))?)/, //less intuitive, more accurate to the specs 42 loose : /^(?:(?![^:@]+:[^:@\/]*@)([^:\/?#.]+):)?(?:\/\/)?((?:(([^:@]*):?([^:@]*))?@)?([^:\/?#]*)(?::(\d*))?)(((\/(?:[^?#](?![^?#\/]*\.[^?#\/.]+(?:[?#]|$)))*\/?)?([^?#\/]*))(?:\?([^#]*))?(?:#(.*))?)/ // more intuitive, fails on relative paths and deviates from specs 43 }, 44 45 toString = Object.prototype.toString, 46 47 isint = /^[0-9]+$/; 48 49 function parseUri( url, strictMode ) { 50 var str = decodeURI( url ), 51 res = parser[ strictMode || false ? 'strict' : 'loose' ].exec( str ), 52 uri = { attr : {}, param : {}, seg : {} }, 53 i = 14; 54 55 while ( i-- ) { 56 uri.attr[ key[i] ] = res[i] || ''; 57 } 58 59 // build query and fragment parameters 60 uri.param['query'] = parseString(uri.attr['query']); 61 uri.param['fragment'] = parseString(uri.attr['fragment']); 62 63 // split path and fragement into segments 64 uri.seg['path'] = uri.attr.path.replace(/^\/+|\/+$/g,'').split('/'); 65 uri.seg['fragment'] = uri.attr.fragment.replace(/^\/+|\/+$/g,'').split('/'); 66 67 // compile a 'base' domain attribute 68 uri.attr['base'] = uri.attr.host ? (uri.attr.protocol ? uri.attr.protocol+'://'+uri.attr.host : uri.attr.host) + (uri.attr.port ? ':'+uri.attr.port : '') : ''; 69 70 return uri; 71 }; 72 73 function getAttrName( elm ) { 74 var tn = elm.tagName; 75 if ( typeof tn !== 'undefined' ) return tag2attr[tn.toLowerCase()]; 76 return tn; 77 } 78 79 function promote(parent, key) { 80 if (parent[key].length == 0) return parent[key] = {}; 81 var t = {}; 82 for (var i in parent[key]) t[i] = parent[key][i]; 83 parent[key] = t; 84 return t; 85 } 86 87 function parse(parts, parent, key, val) { 88 var part = parts.shift(); 89 if (!part) { 90 if (isArray(parent[key])) { 91 parent[key].push(val); 92 } else if ('object' == typeof parent[key]) { 93 parent[key] = val; 94 } else if ('undefined' == typeof parent[key]) { 95 parent[key] = val; 96 } else { 97 parent[key] = [parent[key], val]; 98 } 99 } else { 100 var obj = parent[key] = parent[key] || []; 101 if (']' == part) { 102 if (isArray(obj)) { 103 if ('' != val) obj.push(val); 104 } else if ('object' == typeof obj) { 105 obj[keys(obj).length] = val; 106 } else { 107 obj = parent[key] = [parent[key], val]; 108 } 109 } else if (~part.indexOf(']')) { 110 part = part.substr(0, part.length - 1); 111 if (!isint.test(part) && isArray(obj)) obj = promote(parent, key); 112 parse(parts, obj, part, val); 113 // key 114 } else { 115 if (!isint.test(part) && isArray(obj)) obj = promote(parent, key); 116 parse(parts, obj, part, val); 117 } 118 } 119 } 120 121 function merge(parent, key, val) { 122 if (~key.indexOf(']')) { 123 var parts = key.split('['), 124 len = parts.length, 125 last = len - 1; 126 parse(parts, parent, 'base', val); 127 } else { 128 if (!isint.test(key) && isArray(parent.base)) { 129 var t = {}; 130 for (var k in parent.base) t[k] = parent.base[k]; 131 parent.base = t; 132 } 133 set(parent.base, key, val); 134 } 135 return parent; 136 } 137 138 function parseString(str) { 139 return reduce(String(str).split(/&|;/), function(ret, pair) { 140 try { 141 pair = decodeURIComponent(pair.replace(/\+/g, ' ')); 142 } catch(e) { 143 // ignore 144 } 145 var eql = pair.indexOf('='), 146 brace = lastBraceInKey(pair), 147 key = pair.substr(0, brace || eql), 148 val = pair.substr(brace || eql, pair.length), 149 val = val.substr(val.indexOf('=') + 1, val.length); 150 151 if ('' == key) key = pair, val = ''; 152 153 return merge(ret, key, val); 154 }, { base: {} }).base; 155 } 156 157 function set(obj, key, val) { 158 var v = obj[key]; 159 if (undefined === v) { 160 obj[key] = val; 161 } else if (isArray(v)) { 162 v.push(val); 163 } else { 164 obj[key] = [v, val]; 165 } 166 } 167 168 function lastBraceInKey(str) { 169 var len = str.length, 170 brace, c; 171 for (var i = 0; i < len; ++i) { 172 c = str[i]; 173 if (']' == c) brace = false;
174 if ('[' == c) brace = true; 175 if ('=' == c && !brace) return i; 176 } 177 } 178 179 function reduce(obj, accumulator){ 180 var i = 0, 181 l = obj.length >> 0, 182 curr = arguments[2]; 183 while (i < l) { 184 if (i in obj) curr = accumulator.call(undefined, curr, obj[i], i, obj); 185 ++i; 186 } 187 return curr; 188 } 189 190 function isArray(vArg) { 191 return Object.prototype.toString.call(vArg) === "[object Array]"; 192 } 193 194 function keys(obj) { 195 var keys = []; 196 for ( prop in obj ) { 197 if ( obj.hasOwnProperty(prop) ) keys.push(prop); 198 } 199 return keys; 200 } 201 202 function purl( url, strictMode ) { 203 if ( arguments.length === 1 && url === true ) { 204 strictMode = true; 205 url = undefined; 206 } 207 strictMode = strictMode || false; 208 url = url || window.location.toString(); 209 210 return { 211 212 data : parseUri(url, strictMode), 213 214 // get various attributes from the URI 215 attr : function( attr ) { 216 attr = aliases[attr] || attr; 217 return typeof attr !== 'undefined' ? this.data.attr[attr] : this.data.attr; 218 }, 219 220 // return query string parameters 221 param : function( param ) { 222 return typeof param !== 'undefined' ? this.data.param.query[param] : this.data.param.query; 223 }, 224 225 // return fragment parameters 226 fparam : function( param ) { 227 return typeof param !== 'undefined' ? this.data.param.fragment[param] : this.data.param.fragment; 228 }, 229 230 // return path segments 231 segment : function( seg ) { 232 if ( typeof seg === 'undefined' ) { 233 return this.data.seg.path; 234 } else { 235 seg = seg < 0 ? this.data.seg.path.length + seg : seg - 1; // negative segments count from the end 236 return this.data.seg.path[seg]; 237 } 238 }, 239 240 // return fragment segments 241 fsegment : function( seg ) { 242 if ( typeof seg === 'undefined' ) { 243 return this.data.seg.fragment; 244 } else { 245 seg = seg < 0 ? this.data.seg.fragment.length + seg : seg - 1; // negative segments count from the end 246 return this.data.seg.fragment[seg]; 247 } 248 } 249 250 }; 251 252 }; 253 254 if ( typeof $ !== 'undefined' ) { 255 256 $.fn.url = function( strictMode ) { 257 var url = ''; 258 if ( this.length ) { 259 url = $(this).attr( getAttrName(this[0]) ) || ''; 260 } 261 return purl( url, strictMode ); 262 }; 263 264 $.url = purl; 265 266 } else { 267 window.purl = purl; 268 } 269 270}); 271
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.