LocationHashbangUrl represents url
This object is exposed as $location service when html5 history api is disabled or not supported

@constructor
@param {string} url Legacy url
@param {string} hashPrefix Prefix for hash part (containing path and search)
3621
function LocationHashbangUrl(url, hashPrefix, appBaseUrl) {
  var basePath;

  /**
   * Parse given hashbang url into properties
   * @param {string} url Hashbang url
   * @private
   */
  this.$$parse = function(url) {
    var match = matchUrl(url, this);


    if (match.hash && match.hash.indexOf(hashPrefix) !== 0) {
      throw Error('Invalid url "' + url + '", missing hash prefix "' + hashPrefix + '" !');
    }

    basePath = match.path + (match.search ? '?' + match.search : '');
    match = HASH_MATCH.exec((match.hash || '').substr(hashPrefix.length));
    if (match[1]) {
      this.$$path = (match[1].charAt(0) == '/' ? '' : '/') + decodeURIComponent(match[1]);
    } else {
      this.$$path = '';
    }

    this.$$search = parseKeyValue(match[3]);
    this.$$hash = match[5] && decodeURIComponent(match[5]) || '';

    this.$$compose();
  };

  /**
   * Compose hashbang url and update `absUrl` property
   * @private
   */
  this.$$compose = function() {
    var search = toKeyValue(this.$$search),
        hash = this.$$hash ? '#' + encodeUriSegment(this.$$hash) : '';

    this.$$url = encodePath(this.$$path) + (search ? '?' + search : '') + hash;
    this.$$absUrl = composeProtocolHostPort(this.$$protocol, this.$$host, this.$$port) +
                    basePath + (this.$$url ? '#' + hashPrefix + this.$$url : '');
  };

  this.$$rewriteAppUrl = function(absoluteLinkUrl) {
    if(absoluteLinkUrl.indexOf(appBaseUrl) == 0) {
      return absoluteLinkUrl;
    }
  }


  this.$$parse(url);
}
873578
function makeRelPath(sourceUrl, targetUrl) {
  var source = sourceUrl.pathname;
  var target = targetUrl.pathname;
  var s = source.split('/');
  var t = target.split('/');
  while (s.length && s[0] === t[0]){
    s.shift();
    t.shift();
  }
  for (var i = 0, l = s.length - 1; i < l; i++) {
    t.unshift('..');
  }
  // empty '#' is discarded but we need to preserve it.
  var hash = (targetUrl.href.slice(-1) === URL_HASH) ? URL_HASH : targetUrl.hash;
  return t.join('/') + targetUrl.search + hash;
}
53062
function normalizeUrl(url, options)
{
	var portSuffix;
	url = parseUrl(url, options);
	
	// Remove default port
	if (url.extra.portIsDefault===true && url.port!==null)
	{
		if (isString(url.host) === true)
		{
			portSuffix = ":" + url.port;
			
			// Remove ":123" suffix from host
			if (url.host.substr(-portSuffix.length) === portSuffix)
			{
				url.host = url.host.slice(0, -portSuffix.length);
			}
		}
		
		url.port = null;
	}
	
	url.extra.directory = normalizeDirs(url.extra.directory, url.extra.directoryLeadingSlash).dir;
	
	url.pathname = formatPathname(url);
	
	// Remove empty query
	if (url.search === "?")
	{
		url.search = null;
		
		if (url.query==="?" || url.query==="") url.query = null;
	}
	
	// TODO :: remove empty hashes ("path#") ?
	
	url.path = formatPath(url);
	
	url.href = urllib.format(url);
	
	return url;
}
125775
function getExpressRoutePrefix(site) {
  let prefix = site.host;

  if (site.path.length > 1) {
    prefix += site.path;
  }

  return prefix;
}
1096653
async function onLocationChange(location, action) {
  // Remember the latest scroll position for the previous location
  scrollPositionsHistory[currentLocation.key] = {
    scrollX: window.pageXOffset,
    scrollY: window.pageYOffset,
  };
  // Delete stored scroll position for next page if any
  if (action === 'PUSH') {
    delete scrollPositionsHistory[location.key];
  }
  currentLocation = location;

  const isInitialRender = !action;
  try {
    context.pathname = location.pathname;
    context.query = queryString.parse(location.search);

    // Traverses the list of routes in the order they are defined until
    // it finds the first route that matches provided URL path string
    // and whose action method returns anything other than `undefined`.
    const route = await router.resolve(context);

    // Prevent multiple page renders during the routing process
    if (currentLocation.key !== location.key) {
      return;
    }

    if (route.redirect) {
      history.replace(route.redirect);
      return;
    }

    const renderReactApp = isInitialRender ? ReactDOM.hydrate : ReactDOM.render;
    appInstance = renderReactApp(
      <App context={context}>{route.component}</App>,
      container,
      () => {
        if (isInitialRender) {
          // Switch off the native scroll restoration behavior and handle it manually
          // https://developers.google.com/web/updates/2015/09/history-api-scroll-restoration
          if (window.history && 'scrollRestoration' in window.history) {
            window.history.scrollRestoration = 'manual';
          }

          const elem = document.getElementById('css');
          if (elem) elem.parentNode.removeChild(elem);
          return;
        }

        document.title = route.title;

        updateMeta('description', route.description);
        // Update necessary tags in <head> at runtime here, ie:
        // updateMeta('keywords', route.keywords);
        // updateCustomMeta('og:url', route.canonicalUrl);
        // updateCustomMeta('og:image', route.imageUrl);
        // updateLink('canonical', route.canonicalUrl);
        // etc.

        let scrollX = 0;
        let scrollY = 0;
        const pos = scrollPositionsHistory[location.key];
        if (pos) {
          scrollX = pos.scrollX;
          scrollY = pos.scrollY;
        } else {
          const targetHash = location.hash.substr(1);
          if (targetHash) {
            const target = document.getElementById(targetHash);
            if (target) {
              scrollY = window.pageYOffset + target.getBoundingClientRect().top;
            }
          }
        }

        // Restore the scroll position if it was saved into the state
        // or scroll to the given #hash anchor
        // or scroll to top of the page
        window.scrollTo(scrollX, scrollY);

        // Google Analytics tracking. Don't send 'pageview' event after
        // the initial rendering, as it was already sent
        if (window.ga) {
          window.ga('send', 'pageview', createPath(location));
        }
      },
    );
  } catch (error) {
    if (__DEV__) {
      throw error;
    }

    console.error(error);

    // Do a full page reload if error occurs during client-side navigation
    if (!isInitialRender && currentLocation.key === location.key) {
      console.error('RSK will reload your page after error');
      window.location.reload();
    }
  }
}
987129
function hasHTMLExtension(url, callback) {
    var extension = path.extname(url);
    if (extension === "" || extension === ".html" /* || extension === ".htm" */) {
        return callback(true, extension);
    } else {
        return callback(false);
    }
}
990352
function getUrlForRouter(urlStr) {
        urlStr = urlStr || location.href;
        var uri = url.parse(urlStr);
        if (!globalConfig.useHash && supportHistoryPushState) {
            return uri.pathname.substr(globalConfig.urlRoot.length) + (uri.search || '');
        } else {
            return utils.getHash(urlStr);
        }
    }
453931
function( url, data ) {
            data = data || {};

            //if there's forward history, wipe it
            if ( this.getNext() ) {
                this.clearForward();
            }

            // if the hash is included in the data make sure the shape
            // is consistent for comparison
            if ( data.hash && data.hash.indexOf( "#" ) === -1) {
                data.hash = "#" + data.hash;
            }

            data.url = url;
            this.stack.push( data );
            this.activeIndex = this.stack.length - 1;
        }
1180196
function(){
        var url = window.location.href;
        var vars = {};
        var hashes = url.slice(url.indexOf('#') + 1).split('&');
        for(var i=0; i<hashes.length; i++) {
            var hash = hashes[i].split('=');
            if(hash.length > 1) {
                vars[hash[0]] = hash[1];
            } else {
                vars[hash[0]] = null;
            }
        }
        return vars;
    }
105214
function parseUrlHash_(hash) {
    const parameters = hash.split('&');

    let tabHash = parameters[0];
    if (tabHash === '' || tabHash === '#') {
      tabHash = undefined;
    }

    // Split each string except the first around the '='.
    let paramDict = null;
    for (let i = 1; i < parameters.length; i++) {
      const paramStrings = parameters[i].split('=');
      if (paramStrings.length !== 2) {
        continue;
      }
      if (paramDict === null) {
        paramDict = {};
      }
      const key = decodeURIComponent(paramStrings[0]);
      const value = decodeURIComponent(paramStrings[1]);
      paramDict[key] = value;
    }

    return {tabHash, parameters: paramDict};
  }
480959
function parseUrl(url, params) {
  var paramsStr = '';

  if (typeof params === 'string') {
    paramsStr = params;
  } else if ((typeof params === 'undefined' ? 'undefined' : _typeof(params)) === 'object') {
    Object.keys(params).forEach(function (key) {
      if (url.indexOf(key + '=') < 0) {
        paramsStr += '&' + key + '=' + encodeURIComponent(params[key]);
      }
    });
  }
  // add a timestampe to remove cache
  paramsStr += '&_time=' + getNow();

  if (paramsStr[0] === '&') {
    paramsStr = paramsStr.substr(1);
  }

  return url + (url.indexOf('?') === -1 ? '?' : '&') + paramsStr;
}
529848
function fetch(params) {
    let fetchObj = null;
    if (/^http(s{0,1}):\/\//.test(params.url)) {
        const pageLoc = location.href.match(/^https{0,1}:\/\/(.+?)(?=\/|$)/);
        const ajaxLoc = params.url.match(/^https{0,1}:\/\/(.+?)(?=\/|$)/);
        if (pageLoc.length === 2 && ajaxLoc.length === 2 && ajaxLoc[1] === pageLoc[1]) {
            fetchObj = this.ajax(params);
        } else {
            fetchObj = this.jsonp(params);
        }
    } else {
        fetchObj = this.ajax(params);
    }
    return fetchObj;
}
1159644
function setUrlHashParameters(params) {

  var keys = Object.keys(params);
  var values = Object.values(params);
  var pairs = [];
  keys.forEach(function(key, i) {
    if (key != '') pairs.push(keys[i] + '=' + values[i]);
  });
  var hash = pairs.join('&');
  window.location.hash = hash;

}
323307
function () {
                return {
                    href: location.href,
                    hash: location.hash,
                    host: location.host,
                    hostName: location.hostname,
                    port: location.port,
                    protocol: location.protocol
                };
            }
1311171
function onHashChange(event) {
    // https://github.com/devote/HTML5-History-API/issues/46
    var fireNow = lastURL;
    // new value to lastURL
    lastURL = windowLocation.href;
    // if not empty fireNow, otherwise skipped the current handler event
    if (fireNow) {
      // if checkUrlForPopState equal current url, this means that the event was raised popstate browser
      if (checkUrlForPopState !== windowLocation.href) {
        // otherwise,
        // the browser does not support popstate event or just does not run the event by changing the hash.
        firePopState();
      }
      // current event object
      event = event || global.event;

      var oldURLObject = parseURL(fireNow, true);
      var newURLObject = parseURL();
      // HTML4 browser not support properties oldURL/newURL
      if (!event.oldURL) {
        event.oldURL = oldURLObject._href;
        event.newURL = newURLObject._href;
      }
      if (oldURLObject._hash !== newURLObject._hash) {
        // if current hash not equal previous hash
        dispatchEvent(event);
      }
    }
  }
156011
@Override
	public String getURLPrefix(Map<String, String> variants) {

		if (null == this.urlPrefix)
			throw new IllegalStateException("The bundleDataHashCode must be set before accessing the url prefix.");

		if (variants != null && !variants.isEmpty()) {
			String key = getAvailableVariant(variants);
			if (StringUtils.isNotEmpty(key)) {
				return prefixMap.get(key) + "." + key + "/";
			}
		}
		return this.urlPrefix + "/";
	}
1325766
function(url) {
      if (!isSupportHistoryAPI && ('' + url).indexOf('#') === 0) {
        changeState(null, url);
      } else {
        windowLocation.assign(url);
      }
    }