Files
gerrit/polygerrit-ui/app/elements/shared/gr-lib-loader/gr-lib-loader.js
Wyatt Allen e60796ac6f Provide the static resource path via index
When the side loader for the syntax library was written, it needed to be
compatible with CDN configurations, but at that time the simplest way to
determine the CDN's path was by extracting it from the URL of the
application's main link element.

Since that time, the CDN path is provided to the page's index Soy
template using a trusted string. This can be safely inserted into the
page's JS block of constants and provided to the loader more directly.

Change-Id: I3a3432c1bf99a650645a7adf1d6979a900988ac4
2018-05-22 16:28:22 +00:00

157 lines
4.4 KiB
JavaScript

/**
* @license
* Copyright (C) 2016 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
(function() {
'use strict';
const HLJS_PATH = 'bower_components/highlightjs/highlight.min.js';
const DARK_THEME_PATH = 'styles/themes/dark-theme.html';
const LIB_ROOT_PATTERN = /(.+\/)elements\/gr-app\.html/;
Polymer({
is: 'gr-lib-loader',
properties: {
_hljsState: {
type: Object,
// NOTE: intended singleton.
value: {
configured: false,
loading: false,
callbacks: [],
},
},
},
/**
* Get the HLJS library. Returns a promise that resolves with a reference to
* the library after it's been loaded. The promise resolves immediately if
* it's already been loaded.
* @return {!Promise<Object>}
*/
getHLJS() {
return new Promise((resolve, reject) => {
// If the lib is totally loaded, resolve immediately.
if (this._getHighlightLib()) {
resolve(this._getHighlightLib());
return;
}
// If the library is not currently being loaded, then start loading it.
if (!this._hljsState.loading) {
this._hljsState.loading = true;
this._loadScript(this._getHLJSUrl())
.then(this._onHLJSLibLoaded.bind(this)).catch(reject);
}
this._hljsState.callbacks.push(resolve);
});
},
/**
* Load and apply the dark theme document.
*/
loadDarkTheme() {
this.importHref(this._getLibRoot() + DARK_THEME_PATH);
},
/**
* Execute callbacks awaiting the HLJS lib load.
*/
_onHLJSLibLoaded() {
const lib = this._getHighlightLib();
this._hljsState.loading = false;
for (const cb of this._hljsState.callbacks) {
cb(lib);
}
this._hljsState.callbacks = [];
},
/**
* Get the HLJS library, assuming it has been loaded. Configure the library
* if it hasn't already been configured.
* @return {!Object}
*/
_getHighlightLib() {
const lib = window.hljs;
if (lib && !this._hljsState.configured) {
this._hljsState.configured = true;
lib.configure({classPrefix: 'gr-diff gr-syntax gr-syntax-'});
}
return lib;
},
/**
* Get the resource path used to load the application. If the application
* was loaded through a CDN, then this will be the path to CDN resources.
* @return {string}
*/
_getLibRoot() {
// TODO(wyatta): Remove the remainder of this method logic once the
// STATIC_RESOURCE_PATH variable is being provided generally.
if (window.STATIC_RESOURCE_PATH) { return window.STATIC_RESOURCE_PATH; }
if (this._cachedLibRoot) { return this._cachedLibRoot; }
const appLink = document.head
.querySelector('link[rel=import][href$="gr-app.html"]');
if (!appLink) { throw new Error('Could not find application link'); }
this._cachedLibRoot = appLink
.href
.match(LIB_ROOT_PATTERN)[1];
if (!this._cachedLibRoot) {
throw new Error('Could not extract lib root');
}
return this._cachedLibRoot;
},
_cachedLibRoot: null,
/**
* Load and execute a JS file from the lib root.
* @param {string} src The path to the JS file without the lib root.
* @return {Promise} a promise that resolves when the script's onload
* executes.
*/
_loadScript(src) {
return new Promise((resolve, reject) => {
const script = document.createElement('script');
if (!src) {
reject(new Error('Unable to load blank script url.'));
return;
}
script.src = src;
script.onload = resolve;
script.onerror = reject;
Polymer.dom(document.head).appendChild(script);
});
},
_getHLJSUrl() {
const root = this._getLibRoot();
if (!root) { return null; }
return root + HLJS_PATH;
},
});
})();