aboutsummaryrefslogtreecommitdiff
path: root/ext/js/script
diff options
context:
space:
mode:
Diffstat (limited to 'ext/js/script')
-rw-r--r--ext/js/script/dynamic-loader-sentinel.js3
-rw-r--r--ext/js/script/dynamic-loader.js43
2 files changed, 41 insertions, 5 deletions
diff --git a/ext/js/script/dynamic-loader-sentinel.js b/ext/js/script/dynamic-loader-sentinel.js
index 3c06fc02..d77f3cb0 100644
--- a/ext/js/script/dynamic-loader-sentinel.js
+++ b/ext/js/script/dynamic-loader-sentinel.js
@@ -18,5 +18,4 @@
import {yomitan} from '../yomitan.js';
-
-yomitan.trigger('dynamicLoaderSentinel', {script: import.meta.url});
+yomitan.trigger('dynamicLoaderSentinel', /** @type {import('dynamic-loader').DynamicLoaderSentinelDetails} */ ({scriptUrl: import.meta.url}));
diff --git a/ext/js/script/dynamic-loader.js b/ext/js/script/dynamic-loader.js
index 2abc9e04..75bf7b8b 100644
--- a/ext/js/script/dynamic-loader.js
+++ b/ext/js/script/dynamic-loader.js
@@ -19,9 +19,16 @@
import {yomitan} from '../yomitan.js';
export const dynamicLoader = (() => {
+ /** @type {Map<string, ?HTMLStyleElement|HTMLLinkElement>} */
const injectedStylesheets = new Map();
+ /** @type {WeakMap<Node, Map<string, ?HTMLStyleElement|HTMLLinkElement>>} */
const injectedStylesheetsWithParent = new WeakMap();
+ /**
+ * @param {string} id
+ * @param {?Node} parentNode
+ * @returns {?HTMLStyleElement|HTMLLinkElement|undefined}
+ */
function getInjectedStylesheet(id, parentNode) {
if (parentNode === null) {
return injectedStylesheets.get(id);
@@ -30,6 +37,11 @@ export const dynamicLoader = (() => {
return typeof map !== 'undefined' ? map.get(id) : void 0;
}
+ /**
+ * @param {string} id
+ * @param {?Node} parentNode
+ * @param {?HTMLStyleElement|HTMLLinkElement} value
+ */
function setInjectedStylesheet(id, parentNode, value) {
if (parentNode === null) {
injectedStylesheets.set(id, value);
@@ -43,6 +55,15 @@ export const dynamicLoader = (() => {
map.set(id, value);
}
+ /**
+ * @param {string} id
+ * @param {'code'|'file'|'file-content'} type
+ * @param {string} value
+ * @param {boolean} [useWebExtensionApi]
+ * @param {?Node} [parentNode]
+ * @returns {Promise<?HTMLStyleElement|HTMLLinkElement>}
+ * @throws {Error}
+ */
async function loadStyle(id, type, value, useWebExtensionApi=false, parentNode=null) {
if (useWebExtensionApi && yomitan.isExtensionUrl(window.location.href)) {
// Permissions error will occur if trying to use the WebExtension API to inject into an extension page
@@ -97,8 +118,8 @@ export const dynamicLoader = (() => {
// Update node style
if (isFile) {
- styleNode.rel = 'stylesheet';
- styleNode.href = value;
+ /** @type {HTMLLinkElement} */ (styleNode).rel = 'stylesheet';
+ /** @type {HTMLLinkElement} */ (styleNode).href = value;
} else {
styleNode.textContent = value;
}
@@ -113,6 +134,10 @@ export const dynamicLoader = (() => {
return styleNode;
}
+ /**
+ * @param {string[]} urls
+ * @returns {Promise<void>}
+ */
function loadScripts(urls) {
return new Promise((resolve, reject) => {
const parent = document.body;
@@ -136,12 +161,20 @@ export const dynamicLoader = (() => {
});
}
+ /**
+ * @param {HTMLElement} parent
+ * @param {() => void} resolve
+ * @param {(reason?: unknown) => void} reject
+ */
function loadScriptSentinel(parent, resolve, reject) {
const script = document.createElement('script');
const sentinelEventName = 'dynamicLoaderSentinel';
+ /**
+ * @param {import('dynamic-loader').DynamicLoaderSentinelDetails} e
+ */
const sentinelEventCallback = (e) => {
- if (e.script !== script.src) { return; }
+ if (e.scriptUrl !== script.src) { return; }
yomitan.off(sentinelEventName, sentinelEventCallback);
parent.removeChild(script);
resolve();
@@ -159,6 +192,10 @@ export const dynamicLoader = (() => {
}
}
+ /**
+ * @param {string} value
+ * @returns {string}
+ */
function escapeCSSAttribute(value) {
return value.replace(/['\\]/g, (character) => `\\${character}`);
}