From dd673f0b2626c2bffbcb301dc364009f077c3d08 Mon Sep 17 00:00:00 2001 From: toasted-nutbread Date: Tue, 19 May 2020 20:33:06 -0400 Subject: [PATCH] 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 --- ext/bg/js/search-main.js | 3 -- ext/bg/settings-popup-preview.html | 1 + ext/fg/js/popup.js | 78 ++---------------------------- ext/manifest.json | 1 + ext/mixed/js/dynamic-loader.js | 77 ++++++++++++++++++++++++----- 5 files changed, 70 insertions(+), 90 deletions(-) diff --git a/ext/bg/js/search-main.js b/ext/bg/js/search-main.js index 6e092fbc..54fa549d 100644 --- a/ext/bg/js/search-main.js +++ b/ext/bg/js/search-main.js @@ -23,9 +23,6 @@ */ async function injectSearchFrontend() { - dynamicLoader.loadStyles([ - '/fg/css/client.css' - ]); await dynamicLoader.loadScripts([ '/mixed/js/text-scanner.js', '/fg/js/frontend-api-receiver.js', diff --git a/ext/bg/settings-popup-preview.html b/ext/bg/settings-popup-preview.html index 3d7f6455..2f0b841b 100644 --- a/ext/bg/settings-popup-preview.html +++ b/ext/bg/settings-popup-preview.html @@ -121,6 +121,7 @@ + diff --git a/ext/fg/js/popup.js b/ext/fg/js/popup.js index 9e9debd8..b7d4b57e 100644 --- a/ext/fg/js/popup.js +++ b/ext/fg/js/popup.js @@ -17,8 +17,8 @@ /* global * DOM - * apiInjectStylesheet * apiOptionsGet + * dynamicLoader */ class Popup { @@ -180,12 +180,7 @@ class Popup { } async setCustomOuterCss(css, useWebExtensionApi) { - return await this._injectStylesheet( - 'yomichan-popup-outer-user-stylesheet', - 'code', - css, - useWebExtensionApi - ); + return await dynamicLoader.loadStyle('yomichan-popup-outer-user-stylesheet', 'code', css, useWebExtensionApi); } setChildrenSupported(value) { @@ -391,7 +386,7 @@ class Popup { async _injectStyles() { try { - await this._injectStylesheet('yomichan-popup-outer-stylesheet', 'file', '/fg/css/client.css', true); + await dynamicLoader.loadStyle('yomichan-popup-outer-stylesheet', 'file', '/fg/css/client.css', true); } catch (e) { // NOP } @@ -717,71 +712,6 @@ class Popup { }; } - async _injectStylesheet(id, type, value, useWebExtensionApi) { - const injectedStylesheets = Popup._injectedStylesheets; - - if (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); - } - - await apiInjectStylesheet(type, value); - - injectedStylesheets.set(id, null); - 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); - styleNode.id = id; - } - - // Update node style - if (isFile) { - styleNode.rel = value; - } else { - styleNode.textContent = value; - } - - // Update parent - if (styleNode.parentNode !== parentNode) { - parentNode.appendChild(styleNode); - } - - // Add to map - injectedStylesheets.set(id, styleNode); - return styleNode; - } - static isFrameAboutBlank(frame) { try { const contentDocument = frame.contentDocument; @@ -793,5 +723,3 @@ class Popup { } } } - -Popup._injectedStylesheets = new Map(); diff --git a/ext/manifest.json b/ext/manifest.json index 865fe3f3..c87b9296 100644 --- a/ext/manifest.json +++ b/ext/manifest.json @@ -38,6 +38,7 @@ "mixed/js/core.js", "mixed/js/dom.js", "mixed/js/api.js", + "mixed/js/dynamic-loader.js", "mixed/js/text-scanner.js", "fg/js/document.js", "fg/js/frontend-api-sender.js", 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 . */ -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; } +/* global + * apiInjectStylesheet + */ - const style = document.createElement('link'); - style.rel = 'stylesheet'; - style.type = 'text/css'; - style.href = url; - parent.appendChild(style); +const dynamicLoader = (() => { + 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 }; })();