docs: function urlFor(context, data, absolute) {
      var urlPath = '/',
          secure, imagePathRe,
          knownObjects = ['image', 'nav'], baseUrl,
          hostname,
  
          // this will become really big
          knownPaths = {
              home: '/',
              sitemap_xsl: '/sitemap.xsl'
          };
  
      // Make data properly optional
      if (_.isBoolean(data)) {
          absolute = data;
          data = null;
      }
  
      // Can pass 'secure' flag in either context or data arg
      secure = (context && context.secure) || (data && data.secure);
  
      if (_.isObject(context) && context.relativeUrl) {
          urlPath = context.relativeUrl;
      } else if (_.isString(context) && _.indexOf(knownObjects, context) !== -1) {
          if (context === 'image' && data.image) {
              urlPath = data.image;
              imagePathRe = new RegExp('^' + getSubdir() + '/' + STATIC_IMAGE_URL_PREFIX);
              absolute = imagePathRe.test(data.image) ? absolute : false;
  
              if (absolute) {
                  // Remove the sub-directory from the URL because ghostConfig will add it back.
                  urlPath = urlPath.replace(new RegExp('^' + getSubdir()), '');
                  baseUrl = getBlogUrl(secure).replace(/\/$/, '');
                  urlPath = baseUrl + urlPath;
              }
  
              return urlPath;
          } else if (context === 'nav' && data.nav) {
              urlPath = data.nav.url;
              secure = data.nav.secure || secure;
              baseUrl = getBlogUrl(secure);
              hostname = baseUrl.split('//')[1];
  
              // If the hostname is present in the url
              if (urlPath.indexOf(hostname) > -1
                  // do no not apply, if there is a subdomain, or a mailto link
                  && !urlPath.split(hostname)[0].match(/\.|mailto:/)
                  // do not apply, if there is a port after the hostname
                  && urlPath.split(hostname)[1].substring(0, 1) !== ':') {
                  // make link relative to account for possible mismatch in http/https etc, force absolute
                  urlPath = urlPath.split(hostname)[1];
                  urlPath = urlJoin('/', urlPath);
                  absolute = true;
              }
          }
      } else if (context === 'home' && absolute) {
          urlPath = getBlogUrl(secure);
  
          // CASE: there are cases where urlFor('home') needs to be returned without trailing
          // slash e. g. the `{{@site.url}}` helper. See https://github.com/TryGhost/Ghost/issues/8569
          if (data && data.trailingSlash === false) {
              urlPath = urlPath.replace(/\/$/, '');
          }
      } else if (context === 'admin') {
          urlPath = getAdminUrl() || getBlogUrl();
  
          if (absolute) {
              urlPath += 'ghost/';
          } else {
              urlPath = '/ghost/';
          }
      } else if (context === 'api') {
          urlPath = getAdminUrl() || getBlogUrl();
          let apiPath = getApiPath({version: 'v0.1', type: 'content'});
          // CASE: with or without protocol? If your blog url (or admin url) is configured to http, it's still possible that e.g. nginx allows both https+http.
          // So it depends how you serve your blog. The main focus here is to avoid cors problems.
          // @TODO: rename cors
          if (data && data.cors) {
              if (!urlPath.match(/^https:/)) {
                  urlPath = urlPath.replace(/^.*?:\/\//g, '//');
              }
          }
  
          if (data && data.version) {
              apiPath = getApiPath({version: data.version, type: data.versionType});
          }
  
          if (absolute) {
              urlPath = urlPath.replace(/\/$/, '') + apiPath;
          } else {
              urlPath = apiPath;
          }
      } else if (_.isString(context) && _.indexOf(_.keys(knownPaths), context) !== -1) {
          // trying to create a url for a named path
          urlPath = knownPaths[context];
      }
  
      // This url already has a protocol so is likely an external url to be returned
      // or it is an alternative scheme, protocol-less, or an anchor-only path
      if (urlPath && (urlPath.indexOf('://') !== -1 || urlPath.match(/^(\/\/|#|[a-zA-Z0-9-]+:)/))) {
          return urlPath;
      }
  
      return createUrl(urlPath, absolute, secure);
  }