| 
									
										
										
										
											2015-12-05 02:21:38 -08:00
										 |  |  | import {Injectable, Inject} from 'angular2/src/core/di'; | 
					
						
							|  |  |  | import { | 
					
						
							|  |  |  |   StringWrapper, | 
					
						
							|  |  |  |   isPresent, | 
					
						
							|  |  |  |   isBlank, | 
					
						
							|  |  |  |   RegExpWrapper, | 
					
						
							|  |  |  |   normalizeBlank | 
					
						
							|  |  |  | } from 'angular2/src/facade/lang'; | 
					
						
							| 
									
										
										
										
											2015-11-06 17:34:07 -08:00
										 |  |  | import {BaseException, WrappedException} from 'angular2/src/facade/exceptions'; | 
					
						
							|  |  |  | import {ListWrapper} from 'angular2/src/facade/collection'; | 
					
						
							| 
									
										
										
										
											2015-12-05 02:21:38 -08:00
										 |  |  | import {PACKAGE_ROOT_URL} from 'angular2/src/core/application_tokens'; | 
					
						
							|  |  |  | import {Provider} from 'angular2/src/core/di'; | 
					
						
							| 
									
										
										
										
											2015-02-20 18:00:09 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-10-15 16:03:23 -07:00
										 |  |  | export function createWithoutPackagePrefix(): UrlResolver { | 
					
						
							|  |  |  |   return new UrlResolver(); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-12-05 02:21:38 -08:00
										 |  |  | export var DEFAULT_PACKAGE_URL_PROVIDER = new Provider(PACKAGE_ROOT_URL, {useValue: "/"}); | 
					
						
							| 
									
										
										
										
											2015-10-15 16:03:23 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-07-07 08:15:58 +02:00
										 |  |  | /** | 
					
						
							|  |  |  |  * Used by the {@link Compiler} when resolving HTML and CSS template URLs. | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * This interface can be overridden by the application developer to create custom behavior. | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * See {@link Compiler} | 
					
						
							|  |  |  |  */ | 
					
						
							| 
									
										
										
										
											2015-03-16 14:44:14 -07:00
										 |  |  | @Injectable() | 
					
						
							| 
									
										
										
										
											2015-02-20 18:00:09 +01:00
										 |  |  | export class UrlResolver { | 
					
						
							| 
									
										
										
										
											2015-12-05 02:21:38 -08:00
										 |  |  |   private _packagePrefix: string; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   constructor(@Inject(PACKAGE_ROOT_URL) packagePrefix: string = null) { | 
					
						
							|  |  |  |     if (isPresent(packagePrefix)) { | 
					
						
							|  |  |  |       this._packagePrefix = StringWrapper.stripRight(packagePrefix, "/") + "/"; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-05-13 09:28:42 +02:00
										 |  |  |   /** | 
					
						
							| 
									
										
										
										
											2015-06-23 11:28:06 +02:00
										 |  |  |    * Resolves the `url` given the `baseUrl`: | 
					
						
							| 
									
										
										
										
											2015-05-13 09:28:42 +02:00
										 |  |  |    * - when the `url` is null, the `baseUrl` is returned, | 
					
						
							| 
									
										
										
										
											2015-05-18 11:57:20 -07:00
										 |  |  |    * - if `url` is relative ('path/to/here', './path/to/here'), the resolved url is a combination of | 
					
						
							|  |  |  |    * `baseUrl` and `url`, | 
					
						
							| 
									
										
										
										
											2015-06-23 12:05:09 +02:00
										 |  |  |    * - if `url` is absolute (it has a scheme: 'http://', 'https://' or start with '/'), the `url` is | 
					
						
							|  |  |  |    * returned as is (ignoring the `baseUrl`) | 
					
						
							| 
									
										
										
										
											2015-05-13 09:28:42 +02:00
										 |  |  |    * | 
					
						
							|  |  |  |    * @param {string} baseUrl | 
					
						
							|  |  |  |    * @param {string} url | 
					
						
							|  |  |  |    * @returns {string} the resolved URL | 
					
						
							|  |  |  |    */ | 
					
						
							| 
									
										
										
										
											2015-12-05 02:21:38 -08:00
										 |  |  |   resolve(baseUrl: string, url: string): string { | 
					
						
							|  |  |  |     var resolvedUrl = url; | 
					
						
							|  |  |  |     if (isPresent(baseUrl) && baseUrl.length > 0) { | 
					
						
							|  |  |  |       resolvedUrl = _resolveUrl(baseUrl, resolvedUrl); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     if (isPresent(this._packagePrefix) && getUrlScheme(resolvedUrl) == "package") { | 
					
						
							|  |  |  |       resolvedUrl = resolvedUrl.replace("package:", this._packagePrefix); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     return resolvedUrl; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | export function getUrlScheme(url: string): string { | 
					
						
							|  |  |  |   var match = _split(url); | 
					
						
							|  |  |  |   return (match && match[_ComponentIndex.Scheme]) || ""; | 
					
						
							| 
									
										
										
										
											2015-06-23 12:05:09 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // The code below is adapted from Traceur:
 | 
					
						
							|  |  |  | // https://github.com/google/traceur-compiler/blob/9511c1dafa972bf0de1202a8a863bad02f0f95a8/src/runtime/url.js
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /** | 
					
						
							|  |  |  |  * Builds a URI string from already-encoded parts. | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * No encoding is performed.  Any component may be omitted as either null or | 
					
						
							|  |  |  |  * undefined. | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * @param {?string=} opt_scheme The scheme such as 'http'. | 
					
						
							|  |  |  |  * @param {?string=} opt_userInfo The user name before the '@'. | 
					
						
							|  |  |  |  * @param {?string=} opt_domain The domain such as 'www.google.com', already | 
					
						
							|  |  |  |  *     URI-encoded. | 
					
						
							|  |  |  |  * @param {(string|null)=} opt_port The port number. | 
					
						
							|  |  |  |  * @param {?string=} opt_path The path, already URI-encoded.  If it is not | 
					
						
							|  |  |  |  *     empty, it must begin with a slash. | 
					
						
							|  |  |  |  * @param {?string=} opt_queryData The URI-encoded query data. | 
					
						
							|  |  |  |  * @param {?string=} opt_fragment The URI-encoded fragment identifier. | 
					
						
							|  |  |  |  * @return {string} The fully combined URI. | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | function _buildFromEncodedParts(opt_scheme?: string, opt_userInfo?: string, opt_domain?: string, | 
					
						
							|  |  |  |                                 opt_port?: string, opt_path?: string, opt_queryData?: string, | 
					
						
							|  |  |  |                                 opt_fragment?: string): string { | 
					
						
							|  |  |  |   var out = []; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   if (isPresent(opt_scheme)) { | 
					
						
							|  |  |  |     out.push(opt_scheme + ':'); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   if (isPresent(opt_domain)) { | 
					
						
							|  |  |  |     out.push('//'); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (isPresent(opt_userInfo)) { | 
					
						
							|  |  |  |       out.push(opt_userInfo + '@'); | 
					
						
							| 
									
										
										
										
											2015-02-20 18:00:09 +01:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-06-23 12:05:09 +02:00
										 |  |  |     out.push(opt_domain); | 
					
						
							| 
									
										
										
										
											2015-02-20 18:00:09 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-06-23 12:05:09 +02:00
										 |  |  |     if (isPresent(opt_port)) { | 
					
						
							|  |  |  |       out.push(':' + opt_port); | 
					
						
							| 
									
										
										
										
											2015-02-20 18:00:09 +01:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2015-06-23 12:05:09 +02:00
										 |  |  |   } | 
					
						
							| 
									
										
										
										
											2015-02-20 18:00:09 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-06-23 12:05:09 +02:00
										 |  |  |   if (isPresent(opt_path)) { | 
					
						
							|  |  |  |     out.push(opt_path); | 
					
						
							| 
									
										
										
										
											2015-02-20 18:00:09 +01:00
										 |  |  |   } | 
					
						
							| 
									
										
										
										
											2015-06-23 12:05:09 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |   if (isPresent(opt_queryData)) { | 
					
						
							|  |  |  |     out.push('?' + opt_queryData); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   if (isPresent(opt_fragment)) { | 
					
						
							|  |  |  |     out.push('#' + opt_fragment); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   return out.join(''); | 
					
						
							| 
									
										
										
										
											2015-02-20 18:00:09 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-06-23 12:05:09 +02:00
										 |  |  | /** | 
					
						
							|  |  |  |  * A regular expression for breaking a URI into its component parts. | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * {@link http://www.gbiv.com/protocols/uri/rfc/rfc3986.html#RFC2234} says
 | 
					
						
							|  |  |  |  * As the "first-match-wins" algorithm is identical to the "greedy" | 
					
						
							|  |  |  |  * disambiguation method used by POSIX regular expressions, it is natural and | 
					
						
							|  |  |  |  * commonplace to use a regular expression for parsing the potential five | 
					
						
							|  |  |  |  * components of a URI reference. | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * The following line is the regular expression for breaking-down a | 
					
						
							|  |  |  |  * well-formed URI reference into its components. | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * <pre> | 
					
						
							|  |  |  |  * ^(([^:/?#]+):)?(//([^/?#]*))?([^?#]*)(\?([^#]*))?(#(.*))? | 
					
						
							|  |  |  |  *  12            3  4          5       6  7        8 9 | 
					
						
							|  |  |  |  * </pre> | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * The numbers in the second line above are only to assist readability; they | 
					
						
							|  |  |  |  * indicate the reference points for each subexpression (i.e., each paired | 
					
						
							|  |  |  |  * parenthesis). We refer to the value matched for subexpression <n> as $<n>. | 
					
						
							|  |  |  |  * For example, matching the above expression to | 
					
						
							|  |  |  |  * <pre> | 
					
						
							|  |  |  |  *     http://www.ics.uci.edu/pub/ietf/uri/#Related
 | 
					
						
							|  |  |  |  * </pre> | 
					
						
							|  |  |  |  * results in the following subexpression matches: | 
					
						
							|  |  |  |  * <pre> | 
					
						
							|  |  |  |  *    $1 = http: | 
					
						
							|  |  |  |  *    $2 = http | 
					
						
							|  |  |  |  *    $3 = //www.ics.uci.edu
 | 
					
						
							|  |  |  |  *    $4 = www.ics.uci.edu | 
					
						
							|  |  |  |  *    $5 = /pub/ietf/uri/ | 
					
						
							|  |  |  |  *    $6 = <undefined> | 
					
						
							|  |  |  |  *    $7 = <undefined> | 
					
						
							|  |  |  |  *    $8 = #Related | 
					
						
							|  |  |  |  *    $9 = Related | 
					
						
							|  |  |  |  * </pre> | 
					
						
							|  |  |  |  * where <undefined> indicates that the component is not present, as is the | 
					
						
							|  |  |  |  * case for the query component in the above example. Therefore, we can | 
					
						
							|  |  |  |  * determine the value of the five components as | 
					
						
							|  |  |  |  * <pre> | 
					
						
							|  |  |  |  *    scheme    = $2 | 
					
						
							|  |  |  |  *    authority = $4 | 
					
						
							|  |  |  |  *    path      = $5 | 
					
						
							|  |  |  |  *    query     = $7 | 
					
						
							|  |  |  |  *    fragment  = $9 | 
					
						
							|  |  |  |  * </pre> | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * The regular expression has been modified slightly to expose the | 
					
						
							|  |  |  |  * userInfo, domain, and port separately from the authority. | 
					
						
							|  |  |  |  * The modified version yields | 
					
						
							|  |  |  |  * <pre> | 
					
						
							|  |  |  |  *    $1 = http              scheme | 
					
						
							|  |  |  |  *    $2 = <undefined>       userInfo -\ | 
					
						
							|  |  |  |  *    $3 = www.ics.uci.edu   domain     | authority | 
					
						
							|  |  |  |  *    $4 = <undefined>       port     -/ | 
					
						
							|  |  |  |  *    $5 = /pub/ietf/uri/    path | 
					
						
							|  |  |  |  *    $6 = <undefined>       query without ? | 
					
						
							|  |  |  |  *    $7 = Related           fragment without # | 
					
						
							|  |  |  |  * </pre> | 
					
						
							|  |  |  |  * @type {!RegExp} | 
					
						
							| 
									
										
										
										
											2015-10-02 13:32:48 -07:00
										 |  |  |  * @internal | 
					
						
							| 
									
										
										
										
											2015-06-23 12:05:09 +02:00
										 |  |  |  */ | 
					
						
							|  |  |  | var _splitRe = | 
					
						
							|  |  |  |     RegExpWrapper.create('^' + | 
					
						
							|  |  |  |                          '(?:' + | 
					
						
							|  |  |  |                          '([^:/?#.]+)' +  // scheme - ignore special characters
 | 
					
						
							|  |  |  |                                           // used by other URL parts such as :,
 | 
					
						
							|  |  |  |                                           // ?, /, #, and .
 | 
					
						
							|  |  |  |                          ':)?' + | 
					
						
							|  |  |  |                          '(?://' + | 
					
						
							|  |  |  |                          '(?:([^/?#]*)@)?' +                  // userInfo
 | 
					
						
							|  |  |  |                          '([\\w\\d\\-\\u0100-\\uffff.%]*)' +  // domain - restrict to letters,
 | 
					
						
							|  |  |  |                                                               // digits, dashes, dots, percent
 | 
					
						
							|  |  |  |                                                               // escapes, and unicode characters.
 | 
					
						
							|  |  |  |                          '(?::([0-9]+))?' +                   // port
 | 
					
						
							|  |  |  |                          ')?' + | 
					
						
							|  |  |  |                          '([^?#]+)?' +        // path
 | 
					
						
							|  |  |  |                          '(?:\\?([^#]*))?' +  // query
 | 
					
						
							|  |  |  |                          '(?:#(.*))?' +       // fragment
 | 
					
						
							|  |  |  |                          '$'); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /** | 
					
						
							|  |  |  |  * The index of each URI component in the return value of goog.uri.utils.split. | 
					
						
							|  |  |  |  * @enum {number} | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | enum _ComponentIndex { | 
					
						
							| 
									
										
										
										
											2015-08-26 13:40:12 -07:00
										 |  |  |   Scheme = 1, | 
					
						
							|  |  |  |   UserInfo, | 
					
						
							|  |  |  |   Domain, | 
					
						
							|  |  |  |   Port, | 
					
						
							|  |  |  |   Path, | 
					
						
							|  |  |  |   QueryData, | 
					
						
							|  |  |  |   Fragment | 
					
						
							| 
									
										
										
										
											2015-06-23 12:05:09 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /** | 
					
						
							|  |  |  |  * Splits a URI into its component parts. | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * Each component can be accessed via the component indices; for example: | 
					
						
							|  |  |  |  * <pre> | 
					
						
							|  |  |  |  * goog.uri.utils.split(someStr)[goog.uri.utils.CompontentIndex.QUERY_DATA]; | 
					
						
							|  |  |  |  * </pre> | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * @param {string} uri The URI string to examine. | 
					
						
							|  |  |  |  * @return {!Array.<string|undefined>} Each component still URI-encoded. | 
					
						
							|  |  |  |  *     Each component that is present will contain the encoded value, whereas | 
					
						
							|  |  |  |  *     components that are not present will be undefined or empty, depending | 
					
						
							|  |  |  |  *     on the browser's regular expression implementation.  Never null, since | 
					
						
							|  |  |  |  *     arbitrary strings may still look like path names. | 
					
						
							|  |  |  |  */ | 
					
						
							| 
									
										
										
										
											2015-08-28 11:29:19 -07:00
										 |  |  | function _split(uri: string): Array<string | any> { | 
					
						
							| 
									
										
										
										
											2015-06-23 12:05:09 +02:00
										 |  |  |   return RegExpWrapper.firstMatch(_splitRe, uri); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /** | 
					
						
							|  |  |  |   * Removes dot segments in given path component, as described in | 
					
						
							|  |  |  |   * RFC 3986, section 5.2.4. | 
					
						
							|  |  |  |   * | 
					
						
							|  |  |  |   * @param {string} path A non-empty path component. | 
					
						
							|  |  |  |   * @return {string} Path component with removed dot segments. | 
					
						
							|  |  |  |   */ | 
					
						
							|  |  |  | function _removeDotSegments(path: string): string { | 
					
						
							|  |  |  |   if (path == '/') return '/'; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   var leadingSlash = path[0] == '/' ? '/' : ''; | 
					
						
							|  |  |  |   var trailingSlash = path[path.length - 1] === '/' ? '/' : ''; | 
					
						
							|  |  |  |   var segments = path.split('/'); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-10-07 09:09:43 -07:00
										 |  |  |   var out: string[] = []; | 
					
						
							| 
									
										
										
										
											2015-06-23 12:05:09 +02:00
										 |  |  |   var up = 0; | 
					
						
							|  |  |  |   for (var pos = 0; pos < segments.length; pos++) { | 
					
						
							|  |  |  |     var segment = segments[pos]; | 
					
						
							|  |  |  |     switch (segment) { | 
					
						
							|  |  |  |       case '': | 
					
						
							|  |  |  |       case '.': | 
					
						
							|  |  |  |         break; | 
					
						
							|  |  |  |       case '..': | 
					
						
							|  |  |  |         if (out.length > 0) { | 
					
						
							| 
									
										
										
										
											2015-10-07 09:09:43 -07:00
										 |  |  |           out.pop(); | 
					
						
							| 
									
										
										
										
											2015-06-23 12:05:09 +02:00
										 |  |  |         } else { | 
					
						
							|  |  |  |           up++; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         break; | 
					
						
							|  |  |  |       default: | 
					
						
							|  |  |  |         out.push(segment); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   if (leadingSlash == '') { | 
					
						
							|  |  |  |     while (up-- > 0) { | 
					
						
							| 
									
										
										
										
											2015-10-07 09:09:43 -07:00
										 |  |  |       out.unshift('..'); | 
					
						
							| 
									
										
										
										
											2015-06-23 12:05:09 +02:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (out.length === 0) out.push('.'); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   return leadingSlash + out.join('/') + trailingSlash; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /** | 
					
						
							|  |  |  |  * Takes an array of the parts from split and canonicalizes the path part | 
					
						
							|  |  |  |  * and then joins all the parts. | 
					
						
							|  |  |  |  * @param {Array.<string?>} parts | 
					
						
							|  |  |  |  * @return {string} | 
					
						
							|  |  |  |  */ | 
					
						
							| 
									
										
										
										
											2015-08-28 11:29:19 -07:00
										 |  |  | function _joinAndCanonicalizePath(parts: any[]): string { | 
					
						
							| 
									
										
										
										
											2015-08-26 13:40:12 -07:00
										 |  |  |   var path = parts[_ComponentIndex.Path]; | 
					
						
							| 
									
										
										
										
											2015-06-23 12:05:09 +02:00
										 |  |  |   path = isBlank(path) ? '' : _removeDotSegments(path); | 
					
						
							| 
									
										
										
										
											2015-08-26 13:40:12 -07:00
										 |  |  |   parts[_ComponentIndex.Path] = path; | 
					
						
							| 
									
										
										
										
											2015-06-23 12:05:09 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-08-26 13:40:12 -07:00
										 |  |  |   return _buildFromEncodedParts(parts[_ComponentIndex.Scheme], parts[_ComponentIndex.UserInfo], | 
					
						
							|  |  |  |                                 parts[_ComponentIndex.Domain], parts[_ComponentIndex.Port], path, | 
					
						
							|  |  |  |                                 parts[_ComponentIndex.QueryData], parts[_ComponentIndex.Fragment]); | 
					
						
							| 
									
										
										
										
											2015-06-23 12:05:09 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /** | 
					
						
							|  |  |  |  * Resolves a URL. | 
					
						
							|  |  |  |  * @param {string} base The URL acting as the base URL. | 
					
						
							|  |  |  |  * @param {string} to The URL to resolve. | 
					
						
							|  |  |  |  * @return {string} | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | function _resolveUrl(base: string, url: string): string { | 
					
						
							| 
									
										
										
										
											2015-08-08 09:25:24 +02:00
										 |  |  |   var parts = _split(encodeURI(url)); | 
					
						
							| 
									
										
										
										
											2015-06-23 12:05:09 +02:00
										 |  |  |   var baseParts = _split(base); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-08-26 13:40:12 -07:00
										 |  |  |   if (isPresent(parts[_ComponentIndex.Scheme])) { | 
					
						
							| 
									
										
										
										
											2015-06-23 12:05:09 +02:00
										 |  |  |     return _joinAndCanonicalizePath(parts); | 
					
						
							|  |  |  |   } else { | 
					
						
							| 
									
										
										
										
											2015-08-26 13:40:12 -07:00
										 |  |  |     parts[_ComponentIndex.Scheme] = baseParts[_ComponentIndex.Scheme]; | 
					
						
							| 
									
										
										
										
											2015-06-23 12:05:09 +02:00
										 |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-08-26 13:40:12 -07:00
										 |  |  |   for (var i = _ComponentIndex.Scheme; i <= _ComponentIndex.Port; i++) { | 
					
						
							| 
									
										
										
										
											2015-06-23 12:05:09 +02:00
										 |  |  |     if (isBlank(parts[i])) { | 
					
						
							|  |  |  |       parts[i] = baseParts[i]; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-08-26 13:40:12 -07:00
										 |  |  |   if (parts[_ComponentIndex.Path][0] == '/') { | 
					
						
							| 
									
										
										
										
											2015-06-23 12:05:09 +02:00
										 |  |  |     return _joinAndCanonicalizePath(parts); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-08-26 13:40:12 -07:00
										 |  |  |   var path = baseParts[_ComponentIndex.Path]; | 
					
						
							| 
									
										
										
										
											2015-06-23 12:05:09 +02:00
										 |  |  |   if (isBlank(path)) path = '/'; | 
					
						
							|  |  |  |   var index = path.lastIndexOf('/'); | 
					
						
							| 
									
										
										
										
											2015-08-26 13:40:12 -07:00
										 |  |  |   path = path.substring(0, index + 1) + parts[_ComponentIndex.Path]; | 
					
						
							|  |  |  |   parts[_ComponentIndex.Path] = path; | 
					
						
							| 
									
										
										
										
											2015-06-23 12:05:09 +02:00
										 |  |  |   return _joinAndCanonicalizePath(parts); | 
					
						
							|  |  |  | } |