diff options
Diffstat (limited to 'ext/mixed/js')
| -rw-r--r-- | ext/mixed/js/api.js | 4 | ||||
| -rw-r--r-- | ext/mixed/js/dynamic-loader.js | 49 | 
2 files changed, 44 insertions, 9 deletions
diff --git a/ext/mixed/js/api.js b/ext/mixed/js/api.js index c54196e2..5c17d50e 100644 --- a/ext/mixed/js/api.js +++ b/ext/mixed/js/api.js @@ -121,6 +121,10 @@ const api = (() => {              return this._invoke('injectStylesheet', {type, value});          } +        getStylesheetContent(url) { +            return this._invoke('getStylesheetContent', {url}); +        } +          getEnvironmentInfo() {              return this._invoke('getEnvironmentInfo');          } diff --git a/ext/mixed/js/dynamic-loader.js b/ext/mixed/js/dynamic-loader.js index 37f85112..981d1ee5 100644 --- a/ext/mixed/js/dynamic-loader.js +++ b/ext/mixed/js/dynamic-loader.js @@ -21,14 +21,36 @@  const dynamicLoader = (() => {      const injectedStylesheets = new Map(); +    const injectedStylesheetsWithParent = new WeakMap(); -    async function loadStyle(id, type, value, useWebExtensionApi=false) { +    function getInjectedStylesheet(id, parentNode) { +        if (parentNode === null) { +            return injectedStylesheets.get(id); +        } +        const map = injectedStylesheetsWithParent.get(parentNode); +        return typeof map !== 'undefined' ? map.get(id) : void 0; +    } + +    function setInjectedStylesheet(id, parentNode, value) { +        if (parentNode === null) { +            injectedStylesheets.set(id, value); +            return; +        } +        let map = injectedStylesheetsWithParent.get(parentNode); +        if (typeof map === 'undefined') { +            map = new Map(); +            injectedStylesheetsWithParent.set(parentNode, map); +        } +        map.set(id, value); +    } + +    async function loadStyle(id, type, value, useWebExtensionApi=false, parentNode=null) {          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); +        let styleNode = getInjectedStylesheet(id, parentNode);          if (typeof styleNode !== 'undefined') {              if (styleNode === null) {                  // Previously injected via WebExtension API @@ -38,21 +60,30 @@ const dynamicLoader = (() => {              styleNode = null;          } +        if (type === 'file-content') { +            value = await api.getStylesheetContent(value); +            type = 'code'; +            useWebExtensionApi = false; +        } +          if (useWebExtensionApi) {              // Inject via WebExtension API              if (styleNode !== null && styleNode.parentNode !== null) {                  styleNode.parentNode.removeChild(styleNode);              } -            injectedStylesheets.set(id, null); +            setInjectedStylesheet(id, parentNode, null);              await api.injectStylesheet(type, value);              return null;          }          // Create node in document -        const parentNode = document.head; -        if (parentNode === null) { -            throw new Error('No parent node'); +        let parentNode2 = parentNode; +        if (parentNode2 === null) { +            parentNode2 = document.head; +            if (parentNode2 === null) { +                throw new Error('No parent node'); +            }          }          // Create or reuse node @@ -74,12 +105,12 @@ const dynamicLoader = (() => {          }          // Update parent -        if (styleNode.parentNode !== parentNode) { -            parentNode.appendChild(styleNode); +        if (styleNode.parentNode !== parentNode2) { +            parentNode2.appendChild(styleNode);          }          // Add to map -        injectedStylesheets.set(id, styleNode); +        setInjectedStylesheet(id, parentNode, styleNode);          return styleNode;      }  |