377 lines
14 KiB
Diff
377 lines
14 KiB
Diff
diff --git a/build/build.js b/build/build.js
|
|
index b3c9aad4..c4df034f 100644
|
|
--- a/build/build.js
|
|
+++ b/build/build.js
|
|
@@ -23,6 +23,9 @@ rm('-rf', assetsPath)
|
|
mkdir('-p', assetsPath)
|
|
cp('-R', 'static/*', assetsPath)
|
|
|
|
+sed('-i', /'jxl_dec.js/, "'/node_modules/jxl.js/jxl_dec.js", 'node_modules/jxl.js/jxl.js')
|
|
+sed('-i', /"jxl_dec.wasm/, '"/node_modules/jxl.js/jxl_dec.wasm', 'node_modules/jxl.js/jxl_dec.js')
|
|
+
|
|
webpack(webpackConfig, function (err, stats) {
|
|
spinner.stop()
|
|
if (err) throw err
|
|
diff --git a/build/dev-server.js b/build/dev-server.js
|
|
index 5acd0fed..ef275509 100644
|
|
--- a/build/dev-server.js
|
|
+++ b/build/dev-server.js
|
|
@@ -5,11 +5,15 @@ var path = require('path')
|
|
var express = require('express')
|
|
var webpack = require('webpack')
|
|
var opn = require('opn')
|
|
+require('shelljs/global')
|
|
var proxyMiddleware = require('http-proxy-middleware')
|
|
var webpackConfig = process.env.NODE_ENV === 'testing'
|
|
? require('./webpack.prod.conf')
|
|
: require('./webpack.dev.conf')
|
|
|
|
+sed('-i', /'jxl_dec.js/, "'/node_modules/jxl.js/jxl_dec.js", 'node_modules/jxl.js/jxl.js')
|
|
+sed('-i', /"jxl_dec.wasm/, '"/node_modules/jxl.js/jxl_dec.wasm', 'node_modules/jxl.js/jxl_dec.js')
|
|
+
|
|
// default port where dev server listens for incoming traffic
|
|
var port = process.env.PORT || config.dev.port
|
|
// Define HTTP proxies to your custom API backend
|
|
diff --git a/build/webpack.base.conf.js b/build/webpack.base.conf.js
|
|
index 2a3db96e..665eaa21 100644
|
|
--- a/build/webpack.base.conf.js
|
|
+++ b/build/webpack.base.conf.js
|
|
@@ -2,6 +2,8 @@ var path = require('path')
|
|
var config = require('../config')
|
|
var utils = require('./utils')
|
|
var projectRoot = path.resolve(__dirname, '../')
|
|
+const CopyPlugin = require("copy-webpack-plugin");
|
|
+const WriteFilePlugin = require("write-file-webpack-plugin");
|
|
var { VueLoaderPlugin } = require('vue-loader')
|
|
|
|
var env = process.env.NODE_ENV
|
|
@@ -118,6 +120,14 @@ module.exports = {
|
|
]
|
|
},
|
|
plugins: [
|
|
- new VueLoaderPlugin()
|
|
+ new VueLoaderPlugin(),
|
|
+ new CopyPlugin({
|
|
+ patterns: [
|
|
+ {
|
|
+ from: "node_modules/jxl.js/jxl*"
|
|
+ }
|
|
+ ]
|
|
+ }),
|
|
+ new WriteFilePlugin()
|
|
]
|
|
}
|
|
diff --git a/package.json b/package.json
|
|
index 19a7e186..54a9c4af 100644
|
|
--- a/package.json
|
|
+++ b/package.json
|
|
@@ -32,6 +32,7 @@
|
|
"diff": "3.5.0",
|
|
"escape-html": "1.0.3",
|
|
"js-cookie": "^3.0.1",
|
|
+ "jxl.js": "^1.0.0",
|
|
"localforage": "1.10.0",
|
|
"parse-link-header": "^2.0.0",
|
|
"phoenix": "1.6.2",
|
|
@@ -63,6 +64,7 @@
|
|
"chalk": "1.1.3",
|
|
"chromedriver": "^107.0.3",
|
|
"connect-history-api-fallback": "^2.0.0",
|
|
+ "copy-webpack-plugin": "^11.0.0",
|
|
"cross-spawn": "^7.0.3",
|
|
"css-loader": "^6.7.2",
|
|
"custom-event-polyfill": "^1.0.7",
|
|
@@ -124,7 +126,8 @@
|
|
"webpack-dev-middleware": "^5.3.3",
|
|
"webpack-hot-middleware": "^2.25.1",
|
|
"webpack-merge": "^5.8.0",
|
|
- "workbox-webpack-plugin": "^6.5.4"
|
|
+ "workbox-webpack-plugin": "^6.5.4",
|
|
+ "write-file-webpack-plugin": "^4.5.1"
|
|
},
|
|
"engines": {
|
|
"node": ">= 16.0.0",
|
|
diff --git a/src/App.js b/src/App.js
|
|
index d4b3b41a..ef67a6a4 100644
|
|
--- a/src/App.js
|
|
+++ b/src/App.js
|
|
@@ -53,6 +53,9 @@ export default {
|
|
unmounted () {
|
|
window.removeEventListener('resize', this.updateMobileState)
|
|
},
|
|
+ mounted() {
|
|
+ import("./lib/jxl.js").then(jxl => jxl.startPolyfill());
|
|
+ },
|
|
computed: {
|
|
classes () {
|
|
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
|
|
index bbceba0b..92cfd7cd 100644
|
|
--- a/yarn.lock
|
|
+++ b/yarn.lock
|
|
@@ -2732,7 +2732,7 @@ chalk@1.1.3, chalk@^1.0.0, chalk@^1.1.1, chalk@^1.1.3:
|
|
strip-ansi "^3.0.0"
|
|
supports-color "^2.0.0"
|
|
|
|
-chalk@^2.0.0, chalk@^2.0.1, chalk@^2.1.0:
|
|
+chalk@^2.0.0, chalk@^2.0.1, chalk@^2.1.0, chalk@^2.4.0:
|
|
version "2.4.2"
|
|
resolved "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz"
|
|
integrity sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==
|
|
@@ -2994,6 +2994,18 @@ cookie@0.4.2, cookie@~0.4.1:
|
|
resolved "https://registry.npmjs.org/cookie/-/cookie-0.4.2.tgz"
|
|
integrity sha512-aSWTXFzaKWkvHO1Ny/s+ePFpvKsPnjc551iI41v3ny/ow6tBG5Vd+FuqGNhh1LxOmVzOlGUriIlOaokOvhaStA==
|
|
|
|
+copy-webpack-plugin@^11.0.0:
|
|
+ version "11.0.0"
|
|
+ resolved "https://registry.yarnpkg.com/copy-webpack-plugin/-/copy-webpack-plugin-11.0.0.tgz#96d4dbdb5f73d02dd72d0528d1958721ab72e04a"
|
|
+ integrity sha512-fX2MWpamkW0hZxMEg0+mYnA40LTosOSa5TqZ9GYIBzyJa9C3QUaMPSE2xAi/buNr8u89SfD9wHSQVBzrRa/SOQ==
|
|
+ dependencies:
|
|
+ fast-glob "^3.2.11"
|
|
+ glob-parent "^6.0.1"
|
|
+ globby "^13.1.1"
|
|
+ normalize-path "^3.0.0"
|
|
+ schema-utils "^4.0.0"
|
|
+ serialize-javascript "^6.0.0"
|
|
+
|
|
core-js-compat@^3.20.2, core-js-compat@^3.21.0:
|
|
version "3.24.1"
|
|
resolved "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.24.1.tgz"
|
|
@@ -3187,7 +3199,7 @@ debug@4.3.1:
|
|
dependencies:
|
|
ms "2.1.2"
|
|
|
|
-debug@^3.2.7:
|
|
+debug@^3.1.0, debug@^3.2.7:
|
|
version "3.2.7"
|
|
resolved "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz"
|
|
integrity sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==
|
|
@@ -4006,7 +4018,7 @@ fast-deep-equal@^3.1.1, fast-deep-equal@^3.1.3:
|
|
resolved "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz"
|
|
integrity sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==
|
|
|
|
-fast-glob@^3.2.12:
|
|
+fast-glob@^3.2.11, fast-glob@^3.2.12:
|
|
version "3.2.12"
|
|
resolved "https://registry.yarnpkg.com/fast-glob/-/fast-glob-3.2.12.tgz#7f39ec99c2e6ab030337142da9e0c18f37afae80"
|
|
integrity sha512-DVj4CQIYYow0BlaelwK1pHl5n5cRSJfM60UA0zK891sVInoPri2Ekj7+e1CT3/3qxXenpI+nBBmQAcJPJgaj4w==
|
|
@@ -4084,6 +4096,11 @@ filelist@^1.0.1:
|
|
dependencies:
|
|
minimatch "^5.0.1"
|
|
|
|
+filesize@^3.6.1:
|
|
+ version "3.6.1"
|
|
+ resolved "https://registry.yarnpkg.com/filesize/-/filesize-3.6.1.tgz#090bb3ee01b6f801a8a8be99d31710b3422bb317"
|
|
+ integrity sha512-7KjR1vv6qnicaPMi1iiTcI85CyYwRO/PSFCu6SvqL8jN2Wjt/NIYQTFtFs7fSDCYOstUkEWIQGFUg5YZQfjlcg==
|
|
+
|
|
fill-range@^7.0.1:
|
|
version "7.0.1"
|
|
resolved "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz"
|
|
@@ -4343,6 +4360,13 @@ glob-parent@^5.1.2, glob-parent@~5.1.2:
|
|
dependencies:
|
|
is-glob "^4.0.1"
|
|
|
|
+glob-parent@^6.0.1:
|
|
+ version "6.0.2"
|
|
+ resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-6.0.2.tgz#6d237d99083950c79290f24c7642a3de9a28f9e3"
|
|
+ integrity sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==
|
|
+ dependencies:
|
|
+ is-glob "^4.0.3"
|
|
+
|
|
glob-to-regexp@^0.4.1:
|
|
version "0.4.1"
|
|
resolved "https://registry.yarnpkg.com/glob-to-regexp/-/glob-to-regexp-0.4.1.tgz#c75297087c851b9a578bd217dd59a92f59fe546e"
|
|
@@ -4440,6 +4464,17 @@ globby@^11.1.0:
|
|
merge2 "^1.4.1"
|
|
slash "^3.0.0"
|
|
|
|
+globby@^13.1.1:
|
|
+ version "13.1.2"
|
|
+ resolved "https://registry.yarnpkg.com/globby/-/globby-13.1.2.tgz#29047105582427ab6eca4f905200667b056da515"
|
|
+ integrity sha512-LKSDZXToac40u8Q1PQtZihbNdTYSNMuWe+K5l+oa6KgDzSvVrHXlJy40hUP522RjAIoNLJYBJi7ow+rbFpIhHQ==
|
|
+ dependencies:
|
|
+ dir-glob "^3.0.1"
|
|
+ fast-glob "^3.2.11"
|
|
+ ignore "^5.2.0"
|
|
+ merge2 "^1.4.1"
|
|
+ slash "^4.0.0"
|
|
+
|
|
globjoin@^0.1.4:
|
|
version "0.1.4"
|
|
resolved "https://registry.npmjs.org/globjoin/-/globjoin-0.1.4.tgz"
|
|
@@ -4452,7 +4487,7 @@ gonzales-pe@^4.3.0:
|
|
dependencies:
|
|
minimist "^1.2.5"
|
|
|
|
-graceful-fs@^4.1.2, graceful-fs@^4.1.6, graceful-fs@^4.2.0, graceful-fs@^4.2.4, graceful-fs@^4.2.6, graceful-fs@^4.2.9:
|
|
+graceful-fs@^4.1.11, graceful-fs@^4.1.2, graceful-fs@^4.1.6, graceful-fs@^4.2.0, graceful-fs@^4.2.4, graceful-fs@^4.2.6, graceful-fs@^4.2.9:
|
|
version "4.2.10"
|
|
resolved "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.10.tgz"
|
|
integrity sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA==
|
|
@@ -5314,6 +5349,11 @@ jsonpointer@^5.0.0:
|
|
resolved "https://registry.yarnpkg.com/jsonpointer/-/jsonpointer-5.0.1.tgz#2110e0af0900fd37467b5907ecd13a7884a1b559"
|
|
integrity sha512-p/nXbhSEcu3pZRdkW1OfJhpsVtW1gd4Wa1fnQc9YLiTfAjn0312eMKimbdIQzuZl9aa9xUGaRlP9T/CJE/ditQ==
|
|
|
|
+jxl.js@^1.0.0:
|
|
+ version "1.0.0"
|
|
+ resolved "https://registry.yarnpkg.com/jxl.js/-/jxl.js-1.0.0.tgz#e2c78e5c135d7d272c0d36f86b7f79de6f4b40b3"
|
|
+ integrity sha512-1br2vK02/9nYAbIEdrt7Qe6uRk5e+S0TGoRxUlxnGpXJYARfhFAfFHHArcQYjU4WMPNjLPci4oXBNsEUFVdEEQ==
|
|
+
|
|
karma-coverage@1.1.2:
|
|
version "1.1.2"
|
|
resolved "https://registry.npmjs.org/karma-coverage/-/karma-coverage-1.1.2.tgz"
|
|
@@ -5679,7 +5719,7 @@ lodash.truncate@^4.4.2:
|
|
resolved "https://registry.yarnpkg.com/lodash.truncate/-/lodash.truncate-4.4.2.tgz#5a350da0b1113b837ecfffd5812cbe58d6eae193"
|
|
integrity sha512-jttmRe7bRse52OsWIMDLaXxWqRAmtIUccAQ3garviCqJjafXOfNMO0yMfNpdD6zbGaTU0P5Nz7e7gAT6cKmJRw==
|
|
|
|
-lodash@4.17.21, lodash@^4.17.0, lodash@^4.17.10, lodash@^4.17.15, lodash@^4.17.20, lodash@^4.17.21, lodash@^4.17.4:
|
|
+lodash@4.17.21, lodash@^4.17.0, lodash@^4.17.10, lodash@^4.17.13, lodash@^4.17.15, lodash@^4.17.20, lodash@^4.17.21, lodash@^4.17.4:
|
|
version "4.17.21"
|
|
resolved "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz"
|
|
integrity sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==
|
|
@@ -6007,6 +6047,11 @@ mocha@3.5.3:
|
|
mkdirp "0.5.1"
|
|
supports-color "3.1.2"
|
|
|
|
+moment@^2.22.1:
|
|
+ version "2.29.4"
|
|
+ resolved "https://registry.yarnpkg.com/moment/-/moment-2.29.4.tgz#3dbe052889fe7c1b2ed966fcb3a77328964ef108"
|
|
+ integrity sha512-5LC9SOxjSc2HF6vO2CyuTDNivEdoz2IvyJJGj6X8DJ0eFyfszE0QiEd+iXmBvUP3WHxSjFH/vIsA0EN00cgr8w==
|
|
+
|
|
ms@0.7.1:
|
|
version "0.7.1"
|
|
resolved "https://registry.npmjs.org/ms/-/ms-0.7.1.tgz"
|
|
@@ -7414,6 +7459,11 @@ slash@^3.0.0:
|
|
resolved "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz"
|
|
integrity sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==
|
|
|
|
+slash@^4.0.0:
|
|
+ version "4.0.0"
|
|
+ resolved "https://registry.yarnpkg.com/slash/-/slash-4.0.0.tgz#2422372176c4c6c5addb5e2ada885af984b396a7"
|
|
+ integrity sha512-3dOsAHXXUkQTpOYcoAxLIorMTp4gIQr5IW3iVb7A7lFIp0VHhnynm9izx6TssdrIcVIESAlVjtnO2K8bg+Coew==
|
|
+
|
|
slice-ansi@^4.0.0:
|
|
version "4.0.0"
|
|
resolved "https://registry.yarnpkg.com/slice-ansi/-/slice-ansi-4.0.0.tgz#500e8dd0fd55b05815086255b3195adf2a45fe6b"
|
|
@@ -8661,6 +8711,15 @@ wrappy@1:
|
|
resolved "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz"
|
|
integrity sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==
|
|
|
|
+write-file-atomic@^2.3.0:
|
|
+ version "2.4.3"
|
|
+ resolved "https://registry.yarnpkg.com/write-file-atomic/-/write-file-atomic-2.4.3.tgz#1fd2e9ae1df3e75b8d8c367443c692d4ca81f481"
|
|
+ integrity sha512-GaETH5wwsX+GcnzhPgKcKjJ6M2Cq3/iZp1WyY/X1CSqrW+jVNM9Y7D8EC2sM4ZG/V8wZlSniJnCKWPmBYAucRQ==
|
|
+ dependencies:
|
|
+ graceful-fs "^4.1.11"
|
|
+ imurmurhash "^0.1.4"
|
|
+ signal-exit "^3.0.2"
|
|
+
|
|
write-file-atomic@^4.0.2:
|
|
version "4.0.2"
|
|
resolved "https://registry.yarnpkg.com/write-file-atomic/-/write-file-atomic-4.0.2.tgz#a9df01ae5b77858a027fd2e80768ee433555fcfd"
|
|
@@ -8669,6 +8728,19 @@ write-file-atomic@^4.0.2:
|
|
imurmurhash "^0.1.4"
|
|
signal-exit "^3.0.7"
|
|
|
|
+write-file-webpack-plugin@^4.5.1:
|
|
+ version "4.5.1"
|
|
+ resolved "https://registry.yarnpkg.com/write-file-webpack-plugin/-/write-file-webpack-plugin-4.5.1.tgz#aeeb68889194da5ec8a864667d46da9e00ee92d5"
|
|
+ integrity sha512-AZ7qJUvhTCBiOtG21aFJUcNuLVo2FFM6JMGKvaUGAH+QDqQAp2iG0nq3GcuXmJOFQR2JjpjhyYkyPrbFKhdjNQ==
|
|
+ dependencies:
|
|
+ chalk "^2.4.0"
|
|
+ debug "^3.1.0"
|
|
+ filesize "^3.6.1"
|
|
+ lodash "^4.17.13"
|
|
+ mkdirp "^0.5.1"
|
|
+ moment "^2.22.1"
|
|
+ write-file-atomic "^2.3.0"
|
|
+
|
|
ws@~8.2.3:
|
|
version "8.2.3"
|
|
resolved "https://registry.npmjs.org/ws/-/ws-8.2.3.tgz"
|