From a42193b997b562467fd714dd3405d1eaf709951a Mon Sep 17 00:00:00 2001 From: Mitchell Hashimoto Date: Sat, 20 Sep 2025 14:37:04 -0700 Subject: [PATCH 01/19] start extracting core terminal zig module --- build.zig | 47 +++++++++++++++++++++------ src/build/GhosttyZig.zig | 36 ++++++++++++++++++++ src/build/SharedDeps.zig | 15 +++++++++ src/build/UnicodeTables.zig | 14 ++++++-- src/build/main.zig | 1 + src/config/Config.zig | 11 ++++++- src/lib_vt.zig | 5 +++ src/os/TempDir.zig | 7 ++-- src/terminal/PageList.zig | 14 ++++---- src/terminal/Screen.zig | 24 +++----------- src/terminal/build_options.zig | 31 ++++++++++++++++++ src/terminal/cursor.zig | 15 +++++++++ src/terminal/kitty/graphics_image.zig | 19 +++++++---- src/terminal/mouse_shape.zig | 21 ++++++++---- src/terminal/page.zig | 24 +++++++------- 15 files changed, 215 insertions(+), 69 deletions(-) create mode 100644 src/build/GhosttyZig.zig create mode 100644 src/lib_vt.zig create mode 100644 src/terminal/build_options.zig create mode 100644 src/terminal/cursor.zig diff --git a/build.zig b/build.zig index 38cfd0e56..f651c30e4 100644 --- a/build.zig +++ b/build.zig @@ -8,12 +8,25 @@ comptime { } pub fn build(b: *std.Build) !void { - // This defines all the available build options (e.g. `-D`). + // This defines all the available build options (e.g. `-D`). If you + // want to know what options are available, you can run `--help` or + // you can read `src/build/Config.zig`. const config = try buildpkg.Config.init(b); - const test_filter = b.option( - []const u8, + const test_filters = b.option( + [][]const u8, "test-filter", "Filter for test. Only applies to Zig tests.", + ) orelse &[0][]const u8{}; + + // Ghostty dependencies used by many artifacts. + const deps = try buildpkg.SharedDeps.init(b, &config); + + // The modules exported for Zig consumers of libghostty. If you're + // writing a Zig program that uses libghostty, read this file. + const mod = try buildpkg.GhosttyZig.init( + b, + &config, + &deps, ); // All our steps which we'll hook up later. The steps are shown @@ -24,6 +37,10 @@ pub fn build(b: *std.Build) !void { "Run the app under valgrind", ); const test_step = b.step("test", "Run tests"); + const test_lib_vt_step = b.step( + "test-lib-vt", + "Run libghostty-vt tests", + ); const test_valgrind_step = b.step( "test-valgrind", "Run tests under valgrind", @@ -37,10 +54,6 @@ pub fn build(b: *std.Build) !void { const resources = try buildpkg.GhosttyResources.init(b, &config); const i18n = if (config.i18n) try buildpkg.GhosttyI18n.init(b, &config) else null; - // Ghostty dependencies used by many artifacts. - const deps = try buildpkg.SharedDeps.init(b, &config); - if (config.emit_helpgen) deps.help_strings.install(); - // Ghostty executable, the actual runnable Ghostty program. const exe = try buildpkg.GhosttyExe.init(b, &config, &deps); @@ -83,6 +96,9 @@ pub fn build(b: *std.Build) !void { &deps, ); + // Helpgen + if (config.emit_helpgen) deps.help_strings.install(); + // Runtime "none" is libghostty, anything else is an executable. if (config.app_runtime != .none) { if (config.emit_exe) { @@ -185,7 +201,7 @@ pub fn build(b: *std.Build) !void { run_step.dependOn(&macos_app_native_only.open.step); // If we have no test filters, install the tests too - if (test_filter == null) { + if (test_filters.len == 0) { macos_app_native_only.addTestStepDependencies(test_step); } } @@ -216,11 +232,23 @@ pub fn build(b: *std.Build) !void { run_valgrind_step.dependOn(&run_cmd.step); } + // Zig module tests + { + const mod_vt_test = b.addTest(.{ + .root_module = mod.vt, + .target = config.target, + .optimize = config.optimize, + .filters = test_filters, + }); + test_lib_vt_step.dependOn(&mod_vt_test.step); + } + // Tests { + // Full unit tests const test_exe = b.addTest(.{ .name = "ghostty-test", - .filters = if (test_filter) |v| &.{v} else &.{}, + .filters = test_filters, .root_module = b.createModule(.{ .root_source_file = b.path("src/main.zig"), .target = config.baselineTarget(), @@ -230,7 +258,6 @@ pub fn build(b: *std.Build) !void { .unwind_tables = .sync, }), }); - if (config.emit_test_exe) b.installArtifact(test_exe); _ = try deps.add(test_exe); diff --git a/src/build/GhosttyZig.zig b/src/build/GhosttyZig.zig new file mode 100644 index 000000000..e3c22bc67 --- /dev/null +++ b/src/build/GhosttyZig.zig @@ -0,0 +1,36 @@ +//! GhosttyZig generates the Zig modules that Ghostty exports +//! for downstream usage. +const GhosttyZig = @This(); + +const std = @import("std"); +const Config = @import("Config.zig"); +const SharedDeps = @import("SharedDeps.zig"); + +const vt_options = @import("../terminal/build_options.zig"); + +vt: *std.Build.Module, + +pub fn init( + b: *std.Build, + cfg: *const Config, + deps: *const SharedDeps, +) !GhosttyZig { + const vt = b.addModule("ghostty-vt", .{ + .root_source_file = b.path("src/lib_vt.zig"), + .target = cfg.target, + .optimize = cfg.optimize, + }); + deps.unicode_tables.addModuleImport(vt); + vt_options.addOptions(b, vt, .{ + .artifact = .lib, + .slow_runtime_safety = switch (cfg.optimize) { + .Debug => true, + .ReleaseSafe, + .ReleaseSmall, + .ReleaseFast, + => false, + }, + }); + + return .{ .vt = vt }; +} diff --git a/src/build/SharedDeps.zig b/src/build/SharedDeps.zig index ab5b0d8bf..67d416f5d 100644 --- a/src/build/SharedDeps.zig +++ b/src/build/SharedDeps.zig @@ -107,6 +107,21 @@ pub fn add( // Every exe gets build options populated step.root_module.addOptions("build_options", self.options); + // Every exe needs the terminal options + { + const vt_options = @import("../terminal/build_options.zig"); + vt_options.addOptions(b, step.root_module, .{ + .artifact = .ghostty, + .slow_runtime_safety = switch (optimize) { + .Debug => true, + .ReleaseSafe, + .ReleaseSmall, + .ReleaseFast, + => false, + }, + }); + } + // Freetype _ = b.systemIntegrationOption("freetype", .{}); // Shows it in help if (self.config.font_backend.hasFreetype()) { diff --git a/src/build/UnicodeTables.zig b/src/build/UnicodeTables.zig index 6733b5315..0f558b708 100644 --- a/src/build/UnicodeTables.zig +++ b/src/build/UnicodeTables.zig @@ -64,11 +64,19 @@ pub fn init(b: *std.Build) !UnicodeTables { /// Add the "unicode_tables" import. pub fn addImport(self: *const UnicodeTables, step: *std.Build.Step.Compile) void { self.props_output.addStepDependencies(&step.step); - step.root_module.addAnonymousImport("unicode_tables", .{ + self.symbols_output.addStepDependencies(&step.step); + self.addModuleImport(step.root_module); +} + +/// Add the "unicode_tables" import to a module. +pub fn addModuleImport( + self: *const UnicodeTables, + module: *std.Build.Module, +) void { + module.addAnonymousImport("unicode_tables", .{ .root_source_file = self.props_output, }); - self.symbols_output.addStepDependencies(&step.step); - step.root_module.addAnonymousImport("symbols_tables", .{ + module.addAnonymousImport("symbols_tables", .{ .root_source_file = self.symbols_output, }); } diff --git a/src/build/main.zig b/src/build/main.zig index af99802df..0ee41352b 100644 --- a/src/build/main.zig +++ b/src/build/main.zig @@ -18,6 +18,7 @@ pub const GhosttyI18n = @import("GhosttyI18n.zig"); pub const GhosttyXcodebuild = @import("GhosttyXcodebuild.zig"); pub const GhosttyXCFramework = @import("GhosttyXCFramework.zig"); pub const GhosttyWebdata = @import("GhosttyWebdata.zig"); +pub const GhosttyZig = @import("GhosttyZig.zig"); pub const HelpStrings = @import("HelpStrings.zig"); pub const SharedDeps = @import("SharedDeps.zig"); pub const UnicodeTables = @import("UnicodeTables.zig"); diff --git a/src/config/Config.zig b/src/config/Config.zig index 9a40dc0e4..1ef9de947 100644 --- a/src/config/Config.zig +++ b/src/config/Config.zig @@ -19,7 +19,6 @@ const ArenaAllocator = std.heap.ArenaAllocator; const global_state = &@import("../global.zig").state; const fontpkg = @import("../font/main.zig"); const inputpkg = @import("../input.zig"); -const terminal = @import("../terminal/main.zig"); const internal_os = @import("../os/main.zig"); const cli = @import("../cli.zig"); @@ -39,6 +38,16 @@ const RepeatableStringMap = @import("RepeatableStringMap.zig"); pub const Path = @import("path.zig").Path; pub const RepeatablePath = @import("path.zig").RepeatablePath; +// We do this instead of importing all of terminal/main.zig to +// limit the dependency graph. This is important because some things +// like the `ghostty-build-data` binary depend on the Config but don't +// want to include all the other stuff. +const terminal = struct { + const CursorStyle = @import("../terminal/cursor.zig").Style; + const color = @import("../terminal/color.zig"); + const x11_color = @import("../terminal/x11_color.zig"); +}; + const log = std.log.scoped(.config); /// Used on Unixes for some defaults. diff --git a/src/lib_vt.zig b/src/lib_vt.zig new file mode 100644 index 000000000..fbe524014 --- /dev/null +++ b/src/lib_vt.zig @@ -0,0 +1,5 @@ +const terminal = @import("terminal/main.zig"); + +test { + _ = terminal; +} diff --git a/src/os/TempDir.zig b/src/os/TempDir.zig index 7d3a34c84..f2e9992c4 100644 --- a/src/os/TempDir.zig +++ b/src/os/TempDir.zig @@ -6,7 +6,8 @@ const std = @import("std"); const builtin = @import("builtin"); const testing = std.testing; const Dir = std.fs.Dir; -const internal_os = @import("main.zig"); +const allocTmpDir = @import("file.zig").allocTmpDir; +const freeTmpDir = @import("file.zig").freeTmpDir; const log = std.log.scoped(.tempdir); @@ -31,8 +32,8 @@ pub fn init() !TempDir { const dir = dir: { const cwd = std.fs.cwd(); - const tmp_dir = internal_os.allocTmpDir(std.heap.page_allocator) orelse break :dir cwd; - defer internal_os.freeTmpDir(std.heap.page_allocator, tmp_dir); + const tmp_dir = allocTmpDir(std.heap.page_allocator) orelse break :dir cwd; + defer freeTmpDir(std.heap.page_allocator, tmp_dir); break :dir try cwd.openDir(tmp_dir, .{}); }; diff --git a/src/terminal/PageList.zig b/src/terminal/PageList.zig index a4136d7f3..b5d511b7f 100644 --- a/src/terminal/PageList.zig +++ b/src/terminal/PageList.zig @@ -4,7 +4,7 @@ const PageList = @This(); const std = @import("std"); -const build_config = @import("../build_config.zig"); +const build_options = @import("terminal_options"); const Allocator = std.mem.Allocator; const assert = std.debug.assert; const fastmem = @import("../fastmem.zig"); @@ -1492,7 +1492,7 @@ fn resizeWithoutReflow(self: *PageList, opts: Resize) !void { }, } - if (build_config.slow_runtime_safety) { + if (build_options.slow_runtime_safety) { assert(self.totalRows() >= self.rows); } } @@ -2524,7 +2524,7 @@ pub fn pin(self: *const PageList, pt: point.Point) ?Pin { /// pin points to is removed completely, the tracked pin will be updated /// to the top-left of the screen. pub fn trackPin(self: *PageList, p: Pin) Allocator.Error!*Pin { - if (build_config.slow_runtime_safety) assert(self.pinIsValid(p)); + if (build_options.slow_runtime_safety) assert(self.pinIsValid(p)); // Create our tracked pin const tracked = try self.pool.pins.create(); @@ -2556,7 +2556,7 @@ pub fn countTrackedPins(self: *const PageList) usize { pub fn pinIsValid(self: *const PageList, p: Pin) bool { // This is very slow so we want to ensure we only ever // call this during slow runtime safety builds. - comptime assert(build_config.slow_runtime_safety); + comptime assert(build_options.slow_runtime_safety); var it = self.pages.first; while (it) |node| : (it = node.next) { @@ -3234,7 +3234,7 @@ pub fn pageIterator( else self.getBottomRight(tl_pt) orelse return .{ .row = null }; - if (build_config.slow_runtime_safety) { + if (build_options.slow_runtime_safety) { assert(tl_pin.eql(bl_pin) or tl_pin.before(bl_pin)); } @@ -3510,7 +3510,7 @@ pub const Pin = struct { direction: Direction, limit: ?Pin, ) PageIterator { - if (build_config.slow_runtime_safety) { + if (build_options.slow_runtime_safety) { if (limit) |l| { // Check the order according to the iteration direction. switch (direction) { @@ -3560,7 +3560,7 @@ pub const Pin = struct { // Note: this is primarily unit tested as part of the Kitty // graphics deletion code. pub fn isBetween(self: Pin, top: Pin, bottom: Pin) bool { - if (build_config.slow_runtime_safety) { + if (build_options.slow_runtime_safety) { if (top.node == bottom.node) { // If top is bottom, must be ordered. assert(top.y <= bottom.y); diff --git a/src/terminal/Screen.zig b/src/terminal/Screen.zig index 67769923f..cc7aa4a16 100644 --- a/src/terminal/Screen.zig +++ b/src/terminal/Screen.zig @@ -1,7 +1,7 @@ const Screen = @This(); const std = @import("std"); -const build_config = @import("../build_config.zig"); +const build_options = @import("terminal_options"); const Allocator = std.mem.Allocator; const assert = std.debug.assert; const ansi = @import("ansi.zig"); @@ -24,6 +24,8 @@ const Row = pagepkg.Row; const Cell = pagepkg.Cell; const Pin = PageList.Pin; +pub const CursorStyle = @import("cursor.zig").Style; + const log = std.log.scoped(.screen); /// The general purpose allocator to use for all memory allocations. @@ -141,22 +143,6 @@ pub const Cursor = struct { } }; -/// The visual style of the cursor. Whether or not it blinks -/// is determined by mode 12 (modes.zig). This mode is synchronized -/// with CSI q, the same as xterm. -pub const CursorStyle = enum { - bar, // DECSCUSR 5, 6 - block, // DECSCUSR 1, 2 - underline, // DECSCUSR 3, 4 - - /// The cursor styles below aren't known by DESCUSR and are custom - /// implemented in Ghostty. They are reported as some standard style - /// if requested, though. - /// Hollow block cursor. This is a block cursor with the center empty. - /// Reported as DECSCUSR 1 or 2 (block). - block_hollow, -}; - /// Saved cursor state. pub const SavedCursor = struct { x: size.CellCountInt, @@ -232,7 +218,7 @@ pub fn deinit(self: *Screen) void { /// tests. This only asserts the screen specific data so callers should /// ensure they're also calling page integrity checks if necessary. pub fn assertIntegrity(self: *const Screen) void { - if (build_config.slow_runtime_safety) { + if (build_options.slow_runtime_safety) { // We don't run integrity checks on Valgrind because its soooooo slow, // Valgrind is our integrity checker, and we run these during unit // tests (non-Valgrind) anyways so we're verifying anyways. @@ -772,7 +758,7 @@ pub fn cursorDownScroll(self: *Screen) !void { // These assertions help catch some pagelist math errors. Our // x/y should be unchanged after the grow. - if (build_config.slow_runtime_safety) { + if (build_options.slow_runtime_safety) { const active = self.pages.pointFromPin( .active, page_pin, diff --git a/src/terminal/build_options.zig b/src/terminal/build_options.zig new file mode 100644 index 000000000..33cf7a2ef --- /dev/null +++ b/src/terminal/build_options.zig @@ -0,0 +1,31 @@ +const std = @import("std"); + +pub const Options = struct { + /// The target artifact to build. This will gate some functionality. + artifact: Artifact = .ghostty, + + /// True if we should enable the "slow" runtime safety checks. These + /// are runtime safety checks that are slower than typical and should + /// generally be disabled in production builds. + slow_runtime_safety: bool = false, +}; + +pub const Artifact = enum { + /// Ghostty application + ghostty, + + /// libghostty-vt, Zig module + lib, +}; + +/// Add the required build options for the terminal module. +pub fn addOptions( + b: *std.Build, + m: *std.Build.Module, + v: Options, +) void { + const opts = b.addOptions(); + opts.addOption(Artifact, "artifact", v.artifact); + opts.addOption(bool, "slow_runtime_safety", v.slow_runtime_safety); + m.addOptions("terminal_options", opts); +} diff --git a/src/terminal/cursor.zig b/src/terminal/cursor.zig new file mode 100644 index 000000000..136ee085a --- /dev/null +++ b/src/terminal/cursor.zig @@ -0,0 +1,15 @@ +/// The visual style of the cursor. Whether or not it blinks +/// is determined by mode 12 (modes.zig). This mode is synchronized +/// with CSI q, the same as xterm. +pub const Style = enum { + bar, // DECSCUSR 5, 6 + block, // DECSCUSR 1, 2 + underline, // DECSCUSR 3, 4 + + /// The cursor styles below aren't known by DESCUSR and are custom + /// implemented in Ghostty. They are reported as some standard style + /// if requested, though. + /// Hollow block cursor. This is a block cursor with the center empty. + /// Reported as DECSCUSR 1 or 2 (block). + block_hollow, +}; diff --git a/src/terminal/kitty/graphics_image.zig b/src/terminal/kitty/graphics_image.zig index 54ed1b934..f32b70be2 100644 --- a/src/terminal/kitty/graphics_image.zig +++ b/src/terminal/kitty/graphics_image.zig @@ -9,9 +9,14 @@ const fastmem = @import("../../fastmem.zig"); const command = @import("graphics_command.zig"); const point = @import("../point.zig"); const PageList = @import("../PageList.zig"); -const internal_os = @import("../../os/main.zig"); const wuffs = @import("wuffs"); +const temp_dir = struct { + const TempDir = @import("../../os/TempDir.zig"); + const allocTmpDir = @import("../../os/file.zig").allocTmpDir; + const freeTmpDir = @import("../../os/file.zig").freeTmpDir; +}; + const log = std.log.scoped(.kitty_gfx); /// Maximum width or height of an image. Taken directly from Kitty. @@ -276,8 +281,8 @@ pub const LoadingImage = struct { fn isPathInTempDir(path: []const u8) bool { if (std.mem.startsWith(u8, path, "/tmp")) return true; if (std.mem.startsWith(u8, path, "/dev/shm")) return true; - if (internal_os.allocTmpDir(std.heap.page_allocator)) |dir| { - defer internal_os.freeTmpDir(std.heap.page_allocator, dir); + if (temp_dir.allocTmpDir(std.heap.page_allocator)) |dir| { + defer temp_dir.freeTmpDir(std.heap.page_allocator, dir); if (std.mem.startsWith(u8, path, dir)) return true; // The temporary dir is sometimes a symlink. On macOS for @@ -690,7 +695,7 @@ test "image load: temporary file without correct path" { const testing = std.testing; const alloc = testing.allocator; - var tmp_dir = try internal_os.TempDir.init(); + var tmp_dir = try temp_dir.TempDir.init(); defer tmp_dir.deinit(); const data = @embedFile("testdata/image-rgb-none-20x15-2147483647-raw.data"); try tmp_dir.dir.writeFile(.{ @@ -723,7 +728,7 @@ test "image load: rgb, not compressed, temporary file" { const testing = std.testing; const alloc = testing.allocator; - var tmp_dir = try internal_os.TempDir.init(); + var tmp_dir = try temp_dir.TempDir.init(); defer tmp_dir.deinit(); const data = @embedFile("testdata/image-rgb-none-20x15-2147483647-raw.data"); try tmp_dir.dir.writeFile(.{ @@ -760,7 +765,7 @@ test "image load: rgb, not compressed, regular file" { const testing = std.testing; const alloc = testing.allocator; - var tmp_dir = try internal_os.TempDir.init(); + var tmp_dir = try temp_dir.TempDir.init(); defer tmp_dir.deinit(); const data = @embedFile("testdata/image-rgb-none-20x15-2147483647-raw.data"); try tmp_dir.dir.writeFile(.{ @@ -795,7 +800,7 @@ test "image load: png, not compressed, regular file" { const testing = std.testing; const alloc = testing.allocator; - var tmp_dir = try internal_os.TempDir.init(); + var tmp_dir = try temp_dir.TempDir.init(); defer tmp_dir.deinit(); const data = @embedFile("testdata/image-png-none-50x76-2147483647-raw.data"); try tmp_dir.dir.writeFile(.{ diff --git a/src/terminal/mouse_shape.zig b/src/terminal/mouse_shape.zig index 23ab215d6..3694ba8ec 100644 --- a/src/terminal/mouse_shape.zig +++ b/src/terminal/mouse_shape.zig @@ -1,5 +1,5 @@ const std = @import("std"); -const build_config = @import("../build_config.zig"); +const build_options = @import("terminal_options"); /// The possible cursor shapes. Not all app runtimes support these shapes. /// The shapes are always based on the W3C supported cursor styles so we @@ -48,13 +48,20 @@ pub const MouseShape = enum(c_int) { } /// Make this a valid gobject if we're in a GTK environment. - pub const getGObjectType = switch (build_config.app_runtime) { - .gtk => @import("gobject").ext.defineEnum( - MouseShape, - .{ .name = "GhosttyMouseShape" }, - ), + pub const getGObjectType = gtk: { + switch (build_options.artifact) { + .ghostty => break :gtk void, + .lib => {}, + } - .none => void, + break :gtk switch (@import("../build_config.zig").app_runtime) { + .gtk => @import("gobject").ext.defineEnum( + MouseShape, + .{ .name = "GhosttyMouseShape" }, + ), + + .none => void, + }; }; }; diff --git a/src/terminal/page.zig b/src/terminal/page.zig index d870bd160..f5ee1de71 100644 --- a/src/terminal/page.zig +++ b/src/terminal/page.zig @@ -1,6 +1,6 @@ const std = @import("std"); const builtin = @import("builtin"); -const build_config = @import("../build_config.zig"); +const build_options = @import("terminal_options"); const Allocator = std.mem.Allocator; const ArenaAllocator = std.heap.ArenaAllocator; const assert = std.debug.assert; @@ -182,8 +182,8 @@ pub const Page = struct { /// If this is true then verifyIntegrity will do nothing. This is /// only present with runtime safety enabled. - pause_integrity_checks: if (build_config.slow_runtime_safety) usize else void = - if (build_config.slow_runtime_safety) 0 else {}, + pause_integrity_checks: if (build_options.slow_runtime_safety) usize else void = + if (build_options.slow_runtime_safety) 0 else {}, /// Initialize a new page, allocating the required backing memory. /// The size of the initialized page defaults to the full capacity. @@ -307,7 +307,7 @@ pub const Page = struct { /// doing a lot of operations that would trigger integrity check /// violations but you know the page will end up in a consistent state. pub fn pauseIntegrityChecks(self: *Page, v: bool) void { - if (build_config.slow_runtime_safety) { + if (build_options.slow_runtime_safety) { if (v) { self.pause_integrity_checks += 1; } else { @@ -320,7 +320,7 @@ pub const Page = struct { /// when runtime safety is enabled. This is a no-op when runtime /// safety is disabled. This uses the libc allocator. pub fn assertIntegrity(self: *const Page) void { - if (comptime build_config.slow_runtime_safety) { + if (comptime build_options.slow_runtime_safety) { self.verifyIntegrity(std.heap.c_allocator) catch |err| { log.err("page integrity violation, crashing. err={}", .{err}); @panic("page integrity violation"); @@ -351,7 +351,7 @@ pub const Page = struct { // tests (non-Valgrind) anyways so we're verifying anyways. if (std.valgrind.runningOnValgrind() > 0) return; - if (build_config.slow_runtime_safety) { + if (build_options.slow_runtime_safety) { if (self.pause_integrity_checks > 0) return; } @@ -760,7 +760,7 @@ pub const Page = struct { // This is an integrity check: if the row claims it doesn't // have managed memory then all cells must also not have // managed memory. - if (build_config.slow_runtime_safety) { + if (build_options.slow_runtime_safety) { for (other_cells) |cell| { assert(!cell.hasGrapheme()); assert(!cell.hyperlink); @@ -787,7 +787,7 @@ pub const Page = struct { if (src_cell.hasGrapheme()) { // To prevent integrity checks flipping. This will // get fixed up when we check the style id below. - if (build_config.slow_runtime_safety) { + if (build_options.slow_runtime_safety) { dst_cell.style_id = style.default_id; } @@ -914,7 +914,7 @@ pub const Page = struct { /// Get the cells for a row. pub fn getCells(self: *const Page, row: *Row) []Cell { - if (build_config.slow_runtime_safety) { + if (build_options.slow_runtime_safety) { const rows = self.rows.ptr(self.memory); const cells = self.cells.ptr(self.memory); assert(@intFromPtr(row) >= @intFromPtr(rows)); @@ -1363,7 +1363,7 @@ pub const Page = struct { pub fn appendGrapheme(self: *Page, row: *Row, cell: *Cell, cp: u21) Allocator.Error!void { defer self.assertIntegrity(); - if (build_config.slow_runtime_safety) assert(cell.codepoint() != 0); + if (build_options.slow_runtime_safety) assert(cell.codepoint() != 0); const cell_offset = getOffset(Cell, self.memory, cell); var map = self.grapheme_map.map(self.memory); @@ -1436,7 +1436,7 @@ pub const Page = struct { /// there are scenarios where we want to move graphemes without changing /// the content tag. Callers beware but assertIntegrity should catch this. fn moveGrapheme(self: *Page, src: *Cell, dst: *Cell) void { - if (build_config.slow_runtime_safety) { + if (build_options.slow_runtime_safety) { assert(src.hasGrapheme()); assert(!dst.hasGrapheme()); } @@ -1453,7 +1453,7 @@ pub const Page = struct { /// Clear the graphemes for a given cell. pub fn clearGrapheme(self: *Page, row: *Row, cell: *Cell) void { defer self.assertIntegrity(); - if (build_config.slow_runtime_safety) assert(cell.hasGrapheme()); + if (build_options.slow_runtime_safety) assert(cell.hasGrapheme()); // Get our entry in the map, which must exist const cell_offset = getOffset(Cell, self.memory, cell); From 1b46884e726ce063f183fbb119a6ac07fb7c7ba1 Mon Sep 17 00:00:00 2001 From: Mitchell Hashimoto Date: Sat, 20 Sep 2025 20:47:37 -0700 Subject: [PATCH 02/19] terminal: add build option for oniguruma, which controls tmux cc mode --- src/build/GhosttyZig.zig | 1 + src/terminal/build_options.zig | 9 +++++++++ src/terminal/dcs.zig | 34 ++++++++++++++++++++++++++-------- src/terminal/main.zig | 3 ++- 4 files changed, 38 insertions(+), 9 deletions(-) diff --git a/src/build/GhosttyZig.zig b/src/build/GhosttyZig.zig index e3c22bc67..571428233 100644 --- a/src/build/GhosttyZig.zig +++ b/src/build/GhosttyZig.zig @@ -23,6 +23,7 @@ pub fn init( deps.unicode_tables.addModuleImport(vt); vt_options.addOptions(b, vt, .{ .artifact = .lib, + .oniguruma = false, .slow_runtime_safety = switch (cfg.optimize) { .Debug => true, .ReleaseSafe, diff --git a/src/terminal/build_options.zig b/src/terminal/build_options.zig index 33cf7a2ef..98d9bc8fa 100644 --- a/src/terminal/build_options.zig +++ b/src/terminal/build_options.zig @@ -4,6 +4,10 @@ pub const Options = struct { /// The target artifact to build. This will gate some functionality. artifact: Artifact = .ghostty, + /// Whether Oniguruma regex support is available. If this isn't + /// available, some features will be disabled. + oniguruma: bool = true, + /// True if we should enable the "slow" runtime safety checks. These /// are runtime safety checks that are slower than typical and should /// generally be disabled in production builds. @@ -26,6 +30,11 @@ pub fn addOptions( ) void { const opts = b.addOptions(); opts.addOption(Artifact, "artifact", v.artifact); + opts.addOption(bool, "oniguruma", v.oniguruma); opts.addOption(bool, "slow_runtime_safety", v.slow_runtime_safety); + + // These are synthesized based on other options. + opts.addOption(bool, "tmux_control_mode", v.oniguruma); + m.addOptions("terminal_options", opts); } diff --git a/src/terminal/dcs.zig b/src/terminal/dcs.zig index db5f95c4f..e4d0f3de2 100644 --- a/src/terminal/dcs.zig +++ b/src/terminal/dcs.zig @@ -1,4 +1,5 @@ const std = @import("std"); +const build_options = @import("terminal_options"); const assert = std.debug.assert; const Allocator = std.mem.Allocator; const terminal = @import("main.zig"); @@ -51,6 +52,11 @@ pub const Handler = struct { 0 => switch (dcs.final) { // Tmux control mode 'p' => tmux: { + if (comptime !build_options.tmux_control_mode) { + log.debug("tmux control mode not enabled in build, ignoring", .{}); + break :tmux null; + } + // Tmux control mode must start with ESC P 1000 p if (dcs.params.len != 1 or dcs.params[0] != 1000) break :tmux null; @@ -121,9 +127,11 @@ pub const Handler = struct { .ignore, => {}, - .tmux => |*tmux| return .{ - .tmux = (try tmux.put(byte)) orelse return null, - }, + .tmux => |*tmux| if (comptime build_options.tmux_control_mode) { + return .{ + .tmux = (try tmux.put(byte)) orelse return null, + }; + } else unreachable, .xtgettcap => |*list| { if (list.items.len >= self.max_bytes) { @@ -157,10 +165,10 @@ pub const Handler = struct { .ignore, => null, - .tmux => tmux: { + .tmux => if (comptime build_options.tmux_control_mode) tmux: { self.state.deinit(); break :tmux .{ .tmux = .{ .exit = {} } }; - }, + } else unreachable, .xtgettcap => |list| xtgettcap: { for (list.items, 0..) |b, i| { @@ -203,7 +211,10 @@ pub const Command = union(enum) { decrqss: DECRQSS, /// Tmux control mode - tmux: terminal.tmux.Notification, + tmux: if (build_options.tmux_control_mode) + terminal.tmux.Notification + else + void, pub fn deinit(self: Command) void { switch (self) { @@ -269,7 +280,10 @@ const State = union(enum) { }, /// Tmux control mode: https://github.com/tmux/tmux/wiki/Control-Mode - tmux: terminal.tmux.Client, + tmux: if (build_options.tmux_control_mode) + terminal.tmux.Client + else + void, pub fn deinit(self: *State) void { switch (self.*) { @@ -279,7 +293,9 @@ const State = union(enum) { .xtgettcap => |*v| v.deinit(), .decrqss => {}, - .tmux => |*v| v.deinit(), + .tmux => |*v| if (comptime build_options.tmux_control_mode) { + v.deinit(); + } else unreachable, } } }; @@ -395,6 +411,8 @@ test "DECRQSS invalid command" { } test "tmux enter and implicit exit" { + if (comptime !build_options.tmux_control_mode) return error.SkipZigTest; + const testing = std.testing; const alloc = testing.allocator; diff --git a/src/terminal/main.zig b/src/terminal/main.zig index 74ffe6341..1fea9934e 100644 --- a/src/terminal/main.zig +++ b/src/terminal/main.zig @@ -1,4 +1,5 @@ const builtin = @import("builtin"); +const build_options = @import("terminal_options"); const charsets = @import("charsets.zig"); const sanitize = @import("sanitize.zig"); @@ -20,7 +21,7 @@ pub const page = @import("page.zig"); pub const parse_table = @import("parse_table.zig"); pub const search = @import("search.zig"); pub const size = @import("size.zig"); -pub const tmux = @import("tmux.zig"); +pub const tmux = if (build_options.tmux_control_mode) @import("tmux.zig") else struct {}; pub const x11_color = @import("x11_color.zig"); pub const Charset = charsets.Charset; From 811f9f05d091187023689996ffc66287f379459b Mon Sep 17 00:00:00 2001 From: Mitchell Hashimoto Date: Sat, 20 Sep 2025 21:03:22 -0700 Subject: [PATCH 03/19] terminal: support disabling kitty graphics protocol --- src/terminal/PageList.zig | 14 +++++-- src/terminal/Screen.zig | 67 +++++++++++++++++++++------------- src/terminal/Terminal.zig | 65 +++++++++++++++++++++------------ src/terminal/apc.zig | 38 ++++++++++++++----- src/terminal/build_options.zig | 1 + src/terminal/kitty.zig | 4 +- src/terminal/osc.zig | 12 +++--- src/terminal/page.zig | 37 ++++++++++++------- 8 files changed, 157 insertions(+), 81 deletions(-) diff --git a/src/terminal/PageList.zig b/src/terminal/PageList.zig index b5d511b7f..b8e16dbf7 100644 --- a/src/terminal/PageList.zig +++ b/src/terminal/PageList.zig @@ -1153,9 +1153,11 @@ const ReflowCursor = struct { self.page_cell.style_id = id; } - // Copy Kitty virtual placeholder status - if (cell.codepoint() == kitty.graphics.unicode.placeholder) { - self.page_row.kitty_virtual_placeholder = true; + if (comptime build_options.kitty_graphics) { + // Copy Kitty virtual placeholder status + if (cell.codepoint() == kitty.graphics.unicode.placeholder) { + self.page_row.kitty_virtual_placeholder = true; + } } self.cursorForward(); @@ -8917,6 +8919,8 @@ test "PageList resize reflow less cols to wrap a multi-codepoint grapheme with a } test "PageList resize reflow less cols copy kitty placeholder" { + if (comptime !build_options.kitty_graphics) return error.SkipZigTest; + const testing = std.testing; const alloc = testing.allocator; @@ -8956,6 +8960,8 @@ test "PageList resize reflow less cols copy kitty placeholder" { } test "PageList resize reflow more cols clears kitty placeholder" { + if (comptime !build_options.kitty_graphics) return error.SkipZigTest; + const testing = std.testing; const alloc = testing.allocator; @@ -8997,6 +9003,8 @@ test "PageList resize reflow more cols clears kitty placeholder" { } test "PageList resize reflow wrap moves kitty placeholder" { + if (comptime !build_options.kitty_graphics) return error.SkipZigTest; + const testing = std.testing; const alloc = testing.allocator; diff --git a/src/terminal/Screen.zig b/src/terminal/Screen.zig index cc7aa4a16..7be4d7c12 100644 --- a/src/terminal/Screen.zig +++ b/src/terminal/Screen.zig @@ -66,7 +66,10 @@ protected_mode: ansi.ProtectedMode = .off, kitty_keyboard: kitty.KeyFlagStack = .{}, /// Kitty graphics protocol state. -kitty_images: kitty.graphics.ImageStorage = .{}, +kitty_images: if (build_options.kitty_graphics) + kitty.graphics.ImageStorage +else + struct {} = .{}, /// Dirty flags for the renderer. dirty: Dirty = .{}, @@ -208,7 +211,9 @@ pub fn init( } pub fn deinit(self: *Screen) void { - self.kitty_images.deinit(self.alloc, self); + if (comptime build_options.kitty_graphics) { + self.kitty_images.deinit(self.alloc, self); + } self.cursor.deinit(self.alloc); self.pages.deinit(); } @@ -269,9 +274,11 @@ pub fn reset(self: *Screen) void { .page_cell = cursor_rac.cell, }; - // Reset kitty graphics storage - self.kitty_images.deinit(self.alloc, self); - self.kitty_images = .{ .dirty = true }; + if (comptime build_options.kitty_graphics) { + // Reset kitty graphics storage + self.kitty_images.deinit(self.alloc, self); + self.kitty_images = .{ .dirty = true }; + } // Reset our basic state self.saved_cursor = null; @@ -690,8 +697,10 @@ pub fn cursorDownScroll(self: *Screen) !void { assert(self.cursor.y == self.pages.rows - 1); defer self.assertIntegrity(); - // Scrolling dirties the images because it updates their placements pins. - self.kitty_images.dirty = true; + if (comptime build_options.kitty_graphics) { + // Scrolling dirties the images because it updates their placements pins. + self.kitty_images.dirty = true; + } // If we have no scrollback, then we shift all our rows instead. if (self.no_scrollback) { @@ -1154,10 +1163,12 @@ pub const Scroll = union(enum) { pub fn scroll(self: *Screen, behavior: Scroll) void { defer self.assertIntegrity(); - // No matter what, scrolling marks our image state as dirty since - // it could move placements. If there are no placements or no images - // this is still a very cheap operation. - self.kitty_images.dirty = true; + if (comptime build_options.kitty_graphics) { + // No matter what, scrolling marks our image state as dirty since + // it could move placements. If there are no placements or no images + // this is still a very cheap operation. + self.kitty_images.dirty = true; + } switch (behavior) { .active => self.pages.scroll(.{ .active = {} }), @@ -1176,10 +1187,12 @@ pub fn scrollClear(self: *Screen) !void { try self.pages.scrollClear(); self.cursorReload(); - // No matter what, scrolling marks our image state as dirty since - // it could move placements. If there are no placements or no images - // this is still a very cheap operation. - self.kitty_images.dirty = true; + if (comptime build_options.kitty_graphics) { + // No matter what, scrolling marks our image state as dirty since + // it could move placements. If there are no placements or no images + // this is still a very cheap operation. + self.kitty_images.dirty = true; + } } /// Returns true if the viewport is scrolled to the bottom of the screen. @@ -1299,14 +1312,16 @@ pub fn clearCells( if (cells.len == self.pages.cols) row.styled = false; } - if (row.kitty_virtual_placeholder and - cells.len == self.pages.cols) - { - for (cells) |c| { - if (c.codepoint() == kitty.graphics.unicode.placeholder) { - break; - } - } else row.kitty_virtual_placeholder = false; + if (comptime build_options.kitty_graphics) { + if (row.kitty_virtual_placeholder and + cells.len == self.pages.cols) + { + for (cells) |c| { + if (c.codepoint() == kitty.graphics.unicode.placeholder) { + break; + } + } else row.kitty_virtual_placeholder = false; + } } @memset(cells, self.blankCell()); @@ -1570,8 +1585,10 @@ fn resizeInternal( ) !void { defer self.assertIntegrity(); - // No matter what we mark our image state as dirty - self.kitty_images.dirty = true; + if (comptime build_options.kitty_graphics) { + // No matter what we mark our image state as dirty + self.kitty_images.dirty = true; + } // Release the cursor style while resizing just // in case the cursor ends up on a different page. diff --git a/src/terminal/Terminal.zig b/src/terminal/Terminal.zig index 0d659eb9a..c9a1f1d1d 100644 --- a/src/terminal/Terminal.zig +++ b/src/terminal/Terminal.zig @@ -4,6 +4,7 @@ const Terminal = @This(); const std = @import("std"); +const build_options = @import("terminal_options"); const builtin = @import("builtin"); const assert = std.debug.assert; const testing = std.testing; @@ -679,8 +680,10 @@ fn printCell( // If this is a Kitty unicode placeholder then we need to mark the // row so that the renderer can lookup rows with these much faster. - if (c == kitty.graphics.unicode.placeholder) { - self.screen.cursor.page_row.kitty_virtual_placeholder = true; + if (comptime build_options.kitty_graphics) { + if (c == kitty.graphics.unicode.placeholder) { + self.screen.cursor.page_row.kitty_virtual_placeholder = true; + } } // We check for an active hyperlink first because setHyperlink @@ -1143,8 +1146,10 @@ pub fn index(self: *Terminal) !void { self.screen.cursor.x >= self.scrolling_region.left and self.screen.cursor.x <= self.scrolling_region.right) { - // Scrolling dirties the images because it updates their placements pins. - self.screen.kitty_images.dirty = true; + if (comptime build_options.kitty_graphics) { + // Scrolling dirties the images because it updates their placements pins. + self.screen.kitty_images.dirty = true; + } // If our scrolling region is at the top, we create scrollback. if (self.scrolling_region.top == 0 and @@ -1472,8 +1477,10 @@ pub fn insertLines(self: *Terminal, count: usize) void { self.screen.cursor.x < self.scrolling_region.left or self.screen.cursor.x > self.scrolling_region.right) return; - // Scrolling dirties the images because it updates their placements pins. - self.screen.kitty_images.dirty = true; + if (comptime build_options.kitty_graphics) { + // Scrolling dirties the images because it updates their placements pins. + self.screen.kitty_images.dirty = true; + } // At the end we need to return the cursor to the row it started on. const start_y = self.screen.cursor.y; @@ -1676,8 +1683,10 @@ pub fn deleteLines(self: *Terminal, count: usize) void { self.screen.cursor.x < self.scrolling_region.left or self.screen.cursor.x > self.scrolling_region.right) return; - // Scrolling dirties the images because it updates their placements pins. - self.screen.kitty_images.dirty = true; + if (comptime build_options.kitty_graphics) { + // Scrolling dirties the images because it updates their placements pins. + self.screen.kitty_images.dirty = true; + } // At the end we need to return the cursor to the row it started on. const start_y = self.screen.cursor.y; @@ -2136,12 +2145,14 @@ pub fn eraseDisplay( // Unsets pending wrap state self.screen.cursor.pending_wrap = false; - // Clear all Kitty graphics state for this screen - self.screen.kitty_images.delete( - self.screen.alloc, - self, - .{ .all = true }, - ); + if (comptime build_options.kitty_graphics) { + // Clear all Kitty graphics state for this screen + self.screen.kitty_images.delete( + self.screen.alloc, + self, + .{ .all = true }, + ); + } }, .complete => { @@ -2195,12 +2206,14 @@ pub fn eraseDisplay( // Unsets pending wrap state self.screen.cursor.pending_wrap = false; - // Clear all Kitty graphics state for this screen - self.screen.kitty_images.delete( - self.screen.alloc, - self, - .{ .all = true }, - ); + if (comptime build_options.kitty_graphics) { + // Clear all Kitty graphics state for this screen + self.screen.kitty_images.delete( + self.screen.alloc, + self, + .{ .all = true }, + ); + } // Cleared screen dirty bit self.flags.dirty.clear = true; @@ -2574,10 +2587,12 @@ pub fn switchScreen(self: *Terminal, t: ScreenType) ?*Screen { // Clear our selection self.screen.clearSelection(); - // Mark kitty images as dirty so they redraw. Without this set - // the images will remain where they were (the dirty bit on - // the screen only tracks the terminal grid, not the images). - self.screen.kitty_images.dirty = true; + if (comptime build_options.kitty_graphics) { + // Mark kitty images as dirty so they redraw. Without this set + // the images will remain where they were (the dirty bit on + // the screen only tracks the terminal grid, not the images). + self.screen.kitty_images.dirty = true; + } // Mark our terminal as dirty to redraw the grid. self.flags.dirty.clear = true; @@ -3862,6 +3877,8 @@ test "Terminal: print invoke charset single" { } test "Terminal: print kitty unicode placeholder" { + if (comptime !build_options.kitty_graphics) return error.SkipZigTest; + var t = try init(testing.allocator, .{ .cols = 10, .rows = 10 }); defer t.deinit(testing.allocator); diff --git a/src/terminal/apc.zig b/src/terminal/apc.zig index 26c59729a..9663afb3e 100644 --- a/src/terminal/apc.zig +++ b/src/terminal/apc.zig @@ -1,4 +1,5 @@ const std = @import("std"); +const build_options = @import("terminal_options"); const assert = std.debug.assert; const Allocator = std.mem.Allocator; @@ -33,17 +34,22 @@ pub const Handler = struct { .identify => { switch (byte) { // Kitty graphics protocol - 'G' => self.state = .{ .kitty = kitty_gfx.CommandParser.init(alloc) }, + 'G' => self.state = if (comptime build_options.kitty_graphics) + .{ .kitty = kitty_gfx.CommandParser.init(alloc) } + else + .{ .ignore = {} }, // Unknown else => self.state = .{ .ignore = {} }, } }, - .kitty => |*p| p.feed(byte) catch |err| { - log.warn("kitty graphics protocol error: {}", .{err}); - self.state = .{ .ignore = {} }; - }, + .kitty => |*p| if (comptime build_options.kitty_graphics) { + p.feed(byte) catch |err| { + log.warn("kitty graphics protocol error: {}", .{err}); + self.state = .{ .ignore = {} }; + }; + } else unreachable, } } @@ -57,6 +63,8 @@ pub const Handler = struct { .inactive => unreachable, .ignore, .identify => null, .kitty => |*p| kitty: { + if (comptime !build_options.kitty_graphics) unreachable; + const command = p.complete() catch |err| { log.warn("kitty graphics protocol error: {}", .{err}); break :kitty null; @@ -81,23 +89,35 @@ pub const State = union(enum) { identify: void, /// Kitty graphics protocol - kitty: kitty_gfx.CommandParser, + kitty: if (build_options.kitty_graphics) + kitty_gfx.CommandParser + else + void, pub fn deinit(self: *State) void { switch (self.*) { .inactive, .ignore, .identify => {}, - .kitty => |*v| v.deinit(), + .kitty => |*v| if (comptime build_options.kitty_graphics) + v.deinit() + else + unreachable, } } }; /// Possible APC commands. pub const Command = union(enum) { - kitty: kitty_gfx.Command, + kitty: if (build_options.kitty_graphics) + kitty_gfx.Command + else + void, pub fn deinit(self: *Command, alloc: Allocator) void { switch (self.*) { - .kitty => |*v| v.deinit(alloc), + .kitty => |*v| if (comptime build_options.kitty_graphics) + v.deinit(alloc) + else + unreachable, } } }; diff --git a/src/terminal/build_options.zig b/src/terminal/build_options.zig index 98d9bc8fa..57129f5f0 100644 --- a/src/terminal/build_options.zig +++ b/src/terminal/build_options.zig @@ -34,6 +34,7 @@ pub fn addOptions( opts.addOption(bool, "slow_runtime_safety", v.slow_runtime_safety); // These are synthesized based on other options. + opts.addOption(bool, "kitty_graphics", v.oniguruma); opts.addOption(bool, "tmux_control_mode", v.oniguruma); m.addOptions("terminal_options", opts); diff --git a/src/terminal/kitty.zig b/src/terminal/kitty.zig index 482919f9f..0868a7710 100644 --- a/src/terminal/kitty.zig +++ b/src/terminal/kitty.zig @@ -1,8 +1,10 @@ //! Types and functions related to Kitty protocols. +const build_options = @import("terminal_options"); + const key = @import("kitty/key.zig"); pub const color = @import("kitty/color.zig"); -pub const graphics = @import("kitty/graphics.zig"); +pub const graphics = if (build_options.kitty_graphics) @import("kitty/graphics.zig") else struct {}; pub const KeyFlags = key.Flags; pub const KeyFlagStack = key.FlagStack; diff --git a/src/terminal/osc.zig b/src/terminal/osc.zig index 028fcdf0a..bd7337b42 100644 --- a/src/terminal/osc.zig +++ b/src/terminal/osc.zig @@ -11,7 +11,7 @@ const mem = std.mem; const assert = std.debug.assert; const Allocator = mem.Allocator; const RGB = @import("color.zig").RGB; -const kitty = @import("kitty.zig"); +const kitty_color = @import("kitty/color.zig"); const osc_color = @import("osc/color.zig"); pub const color = osc_color; @@ -132,7 +132,7 @@ pub const Command = union(enum) { /// Kitty color protocol, OSC 21 /// https://sw.kovidgoyal.net/kitty/color-stack/#id1 - kitty_color_protocol: kitty.color.OSC, + kitty_color_protocol: kitty_color.OSC, /// Show a desktop notification (OSC 9 or OSC 777) show_desktop_notification: struct { @@ -796,7 +796,7 @@ pub const Parser = struct { self.command = .{ .kitty_color_protocol = .{ - .list = std.ArrayList(kitty.color.OSC.Request).init(alloc), + .list = std.ArrayList(kitty_color.OSC.Request).init(alloc), }, }; @@ -1490,7 +1490,7 @@ pub const Parser = struct { return; } - const key = kitty.color.Kind.parse(self.temp_state.key) orelse { + const key = kitty_color.Kind.parse(self.temp_state.key) orelse { log.warn("unknown key in kitty color protocol: {s}", .{self.temp_state.key}); return; }; @@ -1504,7 +1504,7 @@ pub const Parser = struct { switch (self.command) { .kitty_color_protocol => |*v| { // Cap our allocation amount for our list. - if (v.list.items.len >= @as(usize, kitty.color.Kind.max) * 2) { + if (v.list.items.len >= @as(usize, kitty_color.Kind.max) * 2) { self.state = .invalid; log.warn("exceeded limit for number of keys in kitty color protocol, ignoring", .{}); return; @@ -2600,7 +2600,7 @@ test "OSC: hyperlink end" { test "OSC: kitty color protocol" { const testing = std.testing; - const Kind = kitty.color.Kind; + const Kind = kitty_color.Kind; var p: Parser = .initAlloc(testing.allocator); defer p.deinit(); diff --git a/src/terminal/page.zig b/src/terminal/page.zig index f5ee1de71..086bfe96c 100644 --- a/src/terminal/page.zig +++ b/src/terminal/page.zig @@ -890,8 +890,10 @@ pub const Page = struct { error.NeedsRehash => return error.StyleSetNeedsRehash, } orelse src_cell.style_id; } - if (src_cell.codepoint() == kitty.graphics.unicode.placeholder) { - dst_row.kitty_virtual_placeholder = true; + if (comptime build_options.kitty_graphics) { + if (src_cell.codepoint() == kitty.graphics.unicode.placeholder) { + dst_row.kitty_virtual_placeholder = true; + } } } } @@ -980,8 +982,10 @@ pub const Page = struct { dst.hyperlink = true; dst_row.hyperlink = true; } - if (src.codepoint() == kitty.graphics.unicode.placeholder) { - dst_row.kitty_virtual_placeholder = true; + if (comptime build_options.kitty_graphics) { + if (src.codepoint() == kitty.graphics.unicode.placeholder) { + dst_row.kitty_virtual_placeholder = true; + } } } } @@ -1002,7 +1006,9 @@ pub const Page = struct { src_row.grapheme = false; src_row.hyperlink = false; src_row.styled = false; - src_row.kitty_virtual_placeholder = false; + if (comptime build_options.kitty_graphics) { + src_row.kitty_virtual_placeholder = false; + } } } @@ -1100,14 +1106,16 @@ pub const Page = struct { if (cells.len == self.size.cols) row.styled = false; } - if (row.kitty_virtual_placeholder and - cells.len == self.size.cols) - { - for (cells) |c| { - if (c.codepoint() == kitty.graphics.unicode.placeholder) { - break; - } - } else row.kitty_virtual_placeholder = false; + if (comptime build_options.kitty_graphics) { + if (row.kitty_virtual_placeholder and + cells.len == self.size.cols) + { + for (cells) |c| { + if (c.codepoint() == kitty.graphics.unicode.placeholder) { + break; + } + } else row.kitty_virtual_placeholder = false; + } } // Zero the cells as u64s since empirically this seems @@ -1929,6 +1937,9 @@ pub const Row = packed struct(u64) { /// True if this row contains a virtual placeholder for the Kitty /// graphics protocol. (U+10EEEE) + // Note: We keep this as memory-using even if the kitty graphics + // feature is disabled because we want to keep our padding and + // everything throughout the same. kitty_virtual_placeholder: bool = false, _padding: u23 = 0, From 4f974f427839d875ff8b1ac14c7e385b49c461c9 Mon Sep 17 00:00:00 2001 From: Mitchell Hashimoto Date: Sat, 20 Sep 2025 21:06:53 -0700 Subject: [PATCH 04/19] terminal: don't build StringMap.searchIterator without regex support --- src/build/GhosttyZig.zig | 5 +++++ src/terminal/StringMap.zig | 11 ++++++++++- src/terminal/build_options.zig | 7 ++++++- 3 files changed, 21 insertions(+), 2 deletions(-) diff --git a/src/build/GhosttyZig.zig b/src/build/GhosttyZig.zig index 571428233..fee4379f0 100644 --- a/src/build/GhosttyZig.zig +++ b/src/build/GhosttyZig.zig @@ -23,7 +23,12 @@ pub fn init( deps.unicode_tables.addModuleImport(vt); vt_options.addOptions(b, vt, .{ .artifact = .lib, + + // We presently don't allow Oniguruma in our Zig module at all. + // We should expose this as a build option in the future so we can + // conditionally do this. .oniguruma = false, + .slow_runtime_safety = switch (cfg.optimize) { .Debug => true, .ReleaseSafe, diff --git a/src/terminal/StringMap.zig b/src/terminal/StringMap.zig index dde69d25e..ae34f5fc8 100644 --- a/src/terminal/StringMap.zig +++ b/src/terminal/StringMap.zig @@ -3,6 +3,7 @@ const StringMap = @This(); const std = @import("std"); +const build_options = @import("terminal_options"); const oni = @import("oniguruma"); const point = @import("point.zig"); const Selection = @import("Selection.zig"); @@ -19,7 +20,13 @@ pub fn deinit(self: StringMap, alloc: Allocator) void { } /// Returns an iterator that yields the next match of the given regex. -pub fn searchIterator( +/// Requires Ghostty to be compiled with regex support. +pub const searchIterator = if (build_options.oniguruma) + searchIteratorOni +else + void; + +fn searchIteratorOni( self: StringMap, regex: oni.Regex, ) SearchIterator { @@ -85,6 +92,8 @@ pub const Match = struct { }; test "StringMap searchIterator" { + if (comptime !build_options.oniguruma) return error.SkipZigTest; + const testing = std.testing; const alloc = testing.allocator; diff --git a/src/terminal/build_options.zig b/src/terminal/build_options.zig index 57129f5f0..2a5153eb9 100644 --- a/src/terminal/build_options.zig +++ b/src/terminal/build_options.zig @@ -5,7 +5,12 @@ pub const Options = struct { artifact: Artifact = .ghostty, /// Whether Oniguruma regex support is available. If this isn't - /// available, some features will be disabled. + /// available, some features will be disabled. This may be outdated, + /// but the specific disabled features are: + /// + /// - Kitty graphics protocol + /// - Tmux control mode + /// oniguruma: bool = true, /// True if we should enable the "slow" runtime safety checks. These From 1758f962f6af5813a8d3f24de2dafc278d00e085 Mon Sep 17 00:00:00 2001 From: Mitchell Hashimoto Date: Sun, 21 Sep 2025 10:02:09 -0700 Subject: [PATCH 05/19] remove stale example wasm app --- example/app.ts | 189 -- example/index.html | 15 - example/package-lock.json | 4436 ------------------------------------- example/package.json | 22 - 4 files changed, 4662 deletions(-) delete mode 100644 example/app.ts delete mode 100644 example/index.html delete mode 100644 example/package-lock.json delete mode 100644 example/package.json diff --git a/example/app.ts b/example/app.ts deleted file mode 100644 index 5b426a333..000000000 --- a/example/app.ts +++ /dev/null @@ -1,189 +0,0 @@ -import { ZigJS } from "zig-js"; - -const zjs = new ZigJS(); -const importObject = { - module: {}, - env: { - memory: new WebAssembly.Memory({ - initial: 25, - maximum: 65536, - shared: true, - }), - log: (ptr: number, len: number) => { - const arr = new Uint8ClampedArray(zjs.memory.buffer, ptr, len); - const data = arr.slice(); - const str = new TextDecoder("utf-8").decode(data); - 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 = importObject.env.memory; - const { - malloc, - free, - config_new, - config_free, - config_load_string, - config_finalize, - face_new, - face_free, - face_render_glyph, - face_debug_canvas, - deferred_face_new, - deferred_face_free, - deferred_face_load, - deferred_face_face, - group_new, - group_free, - group_add_face, - group_init_sprite_face, - group_index_for_codepoint, - group_render_glyph, - group_cache_new, - group_cache_free, - group_cache_index_for_codepoint, - group_cache_render_glyph, - group_cache_atlas_grayscale, - group_cache_atlas_color, - atlas_new, - atlas_free, - atlas_debug_canvas, - shaper_new, - shaper_free, - shaper_test, - } = 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; - - // Helpers - const makeStr = (str) => { - const utf8 = new TextEncoder().encode(str); - const ptr = malloc(utf8.byteLength); - new Uint8Array(memory.buffer, ptr).set(utf8); - return { ptr: ptr, len: utf8.byteLength }; - }; - - // Create our config - const config = config_new(); - const config_str = makeStr("font-family = monospace"); - config_load_string(config, config_str.ptr, config_str.len); - config_finalize(config); - free(config_str.ptr); - - // Create our atlas - // const atlas = atlas_new(512, 0 /* grayscale */); - - // Create some memory for our string - const font_name = makeStr("monospace"); - - // Initialize our deferred face - // const df = deferred_face_new(font_ptr, font.byteLength, 0 /* text */); - //deferred_face_load(df, 72 /* size */); - //const face = deferred_face_face(df); - - // Initialize our font face - //const face = face_new(font_ptr, font.byteLength, 72 /* size in px */); - //free(font_ptr); - - // Create our group - const group = group_new(32 /* size */); - group_add_face( - group, - 0 /* regular */, - deferred_face_new(font_name.ptr, font_name.len, 0 /* text */), - ); - group_add_face( - group, - 0 /* regular */, - deferred_face_new(font_name.ptr, font_name.len, 1 /* emoji */), - ); - - // Initialize our sprite font, without this we just use the browser. - group_init_sprite_face(group); - - // Create our group cache - const group_cache = group_cache_new(group); - - // Render a glyph - // for (let i = 33; i <= 126; i++) { - // const font_idx = group_cache_index_for_codepoint(group_cache, i, 0, -1); - // group_cache_render_glyph(group_cache, font_idx, i, 0); - // //face_render_glyph(face, atlas, i); - // } - // - // const emoji = ["🐏","🌞","🌚","🍱","πŸ’Ώ","🐈","πŸ“ƒ","πŸ“€","πŸ•‘","πŸ™ƒ"]; - // for (let i = 0; i < emoji.length; i++) { - // const cp = emoji[i].codePointAt(0); - // const font_idx = group_cache_index_for_codepoint(group_cache, cp, 0, -1 /* best choice */); - // group_cache_render_glyph(group_cache, font_idx, cp, 0); - // } - - for (let i = 0x2500; i <= 0x257f; i++) { - const font_idx = group_cache_index_for_codepoint(group_cache, i, 0, -1); - group_cache_render_glyph(group_cache, font_idx, i, 0); - } - for (let i = 0x2580; i <= 0x259f; i++) { - const font_idx = group_cache_index_for_codepoint(group_cache, i, 0, -1); - group_cache_render_glyph(group_cache, font_idx, i, 0); - } - for (let i = 0x2800; i <= 0x28ff; i++) { - const font_idx = group_cache_index_for_codepoint(group_cache, i, 0, -1); - group_cache_render_glyph(group_cache, font_idx, i, 0); - } - for (let i = 0x1fb00; i <= 0x1fb3b; i++) { - const font_idx = group_cache_index_for_codepoint(group_cache, i, 0, -1); - group_cache_render_glyph(group_cache, font_idx, i, 0); - } - for (let i = 0x1fb3c; i <= 0x1fb6b; i++) { - const font_idx = group_cache_index_for_codepoint(group_cache, i, 0, -1); - group_cache_render_glyph(group_cache, font_idx, i, 0); - } - - //face_render_glyph(face, atlas, "ζ©‹".codePointAt(0)); - //face_render_glyph(face, atlas, "p".codePointAt(0)); - - // Debug our canvas - //face_debug_canvas(face); - - // Let's try shaping - const shaper = shaper_new(120); - //const input = makeStr("hello🐏"); - const input = makeStr("helloπŸπŸ‘πŸ½"); - shaper_test(shaper, group_cache, input.ptr, input.len); - - const cp = 1114112; - const font_idx = group_cache_index_for_codepoint( - group_cache, - cp, - 0, - -1 /* best choice */, - ); - group_cache_render_glyph(group_cache, font_idx, cp, -1); - - // Debug our atlas canvas - { - const atlas = group_cache_atlas_grayscale(group_cache); - const id = atlas_debug_canvas(atlas); - document.getElementById("atlas-canvas").append(zjs.deleteValue(id)); - } - - { - const atlas = group_cache_atlas_color(group_cache); - const id = atlas_debug_canvas(atlas); - document.getElementById("atlas-color-canvas").append(zjs.deleteValue(id)); - } - - //face_free(face); - }); diff --git a/example/index.html b/example/index.html deleted file mode 100644 index 2e66f92d1..000000000 --- a/example/index.html +++ /dev/null @@ -1,15 +0,0 @@ - - - - - Ghostty Example - - - -

Open your console, we are just debugging here.

-

The current grayscale font atlas is rendered below.

-
-

The current color font atlas is rendered below.

-
- - diff --git a/example/package-lock.json b/example/package-lock.json deleted file mode 100644 index 3cb4de6f0..000000000 --- a/example/package-lock.json +++ /dev/null @@ -1,4436 +0,0 @@ -{ - "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 deleted file mode 100644 index e884e5c6c..000000000 --- a/example/package.json +++ /dev/null @@ -1,22 +0,0 @@ -{ - "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" - } -} From 64f26c14d3f370b026f61c8b6c53d4bb32a61b5b Mon Sep 17 00:00:00 2001 From: Mitchell Hashimoto Date: Sun, 21 Sep 2025 10:06:53 -0700 Subject: [PATCH 06/19] example/zig-vt --- example/zig-vt/README.md | 14 ++++++++++++ example/zig-vt/build.zig | 44 ++++++++++++++++++++++++++++++++++++ example/zig-vt/build.zig.zon | 24 ++++++++++++++++++++ example/zig-vt/src/main.zig | 26 +++++++++++++++++++++ src/lib_vt.zig | 9 ++++++++ 5 files changed, 117 insertions(+) create mode 100644 example/zig-vt/README.md create mode 100644 example/zig-vt/build.zig create mode 100644 example/zig-vt/build.zig.zon create mode 100644 example/zig-vt/src/main.zig diff --git a/example/zig-vt/README.md b/example/zig-vt/README.md new file mode 100644 index 000000000..f985d4105 --- /dev/null +++ b/example/zig-vt/README.md @@ -0,0 +1,14 @@ +# Example: `ghostty-vt` Zig Module + +This contains a simple example of how to use the `ghostty-vt` Zig module +exported by Ghostty to have access to a production grade terminal emulator. + +Requires the Zig version stated in the `build.zig.zon` file. + +## Usage + +Run the program: + +```shell-session +zig build run +``` diff --git a/example/zig-vt/build.zig b/example/zig-vt/build.zig new file mode 100644 index 000000000..d52ea7ce7 --- /dev/null +++ b/example/zig-vt/build.zig @@ -0,0 +1,44 @@ +const std = @import("std"); + +pub fn build(b: *std.Build) void { + const target = b.standardTargetOptions(.{}); + const optimize = b.standardOptimizeOption(.{}); + + const run_step = b.step("run", "Run the app"); + const test_step = b.step("test", "Run unit tests"); + + const exe_mod = b.createModule(.{ + .root_source_file = b.path("src/main.zig"), + .target = target, + .optimize = optimize, + }); + + // You'll want to use a lazy dependency here so that ghostty is only + // downloaded if you actually need it. + if (b.lazyDependency("ghostty", .{})) |dep| { + exe_mod.addImport( + "ghostty-vt", + dep.module("ghostty-vt"), + ); + } + + // Exe + const exe = b.addExecutable(.{ + .name = "zig_vt", + .root_module = exe_mod, + }); + b.installArtifact(exe); + + // Run + const run_cmd = b.addRunArtifact(exe); + run_cmd.step.dependOn(b.getInstallStep()); + if (b.args) |args| run_cmd.addArgs(args); + run_step.dependOn(&run_cmd.step); + + // Test + const exe_unit_tests = b.addTest(.{ + .root_module = exe_mod, + }); + const run_exe_unit_tests = b.addRunArtifact(exe_unit_tests); + test_step.dependOn(&run_exe_unit_tests.step); +} diff --git a/example/zig-vt/build.zig.zon b/example/zig-vt/build.zig.zon new file mode 100644 index 000000000..852e736ca --- /dev/null +++ b/example/zig-vt/build.zig.zon @@ -0,0 +1,24 @@ +.{ + .name = .zig_vt, + .version = "0.0.0", + .fingerprint = 0x6045575a7a8387e6, + .minimum_zig_version = "0.14.1", + .dependencies = .{ + // Ghostty dependency. In reality, you'd probably use a URL-based + // dependency like the one showed (and commented out) below this one. + // We use a path dependency here for simplicity and to ensure our + // examples always test against the source they're bundled with. + .ghostty = .{ .path = "../../" }, + + // Example of what a URL-based dependency looks like: + // .ghostty = .{ + // .url = "https://github.com/ghostty-org/ghostty/archive/COMMIT.tar.gz", + // .hash = "N-V-__8AAMVLTABmYkLqhZPLXnMl-KyN38R8UVYqGrxqO36s", + // }, + }, + .paths = .{ + "build.zig", + "build.zig.zon", + "src", + }, +} diff --git a/example/zig-vt/src/main.zig b/example/zig-vt/src/main.zig new file mode 100644 index 000000000..f57c70087 --- /dev/null +++ b/example/zig-vt/src/main.zig @@ -0,0 +1,26 @@ +const std = @import("std"); +const ghostty_vt = @import("ghostty-vt"); + +pub fn main() !void { + // Use a debug allocator so we get leak checking. You probably want + // to replace this for release builds. + var gpa: std.heap.DebugAllocator(.{}) = .init; + defer _ = gpa.deinit(); + const alloc = gpa.allocator(); + + // Initialize a terminal. + var t: ghostty_vt.Terminal = try .init(alloc, .{ + .cols = 6, + .rows = 40, + }); + defer t.deinit(alloc); + + // Write some text. It'll wrap because this is too long for our + // columns size above (6). + try t.printString("Hello, World!"); + + // Get the plain string view of the terminal screen. + const str = try t.plainString(alloc); + defer alloc.free(str); + std.debug.print("{s}\n", .{str}); +} diff --git a/src/lib_vt.zig b/src/lib_vt.zig index fbe524014..d8e268b1b 100644 --- a/src/lib_vt.zig +++ b/src/lib_vt.zig @@ -1,4 +1,13 @@ +//! This is the public API of the ghostty-vt Zig module. + +// The public API below reproduces a lot of terminal/main.zig but +// is separate because (1) we need our root file to be in `src/` +// so we can access other directories and (2) we may want to withhold +// parts of `terminal` that are not ready for public consumption +// or are too Ghostty-internal. const terminal = @import("terminal/main.zig"); +pub const Parser = terminal.Parser; +pub const Terminal = terminal.Terminal; test { _ = terminal; From 3e34009492ef9f412e2f28b9d6aba93828c71279 Mon Sep 17 00:00:00 2001 From: Mitchell Hashimoto Date: Sun, 21 Sep 2025 19:44:07 -0700 Subject: [PATCH 07/19] lib-vt: expose all of terminal for now --- build.zig | 3 +++ src/lib_vt.zig | 56 ++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 59 insertions(+) diff --git a/build.zig b/build.zig index f651c30e4..0b87dbbe1 100644 --- a/build.zig +++ b/build.zig @@ -265,6 +265,9 @@ pub fn build(b: *std.Build) !void { const test_run = b.addRunArtifact(test_exe); test_step.dependOn(&test_run.step); + // Normal tests always test our libghostty modules + test_step.dependOn(test_lib_vt_step); + // Valgrind test running const valgrind_run = b.addSystemCommand(&.{ "valgrind", diff --git a/src/lib_vt.zig b/src/lib_vt.zig index d8e268b1b..d375a89d2 100644 --- a/src/lib_vt.zig +++ b/src/lib_vt.zig @@ -1,4 +1,12 @@ //! This is the public API of the ghostty-vt Zig module. +//! +//! WARNING: The API is not guaranteed to be stable. +//! +//! The functionality is extremely stable, since it is extracted +//! directly from Ghostty which has been used in real world scenarios +//! by thousands of users for years. However, the API itself (functions, +//! types, etc.) may change without warning. We're working on stabilizing +//! this in the future. // The public API below reproduces a lot of terminal/main.zig but // is separate because (1) we need our root file to be in `src/` @@ -6,8 +14,56 @@ // parts of `terminal` that are not ready for public consumption // or are too Ghostty-internal. const terminal = @import("terminal/main.zig"); + +pub const apc = terminal.apc; +pub const dcs = terminal.dcs; +pub const osc = terminal.osc; +pub const point = terminal.point; +pub const color = terminal.color; +pub const device_status = terminal.device_status; +pub const kitty = terminal.kitty; +pub const modes = terminal.modes; +pub const page = terminal.page; +pub const parse_table = terminal.parse_table; +pub const search = terminal.search; +pub const size = terminal.size; +pub const x11_color = terminal.x11_color; + +pub const Charset = terminal.Charset; +pub const CharsetSlot = terminal.Slots; +pub const CharsetActiveSlot = terminal.ActiveSlot; +pub const Cell = page.Cell; +pub const Coordinate = point.Coordinate; +pub const CSI = Parser.Action.CSI; +pub const DCS = Parser.Action.DCS; +pub const MouseShape = terminal.MouseShape; +pub const Page = page.Page; +pub const PageList = terminal.PageList; pub const Parser = terminal.Parser; +pub const Pin = PageList.Pin; +pub const Point = point.Point; +pub const Screen = terminal.Screen; +pub const ScreenType = Terminal.ScreenType; +pub const Selection = terminal.Selection; +pub const SizeReportStyle = terminal.SizeReportStyle; +pub const StringMap = terminal.StringMap; +pub const Style = terminal.Style; pub const Terminal = terminal.Terminal; +pub const Stream = terminal.Stream; +pub const Cursor = Screen.Cursor; +pub const CursorStyle = Screen.CursorStyle; +pub const CursorStyleReq = terminal.CursorStyle; +pub const DeviceAttributeReq = terminal.DeviceAttributeReq; +pub const Mode = modes.Mode; +pub const ModePacked = modes.ModePacked; +pub const ModifyKeyFormat = terminal.ModifyKeyFormat; +pub const ProtectedMode = terminal.ProtectedMode; +pub const StatusLineType = terminal.StatusLineType; +pub const StatusDisplay = terminal.StatusDisplay; +pub const EraseDisplay = terminal.EraseDisplay; +pub const EraseLine = terminal.EraseLine; +pub const TabClear = terminal.TabClear; +pub const Attribute = terminal.Attribute; test { _ = terminal; From 645520b5028c62ef45ad70cda339f7f554cc3c16 Mon Sep 17 00:00:00 2001 From: Mitchell Hashimoto Date: Sun, 21 Sep 2025 19:54:10 -0700 Subject: [PATCH 08/19] ci: build examples in CI --- .github/workflows/test.yml | 37 +++++++++++++++++++++++++++++++++++++ 1 file changed, 37 insertions(+) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 684ec3cf8..71d701c80 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -12,6 +12,7 @@ jobs: needs: - build-bench - build-dist + - build-examples - build-flatpak - build-freebsd - build-linux @@ -87,6 +88,42 @@ jobs: - name: Build Benchmarks run: nix develop -c zig build -Demit-bench + build-examples: + strategy: + fail-fast: false + matrix: + dir: [zig-vt] + name: Example ${{ matrix.dir }} + runs-on: namespace-profile-ghostty-sm + needs: test + env: + ZIG_LOCAL_CACHE_DIR: /zig/local-cache + ZIG_GLOBAL_CACHE_DIR: /zig/global-cache + steps: + - name: Checkout code + uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 + + - name: Setup Cache + uses: namespacelabs/nscloud-cache-action@a289cf5d2fcd6874376aa92f0ef7f99dc923592a # v1.2.17 + with: + path: | + /nix + /zig + + # Install Nix and use that to run our tests so our environment matches exactly. + - uses: cachix/install-nix-action@a809471b5c7c913aa67bec8f459a11a0decc3fce # v31.6.2 + with: + nix_path: nixpkgs=channel:nixos-unstable + - uses: cachix/cachix-action@0fc020193b5a1fa3ac4575aa3a7d3aa6a35435ad # v16 + with: + name: ghostty + authToken: "${{ secrets.CACHIX_AUTH_TOKEN }}" + + - name: Build Example + run: | + cd example/${{ matrix.dir }} + nix develop -c zig build -Demit-bench + build-flatpak: strategy: fail-fast: false From f42656b0acdd88e1040f65f065eec9113c904d05 Mon Sep 17 00:00:00 2001 From: Mitchell Hashimoto Date: Sun, 21 Sep 2025 19:59:03 -0700 Subject: [PATCH 09/19] lib-vt: require libc for now --- src/build/GhosttyZig.zig | 1 + 1 file changed, 1 insertion(+) diff --git a/src/build/GhosttyZig.zig b/src/build/GhosttyZig.zig index fee4379f0..306603cf5 100644 --- a/src/build/GhosttyZig.zig +++ b/src/build/GhosttyZig.zig @@ -19,6 +19,7 @@ pub fn init( .root_source_file = b.path("src/lib_vt.zig"), .target = cfg.target, .optimize = cfg.optimize, + .link_libc = true, }); deps.unicode_tables.addModuleImport(vt); vt_options.addOptions(b, vt, .{ From 14eb8aa4e4ccf099d826bba6472321fae59a7c7c Mon Sep 17 00:00:00 2001 From: Mitchell Hashimoto Date: Sun, 21 Sep 2025 20:13:06 -0700 Subject: [PATCH 10/19] Add simd flag for disabling SIMD functionality --- build.zig | 3 +- src/build/Config.zig | 7 ++ src/build/GhosttyZig.zig | 15 +++- src/build/SharedDeps.zig | 140 +++++++++++++++++++-------------- src/terminal/apc.zig | 8 ++ src/terminal/build_options.zig | 6 ++ src/terminal/page.zig | 5 +- src/terminal/stream.zig | 6 +- 8 files changed, 123 insertions(+), 67 deletions(-) diff --git a/build.zig b/build.zig index 0b87dbbe1..8838572b7 100644 --- a/build.zig +++ b/build.zig @@ -240,7 +240,8 @@ pub fn build(b: *std.Build) !void { .optimize = config.optimize, .filters = test_filters, }); - test_lib_vt_step.dependOn(&mod_vt_test.step); + const mod_vt_test_run = b.addRunArtifact(mod_vt_test); + test_lib_vt_step.dependOn(&mod_vt_test_run.step); } // Tests diff --git a/src/build/Config.zig b/src/build/Config.zig index 746021930..e075ed7ed 100644 --- a/src/build/Config.zig +++ b/src/build/Config.zig @@ -37,6 +37,7 @@ font_backend: FontBackend = .freetype, x11: bool = false, wayland: bool = false, sentry: bool = true, +simd: bool = true, i18n: bool = true, wasm_shared: bool = true, @@ -173,6 +174,12 @@ pub fn init(b: *std.Build) !Config { } }; + config.simd = b.option( + bool, + "simd", + "Build with SIMD-accelerated code paths. This requires additional build dependencies and adds libc as a runtime dependency, but results in significant performance improvements.", + ) orelse true; + config.wayland = b.option( bool, "gtk-wayland", diff --git a/src/build/GhosttyZig.zig b/src/build/GhosttyZig.zig index 306603cf5..56727f9ae 100644 --- a/src/build/GhosttyZig.zig +++ b/src/build/GhosttyZig.zig @@ -19,11 +19,14 @@ pub fn init( .root_source_file = b.path("src/lib_vt.zig"), .target = cfg.target, .optimize = cfg.optimize, - .link_libc = true, + + // SIMD require libc/libcpp (both) but otherwise we don't care. + .link_libc = if (cfg.simd) true else null, + .link_libcpp = if (cfg.simd) true else null, }); - deps.unicode_tables.addModuleImport(vt); vt_options.addOptions(b, vt, .{ .artifact = .lib, + .simd = cfg.simd, // We presently don't allow Oniguruma in our Zig module at all. // We should expose this as a build option in the future so we can @@ -39,5 +42,13 @@ pub fn init( }, }); + // We always need unicode tables + deps.unicode_tables.addModuleImport(vt); + + // If SIMD is enabled, add all our SIMD dependencies. + if (cfg.simd) { + try SharedDeps.addSimd(b, vt, null); + } + return .{ .vt = vt }; } diff --git a/src/build/SharedDeps.zig b/src/build/SharedDeps.zig index 67d416f5d..0cf0ef5c1 100644 --- a/src/build/SharedDeps.zig +++ b/src/build/SharedDeps.zig @@ -281,21 +281,6 @@ pub fn add( } } - // Simdutf - if (b.systemIntegrationOption("simdutf", .{})) { - step.linkSystemLibrary2("simdutf", dynamic_link_opts); - } else { - if (b.lazyDependency("simdutf", .{ - .target = target, - .optimize = optimize, - })) |simdutf_dep| { - step.linkLibrary(simdutf_dep.artifact("simdutf")); - try static_libs.append( - simdutf_dep.artifact("simdutf").getEmittedBin(), - ); - } - } - // Sentry if (self.config.sentry) { if (b.lazyDependency("sentry", .{ @@ -324,6 +309,13 @@ pub fn add( } } + // Simd + if (self.config.simd) try addSimd( + b, + step.root_module, + &static_libs, + ); + // Wasm we do manually since it is such a different build. if (step.rootModuleTarget().cpu.arch == .wasm32) { if (b.lazyDependency("zig_js", .{ @@ -358,35 +350,8 @@ pub fn add( step.addIncludePath(b.path("src/apprt/gtk")); } - // C++ files + // libcpp is required for various dependencies step.linkLibCpp(); - step.addIncludePath(b.path("src")); - { - // From hwy/detect_targets.h - const HWY_AVX3_SPR: c_int = 1 << 4; - const HWY_AVX3_ZEN4: c_int = 1 << 6; - const HWY_AVX3_DL: c_int = 1 << 7; - const HWY_AVX3: c_int = 1 << 8; - - // Zig 0.13 bug: https://github.com/ziglang/zig/issues/20414 - // To workaround this we just disable AVX512 support completely. - // The performance difference between AVX2 and AVX512 is not - // significant for our use case and AVX512 is very rare on consumer - // hardware anyways. - const HWY_DISABLED_TARGETS: c_int = HWY_AVX3_SPR | HWY_AVX3_ZEN4 | HWY_AVX3_DL | HWY_AVX3; - - step.addCSourceFiles(.{ - .files = &.{ - "src/simd/base64.cpp", - "src/simd/codepoint_width.cpp", - "src/simd/index_of.cpp", - "src/simd/vt.cpp", - }, - .flags = if (step.rootModuleTarget().cpu.arch == .x86_64) &.{ - b.fmt("-DHWY_DISABLED_TARGETS={}", .{HWY_DISABLED_TARGETS}), - } else &.{}, - }); - } // We always require the system SDK so that our system headers are available. // This makes things like `os/log.h` available for cross-compiling. @@ -496,24 +461,6 @@ pub fn add( try static_libs.append(cimgui_dep.artifact("cimgui").getEmittedBin()); } - // Highway - if (b.lazyDependency("highway", .{ - .target = target, - .optimize = optimize, - })) |highway_dep| { - step.linkLibrary(highway_dep.artifact("highway")); - try static_libs.append(highway_dep.artifact("highway").getEmittedBin()); - } - - // utfcpp - This is used as a dependency on our hand-written C++ code - if (b.lazyDependency("utfcpp", .{ - .target = target, - .optimize = optimize, - })) |utfcpp_dep| { - step.linkLibrary(utfcpp_dep.artifact("utfcpp")); - try static_libs.append(utfcpp_dep.artifact("utfcpp").getEmittedBin()); - } - // Fonts { // JetBrains Mono @@ -715,6 +662,77 @@ fn addGtkNg( } } +pub fn addSimd( + b: *std.Build, + m: *std.Build.Module, + static_libs: ?*LazyPathList, +) !void { + const target = m.resolved_target.?; + const optimize = m.optimize.?; + + // Simdutf + if (b.systemIntegrationOption("simdutf", .{})) { + m.linkSystemLibrary("simdutf", dynamic_link_opts); + } else { + if (b.lazyDependency("simdutf", .{ + .target = target, + .optimize = optimize, + })) |simdutf_dep| { + m.linkLibrary(simdutf_dep.artifact("simdutf")); + if (static_libs) |v| try v.append( + simdutf_dep.artifact("simdutf").getEmittedBin(), + ); + } + } + + // Highway + if (b.lazyDependency("highway", .{ + .target = target, + .optimize = optimize, + })) |highway_dep| { + m.linkLibrary(highway_dep.artifact("highway")); + if (static_libs) |v| try v.append(highway_dep.artifact("highway").getEmittedBin()); + } + + // utfcpp - This is used as a dependency on our hand-written C++ code + if (b.lazyDependency("utfcpp", .{ + .target = target, + .optimize = optimize, + })) |utfcpp_dep| { + m.linkLibrary(utfcpp_dep.artifact("utfcpp")); + if (static_libs) |v| try v.append(utfcpp_dep.artifact("utfcpp").getEmittedBin()); + } + + // SIMD C++ files + m.addIncludePath(b.path("src")); + { + // From hwy/detect_targets.h + const HWY_AVX3_SPR: c_int = 1 << 4; + const HWY_AVX3_ZEN4: c_int = 1 << 6; + const HWY_AVX3_DL: c_int = 1 << 7; + const HWY_AVX3: c_int = 1 << 8; + + // Zig 0.13 bug: https://github.com/ziglang/zig/issues/20414 + // To workaround this we just disable AVX512 support completely. + // The performance difference between AVX2 and AVX512 is not + // significant for our use case and AVX512 is very rare on consumer + // hardware anyways. + const HWY_DISABLED_TARGETS: c_int = HWY_AVX3_SPR | HWY_AVX3_ZEN4 | HWY_AVX3_DL | HWY_AVX3; + + m.addCSourceFiles(.{ + .files = &.{ + "src/simd/base64.cpp", + "src/simd/codepoint_width.cpp", + "src/simd/index_of.cpp", + "src/simd/vt.cpp", + }, + .flags = if (target.result.cpu.arch == .x86_64) &.{ + b.fmt("-DHWY_DISABLED_TARGETS={}", .{HWY_DISABLED_TARGETS}), + } else &.{}, + }); + } +} + /// Creates the resources that can be prebuilt for our dist build. pub fn gtkNgDistResources( b: *std.Build, diff --git a/src/terminal/apc.zig b/src/terminal/apc.zig index 9663afb3e..a168da4a1 100644 --- a/src/terminal/apc.zig +++ b/src/terminal/apc.zig @@ -133,6 +133,8 @@ test "unknown APC command" { } test "garbage Kitty command" { + if (comptime !build_options.kitty_graphics) return error.SkipZigTest; + const testing = std.testing; const alloc = testing.allocator; @@ -143,6 +145,8 @@ test "garbage Kitty command" { } test "Kitty command with overflow u32" { + if (comptime !build_options.kitty_graphics) return error.SkipZigTest; + const testing = std.testing; const alloc = testing.allocator; @@ -153,6 +157,8 @@ test "Kitty command with overflow u32" { } test "Kitty command with overflow i32" { + if (comptime !build_options.kitty_graphics) return error.SkipZigTest; + const testing = std.testing; const alloc = testing.allocator; @@ -163,6 +169,8 @@ test "Kitty command with overflow i32" { } test "valid Kitty command" { + if (comptime !build_options.kitty_graphics) return error.SkipZigTest; + const testing = std.testing; const alloc = testing.allocator; diff --git a/src/terminal/build_options.zig b/src/terminal/build_options.zig index 2a5153eb9..be5335f47 100644 --- a/src/terminal/build_options.zig +++ b/src/terminal/build_options.zig @@ -13,6 +13,11 @@ pub const Options = struct { /// oniguruma: bool = true, + /// Whether to build SIMD-accelerated code paths. This pulls in more + /// build-time dependencies and adds libc as a runtime dependency, + /// but results in significant performance improvements. + simd: bool = true, + /// True if we should enable the "slow" runtime safety checks. These /// are runtime safety checks that are slower than typical and should /// generally be disabled in production builds. @@ -36,6 +41,7 @@ pub fn addOptions( const opts = b.addOptions(); opts.addOption(Artifact, "artifact", v.artifact); opts.addOption(bool, "oniguruma", v.oniguruma); + opts.addOption(bool, "simd", v.simd); opts.addOption(bool, "slow_runtime_safety", v.slow_runtime_safety); // These are synthesized based on other options. diff --git a/src/terminal/page.zig b/src/terminal/page.zig index 086bfe96c..b1a24e9a9 100644 --- a/src/terminal/page.zig +++ b/src/terminal/page.zig @@ -321,7 +321,10 @@ pub const Page = struct { /// safety is disabled. This uses the libc allocator. pub fn assertIntegrity(self: *const Page) void { if (comptime build_options.slow_runtime_safety) { - self.verifyIntegrity(std.heap.c_allocator) catch |err| { + var debug_allocator: std.heap.DebugAllocator(.{}) = .init; + defer _ = debug_allocator.deinit(); + const alloc = debug_allocator.allocator(); + self.verifyIntegrity(alloc) catch |err| { log.err("page integrity violation, crashing. err={}", .{err}); @panic("page integrity violation"); }; diff --git a/src/terminal/stream.zig b/src/terminal/stream.zig index 29d8c42d3..a58e01576 100644 --- a/src/terminal/stream.zig +++ b/src/terminal/stream.zig @@ -1,4 +1,5 @@ const std = @import("std"); +const build_options = @import("terminal_options"); const assert = std.debug.assert; const testing = std.testing; const simd = @import("../simd/main.zig"); @@ -64,8 +65,9 @@ pub fn Stream(comptime Handler: type) type { /// Process a string of characters. pub fn nextSlice(self: *Self, input: []const u8) !void { - // Debug mode disables the SIMD optimizations - if (comptime debug) { + // Disable SIMD optimizations if build requests it or if our + // manual debug mode is on. + if (comptime debug or !build_options.simd) { for (input) |c| try self.next(c); return; } From 3e1ba3584372290c7d9181363d22cbc8e4c9701f Mon Sep 17 00:00:00 2001 From: Mitchell Hashimoto Date: Sun, 21 Sep 2025 20:29:16 -0700 Subject: [PATCH 11/19] terminal: fix mistaken gtk logic --- src/terminal/mouse_shape.zig | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/terminal/mouse_shape.zig b/src/terminal/mouse_shape.zig index 3694ba8ec..1e178c7ee 100644 --- a/src/terminal/mouse_shape.zig +++ b/src/terminal/mouse_shape.zig @@ -50,8 +50,8 @@ pub const MouseShape = enum(c_int) { /// Make this a valid gobject if we're in a GTK environment. pub const getGObjectType = gtk: { switch (build_options.artifact) { - .ghostty => break :gtk void, - .lib => {}, + .ghostty => {}, + .lib => break :gtk void, } break :gtk switch (@import("../build_config.zig").app_runtime) { From dfda3ac280499ff01093e4497592a9747fd70748 Mon Sep 17 00:00:00 2001 From: Mitchell Hashimoto Date: Sun, 21 Sep 2025 20:39:41 -0700 Subject: [PATCH 12/19] ci: fix example build --- .github/workflows/test.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 71d701c80..ef7490bea 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -122,7 +122,7 @@ jobs: - name: Build Example run: | cd example/${{ matrix.dir }} - nix develop -c zig build -Demit-bench + nix develop -c zig build build-flatpak: strategy: From 9c92c3bb81cbd9c23d9ecee5e1f18c3a08dc1ebc Mon Sep 17 00:00:00 2001 From: Mitchell Hashimoto Date: Sun, 21 Sep 2025 20:47:58 -0700 Subject: [PATCH 13/19] fastmem non-libc needs to use copyBackwards if dest > src This fixes test failures when Ghostty's core is run without libc. Ghostty in the real world (all built executables) require libc so this bug has never been hit before, but I'm working on a libc-less core and this caused real test failures (so its already tested, as well). --- src/fastmem.zig | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/src/fastmem.zig b/src/fastmem.zig index 687c057af..bdea44155 100644 --- a/src/fastmem.zig +++ b/src/fastmem.zig @@ -2,13 +2,20 @@ const std = @import("std"); const builtin = @import("builtin"); const assert = std.debug.assert; -/// Same as std.mem.copyForwards but prefers libc memmove if it is available -/// because it is generally much faster. +/// Same as std.mem.copyForwards/Backwards but prefers libc memmove if it is +/// available because it is generally much faster. pub inline fn move(comptime T: type, dest: []T, source: []const T) void { if (builtin.link_libc) { _ = memmove(dest.ptr, source.ptr, source.len * @sizeOf(T)); } else { - std.mem.copyForwards(T, dest, source); + // Depending on the ordering of the copy, we need to use the + // proper call here. Unfortunately this function call is + // too generic to know this at comptime. + if (@intFromPtr(dest.ptr) <= @intFromPtr(source.ptr)) { + std.mem.copyForwards(T, dest, source); + } else { + std.mem.copyBackwards(T, dest, source); + } } } From 8aa4373aaf103d5e84aa78feed37493916c48b03 Mon Sep 17 00:00:00 2001 From: Mitchell Hashimoto Date: Mon, 22 Sep 2025 06:47:30 -0700 Subject: [PATCH 14/19] ci: add simd on/off test --- .github/workflows/test.yml | 36 ++++++++++++++++++++++++++++++++++++ 1 file changed, 36 insertions(+) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index ef7490bea..ceffde09e 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -23,6 +23,7 @@ jobs: - build-snap - build-windows - test + - test-simd - test-gtk - test-sentry-linux - test-macos @@ -601,6 +602,41 @@ jobs: -Dgtk-x11=${{ matrix.x11 }} \ -Dgtk-wayland=${{ matrix.wayland }} + test-simd: + strategy: + fail-fast: false + matrix: + simd: ["true", "false"] + name: Build -Dsimd=${{ matrix.simd }} + runs-on: namespace-profile-ghostty-sm + needs: test + env: + ZIG_LOCAL_CACHE_DIR: /zig/local-cache + ZIG_GLOBAL_CACHE_DIR: /zig/global-cache + steps: + - name: Checkout code + uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 + + - name: Setup Cache + uses: namespacelabs/nscloud-cache-action@a289cf5d2fcd6874376aa92f0ef7f99dc923592a # v1.2.17 + with: + path: | + /nix + /zig + + # Install Nix and use that to run our tests so our environment matches exactly. + - uses: cachix/install-nix-action@a809471b5c7c913aa67bec8f459a11a0decc3fce # v31.6.2 + with: + nix_path: nixpkgs=channel:nixos-unstable + - uses: cachix/cachix-action@0fc020193b5a1fa3ac4575aa3a7d3aa6a35435ad # v16 + with: + name: ghostty + authToken: "${{ secrets.CACHIX_AUTH_TOKEN }}" + + - name: Test + run: | + nix develop -c zig build test -Dsimd=${{ matrix.simd }} + test-sentry-linux: strategy: fail-fast: false From 6893024c5194a61c79be924390751fce6edee8a5 Mon Sep 17 00:00:00 2001 From: Mitchell Hashimoto Date: Mon, 22 Sep 2025 08:02:55 -0700 Subject: [PATCH 15/19] simd: add scalar fallbacks to all for build_options.simd false --- src/build/Config.zig | 1 + src/build/SharedDeps.zig | 1 + src/simd/base64.zig | 69 ++++++++++++++++++++++++++++++------ src/simd/codepoint_width.zig | 5 +-- src/simd/index_of.zig | 13 +++++-- src/simd/main.zig | 3 ++ src/simd/vt.zig | 47 +++++++++++++++++++----- 7 files changed, 117 insertions(+), 22 deletions(-) diff --git a/src/build/Config.zig b/src/build/Config.zig index e075ed7ed..97a98b752 100644 --- a/src/build/Config.zig +++ b/src/build/Config.zig @@ -460,6 +460,7 @@ pub fn addOptions(self: *const Config, step: *std.Build.Step.Options) !void { step.addOption(bool, "x11", self.x11); step.addOption(bool, "wayland", self.wayland); step.addOption(bool, "sentry", self.sentry); + step.addOption(bool, "simd", self.simd); step.addOption(bool, "i18n", self.i18n); step.addOption(ApprtRuntime, "app_runtime", self.app_runtime); step.addOption(FontBackend, "font_backend", self.font_backend); diff --git a/src/build/SharedDeps.zig b/src/build/SharedDeps.zig index 0cf0ef5c1..cf84b3e0c 100644 --- a/src/build/SharedDeps.zig +++ b/src/build/SharedDeps.zig @@ -112,6 +112,7 @@ pub fn add( const vt_options = @import("../terminal/build_options.zig"); vt_options.addOptions(b, step.root_module, .{ .artifact = .ghostty, + .simd = self.config.simd, .slow_runtime_safety = switch (optimize) { .Debug => true, .ReleaseSafe, diff --git a/src/simd/base64.zig b/src/simd/base64.zig index 778fbfe3e..c733cf103 100644 --- a/src/simd/base64.zig +++ b/src/simd/base64.zig @@ -1,4 +1,63 @@ const std = @import("std"); +const options = @import("build_options"); +const assert = std.debug.assert; +const log = std.log.scoped(.simd_base64); + +// Used for the non-SIMD implementation +const Base64Decoder = std.base64.standard_no_pad.Decoder; + +pub fn maxLen(input: []const u8) usize { + if (comptime options.simd) return ghostty_simd_base64_max_length( + input.ptr, + input.len, + ); + + return maxLenScalar(input); +} + +fn maxLenScalar(input: []const u8) usize { + return Base64Decoder.calcSizeForSlice(scalarInput(input)) catch |err| { + log.warn("failed to calculate base64 size for payload: {}", .{err}); + return 0; + }; +} + +pub fn decode(input: []const u8, output: []u8) error{Base64Invalid}![]const u8 { + if (comptime options.simd) { + const res = ghostty_simd_base64_decode( + input.ptr, + input.len, + output.ptr, + ); + if (res < 0) return error.Base64Invalid; + return output[0..@intCast(res)]; + } + + return decodeScalar(input, output); +} + +fn decodeScalar( + input_raw: []const u8, + output: []u8, +) error{Base64Invalid}![]const u8 { + const input = scalarInput(input_raw); + const size = maxLenScalar(input); + if (size == 0) return ""; + assert(output.len >= size); + Base64Decoder.decode( + output, + scalarInput(input), + ) catch return error.Base64Invalid; + return output[0..size]; +} + +/// For non-SIMD enabled builds, we trim the padding from the end of the +/// base64 input in order to get identical output with the SIMD version. +fn scalarInput(input: []const u8) []const u8 { + var i: usize = 0; + while (input[input.len - i - 1] == '=') i += 1; + return input[0 .. input.len - i]; +} // base64.cpp extern "c" fn ghostty_simd_base64_max_length( @@ -11,16 +70,6 @@ extern "c" fn ghostty_simd_base64_decode( output: [*]u8, ) isize; -pub fn maxLen(input: []const u8) usize { - return ghostty_simd_base64_max_length(input.ptr, input.len); -} - -pub fn decode(input: []const u8, output: []u8) error{Base64Invalid}![]const u8 { - const res = ghostty_simd_base64_decode(input.ptr, input.len, output.ptr); - if (res < 0) return error.Base64Invalid; - return output[0..@intCast(res)]; -} - test "base64 maxLen" { const testing = std.testing; const len = maxLen("aGVsbG8gd29ybGQ="); diff --git a/src/simd/codepoint_width.zig b/src/simd/codepoint_width.zig index aab4bdd95..e097dbd61 100644 --- a/src/simd/codepoint_width.zig +++ b/src/simd/codepoint_width.zig @@ -1,11 +1,12 @@ const std = @import("std"); +const options = @import("build_options"); // vt.cpp extern "c" fn ghostty_simd_codepoint_width(u32) i8; pub fn codepointWidth(cp: u32) i8 { - //return @import("ziglyph").display_width.codePointWidth(@intCast(cp), .half); - return ghostty_simd_codepoint_width(cp); + if (comptime options.simd) return ghostty_simd_codepoint_width(cp); + return @import("ziglyph").display_width.codePointWidth(@intCast(cp), .half); } test "codepointWidth basic" { diff --git a/src/simd/index_of.zig b/src/simd/index_of.zig index b39605996..cea549b95 100644 --- a/src/simd/index_of.zig +++ b/src/simd/index_of.zig @@ -1,5 +1,6 @@ const std = @import("std"); const builtin = @import("builtin"); +const options = @import("build_options"); extern "c" fn ghostty_simd_index_of( needle: u8, @@ -8,8 +9,16 @@ extern "c" fn ghostty_simd_index_of( ) usize; pub fn indexOf(input: []const u8, needle: u8) ?usize { - const result = ghostty_simd_index_of(needle, input.ptr, input.len); - return if (result == input.len) null else result; + if (comptime options.simd) { + const result = ghostty_simd_index_of(needle, input.ptr, input.len); + return if (result == input.len) null else result; + } + + return indexOfScalar(input, needle); +} + +fn indexOfScalar(input: []const u8, needle: u8) ?usize { + return std.mem.indexOfScalar(u8, input, needle); } test "indexOf" { diff --git a/src/simd/main.zig b/src/simd/main.zig index bfcd68c0a..aabdd21d1 100644 --- a/src/simd/main.zig +++ b/src/simd/main.zig @@ -1,3 +1,6 @@ +//! SIMD-optimized routines. If `build_options.simd` is false, then the API +//! still works but we fall back to pure Zig scalar implementations. + const std = @import("std"); const codepoint_width = @import("codepoint_width.zig"); diff --git a/src/simd/vt.zig b/src/simd/vt.zig index dc1c0a511..2a19c52c7 100644 --- a/src/simd/vt.zig +++ b/src/simd/vt.zig @@ -1,4 +1,7 @@ const std = @import("std"); +const options = @import("build_options"); +const assert = std.debug.assert; +const indexOf = @import("index_of.zig").indexOf; // vt.cpp extern "c" fn ghostty_simd_decode_utf8_until_control_seq( @@ -17,15 +20,43 @@ pub fn utf8DecodeUntilControlSeq( input: []const u8, output: []u32, ) DecodeResult { - var decoded: usize = 0; - const consumed = ghostty_simd_decode_utf8_until_control_seq( - input.ptr, - input.len, - output.ptr, - &decoded, - ); + assert(output.len >= input.len); - return .{ .consumed = consumed, .decoded = decoded }; + if (comptime options.simd) { + var decoded: usize = 0; + const consumed = ghostty_simd_decode_utf8_until_control_seq( + input.ptr, + input.len, + output.ptr, + &decoded, + ); + + return .{ .consumed = consumed, .decoded = decoded }; + } + + return utf8DecodeUntilControlSeqScalar(input, output); +} + +fn utf8DecodeUntilControlSeqScalar( + input: []const u8, + output: []u32, +) DecodeResult { + // Find our escape + const idx = indexOf(input, 0x1B) orelse input.len; + + // Copy up to the escape + const view = std.unicode.Utf8View.init(input[0..idx]) catch unreachable; + var it = view.iterator(); + var i: usize = 0; + while (it.nextCodepoint()) |cp| { + output[i] = @intCast(cp); + i += 1; + } + + return .{ + .consumed = idx, + .decoded = i, + }; } test "decode no escape" { From 5a29dd3ef5e2fdf47963ded980251f314a0c6b95 Mon Sep 17 00:00:00 2001 From: Mitchell Hashimoto Date: Mon, 22 Sep 2025 08:35:44 -0700 Subject: [PATCH 16/19] build: make build_options generally available --- src/build/Config.zig | 18 +++++++++++++ src/build/GhosttyZig.zig | 33 +++++++++++------------- src/build/SharedDeps.zig | 15 +---------- src/terminal/build_options.zig | 46 +++++++++++++++++----------------- 4 files changed, 56 insertions(+), 56 deletions(-) diff --git a/src/build/Config.zig b/src/build/Config.zig index 97a98b752..244af8d93 100644 --- a/src/build/Config.zig +++ b/src/build/Config.zig @@ -8,6 +8,7 @@ const builtin = @import("builtin"); const ApprtRuntime = @import("../apprt/runtime.zig").Runtime; const FontBackend = @import("../font/backend.zig").Backend; const RendererBackend = @import("../renderer/backend.zig").Backend; +const TerminalBuildOptions = @import("../terminal/build_options.zig").Options; const XCFramework = @import("GhosttyXCFramework.zig"); const WasmTarget = @import("../os/wasm/target.zig").Target; const expandPath = @import("../os/path.zig").expand; @@ -490,6 +491,23 @@ pub fn addOptions(self: *const Config, step: *std.Build.Step.Options) !void { ); } +/// Returns the build options for the terminal module. This assumes a +/// Ghostty executable being built. Callers should modify this as needed. +pub fn terminalOptions(self: *const Config) TerminalBuildOptions { + return .{ + .artifact = .ghostty, + .simd = self.simd, + .oniguruma = true, + .slow_runtime_safety = switch (self.optimize) { + .Debug => true, + .ReleaseSafe, + .ReleaseSmall, + .ReleaseFast, + => false, + }, + }; +} + /// Returns a baseline CPU target retaining all the other CPU configs. pub fn baselineTarget(self: *const Config) std.Build.ResolvedTarget { // Set our cpu model as baseline. There may need to be other modifications diff --git a/src/build/GhosttyZig.zig b/src/build/GhosttyZig.zig index 56727f9ae..f175eb957 100644 --- a/src/build/GhosttyZig.zig +++ b/src/build/GhosttyZig.zig @@ -6,8 +6,6 @@ const std = @import("std"); const Config = @import("Config.zig"); const SharedDeps = @import("SharedDeps.zig"); -const vt_options = @import("../terminal/build_options.zig"); - vt: *std.Build.Module, pub fn init( @@ -15,6 +13,18 @@ pub fn init( cfg: *const Config, deps: *const SharedDeps, ) !GhosttyZig { + // General build options + const general_options = b.addOptions(); + try cfg.addOptions(general_options); + + // Terminal module build options + var vt_options = cfg.terminalOptions(); + vt_options.artifact = .lib; + // We presently don't allow Oniguruma in our Zig module at all. + // We should expose this as a build option in the future so we can + // conditionally do this. + vt_options.oniguruma = false; + const vt = b.addModule("ghostty-vt", .{ .root_source_file = b.path("src/lib_vt.zig"), .target = cfg.target, @@ -24,23 +34,8 @@ pub fn init( .link_libc = if (cfg.simd) true else null, .link_libcpp = if (cfg.simd) true else null, }); - vt_options.addOptions(b, vt, .{ - .artifact = .lib, - .simd = cfg.simd, - - // We presently don't allow Oniguruma in our Zig module at all. - // We should expose this as a build option in the future so we can - // conditionally do this. - .oniguruma = false, - - .slow_runtime_safety = switch (cfg.optimize) { - .Debug => true, - .ReleaseSafe, - .ReleaseSmall, - .ReleaseFast, - => false, - }, - }); + vt.addOptions("build_options", general_options); + vt_options.add(b, vt); // We always need unicode tables deps.unicode_tables.addModuleImport(vt); diff --git a/src/build/SharedDeps.zig b/src/build/SharedDeps.zig index cf84b3e0c..4f3e291fa 100644 --- a/src/build/SharedDeps.zig +++ b/src/build/SharedDeps.zig @@ -108,20 +108,7 @@ pub fn add( step.root_module.addOptions("build_options", self.options); // Every exe needs the terminal options - { - const vt_options = @import("../terminal/build_options.zig"); - vt_options.addOptions(b, step.root_module, .{ - .artifact = .ghostty, - .simd = self.config.simd, - .slow_runtime_safety = switch (optimize) { - .Debug => true, - .ReleaseSafe, - .ReleaseSmall, - .ReleaseFast, - => false, - }, - }); - } + self.config.terminalOptions().add(b, step.root_module); // Freetype _ = b.systemIntegrationOption("freetype", .{}); // Shows it in help diff --git a/src/terminal/build_options.zig b/src/terminal/build_options.zig index be5335f47..1b0449bbf 100644 --- a/src/terminal/build_options.zig +++ b/src/terminal/build_options.zig @@ -2,7 +2,7 @@ const std = @import("std"); pub const Options = struct { /// The target artifact to build. This will gate some functionality. - artifact: Artifact = .ghostty, + artifact: Artifact, /// Whether Oniguruma regex support is available. If this isn't /// available, some features will be disabled. This may be outdated, @@ -11,17 +11,36 @@ pub const Options = struct { /// - Kitty graphics protocol /// - Tmux control mode /// - oniguruma: bool = true, + oniguruma: bool, /// Whether to build SIMD-accelerated code paths. This pulls in more /// build-time dependencies and adds libc as a runtime dependency, /// but results in significant performance improvements. - simd: bool = true, + simd: bool, /// True if we should enable the "slow" runtime safety checks. These /// are runtime safety checks that are slower than typical and should /// generally be disabled in production builds. - slow_runtime_safety: bool = false, + slow_runtime_safety: bool, + + /// Add the required build options for the terminal module. + pub fn add( + self: Options, + b: *std.Build, + m: *std.Build.Module, + ) void { + const opts = b.addOptions(); + opts.addOption(Artifact, "artifact", self.artifact); + opts.addOption(bool, "oniguruma", self.oniguruma); + opts.addOption(bool, "simd", self.simd); + opts.addOption(bool, "slow_runtime_safety", self.slow_runtime_safety); + + // These are synthesized based on other options. + opts.addOption(bool, "kitty_graphics", self.oniguruma); + opts.addOption(bool, "tmux_control_mode", self.oniguruma); + + m.addOptions("terminal_options", opts); + } }; pub const Artifact = enum { @@ -31,22 +50,3 @@ pub const Artifact = enum { /// libghostty-vt, Zig module lib, }; - -/// Add the required build options for the terminal module. -pub fn addOptions( - b: *std.Build, - m: *std.Build.Module, - v: Options, -) void { - const opts = b.addOptions(); - opts.addOption(Artifact, "artifact", v.artifact); - opts.addOption(bool, "oniguruma", v.oniguruma); - opts.addOption(bool, "simd", v.simd); - opts.addOption(bool, "slow_runtime_safety", v.slow_runtime_safety); - - // These are synthesized based on other options. - opts.addOption(bool, "kitty_graphics", v.oniguruma); - opts.addOption(bool, "tmux_control_mode", v.oniguruma); - - m.addOptions("terminal_options", opts); -} From 530633b9e92ef7688b825007131f554c899ee458 Mon Sep 17 00:00:00 2001 From: Mitchell Hashimoto Date: Mon, 22 Sep 2025 09:12:48 -0700 Subject: [PATCH 17/19] simd: fix scalar utf8 decoding --- src/simd/vt.zig | 49 ++++++++++++++++++++++++++++++++++++++----------- 1 file changed, 38 insertions(+), 11 deletions(-) diff --git a/src/simd/vt.zig b/src/simd/vt.zig index 2a19c52c7..8e974ad7e 100644 --- a/src/simd/vt.zig +++ b/src/simd/vt.zig @@ -43,19 +43,44 @@ fn utf8DecodeUntilControlSeqScalar( ) DecodeResult { // Find our escape const idx = indexOf(input, 0x1B) orelse input.len; + const decode = input[0..idx]; - // Copy up to the escape - const view = std.unicode.Utf8View.init(input[0..idx]) catch unreachable; - var it = view.iterator(); - var i: usize = 0; - while (it.nextCodepoint()) |cp| { - output[i] = @intCast(cp); - i += 1; + // Go through and decode one item at a time. + var decode_offset: usize = 0; + var decode_count: usize = 0; + while (decode_offset < decode.len) { + const decode_rem = decode[decode_offset..]; + const cp_len = std.unicode.utf8ByteSequenceLength(decode_rem[0]) catch { + // Note, this is matching our SIMD behavior, but it is admittedly + // a bit weird. See our "decode invalid leading byte" test too. + // SIMD should be our source of truth then we copy behavior here. + break; + }; + + // If we don't have that number of bytes available. we finish. We + // assume this is a partial input and we defer to the future. + if (decode_rem.len < cp_len) break; + + // We have the bytes available, so move forward + const cp_bytes = decode_rem[0..cp_len]; + decode_offset += cp_len; + if (std.unicode.utf8Decode(cp_bytes)) |cp| { + output[decode_count] = @intCast(cp); + decode_count += 1; + } else |_| { + // If decoding failed, we replace the leading byte with the + // replacement char and then continue decoding after that + // byte. This matches the SIMD behavior and is tested by the + // "invalid UTF-8" tests. + output[decode_count] = 0xFFFD; + decode_count += 1; + decode_offset -= cp_len - 1; + } } return .{ - .consumed = idx, - .decoded = i, + .consumed = decode_offset, + .decoded = decode_count, }; } @@ -139,16 +164,18 @@ test "decode invalid UTF-8" { var output: [64]u32 = undefined; - // Invalid leading 1s + // Invalid leading 2-byte sequence { - const str = "hello\xc2\x00"; + const str = "hello\xc2\x01"; try testing.expectEqual(DecodeResult{ .consumed = 7, .decoded = 7, }, utf8DecodeUntilControlSeq(str, &output)); } + // Replacement will only replace the invalid leading byte. try testing.expectEqual(@as(u32, 0xFFFD), output[5]); + try testing.expectEqual(@as(u32, 0x01), output[6]); } // This is testing our current behavior so that we know we have to handle From 8477b6a21aaaa62c55323f9f7ddba8d85f434d7f Mon Sep 17 00:00:00 2001 From: Mitchell Hashimoto Date: Mon, 22 Sep 2025 09:42:53 -0700 Subject: [PATCH 18/19] simd: scalar base64 ignores invalid padding --- src/simd/base64.zig | 9 +-- src/simd/base64_scalar.zig | 147 +++++++++++++++++++++++++++++++++++++ 2 files changed, 151 insertions(+), 5 deletions(-) create mode 100644 src/simd/base64_scalar.zig diff --git a/src/simd/base64.zig b/src/simd/base64.zig index c733cf103..88b97bb03 100644 --- a/src/simd/base64.zig +++ b/src/simd/base64.zig @@ -1,10 +1,9 @@ const std = @import("std"); const options = @import("build_options"); const assert = std.debug.assert; -const log = std.log.scoped(.simd_base64); +const scalar_decoder = @import("base64_scalar.zig").scalar_decoder; -// Used for the non-SIMD implementation -const Base64Decoder = std.base64.standard_no_pad.Decoder; +const log = std.log.scoped(.simd_base64); pub fn maxLen(input: []const u8) usize { if (comptime options.simd) return ghostty_simd_base64_max_length( @@ -16,7 +15,7 @@ pub fn maxLen(input: []const u8) usize { } fn maxLenScalar(input: []const u8) usize { - return Base64Decoder.calcSizeForSlice(scalarInput(input)) catch |err| { + return scalar_decoder.calcSizeForSlice(scalarInput(input)) catch |err| { log.warn("failed to calculate base64 size for payload: {}", .{err}); return 0; }; @@ -44,7 +43,7 @@ fn decodeScalar( const size = maxLenScalar(input); if (size == 0) return ""; assert(output.len >= size); - Base64Decoder.decode( + scalar_decoder.decode( output, scalarInput(input), ) catch return error.Base64Invalid; diff --git a/src/simd/base64_scalar.zig b/src/simd/base64_scalar.zig new file mode 100644 index 000000000..4172ed107 --- /dev/null +++ b/src/simd/base64_scalar.zig @@ -0,0 +1,147 @@ +const std = @import("std"); +const assert = std.debug.assert; + +pub const scalar_decoder: Base64Decoder = .init( + std.base64.standard_alphabet_chars, + null, +); + +/// Copied from Zig 0.14.1 stdlib and commented out the invalid padding +/// scenarios, because Kitty Graphics requires a decoder that doesn't care +/// about invalid padding scenarios. +const Base64Decoder = struct { + const invalid_char: u8 = 0xff; + const invalid_char_tst: u32 = 0xff000000; + + const Error = error{ + InvalidCharacter, + InvalidPadding, + NoSpaceLeft, + }; + + /// e.g. 'A' => 0. + /// `invalid_char` for any value not in the 64 alphabet chars. + char_to_index: [256]u8, + fast_char_to_index: [4][256]u32, + pad_char: ?u8, + + pub fn init(alphabet_chars: [64]u8, pad_char: ?u8) Base64Decoder { + var result = Base64Decoder{ + .char_to_index = [_]u8{invalid_char} ** 256, + .fast_char_to_index = .{[_]u32{invalid_char_tst} ** 256} ** 4, + .pad_char = pad_char, + }; + + var char_in_alphabet = [_]bool{false} ** 256; + for (alphabet_chars, 0..) |c, i| { + assert(!char_in_alphabet[c]); + assert(pad_char == null or c != pad_char.?); + + const ci = @as(u32, @intCast(i)); + result.fast_char_to_index[0][c] = ci << 2; + result.fast_char_to_index[1][c] = (ci >> 4) | ((ci & 0x0f) << 12); + result.fast_char_to_index[2][c] = ((ci & 0x3) << 22) | ((ci & 0x3c) << 6); + result.fast_char_to_index[3][c] = ci << 16; + + result.char_to_index[c] = @as(u8, @intCast(i)); + char_in_alphabet[c] = true; + } + return result; + } + + /// Return the maximum possible decoded size for a given input length - The actual length may be less if the input includes padding. + /// `InvalidPadding` is returned if the input length is not valid. + pub fn calcSizeUpperBound(decoder: *const Base64Decoder, source_len: usize) Error!usize { + var result = source_len / 4 * 3; + const leftover = source_len % 4; + if (decoder.pad_char != null) { + if (leftover % 4 != 0) return error.InvalidPadding; + } else { + if (leftover % 4 == 1) return error.InvalidPadding; + result += leftover * 3 / 4; + } + return result; + } + + /// Return the exact decoded size for a slice. + /// `InvalidPadding` is returned if the input length is not valid. + pub fn calcSizeForSlice(decoder: *const Base64Decoder, source: []const u8) Error!usize { + const source_len = source.len; + var result = try decoder.calcSizeUpperBound(source_len); + if (decoder.pad_char) |pad_char| { + if (source_len >= 1 and source[source_len - 1] == pad_char) result -= 1; + if (source_len >= 2 and source[source_len - 2] == pad_char) result -= 1; + } + return result; + } + + /// dest.len must be what you get from ::calcSize. + /// Invalid characters result in `error.InvalidCharacter`. + /// Invalid padding results in `error.InvalidPadding`. + pub fn decode(decoder: *const Base64Decoder, dest: []u8, source: []const u8) Error!void { + if (decoder.pad_char != null and source.len % 4 != 0) return error.InvalidPadding; + var dest_idx: usize = 0; + var fast_src_idx: usize = 0; + var acc: u12 = 0; + var acc_len: u4 = 0; + var leftover_idx: ?usize = null; + while (fast_src_idx + 16 < source.len and dest_idx + 15 < dest.len) : ({ + fast_src_idx += 16; + dest_idx += 12; + }) { + var bits: u128 = 0; + inline for (0..4) |i| { + var new_bits: u128 = decoder.fast_char_to_index[0][source[fast_src_idx + i * 4]]; + new_bits |= decoder.fast_char_to_index[1][source[fast_src_idx + 1 + i * 4]]; + new_bits |= decoder.fast_char_to_index[2][source[fast_src_idx + 2 + i * 4]]; + new_bits |= decoder.fast_char_to_index[3][source[fast_src_idx + 3 + i * 4]]; + if ((new_bits & invalid_char_tst) != 0) return error.InvalidCharacter; + bits |= (new_bits << (24 * i)); + } + std.mem.writeInt(u128, dest[dest_idx..][0..16], bits, .little); + } + while (fast_src_idx + 4 < source.len and dest_idx + 3 < dest.len) : ({ + fast_src_idx += 4; + dest_idx += 3; + }) { + var bits = decoder.fast_char_to_index[0][source[fast_src_idx]]; + bits |= decoder.fast_char_to_index[1][source[fast_src_idx + 1]]; + bits |= decoder.fast_char_to_index[2][source[fast_src_idx + 2]]; + bits |= decoder.fast_char_to_index[3][source[fast_src_idx + 3]]; + if ((bits & invalid_char_tst) != 0) return error.InvalidCharacter; + std.mem.writeInt(u32, dest[dest_idx..][0..4], bits, .little); + } + const remaining = source[fast_src_idx..]; + for (remaining, fast_src_idx..) |c, src_idx| { + const d = decoder.char_to_index[c]; + if (d == invalid_char) { + if (decoder.pad_char == null or c != decoder.pad_char.?) return error.InvalidCharacter; + leftover_idx = src_idx; + break; + } + acc = (acc << 6) + d; + acc_len += 6; + if (acc_len >= 8) { + acc_len -= 8; + dest[dest_idx] = @as(u8, @truncate(acc >> acc_len)); + dest_idx += 1; + } + } + // if (acc_len > 4 or (acc & (@as(u12, 1) << acc_len) - 1) != 0) { + // return error.InvalidPadding; + // } + if (leftover_idx == null) return; + const leftover = source[leftover_idx.?..]; + if (decoder.pad_char) |pad_char| { + const padding_len = acc_len / 2; + var padding_chars: usize = 0; + for (leftover) |c| { + if (c != pad_char) { + return if (c == Base64Decoder.invalid_char) error.InvalidCharacter else error.InvalidPadding; + } + padding_chars += 1; + } + if (padding_chars != padding_len) return error.InvalidPadding; + } + } +}; From c177716ac64b7180069e6529e8c27d4f12c53dd0 Mon Sep 17 00:00:00 2001 From: Mitchell Hashimoto Date: Mon, 22 Sep 2025 09:53:18 -0700 Subject: [PATCH 19/19] build: some docs --- src/build/Config.zig | 2 +- src/build/SharedDeps.zig | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/src/build/Config.zig b/src/build/Config.zig index 244af8d93..474674d3a 100644 --- a/src/build/Config.zig +++ b/src/build/Config.zig @@ -178,7 +178,7 @@ pub fn init(b: *std.Build) !Config { config.simd = b.option( bool, "simd", - "Build with SIMD-accelerated code paths. This requires additional build dependencies and adds libc as a runtime dependency, but results in significant performance improvements.", + "Build with SIMD-accelerated code paths. Results in significant performance improvements.", ) orelse true; config.wayland = b.option( diff --git a/src/build/SharedDeps.zig b/src/build/SharedDeps.zig index 4f3e291fa..d6f6a05bf 100644 --- a/src/build/SharedDeps.zig +++ b/src/build/SharedDeps.zig @@ -650,6 +650,8 @@ fn addGtkNg( } } +/// Add only the dependencies required for `Config.simd` enbled. This also +/// adds all the simd source files for compilation. pub fn addSimd( b: *std.Build, m: *std.Build.Module,