diff options
author | toasted-nutbread <toasted-nutbread@users.noreply.github.com> | 2020-05-19 20:33:06 -0400 |
---|---|---|
committer | GitHub <noreply@github.com> | 2020-05-19 20:33:06 -0400 |
commit | dd673f0b2626c2bffbcb301dc364009f077c3d08 (patch) | |
tree | 64319346c3e9a9debe76e62b6adc77034aec52e8 /ext/mixed/js | |
parent | dd6c3015c4af6db5f1deca797366ed6269b7d82c (diff) |
Dynamic loader load style (#521)
* Remove unnecessary load of /fg/css/client.css
* Replace dynamicLoader.loadStyles with dynamicLoader.loadStyle
* Replace Popup._injectStylesheet with dynamicLoader.loadStyle
* Remove unused global
Diffstat (limited to 'ext/mixed/js')
-rw-r--r-- | ext/mixed/js/dynamic-loader.js | 77 |
1 files changed, 65 insertions, 12 deletions
diff --git a/ext/mixed/js/dynamic-loader.js b/ext/mixed/js/dynamic-loader.js index 51b6821b..ce946109 100644 --- a/ext/mixed/js/dynamic-loader.js +++ b/ext/mixed/js/dynamic-loader.js @@ -15,19 +15,72 @@ * along with this program. If not, see <https://www.gnu.org/licenses/>. */ +/* global + * apiInjectStylesheet + */ + const dynamicLoader = (() => { - function loadStyles(urls) { - const parent = document.head; - for (const url of urls) { - const node = parent.querySelector(`link[href='${escapeCSSAttribute(url)}']`); - if (node !== null) { continue; } - - const style = document.createElement('link'); - style.rel = 'stylesheet'; - style.type = 'text/css'; - style.href = url; - parent.appendChild(style); + const injectedStylesheets = new Map(); + + async function loadStyle(id, type, value, useWebExtensionApi=false) { + if (useWebExtensionApi && yomichan.isExtensionUrl(window.location.href)) { + // Permissions error will occur if trying to use the WebExtension API to inject into an extension page + useWebExtensionApi = false; + } + + let styleNode = injectedStylesheets.get(id); + if (typeof styleNode !== 'undefined') { + if (styleNode === null) { + // Previously injected via WebExtension API + throw new Error(`Stylesheet with id ${id} has already been injected using the WebExtension API`); + } + } else { + styleNode = null; + } + + if (useWebExtensionApi) { + // Inject via WebExtension API + if (styleNode !== null && styleNode.parentNode !== null) { + styleNode.parentNode.removeChild(styleNode); + } + + injectedStylesheets.set(id, null); + await apiInjectStylesheet(type, value); + return null; } + + // Create node in document + const parentNode = document.head; + if (parentNode === null) { + throw new Error('No parent node'); + } + + // Create or reuse node + const isFile = (type === 'file'); + const tagName = isFile ? 'link' : 'style'; + if (styleNode === null || styleNode.nodeName.toLowerCase() !== tagName) { + if (styleNode !== null && styleNode.parentNode !== null) { + styleNode.parentNode.removeChild(styleNode); + } + styleNode = document.createElement(tagName); + } + + // Update node style + if (isFile) { + styleNode.rel = 'stylesheet'; + styleNode.href = value; + } else { + styleNode.textContent = value; + } + + // Update parent + if (styleNode.parentNode !== parentNode) { + parentNode.appendChild(styleNode); + } + + // Add to map + injectedStylesheets.set(id, styleNode); + return styleNode; } function loadScripts(urls) { @@ -80,7 +133,7 @@ const dynamicLoader = (() => { return { - loadStyles, + loadStyle, loadScripts }; })(); |