source map exposed analyzed
https://www.antuit.ai/hs/hsstatic/HubspotToolsMenu/static-1.640/js/index.js
map: https://static.hsappstatic.net/HubspotToolsMenu/static-1.640/js/index.js.map
24 source files 43.9 KB map size 0 endpoints found 1 secrets found discovered 6 hours, 34 minutes ago
24
source files
43.9 KB
map size
1
secrets
0
endpoints

secrets from source map (1)

internal_url fetch(`http://localhost:1442/check-if-local-dev-server?${params}`).then(response => { 0.8
Source map: bpm:///[email protected]/js/SprocketMenu.js
    const onFailure = this.setLocalDevServerFailure.bind(this);
    resetUI(localDevServerButton);
    fetch(`http://localhost:1442/check-if-local-dev-server?${params}`).then(response => {
      if (!response.ok) {
        throw response.statusText;

source file tree (24)

24 files with original source
bpm:///[email protected]/icons/sprocket_white.svg
module.exports = "//static.hsappstatic.net/HubspotToolsMenu/static-1.640/icons/sprocket_white.svg"
bpm:///[email protected]/icons/sprocket_orange.svg
module.exports = "//static.hsappstatic.net/HubspotToolsMenu/static-1.640/icons/sprocket_orange.svg"
bpm:///[email protected]/icons/Edit.svg
module.exports = "//static.hsappstatic.net/HubspotToolsMenu/static-1.640/icons/Edit.svg"
bpm:///[email protected]/icons/ViewDetails.svg
module.exports = "//static.hsappstatic.net/HubspotToolsMenu/static-1.640/icons/ViewDetails.svg"
bpm:///[email protected]/icons/SiteTree.svg
module.exports = "//static.hsappstatic.net/HubspotToolsMenu/static-1.640/icons/SiteTree.svg"
bpm:///[email protected]/icons/ExternalLink.svg
module.exports = "//static.hsappstatic.net/HubspotToolsMenu/static-1.640/icons/ExternalLink.svg"
bpm:///[email protected]/icons/Gauge.svg
module.exports = "//static.hsappstatic.net/HubspotToolsMenu/static-1.640/icons/Gauge.svg"
bpm:///[email protected]/icons/Code.svg
module.exports = "//static.hsappstatic.net/HubspotToolsMenu/static-1.640/icons/Code.svg"
bpm:///[email protected]/icons/HtmlFile.svg
module.exports = "//static.hsappstatic.net/HubspotToolsMenu/static-1.640/icons/HtmlFile.svg"
bpm:///[email protected]/icons/Warning.svg
module.exports = "//static.hsappstatic.net/HubspotToolsMenu/static-1.640/icons/Warning.svg"
bpm:///[email protected]/icons/Menu.svg
module.exports = "//static.hsappstatic.net/HubspotToolsMenu/static-1.640/icons/Menu.svg"
bpm:///[email protected]/icons/Desktop.svg
module.exports = "//static.hsappstatic.net/HubspotToolsMenu/static-1.640/icons/Desktop.svg"
bpm:///[email protected]/icons/Hide.svg
module.exports = "//static.hsappstatic.net/HubspotToolsMenu/static-1.640/icons/Hide.svg"
bpm:///[email protected]/icons/Remove.svg
module.exports = "//static.hsappstatic.net/HubspotToolsMenu/static-1.640/icons/Remove.svg"
bpm:///[email protected]/css/toolsmenu.css
module.exports = "//static.hsappstatic.net/HubspotToolsMenu/static-1.640/css/toolsmenu.css"
webpack://webpack/bootstrap
// The module cache
var __webpack_module_cache__ = {};

// The require function
function __webpack_require__(moduleId) {
	// Check if module is in cache
	var cachedModule = __webpack_module_cache__[moduleId];
	if (cachedModule !== undefined) {
		return cachedModule.exports;
	}
	// Create a new module (and put it into the cache)
	var module = __webpack_module_cache__[moduleId] = {
		// no module.id needed
		// no module.loaded needed
		exports: {}
	};

	// Execute the module function
	__webpack_modules__[moduleId].call(module.exports, module, module.exports, __webpack_require__);

	// Return the exports of the module
	return module.exports;
}

webpack://webpack/runtime/compat get default export
// getDefaultExport function for compatibility with non-harmony modules
__webpack_require__.n = function(module) {
	var getter = module && module.__esModule ?
		function() { return module['default']; } :
		function() { return module; };
	__webpack_require__.d(getter, { a: getter });
	return getter;
};
webpack://webpack/runtime/define property getters
// define getter functions for harmony exports
__webpack_require__.d = function(exports, definition) {
	for(var key in definition) {
		if(__webpack_require__.o(definition, key) && !__webpack_require__.o(exports, key)) {
			Object.defineProperty(exports, key, { enumerable: true, get: definition[key] });
		}
	}
};
webpack://webpack/runtime/hasOwnProperty shorthand
__webpack_require__.o = function(obj, prop) { return Object.prototype.hasOwnProperty.call(obj, prop); }
bpm:///[email protected]/js/localVersionOverride.js
/* hs-eslint ignored failing-rules */
/* eslint-disable hubspot-dev/no-unsafe-storage */

'use es6';

const LOCAL_STORAGE_KEY = 'HS_SPROCKET_MENU_LOCAL_OVERRIDE';
const LOCAL_SRC = 'https://local.hsappstatic.net/HubspotToolsMenu/static-1.640/js/index.js';
const localScriptExists = () => Array.from(document.body.getElementsByTagName('script')).some(scriptEl => scriptEl.src === LOCAL_SRC);
export const isLocal = () => {
  const useLocal = window.localStorage.getItem(LOCAL_STORAGE_KEY) || false;
  if (useLocal) {
    // Assume that this IS the local version if the local script already exists
    return !localScriptExists();
  }
  return false;
};
export const loadLocalVersion = () => {
  const newScript = document.createElement('script');
  newScript.src = LOCAL_SRC;
  newScript.onload = () => {
    // Give the app a bit of time to load
    setTimeout(() => {
      const loadEvent = new Event('DOMContentLoaded');
      document.dispatchEvent(loadEvent);
    }, 100);
  };
  document.body.appendChild(newScript);
};
if (isLocal()) {
  loadLocalVersion();
}
bpm:///[email protected]/js/constants.js
'use es6';

export const localDevClassList = {
  SUCCESS: 'hs-local-dev-server--success',
  WARNING: 'hs-local-dev-server--warning',
  FAILURE: 'hs-local-dev-server--failed'
};
bpm:///[email protected]/js/SprocketMenu.js
/* hs-eslint ignored failing-rules */
/* eslint-disable hubspot-dev/no-unsafe-storage */
/* eslint-disable hubspot-dev/no-confusing-browser-globals */

'use es6';

import sprocketWhiteImageUrl from 'bender-url!../icons/sprocket_white.svg';
import sprocketOrangeImageUrl from 'bender-url!../icons/sprocket_orange.svg';
import editIconUrl from 'bender-url!../icons/Edit.svg';
import viewDetailsIconUrl from 'bender-url!../icons/ViewDetails.svg';
import siteTreeIconUrl from 'bender-url!../icons/SiteTree.svg';
import externalLinkIconUrl from 'bender-url!../icons/ExternalLink.svg';
import gaugeIconUrl from 'bender-url!../icons/Gauge.svg';
import codeIconUrl from 'bender-url!../icons/Code.svg';
import htmlFileIconUrl from 'bender-url!../icons/HtmlFile.svg';
import warningIconUrl from 'bender-url!../icons/Warning.svg';
import menuIconUrl from 'bender-url!../icons/Menu.svg';
import desktopIconUrl from 'bender-url!../icons/Desktop.svg';
import hideIconUrl from 'bender-url!../icons/Hide.svg';
import removeIconUrl from 'bender-url!../icons/Remove.svg';
import toolsMenuCssUrl from 'bender-url!../css/toolsmenu.css';
import { localDevClassList } from './constants';

// Helper function to create icon HTML from URLs
const createIcon = (url, className = 'hs-action-menu-icon') => `<img class="${className}" src="${url}" alt="" aria-hidden="true" />`;

// Icon HTML strings (imported from static/icons/ directory)
const ICONS = {
  edit: createIcon(editIconUrl),
  viewDetails: createIcon(viewDetailsIconUrl),
  siteTree: createIcon(siteTreeIconUrl),
  externalLink: createIcon(externalLinkIconUrl),
  gauge: createIcon(gaugeIconUrl),
  code: createIcon(codeIconUrl),
  file: createIcon(htmlFileIconUrl),
  warning: createIcon(warningIconUrl),
  menu: createIcon(menuIconUrl),
  desktop: createIcon(desktopIconUrl),
  hide: createIcon(hideIconUrl),
  close: createIcon(removeIconUrl, 'hs-remove-icon')
};
export default class SprocketMenu {
  constructor(options) {
    this.baseUrl = this.getHsBaseUrl(options.app_hs_base_url);
    this.cpBaseUrl = this.getHsBaseUrl(options.cp_hs_base_url);
    this.contentId = options.dynamic_page_id && options.dynamic_page_id !== '0' && options.dynamic_page_id !== 'null' ? options.dynamic_page_id : options.page_id;
    this.categoryId = options.category_id;
    this.contentGroupId = options.content_group_id;
    this.portalId = options.portal_id;
    this.environments = {
      PRODUCTION: 1,
      STAGING: 2
    };
    this.isCustomerPortal = options.is_customer_portal === true;
    this.cmsEnvironment = this.getCmsEnvironmentFromCookie();
    this.contentUrl = this.getHsContentUrl();
    this.permissionObj = {};
    this.dynamic_page_id = options.dynamic_page_id;

    // Override the content ID for SCP.
    if (options.scp_id && options.scp_id !== '0' && options.scp_id !== 'null') {
      this.contentId = options.scp_id;
    }
  }
  getHsBaseUrl(baseUrl) {
    return window.localStorage.getItem('HS_LOCAL_TESTING') ? baseUrl.replace(/[^/](\w+?)(?=\.)/, 'local') : baseUrl;
  }
  getHsContentUrl() {
    const contentUrl = window.location.href.split('?')[0];
    const searchParams = new URLSearchParams(window.location.search);
    if (searchParams.has('hs_preview')) {
      return `${contentUrl}?hs_preview=${searchParams.get('hs_preview')}`;
    } else {
      return contentUrl;
    }
  }
  createElementFromHTML(htmlString) {
    const div = document.createElement('div');
    div.innerHTML = htmlString.trim();
    return div.firstChild;
  }
  jsonp(url, callback) {
    window.jsonpHandler = data => {
      callback(data);
    };
    const src = `${url}${url.indexOf('?') !== -1 ? '&' : '?'}callback=jsonpHandler`;
    const script = document.createElement('script');
    script.type = 'text/javascript';
    script.referrerPolicy = 'no-referrer-when-downgrade';
    script.async = true;
    script.src = src;
    document.getElementsByTagName('head')[0].appendChild(script);
  }
  httpGet(url, callback) {
    const request = new XMLHttpRequest();
    request.withCredentials = true;
    request.onreadystatechange = function () {
      if (this.readyState === 4 && this.status === 200) {
        callback(JSON.parse(this.responseText));
      }
    };
    request.open('GET', url, true);
    request.send();
  }
  showToolsMenuIfAuthor() {
    let resourceName;
    let resourceId = this.contentId;
    const resourceUrl = this.contentUrl;
    let canPrefetchEditorForResource = false;
    if (this.isCustomerPortal) {
      resourceName = 'customer-portal';
    } else if (window.location.pathname.endsWith('_hcms/mem/login')) {
      resourceName = 'content-membership';
    } else if (this.categoryId === 20) {
      resourceName = 'app-pages';
    } else if (this.contentId && this.contentGroupId) {
      if (this.categoryId === 7) {
        resourceName = 'blog-listing-pages';
      } else if (this.categoryId === 6) {
        resourceName = 'knowledge-articles';
      } else if (this.categoryId === 12) {
        // If dynamic page ID is present, this is a KBv3 article.
        if (this.dynamic_page_id) {
          resourceName = 'knowledge-articles';
        } else {
          // Otherwise, it's a static page, so get the KB action menu.
          resourceName = 'knowledge-bases';
          resourceId = this.contentGroupId;
        }
      } else if (this.categoryId === 13) {
        resourceName = 'case-studies';
      } else {
        resourceName = 'blog-posts';
      }
    } else if (this.contentGroupId) {
      if (this.categoryId === 6) {
        resourceName = 'knowledge-bases';
      } else {
        resourceName = 'blogs';
      }
      resourceId = this.contentGroupId;
    } else {
      canPrefetchEditorForResource = true;
      resourceName = 'landing-pages';
    }
    const hasPermissionUrl = `${this.baseUrl}/content-tools-menu/api/v1/tools-menu/has-permission-json?portalId=${this.portalId}`;
    this.httpGet(hasPermissionUrl, data => {
      if (data.has_permission) {
        const permissionsUrl = `${this.cpBaseUrl}/content-tools-menu/api/v1/tools-menu/permissions?portalId=${this.portalId}`;
        this.httpGet(permissionsUrl, response => {
          this.permissionObj = response;
          if (resourceName === 'content-membership') {
            this.getContentMembershipCookie(resourceName, this.portalId);
          } else {
            this.getAppLinks(resourceName, resourceId, this.portalId, resourceUrl);
          }
          if (canPrefetchEditorForResource) {
            this.setupDeferredPrefetchingOfEditorAssets(resourceName);
          }
        });
      }
    });
  }
  getContentMembershipCookie(resourceName, portalId) {
    this.jsonp(`${this.baseUrl}/content-tools-menu/api/v1/content/validate-hubspot-user?redirect_url=${window.location.href}&portalId=${portalId}`, data => {
      if (data && data.verified) {
        const redirectUrl = this.getUrlParameter('redirect_url');
        const finalRedirectUrl = redirectUrl || data.redirectUrl || window.location.origin;
        window.location.href = `/_hcms/mem/automatic-login-loading-message?redirect_url=${finalRedirectUrl}`;
      }
    });
  }
  getAppLinks(resourceName, pk, portalId, contentUrl) {
    // For app-pages, skip fetching actions but allow permission checks to complete
    if (resourceName === 'app-pages') {
      // Don't render any menu
      return;
    }
    this.httpGet(`${this.baseUrl}/content-tools-menu/api/v1/tools-menu/${resourceName}/${pk}/actions-json?portalId=${portalId}&clientUrl=${contentUrl}`, data => {
      if (data.actions && data.strings) {
        this.showAppLinks(data.actions, data.strings);
      }
    });
  }
  renderAction(link, icon = '') {
    const className = link[2] ? `class='${link[2]}'` : '';
    const href = link[1] ? `href='${link[1]}'` : '';
    return `\
<li><a target='_blank' ${href} ${className}>
${icon}
<span>${link[0]}</span>
</a></li>\
`;
  }

  /**
   * Maps menu action text to icons using substring matching.
   *
   * KNOWN LIMITATION: This is fragile to server-side copy changes and
   * localization. Ideally the server should provide an 'icon' or 'actionType'
   * field on each action. This is a follow-up candidate.
   */
  getIconForAction(actionText) {
    // Map action text to icon
    if (actionText.includes('Edit') && !actionText.includes('Template') && !actionText.includes('Navigation')) {
      return ICONS.edit;
    }
    if (actionText.includes('View') && actionText.includes('Details')) {
      return ICONS.viewDetails;
    }
    if (actionText.includes('Site Pages') || actionText.includes('Pages')) {
      return ICONS.siteTree;
    }
    if (actionText.includes('Redirect') || actionText.includes('URL')) {
      return ICONS.externalLink;
    }
    if (actionText.includes('Speed') || actionText.includes('Track')) {
      return ICONS.gauge;
    }
    if (actionText.includes('Developer')) {
      return ICONS.code;
    }
    if (actionText.includes('Template') || actionText.includes('File')) {
      return ICONS.file;
    }
    if (actionText.includes('Alert') || actionText.includes('Warning')) {
      return ICONS.warning;
    }
    if (actionText.includes('Navigation') || actionText.includes('Menu')) {
      return ICONS.siteTree;
    }
    // Default icon
    return ICONS.viewDetails;
  }
  showAppLinks(actions, strings) {
    // Insert site maps link if there is a site map on the page
    const mapWidgets = [].slice.call(document.querySelectorAll('[data-menu-id]')).filter(element => !!element.getAttribute('data-menu-id').trim());
    const mapWidget = mapWidgets.length > 0 ? mapWidgets[0] : null;
    if (mapWidget !== null) {
      const dataMenuId = mapWidget.getAttribute('data-menu-id').trim();
      actions.push([strings.EDIT_NAVIGATION_MENU, `${this.baseUrl}/menus/${this.portalId}/edit/${dataMenuId}`]);
    }

    // Render action links with icons
    let links = actions.map(action => this.renderAction(action, this.getIconForAction(action[0]))).join('');

    // Add environment switching options if user has permissions
    if (this.permissionObj.permissions.includes('CAN_PREVIEW_ENVIRONMENTS')) {
      links += `\
        <li><a class="hs-environment-buffer-on">${ICONS.viewDetails}<span>${strings.VIEW_BUFFER}</span></a></li>\
        <li><a class="hs-environment-buffer-off">${ICONS.viewDetails}<span>${strings.VIEW_HARD}</span></a></li>\
      `;
      links += `\
        <li><a class="hs-environment-staging">${ICONS.viewDetails}<span>${strings.VIEW_STAGING}</span></a></li>\
        <li><a class="hs-environment-production">${ICONS.viewDetails}<span>${strings.VIEW_PRODUCTION}</span></a></li>\
      `;
    }
    const css = `<link rel="stylesheet" href="${toolsMenuCssUrl}" />`;
    const menu = `
      <div class="hs-tools-menu hs-collapsed" aria-label="HubSpot Tools Menu">
        <button class="hs-sprocket-button" aria-expanded="false" aria-label="Toggle menu">
          <img class="hs-sprocket-icon" alt="${strings.MENU_ICON_ALT_TEXT}" src="${sprocketWhiteImageUrl}" />
        </button>
        <div class="hs-tools-menu-dropdown" aria-hidden="true">
          <div class="hs-tools-menu-header">
            <img class="hs-sprocket-logo" src="${sprocketOrangeImageUrl}" alt="" />
            <span class="hs-tools-menu-title">${strings.MENU_TITLE}</span>
          </div>
          <hr class="hs-tools-menu-divider" />
          <ul class="hs-tools-actions">
            ${links}
          </ul>
          <hr class="hs-tools-menu-divider" />
          <div class="hs-tools-menu-footer">
            <button class="hs-tools-menu-item-button hs-local-dev-server" type="button">
              ${ICONS.desktop}
              <span>Local Dev Server</span>
              <div class="hs-toggle-switch">
                <div class="hs-toggle-track"></div>
                <div class="hs-toggle-knob"></div>
              </div>
            </button>
            <button class="hs-tools-menu-item-button hs-tools-menu-hider" type="button">
              ${ICONS.hide}
              <span>${strings.HIDE_THIS_MENU}</span>
            </button>
          </div>
        </div>
      </div>
    `;
    document.body.appendChild(this.createElementFromHTML(css));
    document.body.appendChild(this.createElementFromHTML(menu));
    this.registerEvents();
  }
  registerEvents() {
    const element = document.querySelector('.hs-tools-menu');
    this.registerDropdown(element);

    // Hide menu button
    element.querySelector('.hs-tools-menu-hider').addEventListener('click', event => {
      event.preventDefault();
      event.stopPropagation();
      element.style.display = 'none';
    });

    // Local dev server button
    const localDevButton = element.querySelector('.hs-local-dev-server');
    if (localDevButton) {
      localDevButton.addEventListener('click', event => {
        event.preventDefault();
        event.stopPropagation();
        this.setUpLocalDevUrl();
      });
    }
    const bufferOn = element.querySelector('.hs-environment-buffer-on');
    if (bufferOn) {
      if (!this.cmsEnvironment.buffer) {
        bufferOn.addEventListener('click', event => {
          event.preventDefault();
          event.stopPropagation();
          this.requestAndSetEnvironmentCookie(this.portalId, true, this.cmsEnvironment.environmentId);
        });
      } else {
        bufferOn.parentElement.removeChild(bufferOn);
      }
    }
    const bufferOff = element.querySelector('.hs-environment-buffer-off');
    if (bufferOff) {
      if (this.cmsEnvironment.buffer) {
        bufferOff.addEventListener('click', event => {
          event.preventDefault();
          event.stopPropagation();
          this.requestAndSetEnvironmentCookie(this.portalId, false, this.cmsEnvironment.environmentId);
        });
      } else {
        bufferOff.parentElement.removeChild(bufferOff);
      }
    }
    const stagingEnv = element.querySelector('.hs-environment-staging');
    if (stagingEnv) {
      if (this.cmsEnvironment.environmentId !== this.environments.STAGING) {
        stagingEnv.addEventListener('click', event => {
          event.preventDefault();
          event.stopPropagation();
          this.requestAndSetEnvironmentCookie(this.portalId, this.cmsEnvironment.buffer, this.environments.STAGING);
        });
      } else {
        stagingEnv.parentElement.removeChild(stagingEnv);
      }
    }
    const productionEnv = element.querySelector('.hs-environment-production');
    if (productionEnv) {
      if (this.cmsEnvironment.environmentId !== this.environments.PRODUCTION) {
        productionEnv.addEventListener('click', event => {
          event.preventDefault();
          event.stopPropagation();
          this.requestAndSetEnvironmentCookie(this.portalId, this.cmsEnvironment.buffer, this.environments.PRODUCTION);
        });
      } else {
        productionEnv.parentElement.removeChild(productionEnv);
      }
    }
  }
  requestAndSetEnvironmentCookie(portalId, buffer, environmentId) {
    const cookieUrl = `${this.cpBaseUrl}/content-tools-menu/api/v1/tools-menu/environment-cookie?portalId=${portalId}&environmentId=${environmentId}&buffer=${buffer}`;
    this.httpGet(cookieUrl, data => {
      document.cookie = `hs_cms_environment=${btoa(JSON.stringify(data))}`;
      window.location.reload();
    });
  }
  registerDropdown(element) {
    const sprocketButton = element.querySelector('.hs-sprocket-button');
    const dropdown = element.querySelector('.hs-tools-menu-dropdown');
    const hideDropdown = () => {
      element.classList.add('hs-collapsed');
      sprocketButton.setAttribute('aria-expanded', 'false');
      dropdown.setAttribute('aria-hidden', 'true');
      const icon = sprocketButton.querySelector('img');
      if (icon) {
        icon.src = sprocketWhiteImageUrl;
        icon.className = 'hs-sprocket-icon';
        icon.alt = 'Toggle menu';
      }
    };
    const showDropdown = () => {
      element.classList.remove('hs-collapsed');
      sprocketButton.setAttribute('aria-expanded', 'true');
      dropdown.setAttribute('aria-hidden', 'false');
      const icon = sprocketButton.querySelector('img');
      if (icon) {
        icon.src = removeIconUrl;
        icon.className = 'hs-remove-icon';
        icon.alt = '';
      }

      // Remove display: none on first show to prevent flash
      dropdown.style.display = '';
    };
    const bodyClickHandler = () => {
      hideDropdown();
      document.body.removeEventListener('click', bodyClickHandler);
    };
    const buttonClickHandler = event => {
      event.preventDefault();
      event.stopPropagation();
      if (element.classList.contains('hs-collapsed')) {
        showDropdown();
        document.body.addEventListener('click', bodyClickHandler);
      } else {
        hideDropdown();
        document.body.removeEventListener('click', bodyClickHandler);
      }
    };

    // Only attach click handler to the sprocket button
    sprocketButton.addEventListener('click', buttonClickHandler, false);

    // Prevent dropdown clicks from closing the menu
    dropdown.addEventListener('click', event => {
      // Allow links to navigate
      const link = event.target.closest('a[href]');
      if (link) {
        return;
      }
      event.stopPropagation();
    });
  }
  getUrlParameter(name) {
    name = name.replace(/[[]/, '\\[').replace(/[\]]/, '\\]');
    const regex = new RegExp(`[\\?&]${name}=([^&#]*)`);
    const results = regex.exec(location.search);
    return results === null ? '' : decodeURIComponent(results[1].replace(/\+/g, ' '));
  }
  getCmsEnvironmentFromCookie() {
    const cookieStr = this.getCookie('hs_cms_environment');
    if (cookieStr) {
      return JSON.parse(atob(cookieStr));
    } else {
      return {
        portalId: 0,
        environmentId: this.environments.PRODUCTION,
        buffer: false,
        createdAt: 0
      };
    }
  }
  getCookie(cookieName) {
    const name = `${cookieName}=`;
    const cookieArr = document.cookie.split(';');
    for (let i = 0; i < cookieArr.length; i++) {
      let c = cookieArr[i];
      while (c.charAt(0) === ' ') {
        c = c.substring(1);
      }
      if (c.indexOf(name) === 0) {
        return c.substring(name.length, c.length);
      }
    }
    return '';
  }

  // Two seconds after window load, fetch a small script that in turn, appends
  // abunch of <link rel="prefetch"> tags to the page. The idea is to use the
  // idle time of the users page load to get a jump start on loading the heavy
  // assets of the editor. The prefetches are given the lowest priority by the
  // browser, so it hopefully doesn't interfere with the users page.
  // See https://developer.mozilla.org/en-US/docs/Web/HTTP/Link_prefetching_FAQ
  setupDeferredPrefetchingOfEditorAssets(resourceName) {
    window.addEventListener('load', () => {
      setTimeout(() => {
        let prefetcherPath;
        if (resourceName === 'landing-pages') {
          prefetcherPath = 'content/editor/prefetcher.js';
        } else {
          return;
        }
        const script = document.createElement('script');
        script.src = `${this.baseUrl}/${prefetcherPath}`;
        document.head.appendChild(script);
      }, 2000);
    });
  }

  /* Local Dev Server / JS Building Blocks
     Sets up the local dev server link to a proxy url if the localhost server is running
  */
  setUpLocalDevUrl() {
    let hostName = window.location.hostname;
    let pathName = window.location.pathname;
    const pageQueryParams = window.location.search;
    const localDevServerButton = document.querySelector('.hs-tools-menu .hs-local-dev-server');

    // For when running with local renderer
    if (pageQueryParams) {
      pageQueryParams.slice('1').split('&').forEach(param => {
        if (param.indexOf('hsDebugOverridePublicHost') > -1) {
          hostName = param.split('=')[1];
          pathName = pathName.replace('/cos-rendering/v1/public', '');
        }
      });
    }
    const paramMap = {
      hostName,
      pathName,
      protocol: window.location.protocol,
      contentId: this.contentId,
      portalId: this.portalId
    };
    const params = Object.keys(paramMap).map(key => `${key}=${paramMap[key]}`).join('&');
    const resetUI = this.resetLocalDevLink.bind(this);
    const onSuccess = this.setLocalDevServerSuccess.bind(this);
    const onFailure = this.setLocalDevServerFailure.bind(this);
    resetUI(localDevServerButton);
    fetch(`http://localhost:1442/check-if-local-dev-server?${params}`).then(response => {
      if (!response.ok) {
        throw response.statusText;
      }
      return response.json();
    }).then(data => onSuccess(data, localDevServerButton)).catch(error => {
      console.error(error);
      onFailure(localDevServerButton);
    });
  }
  resetLocalDevLink(serverButton) {
    serverButton.classList.remove(localDevClassList.SUCCESS, localDevClassList.WARNING, localDevClassList.FAILURE);
    serverButton.removeAttribute('title');
  }
  setLocalDevServerSuccess(localDevData, serverButton) {
    if (!localDevData.localProxyUrl) {
      serverButton.classList.add(localDevClassList.WARNING);
      serverButton.setAttribute('title', 'Proxy unavailable - Click to retry');
      return;
    }
    serverButton.classList.add(localDevClassList.SUCCESS);
    window.open(localDevData.localProxyUrl, '_blank');
  }
  setLocalDevServerFailure(serverButton) {
    serverButton.classList.add(localDevClassList.FAILURE);
    serverButton.setAttribute('title', 'Local server not running - Click to retry');
  }
}
bpm:///[email protected]/js/PostFilterWidget.js
'use es6';

// Added this as a one off to fix the post filter widget. This wiring was
// previously included in public_common via common_init.js
export default class PostFilterWidget {
  constructor() {
    this.getShowAllFiltersLinkEventHandler = link => {
      return event => {
        const {
          previousElementSibling: {
            children
          }
        } = link;
        if (children) {
          [].slice.call(children, 0).forEach(child => {
            child.style.display = 'block';
          });
        }
        link.style.display = 'none';
        event.preventDefault();
        event.stopPropagation();
      };
    };
  }
  setup() {
    const filterLinksNodes = [].slice.call(document.querySelectorAll('.filter-expand-link'), 0);
    filterLinksNodes.forEach(link => {
      link.addEventListener('click', this.getShowAllFiltersLinkEventHandler(link));
    });
  }
}
bpm:///[email protected]/js/index.js
'use es6';

import { isLocal } from './localVersionOverride';
import SprocketMenu from './SprocketMenu';
import PostFilterWidget from './PostFilterWidget';
const isValidSprocketContext = () => {
  const windowLocation = window.location;
  const {
    port,
    hostname,
    pathname
  } = windowLocation;
  const isIframe = windowLocation !== window.parent.location;
  const isTemplatePreview = pathname.includes('_hcms/preview/template');
  const maybeLocalProxy = port !== '' || hostname.includes('hslocal.net') || hostname.includes('localhost');
  if (isIframe || isTemplatePreview || isLocal() || maybeLocalProxy) {
    return false;
  }
  return true;
};
(function () {
  /**
   * documentMode is an IE-only property
   * https://www.w3schools.com/jsref/prop_doc_documentmode.asp
   */
  // holds major version number for IE, or NaN if UA is not IE.
  // Support: IE 9-11 only
  const msie = window.document.documentMode;
  if (msie) {
    return;
  }
  const loadHubspotToolsMenu = () => {
    if (!window.hsVars || !window.hsVars.portal_id) {
      return;
    }
    const menu = new SprocketMenu(window.hsVars);
    menu.showToolsMenuIfAuthor();
    const postFilterWidget = new PostFilterWidget();
    postFilterWidget.setup();
  };
  if (isValidSprocketContext()) {
    if (document.readyState === 'loading') {
      document.addEventListener('DOMContentLoaded', function init() {
        loadHubspotToolsMenu();
        document.removeEventListener('DOMContentLoaded', init);
      }, false);
    } else {
      loadHubspotToolsMenu();
    }
  }
})();