mirror of
https://github.com/futurepress/epub.js.git
synced 2025-10-05 15:32:55 +02:00
updated polymer example, added urljs (no implemented)
This commit is contained in:
parent
8f06e86d9c
commit
150b6b6050
10 changed files with 2635 additions and 4 deletions
666
libs/urljs/url.js
Executable file
666
libs/urljs/url.js
Executable file
|
@ -0,0 +1,666 @@
|
|||
/*!
|
||||
* URL.js
|
||||
*
|
||||
* Copyright 2011 Eric Ferraiuolo
|
||||
* https://github.com/ericf/urljs
|
||||
*/
|
||||
|
||||
/**
|
||||
* URL constructor and utility.
|
||||
* Provides support for validating whether something is a URL,
|
||||
* formats and cleans up URL-like inputs into something nice and pretty,
|
||||
* ability to resolve one URL against another and returned the formatted result,
|
||||
* and is a convenient API for working with URL Objects and the various parts of URLs.
|
||||
*
|
||||
* @constructor URL
|
||||
* @param {String | URL} url - the URL String to parse or URL instance to copy
|
||||
* @return {URL} url - instance of a URL all nice and parsed
|
||||
*/
|
||||
var URL = function () {
|
||||
|
||||
var u = this;
|
||||
|
||||
if ( ! (u && u.hasOwnProperty && (u instanceof URL))) {
|
||||
u = new URL();
|
||||
}
|
||||
|
||||
return u._init.apply(u, arguments);
|
||||
};
|
||||
|
||||
(function(){
|
||||
|
||||
var ABSOLUTE = 'absolute',
|
||||
RELATIVE = 'relative',
|
||||
|
||||
HTTP = 'http',
|
||||
HTTPS = 'https',
|
||||
COLON = ':',
|
||||
SLASH_SLASH = '//',
|
||||
AT = '@',
|
||||
DOT = '.',
|
||||
SLASH = '/',
|
||||
DOT_DOT = '..',
|
||||
DOT_DOT_SLASH = '../',
|
||||
QUESTION = '?',
|
||||
EQUALS = '=',
|
||||
AMP = '&',
|
||||
HASH = '#',
|
||||
EMPTY_STRING = '',
|
||||
|
||||
TYPE = 'type',
|
||||
SCHEME = 'scheme',
|
||||
USER_INFO = 'userInfo',
|
||||
HOST = 'host',
|
||||
PORT = 'port',
|
||||
PATH = 'path',
|
||||
QUERY = 'query',
|
||||
FRAGMENT = 'fragment',
|
||||
|
||||
URL_TYPE_REGEX = /^(?:(https?:\/\/|\/\/)|(\/|\?|#)|[^;:@=\.\s])/i,
|
||||
URL_ABSOLUTE_REGEX = /^(?:(https?):\/\/|\/\/)(?:([^:@\s]+:?[^:@\s]+?)@)?((?:[^;:@=\/\?\.\s]+\.)+[A-Za-z0-9\-]{2,})(?::(\d+))?(?=\/|\?|#|$)([^\?#]+)?(?:\?([^#]+))?(?:#(.+))?/i,
|
||||
URL_RELATIVE_REGEX = /^([^\?#]+)?(?:\?([^#]+))?(?:#(.+))?/i,
|
||||
|
||||
OBJECT = 'object',
|
||||
STRING = 'string',
|
||||
TRIM_REGEX = /^\s+|\s+$/g,
|
||||
|
||||
trim, isObject, isString;
|
||||
|
||||
|
||||
// *** Utilities *** //
|
||||
|
||||
trim = String.prototype.trim ? function (s) {
|
||||
return ( s && s.trim ? s.trim() : s );
|
||||
} : function (s) {
|
||||
try {
|
||||
return s.replace(TRIM_REGEX, EMPTY_STRING);
|
||||
} catch (e) { return s; }
|
||||
};
|
||||
|
||||
isObject = function (o) {
|
||||
return ( o && typeof o === OBJECT );
|
||||
};
|
||||
|
||||
isString = function (o) {
|
||||
return typeof o === STRING;
|
||||
};
|
||||
|
||||
|
||||
// *** Static *** //
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
URL.ABSOLUTE = ABSOLUTE;
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
URL.RELATIVE = RELATIVE;
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
URL.normalize = function (url) {
|
||||
return new URL(url).toString();
|
||||
};
|
||||
|
||||
/**
|
||||
* Returns a resolved URL String using the baseUrl to resolve the url against.
|
||||
* This attempts to resolve URLs like a browser would on a web page.
|
||||
*
|
||||
* @static
|
||||
* @method resolve
|
||||
* @param {String | URL} baseUrl - the URL String, or URL instance as the resolving base
|
||||
* @param {String | URL} url - the URL String, or URL instance to resolve
|
||||
* @return {String} resolvedUrl - a resolved URL String
|
||||
*/
|
||||
URL.resolve = function (baseUrl, url) {
|
||||
return new URL(baseUrl).resolve(url).toString();
|
||||
};
|
||||
|
||||
|
||||
// *** Prototype *** //
|
||||
|
||||
URL.prototype = {
|
||||
|
||||
// *** Lifecycle Methods *** //
|
||||
|
||||
/**
|
||||
* Initializes a new URL instance, or re-initializes an existing one.
|
||||
* The URL constructor delegates to this method to do the initializing,
|
||||
* and the mutator instance methods call this to re-initialize when something changes.
|
||||
*
|
||||
* @protected
|
||||
* @method _init
|
||||
* @param {String | URL} url - the URL String, or URL instance
|
||||
* @return {URL} url - instance of a URL all nice and parsed/re-parsed
|
||||
*/
|
||||
_init : function (url) {
|
||||
|
||||
this.constructor = URL;
|
||||
|
||||
url = isString(url) ? url : url instanceof URL ? url.toString() : null;
|
||||
|
||||
this._original = url;
|
||||
this._url = {};
|
||||
this._isValid = this._parse(url);
|
||||
|
||||
return this;
|
||||
},
|
||||
|
||||
// *** Object Methods *** //
|
||||
|
||||
/**
|
||||
* Returns the formatted URL String.
|
||||
* Overridden Object toString method to do something useful.
|
||||
*
|
||||
* @public
|
||||
* @method toString
|
||||
* @return {String} url - formatted URL string
|
||||
*/
|
||||
toString : function () {
|
||||
|
||||
var url = this._url,
|
||||
urlParts = [],
|
||||
type = url[TYPE],
|
||||
scheme = url[SCHEME],
|
||||
path = url[PATH],
|
||||
query = url[QUERY],
|
||||
fragment = url[FRAGMENT];
|
||||
|
||||
if (type === ABSOLUTE) {
|
||||
urlParts.push(
|
||||
scheme ? (scheme + COLON + SLASH_SLASH) : SLASH_SLASH,
|
||||
this.authority()
|
||||
);
|
||||
if (path && path.indexOf(SLASH) !== 0) { // this should maybe go in _set
|
||||
path = SLASH + path;
|
||||
}
|
||||
}
|
||||
|
||||
urlParts.push(
|
||||
path,
|
||||
query ? (QUESTION + this.queryString()) : EMPTY_STRING,
|
||||
fragment ? (HASH + fragment) : EMPTY_STRING
|
||||
);
|
||||
|
||||
return urlParts.join(EMPTY_STRING);
|
||||
},
|
||||
|
||||
// *** Accessor/Mutator Methods *** //
|
||||
|
||||
original : function () {
|
||||
return this._original;
|
||||
},
|
||||
|
||||
/**
|
||||
* Whether parsing from initialization or re-initialization produced something valid.
|
||||
*
|
||||
* @public
|
||||
* @method isValid
|
||||
* @return {Boolean} valid - whether the URL is valid
|
||||
*/
|
||||
isValid : function () {
|
||||
return this._isValid;
|
||||
},
|
||||
|
||||
/**
|
||||
* URL is absolute if it has a scheme or is scheme-relative (//).
|
||||
*
|
||||
* @public
|
||||
* @method isAbsolute
|
||||
* @return {Boolean} absolute - whether the URL is absolute
|
||||
*/
|
||||
isAbsolute : function () {
|
||||
return this._url[TYPE] === ABSOLUTE;
|
||||
},
|
||||
|
||||
/**
|
||||
* URL is relative if it host or path relative, i.e. doesn't contain a host.
|
||||
*
|
||||
* @public
|
||||
* @method isRelative
|
||||
* @return {Boolean} relative - whether the URL is relative
|
||||
*/
|
||||
isRelative : function () {
|
||||
return this._url[TYPE] === RELATIVE;
|
||||
},
|
||||
|
||||
/**
|
||||
* URL is host relative if it's relative and the path begins with '/'.
|
||||
*
|
||||
* @public
|
||||
* @method isHostRelative
|
||||
* @return {Boolean} hostRelative - whether the URL is host-relative
|
||||
*/
|
||||
isHostRelative : function () {
|
||||
var path = this._url[PATH];
|
||||
return ( this.isRelative() && path && path.indexOf(SLASH) === 0 );
|
||||
},
|
||||
|
||||
/**
|
||||
* Returns the type of the URL, either: URL.ABSOLUTE or URL.RELATIVE.
|
||||
*
|
||||
* @public
|
||||
* @method type
|
||||
* @return {String} type - the type of the URL: URL.ABSOLUTE or URL.RELATIVE
|
||||
*/
|
||||
type : function () {
|
||||
return this._url[TYPE];
|
||||
},
|
||||
|
||||
/**
|
||||
* Returns or sets the scheme of the URL.
|
||||
* If URL is determined to be absolute (i.e. contains a host) and no scheme is provided,
|
||||
* the scheme will default to http.
|
||||
*
|
||||
* @public
|
||||
* @method scheme
|
||||
* @param {String} scheme - Optional scheme to set on the URL
|
||||
* @return {String | URL} the URL scheme or the URL instance
|
||||
*/
|
||||
scheme : function (scheme) {
|
||||
return ( arguments.length ? this._set(SCHEME, scheme) : this._url[SCHEME] );
|
||||
},
|
||||
|
||||
/**
|
||||
* Returns or set the user info of the URL.
|
||||
* The user info can optionally contain a password and is only valid for absolute URLs.
|
||||
*
|
||||
* @public
|
||||
* @method userInfo
|
||||
* @param {String} userInfo - Optional userInfo to set on the URL
|
||||
* @return {String | URL} the URL userInfo or the URL instance
|
||||
*/
|
||||
userInfo : function (userInfo) {
|
||||
return ( arguments.length ? this._set(USER_INFO, userInfo) : this._url[USER_INFO] );
|
||||
},
|
||||
|
||||
/**
|
||||
* Returns or sets the host of the URL.
|
||||
* The host name, if set, must be something valid otherwise the URL will become invalid.
|
||||
*
|
||||
* @public
|
||||
* @method host
|
||||
* @param {String} host - Optional host to set on the URL
|
||||
* @return {String | URL} the URL host or the URL instance
|
||||
*/
|
||||
host : function (host) {
|
||||
return ( arguments.length ? this._set(HOST, host) : this._url[HOST] );
|
||||
},
|
||||
|
||||
/**
|
||||
* Returns the URL's domain, where the domain is the TLD and SLD of the host.
|
||||
* e.g. foo.example.com -> example.com
|
||||
*
|
||||
* @public
|
||||
* @method domain
|
||||
* @return {String} domain - the URL domain
|
||||
*/
|
||||
domain : function () {
|
||||
var host = this._url[HOST];
|
||||
return ( host ? host.split(DOT).slice(-2).join(DOT) : undefined );
|
||||
},
|
||||
|
||||
/**
|
||||
* Returns or sets the port of the URL.
|
||||
*
|
||||
* @public
|
||||
* @method port
|
||||
* @param {Number} port - Optional port to set on the URL
|
||||
* @return {Number | URL} the URL port or the URL instance
|
||||
*/
|
||||
port : function (port) {
|
||||
return ( arguments.length ? this._set(PORT, port) : this._url[PORT] );
|
||||
},
|
||||
|
||||
/**
|
||||
* Returns the URL's authority which is the userInfo, host, and port combined.
|
||||
* This only makes sense for absolute URLs
|
||||
*
|
||||
* @public
|
||||
* @method authority
|
||||
* @return {String} authority - the URL's authority (userInfo, host, and port)
|
||||
*/
|
||||
authority : function () {
|
||||
|
||||
var url = this._url,
|
||||
userInfo = url[USER_INFO],
|
||||
host = url[HOST],
|
||||
port = url[PORT];
|
||||
|
||||
return [
|
||||
|
||||
userInfo ? (userInfo + AT) : EMPTY_STRING,
|
||||
host,
|
||||
port ? (COLON + port) : EMPTY_STRING,
|
||||
|
||||
].join(EMPTY_STRING);
|
||||
},
|
||||
|
||||
/**
|
||||
* Returns or sets the path of the URL.
|
||||
*
|
||||
* @public
|
||||
* @method path
|
||||
* @param {String} path - Optional path to set on the URL
|
||||
* @return {String | URL} the URL path or the URL instance
|
||||
*/
|
||||
path : function (path) {
|
||||
return ( arguments.length ? this._set(PATH, path) : this._url[PATH] );
|
||||
},
|
||||
|
||||
/**
|
||||
* Returns or sets the query of the URL.
|
||||
* This takes or returns the parsed query as an Array of Arrays.
|
||||
*
|
||||
* @public
|
||||
* @method query
|
||||
* @param {Array} query - Optional query to set on the URL
|
||||
* @return {Array | URL} the URL query or the URL instance
|
||||
*/
|
||||
query : function (query) {
|
||||
return ( arguments.length ? this._set(QUERY, query) : this._url[QUERY] );
|
||||
},
|
||||
|
||||
/**
|
||||
* Returns or sets the query of the URL.
|
||||
* This takes or returns the query as a String; doesn't include the '?'
|
||||
*
|
||||
* @public
|
||||
* @method queryString
|
||||
* @param {String} queryString - Optional queryString to set on the URL
|
||||
* @return {String | URL} the URL queryString or the URL instance
|
||||
*/
|
||||
queryString : function (queryString) {
|
||||
|
||||
// parse and set queryString
|
||||
if (arguments.length) {
|
||||
return this._set(QUERY, this._parseQuery(queryString));
|
||||
}
|
||||
|
||||
queryString = EMPTY_STRING;
|
||||
|
||||
var query = this._url[QUERY],
|
||||
i, len;
|
||||
|
||||
if (query) {
|
||||
for (i = 0, len = query.length; i < len; i++) {
|
||||
queryString += query[i].join(EQUALS);
|
||||
if (i < len - 1) {
|
||||
queryString += AMP;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return queryString;
|
||||
},
|
||||
|
||||
/**
|
||||
* Returns or sets the fragment on the URL.
|
||||
* The fragment does not contain the '#'.
|
||||
*
|
||||
* @public
|
||||
* @method fragment
|
||||
* @param {String} fragment - Optional fragment to set on the URL
|
||||
* @return {String | URL} the URL fragment or the URL instance
|
||||
*/
|
||||
fragment : function (fragment) {
|
||||
return ( arguments.length ? this._set(FRAGMENT, fragment) : this._url[FRAGMENT] );
|
||||
},
|
||||
|
||||
/**
|
||||
* Returns a new, resolved URL instance using this as the baseUrl.
|
||||
* The URL passed in will be resolved against the baseUrl.
|
||||
*
|
||||
* @public
|
||||
* @method resolve
|
||||
* @param {String | URL} url - the URL String, or URL instance to resolve
|
||||
* @return {URL} url - a resolved URL instance
|
||||
*/
|
||||
resolve : function (url) {
|
||||
|
||||
url = (url instanceof URL) ? url : new URL(url);
|
||||
|
||||
var resolved, path;
|
||||
|
||||
if ( ! (this.isValid() && url.isValid())) { return this; } // not sure what to do???
|
||||
|
||||
// the easy way
|
||||
if (url.isAbsolute()) {
|
||||
return ( this.isAbsolute() ? url.scheme() ? url : new URL(url).scheme(this.scheme()) : url );
|
||||
}
|
||||
|
||||
// the hard way
|
||||
resolved = new URL(this.isAbsolute() ? this : null);
|
||||
|
||||
if (url.path()) {
|
||||
|
||||
if (url.isHostRelative() || ! this.path()) {
|
||||
path = url.path();
|
||||
} else {
|
||||
path = this.path().substring(0, this.path().lastIndexOf(SLASH) + 1) + url.path();
|
||||
}
|
||||
|
||||
resolved.path(this._normalizePath(path)).query(url.query()).fragment(url.fragment());
|
||||
|
||||
} else if (url.query()) {
|
||||
resolved.query(url.query()).fragment(url.fragment());
|
||||
} else if (url.fragment()) {
|
||||
resolved.fragment(url.fragment());
|
||||
}
|
||||
|
||||
return resolved;
|
||||
},
|
||||
|
||||
/**
|
||||
* Returns a new, reduced relative URL instance using this as the baseUrl.
|
||||
* The URL passed in will be compared to the baseUrl with the goal of
|
||||
* returning a reduced-down URL to one that’s relative to the base (this).
|
||||
* This method is basically the opposite of resolve.
|
||||
*
|
||||
* @public
|
||||
* @method reduce
|
||||
* @param {String | URL} url - the URL String, or URL instance to resolve
|
||||
* @return {URL} url - the reduced URL instance
|
||||
*/
|
||||
reduce : function (url) {
|
||||
|
||||
url = (url instanceof URL) ? url : new URL(url);
|
||||
|
||||
var reduced = this.resolve(url);
|
||||
|
||||
if (this.isAbsolute() && reduced.isAbsolute()) {
|
||||
if (reduced.scheme() === this.scheme() && reduced.authority() === this.authority()) {
|
||||
reduced.scheme(null).userInfo(null).host(null).port(null);
|
||||
}
|
||||
}
|
||||
|
||||
return reduced;
|
||||
},
|
||||
|
||||
// *** Private Methods *** //
|
||||
|
||||
/**
|
||||
* Parses a URL into usable parts.
|
||||
* Reasonable defaults are applied to parts of the URL which weren't present in the input,
|
||||
* e.g. 'http://example.com' -> { type: 'absolute', scheme: 'http', host: 'example.com', path: '/' }
|
||||
* If nothing or a falsy value is returned, the URL wasn't something valid.
|
||||
*
|
||||
* @private
|
||||
* @method _parse
|
||||
* @param {String} url - the URL string to parse
|
||||
* @param {String} type - Optional type to seed parsing: URL.ABSOLUTE or URL.RELATIVE
|
||||
* @return {Boolean} parsed - whether or not the URL string was parsed
|
||||
*/
|
||||
_parse : function (url, type) {
|
||||
|
||||
// make sure we have a good string
|
||||
url = trim(url);
|
||||
if ( ! (isString(url) && url.length > 0)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
var urlParts, parsed;
|
||||
|
||||
// figure out type, absolute or relative, or quit
|
||||
if ( ! type) {
|
||||
type = url.match(URL_TYPE_REGEX);
|
||||
type = type ? type[1] ? ABSOLUTE : type[2] ? RELATIVE : null : null;
|
||||
}
|
||||
|
||||
switch (type) {
|
||||
|
||||
case ABSOLUTE:
|
||||
urlParts = url.match(URL_ABSOLUTE_REGEX);
|
||||
if (urlParts) {
|
||||
parsed = {};
|
||||
parsed[TYPE] = ABSOLUTE;
|
||||
parsed[SCHEME] = urlParts[1] ? urlParts[1].toLowerCase() : undefined;
|
||||
parsed[USER_INFO] = urlParts[2];
|
||||
parsed[HOST] = urlParts[3].toLowerCase();
|
||||
parsed[PORT] = urlParts[4] ? parseInt(urlParts[4], 10) : undefined;
|
||||
parsed[PATH] = urlParts[5] || SLASH;
|
||||
parsed[QUERY] = this._parseQuery(urlParts[6]);
|
||||
parsed[FRAGMENT] = urlParts[7];
|
||||
}
|
||||
break;
|
||||
|
||||
case RELATIVE:
|
||||
urlParts = url.match(URL_RELATIVE_REGEX);
|
||||
if (urlParts) {
|
||||
parsed = {};
|
||||
parsed[TYPE] = RELATIVE;
|
||||
parsed[PATH] = urlParts[1];
|
||||
parsed[QUERY] = this._parseQuery(urlParts[2]);
|
||||
parsed[FRAGMENT] = urlParts[3];
|
||||
}
|
||||
break;
|
||||
|
||||
// try to parse as absolute, if that fails then as relative
|
||||
default:
|
||||
return ( this._parse(url, ABSOLUTE) || this._parse(url, RELATIVE) );
|
||||
break;
|
||||
|
||||
}
|
||||
|
||||
if (parsed) {
|
||||
this._url = parsed;
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Helper to parse a URL query string into an array of arrays.
|
||||
* Order of the query paramerters is maintained, an example structure would be:
|
||||
* queryString: 'foo=bar&baz' -> [['foo', 'bar'], ['baz']]
|
||||
*
|
||||
* @private
|
||||
* @method _parseQuery
|
||||
* @param {String} queryString - the query string to parse, should not include '?'
|
||||
* @return {Array} parsedQuery - array of arrays representing the query parameters and values
|
||||
*/
|
||||
_parseQuery : function (queryString) {
|
||||
|
||||
if ( ! isString(queryString)) { return; }
|
||||
|
||||
queryString = trim(queryString);
|
||||
|
||||
var query = [],
|
||||
queryParts = queryString.split(AMP),
|
||||
queryPart, i, len;
|
||||
|
||||
for (i = 0, len = queryParts.length; i < len; i++) {
|
||||
if (queryParts[i]) {
|
||||
queryPart = queryParts[i].split(EQUALS);
|
||||
query.push(queryPart[1] ? queryPart : [queryPart[0]]);
|
||||
}
|
||||
}
|
||||
|
||||
return query;
|
||||
},
|
||||
|
||||
/**
|
||||
* Helper for mutators to set a new URL-part value.
|
||||
* After the URL-part is updated, the URL will be toString'd and re-parsed.
|
||||
* This is a brute, but will make sure the URL stays in sync and is re-validated.
|
||||
*
|
||||
* @private
|
||||
* @method _set
|
||||
* @param {String} urlPart - the _url Object member String name
|
||||
* @param {Object} val - the new value for the URL-part, mixed type
|
||||
* @return {URL} this - returns this URL instance, chainable
|
||||
*/
|
||||
_set : function (urlPart, val) {
|
||||
|
||||
this._url[urlPart] = val;
|
||||
|
||||
if (val && (
|
||||
urlPart === SCHEME ||
|
||||
urlPart === USER_INFO ||
|
||||
urlPart === HOST ||
|
||||
urlPart === PORT )){
|
||||
this._url[TYPE] = ABSOLUTE; // temp, set this to help clue parsing
|
||||
}
|
||||
if ( ! val && urlPart === HOST) {
|
||||
this._url[TYPE] = RELATIVE; // temp, no host means relative
|
||||
}
|
||||
|
||||
this._isValid = this._parse(this.toString());
|
||||
|
||||
return this;
|
||||
},
|
||||
|
||||
/**
|
||||
* Returns a normalized path String, by removing ../'s.
|
||||
*
|
||||
* @private
|
||||
* @method _normalizePath
|
||||
* @param {String} path — the path String to normalize
|
||||
* @return {String} normalizedPath — the normalized path String
|
||||
*/
|
||||
_normalizePath : function (path) {
|
||||
|
||||
var pathParts, pathPart, pathStack, normalizedPath, i, len;
|
||||
|
||||
if (path.indexOf(DOT_DOT_SLASH) > -1) {
|
||||
|
||||
pathParts = path.split(SLASH);
|
||||
pathStack = [];
|
||||
|
||||
for ( i = 0, len = pathParts.length; i < len; i++ ) {
|
||||
pathPart = pathParts[i];
|
||||
if (pathPart === DOT_DOT) {
|
||||
pathStack.pop();
|
||||
} else if (pathPart) {
|
||||
pathStack.push(pathPart);
|
||||
}
|
||||
}
|
||||
|
||||
normalizedPath = pathStack.join(SLASH);
|
||||
|
||||
// prepend slash if needed
|
||||
if (path[0] === SLASH) {
|
||||
normalizedPath = SLASH + normalizedPath;
|
||||
}
|
||||
|
||||
// append slash if needed
|
||||
if (path[path.length - 1] === SLASH && normalizedPath.length > 1) {
|
||||
normalizedPath += SLASH;
|
||||
}
|
||||
|
||||
} else {
|
||||
|
||||
normalizedPath = path;
|
||||
|
||||
}
|
||||
|
||||
return normalizedPath;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
}());
|
Loading…
Add table
Add a link
Reference in a new issue