From 21faf0b6fb4b536ea7c8a35e04b2d66784c47a55 Mon Sep 17 00:00:00 2001 From: Mitchell Hashimoto Date: Sat, 3 Dec 2022 21:46:00 -0800 Subject: [PATCH 01/14] add zig-js --- .gitmodules | 3 +++ build.zig | 6 ++++++ vendor/zig-js | 1 + 3 files changed, 10 insertions(+) create mode 160000 vendor/zig-js diff --git a/.gitmodules b/.gitmodules index 7250a6c86..4b66a803a 100644 --- a/.gitmodules +++ b/.gitmodules @@ -34,3 +34,6 @@ [submodule "vendor/pixman"] path = vendor/pixman url = https://github.com/freedesktop/pixman.git +[submodule "vendor/zig-js"] + path = vendor/zig-js + url = https://github.com/mitchellh/zig-js.git diff --git a/build.zig b/build.zig index 7232f1d88..207acfa06 100644 --- a/build.zig +++ b/build.zig @@ -7,6 +7,7 @@ const fontconfig = @import("pkg/fontconfig/build.zig"); const freetype = @import("pkg/freetype/build.zig"); const harfbuzz = @import("pkg/harfbuzz/build.zig"); const imgui = @import("pkg/imgui/build.zig"); +const js = @import("vendor/zig-js/build.zig"); const libxml2 = @import("vendor/zig-libxml2/libxml2.zig"); const libuv = @import("pkg/libuv/build.zig"); const libpng = @import("pkg/libpng/build.zig"); @@ -235,6 +236,11 @@ fn addDeps( _ = try macos.link(b, step, .{}); } + // Wasm + if (step.target.getCpuArch() == .wasm32) { + step.addPackage(js.pkg); + } + // We always statically compile glad step.addIncludePath("vendor/glad/include/"); step.addCSourceFile("vendor/glad/src/gl.c", &.{}); diff --git a/vendor/zig-js b/vendor/zig-js new file mode 160000 index 000000000..a6d0b5a0c --- /dev/null +++ b/vendor/zig-js @@ -0,0 +1 @@ +Subproject commit a6d0b5a0c421925409f1bce542f64b9e5f6b96df From 940828ed974b1497dc5cdb411ef175f4c6dba74b Mon Sep 17 00:00:00 2001 From: Mitchell Hashimoto Date: Sat, 3 Dec 2022 22:11:01 -0800 Subject: [PATCH 02/14] font: web canvas creates a canvas element --- build.zig | 1 + src/font/face.zig | 6 +-- src/font/face/web_canvas.zig | 90 +++++++++++++++++++++++++++++++++++- src/font/main.zig | 2 + 4 files changed, 95 insertions(+), 4 deletions(-) diff --git a/build.zig b/build.zig index 207acfa06..25df881bf 100644 --- a/build.zig +++ b/build.zig @@ -122,6 +122,7 @@ pub fn build(b: *std.build.Builder) !void { wasm.setOutputDir("zig-out"); // Wasm-specific deps + wasm.addPackage(js.pkg); wasm.addPackage(tracylib.pkg); wasm.addPackage(utf8proc.pkg); _ = try utf8proc.link(b, wasm); diff --git a/src/font/face.zig b/src/font/face.zig index 3986d7aa9..22fec7eeb 100644 --- a/src/font/face.zig +++ b/src/font/face.zig @@ -1,8 +1,8 @@ const builtin = @import("builtin"); const options = @import("main.zig").options; -const freetype = @import("face/freetype.zig"); -const coretext = @import("face/coretext.zig"); -const web_canvas = @import("face/web_canvas.zig"); +pub const freetype = @import("face/freetype.zig"); +pub const coretext = @import("face/coretext.zig"); +pub const web_canvas = @import("face/web_canvas.zig"); /// Face implementation for the compile options. pub const Face = switch (options.backend) { diff --git a/src/font/face/web_canvas.zig b/src/font/face/web_canvas.zig index a2969ef68..9710c810e 100644 --- a/src/font/face/web_canvas.zig +++ b/src/font/face/web_canvas.zig @@ -1,11 +1,99 @@ const std = @import("std"); const builtin = @import("builtin"); const assert = std.debug.assert; +const testing = std.testing; const Allocator = std.mem.Allocator; +const js = @import("zig-js"); const font = @import("../main.zig"); const log = std.log.scoped(.font_face); pub const Face = struct { - // TODO + /// The web canvas face makes use of an allocator when interacting + /// with the JS environment. + alloc: Allocator, + + /// The CSS "font" attribute, excluding size. + font_str: []const u8, + + /// The size we currently have set. + size: font.face.DesiredSize, + + /// The presentation for this font. This is a heuristic since fonts don't have + /// a way to declare this. We just assume a font with color is an emoji font. + presentation: font.Presentation, + + /// Metrics for this font face. These are useful for renderers. + metrics: font.face.Metrics, + + /// The canvas element that we will reuse to render glyphs + canvas: js.Object, + + /// Initialize a web canvas font with a "raw" value. The "raw" value can + /// be any valid value for a CSS "font" property EXCLUDING the size. The + /// size is always added via the `size` parameter. + /// + /// The raw value is copied so the caller can free it after it is gone. + pub fn initNamed( + alloc: Allocator, + raw: []const u8, + size: font.face.DesiredSize, + ) !Face { + // Copy our font string because we're going to have to reuse it. + const font_str = try alloc.dupe(u8, raw); + errdefer alloc.free(font_str); + + // Create our canvas that we're going to continue to reuse. + const doc = try js.global.get(js.Object, "document"); + defer doc.deinit(); + const canvas = try doc.call(js.Object, "createElement", .{js.string("canvas")}); + errdefer canvas.deinit(); + + return Face{ + .alloc = alloc, + .font_str = font_str, + .size = size, + + .canvas = canvas, + + // TODO: real metrics + .metrics = undefined, + + // TODO: figure out how we're going to do emoji with web canvas + .presentation = .text, + }; + } + + pub fn deinit(self: *Face) void { + self.alloc.free(self.font_str); + self.canvas.deinit(); + self.* = undefined; + } +}; + +/// The wasm-compatible API. +pub const Wasm = struct { + const wasm = @import("../../wasm.zig"); + const alloc = wasm.alloc; + + export fn face_new(ptr: [*]const u8, len: usize, pts: u16) ?*Face { + return face_new_(ptr, len, pts) catch null; + } + + fn face_new_(ptr: [*]const u8, len: usize, pts: u16) !*Face { + var face = try Face.initNamed(alloc, ptr[0..len], .{ .points = pts }); + errdefer face.deinit(); + + var result = try alloc.create(Face); + errdefer alloc.destroy(result); + result.* = face; + return result; + } + + export fn face_free(ptr: ?*Face) void { + if (ptr) |v| { + v.deinit(); + alloc.destroy(v); + } + } }; diff --git a/src/font/main.zig b/src/font/main.zig index 4226f732c..10c63d49f 100644 --- a/src/font/main.zig +++ b/src/font/main.zig @@ -17,8 +17,10 @@ pub const Sprite = sprite.Sprite; pub const Descriptor = discovery.Descriptor; pub const Discover = discovery.Discover; +/// If we're targeting wasm then we export some wasm APIs. pub usingnamespace if (builtin.target.isWasm()) struct { pub usingnamespace Atlas.Wasm; + pub usingnamespace face.web_canvas.Wasm; } else struct {}; /// Build options From 437f1772f173abfa690072d9d4f9e8fbd3625996 Mon Sep 17 00:00:00 2001 From: Mitchell Hashimoto Date: Sun, 4 Dec 2022 12:29:11 -0800 Subject: [PATCH 03/14] logging works for wasm --- build.zig | 1 + src/font/Atlas.zig | 2 +- src/font/face/web_canvas.zig | 2 +- src/main_wasm.zig | 3 ++- src/{ => os}/wasm.zig | 0 src/os/wasm/log.zig | 27 +++++++++++++++++++++++++++ 6 files changed, 32 insertions(+), 3 deletions(-) rename src/{ => os}/wasm.zig (100%) create mode 100644 src/os/wasm/log.zig diff --git a/build.zig b/build.zig index 25df881bf..fadf1539b 100644 --- a/build.zig +++ b/build.zig @@ -137,6 +137,7 @@ pub fn build(b: *std.build.Builder) !void { const main_test = b.addTest("src/main_wasm.zig"); main_test.setTarget(.{ .cpu_arch = .wasm32, .os_tag = .wasi }); main_test.addOptions("build_options", exe_options); + main_test.addPackage(js.pkg); test_step.dependOn(&main_test.step); } diff --git a/src/font/Atlas.zig b/src/font/Atlas.zig index 4259d5dda..a48edb966 100644 --- a/src/font/Atlas.zig +++ b/src/font/Atlas.zig @@ -307,7 +307,7 @@ pub fn clear(self: *Atlas) void { pub const Wasm = struct { // If you're copying this file (Atlas.zig) out to a separate project, // just replace this with the allocator you want to use. - const wasm = @import("../wasm.zig"); + const wasm = @import("../os/wasm.zig"); const alloc = wasm.alloc; export fn atlas_new(size: u32, format: u8) ?*Atlas { diff --git a/src/font/face/web_canvas.zig b/src/font/face/web_canvas.zig index 9710c810e..13d0252e8 100644 --- a/src/font/face/web_canvas.zig +++ b/src/font/face/web_canvas.zig @@ -73,7 +73,7 @@ pub const Face = struct { /// The wasm-compatible API. pub const Wasm = struct { - const wasm = @import("../../wasm.zig"); + const wasm = @import("../../os/wasm.zig"); const alloc = wasm.alloc; export fn face_new(ptr: [*]const u8, len: usize, pts: u16) ?*Face { diff --git a/src/main_wasm.zig b/src/main_wasm.zig index 5c4bdbf45..81f8265d8 100644 --- a/src/main_wasm.zig +++ b/src/main_wasm.zig @@ -1,5 +1,6 @@ // This is the main file for the WASM module. The WASM module has to // export a C ABI compatible API. -pub usingnamespace @import("wasm.zig"); +pub usingnamespace @import("os/wasm.zig"); +pub usingnamespace @import("os/wasm/log.zig"); pub usingnamespace @import("font/main.zig"); diff --git a/src/wasm.zig b/src/os/wasm.zig similarity index 100% rename from src/wasm.zig rename to src/os/wasm.zig diff --git a/src/os/wasm/log.zig b/src/os/wasm/log.zig new file mode 100644 index 000000000..b1957d05a --- /dev/null +++ b/src/os/wasm/log.zig @@ -0,0 +1,27 @@ +const std = @import("std"); +const builtin = @import("builtin"); +const wasm = @import("../wasm.zig"); + +// The function std.log will call. +pub fn log( + comptime level: std.log.Level, + comptime scope: @TypeOf(.EnumLiteral), + comptime format: []const u8, + args: anytype, +) void { + // Build the string + const level_txt = comptime level.asText(); + const prefix = if (scope == .default) ": " else "(" ++ @tagName(scope) ++ "): "; + const txt = level_txt ++ prefix ++ format; + const str = nosuspend std.fmt.allocPrint(wasm.alloc, txt, args) catch return; + defer wasm.alloc.free(str); + + // Send it over to the JS side + JS.log(str.ptr, str.len); +} + +// We wrap our externs in this namespace so we can reuse symbols, otherwise +// "log" would collide. +const JS = struct { + extern "env" fn log(ptr: [*]const u8, len: usize) void; +}; From c48d8cd151e019db787e5a67b6e63d47ae73af04 Mon Sep 17 00:00:00 2001 From: Mitchell Hashimoto Date: Sun, 4 Dec 2022 13:16:54 -0800 Subject: [PATCH 04/14] hook up logging to wasm, example uses new zig-js package --- example/.gitignore | 4 + example/app.ts | 49 + example/index.html | 45 +- example/package-lock.json | 4436 ++++++++++++++++++++++++++++++++++ example/package.json | 22 + src/font/face/web_canvas.zig | 2 + src/main_wasm.zig | 11 + src/os/wasm.zig | 24 +- vendor/zig-js | 2 +- 9 files changed, 4547 insertions(+), 48 deletions(-) create mode 100644 example/.gitignore create mode 100644 example/app.ts create mode 100644 example/package-lock.json create mode 100644 example/package.json diff --git a/example/.gitignore b/example/.gitignore new file mode 100644 index 000000000..3fa248f4c --- /dev/null +++ b/example/.gitignore @@ -0,0 +1,4 @@ +.parcel-cache/ +dist/ +node_modules/ +example.wasm* diff --git a/example/app.ts b/example/app.ts new file mode 100644 index 000000000..aac4e7b26 --- /dev/null +++ b/example/app.ts @@ -0,0 +1,49 @@ +import { ZigJS } from 'zig-js'; + +const zjs = new ZigJS(); +const importObject = { + module: {}, + env: { + log: (ptr: number, len: number) => { + const view = new DataView(zjs.memory.buffer, ptr, Number(len)); + const str = new TextDecoder('utf-8').decode(view); + console.log(str); + }, + }, + + ...zjs.importObject(), +}; + +const url = new URL('ghostty-wasm.wasm', import.meta.url); +fetch(url.href).then(response => + response.arrayBuffer() +).then(bytes => + WebAssembly.instantiate(bytes, importObject) +).then(results => { + const { + memory, + malloc, + free, + face_new, + face_free, + } = results.instance.exports; + // Give us access to the zjs value for debugging. + globalThis.zjs = zjs; + console.log(zjs); + + // Initialize our zig-js memory + zjs.memory = memory; + + // Create some memory for our string + const font = new TextEncoder().encode("monospace"); + const font_ptr = malloc(font.byteLength); + try { + new Uint8Array(memory.buffer, font_ptr).set(font); + + // Call whatever example you want: + const face = face_new(font_ptr, font.byteLength); + face_free(face); + } finally { + free(font_ptr); + } +}); diff --git a/example/index.html b/example/index.html index 24acd9527..0866d6256 100644 --- a/example/index.html +++ b/example/index.html @@ -1,36 +1,11 @@ - - - - - WASM Example - - - - + + + + + Ghostty Example + + + + Open your console, we are just debugging here. + diff --git a/example/package-lock.json b/example/package-lock.json new file mode 100644 index 000000000..3cb4de6f0 --- /dev/null +++ b/example/package-lock.json @@ -0,0 +1,4436 @@ +{ + "name": "ghostty example", + "version": "0.1.0", + "lockfileVersion": 2, + "requires": true, + "packages": { + "": { + "name": "ghostty example", + "version": "0.1.0", + "license": "MIT", + "dependencies": { + "zig-js": "file:../vendor/zig-js/js" + }, + "devDependencies": { + "@parcel/transformer-inline-string": "^2.8.0", + "parcel": "^2.8.0", + "typescript": "^4.9.3" + } + }, + "../js": { + "extraneous": true + }, + "../vendor/zig-js/js": { + "name": "zig-js-glue", + "version": "0.1.2", + "license": "MIT", + "devDependencies": { + "@parcel/packager-ts": "^2.8.0", + "@parcel/transformer-typescript-types": "^2.8.0", + "@types/jest": "^29.2.3", + "jest": "^29.3.1", + "parcel": "^2.8.0", + "ts-jest": "^29.0.3", + "typescript": "^4.9.3" + } + }, + "node_modules/@babel/code-frame": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.18.6.tgz", + "integrity": "sha512-TDCmlK5eOvH+eH7cdAFlNXeVJqWIQ7gW9tY1GJIpUtFb6CmjVyq2VM3u71bOyR8CRihcCgMUYoDNyLXao3+70Q==", + "dev": true, + "dependencies": { + "@babel/highlight": "^7.18.6" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-validator-identifier": { + "version": "7.19.1", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.19.1.tgz", + "integrity": "sha512-awrNfaMtnHUr653GgGEs++LlAvW6w+DcPrOliSMXWCKo597CwL5Acf/wWdNkf/tfEQE3mjkeD1YOVZOUV/od1w==", + "dev": true, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/highlight": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.18.6.tgz", + "integrity": "sha512-u7stbOuYjaPezCuLj29hNW1v64M2Md2qupEKP1fHc7WdOA3DgLh37suiSrZYY7haUB7iBeQZ9P1uiRF359do3g==", + "dev": true, + "dependencies": { + "@babel/helper-validator-identifier": "^7.18.6", + "chalk": "^2.0.0", + "js-tokens": "^4.0.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/highlight/node_modules/ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "dependencies": { + "color-convert": "^1.9.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/@babel/highlight/node_modules/chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, + "dependencies": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/@babel/highlight/node_modules/color-convert": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "dev": true, + "dependencies": { + "color-name": "1.1.3" + } + }, + "node_modules/@babel/highlight/node_modules/color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==", + "dev": true + }, + "node_modules/@babel/highlight/node_modules/has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/@babel/highlight/node_modules/supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "dependencies": { + "has-flag": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/@jridgewell/gen-mapping": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.2.tgz", + "integrity": "sha512-mh65xKQAzI6iBcFzwv28KVWSmCkdRBWoOh+bYQGW3+6OZvbbN3TqMGo5hqYxQniRcH9F2VZIoJCm4pa3BPDK/A==", + "dev": true, + "dependencies": { + "@jridgewell/set-array": "^1.0.1", + "@jridgewell/sourcemap-codec": "^1.4.10", + "@jridgewell/trace-mapping": "^0.3.9" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/resolve-uri": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.0.tgz", + "integrity": "sha512-F2msla3tad+Mfht5cJq7LSXcdudKTWCVYUgw6pLFOOHSTtZlj6SWNYAp+AhuqLmWdBO2X5hPrLcu8cVP8fy28w==", + "dev": true, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/set-array": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.1.2.tgz", + "integrity": "sha512-xnkseuNADM0gt2bs+BvhO0p78Mk762YnZdsuzFV018NoG1Sj1SCQvpSqa7XUaTam5vAGasABV9qXASMKnFMwMw==", + "dev": true, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/source-map": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/@jridgewell/source-map/-/source-map-0.3.2.tgz", + "integrity": "sha512-m7O9o2uR8k2ObDysZYzdfhb08VuEml5oWGiosa1VdaPZ/A6QyPkAJuwN0Q1lhULOf6B7MtQmHENS743hWtCrgw==", + "dev": true, + "dependencies": { + "@jridgewell/gen-mapping": "^0.3.0", + "@jridgewell/trace-mapping": "^0.3.9" + } + }, + "node_modules/@jridgewell/sourcemap-codec": { + "version": "1.4.14", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.14.tgz", + "integrity": "sha512-XPSJHWmi394fuUuzDnGz1wiKqWfo1yXecHQMRf2l6hztTO+nPru658AyDngaBe7isIxEkRsPR3FZh+s7iVa4Uw==", + "dev": true + }, + "node_modules/@jridgewell/trace-mapping": { + "version": "0.3.17", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.17.tgz", + "integrity": "sha512-MCNzAp77qzKca9+W/+I0+sEpaUnZoeasnghNeVc41VZCEKaCH73Vq3BZZ/SzWIgrqE4H4ceI+p+b6C0mHf9T4g==", + "dev": true, + "dependencies": { + "@jridgewell/resolve-uri": "3.1.0", + "@jridgewell/sourcemap-codec": "1.4.14" + } + }, + "node_modules/@lezer/common": { + "version": "0.15.12", + "resolved": "https://registry.npmjs.org/@lezer/common/-/common-0.15.12.tgz", + "integrity": "sha512-edfwCxNLnzq5pBA/yaIhwJ3U3Kz8VAUOTRg0hhxaizaI1N+qxV7EXDv/kLCkLeq2RzSFvxexlaj5Mzfn2kY0Ig==", + "dev": true + }, + "node_modules/@lezer/lr": { + "version": "0.15.8", + "resolved": "https://registry.npmjs.org/@lezer/lr/-/lr-0.15.8.tgz", + "integrity": "sha512-bM6oE6VQZ6hIFxDNKk8bKPa14hqFrV07J/vHGOeiAbJReIaQXmkVb6xQu4MR+JBTLa5arGRyAAjJe1qaQt3Uvg==", + "dev": true, + "dependencies": { + "@lezer/common": "^0.15.0" + } + }, + "node_modules/@lmdb/lmdb-darwin-arm64": { + "version": "2.5.2", + "resolved": "https://registry.npmjs.org/@lmdb/lmdb-darwin-arm64/-/lmdb-darwin-arm64-2.5.2.tgz", + "integrity": "sha512-+F8ioQIUN68B4UFiIBYu0QQvgb9FmlKw2ctQMSBfW2QBrZIxz9vD9jCGqTCPqZBRbPHAS/vG1zSXnKqnS2ch/A==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@lmdb/lmdb-darwin-x64": { + "version": "2.5.2", + "resolved": "https://registry.npmjs.org/@lmdb/lmdb-darwin-x64/-/lmdb-darwin-x64-2.5.2.tgz", + "integrity": "sha512-KvPH56KRLLx4KSfKBx0m1r7GGGUMXm0jrKmNE7plbHlesZMuPJICtn07HYgQhj1LNsK7Yqwuvnqh1QxhJnF1EA==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@lmdb/lmdb-linux-arm": { + "version": "2.5.2", + "resolved": "https://registry.npmjs.org/@lmdb/lmdb-linux-arm/-/lmdb-linux-arm-2.5.2.tgz", + "integrity": "sha512-5kQAP21hAkfW5Bl+e0P57dV4dGYnkNIpR7f/GAh6QHlgXx+vp/teVj4PGRZaKAvt0GX6++N6hF8NnGElLDuIDw==", + "cpu": [ + "arm" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@lmdb/lmdb-linux-arm64": { + "version": "2.5.2", + "resolved": "https://registry.npmjs.org/@lmdb/lmdb-linux-arm64/-/lmdb-linux-arm64-2.5.2.tgz", + "integrity": "sha512-aLl89VHL/wjhievEOlPocoefUyWdvzVrcQ/MHQYZm2JfV1jUsrbr/ZfkPPUFvZBf+VSE+Q0clWs9l29PCX1hTQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@lmdb/lmdb-linux-x64": { + "version": "2.5.2", + "resolved": "https://registry.npmjs.org/@lmdb/lmdb-linux-x64/-/lmdb-linux-x64-2.5.2.tgz", + "integrity": "sha512-xUdUfwDJLGjOUPH3BuPBt0NlIrR7f/QHKgu3GZIXswMMIihAekj2i97oI0iWG5Bok/b+OBjHPfa8IU9velnP/Q==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@lmdb/lmdb-win32-x64": { + "version": "2.5.2", + "resolved": "https://registry.npmjs.org/@lmdb/lmdb-win32-x64/-/lmdb-win32-x64-2.5.2.tgz", + "integrity": "sha512-zrBczSbXKxEyK2ijtbRdICDygRqWSRPpZMN5dD1T8VMEW5RIhIbwFWw2phDRXuBQdVDpSjalCIUMWMV2h3JaZA==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@mischnic/json-sourcemap": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/@mischnic/json-sourcemap/-/json-sourcemap-0.1.0.tgz", + "integrity": "sha512-dQb3QnfNqmQNYA4nFSN/uLaByIic58gOXq4Y4XqLOWmOrw73KmJPt/HLyG0wvn1bnR6mBKs/Uwvkh+Hns1T0XA==", + "dev": true, + "dependencies": { + "@lezer/common": "^0.15.7", + "@lezer/lr": "^0.15.4", + "json5": "^2.2.1" + }, + "engines": { + "node": ">=12.0.0" + } + }, + "node_modules/@msgpackr-extract/msgpackr-extract-darwin-arm64": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/@msgpackr-extract/msgpackr-extract-darwin-arm64/-/msgpackr-extract-darwin-arm64-2.2.0.tgz", + "integrity": "sha512-Z9LFPzfoJi4mflGWV+rv7o7ZbMU5oAU9VmzCgL240KnqDW65Y2HFCT3MW06/ITJSnbVLacmcEJA8phywK7JinQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@msgpackr-extract/msgpackr-extract-darwin-x64": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/@msgpackr-extract/msgpackr-extract-darwin-x64/-/msgpackr-extract-darwin-x64-2.2.0.tgz", + "integrity": "sha512-vq0tT8sjZsy4JdSqmadWVw6f66UXqUCabLmUVHZwUFzMgtgoIIQjT4VVRHKvlof3P/dMCkbMJ5hB1oJ9OWHaaw==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@msgpackr-extract/msgpackr-extract-linux-arm": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/@msgpackr-extract/msgpackr-extract-linux-arm/-/msgpackr-extract-linux-arm-2.2.0.tgz", + "integrity": "sha512-SaJ3Qq4lX9Syd2xEo9u3qPxi/OB+5JO/ngJKK97XDpa1C587H9EWYO6KD8995DAjSinWvdHKRrCOXVUC5fvGOg==", + "cpu": [ + "arm" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@msgpackr-extract/msgpackr-extract-linux-arm64": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/@msgpackr-extract/msgpackr-extract-linux-arm64/-/msgpackr-extract-linux-arm64-2.2.0.tgz", + "integrity": "sha512-hlxxLdRmPyq16QCutUtP8Tm6RDWcyaLsRssaHROatgnkOxdleMTgetf9JsdncL8vLh7FVy/RN9i3XR5dnb9cRA==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@msgpackr-extract/msgpackr-extract-linux-x64": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/@msgpackr-extract/msgpackr-extract-linux-x64/-/msgpackr-extract-linux-x64-2.2.0.tgz", + "integrity": "sha512-94y5PJrSOqUNcFKmOl7z319FelCLAE0rz/jPCWS+UtdMZvpa4jrQd+cJPQCLp2Fes1yAW/YUQj/Di6YVT3c3Iw==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@msgpackr-extract/msgpackr-extract-win32-x64": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/@msgpackr-extract/msgpackr-extract-win32-x64/-/msgpackr-extract-win32-x64-2.2.0.tgz", + "integrity": "sha512-XrC0JzsqQSvOyM3t04FMLO6z5gCuhPE6k4FXuLK5xf52ZbdvcFe1yBmo7meCew9B8G2f0T9iu9t3kfTYRYROgA==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@parcel/bundler-default": { + "version": "2.8.0", + "resolved": "https://registry.npmjs.org/@parcel/bundler-default/-/bundler-default-2.8.0.tgz", + "integrity": "sha512-OvDDhxX4LwfGe7lYVMbJMzqNcDk8ydOqNw0Hra9WPgl0m5gju/eVIbDvot3JXp5F96FmV36uCxdODJhKTNoAzQ==", + "dev": true, + "dependencies": { + "@parcel/diagnostic": "2.8.0", + "@parcel/graph": "2.8.0", + "@parcel/hash": "2.8.0", + "@parcel/plugin": "2.8.0", + "@parcel/utils": "2.8.0", + "nullthrows": "^1.1.1" + }, + "engines": { + "node": ">= 12.0.0", + "parcel": "^2.8.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/cache": { + "version": "2.8.0", + "resolved": "https://registry.npmjs.org/@parcel/cache/-/cache-2.8.0.tgz", + "integrity": "sha512-k945hrafMDR2wyCKyZYgwypeLLuZWce6FzhgunI4taBUeVnNCcpFAWzbfOVQ39SqZTGDqG3MNT+VuehssHXxyg==", + "dev": true, + "dependencies": { + "@parcel/fs": "2.8.0", + "@parcel/logger": "2.8.0", + "@parcel/utils": "2.8.0", + "lmdb": "2.5.2" + }, + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + }, + "peerDependencies": { + "@parcel/core": "^2.8.0" + } + }, + "node_modules/@parcel/codeframe": { + "version": "2.8.0", + "resolved": "https://registry.npmjs.org/@parcel/codeframe/-/codeframe-2.8.0.tgz", + "integrity": "sha512-821d+KVcpEvJNMj9WMC39xXZK6zvRS/HUjQag2f3DkcRcZwk1uXJZdW6p1EB7C3e4e/0KSK3NTSVGEvbOSR+9w==", + "dev": true, + "dependencies": { + "chalk": "^4.1.0" + }, + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/compressor-raw": { + "version": "2.8.0", + "resolved": "https://registry.npmjs.org/@parcel/compressor-raw/-/compressor-raw-2.8.0.tgz", + "integrity": "sha512-tM49t0gDQnwJbrDCeoCn9LRc8inZ/TSPQTttJTfcmFHHFqEllI0ZDVG0AiQw5NOMQbBLYiKun1adXn8pkcPLEA==", + "dev": true, + "dependencies": { + "@parcel/plugin": "2.8.0" + }, + "engines": { + "node": ">= 12.0.0", + "parcel": "^2.8.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/config-default": { + "version": "2.8.0", + "resolved": "https://registry.npmjs.org/@parcel/config-default/-/config-default-2.8.0.tgz", + "integrity": "sha512-j9g50QNSLjuNpY0TP01EgGJPxWNes9d+e8+N07Z5Wv0u+UUnJ2uIOpo7PVn7ullOGhm1f9lP4KsJenu5gWb+cg==", + "dev": true, + "dependencies": { + "@parcel/bundler-default": "2.8.0", + "@parcel/compressor-raw": "2.8.0", + "@parcel/namer-default": "2.8.0", + "@parcel/optimizer-css": "2.8.0", + "@parcel/optimizer-htmlnano": "2.8.0", + "@parcel/optimizer-image": "2.8.0", + "@parcel/optimizer-svgo": "2.8.0", + "@parcel/optimizer-terser": "2.8.0", + "@parcel/packager-css": "2.8.0", + "@parcel/packager-html": "2.8.0", + "@parcel/packager-js": "2.8.0", + "@parcel/packager-raw": "2.8.0", + "@parcel/packager-svg": "2.8.0", + "@parcel/reporter-dev-server": "2.8.0", + "@parcel/resolver-default": "2.8.0", + "@parcel/runtime-browser-hmr": "2.8.0", + "@parcel/runtime-js": "2.8.0", + "@parcel/runtime-react-refresh": "2.8.0", + "@parcel/runtime-service-worker": "2.8.0", + "@parcel/transformer-babel": "2.8.0", + "@parcel/transformer-css": "2.8.0", + "@parcel/transformer-html": "2.8.0", + "@parcel/transformer-image": "2.8.0", + "@parcel/transformer-js": "2.8.0", + "@parcel/transformer-json": "2.8.0", + "@parcel/transformer-postcss": "2.8.0", + "@parcel/transformer-posthtml": "2.8.0", + "@parcel/transformer-raw": "2.8.0", + "@parcel/transformer-react-refresh-wrap": "2.8.0", + "@parcel/transformer-svg": "2.8.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + }, + "peerDependencies": { + "@parcel/core": "^2.8.0" + } + }, + "node_modules/@parcel/core": { + "version": "2.8.0", + "resolved": "https://registry.npmjs.org/@parcel/core/-/core-2.8.0.tgz", + "integrity": "sha512-udzbe3jjbpfKlRE9pdlROAa+lvAjS1L/AzN6r2j1y/Fsn7ze/NfvnCFw6o2YNIrXg002aQ7M1St/x1fdGfmVKA==", + "dev": true, + "dependencies": { + "@mischnic/json-sourcemap": "^0.1.0", + "@parcel/cache": "2.8.0", + "@parcel/diagnostic": "2.8.0", + "@parcel/events": "2.8.0", + "@parcel/fs": "2.8.0", + "@parcel/graph": "2.8.0", + "@parcel/hash": "2.8.0", + "@parcel/logger": "2.8.0", + "@parcel/package-manager": "2.8.0", + "@parcel/plugin": "2.8.0", + "@parcel/source-map": "^2.1.1", + "@parcel/types": "2.8.0", + "@parcel/utils": "2.8.0", + "@parcel/workers": "2.8.0", + "abortcontroller-polyfill": "^1.1.9", + "base-x": "^3.0.8", + "browserslist": "^4.6.6", + "clone": "^2.1.1", + "dotenv": "^7.0.0", + "dotenv-expand": "^5.1.0", + "json5": "^2.2.0", + "msgpackr": "^1.5.4", + "nullthrows": "^1.1.1", + "semver": "^5.7.1" + }, + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/diagnostic": { + "version": "2.8.0", + "resolved": "https://registry.npmjs.org/@parcel/diagnostic/-/diagnostic-2.8.0.tgz", + "integrity": "sha512-ERnk0zDvm0jQUSj1M+2PLiwVC6nWrtuFEuye6VGuxRDcp9NHbz6gwApeEYxFkPsb3TQPhNjnXXm5nmAw1bpWWw==", + "dev": true, + "dependencies": { + "@mischnic/json-sourcemap": "^0.1.0", + "nullthrows": "^1.1.1" + }, + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/events": { + "version": "2.8.0", + "resolved": "https://registry.npmjs.org/@parcel/events/-/events-2.8.0.tgz", + "integrity": "sha512-xqSZYY3oONM4IZm9+vhyFqX+KFIl145veIczUikwGJlcJZQfAAw736syPx6ecpB+m1EVg3AlvJWy7Lmel4Ak+Q==", + "dev": true, + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/fs": { + "version": "2.8.0", + "resolved": "https://registry.npmjs.org/@parcel/fs/-/fs-2.8.0.tgz", + "integrity": "sha512-v3DbJlpl8v2/VRlZPw7cy+0myi0YfLblGZcwDvqIsWS35qyxD2rmtYV8u1BusonbgmJeaKiopSECmJkumt0jCw==", + "dev": true, + "dependencies": { + "@parcel/fs-search": "2.8.0", + "@parcel/types": "2.8.0", + "@parcel/utils": "2.8.0", + "@parcel/watcher": "^2.0.7", + "@parcel/workers": "2.8.0" + }, + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + }, + "peerDependencies": { + "@parcel/core": "^2.8.0" + } + }, + "node_modules/@parcel/fs-search": { + "version": "2.8.0", + "resolved": "https://registry.npmjs.org/@parcel/fs-search/-/fs-search-2.8.0.tgz", + "integrity": "sha512-yo7/Y8DCFlhOlIBb5SsRDTkM+7g0DY9sK57iw3hn2z1tGoIiIRptrieImFYSizs7HfDwDY/PMLfORmUdoReDzQ==", + "dev": true, + "dependencies": { + "detect-libc": "^1.0.3" + }, + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/graph": { + "version": "2.8.0", + "resolved": "https://registry.npmjs.org/@parcel/graph/-/graph-2.8.0.tgz", + "integrity": "sha512-JvAyvBpGmhZ30bi+hStQr52eu+InfJBoiN9Z/32byIWhXEl02EAOwfsPqAe+FGCsdgXnnCGg5F9ZCqwzZ9dwbw==", + "dev": true, + "dependencies": { + "@parcel/utils": "2.8.0", + "nullthrows": "^1.1.1" + }, + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/hash": { + "version": "2.8.0", + "resolved": "https://registry.npmjs.org/@parcel/hash/-/hash-2.8.0.tgz", + "integrity": "sha512-KV1+96t7Nukth5K7ldUXjVr8ZTH9Dohl49K0Tc+5Qkysif0OxwcDtpVDmcnrUnWmqdBX0AdoLY0Q2Nnly89n/w==", + "dev": true, + "dependencies": { + "detect-libc": "^1.0.3", + "xxhash-wasm": "^0.4.2" + }, + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/logger": { + "version": "2.8.0", + "resolved": "https://registry.npmjs.org/@parcel/logger/-/logger-2.8.0.tgz", + "integrity": "sha512-W+7rKsLxLUX6xRmP8PhGWcG48PqrzTPeMWpgSds5nXxAHEFh4cYbkwPKGoTU65a9xUDVyqNreHNIKyizgwAZHQ==", + "dev": true, + "dependencies": { + "@parcel/diagnostic": "2.8.0", + "@parcel/events": "2.8.0" + }, + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/markdown-ansi": { + "version": "2.8.0", + "resolved": "https://registry.npmjs.org/@parcel/markdown-ansi/-/markdown-ansi-2.8.0.tgz", + "integrity": "sha512-xItzXmc3btFhJXsIbE946iaqE6STd2xe5H0zSIaZVXEeucCtMzcd4hxRELquxPstlrAOrrp/lrRpbAlMhso9iA==", + "dev": true, + "dependencies": { + "chalk": "^4.1.0" + }, + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/namer-default": { + "version": "2.8.0", + "resolved": "https://registry.npmjs.org/@parcel/namer-default/-/namer-default-2.8.0.tgz", + "integrity": "sha512-cVCx2kJA/Bv7O9pVad1UOibaybR/B+QdWV8Ols8HH4lC2gyjLBXEIR0uuPSEbkGwMEcofG6zA3MwsoPa6r5lBg==", + "dev": true, + "dependencies": { + "@parcel/diagnostic": "2.8.0", + "@parcel/plugin": "2.8.0", + "nullthrows": "^1.1.1" + }, + "engines": { + "node": ">= 12.0.0", + "parcel": "^2.8.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/node-resolver-core": { + "version": "2.8.0", + "resolved": "https://registry.npmjs.org/@parcel/node-resolver-core/-/node-resolver-core-2.8.0.tgz", + "integrity": "sha512-cECSh08NSRt1csmmMeKxlnO6ZhXRTuRijkHKFa4iG5hPL+3Cu04YGhuK/QWlP5vNCPVrH3ISlhzlPU5fAi/nEg==", + "dev": true, + "dependencies": { + "@parcel/diagnostic": "2.8.0", + "@parcel/utils": "2.8.0", + "nullthrows": "^1.1.1", + "semver": "^5.7.1" + }, + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/optimizer-css": { + "version": "2.8.0", + "resolved": "https://registry.npmjs.org/@parcel/optimizer-css/-/optimizer-css-2.8.0.tgz", + "integrity": "sha512-T5r3gZVm1xFw6l//iLkzLDUvFzNTUvL5kAtyU5gS5yH/dg7eCS09Km/c2anViQnmXwFUt7zIlBovj1doxAVNSw==", + "dev": true, + "dependencies": { + "@parcel/diagnostic": "2.8.0", + "@parcel/plugin": "2.8.0", + "@parcel/source-map": "^2.1.1", + "@parcel/utils": "2.8.0", + "browserslist": "^4.6.6", + "lightningcss": "^1.16.1", + "nullthrows": "^1.1.1" + }, + "engines": { + "node": ">= 12.0.0", + "parcel": "^2.8.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/optimizer-htmlnano": { + "version": "2.8.0", + "resolved": "https://registry.npmjs.org/@parcel/optimizer-htmlnano/-/optimizer-htmlnano-2.8.0.tgz", + "integrity": "sha512-NxEKTRvue/WAU+XbQGfNIU6c7chDekdkwwv9YnCxHEOhnBu4Ok+2tdmCtPuA+4UUNszGxXlaHMnqSrjmqX2S6Q==", + "dev": true, + "dependencies": { + "@parcel/plugin": "2.8.0", + "htmlnano": "^2.0.0", + "nullthrows": "^1.1.1", + "posthtml": "^0.16.5", + "svgo": "^2.4.0" + }, + "engines": { + "node": ">= 12.0.0", + "parcel": "^2.8.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/optimizer-image": { + "version": "2.8.0", + "resolved": "https://registry.npmjs.org/@parcel/optimizer-image/-/optimizer-image-2.8.0.tgz", + "integrity": "sha512-66eSoCCGZVRiY6U4OqqYrhQcBcHI9cOkIEbxadZYOF4cJhsskjUDJR0jLb4j2PE6QxUNYlyj5OglQqRLwhz7vA==", + "dev": true, + "dependencies": { + "@parcel/diagnostic": "2.8.0", + "@parcel/plugin": "2.8.0", + "@parcel/utils": "2.8.0", + "@parcel/workers": "2.8.0", + "detect-libc": "^1.0.3" + }, + "engines": { + "node": ">= 12.0.0", + "parcel": "^2.8.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/optimizer-svgo": { + "version": "2.8.0", + "resolved": "https://registry.npmjs.org/@parcel/optimizer-svgo/-/optimizer-svgo-2.8.0.tgz", + "integrity": "sha512-qQzM32CzJJuniFaTZDspVn/Vtz/PJ/f89+FckLpWZJVWNihgwTHC1/F0YTDH8g6czNw5ZijwQ3xBVuJQYyIXsQ==", + "dev": true, + "dependencies": { + "@parcel/diagnostic": "2.8.0", + "@parcel/plugin": "2.8.0", + "@parcel/utils": "2.8.0", + "svgo": "^2.4.0" + }, + "engines": { + "node": ">= 12.0.0", + "parcel": "^2.8.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/optimizer-terser": { + "version": "2.8.0", + "resolved": "https://registry.npmjs.org/@parcel/optimizer-terser/-/optimizer-terser-2.8.0.tgz", + "integrity": "sha512-slS6GWQ3u418WtJmlqlA5Njljcq4OaEdDDR2ifEwltG8POv+hsvD5AAoM2XB0GJwY97TQtdMbBu2DuDF3yM/1Q==", + "dev": true, + "dependencies": { + "@parcel/diagnostic": "2.8.0", + "@parcel/plugin": "2.8.0", + "@parcel/source-map": "^2.1.1", + "@parcel/utils": "2.8.0", + "nullthrows": "^1.1.1", + "terser": "^5.2.0" + }, + "engines": { + "node": ">= 12.0.0", + "parcel": "^2.8.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/package-manager": { + "version": "2.8.0", + "resolved": "https://registry.npmjs.org/@parcel/package-manager/-/package-manager-2.8.0.tgz", + "integrity": "sha512-n4FgerAX1lTKKTgxmiocnos47Y+b0L60iwU6Q4cC2n4KQNRuNyfhxFXwWcqHstR9wa72JgPaDgo4k0l3Bk8FZw==", + "dev": true, + "dependencies": { + "@parcel/diagnostic": "2.8.0", + "@parcel/fs": "2.8.0", + "@parcel/logger": "2.8.0", + "@parcel/types": "2.8.0", + "@parcel/utils": "2.8.0", + "@parcel/workers": "2.8.0", + "semver": "^5.7.1" + }, + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + }, + "peerDependencies": { + "@parcel/core": "^2.8.0" + } + }, + "node_modules/@parcel/packager-css": { + "version": "2.8.0", + "resolved": "https://registry.npmjs.org/@parcel/packager-css/-/packager-css-2.8.0.tgz", + "integrity": "sha512-tv/Bto0P6fXjqQ9uCZ8/6b/+38Zr/N2MC7/Nbflzww/lp0k2+kkE9MVJJDr5kST/SzTBRrhbDo+yTbtdZikJYg==", + "dev": true, + "dependencies": { + "@parcel/plugin": "2.8.0", + "@parcel/source-map": "^2.1.1", + "@parcel/utils": "2.8.0", + "nullthrows": "^1.1.1" + }, + "engines": { + "node": ">= 12.0.0", + "parcel": "^2.8.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/packager-html": { + "version": "2.8.0", + "resolved": "https://registry.npmjs.org/@parcel/packager-html/-/packager-html-2.8.0.tgz", + "integrity": "sha512-4x09v/bt767rxwGTuEw82CjheoOtIKNu4sx1gqwQOz9QowKPniXOIaD+0XmLiARdzRErucf0sL19QHfNcPAhUw==", + "dev": true, + "dependencies": { + "@parcel/plugin": "2.8.0", + "@parcel/types": "2.8.0", + "@parcel/utils": "2.8.0", + "nullthrows": "^1.1.1", + "posthtml": "^0.16.5" + }, + "engines": { + "node": ">= 12.0.0", + "parcel": "^2.8.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/packager-js": { + "version": "2.8.0", + "resolved": "https://registry.npmjs.org/@parcel/packager-js/-/packager-js-2.8.0.tgz", + "integrity": "sha512-Tn2EtWM1TEdj4t5pt0QjBDzqrXrfRTL3WsdMipZwDSuX04KS0jedJINHjh46HOMwyfJxLbUg3xkGX7F5mYQj5g==", + "dev": true, + "dependencies": { + "@parcel/diagnostic": "2.8.0", + "@parcel/hash": "2.8.0", + "@parcel/plugin": "2.8.0", + "@parcel/source-map": "^2.1.1", + "@parcel/utils": "2.8.0", + "globals": "^13.2.0", + "nullthrows": "^1.1.1" + }, + "engines": { + "node": ">= 12.0.0", + "parcel": "^2.8.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/packager-raw": { + "version": "2.8.0", + "resolved": "https://registry.npmjs.org/@parcel/packager-raw/-/packager-raw-2.8.0.tgz", + "integrity": "sha512-s3VniER3X2oNTlfytBGIQF+UZFVNLFWuVu1IkZ8Wg6uYQffrExDlbNDcmFCDcfvcejL3Ch5igP+L6N00f6+wAQ==", + "dev": true, + "dependencies": { + "@parcel/plugin": "2.8.0" + }, + "engines": { + "node": ">= 12.0.0", + "parcel": "^2.8.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/packager-svg": { + "version": "2.8.0", + "resolved": "https://registry.npmjs.org/@parcel/packager-svg/-/packager-svg-2.8.0.tgz", + "integrity": "sha512-+BSpdPiNjlAne28nOjG2AyiOejAehe/+X9MxL2FIpPP7UBLNc2ekaM0mDTR5iY45YtZa57oyErBT/U6wZ1TCjw==", + "dev": true, + "dependencies": { + "@parcel/plugin": "2.8.0", + "@parcel/types": "2.8.0", + "@parcel/utils": "2.8.0", + "posthtml": "^0.16.4" + }, + "engines": { + "node": ">= 12.0.0", + "parcel": "^2.8.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/plugin": { + "version": "2.8.0", + "resolved": "https://registry.npmjs.org/@parcel/plugin/-/plugin-2.8.0.tgz", + "integrity": "sha512-Tsf+7nDg7KauvTVY6rGc7CmgJruKSwJ54KJ9s5nYFFP9nfwmyqbayCi9xOxicWU9zIHfuF5Etwf17lcA0oAvzw==", + "dev": true, + "dependencies": { + "@parcel/types": "2.8.0" + }, + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/reporter-cli": { + "version": "2.8.0", + "resolved": "https://registry.npmjs.org/@parcel/reporter-cli/-/reporter-cli-2.8.0.tgz", + "integrity": "sha512-ea4/Lp+2jDbzb/tfTgUKzYU51FK8wcewDoYNr06uL+wvx/vzYIDG0jHfzaOTasREnm7ECDr1Zu2Iknrgk1STqQ==", + "dev": true, + "dependencies": { + "@parcel/plugin": "2.8.0", + "@parcel/types": "2.8.0", + "@parcel/utils": "2.8.0", + "chalk": "^4.1.0", + "term-size": "^2.2.1" + }, + "engines": { + "node": ">= 12.0.0", + "parcel": "^2.8.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/reporter-dev-server": { + "version": "2.8.0", + "resolved": "https://registry.npmjs.org/@parcel/reporter-dev-server/-/reporter-dev-server-2.8.0.tgz", + "integrity": "sha512-wg6hUrQ8vUmvlP2fg8YEzYndmq7hWZ21ZgBv4So1Z65I+Qav85Uox7bjGLCSJwEAjdjFKfhV9RGULGzqh8vcAQ==", + "dev": true, + "dependencies": { + "@parcel/plugin": "2.8.0", + "@parcel/utils": "2.8.0" + }, + "engines": { + "node": ">= 12.0.0", + "parcel": "^2.8.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/resolver-default": { + "version": "2.8.0", + "resolved": "https://registry.npmjs.org/@parcel/resolver-default/-/resolver-default-2.8.0.tgz", + "integrity": "sha512-kO5W+O3Ql6NXNFS6lvfSSt1R+PxO1atNLYxZdVSM6+QQxRMiztfqzZs//RM+oUp+af6muDSUPlNs+RORX0fing==", + "dev": true, + "dependencies": { + "@parcel/node-resolver-core": "2.8.0", + "@parcel/plugin": "2.8.0" + }, + "engines": { + "node": ">= 12.0.0", + "parcel": "^2.8.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/runtime-browser-hmr": { + "version": "2.8.0", + "resolved": "https://registry.npmjs.org/@parcel/runtime-browser-hmr/-/runtime-browser-hmr-2.8.0.tgz", + "integrity": "sha512-zV5wGGvm1cDwWAzkwPUaKh6inWYKxq67YWY4G396PXLMxddM9SQC1c7iFM60OPnD4A+BMOLOy7N6//20h15Dlg==", + "dev": true, + "dependencies": { + "@parcel/plugin": "2.8.0", + "@parcel/utils": "2.8.0" + }, + "engines": { + "node": ">= 12.0.0", + "parcel": "^2.8.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/runtime-js": { + "version": "2.8.0", + "resolved": "https://registry.npmjs.org/@parcel/runtime-js/-/runtime-js-2.8.0.tgz", + "integrity": "sha512-IwT1rX8ZamoYZv0clfswZemfXcIfk+YXwNsqXwzzh6TaMGagj/ZZl1llkn7ERQFq4EoLEoDGGkxqsrJjBp9NDQ==", + "dev": true, + "dependencies": { + "@parcel/plugin": "2.8.0", + "@parcel/utils": "2.8.0", + "nullthrows": "^1.1.1" + }, + "engines": { + "node": ">= 12.0.0", + "parcel": "^2.8.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/runtime-react-refresh": { + "version": "2.8.0", + "resolved": "https://registry.npmjs.org/@parcel/runtime-react-refresh/-/runtime-react-refresh-2.8.0.tgz", + "integrity": "sha512-a6uuZWkl+mJur2WLZKmpEqq1P06tvRwqGefYbE26DWpwXwU9dLpfnv/nT0hqCmVDHd2TkMyCffolSmq1vY05ew==", + "dev": true, + "dependencies": { + "@parcel/plugin": "2.8.0", + "@parcel/utils": "2.8.0", + "react-error-overlay": "6.0.9", + "react-refresh": "^0.9.0" + }, + "engines": { + "node": ">= 12.0.0", + "parcel": "^2.8.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/runtime-service-worker": { + "version": "2.8.0", + "resolved": "https://registry.npmjs.org/@parcel/runtime-service-worker/-/runtime-service-worker-2.8.0.tgz", + "integrity": "sha512-Q3Q2O/axQbFi/5Z+BidLB3qhmYdZLTMDagZtsmyH7CktDkZVNV/0UoOGYlqoK06T4cww3XjLSEomXbBu9TlQKQ==", + "dev": true, + "dependencies": { + "@parcel/plugin": "2.8.0", + "@parcel/utils": "2.8.0", + "nullthrows": "^1.1.1" + }, + "engines": { + "node": ">= 12.0.0", + "parcel": "^2.8.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/source-map": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/@parcel/source-map/-/source-map-2.1.1.tgz", + "integrity": "sha512-Ejx1P/mj+kMjQb8/y5XxDUn4reGdr+WyKYloBljpppUy8gs42T+BNoEOuRYqDVdgPc6NxduzIDoJS9pOFfV5Ew==", + "dev": true, + "dependencies": { + "detect-libc": "^1.0.3" + }, + "engines": { + "node": "^12.18.3 || >=14" + } + }, + "node_modules/@parcel/transformer-babel": { + "version": "2.8.0", + "resolved": "https://registry.npmjs.org/@parcel/transformer-babel/-/transformer-babel-2.8.0.tgz", + "integrity": "sha512-ie+wFe9pucdnRyX2PTN9amOHrhr/IOwUEAfTz/3dPydOYCuX7ErEngCpI9fBzdYE2AV6/noEwC2Mjeoyz9mT2A==", + "dev": true, + "dependencies": { + "@parcel/diagnostic": "2.8.0", + "@parcel/plugin": "2.8.0", + "@parcel/source-map": "^2.1.1", + "@parcel/utils": "2.8.0", + "browserslist": "^4.6.6", + "json5": "^2.2.0", + "nullthrows": "^1.1.1", + "semver": "^5.7.0" + }, + "engines": { + "node": ">= 12.0.0", + "parcel": "^2.8.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/transformer-css": { + "version": "2.8.0", + "resolved": "https://registry.npmjs.org/@parcel/transformer-css/-/transformer-css-2.8.0.tgz", + "integrity": "sha512-jCMQSfsxCoepblBAHCYMuNWNPQlqasoD6PfNftMdTlv12aUcnjNIYO9600TVLTL799CrEohljbXcfFn6hDGVWw==", + "dev": true, + "dependencies": { + "@parcel/diagnostic": "2.8.0", + "@parcel/plugin": "2.8.0", + "@parcel/source-map": "^2.1.1", + "@parcel/utils": "2.8.0", + "browserslist": "^4.6.6", + "lightningcss": "^1.16.1", + "nullthrows": "^1.1.1" + }, + "engines": { + "node": ">= 12.0.0", + "parcel": "^2.8.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/transformer-html": { + "version": "2.8.0", + "resolved": "https://registry.npmjs.org/@parcel/transformer-html/-/transformer-html-2.8.0.tgz", + "integrity": "sha512-KLcZCWSIItZ1s12Sav3uvfTrwhX92craN9u7V3qUs8ld7ompTKsCdnf+gYmeCyISb5yiFDyYBvTGc1bOXvaDRQ==", + "dev": true, + "dependencies": { + "@parcel/diagnostic": "2.8.0", + "@parcel/hash": "2.8.0", + "@parcel/plugin": "2.8.0", + "nullthrows": "^1.1.1", + "posthtml": "^0.16.5", + "posthtml-parser": "^0.10.1", + "posthtml-render": "^3.0.0", + "semver": "^5.7.1" + }, + "engines": { + "node": ">= 12.0.0", + "parcel": "^2.8.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/transformer-image": { + "version": "2.8.0", + "resolved": "https://registry.npmjs.org/@parcel/transformer-image/-/transformer-image-2.8.0.tgz", + "integrity": "sha512-hJGsZxGlGEkiUvN8kCxA4DhB6/WrHzcIlZZYEgEien9pLctyc6np6idjdcyudPAhH3LwBPkiyeUfCvLAOA1zkA==", + "dev": true, + "dependencies": { + "@parcel/plugin": "2.8.0", + "@parcel/utils": "2.8.0", + "@parcel/workers": "2.8.0", + "nullthrows": "^1.1.1" + }, + "engines": { + "node": ">= 12.0.0", + "parcel": "^2.8.0" + }, + "peerDependencies": { + "@parcel/core": "^2.8.0" + } + }, + "node_modules/@parcel/transformer-inline-string": { + "version": "2.8.0", + "resolved": "https://registry.npmjs.org/@parcel/transformer-inline-string/-/transformer-inline-string-2.8.0.tgz", + "integrity": "sha512-YBBgolTygr93hos4f5/xkM8VqP+Wc2exeXOyJfVCJJEaSVseXVdF8JtuZLlrcqOkw+ZC3nJtD4CEu+Glz9zCRg==", + "dev": true, + "dependencies": { + "@parcel/plugin": "2.8.0" + }, + "engines": { + "node": ">= 12.0.0", + "parcel": "^2.8.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/transformer-js": { + "version": "2.8.0", + "resolved": "https://registry.npmjs.org/@parcel/transformer-js/-/transformer-js-2.8.0.tgz", + "integrity": "sha512-C5WTkDRiJGBB9tZa1mBsZwsqZjYEKkOa4mdVym3dMokwhFLUga8WtK7kGw4fmXIq41U8ip4orywj+Rd4mvGVWg==", + "dev": true, + "dependencies": { + "@parcel/diagnostic": "2.8.0", + "@parcel/plugin": "2.8.0", + "@parcel/source-map": "^2.1.1", + "@parcel/utils": "2.8.0", + "@parcel/workers": "2.8.0", + "@swc/helpers": "^0.4.12", + "browserslist": "^4.6.6", + "detect-libc": "^1.0.3", + "nullthrows": "^1.1.1", + "regenerator-runtime": "^0.13.7", + "semver": "^5.7.1" + }, + "engines": { + "node": ">= 12.0.0", + "parcel": "^2.8.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + }, + "peerDependencies": { + "@parcel/core": "^2.8.0" + } + }, + "node_modules/@parcel/transformer-json": { + "version": "2.8.0", + "resolved": "https://registry.npmjs.org/@parcel/transformer-json/-/transformer-json-2.8.0.tgz", + "integrity": "sha512-Pp5gROSMpzFDEI6KA2APuSpft6eXZxFgTPV6Xx9pElqseod3iL5+RnpMNV/nv76Ai2bcMEiafus5Pb09vjHgbQ==", + "dev": true, + "dependencies": { + "@parcel/plugin": "2.8.0", + "json5": "^2.2.0" + }, + "engines": { + "node": ">= 12.0.0", + "parcel": "^2.8.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/transformer-postcss": { + "version": "2.8.0", + "resolved": "https://registry.npmjs.org/@parcel/transformer-postcss/-/transformer-postcss-2.8.0.tgz", + "integrity": "sha512-45Ij+cgwXprd1sCLmaMIlCbPz3eEwolGHizgZmXl5l4yjlE2wGyzodhxLpBk1PWu7OxxWRbLnJIlvMYf7Vfw0g==", + "dev": true, + "dependencies": { + "@parcel/diagnostic": "2.8.0", + "@parcel/hash": "2.8.0", + "@parcel/plugin": "2.8.0", + "@parcel/utils": "2.8.0", + "clone": "^2.1.1", + "nullthrows": "^1.1.1", + "postcss-value-parser": "^4.2.0", + "semver": "^5.7.1" + }, + "engines": { + "node": ">= 12.0.0", + "parcel": "^2.8.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/transformer-posthtml": { + "version": "2.8.0", + "resolved": "https://registry.npmjs.org/@parcel/transformer-posthtml/-/transformer-posthtml-2.8.0.tgz", + "integrity": "sha512-KrkKBFDW5PNZpr2Ha711eIABQOiJQKvfwfVs3CVpJK5wSADkappDk7CQ0mISPjhamFJ6xx/sNsi7e871I8R9lg==", + "dev": true, + "dependencies": { + "@parcel/plugin": "2.8.0", + "@parcel/utils": "2.8.0", + "nullthrows": "^1.1.1", + "posthtml": "^0.16.5", + "posthtml-parser": "^0.10.1", + "posthtml-render": "^3.0.0", + "semver": "^5.7.1" + }, + "engines": { + "node": ">= 12.0.0", + "parcel": "^2.8.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/transformer-raw": { + "version": "2.8.0", + "resolved": "https://registry.npmjs.org/@parcel/transformer-raw/-/transformer-raw-2.8.0.tgz", + "integrity": "sha512-uEbj+kE70vg2Gmdji/AIXPK13s5aQRw7X+xWs3vNpY2oymyMRHbfx1izJFWBh+kxu6Yo6q6qsekkh2rNHEHIUA==", + "dev": true, + "dependencies": { + "@parcel/plugin": "2.8.0" + }, + "engines": { + "node": ">= 12.0.0", + "parcel": "^2.8.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/transformer-react-refresh-wrap": { + "version": "2.8.0", + "resolved": "https://registry.npmjs.org/@parcel/transformer-react-refresh-wrap/-/transformer-react-refresh-wrap-2.8.0.tgz", + "integrity": "sha512-d7G6wBdlwVXLkhC7EO/3UkUOfEOJvsIsQUCEujsrdFF+nfBElXw/TZ+KP8UkmrwMdD0spU/8cKoTyi5k19vt6w==", + "dev": true, + "dependencies": { + "@parcel/plugin": "2.8.0", + "@parcel/utils": "2.8.0", + "react-refresh": "^0.9.0" + }, + "engines": { + "node": ">= 12.0.0", + "parcel": "^2.8.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/transformer-svg": { + "version": "2.8.0", + "resolved": "https://registry.npmjs.org/@parcel/transformer-svg/-/transformer-svg-2.8.0.tgz", + "integrity": "sha512-8S6yZoUTCbHOnuWY3M50fscTpI8414945I44fmed+C1e36TnWem8FifuVtGkRZeR8pokF453lmmwWG1eH/4U3w==", + "dev": true, + "dependencies": { + "@parcel/diagnostic": "2.8.0", + "@parcel/hash": "2.8.0", + "@parcel/plugin": "2.8.0", + "nullthrows": "^1.1.1", + "posthtml": "^0.16.5", + "posthtml-parser": "^0.10.1", + "posthtml-render": "^3.0.0", + "semver": "^5.7.1" + }, + "engines": { + "node": ">= 12.0.0", + "parcel": "^2.8.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/types": { + "version": "2.8.0", + "resolved": "https://registry.npmjs.org/@parcel/types/-/types-2.8.0.tgz", + "integrity": "sha512-DeN3vCnVl9onjtyWxpbP7LwRslVEko4kBaM7yILsuQjEnXmaIOsqIf6FQJOUOPBtQTFFNeQQ2qyf5XoO/rkJ8g==", + "dev": true, + "dependencies": { + "@parcel/cache": "2.8.0", + "@parcel/diagnostic": "2.8.0", + "@parcel/fs": "2.8.0", + "@parcel/package-manager": "2.8.0", + "@parcel/source-map": "^2.1.1", + "@parcel/workers": "2.8.0", + "utility-types": "^3.10.0" + } + }, + "node_modules/@parcel/utils": { + "version": "2.8.0", + "resolved": "https://registry.npmjs.org/@parcel/utils/-/utils-2.8.0.tgz", + "integrity": "sha512-r4ACsGtW7zkMUIgwQyOVtPAFiy8L81gbz4tMIRSqyQKnkW7oEHcQ3uN1/LPxj2yfkyQLmhJxmtptLUy9j53rcw==", + "dev": true, + "dependencies": { + "@parcel/codeframe": "2.8.0", + "@parcel/diagnostic": "2.8.0", + "@parcel/hash": "2.8.0", + "@parcel/logger": "2.8.0", + "@parcel/markdown-ansi": "2.8.0", + "@parcel/source-map": "^2.1.1", + "chalk": "^4.1.0" + }, + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/watcher": { + "version": "2.0.7", + "resolved": "https://registry.npmjs.org/@parcel/watcher/-/watcher-2.0.7.tgz", + "integrity": "sha512-gc3hoS6e+2XdIQ4HHljDB1l0Yx2EWh/sBBtCEFNKGSMlwASWeAQsOY/fPbxOBcZ/pg0jBh4Ga+4xHlZc4faAEQ==", + "dev": true, + "hasInstallScript": true, + "dependencies": { + "node-addon-api": "^3.2.1", + "node-gyp-build": "^4.3.0" + }, + "engines": { + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/workers": { + "version": "2.8.0", + "resolved": "https://registry.npmjs.org/@parcel/workers/-/workers-2.8.0.tgz", + "integrity": "sha512-vAzoC/wPHLQnyy9P/TrSPftY8F3MhZqPTFi681mxVtLWA3t7wiNlw1zDVKRDP8m5XS1yQOr8Q56CAHyRexhc8g==", + "dev": true, + "dependencies": { + "@parcel/diagnostic": "2.8.0", + "@parcel/logger": "2.8.0", + "@parcel/types": "2.8.0", + "@parcel/utils": "2.8.0", + "chrome-trace-event": "^1.0.2", + "nullthrows": "^1.1.1" + }, + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + }, + "peerDependencies": { + "@parcel/core": "^2.8.0" + } + }, + "node_modules/@swc/helpers": { + "version": "0.4.14", + "resolved": "https://registry.npmjs.org/@swc/helpers/-/helpers-0.4.14.tgz", + "integrity": "sha512-4C7nX/dvpzB7za4Ql9K81xK3HPxCpHMgwTZVyf+9JQ6VUbn9jjZVN7/Nkdz/Ugzs2CSjqnL/UPXroiVBVHUWUw==", + "dev": true, + "dependencies": { + "tslib": "^2.4.0" + } + }, + "node_modules/@trysound/sax": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/@trysound/sax/-/sax-0.2.0.tgz", + "integrity": "sha512-L7z9BgrNEcYyUYtF+HaEfiS5ebkh9jXqbszz7pC0hRBPaatV0XjSD3+eHrpqFemQfgwiFF0QPIarnIihIDn7OA==", + "dev": true, + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/@types/parse-json": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/@types/parse-json/-/parse-json-4.0.0.tgz", + "integrity": "sha512-//oorEZjL6sbPcKUaCdIGlIUeH26mgzimjBB77G6XRgnDl/L5wOnpyBGRe/Mmf5CVW3PwEBE1NjiMZ/ssFh4wA==", + "dev": true + }, + "node_modules/abortcontroller-polyfill": { + "version": "1.7.5", + "resolved": "https://registry.npmjs.org/abortcontroller-polyfill/-/abortcontroller-polyfill-1.7.5.tgz", + "integrity": "sha512-JMJ5soJWP18htbbxJjG7bG6yuI6pRhgJ0scHHTfkUjf6wjP912xZWvM+A4sJK3gqd9E8fcPbDnOefbA9Th/FIQ==", + "dev": true + }, + "node_modules/acorn": { + "version": "8.8.1", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.8.1.tgz", + "integrity": "sha512-7zFpHzhnqYKrkYdUjF1HI1bzd0VygEGX8lFk4k5zVMqHEoES+P+7TKI+EvLO9WVMJ8eekdO0aDEK044xTXwPPA==", + "dev": true, + "bin": { + "acorn": "bin/acorn" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/base-x": { + "version": "3.0.9", + "resolved": "https://registry.npmjs.org/base-x/-/base-x-3.0.9.tgz", + "integrity": "sha512-H7JU6iBHTal1gp56aKoaa//YUxEaAOUiydvrV/pILqIHXTtqxSkATOnDA2u+jZ/61sD+L/412+7kzXRtWukhpQ==", + "dev": true, + "dependencies": { + "safe-buffer": "^5.0.1" + } + }, + "node_modules/boolbase": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/boolbase/-/boolbase-1.0.0.tgz", + "integrity": "sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww==", + "dev": true + }, + "node_modules/browserslist": { + "version": "4.21.4", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.21.4.tgz", + "integrity": "sha512-CBHJJdDmgjl3daYjN5Cp5kbTf1mUhZoS+beLklHIvkOWscs83YAhLlF3Wsh/lciQYAcbBJgTOD44VtG31ZM4Hw==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/browserslist" + } + ], + "dependencies": { + "caniuse-lite": "^1.0.30001400", + "electron-to-chromium": "^1.4.251", + "node-releases": "^2.0.6", + "update-browserslist-db": "^1.0.9" + }, + "bin": { + "browserslist": "cli.js" + }, + "engines": { + "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7" + } + }, + "node_modules/buffer-from": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", + "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==", + "dev": true + }, + "node_modules/callsites": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", + "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/caniuse-lite": { + "version": "1.0.30001436", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001436.tgz", + "integrity": "sha512-ZmWkKsnC2ifEPoWUvSAIGyOYwT+keAaaWPHiQ9DfMqS1t6tfuyFYoWR78TeZtznkEQ64+vGXH9cZrElwR2Mrxg==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/caniuse-lite" + } + ] + }, + "node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/chrome-trace-event": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/chrome-trace-event/-/chrome-trace-event-1.0.3.tgz", + "integrity": "sha512-p3KULyQg4S7NIHixdwbGX+nFHkoBiA4YQmyWtjb8XngSKV124nJmRysgAeujbUVb15vh+RvFUfCPqU7rXk+hZg==", + "dev": true, + "engines": { + "node": ">=6.0" + } + }, + "node_modules/clone": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/clone/-/clone-2.1.2.tgz", + "integrity": "sha512-3Pe/CF1Nn94hyhIYpjtiLhdCoEoz0DqQ+988E9gmeEdQZlojxnOb74wctFyuwWQHzqyf9X7C7MG8juUpqBJT8w==", + "dev": true, + "engines": { + "node": ">=0.8" + } + }, + "node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "node_modules/commander": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-7.2.0.tgz", + "integrity": "sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw==", + "dev": true, + "engines": { + "node": ">= 10" + } + }, + "node_modules/cosmiconfig": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-7.1.0.tgz", + "integrity": "sha512-AdmX6xUzdNASswsFtmwSt7Vj8po9IuqXm0UXz7QKPuEUmPB4XyjGfaAr2PSuELMwkRMVH1EpIkX5bTZGRB3eCA==", + "dev": true, + "dependencies": { + "@types/parse-json": "^4.0.0", + "import-fresh": "^3.2.1", + "parse-json": "^5.0.0", + "path-type": "^4.0.0", + "yaml": "^1.10.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/css-select": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/css-select/-/css-select-4.3.0.tgz", + "integrity": "sha512-wPpOYtnsVontu2mODhA19JrqWxNsfdatRKd64kmpRbQgh1KtItko5sTnEpPdpSaJszTOhEMlF/RPz28qj4HqhQ==", + "dev": true, + "dependencies": { + "boolbase": "^1.0.0", + "css-what": "^6.0.1", + "domhandler": "^4.3.1", + "domutils": "^2.8.0", + "nth-check": "^2.0.1" + }, + "funding": { + "url": "https://github.com/sponsors/fb55" + } + }, + "node_modules/css-tree": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/css-tree/-/css-tree-1.1.3.tgz", + "integrity": "sha512-tRpdppF7TRazZrjJ6v3stzv93qxRcSsFmW6cX0Zm2NVKpxE1WV1HblnghVv9TreireHkqI/VDEsfolRF1p6y7Q==", + "dev": true, + "dependencies": { + "mdn-data": "2.0.14", + "source-map": "^0.6.1" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/css-what": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/css-what/-/css-what-6.1.0.tgz", + "integrity": "sha512-HTUrgRJ7r4dsZKU6GjmpfRK1O76h97Z8MfS1G0FozR+oF2kG6Vfe8JE6zwrkbxigziPHinCJ+gCPjA9EaBDtRw==", + "dev": true, + "engines": { + "node": ">= 6" + }, + "funding": { + "url": "https://github.com/sponsors/fb55" + } + }, + "node_modules/csso": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/csso/-/csso-4.2.0.tgz", + "integrity": "sha512-wvlcdIbf6pwKEk7vHj8/Bkc0B4ylXZruLvOgs9doS5eOsOpuodOV2zJChSpkp+pRpYQLQMeF04nr3Z68Sta9jA==", + "dev": true, + "dependencies": { + "css-tree": "^1.1.2" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/detect-libc": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-1.0.3.tgz", + "integrity": "sha512-pGjwhsmsp4kL2RTz08wcOlGN83otlqHeD/Z5T8GXZB+/YcpQ/dgo+lbU8ZsGxV0HIvqqxo9l7mqYwyYMD9bKDg==", + "dev": true, + "bin": { + "detect-libc": "bin/detect-libc.js" + }, + "engines": { + "node": ">=0.10" + } + }, + "node_modules/dom-serializer": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-1.4.1.tgz", + "integrity": "sha512-VHwB3KfrcOOkelEG2ZOfxqLZdfkil8PtJi4P8N2MMXucZq2yLp75ClViUlOVwyoHEDjYU433Aq+5zWP61+RGag==", + "dev": true, + "dependencies": { + "domelementtype": "^2.0.1", + "domhandler": "^4.2.0", + "entities": "^2.0.0" + }, + "funding": { + "url": "https://github.com/cheeriojs/dom-serializer?sponsor=1" + } + }, + "node_modules/dom-serializer/node_modules/entities": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/entities/-/entities-2.2.0.tgz", + "integrity": "sha512-p92if5Nz619I0w+akJrLZH0MX0Pb5DX39XOwQTtXSdQQOaYH03S1uIQp4mhOZtAXrxq4ViO67YTiLBo2638o9A==", + "dev": true, + "funding": { + "url": "https://github.com/fb55/entities?sponsor=1" + } + }, + "node_modules/domelementtype": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-2.3.0.tgz", + "integrity": "sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/fb55" + } + ] + }, + "node_modules/domhandler": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-4.3.1.tgz", + "integrity": "sha512-GrwoxYN+uWlzO8uhUXRl0P+kHE4GtVPfYzVLcUxPL7KNdHKj66vvlhiweIHqYYXWlw+T8iLMp42Lm67ghw4WMQ==", + "dev": true, + "dependencies": { + "domelementtype": "^2.2.0" + }, + "engines": { + "node": ">= 4" + }, + "funding": { + "url": "https://github.com/fb55/domhandler?sponsor=1" + } + }, + "node_modules/domutils": { + "version": "2.8.0", + "resolved": "https://registry.npmjs.org/domutils/-/domutils-2.8.0.tgz", + "integrity": "sha512-w96Cjofp72M5IIhpjgobBimYEfoPjx1Vx0BSX9P30WBdZW2WIKU0T1Bd0kz2eNZ9ikjKgHbEyKx8BB6H1L3h3A==", + "dev": true, + "dependencies": { + "dom-serializer": "^1.0.1", + "domelementtype": "^2.2.0", + "domhandler": "^4.2.0" + }, + "funding": { + "url": "https://github.com/fb55/domutils?sponsor=1" + } + }, + "node_modules/dotenv": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-7.0.0.tgz", + "integrity": "sha512-M3NhsLbV1i6HuGzBUH8vXrtxOk+tWmzWKDMbAVSUp3Zsjm7ywFeuwrUXhmhQyRK1q5B5GGy7hcXPbj3bnfZg2g==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/dotenv-expand": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/dotenv-expand/-/dotenv-expand-5.1.0.tgz", + "integrity": "sha512-YXQl1DSa4/PQyRfgrv6aoNjhasp/p4qs9FjJ4q4cQk+8m4r6k4ZSiEyytKG8f8W9gi8WsQtIObNmKd+tMzNTmA==", + "dev": true + }, + "node_modules/electron-to-chromium": { + "version": "1.4.284", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.284.tgz", + "integrity": "sha512-M8WEXFuKXMYMVr45fo8mq0wUrrJHheiKZf6BArTKk9ZBYCKJEOU5H8cdWgDT+qCVZf7Na4lVUaZsA+h6uA9+PA==", + "dev": true + }, + "node_modules/entities": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/entities/-/entities-3.0.1.tgz", + "integrity": "sha512-WiyBqoomrwMdFG1e0kqvASYfnlb0lp8M5o5Fw2OFq1hNZxxcNk8Ik0Xm7LxzBhuidnZB/UtBqVCgUz3kBOP51Q==", + "dev": true, + "engines": { + "node": ">=0.12" + }, + "funding": { + "url": "https://github.com/fb55/entities?sponsor=1" + } + }, + "node_modules/error-ex": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", + "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==", + "dev": true, + "dependencies": { + "is-arrayish": "^0.2.1" + } + }, + "node_modules/escalade": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", + "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", + "dev": true, + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/get-port": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/get-port/-/get-port-4.2.0.tgz", + "integrity": "sha512-/b3jarXkH8KJoOMQc3uVGHASwGLPq3gSFJ7tgJm2diza+bydJPTGOibin2steecKeOylE8oY2JERlVWkAJO6yw==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/globals": { + "version": "13.18.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-13.18.0.tgz", + "integrity": "sha512-/mR4KI8Ps2spmoc0Ulu9L7agOF0du1CZNQ3dke8yItYlyKNmGrkONemBbd6V8UTc1Wgcqn21t3WYB7dbRmh6/A==", + "dev": true, + "dependencies": { + "type-fest": "^0.20.2" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/htmlnano": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/htmlnano/-/htmlnano-2.0.3.tgz", + "integrity": "sha512-S4PGGj9RbdgW8LhbILNK7W9JhmYP8zmDY7KDV/8eCiJBQJlbmltp5I0gv8c5ntLljfdxxfmJ+UJVSqyH4mb41A==", + "dev": true, + "dependencies": { + "cosmiconfig": "^7.0.1", + "posthtml": "^0.16.5", + "timsort": "^0.3.0" + }, + "peerDependencies": { + "cssnano": "^5.0.11", + "postcss": "^8.3.11", + "purgecss": "^5.0.0", + "relateurl": "^0.2.7", + "srcset": "4.0.0", + "svgo": "^2.8.0", + "terser": "^5.10.0", + "uncss": "^0.17.3" + }, + "peerDependenciesMeta": { + "cssnano": { + "optional": true + }, + "postcss": { + "optional": true + }, + "purgecss": { + "optional": true + }, + "relateurl": { + "optional": true + }, + "srcset": { + "optional": true + }, + "svgo": { + "optional": true + }, + "terser": { + "optional": true + }, + "uncss": { + "optional": true + } + } + }, + "node_modules/htmlparser2": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-7.2.0.tgz", + "integrity": "sha512-H7MImA4MS6cw7nbyURtLPO1Tms7C5H602LRETv95z1MxO/7CP7rDVROehUYeYBUYEON94NXXDEPmZuq+hX4sog==", + "dev": true, + "funding": [ + "https://github.com/fb55/htmlparser2?sponsor=1", + { + "type": "github", + "url": "https://github.com/sponsors/fb55" + } + ], + "dependencies": { + "domelementtype": "^2.0.1", + "domhandler": "^4.2.2", + "domutils": "^2.8.0", + "entities": "^3.0.1" + } + }, + "node_modules/import-fresh": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz", + "integrity": "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==", + "dev": true, + "dependencies": { + "parent-module": "^1.0.0", + "resolve-from": "^4.0.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/is-arrayish": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", + "integrity": "sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==", + "dev": true + }, + "node_modules/is-json": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-json/-/is-json-2.0.1.tgz", + "integrity": "sha512-6BEnpVn1rcf3ngfmViLM6vjUjGErbdrL4rwlv+u1NO1XO8kqT4YGL8+19Q+Z/bas8tY90BTWMk2+fW1g6hQjbA==", + "dev": true + }, + "node_modules/js-tokens": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", + "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", + "dev": true + }, + "node_modules/json-parse-even-better-errors": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz", + "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==", + "dev": true + }, + "node_modules/json5": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.1.tgz", + "integrity": "sha512-1hqLFMSrGHRHxav9q9gNjJ5EXznIxGVO09xQRrwplcS8qs28pZ8s8hupZAmqDwZUmVZ2Qb2jnyPOWcDH8m8dlA==", + "dev": true, + "bin": { + "json5": "lib/cli.js" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/lightningcss": { + "version": "1.17.1", + "resolved": "https://registry.npmjs.org/lightningcss/-/lightningcss-1.17.1.tgz", + "integrity": "sha512-DwwM/YYqGwLLP3he41wzDXT/m+8jdEZ80i9ViQNLRgyhey3Vm6N7XHn+4o3PY6wSnVT23WLuaROIpbpIVTNOjg==", + "dev": true, + "dependencies": { + "detect-libc": "^1.0.3" + }, + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + }, + "optionalDependencies": { + "lightningcss-darwin-arm64": "1.17.1", + "lightningcss-darwin-x64": "1.17.1", + "lightningcss-linux-arm-gnueabihf": "1.17.1", + "lightningcss-linux-arm64-gnu": "1.17.1", + "lightningcss-linux-arm64-musl": "1.17.1", + "lightningcss-linux-x64-gnu": "1.17.1", + "lightningcss-linux-x64-musl": "1.17.1", + "lightningcss-win32-x64-msvc": "1.17.1" + } + }, + "node_modules/lightningcss-darwin-arm64": { + "version": "1.17.1", + "resolved": "https://registry.npmjs.org/lightningcss-darwin-arm64/-/lightningcss-darwin-arm64-1.17.1.tgz", + "integrity": "sha512-YTAHEy4XlzI3sMbUVjbPi9P7+N7lGcgl2JhCZhiQdRAEKnZLQch8kb5601sgESxdGXjgei7JZFqi/vVEk81wYg==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-darwin-x64": { + "version": "1.17.1", + "resolved": "https://registry.npmjs.org/lightningcss-darwin-x64/-/lightningcss-darwin-x64-1.17.1.tgz", + "integrity": "sha512-UhXPUS2+yTTf5sXwUV0+8QY2x0bPGLgC/uhcknWSQMqWn1zGty4fFvH04D7f7ij0ujwSuN+Q0HtU7lgmMrPz0A==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-linux-arm-gnueabihf": { + "version": "1.17.1", + "resolved": "https://registry.npmjs.org/lightningcss-linux-arm-gnueabihf/-/lightningcss-linux-arm-gnueabihf-1.17.1.tgz", + "integrity": "sha512-alUZumuznB6K/9yZ0zuZkODXUm8uRnvs9t0CL46CXN16Y2h4gOx5ahUCMlelUb7inZEsgJIoepgLsJzBUrSsBw==", + "cpu": [ + "arm" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-linux-arm64-gnu": { + "version": "1.17.1", + "resolved": "https://registry.npmjs.org/lightningcss-linux-arm64-gnu/-/lightningcss-linux-arm64-gnu-1.17.1.tgz", + "integrity": "sha512-/1XaH2cOjDt+ivmgfmVFUYCA0MtfNWwtC4P8qVi53zEQ7P8euyyZ1ynykZOyKXW9Q0DzrwcLTh6+hxVLcbtGBg==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-linux-arm64-musl": { + "version": "1.17.1", + "resolved": "https://registry.npmjs.org/lightningcss-linux-arm64-musl/-/lightningcss-linux-arm64-musl-1.17.1.tgz", + "integrity": "sha512-/IgE7lYWFHCCQFTMIwtt+fXLcVOha8rcrNze1JYGPWNorO6NBc6MJo5u5cwn5qMMSz9fZCCDIlBBU4mGwjQszQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-linux-x64-gnu": { + "version": "1.17.1", + "resolved": "https://registry.npmjs.org/lightningcss-linux-x64-gnu/-/lightningcss-linux-x64-gnu-1.17.1.tgz", + "integrity": "sha512-OyE802IAp4DB9vZrHlOyWunbHLM9dN08tJIKN/HhzzLKIHizubOWX6NMzUXMZLsaUrYwVAHHdyEA+712p8mMzA==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-linux-x64-musl": { + "version": "1.17.1", + "resolved": "https://registry.npmjs.org/lightningcss-linux-x64-musl/-/lightningcss-linux-x64-musl-1.17.1.tgz", + "integrity": "sha512-ydwGgV3Usba5P53RAOqCA9MsRsbb8jFIEVhf7/BXFjpKNoIQyijVTXhwIgQr/oGwUNOHfgQ3F8ruiUjX/p2YKw==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-win32-x64-msvc": { + "version": "1.17.1", + "resolved": "https://registry.npmjs.org/lightningcss-win32-x64-msvc/-/lightningcss-win32-x64-msvc-1.17.1.tgz", + "integrity": "sha512-Ngqtx9NazaiAOk71XWwSsqgAuwYF+8PO6UYsoU7hAukdrSS98kwaBMEDw1igeIiZy1XD/4kh5KVnkjNf7ZOxVQ==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lines-and-columns": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz", + "integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==", + "dev": true + }, + "node_modules/lmdb": { + "version": "2.5.2", + "resolved": "https://registry.npmjs.org/lmdb/-/lmdb-2.5.2.tgz", + "integrity": "sha512-V5V5Xa2Hp9i2XsbDALkBTeHXnBXh/lEmk9p22zdr7jtuOIY9TGhjK6vAvTpOOx9IKU4hJkRWZxn/HsvR1ELLtA==", + "dev": true, + "hasInstallScript": true, + "dependencies": { + "msgpackr": "^1.5.4", + "node-addon-api": "^4.3.0", + "node-gyp-build-optional-packages": "5.0.3", + "ordered-binary": "^1.2.4", + "weak-lru-cache": "^1.2.2" + }, + "optionalDependencies": { + "@lmdb/lmdb-darwin-arm64": "2.5.2", + "@lmdb/lmdb-darwin-x64": "2.5.2", + "@lmdb/lmdb-linux-arm": "2.5.2", + "@lmdb/lmdb-linux-arm64": "2.5.2", + "@lmdb/lmdb-linux-x64": "2.5.2", + "@lmdb/lmdb-win32-x64": "2.5.2" + } + }, + "node_modules/lmdb/node_modules/node-addon-api": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-4.3.0.tgz", + "integrity": "sha512-73sE9+3UaLYYFmDsFZnqCInzPyh3MqIwZO9cw58yIqAZhONrrabrYyYe3TuIqtIiOuTXVhsGau8hcrhhwSsDIQ==", + "dev": true + }, + "node_modules/mdn-data": { + "version": "2.0.14", + "resolved": "https://registry.npmjs.org/mdn-data/-/mdn-data-2.0.14.tgz", + "integrity": "sha512-dn6wd0uw5GsdswPFfsgMp5NSB0/aDe6fK94YJV/AJDYXL6HVLWBsxeq7js7Ad+mU2K9LAlwpk6kN2D5mwCPVow==", + "dev": true + }, + "node_modules/msgpackr": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/msgpackr/-/msgpackr-1.8.1.tgz", + "integrity": "sha512-05fT4J8ZqjYlR4QcRDIhLCYKUOHXk7C/xa62GzMKj74l3up9k2QZ3LgFc6qWdsPHl91QA2WLWqWc8b8t7GLNNw==", + "dev": true, + "optionalDependencies": { + "msgpackr-extract": "^2.2.0" + } + }, + "node_modules/msgpackr-extract": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/msgpackr-extract/-/msgpackr-extract-2.2.0.tgz", + "integrity": "sha512-0YcvWSv7ZOGl9Od6Y5iJ3XnPww8O7WLcpYMDwX+PAA/uXLDtyw94PJv9GLQV/nnp3cWlDhMoyKZIQLrx33sWog==", + "dev": true, + "hasInstallScript": true, + "optional": true, + "dependencies": { + "node-gyp-build-optional-packages": "5.0.3" + }, + "bin": { + "download-msgpackr-prebuilds": "bin/download-prebuilds.js" + }, + "optionalDependencies": { + "@msgpackr-extract/msgpackr-extract-darwin-arm64": "2.2.0", + "@msgpackr-extract/msgpackr-extract-darwin-x64": "2.2.0", + "@msgpackr-extract/msgpackr-extract-linux-arm": "2.2.0", + "@msgpackr-extract/msgpackr-extract-linux-arm64": "2.2.0", + "@msgpackr-extract/msgpackr-extract-linux-x64": "2.2.0", + "@msgpackr-extract/msgpackr-extract-win32-x64": "2.2.0" + } + }, + "node_modules/node-addon-api": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-3.2.1.tgz", + "integrity": "sha512-mmcei9JghVNDYydghQmeDX8KoAm0FAiYyIcUt/N4nhyAipB17pllZQDOJD2fotxABnt4Mdz+dKTO7eftLg4d0A==", + "dev": true + }, + "node_modules/node-gyp-build": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/node-gyp-build/-/node-gyp-build-4.5.0.tgz", + "integrity": "sha512-2iGbaQBV+ITgCz76ZEjmhUKAKVf7xfY1sRl4UiKQspfZMH2h06SyhNsnSVy50cwkFQDGLyif6m/6uFXHkOZ6rg==", + "dev": true, + "bin": { + "node-gyp-build": "bin.js", + "node-gyp-build-optional": "optional.js", + "node-gyp-build-test": "build-test.js" + } + }, + "node_modules/node-gyp-build-optional-packages": { + "version": "5.0.3", + "resolved": "https://registry.npmjs.org/node-gyp-build-optional-packages/-/node-gyp-build-optional-packages-5.0.3.tgz", + "integrity": "sha512-k75jcVzk5wnnc/FMxsf4udAoTEUv2jY3ycfdSd3yWu6Cnd1oee6/CfZJApyscA4FJOmdoixWwiwOyf16RzD5JA==", + "dev": true, + "bin": { + "node-gyp-build-optional-packages": "bin.js", + "node-gyp-build-optional-packages-optional": "optional.js", + "node-gyp-build-optional-packages-test": "build-test.js" + } + }, + "node_modules/node-releases": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.6.tgz", + "integrity": "sha512-PiVXnNuFm5+iYkLBNeq5211hvO38y63T0i2KKh2KnUs3RpzJ+JtODFjkD8yjLwnDkTYF1eKXheUwdssR+NRZdg==", + "dev": true + }, + "node_modules/nth-check": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/nth-check/-/nth-check-2.1.1.tgz", + "integrity": "sha512-lqjrjmaOoAnWfMmBPL+XNnynZh2+swxiX3WUE0s4yEHI6m+AwrK2UZOimIRl3X/4QctVqS8AiZjFqyOGrMXb/w==", + "dev": true, + "dependencies": { + "boolbase": "^1.0.0" + }, + "funding": { + "url": "https://github.com/fb55/nth-check?sponsor=1" + } + }, + "node_modules/nullthrows": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/nullthrows/-/nullthrows-1.1.1.tgz", + "integrity": "sha512-2vPPEi+Z7WqML2jZYddDIfy5Dqb0r2fze2zTxNNknZaFpVHU3mFB3R+DWeJWGVx0ecvttSGlJTI+WG+8Z4cDWw==", + "dev": true + }, + "node_modules/ordered-binary": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/ordered-binary/-/ordered-binary-1.4.0.tgz", + "integrity": "sha512-EHQ/jk4/a9hLupIKxTfUsQRej1Yd/0QLQs3vGvIqg5ZtCYSzNhkzHoZc7Zf4e4kUlDaC3Uw8Q/1opOLNN2OKRQ==", + "dev": true + }, + "node_modules/parcel": { + "version": "2.8.0", + "resolved": "https://registry.npmjs.org/parcel/-/parcel-2.8.0.tgz", + "integrity": "sha512-p7Fo75CeMw5HC1luovYpBjzPbAJv/Gn7lxcs4f0LxcwBCWbkQ73zHgJXJQqnM38qQABEYEiQq6000+j+k5U/Mw==", + "dev": true, + "dependencies": { + "@parcel/config-default": "2.8.0", + "@parcel/core": "2.8.0", + "@parcel/diagnostic": "2.8.0", + "@parcel/events": "2.8.0", + "@parcel/fs": "2.8.0", + "@parcel/logger": "2.8.0", + "@parcel/package-manager": "2.8.0", + "@parcel/reporter-cli": "2.8.0", + "@parcel/reporter-dev-server": "2.8.0", + "@parcel/utils": "2.8.0", + "chalk": "^4.1.0", + "commander": "^7.0.0", + "get-port": "^4.2.0", + "v8-compile-cache": "^2.0.0" + }, + "bin": { + "parcel": "lib/bin.js" + }, + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/parent-module": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", + "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", + "dev": true, + "dependencies": { + "callsites": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/parse-json": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.2.0.tgz", + "integrity": "sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==", + "dev": true, + "dependencies": { + "@babel/code-frame": "^7.0.0", + "error-ex": "^1.3.1", + "json-parse-even-better-errors": "^2.3.0", + "lines-and-columns": "^1.1.6" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/path-type": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", + "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/picocolors": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz", + "integrity": "sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==", + "dev": true + }, + "node_modules/postcss-value-parser": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz", + "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==", + "dev": true + }, + "node_modules/posthtml": { + "version": "0.16.6", + "resolved": "https://registry.npmjs.org/posthtml/-/posthtml-0.16.6.tgz", + "integrity": "sha512-JcEmHlyLK/o0uGAlj65vgg+7LIms0xKXe60lcDOTU7oVX/3LuEuLwrQpW3VJ7de5TaFKiW4kWkaIpJL42FEgxQ==", + "dev": true, + "dependencies": { + "posthtml-parser": "^0.11.0", + "posthtml-render": "^3.0.0" + }, + "engines": { + "node": ">=12.0.0" + } + }, + "node_modules/posthtml-parser": { + "version": "0.10.2", + "resolved": "https://registry.npmjs.org/posthtml-parser/-/posthtml-parser-0.10.2.tgz", + "integrity": "sha512-PId6zZ/2lyJi9LiKfe+i2xv57oEjJgWbsHGGANwos5AvdQp98i6AtamAl8gzSVFGfQ43Glb5D614cvZf012VKg==", + "dev": true, + "dependencies": { + "htmlparser2": "^7.1.1" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/posthtml-render": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/posthtml-render/-/posthtml-render-3.0.0.tgz", + "integrity": "sha512-z+16RoxK3fUPgwaIgH9NGnK1HKY9XIDpydky5eQGgAFVXTCSezalv9U2jQuNV+Z9qV1fDWNzldcw4eK0SSbqKA==", + "dev": true, + "dependencies": { + "is-json": "^2.0.1" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/posthtml/node_modules/posthtml-parser": { + "version": "0.11.0", + "resolved": "https://registry.npmjs.org/posthtml-parser/-/posthtml-parser-0.11.0.tgz", + "integrity": "sha512-QecJtfLekJbWVo/dMAA+OSwY79wpRmbqS5TeXvXSX+f0c6pW4/SE6inzZ2qkU7oAMCPqIDkZDvd/bQsSFUnKyw==", + "dev": true, + "dependencies": { + "htmlparser2": "^7.1.1" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/react-error-overlay": { + "version": "6.0.9", + "resolved": "https://registry.npmjs.org/react-error-overlay/-/react-error-overlay-6.0.9.tgz", + "integrity": "sha512-nQTTcUu+ATDbrSD1BZHr5kgSD4oF8OFjxun8uAaL8RwPBacGBNPf/yAuVVdx17N8XNzRDMrZ9XcKZHCjPW+9ew==", + "dev": true + }, + "node_modules/react-refresh": { + "version": "0.9.0", + "resolved": "https://registry.npmjs.org/react-refresh/-/react-refresh-0.9.0.tgz", + "integrity": "sha512-Gvzk7OZpiqKSkxsQvO/mbTN1poglhmAV7gR/DdIrRrSMXraRQQlfikRJOr3Nb9GTMPC5kof948Zy6jJZIFtDvQ==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/regenerator-runtime": { + "version": "0.13.11", + "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.11.tgz", + "integrity": "sha512-kY1AZVr2Ra+t+piVaJ4gxaFaReZVH40AKNo7UCX6W+dEwBo/2oZJzqfuN1qLq1oL45o56cPaTXELwrTh8Fpggg==", + "dev": true + }, + "node_modules/resolve-from": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", + "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/safe-buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "node_modules/semver": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", + "dev": true, + "bin": { + "semver": "bin/semver" + } + }, + "node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/source-map-support": { + "version": "0.5.21", + "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.21.tgz", + "integrity": "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==", + "dev": true, + "dependencies": { + "buffer-from": "^1.0.0", + "source-map": "^0.6.0" + } + }, + "node_modules/stable": { + "version": "0.1.8", + "resolved": "https://registry.npmjs.org/stable/-/stable-0.1.8.tgz", + "integrity": "sha512-ji9qxRnOVfcuLDySj9qzhGSEFVobyt1kIOSkj1qZzYLzq7Tos/oUUWvotUPQLlrsidqsK6tBH89Bc9kL5zHA6w==", + "deprecated": "Modern JS already guarantees Array#sort() is a stable sort, so this library is deprecated. See the compatibility table on MDN: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/sort#browser_compatibility", + "dev": true + }, + "node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/svgo": { + "version": "2.8.0", + "resolved": "https://registry.npmjs.org/svgo/-/svgo-2.8.0.tgz", + "integrity": "sha512-+N/Q9kV1+F+UeWYoSiULYo4xYSDQlTgb+ayMobAXPwMnLvop7oxKMo9OzIrX5x3eS4L4f2UHhc9axXwY8DpChg==", + "dev": true, + "dependencies": { + "@trysound/sax": "0.2.0", + "commander": "^7.2.0", + "css-select": "^4.1.3", + "css-tree": "^1.1.3", + "csso": "^4.2.0", + "picocolors": "^1.0.0", + "stable": "^0.1.8" + }, + "bin": { + "svgo": "bin/svgo" + }, + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/term-size": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/term-size/-/term-size-2.2.1.tgz", + "integrity": "sha512-wK0Ri4fOGjv/XPy8SBHZChl8CM7uMc5VML7SqiQ0zG7+J5Vr+RMQDoHa2CNT6KHUnTGIXH34UDMkPzAUyapBZg==", + "dev": true, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/terser": { + "version": "5.16.1", + "resolved": "https://registry.npmjs.org/terser/-/terser-5.16.1.tgz", + "integrity": "sha512-xvQfyfA1ayT0qdK47zskQgRZeWLoOQ8JQ6mIgRGVNwZKdQMU+5FkCBjmv4QjcrTzyZquRw2FVtlJSRUmMKQslw==", + "dev": true, + "dependencies": { + "@jridgewell/source-map": "^0.3.2", + "acorn": "^8.5.0", + "commander": "^2.20.0", + "source-map-support": "~0.5.20" + }, + "bin": { + "terser": "bin/terser" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/terser/node_modules/commander": { + "version": "2.20.3", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", + "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", + "dev": true + }, + "node_modules/timsort": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/timsort/-/timsort-0.3.0.tgz", + "integrity": "sha512-qsdtZH+vMoCARQtyod4imc2nIJwg9Cc7lPRrw9CzF8ZKR0khdr8+2nX80PBhET3tcyTtJDxAffGh2rXH4tyU8A==", + "dev": true + }, + "node_modules/tslib": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.4.1.tgz", + "integrity": "sha512-tGyy4dAjRIEwI7BzsB0lynWgOpfqjUdq91XXAlIWD2OwKBH7oCl/GZG/HT4BOHrTlPMOASlMQ7veyTqpmRcrNA==", + "dev": true + }, + "node_modules/type-fest": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", + "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/typescript": { + "version": "4.9.3", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.9.3.tgz", + "integrity": "sha512-CIfGzTelbKNEnLpLdGFgdyKhG23CKdKgQPOBc+OUNrkJ2vr+KSzsSV5kq5iWhEQbok+quxgGzrAtGWCyU7tHnA==", + "dev": true, + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" + }, + "engines": { + "node": ">=4.2.0" + } + }, + "node_modules/update-browserslist-db": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.0.10.tgz", + "integrity": "sha512-OztqDenkfFkbSG+tRxBeAnCVPckDBcvibKd35yDONx6OU8N7sqgwc7rCbkJ/WcYtVRZ4ba68d6byhC21GFh7sQ==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/browserslist" + } + ], + "dependencies": { + "escalade": "^3.1.1", + "picocolors": "^1.0.0" + }, + "bin": { + "browserslist-lint": "cli.js" + }, + "peerDependencies": { + "browserslist": ">= 4.21.0" + } + }, + "node_modules/utility-types": { + "version": "3.10.0", + "resolved": "https://registry.npmjs.org/utility-types/-/utility-types-3.10.0.tgz", + "integrity": "sha512-O11mqxmi7wMKCo6HKFt5AhO4BwY3VV68YU07tgxfz8zJTIxr4BpsezN49Ffwy9j3ZpwwJp4fkRwjRzq3uWE6Rg==", + "dev": true, + "engines": { + "node": ">= 4" + } + }, + "node_modules/v8-compile-cache": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/v8-compile-cache/-/v8-compile-cache-2.3.0.tgz", + "integrity": "sha512-l8lCEmLcLYZh4nbunNZvQCJc5pv7+RCwa8q/LdUx8u7lsWvPDKmpodJAJNwkAhJC//dFY48KuIEmjtd4RViDrA==", + "dev": true + }, + "node_modules/weak-lru-cache": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/weak-lru-cache/-/weak-lru-cache-1.2.2.tgz", + "integrity": "sha512-DEAoo25RfSYMuTGc9vPJzZcZullwIqRDSI9LOy+fkCJPi6hykCnfKaXTuPBDuXAUcqHXyOgFtHNp/kB2FjYHbw==", + "dev": true + }, + "node_modules/xxhash-wasm": { + "version": "0.4.2", + "resolved": "https://registry.npmjs.org/xxhash-wasm/-/xxhash-wasm-0.4.2.tgz", + "integrity": "sha512-/eyHVRJQCirEkSZ1agRSCwriMhwlyUcFkXD5TPVSLP+IPzjsqMVzZwdoczLp1SoQU0R3dxz1RpIK+4YNQbCVOA==", + "dev": true + }, + "node_modules/yaml": { + "version": "1.10.2", + "resolved": "https://registry.npmjs.org/yaml/-/yaml-1.10.2.tgz", + "integrity": "sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg==", + "dev": true, + "engines": { + "node": ">= 6" + } + }, + "node_modules/zig-js": { + "resolved": "../vendor/zig-js/js", + "link": true + } + }, + "dependencies": { + "@babel/code-frame": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.18.6.tgz", + "integrity": "sha512-TDCmlK5eOvH+eH7cdAFlNXeVJqWIQ7gW9tY1GJIpUtFb6CmjVyq2VM3u71bOyR8CRihcCgMUYoDNyLXao3+70Q==", + "dev": true, + "requires": { + "@babel/highlight": "^7.18.6" + } + }, + "@babel/helper-validator-identifier": { + "version": "7.19.1", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.19.1.tgz", + "integrity": "sha512-awrNfaMtnHUr653GgGEs++LlAvW6w+DcPrOliSMXWCKo597CwL5Acf/wWdNkf/tfEQE3mjkeD1YOVZOUV/od1w==", + "dev": true + }, + "@babel/highlight": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.18.6.tgz", + "integrity": "sha512-u7stbOuYjaPezCuLj29hNW1v64M2Md2qupEKP1fHc7WdOA3DgLh37suiSrZYY7haUB7iBeQZ9P1uiRF359do3g==", + "dev": true, + "requires": { + "@babel/helper-validator-identifier": "^7.18.6", + "chalk": "^2.0.0", + "js-tokens": "^4.0.0" + }, + "dependencies": { + "ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "requires": { + "color-convert": "^1.9.0" + } + }, + "chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, + "requires": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + } + }, + "color-convert": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "dev": true, + "requires": { + "color-name": "1.1.3" + } + }, + "color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==", + "dev": true + }, + "has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", + "dev": true + }, + "supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "requires": { + "has-flag": "^3.0.0" + } + } + } + }, + "@jridgewell/gen-mapping": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.2.tgz", + "integrity": "sha512-mh65xKQAzI6iBcFzwv28KVWSmCkdRBWoOh+bYQGW3+6OZvbbN3TqMGo5hqYxQniRcH9F2VZIoJCm4pa3BPDK/A==", + "dev": true, + "requires": { + "@jridgewell/set-array": "^1.0.1", + "@jridgewell/sourcemap-codec": "^1.4.10", + "@jridgewell/trace-mapping": "^0.3.9" + } + }, + "@jridgewell/resolve-uri": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.0.tgz", + "integrity": "sha512-F2msla3tad+Mfht5cJq7LSXcdudKTWCVYUgw6pLFOOHSTtZlj6SWNYAp+AhuqLmWdBO2X5hPrLcu8cVP8fy28w==", + "dev": true + }, + "@jridgewell/set-array": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.1.2.tgz", + "integrity": "sha512-xnkseuNADM0gt2bs+BvhO0p78Mk762YnZdsuzFV018NoG1Sj1SCQvpSqa7XUaTam5vAGasABV9qXASMKnFMwMw==", + "dev": true + }, + "@jridgewell/source-map": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/@jridgewell/source-map/-/source-map-0.3.2.tgz", + "integrity": "sha512-m7O9o2uR8k2ObDysZYzdfhb08VuEml5oWGiosa1VdaPZ/A6QyPkAJuwN0Q1lhULOf6B7MtQmHENS743hWtCrgw==", + "dev": true, + "requires": { + "@jridgewell/gen-mapping": "^0.3.0", + "@jridgewell/trace-mapping": "^0.3.9" + } + }, + "@jridgewell/sourcemap-codec": { + "version": "1.4.14", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.14.tgz", + "integrity": "sha512-XPSJHWmi394fuUuzDnGz1wiKqWfo1yXecHQMRf2l6hztTO+nPru658AyDngaBe7isIxEkRsPR3FZh+s7iVa4Uw==", + "dev": true + }, + "@jridgewell/trace-mapping": { + "version": "0.3.17", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.17.tgz", + "integrity": "sha512-MCNzAp77qzKca9+W/+I0+sEpaUnZoeasnghNeVc41VZCEKaCH73Vq3BZZ/SzWIgrqE4H4ceI+p+b6C0mHf9T4g==", + "dev": true, + "requires": { + "@jridgewell/resolve-uri": "3.1.0", + "@jridgewell/sourcemap-codec": "1.4.14" + } + }, + "@lezer/common": { + "version": "0.15.12", + "resolved": "https://registry.npmjs.org/@lezer/common/-/common-0.15.12.tgz", + "integrity": "sha512-edfwCxNLnzq5pBA/yaIhwJ3U3Kz8VAUOTRg0hhxaizaI1N+qxV7EXDv/kLCkLeq2RzSFvxexlaj5Mzfn2kY0Ig==", + "dev": true + }, + "@lezer/lr": { + "version": "0.15.8", + "resolved": "https://registry.npmjs.org/@lezer/lr/-/lr-0.15.8.tgz", + "integrity": "sha512-bM6oE6VQZ6hIFxDNKk8bKPa14hqFrV07J/vHGOeiAbJReIaQXmkVb6xQu4MR+JBTLa5arGRyAAjJe1qaQt3Uvg==", + "dev": true, + "requires": { + "@lezer/common": "^0.15.0" + } + }, + "@lmdb/lmdb-darwin-arm64": { + "version": "2.5.2", + "resolved": "https://registry.npmjs.org/@lmdb/lmdb-darwin-arm64/-/lmdb-darwin-arm64-2.5.2.tgz", + "integrity": "sha512-+F8ioQIUN68B4UFiIBYu0QQvgb9FmlKw2ctQMSBfW2QBrZIxz9vD9jCGqTCPqZBRbPHAS/vG1zSXnKqnS2ch/A==", + "dev": true, + "optional": true + }, + "@lmdb/lmdb-darwin-x64": { + "version": "2.5.2", + "resolved": "https://registry.npmjs.org/@lmdb/lmdb-darwin-x64/-/lmdb-darwin-x64-2.5.2.tgz", + "integrity": "sha512-KvPH56KRLLx4KSfKBx0m1r7GGGUMXm0jrKmNE7plbHlesZMuPJICtn07HYgQhj1LNsK7Yqwuvnqh1QxhJnF1EA==", + "dev": true, + "optional": true + }, + "@lmdb/lmdb-linux-arm": { + "version": "2.5.2", + "resolved": "https://registry.npmjs.org/@lmdb/lmdb-linux-arm/-/lmdb-linux-arm-2.5.2.tgz", + "integrity": "sha512-5kQAP21hAkfW5Bl+e0P57dV4dGYnkNIpR7f/GAh6QHlgXx+vp/teVj4PGRZaKAvt0GX6++N6hF8NnGElLDuIDw==", + "dev": true, + "optional": true + }, + "@lmdb/lmdb-linux-arm64": { + "version": "2.5.2", + "resolved": "https://registry.npmjs.org/@lmdb/lmdb-linux-arm64/-/lmdb-linux-arm64-2.5.2.tgz", + "integrity": "sha512-aLl89VHL/wjhievEOlPocoefUyWdvzVrcQ/MHQYZm2JfV1jUsrbr/ZfkPPUFvZBf+VSE+Q0clWs9l29PCX1hTQ==", + "dev": true, + "optional": true + }, + "@lmdb/lmdb-linux-x64": { + "version": "2.5.2", + "resolved": "https://registry.npmjs.org/@lmdb/lmdb-linux-x64/-/lmdb-linux-x64-2.5.2.tgz", + "integrity": "sha512-xUdUfwDJLGjOUPH3BuPBt0NlIrR7f/QHKgu3GZIXswMMIihAekj2i97oI0iWG5Bok/b+OBjHPfa8IU9velnP/Q==", + "dev": true, + "optional": true + }, + "@lmdb/lmdb-win32-x64": { + "version": "2.5.2", + "resolved": "https://registry.npmjs.org/@lmdb/lmdb-win32-x64/-/lmdb-win32-x64-2.5.2.tgz", + "integrity": "sha512-zrBczSbXKxEyK2ijtbRdICDygRqWSRPpZMN5dD1T8VMEW5RIhIbwFWw2phDRXuBQdVDpSjalCIUMWMV2h3JaZA==", + "dev": true, + "optional": true + }, + "@mischnic/json-sourcemap": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/@mischnic/json-sourcemap/-/json-sourcemap-0.1.0.tgz", + "integrity": "sha512-dQb3QnfNqmQNYA4nFSN/uLaByIic58gOXq4Y4XqLOWmOrw73KmJPt/HLyG0wvn1bnR6mBKs/Uwvkh+Hns1T0XA==", + "dev": true, + "requires": { + "@lezer/common": "^0.15.7", + "@lezer/lr": "^0.15.4", + "json5": "^2.2.1" + } + }, + "@msgpackr-extract/msgpackr-extract-darwin-arm64": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/@msgpackr-extract/msgpackr-extract-darwin-arm64/-/msgpackr-extract-darwin-arm64-2.2.0.tgz", + "integrity": "sha512-Z9LFPzfoJi4mflGWV+rv7o7ZbMU5oAU9VmzCgL240KnqDW65Y2HFCT3MW06/ITJSnbVLacmcEJA8phywK7JinQ==", + "dev": true, + "optional": true + }, + "@msgpackr-extract/msgpackr-extract-darwin-x64": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/@msgpackr-extract/msgpackr-extract-darwin-x64/-/msgpackr-extract-darwin-x64-2.2.0.tgz", + "integrity": "sha512-vq0tT8sjZsy4JdSqmadWVw6f66UXqUCabLmUVHZwUFzMgtgoIIQjT4VVRHKvlof3P/dMCkbMJ5hB1oJ9OWHaaw==", + "dev": true, + "optional": true + }, + "@msgpackr-extract/msgpackr-extract-linux-arm": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/@msgpackr-extract/msgpackr-extract-linux-arm/-/msgpackr-extract-linux-arm-2.2.0.tgz", + "integrity": "sha512-SaJ3Qq4lX9Syd2xEo9u3qPxi/OB+5JO/ngJKK97XDpa1C587H9EWYO6KD8995DAjSinWvdHKRrCOXVUC5fvGOg==", + "dev": true, + "optional": true + }, + "@msgpackr-extract/msgpackr-extract-linux-arm64": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/@msgpackr-extract/msgpackr-extract-linux-arm64/-/msgpackr-extract-linux-arm64-2.2.0.tgz", + "integrity": "sha512-hlxxLdRmPyq16QCutUtP8Tm6RDWcyaLsRssaHROatgnkOxdleMTgetf9JsdncL8vLh7FVy/RN9i3XR5dnb9cRA==", + "dev": true, + "optional": true + }, + "@msgpackr-extract/msgpackr-extract-linux-x64": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/@msgpackr-extract/msgpackr-extract-linux-x64/-/msgpackr-extract-linux-x64-2.2.0.tgz", + "integrity": "sha512-94y5PJrSOqUNcFKmOl7z319FelCLAE0rz/jPCWS+UtdMZvpa4jrQd+cJPQCLp2Fes1yAW/YUQj/Di6YVT3c3Iw==", + "dev": true, + "optional": true + }, + "@msgpackr-extract/msgpackr-extract-win32-x64": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/@msgpackr-extract/msgpackr-extract-win32-x64/-/msgpackr-extract-win32-x64-2.2.0.tgz", + "integrity": "sha512-XrC0JzsqQSvOyM3t04FMLO6z5gCuhPE6k4FXuLK5xf52ZbdvcFe1yBmo7meCew9B8G2f0T9iu9t3kfTYRYROgA==", + "dev": true, + "optional": true + }, + "@parcel/bundler-default": { + "version": "2.8.0", + "resolved": "https://registry.npmjs.org/@parcel/bundler-default/-/bundler-default-2.8.0.tgz", + "integrity": "sha512-OvDDhxX4LwfGe7lYVMbJMzqNcDk8ydOqNw0Hra9WPgl0m5gju/eVIbDvot3JXp5F96FmV36uCxdODJhKTNoAzQ==", + "dev": true, + "requires": { + "@parcel/diagnostic": "2.8.0", + "@parcel/graph": "2.8.0", + "@parcel/hash": "2.8.0", + "@parcel/plugin": "2.8.0", + "@parcel/utils": "2.8.0", + "nullthrows": "^1.1.1" + } + }, + "@parcel/cache": { + "version": "2.8.0", + "resolved": "https://registry.npmjs.org/@parcel/cache/-/cache-2.8.0.tgz", + "integrity": "sha512-k945hrafMDR2wyCKyZYgwypeLLuZWce6FzhgunI4taBUeVnNCcpFAWzbfOVQ39SqZTGDqG3MNT+VuehssHXxyg==", + "dev": true, + "requires": { + "@parcel/fs": "2.8.0", + "@parcel/logger": "2.8.0", + "@parcel/utils": "2.8.0", + "lmdb": "2.5.2" + } + }, + "@parcel/codeframe": { + "version": "2.8.0", + "resolved": "https://registry.npmjs.org/@parcel/codeframe/-/codeframe-2.8.0.tgz", + "integrity": "sha512-821d+KVcpEvJNMj9WMC39xXZK6zvRS/HUjQag2f3DkcRcZwk1uXJZdW6p1EB7C3e4e/0KSK3NTSVGEvbOSR+9w==", + "dev": true, + "requires": { + "chalk": "^4.1.0" + } + }, + "@parcel/compressor-raw": { + "version": "2.8.0", + "resolved": "https://registry.npmjs.org/@parcel/compressor-raw/-/compressor-raw-2.8.0.tgz", + "integrity": "sha512-tM49t0gDQnwJbrDCeoCn9LRc8inZ/TSPQTttJTfcmFHHFqEllI0ZDVG0AiQw5NOMQbBLYiKun1adXn8pkcPLEA==", + "dev": true, + "requires": { + "@parcel/plugin": "2.8.0" + } + }, + "@parcel/config-default": { + "version": "2.8.0", + "resolved": "https://registry.npmjs.org/@parcel/config-default/-/config-default-2.8.0.tgz", + "integrity": "sha512-j9g50QNSLjuNpY0TP01EgGJPxWNes9d+e8+N07Z5Wv0u+UUnJ2uIOpo7PVn7ullOGhm1f9lP4KsJenu5gWb+cg==", + "dev": true, + "requires": { + "@parcel/bundler-default": "2.8.0", + "@parcel/compressor-raw": "2.8.0", + "@parcel/namer-default": "2.8.0", + "@parcel/optimizer-css": "2.8.0", + "@parcel/optimizer-htmlnano": "2.8.0", + "@parcel/optimizer-image": "2.8.0", + "@parcel/optimizer-svgo": "2.8.0", + "@parcel/optimizer-terser": "2.8.0", + "@parcel/packager-css": "2.8.0", + "@parcel/packager-html": "2.8.0", + "@parcel/packager-js": "2.8.0", + "@parcel/packager-raw": "2.8.0", + "@parcel/packager-svg": "2.8.0", + "@parcel/reporter-dev-server": "2.8.0", + "@parcel/resolver-default": "2.8.0", + "@parcel/runtime-browser-hmr": "2.8.0", + "@parcel/runtime-js": "2.8.0", + "@parcel/runtime-react-refresh": "2.8.0", + "@parcel/runtime-service-worker": "2.8.0", + "@parcel/transformer-babel": "2.8.0", + "@parcel/transformer-css": "2.8.0", + "@parcel/transformer-html": "2.8.0", + "@parcel/transformer-image": "2.8.0", + "@parcel/transformer-js": "2.8.0", + "@parcel/transformer-json": "2.8.0", + "@parcel/transformer-postcss": "2.8.0", + "@parcel/transformer-posthtml": "2.8.0", + "@parcel/transformer-raw": "2.8.0", + "@parcel/transformer-react-refresh-wrap": "2.8.0", + "@parcel/transformer-svg": "2.8.0" + } + }, + "@parcel/core": { + "version": "2.8.0", + "resolved": "https://registry.npmjs.org/@parcel/core/-/core-2.8.0.tgz", + "integrity": "sha512-udzbe3jjbpfKlRE9pdlROAa+lvAjS1L/AzN6r2j1y/Fsn7ze/NfvnCFw6o2YNIrXg002aQ7M1St/x1fdGfmVKA==", + "dev": true, + "requires": { + "@mischnic/json-sourcemap": "^0.1.0", + "@parcel/cache": "2.8.0", + "@parcel/diagnostic": "2.8.0", + "@parcel/events": "2.8.0", + "@parcel/fs": "2.8.0", + "@parcel/graph": "2.8.0", + "@parcel/hash": "2.8.0", + "@parcel/logger": "2.8.0", + "@parcel/package-manager": "2.8.0", + "@parcel/plugin": "2.8.0", + "@parcel/source-map": "^2.1.1", + "@parcel/types": "2.8.0", + "@parcel/utils": "2.8.0", + "@parcel/workers": "2.8.0", + "abortcontroller-polyfill": "^1.1.9", + "base-x": "^3.0.8", + "browserslist": "^4.6.6", + "clone": "^2.1.1", + "dotenv": "^7.0.0", + "dotenv-expand": "^5.1.0", + "json5": "^2.2.0", + "msgpackr": "^1.5.4", + "nullthrows": "^1.1.1", + "semver": "^5.7.1" + } + }, + "@parcel/diagnostic": { + "version": "2.8.0", + "resolved": "https://registry.npmjs.org/@parcel/diagnostic/-/diagnostic-2.8.0.tgz", + "integrity": "sha512-ERnk0zDvm0jQUSj1M+2PLiwVC6nWrtuFEuye6VGuxRDcp9NHbz6gwApeEYxFkPsb3TQPhNjnXXm5nmAw1bpWWw==", + "dev": true, + "requires": { + "@mischnic/json-sourcemap": "^0.1.0", + "nullthrows": "^1.1.1" + } + }, + "@parcel/events": { + "version": "2.8.0", + "resolved": "https://registry.npmjs.org/@parcel/events/-/events-2.8.0.tgz", + "integrity": "sha512-xqSZYY3oONM4IZm9+vhyFqX+KFIl145veIczUikwGJlcJZQfAAw736syPx6ecpB+m1EVg3AlvJWy7Lmel4Ak+Q==", + "dev": true + }, + "@parcel/fs": { + "version": "2.8.0", + "resolved": "https://registry.npmjs.org/@parcel/fs/-/fs-2.8.0.tgz", + "integrity": "sha512-v3DbJlpl8v2/VRlZPw7cy+0myi0YfLblGZcwDvqIsWS35qyxD2rmtYV8u1BusonbgmJeaKiopSECmJkumt0jCw==", + "dev": true, + "requires": { + "@parcel/fs-search": "2.8.0", + "@parcel/types": "2.8.0", + "@parcel/utils": "2.8.0", + "@parcel/watcher": "^2.0.7", + "@parcel/workers": "2.8.0" + } + }, + "@parcel/fs-search": { + "version": "2.8.0", + "resolved": "https://registry.npmjs.org/@parcel/fs-search/-/fs-search-2.8.0.tgz", + "integrity": "sha512-yo7/Y8DCFlhOlIBb5SsRDTkM+7g0DY9sK57iw3hn2z1tGoIiIRptrieImFYSizs7HfDwDY/PMLfORmUdoReDzQ==", + "dev": true, + "requires": { + "detect-libc": "^1.0.3" + } + }, + "@parcel/graph": { + "version": "2.8.0", + "resolved": "https://registry.npmjs.org/@parcel/graph/-/graph-2.8.0.tgz", + "integrity": "sha512-JvAyvBpGmhZ30bi+hStQr52eu+InfJBoiN9Z/32byIWhXEl02EAOwfsPqAe+FGCsdgXnnCGg5F9ZCqwzZ9dwbw==", + "dev": true, + "requires": { + "@parcel/utils": "2.8.0", + "nullthrows": "^1.1.1" + } + }, + "@parcel/hash": { + "version": "2.8.0", + "resolved": "https://registry.npmjs.org/@parcel/hash/-/hash-2.8.0.tgz", + "integrity": "sha512-KV1+96t7Nukth5K7ldUXjVr8ZTH9Dohl49K0Tc+5Qkysif0OxwcDtpVDmcnrUnWmqdBX0AdoLY0Q2Nnly89n/w==", + "dev": true, + "requires": { + "detect-libc": "^1.0.3", + "xxhash-wasm": "^0.4.2" + } + }, + "@parcel/logger": { + "version": "2.8.0", + "resolved": "https://registry.npmjs.org/@parcel/logger/-/logger-2.8.0.tgz", + "integrity": "sha512-W+7rKsLxLUX6xRmP8PhGWcG48PqrzTPeMWpgSds5nXxAHEFh4cYbkwPKGoTU65a9xUDVyqNreHNIKyizgwAZHQ==", + "dev": true, + "requires": { + "@parcel/diagnostic": "2.8.0", + "@parcel/events": "2.8.0" + } + }, + "@parcel/markdown-ansi": { + "version": "2.8.0", + "resolved": "https://registry.npmjs.org/@parcel/markdown-ansi/-/markdown-ansi-2.8.0.tgz", + "integrity": "sha512-xItzXmc3btFhJXsIbE946iaqE6STd2xe5H0zSIaZVXEeucCtMzcd4hxRELquxPstlrAOrrp/lrRpbAlMhso9iA==", + "dev": true, + "requires": { + "chalk": "^4.1.0" + } + }, + "@parcel/namer-default": { + "version": "2.8.0", + "resolved": "https://registry.npmjs.org/@parcel/namer-default/-/namer-default-2.8.0.tgz", + "integrity": "sha512-cVCx2kJA/Bv7O9pVad1UOibaybR/B+QdWV8Ols8HH4lC2gyjLBXEIR0uuPSEbkGwMEcofG6zA3MwsoPa6r5lBg==", + "dev": true, + "requires": { + "@parcel/diagnostic": "2.8.0", + "@parcel/plugin": "2.8.0", + "nullthrows": "^1.1.1" + } + }, + "@parcel/node-resolver-core": { + "version": "2.8.0", + "resolved": "https://registry.npmjs.org/@parcel/node-resolver-core/-/node-resolver-core-2.8.0.tgz", + "integrity": "sha512-cECSh08NSRt1csmmMeKxlnO6ZhXRTuRijkHKFa4iG5hPL+3Cu04YGhuK/QWlP5vNCPVrH3ISlhzlPU5fAi/nEg==", + "dev": true, + "requires": { + "@parcel/diagnostic": "2.8.0", + "@parcel/utils": "2.8.0", + "nullthrows": "^1.1.1", + "semver": "^5.7.1" + } + }, + "@parcel/optimizer-css": { + "version": "2.8.0", + "resolved": "https://registry.npmjs.org/@parcel/optimizer-css/-/optimizer-css-2.8.0.tgz", + "integrity": "sha512-T5r3gZVm1xFw6l//iLkzLDUvFzNTUvL5kAtyU5gS5yH/dg7eCS09Km/c2anViQnmXwFUt7zIlBovj1doxAVNSw==", + "dev": true, + "requires": { + "@parcel/diagnostic": "2.8.0", + "@parcel/plugin": "2.8.0", + "@parcel/source-map": "^2.1.1", + "@parcel/utils": "2.8.0", + "browserslist": "^4.6.6", + "lightningcss": "^1.16.1", + "nullthrows": "^1.1.1" + } + }, + "@parcel/optimizer-htmlnano": { + "version": "2.8.0", + "resolved": "https://registry.npmjs.org/@parcel/optimizer-htmlnano/-/optimizer-htmlnano-2.8.0.tgz", + "integrity": "sha512-NxEKTRvue/WAU+XbQGfNIU6c7chDekdkwwv9YnCxHEOhnBu4Ok+2tdmCtPuA+4UUNszGxXlaHMnqSrjmqX2S6Q==", + "dev": true, + "requires": { + "@parcel/plugin": "2.8.0", + "htmlnano": "^2.0.0", + "nullthrows": "^1.1.1", + "posthtml": "^0.16.5", + "svgo": "^2.4.0" + } + }, + "@parcel/optimizer-image": { + "version": "2.8.0", + "resolved": "https://registry.npmjs.org/@parcel/optimizer-image/-/optimizer-image-2.8.0.tgz", + "integrity": "sha512-66eSoCCGZVRiY6U4OqqYrhQcBcHI9cOkIEbxadZYOF4cJhsskjUDJR0jLb4j2PE6QxUNYlyj5OglQqRLwhz7vA==", + "dev": true, + "requires": { + "@parcel/diagnostic": "2.8.0", + "@parcel/plugin": "2.8.0", + "@parcel/utils": "2.8.0", + "@parcel/workers": "2.8.0", + "detect-libc": "^1.0.3" + } + }, + "@parcel/optimizer-svgo": { + "version": "2.8.0", + "resolved": "https://registry.npmjs.org/@parcel/optimizer-svgo/-/optimizer-svgo-2.8.0.tgz", + "integrity": "sha512-qQzM32CzJJuniFaTZDspVn/Vtz/PJ/f89+FckLpWZJVWNihgwTHC1/F0YTDH8g6czNw5ZijwQ3xBVuJQYyIXsQ==", + "dev": true, + "requires": { + "@parcel/diagnostic": "2.8.0", + "@parcel/plugin": "2.8.0", + "@parcel/utils": "2.8.0", + "svgo": "^2.4.0" + } + }, + "@parcel/optimizer-terser": { + "version": "2.8.0", + "resolved": "https://registry.npmjs.org/@parcel/optimizer-terser/-/optimizer-terser-2.8.0.tgz", + "integrity": "sha512-slS6GWQ3u418WtJmlqlA5Njljcq4OaEdDDR2ifEwltG8POv+hsvD5AAoM2XB0GJwY97TQtdMbBu2DuDF3yM/1Q==", + "dev": true, + "requires": { + "@parcel/diagnostic": "2.8.0", + "@parcel/plugin": "2.8.0", + "@parcel/source-map": "^2.1.1", + "@parcel/utils": "2.8.0", + "nullthrows": "^1.1.1", + "terser": "^5.2.0" + } + }, + "@parcel/package-manager": { + "version": "2.8.0", + "resolved": "https://registry.npmjs.org/@parcel/package-manager/-/package-manager-2.8.0.tgz", + "integrity": "sha512-n4FgerAX1lTKKTgxmiocnos47Y+b0L60iwU6Q4cC2n4KQNRuNyfhxFXwWcqHstR9wa72JgPaDgo4k0l3Bk8FZw==", + "dev": true, + "requires": { + "@parcel/diagnostic": "2.8.0", + "@parcel/fs": "2.8.0", + "@parcel/logger": "2.8.0", + "@parcel/types": "2.8.0", + "@parcel/utils": "2.8.0", + "@parcel/workers": "2.8.0", + "semver": "^5.7.1" + } + }, + "@parcel/packager-css": { + "version": "2.8.0", + "resolved": "https://registry.npmjs.org/@parcel/packager-css/-/packager-css-2.8.0.tgz", + "integrity": "sha512-tv/Bto0P6fXjqQ9uCZ8/6b/+38Zr/N2MC7/Nbflzww/lp0k2+kkE9MVJJDr5kST/SzTBRrhbDo+yTbtdZikJYg==", + "dev": true, + "requires": { + "@parcel/plugin": "2.8.0", + "@parcel/source-map": "^2.1.1", + "@parcel/utils": "2.8.0", + "nullthrows": "^1.1.1" + } + }, + "@parcel/packager-html": { + "version": "2.8.0", + "resolved": "https://registry.npmjs.org/@parcel/packager-html/-/packager-html-2.8.0.tgz", + "integrity": "sha512-4x09v/bt767rxwGTuEw82CjheoOtIKNu4sx1gqwQOz9QowKPniXOIaD+0XmLiARdzRErucf0sL19QHfNcPAhUw==", + "dev": true, + "requires": { + "@parcel/plugin": "2.8.0", + "@parcel/types": "2.8.0", + "@parcel/utils": "2.8.0", + "nullthrows": "^1.1.1", + "posthtml": "^0.16.5" + } + }, + "@parcel/packager-js": { + "version": "2.8.0", + "resolved": "https://registry.npmjs.org/@parcel/packager-js/-/packager-js-2.8.0.tgz", + "integrity": "sha512-Tn2EtWM1TEdj4t5pt0QjBDzqrXrfRTL3WsdMipZwDSuX04KS0jedJINHjh46HOMwyfJxLbUg3xkGX7F5mYQj5g==", + "dev": true, + "requires": { + "@parcel/diagnostic": "2.8.0", + "@parcel/hash": "2.8.0", + "@parcel/plugin": "2.8.0", + "@parcel/source-map": "^2.1.1", + "@parcel/utils": "2.8.0", + "globals": "^13.2.0", + "nullthrows": "^1.1.1" + } + }, + "@parcel/packager-raw": { + "version": "2.8.0", + "resolved": "https://registry.npmjs.org/@parcel/packager-raw/-/packager-raw-2.8.0.tgz", + "integrity": "sha512-s3VniER3X2oNTlfytBGIQF+UZFVNLFWuVu1IkZ8Wg6uYQffrExDlbNDcmFCDcfvcejL3Ch5igP+L6N00f6+wAQ==", + "dev": true, + "requires": { + "@parcel/plugin": "2.8.0" + } + }, + "@parcel/packager-svg": { + "version": "2.8.0", + "resolved": "https://registry.npmjs.org/@parcel/packager-svg/-/packager-svg-2.8.0.tgz", + "integrity": "sha512-+BSpdPiNjlAne28nOjG2AyiOejAehe/+X9MxL2FIpPP7UBLNc2ekaM0mDTR5iY45YtZa57oyErBT/U6wZ1TCjw==", + "dev": true, + "requires": { + "@parcel/plugin": "2.8.0", + "@parcel/types": "2.8.0", + "@parcel/utils": "2.8.0", + "posthtml": "^0.16.4" + } + }, + "@parcel/plugin": { + "version": "2.8.0", + "resolved": "https://registry.npmjs.org/@parcel/plugin/-/plugin-2.8.0.tgz", + "integrity": "sha512-Tsf+7nDg7KauvTVY6rGc7CmgJruKSwJ54KJ9s5nYFFP9nfwmyqbayCi9xOxicWU9zIHfuF5Etwf17lcA0oAvzw==", + "dev": true, + "requires": { + "@parcel/types": "2.8.0" + } + }, + "@parcel/reporter-cli": { + "version": "2.8.0", + "resolved": "https://registry.npmjs.org/@parcel/reporter-cli/-/reporter-cli-2.8.0.tgz", + "integrity": "sha512-ea4/Lp+2jDbzb/tfTgUKzYU51FK8wcewDoYNr06uL+wvx/vzYIDG0jHfzaOTasREnm7ECDr1Zu2Iknrgk1STqQ==", + "dev": true, + "requires": { + "@parcel/plugin": "2.8.0", + "@parcel/types": "2.8.0", + "@parcel/utils": "2.8.0", + "chalk": "^4.1.0", + "term-size": "^2.2.1" + } + }, + "@parcel/reporter-dev-server": { + "version": "2.8.0", + "resolved": "https://registry.npmjs.org/@parcel/reporter-dev-server/-/reporter-dev-server-2.8.0.tgz", + "integrity": "sha512-wg6hUrQ8vUmvlP2fg8YEzYndmq7hWZ21ZgBv4So1Z65I+Qav85Uox7bjGLCSJwEAjdjFKfhV9RGULGzqh8vcAQ==", + "dev": true, + "requires": { + "@parcel/plugin": "2.8.0", + "@parcel/utils": "2.8.0" + } + }, + "@parcel/resolver-default": { + "version": "2.8.0", + "resolved": "https://registry.npmjs.org/@parcel/resolver-default/-/resolver-default-2.8.0.tgz", + "integrity": "sha512-kO5W+O3Ql6NXNFS6lvfSSt1R+PxO1atNLYxZdVSM6+QQxRMiztfqzZs//RM+oUp+af6muDSUPlNs+RORX0fing==", + "dev": true, + "requires": { + "@parcel/node-resolver-core": "2.8.0", + "@parcel/plugin": "2.8.0" + } + }, + "@parcel/runtime-browser-hmr": { + "version": "2.8.0", + "resolved": "https://registry.npmjs.org/@parcel/runtime-browser-hmr/-/runtime-browser-hmr-2.8.0.tgz", + "integrity": "sha512-zV5wGGvm1cDwWAzkwPUaKh6inWYKxq67YWY4G396PXLMxddM9SQC1c7iFM60OPnD4A+BMOLOy7N6//20h15Dlg==", + "dev": true, + "requires": { + "@parcel/plugin": "2.8.0", + "@parcel/utils": "2.8.0" + } + }, + "@parcel/runtime-js": { + "version": "2.8.0", + "resolved": "https://registry.npmjs.org/@parcel/runtime-js/-/runtime-js-2.8.0.tgz", + "integrity": "sha512-IwT1rX8ZamoYZv0clfswZemfXcIfk+YXwNsqXwzzh6TaMGagj/ZZl1llkn7ERQFq4EoLEoDGGkxqsrJjBp9NDQ==", + "dev": true, + "requires": { + "@parcel/plugin": "2.8.0", + "@parcel/utils": "2.8.0", + "nullthrows": "^1.1.1" + } + }, + "@parcel/runtime-react-refresh": { + "version": "2.8.0", + "resolved": "https://registry.npmjs.org/@parcel/runtime-react-refresh/-/runtime-react-refresh-2.8.0.tgz", + "integrity": "sha512-a6uuZWkl+mJur2WLZKmpEqq1P06tvRwqGefYbE26DWpwXwU9dLpfnv/nT0hqCmVDHd2TkMyCffolSmq1vY05ew==", + "dev": true, + "requires": { + "@parcel/plugin": "2.8.0", + "@parcel/utils": "2.8.0", + "react-error-overlay": "6.0.9", + "react-refresh": "^0.9.0" + } + }, + "@parcel/runtime-service-worker": { + "version": "2.8.0", + "resolved": "https://registry.npmjs.org/@parcel/runtime-service-worker/-/runtime-service-worker-2.8.0.tgz", + "integrity": "sha512-Q3Q2O/axQbFi/5Z+BidLB3qhmYdZLTMDagZtsmyH7CktDkZVNV/0UoOGYlqoK06T4cww3XjLSEomXbBu9TlQKQ==", + "dev": true, + "requires": { + "@parcel/plugin": "2.8.0", + "@parcel/utils": "2.8.0", + "nullthrows": "^1.1.1" + } + }, + "@parcel/source-map": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/@parcel/source-map/-/source-map-2.1.1.tgz", + "integrity": "sha512-Ejx1P/mj+kMjQb8/y5XxDUn4reGdr+WyKYloBljpppUy8gs42T+BNoEOuRYqDVdgPc6NxduzIDoJS9pOFfV5Ew==", + "dev": true, + "requires": { + "detect-libc": "^1.0.3" + } + }, + "@parcel/transformer-babel": { + "version": "2.8.0", + "resolved": "https://registry.npmjs.org/@parcel/transformer-babel/-/transformer-babel-2.8.0.tgz", + "integrity": "sha512-ie+wFe9pucdnRyX2PTN9amOHrhr/IOwUEAfTz/3dPydOYCuX7ErEngCpI9fBzdYE2AV6/noEwC2Mjeoyz9mT2A==", + "dev": true, + "requires": { + "@parcel/diagnostic": "2.8.0", + "@parcel/plugin": "2.8.0", + "@parcel/source-map": "^2.1.1", + "@parcel/utils": "2.8.0", + "browserslist": "^4.6.6", + "json5": "^2.2.0", + "nullthrows": "^1.1.1", + "semver": "^5.7.0" + } + }, + "@parcel/transformer-css": { + "version": "2.8.0", + "resolved": "https://registry.npmjs.org/@parcel/transformer-css/-/transformer-css-2.8.0.tgz", + "integrity": "sha512-jCMQSfsxCoepblBAHCYMuNWNPQlqasoD6PfNftMdTlv12aUcnjNIYO9600TVLTL799CrEohljbXcfFn6hDGVWw==", + "dev": true, + "requires": { + "@parcel/diagnostic": "2.8.0", + "@parcel/plugin": "2.8.0", + "@parcel/source-map": "^2.1.1", + "@parcel/utils": "2.8.0", + "browserslist": "^4.6.6", + "lightningcss": "^1.16.1", + "nullthrows": "^1.1.1" + } + }, + "@parcel/transformer-html": { + "version": "2.8.0", + "resolved": "https://registry.npmjs.org/@parcel/transformer-html/-/transformer-html-2.8.0.tgz", + "integrity": "sha512-KLcZCWSIItZ1s12Sav3uvfTrwhX92craN9u7V3qUs8ld7ompTKsCdnf+gYmeCyISb5yiFDyYBvTGc1bOXvaDRQ==", + "dev": true, + "requires": { + "@parcel/diagnostic": "2.8.0", + "@parcel/hash": "2.8.0", + "@parcel/plugin": "2.8.0", + "nullthrows": "^1.1.1", + "posthtml": "^0.16.5", + "posthtml-parser": "^0.10.1", + "posthtml-render": "^3.0.0", + "semver": "^5.7.1" + } + }, + "@parcel/transformer-image": { + "version": "2.8.0", + "resolved": "https://registry.npmjs.org/@parcel/transformer-image/-/transformer-image-2.8.0.tgz", + "integrity": "sha512-hJGsZxGlGEkiUvN8kCxA4DhB6/WrHzcIlZZYEgEien9pLctyc6np6idjdcyudPAhH3LwBPkiyeUfCvLAOA1zkA==", + "dev": true, + "requires": { + "@parcel/plugin": "2.8.0", + "@parcel/utils": "2.8.0", + "@parcel/workers": "2.8.0", + "nullthrows": "^1.1.1" + } + }, + "@parcel/transformer-inline-string": { + "version": "2.8.0", + "resolved": "https://registry.npmjs.org/@parcel/transformer-inline-string/-/transformer-inline-string-2.8.0.tgz", + "integrity": "sha512-YBBgolTygr93hos4f5/xkM8VqP+Wc2exeXOyJfVCJJEaSVseXVdF8JtuZLlrcqOkw+ZC3nJtD4CEu+Glz9zCRg==", + "dev": true, + "requires": { + "@parcel/plugin": "2.8.0" + } + }, + "@parcel/transformer-js": { + "version": "2.8.0", + "resolved": "https://registry.npmjs.org/@parcel/transformer-js/-/transformer-js-2.8.0.tgz", + "integrity": "sha512-C5WTkDRiJGBB9tZa1mBsZwsqZjYEKkOa4mdVym3dMokwhFLUga8WtK7kGw4fmXIq41U8ip4orywj+Rd4mvGVWg==", + "dev": true, + "requires": { + "@parcel/diagnostic": "2.8.0", + "@parcel/plugin": "2.8.0", + "@parcel/source-map": "^2.1.1", + "@parcel/utils": "2.8.0", + "@parcel/workers": "2.8.0", + "@swc/helpers": "^0.4.12", + "browserslist": "^4.6.6", + "detect-libc": "^1.0.3", + "nullthrows": "^1.1.1", + "regenerator-runtime": "^0.13.7", + "semver": "^5.7.1" + } + }, + "@parcel/transformer-json": { + "version": "2.8.0", + "resolved": "https://registry.npmjs.org/@parcel/transformer-json/-/transformer-json-2.8.0.tgz", + "integrity": "sha512-Pp5gROSMpzFDEI6KA2APuSpft6eXZxFgTPV6Xx9pElqseod3iL5+RnpMNV/nv76Ai2bcMEiafus5Pb09vjHgbQ==", + "dev": true, + "requires": { + "@parcel/plugin": "2.8.0", + "json5": "^2.2.0" + } + }, + "@parcel/transformer-postcss": { + "version": "2.8.0", + "resolved": "https://registry.npmjs.org/@parcel/transformer-postcss/-/transformer-postcss-2.8.0.tgz", + "integrity": "sha512-45Ij+cgwXprd1sCLmaMIlCbPz3eEwolGHizgZmXl5l4yjlE2wGyzodhxLpBk1PWu7OxxWRbLnJIlvMYf7Vfw0g==", + "dev": true, + "requires": { + "@parcel/diagnostic": "2.8.0", + "@parcel/hash": "2.8.0", + "@parcel/plugin": "2.8.0", + "@parcel/utils": "2.8.0", + "clone": "^2.1.1", + "nullthrows": "^1.1.1", + "postcss-value-parser": "^4.2.0", + "semver": "^5.7.1" + } + }, + "@parcel/transformer-posthtml": { + "version": "2.8.0", + "resolved": "https://registry.npmjs.org/@parcel/transformer-posthtml/-/transformer-posthtml-2.8.0.tgz", + "integrity": "sha512-KrkKBFDW5PNZpr2Ha711eIABQOiJQKvfwfVs3CVpJK5wSADkappDk7CQ0mISPjhamFJ6xx/sNsi7e871I8R9lg==", + "dev": true, + "requires": { + "@parcel/plugin": "2.8.0", + "@parcel/utils": "2.8.0", + "nullthrows": "^1.1.1", + "posthtml": "^0.16.5", + "posthtml-parser": "^0.10.1", + "posthtml-render": "^3.0.0", + "semver": "^5.7.1" + } + }, + "@parcel/transformer-raw": { + "version": "2.8.0", + "resolved": "https://registry.npmjs.org/@parcel/transformer-raw/-/transformer-raw-2.8.0.tgz", + "integrity": "sha512-uEbj+kE70vg2Gmdji/AIXPK13s5aQRw7X+xWs3vNpY2oymyMRHbfx1izJFWBh+kxu6Yo6q6qsekkh2rNHEHIUA==", + "dev": true, + "requires": { + "@parcel/plugin": "2.8.0" + } + }, + "@parcel/transformer-react-refresh-wrap": { + "version": "2.8.0", + "resolved": "https://registry.npmjs.org/@parcel/transformer-react-refresh-wrap/-/transformer-react-refresh-wrap-2.8.0.tgz", + "integrity": "sha512-d7G6wBdlwVXLkhC7EO/3UkUOfEOJvsIsQUCEujsrdFF+nfBElXw/TZ+KP8UkmrwMdD0spU/8cKoTyi5k19vt6w==", + "dev": true, + "requires": { + "@parcel/plugin": "2.8.0", + "@parcel/utils": "2.8.0", + "react-refresh": "^0.9.0" + } + }, + "@parcel/transformer-svg": { + "version": "2.8.0", + "resolved": "https://registry.npmjs.org/@parcel/transformer-svg/-/transformer-svg-2.8.0.tgz", + "integrity": "sha512-8S6yZoUTCbHOnuWY3M50fscTpI8414945I44fmed+C1e36TnWem8FifuVtGkRZeR8pokF453lmmwWG1eH/4U3w==", + "dev": true, + "requires": { + "@parcel/diagnostic": "2.8.0", + "@parcel/hash": "2.8.0", + "@parcel/plugin": "2.8.0", + "nullthrows": "^1.1.1", + "posthtml": "^0.16.5", + "posthtml-parser": "^0.10.1", + "posthtml-render": "^3.0.0", + "semver": "^5.7.1" + } + }, + "@parcel/types": { + "version": "2.8.0", + "resolved": "https://registry.npmjs.org/@parcel/types/-/types-2.8.0.tgz", + "integrity": "sha512-DeN3vCnVl9onjtyWxpbP7LwRslVEko4kBaM7yILsuQjEnXmaIOsqIf6FQJOUOPBtQTFFNeQQ2qyf5XoO/rkJ8g==", + "dev": true, + "requires": { + "@parcel/cache": "2.8.0", + "@parcel/diagnostic": "2.8.0", + "@parcel/fs": "2.8.0", + "@parcel/package-manager": "2.8.0", + "@parcel/source-map": "^2.1.1", + "@parcel/workers": "2.8.0", + "utility-types": "^3.10.0" + } + }, + "@parcel/utils": { + "version": "2.8.0", + "resolved": "https://registry.npmjs.org/@parcel/utils/-/utils-2.8.0.tgz", + "integrity": "sha512-r4ACsGtW7zkMUIgwQyOVtPAFiy8L81gbz4tMIRSqyQKnkW7oEHcQ3uN1/LPxj2yfkyQLmhJxmtptLUy9j53rcw==", + "dev": true, + "requires": { + "@parcel/codeframe": "2.8.0", + "@parcel/diagnostic": "2.8.0", + "@parcel/hash": "2.8.0", + "@parcel/logger": "2.8.0", + "@parcel/markdown-ansi": "2.8.0", + "@parcel/source-map": "^2.1.1", + "chalk": "^4.1.0" + } + }, + "@parcel/watcher": { + "version": "2.0.7", + "resolved": "https://registry.npmjs.org/@parcel/watcher/-/watcher-2.0.7.tgz", + "integrity": "sha512-gc3hoS6e+2XdIQ4HHljDB1l0Yx2EWh/sBBtCEFNKGSMlwASWeAQsOY/fPbxOBcZ/pg0jBh4Ga+4xHlZc4faAEQ==", + "dev": true, + "requires": { + "node-addon-api": "^3.2.1", + "node-gyp-build": "^4.3.0" + } + }, + "@parcel/workers": { + "version": "2.8.0", + "resolved": "https://registry.npmjs.org/@parcel/workers/-/workers-2.8.0.tgz", + "integrity": "sha512-vAzoC/wPHLQnyy9P/TrSPftY8F3MhZqPTFi681mxVtLWA3t7wiNlw1zDVKRDP8m5XS1yQOr8Q56CAHyRexhc8g==", + "dev": true, + "requires": { + "@parcel/diagnostic": "2.8.0", + "@parcel/logger": "2.8.0", + "@parcel/types": "2.8.0", + "@parcel/utils": "2.8.0", + "chrome-trace-event": "^1.0.2", + "nullthrows": "^1.1.1" + } + }, + "@swc/helpers": { + "version": "0.4.14", + "resolved": "https://registry.npmjs.org/@swc/helpers/-/helpers-0.4.14.tgz", + "integrity": "sha512-4C7nX/dvpzB7za4Ql9K81xK3HPxCpHMgwTZVyf+9JQ6VUbn9jjZVN7/Nkdz/Ugzs2CSjqnL/UPXroiVBVHUWUw==", + "dev": true, + "requires": { + "tslib": "^2.4.0" + } + }, + "@trysound/sax": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/@trysound/sax/-/sax-0.2.0.tgz", + "integrity": "sha512-L7z9BgrNEcYyUYtF+HaEfiS5ebkh9jXqbszz7pC0hRBPaatV0XjSD3+eHrpqFemQfgwiFF0QPIarnIihIDn7OA==", + "dev": true + }, + "@types/parse-json": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/@types/parse-json/-/parse-json-4.0.0.tgz", + "integrity": "sha512-//oorEZjL6sbPcKUaCdIGlIUeH26mgzimjBB77G6XRgnDl/L5wOnpyBGRe/Mmf5CVW3PwEBE1NjiMZ/ssFh4wA==", + "dev": true + }, + "abortcontroller-polyfill": { + "version": "1.7.5", + "resolved": "https://registry.npmjs.org/abortcontroller-polyfill/-/abortcontroller-polyfill-1.7.5.tgz", + "integrity": "sha512-JMJ5soJWP18htbbxJjG7bG6yuI6pRhgJ0scHHTfkUjf6wjP912xZWvM+A4sJK3gqd9E8fcPbDnOefbA9Th/FIQ==", + "dev": true + }, + "acorn": { + "version": "8.8.1", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.8.1.tgz", + "integrity": "sha512-7zFpHzhnqYKrkYdUjF1HI1bzd0VygEGX8lFk4k5zVMqHEoES+P+7TKI+EvLO9WVMJ8eekdO0aDEK044xTXwPPA==", + "dev": true + }, + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "requires": { + "color-convert": "^2.0.1" + } + }, + "base-x": { + "version": "3.0.9", + "resolved": "https://registry.npmjs.org/base-x/-/base-x-3.0.9.tgz", + "integrity": "sha512-H7JU6iBHTal1gp56aKoaa//YUxEaAOUiydvrV/pILqIHXTtqxSkATOnDA2u+jZ/61sD+L/412+7kzXRtWukhpQ==", + "dev": true, + "requires": { + "safe-buffer": "^5.0.1" + } + }, + "boolbase": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/boolbase/-/boolbase-1.0.0.tgz", + "integrity": "sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww==", + "dev": true + }, + "browserslist": { + "version": "4.21.4", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.21.4.tgz", + "integrity": "sha512-CBHJJdDmgjl3daYjN5Cp5kbTf1mUhZoS+beLklHIvkOWscs83YAhLlF3Wsh/lciQYAcbBJgTOD44VtG31ZM4Hw==", + "dev": true, + "requires": { + "caniuse-lite": "^1.0.30001400", + "electron-to-chromium": "^1.4.251", + "node-releases": "^2.0.6", + "update-browserslist-db": "^1.0.9" + } + }, + "buffer-from": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", + "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==", + "dev": true + }, + "callsites": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", + "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", + "dev": true + }, + "caniuse-lite": { + "version": "1.0.30001436", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001436.tgz", + "integrity": "sha512-ZmWkKsnC2ifEPoWUvSAIGyOYwT+keAaaWPHiQ9DfMqS1t6tfuyFYoWR78TeZtznkEQ64+vGXH9cZrElwR2Mrxg==", + "dev": true + }, + "chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + } + }, + "chrome-trace-event": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/chrome-trace-event/-/chrome-trace-event-1.0.3.tgz", + "integrity": "sha512-p3KULyQg4S7NIHixdwbGX+nFHkoBiA4YQmyWtjb8XngSKV124nJmRysgAeujbUVb15vh+RvFUfCPqU7rXk+hZg==", + "dev": true + }, + "clone": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/clone/-/clone-2.1.2.tgz", + "integrity": "sha512-3Pe/CF1Nn94hyhIYpjtiLhdCoEoz0DqQ+988E9gmeEdQZlojxnOb74wctFyuwWQHzqyf9X7C7MG8juUpqBJT8w==", + "dev": true + }, + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "requires": { + "color-name": "~1.1.4" + } + }, + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "commander": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-7.2.0.tgz", + "integrity": "sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw==", + "dev": true + }, + "cosmiconfig": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-7.1.0.tgz", + "integrity": "sha512-AdmX6xUzdNASswsFtmwSt7Vj8po9IuqXm0UXz7QKPuEUmPB4XyjGfaAr2PSuELMwkRMVH1EpIkX5bTZGRB3eCA==", + "dev": true, + "requires": { + "@types/parse-json": "^4.0.0", + "import-fresh": "^3.2.1", + "parse-json": "^5.0.0", + "path-type": "^4.0.0", + "yaml": "^1.10.0" + } + }, + "css-select": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/css-select/-/css-select-4.3.0.tgz", + "integrity": "sha512-wPpOYtnsVontu2mODhA19JrqWxNsfdatRKd64kmpRbQgh1KtItko5sTnEpPdpSaJszTOhEMlF/RPz28qj4HqhQ==", + "dev": true, + "requires": { + "boolbase": "^1.0.0", + "css-what": "^6.0.1", + "domhandler": "^4.3.1", + "domutils": "^2.8.0", + "nth-check": "^2.0.1" + } + }, + "css-tree": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/css-tree/-/css-tree-1.1.3.tgz", + "integrity": "sha512-tRpdppF7TRazZrjJ6v3stzv93qxRcSsFmW6cX0Zm2NVKpxE1WV1HblnghVv9TreireHkqI/VDEsfolRF1p6y7Q==", + "dev": true, + "requires": { + "mdn-data": "2.0.14", + "source-map": "^0.6.1" + } + }, + "css-what": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/css-what/-/css-what-6.1.0.tgz", + "integrity": "sha512-HTUrgRJ7r4dsZKU6GjmpfRK1O76h97Z8MfS1G0FozR+oF2kG6Vfe8JE6zwrkbxigziPHinCJ+gCPjA9EaBDtRw==", + "dev": true + }, + "csso": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/csso/-/csso-4.2.0.tgz", + "integrity": "sha512-wvlcdIbf6pwKEk7vHj8/Bkc0B4ylXZruLvOgs9doS5eOsOpuodOV2zJChSpkp+pRpYQLQMeF04nr3Z68Sta9jA==", + "dev": true, + "requires": { + "css-tree": "^1.1.2" + } + }, + "detect-libc": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-1.0.3.tgz", + "integrity": "sha512-pGjwhsmsp4kL2RTz08wcOlGN83otlqHeD/Z5T8GXZB+/YcpQ/dgo+lbU8ZsGxV0HIvqqxo9l7mqYwyYMD9bKDg==", + "dev": true + }, + "dom-serializer": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-1.4.1.tgz", + "integrity": "sha512-VHwB3KfrcOOkelEG2ZOfxqLZdfkil8PtJi4P8N2MMXucZq2yLp75ClViUlOVwyoHEDjYU433Aq+5zWP61+RGag==", + "dev": true, + "requires": { + "domelementtype": "^2.0.1", + "domhandler": "^4.2.0", + "entities": "^2.0.0" + }, + "dependencies": { + "entities": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/entities/-/entities-2.2.0.tgz", + "integrity": "sha512-p92if5Nz619I0w+akJrLZH0MX0Pb5DX39XOwQTtXSdQQOaYH03S1uIQp4mhOZtAXrxq4ViO67YTiLBo2638o9A==", + "dev": true + } + } + }, + "domelementtype": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-2.3.0.tgz", + "integrity": "sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw==", + "dev": true + }, + "domhandler": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-4.3.1.tgz", + "integrity": "sha512-GrwoxYN+uWlzO8uhUXRl0P+kHE4GtVPfYzVLcUxPL7KNdHKj66vvlhiweIHqYYXWlw+T8iLMp42Lm67ghw4WMQ==", + "dev": true, + "requires": { + "domelementtype": "^2.2.0" + } + }, + "domutils": { + "version": "2.8.0", + "resolved": "https://registry.npmjs.org/domutils/-/domutils-2.8.0.tgz", + "integrity": "sha512-w96Cjofp72M5IIhpjgobBimYEfoPjx1Vx0BSX9P30WBdZW2WIKU0T1Bd0kz2eNZ9ikjKgHbEyKx8BB6H1L3h3A==", + "dev": true, + "requires": { + "dom-serializer": "^1.0.1", + "domelementtype": "^2.2.0", + "domhandler": "^4.2.0" + } + }, + "dotenv": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-7.0.0.tgz", + "integrity": "sha512-M3NhsLbV1i6HuGzBUH8vXrtxOk+tWmzWKDMbAVSUp3Zsjm7ywFeuwrUXhmhQyRK1q5B5GGy7hcXPbj3bnfZg2g==", + "dev": true + }, + "dotenv-expand": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/dotenv-expand/-/dotenv-expand-5.1.0.tgz", + "integrity": "sha512-YXQl1DSa4/PQyRfgrv6aoNjhasp/p4qs9FjJ4q4cQk+8m4r6k4ZSiEyytKG8f8W9gi8WsQtIObNmKd+tMzNTmA==", + "dev": true + }, + "electron-to-chromium": { + "version": "1.4.284", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.284.tgz", + "integrity": "sha512-M8WEXFuKXMYMVr45fo8mq0wUrrJHheiKZf6BArTKk9ZBYCKJEOU5H8cdWgDT+qCVZf7Na4lVUaZsA+h6uA9+PA==", + "dev": true + }, + "entities": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/entities/-/entities-3.0.1.tgz", + "integrity": "sha512-WiyBqoomrwMdFG1e0kqvASYfnlb0lp8M5o5Fw2OFq1hNZxxcNk8Ik0Xm7LxzBhuidnZB/UtBqVCgUz3kBOP51Q==", + "dev": true + }, + "error-ex": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", + "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==", + "dev": true, + "requires": { + "is-arrayish": "^0.2.1" + } + }, + "escalade": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", + "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==", + "dev": true + }, + "escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", + "dev": true + }, + "get-port": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/get-port/-/get-port-4.2.0.tgz", + "integrity": "sha512-/b3jarXkH8KJoOMQc3uVGHASwGLPq3gSFJ7tgJm2diza+bydJPTGOibin2steecKeOylE8oY2JERlVWkAJO6yw==", + "dev": true + }, + "globals": { + "version": "13.18.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-13.18.0.tgz", + "integrity": "sha512-/mR4KI8Ps2spmoc0Ulu9L7agOF0du1CZNQ3dke8yItYlyKNmGrkONemBbd6V8UTc1Wgcqn21t3WYB7dbRmh6/A==", + "dev": true, + "requires": { + "type-fest": "^0.20.2" + } + }, + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true + }, + "htmlnano": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/htmlnano/-/htmlnano-2.0.3.tgz", + "integrity": "sha512-S4PGGj9RbdgW8LhbILNK7W9JhmYP8zmDY7KDV/8eCiJBQJlbmltp5I0gv8c5ntLljfdxxfmJ+UJVSqyH4mb41A==", + "dev": true, + "requires": { + "cosmiconfig": "^7.0.1", + "posthtml": "^0.16.5", + "timsort": "^0.3.0" + } + }, + "htmlparser2": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-7.2.0.tgz", + "integrity": "sha512-H7MImA4MS6cw7nbyURtLPO1Tms7C5H602LRETv95z1MxO/7CP7rDVROehUYeYBUYEON94NXXDEPmZuq+hX4sog==", + "dev": true, + "requires": { + "domelementtype": "^2.0.1", + "domhandler": "^4.2.2", + "domutils": "^2.8.0", + "entities": "^3.0.1" + } + }, + "import-fresh": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz", + "integrity": "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==", + "dev": true, + "requires": { + "parent-module": "^1.0.0", + "resolve-from": "^4.0.0" + } + }, + "is-arrayish": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", + "integrity": "sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==", + "dev": true + }, + "is-json": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-json/-/is-json-2.0.1.tgz", + "integrity": "sha512-6BEnpVn1rcf3ngfmViLM6vjUjGErbdrL4rwlv+u1NO1XO8kqT4YGL8+19Q+Z/bas8tY90BTWMk2+fW1g6hQjbA==", + "dev": true + }, + "js-tokens": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", + "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", + "dev": true + }, + "json-parse-even-better-errors": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz", + "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==", + "dev": true + }, + "json5": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.1.tgz", + "integrity": "sha512-1hqLFMSrGHRHxav9q9gNjJ5EXznIxGVO09xQRrwplcS8qs28pZ8s8hupZAmqDwZUmVZ2Qb2jnyPOWcDH8m8dlA==", + "dev": true + }, + "lightningcss": { + "version": "1.17.1", + "resolved": "https://registry.npmjs.org/lightningcss/-/lightningcss-1.17.1.tgz", + "integrity": "sha512-DwwM/YYqGwLLP3he41wzDXT/m+8jdEZ80i9ViQNLRgyhey3Vm6N7XHn+4o3PY6wSnVT23WLuaROIpbpIVTNOjg==", + "dev": true, + "requires": { + "detect-libc": "^1.0.3", + "lightningcss-darwin-arm64": "1.17.1", + "lightningcss-darwin-x64": "1.17.1", + "lightningcss-linux-arm-gnueabihf": "1.17.1", + "lightningcss-linux-arm64-gnu": "1.17.1", + "lightningcss-linux-arm64-musl": "1.17.1", + "lightningcss-linux-x64-gnu": "1.17.1", + "lightningcss-linux-x64-musl": "1.17.1", + "lightningcss-win32-x64-msvc": "1.17.1" + } + }, + "lightningcss-darwin-arm64": { + "version": "1.17.1", + "resolved": "https://registry.npmjs.org/lightningcss-darwin-arm64/-/lightningcss-darwin-arm64-1.17.1.tgz", + "integrity": "sha512-YTAHEy4XlzI3sMbUVjbPi9P7+N7lGcgl2JhCZhiQdRAEKnZLQch8kb5601sgESxdGXjgei7JZFqi/vVEk81wYg==", + "dev": true, + "optional": true + }, + "lightningcss-darwin-x64": { + "version": "1.17.1", + "resolved": "https://registry.npmjs.org/lightningcss-darwin-x64/-/lightningcss-darwin-x64-1.17.1.tgz", + "integrity": "sha512-UhXPUS2+yTTf5sXwUV0+8QY2x0bPGLgC/uhcknWSQMqWn1zGty4fFvH04D7f7ij0ujwSuN+Q0HtU7lgmMrPz0A==", + "dev": true, + "optional": true + }, + "lightningcss-linux-arm-gnueabihf": { + "version": "1.17.1", + "resolved": "https://registry.npmjs.org/lightningcss-linux-arm-gnueabihf/-/lightningcss-linux-arm-gnueabihf-1.17.1.tgz", + "integrity": "sha512-alUZumuznB6K/9yZ0zuZkODXUm8uRnvs9t0CL46CXN16Y2h4gOx5ahUCMlelUb7inZEsgJIoepgLsJzBUrSsBw==", + "dev": true, + "optional": true + }, + "lightningcss-linux-arm64-gnu": { + "version": "1.17.1", + "resolved": "https://registry.npmjs.org/lightningcss-linux-arm64-gnu/-/lightningcss-linux-arm64-gnu-1.17.1.tgz", + "integrity": "sha512-/1XaH2cOjDt+ivmgfmVFUYCA0MtfNWwtC4P8qVi53zEQ7P8euyyZ1ynykZOyKXW9Q0DzrwcLTh6+hxVLcbtGBg==", + "dev": true, + "optional": true + }, + "lightningcss-linux-arm64-musl": { + "version": "1.17.1", + "resolved": "https://registry.npmjs.org/lightningcss-linux-arm64-musl/-/lightningcss-linux-arm64-musl-1.17.1.tgz", + "integrity": "sha512-/IgE7lYWFHCCQFTMIwtt+fXLcVOha8rcrNze1JYGPWNorO6NBc6MJo5u5cwn5qMMSz9fZCCDIlBBU4mGwjQszQ==", + "dev": true, + "optional": true + }, + "lightningcss-linux-x64-gnu": { + "version": "1.17.1", + "resolved": "https://registry.npmjs.org/lightningcss-linux-x64-gnu/-/lightningcss-linux-x64-gnu-1.17.1.tgz", + "integrity": "sha512-OyE802IAp4DB9vZrHlOyWunbHLM9dN08tJIKN/HhzzLKIHizubOWX6NMzUXMZLsaUrYwVAHHdyEA+712p8mMzA==", + "dev": true, + "optional": true + }, + "lightningcss-linux-x64-musl": { + "version": "1.17.1", + "resolved": "https://registry.npmjs.org/lightningcss-linux-x64-musl/-/lightningcss-linux-x64-musl-1.17.1.tgz", + "integrity": "sha512-ydwGgV3Usba5P53RAOqCA9MsRsbb8jFIEVhf7/BXFjpKNoIQyijVTXhwIgQr/oGwUNOHfgQ3F8ruiUjX/p2YKw==", + "dev": true, + "optional": true + }, + "lightningcss-win32-x64-msvc": { + "version": "1.17.1", + "resolved": "https://registry.npmjs.org/lightningcss-win32-x64-msvc/-/lightningcss-win32-x64-msvc-1.17.1.tgz", + "integrity": "sha512-Ngqtx9NazaiAOk71XWwSsqgAuwYF+8PO6UYsoU7hAukdrSS98kwaBMEDw1igeIiZy1XD/4kh5KVnkjNf7ZOxVQ==", + "dev": true, + "optional": true + }, + "lines-and-columns": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz", + "integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==", + "dev": true + }, + "lmdb": { + "version": "2.5.2", + "resolved": "https://registry.npmjs.org/lmdb/-/lmdb-2.5.2.tgz", + "integrity": "sha512-V5V5Xa2Hp9i2XsbDALkBTeHXnBXh/lEmk9p22zdr7jtuOIY9TGhjK6vAvTpOOx9IKU4hJkRWZxn/HsvR1ELLtA==", + "dev": true, + "requires": { + "@lmdb/lmdb-darwin-arm64": "2.5.2", + "@lmdb/lmdb-darwin-x64": "2.5.2", + "@lmdb/lmdb-linux-arm": "2.5.2", + "@lmdb/lmdb-linux-arm64": "2.5.2", + "@lmdb/lmdb-linux-x64": "2.5.2", + "@lmdb/lmdb-win32-x64": "2.5.2", + "msgpackr": "^1.5.4", + "node-addon-api": "^4.3.0", + "node-gyp-build-optional-packages": "5.0.3", + "ordered-binary": "^1.2.4", + "weak-lru-cache": "^1.2.2" + }, + "dependencies": { + "node-addon-api": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-4.3.0.tgz", + "integrity": "sha512-73sE9+3UaLYYFmDsFZnqCInzPyh3MqIwZO9cw58yIqAZhONrrabrYyYe3TuIqtIiOuTXVhsGau8hcrhhwSsDIQ==", + "dev": true + } + } + }, + "mdn-data": { + "version": "2.0.14", + "resolved": "https://registry.npmjs.org/mdn-data/-/mdn-data-2.0.14.tgz", + "integrity": "sha512-dn6wd0uw5GsdswPFfsgMp5NSB0/aDe6fK94YJV/AJDYXL6HVLWBsxeq7js7Ad+mU2K9LAlwpk6kN2D5mwCPVow==", + "dev": true + }, + "msgpackr": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/msgpackr/-/msgpackr-1.8.1.tgz", + "integrity": "sha512-05fT4J8ZqjYlR4QcRDIhLCYKUOHXk7C/xa62GzMKj74l3up9k2QZ3LgFc6qWdsPHl91QA2WLWqWc8b8t7GLNNw==", + "dev": true, + "requires": { + "msgpackr-extract": "^2.2.0" + } + }, + "msgpackr-extract": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/msgpackr-extract/-/msgpackr-extract-2.2.0.tgz", + "integrity": "sha512-0YcvWSv7ZOGl9Od6Y5iJ3XnPww8O7WLcpYMDwX+PAA/uXLDtyw94PJv9GLQV/nnp3cWlDhMoyKZIQLrx33sWog==", + "dev": true, + "optional": true, + "requires": { + "@msgpackr-extract/msgpackr-extract-darwin-arm64": "2.2.0", + "@msgpackr-extract/msgpackr-extract-darwin-x64": "2.2.0", + "@msgpackr-extract/msgpackr-extract-linux-arm": "2.2.0", + "@msgpackr-extract/msgpackr-extract-linux-arm64": "2.2.0", + "@msgpackr-extract/msgpackr-extract-linux-x64": "2.2.0", + "@msgpackr-extract/msgpackr-extract-win32-x64": "2.2.0", + "node-gyp-build-optional-packages": "5.0.3" + } + }, + "node-addon-api": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-3.2.1.tgz", + "integrity": "sha512-mmcei9JghVNDYydghQmeDX8KoAm0FAiYyIcUt/N4nhyAipB17pllZQDOJD2fotxABnt4Mdz+dKTO7eftLg4d0A==", + "dev": true + }, + "node-gyp-build": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/node-gyp-build/-/node-gyp-build-4.5.0.tgz", + "integrity": "sha512-2iGbaQBV+ITgCz76ZEjmhUKAKVf7xfY1sRl4UiKQspfZMH2h06SyhNsnSVy50cwkFQDGLyif6m/6uFXHkOZ6rg==", + "dev": true + }, + "node-gyp-build-optional-packages": { + "version": "5.0.3", + "resolved": "https://registry.npmjs.org/node-gyp-build-optional-packages/-/node-gyp-build-optional-packages-5.0.3.tgz", + "integrity": "sha512-k75jcVzk5wnnc/FMxsf4udAoTEUv2jY3ycfdSd3yWu6Cnd1oee6/CfZJApyscA4FJOmdoixWwiwOyf16RzD5JA==", + "dev": true + }, + "node-releases": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.6.tgz", + "integrity": "sha512-PiVXnNuFm5+iYkLBNeq5211hvO38y63T0i2KKh2KnUs3RpzJ+JtODFjkD8yjLwnDkTYF1eKXheUwdssR+NRZdg==", + "dev": true + }, + "nth-check": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/nth-check/-/nth-check-2.1.1.tgz", + "integrity": "sha512-lqjrjmaOoAnWfMmBPL+XNnynZh2+swxiX3WUE0s4yEHI6m+AwrK2UZOimIRl3X/4QctVqS8AiZjFqyOGrMXb/w==", + "dev": true, + "requires": { + "boolbase": "^1.0.0" + } + }, + "nullthrows": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/nullthrows/-/nullthrows-1.1.1.tgz", + "integrity": "sha512-2vPPEi+Z7WqML2jZYddDIfy5Dqb0r2fze2zTxNNknZaFpVHU3mFB3R+DWeJWGVx0ecvttSGlJTI+WG+8Z4cDWw==", + "dev": true + }, + "ordered-binary": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/ordered-binary/-/ordered-binary-1.4.0.tgz", + "integrity": "sha512-EHQ/jk4/a9hLupIKxTfUsQRej1Yd/0QLQs3vGvIqg5ZtCYSzNhkzHoZc7Zf4e4kUlDaC3Uw8Q/1opOLNN2OKRQ==", + "dev": true + }, + "parcel": { + "version": "2.8.0", + "resolved": "https://registry.npmjs.org/parcel/-/parcel-2.8.0.tgz", + "integrity": "sha512-p7Fo75CeMw5HC1luovYpBjzPbAJv/Gn7lxcs4f0LxcwBCWbkQ73zHgJXJQqnM38qQABEYEiQq6000+j+k5U/Mw==", + "dev": true, + "requires": { + "@parcel/config-default": "2.8.0", + "@parcel/core": "2.8.0", + "@parcel/diagnostic": "2.8.0", + "@parcel/events": "2.8.0", + "@parcel/fs": "2.8.0", + "@parcel/logger": "2.8.0", + "@parcel/package-manager": "2.8.0", + "@parcel/reporter-cli": "2.8.0", + "@parcel/reporter-dev-server": "2.8.0", + "@parcel/utils": "2.8.0", + "chalk": "^4.1.0", + "commander": "^7.0.0", + "get-port": "^4.2.0", + "v8-compile-cache": "^2.0.0" + } + }, + "parent-module": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", + "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", + "dev": true, + "requires": { + "callsites": "^3.0.0" + } + }, + "parse-json": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.2.0.tgz", + "integrity": "sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==", + "dev": true, + "requires": { + "@babel/code-frame": "^7.0.0", + "error-ex": "^1.3.1", + "json-parse-even-better-errors": "^2.3.0", + "lines-and-columns": "^1.1.6" + } + }, + "path-type": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", + "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==", + "dev": true + }, + "picocolors": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz", + "integrity": "sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==", + "dev": true + }, + "postcss-value-parser": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz", + "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==", + "dev": true + }, + "posthtml": { + "version": "0.16.6", + "resolved": "https://registry.npmjs.org/posthtml/-/posthtml-0.16.6.tgz", + "integrity": "sha512-JcEmHlyLK/o0uGAlj65vgg+7LIms0xKXe60lcDOTU7oVX/3LuEuLwrQpW3VJ7de5TaFKiW4kWkaIpJL42FEgxQ==", + "dev": true, + "requires": { + "posthtml-parser": "^0.11.0", + "posthtml-render": "^3.0.0" + }, + "dependencies": { + "posthtml-parser": { + "version": "0.11.0", + "resolved": "https://registry.npmjs.org/posthtml-parser/-/posthtml-parser-0.11.0.tgz", + "integrity": "sha512-QecJtfLekJbWVo/dMAA+OSwY79wpRmbqS5TeXvXSX+f0c6pW4/SE6inzZ2qkU7oAMCPqIDkZDvd/bQsSFUnKyw==", + "dev": true, + "requires": { + "htmlparser2": "^7.1.1" + } + } + } + }, + "posthtml-parser": { + "version": "0.10.2", + "resolved": "https://registry.npmjs.org/posthtml-parser/-/posthtml-parser-0.10.2.tgz", + "integrity": "sha512-PId6zZ/2lyJi9LiKfe+i2xv57oEjJgWbsHGGANwos5AvdQp98i6AtamAl8gzSVFGfQ43Glb5D614cvZf012VKg==", + "dev": true, + "requires": { + "htmlparser2": "^7.1.1" + } + }, + "posthtml-render": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/posthtml-render/-/posthtml-render-3.0.0.tgz", + "integrity": "sha512-z+16RoxK3fUPgwaIgH9NGnK1HKY9XIDpydky5eQGgAFVXTCSezalv9U2jQuNV+Z9qV1fDWNzldcw4eK0SSbqKA==", + "dev": true, + "requires": { + "is-json": "^2.0.1" + } + }, + "react-error-overlay": { + "version": "6.0.9", + "resolved": "https://registry.npmjs.org/react-error-overlay/-/react-error-overlay-6.0.9.tgz", + "integrity": "sha512-nQTTcUu+ATDbrSD1BZHr5kgSD4oF8OFjxun8uAaL8RwPBacGBNPf/yAuVVdx17N8XNzRDMrZ9XcKZHCjPW+9ew==", + "dev": true + }, + "react-refresh": { + "version": "0.9.0", + "resolved": "https://registry.npmjs.org/react-refresh/-/react-refresh-0.9.0.tgz", + "integrity": "sha512-Gvzk7OZpiqKSkxsQvO/mbTN1poglhmAV7gR/DdIrRrSMXraRQQlfikRJOr3Nb9GTMPC5kof948Zy6jJZIFtDvQ==", + "dev": true + }, + "regenerator-runtime": { + "version": "0.13.11", + "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.11.tgz", + "integrity": "sha512-kY1AZVr2Ra+t+piVaJ4gxaFaReZVH40AKNo7UCX6W+dEwBo/2oZJzqfuN1qLq1oL45o56cPaTXELwrTh8Fpggg==", + "dev": true + }, + "resolve-from": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", + "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", + "dev": true + }, + "safe-buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", + "dev": true + }, + "semver": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", + "dev": true + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + }, + "source-map-support": { + "version": "0.5.21", + "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.21.tgz", + "integrity": "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==", + "dev": true, + "requires": { + "buffer-from": "^1.0.0", + "source-map": "^0.6.0" + } + }, + "stable": { + "version": "0.1.8", + "resolved": "https://registry.npmjs.org/stable/-/stable-0.1.8.tgz", + "integrity": "sha512-ji9qxRnOVfcuLDySj9qzhGSEFVobyt1kIOSkj1qZzYLzq7Tos/oUUWvotUPQLlrsidqsK6tBH89Bc9kL5zHA6w==", + "dev": true + }, + "supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "requires": { + "has-flag": "^4.0.0" + } + }, + "svgo": { + "version": "2.8.0", + "resolved": "https://registry.npmjs.org/svgo/-/svgo-2.8.0.tgz", + "integrity": "sha512-+N/Q9kV1+F+UeWYoSiULYo4xYSDQlTgb+ayMobAXPwMnLvop7oxKMo9OzIrX5x3eS4L4f2UHhc9axXwY8DpChg==", + "dev": true, + "requires": { + "@trysound/sax": "0.2.0", + "commander": "^7.2.0", + "css-select": "^4.1.3", + "css-tree": "^1.1.3", + "csso": "^4.2.0", + "picocolors": "^1.0.0", + "stable": "^0.1.8" + } + }, + "term-size": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/term-size/-/term-size-2.2.1.tgz", + "integrity": "sha512-wK0Ri4fOGjv/XPy8SBHZChl8CM7uMc5VML7SqiQ0zG7+J5Vr+RMQDoHa2CNT6KHUnTGIXH34UDMkPzAUyapBZg==", + "dev": true + }, + "terser": { + "version": "5.16.1", + "resolved": "https://registry.npmjs.org/terser/-/terser-5.16.1.tgz", + "integrity": "sha512-xvQfyfA1ayT0qdK47zskQgRZeWLoOQ8JQ6mIgRGVNwZKdQMU+5FkCBjmv4QjcrTzyZquRw2FVtlJSRUmMKQslw==", + "dev": true, + "requires": { + "@jridgewell/source-map": "^0.3.2", + "acorn": "^8.5.0", + "commander": "^2.20.0", + "source-map-support": "~0.5.20" + }, + "dependencies": { + "commander": { + "version": "2.20.3", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", + "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", + "dev": true + } + } + }, + "timsort": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/timsort/-/timsort-0.3.0.tgz", + "integrity": "sha512-qsdtZH+vMoCARQtyod4imc2nIJwg9Cc7lPRrw9CzF8ZKR0khdr8+2nX80PBhET3tcyTtJDxAffGh2rXH4tyU8A==", + "dev": true + }, + "tslib": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.4.1.tgz", + "integrity": "sha512-tGyy4dAjRIEwI7BzsB0lynWgOpfqjUdq91XXAlIWD2OwKBH7oCl/GZG/HT4BOHrTlPMOASlMQ7veyTqpmRcrNA==", + "dev": true + }, + "type-fest": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", + "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", + "dev": true + }, + "typescript": { + "version": "4.9.3", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.9.3.tgz", + "integrity": "sha512-CIfGzTelbKNEnLpLdGFgdyKhG23CKdKgQPOBc+OUNrkJ2vr+KSzsSV5kq5iWhEQbok+quxgGzrAtGWCyU7tHnA==", + "dev": true + }, + "update-browserslist-db": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.0.10.tgz", + "integrity": "sha512-OztqDenkfFkbSG+tRxBeAnCVPckDBcvibKd35yDONx6OU8N7sqgwc7rCbkJ/WcYtVRZ4ba68d6byhC21GFh7sQ==", + "dev": true, + "requires": { + "escalade": "^3.1.1", + "picocolors": "^1.0.0" + } + }, + "utility-types": { + "version": "3.10.0", + "resolved": "https://registry.npmjs.org/utility-types/-/utility-types-3.10.0.tgz", + "integrity": "sha512-O11mqxmi7wMKCo6HKFt5AhO4BwY3VV68YU07tgxfz8zJTIxr4BpsezN49Ffwy9j3ZpwwJp4fkRwjRzq3uWE6Rg==", + "dev": true + }, + "v8-compile-cache": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/v8-compile-cache/-/v8-compile-cache-2.3.0.tgz", + "integrity": "sha512-l8lCEmLcLYZh4nbunNZvQCJc5pv7+RCwa8q/LdUx8u7lsWvPDKmpodJAJNwkAhJC//dFY48KuIEmjtd4RViDrA==", + "dev": true + }, + "weak-lru-cache": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/weak-lru-cache/-/weak-lru-cache-1.2.2.tgz", + "integrity": "sha512-DEAoo25RfSYMuTGc9vPJzZcZullwIqRDSI9LOy+fkCJPi6hykCnfKaXTuPBDuXAUcqHXyOgFtHNp/kB2FjYHbw==", + "dev": true + }, + "xxhash-wasm": { + "version": "0.4.2", + "resolved": "https://registry.npmjs.org/xxhash-wasm/-/xxhash-wasm-0.4.2.tgz", + "integrity": "sha512-/eyHVRJQCirEkSZ1agRSCwriMhwlyUcFkXD5TPVSLP+IPzjsqMVzZwdoczLp1SoQU0R3dxz1RpIK+4YNQbCVOA==", + "dev": true + }, + "yaml": { + "version": "1.10.2", + "resolved": "https://registry.npmjs.org/yaml/-/yaml-1.10.2.tgz", + "integrity": "sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg==", + "dev": true + }, + "zig-js": { + "version": "file:../vendor/zig-js/js", + "requires": { + "@parcel/packager-ts": "^2.8.0", + "@parcel/transformer-typescript-types": "^2.8.0", + "@types/jest": "^29.2.3", + "jest": "^29.3.1", + "parcel": "^2.8.0", + "ts-jest": "^29.0.3", + "typescript": "^4.9.3" + } + } + } +} diff --git a/example/package.json b/example/package.json new file mode 100644 index 000000000..e884e5c6c --- /dev/null +++ b/example/package.json @@ -0,0 +1,22 @@ +{ + "name": "ghostty example", + "version": "0.1.0", + "description": "Example showing ghostty and wasm.", + "source": "index.html", + "browserslist": "> 0.5%, last 2 versions, not dead", + "scripts": { + "start": "parcel", + "build": "parcel build", + "check": "tsc --noEmit" + }, + "author": "Mitchell Hashimoto", + "license": "MIT", + "devDependencies": { + "@parcel/transformer-inline-string": "^2.8.0", + "parcel": "^2.8.0", + "typescript": "^4.9.3" + }, + "dependencies": { + "zig-js": "file:../vendor/zig-js/js" + } +} diff --git a/src/font/face/web_canvas.zig b/src/font/face/web_canvas.zig index 13d0252e8..87ba682df 100644 --- a/src/font/face/web_canvas.zig +++ b/src/font/face/web_canvas.zig @@ -49,6 +49,8 @@ pub const Face = struct { const canvas = try doc.call(js.Object, "createElement", .{js.string("canvas")}); errdefer canvas.deinit(); + log.debug("face initialized: {s}", .{raw}); + return Face{ .alloc = alloc, .font_str = font_str, diff --git a/src/main_wasm.zig b/src/main_wasm.zig index 81f8265d8..f16420450 100644 --- a/src/main_wasm.zig +++ b/src/main_wasm.zig @@ -1,6 +1,17 @@ // This is the main file for the WASM module. The WASM module has to // export a C ABI compatible API. +const std = @import("std"); +const builtin = @import("builtin"); pub usingnamespace @import("os/wasm.zig"); pub usingnamespace @import("os/wasm/log.zig"); pub usingnamespace @import("font/main.zig"); + +// Set our log level. We try to get as much logging as possible but in +// ReleaseSmall mode where we're optimizing for space, we elevate the +// log level. +pub const log_level: std.log.Level = switch (builtin.mode) { + .Debug => .debug, + .ReleaseSmall => .warn, + else => .info, +}; diff --git a/src/os/wasm.zig b/src/os/wasm.zig index d496e404e..5d3c65830 100644 --- a/src/os/wasm.zig +++ b/src/os/wasm.zig @@ -37,6 +37,18 @@ pub export fn malloc(len: usize) ?[*]u8 { return alloc_(len) catch return null; } +fn alloc_(len: usize) ![*]u8 { + // Create the allocation + const slice = try alloc.alloc(u8, len); + errdefer alloc.free(slice); + + // Store the size so we can deallocate later + try allocs.putNoClobber(alloc, slice.ptr, slice.len); + errdefer _ = allocs.remove(slice.ptr); + + return slice.ptr; +} + /// Free an allocation from malloc. pub export fn free(ptr: ?[*]u8) void { if (ptr) |v| { @@ -79,18 +91,6 @@ pub fn toModuleOwned(ptr: anytype) void { _ = allocs.remove(casted); } -fn alloc_(len: usize) ![*]u8 { - // Create the allocation - const slice = try alloc.alloc(u8, len); - errdefer alloc.free(slice); - - // Store the size so we can deallocate later - try allocs.putNoClobber(alloc, slice.ptr, slice.len); - errdefer _ = allocs.remove(slice.ptr); - - return slice.ptr; -} - test "basics" { const testing = std.testing; var buf = malloc(32).?; diff --git a/vendor/zig-js b/vendor/zig-js index a6d0b5a0c..faa353da8 160000 --- a/vendor/zig-js +++ b/vendor/zig-js @@ -1 +1 @@ -Subproject commit a6d0b5a0c421925409f1bce542f64b9e5f6b96df +Subproject commit faa353da8aca78269bc7d2afaf481b755007e849 From 37f00ac7250c589d22819b2741186ffa5ad1438a Mon Sep 17 00:00:00 2001 From: Mitchell Hashimoto Date: Sun, 4 Dec 2022 13:19:29 -0800 Subject: [PATCH 05/14] don't export coretext/freetype --- src/font/face.zig | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/font/face.zig b/src/font/face.zig index 22fec7eeb..e94b4ee94 100644 --- a/src/font/face.zig +++ b/src/font/face.zig @@ -1,7 +1,7 @@ const builtin = @import("builtin"); const options = @import("main.zig").options; -pub const freetype = @import("face/freetype.zig"); -pub const coretext = @import("face/coretext.zig"); +const freetype = @import("face/freetype.zig"); +const coretext = @import("face/coretext.zig"); pub const web_canvas = @import("face/web_canvas.zig"); /// Face implementation for the compile options. From df302fc2b6f700cdadcc08e88dfc4b3f4d626c1a Mon Sep 17 00:00:00 2001 From: Mitchell Hashimoto Date: Sun, 4 Dec 2022 22:01:58 -0800 Subject: [PATCH 06/14] calculate font metrics via canvas --- example/app.ts | 4 +- src/font/face/web_canvas.zig | 81 ++++++++++++++++++++++++++++++++---- vendor/zig-js | 2 +- 3 files changed, 77 insertions(+), 10 deletions(-) diff --git a/example/app.ts b/example/app.ts index aac4e7b26..8b3528223 100644 --- a/example/app.ts +++ b/example/app.ts @@ -41,8 +41,8 @@ fetch(url.href).then(response => new Uint8Array(memory.buffer, font_ptr).set(font); // Call whatever example you want: - const face = face_new(font_ptr, font.byteLength); - face_free(face); + const face = face_new(font_ptr, font.byteLength, 14); + //face_free(face); } finally { free(font_ptr); } diff --git a/src/font/face/web_canvas.zig b/src/font/face/web_canvas.zig index 87ba682df..1c552a6f3 100644 --- a/src/font/face/web_canvas.zig +++ b/src/font/face/web_canvas.zig @@ -49,21 +49,22 @@ pub const Face = struct { const canvas = try doc.call(js.Object, "createElement", .{js.string("canvas")}); errdefer canvas.deinit(); - log.debug("face initialized: {s}", .{raw}); - - return Face{ + var result = Face{ .alloc = alloc, .font_str = font_str, .size = size, + // TODO: figure out how we're going to do emoji with web canvas + .presentation = .text, .canvas = canvas, - // TODO: real metrics + // We're going to calculate these right after initialization. .metrics = undefined, - - // TODO: figure out how we're going to do emoji with web canvas - .presentation = .text, }; + try result.calcMetrics(); + + log.debug("face initialized: {s}", .{raw}); + return result; } pub fn deinit(self: *Face) void { @@ -71,6 +72,72 @@ pub const Face = struct { self.canvas.deinit(); self.* = undefined; } + + /// Calculate the metrics associated with a given face. + fn calcMetrics(self: *Face) !void { + // This will return the same context on subsequent calls so it + // is important to reset it. + const ctx = try self.canvas.call(js.Object, "getContext", .{js.string("2d")}); + defer ctx.deinit(); + + // Set our context font + var font_val = try std.fmt.allocPrint( + self.alloc, + "{d}px {s}", + .{ self.size.points, self.font_str }, + ); + defer self.alloc.free(font_val); + try ctx.set("font", js.string(font_val)); + + // If the font property didn't change, then the font set didn't work. + // We do this check because it is very easy to put an invalid font + // in and this at least makes it show up in the logs. + { + const check = try ctx.getAlloc(js.String, self.alloc, "font"); + defer self.alloc.free(check); + if (!std.mem.eql(u8, font_val, check)) { + log.warn("canvas font didn't set, fonts may be broken, expected={s} got={s}", .{ + font_val, + check, + }); + } + } + + // Cell width is the width of our M text + const cell_width: f32 = cell_width: { + const metrics = try ctx.call(js.Object, "measureText", .{js.string("M")}); + defer metrics.deinit(); + break :cell_width try metrics.get(f32, "actualBoundingBoxRight"); + }; + + // To get the cell height we render a high and low character and get + // the total of the ascent and descent. This should equal our + // pixel height but this is a more surefire way to get it. + const height_metrics = try ctx.call(js.Object, "measureText", .{js.string("M_")}); + defer height_metrics.deinit(); + const asc = try height_metrics.get(f32, "actualBoundingBoxAscent"); + const desc = try height_metrics.get(f32, "actualBoundingBoxDescent"); + const cell_height = asc + desc; + const cell_baseline = desc; + + // There isn't a declared underline position for canvas measurements + // so we just go 1 under the cell height to match freetype logic + // at this time (our freetype logic). + const underline_position = cell_height - 1; + const underline_thickness: f32 = 1; + + self.metrics = .{ + .cell_width = cell_width, + .cell_height = cell_height, + .cell_baseline = cell_baseline, + .underline_position = underline_position, + .underline_thickness = underline_thickness, + .strikethrough_position = underline_position, + .strikethrough_thickness = underline_thickness, + }; + + log.debug("metrics font={s} value={}", .{ font_val, self.metrics }); + } }; /// The wasm-compatible API. diff --git a/vendor/zig-js b/vendor/zig-js index faa353da8..b6352b62a 160000 --- a/vendor/zig-js +++ b/vendor/zig-js @@ -1 +1 @@ -Subproject commit faa353da8aca78269bc7d2afaf481b755007e849 +Subproject commit b6352b62a61e306df09e8bec7c7a99153829ec61 From d3b46eeeafe6e6bba93c79ce5f6fa5e7bca979c6 Mon Sep 17 00:00:00 2001 From: Mitchell Hashimoto Date: Sun, 4 Dec 2022 22:07:50 -0800 Subject: [PATCH 07/14] fix zig-js so wasm-test works --- vendor/zig-js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/vendor/zig-js b/vendor/zig-js index b6352b62a..a70f5da4f 160000 --- a/vendor/zig-js +++ b/vendor/zig-js @@ -1 +1 @@ -Subproject commit b6352b62a61e306df09e8bec7c7a99153829ec61 +Subproject commit a70f5da4f51b643be47fa39ba697dcd9444204c8 From 19e326dab67e719376bb764c687ef1738f6cd1a5 Mon Sep 17 00:00:00 2001 From: Mitchell Hashimoto Date: Mon, 5 Dec 2022 10:54:40 -0800 Subject: [PATCH 08/14] font: working on rendering glyphs in canvas --- example/app.ts | 23 +++- example/index.html | 4 +- src/font/face/freetype.zig | 2 +- src/font/face/web_canvas.zig | 215 ++++++++++++++++++++++++++++++----- vendor/zig-js | 2 +- 5 files changed, 209 insertions(+), 37 deletions(-) diff --git a/example/app.ts b/example/app.ts index 8b3528223..65ba6450f 100644 --- a/example/app.ts +++ b/example/app.ts @@ -26,6 +26,10 @@ fetch(url.href).then(response => free, face_new, face_free, + face_render_glyph, + face_debug_canvas, + atlas_new, + atlas_free, } = results.instance.exports; // Give us access to the zjs value for debugging. globalThis.zjs = zjs; @@ -34,16 +38,23 @@ fetch(url.href).then(response => // Initialize our zig-js memory zjs.memory = memory; + // Create our atlas + const atlas = atlas_new(512, 0 /* greyscale */); + // Create some memory for our string const font = new TextEncoder().encode("monospace"); const font_ptr = malloc(font.byteLength); - try { new Uint8Array(memory.buffer, font_ptr).set(font); - // Call whatever example you want: - const face = face_new(font_ptr, font.byteLength, 14); + // Call whatever example you want: + const face = face_new(font_ptr, font.byteLength, 144); + free(font_ptr); + + // Render a glyph + face_render_glyph(face, atlas, "A".codePointAt(0)); + + // Debug our canvas + face_debug_canvas(face); + //face_free(face); - } finally { - free(font_ptr); - } }); diff --git a/example/index.html b/example/index.html index 0866d6256..12b4fb1dd 100644 --- a/example/index.html +++ b/example/index.html @@ -6,6 +6,8 @@ - Open your console, we are just debugging here. +

Open your console, we are just debugging here.

+

The font rendering canvas should show below. This shows a single glyph.

+
diff --git a/src/font/face/freetype.zig b/src/font/face/freetype.zig index eca1da33c..526a980fc 100644 --- a/src/font/face/freetype.zig +++ b/src/font/face/freetype.zig @@ -113,7 +113,7 @@ pub const Face = struct { /// Returns true if this font is colored. This can be used by callers to /// determine what kind of atlas to pass in. - pub fn hasColor(self: Face) bool { + fn hasColor(self: Face) bool { return self.face.hasColor(); } diff --git a/src/font/face/web_canvas.zig b/src/font/face/web_canvas.zig index 1c552a6f3..4cd7a8de9 100644 --- a/src/font/face/web_canvas.zig +++ b/src/font/face/web_canvas.zig @@ -73,41 +73,120 @@ pub const Face = struct { self.* = undefined; } - /// Calculate the metrics associated with a given face. - fn calcMetrics(self: *Face) !void { - // This will return the same context on subsequent calls so it - // is important to reset it. - const ctx = try self.canvas.call(js.Object, "getContext", .{js.string("2d")}); + /// Resize the font in-place. If this succeeds, the caller is responsible + /// for clearing any glyph caches, font atlas data, etc. + pub fn setSize(self: *Face, size: font.face.DesiredSize) !void { + const old = self.size; + self.size = size; + errdefer self.size = old; + try self.calcMetrics(); + } + + /// Returns the glyph index for the given Unicode code point. For canvas, + /// we support every glyph and the ID is just the codepoint since we don't + /// have access to the underlying tables anyways. We let the browser deal + /// with bad codepoints. + pub fn glyphIndex(self: Face, cp: u32) ?u32 { + _ = self; + return cp; + } + + /// Render a glyph using the glyph index. The rendered glyph is stored in the + /// given texture atlas. + pub fn renderGlyph( + self: Face, + alloc: Allocator, + atlas: *font.Atlas, + glyph_index: u32, + max_height: ?u16, + ) !font.Glyph { + // Encode our glyph into UTF-8 so we can build a JS string out of it. + var utf8: [4]u8 = undefined; + const utf8_len = try std.unicode.utf8Encode(@intCast(u21, glyph_index), &utf8); + const glyph_str = js.string(utf8[0..utf8_len]); + + // Get our drawing context + const measure_ctx = try self.context(); + defer measure_ctx.deinit(); + + // Get the width and height of the render + const metrics = try measure_ctx.call(js.Object, "measureText", .{glyph_str}); + defer metrics.deinit(); + const width: u32 = @floatToInt(u32, @ceil(width: { + // We prefer the bounding box since it is tighter but certain + // text such as emoji do not have a bounding box set so we use + // the full run width instead. + const bounding_right = try metrics.get(f32, "actualBoundingBoxRight"); + if (bounding_right > 0) break :width bounding_right; + break :width try metrics.get(f32, "width"); + })); + + // Height is our ascender + descender for this char + const asc = try metrics.get(f32, "actualBoundingBoxAscent"); + const desc = try metrics.get(f32, "actualBoundingBoxDescent"); + const height = @floatToInt(u32, @ceil(asc + desc)); + + // Resize canvas to match the glyph size exactly + { + try self.canvas.set("width", width); + try self.canvas.set("height", height); + + const width_str = try std.fmt.allocPrint(alloc, "{d}px", .{width}); + defer alloc.free(width_str); + const height_str = try std.fmt.allocPrint(alloc, "{d}px", .{height}); + defer alloc.free(height_str); + + const style = try self.canvas.get(js.Object, "style"); + defer style.deinit(); + try style.set("width", js.string(width_str)); + try style.set("height", js.string(height_str)); + } + + // Reload our context since we resized the canvas + const ctx = try self.context(); defer ctx.deinit(); - // Set our context font - var font_val = try std.fmt.allocPrint( - self.alloc, - "{d}px {s}", - .{ self.size.points, self.font_str }, - ); - defer self.alloc.free(font_val); - try ctx.set("font", js.string(font_val)); + // Set our alignment different since we want it centered exactly + try ctx.set("textBaseline", js.string("top")); - // If the font property didn't change, then the font set didn't work. - // We do this check because it is very easy to put an invalid font - // in and this at least makes it show up in the logs. - { - const check = try ctx.getAlloc(js.String, self.alloc, "font"); - defer self.alloc.free(check); - if (!std.mem.eql(u8, font_val, check)) { - log.warn("canvas font didn't set, fonts may be broken, expected={s} got={s}", .{ - font_val, - check, - }); - } - } + // Draw background + try ctx.set("fillStyle", js.string("transparent")); + try ctx.call(void, "fillRect", .{ + @as(u32, 0), + @as(u32, 0), + width, + height, + }); + + // Draw glyph + try ctx.set("fillStyle", js.string("black")); + try ctx.call(void, "fillText", .{ + glyph_str, + width / 2, + height / 2, + }); + + _ = atlas; + _ = max_height; + return error.Unimplemented; + } + + /// Calculate the metrics associated with a given face. + fn calcMetrics(self: *Face) !void { + const ctx = try self.context(); + defer ctx.deinit(); // Cell width is the width of our M text const cell_width: f32 = cell_width: { const metrics = try ctx.call(js.Object, "measureText", .{js.string("M")}); defer metrics.deinit(); - break :cell_width try metrics.get(f32, "actualBoundingBoxRight"); + + // We prefer the bounding box since it is tighter but certain + // text such as emoji do not have a bounding box set so we use + // the full run width instead. + const bounding_right = try metrics.get(f32, "actualBoundingBoxRight"); + if (bounding_right > 0) break :cell_width bounding_right; + break :cell_width try metrics.get(f32, "width"); }; // To get the cell height we render a high and low character and get @@ -136,7 +215,45 @@ pub const Face = struct { .strikethrough_thickness = underline_thickness, }; - log.debug("metrics font={s} value={}", .{ font_val, self.metrics }); + log.debug("metrics font={s} value={}", .{ self.font_str, self.metrics }); + } + + /// Returns the 2d context configured for drawing + fn context(self: Face) !js.Object { + // This will return the same context on subsequent calls so it + // is important to reset it. + const ctx = try self.canvas.call(js.Object, "getContext", .{js.string("2d")}); + errdefer ctx.deinit(); + + // Clear the canvas + { + const width = try self.canvas.get(f64, "width"); + const height = try self.canvas.get(f64, "height"); + try ctx.call(void, "clearRect", .{ 0, 0, width, height }); + } + + // Set our context font + var font_val = try std.fmt.allocPrint( + self.alloc, + "{d}px {s}", + .{ self.size.points, self.font_str }, + ); + defer self.alloc.free(font_val); + try ctx.set("font", js.string(font_val)); + + // If the font property didn't change, then the font set didn't work. + // We do this check because it is very easy to put an invalid font + // in and this at least makes it show up in the logs. + const check = try ctx.getAlloc(js.String, self.alloc, "font"); + defer self.alloc.free(check); + if (!std.mem.eql(u8, font_val, check)) { + log.warn("canvas font didn't set, fonts may be broken, expected={s} got={s}", .{ + font_val, + check, + }); + } + + return ctx; } }; @@ -165,4 +282,46 @@ pub const Wasm = struct { alloc.destroy(v); } } + + /// Resulting pointer must be freed using the global "free". + export fn face_render_glyph( + face: *Face, + atlas: *font.Atlas, + codepoint: u32, + ) ?*font.Glyph { + return face_render_glyph_(face, atlas, codepoint) catch |err| { + log.warn("error rendering glyph err={}", .{err}); + return null; + }; + } + + export fn face_debug_canvas(face: *Face) void { + face_debug_canvas_(face) catch |err| { + log.warn("error adding debug canvas err={}", .{err}); + }; + } + + fn face_debug_canvas_(face: *Face) !void { + const doc = try js.global.get(js.Object, "document"); + defer doc.deinit(); + + const elem = try doc.call( + ?js.Object, + "getElementById", + .{js.string("face-canvas")}, + ) orelse return error.CanvasContainerNotFound; + defer elem.deinit(); + + try elem.call(void, "append", .{face.canvas}); + } + + fn face_render_glyph_(face: *Face, atlas: *font.Atlas, codepoint: u32) !*font.Glyph { + const glyph = try face.renderGlyph(alloc, atlas, codepoint, null); + + const result = try alloc.create(font.Glyph); + errdefer alloc.destroy(result); + _ = try wasm.toHostOwned(result); + result.* = glyph; + return result; + } }; diff --git a/vendor/zig-js b/vendor/zig-js index a70f5da4f..3aebb1cbe 160000 --- a/vendor/zig-js +++ b/vendor/zig-js @@ -1 +1 @@ -Subproject commit a70f5da4f51b643be47fa39ba697dcd9444204c8 +Subproject commit 3aebb1cbee374025368e223ef23b0c488ba612eb From 84f6f374505bd11b0c62689b24583fddaf2f9f9f Mon Sep 17 00:00:00 2001 From: Mitchell Hashimoto Date: Mon, 5 Dec 2022 14:28:10 -0800 Subject: [PATCH 09/14] face: web canvas glyph rendering appears to work! --- src/font/face/web_canvas.zig | 75 +++++++++++++++++++++++++++++++++--- vendor/zig-js | 2 +- 2 files changed, 70 insertions(+), 7 deletions(-) diff --git a/src/font/face/web_canvas.zig b/src/font/face/web_canvas.zig index 4cd7a8de9..304ebb79d 100644 --- a/src/font/face/web_canvas.zig +++ b/src/font/face/web_canvas.zig @@ -100,6 +100,8 @@ pub const Face = struct { glyph_index: u32, max_height: ?u16, ) !font.Glyph { + _ = max_height; + // Encode our glyph into UTF-8 so we can build a JS string out of it. var utf8: [4]u8 = undefined; const utf8_len = try std.unicode.utf8Encode(@intCast(u21, glyph_index), &utf8); @@ -146,7 +148,9 @@ pub const Face = struct { const ctx = try self.context(); defer ctx.deinit(); - // Set our alignment different since we want it centered exactly + // We use top alignment because our renderer handles all the + // baseline and so on so we just want a top-left rendered glyph + // by itself. try ctx.set("textBaseline", js.string("top")); // Draw background @@ -162,13 +166,72 @@ pub const Face = struct { try ctx.set("fillStyle", js.string("black")); try ctx.call(void, "fillText", .{ glyph_str, - width / 2, - height / 2, + 0, + 0, }); - _ = atlas; - _ = max_height; - return error.Unimplemented; + // Read the image data and get it into a []u8 on our side + const bitmap: []u8 = bitmap: { + // Read the raw bitmap data and get the "data" value which is a + // Uint8ClampedArray. + const data = try ctx.call(js.Object, "getImageData", .{ 0, 0, width, height }); + defer data.deinit(); + const src_array = try data.get(js.Object, "data"); + defer src_array.deinit(); + + // Allocate our local memory to copy the data to. + const len = try src_array.get(u32, "length"); + var bitmap = try alloc.alloc(u8, @intCast(usize, len)); + errdefer alloc.free(bitmap); + + // Create our target Uint8Array that we can use to copy from src. + const mem_array = mem_array: { + // Get our runtime memory + const mem = try js.runtime.get(js.Object, "memory"); + defer mem.deinit(); + const buf = try mem.get(js.Object, "buffer"); + defer buf.deinit(); + + // Construct our array to peer into our memory + const Uint8Array = try js.global.get(js.Object, "Uint8Array"); + defer Uint8Array.deinit(); + const mem_array = try Uint8Array.new(.{ buf, bitmap.ptr }); + errdefer mem_array.deinit(); + + break :mem_array mem_array; + }; + defer mem_array.deinit(); + + // Copy + try mem_array.call(void, "set", .{src_array}); + + break :bitmap bitmap; + }; + defer alloc.free(bitmap); + + // The bitmap is in RGBA format and we just want alpha8. + assert(@mod(bitmap.len, 4) == 0); + var bitmap_a8 = try alloc.alloc(u8, bitmap.len / 4); + defer alloc.free(bitmap_a8); + var i: usize = 0; + while (i < bitmap_a8.len) : (i += 1) { + bitmap_a8[i] = bitmap[i * 4]; + } + + // Put it in our atlas + const region = try atlas.reserve(alloc, width, height); + if (region.width > 0 and region.height > 0) atlas.set(region, bitmap_a8); + + return font.Glyph{ + .width = width, + .height = height, + // TODO: this can't be right + .offset_x = 0, + .offset_y = 0, + .atlas_x = region.x, + .atlas_y = region.y, + .advance_x = 0, + }; } /// Calculate the metrics associated with a given face. diff --git a/vendor/zig-js b/vendor/zig-js index 3aebb1cbe..00eb5166e 160000 --- a/vendor/zig-js +++ b/vendor/zig-js @@ -1 +1 @@ -Subproject commit 3aebb1cbee374025368e223ef23b0c488ba612eb +Subproject commit 00eb5166ea3a070ac985b2b4409f2e51877865f4 From 5e9dd02eab233ceba8f31d879a8d66cbdf747dc9 Mon Sep 17 00:00:00 2001 From: Mitchell Hashimoto Date: Mon, 5 Dec 2022 15:01:34 -0800 Subject: [PATCH 10/14] font: add method for drawing atlas to canvas --- example/app.ts | 12 ++++- example/index.html | 4 +- src/font/Atlas.zig | 96 ++++++++++++++++++++++++++++++++++-- src/font/face/web_canvas.zig | 2 +- vendor/zig-js | 2 +- 5 files changed, 107 insertions(+), 9 deletions(-) diff --git a/example/app.ts b/example/app.ts index 65ba6450f..9113faa5d 100644 --- a/example/app.ts +++ b/example/app.ts @@ -30,6 +30,7 @@ fetch(url.href).then(response => face_debug_canvas, atlas_new, atlas_free, + atlas_debug_canvas, } = results.instance.exports; // Give us access to the zjs value for debugging. globalThis.zjs = zjs; @@ -47,14 +48,21 @@ fetch(url.href).then(response => new Uint8Array(memory.buffer, font_ptr).set(font); // Call whatever example you want: - const face = face_new(font_ptr, font.byteLength, 144); + const face = face_new(font_ptr, font.byteLength, 72); free(font_ptr); // Render a glyph - face_render_glyph(face, atlas, "A".codePointAt(0)); + for (let i = 33; i <= 126; i++) { + face_render_glyph(face, atlas, i); + } + // face_render_glyph(face, atlas, "A".codePointAt(0)); // Debug our canvas face_debug_canvas(face); + // Debug our atlas canvas + const id = atlas_debug_canvas(atlas); + document.getElementById("atlas-canvas").append(zjs.deleteValue(id)); + //face_free(face); }); diff --git a/example/index.html b/example/index.html index 12b4fb1dd..a9bd81547 100644 --- a/example/index.html +++ b/example/index.html @@ -8,6 +8,8 @@

Open your console, we are just debugging here.

The font rendering canvas should show below. This shows a single glyph.

-
+
+

The current font atlas is rendered below.

+
diff --git a/src/font/Atlas.zig b/src/font/Atlas.zig index a48edb966..bcfc6f9c5 100644 --- a/src/font/Atlas.zig +++ b/src/font/Atlas.zig @@ -21,6 +21,8 @@ const Allocator = std.mem.Allocator; const testing = std.testing; const fastmem = @import("../fastmem.zig"); +const log = std.log.scoped(.atlas); + /// Data is the raw texture data. data: []u8, @@ -309,6 +311,7 @@ pub const Wasm = struct { // just replace this with the allocator you want to use. const wasm = @import("../os/wasm.zig"); const alloc = wasm.alloc; + const js = @import("zig-js"); export fn atlas_new(size: u32, format: u8) ?*Atlas { const atlas = init( @@ -321,6 +324,13 @@ pub const Wasm = struct { return result; } + export fn atlas_free(ptr: ?*Atlas) void { + if (ptr) |v| { + v.deinit(alloc); + alloc.destroy(v); + } + } + /// The return value for this should be freed by the caller with "free". export fn atlas_reserve(self: *Atlas, width: u32, height: u32) ?*Region { return atlas_reserve_(self, width, height) catch return null; @@ -348,11 +358,89 @@ pub const Wasm = struct { self.clear(); } - export fn atlas_free(ptr: ?*Atlas) void { - if (ptr) |v| { - v.deinit(alloc); - alloc.destroy(v); + /// This creates a Canvas element identified by the id returned that + /// the caller can draw into the DOM to visualize the atlas. The returned + /// ID must be freed from the JS runtime by calling "zigjs.deleteValue". + export fn atlas_debug_canvas(self: *Atlas) u32 { + return atlas_debug_canvas_(self) catch |err| { + log.warn("error dumping atlas canvas err={}", .{err}); + return 0; + }; + } + + fn atlas_debug_canvas_(self: *Atlas) !u32 { + // Create our canvas + const doc = try js.global.get(js.Object, "document"); + defer doc.deinit(); + const canvas = try doc.call(js.Object, "createElement", .{js.string("canvas")}); + errdefer canvas.deinit(); + + // Setup our canvas size + { + try canvas.set("width", self.size); + try canvas.set("height", self.size); + + const width_str = try std.fmt.allocPrint(alloc, "{d}px", .{self.size}); + defer alloc.free(width_str); + + const style = try canvas.get(js.Object, "style"); + defer style.deinit(); + try style.set("width", js.string(width_str)); + try style.set("height", js.string(width_str)); } + + // This will return the same context on subsequent calls so it + // is important to reset it. + const ctx = try canvas.call(js.Object, "getContext", .{js.string("2d")}); + errdefer ctx.deinit(); + + // We need to draw pixels so this is format dependent. + var buf: []u8 = switch (self.format) { + // RGBA is the native ImageData format + .rgba => self.data, + + .greyscale => buf: { + // Convert from A8 to RGBA so every 4th byte is set to a value. + var buf: []u8 = try alloc.alloc(u8, self.data.len * 4); + errdefer alloc.free(buf); + std.mem.set(u8, buf, 0); + for (self.data) |value, i| { + buf[(i * 4) + 3] = value; + } + break :buf buf; + }, + + else => return error.UnsupportedAtlasFormat, + }; + defer if (buf.ptr != self.data.ptr) alloc.free(buf); + + // Create an ImageData from our buffer and then write it to the canvas + const image_data: js.Object = data: { + // Get our runtime memory + const mem = try js.runtime.get(js.Object, "memory"); + defer mem.deinit(); + const mem_buf = try mem.get(js.Object, "buffer"); + defer mem_buf.deinit(); + + // Create an array that points to our buffer + const Uint8ClampedArray = try js.global.get(js.Object, "Uint8ClampedArray"); + defer Uint8ClampedArray.deinit(); + const arr = try Uint8ClampedArray.new(.{ mem_buf, buf.ptr, buf.len }); + + // Create the image data from our array + const ImageData = try js.global.get(js.Object, "ImageData"); + defer ImageData.deinit(); + const data = try ImageData.new(.{ arr, self.size, self.size }); + errdefer data.deinit(); + + break :data data; + }; + + // Draw it + try ctx.call(void, "putImageData", .{ image_data, 0, 0 }); + + const id = @bitCast(js.Ref, @enumToInt(canvas.value)).id; + return id; } test "happy path" { diff --git a/src/font/face/web_canvas.zig b/src/font/face/web_canvas.zig index 304ebb79d..25dca9a19 100644 --- a/src/font/face/web_canvas.zig +++ b/src/font/face/web_canvas.zig @@ -215,7 +215,7 @@ pub const Face = struct { defer alloc.free(bitmap_a8); var i: usize = 0; while (i < bitmap_a8.len) : (i += 1) { - bitmap_a8[i] = bitmap[i * 4]; + bitmap_a8[i] = bitmap[(i * 4) + 3]; } // Put it in our atlas diff --git a/vendor/zig-js b/vendor/zig-js index 00eb5166e..52eed4dad 160000 --- a/vendor/zig-js +++ b/vendor/zig-js @@ -1 +1 @@ -Subproject commit 00eb5166ea3a070ac985b2b4409f2e51877865f4 +Subproject commit 52eed4daddcf9fa974ad4457691de26ef2351c56 From 25f2f1a652ab01a6f404d867e955172a3112654b Mon Sep 17 00:00:00 2001 From: Mitchell Hashimoto Date: Mon, 5 Dec 2022 15:25:09 -0800 Subject: [PATCH 11/14] font: fix glyph offset calculations for render --- example/app.ts | 2 +- src/font/Atlas.zig | 2 ++ src/font/face/web_canvas.zig | 11 ++++------- 3 files changed, 7 insertions(+), 8 deletions(-) diff --git a/example/app.ts b/example/app.ts index 9113faa5d..966bb4224 100644 --- a/example/app.ts +++ b/example/app.ts @@ -55,7 +55,7 @@ fetch(url.href).then(response => for (let i = 33; i <= 126; i++) { face_render_glyph(face, atlas, i); } - // face_render_glyph(face, atlas, "A".codePointAt(0)); + //face_render_glyph(face, atlas, "p".codePointAt(0)); // Debug our canvas face_debug_canvas(face); diff --git a/src/font/Atlas.zig b/src/font/Atlas.zig index bcfc6f9c5..db73f1e90 100644 --- a/src/font/Atlas.zig +++ b/src/font/Atlas.zig @@ -426,6 +426,7 @@ pub const Wasm = struct { const Uint8ClampedArray = try js.global.get(js.Object, "Uint8ClampedArray"); defer Uint8ClampedArray.deinit(); const arr = try Uint8ClampedArray.new(.{ mem_buf, buf.ptr, buf.len }); + defer arr.deinit(); // Create the image data from our array const ImageData = try js.global.get(js.Object, "ImageData"); @@ -435,6 +436,7 @@ pub const Wasm = struct { break :data data; }; + defer image_data.deinit(); // Draw it try ctx.call(void, "putImageData", .{ image_data, 0, 0 }); diff --git a/src/font/face/web_canvas.zig b/src/font/face/web_canvas.zig index 25dca9a19..8fd84edc2 100644 --- a/src/font/face/web_canvas.zig +++ b/src/font/face/web_canvas.zig @@ -126,6 +126,7 @@ pub const Face = struct { // Height is our ascender + descender for this char const asc = try metrics.get(f32, "actualBoundingBoxAscent"); const desc = try metrics.get(f32, "actualBoundingBoxDescent"); + const left = try metrics.get(f32, "actualBoundingBoxLeft"); const height = @floatToInt(u32, @ceil(asc + desc)); // Resize canvas to match the glyph size exactly @@ -148,11 +149,6 @@ pub const Face = struct { const ctx = try self.context(); defer ctx.deinit(); - // We use top alignment because our renderer handles all the - // baseline and so on so we just want a top-left rendered glyph - // by itself. - try ctx.set("textBaseline", js.string("top")); - // Draw background try ctx.set("fillStyle", js.string("transparent")); try ctx.call(void, "fillRect", .{ @@ -163,11 +159,12 @@ pub const Face = struct { }); // Draw glyph + // TODO: may need a +1 on the left/asc here to avoid clipping try ctx.set("fillStyle", js.string("black")); try ctx.call(void, "fillText", .{ glyph_str, - 0, - 0, + left, + asc, }); // Read the image data and get it into a []u8 on our side From ed4e8c36b064e653499b2987cedbd8c47796f807 Mon Sep 17 00:00:00 2001 From: Mitchell Hashimoto Date: Mon, 5 Dec 2022 15:37:55 -0800 Subject: [PATCH 12/14] font: add 1 to the canvas glyph to avoid clipping --- example/app.ts | 4 ++-- src/font/face/web_canvas.zig | 12 ++++++++---- 2 files changed, 10 insertions(+), 6 deletions(-) diff --git a/example/app.ts b/example/app.ts index 966bb4224..696d1d17a 100644 --- a/example/app.ts +++ b/example/app.ts @@ -47,8 +47,8 @@ fetch(url.href).then(response => const font_ptr = malloc(font.byteLength); new Uint8Array(memory.buffer, font_ptr).set(font); - // Call whatever example you want: - const face = face_new(font_ptr, font.byteLength, 72); + // Initialize our font face + const face = face_new(font_ptr, font.byteLength, 72 /* size in px */); free(font_ptr); // Render a glyph diff --git a/src/font/face/web_canvas.zig b/src/font/face/web_canvas.zig index 8fd84edc2..addac8763 100644 --- a/src/font/face/web_canvas.zig +++ b/src/font/face/web_canvas.zig @@ -121,13 +121,17 @@ pub const Face = struct { const bounding_right = try metrics.get(f32, "actualBoundingBoxRight"); if (bounding_right > 0) break :width bounding_right; break :width try metrics.get(f32, "width"); - })); + })) + 1; // Height is our ascender + descender for this char const asc = try metrics.get(f32, "actualBoundingBoxAscent"); const desc = try metrics.get(f32, "actualBoundingBoxDescent"); const left = try metrics.get(f32, "actualBoundingBoxLeft"); - const height = @floatToInt(u32, @ceil(asc + desc)); + const height = @floatToInt(u32, @ceil(asc + desc)) + 1; + + // Note: width and height both get "+ 1" added to them above. This + // is important so that there is a 1px border around the glyph to avoid + // any clipping in the atlas. // Resize canvas to match the glyph size exactly { @@ -163,8 +167,8 @@ pub const Face = struct { try ctx.set("fillStyle", js.string("black")); try ctx.call(void, "fillText", .{ glyph_str, - left, - asc, + left + 1, + asc + 1, }); // Read the image data and get it into a []u8 on our side From d2afddb7e24c8ccbfbdd3c96f27cf3c927f5f5b7 Mon Sep 17 00:00:00 2001 From: Mitchell Hashimoto Date: Mon, 5 Dec 2022 15:45:31 -0800 Subject: [PATCH 13/14] font: fix some JS memory leaks --- example/app.ts | 1 + src/font/Atlas.zig | 2 +- src/font/face/web_canvas.zig | 1 - 3 files changed, 2 insertions(+), 2 deletions(-) diff --git a/example/app.ts b/example/app.ts index 696d1d17a..4026bbc04 100644 --- a/example/app.ts +++ b/example/app.ts @@ -55,6 +55,7 @@ fetch(url.href).then(response => for (let i = 33; i <= 126; i++) { face_render_glyph(face, atlas, i); } + //face_render_glyph(face, atlas, "橋".codePointAt(0)); //face_render_glyph(face, atlas, "p".codePointAt(0)); // Debug our canvas diff --git a/src/font/Atlas.zig b/src/font/Atlas.zig index db73f1e90..f38af41df 100644 --- a/src/font/Atlas.zig +++ b/src/font/Atlas.zig @@ -392,7 +392,7 @@ pub const Wasm = struct { // This will return the same context on subsequent calls so it // is important to reset it. const ctx = try canvas.call(js.Object, "getContext", .{js.string("2d")}); - errdefer ctx.deinit(); + defer ctx.deinit(); // We need to draw pixels so this is format dependent. var buf: []u8 = switch (self.format) { diff --git a/src/font/face/web_canvas.zig b/src/font/face/web_canvas.zig index addac8763..6f5e86a2d 100644 --- a/src/font/face/web_canvas.zig +++ b/src/font/face/web_canvas.zig @@ -163,7 +163,6 @@ pub const Face = struct { }); // Draw glyph - // TODO: may need a +1 on the left/asc here to avoid clipping try ctx.set("fillStyle", js.string("black")); try ctx.call(void, "fillText", .{ glyph_str, From 2a74330911bb9cb000f5c2671b0854da683e505d Mon Sep 17 00:00:00 2001 From: Mitchell Hashimoto Date: Mon, 5 Dec 2022 16:08:20 -0800 Subject: [PATCH 14/14] font: begin making Group work with wasm --- build.zig | 2 ++ src/font/DeferredFace.zig | 22 ++++++++++---------- src/font/Group.zig | 20 +++++++++++++++++++ src/font/Library.zig | 19 ------------------ src/font/face.zig | 10 ++++++---- src/font/library.zig | 42 +++++++++++++++++++++++++++++++++++++++ src/font/main.zig | 8 ++++++-- 7 files changed, 86 insertions(+), 37 deletions(-) delete mode 100644 src/font/Library.zig create mode 100644 src/font/library.zig diff --git a/build.zig b/build.zig index fadf1539b..ee98edeb0 100644 --- a/build.zig +++ b/build.zig @@ -121,6 +121,8 @@ pub fn build(b: *std.build.Builder) !void { wasm.setBuildMode(mode); wasm.setOutputDir("zig-out"); + wasm.addOptions("build_options", exe_options); + // Wasm-specific deps wasm.addPackage(js.pkg); wasm.addPackage(tracylib.pkg); diff --git a/src/font/DeferredFace.zig b/src/font/DeferredFace.zig index 9ae816fa2..0c8fd709e 100644 --- a/src/font/DeferredFace.zig +++ b/src/font/DeferredFace.zig @@ -24,8 +24,8 @@ fc: if (options.backend == .fontconfig_freetype) ?Fontconfig else void = if (options.backend == .fontconfig_freetype) null else {}, /// CoreText -ct: if (options.backend == .coretext) ?CoreText else void = - if (options.backend == .coretext) null else {}, +ct: if (font.Discover == font.discovery.CoreText) ?CoreText else void = + if (font.Discover == font.discovery.CoreText) null else {}, /// Fontconfig specific data. This is only present if building with fontconfig. pub const Fontconfig = struct { @@ -66,7 +66,7 @@ pub fn deinit(self: *DeferredFace) void { if (self.face) |*face| face.deinit(); switch (options.backend) { .fontconfig_freetype => if (self.fc) |*fc| fc.deinit(), - .coretext => if (self.ct) |*ct| ct.deinit(), + .coretext, .coretext_freetype => if (self.ct) |*ct| ct.deinit(), .freetype => {}, // TODO .web_canvas => unreachable, @@ -86,7 +86,7 @@ pub fn name(self: DeferredFace) ![:0]const u8 { .fontconfig_freetype => if (self.fc) |fc| return (try fc.pattern.get(.fullname, 0)).string, - .coretext => if (self.ct) |ct| { + .coretext, .coretext_freetype => if (self.ct) |ct| { const display_name = ct.font.copyDisplayName(); return display_name.cstringPtr(.utf8) orelse ""; }, @@ -116,14 +116,12 @@ pub fn load( }, .coretext => { - // It is possible to use CoreText with Freetype so we support - // both here. - switch (font.Face) { - @import("face/freetype.zig").Face => try self.loadCoreTextFreetype(lib, size), - @import("face/coretext.zig").Face => try self.loadCoreText(lib, size), - else => unreachable, - } + try self.loadCoreText(lib, size); + return; + }, + .coretext_freetype => { + try self.loadCoreTextFreetype(lib, size); return; }, @@ -239,7 +237,7 @@ pub fn hasCodepoint(self: DeferredFace, cp: u32, p: ?Presentation) bool { } }, - .coretext => { + .coretext, .coretext_freetype => { // If we are using coretext, we check the loaded CT font. if (self.ct) |ct| { // Turn UTF-32 into UTF-16 for CT API diff --git a/src/font/Group.zig b/src/font/Group.zig index 90024bdd8..92fbf7100 100644 --- a/src/font/Group.zig +++ b/src/font/Group.zig @@ -285,6 +285,26 @@ pub fn renderGlyph( return try face.face.?.renderGlyph(alloc, atlas, glyph_index, max_height); } +/// The wasm-compatible API. +pub const Wasm = struct { + const wasm = @import("../os/wasm.zig"); + const alloc = wasm.alloc; + + export fn group_new(pts: u16) ?*Group { + return group_new_(pts) catch null; + } + + fn group_new_(pts: u16) !*Group { + var group = try Group.init(alloc, .{}, .{ .points = pts }); + errdefer group.deinit(); + + var result = try alloc.create(Group); + errdefer alloc.destroy(result); + result.* = group; + return result; + } +}; + test { const testing = std.testing; const alloc = testing.allocator; diff --git a/src/font/Library.zig b/src/font/Library.zig deleted file mode 100644 index 62a4e77d0..000000000 --- a/src/font/Library.zig +++ /dev/null @@ -1,19 +0,0 @@ -//! A library represents the shared state that the underlying font -//! library implementation(s) require per-process. -//! -//! In the future, this will be abstracted so that the underlying text -//! engine might not be Freetype and may be something like Core Text, -//! but the API will remain the same. -const Library = @This(); - -const freetype = @import("freetype"); - -lib: freetype.Library, - -pub fn init() freetype.Error!Library { - return Library{ .lib = try freetype.Library.init() }; -} - -pub fn deinit(self: *Library) void { - self.lib.deinit(); -} diff --git a/src/font/face.zig b/src/font/face.zig index e94b4ee94..b6d7465cf 100644 --- a/src/font/face.zig +++ b/src/font/face.zig @@ -6,11 +6,13 @@ pub const web_canvas = @import("face/web_canvas.zig"); /// Face implementation for the compile options. pub const Face = switch (options.backend) { - .fontconfig_freetype => freetype.Face, - .coretext => freetype.Face, - //.coretext => coretext.Face, + .freetype, + .fontconfig_freetype, + .coretext_freetype, + => freetype.Face, + + .coretext => coretext.Face, .web_canvas => web_canvas.Face, - else => unreachable, }; /// If a DPI can't be calculated, this DPI is used. This is probably diff --git a/src/font/library.zig b/src/font/library.zig new file mode 100644 index 000000000..7b7417cf4 --- /dev/null +++ b/src/font/library.zig @@ -0,0 +1,42 @@ +//! A library represents the shared state that the underlying font +//! library implementation(s) require per-process. +const builtin = @import("builtin"); +const options = @import("main.zig").options; +const freetype = @import("freetype"); +const font = @import("main.zig"); + +/// Library implementation for the compile options. +pub const Library = switch (options.backend) { + // Freetype requires a state library + .freetype, + .fontconfig_freetype, + .coretext_freetype, + => FreetypeLibrary, + + // Some backends such as CT and Canvas don't have a "library" + .coretext, + .web_canvas, + => NoopLibrary, +}; + +pub const FreetypeLibrary = struct { + lib: freetype.Library, + + pub fn init() freetype.Error!Library { + return Library{ .lib = try freetype.Library.init() }; + } + + pub fn deinit(self: *Library) void { + self.lib.deinit(); + } +}; + +pub const NoopLibrary = struct { + pub fn init() !Library { + return Library{}; + } + + pub fn deinit(self: *Library) void { + _ = self; + } +}; diff --git a/src/font/main.zig b/src/font/main.zig index 10c63d49f..008b955c0 100644 --- a/src/font/main.zig +++ b/src/font/main.zig @@ -10,16 +10,17 @@ pub const Face = face.Face; pub const Group = @import("Group.zig"); pub const GroupCache = @import("GroupCache.zig"); pub const Glyph = @import("Glyph.zig"); -pub const Library = @import("Library.zig"); pub const Shaper = @import("Shaper.zig"); pub const sprite = @import("sprite.zig"); pub const Sprite = sprite.Sprite; pub const Descriptor = discovery.Descriptor; pub const Discover = discovery.Discover; +pub usingnamespace @import("library.zig"); /// If we're targeting wasm then we export some wasm APIs. pub usingnamespace if (builtin.target.isWasm()) struct { pub usingnamespace Atlas.Wasm; + pub usingnamespace Group.Wasm; pub usingnamespace face.web_canvas.Wasm; } else struct {}; @@ -37,9 +38,12 @@ pub const Backend = enum { /// Fontconfig for font discovery and FreeType for font rendering. fontconfig_freetype, - /// CoreText for both font discovery and rendering (macOS). + /// CoreText for both font discovery for rendering (macOS). coretext, + /// CoreText for font discovery and FreeType for rendering (macOS). + coretext_freetype, + /// Use the browser font system and the Canvas API (wasm). This limits /// the available fonts to browser fonts (anything Canvas natively /// supports).