| 
									
										
										
										
											2016-06-23 09:47:54 -07:00
										 |  |  | /** | 
					
						
							|  |  |  |  * @license | 
					
						
							|  |  |  |  * Copyright Google Inc. All Rights Reserved. | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * Use of this source code is governed by an MIT-style license that can be | 
					
						
							|  |  |  |  * found in the LICENSE file at https://angular.io/license
 | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-01-03 16:54:46 -08:00
										 |  |  | import {Inject, InjectionToken, PACKAGE_ROOT_URL} from '@angular/core'; | 
					
						
							| 
									
										
										
										
											2016-06-08 16:38:52 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-10-06 15:10:27 -07:00
										 |  |  | import {isBlank, isPresent} from './facade/lang'; | 
					
						
							| 
									
										
										
										
											2016-12-15 09:12:40 -08:00
										 |  |  | import {CompilerInjectable} from './injectable'; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-04-28 17:50:03 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-01-03 16:54:46 -08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-12-03 15:49:09 -08:00
										 |  |  | /** | 
					
						
							|  |  |  |  * Create a {@link UrlResolver} with no package prefix. | 
					
						
							|  |  |  |  */ | 
					
						
							| 
									
										
										
										
											2016-01-06 14:13:44 -08:00
										 |  |  | export function createUrlResolverWithoutPackagePrefix(): UrlResolver { | 
					
						
							| 
									
										
										
										
											2015-10-15 16:03:23 -07:00
										 |  |  |   return new UrlResolver(); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-01-06 14:13:44 -08:00
										 |  |  | export function createOfflineCompileUrlResolver(): UrlResolver { | 
					
						
							| 
									
										
										
										
											2016-11-15 10:14:01 -08:00
										 |  |  |   return new UrlResolver('.'); | 
					
						
							| 
									
										
										
										
											2016-01-06 14:13:44 -08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-12-03 15:49:09 -08:00
										 |  |  | /** | 
					
						
							|  |  |  |  * A default provider for {@link PACKAGE_ROOT_URL} that maps to '/'. | 
					
						
							|  |  |  |  */ | 
					
						
							| 
									
										
										
										
											2016-12-27 14:55:58 -08:00
										 |  |  | export const DEFAULT_PACKAGE_URL_PROVIDER = { | 
					
						
							| 
									
										
										
										
											2016-04-25 22:25:21 -07:00
										 |  |  |   provide: PACKAGE_ROOT_URL, | 
					
						
							| 
									
										
										
										
											2016-06-08 16:38:52 -07:00
										 |  |  |   useValue: '/' | 
					
						
							| 
									
										
										
										
											2016-04-25 22:25:21 -07:00
										 |  |  | }; | 
					
						
							| 
									
										
										
										
											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. | 
					
						
							|  |  |  |  * | 
					
						
							| 
									
										
										
										
											2015-12-03 15:49:09 -08:00
										 |  |  |  * This class can be overridden by the application developer to create custom behavior. | 
					
						
							| 
									
										
										
										
											2015-07-07 08:15:58 +02:00
										 |  |  |  * | 
					
						
							|  |  |  |  * See {@link Compiler} | 
					
						
							| 
									
										
										
										
											2015-12-03 15:49:09 -08:00
										 |  |  |  * | 
					
						
							|  |  |  |  * ## Example | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * {@example compiler/ts/url_resolver/url_resolver.ts region='url_resolver'} | 
					
						
							| 
									
										
										
										
											2016-06-28 11:01:35 -07:00
										 |  |  |  * | 
					
						
							|  |  |  |  * @security  When compiling templates at runtime, you must | 
					
						
							|  |  |  |  * ensure that the entire template comes from a trusted source. | 
					
						
							|  |  |  |  * Attacker-controlled data introduced by a template could expose your | 
					
						
							|  |  |  |  * application to XSS risks. For more detail, see the [Security Guide](http://g.co/ng/security).
 | 
					
						
							| 
									
										
										
										
											2015-07-07 08:15:58 +02:00
										 |  |  |  */ | 
					
						
							| 
									
										
										
										
											2016-12-15 09:12:40 -08:00
										 |  |  | @CompilerInjectable() | 
					
						
							| 
									
										
										
										
											2015-02-20 18:00:09 +01:00
										 |  |  | export class UrlResolver { | 
					
						
							| 
									
										
										
										
											2016-01-06 14:13:44 -08:00
										 |  |  |   constructor(@Inject(PACKAGE_ROOT_URL) private _packagePrefix: string = null) {} | 
					
						
							| 
									
										
										
										
											2015-12-05 02:21:38 -08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											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
										 |  |  |    */ | 
					
						
							| 
									
										
										
										
											2015-12-05 02:21:38 -08:00
										 |  |  |   resolve(baseUrl: string, url: string): string { | 
					
						
							| 
									
										
										
										
											2016-11-12 14:08:58 +01:00
										 |  |  |     let resolvedUrl = url; | 
					
						
							| 
									
										
										
										
											2015-12-05 02:21:38 -08:00
										 |  |  |     if (isPresent(baseUrl) && baseUrl.length > 0) { | 
					
						
							|  |  |  |       resolvedUrl = _resolveUrl(baseUrl, resolvedUrl); | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2016-11-12 14:08:58 +01:00
										 |  |  |     const resolvedParts = _split(resolvedUrl); | 
					
						
							|  |  |  |     let prefix = this._packagePrefix; | 
					
						
							| 
									
										
										
										
											2016-01-06 14:13:44 -08:00
										 |  |  |     if (isPresent(prefix) && isPresent(resolvedParts) && | 
					
						
							| 
									
										
										
										
											2016-06-08 16:38:52 -07:00
										 |  |  |         resolvedParts[_ComponentIndex.Scheme] == 'package') { | 
					
						
							| 
									
										
										
										
											2016-11-12 14:08:58 +01:00
										 |  |  |       let path = resolvedParts[_ComponentIndex.Path]; | 
					
						
							| 
									
										
										
										
											2016-11-15 10:14:01 -08:00
										 |  |  |       prefix = prefix.replace(/\/+$/, ''); | 
					
						
							|  |  |  |       path = path.replace(/^\/+/, ''); | 
					
						
							|  |  |  |       return `${prefix}/${path}`; | 
					
						
							| 
									
										
										
										
											2015-12-05 02:21:38 -08:00
										 |  |  |     } | 
					
						
							|  |  |  |     return resolvedUrl; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-12-03 15:49:09 -08:00
										 |  |  | /** | 
					
						
							|  |  |  |  * Extract the scheme of a URL. | 
					
						
							|  |  |  |  */ | 
					
						
							| 
									
										
										
										
											2015-12-05 02:21:38 -08:00
										 |  |  | export function getUrlScheme(url: string): string { | 
					
						
							| 
									
										
										
										
											2016-11-12 14:08:58 +01:00
										 |  |  |   const match = _split(url); | 
					
						
							| 
									
										
										
										
											2016-06-08 16:38:52 -07:00
										 |  |  |   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. | 
					
						
							|  |  |  |  * | 
					
						
							| 
									
										
										
										
											2016-05-09 15:44:40 -07:00
										 |  |  |  * @param opt_scheme The scheme such as 'http'. | 
					
						
							|  |  |  |  * @param opt_userInfo The user name before the '@'. | 
					
						
							|  |  |  |  * @param opt_domain The domain such as 'www.google.com', already | 
					
						
							| 
									
										
										
										
											2015-06-23 12:05:09 +02:00
										 |  |  |  *     URI-encoded. | 
					
						
							| 
									
										
										
										
											2016-05-09 15:44:40 -07:00
										 |  |  |  * @param opt_port The port number. | 
					
						
							|  |  |  |  * @param opt_path The path, already URI-encoded.  If it is not | 
					
						
							| 
									
										
										
										
											2015-06-23 12:05:09 +02:00
										 |  |  |  *     empty, it must begin with a slash. | 
					
						
							| 
									
										
										
										
											2016-05-09 15:44:40 -07:00
										 |  |  |  * @param opt_queryData The URI-encoded query data. | 
					
						
							|  |  |  |  * @param opt_fragment The URI-encoded fragment identifier. | 
					
						
							|  |  |  |  * @return The fully combined URI. | 
					
						
							| 
									
										
										
										
											2015-06-23 12:05:09 +02:00
										 |  |  |  */ | 
					
						
							| 
									
										
										
										
											2016-06-08 16:38:52 -07:00
										 |  |  | function _buildFromEncodedParts( | 
					
						
							|  |  |  |     opt_scheme?: string, opt_userInfo?: string, opt_domain?: string, opt_port?: string, | 
					
						
							|  |  |  |     opt_path?: string, opt_queryData?: string, opt_fragment?: string): string { | 
					
						
							| 
									
										
										
										
											2016-11-12 14:08:58 +01:00
										 |  |  |   const out: string[] = []; | 
					
						
							| 
									
										
										
										
											2015-06-23 12:05:09 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |   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
										 |  |  |  */ | 
					
						
							| 
									
										
										
										
											2016-11-12 14:08:58 +01:00
										 |  |  | const _splitRe = new RegExp( | 
					
						
							| 
									
										
										
										
											2016-06-08 16:38:52 -07:00
										 |  |  |     '^' + | 
					
						
							|  |  |  |     '(?:' + | 
					
						
							|  |  |  |     '([^:/?#.]+)' +  // 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
 | 
					
						
							|  |  |  |     '$'); | 
					
						
							| 
									
										
										
										
											2015-06-23 12:05:09 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | /** | 
					
						
							|  |  |  |  * 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> | 
					
						
							|  |  |  |  * | 
					
						
							| 
									
										
										
										
											2016-05-09 15:44:40 -07:00
										 |  |  |  * @param uri The URI string to examine. | 
					
						
							|  |  |  |  * @return Each component still URI-encoded. | 
					
						
							| 
									
										
										
										
											2015-06-23 12:05:09 +02:00
										 |  |  |  *     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. | 
					
						
							|  |  |  |  */ | 
					
						
							| 
									
										
										
										
											2016-06-08 16:38:52 -07:00
										 |  |  | function _split(uri: string): Array<string|any> { | 
					
						
							| 
									
										
										
										
											2016-08-05 09:50:49 -07:00
										 |  |  |   return uri.match(_splitRe); | 
					
						
							| 
									
										
										
										
											2015-06-23 12:05:09 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /** | 
					
						
							|  |  |  |   * Removes dot segments in given path component, as described in | 
					
						
							|  |  |  |   * RFC 3986, section 5.2.4. | 
					
						
							|  |  |  |   * | 
					
						
							| 
									
										
										
										
											2016-05-09 15:44:40 -07:00
										 |  |  |   * @param path A non-empty path component. | 
					
						
							|  |  |  |   * @return Path component with removed dot segments. | 
					
						
							| 
									
										
										
										
											2015-06-23 12:05:09 +02:00
										 |  |  |   */ | 
					
						
							|  |  |  | function _removeDotSegments(path: string): string { | 
					
						
							|  |  |  |   if (path == '/') return '/'; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-11-12 14:08:58 +01:00
										 |  |  |   const leadingSlash = path[0] == '/' ? '/' : ''; | 
					
						
							|  |  |  |   const trailingSlash = path[path.length - 1] === '/' ? '/' : ''; | 
					
						
							|  |  |  |   const segments = path.split('/'); | 
					
						
							| 
									
										
										
										
											2015-06-23 12:05:09 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-11-12 14:08:58 +01:00
										 |  |  |   const out: string[] = []; | 
					
						
							|  |  |  |   let up = 0; | 
					
						
							|  |  |  |   for (let pos = 0; pos < segments.length; pos++) { | 
					
						
							|  |  |  |     const segment = segments[pos]; | 
					
						
							| 
									
										
										
										
											2015-06-23 12:05:09 +02:00
										 |  |  |     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. | 
					
						
							|  |  |  |  */ | 
					
						
							| 
									
										
										
										
											2015-08-28 11:29:19 -07:00
										 |  |  | function _joinAndCanonicalizePath(parts: any[]): string { | 
					
						
							| 
									
										
										
										
											2016-11-12 14:08:58 +01:00
										 |  |  |   let 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
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-06-08 16:38:52 -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. | 
					
						
							| 
									
										
										
										
											2016-05-09 15:44:40 -07:00
										 |  |  |  * @param base The URL acting as the base URL. | 
					
						
							|  |  |  |  * @param to The URL to resolve. | 
					
						
							| 
									
										
										
										
											2015-06-23 12:05:09 +02:00
										 |  |  |  */ | 
					
						
							|  |  |  | function _resolveUrl(base: string, url: string): string { | 
					
						
							| 
									
										
										
										
											2016-11-12 14:08:58 +01:00
										 |  |  |   const parts = _split(encodeURI(url)); | 
					
						
							|  |  |  |   const baseParts = _split(base); | 
					
						
							| 
									
										
										
										
											2015-06-23 12:05:09 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											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
										 |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-11-12 14:08:58 +01:00
										 |  |  |   for (let 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); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-11-12 14:08:58 +01:00
										 |  |  |   let path = baseParts[_ComponentIndex.Path]; | 
					
						
							| 
									
										
										
										
											2015-06-23 12:05:09 +02:00
										 |  |  |   if (isBlank(path)) path = '/'; | 
					
						
							| 
									
										
										
										
											2016-11-12 14:08:58 +01:00
										 |  |  |   const 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); | 
					
						
							|  |  |  | } |