Fix the pleroma-fe jxl polyfill patch
This commit is contained in:
parent
a38f86d634
commit
17d90356fb
1 changed files with 89 additions and 5 deletions
|
@ -92,21 +92,105 @@ index 19a7e186..54a9c4af 100644
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">= 16.0.0",
|
"node": ">= 16.0.0",
|
||||||
diff --git a/src/App.js b/src/App.js
|
diff --git a/src/App.js b/src/App.js
|
||||||
index d4b3b41a..ee75815b 100644
|
index d4b3b41a..ef67a6a4 100644
|
||||||
--- a/src/App.js
|
--- a/src/App.js
|
||||||
+++ b/src/App.js
|
+++ b/src/App.js
|
||||||
@@ -53,6 +53,11 @@ export default {
|
@@ -53,6 +53,9 @@ export default {
|
||||||
unmounted () {
|
unmounted () {
|
||||||
window.removeEventListener('resize', this.updateMobileState)
|
window.removeEventListener('resize', this.updateMobileState)
|
||||||
},
|
},
|
||||||
+ mounted() {
|
+ mounted() {
|
||||||
+ let jxlPolyfill = document.createElement("script");
|
+ import("./lib/jxl.js").then(jxl => jxl.startPolyfill());
|
||||||
+ jxlPolyfill.setAttribute("src", "/node_modules/jxl.js/jxl.js");
|
|
||||||
+ document.head.appendChild(jxlPolyfill);
|
|
||||||
+ },
|
+ },
|
||||||
computed: {
|
computed: {
|
||||||
classes () {
|
classes () {
|
||||||
return [
|
return [
|
||||||
|
diff --git a/src/lib/jxl.js b/src/lib/jxl.js
|
||||||
|
new file mode 100644
|
||||||
|
index 00000000..568b5293
|
||||||
|
--- /dev/null
|
||||||
|
+++ b/src/lib/jxl.js
|
||||||
|
@@ -0,0 +1,80 @@
|
||||||
|
+const config = {
|
||||||
|
+ useCache: true
|
||||||
|
+};
|
||||||
|
+
|
||||||
|
+let cache, workers = {};
|
||||||
|
+
|
||||||
|
+function imgDataToDataURL(img, imgData, isCSS) {
|
||||||
|
+ const jxlSrc = img.dataset.jxlSrc;
|
||||||
|
+ if (imgData instanceof Blob) {
|
||||||
|
+ const dataURL = URL.createObjectURL(imgData);
|
||||||
|
+ if (isCSS)
|
||||||
|
+ img.style.backgroundImage = 'url("' + dataURL + '")';
|
||||||
|
+ else
|
||||||
|
+ img.src = dataURL;
|
||||||
|
+ } else if ('OffscreenCanvas' in window) {
|
||||||
|
+ const canvas = new OffscreenCanvas(imgData.width, imgData.height);
|
||||||
|
+ workers[jxlSrc].postMessage({ canvas, imgData }, [canvas]);
|
||||||
|
+ workers[jxlSrc].addEventListener('message', m => {
|
||||||
|
+ if (m.data.url && m.data.blob) {
|
||||||
|
+ if (isCSS)
|
||||||
|
+ img.style.backgroundImage = 'url("' + m.data.url + '")';
|
||||||
|
+ else
|
||||||
|
+ img.src = m.data.url;
|
||||||
|
+ config.useCache && cache && cache.put(jxlSrc, new Response(m.data.blob));
|
||||||
|
+ }
|
||||||
|
+ });
|
||||||
|
+ } else {
|
||||||
|
+ const canvas = document.createElement('canvas');
|
||||||
|
+ canvas.width = imgData.width;
|
||||||
|
+ canvas.height = imgData.height;
|
||||||
|
+ canvas.getContext('2d').putImageData(imgData, 0, 0);
|
||||||
|
+ canvas.toBlob(blob => {
|
||||||
|
+ const dataURL = URL.createObjectURL(blob);
|
||||||
|
+ if (isCSS)
|
||||||
|
+ img.style.backgroundImage = 'url("' + dataURL + '")';
|
||||||
|
+ else
|
||||||
|
+ img.src = dataURL;
|
||||||
|
+ config.useCache && cache && cache.put(jxlSrc, new Response(blob));
|
||||||
|
+ }, 'image/jpeg');
|
||||||
|
+ }
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+
|
||||||
|
+async function decode(img, isCSS) {
|
||||||
|
+ const jxlSrc = img.dataset.jxlSrc = isCSS ? getComputedStyle(img).backgroundImage.slice(5, -2) : img.currentSrc;
|
||||||
|
+ img.src = 'data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw=='; // blank 1x1 image
|
||||||
|
+ if (config.useCache) {
|
||||||
|
+ try {
|
||||||
|
+ cache = cache || await caches.open('jxl');
|
||||||
|
+ } catch (e) { }
|
||||||
|
+ const cachedImg = cache && await cache.match(jxlSrc);
|
||||||
|
+ if (cachedImg) {
|
||||||
|
+ const cachedImgData = await cachedImg.blob();
|
||||||
|
+ requestAnimationFrame(() => imgDataToDataURL(img, cachedImgData, isCSS));
|
||||||
|
+ return;
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
+ const res = await fetch(jxlSrc);
|
||||||
|
+ const image = await res.arrayBuffer();
|
||||||
|
+ workers[jxlSrc] = new Worker('/node_modules/jxl.js/jxl_dec.js');
|
||||||
|
+ workers[jxlSrc].postMessage({ jxlSrc, image });
|
||||||
|
+ workers[jxlSrc].addEventListener('message', m => m.data.imgData && requestAnimationFrame(() => imgDataToDataURL(img, m.data.imgData, isCSS)));
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+function handleElement(el) {
|
||||||
|
+ if (el instanceof HTMLImageElement && el.src.endsWith('.jxl')) {
|
||||||
|
+ decode(el, false);
|
||||||
|
+ return;
|
||||||
|
+ } else if (el instanceof Element && getComputedStyle(el).backgroundImage.endsWith('.jxl)'))
|
||||||
|
+ decode(el, true);
|
||||||
|
+ el.childNodes.forEach(handleElement);
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+
|
||||||
|
+export function startPolyfill() {
|
||||||
|
+ new MutationObserver(mutations => mutations.forEach(mutation => {
|
||||||
|
+ mutation.addedNodes.forEach(handleElement);
|
||||||
|
+ })).observe(document.documentElement, { subtree: true, childList: true });
|
||||||
|
+ handleElement(document.documentElement); // Run the polyfill once on the full DOM
|
||||||
|
+}
|
||||||
diff --git a/yarn.lock b/yarn.lock
|
diff --git a/yarn.lock b/yarn.lock
|
||||||
index bbceba0b..92cfd7cd 100644
|
index bbceba0b..92cfd7cd 100644
|
||||||
--- a/yarn.lock
|
--- a/yarn.lock
|
||||||
|
|
Reference in a new issue