single-file-core 1.5.95 → 1.5.97

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/core/helper.js CHANGED
@@ -91,6 +91,9 @@ const CustomEvent = globalThis.CustomEvent;
91
91
  const MutationObserver = globalThis.MutationObserver;
92
92
  const URL = globalThis.URL;
93
93
  const DOMParser = globalThis.DOMParser;
94
+ const Uint8Array = globalThis.Uint8Array;
95
+ const btoa = globalThis.btoa;
96
+ const FileReader = globalThis.FileReader;
94
97
 
95
98
  export {
96
99
  initUserScriptHandler,
@@ -105,6 +108,7 @@ export {
105
108
  getShadowRoot,
106
109
  appendInfobar,
107
110
  getContentSize,
111
+ getDataURI,
108
112
  digest,
109
113
  getValidFilename,
110
114
  parseDocContent,
@@ -297,7 +301,10 @@ function markInvalidNesting(doc) {
297
301
 
298
302
  function addTrackIds(element, index = 0, parentTrackId = "") {
299
303
  const trackId = parentTrackId ? `${parentTrackId}.${index + 1}` : `${index + 1}`;
300
- element.setAttribute(NESTING_TRACK_ID_ATTRIBUTE_NAME, trackId);
304
+ const tagName = element.tagName.toUpperCase();
305
+ if (!(parentTrackId && (tagName == "BODY" || tagName == "HEAD" || tagName == "HTML"))) {
306
+ element.setAttribute(NESTING_TRACK_ID_ATTRIBUTE_NAME, trackId);
307
+ }
301
308
  Array.from(element.children).forEach((child, indexChild) => addTrackIds(child, indexChild, trackId));
302
309
  }
303
310
 
@@ -338,7 +345,7 @@ function fixInvalidNesting(document, NESTING_TRACK_ID_ATTRIBUTE_NAME, preventCle
338
345
  if (idParts.length > 1) {
339
346
  const parentId = idParts.slice(0, -1).join(".");
340
347
  const expectedParent = trackIds[parentId];
341
- if (expectedParent && element.parentElement !== expectedParent) {
348
+ if (expectedParent && element.parentElement !== expectedParent && !element.contains(expectedParent)) {
342
349
  expectedParent.appendChild(element);
343
350
  }
344
351
  }
@@ -793,6 +800,24 @@ function getContentSize(content) {
793
800
  return new Blob([content]).size;
794
801
  }
795
802
 
803
+ async function getDataURI(blob) {
804
+ if (FileReader) {
805
+ const reader = new FileReader();
806
+ reader.readAsDataURL(blob);
807
+ return new Promise((resolve, reject) => {
808
+ reader.addEventListener("load", () => resolve(reader.result), false);
809
+ reader.addEventListener("error", reject, false);
810
+ });
811
+ } else {
812
+ const bytes = new Uint8Array(await blob.arrayBuffer());
813
+ let content = "";
814
+ for (let offset = 0; offset < bytes.length; offset += 8192) {
815
+ content += String.fromCharCode(...bytes.subarray(offset, offset + 8192));
816
+ }
817
+ return "data:" + (blob.type || "application/octet-stream") + ";base64," + btoa(content);
818
+ }
819
+ }
820
+
796
821
  async function digest(algo, text) {
797
822
  try {
798
823
  const data = new TextEncoder("utf-8").encode(text);
@@ -23,7 +23,8 @@
23
23
 
24
24
  import {
25
25
  normalizeFontFamily,
26
- getFontWeight
26
+ getFontWeight,
27
+ getDataURI
27
28
  } from "./../helper.js";
28
29
 
29
30
  const DATA_URI_PREFIX = "data:";
@@ -60,7 +61,6 @@ const FONT_STRETCHES = {
60
61
  "ultra-expanded": "200%"
61
62
  };
62
63
  const Blob = globalThis.Blob;
63
- const FileReader = globalThis.FileReader;
64
64
  const Image = globalThis.Image;
65
65
  const OffscreenCanvas = globalThis.OffscreenCanvas;
66
66
 
@@ -710,10 +710,5 @@ async function resizeImage(doc, dataURI, { imageReductionFactor }) {
710
710
 
711
711
  function toDataURI(content, contentType, charset) {
712
712
  const blob = content instanceof Blob ? content : new Blob([content], { type: (contentType || "") + (charset ? ";charset=" + charset : "") });
713
- return new Promise((resolve, reject) => {
714
- const reader = new FileReader();
715
- reader.onload = () => resolve(reader.result);
716
- reader.onerror = () => reject(new Error(reader.error));
717
- reader.readAsDataURL(blob);
718
- });
713
+ return getDataURI(blob);
719
714
  }
package/core/util.js CHANGED
@@ -66,7 +66,6 @@ const CONTENT_TYPE_OCTET_STREAM = "application/octet-stream";
66
66
  const URL = globalThis.URL;
67
67
  const DOMParser = globalThis.DOMParser;
68
68
  const Blob = globalThis.Blob;
69
- const FileReader = globalThis.FileReader;
70
69
  const fetch = (url, options) => {
71
70
  options.cache = "force-cache";
72
71
  options.referrerPolicy = "strict-origin-when-cross-origin";
@@ -351,12 +350,7 @@ async function getFetchResponse(resourceURL, options, data, charset, contentType
351
350
  if (data) {
352
351
  if (options.asBinary) {
353
352
  if (options.inline) {
354
- const reader = new FileReader();
355
- reader.readAsDataURL(new Blob([data], { type: contentType + (options.charset ? ";charset=" + options.charset : "") }));
356
- data = await new Promise((resolve, reject) => {
357
- reader.addEventListener("load", () => resolve(reader.result), false);
358
- reader.addEventListener("error", reject, false);
359
- });
353
+ data = await helper.getDataURI(new Blob([data], { type: contentType + (options.charset ? ";charset=" + options.charset : "") }));
360
354
  } else {
361
355
  data = new Uint8Array(data);
362
356
  }
@@ -4,7 +4,6 @@ import { build } from "esbuild";
4
4
 
5
5
  const require = createRequire(import.meta.url);
6
6
  const packagePath = require.resolve("css-tree/package.json");
7
- const tokenStreamPath = packagePath.replace(/package\.json$/, "lib/tokenizer/TokenStream.js");
8
7
  const licensePath = packagePath.replace(/package\.json$/, "LICENSE");
9
8
  const { version } = JSON.parse(readFileSync(packagePath));
10
9
 
package/eslint.config.mjs CHANGED
@@ -1,6 +1,12 @@
1
1
  import js from "@eslint/js";
2
2
 
3
3
  export default [
4
+ {
5
+ ignores: [
6
+ "vendor/**",
7
+ "zip-build/lib/**"
8
+ ]
9
+ },
4
10
  js.configs.recommended,
5
11
  {
6
12
  languageOptions: {
@@ -27,5 +33,22 @@ export default [
27
33
  "warn"
28
34
  ]
29
35
  }
36
+ },
37
+ {
38
+ files: ["test/sfz-harness/**"],
39
+ languageOptions: {
40
+ globals: {
41
+ Deno: "readonly",
42
+ setTimeout: "readonly",
43
+ Blob: "readonly",
44
+ TextDecoder: "readonly",
45
+ TextEncoder: "readonly",
46
+ URL: "readonly",
47
+ performance: "readonly"
48
+ }
49
+ },
50
+ rules: {
51
+ "no-console": "off"
52
+ }
30
53
  }
31
54
  ];
@@ -27,7 +27,6 @@ import { parse } from "./template-parser.js";
27
27
  import { getContentSize, digest, getValidFilename } from "./../core/helper.js";
28
28
 
29
29
  const Blob = globalThis.Blob;
30
- const FileReader = globalThis.FileReader;
31
30
  const URL = globalThis.URL;
32
31
  const Intl = globalThis.Intl;
33
32
  const URLSearchParams = globalThis.URLSearchParams;
@@ -17263,26 +17262,25 @@ function getLastSegment(url, replacementCharacter) {
17263
17262
  return lastSegment;
17264
17263
  }
17265
17264
 
17266
- function truncateText(content, maxSize) {
17265
+ async function truncateText(content, maxSize) {
17267
17266
  const blob = new Blob([content]);
17268
- const reader = new FileReader();
17269
- reader.readAsText(blob.slice(0, maxSize));
17270
- return new Promise((resolve, reject) => {
17271
- reader.addEventListener(
17272
- "load",
17273
- () => {
17274
- if (content.startsWith(reader.result)) {
17275
- resolve(reader.result);
17276
- } else {
17277
- truncateText(content, maxSize - 1)
17278
- .then(resolve)
17279
- .catch(reject);
17280
- }
17281
- },
17282
- false
17283
- );
17284
- reader.addEventListener("error", reject, false);
17285
- });
17267
+ const truncatedBlob = blob.slice(0, maxSize);
17268
+ let result;
17269
+ if (globalThis.FileReader) {
17270
+ const reader = new globalThis.FileReader();
17271
+ reader.readAsText(truncatedBlob);
17272
+ result = await new Promise((resolve, reject) => {
17273
+ reader.addEventListener("load", () => resolve(reader.result), false);
17274
+ reader.addEventListener("error", reject, false);
17275
+ });
17276
+ } else {
17277
+ result = await truncatedBlob.text();
17278
+ }
17279
+ if (content.startsWith(result)) {
17280
+ return result;
17281
+ } else {
17282
+ return truncateText(content, maxSize - 1);
17283
+ }
17286
17284
  }
17287
17285
 
17288
17286
  function getFilenameExtension(options) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "single-file-core",
3
- "version": "1.5.95",
3
+ "version": "1.5.97",
4
4
  "description": "SingleFile Core",
5
5
  "author": "Gildas Lormeau",
6
6
  "license": "AGPL-3.0-or-later",
@@ -20,6 +20,7 @@
20
20
  },
21
21
  "homepage": "https://github.com/gildas-lormeau/single-file-core#readme",
22
22
  "devDependencies": {
23
- "eslint": "^9.39.1"
23
+ "@eslint/js": "^9.39.5",
24
+ "eslint": "^10.9.1"
24
25
  }
25
26
  }
@@ -21,7 +21,7 @@
21
21
  * Source.
22
22
  */
23
23
 
24
- /* global zip, Blob, FileReader, URL */
24
+ /* global zip, Blob, btoa, URL */
25
25
 
26
26
  export {
27
27
  extract
@@ -220,12 +220,13 @@ async function extract(content, { password, prompt = () => { }, zipOptions = { u
220
220
  }
221
221
 
222
222
  async function getDataURI(textContent, mimeType) {
223
- const reader = new FileReader();
224
- reader.readAsDataURL(new Blob([textContent], { type: mimeType }));
225
- return new Promise((resolve, reject) => {
226
- reader.onload = () => resolve(reader.result.replace(CHARSET_UTF8, ""));
227
- reader.onerror = reject;
228
- });
223
+ const blob = new Blob([textContent], { type: mimeType });
224
+ const bytes = new Uint8Array(await blob.arrayBuffer());
225
+ let content = "";
226
+ for (let offset = 0; offset < bytes.length; offset += 8192) {
227
+ content += String.fromCharCode(...bytes.subarray(offset, offset + 8192));
228
+ }
229
+ return ("data:" + (blob.type || "application/octet-stream") + ";base64," + btoa(content)).replace(CHARSET_UTF8, "");
229
230
  }
230
231
 
231
232
  function replaceAll(string, search, replacement) {
@@ -606,6 +606,7 @@ async function getContent() {
606
606
  displayMessage("sfz-wait-message", 2);
607
607
  resolve(pageData);
608
608
  } catch (error) {
609
+ // eslint-disable-next-line no-console
609
610
  console.error(error);
610
611
  displayMessage("sfz-error-message", 2);
611
612
  reject(error);
@@ -397,8 +397,8 @@ function sendMessage(targetWindow, message, useChannel) {
397
397
  }
398
398
  }
399
399
 
400
- function getFrameData(document, globalThis, windowId, options, scrolling) {
401
- const docData = helper.preProcessDoc(document, globalThis, options);
400
+ function getFrameData(document, win, windowId, options, scrolling) {
401
+ const docData = helper.preProcessDoc(document, win, options);
402
402
  const content = helper.serialize(document);
403
403
  helper.postProcessDoc(document, docData.markedElements, docData.invalidElements);
404
404
  const baseURI = document.baseURI.split("#")[0];
@@ -21,7 +21,7 @@
21
21
  * Source.
22
22
  */
23
23
 
24
- (globalThis => {
24
+ (() => {
25
25
 
26
26
  const LOAD_DEFERRED_IMAGES_START_EVENT = "single-file-load-deferred-images-start";
27
27
  const LOAD_DEFERRED_IMAGES_END_EVENT = "single-file-load-deferred-images-end";
@@ -71,8 +71,8 @@
71
71
  const Element = globalThis.Element;
72
72
  const UIEvent = globalThis.UIEvent;
73
73
  const Event = globalThis.Event;
74
- const FileReader = globalThis.FileReader;
75
- const Blob = globalThis.Blob;
74
+ const Uint8Array = globalThis.Uint8Array;
75
+ const btoa = globalThis.btoa;
76
76
  const JSON = globalThis.JSON;
77
77
  const MutationObserver = globalThis.MutationObserver;
78
78
  const URL = globalThis.URL;
@@ -88,83 +88,126 @@
88
88
  new MutationObserver(init).observe(document, { childList: true });
89
89
 
90
90
  function init() {
91
- document.addEventListener(LOAD_DEFERRED_IMAGES_START_EVENT, () => loadDeferredImagesStart());
92
- document.addEventListener(LOAD_DEFERRED_IMAGES_KEEP_ZOOM_LEVEL_START_EVENT, () => loadDeferredImagesStart(true));
93
- document.addEventListener(LOAD_DEFERRED_IMAGES_END_EVENT, () => loadDeferredImagesEnd());
94
- document.addEventListener(LOAD_DEFERRED_IMAGES_KEEP_ZOOM_LEVEL_END_EVENT, () => loadDeferredImagesEnd(true));
91
+ document.addEventListener(LOAD_DEFERRED_IMAGES_START_EVENT, onLoadDeferredImagesStart);
92
+ document.addEventListener(LOAD_DEFERRED_IMAGES_KEEP_ZOOM_LEVEL_START_EVENT, onLoadDeferredImagesKeepZoomLevelStart);
93
+ document.addEventListener(LOAD_DEFERRED_IMAGES_END_EVENT, onLoadDeferredImagesEnd);
94
+ document.addEventListener(LOAD_DEFERRED_IMAGES_KEEP_ZOOM_LEVEL_END_EVENT, onLoadDeferredImagesKeepZoomLevelEnd);
95
95
  document.addEventListener(LOAD_DEFERRED_IMAGES_RESET_EVENT, resetScreenSize);
96
- document.addEventListener(LOAD_DEFERRED_IMAGES_RESET_ZOOM_LEVEL_EVENT, () => {
97
- const transform = document.documentElement.style.getPropertyValue("-sf-transform");
98
- const transformPriority = document.documentElement.style.getPropertyPriority("-sf-transform");
99
- const transformOrigin = document.documentElement.style.getPropertyValue("-sf-transform-origin");
100
- const transformOriginPriority = document.documentElement.style.getPropertyPriority("-sf-transform-origin");
101
- const minHeight = document.documentElement.style.getPropertyValue("-sf-min-height");
102
- const minHeightPriority = document.documentElement.style.getPropertyPriority("-sf-min-height");
103
- document.documentElement.style.setProperty("transform", transform, transformPriority);
104
- document.documentElement.style.setProperty("transform-origin", transformOrigin, transformOriginPriority);
105
- document.documentElement.style.setProperty("min-height", minHeight, minHeightPriority);
106
- document.documentElement.style.removeProperty("-sf-transform");
107
- document.documentElement.style.removeProperty("-sf-transform-origin");
108
- document.documentElement.style.removeProperty("-sf-min-height");
109
- resetScreenSize();
110
- });
111
- document.addEventListener(DISPATCH_SCROLL_START_EVENT, () => { dispatchScrollEvent = true; });
112
- document.addEventListener(DISPATCH_SCROLL_END_EVENT, () => { dispatchScrollEvent = false; });
113
- document.addEventListener(BLOCK_COOKIES_START_EVENT, () => {
114
- try {
115
- document.__defineGetter__("cookie", () => { throw new Error("document.cookie temporary blocked by SingleFile"); });
116
- // eslint-disable-next-line no-unused-vars
117
- } catch (error) {
118
- // ignored
119
- }
120
- });
121
- document.addEventListener(BLOCK_COOKIES_END_EVENT, () => { delete document.cookie; });
122
- document.addEventListener(BLOCK_STORAGE_START_EVENT, () => {
123
- if (!globalThis._singleFile_localStorage) {
124
- globalThis._singleFile_localStorage = globalThis.localStorage;
125
- globalThis.__defineGetter__("localStorage", () => { throw new Error("localStorage temporary blocked by SingleFile"); });
126
- }
127
- if (!globalThis._singleFile_indexedDB) {
128
- globalThis._singleFile_indexedDB = globalThis.indexedDB;
129
- globalThis.__defineGetter__("indexedDB", () => { throw new Error("indexedDB temporary blocked by SingleFile"); });
130
- }
131
- });
132
- document.addEventListener(BLOCK_STORAGE_END_EVENT, () => {
133
- if (globalThis._singleFile_localStorage) {
134
- delete globalThis.localStorage;
135
- globalThis.localStorage = globalThis._singleFile_localStorage;
136
- delete globalThis._singleFile_localStorage;
137
- }
138
- if (!globalThis._singleFile_indexedDB) {
139
- delete globalThis.indexedDB;
140
- globalThis.indexedDB = globalThis._singleFile_indexedDB;
141
- delete globalThis._singleFile_indexedDB;
142
- }
143
- });
144
- document.addEventListener(FETCH_SUPPORTED_REQUEST_EVENT, () =>
145
- document.dispatchEvent(new CustomEvent(FETCH_SUPPORTED_RESPONSE_EVENT)));
146
- document.addEventListener(FETCH_REQUEST_EVENT, async event => {
147
- const { url, options } = JSON.parse(event.detail);
148
- let detail;
149
- try {
150
- const response = await fetch(url, options);
151
- detail = { url, response: await response.arrayBuffer(), headers: [...response.headers], status: response.status };
152
- } catch (error) {
153
- detail = { url, error: error && (error.message || error.toString()) };
154
- }
155
- document.dispatchEvent(new CustomEvent(FETCH_RESPONSE_EVENT, { detail }));
156
- });
96
+ document.addEventListener(LOAD_DEFERRED_IMAGES_RESET_ZOOM_LEVEL_EVENT, onLoadDeferredImagesResetZoomLevel);
97
+ document.addEventListener(DISPATCH_SCROLL_START_EVENT, onDispatchScrollStart);
98
+ document.addEventListener(DISPATCH_SCROLL_END_EVENT, onDispatchScrollEnd);
99
+ document.addEventListener(BLOCK_COOKIES_START_EVENT, onBlockCookiesStart);
100
+ document.addEventListener(BLOCK_COOKIES_END_EVENT, onBlockCookiesEnd);
101
+ document.addEventListener(BLOCK_STORAGE_START_EVENT, onBlockStorageStart);
102
+ document.addEventListener(BLOCK_STORAGE_END_EVENT, onBlockStorageEnd);
103
+ document.addEventListener(FETCH_SUPPORTED_REQUEST_EVENT, onFetchSupportedRequest);
104
+ document.addEventListener(FETCH_REQUEST_EVENT, onFetchRequest);
157
105
  document.addEventListener(GET_ADOPTED_STYLESHEETS_REQUEST_EVENT, getAdoptedStylesheetsListener);
158
- document.addEventListener(BOOTSTRAP_EVENT, event => {
159
- try {
160
- if (globalThis.bootstrap && event.detail.data) {
161
- globalThis.bootstrap(event.detail.data);
162
- }
163
- // eslint-disable-next-line no-unused-vars
164
- } catch (error) {
165
- // ignored
106
+ document.addEventListener(BOOTSTRAP_EVENT, onBootstrap);
107
+ }
108
+
109
+ function onLoadDeferredImagesStart() {
110
+ loadDeferredImagesStart();
111
+ }
112
+
113
+ function onLoadDeferredImagesKeepZoomLevelStart() {
114
+ loadDeferredImagesStart(true);
115
+ }
116
+
117
+ function onLoadDeferredImagesEnd() {
118
+ loadDeferredImagesEnd();
119
+ }
120
+
121
+ function onLoadDeferredImagesKeepZoomLevelEnd() {
122
+ loadDeferredImagesEnd(true);
123
+ }
124
+
125
+ function onLoadDeferredImagesResetZoomLevel() {
126
+ const transform = document.documentElement.style.getPropertyValue("-sf-transform");
127
+ const transformPriority = document.documentElement.style.getPropertyPriority("-sf-transform");
128
+ const transformOrigin = document.documentElement.style.getPropertyValue("-sf-transform-origin");
129
+ const transformOriginPriority = document.documentElement.style.getPropertyPriority("-sf-transform-origin");
130
+ const minHeight = document.documentElement.style.getPropertyValue("-sf-min-height");
131
+ const minHeightPriority = document.documentElement.style.getPropertyPriority("-sf-min-height");
132
+ document.documentElement.style.setProperty("transform", transform, transformPriority);
133
+ document.documentElement.style.setProperty("transform-origin", transformOrigin, transformOriginPriority);
134
+ document.documentElement.style.setProperty("min-height", minHeight, minHeightPriority);
135
+ document.documentElement.style.removeProperty("-sf-transform");
136
+ document.documentElement.style.removeProperty("-sf-transform-origin");
137
+ document.documentElement.style.removeProperty("-sf-min-height");
138
+ resetScreenSize();
139
+ }
140
+
141
+ function onDispatchScrollStart() {
142
+ dispatchScrollEvent = true;
143
+ }
144
+
145
+ function onDispatchScrollEnd() {
146
+ dispatchScrollEvent = false;
147
+ }
148
+
149
+ function onBlockCookiesStart() {
150
+ try {
151
+ document.__defineGetter__("cookie", () => { throw new Error("document.cookie temporary blocked by SingleFile"); });
152
+ // eslint-disable-next-line no-unused-vars
153
+ } catch (error) {
154
+ // ignored
155
+ }
156
+ }
157
+
158
+ function onBlockCookiesEnd() {
159
+ delete document.cookie;
160
+ }
161
+
162
+ function onBlockStorageStart() {
163
+ if (!globalThis._singleFile_localStorage) {
164
+ globalThis._singleFile_localStorage = globalThis.localStorage;
165
+ globalThis.__defineGetter__("localStorage", () => { throw new Error("localStorage temporary blocked by SingleFile"); });
166
+ }
167
+ if (!globalThis._singleFile_indexedDB) {
168
+ globalThis._singleFile_indexedDB = globalThis.indexedDB;
169
+ globalThis.__defineGetter__("indexedDB", () => { throw new Error("indexedDB temporary blocked by SingleFile"); });
170
+ }
171
+ }
172
+
173
+ function onBlockStorageEnd() {
174
+ if (globalThis._singleFile_localStorage) {
175
+ delete globalThis.localStorage;
176
+ globalThis.localStorage = globalThis._singleFile_localStorage;
177
+ delete globalThis._singleFile_localStorage;
178
+ }
179
+ if (!globalThis._singleFile_indexedDB) {
180
+ delete globalThis.indexedDB;
181
+ globalThis.indexedDB = globalThis._singleFile_indexedDB;
182
+ delete globalThis._singleFile_indexedDB;
183
+ }
184
+ }
185
+
186
+ function onFetchSupportedRequest() {
187
+ document.dispatchEvent(new CustomEvent(FETCH_SUPPORTED_RESPONSE_EVENT));
188
+ }
189
+
190
+ async function onFetchRequest(event) {
191
+ const { url, options } = JSON.parse(event.detail);
192
+ let detail;
193
+ try {
194
+ const response = await fetch(url, options);
195
+ detail = { url, response: await response.arrayBuffer(), headers: [...response.headers], status: response.status };
196
+ } catch (error) {
197
+ detail = { url, error: error && (error.message || error.toString()) };
198
+ }
199
+ document.dispatchEvent(new CustomEvent(FETCH_RESPONSE_EVENT, { detail }));
200
+ }
201
+
202
+ function onBootstrap(event) {
203
+ try {
204
+ if (globalThis.bootstrap && event.detail.data) {
205
+ globalThis.bootstrap(event.detail.data);
166
206
  }
167
- });
207
+ // eslint-disable-next-line no-unused-vars
208
+ } catch (error) {
209
+ // ignored
210
+ }
168
211
  }
169
212
 
170
213
  function loadDeferredImagesStart(keepZoomLevel) {
@@ -358,6 +401,7 @@
358
401
  };
359
402
  globalThis.FontFace.prototype = origFontFace.prototype;
360
403
  globalThis.FontFace.toString = function () { return "function FontFace() { [native code] }"; };
404
+ setFunctionName(globalThis.FontFace, "FontFace");
361
405
  const deleteFont = document.fonts.delete;
362
406
  document.fonts.delete = function (fontFace) {
363
407
  try {
@@ -383,12 +427,12 @@
383
427
  }
384
428
 
385
429
  if (globalThis.IntersectionObserver) {
386
- const IntersectionObserver = globalThis.IntersectionObserver;
387
- globalThis.IntersectionObserver = function () {
430
+ const origIntersectionObserver = globalThis.IntersectionObserver;
431
+ globalThis.IntersectionObserver = function IntersectionObserver() {
388
432
  try {
389
- const intersectionObserver = new IntersectionObserver(...arguments);
390
- const observeIntersection = IntersectionObserver.prototype.observe || intersectionObserver.observe;
391
- const unobserveIntersection = IntersectionObserver.prototype.unobserve || intersectionObserver.unobserve;
433
+ const intersectionObserver = new origIntersectionObserver(...arguments);
434
+ const observeIntersection = origIntersectionObserver.prototype.observe || intersectionObserver.observe;
435
+ const unobserveIntersection = origIntersectionObserver.prototype.unobserve || intersectionObserver.unobserve;
392
436
  const callback = arguments[0];
393
437
  const options = arguments[1];
394
438
  if (observeIntersection) {
@@ -436,8 +480,9 @@
436
480
  throw error;
437
481
  }
438
482
  };
439
- globalThis.IntersectionObserver.prototype = IntersectionObserver.prototype;
483
+ globalThis.IntersectionObserver.prototype = origIntersectionObserver.prototype;
440
484
  globalThis.IntersectionObserver.toString = function () { return "function IntersectionObserver() { [native code] }"; };
485
+ setFunctionName(globalThis.IntersectionObserver, "IntersectionObserver");
441
486
  }
442
487
 
443
488
  const originalReplaceSync = CSSStyleSheet.prototype.replaceSync;
@@ -521,18 +566,19 @@
521
566
  }
522
567
  });
523
568
  }
524
- return new Promise(resolve => {
525
- if (detail.src instanceof ArrayBuffer) {
526
- const reader = new FileReader();
527
- reader.readAsDataURL(new Blob([detail.src]));
528
- reader.addEventListener("load", () => {
529
- detail.src = "url(" + reader.result + ")";
530
- resolve(detail);
531
- });
532
- } else {
533
- resolve(detail);
569
+ if (detail.src instanceof ArrayBuffer) {
570
+ const bytes = new Uint8Array(detail.src);
571
+ let content = "";
572
+ for (let offset = 0; offset < bytes.length; offset += 8192) {
573
+ content += String.fromCharCode(...bytes.subarray(offset, offset + 8192));
534
574
  }
535
- });
575
+ detail.src = "url(data:application/octet-stream;base64," + btoa(content) + ")";
576
+ }
577
+ return detail;
578
+ }
579
+
580
+ function setFunctionName(fn, name) {
581
+ Object.defineProperty(fn, "name", { value: name, configurable: true });
536
582
  }
537
583
 
538
584
  function dispatchResizeEvent() {
@@ -547,4 +593,4 @@
547
593
  }
548
594
  }
549
595
 
550
- })(typeof globalThis == "object" ? globalThis : globalThis.window);
596
+ })();
@@ -65,26 +65,36 @@ new MutationObserver(init).observe(document, { childList: true });
65
65
 
66
66
  function init() {
67
67
  if (document instanceof Document) {
68
- document.addEventListener(NEW_FONT_FACE_EVENT, event => {
69
- const detail = event.detail;
70
- const key = Object.assign({}, detail);
71
- delete key.src;
72
- fontFaces.set(JSON.stringify(key), detail);
73
- });
74
- document.addEventListener(DELETE_FONT_EVENT, event => {
75
- const detail = event.detail;
76
- const key = Object.assign({}, detail);
77
- delete key.src;
78
- fontFaces.delete(JSON.stringify(key));
79
- });
80
- document.addEventListener(CLEAR_FONTS_EVENT, () => fontFaces = new Map());
81
- document.addEventListener(NEW_WORKLET_EVENT, event => {
82
- const detail = event.detail;
83
- worklets.set(detail.moduleURL, detail);
84
- });
68
+ document.addEventListener(NEW_FONT_FACE_EVENT, onNewFontFace);
69
+ document.addEventListener(DELETE_FONT_EVENT, onDeleteFont);
70
+ document.addEventListener(CLEAR_FONTS_EVENT, onClearFonts);
71
+ document.addEventListener(NEW_WORKLET_EVENT, onNewWorklet);
85
72
  }
86
73
  }
87
74
 
75
+ function onNewFontFace(event) {
76
+ const detail = event.detail;
77
+ const key = Object.assign({}, detail);
78
+ delete key.src;
79
+ fontFaces.set(JSON.stringify(key), detail);
80
+ }
81
+
82
+ function onDeleteFont(event) {
83
+ const detail = event.detail;
84
+ const key = Object.assign({}, detail);
85
+ delete key.src;
86
+ fontFaces.delete(JSON.stringify(key));
87
+ }
88
+
89
+ function onClearFonts() {
90
+ fontFaces.clear();
91
+ }
92
+
93
+ function onNewWorklet(event) {
94
+ const detail = event.detail;
95
+ worklets.set(detail.moduleURL, detail);
96
+ }
97
+
88
98
  export {
89
99
  getFontsData,
90
100
  getWorkletsData,
@@ -21,11 +21,11 @@
21
21
  * Source.
22
22
  */
23
23
 
24
- /* global window, document */
24
+ /* global document */
25
25
 
26
26
  import { appendInfobar, refreshInfobarInfo, extractInfobarData } from "./core/infobar.js";
27
27
 
28
- (globalThis => {
28
+ (() => {
29
29
 
30
30
  const browser = globalThis.browser;
31
31
  const MutationObserver = globalThis.MutationObserver;
@@ -36,7 +36,8 @@ import { appendInfobar, refreshInfobarInfo, extractInfobarData } from "./core/in
36
36
  if (globalThis.window == globalThis.top) {
37
37
  document.addEventListener("single-file-display-infobar", displayIcon, false);
38
38
  if (document.documentElement.getAttribute("data-sfz") == "" && !mutationObserver) {
39
- mutationObserver = new MutationObserver(init).observe(document, { childList: true });
39
+ mutationObserver = new MutationObserver(init);
40
+ mutationObserver.observe(document, { childList: true });
40
41
  } else {
41
42
  if (document.readyState == "loading") {
42
43
  document.addEventListener("DOMContentLoaded", displayIcon, false);
@@ -77,4 +78,4 @@ import { appendInfobar, refreshInfobarInfo, extractInfobarData } from "./core/in
77
78
  }
78
79
  }
79
80
 
80
- })(typeof globalThis == "object" ? globalThis : window);
81
+ })();