|
|
@@ -36,6 +36,8 @@ const BLOCK_STORAGE_END_EVENT = "single-file-block-storage-end";
|
|
|
const LOAD_IMAGE_EVENT = "single-file-load-image";
|
|
|
const IMAGE_LOADED_EVENT = "single-file-image-loaded";
|
|
|
const NEW_FONT_FACE_EVENT = "single-file-new-font-face";
|
|
|
+const DELETE_FONT_EVENT = "single-file-delete-font";
|
|
|
+const CLEAR_FONTS_EVENT = "single-file-clear-fonts";
|
|
|
|
|
|
const browser = globalThis.browser;
|
|
|
const addEventListener = (type, listener, options) => globalThis.addEventListener(type, listener, options);
|
|
|
@@ -59,6 +61,14 @@ if (document instanceof HTMLDocument) {
|
|
|
fontFaces.push(event.detail);
|
|
|
}
|
|
|
});
|
|
|
+ addEventListener(DELETE_FONT_EVENT, event => {
|
|
|
+ const detail = event.detail;
|
|
|
+ const indexFontFace = fontFaces.findIndex(fontFace => fontFace["family-name"] == detail["family-name"]);
|
|
|
+ if (indexFontFace != -1) {
|
|
|
+ fontFaces.splice(indexFontFace, 1);
|
|
|
+ }
|
|
|
+ });
|
|
|
+ addEventListener(CLEAR_FONTS_EVENT, () => fontFaces = []);
|
|
|
let scriptElement = document.createElement("script");
|
|
|
scriptElement.src = "data:," + "(" + injectedScript.toString() + ")()";
|
|
|
(document.documentElement || document).appendChild(scriptElement);
|
|
|
@@ -131,6 +141,8 @@ function injectedScript() {
|
|
|
const Blob = globalThis.Blob;
|
|
|
const warn = (console && console.warn && ((...args) => console.warn(...args))) || (() => { });
|
|
|
const NEW_FONT_FACE_EVENT = "single-file-new-font-face";
|
|
|
+ const DELETE_FONT_EVENT = "single-file-delete-font";
|
|
|
+ const CLEAR_FONTS_EVENT = "single-file-clear-fonts";
|
|
|
const FONT_STYLE_PROPERTIES = {
|
|
|
family: "font-family",
|
|
|
style: "font-style",
|
|
|
@@ -146,32 +158,49 @@ function injectedScript() {
|
|
|
let warningFontFaceDisplayed;
|
|
|
globalThis.FontFace = function () {
|
|
|
if (!warningFontFaceDisplayed) {
|
|
|
- warn("SingleFile is hooking the FontFace constructor to get font URLs.");
|
|
|
+ warn("SingleFile is hooking the FontFace constructor, document.fonts.delete and document.fonts.clear to handle dynamically loaded fonts.");
|
|
|
warningFontFaceDisplayed = true;
|
|
|
}
|
|
|
- const detail = {};
|
|
|
- detail["font-family"] = arguments[0];
|
|
|
- detail.src = arguments[1];
|
|
|
- const descriptors = arguments[2];
|
|
|
- if (descriptors) {
|
|
|
- Object.keys(descriptors).forEach(descriptor => {
|
|
|
- if (FONT_STYLE_PROPERTIES[descriptor]) {
|
|
|
- detail[FONT_STYLE_PROPERTIES[descriptor]] = descriptors[descriptor];
|
|
|
- }
|
|
|
- });
|
|
|
- }
|
|
|
+ getDetailObject(...arguments).then(detail => dispatchEvent(new CustomEvent(NEW_FONT_FACE_EVENT, { detail })));
|
|
|
+ return new FontFace(...arguments);
|
|
|
+ };
|
|
|
+ globalThis.FontFace.toString = function () { return "function FontFace() { [native code] }"; };
|
|
|
+ const deleteFont = document.fonts.delete;
|
|
|
+ document.fonts.delete = function (fontFace) {
|
|
|
+ getDetailObject(fontFace.family).then(detail => dispatchEvent(new CustomEvent(DELETE_FONT_EVENT, { detail })));
|
|
|
+ return deleteFont.call(document.fonts, fontFace);
|
|
|
+ };
|
|
|
+ document.fonts.delete.toString = function () { return "function delete() { [native code] }"; };
|
|
|
+ const clearFonts = document.fonts.clear;
|
|
|
+ document.fonts.clear = function () {
|
|
|
+ dispatchEvent(new CustomEvent(CLEAR_FONTS_EVENT));
|
|
|
+ return clearFonts.call(document.fonts);
|
|
|
+ };
|
|
|
+ document.fonts.clear.toString = function () { return "function clear() { [native code] }"; };
|
|
|
+ }
|
|
|
+
|
|
|
+ async function getDetailObject(fontFamily, src, descriptors) {
|
|
|
+ const detail = {};
|
|
|
+ detail["font-family"] = fontFamily;
|
|
|
+ detail.src = src;
|
|
|
+ if (descriptors) {
|
|
|
+ Object.keys(descriptors).forEach(descriptor => {
|
|
|
+ if (FONT_STYLE_PROPERTIES[descriptor]) {
|
|
|
+ detail[FONT_STYLE_PROPERTIES[descriptor]] = descriptors[descriptor];
|
|
|
+ }
|
|
|
+ });
|
|
|
+ }
|
|
|
+ return new Promise(resolve => {
|
|
|
if (detail.src instanceof ArrayBuffer) {
|
|
|
const reader = new FileReader();
|
|
|
reader.readAsDataURL(new Blob([detail.src]));
|
|
|
reader.addEventListener("load", () => {
|
|
|
detail.src = "url(" + reader.result + ")";
|
|
|
- dispatchEvent(new CustomEvent(NEW_FONT_FACE_EVENT, { detail }));
|
|
|
+ resolve(detail);
|
|
|
});
|
|
|
} else {
|
|
|
- dispatchEvent(new CustomEvent(NEW_FONT_FACE_EVENT, { detail }));
|
|
|
+ resolve(detail);
|
|
|
}
|
|
|
- return new FontFace(...arguments);
|
|
|
- };
|
|
|
- globalThis.FontFace.toString = function () { return "function FontFace() { [native code] }"; };
|
|
|
+ });
|
|
|
}
|
|
|
}
|