Compare commits

..

2 Commits

Author SHA1 Message Date
Jake Archibald
ffe8cd3562 Trick to avoid duplicating the SVG in the source 2021-09-22 15:04:44 +01:00
Jake Archibald
853a26ba26 Inlining logo SVG 2021-09-22 14:46:29 +01:00
47 changed files with 491 additions and 275 deletions

4
.gitattributes vendored
View File

@@ -1,2 +1,2 @@
/codecs/**/*.js linguist-generated -diff /codecs/**/*.js linguist-generated=true
/codecs/*/pkg*/*.d.ts linguist-generated /codecs/*/pkg*/*.d.ts linguist-generated=true

View File

@@ -1 +0,0 @@
npx lint-staged

View File

@@ -1,5 +1,5 @@
CODEC_URL = https://github.com/libjxl/libjxl.git CODEC_URL = https://github.com/libjxl/libjxl.git
CODEC_VERSION = 9f544641ec83f6abd9da598bdd08178ee8a003e0 CODEC_VERSION = v0.5
CODEC_DIR = node_modules/jxl CODEC_DIR = node_modules/jxl
CODEC_BUILD_ROOT := $(CODEC_DIR)/build CODEC_BUILD_ROOT := $(CODEC_DIR)/build
CODEC_MT_BUILD_DIR := $(CODEC_BUILD_ROOT)/mt CODEC_MT_BUILD_DIR := $(CODEC_BUILD_ROOT)/mt
@@ -75,9 +75,6 @@ $(CODEC_MT_SIMD_BUILD_DIR)/Makefile: CXXFLAGS+=-msimd128
-DCMAKE_CROSSCOMPILING_EMULATOR=node \ -DCMAKE_CROSSCOMPILING_EMULATOR=node \
-B $(@D) \ -B $(@D) \
$(<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: $(CODEC_DIR)/CMakeLists.txt:
$(RM) -r $(@D) $(RM) -r $(@D)

File diff suppressed because one or more lines are too long

Binary file not shown.

File diff suppressed because one or more lines are too long

Binary file not shown.

View File

@@ -4,7 +4,6 @@
#include "lib/jxl/base/thread_pool_internal.h" #include "lib/jxl/base/thread_pool_internal.h"
#include "lib/jxl/enc_external_image.h" #include "lib/jxl/enc_external_image.h"
#include "lib/jxl/enc_file.h" #include "lib/jxl/enc_file.h"
#include "lib/jxl/enc_color_management.h"
using namespace emscripten; using namespace emscripten;
@@ -18,7 +17,6 @@ struct JXLOptions {
bool lossyPalette; bool lossyPalette;
size_t decodingSpeedTier; size_t decodingSpeedTier;
float photonNoiseIso; float photonNoiseIso;
bool lossyModular;
}; };
val encode(std::string image, int width, int height, JXLOptions options) { val encode(std::string image, int width, int height, JXLOptions options) {
@@ -52,16 +50,11 @@ val encode(std::string image, int width, int height, JXLOptions options) {
float quality = options.quality; float quality = options.quality;
// Quality settings roughly match libjpeg qualities. // Quality settings roughly match libjpeg qualities.
if (options.lossyModular || quality == 100) { if (quality < 7 || quality == 100) {
cparams.modular_mode = true; cparams.modular_mode = true;
// Internal modular quality to roughly match VarDCT size. // Internal modular quality to roughly match VarDCT size.
if (quality < 7) { cparams.quality_pair.first = cparams.quality_pair.second =
cparams.quality_pair.first = cparams.quality_pair.second = std::min(35 + (quality - 7) * 3.0f, 100.0f);
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 { } else {
cparams.modular_mode = false; cparams.modular_mode = false;
if (quality >= 30) { if (quality >= 30) {
@@ -98,14 +91,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, 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, height, jxl::ColorEncoding::SRGB(/*is_gray=*/false), /*has_alpha=*/true,
/*alpha_is_premultiplied=*/false, /*bits_per_sample=*/8, /*endiannes=*/JXL_LITTLE_ENDIAN, /*alpha_is_premultiplied=*/false, /*bits_per_sample=*/8, /*endiannes=*/JXL_LITTLE_ENDIAN,
/*flipped_y=*/false, pool_ptr, main, /*(only true if bits_per_sample==32) float_in=*/false); /*flipped_y=*/false, pool_ptr, main);
if (!result) { if (!result) {
return val::null(); return val::null();
} }
auto js_result = val::null(); auto js_result = val::null();
if (EncodeFile(cparams, &io, &passes_enc_state, &bytes, jxl::GetJxlCms(), /*aux=*/nullptr, pool_ptr)) { if (EncodeFile(cparams, &io, &passes_enc_state, &bytes, /*aux=*/nullptr, pool_ptr)) {
js_result = Uint8Array.new_(typed_memory_view(bytes.size(), bytes.data())); js_result = Uint8Array.new_(typed_memory_view(bytes.size(), bytes.data()));
} }
@@ -120,7 +113,6 @@ EMSCRIPTEN_BINDINGS(my_module) {
.field("lossyPalette", &JXLOptions::lossyPalette) .field("lossyPalette", &JXLOptions::lossyPalette)
.field("decodingSpeedTier", &JXLOptions::decodingSpeedTier) .field("decodingSpeedTier", &JXLOptions::decodingSpeedTier)
.field("photonNoiseIso", &JXLOptions::photonNoiseIso) .field("photonNoiseIso", &JXLOptions::photonNoiseIso)
.field("lossyModular", &JXLOptions::lossyModular)
.field("epf", &JXLOptions::epf); .field("epf", &JXLOptions::epf);
function("encode", &encode); function("encode", &encode);

View File

@@ -6,7 +6,6 @@ export interface EncodeOptions {
lossyPalette: boolean; lossyPalette: boolean;
decodingSpeedTier: number; decodingSpeedTier: number;
photonNoiseIso: number; photonNoiseIso: number;
lossyModular: boolean;
} }
export interface JXLModule extends EmscriptenWasm.Module { export interface JXLModule extends EmscriptenWasm.Module {

File diff suppressed because one or more lines are too long

Binary file not shown.

File diff suppressed because one or more lines are too long

Binary file not shown.

File diff suppressed because one or more lines are too long

Binary file not shown.

File diff suppressed because one or more lines are too long

Binary file not shown.

38
lib/as-text-plugin.js Normal file
View File

@@ -0,0 +1,38 @@
/**
* Copyright 2020 Google Inc. All Rights Reserved.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* http://www.apache.org/licenses/LICENSE-2.0
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import { promises as fs } from 'fs';
const prefix = 'as-text:';
export default function dataURLPlugin() {
return {
name: 'as-text-plugin',
async resolveId(id, importer) {
if (!id.startsWith(prefix)) return;
const realId = id.slice(prefix.length);
const resolveResult = await this.resolve(realId, importer);
if (!resolveResult) throw Error(`Cannot find ${realId} from ${importer}`);
return prefix + resolveResult.id;
},
async load(id) {
if (!id.startsWith(prefix)) return;
const realId = id.slice(prefix.length);
this.addWatchFile(realId);
const source = await fs.readFile(realId, { encoding: 'utf-8' });
return `export default ${JSON.stringify(source)}`;
},
};
}

View File

@@ -77,9 +77,7 @@ export default function entryDataPlugin() {
} }
return JSON.stringify( return JSON.stringify(
getDependencies(chunks, chunk).map((filename) => getDependencies(chunks, chunk).map((filename) => fileNameToURL(filename)),
fileNameToURL(filename),
),
); );
}, },
); );

View File

@@ -11,23 +11,10 @@
* limitations under the License. * limitations under the License.
*/ */
import { promisify } from 'util'; import { promisify } from 'util';
import { promises as fsp, readFileSync } from 'fs';
import path from 'path'; import path from 'path';
import { posix } from 'path'; import { posix } from 'path';
import glob from 'glob'; import glob from 'glob';
import postcss from 'postcss';
import postCSSNested from 'postcss-nested';
import postCSSUrl from 'postcss-url';
import postCSSModules from 'postcss-modules';
import postCSSSimpleVars from 'postcss-simple-vars';
import cssNano from 'cssnano';
import {
parse as parsePath,
resolve as resolvePath,
dirname,
normalize as nomalizePath,
sep as pathSep,
} from 'path';
const globP = promisify(glob); const globP = promisify(glob);
@@ -43,72 +30,26 @@ export default function initialCssPlugin() {
async load(id) { async load(id) {
if (id !== initialCssModule) return; if (id !== initialCssModule) return;
const matches = ( const matches = await globP('shared/prerendered-app/**/*.css', {
await globP('shared/prerendered-app/**/*.css', { nodir: true,
nodir: true, cwd: path.join(process.cwd(), 'src'),
cwd: path.join(process.cwd(), 'src'), });
absolute: true,
})
).map((cssPath) =>
// glob() returns windows paths with a forward slash. Normalise it:
path.normalize(cssPath),
);
// Sort the matches so the parentmost items appear first. // Sort the matches so the parentmost items appear first.
// This is a bit of a hack, but it means the util stuff appears in the cascade first. // This is a bit of a hack, but it means the util stuff appears in the cascade first.
const sortedMatches = matches const sortedMatches = matches
.map((match) => path.normalize(match).split(path.sep)) .map((match) => path.normalize(match).split(path.sep))
.sort((a, b) => a.length - b.length) .sort((a, b) => a.length - b.length)
.map((match) => '/' + posix.join(...match)); .map((match) => posix.join(...match));
const cssSources = await Promise.all( const imports = sortedMatches
sortedMatches.map(async (path) => { .map((id, i) => `import css${i} from 'css:${id}';\n`)
this.addWatchFile(path); .join('');
const file = await fsp.readFile(path);
const cssResult = await postcss([ return (
postCSSNested, imports +
postCSSSimpleVars(), `export default ${sortedMatches.map((_, i) => `css${i}`).join(' + ')};`
postCSSModules({
root: '',
}),
postCSSUrl({
url: ({ relativePath, url }) => {
if (/^((https?|data):|#)/.test(url)) return url;
const parsedPath = parsePath(relativePath);
const source = readFileSync(
resolvePath(dirname(path), relativePath),
);
const fileId = this.emitFile({
type: 'asset',
name: parsedPath.base,
source,
});
const hash = createHash('md5');
hash.update(source);
const md5 = hash.digest('hex');
hashToId.set(md5, fileId);
return `/fake/path/to/asset/${md5}/`;
},
}),
cssNano,
]).process(file, {
from: path,
});
return cssResult.css;
}),
); );
const css = cssSources.join('\n');
const fileId = this.emitFile({
type: 'asset',
source: css,
name: 'initial.css',
});
return `export default import.meta.ROLLUP_FILE_URL_${fileId};`;
}, },
}; };
} }

View File

@@ -22,8 +22,6 @@ 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. 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 ## Ingesting images
You can ingest a new image like so: You can ingest a new image like so:
@@ -43,15 +41,19 @@ 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: 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 ```js
await image.decoded; //Wait until the image is decoded before running preprocessors.
const preprocessOptions = { const preprocessOptions = {
//When both width and height are specified, the image resized to specified size. //When both width and height are specified, the image resized to specified size.
resize: { resize: {
enabled: true,
width: 100, width: 100,
height: 50, height: 50,
}, },
/* /*
//When either width or height is specified, the image resized to specified size keeping aspect ratio. //When either width or height is specified, the image resized to specified size keeping aspect ratio.
resize: { resize: {
enabled: true,
width: 100, width: 100,
} }
*/ */
@@ -64,7 +66,7 @@ const encodeOptions = {
quality: 90, quality: 90,
}, },
}; };
const result = await image.encode(encodeOptions); 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._ 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._
@@ -88,7 +90,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: This example takes an image that has been encoded as a `jpg` and writes it to a file:
```js ```js
const rawEncodedImage = image.encodedWith.mozjpeg.binary; const rawEncodedImage = (await image.encodedWith.mozjpeg).binary;
fs.writeFile('/path/to/new/image.jpg', rawEncodedImage); fs.writeFile('/path/to/new/image.jpg', rawEncodedImage);
``` ```
@@ -99,7 +101,10 @@ This example iterates through all encoded versions of the image and writes them
const newImagePath = '/path/to/image.'; //extension is added automatically const newImagePath = '/path/to/image.'; //extension is added automatically
for (const encodedImage of Object.values(image.encodedWith)) { for (const encodedImage of Object.values(image.encodedWith)) {
fs.writeFile(newImagePath + encodedImage.extension, encodedImage.binary); fs.writeFile(
newImagePath + (await encodedImage).extension,
(await encodedImage).binary,
);
} }
``` ```
@@ -128,7 +133,7 @@ console.log(await image.decoded);
Information about an encoded image can be found at `Image.encodedWith[encoderName]`. It looks something like this: Information about an encoded image can be found at `Image.encodedWith[encoderName]`. It looks something like this:
```js ```js
console.log(image.encodedWith.jxl); console.log(await image.encodedWith.jxl);
// Returns: // Returns:
{ {
optionsUsed: { optionsUsed: {

View File

@@ -1,26 +0,0 @@
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 });
})();

View File

@@ -1,15 +1,14 @@
{ {
"name": "@squoosh/lib", "name": "@squoosh/lib",
"version": "0.5.0", "version": "0.4.0",
"description": "A Node library for Squoosh", "description": "A Node library for Squoosh",
"public": true, "public": true,
"main": "./build/index.js", "main": "./build/index.js",
"types": "./build/index.d.ts",
"files": [ "files": [
"/build/*" "/build/*"
], ],
"scripts": { "scripts": {
"build": "rollup -c && node lib/move-d-ts.js" "build": "rollup -c"
}, },
"keywords": [], "keywords": [],
"author": "Google Chrome Developers <chromium-dev@google.com>", "author": "Google Chrome Developers <chromium-dev@google.com>",

View File

@@ -419,7 +419,6 @@ export const codecs = {
lossyPalette: false, lossyPalette: false,
decodingSpeedTier: 0, decodingSpeedTier: 0,
photonNoiseIso: 0, photonNoiseIso: 0,
lossyModular: false,
}, },
autoOptimize: { autoOptimize: {
option: 'quality', option: 'quality',

View File

@@ -22,10 +22,9 @@ type EncoderKey = keyof typeof encoders;
type PreprocessorKey = keyof typeof preprocessors; type PreprocessorKey = keyof typeof preprocessors;
type PreprocessOptions = { type PreprocessOptions = {
resize?: Partial<Omit<ResizeOptions, 'width' | 'height'>> & resize?: ResizeOptions;
(Pick<ResizeOptions, 'width'> | Pick<ResizeOptions, 'height'>); quant?: QuantOptions;
quant?: Partial<QuantOptions>; rotate?: RotateOptions;
rotate?: Partial<RotateOptions>;
}; };
type EncodeResult = { type EncodeResult = {
optionsUsed: object; optionsUsed: object;

View File

@@ -3,8 +3,7 @@
"compilerOptions": { "compilerOptions": {
"lib": ["esnext"], "lib": ["esnext"],
"types": ["node"], "types": ["node"],
"allowJs": true, "allowJs": true
"declaration": true
}, },
"include": ["src/**/*", "../codecs/**/*"] "include": ["src/**/*", "../codecs/**/*"]
} }

5
missing-types.d.ts vendored
View File

@@ -49,6 +49,11 @@ declare module 'data-url-text:*' {
export default url; export default url;
} }
declare module 'as-text:*' {
const text: string;
export default text;
}
declare module 'service-worker:*' { declare module 'service-worker:*' {
const url: string; const url: string;
export default url; export default url;

328
package-lock.json generated
View File

@@ -16,15 +16,15 @@
"@rollup/plugin-replace": "^2.3.4", "@rollup/plugin-replace": "^2.3.4",
"@surma/rollup-plugin-off-main-thread": "^2.2.2", "@surma/rollup-plugin-off-main-thread": "^2.2.2",
"@types/dedent": "^0.7.0", "@types/dedent": "^0.7.0",
"@types/mime-types": "^2.1.1", "@types/mime-types": "^2.1.0",
"@types/node": "^16.11.1", "@types/node": "^14.14.7",
"@web/rollup-plugin-import-meta-assets": "^1.0.6", "@web/rollup-plugin-import-meta-assets": "^1.0.6",
"comlink": "^4.3.0", "comlink": "^4.3.0",
"cssnano": "^4.1.10", "cssnano": "^4.1.10",
"dedent": "^0.7.0", "dedent": "^0.7.0",
"del": "^5.1.0", "del": "^5.1.0",
"file-drop-element": "^1.0.1", "file-drop-element": "^1.0.1",
"husky": "^7.0.2", "husky": "^4.3.0",
"idb-keyval": "^3.2.0", "idb-keyval": "^3.2.0",
"image-size": "^0.9.3", "image-size": "^0.9.3",
"linkstate": "^2.0.0", "linkstate": "^2.0.0",
@@ -40,11 +40,11 @@
"postcss-url": "^8.0.0", "postcss-url": "^8.0.0",
"preact": "^10.5.5", "preact": "^10.5.5",
"preact-render-to-string": "^5.1.11", "preact-render-to-string": "^5.1.11",
"prettier": "^2.4.1", "prettier": "^2.1.2",
"rollup": "^2.38.0", "rollup": "^2.38.0",
"rollup-plugin-terser": "^7.0.2", "rollup-plugin-terser": "^7.0.2",
"serve": "^11.3.2", "serve": "^11.3.2",
"typescript": "^4.4.4", "typescript": "^4.1.3",
"which": "^2.0.2" "which": "^2.0.2"
} }
}, },
@@ -315,9 +315,9 @@
} }
}, },
"node_modules/@types/mime-types": { "node_modules/@types/mime-types": {
"version": "2.1.1", "version": "2.1.0",
"resolved": "https://registry.npmjs.org/@types/mime-types/-/mime-types-2.1.1.tgz", "resolved": "https://registry.npmjs.org/@types/mime-types/-/mime-types-2.1.0.tgz",
"integrity": "sha512-vXOTGVSLR2jMw440moWTC7H19iUyLtP3Z1YTj7cSsubOICinjMxFeb/V57v9QdyyPGbbWolUFSSmSiRSn94tFw==", "integrity": "sha1-nKUs2jY/aZxpRmwqbM2q2RPqenM=",
"dev": true "dev": true
}, },
"node_modules/@types/minimatch": { "node_modules/@types/minimatch": {
@@ -327,9 +327,9 @@
"dev": true "dev": true
}, },
"node_modules/@types/node": { "node_modules/@types/node": {
"version": "16.11.1", "version": "14.14.7",
"resolved": "https://registry.npmjs.org/@types/node/-/node-16.11.1.tgz", "resolved": "https://registry.npmjs.org/@types/node/-/node-14.14.7.tgz",
"integrity": "sha512-PYGcJHL9mwl1Ek3PLiYgyEKtwTMmkMw4vbiyz/ps3pfdRYLVv+SN7qHVAImrjdAXxgluDEw6Ph4lyv+m9UpRmA==", "integrity": "sha512-Zw1vhUSQZYw+7u5dAwNbIA9TuTotpzY/OF7sJM9FqPOF3SPjKnxrjoTktXDZgUjybf4cWVBP7O8wvKdSaGHweg==",
"dev": true "dev": true
}, },
"node_modules/@types/parse-json": { "node_modules/@types/parse-json": {
@@ -866,6 +866,12 @@
"node": ">=4" "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": { "node_modules/clean-stack": {
"version": "2.2.0", "version": "2.2.0",
"resolved": "https://registry.npmjs.org/clean-stack/-/clean-stack-2.2.0.tgz", "resolved": "https://registry.npmjs.org/clean-stack/-/clean-stack-2.2.0.tgz",
@@ -1170,6 +1176,12 @@
"integrity": "sha1-3dgA2gxmEnOTzKWVDqloo6rxJTs=", "integrity": "sha1-3dgA2gxmEnOTzKWVDqloo6rxJTs=",
"dev": true "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": { "node_modules/compressible": {
"version": "2.0.18", "version": "2.0.18",
"resolved": "https://registry.npmjs.org/compressible/-/compressible-2.0.18.tgz", "resolved": "https://registry.npmjs.org/compressible/-/compressible-2.0.18.tgz",
@@ -2272,6 +2284,31 @@
"node": ">=8" "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": { "node_modules/fs.realpath": {
"version": "1.0.0", "version": "1.0.0",
"resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz",
@@ -2448,18 +2485,28 @@
} }
}, },
"node_modules/husky": { "node_modules/husky": {
"version": "7.0.2", "version": "4.3.0",
"resolved": "https://registry.npmjs.org/husky/-/husky-7.0.2.tgz", "resolved": "https://registry.npmjs.org/husky/-/husky-4.3.0.tgz",
"integrity": "sha512-8yKEWNX4z2YsofXAMT7KvA1g8p+GxtB1ffV8XtpAEGuXNAbCV5wdNKH+qTpw8SM9fh4aMPDR+yQuKfgnreyZlg==", "integrity": "sha512-tTMeLCLqSBqnflBZnlVDhpaIMucSGaYyX6855jM4AguGeWCeSzNdb1mfyWduTZ3pe3SJVvVWGL0jO1iKZVPfTA==",
"dev": true, "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": { "bin": {
"husky": "lib/bin.js" "husky-run": "bin/run.js",
"husky-upgrade": "lib/upgrader/bin.js"
}, },
"engines": { "engines": {
"node": ">=12" "node": ">=10"
},
"funding": {
"url": "https://github.com/sponsors/typicode"
} }
}, },
"node_modules/icss-replace-symbols": { "node_modules/icss-replace-symbols": {
@@ -3117,6 +3164,18 @@
"node": ">=4.0.0" "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": { "node_modules/lodash.camelcase": {
"version": "4.3.0", "version": "4.3.0",
"resolved": "https://registry.npmjs.org/lodash.camelcase/-/lodash.camelcase-4.3.0.tgz", "resolved": "https://registry.npmjs.org/lodash.camelcase/-/lodash.camelcase-4.3.0.tgz",
@@ -3630,6 +3689,15 @@
"node": ">=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": { "node_modules/p-finally": {
"version": "1.0.0", "version": "1.0.0",
"resolved": "https://registry.npmjs.org/p-finally/-/p-finally-1.0.0.tgz", "resolved": "https://registry.npmjs.org/p-finally/-/p-finally-1.0.0.tgz",
@@ -3639,6 +3707,30 @@
"node": ">=4" "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": { "node_modules/p-map": {
"version": "3.0.0", "version": "3.0.0",
"resolved": "https://registry.npmjs.org/p-map/-/p-map-3.0.0.tgz", "resolved": "https://registry.npmjs.org/p-map/-/p-map-3.0.0.tgz",
@@ -3651,6 +3743,15 @@
"node": ">=8" "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": { "node_modules/parent-module": {
"version": "1.0.1", "version": "1.0.1",
"resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz",
@@ -3678,6 +3779,15 @@
"node": ">=4" "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": { "node_modules/path-is-absolute": {
"version": "1.0.1", "version": "1.0.1",
"resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz",
@@ -3753,6 +3863,18 @@
"node": ">=4" "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": { "node_modules/please-upgrade-node": {
"version": "3.2.0", "version": "3.2.0",
"resolved": "https://registry.npmjs.org/please-upgrade-node/-/please-upgrade-node-3.2.0.tgz", "resolved": "https://registry.npmjs.org/please-upgrade-node/-/please-upgrade-node-3.2.0.tgz",
@@ -7407,9 +7529,9 @@
} }
}, },
"node_modules/prettier": { "node_modules/prettier": {
"version": "2.4.1", "version": "2.1.2",
"resolved": "https://registry.npmjs.org/prettier/-/prettier-2.4.1.tgz", "resolved": "https://registry.npmjs.org/prettier/-/prettier-2.1.2.tgz",
"integrity": "sha512-9fbDAXSBcc6Bs1mZrDYb3XKzDLm4EXXL9sC1LqKP5rZkT6KRr/rf9amVUcODVXgguK/isJz0d0hP72WeaKWsvA==", "integrity": "sha512-16c7K+x4qVlJg9rEbXl7HEGmQyZlG4R9AgP+oHKRMsMsuk8s+ATStlf1NpDqyBI1HpVyfjLOeMhH2LvuNvV5Vg==",
"dev": true, "dev": true,
"bin": { "bin": {
"prettier": "bin-prettier.js" "prettier": "bin-prettier.js"
@@ -7686,6 +7808,15 @@
"integrity": "sha1-De4hahyUGrN+nvsXiPavxf9VN/w=", "integrity": "sha1-De4hahyUGrN+nvsXiPavxf9VN/w=",
"dev": true "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": { "node_modules/serialize-javascript": {
"version": "4.0.0", "version": "4.0.0",
"resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-4.0.0.tgz", "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-4.0.0.tgz",
@@ -8471,9 +8602,9 @@
} }
}, },
"node_modules/typescript": { "node_modules/typescript": {
"version": "4.4.4", "version": "4.1.3",
"resolved": "https://registry.npmjs.org/typescript/-/typescript-4.4.4.tgz", "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.1.3.tgz",
"integrity": "sha512-DqGhF5IKoBl8WNf8C1gu8q0xZSInh9j1kJJMqT3a94w1JzVaBU4EXOSMrz9yDqMT0xt3selp83fuFMQ0uzv6qA==", "integrity": "sha512-B3ZIOf1IKeH2ixgHhj6la6xdwR9QrLC5d1VKeCSY4tvkqhF2eqd9O7txNlS0PO3GrBAFIdr3L1ndNwteUbZLYg==",
"dev": true, "dev": true,
"bin": { "bin": {
"tsc": "bin/tsc", "tsc": "bin/tsc",
@@ -8577,6 +8708,12 @@
"node": ">= 8" "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": { "node_modules/widest-line": {
"version": "2.0.1", "version": "2.0.1",
"resolved": "https://registry.npmjs.org/widest-line/-/widest-line-2.0.1.tgz", "resolved": "https://registry.npmjs.org/widest-line/-/widest-line-2.0.1.tgz",
@@ -8903,9 +9040,9 @@
} }
}, },
"@types/mime-types": { "@types/mime-types": {
"version": "2.1.1", "version": "2.1.0",
"resolved": "https://registry.npmjs.org/@types/mime-types/-/mime-types-2.1.1.tgz", "resolved": "https://registry.npmjs.org/@types/mime-types/-/mime-types-2.1.0.tgz",
"integrity": "sha512-vXOTGVSLR2jMw440moWTC7H19iUyLtP3Z1YTj7cSsubOICinjMxFeb/V57v9QdyyPGbbWolUFSSmSiRSn94tFw==", "integrity": "sha1-nKUs2jY/aZxpRmwqbM2q2RPqenM=",
"dev": true "dev": true
}, },
"@types/minimatch": { "@types/minimatch": {
@@ -8915,9 +9052,9 @@
"dev": true "dev": true
}, },
"@types/node": { "@types/node": {
"version": "16.11.1", "version": "14.14.7",
"resolved": "https://registry.npmjs.org/@types/node/-/node-16.11.1.tgz", "resolved": "https://registry.npmjs.org/@types/node/-/node-14.14.7.tgz",
"integrity": "sha512-PYGcJHL9mwl1Ek3PLiYgyEKtwTMmkMw4vbiyz/ps3pfdRYLVv+SN7qHVAImrjdAXxgluDEw6Ph4lyv+m9UpRmA==", "integrity": "sha512-Zw1vhUSQZYw+7u5dAwNbIA9TuTotpzY/OF7sJM9FqPOF3SPjKnxrjoTktXDZgUjybf4cWVBP7O8wvKdSaGHweg==",
"dev": true "dev": true
}, },
"@types/parse-json": { "@types/parse-json": {
@@ -9357,6 +9494,12 @@
"supports-color": "^7.1.0" "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": { "clean-stack": {
"version": "2.2.0", "version": "2.2.0",
"resolved": "https://registry.npmjs.org/clean-stack/-/clean-stack-2.2.0.tgz", "resolved": "https://registry.npmjs.org/clean-stack/-/clean-stack-2.2.0.tgz",
@@ -9610,6 +9753,12 @@
"integrity": "sha1-3dgA2gxmEnOTzKWVDqloo6rxJTs=", "integrity": "sha1-3dgA2gxmEnOTzKWVDqloo6rxJTs=",
"dev": true "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": { "compressible": {
"version": "2.0.18", "version": "2.0.18",
"resolved": "https://registry.npmjs.org/compressible/-/compressible-2.0.18.tgz", "resolved": "https://registry.npmjs.org/compressible/-/compressible-2.0.18.tgz",
@@ -10527,6 +10676,25 @@
"to-regex-range": "^5.0.1" "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": { "fs.realpath": {
"version": "1.0.0", "version": "1.0.0",
"resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz",
@@ -10673,10 +10841,22 @@
"dev": true "dev": true
}, },
"husky": { "husky": {
"version": "7.0.2", "version": "4.3.0",
"resolved": "https://registry.npmjs.org/husky/-/husky-7.0.2.tgz", "resolved": "https://registry.npmjs.org/husky/-/husky-4.3.0.tgz",
"integrity": "sha512-8yKEWNX4z2YsofXAMT7KvA1g8p+GxtB1ffV8XtpAEGuXNAbCV5wdNKH+qTpw8SM9fh4aMPDR+yQuKfgnreyZlg==", "integrity": "sha512-tTMeLCLqSBqnflBZnlVDhpaIMucSGaYyX6855jM4AguGeWCeSzNdb1mfyWduTZ3pe3SJVvVWGL0jO1iKZVPfTA==",
"dev": true "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"
}
}, },
"icss-replace-symbols": { "icss-replace-symbols": {
"version": "1.1.0", "version": "1.1.0",
@@ -11214,6 +11394,15 @@
"json5": "^1.0.1" "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": { "lodash.camelcase": {
"version": "4.3.0", "version": "4.3.0",
"resolved": "https://registry.npmjs.org/lodash.camelcase/-/lodash.camelcase-4.3.0.tgz", "resolved": "https://registry.npmjs.org/lodash.camelcase/-/lodash.camelcase-4.3.0.tgz",
@@ -11626,12 +11815,36 @@
"mimic-fn": "^2.1.0" "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": { "p-finally": {
"version": "1.0.0", "version": "1.0.0",
"resolved": "https://registry.npmjs.org/p-finally/-/p-finally-1.0.0.tgz", "resolved": "https://registry.npmjs.org/p-finally/-/p-finally-1.0.0.tgz",
"integrity": "sha1-P7z7FbiZpEEjs0ttzBi3JDNqLK4=", "integrity": "sha1-P7z7FbiZpEEjs0ttzBi3JDNqLK4=",
"dev": true "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": { "p-map": {
"version": "3.0.0", "version": "3.0.0",
"resolved": "https://registry.npmjs.org/p-map/-/p-map-3.0.0.tgz", "resolved": "https://registry.npmjs.org/p-map/-/p-map-3.0.0.tgz",
@@ -11641,6 +11854,12 @@
"aggregate-error": "^3.0.0" "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": { "parent-module": {
"version": "1.0.1", "version": "1.0.1",
"resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz",
@@ -11662,6 +11881,12 @@
"lines-and-columns": "^1.1.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": { "path-is-absolute": {
"version": "1.0.1", "version": "1.0.1",
"resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz",
@@ -11716,6 +11941,15 @@
"integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=", "integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=",
"dev": true "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": { "please-upgrade-node": {
"version": "3.2.0", "version": "3.2.0",
"resolved": "https://registry.npmjs.org/please-upgrade-node/-/please-upgrade-node-3.2.0.tgz", "resolved": "https://registry.npmjs.org/please-upgrade-node/-/please-upgrade-node-3.2.0.tgz",
@@ -14795,9 +15029,9 @@
} }
}, },
"prettier": { "prettier": {
"version": "2.4.1", "version": "2.1.2",
"resolved": "https://registry.npmjs.org/prettier/-/prettier-2.4.1.tgz", "resolved": "https://registry.npmjs.org/prettier/-/prettier-2.1.2.tgz",
"integrity": "sha512-9fbDAXSBcc6Bs1mZrDYb3XKzDLm4EXXL9sC1LqKP5rZkT6KRr/rf9amVUcODVXgguK/isJz0d0hP72WeaKWsvA==", "integrity": "sha512-16c7K+x4qVlJg9rEbXl7HEGmQyZlG4R9AgP+oHKRMsMsuk8s+ATStlf1NpDqyBI1HpVyfjLOeMhH2LvuNvV5Vg==",
"dev": true "dev": true
}, },
"pretty-format": { "pretty-format": {
@@ -15023,6 +15257,12 @@
"integrity": "sha1-De4hahyUGrN+nvsXiPavxf9VN/w=", "integrity": "sha1-De4hahyUGrN+nvsXiPavxf9VN/w=",
"dev": true "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": { "serialize-javascript": {
"version": "4.0.0", "version": "4.0.0",
"resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-4.0.0.tgz", "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-4.0.0.tgz",
@@ -15677,9 +15917,9 @@
"dev": true "dev": true
}, },
"typescript": { "typescript": {
"version": "4.4.4", "version": "4.1.3",
"resolved": "https://registry.npmjs.org/typescript/-/typescript-4.4.4.tgz", "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.1.3.tgz",
"integrity": "sha512-DqGhF5IKoBl8WNf8C1gu8q0xZSInh9j1kJJMqT3a94w1JzVaBU4EXOSMrz9yDqMT0xt3selp83fuFMQ0uzv6qA==", "integrity": "sha512-B3ZIOf1IKeH2ixgHhj6la6xdwR9QrLC5d1VKeCSY4tvkqhF2eqd9O7txNlS0PO3GrBAFIdr3L1ndNwteUbZLYg==",
"dev": true "dev": true
}, },
"uniq": { "uniq": {
@@ -15767,6 +16007,12 @@
"isexe": "^2.0.0" "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": { "widest-line": {
"version": "2.0.1", "version": "2.0.1",
"resolved": "https://registry.npmjs.org/widest-line/-/widest-line-2.0.1.tgz", "resolved": "https://registry.npmjs.org/widest-line/-/widest-line-2.0.1.tgz",

View File

@@ -8,8 +8,7 @@
"debug": "node --inspect-brk node_modules/.bin/rollup -c", "debug": "node --inspect-brk node_modules/.bin/rollup -c",
"dev": "DEV_PORT=\"${DEV_PORT:=5000}\" run-p watch serve", "dev": "DEV_PORT=\"${DEV_PORT:=5000}\" run-p watch serve",
"watch": "rollup -cw", "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": { "devDependencies": {
"@rollup/plugin-commonjs": "^17.0.0", "@rollup/plugin-commonjs": "^17.0.0",
@@ -17,15 +16,15 @@
"@rollup/plugin-replace": "^2.3.4", "@rollup/plugin-replace": "^2.3.4",
"@surma/rollup-plugin-off-main-thread": "^2.2.2", "@surma/rollup-plugin-off-main-thread": "^2.2.2",
"@types/dedent": "^0.7.0", "@types/dedent": "^0.7.0",
"@types/mime-types": "^2.1.1", "@types/mime-types": "^2.1.0",
"@types/node": "^16.11.1", "@types/node": "^14.14.7",
"@web/rollup-plugin-import-meta-assets": "^1.0.6", "@web/rollup-plugin-import-meta-assets": "^1.0.6",
"comlink": "^4.3.0", "comlink": "^4.3.0",
"cssnano": "^4.1.10", "cssnano": "^4.1.10",
"dedent": "^0.7.0", "dedent": "^0.7.0",
"del": "^5.1.0", "del": "^5.1.0",
"file-drop-element": "^1.0.1", "file-drop-element": "^1.0.1",
"husky": "^7.0.2", "husky": "^4.3.0",
"idb-keyval": "^3.2.0", "idb-keyval": "^3.2.0",
"image-size": "^0.9.3", "image-size": "^0.9.3",
"linkstate": "^2.0.0", "linkstate": "^2.0.0",
@@ -41,13 +40,18 @@
"postcss-url": "^8.0.0", "postcss-url": "^8.0.0",
"preact": "^10.5.5", "preact": "^10.5.5",
"preact-render-to-string": "^5.1.11", "preact-render-to-string": "^5.1.11",
"prettier": "^2.4.1", "prettier": "^2.1.2",
"rollup": "^2.38.0", "rollup": "^2.38.0",
"rollup-plugin-terser": "^7.0.2", "rollup-plugin-terser": "^7.0.2",
"serve": "^11.3.2", "serve": "^11.3.2",
"typescript": "^4.4.4", "typescript": "^4.1.3",
"which": "^2.0.2" "which": "^2.0.2"
}, },
"husky": {
"hooks": {
"pre-commit": "lint-staged"
}
},
"lint-staged": { "lint-staged": {
"*.{js,css,json,md,ts,tsx}": "prettier --write", "*.{js,css,json,md,ts,tsx}": "prettier --write",
"*.{c,h,cpp,hpp}": "clang-format -i", "*.{c,h,cpp,hpp}": "clang-format -i",

View File

@@ -32,6 +32,7 @@ import featurePlugin from './lib/feature-plugin';
import initialCssPlugin from './lib/initial-css-plugin'; import initialCssPlugin from './lib/initial-css-plugin';
import serviceWorkerPlugin from './lib/sw-plugin'; import serviceWorkerPlugin from './lib/sw-plugin';
import dataURLPlugin from './lib/data-url-plugin'; import dataURLPlugin from './lib/data-url-plugin';
import asTextPlugin from './lib/as-text-plugin';
import entryDataPlugin, { fileNameToURL } from './lib/entry-data-plugin'; import entryDataPlugin, { fileNameToURL } from './lib/entry-data-plugin';
import dedent from 'dedent'; import dedent from 'dedent';
@@ -89,6 +90,7 @@ export default async function ({ watch }) {
'codecs', 'codecs',
]), ]),
urlPlugin(), urlPlugin(),
asTextPlugin(),
dataURLPlugin(), dataURLPlugin(),
cssPlugin(), cssPlugin(),
]; ];

View File

@@ -11,11 +11,7 @@ export default class Checkbox extends Component<Props, State> {
return ( return (
<div class={style.checkbox}> <div class={style.checkbox}>
{props.checked ? ( {props.checked ? (
props.disabled ? ( <CheckedIcon class={`${style.icon} ${style.checked}`} />
<CheckedIcon class={`${style.icon} ${style.disabled}`} />
) : (
<CheckedIcon class={`${style.icon} ${style.checked}`} />
)
) : ( ) : (
<UncheckedIcon class={style.icon} /> <UncheckedIcon class={style.icon} />
)} )}

View File

@@ -20,7 +20,3 @@
.checked { .checked {
fill: var(--main-theme-color); fill: var(--main-theme-color);
} }
.disabled {
fill: var(--dark-gray);
}

View File

@@ -40,23 +40,24 @@ type PartialButNotUndefined<T> = {
[P in keyof T]: T[P]; [P in keyof T]: T[P];
}; };
const supportedEncoderMapP: Promise<PartialButNotUndefined<typeof encoderMap>> = const supportedEncoderMapP: Promise<PartialButNotUndefined<
(async () => { typeof encoderMap
const supportedEncoderMap: PartialButNotUndefined<typeof encoderMap> = { >> = (async () => {
...encoderMap, const supportedEncoderMap: PartialButNotUndefined<typeof encoderMap> = {
}; ...encoderMap,
};
// Filter out entries where the feature test fails // Filter out entries where the feature test fails
await Promise.all( await Promise.all(
Object.entries(encoderMap).map(async ([encoderName, details]) => { Object.entries(encoderMap).map(async ([encoderName, details]) => {
if ('featureTest' in details && !(await details.featureTest())) { if ('featureTest' in details && !(await details.featureTest())) {
delete supportedEncoderMap[encoderName as keyof typeof encoderMap]; delete supportedEncoderMap[encoderName as keyof typeof encoderMap];
} }
}), }),
); );
return supportedEncoderMap; return supportedEncoderMap;
})(); })();
export default class Options extends Component<Props, State> { export default class Options extends Component<Props, State> {
state: State = { state: State = {

View File

@@ -116,7 +116,7 @@ async function decodeImage(
// Otherwise fall through and try built-in decoding for a laugh. // Otherwise fall through and try built-in decoding for a laugh.
return await builtinDecode(signal, blob, mimeType); return await builtinDecode(signal, blob, mimeType);
} catch (err) { } catch (err) {
if (err instanceof Error && err.name === 'AbortError') throw err; if (err.name === 'AbortError') throw err;
console.log(err); console.log(err);
throw Error("Couldn't decode image"); 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'); open('https://github.com/GoogleChromeLabs/squoosh/tree/dev/cli');
} }
} catch (e) { } catch (e) {
this.props.showSnack(String(e)); this.props.showSnack(e);
} }
}; };
@@ -640,7 +640,7 @@ export default class Compress extends Component<Props, State> {
return { sides }; return { sides };
}); });
} catch (err) { } catch (err) {
if (err instanceof Error && err.name === 'AbortError') return; if (err.name === 'AbortError') return;
this.props.showSnack(`Source decoding error: ${err}`); this.props.showSnack(`Source decoding error: ${err}`);
throw err; throw err;
} }
@@ -698,7 +698,7 @@ export default class Compress extends Component<Props, State> {
return newState; return newState;
}); });
} catch (err) { } catch (err) {
if (err instanceof Error && err.name === 'AbortError') return; if (err.name === 'AbortError') return;
this.setState({ loading: false }); this.setState({ loading: false });
this.props.showSnack(`Preprocessing error: ${err}`); this.props.showSnack(`Preprocessing error: ${err}`);
throw err; throw err;
@@ -822,7 +822,7 @@ export default class Compress extends Component<Props, State> {
this.activeSideJobs[sideIndex] = undefined; this.activeSideJobs[sideIndex] = undefined;
} catch (err) { } catch (err) {
if (err instanceof Error && err.name === 'AbortError') return; if (err.name === 'AbortError') return;
this.setState((currentState) => { this.setState((currentState) => {
const sides = cleanMerge(currentState.sides, sideIndex, { const sides = cleanMerge(currentState.sides, sideIndex, {
loading: false, loading: false,

View File

@@ -30,7 +30,6 @@ interface State {
autoEdgePreservingFilter: boolean; autoEdgePreservingFilter: boolean;
decodingSpeedTier: number; decodingSpeedTier: number;
photonNoiseIso: number; photonNoiseIso: number;
alternativeLossy: boolean;
} }
export class Options extends Component<Props, State> { export class Options extends Component<Props, State> {
@@ -56,7 +55,6 @@ export class Options extends Component<Props, State> {
autoEdgePreservingFilter: options.epf === -1, autoEdgePreservingFilter: options.epf === -1,
decodingSpeedTier: options.decodingSpeedTier, decodingSpeedTier: options.decodingSpeedTier,
photonNoiseIso: options.photonNoiseIso, photonNoiseIso: options.photonNoiseIso,
alternativeLossy: options.lossyModular,
}; };
} }
@@ -98,7 +96,6 @@ export class Options extends Component<Props, State> {
lossyPalette: optionState.lossless ? optionState.slightLoss : false, lossyPalette: optionState.lossless ? optionState.slightLoss : false,
decodingSpeedTier: optionState.decodingSpeedTier, decodingSpeedTier: optionState.decodingSpeedTier,
photonNoiseIso: optionState.photonNoiseIso, photonNoiseIso: optionState.photonNoiseIso,
lossyModular: optionState.quality < 7 ? true : optionState.alternativeLossy,
}; };
// Updating options, so we don't recalculate in getDerivedStateFromProps. // Updating options, so we don't recalculate in getDerivedStateFromProps.
@@ -125,7 +122,6 @@ export class Options extends Component<Props, State> {
autoEdgePreservingFilter, autoEdgePreservingFilter,
decodingSpeedTier, decodingSpeedTier,
photonNoiseIso, photonNoiseIso,
alternativeLossy,
}: State, }: State,
) { ) {
// I'm rendering both lossy and lossless forms, as it becomes much easier when // I'm rendering both lossy and lossless forms, as it becomes much easier when
@@ -166,14 +162,6 @@ export class Options extends Component<Props, State> {
Quality: Quality:
</Range> </Range>
</div> </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}> <label class={style.optionToggle}>
Auto edge filter Auto edge filter
<Checkbox <Checkbox
@@ -235,7 +223,7 @@ export class Options extends Component<Props, State> {
</label> </label>
<div class={style.optionOneCell}> <div class={style.optionOneCell}>
<Range <Range
min="1" min="3"
max="9" max="9"
value={effort} value={effort}
onInput={this._inputChange('effort', 'number')} onInput={this._inputChange('effort', 'number')}

View File

@@ -25,5 +25,4 @@ export const defaultOptions: EncodeOptions = {
lossyPalette: false, lossyPalette: false,
decodingSpeedTier: 0, decodingSpeedTier: 0,
photonNoiseIso: 0, photonNoiseIso: 0,
lossyModular: false,
}; };

View File

@@ -14,11 +14,9 @@ import { EncodeOptions } from '../shared/meta';
import { threads } from 'wasm-feature-detect'; import { threads } from 'wasm-feature-detect';
async function initMT() { async function initMT() {
const { const { default: init, initThreadPool, optimise } = await import(
default: init, 'codecs/oxipng/pkg-parallel/squoosh_oxipng'
initThreadPool, );
optimise,
} = await import('codecs/oxipng/pkg-parallel/squoosh_oxipng');
await init(); await init();
await initThreadPool(navigator.hardwareConcurrency); await initThreadPool(navigator.hardwareConcurrency);
return optimise; return optimise;

View File

@@ -2,9 +2,9 @@ import * as styles from './styles.css';
import 'add-css:./styles.css'; import 'add-css:./styles.css';
// So it doesn't cause an error when running in node // So it doesn't cause an error when running in node
const HTMLEl = (__PRERENDER__ const HTMLEl = ((__PRERENDER__
? Object ? 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 * A simple spinner. This custom element has no JS API. Just put it in the document, and it'll

View File

@@ -2,9 +2,9 @@ import * as style from './styles.css';
import 'add-css:./styles.css'; import 'add-css:./styles.css';
// So it doesn't cause an error when running in node // So it doesn't cause an error when running in node
const HTMLEl = (__PRERENDER__ const HTMLEl = ((__PRERENDER__
? Object ? Object
: HTMLElement) as unknown as typeof HTMLElement; : HTMLElement) as unknown) as typeof HTMLElement;
export interface SnackOptions { export interface SnackOptions {
timeout?: number; timeout?: number;

View File

@@ -13,3 +13,24 @@
/// <reference path="../../missing-types.d.ts" /> /// <reference path="../../missing-types.d.ts" />
declare const __PRERENDER__: boolean; 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;
};

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 11 KiB

View File

@@ -14,7 +14,7 @@ import smallSectionAsset from 'url:./imgs/info-content/small.svg';
import simpleSectionAsset from 'url:./imgs/info-content/simple.svg'; import simpleSectionAsset from 'url:./imgs/info-content/simple.svg';
import secureSectionAsset from 'url:./imgs/info-content/secure.svg'; import secureSectionAsset from 'url:./imgs/info-content/secure.svg';
import logoIcon from 'url:./imgs/demos/icon-demo-logo.png'; import logoIcon from 'url:./imgs/demos/icon-demo-logo.png';
import logoWithText from 'data-url-text:./imgs/logo-with-text.svg'; import logoSVGSourceImport from 'as-text:./logo-svg-include.txt';
import * as style from './style.css'; import * as style from './style.css';
import type SnackBarElement from 'shared/custom-els/snack-bar'; import type SnackBarElement from 'shared/custom-els/snack-bar';
import 'shared/custom-els/snack-bar'; import 'shared/custom-els/snack-bar';
@@ -69,6 +69,12 @@ async function getImageClipboardItem(
} }
} }
// The logo SVG source is pretty big, so to avoid it existing in both the HTML
// and the JS bundle, we pick it up from the HTML.
const logoSVGSource = __PRERENDER__
? logoSVGSourceImport
: document.querySelector('.' + style.logoContainer)!.innerHTML;
interface Props { interface Props {
onFile?: (file: File) => void; onFile?: (file: File) => void;
showSnack?: SnackBarElement['showSnackbar']; showSnack?: SnackBarElement['showSnackbar'];
@@ -240,15 +246,10 @@ export default class Intro extends Component<Props, State> {
class={style.blobCanvas} class={style.blobCanvas}
/> />
)} )}
<h1 class={style.logoContainer}> <h1
<img class={style.logoContainer}
class={style.logo} dangerouslySetInnerHTML={{ __html: logoSVGSource }}
src={logoWithText} />
alt="Squoosh"
width="539"
height="162"
/>
</h1>
<div class={style.loadImg}> <div class={style.loadImg}>
{showBlobSVG && ( {showBlobSVG && (
<svg <svg

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 8.9 KiB

View File

@@ -30,6 +30,11 @@ interface WindowEventMap {
beforeinstallprompt: BeforeInstallPromptEvent; beforeinstallprompt: BeforeInstallPromptEvent;
} }
interface ClipboardItem {
types: string[];
getType(type: string): Promise<Blob>;
}
interface Clipboard { interface Clipboard {
read(): Promise<ClipboardItem[]>; read(): Promise<ClipboardItem[]>;
} }

View File

@@ -1,3 +1,11 @@
/* Just the glyphs needed for the Squoosh logo */
@font-face {
font-family: logofont;
font-weight: 700;
src: url(data:font/woff;base64,d09GMgABAAAAAASoAA4AAAAACOQAAARUAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGhYbgnYcgXAGYABkEQwKhHiEFgsUAAE2AiQDJAQgBYJaByAbeQfIxId/N/1zb0JJk7qwVQyoSyhM6qJf2zN3wnP5MyX/c6mabKKFAVwk4QDd+3f7Z41FoYvttryoVK6NsWls0wJjfeO38YjNiCJjtHr/1Q8CwAqDCAUBr2QweT2PEoyA1elzSuDRPDnUg8D2odZuRPU0jvQhDaxz5rMh0dmYGFMJs4nu1qE+eGjM/weALmNBwUEBOxTgRXxFMYpg//e8Ci0oLAD5Z/l7jALyz0eIk0p5wwIKMGmoUVDk+I2Voc2UQOpf+V8SHykzsc2YglhhpAxij4qYCCDLLiZGpIxaxGLgdEfA8VXagNHBPOEGN4kdxIwSYCOPFjwtuDxUnqS+IGdGuWtrAgUsQYZRHpDu7Qiw6ukb7cWFrWzAQoFsxEIZPaFS7IAQDQ4cvEx4DjEL+W8XY9w93bi6CVjaTB8XOUO3aIVhv7jXI3UoIVGDVOAYRkFZmv6lSiyebcjPN+BqWJ91Zp43fwUwPxAfFchViYiY6etaTAWH6kKIhE7SgEaAL0DMDnZmf6FCMTrQj0EMY1SW726Rv5Tvki/Jp/KJfCwf5XNoQXWWGi/LsNXQcgvxSnnJ8wFi43KUbaZAdno0JKEudnYudkHOvy6ZysqvkYTtt8jiu2VxJhNZfP99YVuKLLnyTX7rdSy8cT5WkrBgNPL1AkqEuyzOB+WZxXf5LSMoLzmnXHS9/9b7ZNHk7wAjFqQ3hMZy/nbFtQXbNAIRWP4jQ8kUVX7FG8L2Y4VH4/QvOjyltORefuthLJSWBnyUZCKMQBfeEbbfP3h5MvqPEuA12/1Or4a5yB8MYpzmv+DgZ3O9ntK5NjZdTEis7owRG/urcsYir+4JU2+cUdUY36zxbeoo1RsaBsJTkP7a8gPKCq64OCyytqmvKXVZE5mtjskqTmWW8Y3ttF43lZujm57W5+dN63XTObm6qWl9XsDErwGiVhMg/hoY+GugqNEE6n4NxH280sBFFITFZA/oMqby8zKmB3TZMfnqDC5tyrRUm/F7gKhWB4i/Bfj/FiCq1QHi7/643nboYs9I1K/XB/n/4eH+8COPf1aYl6yOya4KiL8ypq8/Qso6O+HoL9pfsL/okJObGJlwoSkkBZds6wfb4pYDYzxCEjIL09ll83QG11IUGgUAAJrLVRQvuOTOlNTbpvzOCcwPZllp+cGK/bUffKT+wRxg/trKyDwPAmVzJTtUmnnR/Ca2bGU0B5hvtjI2u3ZLmoci/IQP0Fz40ipk0Hb402H4k7/hScuRQrJj7rXEg+BR85QaWsDzADqVUNUxBLbRYp0JnCMELkwBnsiOEWgYqDGjYaHCzRoFPPDyyy3gg68goh8DmMQQOtGODoxAhShEIBKx9DgD+tGPdvSgFSrkIAcitEolEz3oIVeRDxy+4lvVSiuGMEbLtUDr97BiNKIPw8hCvzLeYjOefMW4mq5hUSguFWNZnL3D6EQ/+tLPa3ktEYgO08G8O9bbQgkWAA==)
format('woff2');
}
.intro { .intro {
composes: abs-fill from global; composes: abs-fill from global;
-webkit-overflow-scrolling: touch; -webkit-overflow-scrolling: touch;
@@ -35,12 +43,12 @@
.logo-container { .logo-container {
margin: 5rem 0 1rem; margin: 5rem 0 1rem;
}
.logo { & svg {
transform: translate(-1%, 0); transform: translate(-1%, 0);
width: 189px; width: 189px;
height: auto; height: auto;
}
} }
.load-img { .load-img {

View File

@@ -57,14 +57,17 @@ const Index: FunctionalComponent<Props> = () => (
<meta name="mobile-web-app-capable" content="yes" /> <meta name="mobile-web-app-capable" content="yes" />
<meta name="apple-mobile-web-app-capable" content="yes" /> <meta name="apple-mobile-web-app-capable" content="yes" />
<link rel="shortcut icon" href={favicon} /> <link rel="shortcut icon" href={favicon} />
<link rel="apple-touch-icon" href={ogImage} />
<meta name="theme-color" content="#ff3385" /> <meta name="theme-color" content="#ff3385" />
<link rel="manifest" href="/manifest.json" /> <link rel="manifest" href="/manifest.json" />
<link rel="canonical" href={siteOrigin} /> <link rel="canonical" href={siteOrigin} />
<style <style
dangerouslySetInnerHTML={{ __html: escapeStyleScriptContent(baseCss) }} dangerouslySetInnerHTML={{ __html: escapeStyleScriptContent(baseCss) }}
/> />
<link rel="stylesheet" href={initialCss} /> <style
dangerouslySetInnerHTML={{
__html: escapeStyleScriptContent(initialCss),
}}
/>
</head> </head>
<body> <body>
<div id="app"> <div id="app">

View File

@@ -82,20 +82,24 @@ initialJs = subtractSets(
export const initial = ['/', ...initialJs]; export const initial = ['/', ...initialJs];
export const theRest = (async () => { export const theRest = (async () => {
const [supportsThreads, supportsSimd, supportsWebP, supportsAvif] = const [
await Promise.all([ supportsThreads,
threads(), supportsSimd,
simd(), supportsWebP,
...[webpDataUrl, avifDataUrl].map(async (dataUrl) => { supportsAvif,
if (!self.createImageBitmap) return false; ] = await Promise.all([
const response = await fetch(dataUrl); threads(),
const blob = await response.blob(); simd(),
return createImageBitmap(blob).then( ...[webpDataUrl, avifDataUrl].map(async (dataUrl) => {
() => true, if (!self.createImageBitmap) return false;
() => false, const response = await fetch(dataUrl);
); const blob = await response.blob();
}), return createImageBitmap(blob).then(
]); () => true,
() => false,
);
}),
]);
const items: string[] = []; const items: string[] = [];