Compare commits
24 Commits
better-log
...
dependabot
Author | SHA1 | Date | |
---|---|---|---|
945cb28744 | |||
918c596cba | |||
42594277fd | |||
97d13de273 | |||
a1c3304c56 | |||
7a2fc917c1 | |||
1c4233b5ae | |||
4d67ec5a7b | |||
c24505230d | |||
2238d1abaf | |||
65ea02627b | |||
18b53e2b8a | |||
66ec763667 | |||
029eda7b37 | |||
e6810059ef | |||
4eba015009 | |||
dd49a1f23d | |||
5ecb99992c | |||
d9c6ebe0a2 | |||
fba67a7a18 | |||
129b925098 | |||
e23bc4d2e5 | |||
f523a07f01 | |||
e3f840c6da |
4
.gitattributes
vendored
4
.gitattributes
vendored
@ -1,2 +1,2 @@
|
||||
/codecs/**/*.js linguist-generated=true
|
||||
/codecs/*/pkg*/*.d.ts linguist-generated=true
|
||||
/codecs/**/*.js linguist-generated -diff
|
||||
/codecs/*/pkg*/*.d.ts linguist-generated
|
||||
|
1
.husky/pre-commit
Executable file
1
.husky/pre-commit
Executable file
@ -0,0 +1 @@
|
||||
npx lint-staged
|
@ -1,3 +1,7 @@
|
||||
# Project no longer maintained
|
||||
|
||||
Unfortunately, due to a few people leaving the team, and staffing issues resulting from the current economic climate (ugh), this package is no longer actively maintained. I know that sucks, but there simply isn't the time & people to work on this. If anyone from the community wants to fork it, you have my blessing. The [squoosh.app](https://squoosh.app) will continue to be supported and improved.
|
||||
|
||||
# Squoosh CLI
|
||||
|
||||
Squoosh CLI is an _experimental_ way to run all the codecs you know from the [Squoosh] web app on your command line using WebAssembly. The Squoosh CLI uses a worker pool to parallelize processing images. This way you can apply the same codec to many images at once.
|
||||
|
16
cli/package-lock.json
generated
16
cli/package-lock.json
generated
@ -1,12 +1,12 @@
|
||||
{
|
||||
"name": "@squoosh/cli",
|
||||
"version": "0.7.2",
|
||||
"version": "0.7.3",
|
||||
"lockfileVersion": 2,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "@squoosh/cli",
|
||||
"version": "0.7.2",
|
||||
"version": "0.7.3",
|
||||
"license": "Apache-2.0",
|
||||
"dependencies": {
|
||||
"@squoosh/lib": "^0.4.0",
|
||||
@ -36,9 +36,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/ansi-regex": {
|
||||
"version": "5.0.0",
|
||||
"resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.0.tgz",
|
||||
"integrity": "sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg==",
|
||||
"version": "5.0.1",
|
||||
"resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz",
|
||||
"integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==",
|
||||
"engines": {
|
||||
"node": ">=8"
|
||||
}
|
||||
@ -363,9 +363,9 @@
|
||||
}
|
||||
},
|
||||
"ansi-regex": {
|
||||
"version": "5.0.0",
|
||||
"resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.0.tgz",
|
||||
"integrity": "sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg=="
|
||||
"version": "5.0.1",
|
||||
"resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz",
|
||||
"integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ=="
|
||||
},
|
||||
"ansi-styles": {
|
||||
"version": "4.3.0",
|
||||
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@squoosh/cli",
|
||||
"version": "0.7.2",
|
||||
"version": "0.7.3",
|
||||
"description": "A CLI for Squoosh",
|
||||
"public": true,
|
||||
"type": "module",
|
||||
|
@ -1,5 +1,5 @@
|
||||
CODEC_URL = https://github.com/libjxl/libjxl.git
|
||||
CODEC_VERSION = v0.5
|
||||
CODEC_VERSION = 9f544641ec83f6abd9da598bdd08178ee8a003e0
|
||||
CODEC_DIR = node_modules/jxl
|
||||
CODEC_BUILD_ROOT := $(CODEC_DIR)/build
|
||||
CODEC_MT_BUILD_DIR := $(CODEC_BUILD_ROOT)/mt
|
||||
@ -75,6 +75,9 @@ $(CODEC_MT_SIMD_BUILD_DIR)/Makefile: CXXFLAGS+=-msimd128
|
||||
-DCMAKE_CROSSCOMPILING_EMULATOR=node \
|
||||
-B $(@D) \
|
||||
$(<D)
|
||||
emcc -Wall -O3 -o $(CODEC_DIR)/third_party/skcms/skcms.cc.o -I$(CODEC_DIR)/third_party/skcms -c $(CODEC_DIR)/third_party/skcms/skcms.cc
|
||||
llvm-ar rc $(CODEC_BUILD_DIR)/third_party/libskcms.a $(CODEC_DIR)/third_party/skcms/skcms.cc.o
|
||||
rm $(CODEC_DIR)/third_party/skcms/skcms.cc.o
|
||||
|
||||
$(CODEC_DIR)/CMakeLists.txt:
|
||||
$(RM) -r $(@D)
|
||||
|
2
codecs/jxl/dec/jxl_dec.js
generated
2
codecs/jxl/dec/jxl_dec.js
generated
File diff suppressed because one or more lines are too long
Binary file not shown.
2
codecs/jxl/dec/jxl_node_dec.js
generated
2
codecs/jxl/dec/jxl_node_dec.js
generated
File diff suppressed because one or more lines are too long
Binary file not shown.
@ -4,6 +4,7 @@
|
||||
#include "lib/jxl/base/thread_pool_internal.h"
|
||||
#include "lib/jxl/enc_external_image.h"
|
||||
#include "lib/jxl/enc_file.h"
|
||||
#include "lib/jxl/enc_color_management.h"
|
||||
|
||||
using namespace emscripten;
|
||||
|
||||
@ -17,6 +18,7 @@ struct JXLOptions {
|
||||
bool lossyPalette;
|
||||
size_t decodingSpeedTier;
|
||||
float photonNoiseIso;
|
||||
bool lossyModular;
|
||||
};
|
||||
|
||||
val encode(std::string image, int width, int height, JXLOptions options) {
|
||||
@ -50,11 +52,16 @@ val encode(std::string image, int width, int height, JXLOptions options) {
|
||||
float quality = options.quality;
|
||||
|
||||
// Quality settings roughly match libjpeg qualities.
|
||||
if (quality < 7 || quality == 100) {
|
||||
if (options.lossyModular || quality == 100) {
|
||||
cparams.modular_mode = true;
|
||||
// Internal modular quality to roughly match VarDCT size.
|
||||
cparams.quality_pair.first = cparams.quality_pair.second =
|
||||
std::min(35 + (quality - 7) * 3.0f, 100.0f);
|
||||
if (quality < 7) {
|
||||
cparams.quality_pair.first = cparams.quality_pair.second =
|
||||
std::min(35 + (quality - 7) * 3.0f, 100.0f);
|
||||
} else {
|
||||
cparams.quality_pair.first = cparams.quality_pair.second =
|
||||
std::min(35 + (quality - 7) * 65.f / 93.f, 100.0f);
|
||||
}
|
||||
} else {
|
||||
cparams.modular_mode = false;
|
||||
if (quality >= 30) {
|
||||
@ -91,14 +98,14 @@ val encode(std::string image, int width, int height, JXLOptions options) {
|
||||
jxl::Span<const uint8_t>(reinterpret_cast<const uint8_t*>(image.data()), image.size()), width,
|
||||
height, jxl::ColorEncoding::SRGB(/*is_gray=*/false), /*has_alpha=*/true,
|
||||
/*alpha_is_premultiplied=*/false, /*bits_per_sample=*/8, /*endiannes=*/JXL_LITTLE_ENDIAN,
|
||||
/*flipped_y=*/false, pool_ptr, main);
|
||||
/*flipped_y=*/false, pool_ptr, main, /*(only true if bits_per_sample==32) float_in=*/false);
|
||||
|
||||
if (!result) {
|
||||
return val::null();
|
||||
}
|
||||
|
||||
auto js_result = val::null();
|
||||
if (EncodeFile(cparams, &io, &passes_enc_state, &bytes, /*aux=*/nullptr, pool_ptr)) {
|
||||
if (EncodeFile(cparams, &io, &passes_enc_state, &bytes, jxl::GetJxlCms(), /*aux=*/nullptr, pool_ptr)) {
|
||||
js_result = Uint8Array.new_(typed_memory_view(bytes.size(), bytes.data()));
|
||||
}
|
||||
|
||||
@ -113,6 +120,7 @@ EMSCRIPTEN_BINDINGS(my_module) {
|
||||
.field("lossyPalette", &JXLOptions::lossyPalette)
|
||||
.field("decodingSpeedTier", &JXLOptions::decodingSpeedTier)
|
||||
.field("photonNoiseIso", &JXLOptions::photonNoiseIso)
|
||||
.field("lossyModular", &JXLOptions::lossyModular)
|
||||
.field("epf", &JXLOptions::epf);
|
||||
|
||||
function("encode", &encode);
|
||||
|
1
codecs/jxl/enc/jxl_enc.d.ts
vendored
1
codecs/jxl/enc/jxl_enc.d.ts
vendored
@ -6,6 +6,7 @@ export interface EncodeOptions {
|
||||
lossyPalette: boolean;
|
||||
decodingSpeedTier: number;
|
||||
photonNoiseIso: number;
|
||||
lossyModular: boolean;
|
||||
}
|
||||
|
||||
export interface JXLModule extends EmscriptenWasm.Module {
|
||||
|
2
codecs/jxl/enc/jxl_enc.js
generated
2
codecs/jxl/enc/jxl_enc.js
generated
File diff suppressed because one or more lines are too long
Binary file not shown.
2
codecs/jxl/enc/jxl_enc_mt.js
generated
2
codecs/jxl/enc/jxl_enc_mt.js
generated
File diff suppressed because one or more lines are too long
Binary file not shown.
2
codecs/jxl/enc/jxl_enc_mt_simd.js
generated
2
codecs/jxl/enc/jxl_enc_mt_simd.js
generated
File diff suppressed because one or more lines are too long
Binary file not shown.
2
codecs/jxl/enc/jxl_node_enc.js
generated
2
codecs/jxl/enc/jxl_node_enc.js
generated
File diff suppressed because one or more lines are too long
Binary file not shown.
@ -77,7 +77,9 @@ export default function entryDataPlugin() {
|
||||
}
|
||||
|
||||
return JSON.stringify(
|
||||
getDependencies(chunks, chunk).map((filename) => fileNameToURL(filename)),
|
||||
getDependencies(chunks, chunk).map((filename) =>
|
||||
fileNameToURL(filename),
|
||||
),
|
||||
);
|
||||
},
|
||||
);
|
||||
|
@ -1,3 +1,7 @@
|
||||
# Project no longer maintained
|
||||
|
||||
Unfortunately, due to a few people leaving the team, and staffing issues resulting from the current economic climate (ugh), this package is no longer actively maintained. I know that sucks, but there simply isn't the time & people to work on this. If anyone from the community wants to fork it, you have my blessing. The [squoosh.app](https://squoosh.app) will continue to be supported and improved.
|
||||
|
||||
# libSquoosh
|
||||
|
||||
libSquoosh is an _experimental_ way to run all the codecs you know from the [Squoosh] web app directly inside your own JavaScript program. libSquoosh uses a worker pool to parallelize processing images. This way you can apply the same codec to many images at once.
|
||||
@ -22,6 +26,8 @@ const imagePool = new ImagePool(cpus().length);
|
||||
|
||||
This will create an image pool with an underlying processing pipeline that you can use to ingest and encode images. The ImagePool constructor takes one argument that defines how many parallel operations it is allowed to run at any given time.
|
||||
|
||||
:warning: Important! Make sure to only create 1 `ImagePool` when performing parallel image processing. If you create multiple pools, the `ImagePool` can run out of memory and crash. By reusing a single `ImagePool`, you can ensure that the backing worker queue and processing pipeline releases memory prior to processing the next image.
|
||||
|
||||
## Ingesting images
|
||||
|
||||
You can ingest a new image like so:
|
||||
@ -41,19 +47,15 @@ The returned `image` object is a representation of the original image, that you
|
||||
When an image has been ingested, you can start preprocessing it and encoding it to other formats. This example will resize the image and then encode it to a `.jpg` and `.jxl` image:
|
||||
|
||||
```js
|
||||
await image.decoded; //Wait until the image is decoded before running preprocessors.
|
||||
|
||||
const preprocessOptions = {
|
||||
//When both width and height are specified, the image resized to specified size.
|
||||
resize: {
|
||||
enabled: true,
|
||||
width: 100,
|
||||
height: 50,
|
||||
},
|
||||
/*
|
||||
//When either width or height is specified, the image resized to specified size keeping aspect ratio.
|
||||
resize: {
|
||||
enabled: true,
|
||||
width: 100,
|
||||
}
|
||||
*/
|
||||
@ -66,7 +68,7 @@ const encodeOptions = {
|
||||
quality: 90,
|
||||
},
|
||||
};
|
||||
await image.encode(encodeOptions);
|
||||
const result = await image.encode(encodeOptions);
|
||||
```
|
||||
|
||||
The default values for each option can be found in the [`codecs.ts`][codecs.ts] file under `defaultEncoderOptions`. Every unspecified value will use the default value specified there. _Better documentation is needed here._
|
||||
@ -90,7 +92,7 @@ When you have encoded an image, you normally want to write it to a file.
|
||||
This example takes an image that has been encoded as a `jpg` and writes it to a file:
|
||||
|
||||
```js
|
||||
const rawEncodedImage = (await image.encodedWith.mozjpeg).binary;
|
||||
const rawEncodedImage = image.encodedWith.mozjpeg.binary;
|
||||
|
||||
fs.writeFile('/path/to/new/image.jpg', rawEncodedImage);
|
||||
```
|
||||
@ -101,10 +103,7 @@ This example iterates through all encoded versions of the image and writes them
|
||||
const newImagePath = '/path/to/image.'; //extension is added automatically
|
||||
|
||||
for (const encodedImage of Object.values(image.encodedWith)) {
|
||||
fs.writeFile(
|
||||
newImagePath + (await encodedImage).extension,
|
||||
(await encodedImage).binary,
|
||||
);
|
||||
fs.writeFile(newImagePath + encodedImage.extension, encodedImage.binary);
|
||||
}
|
||||
```
|
||||
|
||||
@ -133,7 +132,7 @@ console.log(await image.decoded);
|
||||
Information about an encoded image can be found at `Image.encodedWith[encoderName]`. It looks something like this:
|
||||
|
||||
```js
|
||||
console.log(await image.encodedWith.jxl);
|
||||
console.log(image.encodedWith.jxl);
|
||||
// Returns:
|
||||
{
|
||||
optionsUsed: {
|
||||
|
26
libsquoosh/lib/move-d-ts.js
Normal file
26
libsquoosh/lib/move-d-ts.js
Normal file
@ -0,0 +1,26 @@
|
||||
const fs = require('fs');
|
||||
const del = require('del');
|
||||
const path = require('path');
|
||||
|
||||
const tsOutputDir = path.resolve('..', '.tmp', 'ts', 'libsquoosh');
|
||||
const tsOutputSourceDir = path.join(tsOutputDir, 'src');
|
||||
const buildDir = path.resolve('build');
|
||||
|
||||
(async () => {
|
||||
await del(path.join(buildDir, '*.d.ts'));
|
||||
const files = await fs.promises.readdir(tsOutputSourceDir);
|
||||
|
||||
const movePromises = [];
|
||||
for (const file of files) {
|
||||
if (file.endsWith('d.ts') || file.endsWith('d.ts.map')) {
|
||||
movePromises.push(
|
||||
fs.promises.rename(
|
||||
path.join(tsOutputSourceDir, file),
|
||||
path.join(buildDir, file),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
// We need to remove `tsconfig.tsbuildinfo` otherwise TS does not emit unchanged `.d.ts` files
|
||||
await del([path.join(tsOutputDir, 'tsconfig.tsbuildinfo')], { force: true });
|
||||
})();
|
4
libsquoosh/package-lock.json
generated
4
libsquoosh/package-lock.json
generated
@ -1,12 +1,12 @@
|
||||
{
|
||||
"name": "@squoosh/lib",
|
||||
"version": "0.4.0",
|
||||
"version": "0.5.2",
|
||||
"lockfileVersion": 2,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "@squoosh/lib",
|
||||
"version": "0.4.0",
|
||||
"version": "0.5.2",
|
||||
"license": "Apache-2.0",
|
||||
"dependencies": {
|
||||
"wasm-feature-detect": "^1.2.11",
|
||||
|
@ -1,14 +1,15 @@
|
||||
{
|
||||
"name": "@squoosh/lib",
|
||||
"version": "0.4.0",
|
||||
"version": "0.5.2",
|
||||
"description": "A Node library for Squoosh",
|
||||
"public": true,
|
||||
"main": "./build/index.js",
|
||||
"types": "./build/index.d.ts",
|
||||
"files": [
|
||||
"/build/*"
|
||||
],
|
||||
"scripts": {
|
||||
"build": "rollup -c"
|
||||
"build": "rollup -c && node lib/move-d-ts.js"
|
||||
},
|
||||
"keywords": [],
|
||||
"author": "Google Chrome Developers <chromium-dev@google.com>",
|
||||
|
@ -419,6 +419,7 @@ export const codecs = {
|
||||
lossyPalette: false,
|
||||
decodingSpeedTier: 0,
|
||||
photonNoiseIso: 0,
|
||||
lossyModular: false,
|
||||
},
|
||||
autoOptimize: {
|
||||
option: 'quality',
|
||||
|
@ -22,9 +22,10 @@ type EncoderKey = keyof typeof encoders;
|
||||
type PreprocessorKey = keyof typeof preprocessors;
|
||||
|
||||
type PreprocessOptions = {
|
||||
resize?: ResizeOptions;
|
||||
quant?: QuantOptions;
|
||||
rotate?: RotateOptions;
|
||||
resize?: Partial<Omit<ResizeOptions, 'width' | 'height'>> &
|
||||
(Pick<ResizeOptions, 'width'> | Pick<ResizeOptions, 'height'>);
|
||||
quant?: Partial<QuantOptions>;
|
||||
rotate?: Partial<RotateOptions>;
|
||||
};
|
||||
type EncodeResult = {
|
||||
optionsUsed: object;
|
||||
|
@ -3,7 +3,8 @@
|
||||
"compilerOptions": {
|
||||
"lib": ["esnext"],
|
||||
"types": ["node"],
|
||||
"allowJs": true
|
||||
"allowJs": true,
|
||||
"declaration": true
|
||||
},
|
||||
"include": ["src/**/*", "../codecs/**/*"]
|
||||
}
|
||||
|
328
package-lock.json
generated
328
package-lock.json
generated
@ -16,15 +16,15 @@
|
||||
"@rollup/plugin-replace": "^2.3.4",
|
||||
"@surma/rollup-plugin-off-main-thread": "^2.2.2",
|
||||
"@types/dedent": "^0.7.0",
|
||||
"@types/mime-types": "^2.1.0",
|
||||
"@types/node": "^14.14.7",
|
||||
"@types/mime-types": "^2.1.1",
|
||||
"@types/node": "^16.11.1",
|
||||
"@web/rollup-plugin-import-meta-assets": "^1.0.6",
|
||||
"comlink": "^4.3.0",
|
||||
"cssnano": "^4.1.10",
|
||||
"dedent": "^0.7.0",
|
||||
"del": "^5.1.0",
|
||||
"file-drop-element": "^1.0.1",
|
||||
"husky": "^4.3.0",
|
||||
"husky": "^7.0.2",
|
||||
"idb-keyval": "^3.2.0",
|
||||
"image-size": "^0.9.3",
|
||||
"linkstate": "^2.0.0",
|
||||
@ -40,11 +40,11 @@
|
||||
"postcss-url": "^8.0.0",
|
||||
"preact": "^10.5.5",
|
||||
"preact-render-to-string": "^5.1.11",
|
||||
"prettier": "^2.1.2",
|
||||
"prettier": "^2.4.1",
|
||||
"rollup": "^2.38.0",
|
||||
"rollup-plugin-terser": "^7.0.2",
|
||||
"serve": "^11.3.2",
|
||||
"typescript": "^4.1.3",
|
||||
"typescript": "^4.4.4",
|
||||
"which": "^2.0.2"
|
||||
}
|
||||
},
|
||||
@ -315,9 +315,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@types/mime-types": {
|
||||
"version": "2.1.0",
|
||||
"resolved": "https://registry.npmjs.org/@types/mime-types/-/mime-types-2.1.0.tgz",
|
||||
"integrity": "sha1-nKUs2jY/aZxpRmwqbM2q2RPqenM=",
|
||||
"version": "2.1.1",
|
||||
"resolved": "https://registry.npmjs.org/@types/mime-types/-/mime-types-2.1.1.tgz",
|
||||
"integrity": "sha512-vXOTGVSLR2jMw440moWTC7H19iUyLtP3Z1YTj7cSsubOICinjMxFeb/V57v9QdyyPGbbWolUFSSmSiRSn94tFw==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/@types/minimatch": {
|
||||
@ -327,9 +327,9 @@
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/@types/node": {
|
||||
"version": "14.14.7",
|
||||
"resolved": "https://registry.npmjs.org/@types/node/-/node-14.14.7.tgz",
|
||||
"integrity": "sha512-Zw1vhUSQZYw+7u5dAwNbIA9TuTotpzY/OF7sJM9FqPOF3SPjKnxrjoTktXDZgUjybf4cWVBP7O8wvKdSaGHweg==",
|
||||
"version": "16.11.1",
|
||||
"resolved": "https://registry.npmjs.org/@types/node/-/node-16.11.1.tgz",
|
||||
"integrity": "sha512-PYGcJHL9mwl1Ek3PLiYgyEKtwTMmkMw4vbiyz/ps3pfdRYLVv+SN7qHVAImrjdAXxgluDEw6Ph4lyv+m9UpRmA==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/@types/parse-json": {
|
||||
@ -866,12 +866,6 @@
|
||||
"node": ">=4"
|
||||
}
|
||||
},
|
||||
"node_modules/ci-info": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/ci-info/-/ci-info-2.0.0.tgz",
|
||||
"integrity": "sha512-5tK7EtrZ0N+OLFMthtqOj4fI2Jeb88C4CAZPu25LDVUgXJ0A3Js4PMGqrn0JU1W0Mh1/Z8wZzYPxqUrXeBboCQ==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/clean-stack": {
|
||||
"version": "2.2.0",
|
||||
"resolved": "https://registry.npmjs.org/clean-stack/-/clean-stack-2.2.0.tgz",
|
||||
@ -1176,12 +1170,6 @@
|
||||
"integrity": "sha1-3dgA2gxmEnOTzKWVDqloo6rxJTs=",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/compare-versions": {
|
||||
"version": "3.6.0",
|
||||
"resolved": "https://registry.npmjs.org/compare-versions/-/compare-versions-3.6.0.tgz",
|
||||
"integrity": "sha512-W6Af2Iw1z4CB7q4uU4hv646dW9GQuBM+YpC0UvUCWSD8w90SJjp+ujJuXaEMtAXBtSqGfMPuFOVn4/+FlaqfBA==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/compressible": {
|
||||
"version": "2.0.18",
|
||||
"resolved": "https://registry.npmjs.org/compressible/-/compressible-2.0.18.tgz",
|
||||
@ -2284,31 +2272,6 @@
|
||||
"node": ">=8"
|
||||
}
|
||||
},
|
||||
"node_modules/find-up": {
|
||||
"version": "4.1.0",
|
||||
"resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz",
|
||||
"integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"locate-path": "^5.0.0",
|
||||
"path-exists": "^4.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=10"
|
||||
}
|
||||
},
|
||||
"node_modules/find-versions": {
|
||||
"version": "3.2.0",
|
||||
"resolved": "https://registry.npmjs.org/find-versions/-/find-versions-3.2.0.tgz",
|
||||
"integrity": "sha512-P8WRou2S+oe222TOCHitLy8zj+SIsVJh52VP4lvXkaFVnOFFdoWv1H1Jjvel1aI6NCFOAaeAVm8qrI0odiLcww==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"semver-regex": "^2.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=10"
|
||||
}
|
||||
},
|
||||
"node_modules/fs.realpath": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz",
|
||||
@ -2485,28 +2448,18 @@
|
||||
}
|
||||
},
|
||||
"node_modules/husky": {
|
||||
"version": "4.3.0",
|
||||
"resolved": "https://registry.npmjs.org/husky/-/husky-4.3.0.tgz",
|
||||
"integrity": "sha512-tTMeLCLqSBqnflBZnlVDhpaIMucSGaYyX6855jM4AguGeWCeSzNdb1mfyWduTZ3pe3SJVvVWGL0jO1iKZVPfTA==",
|
||||
"version": "7.0.2",
|
||||
"resolved": "https://registry.npmjs.org/husky/-/husky-7.0.2.tgz",
|
||||
"integrity": "sha512-8yKEWNX4z2YsofXAMT7KvA1g8p+GxtB1ffV8XtpAEGuXNAbCV5wdNKH+qTpw8SM9fh4aMPDR+yQuKfgnreyZlg==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"chalk": "^4.0.0",
|
||||
"ci-info": "^2.0.0",
|
||||
"compare-versions": "^3.6.0",
|
||||
"cosmiconfig": "^7.0.0",
|
||||
"find-versions": "^3.2.0",
|
||||
"opencollective-postinstall": "^2.0.2",
|
||||
"pkg-dir": "^4.2.0",
|
||||
"please-upgrade-node": "^3.2.0",
|
||||
"slash": "^3.0.0",
|
||||
"which-pm-runs": "^1.0.0"
|
||||
},
|
||||
"bin": {
|
||||
"husky-run": "bin/run.js",
|
||||
"husky-upgrade": "lib/upgrader/bin.js"
|
||||
"husky": "lib/bin.js"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=10"
|
||||
"node": ">=12"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/typicode"
|
||||
}
|
||||
},
|
||||
"node_modules/icss-replace-symbols": {
|
||||
@ -3164,18 +3117,6 @@
|
||||
"node": ">=4.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/locate-path": {
|
||||
"version": "5.0.0",
|
||||
"resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz",
|
||||
"integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"p-locate": "^4.1.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=10"
|
||||
}
|
||||
},
|
||||
"node_modules/lodash.camelcase": {
|
||||
"version": "4.3.0",
|
||||
"resolved": "https://registry.npmjs.org/lodash.camelcase/-/lodash.camelcase-4.3.0.tgz",
|
||||
@ -3689,15 +3630,6 @@
|
||||
"node": ">=6"
|
||||
}
|
||||
},
|
||||
"node_modules/opencollective-postinstall": {
|
||||
"version": "2.0.3",
|
||||
"resolved": "https://registry.npmjs.org/opencollective-postinstall/-/opencollective-postinstall-2.0.3.tgz",
|
||||
"integrity": "sha512-8AV/sCtuzUeTo8gQK5qDZzARrulB3egtLzFgteqB2tcT4Mw7B8Kt7JcDHmltjz6FOAHsvTevk70gZEbhM4ZS9Q==",
|
||||
"dev": true,
|
||||
"bin": {
|
||||
"opencollective-postinstall": "index.js"
|
||||
}
|
||||
},
|
||||
"node_modules/p-finally": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/p-finally/-/p-finally-1.0.0.tgz",
|
||||
@ -3707,30 +3639,6 @@
|
||||
"node": ">=4"
|
||||
}
|
||||
},
|
||||
"node_modules/p-limit": {
|
||||
"version": "2.3.0",
|
||||
"resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz",
|
||||
"integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"p-try": "^2.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=10"
|
||||
}
|
||||
},
|
||||
"node_modules/p-locate": {
|
||||
"version": "4.1.0",
|
||||
"resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz",
|
||||
"integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"p-limit": "^2.2.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=10"
|
||||
}
|
||||
},
|
||||
"node_modules/p-map": {
|
||||
"version": "3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/p-map/-/p-map-3.0.0.tgz",
|
||||
@ -3743,15 +3651,6 @@
|
||||
"node": ">=8"
|
||||
}
|
||||
},
|
||||
"node_modules/p-try": {
|
||||
"version": "2.2.0",
|
||||
"resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz",
|
||||
"integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==",
|
||||
"dev": true,
|
||||
"engines": {
|
||||
"node": ">=6"
|
||||
}
|
||||
},
|
||||
"node_modules/parent-module": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz",
|
||||
@ -3779,15 +3678,6 @@
|
||||
"node": ">=4"
|
||||
}
|
||||
},
|
||||
"node_modules/path-exists": {
|
||||
"version": "4.0.0",
|
||||
"resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz",
|
||||
"integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==",
|
||||
"dev": true,
|
||||
"engines": {
|
||||
"node": ">=8"
|
||||
}
|
||||
},
|
||||
"node_modules/path-is-absolute": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz",
|
||||
@ -3863,18 +3753,6 @@
|
||||
"node": ">=4"
|
||||
}
|
||||
},
|
||||
"node_modules/pkg-dir": {
|
||||
"version": "4.2.0",
|
||||
"resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-4.2.0.tgz",
|
||||
"integrity": "sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"find-up": "^4.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=10"
|
||||
}
|
||||
},
|
||||
"node_modules/please-upgrade-node": {
|
||||
"version": "3.2.0",
|
||||
"resolved": "https://registry.npmjs.org/please-upgrade-node/-/please-upgrade-node-3.2.0.tgz",
|
||||
@ -7529,9 +7407,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/prettier": {
|
||||
"version": "2.1.2",
|
||||
"resolved": "https://registry.npmjs.org/prettier/-/prettier-2.1.2.tgz",
|
||||
"integrity": "sha512-16c7K+x4qVlJg9rEbXl7HEGmQyZlG4R9AgP+oHKRMsMsuk8s+ATStlf1NpDqyBI1HpVyfjLOeMhH2LvuNvV5Vg==",
|
||||
"version": "2.4.1",
|
||||
"resolved": "https://registry.npmjs.org/prettier/-/prettier-2.4.1.tgz",
|
||||
"integrity": "sha512-9fbDAXSBcc6Bs1mZrDYb3XKzDLm4EXXL9sC1LqKP5rZkT6KRr/rf9amVUcODVXgguK/isJz0d0hP72WeaKWsvA==",
|
||||
"dev": true,
|
||||
"bin": {
|
||||
"prettier": "bin-prettier.js"
|
||||
@ -7808,15 +7686,6 @@
|
||||
"integrity": "sha1-De4hahyUGrN+nvsXiPavxf9VN/w=",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/semver-regex": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/semver-regex/-/semver-regex-2.0.0.tgz",
|
||||
"integrity": "sha512-mUdIBBvdn0PLOeP3TEkMH7HHeUP3GjsXCwKarjv/kGmUFOYg1VqEemKhoQpWMu6X2I8kHeuVdGibLGkVK+/5Qw==",
|
||||
"dev": true,
|
||||
"engines": {
|
||||
"node": ">=8"
|
||||
}
|
||||
},
|
||||
"node_modules/serialize-javascript": {
|
||||
"version": "4.0.0",
|
||||
"resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-4.0.0.tgz",
|
||||
@ -8602,9 +8471,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/typescript": {
|
||||
"version": "4.1.3",
|
||||
"resolved": "https://registry.npmjs.org/typescript/-/typescript-4.1.3.tgz",
|
||||
"integrity": "sha512-B3ZIOf1IKeH2ixgHhj6la6xdwR9QrLC5d1VKeCSY4tvkqhF2eqd9O7txNlS0PO3GrBAFIdr3L1ndNwteUbZLYg==",
|
||||
"version": "4.4.4",
|
||||
"resolved": "https://registry.npmjs.org/typescript/-/typescript-4.4.4.tgz",
|
||||
"integrity": "sha512-DqGhF5IKoBl8WNf8C1gu8q0xZSInh9j1kJJMqT3a94w1JzVaBU4EXOSMrz9yDqMT0xt3selp83fuFMQ0uzv6qA==",
|
||||
"dev": true,
|
||||
"bin": {
|
||||
"tsc": "bin/tsc",
|
||||
@ -8708,12 +8577,6 @@
|
||||
"node": ">= 8"
|
||||
}
|
||||
},
|
||||
"node_modules/which-pm-runs": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/which-pm-runs/-/which-pm-runs-1.0.0.tgz",
|
||||
"integrity": "sha1-Zws6+8VS4LVd9rd4DKdGFfI60cs=",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/widest-line": {
|
||||
"version": "2.0.1",
|
||||
"resolved": "https://registry.npmjs.org/widest-line/-/widest-line-2.0.1.tgz",
|
||||
@ -9040,9 +8903,9 @@
|
||||
}
|
||||
},
|
||||
"@types/mime-types": {
|
||||
"version": "2.1.0",
|
||||
"resolved": "https://registry.npmjs.org/@types/mime-types/-/mime-types-2.1.0.tgz",
|
||||
"integrity": "sha1-nKUs2jY/aZxpRmwqbM2q2RPqenM=",
|
||||
"version": "2.1.1",
|
||||
"resolved": "https://registry.npmjs.org/@types/mime-types/-/mime-types-2.1.1.tgz",
|
||||
"integrity": "sha512-vXOTGVSLR2jMw440moWTC7H19iUyLtP3Z1YTj7cSsubOICinjMxFeb/V57v9QdyyPGbbWolUFSSmSiRSn94tFw==",
|
||||
"dev": true
|
||||
},
|
||||
"@types/minimatch": {
|
||||
@ -9052,9 +8915,9 @@
|
||||
"dev": true
|
||||
},
|
||||
"@types/node": {
|
||||
"version": "14.14.7",
|
||||
"resolved": "https://registry.npmjs.org/@types/node/-/node-14.14.7.tgz",
|
||||
"integrity": "sha512-Zw1vhUSQZYw+7u5dAwNbIA9TuTotpzY/OF7sJM9FqPOF3SPjKnxrjoTktXDZgUjybf4cWVBP7O8wvKdSaGHweg==",
|
||||
"version": "16.11.1",
|
||||
"resolved": "https://registry.npmjs.org/@types/node/-/node-16.11.1.tgz",
|
||||
"integrity": "sha512-PYGcJHL9mwl1Ek3PLiYgyEKtwTMmkMw4vbiyz/ps3pfdRYLVv+SN7qHVAImrjdAXxgluDEw6Ph4lyv+m9UpRmA==",
|
||||
"dev": true
|
||||
},
|
||||
"@types/parse-json": {
|
||||
@ -9494,12 +9357,6 @@
|
||||
"supports-color": "^7.1.0"
|
||||
}
|
||||
},
|
||||
"ci-info": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/ci-info/-/ci-info-2.0.0.tgz",
|
||||
"integrity": "sha512-5tK7EtrZ0N+OLFMthtqOj4fI2Jeb88C4CAZPu25LDVUgXJ0A3Js4PMGqrn0JU1W0Mh1/Z8wZzYPxqUrXeBboCQ==",
|
||||
"dev": true
|
||||
},
|
||||
"clean-stack": {
|
||||
"version": "2.2.0",
|
||||
"resolved": "https://registry.npmjs.org/clean-stack/-/clean-stack-2.2.0.tgz",
|
||||
@ -9753,12 +9610,6 @@
|
||||
"integrity": "sha1-3dgA2gxmEnOTzKWVDqloo6rxJTs=",
|
||||
"dev": true
|
||||
},
|
||||
"compare-versions": {
|
||||
"version": "3.6.0",
|
||||
"resolved": "https://registry.npmjs.org/compare-versions/-/compare-versions-3.6.0.tgz",
|
||||
"integrity": "sha512-W6Af2Iw1z4CB7q4uU4hv646dW9GQuBM+YpC0UvUCWSD8w90SJjp+ujJuXaEMtAXBtSqGfMPuFOVn4/+FlaqfBA==",
|
||||
"dev": true
|
||||
},
|
||||
"compressible": {
|
||||
"version": "2.0.18",
|
||||
"resolved": "https://registry.npmjs.org/compressible/-/compressible-2.0.18.tgz",
|
||||
@ -10676,25 +10527,6 @@
|
||||
"to-regex-range": "^5.0.1"
|
||||
}
|
||||
},
|
||||
"find-up": {
|
||||
"version": "4.1.0",
|
||||
"resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz",
|
||||
"integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"locate-path": "^5.0.0",
|
||||
"path-exists": "^4.0.0"
|
||||
}
|
||||
},
|
||||
"find-versions": {
|
||||
"version": "3.2.0",
|
||||
"resolved": "https://registry.npmjs.org/find-versions/-/find-versions-3.2.0.tgz",
|
||||
"integrity": "sha512-P8WRou2S+oe222TOCHitLy8zj+SIsVJh52VP4lvXkaFVnOFFdoWv1H1Jjvel1aI6NCFOAaeAVm8qrI0odiLcww==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"semver-regex": "^2.0.0"
|
||||
}
|
||||
},
|
||||
"fs.realpath": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz",
|
||||
@ -10841,22 +10673,10 @@
|
||||
"dev": true
|
||||
},
|
||||
"husky": {
|
||||
"version": "4.3.0",
|
||||
"resolved": "https://registry.npmjs.org/husky/-/husky-4.3.0.tgz",
|
||||
"integrity": "sha512-tTMeLCLqSBqnflBZnlVDhpaIMucSGaYyX6855jM4AguGeWCeSzNdb1mfyWduTZ3pe3SJVvVWGL0jO1iKZVPfTA==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"chalk": "^4.0.0",
|
||||
"ci-info": "^2.0.0",
|
||||
"compare-versions": "^3.6.0",
|
||||
"cosmiconfig": "^7.0.0",
|
||||
"find-versions": "^3.2.0",
|
||||
"opencollective-postinstall": "^2.0.2",
|
||||
"pkg-dir": "^4.2.0",
|
||||
"please-upgrade-node": "^3.2.0",
|
||||
"slash": "^3.0.0",
|
||||
"which-pm-runs": "^1.0.0"
|
||||
}
|
||||
"version": "7.0.2",
|
||||
"resolved": "https://registry.npmjs.org/husky/-/husky-7.0.2.tgz",
|
||||
"integrity": "sha512-8yKEWNX4z2YsofXAMT7KvA1g8p+GxtB1ffV8XtpAEGuXNAbCV5wdNKH+qTpw8SM9fh4aMPDR+yQuKfgnreyZlg==",
|
||||
"dev": true
|
||||
},
|
||||
"icss-replace-symbols": {
|
||||
"version": "1.1.0",
|
||||
@ -11394,15 +11214,6 @@
|
||||
"json5": "^1.0.1"
|
||||
}
|
||||
},
|
||||
"locate-path": {
|
||||
"version": "5.0.0",
|
||||
"resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz",
|
||||
"integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"p-locate": "^4.1.0"
|
||||
}
|
||||
},
|
||||
"lodash.camelcase": {
|
||||
"version": "4.3.0",
|
||||
"resolved": "https://registry.npmjs.org/lodash.camelcase/-/lodash.camelcase-4.3.0.tgz",
|
||||
@ -11815,36 +11626,12 @@
|
||||
"mimic-fn": "^2.1.0"
|
||||
}
|
||||
},
|
||||
"opencollective-postinstall": {
|
||||
"version": "2.0.3",
|
||||
"resolved": "https://registry.npmjs.org/opencollective-postinstall/-/opencollective-postinstall-2.0.3.tgz",
|
||||
"integrity": "sha512-8AV/sCtuzUeTo8gQK5qDZzARrulB3egtLzFgteqB2tcT4Mw7B8Kt7JcDHmltjz6FOAHsvTevk70gZEbhM4ZS9Q==",
|
||||
"dev": true
|
||||
},
|
||||
"p-finally": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/p-finally/-/p-finally-1.0.0.tgz",
|
||||
"integrity": "sha1-P7z7FbiZpEEjs0ttzBi3JDNqLK4=",
|
||||
"dev": true
|
||||
},
|
||||
"p-limit": {
|
||||
"version": "2.3.0",
|
||||
"resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz",
|
||||
"integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"p-try": "^2.0.0"
|
||||
}
|
||||
},
|
||||
"p-locate": {
|
||||
"version": "4.1.0",
|
||||
"resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz",
|
||||
"integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"p-limit": "^2.2.0"
|
||||
}
|
||||
},
|
||||
"p-map": {
|
||||
"version": "3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/p-map/-/p-map-3.0.0.tgz",
|
||||
@ -11854,12 +11641,6 @@
|
||||
"aggregate-error": "^3.0.0"
|
||||
}
|
||||
},
|
||||
"p-try": {
|
||||
"version": "2.2.0",
|
||||
"resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz",
|
||||
"integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==",
|
||||
"dev": true
|
||||
},
|
||||
"parent-module": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz",
|
||||
@ -11881,12 +11662,6 @@
|
||||
"lines-and-columns": "^1.1.6"
|
||||
}
|
||||
},
|
||||
"path-exists": {
|
||||
"version": "4.0.0",
|
||||
"resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz",
|
||||
"integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==",
|
||||
"dev": true
|
||||
},
|
||||
"path-is-absolute": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz",
|
||||
@ -11941,15 +11716,6 @@
|
||||
"integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=",
|
||||
"dev": true
|
||||
},
|
||||
"pkg-dir": {
|
||||
"version": "4.2.0",
|
||||
"resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-4.2.0.tgz",
|
||||
"integrity": "sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"find-up": "^4.0.0"
|
||||
}
|
||||
},
|
||||
"please-upgrade-node": {
|
||||
"version": "3.2.0",
|
||||
"resolved": "https://registry.npmjs.org/please-upgrade-node/-/please-upgrade-node-3.2.0.tgz",
|
||||
@ -15029,9 +14795,9 @@
|
||||
}
|
||||
},
|
||||
"prettier": {
|
||||
"version": "2.1.2",
|
||||
"resolved": "https://registry.npmjs.org/prettier/-/prettier-2.1.2.tgz",
|
||||
"integrity": "sha512-16c7K+x4qVlJg9rEbXl7HEGmQyZlG4R9AgP+oHKRMsMsuk8s+ATStlf1NpDqyBI1HpVyfjLOeMhH2LvuNvV5Vg==",
|
||||
"version": "2.4.1",
|
||||
"resolved": "https://registry.npmjs.org/prettier/-/prettier-2.4.1.tgz",
|
||||
"integrity": "sha512-9fbDAXSBcc6Bs1mZrDYb3XKzDLm4EXXL9sC1LqKP5rZkT6KRr/rf9amVUcODVXgguK/isJz0d0hP72WeaKWsvA==",
|
||||
"dev": true
|
||||
},
|
||||
"pretty-format": {
|
||||
@ -15257,12 +15023,6 @@
|
||||
"integrity": "sha1-De4hahyUGrN+nvsXiPavxf9VN/w=",
|
||||
"dev": true
|
||||
},
|
||||
"semver-regex": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/semver-regex/-/semver-regex-2.0.0.tgz",
|
||||
"integrity": "sha512-mUdIBBvdn0PLOeP3TEkMH7HHeUP3GjsXCwKarjv/kGmUFOYg1VqEemKhoQpWMu6X2I8kHeuVdGibLGkVK+/5Qw==",
|
||||
"dev": true
|
||||
},
|
||||
"serialize-javascript": {
|
||||
"version": "4.0.0",
|
||||
"resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-4.0.0.tgz",
|
||||
@ -15917,9 +15677,9 @@
|
||||
"dev": true
|
||||
},
|
||||
"typescript": {
|
||||
"version": "4.1.3",
|
||||
"resolved": "https://registry.npmjs.org/typescript/-/typescript-4.1.3.tgz",
|
||||
"integrity": "sha512-B3ZIOf1IKeH2ixgHhj6la6xdwR9QrLC5d1VKeCSY4tvkqhF2eqd9O7txNlS0PO3GrBAFIdr3L1ndNwteUbZLYg==",
|
||||
"version": "4.4.4",
|
||||
"resolved": "https://registry.npmjs.org/typescript/-/typescript-4.4.4.tgz",
|
||||
"integrity": "sha512-DqGhF5IKoBl8WNf8C1gu8q0xZSInh9j1kJJMqT3a94w1JzVaBU4EXOSMrz9yDqMT0xt3selp83fuFMQ0uzv6qA==",
|
||||
"dev": true
|
||||
},
|
||||
"uniq": {
|
||||
@ -16007,12 +15767,6 @@
|
||||
"isexe": "^2.0.0"
|
||||
}
|
||||
},
|
||||
"which-pm-runs": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/which-pm-runs/-/which-pm-runs-1.0.0.tgz",
|
||||
"integrity": "sha1-Zws6+8VS4LVd9rd4DKdGFfI60cs=",
|
||||
"dev": true
|
||||
},
|
||||
"widest-line": {
|
||||
"version": "2.0.1",
|
||||
"resolved": "https://registry.npmjs.org/widest-line/-/widest-line-2.0.1.tgz",
|
||||
|
18
package.json
18
package.json
@ -8,7 +8,8 @@
|
||||
"debug": "node --inspect-brk node_modules/.bin/rollup -c",
|
||||
"dev": "DEV_PORT=\"${DEV_PORT:=5000}\" run-p watch serve",
|
||||
"watch": "rollup -cw",
|
||||
"serve": "serve --listen=$DEV_PORT --config ../../../serve.json .tmp/build/static"
|
||||
"serve": "serve --listen=$DEV_PORT --config ../../../serve.json .tmp/build/static",
|
||||
"prepare": "husky install"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@rollup/plugin-commonjs": "^17.0.0",
|
||||
@ -16,15 +17,15 @@
|
||||
"@rollup/plugin-replace": "^2.3.4",
|
||||
"@surma/rollup-plugin-off-main-thread": "^2.2.2",
|
||||
"@types/dedent": "^0.7.0",
|
||||
"@types/mime-types": "^2.1.0",
|
||||
"@types/node": "^14.14.7",
|
||||
"@types/mime-types": "^2.1.1",
|
||||
"@types/node": "^16.11.1",
|
||||
"@web/rollup-plugin-import-meta-assets": "^1.0.6",
|
||||
"comlink": "^4.3.0",
|
||||
"cssnano": "^4.1.10",
|
||||
"dedent": "^0.7.0",
|
||||
"del": "^5.1.0",
|
||||
"file-drop-element": "^1.0.1",
|
||||
"husky": "^4.3.0",
|
||||
"husky": "^7.0.2",
|
||||
"idb-keyval": "^3.2.0",
|
||||
"image-size": "^0.9.3",
|
||||
"linkstate": "^2.0.0",
|
||||
@ -40,18 +41,13 @@
|
||||
"postcss-url": "^8.0.0",
|
||||
"preact": "^10.5.5",
|
||||
"preact-render-to-string": "^5.1.11",
|
||||
"prettier": "^2.1.2",
|
||||
"prettier": "^2.4.1",
|
||||
"rollup": "^2.38.0",
|
||||
"rollup-plugin-terser": "^7.0.2",
|
||||
"serve": "^11.3.2",
|
||||
"typescript": "^4.1.3",
|
||||
"typescript": "^4.4.4",
|
||||
"which": "^2.0.2"
|
||||
},
|
||||
"husky": {
|
||||
"hooks": {
|
||||
"pre-commit": "lint-staged"
|
||||
}
|
||||
},
|
||||
"lint-staged": {
|
||||
"*.{js,css,json,md,ts,tsx}": "prettier --write",
|
||||
"*.{c,h,cpp,hpp}": "clang-format -i",
|
||||
|
@ -11,7 +11,11 @@ export default class Checkbox extends Component<Props, State> {
|
||||
return (
|
||||
<div class={style.checkbox}>
|
||||
{props.checked ? (
|
||||
<CheckedIcon class={`${style.icon} ${style.checked}`} />
|
||||
props.disabled ? (
|
||||
<CheckedIcon class={`${style.icon} ${style.disabled}`} />
|
||||
) : (
|
||||
<CheckedIcon class={`${style.icon} ${style.checked}`} />
|
||||
)
|
||||
) : (
|
||||
<UncheckedIcon class={style.icon} />
|
||||
)}
|
||||
|
@ -20,3 +20,7 @@
|
||||
.checked {
|
||||
fill: var(--main-theme-color);
|
||||
}
|
||||
|
||||
.disabled {
|
||||
fill: var(--dark-gray);
|
||||
}
|
||||
|
@ -40,24 +40,23 @@ type PartialButNotUndefined<T> = {
|
||||
[P in keyof T]: T[P];
|
||||
};
|
||||
|
||||
const supportedEncoderMapP: Promise<PartialButNotUndefined<
|
||||
typeof encoderMap
|
||||
>> = (async () => {
|
||||
const supportedEncoderMap: PartialButNotUndefined<typeof encoderMap> = {
|
||||
...encoderMap,
|
||||
};
|
||||
const supportedEncoderMapP: Promise<PartialButNotUndefined<typeof encoderMap>> =
|
||||
(async () => {
|
||||
const supportedEncoderMap: PartialButNotUndefined<typeof encoderMap> = {
|
||||
...encoderMap,
|
||||
};
|
||||
|
||||
// Filter out entries where the feature test fails
|
||||
await Promise.all(
|
||||
Object.entries(encoderMap).map(async ([encoderName, details]) => {
|
||||
if ('featureTest' in details && !(await details.featureTest())) {
|
||||
delete supportedEncoderMap[encoderName as keyof typeof encoderMap];
|
||||
}
|
||||
}),
|
||||
);
|
||||
// Filter out entries where the feature test fails
|
||||
await Promise.all(
|
||||
Object.entries(encoderMap).map(async ([encoderName, details]) => {
|
||||
if ('featureTest' in details && !(await details.featureTest())) {
|
||||
delete supportedEncoderMap[encoderName as keyof typeof encoderMap];
|
||||
}
|
||||
}),
|
||||
);
|
||||
|
||||
return supportedEncoderMap;
|
||||
})();
|
||||
return supportedEncoderMap;
|
||||
})();
|
||||
|
||||
export default class Options extends Component<Props, State> {
|
||||
state: State = {
|
||||
|
@ -40,7 +40,8 @@ two-up[legacy-clip-compat] > :not(.two-up-handle) {
|
||||
}
|
||||
|
||||
.scrubber {
|
||||
display: flex;
|
||||
display: grid;
|
||||
align-content: center;
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
left: 50%;
|
||||
@ -54,10 +55,6 @@ two-up[legacy-clip-compat] > :not(.two-up-handle) {
|
||||
padding: 0 calc(var(--thumb-size) * 0.24);
|
||||
}
|
||||
|
||||
.scrubber svg {
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.arrow-left {
|
||||
fill: var(--pink);
|
||||
}
|
||||
|
@ -49,6 +49,7 @@
|
||||
align-self: center;
|
||||
padding: 9px 66px;
|
||||
position: relative;
|
||||
gap: 6px;
|
||||
|
||||
/* Allow clicks to fall through to the pinch zoom area */
|
||||
pointer-events: none;
|
||||
@ -68,7 +69,6 @@
|
||||
display: flex;
|
||||
position: relative;
|
||||
z-index: 100;
|
||||
margin: 0 3px;
|
||||
}
|
||||
|
||||
.button,
|
||||
@ -95,6 +95,7 @@
|
||||
|
||||
.button {
|
||||
color: #fff;
|
||||
margin: 0;
|
||||
|
||||
&:hover {
|
||||
background: rgba(50, 50, 50, 0.92);
|
||||
@ -114,7 +115,7 @@
|
||||
.last-button {
|
||||
composes: button;
|
||||
border-radius: 0 6px 6px 0;
|
||||
border-left-width: 1px;
|
||||
border-right-width: 1px;
|
||||
}
|
||||
|
||||
.zoom {
|
||||
|
@ -114,9 +114,9 @@ async function decodeImage(
|
||||
}
|
||||
}
|
||||
// Otherwise fall through and try built-in decoding for a laugh.
|
||||
return await builtinDecode(signal, blob, mimeType);
|
||||
return await builtinDecode(signal, blob);
|
||||
} catch (err) {
|
||||
if (err.name === 'AbortError') throw err;
|
||||
if (err instanceof Error && err.name === 'AbortError') throw err;
|
||||
console.log(err);
|
||||
throw Error("Couldn't decode image");
|
||||
}
|
||||
@ -481,7 +481,7 @@ export default class Compress extends Component<Props, State> {
|
||||
open('https://github.com/GoogleChromeLabs/squoosh/tree/dev/cli');
|
||||
}
|
||||
} catch (e) {
|
||||
this.props.showSnack(e);
|
||||
this.props.showSnack(String(e));
|
||||
}
|
||||
};
|
||||
|
||||
@ -640,7 +640,7 @@ export default class Compress extends Component<Props, State> {
|
||||
return { sides };
|
||||
});
|
||||
} catch (err) {
|
||||
if (err.name === 'AbortError') return;
|
||||
if (err instanceof Error && err.name === 'AbortError') return;
|
||||
this.props.showSnack(`Source decoding error: ${err}`);
|
||||
throw err;
|
||||
}
|
||||
@ -698,7 +698,7 @@ export default class Compress extends Component<Props, State> {
|
||||
return newState;
|
||||
});
|
||||
} catch (err) {
|
||||
if (err.name === 'AbortError') return;
|
||||
if (err instanceof Error && err.name === 'AbortError') return;
|
||||
this.setState({ loading: false });
|
||||
this.props.showSnack(`Preprocessing error: ${err}`);
|
||||
throw err;
|
||||
@ -822,7 +822,7 @@ export default class Compress extends Component<Props, State> {
|
||||
|
||||
this.activeSideJobs[sideIndex] = undefined;
|
||||
} catch (err) {
|
||||
if (err.name === 'AbortError') return;
|
||||
if (err instanceof Error && err.name === 'AbortError') return;
|
||||
this.setState((currentState) => {
|
||||
const sides = cleanMerge(currentState.sides, sideIndex, {
|
||||
loading: false,
|
||||
|
@ -63,35 +63,17 @@ interface DrawableToImageDataOptions {
|
||||
sh?: number;
|
||||
}
|
||||
|
||||
function getWidth(
|
||||
drawable: ImageBitmap | HTMLImageElement | VideoFrame,
|
||||
): number {
|
||||
if ('displayWidth' in drawable) {
|
||||
return drawable.displayWidth;
|
||||
}
|
||||
return drawable.width;
|
||||
}
|
||||
|
||||
function getHeight(
|
||||
drawable: ImageBitmap | HTMLImageElement | VideoFrame,
|
||||
): number {
|
||||
if ('displayHeight' in drawable) {
|
||||
return drawable.displayHeight;
|
||||
}
|
||||
return drawable.height;
|
||||
}
|
||||
|
||||
export function drawableToImageData(
|
||||
drawable: ImageBitmap | HTMLImageElement | VideoFrame,
|
||||
drawable: ImageBitmap | HTMLImageElement,
|
||||
opts: DrawableToImageDataOptions = {},
|
||||
): ImageData {
|
||||
const {
|
||||
width = getWidth(drawable),
|
||||
height = getHeight(drawable),
|
||||
width = drawable.width,
|
||||
height = drawable.height,
|
||||
sx = 0,
|
||||
sy = 0,
|
||||
sw = getWidth(drawable),
|
||||
sh = getHeight(drawable),
|
||||
sw = drawable.width,
|
||||
sh = drawable.height,
|
||||
} = opts;
|
||||
|
||||
// Make canvas same size as image
|
||||
|
@ -10,8 +10,6 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import * as WebCodecs from '../util/web-codecs';
|
||||
import { drawableToImageData } from './canvas';
|
||||
|
||||
/** If render engine is Safari */
|
||||
@ -139,15 +137,7 @@ export async function blobToImg(blob: Blob): Promise<HTMLImageElement> {
|
||||
export async function builtinDecode(
|
||||
signal: AbortSignal,
|
||||
blob: Blob,
|
||||
mimeType: string,
|
||||
): Promise<ImageData> {
|
||||
// If WebCodecs are supported, use that.
|
||||
if (await WebCodecs.isTypeSupported(mimeType)) {
|
||||
assertSignal(signal);
|
||||
try {
|
||||
return await abortable(signal, WebCodecs.decode(blob, mimeType));
|
||||
} catch (e) {}
|
||||
}
|
||||
assertSignal(signal);
|
||||
|
||||
// Prefer createImageBitmap as it's the off-thread option for Firefox.
|
||||
|
@ -1,33 +0,0 @@
|
||||
import { drawableToImageData } from '../canvas';
|
||||
|
||||
const hasImageDecoder = typeof ImageDecoder !== 'undefined';
|
||||
|
||||
export async function isTypeSupported(mimeType: string): Promise<boolean> {
|
||||
if (!hasImageDecoder) return false;
|
||||
// Some old versions of this API threw here.
|
||||
// It only impacted folks with experimental web platform flags enabled in Chrome 90.
|
||||
// The API was updated in Chrome 91.
|
||||
try {
|
||||
return await ImageDecoder.isTypeSupported(mimeType);
|
||||
} catch (err) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
export async function decode(
|
||||
blob: Blob | File,
|
||||
mimeType: string,
|
||||
): Promise<ImageData> {
|
||||
if (!hasImageDecoder) {
|
||||
throw Error(
|
||||
`This browser does not support ImageDecoder. This function should not have been called.`,
|
||||
);
|
||||
}
|
||||
const decoder = new ImageDecoder({
|
||||
type: mimeType,
|
||||
// Non-obvious way to turn an Blob into a ReadableStream
|
||||
data: new Response(blob).body!,
|
||||
});
|
||||
const { image } = await decoder.decode();
|
||||
return drawableToImageData(image);
|
||||
}
|
@ -1,60 +0,0 @@
|
||||
interface ImageDecoderInit {
|
||||
type: string;
|
||||
data: BufferSource | ReadableStream;
|
||||
premultiplyAlpha?: PremultiplyAlpha;
|
||||
colorSpaceConversion?: ColorSpaceConversion;
|
||||
desiredWidth?: number;
|
||||
desiredHeight?: number;
|
||||
preferAnimation?: boolean;
|
||||
}
|
||||
|
||||
interface ImageDecodeOptions {
|
||||
frameIndex: number;
|
||||
completeFramesOnly: boolean;
|
||||
}
|
||||
|
||||
interface ImageDecodeResult {
|
||||
image: VideoFrame;
|
||||
complete: boolean;
|
||||
}
|
||||
|
||||
// I didn’t do all the types because the class is kinda complex.
|
||||
// I focused on what we need.
|
||||
// See https://w3c.github.io/webcodecs/#videoframe
|
||||
declare class VideoFrame {
|
||||
displayWidth: number;
|
||||
displayHeight: number;
|
||||
}
|
||||
|
||||
// Add VideoFrame to canvas’ drawImage()
|
||||
interface CanvasDrawImage {
|
||||
drawImage(
|
||||
image: CanvasImageSource | VideoFrame,
|
||||
dx: number,
|
||||
dy: number,
|
||||
): void;
|
||||
drawImage(
|
||||
image: CanvasImageSource | VideoFrame,
|
||||
dx: number,
|
||||
dy: number,
|
||||
dw: number,
|
||||
dh: number,
|
||||
): void;
|
||||
drawImage(
|
||||
image: CanvasImageSource | VideoFrame,
|
||||
sx: number,
|
||||
sy: number,
|
||||
sw: number,
|
||||
sh: number,
|
||||
dx: number,
|
||||
dy: number,
|
||||
dw: number,
|
||||
dh: number,
|
||||
): void;
|
||||
}
|
||||
|
||||
declare class ImageDecoder {
|
||||
static isTypeSupported(type: string): Promise<boolean>;
|
||||
constructor(desc: ImageDecoderInit);
|
||||
decode(opts?: Partial<ImageDecodeOptions>): Promise<ImageDecodeResult>;
|
||||
}
|
@ -30,6 +30,7 @@ interface State {
|
||||
autoEdgePreservingFilter: boolean;
|
||||
decodingSpeedTier: number;
|
||||
photonNoiseIso: number;
|
||||
alternativeLossy: boolean;
|
||||
}
|
||||
|
||||
export class Options extends Component<Props, State> {
|
||||
@ -55,6 +56,7 @@ export class Options extends Component<Props, State> {
|
||||
autoEdgePreservingFilter: options.epf === -1,
|
||||
decodingSpeedTier: options.decodingSpeedTier,
|
||||
photonNoiseIso: options.photonNoiseIso,
|
||||
alternativeLossy: options.lossyModular,
|
||||
};
|
||||
}
|
||||
|
||||
@ -96,6 +98,7 @@ export class Options extends Component<Props, State> {
|
||||
lossyPalette: optionState.lossless ? optionState.slightLoss : false,
|
||||
decodingSpeedTier: optionState.decodingSpeedTier,
|
||||
photonNoiseIso: optionState.photonNoiseIso,
|
||||
lossyModular: optionState.quality < 7 ? true : optionState.alternativeLossy,
|
||||
};
|
||||
|
||||
// Updating options, so we don't recalculate in getDerivedStateFromProps.
|
||||
@ -122,6 +125,7 @@ export class Options extends Component<Props, State> {
|
||||
autoEdgePreservingFilter,
|
||||
decodingSpeedTier,
|
||||
photonNoiseIso,
|
||||
alternativeLossy,
|
||||
}: State,
|
||||
) {
|
||||
// I'm rendering both lossy and lossless forms, as it becomes much easier when
|
||||
@ -162,6 +166,14 @@ export class Options extends Component<Props, State> {
|
||||
Quality:
|
||||
</Range>
|
||||
</div>
|
||||
<label class={style.optionToggle}>
|
||||
Alternative lossy mode
|
||||
<Checkbox
|
||||
checked={quality < 7 ? true : alternativeLossy}
|
||||
disabled={quality < 7}
|
||||
onChange={this._inputChange('alternativeLossy', 'boolean')}
|
||||
/>
|
||||
</label>
|
||||
<label class={style.optionToggle}>
|
||||
Auto edge filter
|
||||
<Checkbox
|
||||
@ -223,7 +235,7 @@ export class Options extends Component<Props, State> {
|
||||
</label>
|
||||
<div class={style.optionOneCell}>
|
||||
<Range
|
||||
min="3"
|
||||
min="1"
|
||||
max="9"
|
||||
value={effort}
|
||||
onInput={this._inputChange('effort', 'number')}
|
||||
|
@ -25,4 +25,5 @@ export const defaultOptions: EncodeOptions = {
|
||||
lossyPalette: false,
|
||||
decodingSpeedTier: 0,
|
||||
photonNoiseIso: 0,
|
||||
lossyModular: false,
|
||||
};
|
||||
|
@ -14,9 +14,11 @@ import { EncodeOptions } from '../shared/meta';
|
||||
import { threads } from 'wasm-feature-detect';
|
||||
|
||||
async function initMT() {
|
||||
const { default: init, initThreadPool, optimise } = await import(
|
||||
'codecs/oxipng/pkg-parallel/squoosh_oxipng'
|
||||
);
|
||||
const {
|
||||
default: init,
|
||||
initThreadPool,
|
||||
optimise,
|
||||
} = await import('codecs/oxipng/pkg-parallel/squoosh_oxipng');
|
||||
await init();
|
||||
await initThreadPool(navigator.hardwareConcurrency);
|
||||
return optimise;
|
||||
|
@ -2,9 +2,9 @@ import * as styles from './styles.css';
|
||||
import 'add-css:./styles.css';
|
||||
|
||||
// So it doesn't cause an error when running in node
|
||||
const HTMLEl = ((__PRERENDER__
|
||||
const HTMLEl = (__PRERENDER__
|
||||
? Object
|
||||
: HTMLElement) as unknown) as typeof HTMLElement;
|
||||
: HTMLElement) as unknown as typeof HTMLElement;
|
||||
|
||||
/**
|
||||
* A simple spinner. This custom element has no JS API. Just put it in the document, and it'll
|
||||
|
@ -2,9 +2,9 @@ import * as style from './styles.css';
|
||||
import 'add-css:./styles.css';
|
||||
|
||||
// So it doesn't cause an error when running in node
|
||||
const HTMLEl = ((__PRERENDER__
|
||||
const HTMLEl = (__PRERENDER__
|
||||
? Object
|
||||
: HTMLElement) as unknown) as typeof HTMLElement;
|
||||
: HTMLElement) as unknown as typeof HTMLElement;
|
||||
|
||||
export interface SnackOptions {
|
||||
timeout?: number;
|
||||
|
21
src/shared/missing-types.d.ts
vendored
21
src/shared/missing-types.d.ts
vendored
@ -13,24 +13,3 @@
|
||||
/// <reference path="../../missing-types.d.ts" />
|
||||
|
||||
declare const __PRERENDER__: boolean;
|
||||
|
||||
type ResizeObserverCallback = (
|
||||
entries: ResizeObserverEntry[],
|
||||
observer: ResizeObserver,
|
||||
) => void;
|
||||
|
||||
interface ResizeObserverEntry {
|
||||
readonly target: Element;
|
||||
readonly contentRect: DOMRectReadOnly;
|
||||
}
|
||||
|
||||
interface ResizeObserver {
|
||||
observe(target: Element): void;
|
||||
unobserve(target: Element): void;
|
||||
disconnect(): void;
|
||||
}
|
||||
|
||||
declare var ResizeObserver: {
|
||||
prototype: ResizeObserver;
|
||||
new (callback: ResizeObserverCallback): ResizeObserver;
|
||||
};
|
||||
|
@ -30,11 +30,6 @@ interface WindowEventMap {
|
||||
beforeinstallprompt: BeforeInstallPromptEvent;
|
||||
}
|
||||
|
||||
interface ClipboardItem {
|
||||
types: string[];
|
||||
getType(type: string): Promise<Blob>;
|
||||
}
|
||||
|
||||
interface Clipboard {
|
||||
read(): Promise<ClipboardItem[]>;
|
||||
}
|
||||
|
BIN
src/static-build/assets/screenshot4.png
Normal file
BIN
src/static-build/assets/screenshot4.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 26 KiB |
BIN
src/static-build/assets/screenshot5.jpg
Normal file
BIN
src/static-build/assets/screenshot5.jpg
Normal file
Binary file not shown.
After Width: | Height: | Size: 69 KiB |
BIN
src/static-build/assets/screenshot6.jpg
Normal file
BIN
src/static-build/assets/screenshot6.jpg
Normal file
Binary file not shown.
After Width: | Height: | Size: 70 KiB |
@ -19,15 +19,39 @@ import * as iconLarge from 'img-url:static-build/assets/icon-large.png';
|
||||
import * as screenshot1 from 'img-url:static-build/assets/screenshot1.png';
|
||||
import * as screenshot2 from 'img-url:static-build/assets/screenshot2.jpg';
|
||||
import * as screenshot3 from 'img-url:static-build/assets/screenshot3.jpg';
|
||||
import * as screenshot4 from 'img-url:static-build/assets/screenshot4.png';
|
||||
import * as screenshot5 from 'img-url:static-build/assets/screenshot5.jpg';
|
||||
import * as screenshot6 from 'img-url:static-build/assets/screenshot6.jpg';
|
||||
import dedent from 'dedent';
|
||||
import { lookup as lookupMime } from 'mime-types';
|
||||
|
||||
const manifestSize = ({ width, height }: { width: number; height: number }) =>
|
||||
`${width}x${height}`;
|
||||
interface Dimensions {
|
||||
width: number;
|
||||
height: number;
|
||||
}
|
||||
|
||||
const manifestSize = ({ width, height }: Dimensions) => `${width}x${height}`;
|
||||
const formFactor = ({ width, height }: Dimensions) =>
|
||||
width > height ? 'wide' : 'narrow';
|
||||
|
||||
const screenshots = [
|
||||
screenshot1,
|
||||
screenshot2,
|
||||
screenshot3,
|
||||
screenshot4,
|
||||
screenshot5,
|
||||
screenshot6,
|
||||
].map((screenshot) => ({
|
||||
src: screenshot.default,
|
||||
type: lookupMime(screenshot.default),
|
||||
sizes: manifestSize(screenshot),
|
||||
form_factor: formFactor(screenshot),
|
||||
}));
|
||||
|
||||
interface Output {
|
||||
[outputPath: string]: string;
|
||||
}
|
||||
|
||||
const toOutput: Output = {
|
||||
'index.html': renderPage(<IndexPage />),
|
||||
'manifest.json': JSON.stringify({
|
||||
@ -55,23 +79,7 @@ const toOutput: Output = {
|
||||
'Compress and compare images with different codecs, right in your browser.',
|
||||
lang: 'en',
|
||||
categories: ['photo', 'productivity', 'utilities'],
|
||||
screenshots: [
|
||||
{
|
||||
src: screenshot1.default,
|
||||
type: lookupMime(screenshot1.default),
|
||||
sizes: manifestSize(screenshot1),
|
||||
},
|
||||
{
|
||||
src: screenshot2.default,
|
||||
type: lookupMime(screenshot2.default),
|
||||
sizes: manifestSize(screenshot2),
|
||||
},
|
||||
{
|
||||
src: screenshot3.default,
|
||||
type: lookupMime(screenshot3.default),
|
||||
sizes: manifestSize(screenshot3),
|
||||
},
|
||||
],
|
||||
screenshots,
|
||||
share_target: {
|
||||
action: '/?utm_medium=PWA&utm_source=share-target&share-target',
|
||||
method: 'POST',
|
||||
|
@ -57,6 +57,7 @@ const Index: FunctionalComponent<Props> = () => (
|
||||
<meta name="mobile-web-app-capable" content="yes" />
|
||||
<meta name="apple-mobile-web-app-capable" content="yes" />
|
||||
<link rel="shortcut icon" href={favicon} />
|
||||
<link rel="apple-touch-icon" href={ogImage} />
|
||||
<meta name="theme-color" content="#ff3385" />
|
||||
<link rel="manifest" href="/manifest.json" />
|
||||
<link rel="canonical" href={siteOrigin} />
|
||||
|
@ -82,24 +82,20 @@ initialJs = subtractSets(
|
||||
export const initial = ['/', ...initialJs];
|
||||
|
||||
export const theRest = (async () => {
|
||||
const [
|
||||
supportsThreads,
|
||||
supportsSimd,
|
||||
supportsWebP,
|
||||
supportsAvif,
|
||||
] = await Promise.all([
|
||||
threads(),
|
||||
simd(),
|
||||
...[webpDataUrl, avifDataUrl].map(async (dataUrl) => {
|
||||
if (!self.createImageBitmap) return false;
|
||||
const response = await fetch(dataUrl);
|
||||
const blob = await response.blob();
|
||||
return createImageBitmap(blob).then(
|
||||
() => true,
|
||||
() => false,
|
||||
);
|
||||
}),
|
||||
]);
|
||||
const [supportsThreads, supportsSimd, supportsWebP, supportsAvif] =
|
||||
await Promise.all([
|
||||
threads(),
|
||||
simd(),
|
||||
...[webpDataUrl, avifDataUrl].map(async (dataUrl) => {
|
||||
if (!self.createImageBitmap) return false;
|
||||
const response = await fetch(dataUrl);
|
||||
const blob = await response.blob();
|
||||
return createImageBitmap(blob).then(
|
||||
() => true,
|
||||
() => false,
|
||||
);
|
||||
}),
|
||||
]);
|
||||
|
||||
const items: string[] = [];
|
||||
|
||||
|
Reference in New Issue
Block a user