From 55ac946fff6db13a5b0e1f7c3a64601ea26d94ef Mon Sep 17 00:00:00 2001 From: rhodes-b <59537185+rhodes-b@users.noreply.github.com> Date: Wed, 17 Sep 2025 02:41:20 -0500 Subject: [PATCH 01/77] more info on do NOT copy default config --- src/config/config-template | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/config/config-template b/src/config/config-template index aac0b0b12..c9b51deb8 100644 --- a/src/config/config-template +++ b/src/config/config-template @@ -12,6 +12,9 @@ # Run `ghostty +show-config --default --docs` to view a list of # all available config options and their default values. # +# Do not copy the output of the defaults into your config, like stated above +# users only need to set options to change the defaults. +# # Additionally, each config option is also explained in detail # on Ghostty's website, at https://ghostty.org/docs/config. # From a22a1771b55735d75e96dd2dfd7d98cd5eb74b9d Mon Sep 17 00:00:00 2001 From: Matthias von Arx Date: Thu, 18 Sep 2025 18:09:10 +0200 Subject: [PATCH 02/77] documentation: fix MacOSDockDropBehavior valid values --- src/config/Config.zig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/config/Config.zig b/src/config/Config.zig index 945e091f9..9a40dc0e4 100644 --- a/src/config/Config.zig +++ b/src/config/Config.zig @@ -2710,7 +2710,7 @@ keybind: Keybinds = .{}, /// /// * `new-tab` - Create a new tab in the current window, or open /// a new window if none exist. -/// * `new-window` - Create a new window unconditionally. +/// * `window` - Create a new window unconditionally. /// /// The default value is `new-tab`. /// From 773990ada3612f7f80029d814e3b296296a16bd5 Mon Sep 17 00:00:00 2001 From: Mitchell Hashimoto Date: Thu, 18 Sep 2025 12:06:46 -0700 Subject: [PATCH 03/77] macos: window-position-x/y are from top-left corner Fixes #8672 Almost fully written by AI: https://ampcode.com/threads/T-86df68a3-578c-4a1c-91f3-788f8b8f0aae I reviewed all the code. --- .../Window Styles/TerminalWindow.swift | 18 +++- .../Extensions/NSScreen+Extension.swift | 16 +++ macos/Tests/NSScreenTests.swift | 99 +++++++++++++++++++ 3 files changed, 128 insertions(+), 5 deletions(-) create mode 100644 macos/Tests/NSScreenTests.swift diff --git a/macos/Sources/Features/Terminal/Window Styles/TerminalWindow.swift b/macos/Sources/Features/Terminal/Window Styles/TerminalWindow.swift index 44bbe27ac..6879147ce 100644 --- a/macos/Sources/Features/Terminal/Window Styles/TerminalWindow.swift +++ b/macos/Sources/Features/Terminal/Window Styles/TerminalWindow.swift @@ -408,11 +408,19 @@ class TerminalWindow: NSWindow { return } - // Orient based on the top left of the primary monitor - let frame = screen.visibleFrame - setFrameOrigin(.init( - x: frame.minX + CGFloat(x), - y: frame.maxY - (CGFloat(y) + frame.height))) + // Convert top-left coordinates to bottom-left origin using our utility extension + let origin = screen.origin( + fromTopLeftOffsetX: CGFloat(x), + offsetY: CGFloat(y), + windowSize: frame.size) + + // Clamp the origin to ensure the window stays fully visible on screen + var safeOrigin = origin + let vf = screen.visibleFrame + safeOrigin.x = min(max(safeOrigin.x, vf.minX), vf.maxX - frame.width) + safeOrigin.y = min(max(safeOrigin.y, vf.minY), vf.maxY - frame.height) + + setFrameOrigin(safeOrigin) } private func hideWindowButtons() { diff --git a/macos/Sources/Helpers/Extensions/NSScreen+Extension.swift b/macos/Sources/Helpers/Extensions/NSScreen+Extension.swift index 675e0b2ec..f46106004 100644 --- a/macos/Sources/Helpers/Extensions/NSScreen+Extension.swift +++ b/macos/Sources/Helpers/Extensions/NSScreen+Extension.swift @@ -41,4 +41,20 @@ extension NSScreen { // know any other situation this is true. return safeAreaInsets.top > 0 } + + /// Converts top-left offset coordinates to bottom-left origin coordinates for window positioning. + /// - Parameters: + /// - x: X offset from top-left corner + /// - y: Y offset from top-left corner + /// - windowSize: Size of the window to be positioned + /// - Returns: CGPoint suitable for setFrameOrigin that positions the window as requested + func origin(fromTopLeftOffsetX x: CGFloat, offsetY y: CGFloat, windowSize: CGSize) -> CGPoint { + let vf = visibleFrame + + // Convert top-left coordinates to bottom-left origin + let originX = vf.minX + x + let originY = vf.maxY - y - windowSize.height + + return CGPoint(x: originX, y: originY) + } } diff --git a/macos/Tests/NSScreenTests.swift b/macos/Tests/NSScreenTests.swift new file mode 100644 index 000000000..f7431bf05 --- /dev/null +++ b/macos/Tests/NSScreenTests.swift @@ -0,0 +1,99 @@ +// +// WindowPositionTests.swift +// GhosttyTests +// +// Tests for window positioning coordinate conversion functionality. +// + +import Testing +import AppKit +@testable import Ghostty + +struct NSScreenExtensionTests { + /// Test positive coordinate conversion from top-left to bottom-left + @Test func testPositiveCoordinateConversion() async throws { + // Mock screen with 1000x800 visible frame starting at (0, 100) + let mockScreenFrame = NSRect(x: 0, y: 100, width: 1000, height: 800) + let mockScreen = MockNSScreen(visibleFrame: mockScreenFrame) + + // Mock window size + let windowSize = CGSize(width: 400, height: 300) + + // Test top-left positioning: x=15, y=15 + let origin = mockScreen.origin( + fromTopLeftOffsetX: 15, + offsetY: 15, + windowSize: windowSize) + + // Expected: x = 0 + 15 = 15, y = (100 + 800) - 15 - 300 = 585 + #expect(origin.x == 15) + #expect(origin.y == 585) + } + + /// Test zero coordinates (exact top-left corner) + @Test func testZeroCoordinates() async throws { + let mockScreenFrame = NSRect(x: 0, y: 100, width: 1000, height: 800) + let mockScreen = MockNSScreen(visibleFrame: mockScreenFrame) + let windowSize = CGSize(width: 400, height: 300) + + let origin = mockScreen.origin( + fromTopLeftOffsetX: 0, + offsetY: 0, + windowSize: windowSize) + + // Expected: x = 0, y = (100 + 800) - 0 - 300 = 600 + #expect(origin.x == 0) + #expect(origin.y == 600) + } + + /// Test with offset screen (not starting at origin) + @Test func testOffsetScreen() async throws { + // Secondary monitor at position (1440, 0) with 1920x1080 resolution + let mockScreenFrame = NSRect(x: 1440, y: 0, width: 1920, height: 1080) + let mockScreen = MockNSScreen(visibleFrame: mockScreenFrame) + let windowSize = CGSize(width: 600, height: 400) + + let origin = mockScreen.origin( + fromTopLeftOffsetX: 100, + offsetY: 50, + windowSize: windowSize) + + // Expected: x = 1440 + 100 = 1540, y = (0 + 1080) - 50 - 400 = 630 + #expect(origin.x == 1540) + #expect(origin.y == 630) + } + + /// Test large coordinates + @Test func testLargeCoordinates() async throws { + let mockScreenFrame = NSRect(x: 0, y: 0, width: 1920, height: 1080) + let mockScreen = MockNSScreen(visibleFrame: mockScreenFrame) + let windowSize = CGSize(width: 400, height: 300) + + let origin = mockScreen.origin( + fromTopLeftOffsetX: 500, + offsetY: 200, + windowSize: windowSize) + + // Expected: x = 0 + 500 = 500, y = (0 + 1080) - 200 - 300 = 580 + #expect(origin.x == 500) + #expect(origin.y == 580) + } +} + +/// Mock NSScreen class for testing coordinate conversion +private class MockNSScreen: NSScreen { + private let mockVisibleFrame: NSRect + + init(visibleFrame: NSRect) { + self.mockVisibleFrame = visibleFrame + super.init() + } + + required init?(coder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } + + override var visibleFrame: NSRect { + return mockVisibleFrame + } +} From 734d1a13b3565c1cff19861e2c45b3b2220ae7cc Mon Sep 17 00:00:00 2001 From: Mitchell Hashimoto Date: Thu, 18 Sep 2025 13:05:51 -0700 Subject: [PATCH 04/77] macos: set initial window in TerminalWindow awakeFromNib Maybe fixes #8736 I thought `windowDidLoad` was early on because its before the window is shown but apparently not. Let's try `awakeFromNib` which is called just after the window is loaded from the nib. It is hard to get any earlier than that. --- .../Features/Terminal/BaseTerminalController.swift | 11 ----------- .../Terminal/Window Styles/TerminalWindow.swift | 11 +++++++++++ 2 files changed, 11 insertions(+), 11 deletions(-) diff --git a/macos/Sources/Features/Terminal/BaseTerminalController.swift b/macos/Sources/Features/Terminal/BaseTerminalController.swift index ffe7997a6..9c94cfef8 100644 --- a/macos/Sources/Features/Terminal/BaseTerminalController.swift +++ b/macos/Sources/Features/Terminal/BaseTerminalController.swift @@ -863,14 +863,6 @@ class BaseTerminalController: NSWindowController, // Everything beyond here is setting up the window guard let window else { return } - // If there is a hardcoded title in the configuration, we set that - // immediately. Future `set_title` apprt actions will override this - // if necessary but this ensures our window loads with the proper - // title immediately rather than on another event loop tick (see #5934) - if let title = derivedConfig.title { - window.title = title - } - // We always initialize our fullscreen style to native if we can because // initialization sets up some state (i.e. observers). If its set already // somehow we don't do this. @@ -1072,20 +1064,17 @@ class BaseTerminalController: NSWindowController, } private struct DerivedConfig { - let title: String? let macosTitlebarProxyIcon: Ghostty.MacOSTitlebarProxyIcon let windowStepResize: Bool let focusFollowsMouse: Bool init() { - self.title = nil self.macosTitlebarProxyIcon = .visible self.windowStepResize = false self.focusFollowsMouse = false } init(_ config: Ghostty.Config) { - self.title = config.title self.macosTitlebarProxyIcon = config.macosTitlebarProxyIcon self.windowStepResize = config.windowStepResize self.focusFollowsMouse = config.focusFollowsMouse diff --git a/macos/Sources/Features/Terminal/Window Styles/TerminalWindow.swift b/macos/Sources/Features/Terminal/Window Styles/TerminalWindow.swift index 6879147ce..3ab6293dc 100644 --- a/macos/Sources/Features/Terminal/Window Styles/TerminalWindow.swift +++ b/macos/Sources/Features/Terminal/Window Styles/TerminalWindow.swift @@ -49,6 +49,14 @@ class TerminalWindow: NSWindow { // Setup our initial config derivedConfig = .init(config) + + // If there is a hardcoded title in the configuration, we set that + // immediately. Future `set_title` apprt actions will override this + // if necessary but this ensures our window loads with the proper + // title immediately rather than on another event loop tick (see #5934) + if let title = derivedConfig.title { + self.title = title + } // If window decorations are disabled, remove our title if (!config.windowDecorations) { styleMask.remove(.titled) } @@ -432,17 +440,20 @@ class TerminalWindow: NSWindow { // MARK: Config struct DerivedConfig { + let title: String? let backgroundColor: NSColor let backgroundOpacity: Double let macosWindowButtons: Ghostty.MacOSWindowButtons init() { + self.title = nil self.backgroundColor = NSColor.windowBackgroundColor self.backgroundOpacity = 1 self.macosWindowButtons = .visible } init(_ config: Ghostty.Config) { + self.title = config.title self.backgroundColor = NSColor(config.backgroundColor) self.backgroundOpacity = config.backgroundOpacity self.macosWindowButtons = config.macosWindowButtons From 4fa8b8f285fdc0590ccaa2fad30de9003f714164 Mon Sep 17 00:00:00 2001 From: Mitchell Hashimoto Date: Thu, 18 Sep 2025 13:28:23 -0700 Subject: [PATCH 05/77] macos: opening filepaths should make proper file URLs Fixes #8763 --- macos/Sources/Ghostty/Ghostty.App.swift | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/macos/Sources/Ghostty/Ghostty.App.swift b/macos/Sources/Ghostty/Ghostty.App.swift index 65979bd40..bdc64e9e1 100644 --- a/macos/Sources/Ghostty/Ghostty.App.swift +++ b/macos/Sources/Ghostty/Ghostty.App.swift @@ -624,10 +624,15 @@ extension Ghostty { ) -> Bool { let action = Ghostty.Action.OpenURL(c: v) - // Convert the URL string to a URL object - guard let url = URL(string: action.url) else { - Ghostty.logger.warning("invalid URL for open URL action: \(action.url)") - return false + // If the URL doesn't have a valid scheme we assume its a file path. The URL + // initializer will gladly take invalid URLs (e.g. plain file paths) and turn + // them into schema-less URLs, but these won't open properly in text editors. + // See: https://github.com/ghostty-org/ghostty/issues/8763 + let url: URL + if let candidate = URL(string: action.url), candidate.scheme != nil { + url = candidate + } else { + url = URL(filePath: action.url) } switch action.kind { From 9b40e03c4027522414c1cf3627a99e88977ce768 Mon Sep 17 00:00:00 2001 From: Leah Amelia Chen Date: Thu, 18 Sep 2025 22:42:53 +0200 Subject: [PATCH 06/77] build: explicitly suffix generated Zig source files Previously we're just feeding the compiler source files generated via capturing stdout, which all by default have the filename `stdout`. Under some particular yet uncertain circumstances in Zig 0.14 (only factor we've found so far is a large amount of cores/compilation shards) the compiler will actually crash on an unreachable code path that assumes all source files either end in .zig or .zon, causing crashes for packagers for distros like Nixpkgs and Gentoo. Given this has been explicitly made illegal in Zig 0.15 (see ziglang/zig#24957) I don't really see why we shouldn't fix this for 1.2 too. We have to do this at some point no matter what anyways. --- src/build/HelpStrings.zig | 7 ++++++- src/build/UnicodeTables.zig | 9 +++++++-- 2 files changed, 13 insertions(+), 3 deletions(-) diff --git a/src/build/HelpStrings.zig b/src/build/HelpStrings.zig index 04ae629b7..96505caba 100644 --- a/src/build/HelpStrings.zig +++ b/src/build/HelpStrings.zig @@ -31,9 +31,14 @@ pub fn init(b: *std.Build, cfg: *const Config) !HelpStrings { exe.root_module.addOptions("build_options", options); const help_run = b.addRunArtifact(exe); + + // Generated Zig files have to end with .zig + const wf = b.addWriteFiles(); + const output = wf.addCopyFile(help_run.captureStdOut(), "helpgen.zig"); + return .{ .exe = exe, - .output = help_run.captureStdOut(), + .output = output, }; } diff --git a/src/build/UnicodeTables.zig b/src/build/UnicodeTables.zig index 6bb656a29..7c1229f7f 100644 --- a/src/build/UnicodeTables.zig +++ b/src/build/UnicodeTables.zig @@ -48,11 +48,16 @@ pub fn init(b: *std.Build) !UnicodeTables { const props_run = b.addRunArtifact(props_exe); const symbols_run = b.addRunArtifact(symbols_exe); + // Generated Zig files have to end with .zig + const wf = b.addWriteFiles(); + const props_output = wf.addCopyFile(props_run.captureStdOut(), "props.zig"); + const symbols_output = wf.addCopyFile(symbols_run.captureStdOut(), "symbols.zig"); + return .{ .props_exe = props_exe, .symbols_exe = symbols_exe, - .props_output = props_run.captureStdOut(), - .symbols_output = symbols_run.captureStdOut(), + .props_output = props_output, + .symbols_output = symbols_output, }; } From ad92bf7ab5e1fa0256be28fea51ab0698ab03453 Mon Sep 17 00:00:00 2001 From: Mitchell Hashimoto Date: Thu, 18 Sep 2025 14:02:23 -0700 Subject: [PATCH 07/77] macos: bell-features=title works again This was a regression we didn't fix before 1.2. --- .../Features/Terminal/BaseTerminalController.swift | 13 ++++++++++++- macos/Sources/Ghostty/Ghostty.Config.swift | 1 + macos/Sources/Ghostty/SurfaceView.swift | 9 --------- 3 files changed, 13 insertions(+), 10 deletions(-) diff --git a/macos/Sources/Features/Terminal/BaseTerminalController.swift b/macos/Sources/Features/Terminal/BaseTerminalController.swift index 9c94cfef8..2de967daf 100644 --- a/macos/Sources/Features/Terminal/BaseTerminalController.swift +++ b/macos/Sources/Features/Terminal/BaseTerminalController.swift @@ -688,6 +688,8 @@ class BaseTerminalController: NSWindowController, surfaceTree.contains(titleSurface) { // If we have a surface, we want to listen for title changes. titleSurface.$title + .combineLatest(titleSurface.$bell) + .map { [weak self] in self?.computeTitle(title: $0, bell: $1) ?? "" } .sink { [weak self] in self?.titleDidChange(to: $0) } .store(in: &focusedSurfaceCancellables) } else { @@ -695,8 +697,17 @@ class BaseTerminalController: NSWindowController, titleDidChange(to: "👻") } } + + private func computeTitle(title: String, bell: Bool) -> String { + var result = title + if (bell && ghostty.config.bellFeatures.contains(.title)) { + result = "🔔 \(result)" + } - func titleDidChange(to: String) { + return result + } + + private func titleDidChange(to: String) { guard let window else { return } // Set the main window title diff --git a/macos/Sources/Ghostty/Ghostty.Config.swift b/macos/Sources/Ghostty/Ghostty.Config.swift index b106082bb..05a3be2cd 100644 --- a/macos/Sources/Ghostty/Ghostty.Config.swift +++ b/macos/Sources/Ghostty/Ghostty.Config.swift @@ -625,6 +625,7 @@ extension Ghostty.Config { static let audio = BellFeatures(rawValue: 1 << 1) static let attention = BellFeatures(rawValue: 1 << 2) static let title = BellFeatures(rawValue: 1 << 3) + static let border = BellFeatures(rawValue: 1 << 4) } enum MacDockDropBehavior: String { diff --git a/macos/Sources/Ghostty/SurfaceView.swift b/macos/Sources/Ghostty/SurfaceView.swift index 25a142d65..89f7d6c9e 100644 --- a/macos/Sources/Ghostty/SurfaceView.swift +++ b/macos/Sources/Ghostty/SurfaceView.swift @@ -57,15 +57,6 @@ extension Ghostty { @EnvironmentObject private var ghostty: Ghostty.App - var title: String { - var result = surfaceView.title - if (surfaceView.bell && ghostty.config.bellFeatures.contains(.title)) { - result = "🔔 \(result)" - } - - return result - } - var body: some View { let center = NotificationCenter.default From fe55d90ec597997b80001ee29bd158a72f501a04 Mon Sep 17 00:00:00 2001 From: Mitchell Hashimoto Date: Thu, 18 Sep 2025 14:32:46 -0700 Subject: [PATCH 08/77] macos: implement bell-features=border on macOS --- macos/Sources/Ghostty/SurfaceView.swift | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/macos/Sources/Ghostty/SurfaceView.swift b/macos/Sources/Ghostty/SurfaceView.swift index 89f7d6c9e..aca17c0fc 100644 --- a/macos/Sources/Ghostty/SurfaceView.swift +++ b/macos/Sources/Ghostty/SurfaceView.swift @@ -198,6 +198,11 @@ extension Ghostty { SecureInputOverlay() } #endif + + // Show bell border if enabled + if (ghostty.config.bellFeatures.contains(.border)) { + BellBorderOverlay(bell: surfaceView.bell) + } // If our surface is not healthy, then we render an error view over it. if (!surfaceView.healthy) { @@ -526,6 +531,22 @@ extension Ghostty { } } + /// Visual overlay that shows a border around the edges when the bell rings with border feature enabled. + struct BellBorderOverlay: View { + let bell: Bool + + var body: some View { + Rectangle() + .strokeBorder( + Color(red: 1.0, green: 0.8, blue: 0.0).opacity(0.5), + lineWidth: 3 + ) + .allowsHitTesting(false) + .opacity(bell ? 1.0 : 0.0) + .animation(.easeInOut(duration: 0.3), value: bell) + } + } + #if canImport(AppKit) /// When changing the split state, or going full screen (native or non), the terminal view /// will lose focus. There has to be some nice SwiftUI-native way to fix this but I can't From d6e58ef1fc3b96a241f1eacbbf414991c9ed84b6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D8=B9=D8=A8=D8=AF=20=D8=A7=D9=84=D8=B1=D8=AD=D9=85=D9=86?= =?UTF-8?q?=20=D8=B5=D8=A8=D8=A7=D9=87=D9=8A?= Date: Fri, 19 Sep 2025 00:26:05 +0300 Subject: [PATCH 09/77] slightly improve logs --- src/apprt/action.zig | 31 +++++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) diff --git a/src/apprt/action.zig b/src/apprt/action.zig index fbcc92805..b7dc80e03 100644 --- a/src/apprt/action.zig +++ b/src/apprt/action.zig @@ -569,6 +569,15 @@ pub const SetTitle = struct { .title = self.title.ptr, }; } + + pub fn format( + value: @This(), + comptime _: []const u8, + _: std.fmt.FormatOptions, + writer: anytype, + ) !void { + try writer.print("{s}{{ {s} }}", .{ @typeName(@This()), value.title }); + } }; pub const Pwd = struct { @@ -584,6 +593,15 @@ pub const Pwd = struct { .pwd = self.pwd.ptr, }; } + + pub fn format( + value: @This(), + comptime _: []const u8, + _: std.fmt.FormatOptions, + writer: anytype, + ) !void { + try writer.print("{s}{{ {s} }}", .{ @typeName(@This()), value.pwd }); + } }; /// The desktop notification to show. @@ -603,6 +621,19 @@ pub const DesktopNotification = struct { .body = self.body.ptr, }; } + + pub fn format( + value: @This(), + comptime _: []const u8, + _: std.fmt.FormatOptions, + writer: anytype, + ) !void { + try writer.print("{s}{{ title: {s}, body: {s} }}", .{ + @typeName(@This()), + value.title, + value.body, + }); + } }; pub const KeySequence = union(enum) { From 6d2576abeeecc7187ced8365ac865ed333fb876f Mon Sep 17 00:00:00 2001 From: Leah Amelia Chen Date: Fri, 19 Sep 2025 00:35:09 +0200 Subject: [PATCH 10/77] build: explicitly suffix Zig files 2: Electric Boogaloo Of *course* I missed one --- src/build/GhosttyFrameData.zig | 7 +++++-- src/build/framegen/main.zig | 16 +++++++++------- 2 files changed, 14 insertions(+), 9 deletions(-) diff --git a/src/build/GhosttyFrameData.zig b/src/build/GhosttyFrameData.zig index 3dc638a05..1644388bc 100644 --- a/src/build/GhosttyFrameData.zig +++ b/src/build/GhosttyFrameData.zig @@ -25,11 +25,14 @@ pub fn init(b: *std.Build) !GhosttyFrameData { }); const run = b.addRunArtifact(exe); + // Both the compressed framedata and the Zig source file + // have to be put in the same directory, since the compressed file + // has to be within the source file's include path. + const dir = run.addOutputDirectoryArg("framedata"); - _ = run.addOutputFileArg("framedata.compressed"); return .{ .exe = exe, - .output = run.captureStdOut(), + .output = dir.path(b, "framedata.zig"), }; } diff --git a/src/build/framegen/main.zig b/src/build/framegen/main.zig index 1be33eb11..f4a7d9443 100644 --- a/src/build/framegen/main.zig +++ b/src/build/framegen/main.zig @@ -9,12 +9,12 @@ pub fn main() !void { // Skip the exe name _ = arg_iter.skip(); - const output_path = arg_iter.next() orelse return error.MissingOutputPath; + const out_dir_path = arg_iter.next() orelse return error.MissingOutputPath; + const compressed_out = "framedata.compressed"; + const zig_out = "framedata.zig"; - const out_dir_path = fs.path.dirname(output_path) orelse return error.InvalidOutputPath; const out_dir = try fs.cwd().openDir(out_dir_path, .{}); - - const compressed_file = try out_dir.createFile(fs.path.basename(output_path), .{}); + const compressed_file = try out_dir.createFile(compressed_out, .{}); // Join the frames with a null byte. We'll split on this later const all_frames = try std.mem.join(gpa.allocator(), "\x01", &frames); @@ -23,13 +23,15 @@ pub fn main() !void { const reader = fbs.reader(); try std.compress.flate.compress(reader, compressed_file.writer(), .{}); - const stdout = std.io.getStdOut().writer(); + const compressed_path = try std.fs.path.join(gpa.allocator(), &.{ out_dir_path, compressed_out }); - try stdout.print( + const zig_file = try out_dir.createFile(zig_out, .{}); + + try zig_file.writer().print( \\//! This file is auto-generated. Do not edit. \\ \\pub const compressed = @embedFile("{s}"); - , .{output_path}); + , .{compressed_path}); } const frames = [_][]const u8{ From 6d40da1e1c76fbb59e15e32db3bae801c9de75f7 Mon Sep 17 00:00:00 2001 From: maximal Date: Fri, 19 Sep 2025 12:55:19 +0300 Subject: [PATCH 11/77] =?UTF-8?q?Optimize=20PNG=20images=20losslessly:=207?= =?UTF-8?q?3=20=E2=86=92=2051=20KiB=20(=E2=88=9230%)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../testdata/U+1CC00...U+1CCFF-11x21+2.png | Bin 1032 -> 838 bytes .../testdata/U+1CC00...U+1CCFF-12x24+3.png | Bin 1295 -> 1024 bytes .../testdata/U+1CC00...U+1CCFF-18x36+4.png | Bin 2193 -> 1687 bytes .../testdata/U+1CC00...U+1CCFF-9x17+1.png | Bin 794 -> 643 bytes .../testdata/U+1CD00...U+1CDFF-11x21+2.png | Bin 1280 -> 599 bytes .../testdata/U+1CD00...U+1CDFF-12x24+3.png | Bin 1870 -> 553 bytes .../testdata/U+1CD00...U+1CDFF-18x36+4.png | Bin 3411 -> 684 bytes .../testdata/U+1CD00...U+1CDFF-9x17+1.png | Bin 1103 -> 563 bytes .../testdata/U+1CE00...U+1CEFF-11x21+2.png | Bin 1006 -> 727 bytes .../testdata/U+1CE00...U+1CEFF-12x24+3.png | Bin 1255 -> 755 bytes .../testdata/U+1CE00...U+1CEFF-18x36+4.png | Bin 2247 -> 1096 bytes .../testdata/U+1CE00...U+1CEFF-9x17+1.png | Bin 751 -> 602 bytes .../testdata/U+1FB00...U+1FBFF-11x21+2.png | Bin 5427 -> 4884 bytes .../testdata/U+1FB00...U+1FBFF-12x24+3.png | Bin 5724 -> 5045 bytes .../testdata/U+1FB00...U+1FBFF-18x36+4.png | Bin 9975 -> 8354 bytes .../testdata/U+1FB00...U+1FBFF-9x17+1.png | Bin 4341 -> 3950 bytes .../testdata/U+2500...U+25FF-11x21+2.png | Bin 2225 -> 1911 bytes .../testdata/U+2500...U+25FF-12x24+3.png | Bin 2635 -> 2104 bytes .../testdata/U+2500...U+25FF-18x36+4.png | Bin 4570 -> 3125 bytes .../testdata/U+2500...U+25FF-9x17+1.png | Bin 1853 -> 1549 bytes .../testdata/U+2800...U+28FF-11x21+2.png | Bin 1022 -> 285 bytes .../testdata/U+2800...U+28FF-12x24+3.png | Bin 1541 -> 296 bytes .../testdata/U+2800...U+28FF-18x36+4.png | Bin 2501 -> 399 bytes .../testdata/U+2800...U+28FF-9x17+1.png | Bin 917 -> 275 bytes .../testdata/U+E000...U+E0FF-11x21+2.png | Bin 1102 -> 956 bytes .../testdata/U+E000...U+E0FF-12x24+3.png | Bin 1255 -> 1054 bytes .../testdata/U+E000...U+E0FF-18x36+4.png | Bin 2217 -> 1506 bytes .../testdata/U+E000...U+E0FF-9x17+1.png | Bin 894 -> 782 bytes .../testdata/U+F500...U+F5FF-11x21+2.png | Bin 1114 -> 966 bytes .../testdata/U+F500...U+F5FF-12x24+3.png | Bin 1421 -> 1182 bytes .../testdata/U+F500...U+F5FF-18x36+4.png | Bin 2473 -> 1785 bytes .../testdata/U+F500...U+F5FF-9x17+1.png | Bin 872 -> 752 bytes .../testdata/U+F600...U+F6FF-11x21+2.png | Bin 495 -> 324 bytes .../testdata/U+F600...U+F6FF-12x24+3.png | Bin 637 -> 376 bytes .../testdata/U+F600...U+F6FF-18x36+4.png | Bin 1210 -> 511 bytes .../testdata/U+F600...U+F6FF-9x17+1.png | Bin 393 -> 278 bytes test/cases/vttest/1_1.sh.alacritty.png | Bin 10542 -> 9884 bytes test/cases/vttest/1_1.sh.ghostty.png | Bin 10462 -> 10027 bytes test/cases/vttest/1_1.sh.xterm.png | Bin 4454 -> 4422 bytes test/cases/vttest/1_2.sh.alacritty.png | Bin 10152 -> 9416 bytes test/cases/vttest/1_2.sh.ghostty.png | Bin 10703 -> 10308 bytes test/cases/vttest/1_2.sh.xterm.png | Bin 4445 -> 4388 bytes test/cases/vttest/1_3.sh.alacritty.png | Bin 10570 -> 9433 bytes test/cases/vttest/1_3.sh.ghostty.png | Bin 18143 -> 16727 bytes test/cases/vttest/1_3.sh.xterm.png | Bin 3720 -> 3638 bytes test/cases/vttest/1_4.sh.alacritty.png | Bin 10409 -> 9310 bytes test/cases/vttest/1_4.sh.ghostty.png | Bin 18156 -> 16729 bytes test/cases/vttest/1_4.sh.xterm.png | Bin 3766 -> 3634 bytes test/cases/vttest/1_5.sh.alacritty.png | Bin 8237 -> 7265 bytes test/cases/vttest/1_5.sh.ghostty.png | Bin 8119 -> 7281 bytes test/cases/vttest/1_5.sh.xterm.png | Bin 3149 -> 3131 bytes test/cases/vttest/1_6.sh.alacritty.png | Bin 8573 -> 7532 bytes test/cases/vttest/1_6.sh.ghostty.png | Bin 8486 -> 7585 bytes test/cases/vttest/1_6.sh.xterm.png | Bin 3071 -> 3061 bytes test/cases/vttest/launch.sh.alacritty.png | Bin 16776 -> 15506 bytes test/cases/vttest/launch.sh.ghostty.png | Bin 39346 -> 36090 bytes test/cases/vttest/launch.sh.xterm.png | Bin 5439 -> 5389 bytes test/cases/wraptest.sh.alacritty.png | Bin 15314 -> 14544 bytes test/cases/wraptest.sh.ghostty.png | Bin 56376 -> 50414 bytes test/cases/wraptest.sh.xterm.png | Bin 5342 -> 5263 bytes 60 files changed, 0 insertions(+), 0 deletions(-) diff --git a/src/font/sprite/testdata/U+1CC00...U+1CCFF-11x21+2.png b/src/font/sprite/testdata/U+1CC00...U+1CCFF-11x21+2.png index e04e7726b965fab41da5ed0c4f7e3501709db29f..0cd577291b15f6c604c0aef7f6990c57ffe974be 100644 GIT binary patch literal 838 zcmeAS@N?(olHy`uVBq!ia0vp^9~c-IKX3pU40}EI{$gNY=Jj-O45_&F_V(MUvm8X& z608@ncx_prpm4nS4Pki(h9AneFMoOR;A{WV z*jM{2)&f<7wEXvNJZSf2>-35KC)%DakK+Oxqw}GhlZSyp{)SxJ=db&@&mB(u{p3jP ztMucq9>1)5`!eGEy*HQt?K^z-+ZFHKUmu;e>YeXxvaIUo*}DdR%exY{SG@ZD{{Pb2 zJ=V*Zj<@W-Px}Dl@TmSHp&8+oIle=$iUHl{D)q~HUoJ@O5=4}bu|FhuP z&GUX)i>|xX6|dN;v{z(hpGRohG3OK+w`27w_c+g1ESza(aJW5e+KE|WQQpki6&ddZ zZfeDxD-@g8SX=C+|1DBg4 z9$cS4?Z~`KEc5t}GVT9oqw`IM50c`jP9{v1ca3@<;qNi831qgXtDnm{r-UW|uXTo( literal 1032 zcmeAS@N?(olHy`uVBq!ia0vp^9~c-IKX3pU40}EI{$gNYKJV$`7*a9k%?)k7!v+#9 zj`#mx($rqD+qG`RYRPG#2mUYgkYola2LZ9_dFvnFZk_y1Nanau)8h!I0vT_PzQ^^y ze_ZnG-~K-OUHOMEpMEm?3nEJ=bJ{z&RT?lHu+s+`@&Esu+1YEC8VDROY+zAQVC3|0 zU=q@L2quA?6)iV))_bQfOV3pQ-FWA}{?3z)+YH|OdFuUpvqJVoY4QJwuY&IH_%_wa z`C-r2^&(PS>1%42UI?&AeyiPTrpa?4zfINc+R~?-I=Y+nd>s-s=Iq;I!^q{FsKL|9 z2=>Ac`7Mj%w_lqaX1^_7jnAaJ`fU2m>w5Fuc+Q!;v5&}}{i;OxvJ}_pXNtzApE-roh?Kq)jGwTufxy zUj6%*c6fSr4_E)Alkqb%e0aAuHg$hl9lKz`@vS{N?hn&`*>T9vS4)~z5p;NkvV3g( zYAG&Fb&V@8JLH%u4X;&jDV1pJwn}$7uT}rI%$Rcq$9a)`k~dDLco`e)mOT_YoAYYG z%(Ba$_WUehuln^t@=fTw83#>5x*Sz?t1j37m^8J?wYqAzr2bT?%gYS8R zm5Hk!nP#8!cS`9zx@zWADWyQqta(Qh=O3=QereU-f~6YE-gUn^uJ>*W)AisVn~dk1 z6gGU4TJ=t}#@!<3baKSn#Wms`Vmp^d?#bYbyDWWmu3?eO`9}e3ZEPZ*-%XpgRct2z zsWqt|C#hQTbuB7dZXmBynQ`*}AjhFmeJJ4GaFSm!8ywYL$Ty yx{}|5T%gR000%sP?EnAY9)_E8TTnv-As@r)8udQHB9&<_NX*mK&t;ucLK6U`;HXRh diff --git a/src/font/sprite/testdata/U+1CC00...U+1CCFF-12x24+3.png b/src/font/sprite/testdata/U+1CC00...U+1CCFF-12x24+3.png index ce1b1c422e0f413a6084e0ed9ede00def5a9eff9..d2c272e60af59be94bdeb00acf22e75888335383 100644 GIT binary patch literal 1024 zcmeAS@N?(olHy`uVBq!ia0y~yU{qjWU~=GK00NFLPi8YPFdz4HaSW-r_4ZC+;VTCb zwg*-nEGi0&oE{x5UJgt`N{pNn8(M&zV)?3t6Ylc1R$E=Z_j8}Rno8pz%iXhM(<-W& zL54xWzih#cpRP@9U{P7{p2I^NY!J|t3+vCMe(VXptE9mA*V#d8Zk#7jZ~{;j(4rTw z86#UnCo}*}c#u5lcgFAIufJw~_+KRlbOS;aN8Kl$cUyHM)3v2fXGcR^2$L-~1nRBZ z`L=M*v;OIyP2{%o^WSjwxhl+i`RRX?WecljX(p8$&(%}^rmfAP9sR81takXm&KdIW zuK1s}=bHJ8y(W7Df z=G^Jeb56JX>i8(l^h){MdX|!Pu_rc(DLqT9&*i`U*TDVGo#(TnT+5$#Sj0Bpox6(j z?zNK2v(G!+e&3tMc}MQvQSaOwVZpnv&y*o7k5nz3b<;)YG=d9_4)zEL@Yi zJD1Jm-j@K^_2%oYUdhf~bNA4$*O|#{TyFFh+HUz&7H|39tSjs7;vj+L=kK0#l{wF{ zW%ufp`wVl|%$}v2v*TXN!q}+t-Fmm4F1)1M8-KH`I7jmMg*DCJAI-k!e(mhpoN)HX zJF{!U*86tO^^sy`ifrGgQBS zf7HJ9-AkcI>w;$9-t?#~OO`KnQn2y!eU(#}FEV`dp81x|eP46_m&?2z9>0pH0sGnY3ety~oHL1JT)K2B^O^UB6NIhYD&F#ytZ|CPNzqBCgaKuyPZa4F7 zT#Np0v9|kuEZl!eX=0>f`rRK}g3e?~Mf#eqe(mx4%q6SqOU~KlemE(`ce(BPlH;vg zj!$31zG@5mo+a$(wy-}~u)PEqr%x~%pv@-$QCX%WxUYMG}k zBDuXQxnnK4^DDU7SY_ lU%s4=gyw+(pgt`A%lN+J(c#Q(EOH?0Jzf1=);T3K0RUQcsgD2v literal 1295 zcmeAS@N?(olHy`uVBq!ia0y~yU{qjWU~=GK00NFLPi8YPuw3(WaSW-L^X8f%7mK2R zOW^zZm-lieXRhgtlDx+)y70%uY(|i3D3~7>I(zm0n}Ozn8Uh+O*k|1>Qf*{{!>aT4 ze$_=Kj{})l^O?4;XEXQv0o45e|C<|*ZOn-ht{4Bl-^FgrsapA`D`sVJMilS7^HX`W z)a#jeQDI$+EQ=Hi69dBo&U<_B?6dp-|NrOg59{AO;al~V5IztdV?Qn3|6SDXy2x|$ z?zk;*M1=|r3>B;Ff!+Z+Yi9JsEd~Ou*BOP}n1m)Yu&DH~s3<6cSuRd0bN0_@EOq1`WNf7vNb)7PA=5x0#^`iW%YpqY? z=D$9w^K0>WiPl`VRTnNUdpav!;o<$QArEfsJ)|sO&8U!8cR=^km+5Aq`#oH0UKm8b z+{vt$znIyeBQ5c|1DA=c(v_Ld5-QjHHkS9Uju34>>Y}nn?Z~<(h3?1JuK!gdD#T{^ z?rfUkaeXFJ_1Uk4GL`%Nt8Qe;WjYsr{5yfo_TvH1eMwdCFNB|ZIH~M|n6a&QSnHB) znNkV`{ME+;X7QNT@@y|UC43<+@2U>Ro(|5fzjrNh@cDUVa<}i!-!&={!QU<(IhxMY z+pW}P{`l!G*}u9)+wavnzB*I${j|oMg|^&Ze%bn{?+&RG_OLiG@vGv4^=TfP3K#rr zcm2HAcx#u-wrL+<-KswIOtei|@WEk$<#T-tUmsQ|3e;szn%yxm&gyYq-I0YsncFA5 ze{yU0&#NtB%!?AUD+}h9wuSvM@Z8CK`o*7ra+MvA4Lb<+4A3gcJ*~u!z`@GlfR*#q8Qh%?##5?sC zn}6ovoxwX8{{`Qgv|3hhN}ta0&YJ(WHco#vWnW$4o9Welk2$sdgZCLQKAhSnph7>$cGJifsBR)|JJU3$S4iWI7ncFIFJKO>cEwf-7P#XfwV|ZWk=x}P)dXO~?p00i_>zopr0DEp4B>(^b diff --git a/src/font/sprite/testdata/U+1CC00...U+1CCFF-18x36+4.png b/src/font/sprite/testdata/U+1CC00...U+1CCFF-18x36+4.png index 1c21f688a5037887283040e11b02b9024be5702d..167c1fb831bd9d8337e021927e1e09480a9c4dc0 100644 GIT binary patch literal 1687 zcmeHH`#Tc~7~b46;lU|#$zeH>B~*`6EXOk<$4D-@%m|@EX?EoP5UrHalgo&aYsuY= zi6xbTv6+MHeq1&bV$BX`I}X*4{R!uL-skzg@BQI>-|ze3yYCJ^ucD-*1ONb3oSk4E z006KY0FVt*+#vvNrn3hC0EIwj*sq@PjAeGzoyrRb6nJOsWHi8r8ekwOPYslpCT9e* zH!=W%RySMN1t%#M?V%f=0>#oMSD8f{;X8|f6`KJH;LBvdei#&6D`Zi?K2@-M~eO+}*{DG&MCDjUD8s$=&@5qjIvX0dq-yr<40G zv)!8h58o|j^Y3?AB`c%C9-+x;pfxs4u8Jo&XQKqS8$DzIJo1g&@otSx|0!1}IcdP# zKEy_gldC5|y5VJS5O0>3G~#@~FUET-zttBaZQol+Ab=CpuIFS~b3 zBJDq|DzMuA_cn~hCp&Rz-1S`aG(>HpJT08$zuA_y|NZDfxPoZQ{EQqiK< z&1G{uIT-J)sp~M(=*}l z)nsnm@btJ>XEvs&Ovc7dT^-T!#tjLl_Z}|au+E9(LZh$qq(gQ>sLlS4L94ThdSGx( zrbP8p3Quxe=rr(oHcc~dx(mxhcZ&ZKv|7Dg-3bkAT!dVjd&kLIC^<)27smgCw_!QkVBiu=Eb<5Nw> zP=|wn4OSO#YI+<<&%#m6nCoI@aF8AO2H|(h_s7_tQ1HRzB|I+mz&lJFbOq zLX4sk2vrc=FD$yqWXu80?R3apI7CX1-jrW!U5DJINayDa4c`U_azb`doMsrlayyCJn@!R6UQ#l% zdY?c9F0m%#N70&djl@W3xQBVqn&+ycU#V^e_2)8TyKM|AC1tIULu&XPLK5;LleqVz# PyVr1bfWsQ?gVO&4wG6wb literal 2193 zcmeAS@N?(olHy`uVBq!ia0y~yU|hh!z?{GV6kzbzdMv@fz!Bl;;uumf=gk2_MxfxK z1z-JhIsG+23Xs4KNg(I{|2G#ExehS!upIoq-|Fg8HLaXPwns{Q*FYK}V85yH=HFGj zZ?rkoG9Bd<+0I|Gv5mj+5lfe_hTj4U7-Pq42Y#S>pm{eAayA$UFdY21dmB@;;8D|= zjeD4mAN+T2wo1Sp2g~Q}=RclL=YH?DV25?%vCDCB73NI3P6%`020|I{sutX2*6tSo z+XZpZk49#&MK=w(4mmKeUi^Lk);TvNsYB_K_ZoVoCG4Cpt&wji{_*hMpT`rw%h$*3 z`h4f}6Sk{1I~`5^^8(IJmJT7F%ltrL-Tk}i{$Yn+_g~tqZpl=4AZiQXXcORQgpfdP z0>`e-*;~qzY)|K!%bQmjn{U1w)#dMhY4Y5w^<1q^3j;Jn(5XlD4U)^B{#`UDW2XD% zcd2TN81;AZPX7Lz{r&QXZP)o-OqTC|5dXqE{_APmHT?5c^q$UmrD%0{$Atf?hd&1w ztd&_CX7Iqgysq!C*zpCio&o=V+rN*n{g$hirnX4PG5eiaU`oe{#jM-raERTkQ1U7- zRCWCLu)Nb>^W9c~xfgt0Y#d#J)xVpr`^vDd{7!L}Tk@xw{O^^#&u!J2_9}?C{dvPG^5V07U+o0;e!l!uWZT4d!i~;8Ec;G>ZI@sTd%jQYMcJ~&rVB*32))yC z+I({I1~vbxd5T&$6C*}VK=b`#hAKRb?Z-Ff>-x=Z#kHpNXf?{6Fmf0Ulg zA${x5<5HHRzj7xe_V9h5QG4~@VIkFppW=-IRpJ(PeX~;9rkj!SV)x|ed2Q~xx9|Ns z6}#JIZu{Tuf?+0y_llUi?VBZgcT$;NNzUxR{oh`kF<;nw|MP~AEC*R8>Szmod62%Z zOh?F7{<7lsbLWp;IL+pAp!t_~PQ zOt*Vyf9gl2(U)xx)1^$5E9Tr))>?QcKbleGLPXQ$_s3Y&Pb`S`Xp+s!+1DFqwr3*a z*@WC+mQ4$lFUU>TS!Cll_l;KLeXomKHQu@kh(4aPP5a~Afce{8^*nV?^k+#edNOO% zGPWsg_DZS@?TwpWKMhxX!ct_mWOufNUz~TRIJdygbyco6nuSiw-v24n7<}sZw{PyM zC5PERJ)iaA?cblX&iYKA{o^_JI*x-|Q{rYhWV#fa*{2r2dQurv}op)XPWyf~^B@g8x z<;iW|Rfi3DTp#{@|EsY#{#DBjy%%y;7V;uiFZnA3ym#%2>vlh^`g_A+xqBBfzIF}lY+Mr?o&@DSnB2LcX=02@(w?82r%udNW8rJN zHF3f}x2KmFH@khTb4c%P(ci}yS$uO<^zB5ki3gaS#E$Y!(cP!Gy5*QN_rnMqbX?yDo0VG`;Zfd zl13h&+5-ypua#pKY-2&PhJhgtY6>GKkO6ed`ga{os7|?xs^b58=}D+64mhE!_$|l< zs?HFA9qJvZE&tcw7SuqkzI1@jLh%hom>h5fnunsq_aQr~hYu*CD|!2X7fp#ER0%vx zxMdcihDn1kR0-U*=sx}+g02GH#|MJZRbcqoA3cgOd=?Bt{f;LTV2`oVLz5Verr$vhK@2YZt+3aVUmJ?^k*}1z!7GxHK z!{xo%oPb!kJ5%5rGWZATV>41E(*Y}@4>t#OM&MlMDJ^ak2>Z|8${_zig*ZiT~H9>v~VkzZSMD)neLnQ-N*EufP6wr8KwZ>DnAK-{0N%-iJl zJv~q_C)ya4tl+y+@HGb56PE`mFqgr%+WA>%5+Y>IF|C z<)ea`vcofad)6FV7;3*^H^zopr0IrG-RR910 literal 794 zcmeAS@N?(olHy`uVBq!ia0vp^7Z?~ACvX5648I<1EMQ<@dg$rm7*a9k&Gn0H%!UGO z7i<4d&(qx5;oF(1TK~qNl@5&M)9sQPZXA+N_St-u<@v z86f$lPG&N{YExHp(<&BG_UWvQ8;(dbF#P}jW_o?@Q3ZkH&ld7L_-?o89)%zygZbK2g;*NgTyFxUTYJR0}Vu4Mn=)aiXeF|!$??`=HW zZ2Ii~6PfAj|2GxPTbx#I+W+KD^4qLfD;L$tEB5@@@H9U9gRj7(m$SSlnq0f^b%Ej* zMLqcs%ck{;i@tR|qPnC10n^tPo9^6ENvTtG)Oxi>#A=FDM*HP^d~ZE}Jn_6b=e2kI zZ%>^)ANBv8oxXnQqB@Ipnhzs1@1`9uWBrq+yidNIr^;36gX*Q_^Y$0z*34Ub?$>Q= zW!1@>RSvu5Jyv~MJ)v&;I>!5Z(mdD5r#`x%sN-w&%~PCzFN^<@^sR0;vz0Rse)_bu zb-wDO38GvluO|MqFqxt>Z^7a6ko!Nhg0|eL?0 z6V)2VbH5|w+@@{MWP5XGp47-#wD#ny&nc^_Hu+92T@}ect2BJs?8y6-|4zgO4)Sz##dLuOT=3)>bYIkU-`?(_5XDr`)lc0R#BnP*Sxq8 z-Im8R%ewuYmO*`c63^YM;B;Oz<5U} z`7Ou=O0Y=4oe@pRZ9xqUBzYi{hZUsc?O{V+Ag5u$zqPp!S*5`??Pds{x?QB{@}Jcp N9iFa!F6*2UngF{jQ%e8< diff --git a/src/font/sprite/testdata/U+1CD00...U+1CDFF-11x21+2.png b/src/font/sprite/testdata/U+1CD00...U+1CDFF-11x21+2.png index 8d7de36aceef89fbd945cf8a56477f1936953b56..4f4e8c1a5ca0b3da8e81a1f7807552c321e0071a 100644 GIT binary patch delta 586 zcmV-Q0=4~s3fBaX7=Hl+0001@>~LiO000J1OjJbx00960|E1ZV-2ear3`s;mRA}Dq zn?Y`bFbqW z#Z&Bgm$=*Y@dyJSJZ50zXF#sug+&<~*oLO|+t?bWNTtMqOVDP}ZD1*JV2e{Y`pyY) zpd~G*ci5CzbbsE!ab1eaQc|pZDAw*(gX&HmxLJ3nDv{=b&1))B32?OLghjuR!f9`t z1?h0qInura^@S!WM(bz^%jI<{W{I&FIL{2cZz4*}*1)K;+}5FNu^2cz10QyRX)$X3 zZd$$U@zG0@4D;O_h%y@^MYEgqWQPXF0eGJ@w@ZTN9e)uP{ha>+9);Yo1Vq+W4)lmnYFF+VH@&MX7J{4ACdyQd890qf92YpS8a$wKoK#*?1Q zG2?fOD6@kc!R%%^lF+)_#>W|1;O@8`qj=yS+HaItBnG||D;$dJ>8E5J3df_I%di+Y ze*<^@Ttk*dho!E^dnStiq2PLq9ji~&z)Y|hILA4#nhH;L7?v7|9p-yh^1fIk5{dpn Y-)_+Q4@0M9m;e9(07*qoM6N<$g4gpC2LJ#7 literal 1280 zcmXYwe>Br;9LK**n;%~$p;>t7gove3w{1XiBA9v8fx@{7eToviq#=^Uw1CCI!fi#g|%H*pmZJBe~jpg6^B`2PWQZ>aj5a zv87VY05RyTCs=oE9eFceYy?5_Ju^cL_QL)nAG*H%)t;P)_^9~(?K|G`d$JeRq{JJV zc|}kp6DN{Sf@fM<0F;5}XzwRzQAhxX>cgSSQUYL9z5 z{s!uN=KHLLN|_tp5{9>{j|ObbFYVp@SDnN^M`VP-VAeZGx)jH}EeM1qGdiuxmG9*`$PJbF^!uN-Pi|>VEB-|<9Co6yLtpgQJLbj-^abZ zcek!JZjha|P6Rnjcb5v44K@B81b6r>eT99lI8{o5Lm%t)8SOtjFm*Mj zB9Df5;`-A4@d3Lg9Eus&9*S#|cSVN_Ot4sN6!GM_8GS-vKNjy0(QIl)VC^rj4Aksg zfWSvS$BkCyD|@e!G_D_)zCB(mMT5we@N1|A-{5hQ#*6lHH=SAwD&uPWsVj{${FTU= zEyj|Y_LN!D?6@-CkmRi6=$v1X!#yHrkHAmv_rl|Cq!{hMh3hF-_1>)8 zt*jS~9se#Q;f#P}$C0=madLBqlT=oxWCN!tO(e;g_iH11n`Oo4K-*E~h6R4CLBeU1 z$ST)#w%8}JEk`_3kn>LkxCW0)>+d$|`D{qZqfu-zKX9F8>%!LTr)#bMq>$Hst`U=2E2@|;tm)u~RZ=0ijR zAz*t!$Rm;IVl~kxg=qx*Fk*Fh<$fhn0N@_KxV#5hRY`|f51hfa++gjgjE@s}pS*Oe z=66p(Y;<%vYc*W1d|Iu|vjF;+p%=x2ni_m(UVowT!LrpicAUchNw?W>DPKqfCTY49ovYz&YM#Nf92nOmuu633=sO9DY|$D)oUI1+%f zF~*=095SW}DPlT$I|z6H16BXVe66!%T*!wo7?D9r?bR`FNq^aBZl=T7-Porfs%UH Rf^4B-N81?{etieM_&+EnOmP4J diff --git a/src/font/sprite/testdata/U+1CD00...U+1CDFF-12x24+3.png b/src/font/sprite/testdata/U+1CD00...U+1CDFF-12x24+3.png index ab6bec96d48174c49b4822c5bfe87c766207399a..b07853d5d0e53c0e04807029eaf0f40d345469c3 100644 GIT binary patch delta 540 zcmV+%0^|M84ygo?7=Hl+0000NQ7Hrf000J1OjJbx00960|E1ZV-2eaq-bqA3RCwC$ zoXwJhAP|JvlaG-%MfOd7jGST+bp-hdx6qUBN~I|Ia!74xdj?!%wCnM|F89>?~gQG-ovs87xsLS-4AC>G!EHrs_XHuhjX2C74-p7f4W+4^VhwuO%07+BOe$7?aGDv<&o{Z^7@4A>CU9EvAxq%rh@018yo|Iux=X^Zd{$T zQp7$wPA_W) zAIN)E6FuwmId-D*X7?jT6$2-CGh_L~-X`&~infC3$+DCxrrZLBJ$WmmpI^P*>~*vc_ND0K&78M2`wDa)YN6mgXLNJm@Gofy8IN~Eg19|e|DjRWa z+cwdDw-CuHj2QL0nyPM+lnwMojOi-owt7>f;~N)>lWXD^R3%l%V}huDu!*f(b=1)l zG5;HIdM@lNdD_pT$J(@VtS&*`t4vvAn+s*9a&qo0u_ec;Lb*@h&asr+rC&Z;tVqp* zP=w~Yc!r`2Qh6K}ug!%}VKErf$rp zBb$Z9{V+??^mQ!_jqQabj)Djx#R84B)%3O2c7MooZapEyC6NclN#`twxh`w1Uz>R{ zE!0`;zF5Do^tb00H=%=@a88PcIg-7GLqCKMI`2C4!-kbQJ-k+hWN)AfZa@ZiA+I;& zRgU0wHkqefD%%*1cHrPG)710y0m@Iw#dI%pHqnKx81L{J`nxIG@+Q<`ivV9Xw?^JP zv+#6bapA?~O+R{H`aeG{+oH+~Q_0G%6n^nJERo=FGz($e4Aka1bC0p3x=;b&dNCaK zA7K1|c6C(jahI&aR%fR?C@$oBPf>-fQ?fXz3csVCVn&LE6vW%p ztJ7hriV(^wExiz}Id$h_UozK{z{Qwoef)>H(eFC}*)A|1DGs{C@uE4+&n$}fG=`<( zttUrUOYv7)4wk^L#t!w%Vz1U-?5CMq;qApH!CLF;$+^4Il{Ymm+C<7^lY3^$yQ!-DXL)+Vw_{6XJELUoAQcB4% zWxVOMTl9yweb2;&JRJv>6YqQA%J7~aTf&bxJiKu|5IgtCp83VU;f8-nula(Y6*Y1> z%R__s)epWgtDRG4#ONR8Ta~PSJKe~R zuQs@!F5sgzk7&Zyo6vP19L>Q=5vL?rv8Eq|3FVxpJTMFY4RYt(wkLwM^NESJQD#x5_5Cx-L8WTS$aMiXr z7IWG`Bjd%evvzKHis%#1qN1cxe&zSBDvR}0=DK&6uu1!MP3k~c`M1wfD?vssl<5l} zlX%Xn#v-RkG0tBaUOIc_#8BV}H@0#X=AiXt2D{X+W`3WZaz6a>w@5sN%%lq-I31EK zG^nBq0_l<{U%DjEocVhhDIsyn^_3s;xqLS%&H0TcG>UR#Gv4mcAk`dFc}5SO^z0 zYj1W4!OX0?nl*!&SvZ>=`!)=RyP2IXUFeZSr1oZq`}2`C!++RA7y32~?iCn+)?E!r zM0(5gyQy!aN+bXP_yR7IWj2r`q(|_w(`5|O;hDnR3lI&|ND`83`A75ad;>{C0sw%b zXm7q|nbSZLk){#&QKlSIn0o=-5N^jFNltQE%k>a9kW?f904P2!pT|jkGfOp)M5NT% z?4}f61+RHo3x7#MN@cC>zdMqIlp;}`-d?_eq#*%7@o71{TPnMXGtWk;!(m4$z5s73;S_Xj9((?YZ7Jrarq|~H-yd6IpsFC!fogc?Y zrArjq>y-dN6i!>KSlXY$kTfJpbv2hCGlQ2;VMrPh04Ua$-H~I>FzpeG*3Fu~^#Vyi znwW;;6IPFkElwsi#tl8BVUM;nZgzAt4)?8QoUBmoHkNXtm1Wu(8B)|bG3 zbTS!I0TRiQvjf5m90RR9102u)MKYjrM&;DG|c37JL00005n zlJ<5s&H#Xb008AB4j%x!wO+4>&lT)#XnR64KJa&4jAr1_PBT>_V@})2>x5CVC;YGa z{Zw1{TBHs1VZO`<&h<}U=4N`{?+5moN2;uq*ibF8#}_8h)0UcxYuirm7=abtt!2sY?HyuB2O zWucJ2ZsLVsRT{gQDpzD#Mpc>jSwk%T#|7xcJp(^(Y3V~ZO#(^5+wkYJ-K6kHoy(6S zdQp3|J32Z-7M9S~F*t)=0>c7E^qaw8{h>p^BP;BbYn#j}A z%dS{{V5rE>Fpz675E>q}wB&y}>f7nF6eVxj&|B;PjlEwG)z(+em{eJihW47A#FW16 zQ0ho=ImK|NzoZ@g`XIR;GdQo&vqk656@9&A4IC?qy`H%c!(OY0M=Dj2xIt*)%xT)1(dsG<=X7(nlQLbfn5S6-#!f%r`uApbFvyx-Ey1Ph6iyp3osM z%DiXdgVUmlWlKCWn!ziDR~H8kh%KY&yBmgD@kb4|UJqx(7e1n+5rWHJxbd1STuXp( zOXRX10GQ`aP$n8v>kEg}j=M+FryppPVTqNF(8N(>>~R7)BAwd*0+e{A&iGt5N{!8l zPF@liX_RaidiDFhhhs)2Ke&*J#CAM%g(L9YflXX0@?eHTWt-IU*9Ek=S_a;hzj(Ji zT+1#FwCIt@GSFVEePn$K^W#m6Xll-XnRibf{BTOA;M3G}>hE)5bItyX=8K0*BeR6X zZkD^x>@UpzrRsKPYrCiG`=JrtRWt|Y=0EnCNm&Ffn)!J?>TmqPNLXo6GCX9xwBpqy zz9h;CS3C2nT=D)xIebOd7u%iOL=vbn+`k1D&o_W7je(N1bI-+Scn*GAnWj-vnz$7e zD5WqeP*N&6+XULGsX6+cVm(z*ClHgkhM6zH4 z&InCl;#nvDz8NeaS$Th1fh(X%)G}}&Pn3-et-J_TgG$Vuk9Byz{gx{R3&K^FM@~+E zd~;I8ZzlH*RF=UHsfEKhXEY|dJ81h0EF9knWrVf<&GJVzzUfFY=%yRzYx~{L3}m>s zG*w)U9;UzTPH4&#p2{p4e{)O2I{0Y6iQ)KtS5WK8EM`m5K-DX?62gi zzaz>$#FlUtlPy)Jl%-y-`nX8ahJuToc{L|yeB*-ZnkoBTY)?I0aTqH)K=~ypeTPxw zAYbx7whv`~J?%H?uD{WIX;@N|7wilnpH(7dnS1vAxj2r#CSxm+tA^$zBWvv0eYw;? zXOgidK7%Mu7e2CKfPq%I)Oc)Pj2(L&p&FZn)K-rosG{8*7~_}~&CAC!RDpVh1##^w&-1lPX5h znaWxHEf1Dn{-}$T)rBjzd8v#Y#HX=A(=0cv8gIBy7rAN=ei0TfE+AYYL(pPAyb|3b zZ3J@Hg|{7bC)uCvA!GIc7)Kz}|5%J!r_K_Z7gQM$(&S2Uq9+)qi)@f%55!X^ZJ}N3 zR-W1!2LHm|Orxx=)5F&Zm)^ZWu;uDp=^&al03{3PpM0J+d{~edMtHXtD)*4wq>kYW zF-GS*qZMu5*GT^SsZWgmV_-CM+XLGDth)V1*&A=xeoD^TSOkX<-wLfsR)nWpJ_&s| zhlI9W5(hw}vE}r4o&>DQJu`+1cWQ2wtagT#o2FZy*Nn^#=XFF5m1OK?c2Fa~d zAc_Qvf&;6Us!T_M>-TNK`0BUs{D3_kc4iB#e1W5rg)^@4-H%^^1#H+VEV6L*kjj)& z|6Xw^;Zp8*uBP9|7s%#98*(+tiEGC8aybL{pX}6dq#bfQd?Psz(km=(vv*-!b=^M# zYd93#X0^HLx)n_Z#x@DM#xHRlbZ$WXM8lrjoZc0aB^6--3cd~wPfRFI^BZn-$1Rg= z+;kl^5C{IYB4&q$Ghyw|G9|s<<&7L^6w^D|&NA>tT`m8SlUgx{6|ThhzIQuB6wk!A5}2ThHwJTAp7W_dc(B(0*+c30UrPfRiy* zPCq$RtEkhY7H%K#5Nz(LT)QKS?H<0zQ(KYcF2$)0#}j*_p$TO$c9ul0z|i`)iA#(p zVdpF!89B-7EVOAic|>|#B7yd6q+=iyNu1WM>ZHQKvj9+q>87Stv6p+)-%qv9veY1{ zKf61vabowVgYV~GLe%vaT+9ga!kd{Fa7!H-Z_q3LYffyS5|R9ck`T~N2yKN-U${-{ zotj<9{bp*Zqa`RyNFYmB?E{5`%ki_ga?oLPbFaa$j9zI;Xe+dn)_fZ=u;XU=D=Kt)bS^iNG69|5{)<3=Ei`<}ftMJ4-kKp(QFE}^7K$&4JI9sRp zi}+drOh5|Ew}zUYt18)mOA#ktr1t++(5cXKjKgK@KDIRT-q#XQIki$#1vOYu1twh! zCA~P`9RX6WX1(aOL|dg7aN&VR^_1{Ik+KQziNHMI`QJGfL;J53Y%?ds<80*o^>>0) z_jNTe-Kvgf<5)kjafWm5s9#NZD{Y-$Bx!}f)$TaOrs)S)6O}P*ppD5I=4EMcZgu;Wj=flu?zwb zCKRjV8t#Of zS!{$GE4Gl`_xt{Idrl5~VpsH(2rUBbY$thyR6ltq#JW@s1T~fecRf& zSg#ld5x;^TD=32b7wj5Q@%2eSj&6?BUHq*m)aqHPyTKdh#jwHVLir#~V;Y4w;2g;D zh8k}4feqC7T{YM^_PSIK;mULN3VgthuIxUw+tU19*1~AEe0~PIc(tuGW1|4PHC*1y z5ZK6So2!`cZucVtKq7`|PJN9~km7|#Jr3W}lh}$jrTVSzQHILUg$1q zIb4+YX)$V%1q#}ijbPkv1<0L#0P(#65cf&`AFe;^@?ihKK=~9&01&U%Te@?C`k<>_ z-Q`~DoTOMGJXifEf>AA4u}Ymt8Hj>}g@yeHMVQI|d)x*^|EAcG<3&v1IO$0=g1}m` Uw5n@}ota3--j;52$I6TIFRYHc(*OVf diff --git a/src/font/sprite/testdata/U+1CD00...U+1CDFF-9x17+1.png b/src/font/sprite/testdata/U+1CD00...U+1CDFF-9x17+1.png index fc111e2d77136c5735c7665615301ff09dd5f436..81501e6a77dc544cd4e926c4e82ac4785649b478 100644 GIT binary patch delta 550 zcmV+>0@?k~2(tu`7=Hl+0002xMSSl7000J1OjJbx00960|E1ZV-2eaq=t)FDRA}Dq znL&=iFbqYFx?tHO^d{-WkYLBPDsho=1D0JNm=GsT3@J$PlbJ#On<{-st?;j7J4990 zwG%aCccS&sjMVPdhf7E8{)|Uvb+W6$UatFdKl;bhv>r;Mqkmm&>^nImwW^3zZ)tU+ zX*&>`NG#xp<7N$evkgBzgc6SW(hZMbRybCVr*FM8%N`X;B;4-tWugq6|mTHpzy_*#?fHQ(hn;IEtDx>thW7N8hDh z7LrLFiARkOC4YY#X|Y%i#a;Iyvvtc+h9R*kjJ{P(n&G-{TXFuL?OyGky`Zg zEPC)`OgIuPL?0bBCn6xq)S|DD7$1R9&Cfwc_W(4Hg~EuN-$9&L7DG?kigM^l*9J#w z(SK-B5z6qpOzHS!M)V<4i>|fNP<&atwG#7Q%VtK>^ olk7nu93Ry@<@_T^rBVg`0Ka8$_PUMKj{pDw07*qoM6N<$f&=;m%m4rY delta 1094 zcmV-M1iAaO1kVVN7=H)=0002`;IVK300b6EL_t(|ob1=lj)Wi(MPc6mrJc;eNr*TW z)dtZ1&Z=*RpL=R0r2x2_?U%nFduT7|Sl0aGVp(-`a2X*&qlJ#;Vtv}-SRpvZYobL7 z5&8z9;H8-`2SS7f^Ex2_007+2`J3+i!MXCDrOOdoy@s7?rm41p^Ds}dsg zBB3cEJ(g96K#0%`Apih?Qpyhi00960?3O_e!ypU<|NrXt)Jn)P-ZY7A=#13EA`CmZ z6n+b0UUkBoFMpW1_q3BU2qBa$WYTdM&h~?daA90~vK1kO5{1O32$g{lLQ6B4m4ur? z2%#td005NYzb(z`T zvhKP5<+=rgx`(}mHV6$WAoOQK007XJHvj+t|NrcjK@I{T5Cr}Ir}4yLBE-pPmIA60 z54~$AUF?AyeyuZpGkieqpvNghANOaWB%z!Pm0lP+4+<%?ROoIUxBp{?w8=>D7 ziUxrS2qhB&005A{jHj}2-RwLQxf&sab_-R@&Ja0gn?468^?rm9Iw3Uk>Wd+(P(x40 z0e_+I3zb_0L-=yyioYd6%7Iv5K1Nl0Ptb{00030|Lm5*4niRe1poi9J$WF!VrfIWPi7Ji zYbfk^seE3*w2>V9N_j@Q975{l@^9vlf(GjUi}$?7xg()63$&* z#dIR-$dBd{o6^4<{;y4Xv3vQxPxIoFZ@GX|?e*1vIXADG{3`eHedo8c zH)`|zJ^k<7Qu$TiKQFDeFP&8QO>kTF58tY&KHu1@vpqg!{(O;;cm91FXZw!4?Hku! z+nD>hq&fWg`~|xre0Oe7>v%3PODnN<&R#a%Me}$3|L1c%^!t3iSj&HJRoBgbIqO@p z`;Ps&cLeo*8phn&TvB-b;iI&uqi2_T*KZBE^ZMbVdmlC4+3GSd7zutfWRyD_ZeOo- z_2!xftK++UZiwhaY)ClR#L6uOWjvRvIV`Qv#0UytETCe^=Kpbzl0SSnxU}AJ;^XgJ zVmcO|6L!?--QDuj{=0#dcm6G)kp%}2g7hvqacdIL@XcIpr=L&SstU9wTJPz^<*9wM zffk;#kzio>(fOU(t@+wC7H+Yeol|nwCBm4;;}g~xaEj^tcn37;z@GOkJ#1@rf&3dq znm1z(uYoc@&zZJ)j&5WQ#1#w-Gd@54FkLykrW53)+mRq|&GFkXR~6*PWn0ei0Y#Y^ zCfs8AQ1ZD#CCQ|~%IIIylYbK3K;_2V`+l$g{Gtx1bK^*$c_7U$=JBs^XHT-G@yGywn%y*{V_ literal 1006 zcmeAS@N?(olHy`uVBq!ia0vp^9~c-IKX3pU40}EI{$gNY-shZO|a z63h}<+)gmmp5W-2AZWy-T)~nb(0_nKu2E3p;rdt00^i>9axi&R_5b@LnLfXr3~b3f zf)g_id~>$ON^spK5s@O)dP-C~9ymrC2im z#9kn`3}e>HNyytYV+?TB0Ut@uuM+sZ5d8n(%WnYCZFU3zux;a6o* z(f{l8_bz>#>v{M0hF!w^rRh;FK%l}>aGzoJ*SgZ$4iF$3qU7#Dwxb3jEEoR&f34>gYElxj>ae9v+^Hk7n@%g$K~#UZ z_xQ8W_2ZwOg~Im7a1qUF+yMJ|c0-%p?9Qm#2|1uB&_Op1xmXN2STFp(Uv>LtD@%;?2jlk#MZ~(~gDma# z?Rgj8eSm5G>2oZN`K)S=&m+~Q1%DHWc;NhWitRgAHU@^i8}akLeP4Lw-if8GdSBf1 zbPE=W&-=A~>3_99doBgtRN8Rh^(JG-2hoiuFILX!1nOcD`w?K7+F#ws$k4Ft@6*hB zd9OFUF;Nek@}FE{60dr=vOZMH?+3(b*Sz_f4S3oP{+>T8Z}pB)dAG*+dHK^h64jC> zUax=Ye>&{If%ntrnlrp-(q4G({lp!6PM0$I8U2Su&NV}>0}28z7k}Tk%Dv`#TDJAOm12TjgwKzEUnWcamp$0z z&UsJ%w9nuE8>tt*l~(Ui^xg2FNZ`)CYD-Woz(B+7S|AgDaxf4AD|w3}#V9ihtoQNg S*Q(P18S3fk=d#Wzp$Py(5w4#A diff --git a/src/font/sprite/testdata/U+1CE00...U+1CEFF-12x24+3.png b/src/font/sprite/testdata/U+1CE00...U+1CEFF-12x24+3.png index e076da7c52f1c09e553d278e5025d464d17985db..ece419c7403792812d12ea04a794f463577efd8c 100644 GIT binary patch literal 755 zcmeAS@N?(olHy`uVBq!ia0y~yU{qjWU~*t#W?*2rzj0X!kkSqC32_C|{QUg#^78un z`u6tr{{H^)@$vcj`Stbn{r&y>_wPS{{`~#>_us#N|NsC0h&x+*fu=Nix;TbZ+Pe1CZ~ph>#^{STOXPBFl{t(>FwRC+S_^S){F}gg4#(wDz_6E z_or`Y_${22H+{qAb8lLzsf_?b?(cn@il9LSJmy^e=OK6 zNqz0nG*_?mxI|Ks-EAC0^(JeFWTI{n-GM;c1!+$^iY{2%?^JSC{= zi`BX9QTDmkN_?Ah7W7)k@_&C+{M&cS|KAFy*}U=}pRB0R{%2xS@i}2i*thzWyN&*S z%OCIkd~EMugWUAnw}ZVj?{?;2mj3>@GWf#H=EZv)%hSK#{aSH-1N)m}t1a%Gk}T1m z=a+w{kDr%6zI*+~$zQd%NE*K{HDgI8X0E5oVSC4vc3wl5Rw+~*oGwgyXXH)iObI&CMNg^vcM6=<0u^0AKa(9W6FG`Z})@5 NJzf1=);T3K0RWJIPNo0= literal 1255 zcmeAS@N?(olHy`uVBq!ia0y~yU{qjWU~=GK00NFLPi8YPu&ncRaSW-L^X6uLVT*wP zYk`b{qR@l}78QkuDlSZulo&ZDZV-x7XSLFOdc$w}+%tvmzb~EpIL%V-r+bE!lG37T z#tpxpr}6|(dVAb^7Tf&IXAVUC>pSqKm`y%cW+^DJx1MplQ@2B?Yi&?y(S^EMOL-;rv)_8nzk4cd0h--xhhvM#S=74PD*%lgACA9lWQ_hT9JGa`42LJKa(9lUPm0tR2w8vbVQ zn1BArem?n{=hq}AG%;%aEBeUuqRBt6n^6~hMrEN#72^g!@+_Rez4soUyws;4LOh)8G{1SBjt z-~iHnV6Qxo1ln@zASaWffXl@{o6Q(n<4Owb&Q?EI%I_NZAoCjkgZEkUXJ08QYR$6T z>9loD%)%(Ybpg8S;VY&whyVDKny{d;k&R7CA|pZJ$BQfR$*)zzSCpL;T@?$|Fg<4B zEfALxXp30ICy~!jDpRsyx+iOgoCd0U`h@Fh(Sxqd=XLfk-}^su-)@;?h>1B8FIXXt zbL2YY0Ce2%`?r`SUM%4KDS0pY+9D09%~G-_>P0F~U1KlGnj{_KUDTZAnHQjYl6RHr zPRFe*Kszh8TKgN8&vW;C3l#kNgzah-P>n56a^9TGqUfW?q?$ z2M)~aQWgR+w|;5Pn*~%o38)ImU`B=qhaeGm-H;0yT&x#=&yP}O-nvk%b>qbE36uT4 z1>gL^P?ue^y{__)HZ%b!Tu^jk2PXxE0D%_*3!8z70?5+fDCxKWWr?sbF)%!s^j-Wx zMWy9EIXyZ1A1}q=+9#_W>I({yJVMr_JC*>kWdwHy+E*EjMu z81S%O{JVV_e}{8s!IJM{AFh|mnIxa-%xiE(cmO`=-id3XQSf|{!ah#L*v=i zjfiymr2=RY6f}s716iO1YRC&@G%WbH_U~B+X`m~SKmjmPQPQyVq$X4qe}GZ&|NmQr gA!{EpA{%lbGLdbuqQJeqLLg&3UHx3vIVCg!0E+Sig8%>k diff --git a/src/font/sprite/testdata/U+1CE00...U+1CEFF-18x36+4.png b/src/font/sprite/testdata/U+1CE00...U+1CEFF-18x36+4.png index 366be38671868fa0eeefedb0a19356ef4d3c2b59..6b617c4e21c84fe35e896d930f8076aa278b1f7b 100644 GIT binary patch literal 1096 zcmeAS@N?(olHy`uVBq!ia0y~yU|hh!z?{Is3>2A>zwkSdG6?VqaRt)+{QUCr^7{Jv z_V)Jv{{Hdt@%8of{r&y(=g(iie*OOa`_G?0fB*jd_wV2T|NlRG&B3)mgD!izIEGZ* zdVAMCTR2hXz{hRdBGwe_W8A2JFtp{CBRhL0yE%Kfc`dt@C8unOAj?-#jgH`UD=iMk zf@=pOr9S58zCEAam8-Y$(&tNezMg!}tY)Wf`^W5Laee0TV+;+I~tT7LVy z`?~k-0&{)WMx2pfp0xPdyp!r1|LUHdU#Axqb@gz?Ec-DV83cE5@tM$RLeNP4T_0Q-1Eq!!oZq0`shfejaDch$xdwDj` zDSLSOBzK>l0nKi1T_fUxKy;a{j=hX^*U8@43rI!;H<|P8R%J>+O}>tu*gxfBNftmN(`;zV^$!um2S5 z)8bp#-dyWh5d3jx`Nf?-Li9A|UwO7j)A9Oa*Y}Gae_VS;YFSuPt&dx87dt)+noDikzyFdwv(MA}A1A%u5&zAb&nRPG{Uhz4`*%yNf1DlM6qdZL{GvU0ggHiL)!$8O{4icK4--(! ziZi&?Us?Smdf`Wy6+p{DR;(&8p9b~diMc9^x1N5Urvr6_z}I)vLo0iw%>%?EM(f-g<~t{O~`Up0|;ryoR%RMCY-bDrHWUP{1q!~E+P3mzWW u@tmV-2Jinsb%?cBC0RheAOjr8_|3aSe0SHno$qo%+C5$UT-G@yGywpK-@Ziv literal 2247 zcmah}3tW;}7XJ|CCEz<*u!7Ve6~#s;%S`ZXj!2HKQ#om7X0~cNTbh*!YFd*?JJzb9 zV6|2_Dr%FGl`u|CX1dVmHj}1k)>uBXHMcQfKOnW{v3q{M?|%2*^S|eud+s^^<1A(% z28Blf0DuV&@(Tw5h!6mvu?TPj2y=LX0|3OSU_VAgCV#wqsOTaMo&P+?oWd~=_t`8g zp@M${`-^!cbY#gilSFH;SY0-1SD%|X=)(Q%Ho@d|Q|Lo89|S4S6ddLtKza@QL0HpV zUzYR3uK7bR+^HyFTp|Xz)$aF7jgG&%(-8faH&b?Lz+1^Qz^|m|ko>$kO-(Fh#r-2OkuAiUW-c}N>X!$&Q^^XC| z9eaY+X)84Z1$g($9+l1W*P3@1nV5-iW-yG zal5F`O0%t~4D}|}s7XWZWZ{)euh)CNdr`IT?Pjykq)XcydwST+aB{SzvvI+I)Scz`SN_u;-`{ zUF1PnW~DN(PT~wfCFpT_hD8A#T!M^ z@3xdzZ?V?81I12-EncxcwLf!fcPl@-Y8$hTMI}dFKKqqpL}!PU=;;WmH$6Q+X}!ef z8?72UO&UwhnCgg7{&MN+T>ME6+6|vbgm$f!KkZnl3ta&w7(lm+HEjbHpGL&~z~v(T zEkW3^LWrCPz8u5%@0()}*B$9=z!?cm z?YzD;X-UdW@{%yVsq7bS3rk_ulGk1S*H?syu?~!Ab_CX&l@6)_?C_hm)^%kLN7R&w z&^yFJp~8oYD9@ob$HFeg2%;H=>Oy=3CX$BBQ_K%$wI;g>&9lG#{;;?!0C$X0^B=IVw6cFn z=6|fyR^z>+pUZpozmm9+W2jBMYI4%63>D2Td0lzZmB$HyV&a8cVH?;&Fqzsy=xIPo zX_mfVxpu?W`0(t%cqp1KfG-OY_U9TPOYC`c1-#za@b4ii#@S-_+#3rg1B{Ci`7=ZO z4ir<2aJym2k2OooT;m~|!Rsg$w5p!bn=Wq<<!ZG5+J7x!w@mB8MFS5|W>*GA;Acf zg6GG6igK9Ir~an~B-pV=3RUwm8!2LMU8adst@GnK@Df@<9ClH*Z@Tr%ed~o@UuavR zbAc(D#iys~d4W%F(%X9g+M}7aOI6L-7N*8wQfhJc5=a)rJ7(|5V!;4N3An(*4|qhY z(pT`N6`*tQfqrroL0v6<6{`BI@X(#&m_jqg^-*bR9B#n>=~PT)Nno9e|AODi zmC&R5=oJiYv*yt>b>z5?{6I$tI*Uf>7JB3kqfc0XbhRijtnRi;^hWp__x)A|rcL!0 zmk_@pz%V@nFLB#%_)l#4&d4JD6%9c@q_%0Wj6WdA&>{H$K};wyA0ou>h?s*0-ARe; rF=LymYwzC{P#S5yOe}@ENW)^|EL=v*HOba^ZEk}7nSOOXvE2UxY>@ps#r-bK}Ky8@2g47N1%nlr8J@OP^zHaD-lo%)?y+HzjsK^CjCc0aoJ zEj;ooplESS(dU37?ba>Vi%zcHHu*L`qr;cB%^yQ*t4sc$tUgAjVzbm z1D(F0^M9Ej$P3~?uP`XwyLx>^fvF(h;ri~)QlcIUM3`*<-SPKRpWtwCj^ez_s^)B* zDi@9w$NQcQpZx9YAKO`{m@9860cCUc!~Ba$fBVEfb5ZEx-y&&GK$4!WelF{r5}E*- CB>%kt delta 727 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 JH40GJ{{Ub3EZ+bC diff --git a/src/font/sprite/testdata/U+1FB00...U+1FBFF-12x24+3.png b/src/font/sprite/testdata/U+1FB00...U+1FBFF-12x24+3.png index 1a4dcb01ff0fa66a0e34ddbcba8fff27e76b5f09..1c6da38e5bd20ab1e92c84440c49bcc1833dba20 100644 GIT binary patch literal 5045 zcmZ`-2T)U8u)d*53j_$ofEa#hp(9`fDWUf&(iD(hR60nN&=Em8(wmfk(wj7q-a}O| z3JQWC2neA_Xb=DQt21xro!ObYclYeKd+(idzCHJ`o{lP*5=IFC09aj3$p8RAZ~!1e zkpt(0e0M1e02l(*mE;Y5aT__Esb9+JBU3|=54V{P*to-JI8ERl@Jv<7GD{;u0VKaAe3j*oPJ)7v$p5d5<0BpHIyac_>;S)KlAwgC z9EG+hG#LSM^nbFdODsO)F(N0boXYUqMvk^%`hx@6y=8{A4k;G&1Af;+ly7{Y=pcz* z9dYBpZpH(E0HFVs@qd5{tIjS(6VP9LJJ5dxog!Fy{MqO0&ib=KH}{ z5KQPhCve0wB;esbj>|;?OLvxY-ucj?u(xQm9tZ-G#_z{*C8Oh+K#)j-c4mPDNXoNe zj)$#xMy;S^soLt)*Y#uGR3!)^!8Ny>LqzBV?O=m$p{7%gWuab${8T=lmvfJ5(b1}& z>#SQ=LpScZ?cW2S{^BPSisOWFPtPgPK| zCew6Hjuf%T>F)bjvF<-|zxn7#TySfVym5**>sDm=Y`PaD&7Qk=R{!Mdh<3q!nn#qh z+Xu}q+qxI(4~Up`)S~0mFIYL*8@#j=?iv+sw>(aH_=w$ktGHhG!n8j+yPD>5@_zTE z77IqK5VQmHS(mjK3L&*^hvIjcZM9hx>SUi1=Tu+!MHGx$aj#z>Ub^=EgudkdY{tlk zX6PP+wjQ~oIKP4xj!IL^6JM_zN9O1}J0A40~H=%2^UwuQH{ce-2ULcP4)inZ^j&Ay&L=)~D@G}7fI_aM$&4)pB@VYEeU$&&OX{!Je=+QT=+7d%;uN z_$A2El6c$#Jb-s3vHW&r!83yP)DP4k0W>(H0wSusbbj8MVss$;z3L$(GM1OXjh#25* zb?j$xR&{-E91*M6`#3*C7OwBUqk*UQYA@?)mX$YfC)C|!DezC8@C@oHStRjSjZN6q zQH)!rmeLhGxmYwyAL}+~KkpG4X)4OuHl=4LA4{o6P&7+amX7Lj)e7v%CI5Z{oSJ5c z0E*>$xrK;r(&APG%V5d4p0LLG!ZuELZ~t*oM0nJqFxRC4r>`}ImrdVg07XC9I6I&c zXJcB=ykmremVB^LOk}FXhxxqgZcHqcEh4W9^1={euCzje@oIQ=GkeLviRY0*f_X`} ze)fd;*V%AQyuOW;5uc~g>M(^4_ta`PR5PHROBDB1Ig!4q>3YUXa>qkqwQq8ZSx2FU z-BkhF0pi2{y*k_APhG~}+1M(m9k+#@xUKspR=kh7w3(w4L4qd|pBg8KhXO`tdabUY znNACTTF~<1mA5eubcH@zjFghSgz0UTlHFl@Ks{b7XJj>v_K-9ByA=k76c*eU9@)vB znb+a8L*}$xamXq1Xe=u3M+_&jeM|%GbP0_4xqGN4YL^`aL$FeV!yv&!LV z^I!KV2*|CW+88k9X=Y3m>gnVshK8HwZtpaHh}iV&6Y~1UVPnZisRhzsNe($UK_1M& zs?J)?9S7=ICrBM~tSca`kSD)fr1ED6hjQ=*p8}3CCr;+&%l%y#1)@ipuAdYfx(HL9bGfX_9peU>7u^`=ivSsH~I$RIf>F z?Wjh3#+fgpju4ag%L{`Zm*v=JFo2Xe*d_M3(1Fp%0kq59m_b55=Cf{&IC?-(#kISl zq-BW-@2Ys(9_7I>Z5x!7c2Mfm65$b&SQ2@RdEt7uh*%NZaqt68F+{+KZt3QDp+ozn zy-6Ee2xRexZx|t#_5u>}d<`|dR5vyZG{^LduuJ;4S;zFLbJVvhCdyltHf_*4W~h0+ zFdEfH9L`rU&h7d?uO*!C5!L1t5*IVCONHH%%9mMt@rBxG5N#9)?wKaBl~TT-LG00W zNu0Cxt#Loa!-RzBUFDr}Zr(_WJaCwbuoX=Zi`5eDg0?{~& zN3qrW2j`vye(7zOP11B*0o707-u_pQWV zWUqJ2_E!gD$awJ=_uo?f*Jb%M)+n*g<=hbu`i~mV*^x;U6JQZ@8*C-}?>)K;x94)XG%?9#B`UyKwm&b5x;% z{!g;q9rTVxTIJw*$ST+0WhFnxd@0wv>y5712o+ho7j%f*|01qLwEy&z?6PBJ0BG-Q z{^mgGVUF&xt9s7X5p33kKlb2LA;=v0((x$xC}qEK&S?F9i!$<|TcgPJBq`ds_=Yb3 zGeOpI65E$vH}2jG6%t2hG+un4Bo!am=)pfCvpgkD2kA{Lnz}BKEmz`=IW%|te03w# zozwdo18EJT4`9no8~x^PLBwrn9Hy}dE96+lXm5tSn?@5|&?!QNY=)U$QqPI&4{?pi z0p8oahjX`Sy1PA`6aDz5JgR}qyAecQ$=GKOu{jU;@!6%t?Rk61yTs}D;hgD4Cd>)u z()kebnUJmu*w(9a^t3{Fg~(|VUmYi_QkC-MwcXC(Erm{2?j^hvckR)pE*gaw>S zE)izYMC&l!0cjvE3m`e)4`UhFjmOL zZ;&qPSMApI*kHNrC0js6{HSoLc5ZK4ww4v(9`~6qV-v--Tt7poKU|(&GQB@I2&Ig6 zReZ#Jj^fXRq)Ph`;TtNh%NGIaL2`6ZrKWnyJjo&*-cXQ6W%8sdfYb#CHWciZcO527 zt3L{HZa?>1L{P)aK+Wcum)WNRQojH=1I2ZvBZ!jL^JXH3hAv_$9XdT)6SU&LJ}wqP zFRiV37u0%0)^+_0(EZ%c8Ualx*^l>zn`gamDQ``P%;Amz6@5E9x6GM$@B4T&Pks!_ zgi3)KFH=%u1Mb&PUOqC%3QLX&8(@8n)-8v%FM8-YOc0J?SOV8GEqpzv9fm`U7~>pB zUq}Y&l~2@XgJzU$Yed6PVso;dGUZ=ef`*3Z`m8-!J~y-9^1S%D)`JpcClkpYWH`D< zF3evF(ZkxTPN=@UqjT3(G6HS5*&(ZIae?oWN=oWYay2pZ^vd8ms+f4sd%4FjD$wtJCSDwa5#@ z6Jxo(W87q`D+!+M=Bu}%<4qhZgdZPU$HzXz)90^G$gU7vssoq_K1cdQUNX3qJD2h+ zw^*9qJwf|lYsy|HR)UQI|3GF)qCd()A?;veQeN>lP>96R3nHj&SM#z#0e`g+DuiJG zM42<_4O%;O&g^)VGp$n^P;y3%I0M0%$9+{R*b=;+oTT*M6PXNAw`fRAW5-V^1}(?? z4eDoq?DD=5GpW~oDW}38!vQujx4p;yQe%PUtmL-)t1np)5&Y=>*dEzPc*6SF=g!No zh}K&MU*(@Pz44~b9%S@^2jfAK5d$EUOS)%Fb<$!}4W zK`W2G?!&W`Zmyc{wzwQxw7L*nXHFg-D^D17WXm4?413vB*}7C@*|HgTWZGa%$M{~j zyS>s_)(P8Teo*D6HmvGxVe-Vc<#uphfqfG{UyMtO%TMGEE8Yj})|Lv{sVy11;WZZ} zd-6PM6F68=X}XzSNTodk9-__MaVOoKSYn{O$~{I^o~ZV)hLl|5Mg*c|+-pt|`euQW zmq>4rC&(g~j$T{u`3Ho+TtvybMPbwUGUe*z620}+V(hS}LM?@}*S|q-=2d}{(d!eh z=w^1*bD!CS|HF-$*np;ODs+3#?Km-1s;YyN!^5e!@gA{yJtPt>IbD*|VU;&h$8MeZr<7UM7bk{I;CEGcokL-BI#%C=rY#@x z<-G_DPAQXgwcYQI*e~mhLS_zLQ*dXPCchDJLaA!G@N@l{9OPToIY`3`xuLg#x}N>8 zst^qFd`{1`T%tk3O}@S*Cs=5wUR9bF+gn%&Fe(@;;R zkpWMQutJ8^>l16OYk?2%1oo(w^pSIEClpd`e~9L0Uns)H@{2HE9{e`RQcy%;;KlLi z3XXe$TCswCwe z(gCGj@cai~Fnt?Q6r>fN{icp`$1!T62`_WK&U@t%|4mNZ!LHC$Ij-EVT^CO^D zBQqn0Rd3{{_-Di0M_=|bhHG)3;-o&6$!m?x3X=-L#TpeBe?=AaV|wpUXUpCy%VFhj?L zI$NLOyHf>dhK+~}nbJ~sKJ@dOvdvbJU<9g#m*wOv1{cc;G|)pOk?ety3V+`4|Euf< Yt1qHPFR_cnB4O2p=)Hz$QNv=jh+Vyg6}^iRAwdu!(KmVv zQ9?*W^nN$VANRZWK6lPMbI$plIq%H8)6O$-NL@`DN;XOW06?RK&@cc1h#&v}5JnCl zB=WtL8~^~!tEB-q3dr4>f>U-$utbe6T;iF`DbTuXhU^=`{o%{o&AzjM#rz+h-?mR< zN`H)TjJ+~^jGWb-hkGdbkv08KASJQTN4#<(QPuCK11k#nAH=C$1;hOZ5&98M$s1OL zxoipDH>_+w|GH;_7&jQ}oa+az=j=w&|8FdFkK32c3q)zR&ePBcc39PZ-xp z0f5WPtw|lqZWuMm=xM&CyJxnU)F459hb$FFk*Y?K3KJ4SF+kA_ z20;Gx9O4c>kBF4cxNqu8KB{kbh<_Y0zKlO-rM~3wwj9n2J^AUjAa|%h(?seB%!2uC z`LMZC4UkBozE6FV9s}R^1Fo{~vieLsG^=M9AbV~bo$D}3zh0AR>}JAK4wIjRgXde2LWX&5f?%8zIj-kf5>9!jY={C@OEp)aH+t z+ndNm#wzyoNgF+|c9K*~8xihkj9sr`$%=NR+LFFq%)rBtv93qO2YT?p!n#zl{>AZW zg4GMvl6yX}r3F?o`dE4w=SyF3hTRpPshRv3{X}|~zR+Cr7anur3LAd_tf|+pB?gZ| z`k^?tFs|G1=;8wTZmSm-6v~3%iU+JESg5Z=cK%`L5!)by)frFr*v*Y!?2cs3dTXhX zRL-h$p^WQVR1essd%W_i9@to)XG=Y156PIx)Qb`$XT}D5>b;1`Ypg4V8&bEA%Tb}; zWoO;E|K3q6Yhx4G5^fHN<0nyZvC)YvnIh&?gW;a6-oa?hO_a=rSwNVvul&e^@N?-` zWI-rCX)M_J&CP_Y0vNHK*>ziZBVLV4!JbQ7FMAe`lcUStze!Y#+OM={^X)%qdL$oW zfrC>r;^Vof^s=W36>7JQ5HLxJuuwcwlW(M5Hc?Qb^tymU*GVHotm(|)Xu80Bj$m3; z$?ImNDl2}UH}l}0sHR6}N3Afr9|n5KHhIzw#h;H+$y(6qlX8B}cnIg)GXu}gT$*Pm z4!YpPFr%p__WMscG3$esRjK?V9OOk6rSReDcbnxQWn4`Dzwh~WYXZ@s^EAtCfnzUJ zz~p@17Al?I@NvUqtoN_%&2%uUCk5kypWQ-Eh89!@XDNwDjIo8Oq+u@n23K_lFg%Ip zayeYP3vUr>roh2?qH)7Y79+h?yCK2sUe|Idj>Qh(b!8*$cO-t9h z)m%&2Qb8fofmL$i$;hFJLR;8=DkJqx4J5%i#Nv-LgLCSgnH-GPIu~KL5caXfXwou- z`Yzdn2pxowP$z#;YATk&AYR9d;z7h?fh!Ln+$8D#MhlaG^_V}v248>Y5OfxT6WIk}n@4nGRJPj$g%y@(K(DCsx zIPo?9={NJ3Tf}73D{Wn2e#T_03DJw%T8I+Qs)gIM+L74o@5T~jA#Cgn<{L=}XUbMK z1t^W0S%qL{Zfxo()_jAQf9#oYqw^9ZWnjZpLJ;C0&3Eqv#qj;Z_d4e#oLa?<%y_`E zxB}EhnzUw*gdyH%zW$ljBwP!GH)x|=Tci_tR7{G14*8iG`D446yyV$wWB#xUuG7vc zY)^2_;INb1-p@FkI5ZkUi=3%?Wglrf%v}cD<*zn2A1RS z2*)SI8fq_o!PaqfX0jHBq5RbiUmPUUndf|R=ppaxHx~KrEC9eeR zkv!|^UqIj)7sN`^Z(tjX`0-0`US-=Ib@iK6l{rMdHOoat7nMui6xmNovkMSRzkBP} zaz?X}?(AvqRhm^%YkUGz8tb4nslji7_6K$-#`_1i84^bmjBN$im#BbVI&mCcz43g? zo!80{4c<;~hvS@u@liiBu|@SN7{fIYa`;|Wf!P|>yd*D0uk%A*rg$B*2{fJabw(#U zrG96BYP>7#cL!?}#?xH}F#nQ=Pzm_K*@T-M{$4b>$Q1o|ZWASck^Noe&zI8XAk`=I)4a<>nbc=ZjgI+>u_@P0})*2IYoFQrz_ujE^Ao_;?9tWAZi?SZMZYQg!nL zTKoBTH43xmzhaq)nQea^09vH`ujVvYQ>7`6qoo=Zr|Ctmh`pckAhP||F^zfbe%UPM zJ0Zlv&{(ma$%IEkTSZ}8B%K$#`(%jw%!-?gw5(?1L%mg4F^!J|A17pML_Y@dQp{-c zZ6so(0`2LF_Tr{Z>`KZIvn|a$iKwJ|`PZ1zH&Q_ZC}ZkE%gaeKiT}7K;|R_{>hwZ( zc8m^6F4U6%m4O$#syA+N*J%aMply1Bw$BkdWG)0V(9ow~V!nVC?hQ*tuLt1sf-E|0 zRd$EWN{S1o-UkQ=8)8yJ;`|^?P;zRf)?$^|!t{abvh>yLYlqJ;r3{(bHvm$!MF4uX z?@Qu?ofp38TWDOn=v($E zg+p)2E)VF931p|dqX1G~n@0kIKR@Mm)(-PU+7sWRE#rcIwf4rN=3t|A0(4DodlStX z7i>gb<5Fr?bjTBAz3jA*q2!os9P|6zNXQ`xLSZ(hxucZqZ825EVO76TZ=jVRnMA-GW* zi|VA0ZcW5U0KQq)@U-It?i5Rk)6=+nLG>?mgC|EwfTHyihek_X=QL7&rNnA?o~Dm< z4$Uga(5w%@s+a8g06p6YRYdEGu+S5W#mL3KOFNQAdK4~DhZhL3TIKpgv|x3?hhyf)F`sM0?(cPd zxJeKRxra1WyV#)INI2~eyA*dHt~1?l^g67p*ys@(V`qP|q)01#xU6EZu0*x|B;8TJLmGhC}iY5D?f(sJ4)*ogocB9MV_nIfiCZW$2cjMNf_WVq^=M1Tz*D~KyuYa z0YubSvlF4NWx8di5qT}R3%@Iw1e8^p+EH<(;-xUM!RyWq<~gEH#u>6cAL_1QDX;s% z&*QZ!>vYQkB?ewmC0oUg8baA2i#9)e6`gDG!pPml40q=1L>oekbl5AlcOe|(M~jLD zjt&{3%zOLj0NhDM<3RrUBwp4s#1linGE^w4z zk!r=&(qkjoXs|eaO_CcsD8Zthbf8SPR?Y~i8;sXjdKB5e9#kbNM#%vT(yA-@#;mmuG>TfjH;$JHv7# z%DsR0Np|O>O&GQMyq5MOAu*Zaqs7Qi$lHZ|`rs7?SgyLj`+<&MDZ_6hL|uCJI!r3Z zU7IeRx8Fqyy!^6cUTa6&TVBcI%|X$~MLRr07gM1;WM{#pNXB~~ZO_Ay`!Pl}_vozA z_~uYh?(D0)SrE6p9Z98{H!B5oyez$FeR6M$=Vl8XeZ-C1YE+V?2{`x;=N|aC`~zcY z(n>C2L^ri&-6A z%i{C;JbM=PK@70B`*f?Z{_@N0Y3qstl~E>#>Pa^xYmGSGm)iN`0skJ$7?<$E* zfI*J(TH3x;a3yXL?^aH90qwJ;4kTTJ9)G8(@0O&ApRqfWm(qNQTd5T6 zqwSTBW$TepkPm>jxfatDoYTb$NEtf|7M{^{eJM$*KZ=ys2O=3(+PrhFzMWL zQjxc}ORcRHF@ubj+;3IfL|q)k!L&6XzDLd|Ulw4&)jBXj&>ONxUqgy727p@0b19_3 zDX^7oOSSunaj;X%XA`gLgId3Li=ZxeDa|1w?_0yWXeC9o9t*K5YCY&Z3oMJ|+BGQ% zNJmehUyQr%&9nMe+Q?M4+4l`r$ozbLh2z)jZnjK|&$7SX4Y0J7EG_nOw6Lk4%BLp2 zQ$O8k8s5fK<%_(Vycq>jBj+X*XRMya4n3a>W8kQVIG7v~cWr@ro$g31rGuQ|9_!B&69J#x8f_F+!fiG>vwRN!%VPFAuE}elj?=@ApH5?mT$=UZDy+M zc7){NOz);%GXZOuE zy?tRdoK^IfW;3puU5Q|7HIfWv$y$|L%0Gv#lyW!x(YV%n&r`Vy@rKnfFZW1mMB1ls z9FC`FM-Nx2er=~b?*e(F_nzEq-!>1biH`b!He@he4K zfsK4_vq97g21b9%Q=-4~W6|%&%MGH2bIV83Xca&i(O*I2@Lm<+sOfLF7}W3WJK=f- zzsrA)c)=GReQ-n31^H{<(=C7WGEj#ln^(p%JO618)&<^~(*-i{(^$y zp(M$XPPxUgG|-WC*_FuG6bfLCB`Z>BX=d)tY*PI-mJkG2rCe0VPg4*&EQ{}TspG3i zbm0J6(>?zEJ3_+z1B+J$%>T{= zFbF^l9L)@!+5n#aJBkS}t3Wul2H}y?tl70REkp#{6DGn8&yL8-8yhAjMQLs^QajJ{ zUa`cNTEjLi@r&8Dy=p|&Z`L|vY!$#%&a*K*_hocHhEG(pc`m9cJ#Gm{AM}T~6;zLC z+Y3XC;>^G0q#^d{8jW%&$4xOzK3B0D1} O0IgfP8Z~Ox5&s2S-Fip> diff --git a/src/font/sprite/testdata/U+1FB00...U+1FBFF-18x36+4.png b/src/font/sprite/testdata/U+1FB00...U+1FBFF-18x36+4.png index 73ead485dacbb6d9ea2e3fd5d527d069730ecfe2..58395f3e00f4daabb4d9efd832e35a009ff47d67 100644 GIT binary patch literal 8354 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 literal 9975 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 aKbgw`Fyr76C-dJQ>6_X{S{0i1;r{{A+D? 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 R&vd$ejP%TO>$Kg_{{xNIBx3*o diff --git a/src/font/sprite/testdata/U+2500...U+25FF-12x24+3.png b/src/font/sprite/testdata/U+2500...U+25FF-12x24+3.png index 89011df49d34f3da3b765d0df7097c5914331991..dac2ac0a18a479a62c068257a71d0752fdf69854 100644 GIT binary patch literal 2104 zcmbtU`#Y3*8y_{J$$5;%AyZBx?{4L7Gup;Z3?n9)nRf~AIIq(bM#dngXvnDxE9+2+ zXN#=EaHYW_+N-G;F58oawsDAzh(gTBG4C@v`~&azhwt@y?(hBF_vijRpYM}Jr#h%A z=_$crFja~p`DYkR!2kx^VS|K03n`V{fWdZcQOG3M3*z@9 zneK^q%r|9XxiOxpNOAJrJT>)j`Xkxau0eF=FX!@NDbP zY8;$*8k7P(@WOXBXW+zk#lGsj>d5Ooq6Kd_@gUPWq@O}^xm{vaf2iz%1{n;PHDu;- z%Z?ulV}Pts4H8djhkT-U3G9`AnLehpMw6^Tg1A6ixF?kOs ztlvN6-dGWsx^HfpF|@2freEIon6aMN={Dm1ci9rQw*$T45<2CG|V*MB8|2; zrrm_RPYR|awmhLVVSJ!DMd4-bb% zKIKIbv2YYW1&Dh^KQ{3!$&*Kdcbo*@*{!g5$q-K~b{jzw3`KsHigDLKPXDjoYq6=} zt-_`IR$fh`_FpIr?Qs?T$ey;&G$Ynjn`5vE&$~l%RH7yK6z8+AMnVn>CspFjUX(xg zlrizb<%PPLd#nL88BFB{4+0^Bmy2Imagp&h;D#Q5_~rYWzr|4NZE=7ixPrWG*-_7g zag(U<=VQ|S8`~~Gk-<9%VhnAwz9H)V>@!CG&_kZPbC#>gDk$NMO zn##s4)--&Lv$cEJayxr7u%JA8ZF6-BKmTEMT|}di6ZQ2l(idGa{5%S^KUsztIe3-| zI!NIolAw}m`%v)yxkiskg1%aY3;F(*UhR*@_f|3R&D;z7t%LE0r;omN->RFMhm0(=-;70O2NtCpcQd#ZSv};Yf zu5!9Iltom*dKIg@$D2%h3Ov%D?Bqv~0x*kndYTr^`zJqk#=vvjUwdt`9O>?-4%@mY zh_3*7pRlu+3OH$|JNeqA)Uu3ASHIwn`fI=C2SRZRJ9^+bn>DMk12^j88z{}*do}_R zRf?7`n;46doSzv_eaDje5nCg;Neg&ij@8E>PNbvO%wIpSGv>B+l9RlEq+Yk(&bW! z45!gq!vdkhXY`NYZ777O^ot^avH{+Rf1I>RQaAs7AQK#f=j6mqSK6jEn=-??1;kq0 zG)q%v;v<20<3gHc%axpw-TI@a!d^cyl$*gdcoc0})=CssAp_^m=kz%h#1a+DsT!nq zP1i*)HRx_Lbs=Mu!CM3fs&n1yQVqD`JyI60BLlfa!YZ0*pIa&I!p^!hW>QS)2a&e?o? zaU$l+@9C>MHM#Q2|JP!sPxR%fMNTd@N&5dQ$_0A+^7ueR)*&UrC*5=UOWcbRZ#^x} zDuyFeCisL~9++Msigd_K9e|Z4-VNpfPE_#2lMqjCZsZr{fWLiR9;hz4#Hq+)hxwLX97mC{yKd0w?6A<1hAedb zN3d&K%4R1@!-UJ5&Muj9&obe}%*$bU0eq!2S!fivNc!jkry2Q#v8wu7RZf11kPVFT*IWQj|vogN5ADBnxa2yY7 z0C;6WRXp}-M!uR5v4j5$DdMe9SIgIjDNe&gT!kI`5{%~o1~vp7)c?JA2H`9vJZVHR zVkgd08Ulik)#(6BZ3t%>;f``#AFKo7;o1MbgfPgh*rM-F8Vap zp+=E8z`c`zbwP{U6c|ka)J}xUhu}Sc>(lkfzNzO6%*^z7!-?Na?(ylL)j^@Ilu{$c n{E@hh+`ArW;>1!#m|yXR`qEP`z!xth$_1m?Q_1zVe%${7hj^Ix literal 2635 zcmZuy3p7;g7eB@sjhVq15~3Lr<89=f$BdNMjS(u(%7{@OA&PRDK}a;EZbjuF67tBX zyz_qEqL)YI73G~sBFuk=*1Gqu_1|l+y?$qZ`<%1Cy}#f75-2w20!T?D0007(7G?(l zfCmo%FcJdb2;%!_8UP@%mS$v!b9bh1cKb(bp!Y4a(|@qG=)~V0z^I%amhuzQE-5$0 z=DLXiK$Pw=ufm~|NA(nvPA1BXXX^VHhL))8s5~Nuz&eOHsM?m3-p*e?Z#hV4)wzTG zem-Q)gxE68{;Kk4(X8+(6ZQ>xc$l<3qbfO!JS;Xd;{Yc&ffL!yV3J{;A|o^2o>A|1 z1%+(sLOW`Td#98K~DRaESg(8Nq z0?06sUu`SM-4+07x2*)8o4Nxj3xNC>ITCYYl?#S;F;r-icO>{(ChuH)4}VBUEW}Xl z=UHxlo_?x{Z7s@^OtUI89D_M_*sD>>3{TBap>FSi-KYOZ?sr}10RT38y2p-FB@Ey2 zuXKa3GL5;SZCKHi%sy zg{I-$OxdIfS?BUMi-nBp#BaLlw_$J)i4esQ@DvghMdG2u%z2X@d+6-7H5rIJ>{_PZ zS(mzpT~Ds%EBxGhYk4v5^ZdN^XV2wJ!WK{^Od#>X9QveG+uz407Z7J6p-SWGY9V&% z!t{1JLzp1`A2Z&``TMaOy4)PtoYrF*8fcKs&Yu!-_L<%#OcM|FzA#j<=o+Uv3Tz1^&GU{pg!qM#S`>&$@T8>DGYj z;s%%)NCXUf(b$;rEPxuDq22KUVuRJ2o9!bC)|1d?cC(Q_;|x=&D{$-UBWr?G5-!SWBgNBKcG0*PV47_bc>ir*m3>9g(c*;6R32>GuHhq7&c35%}$M_Cc2 z!hDN2YvS}3i-oi+Q?qm`1s{GHbp?f4&XkYg^96rpb=XxWSI+e37vbZfxo_0N)$7J= zRCeN8z`>!wJl`NS24aOwG4fe2Sl=14t7O>cBE*y-cp{Jz4Ab8b1_0+4IEK@@RJvay z9=)%!F6r7;@z|@HR{M`dZLfC>KET`COM1OSmTm1A(m0f^fZMA5la5EMcvr76_4|o> z=`d0S4$xc$n8RD5&?bQAPab^3%knPbK#%>l@YRDS%O4bmwmcjy4m^}CmI;t98FnK{ z`&946-vQ!lt$uiT+)u6Ib7HH^7Hi&gX*hfNL2-`CYR&VU6G}PhU>9`{HB{>T&hU0~ z|1Gpck8{;?sVlFIasza)Qap(fx_z}jd6$P{l%#v> z2SftHbWJ4qPY#Y|WIS&&w2T>ER^Z$RSpgZxf#Efl2s^~i4dApYANj1T=nm$_=)sscFy zC!Ts4gR&kR{~I2Qs!5s4PG?O=Z=EsqEBrq2)>YfS#QV@HOK%#XwPtX<4u@Ni*inVNKdLZU5&iZto6fkyMX}&}4%rW%3n}{U`q1;PZ;5omG|=M_~%e$7gXXW-wwfmPO^fu@ zA}P@pWy@2pJJ&}@Qw#Z(at<&9>|}Ki#g+F)j1|e;wEFN1r=FtOYZL*3!kh3h=-HNV zc?aHh{xWxc@0s(Ex2ZZ$c8me%GhvYVZ@fApw2^We**{hTZFc2a)@oLeX!7UDNTqlq zo#NBjj`@@d50M-ZN!y(0NaHssIhFeo`U=l3V$if)G1CX~Z#-}rt%gwXl*~n0&cnL5 z(PMpi-H0ykc*9-AOg~6D_W-K-D=1b$>}qHLhv0(rSby~Qxnjbl%-_n0rfMX&+j|Y> z^6Ky@ia+_o(l&FymUxq5;K!Ij|6b--N=92Dbq~&{vC=&zDM4tfPG87}Tcl5_qDz^> z4@?^hsZ^N2Q_6?@ymaLDP-$KHE*c76Grd|^;N#ZP3`+WDJntDBykW_^<}#imGx5i0 zeN&Hecu&bkExEf1u6;7HT3yF8(k|Xt&#*pvzt%_$*y2n$tDf)9}G?6(@5&D{9-Sg>bU2oB5)~M6BNRi=Phk*h!mL zVW9uPX+Dg_o|7?5AhW+|y{e&&I6K H^cdrR<8gGH diff --git a/src/font/sprite/testdata/U+2500...U+25FF-18x36+4.png b/src/font/sprite/testdata/U+2500...U+25FF-18x36+4.png index 05ff2a5f2571c2fa689cc839e6e4b2957dc31eef..7c4ce8505754a436a975aaf39f5a31449bde88e7 100644 GIT binary patch literal 3125 zcmcIldpwls7auc>Ta4RJE=^cOZE0<;6XssSXHDG3z`2m~T! zXKU>Yfe3*R2<%%i!4HVzp>ZV$L~`BE+R`OP(%`;vB#;VUiU>4GYqcqzN+=?~T9vg`CkV@R zG>M-Z6P6RKWjgGx0@58!6FZrX)#(QQsu2oIK(kghRO5?^Hr7@fEnkxSpNrsffayI2 zu##gesjRN56X5#HVb4r2CxS3;0SF5DQUrwujZN(6?4Zj(0Kvxb)0GFP&!KUpQ`11O zcf}exj%*3iHq^zmG5{!&y|y)r3pVqmsGIVehz6b1H(xCHa4O3R%;WJz!){v#n;5r% z{&Uc+&aMbOcxb-V@WR@IYsi)G(EvJAjFn9oT#dYP!L9u@DZ^}#xoypq`p&!DyxUHt zalpX=cRIvdow_D6_#ut%sx)%2Bq@@V3HTFVql$dZYWZ zHH?8gZ3bSqr1j!J>EW(TL`G)iPT#mTe8}u<^@_N@X^MIt%3x~U8+ySypd%iXZUa^e z<9O()MJ}bdI8A3;W_L{6fFN^CKN7$1Gs80uhW^(z+wKBMdtCZ&1ogB#f5M0=Y|3)2o4cLJhu-f2wLXBa!+Tyk=wdo9~=h;;6WFSBIw@h02fogv15sz|X z*SNZne0=S)g>R}Q$b)lb&#o&3k_dt=^AObn=82APX*n`H!%$x;qD1Rd=^&P`SDqeW zKjM%*(an7fM3Wo)sek3ND@Y(b@Hy|?Y>2Nw>p^cxvTl=o__k+e!|KHh^r(is{3X;z zZ<%T%{;n2_SId8YD$Uy}RiDqU>n)VXN(dL8QKsjy3o^}e6$3AV-Ad!>*_2}FEhz+>u*h@VMlKA+3+<)v3P zZn*P*Y`1Sfr|8@%y2caOj(T!NFF|{B^mEFG)v3rQ@cOif;h33N+70jd^u~k=en9G_ zxTO6@IsAPDBLu6SJ?)q9RI9)l93h1CHAE-n!EM1QC`}K~5Hpm@031ciJvrnwXcWTb z@{ntcy)JeESZ?G6b!iLF>@Vf7KbgFEMsRh~yi@Zn3V@o+1{M~ZSyjNauzWJ!&nV;T zawnC0lR|R33A9Yr94+6hlcjNq!kylv554FzMUE_Ys;K8UT)ZZB%&=Z#Jp4wJm>~jN z2_*CGT+j=m35Rha7KdPuH$EN?M&}&4t+uJERED0%9d`NtcQNxT4ovz|PO5v-TcZC) z_-r?4<>8e$@)x)yeyV;O`Y1F?%3#R4E=!}p0mMMfLz?ji&40?SXGX}AEW!Ij57(!^ zShKSto*K}Jj`6Av3xX}9oI26!8Ky#^=+}yY7;qg1ou*WMI$xUhB3Mt zH5b-X8Nz+~?UF1i0_3)0ioOoDunLf7x$y??kM0{-RJ0|ir0eibk8#9GM!e=QE&1dJ zY#_8*bc->Gipiu2Bt7=`_FN18I^}3i&ZqUMPbxCEb6wD*mX-fZdk_Ynxox@AJG}1v zxf1qJrqg$XQ1&3tPv+0s0EgpTfCQ-wL;6=Yo!{QPrHP6{yMo=*zc5fg~_b~N7EK*+A&?;9b?^cE(!yF(H ztT5pD5qD5Zlx~FeO$vvxOso`ZS0OYJi3#A1uOGok6{G+!HM5XlitMBEdQrLsR#zm? zxjo0f%HCRn?0ID(e0W!?X@Uqtrn6F6=%qd6=aFx;JQiDot&YI#3VS&2|*& zgc+bGz&=Rp;)}?*#7P~-mdJ4reW03BzqyVFh`x#bh<(2WC1yj-TS}F|_7tyaL*OQ% z$&BjaMtd)S)(Whemc!{|(`cL&H5~k?6j(kN5+#5Z4pP*kV38Yg3OFh3C)hfKK~Fa6 zX}zefEZxX%0z#|blj#M^l28bNVR{%9p$kG^ijc269|uTBTZw%TZ5ZCI3<(YyS5t!$ zGYJjVN!Qj-*R4WIU_7t6vU`pHgKrb!T~hCy-qYr(e&UjFdB10DN~N}yie!6EI+pv|FQr-#A@-uI#FV%o*PpF% Z(a}8<+I4G0$;}Acop7*zVD;_QKLErzM@;|# literal 4570 zcmb7HcRbtM`;Q1BRuHrlQ7h$IrM}ckf(kWaw53*!YACJRt0fT~6fsJxM%1VdvudkV zqeI2&wL;Zao0eMnM%{bA_rAWr-yh%SmDl+^=Q;25d7kr}_jx`i_pqi091uYW007`H z#OPT701RXRfbkNTZUC6cOdJ6KxU&uQP*y?d3n?hhW<_?;4$bT_qn**!UXqDxp_@bq zMlmK(&HLEF1iGBj({r5}6jm3yA1*YyHs7Q&lMHec=d&8w2Z*SVxbI^j6T1F~JDHMR&Pi}<|+jir8~ znv5a{P(P8nbX5VB6yGOR^w|Nb;j}0eZwV+QMKdYa zHOh_K6~?!XapTgF6CgopO4S_lV2yOyotqa}jakku&IrDthX0zUla5^N5j7o)H2A{@3`SYZl#Tuu;EE zlu&$If6HpsyLjl*$)E5+X*T88Zqq-7z7zxw^v5^5ThZj^Wu?X7<9e zo5mKnaZP1eJM6vu_)(t!-tWICP?ZH___YjxmG7bBK~xd_V0mL_kg0k$uWSamaKoM~6dAI>>%ft$xC|XR`nRq6nOwuc|Wa()#2+Dx^kt+inC;(WX0buA0;z9!aS;)-fgDpF#0I289NGOOBPCFZZfuI<0 z8R#stCQ=oBzS43qmg_JZjhmVZA~& z#N@D8-HT-M?Q$fF<8Oc(?ZxmL9+d6JgNier#&=H-c`aiC1BH4V-q7w*Vda|UBm!(h zgGo43R|MA1B|B+jYi?^ha=o(QJKwwaY$1nHcK@ot`b{IWo)Y~h0Uoeyt~47~$ zt$Jz-a^hAIX)Ccx9bvAQxXFt$%? z9jPtGKruE&Gx4EOLL-yuGM}NDLuNY(HM;rZ;u&tTSE)nc#KNM{6Ki%X=dY9m7lUpl zZx5}1xAm9M%vUfkfvPS)AWzk^Ty2~OSc4yL?uVlCzWuzF&5KvKC3i$Ha90=Yd2yq{ zl(TnvFm*9u`1@j6ou@`9?8{^rZxB}-r&pID6V((xlL-{fSFe6W0(F*BUpaJ%#xvFn zPfdP8^Qg23nCWv}o@Ep^U4qx0%h763_ZnOHP?0TrbQ|NxE`@3rJyFcwD1jl+f79Y9 z9+iT>^+L^dK)=YG&JZ1`2-T1O!oArc(j-31Q33Mg^FJA$n4P>L@*DV(=bhj%Su2x$ zT__=)@2L`KuK<3ytA}lbkJ;)(w!M`C(KFwF@cL((?dQ4b=^CE}yyXP8AVD+X56u3a4KRj>??qxeq^h*wCb1Sl4fUABG<6w6k;PvNvU za-I_W!-I%sKx4DW>$CmfC?Jt6kD8x66)z_&q4XU7eIze~)%G;T8H?JkZ19nDs(gB( z@?-&gZ`-C?uyVNfh3!#G3iXa?HZB6%CpKHu5|33uf}d}?y$NV48P`V~gM<1*l^yMz zJ64XvIH833`bWk4rFMPdv*wD=%nZhV?{&d@t>c2kl6bLNfEoZmXKXTXZ=;(aW;whIu9@ZpiodJ3c4v}xU z=^T6Iz1tft85Yg4<MK2NA&K#KzbU z;p2Gy%C*aCCn?u9NZCV^H92eknW6(pz%BDkr&-GRhw>fqCmZe#B%*tnexjx?1lwBR zs>qo8KQC{^!359!@VoQwz| zq~ql+G+2xXr8ms09KSf2(8SFMXK(qDRU-^|YmU1s+GFqVb09_f_<=}=G1u@?n{HM~ zZ_d~R$!8|a*uN}-Gim9g#t{g@O%8|$>Oecj6qQ2;?`NY>Q3wnwiA#d)nVhzb?2Y8! zHpddl7dap`XHbx|TL=c%oW8z0Y0bviaVT7-1_d-71I$MhHI+(HQD=4L z{-%XQaTC^55V-qL`nU@b!SR6b=8z+UO3^Jy7$Ze%NJP%yL$`%`=kE&aywI)sfcxE; zsmbQ`&2Z+L(6T&-rB_tHZg^pJJL%%_)4^O5n>)6vn;&w1SM&9m zaNjd9XLlvn;I$6}OHhL7qF}(~@NckTu-KEB6Z=;jzCk8T6W|!sEy;IcVANdZ71sA$ zDDXTl=mcg=Nm-SZ0Lxu|c=Ry{1?dU=c;AEoXPVP+Ym-8e2phu6E=ly6+i{Od4WYU4 zo9!P5B)}G=H!g0TJpcc6R$PpJA)Ke~$9UjW?Sc001+VF6o?#W@@yOsK^g&h(UI-q+SQU zW&!?@mxD(l{VGELKDRKi(mN4kTCq?f;qT+=hb8Yn<2&4tgMTxBN(m2L`^O80xe=zb}GYI|N#mhfj`~~nDXZi;qosK?m@fSdDob?}omxq8}B}faB zU9UT5ZuWGVg=9rwK#GbH_Z|y#q|o^I`rl##>?V-}%wL3s8~)sgjJabN%w5)eN`}!t zrb|KYF^L10gr&8%Or9c{bTF427SO)heBI8w%)7?mj$RbtO4`KRp|#;A1$$p@o-8p| z6FC_S(Nwy<3vZ0R6Cshk6m#WX2&XI0X{K_izOYrrYR+=ASr{b^yWZ*;dYJCVsG=4) zyIy=s&J1p@Xm!BFyL2EqxM!@&-uh^L7-U*uzo?z%EuSD{5;iov>NKJRe@?-|pHfES zy1s@uBdxMakp+~`aa&>eq3?e$qKY) zTl|Dk3tn={IOjM?rw+=o#VrIAi%UcdNak@D`gzx|-A1q{r5uT^HQs9AgWwUk>Ma7tMR5TI(JqnY60TYVUw&-}?yd<(Vj}4~bl7G~4|&tugOo_DYe&XUo@Dsm zU5!HXtcm1mC!S^Mi<)7c!*qo4HD%h#ljTJOCB((nFN=iwL`4jtaHMGB$nWEx@6G`| zq)So9d3+oZuO%-)W;LTZw(Zf^>C2&?nGC1r^mP;K2Q{`eF0!3{;Vh*@Ozcn;g>C0V zogVI{R+-*feG>0#%Q7Q`tArjQ8(81f?(-J5yF@OIY6NICp?6EkXJ@gC4SV7<%S4x< zcG}ESZ!Svgz!~BWYO#4gcovghbm>@V*u{nB%v*CEb}Qz(k>1YTOb;6=3Du)HDe&>W zI<^uJS^Sg>vx)zcRxbe@w~2vAGy9N*{#3R+_Gon6NMf&Q02}0`eIr_4xSH>&S8P?M zEqD}?EpGEl=^NQ=1ij^UT-Y$yMAE7L=xgX3VKW0s`yc_=9`vW%{HJB+n(x3P`F$#g z-R6b@+Mq|TNR`hLV- diff --git a/src/font/sprite/testdata/U+2500...U+25FF-9x17+1.png b/src/font/sprite/testdata/U+2500...U+25FF-9x17+1.png index cf96b7d15bd266af18ffb33076d8e614b44d4018..6da0940837810b36ee68f8f026cbcfe8afe5188c 100644 GIT binary patch delta 1532 zcma))`#;kQ7{|YpTt?1li*hsvU9GBNL%(4E0^ZfL@KCjQ~c|Wh``G~YKG`TyVjjx>?4w2*E zP2cXtn6b)O~%w`;NH;akl|ejwCxb}9qFMQqS?5o1svB3?hI@`K#2VdJz(mb;_@y%-K|AQ-k1rJ6xz zog3jCG~8+ksQVX_qTnsSL6f)v6#&2iHKXVj_655qr-e~w3b25>r8df{s!Fq{E^6qO z;QaRX{%*eP1UE@^bd&(#Xm>$INX1{C28zk}8&M{^q9Zp6Lh<;u$dtNafY{g&QGb8QXPGBm>g~M@ z8`j9bUv7HYO#5E_$xHgSY;P<4S&o|_a_MEY#+ZMhoJmvN*?2r|r2k#zHzA%ZiJkL( z3rE3MN{!Z;LihDoz$aJyPJKHw&Vg!XPiNUtHuph&Yws(QMYY&~4X|aTH~Dp)8C~Qe zT^jJs&TZ0Y$@;`j-ggfi)AE=BO*Lavtzn%$l4(NwwA4J5wRB1^cZ?9-`+4AM(qhB$ z_W6ujEFEJeokb;k$-OEu72noeT}*ZPwf0`DZbVEZ%4A_IZ-3wmmilE#sVBSnl5#Qi zNf9bxRX#o_I_=HLyN}l;)QA&{Q@YTC)FkXg05a%%g0Q#ELa;LF(FQVES6%#iw-`mg z+7NQkc_$ z3g#MbQ(PuUegC@U!%_=!8`)(u6J46o^cF0%FE@5AL$jIQWxqJbc!Ii?HPWZZ@X#7# z=dxT-geP|e`9fLZ7(P?6%_W_aRNHx%D__q@LAlIES!(V|8 zg8xv9${Tv^bIKd`Lhj zAUM3sD1XY4N;OYz{SdrgvoDlJ(|e*Z9Dq%h1A;JTcOuWD(J7VS%M|PiJ6(wP>QUPs2@l+>A KcZa)RK;nNp@VKb} delta 1839 zcmV+~2hjM9480DJBYy`3NkljHqT$o;c4HcrS1fe=E2S-QChqlAt-a=nD)kE4*t@9oU_z9RkUjh7Bap~S%`lsGtq z(spivs6q2`)#gU#sDVW4EbyhUsgSLMNkZ@5giVE(K61wiy?+Zr0000x68XXFm*ao< zEkFn%PYyyQ2u%^vr(4B}XscOs)hS<%whgb3sl+b!U+ZI-h zkU9sU7=#cS%_$ZNc$^Rb0KhH?zx98iw$tZjPR$LoO%Y0i5JKIi2&GvfWRpEJsh{~p zL1S-Br+=DVsTV<>!@eP1rkYuWzYA@Jqc`j~^;}f#+>r}csCG|Vh0^P7=9NC5w>*({ z7(xiufKWIIp?Z=+005BZ4FCZD|LmRJk)tpWgq49aIEO$0`#=Z|!66WWLm?E0KnR3D z0QcZ4&IU9i%~)eg7`)w8cV(fUnU7wqpJHqAFMo?lPLgZQ%xoJ7pkx6EK;Z!20917} z=q9Ut}~}GeuR?R}?5(3Xav{H%q27G`poWb5+~jZ$j5D2&CY0 zIFxwn1v-O6Ro^^P=caI=*v(pV*PS?8+bo~yW5Y(<3sC2|LciG9XnO&A{zSi?DS%V~ z=zn(sK@bE%J6C;j?o@jh=E7LBeFalgUprU#-i5i)*Su|XfP|Q@%!^_l<(D}|ov-8n z*Ryx&QMlKn2U2od6X;m=Z&8c4~lB+zm?L=55jgyh1v z-LzVv<|ei0ou~7=(TLu&ffRoJ{z&2FowY+|AhJ04FS2ZqRtidX)_)Fp zfynahA+oR&)^bXA#`c+kLW9`S+icNifno-+&5_lj&jOvI*^=$+K6b1S1VPYll=vb@ z-Z&&CiO;re^iO~KqxnP2fePvyfaDio0Q51S=L`T^9mvQ4pf!NrVJHstiU71hpll2P z$_G@20YGm7t-t`Fw}2oBg0`i90Dk}g|NrdO%?X4s5P;E?wxw-pmL@q&@F$VcgP^_# zdq`Nue5djIh_=9fp&tIB9;Q&XOR^0~ej{<{F5?qJ1odAmNRS{w?+;qfU0x)goeVnu z+buz5cRPM*a=>t!AVGoz33^r#0000000000003M!0{{U3|LojB4Z|=Dg@0iPg-|Gi zFbIV(2!${RfiMV#5(tH`X>%Og?P-T;vGjk^Dmm(*Z&uTs%ntwn000000000000000 z004gP(l1Jf4R7yaOE-FW>ldXFBx<%mR~Z|YsySDnMF)Gk z7D<4jWl0sNY9QC5(4gL;|9?E+w{A9ieeH{%=fB%cYo0*UZh`hmSD&G3cjXAQ`r-J! zMWG0{jn4l1(3C@iTq8$kFGqN7jt#O`ZE$Y;3L9J4@^oQt5J)jfFOi(J-ce-k~Jy)2wa=vET+ z$3rm<_tU`zEj*lDilF8h4drYw4t*$}Y1=yuwcjv~D{emKcpo(Ad+Vf4dE<|xB8Fz*hdA5OA6B@N&A d(+|TqEjI=Nw9|GEg;)Rp002ovPDHLkV1hkjT1x-` diff --git a/src/font/sprite/testdata/U+2800...U+28FF-11x21+2.png b/src/font/sprite/testdata/U+2800...U+28FF-11x21+2.png index 804e3017cde14fb46d3dc0c71327d229aa5d7ae1..ea15fdfc99cd59f5b6529ea6a6aa761a9e8d2ba5 100644 GIT binary patch delta 270 zcmV+p0rCF+2b}_t7=Hl+0001@>~LiO000J1OjJbx00960|E1ZV-2eap(n&-?RA}Dq z*ue?IFc3u1FB|rx0#t_Gk-&|p02ifG>dMK%2m&DxV$7f0-h|=pNQV2S02NY$fLeNL z8G#pi)cL>^

P@#_)LCo8q$5OPw1V!#;l75R(9uP1sk@%)s#f|C?I}c^d*am@oX@ zUdAk}D3@{H+vcCgdJ*~iSGTs8HY(muTUq<@?a76v{324<3f~`RoxQnr{{P$J5L9bSN`^y6DxgmI6?ig#^?$CSf=g#i~ zIsxQ4N1(+VtQUUYukthK)r?@hcUv;K#Z~<8jQVZ$DHok=*s5mc*xT!M*hJr`dB3M^ zVZV1<)v=|!rvbIEkubNFxo)uKgV86w>TM|(7q%^&863PP`1`qRiC-svu6m`Dzw+_! zHlWQBAO09m-Mf2MMe6&uuD&;M7Yx3Loov^dryIFNpnrcI)G5#~`2BzNdVj`1fkX9a z=}SaJG;$mtAN^jCrBIh6ATKVlO6$^_mp-oAV6^_Sd?7bo7bHZI)mVH)x= z_vFH_=|5{0 zJl^Cb`=JdN*qM^MapG z%%>mLtMJX`wci&ziAVGEwkz*W%jc*cI`cl&Xa4P|<;M=x`=oUld={}S_L-k|)}$x( zrd-oqaiCD}`IKcG#$SE5|Gd3as#)A|#>#Y~$ukf6*j~;(=aaZ>-btS{F0k~%xRzrF zkVPzwTW40O8PC)_bH(`Xv-XHr2kVj(mVpdZ1IaAAJqKjWS`)z4*}Q$iB}Z_I!o literal 1541 zcmYk62~ZPP7{?b9SO`cmLj_{RpcMmEE~y}f({g$wR5`Rd3>1u3#)?ugK$H!LgHtP2 zR74<%R*4Z5N)e(Q3D`oAB*1WnAuu({mV!#SOae*Y#$()>-^{+5xBu^Z|M&m)LL@zG z1z{Bdf}j-<;lX<#$jAYLj04Re@R-dhiy_FQDGJgYn_zt%1Gd|ovYfw7Y{D;98u!z&ex>!Q4V&XqQ)fNmYQNA(R^guT zoQY;E#R6CR)?W|^asm)mPDd|vo;f?&@`9Ltl5-Rgs$#!yRQ?^I%>g8H`OOpB5f?EU zB2}|3RdyZuuf*918CRx{j(8a9B3{XN#L6um5LlDT)Uz)W+06TMQnH1{V{aU(diX%S zzMfmKF^UEfmu8g`H|^3m0A3Bi@AwOeu?7hcTs$!8#>blpBH-4NFq5|ZvI%#A8MS7Q zN$rm}UwvhkGl^T6ZSAsdRCCL_shOP?_)2eqXV}7QbSmiI0Ma0LWVtY0BMlJW_VZmb zlO1h&F~FW^tXEgBlXibJ9absMWXdAZ0zVrxjFHYk+G6ZMJz%F72F#k8v0s=7K(nqL z;hz52#4skqB6FOFB_z^4rJJ8qcmp5^^H8nnPn_ri5ZNmh{M}eB z8=BfPi9OL?m_Ji`2Q8-gcNdnbU}MGNyV6Xx56G7RVP*UAA!^G+{p(8sb6}XToD$uW z$8Gj)0po?m5Dy{6{y-1R>aYh$5GfeU(Y90J!sKdYK8x6!mq5nTYg9Nyvf=q}FN=!Z zD9=6b^wK^|(bV_?h2rbf&`QwC>n=_NIeHit}Asb)2HRu^Bu`GN)= zg<7%j@nCNi%44cB>Sx1Ma$Mz+q%IPB-z+^G+C!7E0t2L1DIh+Bb*C6^yflU@FO8To zl4S4JoTJdVH5$yu-O)06i<8GbL$V9_)fvU7o!c%fdOL8*qV!~e8@Alzy8t!MX| zJ{$x!#=cDK(9maP?HaoCTq(^J{eh~^M$#qB7!AA6=LDx$dcopqnpO3KVTC^8u59m{ yOR(yh$&TmNwoWd@>LmVy3i?0BcXwkzP%{c=xG1d1q+|N8gqMnhNfq@~QU#}fVu?6^qxB}__|Nk$&IsYyL1EY(li(^Q|t+%%}@*Xk} zVY$#OG9~AL3Xj{&iwTo^CJ4R|VCm6mo=|Y_^}an)#FbZT?Oh~pc|aDeb2hG&^o0% z^)_6ge20JvGXGURy9HEnYZJ)&+?hhVpT6UsI$Pq_rUJ$-sk8R)ECWgvY)u7OH06eF z`FY=-bD#FuKMsNDPT0N%tQn;E-sb3cKQx}GwLwhc=bm~OWGK*GYc7i(K6t5OTA=uS QVAwKvy85}Sb4q9e0LxLg&j0`b literal 2501 zcmY*a3pkW%8-B+anqde@QL$0vEKw9@q;e=m+0+cBzZ@3hn3`A&l9XC$DW@@N%b{hH zH4Lhm9QJppkW<4YL{iq@IMj$S`+hU(+W)<-`MtMe*icAx9b4Fra3tfJ!pATy=FMNsXV4*NYoV`sl;{W&Mgk<-5=3) zX+~ZiHYqK&EN3r8#MPKgd(94KJ`S{297xO&Bj$M`09y~`>3;pWL)Vx@E~p{=6gw() zZyp7XO+3fETKM49rlO{2!{MPK(bOOj2eej6b3~$AlZ%dq1M+9( z-Ax$1Xe6e14XY6OSvT!k_*vUs8d9jlkp>p?(nOa< zACd4AcxdkfJTR4S;s~p!aTuXq??yard)s)v7l|qhhOcUeb~KM?lHH7pdvD5>&W|Mq z+N{Jve#{LeXAGL*l1*1jcPzf)H6LAb{P`K0V%&UcL$Eb>9?fjd{pCvHi?m=o)_Qh$ zTTH&wCYBsdQw(2cz)_B;wx_FX($U@H=t@i90O%CW|IzB>3T+qNs0Fq5)YuQWs`(Ow z?p|3W;;xM=5xH0n0aCGC=ZZ;KU4Po!Ps^?H{o@|-OYjvBL8Z$Y5A#QJsvff=CUt=s zDSszC6N7p{72J*#v|h@)TI6$dM|akdJ`%;%doR@raB|`2kdlE4JghF@3akC3)KC8) z7<4MxtoDY@pA7YNV~etbO+%@kPv5s-dZHtURSYju*|(@jhCnZSP&qchZ~XnomUfJ! zZd^S22l;(mn5U?bsY_v7z&9G?*~`{lsGcaOyQ!b zyfk516lkrkuChMtsCk!#ESFptu4E@pmL6x7#0SvC zh>?*7VQ2r|V4#s^U1el!L?Y)yy+%R3_Mm`ZUz@rIZ6;Hq(?(3R-AkU#QdA>yNnh77tmA`K)+`n0gFH6sivlq{ zd)O8_#qUOqDg!fesf3Z|mP}_A1-Og!!EW3|0ze~j$Bezi0`_=cxj&{0ki3`s~LDF%ACoNCO#Gs?bv6wO| zL92IA#?Ap$awrRpdlP)#14Xwn$UoiX({2?MPEFvw>&67;9#Jc%DgaJhCSykE*X6Su z=;=9DBG;W&WK5zkY6;W}pONN51c*e2f`Jz_kna49@#FO99?rOC{}x5>DUX$L+V3>H zN*PVglfJISM>3YIuxGh-^$XSLlS+&yszD=fgg`} z7MCdk4*Sh?%E3*Cq_TWQ>6Q#>LvCY|J^&9^#64i9Ku4Sn=^d@YV}03;$~(jGP5FwF zY)|xib>d2`E~8%h>-PR(pTlk_42zC$3MeqkF4ez_&~gih=Y!N2{IL3Zo2l~WZxH#uY7#%Hsv|E zUqm_HsqRtvD8`cg?w9JkAI&fHD+CB0ZtVDUiUNl?ixy_n>A$zYi%I?lO)#u);F;!W zTO2>t=7|*QqBo_s(E-E3hnh2V@sd>a@UXlqU}RylBDW=X1E4Zan-G(I5OH7r-b#gCHIfve`<~c z2P=Fde>Yrro>5jqF68BVNw5*ngDB@(V;?>8aV>kG6dREYN8AbkSk5DBXEdpPSys_m zW^!9(8Cv{8=x(`7Fe8yjqv@{CnzTfBQ`~;8o))y|YUzeY?I&;XkbIr?xjK~F`y~DY DQs7cv diff --git a/src/font/sprite/testdata/U+2800...U+28FF-9x17+1.png b/src/font/sprite/testdata/U+2800...U+28FF-9x17+1.png index 4308c536144da75a46f915481571c3344ff02b81..fe5c644a7ae23cc3a43d81289a6d5eafa414acb1 100644 GIT binary patch delta 259 zcmV+e0sQ`z2a^Jj7=Hl+0002xMSSl7000J1OjJbx00960|E1ZV-2eap$Vo&&RA}Dq zn6U}NFcd`32vlhRjUjC$$RbLgp;UP;7g0z=$S)i)vU%4X2fun8$CqYNladr9C$&{6 z*AR+x(T;Y?D@jsuU&e}dYpLOVV=z{PCewk4Ht$oeLFMM+Xnd>)L_zeDE!w=&a({%* z{D-k3M2jBQq96*QY|)oG=g%91u_DA41yK-Xi-IUEdWtOyqO|DjPp4lPMl(WeQ4j@D zwkU|wq7g(9TlDXzQ(Jw?9rM9h5n_viD2TE}L6jCf$6xfCh;Gly;Lt)Hu@C?N002ov JPDHLkV1oS$ZTA2G delta 907 zcmbQtG?jgVL_G%s5d3S2dTQRUrs_{jj0_jlc)FKq;<|OySA%TcuoA>L5_+xtpLP18>C&u^;wG=t{b^m>Xz_CT zJIjx%39a_*O!W*Et05-roB!n30b#JpMLx0m;o=>W=jC4#>HVk3aN+|a#2tZLOolux z7k=Nr#T}87Z9aF|`$qYoQ)&xd^n}kU+Z(gH)#8-TGmm}3wsRWFceOvPy`yvf%N2c_ z<@cRfZr@*`DfO3+k)h`Dy6M^51y;(b{rX{jvHq~HuFI}f`_{a&{41t(!(P7gh&iLO zP8Pt=4yN}DwpQ3*xFwMyQ)7%#iS@xU`N&UOYZ{c01DYxU7XG+&j zWOz^|4~$4qU>)Q-WFWwD;s5{a_l-)ixmJ?*nEB6TF)$Tv}n%mz- z*!GS_y+G=#s-3$Wa=zD1UY7C2orxjh%GaXOMvGG^cRlQY9=ZFj#QgiW*J+iPg6%)d z+2^pNdcS9|NtGlcgAQ2Zl3hD59-rSSmnYIuvisMj*z+&BU3SISiFd{`x&0_sU|4W~ z9pbEwTr7qhEf2rfzs_D4?V{A|cjo^=(eC<|&~IH9fBcS$EBUJ4pJF0fc)M_EtwPMw zO?ejcH|F)-ePF`unQ$ z`x+B+>^y~^7k!4j*Jxp^WUFTPmU@jhO+|LeKE4oqpA!agx<5a3f$Dw@u&bm_w* Uc1G_QpxF$bu6`~o>zopr0IFD}A^-pY diff --git a/src/font/sprite/testdata/U+E000...U+E0FF-11x21+2.png b/src/font/sprite/testdata/U+E000...U+E0FF-11x21+2.png index addd1f49696bacc14482dfbb2ae7e0d4973d46ad..07848ad1ee104ed7e0bc6eaf71e23fef19cef1a9 100644 GIT binary patch literal 956 zcmeAS@N?(olHy`uVBq!ia0vp^9~c-IKX3pU40}EI{$gNYZuWF>45_&F_V(+kvm7MY z608=mcyD0wz9FP>5Q=mfg@8zHm&Ta~6_K7!eU&x>@Pwrv@8AVO-uVYuu z%IL`d_s)j3i(AXBlGocSxzjT$e&OE97B9oMJ$(JeKjVAomD)>tO4feMJz-+*xjuP^ zxXRn`*2k63&CY2r6JzE`Tl!2cd7X1FV|jP!b@}O^XWX^8x8&w~=kl8$w#>YJHRqxc zdz#M_>zvstAI_e5xb%qcmdnofPPct`4!wTc`HoHRHhHs}T)Az3Kipq_Vg>K*n#RY> zu{qAsM;b3LE{u$N^Z0A;#^sJdmqrWr1p*nk=@UAyoOL~~6 z$Hre$ys+woj&7LegO?{BsudPb-qGoQI{4l)oks@}r_X!mTr586!0w6%20OR$DVp<# zeViG3W%{JJcHigot28Pm=ad^2)n`q~+^14l*|ECh-0U^gV&(DtXG@EgEN1?~G}KX)qgk(S-@#Ro#Cl=JNI@BgxNW}Nr(w7GfTD?3;J2$J&tvE)E9 zP+@z`qs07EPpsBVI@@zOaZg!g=CqSJmVYW^zDL+;e>CK?nfAf6(O>o5qXR%U7d}$V z-*LA3{kIF>&VKn;khSfy_sV%^M9zNE)Y!SS_w;W^`L(g?lT#FG|EBN@m`=JL{#2xR3A6T4wxNYu5X7+Uu9q z9&0VF+VJXyM!b1UI^VU&Lf1d~9ru2|W_L#G{k50oY)-zI{p0TIf^%Q@KhgR7&Br>u zE&h|;pKp6h&e_%+RA2jj{muW)*s$`|Mb^O_fOYGJP1vD z`Kp=u{ig16d1;IP%}-v}+x$Fm;CtP)$l8nt-}2hO88hd zM3l;l?y&n^b>r#l-Tmn%qGi0Zm)>o+&8(dEZQGOD8{+-p%>UKzZ-LtfVI)ZIX9!pR UuAI!hd=f~+)78&qol`;+0PEbnH~;_u literal 1102 zcmeAS@N?(olHy`uVBq!ia0vp^9~c-IKX3pU40}EI{$gNY5%qL&45^s&=71q1Q1H-# zul~7Q_8K4sNMMHqkn{ilo5PJfK*j-u`q$br3%0Q!sQ@w)fcAjY81e!+4GaFQwOzv~ z&4j9E1CR?+!^jC%^MAecq$V^aF+gKcl>8Rt0{H+5Y!C!;fNCP*KYmf*Il?I9=cGEP zWpV)L)P|PH4J}?PSX4rogg*K9%c)E$`a3nhZTj7rb}2$kvvun~f_w=A1-x$YT$i8y zFSFJYXP*AC|DJQ2_8Re>!pD^StgAGao;a(_eg2GX$sAeHGs`=oUiNhKNN3))>WbjH zr@GU7re^x1cBOc;4AUP0({-2o|1>i0Irv`od0OTQ)e}1m{v25mvTeCS%?Y3B647Qa zPL#i|=v&2i`H=6@FEZBuW}OzfR9`od#XWf9`^n-_zE4EdbyjbzzIujJ-srOEv1zMC ze%4u+>3n*+^QDJC*%RfnYd-jYI=XX9(V<)Hp2`c`wJNSU3!F2)+_=%!VB4SVGB%NO zZ{<~NzHw0fvv1Rf+3L%3@^nL@*xmo7Yi{=b<*R*NUYK?JqWe0#WSex1ycleimL4;xjyBPVMVm60K{ z)_K@`S~*4Kk7B{39aCnW>Uo^8Wk&nr7izlgd$!*5^=;ZPEzo64mz}rJ`Z)!YKC~b3 zvb9myF%F(v_{7_NU;6E4?qzr6t_17k&EFOjG~07q=P^$8dXK2=T#Lk)-OZDFd=uvU zXtP~w@ZVlQ`@i*!$tpITTXl18EjsPK?53KO@|indHWy}isisR!U9vhGnb>1=7{M+Xo{(X1aE1~dw8(s6Yb>AQA=iSMSes}3^ zoQ={#>Gfi|>s9aG+w#KYk@ou_-S>%>R(qq2Vk#^DG;g0L2}w<;WWsTKpa3v|-agCO z>>$AUAZVM2_lA}!lZ14R2I(9XYvL4Q+C8tSz4AW$yfQvJm+$QtSs4nZ2kyUfJb!-- z=Y5y8#<#fG<8~ePzIotp+mp}7CpR^^=g#b3)VMwIV3_d-6P+1eY;pQp*P0r?-)2BrLjjFlNd z^B=HAycC)EBE{_6xigj5?j7NdI;#Dp)>rNE&(ELFoZoHir6vq?5?SEh^qZT{z1n>I zf6<)$UDjvf_H0hO{aQ!7uHtUiJn5LfwliDq@9VAKshv~vuQ*g>S>>!>->+HpUz#s} zwO@VVy^6RiXJ*e@^+xp5p_r>rh0b0|N&jkf?yH0Sv12-F*5m`+{R z51TATp5A)>-J^_zdLemk5<_x&KJwJZWq^Fkh?yh zT=$|9t4MPWTbH)+-oDoA%mt;1SJ(LNcYVtuAPta#w@hxuE{e>WqTI8;@ADSU*@ry;mCkuGhodxH=xne< zq5GjYuA?CH7T$|rG-re50f`HfZI16Mn8j>$wyf|ZaSxZlDvy}VvrT3ZPjBKa9xtr&^e7>Un)_sNbx35ZD zPwr*odGR2nwn?t&G+&v!Sbf{)!vs#d2Yz4sw|qx$4fK;R1er{r&e>|9SH1lePZFjZ$}~_3EuW{$sQJ{pP}w^?euj#<-XN uk+{#8TjGA>qU@*RCA<&^fL-yA{~m*2!|L^K%?gf#1Uy~+T-G@yGywn=1muPQ literal 1255 zcmeAS@N?(olHy`uVBq!ia0y~yU{qjWU~=GK00NFLPi8YPu&ncRaSW-L^X7mdBT(?r zg0KF$oc!l|(p&7FVY7AV-Z9xq*_Z)}<>PB(S+J_ictzkt|)BBJa-8pN3b_30ceA~Om zfM*ZiHWn{W&gdrZ1ufdGLK=-Aw2j67;9J4^BS-E$^Zfa6qMwzd{yCn>4s(8RvoJL} zCQ0dpQdTWb3`ZQn%0U$EtWqg zHy^q0^n_C-!sW?xv6uzQn+~kk3$HN|Qw&IZVIZ)1LL~QJuErTsI&aq;k(q2JSGh)BUkQ(QCN6a4aQRUQ zQM4YYsLkVK+SC2jIVwh;-tQ;&zWN-x*k$68Da*gauqlZdWs63NiZInFPo1z*xxR3z zjHE|UUxDqbITqH2$0pA`?Qp~?ZSAMxaHbPSLpeQm^miSzHqvTzQ*Cb+QFdpZGUvR* zO{X;7w?k!IVV>)|O^Zk|!N-RltYS>NzEqSUKufft3k=UtpC%jH| z?!-{eEm~Z5Q8T4D4YK^0=K@tsG@Q-Vs1R0la^Z=G)7Q*N+H~2ed&SY2mb@iVC)QkD z>cHEvRcP0F&1(r+6{YKZuj+}v6zg7n+hOX_eW$P2bYI^LWS(!8vlp=yTUGa9>#qlI z3Rgee7*N`MA?x&|hiO-n7yeS)e0ACO!)5KqoxYm6uHNQZ&uiS@D$~0ztatmrsC9DO zmQhRBMs2@q`qudC`B`t*&ieoB2Kzg?-+N|1>FulK_}<@_9VII-YH-)uV$amSl6kT} z{;EEI{}PeNKxs|y4>LH$-Z{Ir*?@=P!FETt3S}cF_Y*5*8@*g#@-zOv=JoZv=bf4Z z(+;qlECXd}Ft{(qyOZ~~;`X4pB6}IdKh`l)0Vj;V*2!HF&4^w9)@FsTH}k8ClzlFN z-At~@hi@+^_{ikD`SSZ^y*jBWx^*|+f6-LV{&=|lEfcG5-3wRllAYX9e=cl0;eSW? zk3fIKA#baNXVq&o)MQMB_*Qos?YGVY+6v5AH#c%JIB>8W{I~nx8&eAbmd%nI8oaN+ z?@8 B?Ii#J diff --git a/src/font/sprite/testdata/U+E000...U+E0FF-18x36+4.png b/src/font/sprite/testdata/U+E000...U+E0FF-18x36+4.png index 32a42097d21a3d0a3d27d68360edb8f3a126a9a1..2b274d6a11125a33e26639601778979d23112894 100644 GIT binary patch literal 1506 zcmc&!`#Tc~7~ZJVq;(M`J3A{~h?YXE*_@%=#xhOlSS6*fsVEU!mmPGOgPKya8OZgSTB}Ics)dVJs<9z70`45k^AC-~Kfl`DS;);#^;& zr5}%3pC^&XeC}KSY>^r}k5J>EznqrN=sRGfi`YN|u?{VBhuhmJO4F{d4th}t~Y2(h-@ zcj~1rtQp44D zx{=#L++fqFiSI4XA;KoUsp+v z8%tlS8@RX`-&ZuYf7R6f7KViB@CL@dyec9Km*nuR!&9}s8KW@iyvymNC~l)p=%?3H z)3f*{z=)mikSn~d@^{egE|=_DDtXvjn05%+0WHuTFN{6@ifF^#o4~MPBX1%+bDWm< z9ufa(^NT2RkHYS!S9scw(jE#%t_?efZ}Dvsx-w<82apGU>F`u89Z?}5mFWN>7OP4k z+@d!^;yNZ4oSBp1KhW3kbhfruGnJD&*CGa{nWz}<*I)H%!cA3T+S%Wmrh8NSP^t4U za(=YTNY!&c?#7fuku_x6^9xn<&1aW_91Nx~N0(JnT2`u|;CG zs!9MZb7~8y$rRT%hBckAWn|5p#^{u_eh7H?QvB&lm}`wKBSK{g1q)8d&i4z&8tPNs z#xa5;^C2}}R#kHE4`YbY^8WYdC-cO+d;(o320?zwyKT#iR3Y$bX~Tkt)dPMNaG_;e zvwf&ie_G0+q^g%+-gnr44l8o06okw+x$XcB<`b@5>j5$)7wJbJxH|G8F&ZVOro}4N z?;dN;^D>4q&9x*`+6%=Sw5BQwNjAOImTgM;XPv>U!jYgV;KvL3m8dSNzrYJ+5Ns#* zH6bTjvIU}w1KTdxk^O>M^n>ilj;^^`4ULn!T#7Wk=RrhNA}S@?n%SeQoAMvqH3LGG zJ0|~O7JwyZT)OO9lj4`p>bcrDWmUDSc;}k$Qhz@NOuz$uSi&6*Ah%`N+0osh0CVcr E-!0CfSO5S3 literal 2217 zcmeAS@N?(olHy`uVBq!ia0y~yU|hh!z?{GV6kzbzdMv@fz)|4o;uumf=gk2_MxfxK z1z-JhIsG+23Xs4KNg(I{|2Kyld4P-q3iYqGWfp8>K~e!^KH!F^G2{hu8W#LpTg%HR z&4jAP0B8xw97ayCn*ZyiCpDodnFBNyMagYJ4K(*0hy>~esexOy_92E;ryuH8N0d!QF$!>oHI_<~Y?xmh{ zDx#O(>;FDc&G*wA%d$i4NDhWFEzbVX_mX-3dXCV#IptjJt>&Bh^a^JPY=3xJ>abY6 z-30aJS8wO2dA|E7wcp#@{+fh&97#@63;U~5iWP({)cY$Cog>E^EE>9 z%jW&d$vXG0OZI1O{W<;=*L{%4iT*#)Sdn8d-@2A51*#FJrfpDN+A<}9Gy2ffN9NPx zwLcgfaN94b{-?A!qv87jiK(xb?_Jnpq}K63LPH_IiS7QWz&5cdH;am%UOg7`(=Yqj ztkq?c83TReF58{w2=x|<6V&LL$TUec<-=N;lnln1z00oUG0OR+yE^~SbSPf-o7*^S zm&Rv=hMpqd80JvR(PJAq0pDG zrlI1LWX)~%-I7rg6myxJrGoz*HsPM{YWjlVG`GZb72$VUG6!yHhdZT6^uLQXy>;>e z6L02W%PZ1bN|(**J+CD7V!gbfmZY%Cht+$Fo;o*ue6jE9;aDEs8x!2r+jkwfyj}R> zoFghWez!QM2M8Uw>vAC6@~KZd&!fyAZjZ_hT*Bu+3&?!#AC{qYeO9PyMra{tqT5^M zCY7qG!RK;36y~+%i!c~Fzq#!w-|==zkluw$QQ3N0j^a}vN@VbRo;l~NQnB0rUCId~ zph6x-W#>P)qa~N!zWB&%tDE(_{h0>rfmc?ze#>vT`);ze_@tiY52f1=9GS3bcUJC6 z)@!F4Q`TO5{^##qD@o320YNp)7xsE=Nz+OZ^gnFg*x0Ce&|lEGMS}C!CgCgFgtZp- z)HGS~92axaWPo(WXFm>E=A4UG2<`vYLwTL%$qkGKyb&{zryN zkkh;4GK=MwpZW1d3&?&Ruy|g%?~ek*Ag6!qt&8P6{C<2f2eQ?7E}kcG{(FU8kW-`k z+r@G(&tI<-(p=~eePV@~_|``4nLjHp9w_C1B3ALAO^>g1{jpVny-8KvPk!3!PUt@` zf0apd!@Dc9ELL6Jq&V4Bu-Nj}o!{pyV|vb>+Pw9l@yly+|L5QOYyW9tzs!_+XdwkJ zGBL_Sc1WhYyAfEQa2(k1e}7r2;G204?^mFdKpFRpZ$6!MQV3Le0Sm^v7de|91X>;j z=^O8t+hzV7U-TQxni z!s?7STGaolyiSd|up0_XQOw9&kk>qESw=bMx zJlpNhk~ufao~pB-J?3g{nX&EPEltnOmG^u-XFXQW%eo@-z^M4-FL!r^`OpxBS5z2P z!v|pF0HyN4s2Db&t9bi>7qvqC0IsCoVrwll=s&%`%vE-$Y!@hoJYD@<);T3K0RZK~ BV?h7_ diff --git a/src/font/sprite/testdata/U+E000...U+E0FF-9x17+1.png b/src/font/sprite/testdata/U+E000...U+E0FF-9x17+1.png index 461516971815032ad0c1d76dfbf36c8ce8a31125..77153113f2452df31aaf4a62147a35ff03d5a004 100644 GIT binary patch delta 759 zcmeyz*2gwMxt{5&r;B4q#jUru5+}}fkYIaY;ozj=;-oT%MMZ&;b7Dh_M+cClD75Xm zOe4R?EbhGvnQQ0C&&?Ar`<^Nup?3Ez1DW7Q^>2BLNA=Qnefs>Cbv3)wu0)Ccn`ip7 zS?rNu<>cCbGhYSYKe6D$)u$`{COg?YyI~`fsbjL=du8d&D>3gvFJB9idH>MLH)QFA z=T$eh%Ff;VZposT-1Ebq-YNSMn$dMzbN9godi{DaHcI>7I4yX*{HFPMq(-I;sa zNzz*D{Kok;1$Q?E&a+w5qO-2$;MaZEOM*>ub2rs&+EulqX4St1Wf!jhsQ;49eO=ArLEzT9Uu&VMKCU(2tr{dXl?50YB`FK*wz^X`%R zcM8HJGJY+-TX(f_6?^E_E@t0<+Yjg8EZy69s=f4S7PG0p*6gipr{;$|)8;LyjH-@| zU*Nkh!rat(_MY}_->2NZQ=L(5-Fo)z({0;t-#hnR0Ff3qFzsi!YHT83Q=Rx1BO&0#}cAfsWyzqMx{@JllxsQ@xJutL-@azfOsf7j83rUYm^ z$e8K;XV+K>9DTh&XhH*v${H3Gg@r;B0ywo9Ii~{oXHGl)pA+?8Ex1;Y3hpm3Qs0#mNXsnJMqoB=ZMhMdtKiyo?AA5 z!)-I)PoDV#D?cA=YcjhLebPIn(ELi=0+kaHJ;tv-+FwRP3RWusTobzt|cm$`5T|Pw852)Wuf`cRT?iQZl0&1F;`&eGtDQW*L`N3 zUcP9BqW;8t4gosNbHpX9qlB(CY@fhbmbHCg75?^!DYf7cb zgczxnk(W0)^_TBnwo3Q>g~y)*ir-1uJ)LL2F>78A?|tXzldJywt*k8Hx?6LK>aNWY_~cnkv2*@6Tait5pK^mg^G?0|qTBRo@#n8UFP|vS z2SxeM-9P!k3Fp>9&O;6&EEh_WR!*A~l;c~_+3`Ey^6Uq>icgaiQ$8P-w+AK3JgM?L z`Tf@06|RTA_ulPZvY`0KYaYHWTV?z5&DD)B)XSz;9%GZ5{&IENWXTLIJ(<;M!jc*G zoAlT3aVUNDF5s#0mGVYk$+riaSvp@r>mdKI;Vst0IvathX4Qo diff --git a/src/font/sprite/testdata/U+F500...U+F5FF-11x21+2.png b/src/font/sprite/testdata/U+F500...U+F5FF-11x21+2.png index 103853790e7c2607901067ab6982702474bbf80e..481edc7a84ef091377e36a4d5fc2a6af1d4db279 100644 GIT binary patch literal 966 zcmeAS@N?(olHy`uVBq!ia0vp^9~c-IKX3pU40}EI{$gNY?)7wW45_&F_LgDaWd{+q z1bK!|AwCD+Ba8u7Dq31zB83bt&dyK!+WMFUIwvtJ1iC(Ah`1uduuIqCK){3vXS{9h z9h}Ykx+cDvE&bTP&5J+Y(D!8q8BaUluy;z|*M~*-v$Ok7eRv&yZBJ?TtH%02CuWtu z_p|-*{e9%;dwW;1|NCW{ZC7FN^+5c-l(X&p%jJGtUcTn%k3!e`dS}a`HeYEyJwtSz z);C?%9_4$PUOhf}w-uI{S!ZhU-VG1LC~`KI&j*T1m#UwQY> z+_YS;&jpgV7yk|y{r!!dPkH%T=J|g1`)mJw_;z)(`}g-IzL!nP-`Q7vd-b;c{QbH- zyN~Z;%a)1jC#^`G9(36x_tmt|Gb%P(=FblD>i)5}ef2G#(iQK&In3VmwB~lq(TT^| z>OQOOK6QP)w$jx7eG?2~p1eB|d1yj?>4!ba%St>XK22B8eJVBY?1#$#E&RqcKlX$+ z9+u%V-m^z1lr8VK`@QI;ecLlyL$%fsxgt zMJ?W#9I{JkYCIfg^u|P8!oo(kCB2iAjqiN(!^}dUuyB2ayurZ(59j(-JT5k7VrD3i zTCOENC+D-qh67C8HBX);O}&&Aom;VK*NzC=pV#+%lzks}bJGQx6-j)d4(Ze1?EVv+ z6DgN>tt7_vWU@^8;`@gHxNeYvR{m0lkGtACr=@!Qi<-2Hb{+T1(# mIpuc&(1M5u(xMU%wEnWq+hAjFpXb#9$~~U0elF{r5}E+|eY$l3 literal 1114 zcmeAS@N?(olHy`uVBq!ia0vp^9~c-IKX3pU40}EI{$gNYQS@|i45^s&=71q1Q1H-# zul~7Q_8K4sNMMHqkn{ilo5PJfK*j-u`q$br3%0Q!sQ@w)fcAjY81e!+4GaFQwOzv~ z&4j9E1CR?+!^jC%^MAecq$V^aF+gKcl>8Rt0{H+5Y!C!;P}JNO)If9d0au8cnTCF! z9Rym78C1M17)-_39bQgYu|i|wQAPn?-l^77R(uVrUVIHMsh!LTfyE3jf(jZORkqEk z+-?0@u`nt6^OE@e^UBhV=10C=XZ!7ZiqT9TwaF`k1xrmM`|i%@y`uQ~dHc<|vaW9w z8u#y;arb`s5k8?GpC{jJW(En}zdzH~DhMR>w)f`aWROsN+zeaW&?D2P=;@g9=p5uW9G=bJNx(E!;?qP{=NMAc)9K4hmC(PT@`hD`qU=g zE!D1dqi59rckxH3d~#gA%4(|qHpvKu0vA-gD0Q+gPx&NLWO+G z_M?JKho$Xn_$3q#YA!eG+Z|>w1BLC$6r)`C+gai{Z$I4-R$=a&^0)pg%gF}i)c^6e zj+1ht1VnweKU_28Y?m?nlBFM{*I(Wyq7x$Nd(_Ra*upH{B)Vw-Rj&PytaH5&G8LGJ zN*_IQ@Wz&RQ$aT)xn}4L(V?YGMiyJrOWootN)=AN&fAEPB}a`+$B7gGKZ}T zT3f)oJ$9P#d8uU&Qs#NZT@rq4w?z0|P_FsB&h+U@iJyvA{aCitDzoHJ@rth(A6d40 z%s3Ntw14S4Jww~Q6+OHadsA1Y9FX4hTE|(3XhmW0c;NR4t(-Jb}10%x$ljElS5@jvXO^NOj2j+d$4LLp|T(FVp>l7**FmJa+|dfs?VhjB4Qspw7y)Jp;>aVqGa{Q7gao5vHhJ+*ORj<(l)pA&HD1rt50B8-=6hJ_Aj4) zny5Pci#!j=z<~x0yEf@;|F&{Y;lJFao1JUx>iD#(tE-t-+1T2$PW}70mNE3%=gI&} zD=VRZryoBWu8@(J=U(yY!v}#7KR-W~keO%G9G`yq65=rR_wU~eipt8aCCyo+)1KX$ z7bk>%N zT_~~Q)e;vM*F7e=SElyscKLlW*EQxP*3N!1C-|`mi^%)cYi@qo_~~U~S+(&_8++Tj z=xcA}=g*7x%game-@5et*|WYIexE*l`pC!oXXD%Dr+?lZ`0M|TEW6W-wYrbYH<(v! z`e|9=tNn5BYS$Whzgc~{Vcq)m&4+jF+QrrX#$C{7*AK&tjlMQOc*VXP4h_rsdFvcM{uG)YY$x=Iz8=wDJWcz0{jOW@bQVGS~lR%6H)uQU#%AWxM^Fr?|rGm$J_IN@CL4D z?z%63?7aj?0h?8w_ubbGkKP+RdT+VU(*c;0-YkoKeelLk_CQ8X4+kcp2@U(U6j{Vh z>3;bzYN5^y_21k3`QN@p6UA58>$9ys_2GTzmLCBQ z`n8$tM|WFie_grb)5He5XvrgY+w<*1r>;BKy63Z=P5dpkEiY>-^Pfyh54gSBGrYT* z_xj4VpE)}oJ^A8!-TmB7wypc+OSe`@)&F_7`Q^N+moww#Ex+qcdvR)Z`kHtvE{&aG zS#$i0t_G*c9KCg7=j#QzdYAs6o?24R{Ogh@Hzbf)zWm=8$il$z!1|+tmI65FPEGy% z_EFjP%9m;{7F{}9Q?zgXyU%8pvV67o)KygiqhUKzMbJ)y7G4 z6AxNg%EsQ!|Ge|Dm;8-a<`>PHGiI-sUcNfl&Qv}<;IiZssVfD%MdI170=MvGy$Zau zH}sQP`0cY(WoypediMF&IomH>PzOD^s>@LOot=$6FIYPK@C;BH;pyt`Uk B4nP0^ literal 1421 zcmeAS@N?(olHy`uVBq!ia0y~yU{qjWU~=GK00NFLPi8YPu!eZLIEGZrd2_&!5h!?Q z!B_uWPJa!M0wnN563F@g|IJ}TULd1k!N0X3ztI?wmD1yHU*XeaMbO z%?#awLkWT z(vL!1PS4w*^5|~w52>YTy5|zQQ!Skd0^3&J~9@A78Qdw2k*<3oiTP zvlMzBshs_^>0OUq^5bovTYdnNns%YVPx zR{LvCjj_+X@US4^_Kmk?HR+qXL}SmkIPzs*nKjdBX8eBh4(;;hb)VynHGG4&@vhu4 zhi`hY+WGFJ0DEzJeSe;y*MXO;*E~A$S?T-~@A^W=w`yy&bK8DRdE>S2>kXbsvhHQ7 z)1^32?$<-nKKCL&#br;qdE}{2aY*xx6qTZt!TljJuQp1mESIyClvEEt zxPQ))r+0MHUk6I7+~4!$_RST%lit7k^tbK`+sXCzpSUjq`S2OHi$;8S0B=gIFS|6T~sc{+V^?gPpCPrO@d zy#HQfJDD%>$@+M=1Ta;DK<=d|w#7TyFJ4>Ln8vQ__XIR_r<1Rl8ez{rg$3W%^aMj(@4=@!a{x?9!SY%dKjj>^!J`M|G+( zo9!wV#U*)hQ_{aSt$+WiPSZ4FeSDvmcv-;9te~E4kLJW$A3E1HdA(Pd+@;NIt&je$ z5Xe1mwflF=Tw87P6Q`W3$_-VgE?4E0zxPvZOK|_(sF2HT&rY5=<6L##vA)vd|8(`2 z-%U?&vPmXPV1y9@kRWSdsMD^%6Z$a?(rq{`?=kj zZ}v&$N$uZx*!Qu8YPsL-s--hm)vvg%=3wB_;K;-ylmN066wMb7akH`K1utSYs0Vq# M)78&qol`;+08TPi6aWAK diff --git a/src/font/sprite/testdata/U+F500...U+F5FF-18x36+4.png b/src/font/sprite/testdata/U+F500...U+F5FF-18x36+4.png index e7415b7aef7801266881cf7c865815fcc67c41c3..c0635036f4b07c318c0cdb442d41968ebd8774db 100644 GIT binary patch literal 1785 zcmeH|`#TeQ9LKk?3LTD1B)2>q#YD77GM$s-(qlXdMViXoFEMw+4vn1YC>rI`=tAUD zhRr4SOH*^3B*V1LTw-&{YHpov^_=JYa{hz!{r>WPUZ2nB`+Yv&_vd-O=}s`4eUd7Y z003a0o$Xm?003A70El_*5deUr9#a_r0JYhjJ#!&ud};Df#z7kekQbrmgPa=$ zyik{XUaMIFu6TPDaTRg*r+aEI`#N$kE;e$mM>H$6CH0Y|x;nm_?8;E~C?UUzd!0;; z^Z5d;eox@7T>}a)`G5V_3$)FhAYay~^eLz&3@_f<$!F=)wRh!N6gk?ptZM!|$O3L> z3(zk@BqKmZB2*|qIzmJgpu-}BW9dUhg{A^zCPeE3ab2s3EEXq7ca#G7{BUCQ`40aoSVqU-2tC{62zrb68G0wHP~aJvTlt$-JxA>qbEb zI+Z;NE~00nW^x7bqXVb&BZ-98H=I>&qsACDkfv%55@RYzDD(#-DIe2lsEuU~<1N~_nFMJk*Urp*04Z*{z|6$4#1mHkvkg{n#|_8_lDV9wRqj%9MfIC?F4Aech|xV zWGpdJyxBKN;N4=9ne80u5F;4->QP@cY1y}xVOFg={LZyNISr0wwCqOlt;V^wNNhQJ zW7=*AC;oZnkL2Q}?h#;R*7VGYiV@YtJSV0y+ zcJ)z~rqe4}3h%#a9ZGzf4lfM2vfK+#cn!Doo{d^|E@EjFhgq%ExuX)?kYv+kUcLD7{X)ex>Y~TX3RNhuo31K4 zjyu#%ecq}&yAw9X%667$rS9lU`;AatcsFC8$X`NrfX(<2^X}W* zHB$kejA@MZ(2i=e!ZW@y zcx0}FRzaaQfr$@&>XesmFOaY%mAe*t+>;yHlVKDYi*@W!PF#=YRFL9ec&+u@&U23- z(7RCypmpq1WQ)#BR0>+fRWEdGuOFM(Eb)(HXpwnyEfV72ZEZ{V$g4xk-VyR2zQQA| zAn>5V=$V=!`xN`^?J|A<$-dLx8YzME*E0=vd^B9;{BFAU#8Q2k|6N3W6zu}!0l}du zxQggM;Xh5HmK+P&hM1~g+LV=j*3A?nJ`8g{noSFhy10n>Z#yZ`_I literal 2473 zcmai$4LsA^AICQj^E5M0e=eG53T4PY7G_dRA=V9dL`ME4nv6WoJSKl(%Jb4l6ph!t z?jm_w*I)EVPtshrOHCn56dAi4Uft~W|NqbH_xiog_ni0ne!rh{&g-0W?x2T@ysU;S z0059jyE=OV06;1LARZ(wXaIPcjH?3xGI+Ez>QEeIy4wOMXuLyR@Qjf0+$sdVDXl*U z3_gGQw^Xp8(yfy+WvWHJDe(;&DQe{B2_#-eCT_^6mrc$e=F7Sr?qa=HP9#ApI++(t6l<8~@K@4|Cj`ligR%QSNsP zFfakTxpaTb&Te052}}q!3Vi92Fx!z(=mM(#O^DZ04E5L1 z*E<*@b6#;L^y8w20bZFJKJX#VZjSu$So7e0jMCsaIZF1miMvn@{eS7a`C#qJGIAWE zwl#)36msGlON_KP0Xs@=HjUe>b4 zk7U%-$GB0w)%bRB+Q_6_FF%ji^(lb)?D>9j9h%3RAI(}_n%6Quex&_S%+uJeBgmG< zhWh%rS9`rwk|tt-S8sPJ>$bIdw+~mF4}JV3uCc3{;R50poL#C&wRQ!x{yt1yA$Em5 zU;3Fj6Pq;A1kO`tp#Kr-YD0v zgc3ct&8pswk>k93dJHEc^`0or?I8|^kt)*>%3xkC<5XRN8c~{CG}<#>t6;W^cPj1+ zlxW`uV&BrJ9LqdVwg(;z#d;{Vko)Heb;EJ=bRSpUe?Nlufj;c_?Q=hp=W(VgXIZlK zF7(Mwnbea|q;~4aMAjn$*1mN->o!66{9_?XmpXj`Tm3Ym_>W5K_tE$7yp59Uk8a8a z1SoQSw0T$iz)Dr7VylrkUG#F49$|0yZUt_nq?Kz%qjcOXWONn>Iyazt^k-kQMc1*< z9p>Uzt^pG5DJrwJ*6GfZIixc|;{nWL1=0dR?bhBM6>^<*gq$l);FPaBxPm*FLT^tm+CuCBItH&TZepL28s)rd`F(ALmlFxyT75 z96`=BZRmd8Wq>aH`tk4bJ$uMSfW=+9zbFCtM$U)DSYsJ|ZU9~d)K7+#qO4~M|Ta1;DxqS=CPa6H)~Ec_Tm0 z>NU;$W!q4I&Jzh?2hnl8!#50>84GE*6oblUU`}VsB6aBEZJ-3@8<-P&-d?mEi;TYB zyDj`O)pt9k&=j)>e7j}9dVskUQ~S!o`rcSgm*#&cSAr0wg{B893$}MmkanO(C8o?) zNW~rApE4^>Plb=d$a9dAX`He3SZyqqXO58~=xQ%IEV~>YB)-0rMf6N3;2Rq4 z1GgeeVhdLbeFEmt|3Op2H9+rEQncj4^W|^Uect8p{*Yl+T#+-WC%v(RXMi?>@ zx=_hMUUQ{%XYTn$x$9Dib5F3zn9|E#rD4g8w&j!;KGjE26@dnofyHkWjf}%CU7{sg z5+m^_uGDTd!fc2H-07L8>@{(9-FL>4&w#nmg$rWu0Q<7Ppn)*}edm=L5`v^yP4sr$ z(k< zK-Zl;4dNBB2g+0HZ-v0-Ep=MK(mTY{?vq#vzK%udw38fqjg0YJyot+iF=-xE{wNNN z!%R@RM8TLWlKU-+a?HxKFeYUe`YmwoxG}`-^4=CJofK@?kr^BKO2P2&3?AaHYGI3o z8jX22Gd$vxhtXZ?DUV*45yYE%7p)~ZZ_uhTrk264>DT$E72y#!#gCbaz)hJ4?Frzt zFO6_$u+SnsO52(J;_q_(eR_f4Y0s_S*bFH*vLW9F|X%Esl1$sNg^WDje; Q6kcKIy&leuPC;pZ0-VU{GXMYp diff --git a/src/font/sprite/testdata/U+F500...U+F5FF-9x17+1.png b/src/font/sprite/testdata/U+F500...U+F5FF-9x17+1.png index 730a4c42c2bf293d6cdc02ba42eac97f8dd0b63c..6b8bc0440f05c1c08406f50ceac4623a11108323 100644 GIT binary patch literal 752 zcmeAS@N?(olHy`uVBq!ia0vp^7Z?~ACvX5648I<1EMQ<@+V1J%7*cWT?M*|!I}RcY z7xp&l3moK}kgbyEz{_gBVAG3BftNPM-dcMp;5pmG4Be$m9R%4GMAr&WOZ~W^CjDB@ zgM{(f(e{M&dY$YjdEfoWN0RS|cd%d_oW_a)p~!)?Na^JN>1n_B9&H18Eu z`Lb75rbl66{@Vuz>-}T*)#$x`vLv;H)pNcyL2Z{){Bmdcf6$Tp&_}pa$8YMad~ZNW!aYhnR2za z?5%e1*|o1aZ*NBbU(3DkB5mcDtW1BZvVLi0UL>d5adZCDcKYoq2M?e9`1}0~Pd@R= z&l7gXZdty%ruyBam#^&n)0~z+ydS?Os7QEK)5S}vn;)8%2)z^d7&mQpfMn0Kyd3F! zPx%hp?s;i=OYBZN-=W=a9E5Li&u?a%b;0k)5~~X>T_0kTZVNFryuFeWuAs>2`9jvw zaP91>T@_Ax=l-)iKf3GZlJz@Jc7JmY;^m2-^_cNc_=g4lf#*6o$AORO^go|rd3eCeVk5v6m0(uaa=90HDU{l23w zv}->5?$7t%-n0LjCoXk4!Eo|ft9Dy4hWmV0>=C>Dg_gv}Jqy2|{@!Dmw%z&Ho}JzY zPxHwdPuXwrE2k~=SXD%%S>eVyONZ}Lr|#_gr4o|%CPG^}`p^3*PZ{cOJ~gXWzuolv z0)z0a6RI8_PV#>WxEPwvcHLgyqH^W$Dw7M-KBSh-(3O4Kmbk4%q^0fVrNB+nX{Udr zWt3!RlcQbP0l+XkKrqf9L literal 872 zcmeAS@N?(olHy`uVBq!ia0vp^7Z?~ACvX5648I<1EMQ<@*7tOA45^s&=71q1Q1H-# zul~85{u&?!NWelG$oc>O&0#}cAfsWyzqMx{@JllxsQ@xJutL-@azfOsf7j83rUYm^ z*chmi|LcDXa)Dfj1U`rZIY6ss80Nil5NNAqj%Tp-`>@6I((Z$+7oOk^iY$4larvR% z+SMjkb~>uuntCZ{K?n1Mt}^AGgTJNwjaB&8Jp8{zgJ-w#>-(qAz2p1Oq1Yne1SU>= zFIZbPxwh_NhD7MI!{$kI{Vz1#t9{&mPCdghf8WRO=fYbSgx~+M{4;0Nh3@=6*MCL? z*O`g2neJ2k)gfgdwMgX48|iYZ`8t~R>XJOOezd(%<~o$o5p-d4{+-t~XN)xOZTFn^ zZ;s2m3qiF^9|Tz(O}0N@F+cij`sI%W7f!FemtZmP+_TlSuNTYzW}I)mxl$nAxZ+it z*!Fx&qeT~!ia%)XZrB*vqa^v1r;#l{{d{v#zzn@$`*MTWvyU}c53c8_tN-K`$j8O4 zH90K&(kH1V8wN?IbE&5s6`w|G{+~H*vrJ0XiHEoTIzBJnR?G1%=tiow7Kfj80pF_? z3Kso`Jhv`xdT@-Pyz>H!ATT%*i`GdUzq#%F>Ffmy()89p>|#B-veZo1@5IL=R@Q-H zH@rX0;ue3)8^V0ld$Wwgo+fU)jc2t(&F)FgyeT%tFSMnVL!(t^ft1EH( z?79_wZ`QJj-~GL}hOiu6B?#1cXtIohMsla!Yo`lV=D&WH|NVOIw!X=tz%wbn-FI@M z8P=FfG0%C!%(lFVpulNVLocAxy{)$X5+QfVIhE&RkoA_G2I?8upOWi8KzJ#AB7 zdULCoxgP6U)p^$Q?kR@&l$~Yen;5<=*?y}vd$@? F2>>4>aa#ZY diff --git a/src/font/sprite/testdata/U+F600...U+F6FF-11x21+2.png b/src/font/sprite/testdata/U+F600...U+F6FF-11x21+2.png index b216174e42ec037c12671a7cc87a0452fff178fd..6b580bf3e4e6935d394ca81e724c5b0e7c35b854 100644 GIT binary patch literal 324 zcmeAS@N?(olHy`uVBq!ia0vp^9~c-IKd>+ZSy?>)MS+xDfKP}kkml#-_xJaYkB`sK z&!0bk{{H>@&!0d4{{8#^|Nm$C+W!Wsc0X`m zGFNZ%`o~rO4?gU2>?xeM{+{y@aD;c2f ZC12l@AfcKIH;X~KJzf1=);T3K0RX&3cr^e3 literal 495 zcmeAS@N?(olHy`uVBq!ia0vp^9~c-IKX3pU40}EI{sMBgdAc};RLpsE?c&;I1D@80 zIR`R&9tcWw21+O{PGO0^Yvy}dT;Na}%fI(;PaI0%>~Lmi__rcX`0u<^8%>#K+ln#I zF0H$DVABe{phrLCk87{elq`)ie|@@U{tiEr$ugHsc!ISy?tj(xW2eP4jrVdJZ@*&u z%XRg5d{XS1Rm)>{?>}{5|E(Hb+4z@c^)`L>Ys1b>y4<()E_cJtst4Pr?Z_(rSaRe* z+Q$>MvW6QXZHnUE`=up7j)#K+^?D%t|Nl3K4S9i#h6VrDu6@WT%>-8fX2h_fsmXoF zilGLm2gMxShn(nYe4uI?d4R?qP^f>cEwf-73#wf^(9Nms!ElcbPz%T|Mou83VZs0P m(vzCdoGi@F4`I6|RXXhMxUucwM%&}%550~R@7iYHc7FNU zeFdt?(`G%=ZmrzvvCyye*^ftCr=}(N-~Ds{Hl2Lyyi>O9$~^15_jzlUgQ$8Pu2JK{yR?%JL@K`R6jjUXZ`$-64#c8q~@1hx%=ajGup0yQae4yh2K{4`=RSkW=yy=IoIvq4;kCJi}%kd&OP?@c=NA#KjWt+#qTYr zr^Wo>H%h72UsBDU`g_xo-(5>@`)+#cc<-!f-tOKz+nQ}Zevi`NG76Z`*u*1}vOs~E zl@a7eFgWnm4oLt1|K_kEFObo&;NRNZhpf^}5Lp;HP`Nlj>06{9QpEyx9mBP6hg70r~}f*Kk~@<8SXF(85B;U@ u-iOTSYSyEhgT?0%HE$6i_}2$v*8wK^3eQJxYnl5&F7$Nub6Mw<&;$VR{LU)? diff --git a/src/font/sprite/testdata/U+F600...U+F6FF-18x36+4.png b/src/font/sprite/testdata/U+F600...U+F6FF-18x36+4.png index f3a887d20c1f9b7646b2e588ac2110d5089c3005..3117fb220c5edbfcb7f0fd4cdd727e9bff377d98 100644 GIT binary patch literal 511 zcmeAS@N?(olHy`uVBq!ia0y~yU|hh!z?{Is3>2A>zwkSdk_+$&aRt))`ug_v_Wu6< z_4W1h=g;52fB*UO=ik47|NsC0BOm^T1GUcaba4!+xb^nNMla?-0oDtFiV4#%UAlJe zRQ(5Tl~{$T@(GEVnd(VBpSO$UPw$w)zRvqb?Yzq^rwu&yIA_;(GBCK6&C_@1e7ujj zRV2tmu~lSN+QQ4BdHVf=?>;?rkob_(KKD-gv)@H&3m+*N8_!P@(~`eXoR(InlP;VMnr#2}Pg>B&T+MI%!SntscRE}9bk=SSlk%H+@7lNSjGq52&+oRi-4(vL z#d0T)+5YnV{r<7y`o$BRxHOkcaN-qZ0*1`s2mc-jr!4V*nZ;uacCV+apUXO@geCxM Cu9|xQ literal 1210 zcmeAS@N?(olHy`uVBq!ia0y~yU|hh!z?{GV6kzbzdMv@fz|!dH;uumf=grKAxrY@* zTJ}zKPhfF7rO|VUqi2#}TeL#66#|@$#9UR^q7&_w=vq^P9Op zRbj^c3t5sJcORX|FFYf^YBf+`|Fm_}4kr9d+#bbt=s)9$TAsH5%13@n@ceK8@ZC`1 z2BY}wzasr4QZ7XQWouqm*X$U)|KNg^_Y*E$$u|H8Jt+7=VBHTO0W{z+BPWp2u;Bmt z--2AA*g^tpSkaW+7Szx{k_R$Bhye+ZF^0TAM#F-CYu7$xlx9Lzq|b<^CifvLx|-GK z=IB1;B&g=>1AcTh-cWPk-jbfwgzB6FvFJ)LeO?T8G29ePpPzvS4jzvmh(`BR??YxZ z2OrQuSA*$sOf{GuKOll`&fd2S=ysvUCq~$85JnFhOplkN$0lZs7l@-f2GipO+-Qly z_aQr)doh&oKIBGIvH|L)MjoJz2NddGE5|I@#sXv`Kmw5a|NmP=3PqR_yq2NsxKZzF PHIQmgS3j3^P6 diff --git a/src/font/sprite/testdata/U+F600...U+F6FF-9x17+1.png b/src/font/sprite/testdata/U+F600...U+F6FF-9x17+1.png index 82ce82468166189d95acac312068a368f06f667b..a5ba3d89ea285a21ada1145f457c666f465abe62 100644 GIT binary patch literal 278 zcmeAS@N?(olHy`uVBq!ia0vp^7Z?~AC$KOBS-ML<&j(U+0X`wFK$@SQUtV5bUthnz zzP`V|fByXW=g*&i|Ni~||Nnzer0xf**zD=z7*cWT?UjYAoE$}1FXUD%IQ!v1mdUI? ze7s3prC0@X!e;xPyD#NqZWAK$-Z^6RTZ7G#=gz3qG-ppr`4U!9$n5Id#Wwr4*2(uT z4f14nsfBJYWIO&d>AqFT+f`Y!=cjH03hITHo-3GjCaQhis#V!;{fygq|CcPfmv-g$ r+ShMoO@HM5k6ZlWG043{fDcz>XWhKwxcdC=7?5gDS3j3^P6JY5_^D(1YocDD1Vf(ToH z^@f&kCodn)X$hXwCJD)WI)3Jq>kglm@^fl6J2m2(W=&~e_&eX}4Oi3h%K<-tSeAhpRwI2;P=XR3#WYfJ!7ZQhS=t9$~ArE^K-wQ za@fDre)hWaaX**ofB9F(anJev{D_0g@3546y|Mjr<@bMqgCisWIdQtNFKf?L$UsCR9a#SkTn?K4eE%^9HB~ t#T?#;+~{g*7(r^@BHZ&^kP8&f-i#*7`<|RLwYm+m*VEO{Wt~$(69DY(jlci^ diff --git a/test/cases/vttest/1_1.sh.alacritty.png b/test/cases/vttest/1_1.sh.alacritty.png index ba4619840f2c8870959ccb02acd8e41408c807d9..0be3ead8fb65bde1affc41d9af45db0839c0127f 100644 GIT binary patch literal 9884 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 literal 10542 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 Q|A+zH(1B{_YuW_=2bp>efdBvi literal 10152 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 B%mV-b diff --git a/test/cases/vttest/1_2.sh.ghostty.png b/test/cases/vttest/1_2.sh.ghostty.png index 78139efac01263e6003f76c68f2406483ea133a9..ed43c7e448b06b550be416724b3ca1124562df83 100644 GIT binary patch literal 10308 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 z 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 H8s7VVWgwv! diff --git a/test/cases/vttest/1_2.sh.xterm.png b/test/cases/vttest/1_2.sh.xterm.png index 90a2e12089ea9ef389bbd9c65bfd43fa6a28fb35..97437fe7ebff7f6a36fa197f0c614676df334253 100644 GIT binary patch literal 4388 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 literal 4445 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 literal 10570 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 D_;F4c literal 18143 zcmeHuX;_nIw{9#|+7E%Y?rNE9Rcw)=fPi7tQb9yO#V}8b5SbMOWX3vBi->}N5FlD* zl2K*|lSP?A0GUFVB9Z|JlL-Vu7|wc8+ppj5KIhxlKIgj5kH#PJ=AE8rJ?mNPzVEei z>!hin@IS==fkL5#jgI|z8im?+7=;qJ{>ex1O@Na7BK-F;_K3+56zW;5(CXQ(aQwCN zvC}3fRIn@x6?q+nT7j=3Cr~K=?@_2JClpHa0SdM2Vrum%Z8)**oU!4Ls14-b!`iHP z6w1KL=*J^xt_;qM1l8R4AK7@jWPS3?#|igO+I=B#qH)+bfA*USm8E>GGH*W<(u%d4 zzeh@`5oW&(w??xtB@dUZUT zXl*9RGJ-RLT;K46+!l{}r`#Ux@TqOL?X;d~-|M3z2q#dQg@cBlBw3~He35g5+l`nw zQgdonxoC8N_4Fo7vr-GW$oR~sRzB0leHqyc3;`#922qeYVCnH(isB}O+_2AG?`OVk zEV1schUL?(yTVy$AKj7_w1Fs`JdBlp^YyHd{N=B?73o!#eu-C<`3}gCx`GlS%UZ&6 zMrDmTb#RQjl4bh>hVsz}vhtCp?gx>3Qxf>HhxTq^rr>P zL@b4mcTO7=4EGt? z+6MZBQ5?jyzmD-=3t?u?wTg!0lCZKlt8+uN87m%pFIht`-^)lYi&;_b=$&N3>6&yC zOMAB8HQs-))8|4w9930j z_ptwI^{~$0jBz-X`U5Ur9DhHuQ4syj3BtGatG*Vjp}L9oHNU=72|cwT88g3dMbBa! zc}EMz9z6DI!tSbDVuq*AjNfqx|^Tz_0I?(ve_Gr#3 z1^v2lB)B+m;9HGQg(RuOoX5WN&Fm5-*CsRH7v%{Vxcs3y&d7fC>5DJtB4kA)^hhQN zWocn3ol2-{7=F`Ki;LAhxVd+>O3(QJv-4b zyu8?6b4V#Y9xpk3)*^by^J$(z0=BA+Q})87H20|wD%zHJ^JZw^+zF`!82sb%x#=(r z<=3a$w83 z7@4KDld`E5^DgCIr6wu0{4Ctua4-FyBh}2^-xoD zosTTFzqe(rd$^ZUA2(BVG}He6=MqmM@S#3LSf_ zcEL_EUl3ElJl@U$oPv&D+ zj`Fy()@43isw^iwCBZUVzM9r`TSu8ykeFcEl6_4xM7{*Ga{jj<^hQHXNXB;QyXM^E z8@k4$zb_1iUbl0(ImcdWo5iBA)1?Cuw1DK$v$`ts2MX`r*Bm8^Jk)5#dV>zrsnWucsE-b{w2i`rA|0=as*Tv%=Dudp4r%Z#XmUN+7Wc@w@M zBDUB(ymHaCCWScHGQOj@M>gSTZoz~8@)P)kV@(vg9()R0qr&4I|MliX`Gbi(#u=%j;%A}Dt-a!__zbj zt|k6j{`qnT>MPYkCvF@U8aQ`Rw!Ou`!zB&Vqq1M=gh^a^d1*Oaz=N5pM{DA9=7nYq zk3X%uS)qNOnnz2vIyEh-ZmfTu3Tc@psRx;^)K;TT%@)k0keU%0{v-z&| z>H6VuK6B~LdTI0|QV!YQs=Cr+pBVp&=?canJ()FYZ0_7Y?TFscpCh>h(sGQF)ej_% zrmt1Bs*sEwc%2b@3pFZU$<*7E&X!fh59R;mKRSqje>yPb%k+w{5Ou$$? zZu5bFi`sc%w*7{>%>gZ+IDNx2;dajgy_XH?3oj$u)b%;ESaw7#t?ikZU!Vh?od0Do zRlI7dqir&X!=b&{9u!D#7AtgZ%1x%Gh?S_G4aWLh%%J-XcTmEwY%93`Wg_W?*oYM6 zP5=BO=7B99K`MRl>Ixa81 zUZ-T@_Gy=roMLg~(w5&%)sg@qx9Don@(r8Wf|Z?REm3wuC3ZM4XPj8c5TvuEvKL7~ zmX5)FmXB|4nr3!0lB};?mUB`&NHf%6)YuMo2GJcOVp7psA*sn~d~5~D_l-3A+z^Zo z8(3!bq>7^@sa^MIcWp}b;wKR+FSk!5DcL7x$-0n9>;x%-R`JXHu^l^lhVPfHU=LG= z7Y^6enS)arYHrI*L`N@wQPEL&R$o){fv1~Ixuv?JhLS09zuw(??fwy4em5Nw#fhr# z^Sy$CPjj^j&B^W;tfm_a`L5=4p4{0TUdO~G2#Y`14kL4`Ifw~LB&aqP)GfH%LQF)q z+(<+;B==SRWUt{TGFKEK=zZEVw9y`%-?$aVAVa;c)7c(1ihGn>fvaylMBn|zZSupB)l)kp82tKHsaVEKw;6(ueAi&2TyA+~g5$7whYzXpEyatY%|0g` zzFQ(c&EJyM+h%FqsNvz=_IgWD=ntKq-%=^6W~ObXdM(QM_9oWlrT%j1I5H!Hdc=CM zsAi5;#cVaTXN~PDeq|Fqn(994IeG`Ofg_dDD(v*gWNFe!OtUC#DEs;8fnVLf@_~F& zre17ZU(cO!FU=wzn?3%~(q6DVW<9H}AAQOYto3_^r9x;R(m5^{NcXkZiW0 zi*}i7Psg!lS^axLr!%IPuP)dtO5`UL&fO2pfAD2uzI?Fz>6-=VnN17s5XR+0U%t!_ zO@Ii)n=W&ijZlnt&9pSvt#k+(yl^3Vdw!MMnAr@*x^eH2_X8;n2({?574ki)td0J$ z>Z}M^bH(;VR^M53xK=V-%g9+jYH`@NR&xE8q`&q0TTjJRX9JmThZ9fja(_{?=qM&x zms|3iDVpPPL){TCS6|nc*iiHO^qOZ2${q<#=O*dAG8;#zZ$Iv zl0DU)5FCF1z&L-WKPS?kIZol^!Pp=*T1wutF3cd;>jqyT>htFE*~=~3$||G{IP7LLIo4yh@Zur%%tUsj`#jHSn=1CB1jGNHP*wHl(@Nqb{!9*EXf z=s1OWB(1WEVqHppN}aEU0t1BOwdX_c45)XeCg@bO6zowg%V_kkkObSDkN2M{`tJ6? z*Kp-9vB!rueA$lSkgl(nzL&^t+ZRPEWpUbxM!u^LY6y;Z_zPbYU`7hpQ+8#!u(u|M z1OY5y#kNizP~zD@0%$gEZDJvCjr(M~L;hOVoSKh%bVy>Zwxe-Pp^sgfu%OE-y6P

>73|Mht%Z!O)W^f<@So-u#RkvHYpa-vn`*s5|W3X@JBbhR2XE?jY!pS^_P zVXPr}ZtOJiU9^Wpp)oqAX9WZ!qUdahl$K|qGwIO@>?}U_&eMRa;{hEtc-JnuxhH~s z19#8nR?Hg@+w%w`i0=3Ncwb1EgRD~B^g;FWtlboUn%4A@vU0i~llel& z_xY~4^Q)zHAwG9x#woKr1%yqs^%lM6TpMpn_1+0b@7{Tt{q-zz&}FXqWs$feXY8QSbsWALEZ%XhntkP}8#0@G0Cz_W7~aso!43lsw?8=KP%ag29$9bT?cuP8|>)Xnb5I~&WI(k~$V zs$QN^bklg_5{4o|r2H5Xss+62;kSRuM23d^3posO_=pKLUS?HYsq@5X9(8NtOu}=4 zZmTjy0KEWtWIHCN!`^X{XT}oZ#ocVmf{s|}amCuO){6dQH9Pm673@A4w$`aY_3{W} zGsZKPeYE`EmA}LId_=Mv(SSJ)Ad+FY_sdjP2 z^HDLrjbtD_$(nM45%PNcbFQm<4LxnGt9jJ`Wovvd!De#|N9Qii^o~C*W@Dt;$$X|( z2xEC<=i5qgadw&x(3fO?qgg$*=Fnnup7SlT&2Uq|#LwFPt_-^rf@xdk++@*BODPO` zgkU*XFwrYm2e*yXs`{Tv=U=)rSm$9o`3?EvC9^gaQgXnlfWgYOI7^v?5LSxhJ__UipUW^2b?oOaw+^~-TQj@yQsvX_PgOlC z@BTHXSZM2poEE#?m`X2p-56etSzVYng&c6ek-i&W6#={+@+Tns4KGdYg0=G2WxtYj z@kxSRxp>@oAgkBhk#2)=tz_;5Gs5iF!`QW9D(k}wvwe`PK@gD`x;NwkGioWytNFoT zmQ0z(xCrNJfA?6lbzhW)sZvjB@~(=k#thy!Pm852tk2N5<$8LSc}bLcMPbfRfRThI zcs(w6lfSs8?6zhdF!~}Q2==h1$NP|`6*Q^UM8EFAX1A}dj2={TC9NlLVn=sBUVmUK z({bCTx+GI`%s`Fg6`R+z`;uCyu5?%w}Th8Fvj|lkWzS#D~2#(Cxpu`lo z&C=+u?FFe;^W;GdZpXld{OKAa5vfzWOD{*O#$-lp9?5AO8t-erqQ8WysDoc z_5R>i@|Q}2SZ$V6!~zlry85X0;89OFTRbj7jCd^JH>xnhtWhE4Nt`Hlr%J9q^9*18 zHL1LPaxf_^Y?3`3;f`n=<=Q&m@zcnvox^7J54NnaGl;-srmL;%ik-8hEk`WF8Pn63 zT>Gc-z*=sF(0=wRAsHEu*5{RbkkY7Q(ObpEyK{3SY;C#+1}OGp)f-RRad^iyHG)t2 zM#x@ZW@c-z(-yw5c_Xao>zq4dT|n69t?pybn;J6k>Ve@t)T)*!l16a-sd3${(W{A# zDLxmUXW@5N88&SUDQk@4FO9QQi}RysWkHjHCsT0UDp|T7R@cltAFOo}rDA1$26s=) z*z%^{k%6K0oyXX(6n=kNhtC3gS?5hA8tJd zo`7q1XuBhG3_{u~8{Ud(5cwCt`TO+VMK#N}Aka+woLA>-F&Q7GcRvv=rZ+QF-OsC_ zHN-L=v$7)asl|b=oh1Jy%uXG(@ANIr%$hwq{AakOF%| z!z#{(YKNpJH0s@Z%VhkrM}<|kFtuQ6Pp#CH5NTWX^BpIbxKn3GU$6F0`vuSmjfy(* z`s-y&FJ5WU$|Dp*zol=jD>Dw~(SdzdB{3&vwB*H~9RXZhl>{Pe)nsLRt#(v+P4R?f z1Sz^lh4&L2_b9e4HUl9dl-(>tUp%93y+6LAGy9tF#7hWD0RtCWV{;)w1hrs>*(cXS zazSM>yWMV~&z@9O8SkrL*^ozZJ>l^OVq1im=ZViL++LuS#S`5_oHxC`TwmKe*d)wm+EGE2N%UOJGA_0;2*PYjJf_W8< zWlM~~kbLC+hSO}H_0NBRzfhx-?+XpGP5{PGCl78BLS@%G>n3A6+VYHjn?I$5+H=4U zY~iwp9d)H)cLo#*8{Z0ubau|Qlc+5ZF(WPy7*8A-KAlfoOgji@ zQEj}Emk-omdQBTXLQT0fssR%mUOmZ2gL?J3g!pz8s%%FQDl%BS^!VVQikmARy#ssR z1SxAglt5mXE-oJTBtL&G6|!A2Y|oLeVU&vp!)?UHA@Xtkwk;5a%!Rjo7=X^aU1s_D zAq}Yo_ZQo$7I$CUf_fP6(N5G!Gmfp_)FRp+6yLoExE-*wUk##JOWOochi6h^K%XsC z^*(0qT%fH25?{Se{ER8M;_nk%OIydKu1h$B8FWLhe+FiX{1qk)pZ_p{dBN8g;3e=m z3X_4)w<(cGJ?ii)&5!f`Y{^E%#t)fgf_X|__&w#sS-rN%Mh-{IkE5Y-;Y-fu*(l6M z7S8&0Wgez0F6-PAHVj$~j?=*5b#oa=$>^|X?#Fq;Ie<5bwWB3X3#0j^A$iA+-d%e77ga!w@T@epJEtDQ_5Z6->76uH+ z{|VB=Z)bjgeZN4bi@R}oSkI9{08F+rD!)IT1fSe|OI7`w?-L#|X<}|;KF+lG6z0mbf{`VL5g$mc; zl0J`j&xk$63gXgNrum|n-Y}$XnT0Jl7ma57`_QGs}f*>%C>q@ShhpHs%p@{gKN?>J| zjiX{eD=!Dt^#m>hDrSqXhVMTYU@w0R70ZVKhy{B`$|V3~ch{Sl4k!>0GFR%wK80Q7 zq5cu-;jHu(T^OZf=y#oFt%%U@@))?feMm#~REM2^)>Wi7ddYyRGxQaFE&8FDi0l_E zh`lt++gnhP)t9z!Zv1sWRd{9k^woEs{pX-jDzb$|)S^wQ_NZu9Na0QTl_e3w2Rno` zXu9(ypV5n*8=r3;&u->JWi zac@@)GWDE~^O7>Na+KHjrAk+pjt5-`+FZ)Y<#f|b$IQ}NBvZM>upOd$p!bJ zC1!urrdu&(u`PrHSvYZ$04j3!X-!V5mL6=2o+Xlnes^FMC{vzA1|5~pLm^%8XQ+O! zBV6MB*|Q10t&bR6P=^E6>MuG&x!Q+nhQ15bk2ct=`rYDWSRJ;Z96^!*Fv~u%gt*iK0-y>ysK^yzqw@e(G%R*iys9f=YA4dtc53xmkO0*bCkFID*A5NR_^4%#3XD};1?gEx}->$#I^Ns zh!EBE#USgMi%2ZA4J}hc?)=xNHyC@>zX|KtzCRwaKzeeju@A9DqKEMy7r1DUIZQFk z|Ip9;x%GSY2Cz3gx#_pjnj9Oy{<)Y>P!lRXa^Q@QMPzn+A~j35$ihf z+|c+ET>jOsu~!$bmX(mYhTmqxl8n4D0k0e(kL|fWB-}|80=X!8FizFG1s(A{vOh=9 zKw>kL;x<&z;DJ@$4wDDEBD326++s_l_~wYD{6DcOB$2L9@}OMf!}3%fxQP02O5x2{ zRvTB;^<;1*BFFTv!TZWMnPAUqtA!)O^^4J-H38hAL0C=ix5(GCwwD`%y^n{7nwt)3 zgau1{jykD@%xR+TCM*>0{P2Sw5)!i_e}(mkdpWbYp-?wI`*Y^_^Zr7T@?QkSw0~Ir zMGaNvF_I>n+>jbdU5LGOkaF`}B2lz+WBnT~Pk@pJ2qtLg?#hYm>rd=24|ST6JR}Ej z9O?%vxgSmr^P+z*g&fp?8&HXHijpsCT}&Nt9_Nr_c}(4ncd5`HDM&ndw%Z6We3#RO z&67GXHtOI$C$HCn)cAXHyvqcdsRHAgd%|4b{KF)d3 zl3HoFtpJJcm!l)MqIxOq6!h|bu`55;1={N_Ue#t_^ZdRAd@VZ-&ekXZ6j|`1u&-+? z?>3xs0(iKIf<_IXV&Z$+V%iI0|9f1NhT*)Pq%g069#Z4+Qd099f_IAJu*>&wK>_6x zXvPQ*@C{!egt|1_g&s>0=d?rvC@!caJH3Bbueq(Q0X6YeMKa_J|M5N7ku~@~V3YR- z?q6-nsUy<)_|{n*z;VzGfX(mmX|LfKz_Ut1WxbC6i9U3>h>f{~XbrE^}M9@rg!wScl*Db<(9qfuM_TeLN?Jfg) zL9^e`+n{sjO^5dgSgQPGaUqDQOx__c!(`Ek)u=l~BHLo}B3@c(I zyvJPp7_L>F5COVepkYL6|M}=0DrGNWRVNCLH)#H+t`8g%TCB<~w}~EezGeg=OAv5d ze_{|P{t2Rs9z-1$PX8+Txj-C^E)+*&Yq6_@HX-V}O`%_(0`uOnhcm0>dfeE?HU^N2 z_vZkvHF4AwUVg%k0M<6tLw=~xZe%Y19J70=KgE8wvhxRMlllQ>IOVfidcvz!+V=bn zmy%Y^$q^!g8W5N6rEXF@m>o15WJI~N97ghNfKY_c7$%VMR4ZmH%*3;_!e=wVLk&OX1DrRuk>dFQ^wevluZ2zZcOillDSBdAL-?tig)~olAd5rH$e_vdWf5vV1!ZN+wgeI!-ZFTDIE@ zB=P6SBwzA)(AiB0#6a@xVxM$TQ%vU`CD$aA`152FznF;cwxZlObMa!|GDBwbxrv}A zKW2p#ev0bt*nDQTJ~CQeZe3^qYjq}BTkqu`sTQ)ZX#L&&vb6iPp_tE5T?+3qcZ|?l zC`ku`quqF|EUHUq^IIih=%-O{tyIp!AqGSp71OQW=QARJWJ=U8-~7R5{~~ezHCs!R zEP_Uu(&*xzrWvMP*qM&?)K^G|D>^8Tb^@+VURMk81f?;V0p(V}&+kuOp4xNWlA4gF zVdQ5X2gSP{tjqNHhdc`PNLHhp7tt_kU#mBcIYsF1cfE{^P+k}^B!|HS(E|eSv)x)g zZ#dUBPw1qr?featD{mY&cXyDB>1@d0Fml4`xTZwW`T~^IeW!E->XA_7lr!bo;O<3K zTRM+>^lnnd7-yzZFfGGv*;6|FdDrHR!Qw!1!3=T#7HNf@^e{bLR~65n{|&o7bpY*+ zErD%rfbaq{vlH!_xw5TEfi0D)#TFZT#cFJ%Ls~r{K-@zDM9+>LC0s(>`P|*sxe@)2 zdyM++6=MGZVW9Uo5?Ll&BWA9at&3ODA8nTcO|p2kIOyE36xb1akW`zsHN;6x{rv0W zAd+qudjMOI(i-Gd@W**jR7va57T0OgQTbL(^ZRRphfshXMv&EBT%f%;sKFSQpuI|B zPZ*1-bbUU&1vR0#`Cv=OPUD`E#(C|P)9JWWs3t5G(m#R9-}^isA1@c;1jWPFTVl_S zNaLIUuD#35)3-i_LIU0ST5Mf!xHxdN9?y>fze*jF6TI^@b(AHKNF#*5CPn|Ug+C|- zup1YWdBah=9JslKw8}Kt$FMZ%&|LY~w*47dx(TD1Egmz0`&upZ!RpYl6_-b_k^Zu1 z^V}(TB(0v?U=tAoa@b9g_Q-JSaEi9_tM|78@OAfWX-ELcSxn`75KJNa{Z5?A=B}2x zZa{|>(3at4Se54jlBi9znNF52N|E5a6$WbtEo5vLn?NiExZ=?lMGj#)P+}Ho z9~N~FAMb_q`#QUAvbIA-47u``uK!NPwfNL(jenkf0~%l2s-V@3NelInfglD;16oS| z{lw7mr-0m66rkm>76W+nJ2J2-_~_)V?YXYUGfz)_;4>39S__3Cb^@N!N8XJ4A6g2H zih0$^NK@g>9B@_uu`ePY4^Zz3Q~19E<#cF)gtsU zP4johZ$Y^)L8ntSAND&s^fIGE14dn)q2Hi6+XD*%;yuU{EaC4#E---p00s-%V0bja z?Fj7z)W*t7an?;Jv`^;aiAu9=$$SYBcr`S^0b0tEp*=8j9rtgCYrWk>t@bPt`vU1# znQ^pbWwB?EB2*xdKcfeuS9hSNidV-ecFWDslEIDvV0jXEykX_VP0H*VI{XBEn3+kN z#`!YVturY<1EB@@qKMv`Wsk=?n8uAa(?-^OhqE>XI<@UkhTQw-^1J-y&jOK!_%`O> zOoAdSR#1feG6eG6*~idsn!BL<4f25C)BBw4p%6`iR-UJ+LtW4>*ycvYx<|jqs2~M| zd(`owSL@9(Bk+4E&KwYl}ZL;7!~5MIMKG!$DN&loEQa+ z?j;Y$m#dp2Ploij+M|bMOs{h1WCc*Y7iNDl``kMb$omVXAcVMr8v+&{xet7borU<`kC08UXe{+@9+ZywaZtk+=spix(b+HeJYZIguuL)u5WN4Ppg zpdkB%(-*2X;&bQPWn|R%fihGB)_z#G^R2>lsGCB6RA;L5Au!4nFzjJ_c}YZ}yT_+D z2&s-^8ezXNH-Sy@e8p$!93GIFf(=|N7~&nK={_r(XRkqQ9!**b8?pMp_ch(A0v^y| zIJ!ZbAad9zoPU2zU!7pT=n`?Qld&r>t18FW)WgGO=r+JM@lDuP$cY>NGAp=%uwAZ zhtyAdNJy(nWX6*c!AsD}xG##aw1jOR`9Sk2Iz`aqB(c4XAFHa2ye{#n>DIj60)8vl z;yFq(T8m`TS}$^I6T10Sz$xf3B`U?UV%_wZ_EE0KqbHF7K3~o{)3CzmgI-cs|iD|5l-j^-ko6#+BagNXOEbmMl9q7B`?0;z!Fct}F~OYlZgVna8T( zHgUsj5_BD;as-D!Z9p{){mLWhfhuyu5d6*)eJDvX1yEMQDV>^dkODPUb@IIuWFnSg zr&UyHLtILh&bPlxCa08yQ^Us+L^|@w$d3nPTdOpfKiS5gpHoovt>3OGXOy9@a4LbH z(jBL?YH3;*FqT{66VvWPdaOh#KqfxrIu`p`2M(WzhIj`hfaxk1dOL{k7(T}ni0isQO zeG*?4W>+rVJthbBe%Sq;KOHZ7&E_yHzZm$bM`*DB3rtlZl=611dyE;T07$M{x*v+| zT$pv~LGW{S>`Q5Z+_HT0N6Zpi=EGPQLXXOPG^Qka5Sea+8AkkC9;4+d&iA9P*l=dbkau`Wjsi8?OFL63)m zX^Y`a`tzQW5xy5v#Yg#f)wKALCGPGihw7~YZ{<%t<+sD~8oM{!MdE1WCCD2d+|E*K zzK6ULz5J<(Ry+}5{ASV$&lD!D{%zjxTT{M3<=S7)jU zp$g+0BEq`@zY`hrSmV50C4a|THH05eF#4l78AzbQAyDh^4AiLlR$SRPpur9@+fyyS z_Aia=*8i&2y6$q*bla`11Q)e{H zo0)y&_{*#TPFhtVBhzl7S$m}s%Gox%%J73370k|9MtXe7+WhKtr#jRX04Dh_e=

DMEGz7)GU8KH&Ad3uO9m{%XXzMQ|^Htcg_ zM;z|c9!}YT5^6u?-289G`$_HBCzHPqYvl(ibPe{8<$fU{uGyO{w*)1yEXNMKG_=sp zd^SB=w4p8*a?U&W;o1SD4GooT5(S!pMUI}(%v$NmiJ)9&7Oh#srBjvjXvuYA3OY-m z1!1h24nr^8uf)AD@rNe7bdK^)SdfA4vt5}1V|4~=%7S6?C0esHYL}g0q^YG?k;<>} z=>74I&!Dt`6n31kiVM9@w%hBN#K2DlN<=1#CWZ*iuFtK*=y~1yp;Jr2PbJ(YknGkm zEU71Jn|e34R!KB{bj>U_TA`SCKCuvCYq`w2gDx*0a$W5Q}DZz`+!ttRvtLgWRQ zj|mLm*2UQcIzj=N!79i5y*Bit2KvpJQ|4LR+IRjBsR7F3CF2HSfd;bmaWW$h(lp#0 zFGIKNsIFL*qXP~ni0|C&mSvT=ZiFg>2nfx1%uM-nlYZvxah&g9T@`nb zv(n!#@wZF-?Gpb#>I#3StG{E@-?8cc|Jam&cEF)I1);R4m&Jnb+M4(q_|$7pe-u2s QS===`YWicr4^BV*F9$!|@c;k- diff --git a/test/cases/vttest/1_3.sh.xterm.png b/test/cases/vttest/1_3.sh.xterm.png index 4087831c74f092ebda4fc1eb7485baaebef9e5d4..d0da962a9c314f72353fc8911e2ea67c7efef41e 100644 GIT binary patch delta 2374 zcmYjSd0bLi8@|9r5m2OY#SJpW$_34eQj>D2Ml<``)HKN@%@s4vOyZ_Z(qyL5xRe%c z`umlPODd@;I8CMHXl1S#;;5M)nwq&X+IPvB`F;1FbMATH^S;k{p7*?mYgBER#pUGh zcHMp;sdxN?Btb&gV!ZWKbx9DPbpZVGmLqQvAgxj1Vaqg+ZiQ*w*OL~75cpFQXIZ@K zn96)5XmBr16Rp!Mlbu9kR0~(=t*rqTJu*)5#63 znK6p9lvjMK!`A#%vTV#wX+e(~s#91nL86cHQZTu$cqUL*mVBgtNAuyNUEO4VT zjJ0HJY|4C4K&<@SK=hXDqoadi$T8}2P)#%yG57eq&?iRTYtEq%<5+MRu_k#Ah`i)ik;CQsEy@Eu+>h6-vzun!+-%|lSNEKA3rjhnbu7`s)Fv}Y{pbF2r}<^8A4N1HqgEnQurIjnm;pjw|5Hn! z%@&osxQWw>_QcXBsy_08O+B1CYQOutTJ~k`s-AD3IBqwB!3^$~)nZ2t_x!mh4JJ$z zeP?`GfV6b{^l5u~k2Spw(V0OqBOp3U9u(f+GM;LxnEGJs*BlR}6U%a3pmd|t@B3nU zM5A%|;RPyX>1#iG)w>9beID1Z5%(!%9jJ%H%aL`bZkD@NOD1?cM^{qKAFSDlyzHgM z$XO9*x05rn%|IsnJk@%1N{;Ffs@j|K0g?B!+?Q*ergRahz?p}DLSNWGjn2*0J^Q+J zY;zmoT5O;E5p`zl!H9!;{JC+(SuOpSfv>1{3QUFsz#JMgJSYR{Y)Fv(WprpR44E>K zeSy9QQb?A2+EB->i0lq=Lj!q{bb;N$5uecC5$OFUIi~opSq}}uto*FTWb~pJWjC1XG_GI?=nz8-YOO9?7npqDgyvZu@{^Tg#NUW8jCRVoU$ zLia6|LNurF!1+;ul=SmCPVmo6P>cEdS<~!+OZ`|)u&G^zE@`!2+FShSkJPZ7LqrU_6ybMr!c^DxQW;DhG&p)D8)y9w*=la{ciHSW-Uw$^7=1CIRh6VO7u1!cJb?E@xN0b$7>ox6RC!`#vI z_UYxu7e$me82TyD9@wg4n2Zkx?QzBqxJ@9I6%Jh#QxM4{O)?Th*bS};G1oz1S(Em9 z2&^VzH3Nb5hA`d`Qj2^KS+b$fU^-1|qsuQwz$Q)dhSt=uo2oa}V1b9+brDC`i~oae z5(8n2-?+XXdygWHMql25{-no>f)2Uiydh6Ren1(J9vz37jQA&`G7Ow}ThKi=sRl@o zsT}q}8rHs*suB5cw@{L_M-3ifXud?)=?-M!E-11%(`01p0Upv{&Kyi^GX;5qONlOzDzZOJH9!5GJp ziG>e!afXIhr-8~whtY)fA@C-hD!ZAuG3Lh1X-2u6r{w=Zbcq1yTF|jcdk#3B- zaRDzurzvw~aYm0fcBs+ZGok&3Y?@3-wgLZYlP;h5T|}6?LxvdECvyX&jqVDxd~1fY zt&tK3%!A1LHe8yC^Xoqbz)C9@OqdB6xHPGX5HLRLH5vo2DLcAy5UWO2{&0T9&&4N$ z4A)~U2bvYbBCTeC7K|4vpVGDet{fH<>NV76wrVlqM7ruUW%a_dzapS`fyM$eSa3~W z>u)@e-K*+(5gBP%hf9QE!*vK31pF4WimoIYdqctcU(xhakLo9p_JG~EEx#)OGN*Vt zs%=*i!3CVuR}@}B&-pI+Z%x4C#RE9_@}u*P_(=R_TKp2 z?=x!mrf-n6*)?&OCf}T47;DQ8$F669O_jVmcoHuQN8oAW;CcJRbjMwGu>-7 delta 2440 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 DlqJkJ literal 10409 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 A1^@s6 literal 18156 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 diff --git a/test/cases/vttest/1_4.sh.xterm.png b/test/cases/vttest/1_4.sh.xterm.png index 7430fcb4abf8833804fcd8cf2b9f09cf5cc57ad5..4219498608aa8227a6e0b4fa26bd23abd85b5771 100644 GIT binary patch delta 2329 zcmYLJc~nyQAAJuHkPyMrz)VqVuyTu5ON9zG!^(EELYx%!XogEJsqxCDXfm-O_fkvK znl!gj9I3#v!d%(~CDY8b83!dTEm0Zh*PP$`=biJ;_r81Y=X3A3eqoJ8##x?GrZ;25 z?u2etPk5ZN(G+?fi_GLmV>p1%)p4s`JfLJV%_PKw8v65SW@);8i>PT|MiKXVfP`J5 zeZ$VtV(_4ibkI`Z)Lp535qYqiXOpFJS9vDvgeH|o_UHRYGBw8}q6OJ?qTs|>3Y}%f z*1TSkj8Ggu*ol%#kPW5zt=rQjL98qpR)%rg68A8T{CC95%^55NF4~`80*^__O?NLV` z$kLeqRc|>Ve;fn*CwscT(`3~Tx7hDz zN|wvZp72cSJe#K~LgSSw@hO`%OO#fBo`6WX7c0b;hZyB+>PI;(Czx86r{^UT(*7xx zASvt1Bh`pTb16b_e7bpJKq;`Bc@!JBR!8Z1!Qt#NWVyhM8Y2$2Vm~VG{jz(Hm>i#&t^6VyV5KW@oxGWLNT?6l|nZu3mOV1m2(-`+Wy?T&Gc;TdVGqbKZ zV^YUhLL$^{XSo&mTS`O+9mHI>CmhIDdkAcMMkv`JS-443rsHt=c);@HJ%{ROlweml<-Cx@ekX((=XE zM$Huy^BKLVRVwqf5t}|P!1zB^@qX)#YaMABpJAm=xK=A`*_8W1V5E~~sF8G)A-R0H zTIIx_fXV8&_O-7*U2_jxbMHj;5l00rF&{KeGU^=e)KJ1`dHZoqU6UT73x*N^ZjQI&JDjbUxF zS?b$QExLccMSYw;dLQVuSS-gxE3-4hp_JZNQC2>YNtpBvukAj39e8{fX@$xOBT)B2 z8i)2Bo#Uc7W}*Da@!jpm&NI7cRlJ_Kx#jtXy9cu#2#2C7nHc$hu%P9zD{Cyf+C#SV?nG4CW zcNbrD34uDmr*r#)#Mkr|YK)&*=L8lLVvs*L|1-Rr{MSn=$%Xvzmrzd}U&rttJpv75 zK5M3+}sONW2a(pG6g_cfB_2}q&ZPYA8;MYf><;R4Uq)iw9+Ol zFCi~g9idIVJC8yKsiWHW2tGj2--gr#dJQ_`Bz$Kw%h?vyY)#aUR44GeMg+PN^DOjM3EYl>-YJ z;QBP8!5@fF=Il9SGitA`ZkE1K+Kuf{+LhTYx>(H9EkY(j`GqXNjHYpyt{TGPb*45z zx`66mLL*sPJ^?G%XVm2+kF>^?cnrj3d?DKZFUip}z>yYOJ8aR93`chZPLqjExiHtq zp(VgK5G?(kw1kU5i1K6lLQuiRCn z1MaEPm8ly2t$ve!y{CYXYINWm=+#pCBgbEc)+5CD6dMl+n?D`h0W3VJOW~!X&zDKZ z5q=0+18@r<-Pks1X$o`gO7KZs_^hEY%+vxFq_A%IVNGAb=THMq=I36Och$BZpJwO_ z{X_?UCfEp{W9Rd9H9rn=D*Qd5gAUSz5Bw)nLppz}<5YCrOZNfCY5@6ICy*4Say!3* z%Jd|Vd*`u7M~G}phTI_M;tnR~9N%sf)|O@m8wehP1i6kjwl!Jh*HL~L4*Fn$r8_MXl zwJ9vRXGGcA+wig90m<xw+8VjSp9R2$)mRr{hhbFhAJ~N; ztP&LBan3>~3`$sojS*sTTw$isdf`i~snFfX8s-ZLH(*@gpXHG7ozW5@8-o*KaKGB# lLih#dXlELm=&+z0T6izzWJ=O;aXO%TygjxtZf|6t`WKyP`?CN5 delta 2470 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 U(-+kI06-46?HPMoCw0R{y_$^ZZW diff --git a/test/cases/vttest/1_5.sh.alacritty.png b/test/cases/vttest/1_5.sh.alacritty.png index d3e342efa47af5f885bb55eb5624d6da42e47024..cdbd5874383f161758db0f853e6f653a3473af85 100644 GIT binary patch literal 7265 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 diff --git a/test/cases/vttest/1_5.sh.xterm.png b/test/cases/vttest/1_5.sh.xterm.png index 934417e9956cebbbbc8c056bf08fb7bfdcddfa6e..3453ac9239a36b53d80ec0c614c15af59792b2ff 100644 GIT binary patch delta 1501 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 diff --git a/test/cases/vttest/1_6.sh.ghostty.png b/test/cases/vttest/1_6.sh.ghostty.png index c21f02cc576f4e2877f173f45ebf72642aa11ff7..672b8eb25d16f6eaf2f491c1cf40a7cfcd6930bb 100644 GIT binary patch literal 7585 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 literal 8486 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 Ba*6-| diff --git a/test/cases/vttest/1_6.sh.xterm.png b/test/cases/vttest/1_6.sh.xterm.png index 37dc4c1d34091130547a0a7811d4c9b673bec909..43bdcb09ef3ee07c777e84f5e0ebeaf91cb086c5 100644 GIT binary patch delta 1278 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 ~u^kxKhlU*k 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 diff --git a/test/cases/vttest/launch.sh.ghostty.png b/test/cases/vttest/launch.sh.ghostty.png index f26da6121c633b901656fdef8e32c1725689276f..283b20daf4a6e831742d4ea3c8c4c6a0deaa1b5c 100644 GIT binary patch literal 36090 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

O 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 Date: Fri, 19 Sep 2025 15:00:04 +0300 Subject: [PATCH 12/77] Revert `src/font/sprite/testdata` --- .../testdata/U+1CC00...U+1CCFF-11x21+2.png | Bin 838 -> 1032 bytes .../testdata/U+1CC00...U+1CCFF-12x24+3.png | Bin 1024 -> 1295 bytes .../testdata/U+1CC00...U+1CCFF-18x36+4.png | Bin 1687 -> 2193 bytes .../testdata/U+1CC00...U+1CCFF-9x17+1.png | Bin 643 -> 794 bytes .../testdata/U+1CD00...U+1CDFF-11x21+2.png | Bin 599 -> 1280 bytes .../testdata/U+1CD00...U+1CDFF-12x24+3.png | Bin 553 -> 1870 bytes .../testdata/U+1CD00...U+1CDFF-18x36+4.png | Bin 684 -> 3411 bytes .../testdata/U+1CD00...U+1CDFF-9x17+1.png | Bin 563 -> 1103 bytes .../testdata/U+1CE00...U+1CEFF-11x21+2.png | Bin 727 -> 1006 bytes .../testdata/U+1CE00...U+1CEFF-12x24+3.png | Bin 755 -> 1255 bytes .../testdata/U+1CE00...U+1CEFF-18x36+4.png | Bin 1096 -> 2247 bytes .../testdata/U+1CE00...U+1CEFF-9x17+1.png | Bin 602 -> 751 bytes .../testdata/U+1FB00...U+1FBFF-11x21+2.png | Bin 4884 -> 5427 bytes .../testdata/U+1FB00...U+1FBFF-12x24+3.png | Bin 5045 -> 5724 bytes .../testdata/U+1FB00...U+1FBFF-18x36+4.png | Bin 8354 -> 9975 bytes .../testdata/U+1FB00...U+1FBFF-9x17+1.png | Bin 3950 -> 4341 bytes .../testdata/U+2500...U+25FF-11x21+2.png | Bin 1911 -> 2225 bytes .../testdata/U+2500...U+25FF-12x24+3.png | Bin 2104 -> 2635 bytes .../testdata/U+2500...U+25FF-18x36+4.png | Bin 3125 -> 4570 bytes .../testdata/U+2500...U+25FF-9x17+1.png | Bin 1549 -> 1853 bytes .../testdata/U+2800...U+28FF-11x21+2.png | Bin 285 -> 1022 bytes .../testdata/U+2800...U+28FF-12x24+3.png | Bin 296 -> 1541 bytes .../testdata/U+2800...U+28FF-18x36+4.png | Bin 399 -> 2501 bytes .../testdata/U+2800...U+28FF-9x17+1.png | Bin 275 -> 917 bytes .../testdata/U+E000...U+E0FF-11x21+2.png | Bin 956 -> 1102 bytes .../testdata/U+E000...U+E0FF-12x24+3.png | Bin 1054 -> 1255 bytes .../testdata/U+E000...U+E0FF-18x36+4.png | Bin 1506 -> 2217 bytes .../testdata/U+E000...U+E0FF-9x17+1.png | Bin 782 -> 894 bytes .../testdata/U+F500...U+F5FF-11x21+2.png | Bin 966 -> 1114 bytes .../testdata/U+F500...U+F5FF-12x24+3.png | Bin 1182 -> 1421 bytes .../testdata/U+F500...U+F5FF-18x36+4.png | Bin 1785 -> 2473 bytes .../testdata/U+F500...U+F5FF-9x17+1.png | Bin 752 -> 872 bytes .../testdata/U+F600...U+F6FF-11x21+2.png | Bin 324 -> 495 bytes .../testdata/U+F600...U+F6FF-12x24+3.png | Bin 376 -> 637 bytes .../testdata/U+F600...U+F6FF-18x36+4.png | Bin 511 -> 1210 bytes .../testdata/U+F600...U+F6FF-9x17+1.png | Bin 278 -> 393 bytes 36 files changed, 0 insertions(+), 0 deletions(-) diff --git a/src/font/sprite/testdata/U+1CC00...U+1CCFF-11x21+2.png b/src/font/sprite/testdata/U+1CC00...U+1CCFF-11x21+2.png index 0cd577291b15f6c604c0aef7f6990c57ffe974be..e04e7726b965fab41da5ed0c4f7e3501709db29f 100644 GIT binary patch literal 1032 zcmeAS@N?(olHy`uVBq!ia0vp^9~c-IKX3pU40}EI{$gNYKJV$`7*a9k%?)k7!v+#9 zj`#mx($rqD+qG`RYRPG#2mUYgkYola2LZ9_dFvnFZk_y1Nanau)8h!I0vT_PzQ^^y ze_ZnG-~K-OUHOMEpMEm?3nEJ=bJ{z&RT?lHu+s+`@&Esu+1YEC8VDROY+zAQVC3|0 zU=q@L2quA?6)iV))_bQfOV3pQ-FWA}{?3z)+YH|OdFuUpvqJVoY4QJwuY&IH_%_wa z`C-r2^&(PS>1%42UI?&AeyiPTrpa?4zfINc+R~?-I=Y+nd>s-s=Iq;I!^q{FsKL|9 z2=>Ac`7Mj%w_lqaX1^_7jnAaJ`fU2m>w5Fuc+Q!;v5&}}{i;OxvJ}_pXNtzApE-roh?Kq)jGwTufxy zUj6%*c6fSr4_E)Alkqb%e0aAuHg$hl9lKz`@vS{N?hn&`*>T9vS4)~z5p;NkvV3g( zYAG&Fb&V@8JLH%u4X;&jDV1pJwn}$7uT}rI%$Rcq$9a)`k~dDLco`e)mOT_YoAYYG z%(Ba$_WUehuln^t@=fTw83#>5x*Sz?t1j37m^8J?wYqAzr2bT?%gYS8R zm5Hk!nP#8!cS`9zx@zWADWyQqta(Qh=O3=QereU-f~6YE-gUn^uJ>*W)AisVn~dk1 z6gGU4TJ=t}#@!<3baKSn#Wms`Vmp^d?#bYbyDWWmu3?eO`9}e3ZEPZ*-%XpgRct2z zsWqt|C#hQTbuB7dZXmBynQ`*}AjhFmeJJ4GaFSm!8ywYL$Ty yx{}|5T%gR000%sP?EnAY9)_E8TTnv-As@r)8udQHB9&<_NX*mK&t;ucLK6U`;HXRh literal 838 zcmeAS@N?(olHy`uVBq!ia0vp^9~c-IKX3pU40}EI{$gNY=Jj-O45_&F_V(MUvm8X& z608@ncx_prpm4nS4Pki(h9AneFMoOR;A{WV z*jM{2)&f<7wEXvNJZSf2>-35KC)%DakK+Oxqw}GhlZSyp{)SxJ=db&@&mB(u{p3jP ztMucq9>1)5`!eGEy*HQt?K^z-+ZFHKUmu;e>YeXxvaIUo*}DdR%exY{SG@ZD{{Pb2 zJ=V*Zj<@W-Px}Dl@TmSHp&8+oIle=$iUHl{D)q~HUoJ@O5=4}bu|FhuP z&GUX)i>|xX6|dN;v{z(hpGRohG3OK+w`27w_c+g1ESza(aJW5e+KE|WQQpki6&ddZ zZfeDxD-@g8SX=C+|1DBg4 z9$cS4?Z~`KEc5t}GVT9oqw`IM50c`jP9{v1ca3@<;qNi831qgXtDnm{r-UW|uXTo( diff --git a/src/font/sprite/testdata/U+1CC00...U+1CCFF-12x24+3.png b/src/font/sprite/testdata/U+1CC00...U+1CCFF-12x24+3.png index d2c272e60af59be94bdeb00acf22e75888335383..ce1b1c422e0f413a6084e0ed9ede00def5a9eff9 100644 GIT binary patch literal 1295 zcmeAS@N?(olHy`uVBq!ia0y~yU{qjWU~=GK00NFLPi8YPuw3(WaSW-L^X8f%7mK2R zOW^zZm-lieXRhgtlDx+)y70%uY(|i3D3~7>I(zm0n}Ozn8Uh+O*k|1>Qf*{{!>aT4 ze$_=Kj{})l^O?4;XEXQv0o45e|C<|*ZOn-ht{4Bl-^FgrsapA`D`sVJMilS7^HX`W z)a#jeQDI$+EQ=Hi69dBo&U<_B?6dp-|NrOg59{AO;al~V5IztdV?Qn3|6SDXy2x|$ z?zk;*M1=|r3>B;Ff!+Z+Yi9JsEd~Ou*BOP}n1m)Yu&DH~s3<6cSuRd0bN0_@EOq1`WNf7vNb)7PA=5x0#^`iW%YpqY? z=D$9w^K0>WiPl`VRTnNUdpav!;o<$QArEfsJ)|sO&8U!8cR=^km+5Aq`#oH0UKm8b z+{vt$znIyeBQ5c|1DA=c(v_Ld5-QjHHkS9Uju34>>Y}nn?Z~<(h3?1JuK!gdD#T{^ z?rfUkaeXFJ_1Uk4GL`%Nt8Qe;WjYsr{5yfo_TvH1eMwdCFNB|ZIH~M|n6a&QSnHB) znNkV`{ME+;X7QNT@@y|UC43<+@2U>Ro(|5fzjrNh@cDUVa<}i!-!&={!QU<(IhxMY z+pW}P{`l!G*}u9)+wavnzB*I${j|oMg|^&Ze%bn{?+&RG_OLiG@vGv4^=TfP3K#rr zcm2HAcx#u-wrL+<-KswIOtei|@WEk$<#T-tUmsQ|3e;szn%yxm&gyYq-I0YsncFA5 ze{yU0&#NtB%!?AUD+}h9wuSvM@Z8CK`o*7ra+MvA4Lb<+4A3gcJ*~u!z`@GlfR*#q8Qh%?##5?sC zn}6ovoxwX8{{`Qgv|3hhN}ta0&YJ(WHco#vWnW$4o9Welk2$sdgZCLQKAhSnph7>$cGJifsBR)|JJU3$S4iWI7ncFIFJKO>cEwf-7P#XfwV|ZWk=x}P)dXO~?p00i_>zopr0DEp4B>(^b literal 1024 zcmeAS@N?(olHy`uVBq!ia0y~yU{qjWU~=GK00NFLPi8YPFdz4HaSW-r_4ZC+;VTCb zwg*-nEGi0&oE{x5UJgt`N{pNn8(M&zV)?3t6Ylc1R$E=Z_j8}Rno8pz%iXhM(<-W& zL54xWzih#cpRP@9U{P7{p2I^NY!J|t3+vCMe(VXptE9mA*V#d8Zk#7jZ~{;j(4rTw z86#UnCo}*}c#u5lcgFAIufJw~_+KRlbOS;aN8Kl$cUyHM)3v2fXGcR^2$L-~1nRBZ z`L=M*v;OIyP2{%o^WSjwxhl+i`RRX?WecljX(p8$&(%}^rmfAP9sR81takXm&KdIW zuK1s}=bHJ8y(W7Df z=G^Jeb56JX>i8(l^h){MdX|!Pu_rc(DLqT9&*i`U*TDVGo#(TnT+5$#Sj0Bpox6(j z?zNK2v(G!+e&3tMc}MQvQSaOwVZpnv&y*o7k5nz3b<;)YG=d9_4)zEL@Yi zJD1Jm-j@K^_2%oYUdhf~bNA4$*O|#{TyFFh+HUz&7H|39tSjs7;vj+L=kK0#l{wF{ zW%ufp`wVl|%$}v2v*TXN!q}+t-Fmm4F1)1M8-KH`I7jmMg*DCJAI-k!e(mhpoN)HX zJF{!U*86tO^^sy`ifrGgQBS zf7HJ9-AkcI>w;$9-t?#~OO`KnQn2y!eU(#}FEV`dp81x|eP46_m&?2z9>0pH0sGnY3ety~oHL1JT)K2B^O^UB6NIhYD&F#ytZ|CPNzqBCgaKuyPZa4F7 zT#Np0v9|kuEZl!eX=0>f`rRK}g3e?~Mf#eqe(mx4%q6SqOU~KlemE(`ce(BPlH;vg zj!$31zG@5mo+a$(wy-}~u)PEqr%x~%pv@-$QCX%WxUYMG}k zBDuXQxnnK4^DDU7SY_ lU%s4=gyw+(pgt`A%lN+J(c#Q(EOH?0Jzf1=);T3K0RUQcsgD2v diff --git a/src/font/sprite/testdata/U+1CC00...U+1CCFF-18x36+4.png b/src/font/sprite/testdata/U+1CC00...U+1CCFF-18x36+4.png index 167c1fb831bd9d8337e021927e1e09480a9c4dc0..1c21f688a5037887283040e11b02b9024be5702d 100644 GIT binary patch literal 2193 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 PyVr1bfWsQ?gVO&4wG6wb diff --git a/src/font/sprite/testdata/U+1CC00...U+1CCFF-9x17+1.png b/src/font/sprite/testdata/U+1CC00...U+1CCFF-9x17+1.png index f2925aedc6f2d3d2ac19011d53841db7b5449baa..459822e6359f512fa3654227681071c1847c59e0 100644 GIT binary patch literal 794 zcmeAS@N?(olHy`uVBq!ia0vp^7Z?~ACvX5648I<1EMQ<@dg$rm7*a9k&Gn0H%!UGO z7i<4d&(qx5;oF(1TK~qNl@5&M)9sQPZXA+N_St-u<@v z86f$lPG&N{YExHp(<&BG_UWvQ8;(dbF#P}jW_o?@Q3ZkH&ld7L_-?o89)%zygZbK2g;*NgTyFxUTYJR0}Vu4Mn=)aiXeF|!$??`=HW zZ2Ii~6PfAj|2GxPTbx#I+W+KD^4qLfD;L$tEB5@@@H9U9gRj7(m$SSlnq0f^b%Ej* zMLqcs%ck{;i@tR|qPnC10n^tPo9^6ENvTtG)Oxi>#A=FDM*HP^d~ZE}Jn_6b=e2kI zZ%>^)ANBv8oxXnQqB@Ipnhzs1@1`9uWBrq+yidNIr^;36gX*Q_^Y$0z*34Ub?$>Q= zW!1@>RSvu5Jyv~MJ)v&;I>!5Z(mdD5r#`x%sN-w&%~PCzFN^<@^sR0;vz0Rse)_bu zb-wDO38GvluO|MqFqxt>Z^7a6ko!Nhg0|eL?0 z6V)2VbH5|w+@@{MWP5XGp47-#wD#ny&nc^_Hu+92T@}ect2BJs?8y6-|4zgO4)Sz##dLuOT=3)>bYIkU-`?(_5XDr`)lc0R#BnP*Sxq8 z-Im8R%ewuYmO*`c63^YM;B;Oz<5U} z`7Ou=O0Y=4oe@pRZ9xqUBzYi{hZUsc?O{V+Ag5u$zqPp!S*5`??Pds{x?QB{@}Jcp N9iFa!F6*2UngF{jQ%e8< literal 643 zcmeAS@N?(olHy`uVBq!ia0vp^7Z?~ACvX5648I<1EMQ<@^73?X45_&F_SVC~*#;79 z31%NSdJb^N9aPR>=?Bt{f;LTV2`oVLz5Verr$vhK@2YZt+3aVUmJ?^k*}1z!7GxHK z!{xo%oPb!kJ5%5rGWZATV>41E(*Y}@4>t#OM&MlMDJ^ak2>Z|8${_zig*ZiT~H9>v~VkzZSMD)neLnQ-N*EufP6wr8KwZ>DnAK-{0N%-iJl zJv~q_C)ya4tl+y+@HGb56PE`mFqgr%+WA>%5+Y>IF|C z<)ea`vcofad)6FV7;3*^H^zopr0IrG-RR910 diff --git a/src/font/sprite/testdata/U+1CD00...U+1CDFF-11x21+2.png b/src/font/sprite/testdata/U+1CD00...U+1CDFF-11x21+2.png index 4f4e8c1a5ca0b3da8e81a1f7807552c321e0071a..8d7de36aceef89fbd945cf8a56477f1936953b56 100644 GIT binary patch literal 1280 zcmXYwe>Br;9LK**n;%~$p;>t7gove3w{1XiBA9v8fx@{7eToviq#=^Uw1CCI!fi#g|%H*pmZJBe~jpg6^B`2PWQZ>aj5a zv87VY05RyTCs=oE9eFceYy?5_Ju^cL_QL)nAG*H%)t;P)_^9~(?K|G`d$JeRq{JJV zc|}kp6DN{Sf@fM<0F;5}XzwRzQAhxX>cgSSQUYL9z5 z{s!uN=KHLLN|_tp5{9>{j|ObbFYVp@SDnN^M`VP-VAeZGx)jH}EeM1qGdiuxmG9*`$PJbF^!uN-Pi|>VEB-|<9Co6yLtpgQJLbj-^abZ zcek!JZjha|P6Rnjcb5v44K@B81b6r>eT99lI8{o5Lm%t)8SOtjFm*Mj zB9Df5;`-A4@d3Lg9Eus&9*S#|cSVN_Ot4sN6!GM_8GS-vKNjy0(QIl)VC^rj4Aksg zfWSvS$BkCyD|@e!G_D_)zCB(mMT5we@N1|A-{5hQ#*6lHH=SAwD&uPWsVj{${FTU= zEyj|Y_LN!D?6@-CkmRi6=$v1X!#yHrkHAmv_rl|Cq!{hMh3hF-_1>)8 zt*jS~9se#Q;f#P}$C0=madLBqlT=oxWCN!tO(e;g_iH11n`Oo4K-*E~h6R4CLBeU1 z$ST)#w%8}JEk`_3kn>LkxCW0)>+d$|`D{qZqfu-zKX9F8>%!LTr)#bMq>$Hst`U=2E2@|;tm)u~RZ=0ijR zAz*t!$Rm;IVl~kxg=qx*Fk*Fh<$fhn0N@_KxV#5hRY`|f51hfa++gjgjE@s}pS*Oe z=66p(Y;<%vYc*W1d|Iu|vjF;+p%=x2ni_m(UVowT!LrpicAUchNw?W>DPKqfCTY49ovYz&YM#Nf92nOmuu633=sO9DY|$D)oUI1+%f zF~*=095SW}DPlT$I|z6H16BXVe66!%T*!wo7?D9r?bR`FNq^aBZl=T7-Porfs%UH Rf^4B-N81?{etieM_&+EnOmP4J delta 586 zcmV-Q0=4~s3fBaX7=Hl+0001@>~LiO000J1OjJbx00960|E1ZV-2ear3`s;mRA}Dq zn?Y`bFbqW z#Z&Bgm$=*Y@dyJSJZ50zXF#sug+&<~*oLO|+t?bWNTtMqOVDP}ZD1*JV2e{Y`pyY) zpd~G*ci5CzbbsE!ab1eaQc|pZDAw*(gX&HmxLJ3nDv{=b&1))B32?OLghjuR!f9`t z1?h0qInura^@S!WM(bz^%jI<{W{I&FIL{2cZz4*}*1)K;+}5FNu^2cz10QyRX)$X3 zZd$$U@zG0@4D;O_h%y@^MYEgqWQPXF0eGJ@w@ZTN9e)uP{ha>+9);Yo1Vq+W4)lmnYFF+VH@&MX7J{4ACdyQd890qf92YpS8a$wKoK#*?1Q zG2?fOD6@kc!R%%^lF+)_#>W|1;O@8`qj=yS+HaItBnG||D;$dJ>8E5J3df_I%di+Y ze*<^@Ttk*dho!E^dnStiq2PLq9ji~&z)Y|hILA4#nhH;L7?v7|9p-yh^1fIk5{dpn Y-)_+Q4@0M9m;e9(07*qoM6N<$g4gpC2LJ#7 diff --git a/src/font/sprite/testdata/U+1CD00...U+1CDFF-12x24+3.png b/src/font/sprite/testdata/U+1CD00...U+1CDFF-12x24+3.png index b07853d5d0e53c0e04807029eaf0f40d345469c3..ab6bec96d48174c49b4822c5bfe87c766207399a 100644 GIT binary patch literal 1870 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 Uw5n@}ota3--j;52$I6TIFRYHc(*OVf delta 672 zcmV;R0$=^p8mtA77=Hl+0000`k1mG*000J1OjJbx00960|E1ZV-2earVM#}5SO^z0 zYj1W4!OX0?nl*!&SvZ>=`!)=RyP2IXUFeZSr1oZq`}2`C!++RA7y32~?iCn+)?E!r zM0(5gyQy!aN+bXP_yR7IWj2r`q(|_w(`5|O;hDnR3lI&|ND`83`A75ad;>{C0sw%b zXm7q|nbSZLk){#&QKlSIn0o=-5N^jFNltQE%k>a9kW?f904P2!pT|jkGfOp)M5NT% z?4}f61+RHo3x7#MN@cC>zdMqIlp;}`-d?_eq#*%7@o71{TPnMXGtWk;!(m4$z5s73;S_Xj9((?YZ7Jrarq|~H-yd6IpsFC!fogc?Y zrArjq>y-dN6i!>KSlXY$kTfJpbv2hCGlQ2;VMrPh04Ua$-H~I>FzpeG*3Fu~^#Vyi znwW;;6IPFkElwsi#tl8BVUM;nZgzAt4)?8QoUBmoHkNXtm1Wu(8B)|bG3 zbTS!I0TRiQvjf5m90RR9102u)MKYjrM&;DG|c37JL0000@s7?rm41p^Ds}dsg zBB3cEJ(g96K#0%`Apih?Qpyhi00960?3O_e!ypU<|NrXt)Jn)P-ZY7A=#13EA`CmZ z6n+b0UUkBoFMpW1_q3BU2qBa$WYTdM&h~?daA90~vK1kO5{1O32$g{lLQ6B4m4ur? z2%#td005NYzb(z`T zvhKP5<+=rgx`(}mHV6$WAoOQK007XJHvj+t|NrcjK@I{T5Cr}Ir}4yLBE-pPmIA60 z54~$AUF?AyeyuZpGkieqpvNghANOaWB%z!Pm0lP+4+<%?ROoIUxBp{?w8=>D7 ziUxrS2qhB&005A{jHj}2-RwLQxf&sab_-R@&Ja0gn?468^?rm9Iw3Uk>Wd+(P(x40 z0e_+I3zb_0L-=yyioYd6%7Iv5K1Nl0Ptb{00030|Lm5*4niRe1poi9J$WF!VrfIWPi7Ji zYbfk^seE3*w2>V9N_j@Q975{l@0@?k~2(tu`7=Hl+0002xMSSl7000J1OjJbx00960|E1ZV-2eaq=t)FDRA}Dq znL&=iFbqYFx?tHO^d{-WkYLBPDsho=1D0JNm=GsT3@J$PlbJ#On<{-st?;j7J4990 zwG%aCccS&sjMVPdhf7E8{)|Uvb+W6$UatFdKl;bhv>r;Mqkmm&>^nImwW^3zZ)tU+ zX*&>`NG#xp<7N$evkgBzgc6SW(hZMbRybCVr*FM8%N`X;B;4-tWugq6|mTHpzy_*#?fHQ(hn;IEtDx>thW7N8hDh z7LrLFiARkOC4YY#X|Y%i#a;Iyvvtc+h9R*kjJ{P(n&G-{TXFuL?OyGky`Zg zEPC)`OgIuPL?0bBCn6xq)S|DD7$1R9&Cfwc_W(4Hg~EuN-$9&L7DG?kigM^l*9J#w z(SK-B5z6qpOzHS!M)V<4i>|fNP<&atwG#7Q%VtK>^ olk7nu93Ry@<@_T^rBVg`0Ka8$_PUMKj{pDw07*qoM6N<$f&=;m%m4rY diff --git a/src/font/sprite/testdata/U+1CE00...U+1CEFF-11x21+2.png b/src/font/sprite/testdata/U+1CE00...U+1CEFF-11x21+2.png index 9d98be5605f2241ac49a0e5df4cb7030c6b36f6d..b3cda82d1391bf8a59367dae98436e1ed243ef7f 100644 GIT binary patch literal 1006 zcmeAS@N?(olHy`uVBq!ia0vp^9~c-IKX3pU40}EI{$gNY-shZO|a z63h}<+)gmmp5W-2AZWy-T)~nb(0_nKu2E3p;rdt00^i>9axi&R_5b@LnLfXr3~b3f zf)g_id~>$ON^spK5s@O)dP-C~9ymrC2im z#9kn`3}e>HNyytYV+?TB0Ut@uuM+sZ5d8n(%WnYCZFU3zux;a6o* z(f{l8_bz>#>v{M0hF!w^rRh;FK%l}>aGzoJ*SgZ$4iF$3qU7#Dwxb3jEEoR&f34>gYElxj>ae9v+^Hk7n@%g$K~#UZ z_xQ8W_2ZwOg~Im7a1qUF+yMJ|c0-%p?9Qm#2|1uB&_Op1xmXN2STFp(Uv>LtD@%;?2jlk#MZ~(~gDma# z?Rgj8eSm5G>2oZN`K)S=&m+~Q1%DHWc;NhWitRgAHU@^i8}akLeP4Lw-if8GdSBf1 zbPE=W&-=A~>3_99doBgtRN8Rh^(JG-2hoiuFILX!1nOcD`w?K7+F#ws$k4Ft@6*hB zd9OFUF;Nek@}FE{60dr=vOZMH?+3(b*Sz_f4S3oP{+>T8Z}pB)dAG*+dHK^h64jC> zUax=Ye>&{If%ntrnlrp-(q4G({lp!6PM0$I8U2Su&NV}>0}28z7k}Tk%Dv`#TDJAOm12TjgwKzEUnWcamp$0z z&UsJ%w9nuE8>tt*l~(Ui^xg2FNZ`)CYD-Woz(B+7S|AgDaxf4AD|w3}#V9ihtoQNg S*Q(P18S3fk=d#Wzp$Py(5w4#A literal 727 zcmeAS@N?(olHy`uVBq!ia0vp^9~c-IKX3pU40}EI{$gNYn&;`_7*cWT?cIx^j~pZ# zE|yFX3Tk5g;lQbRP)J8nHGoN0M|BB{*MgQQAM_8sI>^9vlf(GjUi}$?7xg()63$&* z#dIR-$dBd{o6^4<{;y4Xv3vQxPxIoFZ@GX|?e*1vIXADG{3`eHedo8c zH)`|zJ^k<7Qu$TiKQFDeFP&8QO>kTF58tY&KHu1@vpqg!{(O;;cm91FXZw!4?Hku! z+nD>hq&fWg`~|xre0Oe7>v%3PODnN<&R#a%Me}$3|L1c%^!t3iSj&HJRoBgbIqO@p z`;Ps&cLeo*8phn&TvB-b;iI&uqi2_T*KZBE^ZMbVdmlC4+3GSd7zutfWRyD_ZeOo- z_2!xftK++UZiwhaY)ClR#L6uOWjvRvIV`Qv#0UytETCe^=Kpbzl0SSnxU}AJ;^XgJ zVmcO|6L!?--QDuj{=0#dcm6G)kp%}2g7hvqacdIL@XcIpr=L&SstU9wTJPz^<*9wM zffk;#kzio>(fOU(t@+wC7H+Yeol|nwCBm4;;}g~xaEj^tcn37;z@GOkJ#1@rf&3dq znm1z(uYoc@&zZJ)j&5WQ#1#w-Gd@54FkLykrW53)+mRq|&GFkXR~6*PWn0ei0Y#Y^ zCfs8AQ1ZD#CCQ|~%IIIylYbK3K;_2V`+l$g{Gtx1bK^*$c_7U$=JBs^XHT-G@yGywn%y*{V_ diff --git a/src/font/sprite/testdata/U+1CE00...U+1CEFF-12x24+3.png b/src/font/sprite/testdata/U+1CE00...U+1CEFF-12x24+3.png index ece419c7403792812d12ea04a794f463577efd8c..e076da7c52f1c09e553d278e5025d464d17985db 100644 GIT binary patch literal 1255 zcmeAS@N?(olHy`uVBq!ia0y~yU{qjWU~=GK00NFLPi8YPu&ncRaSW-L^X6uLVT*wP zYk`b{qR@l}78QkuDlSZulo&ZDZV-x7XSLFOdc$w}+%tvmzb~EpIL%V-r+bE!lG37T z#tpxpr}6|(dVAb^7Tf&IXAVUC>pSqKm`y%cW+^DJx1MplQ@2B?Yi&?y(S^EMOL-;rv)_8nzk4cd0h--xhhvM#S=74PD*%lgACA9lWQ_hT9JGa`42LJKa(9lUPm0tR2w8vbVQ zn1BArem?n{=hq}AG%;%aEBeUuqRBt6n^6~hMrEN#72^g!@+_Rez4soUyws;4LOh)8G{1SBjt z-~iHnV6Qxo1ln@zASaWffXl@{o6Q(n<4Owb&Q?EI%I_NZAoCjkgZEkUXJ08QYR$6T z>9loD%)%(Ybpg8S;VY&whyVDKny{d;k&R7CA|pZJ$BQfR$*)zzSCpL;T@?$|Fg<4B zEfALxXp30ICy~!jDpRsyx+iOgoCd0U`h@Fh(Sxqd=XLfk-}^su-)@;?h>1B8FIXXt zbL2YY0Ce2%`?r`SUM%4KDS0pY+9D09%~G-_>P0F~U1KlGnj{_KUDTZAnHQjYl6RHr zPRFe*Kszh8TKgN8&vW;C3l#kNgzah-P>n56a^9TGqUfW?q?$ z2M)~aQWgR+w|;5Pn*~%o38)ImU`B=qhaeGm-H;0yT&x#=&yP}O-nvk%b>qbE36uT4 z1>gL^P?ue^y{__)HZ%b!Tu^jk2PXxE0D%_*3!8z70?5+fDCxKWWr?sbF)%!s^j-Wx zMWy9EIXyZ1A1}q=+9#_W>I({yJVMr_JC*>kWdwHy+E*EjMu z81S%O{JVV_e}{8s!IJM{AFh|mnIxa-%xiE(cmO`=-id3XQSf|{!ah#L*v=i zjfiymr2=RY6f}s716iO1YRC&@G%WbH_U~B+X`m~SKmjmPQPQyVq$X4qe}GZ&|NmQr gA!{EpA{%lbGLdbuqQJeqLLg&3UHx3vIVCg!0E+Sig8%>k literal 755 zcmeAS@N?(olHy`uVBq!ia0y~yU{qjWU~*t#W?*2rzj0X!kkSqC32_C|{QUg#^78un z`u6tr{{H^)@$vcj`Stbn{r&y>_wPS{{`~#>_us#N|NsC0h&x+*fu=Nix;TbZ+Pe1CZ~ph>#^{STOXPBFl{t(>FwRC+S_^S){F}gg4#(wDz_6E z_or`Y_${22H+{qAb8lLzsf_?b?(cn@il9LSJmy^e=OK6 zNqz0nG*_?mxI|Ks-EAC0^(JeFWTI{n-GM;c1!+$^iY{2%?^JSC{= zi`BX9QTDmkN_?Ah7W7)k@_&C+{M&cS|KAFy*}U=}pRB0R{%2xS@i}2i*thzWyN&*S z%OCIkd~EMugWUAnw}ZVj?{?;2mj3>@GWf#H=EZv)%hSK#{aSH-1N)m}t1a%Gk}T1m z=a+w{kDr%6zI*+~$zQd%NE*K{HDgI8X0E5oVSC4vc3wl5Rw+~*oGwgyXXH)iObI&CMNg^vcM6=<0u^0AKa(9W6FG`Z})@5 NJzf1=);T3K0RWJIPNo0= diff --git a/src/font/sprite/testdata/U+1CE00...U+1CEFF-18x36+4.png b/src/font/sprite/testdata/U+1CE00...U+1CEFF-18x36+4.png index 6b617c4e21c84fe35e896d930f8076aa278b1f7b..366be38671868fa0eeefedb0a19356ef4d3c2b59 100644 GIT binary patch literal 2247 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 diff --git a/src/font/sprite/testdata/U+1CE00...U+1CEFF-9x17+1.png b/src/font/sprite/testdata/U+1CE00...U+1CEFF-9x17+1.png index e867c55f84a9718b3286adc7d9fc289340b60a13..5cd7a4efeb2fac99fcaf19e9b0493909aaecfce6 100644 GIT binary patch delta 727 zcmcb`@}6~qO8quZ7srr_Id86C%ss3i(2$safTL#ue#}dlYuiY{jVHXjybfPuQB(m>|_|8MRbWMfd^VSDhs z{&ff6YQD|RV)xxQN&LN1Dh5-^!0_hWMfKMy@2;QJm|Gnc@2BuWd(ZWhz)YU`%8^qz zLUL-vIDl?2hnRO`BUgig0P}_a|Fg@ddvTf0tAF3<+}_N6gYRSE(<+25+PpMA3dbC{jJR{e5T>Ccva|IhtgCC{;HUF-$(TeeLLUa?fNIR0cQz4A_w zCG@%;2ZNol?)Jlp5iNrG{oD0o{VzQIcx~zHQjREl>z#f92RTnZKIKz!Zb#XE$EJT7 z=NBZJ@_Sd`y5AmJSDI<$*feSCPXTb~HN@^^2mrh3Fe4{Wq+!AT_0p4?m=Hk=WF2q> s6950dJ#5GeR`PG{*$4d6AT@ps#r-bK}Ky8@2g47N1%nlr8J@OP^zHaD-lo%)?y+HzjsK^CjCc0aoJ zEj;ooplESS(dU37?ba>Vi%zcHHu*L`qr;cB%^yQ*t4sc$tUgAjVzbm z1D(F0^M9Ej$P3~?uP`XwyLx>^fvF(h;ri~)QlcIUM3`*<-SPKRpWtwCj^ez_s^)B* zDi@9w$NQcQpZx9YAKO`{m@9860cCUc!~Ba$fBVEfb5ZEx-y&&GK$4!WelF{r5}E*- CB>%kt diff --git a/src/font/sprite/testdata/U+1FB00...U+1FBFF-11x21+2.png b/src/font/sprite/testdata/U+1FB00...U+1FBFF-11x21+2.png index fee09f4c82b629ef15cf30f1e328f6c65baf2ab2..023396feb4c6f9c643c7874fcaa14f51f5fe8420 100644 GIT binary patch literal 5427 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 JH40GJ{{Ub3EZ+bC literal 4884 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 O0IgfP8Z~Ox5&s2S-Fip> literal 5045 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 diff --git a/src/font/sprite/testdata/U+1FB00...U+1FBFF-9x17+1.png b/src/font/sprite/testdata/U+1FB00...U+1FBFF-9x17+1.png index 85b858ee198bdfb18312209f1e7035c947db9577..b58ded46c83bdf89afd5252b1a3937f8003c8301 100644 GIT binary patch literal 4341 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 R&vd$ejP%TO>$Kg_{{xNIBx3*o literal 1911 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 H^cdrR<8gGH literal 2104 zcmbtU`#Y3*8y_{J$$5;%AyZBx?{4L7Gup;Z3?n9)nRf~AIIq(bM#dngXvnDxE9+2+ zXN#=EaHYW_+N-G;F58oawsDAzh(gTBG4C@v`~&azhwt@y?(hBF_vijRpYM}Jr#h%A z=_$crFja~p`DYkR!2kx^VS|K03n`V{fWdZcQOG3M3*z@9 zneK^q%r|9XxiOxpNOAJrJT>)j`Xkxau0eF=FX!@NDbP zY8;$*8k7P(@WOXBXW+zk#lGsj>d5Ooq6Kd_@gUPWq@O}^xm{vaf2iz%1{n;PHDu;- z%Z?ulV}Pts4H8djhkT-U3G9`AnLehpMw6^Tg1A6ixF?kOs ztlvN6-dGWsx^HfpF|@2freEIon6aMN={Dm1ci9rQw*$T45<2CG|V*MB8|2; zrrm_RPYR|awmhLVVSJ!DMd4-bb% zKIKIbv2YYW1&Dh^KQ{3!$&*Kdcbo*@*{!g5$q-K~b{jzw3`KsHigDLKPXDjoYq6=} zt-_`IR$fh`_FpIr?Qs?T$ey;&G$Ynjn`5vE&$~l%RH7yK6z8+AMnVn>CspFjUX(xg zlrizb<%PPLd#nL88BFB{4+0^Bmy2Imagp&h;D#Q5_~rYWzr|4NZE=7ixPrWG*-_7g zag(U<=VQ|S8`~~Gk-<9%VhnAwz9H)V>@!CG&_kZPbC#>gDk$NMO zn##s4)--&Lv$cEJayxr7u%JA8ZF6-BKmTEMT|}di6ZQ2l(idGa{5%S^KUsztIe3-| zI!NIolAw}m`%v)yxkiskg1%aY3;F(*UhR*@_f|3R&D;z7t%LE0r;omN->RFMhm0(=-;70O2NtCpcQd#ZSv};Yf zu5!9Iltom*dKIg@$D2%h3Ov%D?Bqv~0x*kndYTr^`zJqk#=vvjUwdt`9O>?-4%@mY zh_3*7pRlu+3OH$|JNeqA)Uu3ASHIwn`fI=C2SRZRJ9^+bn>DMk12^j88z{}*do}_R zRf?7`n;46doSzv_eaDje5nCg;Neg&ij@8E>PNbvO%wIpSGv>B+l9RlEq+Yk(&bW! z45!gq!vdkhXY`NYZ777O^ot^avH{+Rf1I>RQaAs7AQK#f=j6mqSK6jEn=-??1;kq0 zG)q%v;v<20<3gHc%axpw-TI@a!d^cyl$*gdcoc0})=CssAp_^m=kz%h#1a+DsT!nq zP1i*)HRx_Lbs=Mu!CM3fs&n1yQVqD`JyI60BLlfa!YZ0*pIa&I!p^!hW>QS)2a&e?o? zaU$l+@9C>MHM#Q2|JP!sPxR%fMNTd@N&5dQ$_0A+^7ueR)*&UrC*5=UOWcbRZ#^x} zDuyFeCisL~9++Msigd_K9e|Z4-VNpfPE_#2lMqjCZsZr{fWLiR9;hz4#Hq+)hxwLX97mC{yKd0w?6A<1hAedb zN3d&K%4R1@!-UJ5&Muj9&obe}%*$bU0eq!2S!fivNc!jkry2Q#v8wu7RZf11kPVFT*IWQj|vogN5ADBnxa2yY7 z0C;6WRXp}-M!uR5v4j5$DdMe9SIgIjDNe&gT!kI`5{%~o1~vp7)c?JA2H`9vJZVHR zVkgd08Ulik)#(6BZ3t%>;f``#AFKo7;o1MbgfPgh*rM-F8Vap zp+=E8z`c`zbwP{U6c|ka)J}xUhu}Sc>(lkfzNzO6%*^z7!-?Na?(ylL)j^@Ilu{$c n{E@hh+`ArW;>1!#m|yXR`qEP`z!xth$_1m?Q_1zVe%${7hj^Ix diff --git a/src/font/sprite/testdata/U+2500...U+25FF-18x36+4.png b/src/font/sprite/testdata/U+2500...U+25FF-18x36+4.png index 7c4ce8505754a436a975aaf39f5a31449bde88e7..05ff2a5f2571c2fa689cc839e6e4b2957dc31eef 100644 GIT binary patch literal 4570 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 literal 3125 zcmcIldpwls7auc>Ta4RJE=^cOZE0<;6XssSXHDG3z`2m~T! zXKU>Yfe3*R2<%%i!4HVzp>ZV$L~`BE+R`OP(%`;vB#;VUiU>4GYqcqzN+=?~T9vg`CkV@R zG>M-Z6P6RKWjgGx0@58!6FZrX)#(QQsu2oIK(kghRO5?^Hr7@fEnkxSpNrsffayI2 zu##gesjRN56X5#HVb4r2CxS3;0SF5DQUrwujZN(6?4Zj(0Kvxb)0GFP&!KUpQ`11O zcf}exj%*3iHq^zmG5{!&y|y)r3pVqmsGIVehz6b1H(xCHa4O3R%;WJz!){v#n;5r% z{&Uc+&aMbOcxb-V@WR@IYsi)G(EvJAjFn9oT#dYP!L9u@DZ^}#xoypq`p&!DyxUHt zalpX=cRIvdow_D6_#ut%sx)%2Bq@@V3HTFVql$dZYWZ zHH?8gZ3bSqr1j!J>EW(TL`G)iPT#mTe8}u<^@_N@X^MIt%3x~U8+ySypd%iXZUa^e z<9O()MJ}bdI8A3;W_L{6fFN^CKN7$1Gs80uhW^(z+wKBMdtCZ&1ogB#f5M0=Y|3)2o4cLJhu-f2wLXBa!+Tyk=wdo9~=h;;6WFSBIw@h02fogv15sz|X z*SNZne0=S)g>R}Q$b)lb&#o&3k_dt=^AObn=82APX*n`H!%$x;qD1Rd=^&P`SDqeW zKjM%*(an7fM3Wo)sek3ND@Y(b@Hy|?Y>2Nw>p^cxvTl=o__k+e!|KHh^r(is{3X;z zZ<%T%{;n2_SId8YD$Uy}RiDqU>n)VXN(dL8QKsjy3o^}e6$3AV-Ad!>*_2}FEhz+>u*h@VMlKA+3+<)v3P zZn*P*Y`1Sfr|8@%y2caOj(T!NFF|{B^mEFG)v3rQ@cOif;h33N+70jd^u~k=en9G_ zxTO6@IsAPDBLu6SJ?)q9RI9)l93h1CHAE-n!EM1QC`}K~5Hpm@031ciJvrnwXcWTb z@{ntcy)JeESZ?G6b!iLF>@Vf7KbgFEMsRh~yi@Zn3V@o+1{M~ZSyjNauzWJ!&nV;T zawnC0lR|R33A9Yr94+6hlcjNq!kylv554FzMUE_Ys;K8UT)ZZB%&=Z#Jp4wJm>~jN z2_*CGT+j=m35Rha7KdPuH$EN?M&}&4t+uJERED0%9d`NtcQNxT4ovz|PO5v-TcZC) z_-r?4<>8e$@)x)yeyV;O`Y1F?%3#R4E=!}p0mMMfLz?ji&40?SXGX}AEW!Ij57(!^ zShKSto*K}Jj`6Av3xX}9oI26!8Ky#^=+}yY7;qg1ou*WMI$xUhB3Mt zH5b-X8Nz+~?UF1i0_3)0ioOoDunLf7x$y??kM0{-RJ0|ir0eibk8#9GM!e=QE&1dJ zY#_8*bc->Gipiu2Bt7=`_FN18I^}3i&ZqUMPbxCEb6wD*mX-fZdk_Ynxox@AJG}1v zxf1qJrqg$XQ1&3tPv+0s0EgpTfCQ-wL;6=Yo!{QPrHP6{yMo=*zc5fg~_b~N7EK*+A&?;9b?^cE(!yF(H ztT5pD5qD5Zlx~FeO$vvxOso`ZS0OYJi3#A1uOGok6{G+!HM5XlitMBEdQrLsR#zm? zxjo0f%HCRn?0ID(e0W!?X@Uqtrn6F6=%qd6=aFx;JQiDot&YI#3VS&2|*& zgc+bGz&=Rp;)}?*#7P~-mdJ4reW03BzqyVFh`x#bh<(2WC1yj-TS}F|_7tyaL*OQ% z$&BjaMtd)S)(Whemc!{|(`cL&H5~k?6j(kN5+#5Z4pP*kV38Yg3OFh3C)hfKK~Fa6 zX}zefEZxX%0z#|blj#M^l28bNVR{%9p$kG^ijc269|uTBTZw%TZ5ZCI3<(YyS5t!$ zGYJjVN!Qj-*R4WIU_7t6vU`pHgKrb!T~hCy-qYr(e&UjFdB10DN~N}yie!6EI+pv|FQr-#A@-uI#FV%o*PpF% Z(a}8<+I4G0$;}Acop7*zVD;_QKLErzM@;|# diff --git a/src/font/sprite/testdata/U+2500...U+25FF-9x17+1.png b/src/font/sprite/testdata/U+2500...U+25FF-9x17+1.png index 6da0940837810b36ee68f8f026cbcfe8afe5188c..cf96b7d15bd266af18ffb33076d8e614b44d4018 100644 GIT binary patch delta 1839 zcmV+~2hjM9480DJBYy`3NkljHqT$o;c4HcrS1fe=E2S-QChqlAt-a=nD)kE4*t@9oU_z9RkUjh7Bap~S%`lsGtq z(spivs6q2`)#gU#sDVW4EbyhUsgSLMNkZ@5giVE(K61wiy?+Zr0000x68XXFm*ao< zEkFn%PYyyQ2u%^vr(4B}XscOs)hS<%whgb3sl+b!U+ZI-h zkU9sU7=#cS%_$ZNc$^Rb0KhH?zx98iw$tZjPR$LoO%Y0i5JKIi2&GvfWRpEJsh{~p zL1S-Br+=DVsTV<>!@eP1rkYuWzYA@Jqc`j~^;}f#+>r}csCG|Vh0^P7=9NC5w>*({ z7(xiufKWIIp?Z=+005BZ4FCZD|LmRJk)tpWgq49aIEO$0`#=Z|!66WWLm?E0KnR3D z0QcZ4&IU9i%~)eg7`)w8cV(fUnU7wqpJHqAFMo?lPLgZQ%xoJ7pkx6EK;Z!20917} z=q9Ut}~}GeuR?R}?5(3Xav{H%q27G`poWb5+~jZ$j5D2&CY0 zIFxwn1v-O6Ro^^P=caI=*v(pV*PS?8+bo~yW5Y(<3sC2|LciG9XnO&A{zSi?DS%V~ z=zn(sK@bE%J6C;j?o@jh=E7LBeFalgUprU#-i5i)*Su|XfP|Q@%!^_l<(D}|ov-8n z*Ryx&QMlKn2U2od6X;m=Z&8c4~lB+zm?L=55jgyh1v z-LzVv<|ei0ou~7=(TLu&ffRoJ{z&2FowY+|AhJ04FS2ZqRtidX)_)Fp zfynahA+oR&)^bXA#`c+kLW9`S+icNifno-+&5_lj&jOvI*^=$+K6b1S1VPYll=vb@ z-Z&&CiO;re^iO~KqxnP2fePvyfaDio0Q51S=L`T^9mvQ4pf!NrVJHstiU71hpll2P z$_G@20YGm7t-t`Fw}2oBg0`i90Dk}g|NrdO%?X4s5P;E?wxw-pmL@q&@F$VcgP^_# zdq`Nue5djIh_=9fp&tIB9;Q&XOR^0~ej{<{F5?qJ1odAmNRS{w?+;qfU0x)goeVnu z+buz5cRPM*a=>t!AVGoz33^r#0000000000003M!0{{U3|LojB4Z|=Dg@0iPg-|Gi zFbIV(2!${RfiMV#5(tH`X>%Og?P-T;vGjk^Dmm(*Z&uTs%ntwn000000000000000 z004gP(l1Jf4R7yaOE-FW>ldXFBx<%mR~Z|YsySDnMF)Gk z7D<4jWl0sNY9QC5(4gL;|9?E+w{A9ieeH{%=fB%cYo0*UZh`hmSD&G3cjXAQ`r-J! zMWG0{jn4l1(3C@iTq8$kFGqN7jt#O`ZE$Y;3L9J4@^oQt5J)jfFOi(J-ce-k~Jy)2wa=vET+ z$3rm<_tU`zEj*lDilF8h4drYw4t*$}Y1=yuwcjv~D{emKcpo(Ad+Vf4dE<|xB8Fz*hdA5OA6B@N&A d(+|TqEjI=Nw9|GEg;)Rp002ovPDHLkV1hkjT1x-` delta 1532 zcma))`#;kQ7{|YpTt?1li*hsvU9GBNL%(4E0^ZfL@KCjQ~c|Wh``G~YKG`TyVjjx>?4w2*E zP2cXtn6b)O~%w`;NH;akl|ejwCxb}9qFMQqS?5o1svB3?hI@`K#2VdJz(mb;_@y%-K|AQ-k1rJ6xz zog3jCG~8+ksQVX_qTnsSL6f)v6#&2iHKXVj_655qr-e~w3b25>r8df{s!Fq{E^6qO z;QaRX{%*eP1UE@^bd&(#Xm>$INX1{C28zk}8&M{^q9Zp6Lh<;u$dtNafY{g&QGb8QXPGBm>g~M@ z8`j9bUv7HYO#5E_$xHgSY;P<4S&o|_a_MEY#+ZMhoJmvN*?2r|r2k#zHzA%ZiJkL( z3rE3MN{!Z;LihDoz$aJyPJKHw&Vg!XPiNUtHuph&Yws(QMYY&~4X|aTH~Dp)8C~Qe zT^jJs&TZ0Y$@;`j-ggfi)AE=BO*Lavtzn%$l4(NwwA4J5wRB1^cZ?9-`+4AM(qhB$ z_W6ujEFEJeokb;k$-OEu72noeT}*ZPwf0`DZbVEZ%4A_IZ-3wmmilE#sVBSnl5#Qi zNf9bxRX#o_I_=HLyN}l;)QA&{Q@YTC)FkXg05a%%g0Q#ELa;LF(FQVES6%#iw-`mg z+7NQkc_$ z3g#MbQ(PuUegC@U!%_=!8`)(u6J46o^cF0%FE@5AL$jIQWxqJbc!Ii?HPWZZ@X#7# z=dxT-geP|e`9fLZ7(P?6%_W_aRNHx%D__q@LAlIES!(V|8 zg8xv9${Tv^bIKd`Lhj zAUM3sD1XY4N;OYz{SdrgvoDlJ(|e*Z9Dq%h1A;JTcOuWD(J7VS%M|PiJ6(wP>QUPs2@l+>A KcZa)RK;nNp@VKb} diff --git a/src/font/sprite/testdata/U+2800...U+28FF-11x21+2.png b/src/font/sprite/testdata/U+2800...U+28FF-11x21+2.png index ea15fdfc99cd59f5b6529ea6a6aa761a9e8d2ba5..804e3017cde14fb46d3dc0c71327d229aa5d7ae1 100644 GIT binary patch delta 1012 zcmbQs^pAalL_G%s5bX8b`-_2r`KYIhV@SoEH#ZHr8VqG#pi)cL>^

P@#_)LCo8q$5OPw1V!#;l75R(9uP1sk@%)s#f|C?I}c^d*am@oX@ zUdAk}D3@{H+vcCgdJ*~iSGTs8HY(muTUq<@?a76v{324<3f~`RoxQnr{{P$J5L9bSN`^y6DxgmI6?ig#^?$CSf=g#i~ zIsxQ4N1(+VtQUUYukthK)r?@hcUv;K#Z~<8jQVZ$DHok=*s5mc*xT!M*hJr`dB3M^ zVZV1<)v=|!rvbIEkubNFxo)uKgV86w>TM|(7q%^&863PP`1`qRiC-svu6m`Dzw+_! zHlWQBAO09m-Mf2MMe6&uuD&;M7Yx3Loov^dryIFNpnrcI)G5#~`2BzNdVj`1fkX9a z=}SaJG;$mtAN^jCrBIh6ATKVlO6$^_mp-oAV6^_Sd?7bo7bHZI)mVH)x= z_vFH_=|5{0 zJl^Cb`~LiO000J1OjJbx00960|E1ZV-2eap(n&-?RA}Dq z*ue?IFc3u1FB|rx0#t_Gk-&|p02ifG>dMK%2m&DxV$7f0-h|=pNQV2S02NY$fLeNL z81u3#)?ugK$H!LgHtP2 zR74<%R*4Z5N)e(Q3D`oAB*1WnAuu({mV!#SOae*Y#$()>-^{+5xBu^Z|M&m)LL@zG z1z{Bdf}j-<;lX<#$jAYLj04Re@R-dhiy_FQDGJgYn_zt%1Gd|ovYfw7Y{D;98u!z&ex>!Q4V&XqQ)fNmYQNA(R^guT zoQY;E#R6CR)?W|^asm)mPDd|vo;f?&@`9Ltl5-Rgs$#!yRQ?^I%>g8H`OOpB5f?EU zB2}|3RdyZuuf*918CRx{j(8a9B3{XN#L6um5LlDT)Uz)W+06TMQnH1{V{aU(diX%S zzMfmKF^UEfmu8g`H|^3m0A3Bi@AwOeu?7hcTs$!8#>blpBH-4NFq5|ZvI%#A8MS7Q zN$rm}UwvhkGl^T6ZSAsdRCCL_shOP?_)2eqXV}7QbSmiI0Ma0LWVtY0BMlJW_VZmb zlO1h&F~FW^tXEgBlXibJ9absMWXdAZ0zVrxjFHYk+G6ZMJz%F72F#k8v0s=7K(nqL z;hz52#4skqB6FOFB_z^4rJJ8qcmp5^^H8nnPn_ri5ZNmh{M}eB z8=BfPi9OL?m_Ji`2Q8-gcNdnbU}MGNyV6Xx56G7RVP*UAA!^G+{p(8sb6}XToD$uW z$8Gj)0po?m5Dy{6{y-1R>aYh$5GfeU(Y90J!sKdYK8x6!mq5nTYg9Nyvf=q}FN=!Z zD9=6b^wK^|(bV_?h2rbf&`QwC>n=_NIeHit}Asb)2HRu^Bu`GN)= zg<7%j@nCNi%44cB>Sx1Ma$Mz+q%IPB-z+^G+C!7E0t2L1DIh+Bb*C6^yflU@FO8To zl4S4JoTJdVH5$yu-O)06i<8GbL$V9_)fvU7o!c%fdOL8*qV!~e8@Alzy8t!MX| zJ{$x!#=cDK(9maP?HaoCTq(^J{eh~^M$#qB7!AA6=LDx$dcopqnpO3KVTC^8u59m{ yOR(yh$&TmNwoWd@>LmVy3i?0BcXwkzP%{c=xG1d1=JdN*qM^MapG z%%>mLtMJX`wci&ziAVGEwkz*W%jc*cI`cl&Xa4P|<;M=x`=oUld={}S_L-k|)}$x( zrd-oqaiCD}`IKcG#$SE5|Gd3as#)A|#>#Y~$ukf6*j~;(=aaZ>-btS{F0k~%xRzrF zkVPzwTW40O8PC)_bH(`Xv-XHr2kVj(mVpdZ1IaAAJqKjWS`)z4*}Q$iB}Z_I!o diff --git a/src/font/sprite/testdata/U+2800...U+28FF-18x36+4.png b/src/font/sprite/testdata/U+2800...U+28FF-18x36+4.png index f3b8084990661e0d00d44aaf2da75cb581a4ce44..49f431a43466a4f62637845b74b3a69f496ca6fc 100644 GIT binary patch literal 2501 zcmY*a3pkW%8-B+anqde@QL$0vEKw9@q;e=m+0+cBzZ@3hn3`A&l9XC$DW@@N%b{hH zH4Lhm9QJppkW<4YL{iq@IMj$S`+hU(+W)<-`MtMe*icAx9b4Fra3tfJ!pATy=FMNsXV4*NYoV`sl;{W&Mgk<-5=3) zX+~ZiHYqK&EN3r8#MPKgd(94KJ`S{297xO&Bj$M`09y~`>3;pWL)Vx@E~p{=6gw() zZyp7XO+3fETKM49rlO{2!{MPK(bOOj2eej6b3~$AlZ%dq1M+9( z-Ax$1Xe6e14XY6OSvT!k_*vUs8d9jlkp>p?(nOa< zACd4AcxdkfJTR4S;s~p!aTuXq??yard)s)v7l|qhhOcUeb~KM?lHH7pdvD5>&W|Mq z+N{Jve#{LeXAGL*l1*1jcPzf)H6LAb{P`K0V%&UcL$Eb>9?fjd{pCvHi?m=o)_Qh$ zTTH&wCYBsdQw(2cz)_B;wx_FX($U@H=t@i90O%CW|IzB>3T+qNs0Fq5)YuQWs`(Ow z?p|3W;;xM=5xH0n0aCGC=ZZ;KU4Po!Ps^?H{o@|-OYjvBL8Z$Y5A#QJsvff=CUt=s zDSszC6N7p{72J*#v|h@)TI6$dM|akdJ`%;%doR@raB|`2kdlE4JghF@3akC3)KC8) z7<4MxtoDY@pA7YNV~etbO+%@kPv5s-dZHtURSYju*|(@jhCnZSP&qchZ~XnomUfJ! zZd^S22l;(mn5U?bsY_v7z&9G?*~`{lsGcaOyQ!b zyfk516lkrkuChMtsCk!#ESFptu4E@pmL6x7#0SvC zh>?*7VQ2r|V4#s^U1el!L?Y)yy+%R3_Mm`ZUz@rIZ6;Hq(?(3R-AkU#QdA>yNnh77tmA`K)+`n0gFH6sivlq{ zd)O8_#qUOqDg!fesf3Z|mP}_A1-Og!!EW3|0ze~j$Bezi0`_=cxj&{0ki3`s~LDF%ACoNCO#Gs?bv6wO| zL92IA#?Ap$awrRpdlP)#14Xwn$UoiX({2?MPEFvw>&67;9#Jc%DgaJhCSykE*X6Su z=;=9DBG;W&WK5zkY6;W}pONN51c*e2f`Jz_kna49@#FO99?rOC{}x5>DUX$L+V3>H zN*PVglfJISM>3YIuxGh-^$XSLlS+&yszD=fgg`} z7MCdk4*Sh?%E3*Cq_TWQ>6Q#>LvCY|J^&9^#64i9Ku4Sn=^d@YV}03;$~(jGP5FwF zY)|xib>d2`E~8%h>-PR(pTlk_42zC$3MeqkF4ez_&~gih=Y!N2{IL3Zo2l~WZxH#uY7#%Hsv|E zUqm_HsqRtvD8`cg?w9JkAI&fHD+CB0ZtVDUiUNl?ixy_n>A$zYi%I?lO)#u);F;!W zTO2>t=7|*QqBo_s(E-E3hnh2V@sd>a@UXlqU}RylBDW=X1E4Zan-G(I5OH7r-b#gCHIfve`<~c z2P=Fde>Yrro>5jqF68BVNw5*ngDB@(V;?>8aV>kG6dREYN8AbkSk5DBXEdpPSys_m zW^!9(8Cv{8=x(`7Fe8yjqv@{CnzTfBQ`~;8o))y|YUzeY?I&;XkbIr?xjK~F`y~DY DQs7cv delta 384 zcmX>q+|N8gqMnhNfq@~QU#}fVu?6^qxB}__|Nk$&IsYyL1EY(li(^Q|t+%%}@*Xk} zVY$#OG9~AL3Xj{&iwTo^CJ4R|VCm6mo=|Y_^}an)#FbZT?Oh~pc|aDeb2hG&^o0% z^)_6ge20JvGXGURy9HEnYZJ)&+?hhVpT6UsI$Pq_rUJ$-sk8R)ECWgvY)u7OH06eF z`FY=-bD#FuKMsNDPT0N%tQn;E-sb3cKQx}GwLwhc=bm~OWGK*GYc7i(K6t5OTA=uS QVAwKvy85}Sb4q9e0LxLg&j0`b diff --git a/src/font/sprite/testdata/U+2800...U+28FF-9x17+1.png b/src/font/sprite/testdata/U+2800...U+28FF-9x17+1.png index fe5c644a7ae23cc3a43d81289a6d5eafa414acb1..4308c536144da75a46f915481571c3344ff02b81 100644 GIT binary patch delta 907 zcmbQtG?jgVL_G%s5d3S2dTQRUrs_{jj0_jlc)FKq;<|OySA%TcuoA>L5_+xtpLP18>C&u^;wG=t{b^m>Xz_CT zJIjx%39a_*O!W*Et05-roB!n30b#JpMLx0m;o=>W=jC4#>HVk3aN+|a#2tZLOolux z7k=Nr#T}87Z9aF|`$qYoQ)&xd^n}kU+Z(gH)#8-TGmm}3wsRWFceOvPy`yvf%N2c_ z<@cRfZr@*`DfO3+k)h`Dy6M^51y;(b{rX{jvHq~HuFI}f`_{a&{41t(!(P7gh&iLO zP8Pt=4yN}DwpQ3*xFwMyQ)7%#iS@xU`N&UOYZ{c01DYxU7XG+&j zWOz^|4~$4qU>)Q-WFWwD;s5{a_l-)ixmJ?*nEB6TF)$Tv}n%mz- z*!GS_y+G=#s-3$Wa=zD1UY7C2orxjh%GaXOMvGG^cRlQY9=ZFj#QgiW*J+iPg6%)d z+2^pNdcS9|NtGlcgAQ2Zl3hD59-rSSmnYIuvisMj*z+&BU3SISiFd{`x&0_sU|4W~ z9pbEwTr7qhEf2rfzs_D4?V{A|cjo^=(eC<|&~IH9fBcS$EBUJ4pJF0fc)M_EtwPMw zO?ejcH|F)-ePF`unQ$ z`x+B+>^y~^7k!4j*Jxp^WUFTPmU@jhO+|LeKE4oqpA!agx<5a3f$Dw@u&bm_w* Uc1G_QpxF$bu6`~o>zopr0IFD}A^-pY delta 259 zcmV+e0sQ`z2a^Jj7=Hl+0002xMSSl7000J1OjJbx00960|E1ZV-2eap$Vo&&RA}Dq zn6U}NFcd`32vlhRjUjC$$RbLgp;UP;7g0z=$S)i)vU%4X2fun8$CqYNladr9C$&{6 z*AR+x(T;Y?D@jsuU&e}dYpLOVV=z{PCewk4Ht$oeLFMM+Xnd>)L_zeDE!w=&a({%* z{D-k3M2jBQq96*QY|)oG=g%91u_DA41yK-Xi-IUEdWtOyqO|DjPp4lPMl(WeQ4j@D zwkU|wq7g(9TlDXzQ(Jw?9rM9h5n_viD2TE}L6jCf$6xfCh;Gly;Lt)Hu@C?N002ov JPDHLkV1oS$ZTA2G diff --git a/src/font/sprite/testdata/U+E000...U+E0FF-11x21+2.png b/src/font/sprite/testdata/U+E000...U+E0FF-11x21+2.png index 07848ad1ee104ed7e0bc6eaf71e23fef19cef1a9..addd1f49696bacc14482dfbb2ae7e0d4973d46ad 100644 GIT binary patch literal 1102 zcmeAS@N?(olHy`uVBq!ia0vp^9~c-IKX3pU40}EI{$gNY5%qL&45^s&=71q1Q1H-# zul~7Q_8K4sNMMHqkn{ilo5PJfK*j-u`q$br3%0Q!sQ@w)fcAjY81e!+4GaFQwOzv~ z&4j9E1CR?+!^jC%^MAecq$V^aF+gKcl>8Rt0{H+5Y!C!;fNCP*KYmf*Il?I9=cGEP zWpV)L)P|PH4J}?PSX4rogg*K9%c)E$`a3nhZTj7rb}2$kvvun~f_w=A1-x$YT$i8y zFSFJYXP*AC|DJQ2_8Re>!pD^StgAGao;a(_eg2GX$sAeHGs`=oUiNhKNN3))>WbjH zr@GU7re^x1cBOc;4AUP0({-2o|1>i0Irv`od0OTQ)e}1m{v25mvTeCS%?Y3B647Qa zPL#i|=v&2i`H=6@FEZBuW}OzfR9`od#XWf9`^n-_zE4EdbyjbzzIujJ-srOEv1zMC ze%4u+>3n*+^QDJC*%RfnYd-jYI=XX9(V<)Hp2`c`wJNSU3!F2)+_=%!VB4SVGB%NO zZ{<~NzHw0fvv1Rf+3L%3@^nL@*xmo7Yi{=b<*R*NUYK?JqWe0#WSex1ycleimL4;xjyBPVMVm60K{ z)_K@`S~*4Kk7B{39aCnW>Uo^8Wk&nr7izlgd$!*5^=;ZPEzo64mz}rJ`Z)!YKC~b3 zvb9myF%F(v_{7_NU;6E4?qzr6t_17k&EFOjG~07q=P^$8dXK2=T#Lk)-OZDFd=uvU zXtP~w@ZVlQ`@i*!$tpITTXl18EjsPK?53KO@|indHWy}isisR!U9vhGnb>1=7{M+Xo{(X1aE1~dw8(s6Yb>AQA=iSMSes}3^ zoQ={#>Gfi|>s9aG+w#KYk@ou_-S>%>R(qq2Vk#^DG;g0L2}w<;WWsTKpa3v|-agCO z>>$AUAZVM2_lA}!lZ14R2I(9XYvL4Q+C8tSz4AW$yfQvJm+$QtSs4nZ2kyUfJb!-- z=Y5y8#<#fG<8~ePzIotp+mp}7CpR^^=g#b3)VMwIV3_d-6P+1eY;pQp*P0r?-45_&F_V(+kvm7MY z608=mcyD0wz9FP>5Q=mfg@8zHm&Ta~6_K7!eU&x>@Pwrv@8AVO-uVYuu z%IL`d_s)j3i(AXBlGocSxzjT$e&OE97B9oMJ$(JeKjVAomD)>tO4feMJz-+*xjuP^ zxXRn`*2k63&CY2r6JzE`Tl!2cd7X1FV|jP!b@}O^XWX^8x8&w~=kl8$w#>YJHRqxc zdz#M_>zvstAI_e5xb%qcmdnofPPct`4!wTc`HoHRHhHs}T)Az3Kipq_Vg>K*n#RY> zu{qAsM;b3LE{u$N^Z0A;#^sJdmqrWr1p*nk=@UAyoOL~~6 z$Hre$ys+woj&7LegO?{BsudPb-qGoQI{4l)oks@}r_X!mTr586!0w6%20OR$DVp<# zeViG3W%{JJcHigot28Pm=ad^2)n`q~+^14l*|ECh-0U^gV&(DtXG@EgEN1?~G}KX)qgk(S-@#Ro#Cl=JNI@BgxNW}Nr(w7GfTD?3;J2$J&tvE)E9 zP+@z`qs07EPpsBVI@@zOaZg!g=CqSJmVYW^zDL+;e>CK?nfAf6(O>o5qXR%U7d}$V z-*LA3{kIF>&VKn;khSfy_sV%^M9zNE)Y!SS_w;W^`L(g?lT#FG|EBN@m`=JL{#2xR3A6T4wxNYu5X7+Uu9q z9&0VF+VJXyM!b1UI^VU&Lf1d~9ru2|W_L#G{k50oY)-zI{p0TIf^%Q@KhgR7&Br>u zE&h|;pKp6h&e_%+RA2jj{muW)*s$`|Mb^O_fOYGJP1vD z`Kp=u{ig16d1;IP%}-v}+x$Fm;CtP)$l8nt-}2hO88hd zM3l;l?y&n^b>r#l-Tmn%qGi0Zm)>o+&8(dEZQGOD8{+-p%>UKzZ-LtfVI)ZIX9!pR UuAI!hd=f~+)78&qol`;+0PEbnH~;_u diff --git a/src/font/sprite/testdata/U+E000...U+E0FF-12x24+3.png b/src/font/sprite/testdata/U+E000...U+E0FF-12x24+3.png index 804d3e6aa62d0f0c8d9b62f1bb5ecfa13be001d5..70ae810217ded522a7157b5be800e6eab98b584c 100644 GIT binary patch literal 1255 zcmeAS@N?(olHy`uVBq!ia0y~yU{qjWU~=GK00NFLPi8YPu&ncRaSW-L^X7mdBT(?r zg0KF$oc!l|(p&7FVY7AV-Z9xq*_Z)}<>PB(S+J_ictzkt|)BBJa-8pN3b_30ceA~Om zfM*ZiHWn{W&gdrZ1ufdGLK=-Aw2j67;9J4^BS-E$^Zfa6qMwzd{yCn>4s(8RvoJL} zCQ0dpQdTWb3`ZQn%0U$EtWqg zHy^q0^n_C-!sW?xv6uzQn+~kk3$HN|Qw&IZVIZ)1LL~QJuErTsI&aq;k(q2JSGh)BUkQ(QCN6a4aQRUQ zQM4YYsLkVK+SC2jIVwh;-tQ;&zWN-x*k$68Da*gauqlZdWs63NiZInFPo1z*xxR3z zjHE|UUxDqbITqH2$0pA`?Qp~?ZSAMxaHbPSLpeQm^miSzHqvTzQ*Cb+QFdpZGUvR* zO{X;7w?k!IVV>)|O^Zk|!N-RltYS>NzEqSUKufft3k=UtpC%jH| z?!-{eEm~Z5Q8T4D4YK^0=K@tsG@Q-Vs1R0la^Z=G)7Q*N+H~2ed&SY2mb@iVC)QkD z>cHEvRcP0F&1(r+6{YKZuj+}v6zg7n+hOX_eW$P2bYI^LWS(!8vlp=yTUGa9>#qlI z3Rgee7*N`MA?x&|hiO-n7yeS)e0ACO!)5KqoxYm6uHNQZ&uiS@D$~0ztatmrsC9DO zmQhRBMs2@q`qudC`B`t*&ieoB2Kzg?-+N|1>FulK_}<@_9VII-YH-)uV$amSl6kT} z{;EEI{}PeNKxs|y4>LH$-Z{Ir*?@=P!FETt3S}cF_Y*5*8@*g#@-zOv=JoZv=bf4Z z(+;qlECXd}Ft{(qyOZ~~;`X4pB6}IdKh`l)0Vj;V*2!HF&4^w9)@FsTH}k8ClzlFN z-At~@hi@+^_{ikD`SSZ^y*jBWx^*|+f6-LV{&=|lEfcG5-3wRllAYX9e=cl0;eSW? zk3fIKA#baNXVq&o)MQMB_*Qos?YGVY+6v5AH#c%JIB>8W{I~nx8&eAbmd%nI8oaN+ z?@8 B?Ii#J literal 1054 zcmeAS@N?(olHy`uVBq!ia0y~yU{qjWU~*t#W?*2rzj0X!kTMAH32_C|{QUg#^78if z_Wu6<@$vEb`T6zr_5J<*^XJcBzkdDx{rk_KKY#!J{rB(R|NsBr&(&la0|WC)PZ!6K zid%1Q?eCLzm0?II?&FV@F)1)2BrLjjFlNd z^B=HAycC)EBE{_6xigj5?j7NdI;#Dp)>rNE&(ELFoZoHir6vq?5?SEh^qZT{z1n>I zf6<)$UDjvf_H0hO{aQ!7uHtUiJn5LfwliDq@9VAKshv~vuQ*g>S>>!>->+HpUz#s} zwO@VVy^6RiXJ*e@^+xp5p_r>rh0b0|N&jkf?yH0Sv12-F*5m`+{R z51TATp5A)>-J^_zdLemk5<_x&KJwJZWq^Fkh?yh zT=$|9t4MPWTbH)+-oDoA%mt;1SJ(LNcYVtuAPta#w@hxuE{e>WqTI8;@ADSU*@ry;mCkuGhodxH=xne< zq5GjYuA?CH7T$|rG-re50f`HfZI16Mn8j>$wyf|ZaSxZlDvy}VvrT3ZPjBKa9xtr&^e7>Un)_sNbx35ZD zPwr*odGR2nwn?t&G+&v!Sbf{)!vs#d2Yz4sw|qx$4fK;R1er{r&e>|9SH1lePZFjZ$}~_3EuW{$sQJ{pP}w^?euj#<-XN uk+{#8TjGA>qU@*RCA<&^fL-yA{~m*2!|L^K%?gf#1Uy~+T-G@yGywn=1muPQ diff --git a/src/font/sprite/testdata/U+E000...U+E0FF-18x36+4.png b/src/font/sprite/testdata/U+E000...U+E0FF-18x36+4.png index 2b274d6a11125a33e26639601778979d23112894..32a42097d21a3d0a3d27d68360edb8f3a126a9a1 100644 GIT binary patch literal 2217 zcmeAS@N?(olHy`uVBq!ia0y~yU|hh!z?{GV6kzbzdMv@fz)|4o;uumf=gk2_MxfxK z1z-JhIsG+23Xs4KNg(I{|2Kyld4P-q3iYqGWfp8>K~e!^KH!F^G2{hu8W#LpTg%HR z&4jAP0B8xw97ayCn*ZyiCpDodnFBNyMagYJ4K(*0hy>~esexOy_92E;ryuH8N0d!QF$!>oHI_<~Y?xmh{ zDx#O(>;FDc&G*wA%d$i4NDhWFEzbVX_mX-3dXCV#IptjJt>&Bh^a^JPY=3xJ>abY6 z-30aJS8wO2dA|E7wcp#@{+fh&97#@63;U~5iWP({)cY$Cog>E^EE>9 z%jW&d$vXG0OZI1O{W<;=*L{%4iT*#)Sdn8d-@2A51*#FJrfpDN+A<}9Gy2ffN9NPx zwLcgfaN94b{-?A!qv87jiK(xb?_Jnpq}K63LPH_IiS7QWz&5cdH;am%UOg7`(=Yqj ztkq?c83TReF58{w2=x|<6V&LL$TUec<-=N;lnln1z00oUG0OR+yE^~SbSPf-o7*^S zm&Rv=hMpqd80JvR(PJAq0pDG zrlI1LWX)~%-I7rg6myxJrGoz*HsPM{YWjlVG`GZb72$VUG6!yHhdZT6^uLQXy>;>e z6L02W%PZ1bN|(**J+CD7V!gbfmZY%Cht+$Fo;o*ue6jE9;aDEs8x!2r+jkwfyj}R> zoFghWez!QM2M8Uw>vAC6@~KZd&!fyAZjZ_hT*Bu+3&?!#AC{qYeO9PyMra{tqT5^M zCY7qG!RK;36y~+%i!c~Fzq#!w-|==zkluw$QQ3N0j^a}vN@VbRo;l~NQnB0rUCId~ zph6x-W#>P)qa~N!zWB&%tDE(_{h0>rfmc?ze#>vT`);ze_@tiY52f1=9GS3bcUJC6 z)@!F4Q`TO5{^##qD@o320YNp)7xsE=Nz+OZ^gnFg*x0Ce&|lEGMS}C!CgCgFgtZp- z)HGS~92axaWPo(WXFm>E=A4UG2<`vYLwTL%$qkGKyb&{zryN zkkh;4GK=MwpZW1d3&?&Ruy|g%?~ek*Ag6!qt&8P6{C<2f2eQ?7E}kcG{(FU8kW-`k z+r@G(&tI<-(p=~eePV@~_|``4nLjHp9w_C1B3ALAO^>g1{jpVny-8KvPk!3!PUt@` zf0apd!@Dc9ELL6Jq&V4Bu-Nj}o!{pyV|vb>+Pw9l@yly+|L5QOYyW9tzs!_+XdwkJ zGBL_Sc1WhYyAfEQa2(k1e}7r2;G204?^mFdKpFRpZ$6!MQV3Le0Sm^v7de|91X>;j z=^O8t+hzV7U-TQxni z!s?7STGaolyiSd|up0_XQOw9&kk>qESw=bMx zJlpNhk~ufao~pB-J?3g{nX&EPEltnOmG^u-XFXQW%eo@-z^M4-FL!r^`OpxBS5z2P z!v|pF0HyN4s2Db&t9bi>7qvqC0IsCoVrwll=s&%`%vE-$Y!@hoJYD@<);T3K0RZK~ BV?h7_ literal 1506 zcmc&!`#Tc~7~ZJVq;(M`J3A{~h?YXE*_@%=#xhOlSS6*fsVEU!mmPGOgPKya8OZgSTB}Ics)dVJs<9z70`45k^AC-~Kfl`DS;);#^;& zr5}%3pC^&XeC}KSY>^r}k5J>EznqrN=sRGfi`YN|u?{VBhuhmJO4F{d4th}t~Y2(h-@ zcj~1rtQp44D zx{=#L++fqFiSI4XA;KoUsp+v z8%tlS8@RX`-&ZuYf7R6f7KViB@CL@dyec9Km*nuR!&9}s8KW@iyvymNC~l)p=%?3H z)3f*{z=)mikSn~d@^{egE|=_DDtXvjn05%+0WHuTFN{6@ifF^#o4~MPBX1%+bDWm< z9ufa(^NT2RkHYS!S9scw(jE#%t_?efZ}Dvsx-w<82apGU>F`u89Z?}5mFWN>7OP4k z+@d!^;yNZ4oSBp1KhW3kbhfruGnJD&*CGa{nWz}<*I)H%!cA3T+S%Wmrh8NSP^t4U za(=YTNY!&c?#7fuku_x6^9xn<&1aW_91Nx~N0(JnT2`u|;CG zs!9MZb7~8y$rRT%hBckAWn|5p#^{u_eh7H?QvB&lm}`wKBSK{g1q)8d&i4z&8tPNs z#xa5;^C2}}R#kHE4`YbY^8WYdC-cO+d;(o320?zwyKT#iR3Y$bX~Tkt)dPMNaG_;e zvwf&ie_G0+q^g%+-gnr44l8o06okw+x$XcB<`b@5>j5$)7wJbJxH|G8F&ZVOro}4N z?;dN;^D>4q&9x*`+6%=Sw5BQwNjAOImTgM;XPv>U!jYgV;KvL3m8dSNzrYJ+5Ns#* zH6bTjvIU}w1KTdxk^O>M^n>ilj;^^`4ULn!T#7Wk=RrhNA}S@?n%SeQoAMvqH3LGG zJ0|~O7JwyZT)OO9lj4`p>bcrDWmUDSc;}k$Qhz@NOuz$uSi&6*Ah%`N+0osh0CVcr E-!0CfSO5S3 diff --git a/src/font/sprite/testdata/U+E000...U+E0FF-9x17+1.png b/src/font/sprite/testdata/U+E000...U+E0FF-9x17+1.png index 77153113f2452df31aaf4a62147a35ff03d5a004..461516971815032ad0c1d76dfbf36c8ce8a31125 100644 GIT binary patch literal 894 zcmeAS@N?(olHy`uVBq!ia0vp^7Z?~ACvX5648I<1EMQ<@cJ*{|45^s&=71q1Q1H-# zul~85{u&?!NWelG$oc>O&0#}cAfsWyzqMx{@JllxsQ@xJutL-@azfOsf7j83rUYm^ z$e8K;XV+K>9DTh&XhH*v${H3Gg@r;B0ywo9Ii~{oXHGl)pA+?8Ex1;Y3hpm3Qs0#mNXsnJMqoB=ZMhMdtKiyo?AA5 z!)-I)PoDV#D?cA=YcjhLebPIn(ELi=0+kaHJ;tv-+FwRP3RWusTobzt|cm$`5T|Pw852)Wuf`cRT?iQZl0&1F;`&eGtDQW*L`N3 zUcP9BqW;8t4gosNbHpX9qlB(CY@fhbmbHCg75?^!DYf7cb zgczxnk(W0)^_TBnwo3Q>g~y)*ir-1uJ)LL2F>78A?|tXzldJywt*k8Hx?6LK>aNWY_~cnkv2*@6Tait5pK^mg^G?0|qTBRo@#n8UFP|vS z2SxeM-9P!k3Fp>9&O;6&EEh_WR!*A~l;c~_+3`Ey^6Uq>icgaiQ$8P-w+AK3JgM?L z`Tf@06|RTA_ulPZvY`0KYaYHWTV?z5&DD)B)XSz;9%GZ5{&IENWXTLIJ(<;M!jc*G zoAlT3aVUNDF5s#0mGVYk$+riaSvp@r>mdKI;Vst0IvathX4Qo delta 759 zcmeyz*2gwMxt{5&r;B4q#jUru5+}}fkYIaY;ozj=;-oT%MMZ&;b7Dh_M+cClD75Xm zOe4R?EbhGvnQQ0C&&?Ar`<^Nup?3Ez1DW7Q^>2BLNA=Qnefs>Cbv3)wu0)Ccn`ip7 zS?rNu<>cCbGhYSYKe6D$)u$`{COg?YyI~`fsbjL=du8d&D>3gvFJB9idH>MLH)QFA z=T$eh%Ff;VZposT-1Ebq-YNSMn$dMzbN9godi{DaHcI>7I4yX*{HFPMq(-I;sa zNzz*D{Kok;1$Q?E&a+w5qO-2$;MaZEOM*>ub2rs&+EulqX4St1Wf!jhsQ;49eO=ArLEzT9Uu&VMKCU(2tr{dXl?50YB`FK*wz^X`%R zcM8HJGJY+-TX(f_6?^E_E@t0<+Yjg8EZy69s=f4S7PG0p*6gipr{;$|)8;LyjH-@| zU*Nkh!rat(_MY}_->2NZQ=L(5-Fo)z({0;t-#hnR0Ff3qFzsi!YHT83Q=Rx1B8Rt0{H+5Y!C!;P}JNO)If9d0au8cnTCF! z9Rym78C1M17)-_39bQgYu|i|wQAPn?-l^77R(uVrUVIHMsh!LTfyE3jf(jZORkqEk z+-?0@u`nt6^OE@e^UBhV=10C=XZ!7ZiqT9TwaF`k1xrmM`|i%@y`uQ~dHc<|vaW9w z8u#y;arb`s5k8?GpC{jJW(En}zdzH~DhMR>w)f`aWROsN+zeaW&?D2P=;@g9=p5uW9G=bJNx(E!;?qP{=NMAc)9K4hmC(PT@`hD`qU=g zE!D1dqi59rckxH3d~#gA%4(|qHpvKu0vA-gD0Q+gPx&NLWO+G z_M?JKho$Xn_$3q#YA!eG+Z|>w1BLC$6r)`C+gai{Z$I4-R$=a&^0)pg%gF}i)c^6e zj+1ht1VnweKU_28Y?m?nlBFM{*I(Wyq7x$Nd(_Ra*upH{B)Vw-Rj&PytaH5&G8LGJ zN*_IQ@Wz&RQ$aT)xn}4L(V?YGMiyJrOWootN)=AN&fAEPB}a`+$B7gGKZ}T zT3f)oJ$9P#d8uU&Qs#NZT@rq4w?z0|P_FsB&h+U@iJyvA{aCitDzoHJ@rth(A6d40 z%s3Ntw14S4Jww~Q6+OHadsA1Y9FX4hTE|(3XhmW0c;NR4t(-Jb}10%x$ljElS5@jvXO^NOj2j+d$4LLp|T(FVp>l7**FmJa+|dfs?V$PUOhf}w-uI{S!ZhU-VG1LC~`KI&j*T1m#UwQY> z+_YS;&jpgV7yk|y{r!!dPkH%T=J|g1`)mJw_;z)(`}g-IzL!nP-`Q7vd-b;c{QbH- zyN~Z;%a)1jC#^`G9(36x_tmt|Gb%P(=FblD>i)5}ef2G#(iQK&In3VmwB~lq(TT^| z>OQOOK6QP)w$jx7eG?2~p1eB|d1yj?>4!ba%St>XK22B8eJVBY?1#$#E&RqcKlX$+ z9+u%V-m^z1lr8VK`@QI;ecLlyL$%fsxgt zMJ?W#9I{JkYCIfg^u|P8!oo(kCB2iAjqiN(!^}dUuyB2ayurZ(59j(-JT5k7VrD3i zTCOENC+D-qh67C8HBX);O}&&Aom;VK*NzC=pV#+%lzks}bJGQx6-j)d4(Ze1?EVv+ z6DgN>tt7_vWU@^8;`@gHxNeYvR{m0lkGtACr=@!Qi<-2Hb{+T1(# mIpuc&(1M5u(xMU%wEnWq+hAjFpXb#9$~~U0elF{r5}E+|eY$l3 diff --git a/src/font/sprite/testdata/U+F500...U+F5FF-12x24+3.png b/src/font/sprite/testdata/U+F500...U+F5FF-12x24+3.png index dbbe76ca0422f38f0aa263881f9df05e90aec1a9..b1bb803ab3b599643d03c040ffa9a06a1d5efbc3 100644 GIT binary patch literal 1421 zcmeAS@N?(olHy`uVBq!ia0y~yU{qjWU~=GK00NFLPi8YPu!eZLIEGZrd2_&!5h!?Q z!B_uWPJa!M0wnN563F@g|IJ}TULd1k!N0X3ztI?wmD1yHU*XeaMbO z%?#awLkWT z(vL!1PS4w*^5|~w52>YTy5|zQQ!Skd0^3&J~9@A78Qdw2k*<3oiTP zvlMzBshs_^>0OUq^5bovTYdnNns%YVPx zR{LvCjj_+X@US4^_Kmk?HR+qXL}SmkIPzs*nKjdBX8eBh4(;;hb)VynHGG4&@vhu4 zhi`hY+WGFJ0DEzJeSe;y*MXO;*E~A$S?T-~@A^W=w`yy&bK8DRdE>S2>kXbsvhHQ7 z)1^32?$<-nKKCL&#br;qdE}{2aY*xx6qTZt!TljJuQp1mESIyClvEEt zxPQ))r+0MHUk6I7+~4!$_RST%lit7k^tbK`+sXCzpSUjq`S2OHi$;8S0B=gIFS|6T~sc{+V^?gPpCPrO@d zy#HQfJDD%>$@+M=1Ta;DK<=d|w#7TyFJ4>Ln8vQ__XIR_r<1Rl8ez{rg$3W%^aMj(@4=@!a{x?9!SY%dKjj>^!J`M|G+( zo9!wV#U*)hQ_{aSt$+WiPSZ4FeSDvmcv-;9te~E4kLJW$A3E1HdA(Pd+@;NIt&je$ z5Xe1mwflF=Tw87P6Q`W3$_-VgE?4E0zxPvZOK|_(sF2HT&rY5=<6L##vA)vd|8(`2 z-%U?&vPmXPV1y9@kRWSdsMD^%6Z$a?(rq{`?=kj zZ}v&$N$uZx*!Qu8YPsL-s--hm)vvg%=3wB_;K;-ylmN066wMb7akH`K1utSYs0Vq# M)78&qol`;+08TPi6aWAK literal 1182 zcmeAS@N?(olHy`uVBq!ia0y~yU{qjWU~=GK00NFLPi8YPu%vprIEGZ*dV5PT;hjB4Qspw7y)Jp;>aVqGa{Q7gao5vHhJ+*ORj<(l)pA&HD1rt50B8-=6hJ_Aj4) zny5Pci#!j=z<~x0yEf@;|F&{Y;lJFao1JUx>iD#(tE-t-+1T2$PW}70mNE3%=gI&} zD=VRZryoBWu8@(J=U(yY!v}#7KR-W~keO%G9G`yq65=rR_wU~eipt8aCCyo+)1KX$ z7bk>%N zT_~~Q)e;vM*F7e=SElyscKLlW*EQxP*3N!1C-|`mi^%)cYi@qo_~~U~S+(&_8++Tj z=xcA}=g*7x%game-@5et*|WYIexE*l`pC!oXXD%Dr+?lZ`0M|TEW6W-wYrbYH<(v! z`e|9=tNn5BYS$Whzgc~{Vcq)m&4+jF+QrrX#$C{7*AK&tjlMQOc*VXP4h_rsdFvcM{uG)YY$x=Iz8=wDJWcz0{jOW@bQVGS~lR%6H)uQU#%AWxM^Fr?|rGm$J_IN@CL4D z?z%63?7aj?0h?8w_ubbGkKP+RdT+VU(*c;0-YkoKeelLk_CQ8X4+kcp2@U(U6j{Vh z>3;bzYN5^y_21k3`QN@p6UA58>$9ys_2GTzmLCBQ z`n8$tM|WFie_grb)5He5XvrgY+w<*1r>;BKy63Z=P5dpkEiY>-^Pfyh54gSBGrYT* z_xj4VpE)}oJ^A8!-TmB7wypc+OSe`@)&F_7`Q^N+moww#Ex+qcdvR)Z`kHtvE{&aG zS#$i0t_G*c9KCg7=j#QzdYAs6o?24R{Ogh@Hzbf)zWm=8$il$z!1|+tmI65FPEGy% z_EFjP%9m;{7F{}9Q?zgXyU%8pvV67o)KygiqhUKzMbJ)y7G4 z6AxNg%EsQ!|Ge|Dm;8-a<`>PHGiI-sUcNfl&Qv}<;IiZssVfD%MdI170=MvGy$Zau zH}sQP`0cY(WoypediMF&IomH>PzOD^s>@LOot=$6FIYPK@C;BH;pyt`Uk B4nP0^ diff --git a/src/font/sprite/testdata/U+F500...U+F5FF-18x36+4.png b/src/font/sprite/testdata/U+F500...U+F5FF-18x36+4.png index c0635036f4b07c318c0cdb442d41968ebd8774db..e7415b7aef7801266881cf7c865815fcc67c41c3 100644 GIT binary patch literal 2473 zcmai$4LsA^AICQj^E5M0e=eG53T4PY7G_dRA=V9dL`ME4nv6WoJSKl(%Jb4l6ph!t z?jm_w*I)EVPtshrOHCn56dAi4Uft~W|NqbH_xiog_ni0ne!rh{&g-0W?x2T@ysU;S z0059jyE=OV06;1LARZ(wXaIPcjH?3xGI+Ez>QEeIy4wOMXuLyR@Qjf0+$sdVDXl*U z3_gGQw^Xp8(yfy+WvWHJDe(;&DQe{B2_#-eCT_^6mrc$e=F7Sr?qa=HP9#ApI++(t6l<8~@K@4|Cj`ligR%QSNsP zFfakTxpaTb&Te052}}q!3Vi92Fx!z(=mM(#O^DZ04E5L1 z*E<*@b6#;L^y8w20bZFJKJX#VZjSu$So7e0jMCsaIZF1miMvn@{eS7a`C#qJGIAWE zwl#)36msGlON_KP0Xs@=HjUe>b4 zk7U%-$GB0w)%bRB+Q_6_FF%ji^(lb)?D>9j9h%3RAI(}_n%6Quex&_S%+uJeBgmG< zhWh%rS9`rwk|tt-S8sPJ>$bIdw+~mF4}JV3uCc3{;R50poL#C&wRQ!x{yt1yA$Em5 zU;3Fj6Pq;A1kO`tp#Kr-YD0v zgc3ct&8pswk>k93dJHEc^`0or?I8|^kt)*>%3xkC<5XRN8c~{CG}<#>t6;W^cPj1+ zlxW`uV&BrJ9LqdVwg(;z#d;{Vko)Heb;EJ=bRSpUe?Nlufj;c_?Q=hp=W(VgXIZlK zF7(Mwnbea|q;~4aMAjn$*1mN->o!66{9_?XmpXj`Tm3Ym_>W5K_tE$7yp59Uk8a8a z1SoQSw0T$iz)Dr7VylrkUG#F49$|0yZUt_nq?Kz%qjcOXWONn>Iyazt^k-kQMc1*< z9p>Uzt^pG5DJrwJ*6GfZIixc|;{nWL1=0dR?bhBM6>^<*gq$l);FPaBxPm*FLT^tm+CuCBItH&TZepL28s)rd`F(ALmlFxyT75 z96`=BZRmd8Wq>aH`tk4bJ$uMSfW=+9zbFCtM$U)DSYsJ|ZU9~d)K7+#qO4~M|Ta1;DxqS=CPa6H)~Ec_Tm0 z>NU;$W!q4I&Jzh?2hnl8!#50>84GE*6oblUU`}VsB6aBEZJ-3@8<-P&-d?mEi;TYB zyDj`O)pt9k&=j)>e7j}9dVskUQ~S!o`rcSgm*#&cSAr0wg{B893$}MmkanO(C8o?) zNW~rApE4^>Plb=d$a9dAX`He3SZyqqXO58~=xQ%IEV~>YB)-0rMf6N3;2Rq4 z1GgeeVhdLbeFEmt|3Op2H9+rEQncj4^W|^Uect8p{*Yl+T#+-WC%v(RXMi?>@ zx=_hMUUQ{%XYTn$x$9Dib5F3zn9|E#rD4g8w&j!;KGjE26@dnofyHkWjf}%CU7{sg z5+m^_uGDTd!fc2H-07L8>@{(9-FL>4&w#nmg$rWu0Q<7Ppn)*}edm=L5`v^yP4sr$ z(k< zK-Zl;4dNBB2g+0HZ-v0-Ep=MK(mTY{?vq#vzK%udw38fqjg0YJyot+iF=-xE{wNNN z!%R@RM8TLWlKU-+a?HxKFeYUe`YmwoxG}`-^4=CJofK@?kr^BKO2P2&3?AaHYGI3o z8jX22Gd$vxhtXZ?DUV*45yYE%7p)~ZZ_uhTrk264>DT$E72y#!#gCbaz)hJ4?Frzt zFO6_$u+SnsO52(J;_q_(eR_f4Y0s_S*bFH*vLW9F|X%Esl1$sNg^WDje; Q6kcKIy&leuPC;pZ0-VU{GXMYp literal 1785 zcmeH|`#TeQ9LKk?3LTD1B)2>q#YD77GM$s-(qlXdMViXoFEMw+4vn1YC>rI`=tAUD zhRr4SOH*^3B*V1LTw-&{YHpov^_=JYa{hz!{r>WPUZ2nB`+Yv&_vd-O=}s`4eUd7Y z003a0o$Xm?003A70El_*5deUr9#a_r0JYhjJ#!&ud};Df#z7kekQbrmgPa=$ zyik{XUaMIFu6TPDaTRg*r+aEI`#N$kE;e$mM>H$6CH0Y|x;nm_?8;E~C?UUzd!0;; z^Z5d;eox@7T>}a)`G5V_3$)FhAYay~^eLz&3@_f<$!F=)wRh!N6gk?ptZM!|$O3L> z3(zk@BqKmZB2*|qIzmJgpu-}BW9dUhg{A^zCPeE3ab2s3EEXq7ca#G7{BUCQ`40aoSVqU-2tC{62zrb68G0wHP~aJvTlt$-JxA>qbEb zI+Z;NE~00nW^x7bqXVb&BZ-98H=I>&qsACDkfv%55@RYzDD(#-DIe2lsEuU~<1N~_nFMJk*Urp*04Z*{z|6$4#1mHkvkg{n#|_8_lDV9wRqj%9MfIC?F4Aech|xV zWGpdJyxBKN;N4=9ne80u5F;4->QP@cY1y}xVOFg={LZyNISr0wwCqOlt;V^wNNhQJ zW7=*AC;oZnkL2Q}?h#;R*7VGYiV@YtJSV0y+ zcJ)z~rqe4}3h%#a9ZGzf4lfM2vfK+#cn!Doo{d^|E@EjFhgq%ExuX)?kYv+kUcLD7{X)ex>Y~TX3RNhuo31K4 zjyu#%ecq}&yAw9X%667$rS9lU`;AatcsFC8$X`NrfX(<2^X}W* zHB$kejA@MZ(2i=e!ZW@y zcx0}FRzaaQfr$@&>XesmFOaY%mAe*t+>;yHlVKDYi*@W!PF#=YRFL9ec&+u@&U23- z(7RCypmpq1WQ)#BR0>+fRWEdGuOFM(Eb)(HXpwnyEfV72ZEZ{V$g4xk-VyR2zQQA| zAn>5V=$V=!`xN`^?J|A<$-dLx8YzME*E0=vd^B9;{BFAU#8Q2k|6N3W6zu}!0l}du zxQggM;Xh5HmK+P&hM1~g+LV=j*3A?nJ`8g{noSFhy10n>Z#yZ`_I diff --git a/src/font/sprite/testdata/U+F500...U+F5FF-9x17+1.png b/src/font/sprite/testdata/U+F500...U+F5FF-9x17+1.png index 6b8bc0440f05c1c08406f50ceac4623a11108323..730a4c42c2bf293d6cdc02ba42eac97f8dd0b63c 100644 GIT binary patch literal 872 zcmeAS@N?(olHy`uVBq!ia0vp^7Z?~ACvX5648I<1EMQ<@*7tOA45^s&=71q1Q1H-# zul~85{u&?!NWelG$oc>O&0#}cAfsWyzqMx{@JllxsQ@xJutL-@azfOsf7j83rUYm^ z*chmi|LcDXa)Dfj1U`rZIY6ss80Nil5NNAqj%Tp-`>@6I((Z$+7oOk^iY$4larvR% z+SMjkb~>uuntCZ{K?n1Mt}^AGgTJNwjaB&8Jp8{zgJ-w#>-(qAz2p1Oq1Yne1SU>= zFIZbPxwh_NhD7MI!{$kI{Vz1#t9{&mPCdghf8WRO=fYbSgx~+M{4;0Nh3@=6*MCL? z*O`g2neJ2k)gfgdwMgX48|iYZ`8t~R>XJOOezd(%<~o$o5p-d4{+-t~XN)xOZTFn^ zZ;s2m3qiF^9|Tz(O}0N@F+cij`sI%W7f!FemtZmP+_TlSuNTYzW}I)mxl$nAxZ+it z*!Fx&qeT~!ia%)XZrB*vqa^v1r;#l{{d{v#zzn@$`*MTWvyU}c53c8_tN-K`$j8O4 zH90K&(kH1V8wN?IbE&5s6`w|G{+~H*vrJ0XiHEoTIzBJnR?G1%=tiow7Kfj80pF_? z3Kso`Jhv`xdT@-Pyz>H!ATT%*i`GdUzq#%F>Ffmy()89p>|#B-veZo1@5IL=R@Q-H zH@rX0;ue3)8^V0ld$Wwgo+fU)jc2t(&F)FgyeT%tFSMnVL!(t^ft1EH( z?79_wZ`QJj-~GL}hOiu6B?#1cXtIohMsla!Yo`lV=D&WH|NVOIw!X=tz%wbn-FI@M z8P=FfG0%C!%(lFVpulNVLocAxy{)$X5+QfVIhE&RkoA_G2I?8upOWi8KzJ#AB7 zdULCoxgP6U)p^$Q?kR@&l$~Yen;5<=*?y}vd$@? F2>>4>aa#ZY literal 752 zcmeAS@N?(olHy`uVBq!ia0vp^7Z?~ACvX5648I<1EMQ<@+V1J%7*cWT?M*|!I}RcY z7xp&l3moK}kgbyEz{_gBVAG3BftNPM-dcMp;5pmG4Be$m9R%4GMAr&WOZ~W^CjDB@ zgM{(f(e{M&dY$YjdEfoWN0RS|cd%d_oW_a)p~!)?Na^JN>1n_B9&H18Eu z`Lb75rbl66{@Vuz>-}T*)#$x`vLv;H)pNcyL2Z{){Bmdcf6$Tp&_}pa$8YMad~ZNW!aYhnR2za z?5%e1*|o1aZ*NBbU(3DkB5mcDtW1BZvVLi0UL>d5adZCDcKYoq2M?e9`1}0~Pd@R= z&l7gXZdty%ruyBam#^&n)0~z+ydS?Os7QEK)5S}vn;)8%2)z^d7&mQpfMn0Kyd3F! zPx%hp?s;i=OYBZN-=W=a9E5Li&u?a%b;0k)5~~X>T_0kTZVNFryuFeWuAs>2`9jvw zaP91>T@_Ax=l-)iKf3GZlJz@Jc7JmY;^m2-^_cNc_=g4lf#*6o$AORO^go|rd3eCeVk5v6m0(uaa=90HDU{l23w zv}->5?$7t%-n0LjCoXk4!Eo|ft9Dy4hWmV0>=C>Dg_gv}Jqy2|{@!Dmw%z&Ho}JzY zPxHwdPuXwrE2k~=SXD%%S>eVyONZ}Lr|#_gr4o|%CPG^}`p^3*PZ{cOJ~gXWzuolv z0)z0a6RI8_PV#>WxEPwvcHLgyqH^W$Dw7M-KBSh-(3O4Kmbk4%q^0fVrNB+nX{Udr zWt3!RlcQbP0l+XkKrqf9L diff --git a/src/font/sprite/testdata/U+F600...U+F6FF-11x21+2.png b/src/font/sprite/testdata/U+F600...U+F6FF-11x21+2.png index 6b580bf3e4e6935d394ca81e724c5b0e7c35b854..b216174e42ec037c12671a7cc87a0452fff178fd 100644 GIT binary patch literal 495 zcmeAS@N?(olHy`uVBq!ia0vp^9~c-IKX3pU40}EI{sMBgdAc};RLpsE?c&;I1D@80 zIR`R&9tcWw21+O{PGO0^Yvy}dT;Na}%fI(;PaI0%>~Lmi__rcX`0u<^8%>#K+ln#I zF0H$DVABe{phrLCk87{elq`)ie|@@U{tiEr$ugHsc!ISy?tj(xW2eP4jrVdJZ@*&u z%XRg5d{XS1Rm)>{?>}{5|E(Hb+4z@c^)`L>Ys1b>y4<()E_cJtst4Pr?Z_(rSaRe* z+Q$>MvW6QXZHnUE`=up7j)#K+^?D%t|Nl3K4S9i#h6VrDu6@WT%>-8fX2h_fsmXoF zilGLm2gMxShn(nYe4uI?d4R?qP^f>cEwf-73#wf^(9Nms!ElcbPz%T|Mou83VZs0P m(vzCdoGi@+ZSy?>)MS+xDfKP}kkml#-_xJaYkB`sK z&!0bk{{H>@&!0d4{{8#^|Nm$C+W!Wsc0X`m zGFNZ%`o~rO4?gU2>?xeM{+{y@aD;c2f ZC12l@AfcKIH;X~KJzf1=);T3K0RX&3cr^e3 diff --git a/src/font/sprite/testdata/U+F600...U+F6FF-12x24+3.png b/src/font/sprite/testdata/U+F600...U+F6FF-12x24+3.png index 8dcaa24b121f2c94351ad6fc08661ffc944adb24..2243248b07668a08bcd7ba0e5d146238fb1b7b57 100644 GIT binary patch literal 637 zcmeAS@N?(olHy`uVBq!ia0y~yU{qjWU~=GK00NFLPi6x-E}kxqAr*7pTz{C`X28?( zFy|0Q&jBFHkknjU!4fVia3$#Kw2WTI_n$v!3B3$y+z&LR!Yb5vYK6-^SI5BVfdK)J z939!Xj9BiOhJ>zlUgQ$8Pu2JK{yR?%JL@K`R6jjUXZ`$-64#c8q~@1hx%=ajGup0yQae4yh2K{4`=RSkW=yy=IoIvq4;kCJi}%kd&OP?@c=NA#KjWt+#qTYr zr^Wo>H%h72UsBDU`g_xo-(5>@`)+#cc<-!f-tOKz+nQ}Zevi`NG76Z`*u*1}vOs~E zl@a7eFgWnm4oLt1|K_kEFObo&;NRNZhpf^}5Lp;HP`Nlj>06{9QpEyx9mBP6hg70r~}f*Kk~@<8SXF(85B;U@ u-iOTSYSyEhgT?0%HE$6i_}2$v*8wK^3eQJxYnl5&F7$Nub6Mw<&;$VR{LU)? literal 376 zcmeAS@N?(olHy`uVBq!ia0y~yU{qjWU~*t#W?*2rzj0X!kdh1V32_C|^78Wf`ug_v z_Wu6<@$vEV=g&WX{`~v*@Bjb*KPl++C!khQPZ!6Kid%25ZOl3pAj0-w%ao*hhpw(o zmS3D4zWmj_qZco(E!kk1pS^BIL%~MHtF4`I6|RXXhMxUucwM%&}%550~R@7iYHc7FNU zeFdt?(`G%=ZmrzvvCyye*^ftCr=}(N-~Ds{Hl2Lyyi>O9$~^15_jeL#66#|@$#9UR^q7&_w=vq^P9Op zRbj^c3t5sJcORX|FFYf^YBf+`|Fm_}4kr9d+#bbt=s)9$TAsH5%13@n@ceK8@ZC`1 z2BY}wzasr4QZ7XQWouqm*X$U)|KNg^_Y*E$$u|H8Jt+7=VBHTO0W{z+BPWp2u;Bmt z--2AA*g^tpSkaW+7Szx{k_R$Bhye+ZF^0TAM#F-CYu7$xlx9Lzq|b<^CifvLx|-GK z=IB1;B&g=>1AcTh-cWPk-jbfwgzB6FvFJ)LeO?T8G29ePpPzvS4jzvmh(`BR??YxZ z2OrQuSA*$sOf{GuKOll`&fd2S=ysvUCq~$85JnFhOplkN$0lZs7l@-f2GipO+-Qly z_aQr)doh&oKIBGIvH|L)MjoJz2NddGE5|I@#sXv`Kmw5a|NmP=3PqR_yq2NsxKZzF PHIQmgS3j3^P6 literal 511 zcmeAS@N?(olHy`uVBq!ia0y~yU|hh!z?{Is3>2A>zwkSdk_+$&aRt))`ug_v_Wu6< z_4W1h=g;52fB*UO=ik47|NsC0BOm^T1GUcaba4!+xb^nNMla?-0oDtFiV4#%UAlJe zRQ(5Tl~{$T@(GEVnd(VBpSO$UPw$w)zRvqb?Yzq^rwu&yIA_;(GBCK6&C_@1e7ujj zRV2tmu~lSN+QQ4BdHVf=?>;?rkob_(KKD-gv)@H&3m+*N8_!P@(~`eXoR(InlP;VMnr#2}Pg>B&T+MI%!SntscRE}9bk=SSlk%H+@7lNSjGq52&+oRi-4(vL z#d0T)+5YnV{r<7y`o$BRxHOkcaN-qZ0*1`s2mc-jr!4V*nZ;uacCV+apUXO@geCxM Cu9|xQ diff --git a/src/font/sprite/testdata/U+F600...U+F6FF-9x17+1.png b/src/font/sprite/testdata/U+F600...U+F6FF-9x17+1.png index a5ba3d89ea285a21ada1145f457c666f465abe62..82ce82468166189d95acac312068a368f06f667b 100644 GIT binary patch literal 393 zcmeAS@N?(olHy`uVBq!ia0vp^7Z?~ACvX5648I<1EC6x>JY5_^D(1YocDD1Vf(ToH z^@f&kCodn)X$hXwCJD)WI)3Jq>kglm@^fl6J2m2(W=&~e_&eX}4Oi3h%K<-tSeAhpRwI2;P=XR3#WYfJ!7ZQhS=t9$~ArE^K-wQ za@fDre)hWaaX**ofB9F(anJev{D_0g@3546y|Mjr<@bMqgCisWIdQtNFKf?L$UsCR9a#SkTn?K4eE%^9HB~ t#T?#;+~{g*7(r^@BHZ&^kP8&f-i#*7`<|RLwYm+m*VEO{Wt~$(69DY(jlci^ literal 278 zcmeAS@N?(olHy`uVBq!ia0vp^7Z?~AC$KOBS-ML<&j(U+0X`wFK$@SQUtV5bUthnz zzP`V|fByXW=g*&i|Ni~||Nnzer0xf**zD=z7*cWT?UjYAoE$}1FXUD%IQ!v1mdUI? ze7s3prC0@X!e;xPyD#NqZWAK$-Z^6RTZ7G#=gz3qG-ppr`4U!9$n5Id#Wwr4*2(uT z4f14nsfBJYWIO&d>AqFT+f`Y!=cjH03hITHo-3GjCaQhis#V!;{fygq|CcPfmv-g$ r+ShMoO@HM5k6ZlWG043{fDcz>XWhKwxcdC=7?5gDS3j3^P6 Date: Fri, 19 Sep 2025 09:34:09 -0500 Subject: [PATCH 13/77] gtk: add glib log writer function This will funnel GLib/GObject/GTK logging messages through Zig's logging system rather than just dumping them directly to stderr. --- src/apprt/gtk/class/application.zig | 68 +++++++++++++++++++++++++++++ 1 file changed, 68 insertions(+) diff --git a/src/apprt/gtk/class/application.zig b/src/apprt/gtk/class/application.zig index 5f87613cd..4202115e5 100644 --- a/src/apprt/gtk/class/application.zig +++ b/src/apprt/gtk/class/application.zig @@ -42,6 +42,70 @@ const GlobalShortcuts = @import("global_shortcuts.zig").GlobalShortcuts; const log = std.log.scoped(.gtk_ghostty_application); +/// Function used to funnel GLib/GObject/GTK log messages into Zig's logging +/// system rather than just getting dumped directly to stderr. +fn glibLogWriterFunction( + level: glib.LogLevelFlags, + fields: [*]const glib.LogField, + n_fields: usize, + _: ?*anyopaque, +) callconv(.c) glib.LogWriterOutput { + const glib_log = std.log.scoped(.glib); + + var message_: ?[]const u8 = null; + var domain_: ?[]const u8 = null; + for (0..n_fields) |i| { + const field = fields[i]; + const k = std.mem.span(field.f_key orelse continue); + const v: []const u8 = v: { + if (field.f_length >= 0) { + const v: [*]const u8 = @ptrCast(field.f_value orelse continue); + break :v v[0..@intCast(field.f_length)]; + } + const v: [*:0]const u8 = @ptrCast(field.f_value orelse continue); + break :v std.mem.span(v); + }; + if (std.mem.eql(u8, k, "MESSAGE")) { + message_ = v; + continue; + } + if (std.mem.eql(u8, k, "GLIB_DOMAIN")) { + domain_ = v; + continue; + } + } + + const message = message_ orelse return .unhandled; + const domain = domain_ orelse "«unknown»"; + + if (level.level_error) { + glib_log.err("ERROR: {s}: {s}", .{ domain, message }); + return .handled; + } + if (level.level_critical) { + glib_log.err("CRITICAL: {s}: {s}", .{ domain, message }); + return .handled; + } + if (level.level_warning) { + glib_log.warn("WARNING: {s}: {s}", .{ domain, message }); + return .handled; + } + if (level.level_message) { + glib_log.info("MESSAGE: {s}: {s}", .{ domain, message }); + return .handled; + } + if (level.level_info) { + glib_log.info("INFO: {s}: {s}", .{ domain, message }); + return .handled; + } + if (level.level_debug) { + glib_log.debug("DEBUG: {s}: {s}", .{ domain, message }); + return .handled; + } + glib_log.debug("UNKNOWN: {s}: {s}", .{ domain, message }); + return .handled; +} + /// The primary entrypoint for the Ghostty GTK application. /// /// This requires a `ghostty.App` and `ghostty.Config` and takes @@ -177,6 +241,10 @@ pub const Application = extern struct { ) Allocator.Error!*Self { const alloc = core_app.alloc; + // Capture GLib/GObject/GTK log messages and funnel them through Zig's + // logging system rather than just getting dumped directly to stderr. + _ = glib.logSetWriterFunc(glibLogWriterFunction, null, null); + // Log our GTK versions gtk_version.logVersion(); adw_version.logVersion(); From c42ed707588c2de57367c162ef378f651c5716fb Mon Sep 17 00:00:00 2001 From: Mitchell Hashimoto Date: Fri, 19 Sep 2025 09:45:07 -0700 Subject: [PATCH 14/77] renderer/opengl: minimum contrast for black sets proper color Fixes #8745 When rendering black for minimum contrast we were setting opacity to 0 making it invisible. --- src/renderer/shaders/glsl/common.glsl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/renderer/shaders/glsl/common.glsl b/src/renderer/shaders/glsl/common.glsl index a0ed9f7b4..1a7ea03a7 100644 --- a/src/renderer/shaders/glsl/common.glsl +++ b/src/renderer/shaders/glsl/common.glsl @@ -102,7 +102,7 @@ vec4 contrasted_color(float min_ratio, vec4 fg, vec4 bg) { if (white_ratio > black_ratio) { return vec4(1.0); } else { - return vec4(0.0); + return vec4(0.0, 0.0, 0.0, 1.0); } } From 6143aa8ce0f28842d7ec0b1a7f1493e54ef82fa5 Mon Sep 17 00:00:00 2001 From: Mitchell Hashimoto Date: Fri, 19 Sep 2025 09:51:55 -0700 Subject: [PATCH 15/77] macos: "new tab" service should set preferred parent to ensure tab Fixes #8783 Our new tab flow will never have a previously focused window because its triggered by a service so we need to use the "preferred parent" logic we have to open this in the last focused window. --- macos/Sources/Features/Services/ServiceProvider.swift | 5 ++++- .../Features/Terminal/TerminalController.swift | 11 ++++++++++- 2 files changed, 14 insertions(+), 2 deletions(-) diff --git a/macos/Sources/Features/Services/ServiceProvider.swift b/macos/Sources/Features/Services/ServiceProvider.swift index f60f94211..f165769a7 100644 --- a/macos/Sources/Features/Services/ServiceProvider.swift +++ b/macos/Sources/Features/Services/ServiceProvider.swift @@ -55,7 +55,10 @@ class ServiceProvider: NSObject { _ = TerminalController.newWindow(delegate.ghostty, withBaseConfig: config) case .tab: - _ = TerminalController.newTab(delegate.ghostty, withBaseConfig: config) + _ = TerminalController.newTab( + delegate.ghostty, + from: TerminalController.preferredParent?.window, + withBaseConfig: config) } } diff --git a/macos/Sources/Features/Terminal/TerminalController.swift b/macos/Sources/Features/Terminal/TerminalController.swift index 4bb642ea6..779c13d9c 100644 --- a/macos/Sources/Features/Terminal/TerminalController.swift +++ b/macos/Sources/Features/Terminal/TerminalController.swift @@ -184,8 +184,14 @@ class TerminalController: BaseTerminalController, TabGroupCloseCoordinator.Contr static var preferredParent: TerminalController? { all.first { $0.window?.isMainWindow ?? false - } ?? all.last + } ?? lastMain ?? all.last } + + // The last controller to be main. We use this when paired with "preferredParent" + // to find the preferred window to attach new tabs, perform actions, etc. We + // always prefer the main window but if there isn't any (because we're triggered + // by something like an App Intent) then we prefer the most previous main. + static private(set) weak var lastMain: TerminalController? = nil /// The "new window" action. static func newWindow( @@ -1036,6 +1042,9 @@ class TerminalController: BaseTerminalController, TabGroupCloseCoordinator.Contr if let window { LastWindowPosition.shared.save(window) } + + // Remember our last main + Self.lastMain = self } // Called when the window will be encoded. We handle the data encoding here in the From d27bc69f2e1b59703afa28b1576ca69d9ff173e6 Mon Sep 17 00:00:00 2001 From: Mitchell Hashimoto Date: Fri, 19 Sep 2025 11:44:37 -0700 Subject: [PATCH 16/77] macos: correct SurfaceView supported send/receive types for services Fixes #8785 This is the callback AppKit sends when it wants to know if our application can handle sending and receiving certain types of data. The prior implementaiton was incorrect and would erroneously claim support over combinations that we couldn't handle (at least, at the SurfaceView layer). This corrects the implementation. The services we expect still show up and the error in 8785 goes away. --- .../Sources/Ghostty/SurfaceView_AppKit.swift | 43 ++++++++++++++----- 1 file changed, 32 insertions(+), 11 deletions(-) diff --git a/macos/Sources/Ghostty/SurfaceView_AppKit.swift b/macos/Sources/Ghostty/SurfaceView_AppKit.swift index 03c113209..22784d164 100644 --- a/macos/Sources/Ghostty/SurfaceView_AppKit.swift +++ b/macos/Sources/Ghostty/SurfaceView_AppKit.swift @@ -1815,18 +1815,39 @@ extension Ghostty.SurfaceView: NSServicesMenuRequestor { forSendType sendType: NSPasteboard.PasteboardType?, returnType: NSPasteboard.PasteboardType? ) -> Any? { - // Types that we accept sent to us - let accepted: [NSPasteboard.PasteboardType] = [.string, .init("public.utf8-plain-text")] + // This function confused me a bit so I'm going to add my own commentary on + // how this works. macOS sends this callback with the given send/return types and + // we must return the responder capable of handling the COMBINATION of those send + // and return types (or super up if we can't handle it). + // + // The "COMBINATION" bit is key: we might get sent a string (we can handle that) + // but get requested an image (we can't handle that at the time of writing this), + // so we must bubble up. + + // Types we can receive + let receivable: [NSPasteboard.PasteboardType] = [.string, .init("public.utf8-plain-text")] + + // Types that we can send. Currently the same as receivable but I'm separating + // this out so we can modify this in the future. + let sendable: [NSPasteboard.PasteboardType] = receivable + + // The sendable types that require a selection (currently all) + let sendableRequiresSelection = sendable - // We can always receive the accepted types - if (returnType == nil || accepted.contains(returnType!)) { - return self - } - - // If we have a selection we can send the accepted types too - if ((self.surface != nil && ghostty_surface_has_selection(self.surface)) && - (sendType == nil || accepted.contains(sendType!)) - ) { + // If we expect no data to be sent/received we can obviously handle it (that's + // the nil check), otherwise it must conform to the types we support on both sides. + if (returnType == nil || receivable.contains(returnType!)) && + (sendType == nil || sendable.contains(sendType!)) { + // If we're expected to send back a type that requires selection, then + // verify that we have a selection. We do this within this block because + // validateRequestor is called a LOT and we want to prevent unnecessary + // performance hits because `ghostty_surface_has_selection` isn't free. + if let sendType, sendableRequiresSelection.contains(sendType) { + if surface == nil || !ghostty_surface_has_selection(surface) { + return super.validRequestor(forSendType: sendType, returnType: returnType) + } + } + return self } From f60bdb0faa964d06201a0215c254a2d5de91bae3 Mon Sep 17 00:00:00 2001 From: Mitchell Hashimoto Date: Fri, 19 Sep 2025 12:07:23 -0700 Subject: [PATCH 17/77] macos: set the app icon in syncAppearance to delay the icon update Fixes #8734 This forces the app icon to be set on another event loop tick from the main startup. In the future, we should load and set the icon completely in another thread. It appears that all the logic we have is totally thread-safe. --- macos/Sources/App/macOS/AppDelegate.swift | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/macos/Sources/App/macOS/AppDelegate.swift b/macos/Sources/App/macOS/AppDelegate.swift index df3a1f4f4..942aecdd4 100644 --- a/macos/Sources/App/macOS/AppDelegate.swift +++ b/macos/Sources/App/macOS/AppDelegate.swift @@ -860,7 +860,12 @@ class AppDelegate: NSObject, } else { GlobalEventTap.shared.disable() } + } + /// Sync the appearance of our app with the theme specified in the config. + private func syncAppearance(config: Ghostty.Config) { + NSApplication.shared.appearance = .init(ghosttyConfig: config) + switch (config.macosIcon) { case .official: self.appIcon = nil @@ -909,11 +914,6 @@ class AppDelegate: NSObject, } } - /// Sync the appearance of our app with the theme specified in the config. - private func syncAppearance(config: Ghostty.Config) { - NSApplication.shared.appearance = .init(ghosttyConfig: config) - } - //MARK: - Restorable State /// We support NSSecureCoding for restorable state. Required as of macOS Sonoma (14) but a good idea anyways. From 36ef1169f6e3a7e11e03007d015c644dafc0bf30 Mon Sep 17 00:00:00 2001 From: Mitchell Hashimoto Date: Fri, 19 Sep 2025 12:29:19 -0700 Subject: [PATCH 18/77] ci: put a 10 minute timeout on the Debian build This usually takes around 2 minutes. I just saw a runaway one spending 30+ minutes. --- .github/workflows/test.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 3c3be31c6..6c7093bc1 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -857,6 +857,7 @@ jobs: test-debian-13: name: Test build on Debian 13 runs-on: namespace-profile-ghostty-sm + timeout-minutes: 10 needs: [test, build-dist] steps: - name: Install and configure Namespace CLI From 4d761c96e5571fc961a2d63d0a12668fdfffa7fc Mon Sep 17 00:00:00 2001 From: Mitchell Hashimoto Date: Fri, 19 Sep 2025 12:44:32 -0700 Subject: [PATCH 19/77] macos: quick terminal stores the last closed size by screen Fixes #8713 This stores the last closed state of the quick terminal by screen pointer. We use a weak mapping so if a screen is unplugged we'll clear the memory. We will not remember the size if you unplug and replug in a monitor. --- .../QuickTerminalController.swift | 25 ++++++++++++++----- 1 file changed, 19 insertions(+), 6 deletions(-) diff --git a/macos/Sources/Features/QuickTerminal/QuickTerminalController.swift b/macos/Sources/Features/QuickTerminal/QuickTerminalController.swift index 68b9ba337..65186c5d7 100644 --- a/macos/Sources/Features/QuickTerminal/QuickTerminalController.swift +++ b/macos/Sources/Features/QuickTerminal/QuickTerminalController.swift @@ -21,13 +21,13 @@ class QuickTerminalController: BaseTerminalController { // The active space when the quick terminal was last shown. private var previousActiveSpace: CGSSpace? = nil - /// The window frame saved when the quick terminal's surface tree becomes empty. + /// The saved state when the quick terminal's surface tree becomes empty. /// /// This preserves the user's window size and position when all terminal surfaces /// are closed (e.g., via the `exit` command). When a new surface is created, /// the window will be restored to this frame, preventing SwiftUI from resetting /// the window to its default minimum size. - private var lastClosedFrame: NSRect? = nil + private var lastClosedFrames: NSMapTable /// Non-nil if we have hidden dock state. private var hiddenDock: HiddenDock? = nil @@ -45,6 +45,10 @@ class QuickTerminalController: BaseTerminalController { ) { self.position = position self.derivedConfig = DerivedConfig(ghostty.config) + + // This is a weak to strong mapping, so that our keys being NSScreens + // can remove themselves when they disappear. + self.lastClosedFrames = .weakToStrongObjects() // Important detail here: we initialize with an empty surface tree so // that we don't start a terminal process. This gets started when the @@ -360,8 +364,9 @@ class QuickTerminalController: BaseTerminalController { guard let screen = derivedConfig.quickTerminalScreen.screen else { return } // Grab our last closed frame to use, and clear our state since we're animating in. - let lastClosedFrame = self.lastClosedFrame - self.lastClosedFrame = nil + // We only use the last closed frame if we're opening on the same screen. + let lastClosedFrame: NSRect? = lastClosedFrames.object(forKey: screen)?.frame + lastClosedFrames.removeObject(forKey: screen) // Move our window off screen to the initial animation position. position.setInitial( @@ -491,8 +496,8 @@ class QuickTerminalController: BaseTerminalController { // the user's preferred window size and position for when the quick // terminal is reactivated with a new surface. Without this, SwiftUI // would reset the window to its minimum content size. - if window.frame.width > 0 && window.frame.height > 0 { - lastClosedFrame = window.frame + if window.frame.width > 0 && window.frame.height > 0, let screen = window.screen { + lastClosedFrames.setObject(.init(frame: window.frame), forKey: screen) } // If we hid the dock then we unhide it. @@ -715,6 +720,14 @@ class QuickTerminalController: BaseTerminalController { hidden = false } } + + private class LastClosedState { + let frame: NSRect + + init(frame: NSRect) { + self.frame = frame + } + } } extension Notification.Name { From bf047032b52401be9bb12ab2ca08fdcb2b0d2ba7 Mon Sep 17 00:00:00 2001 From: Mitchell Hashimoto Date: Fri, 19 Sep 2025 14:23:33 -0700 Subject: [PATCH 20/77] build: generate various resources at build run, not build graph This is stomping towards minimizing our build.zig dependencies so that it can be cached more often. Right now, touching almost any file in the project forces the build.zig to rebuild which is destroying my productivity. --- src/build/GhosttyResources.zig | 90 +++++++++++-------- src/build/main.zig | 5 -- src/config.zig | 3 - .../bash_completions.zig => extra/bash.zig} | 0 .../fish_completions.zig => extra/fish.zig} | 11 +-- .../sublime_syntax.zig => extra/sublime.zig} | 2 +- src/{config => extra}/vim.zig | 2 +- .../zsh_completions.zig => extra/zsh.zig} | 0 src/main_build_data.zig | 48 ++++++++++ src/main_ghostty.zig | 7 ++ 10 files changed, 118 insertions(+), 50 deletions(-) rename src/{build/bash_completions.zig => extra/bash.zig} (100%) rename src/{build/fish_completions.zig => extra/fish.zig} (95%) rename src/{config/sublime_syntax.zig => extra/sublime.zig} (96%) rename src/{config => extra}/vim.zig (98%) rename src/{build/zsh_completions.zig => extra/zsh.zig} (100%) create mode 100644 src/main_build_data.zig diff --git a/src/build/GhosttyResources.zig b/src/build/GhosttyResources.zig index 266069f83..0db1fd418 100644 --- a/src/build/GhosttyResources.zig +++ b/src/build/GhosttyResources.zig @@ -5,9 +5,6 @@ const builtin = @import("builtin"); const assert = std.debug.assert; const buildpkg = @import("main.zig"); const Config = @import("Config.zig"); -const config_vim = @import("../config/vim.zig"); -const config_sublime_syntax = @import("../config/sublime_syntax.zig"); -const terminfo = @import("../terminfo/main.zig"); const RunStep = std.Build.Step.Run; steps: []*std.Build.Step, @@ -16,6 +13,19 @@ pub fn init(b: *std.Build, cfg: *const Config) !GhosttyResources { var steps = std.ArrayList(*std.Build.Step).init(b.allocator); errdefer steps.deinit(); + // This is the exe used to generate some build data. + const build_data_exe = b.addExecutable(.{ + .name = "ghostty-build-data", + .root_module = b.createModule(.{ + .root_source_file = b.path("src/main_build_data.zig"), + .target = b.graph.host, + .strip = false, + .omit_frame_pointer = false, + .unwind_tables = .sync, + }), + }); + build_data_exe.linkLibC(); + // Terminfo terminfo: { const os_tag = cfg.target.result.os.tag; @@ -25,13 +35,10 @@ pub fn init(b: *std.Build, cfg: *const Config) !GhosttyResources { "terminfo"; // Encode our terminfo - var str = std.ArrayList(u8).init(b.allocator); - defer str.deinit(); - try terminfo.ghostty.encode(str.writer()); - - // Write it - var wf = b.addWriteFiles(); - const source = wf.add("ghostty.terminfo", str.items); + const run = b.addRunArtifact(build_data_exe); + run.addArg("+terminfo"); + const wf = b.addWriteFiles(); + const source = wf.addCopyFile(run.captureStdOut(), "ghostty.terminfo"); if (cfg.emit_terminfo) { const source_install = b.addInstallFile( @@ -130,8 +137,10 @@ pub fn init(b: *std.Build, cfg: *const Config) !GhosttyResources { // Fish shell completions { + const run = b.addRunArtifact(build_data_exe); + run.addArg("+fish"); const wf = b.addWriteFiles(); - _ = wf.add("ghostty.fish", buildpkg.fish_completions); + _ = wf.addCopyFile(run.captureStdOut(), "ghostty.fish"); const install_step = b.addInstallDirectory(.{ .source_dir = wf.getDirectory(), @@ -143,8 +152,10 @@ pub fn init(b: *std.Build, cfg: *const Config) !GhosttyResources { // zsh shell completions { + const run = b.addRunArtifact(build_data_exe); + run.addArg("+zsh"); const wf = b.addWriteFiles(); - _ = wf.add("_ghostty", buildpkg.zsh_completions); + _ = wf.addCopyFile(run.captureStdOut(), "_ghostty"); const install_step = b.addInstallDirectory(.{ .source_dir = wf.getDirectory(), @@ -156,8 +167,10 @@ pub fn init(b: *std.Build, cfg: *const Config) !GhosttyResources { // bash shell completions { + const run = b.addRunArtifact(build_data_exe); + run.addArg("+bash"); const wf = b.addWriteFiles(); - _ = wf.add("ghostty.bash", buildpkg.bash_completions); + _ = wf.addCopyFile(run.captureStdOut(), "ghostty.bash"); const install_step = b.addInstallDirectory(.{ .source_dir = wf.getDirectory(), @@ -167,39 +180,44 @@ pub fn init(b: *std.Build, cfg: *const Config) !GhosttyResources { try steps.append(&install_step.step); } - // Vim plugin + // Vim and Neovim plugin { const wf = b.addWriteFiles(); - _ = wf.add("syntax/ghostty.vim", config_vim.syntax); - _ = wf.add("ftdetect/ghostty.vim", config_vim.ftdetect); - _ = wf.add("ftplugin/ghostty.vim", config_vim.ftplugin); - _ = wf.add("compiler/ghostty.vim", config_vim.compiler); - const install_step = b.addInstallDirectory(.{ + { + const run = b.addRunArtifact(build_data_exe); + run.addArg("+vim-syntax"); + _ = wf.addCopyFile(run.captureStdOut(), "syntax/ghostty.vim"); + } + { + const run = b.addRunArtifact(build_data_exe); + run.addArg("+vim-ftdetect"); + _ = wf.addCopyFile(run.captureStdOut(), "ftdetect/ghostty.vim"); + } + { + const run = b.addRunArtifact(build_data_exe); + run.addArg("+vim-ftplugin"); + _ = wf.addCopyFile(run.captureStdOut(), "ftplugin/ghostty.vim"); + } + { + const run = b.addRunArtifact(build_data_exe); + run.addArg("+vim-compiler"); + _ = wf.addCopyFile(run.captureStdOut(), "compiler/ghostty.vim"); + } + + const vim_step = b.addInstallDirectory(.{ .source_dir = wf.getDirectory(), .install_dir = .prefix, .install_subdir = "share/vim/vimfiles", }); - try steps.append(&install_step.step); - } + try steps.append(&vim_step.step); - // Neovim plugin - // This is just a copy-paste of the Vim plugin, but using a Neovim subdir. - // By default, Neovim doesn't look inside share/vim/vimfiles. Some distros - // configure it to do that however. Fedora, does not as a counterexample. - { - const wf = b.addWriteFiles(); - _ = wf.add("syntax/ghostty.vim", config_vim.syntax); - _ = wf.add("ftdetect/ghostty.vim", config_vim.ftdetect); - _ = wf.add("ftplugin/ghostty.vim", config_vim.ftplugin); - _ = wf.add("compiler/ghostty.vim", config_vim.compiler); - - const install_step = b.addInstallDirectory(.{ + const neovim_step = b.addInstallDirectory(.{ .source_dir = wf.getDirectory(), .install_dir = .prefix, .install_subdir = "share/nvim/site", }); - try steps.append(&install_step.step); + try steps.append(&neovim_step.step); } // Sublime syntax highlighting for bat cli tool @@ -209,8 +227,10 @@ pub fn init(b: *std.Build, cfg: *const Config) !GhosttyResources { // the config file within the '~.config/bat' directory // (ex: --map-syntax "/Users/user/.config/ghostty/config:Ghostty Config"). { + const run = b.addRunArtifact(build_data_exe); + run.addArg("+sublime"); const wf = b.addWriteFiles(); - _ = wf.add("ghostty.sublime-syntax", config_sublime_syntax.syntax); + _ = wf.addCopyFile(run.captureStdOut(), "ghostty.sublime-syntax"); const install_step = b.addInstallDirectory(.{ .source_dir = wf.getDirectory(), diff --git a/src/build/main.zig b/src/build/main.zig index f25ce1c23..af99802df 100644 --- a/src/build/main.zig +++ b/src/build/main.zig @@ -28,10 +28,5 @@ pub const LipoStep = @import("LipoStep.zig"); pub const MetallibStep = @import("MetallibStep.zig"); pub const XCFrameworkStep = @import("XCFrameworkStep.zig"); -// Shell completions -pub const fish_completions = @import("fish_completions.zig").completions; -pub const zsh_completions = @import("zsh_completions.zig").completions; -pub const bash_completions = @import("bash_completions.zig").completions; - // Helpers pub const requireZig = @import("zig.zig").requireZig; diff --git a/src/config.zig b/src/config.zig index bcb48214d..e83dff530 100644 --- a/src/config.zig +++ b/src/config.zig @@ -48,7 +48,4 @@ pub const Wasm = if (!builtin.target.cpu.arch.isWasm()) struct {} else @import(" test { @import("std").testing.refAllDecls(@This()); - - // Vim syntax file, not used at runtime but we want to keep it tested. - _ = @import("config/vim.zig"); } diff --git a/src/build/bash_completions.zig b/src/extra/bash.zig similarity index 100% rename from src/build/bash_completions.zig rename to src/extra/bash.zig diff --git a/src/build/fish_completions.zig b/src/extra/fish.zig similarity index 95% rename from src/build/fish_completions.zig rename to src/extra/fish.zig index 0b6c45e1f..5a4b38e32 100644 --- a/src/build/fish_completions.zig +++ b/src/extra/fish.zig @@ -1,3 +1,4 @@ +//! Fish completions. const std = @import("std"); const Config = @import("../config/Config.zig"); @@ -5,23 +6,23 @@ const Action = @import("../cli.zig").ghostty.Action; /// A fish completions configuration that contains all the available commands /// and options. -pub const completions = comptimeGenerateFishCompletions(); +pub const completions = comptimeGenerateCompletions(); -fn comptimeGenerateFishCompletions() []const u8 { +fn comptimeGenerateCompletions() []const u8 { comptime { @setEvalBranchQuota(50000); var counter = std.io.countingWriter(std.io.null_writer); - try writeFishCompletions(&counter.writer()); + try writeCompletions(&counter.writer()); var buf: [counter.bytes_written]u8 = undefined; var stream = std.io.fixedBufferStream(&buf); - try writeFishCompletions(stream.writer()); + try writeCompletions(stream.writer()); const final = buf; return final[0..stream.getWritten().len]; } } -fn writeFishCompletions(writer: anytype) !void { +fn writeCompletions(writer: anytype) !void { { try writer.writeAll("set -l commands \""); var count: usize = 0; diff --git a/src/config/sublime_syntax.zig b/src/extra/sublime.zig similarity index 96% rename from src/config/sublime_syntax.zig rename to src/extra/sublime.zig index dff7d758e..4af589b4f 100644 --- a/src/config/sublime_syntax.zig +++ b/src/extra/sublime.zig @@ -1,5 +1,5 @@ const std = @import("std"); -const Config = @import("Config.zig"); +const Config = @import("../config/Config.zig"); const Template = struct { const header = diff --git a/src/config/vim.zig b/src/extra/vim.zig similarity index 98% rename from src/config/vim.zig rename to src/extra/vim.zig index 17ab0bc2e..e5261cd74 100644 --- a/src/config/vim.zig +++ b/src/extra/vim.zig @@ -1,5 +1,5 @@ const std = @import("std"); -const Config = @import("Config.zig"); +const Config = @import("../config/Config.zig"); /// This is the associated Vim file as named by the variable. pub const syntax = comptimeGenSyntax(); diff --git a/src/build/zsh_completions.zig b/src/extra/zsh.zig similarity index 100% rename from src/build/zsh_completions.zig rename to src/extra/zsh.zig diff --git a/src/main_build_data.zig b/src/main_build_data.zig new file mode 100644 index 000000000..13e604389 --- /dev/null +++ b/src/main_build_data.zig @@ -0,0 +1,48 @@ +//! This CLI is used to generate data that is used by the build process. +//! +//! We used to do this directly in our `build.zig` but the problem with +//! that approach is that any changes to the dependencies of this data would +//! force a rebuild of our build binary. If we're just doing something like +//! running tests and not emitting any of the info below, then that is a +//! complete waste. + +const std = @import("std"); +const Allocator = std.mem.Allocator; +const cli = @import("cli.zig"); + +pub const Action = enum { + // Shell completions + bash, + fish, + zsh, + + // Editor syntax files + sublime, + @"vim-syntax", + @"vim-ftdetect", + @"vim-ftplugin", + @"vim-compiler", + + // Other + terminfo, +}; + +pub fn main() !void { + const alloc = std.heap.c_allocator; + const action_ = try cli.action.detectArgs(Action, alloc); + const action = action_ orelse return error.NoAction; + + // Our output always goes to stdout. + const writer = std.io.getStdOut().writer(); + switch (action) { + .bash => try writer.writeAll(@import("extra/bash.zig").completions), + .fish => try writer.writeAll(@import("extra/fish.zig").completions), + .zsh => try writer.writeAll(@import("extra/zsh.zig").completions), + .sublime => try writer.writeAll(@import("extra/sublime.zig").syntax), + .@"vim-syntax" => try writer.writeAll(@import("extra/vim.zig").syntax), + .@"vim-ftdetect" => try writer.writeAll(@import("extra/vim.zig").ftdetect), + .@"vim-ftplugin" => try writer.writeAll(@import("extra/vim.zig").ftplugin), + .@"vim-compiler" => try writer.writeAll(@import("extra/vim.zig").compiler), + .terminfo => try @import("terminfo/ghostty.zig").ghostty.encode(writer), + } +} diff --git a/src/main_ghostty.zig b/src/main_ghostty.zig index fb29303f1..aca33a510 100644 --- a/src/main_ghostty.zig +++ b/src/main_ghostty.zig @@ -191,4 +191,11 @@ test { _ = @import("simd/main.zig"); _ = @import("synthetic/main.zig"); _ = @import("unicode/main.zig"); + + // Extra + _ = @import("extra/bash.zig"); + _ = @import("extra/fish.zig"); + _ = @import("extra/sublime.zig"); + _ = @import("extra/vim.zig"); + _ = @import("extra/zsh.zig"); } From 800fa99ff27b317bff789cd0b29a5707663521b6 Mon Sep 17 00:00:00 2001 From: Mitchell Hashimoto Date: Fri, 19 Sep 2025 15:12:20 -0700 Subject: [PATCH 21/77] build: move apprt, font, renderer enums to dedicated files This reduces the surface area of files we depend on for builds. --- src/apprt.zig | 25 +-------- src/apprt/runtime.zig | 29 +++++++++++ src/build/Config.zig | 36 ++++++------- src/build_config.zig | 2 +- src/font/backend.zig | 110 +++++++++++++++++++++++++++++++++++++++ src/font/main.zig | 110 +-------------------------------------- src/renderer.zig | 23 +------- src/renderer/backend.zig | 23 ++++++++ 8 files changed, 184 insertions(+), 174 deletions(-) create mode 100644 src/apprt/runtime.zig create mode 100644 src/font/backend.zig create mode 100644 src/renderer/backend.zig diff --git a/src/apprt.zig b/src/apprt.zig index ccb1251a2..947f29050 100644 --- a/src/apprt.zig +++ b/src/apprt.zig @@ -23,6 +23,7 @@ pub const embedded = @import("apprt/embedded.zig"); pub const surface = @import("apprt/surface.zig"); pub const Action = action.Action; +pub const Runtime = @import("apprt/runtime.zig").Runtime; pub const Target = action.Target; pub const ContentScale = structs.ContentScale; @@ -51,30 +52,6 @@ pub const runtime = switch (build_config.artifact) { pub const App = runtime.App; pub const Surface = runtime.Surface; -/// Runtime is the runtime to use for Ghostty. All runtimes do not provide -/// equivalent feature sets. -pub const Runtime = enum { - /// Will not produce an executable at all when `zig build` is called. - /// This is only useful if you're only interested in the lib only (macOS). - none, - - /// GTK4. Rich windowed application. This uses a full GObject-based - /// approach to building the application. - gtk, - - pub fn default(target: std.Target) Runtime { - return switch (target.os.tag) { - // The Linux and FreeBSD default is GTK because it is a full - // featured application. - .linux, .freebsd => .gtk, - // Otherwise, we do NONE so we don't create an exe and we create - // libghostty. On macOS, Xcode is used to build the app that links - // to libghostty. - else => .none, - }; - } -}; - test { _ = Runtime; _ = runtime; diff --git a/src/apprt/runtime.zig b/src/apprt/runtime.zig new file mode 100644 index 000000000..1be503536 --- /dev/null +++ b/src/apprt/runtime.zig @@ -0,0 +1,29 @@ +const std = @import("std"); + +/// Runtime is the runtime to use for Ghostty. All runtimes do not provide +/// equivalent feature sets. +pub const Runtime = enum { + /// Will not produce an executable at all when `zig build` is called. + /// This is only useful if you're only interested in the lib only (macOS). + none, + + /// GTK4. Rich windowed application. This uses a full GObject-based + /// approach to building the application. + gtk, + + pub fn default(target: std.Target) Runtime { + return switch (target.os.tag) { + // The Linux and FreeBSD default is GTK because it is a full + // featured application. + .linux, .freebsd => .gtk, + // Otherwise, we do NONE so we don't create an exe and we create + // libghostty. On macOS, Xcode is used to build the app that links + // to libghostty. + else => .none, + }; + } +}; + +test { + _ = Runtime; +} diff --git a/src/build/Config.zig b/src/build/Config.zig index 296a6a3b4..d1b7aa81f 100644 --- a/src/build/Config.zig +++ b/src/build/Config.zig @@ -5,9 +5,9 @@ const Config = @This(); const std = @import("std"); const builtin = @import("builtin"); -const apprt = @import("../apprt.zig"); -const font = @import("../font/main.zig"); -const rendererpkg = @import("../renderer.zig"); +const ApprtRuntime = @import("../apprt/runtime.zig").Runtime; +const FontBackend = @import("../font/backend.zig").Backend; +const RendererBackend = @import("../renderer/backend.zig").Backend; const Command = @import("../Command.zig"); const XCFramework = @import("GhosttyXCFramework.zig"); const WasmTarget = @import("../os/wasm/target.zig").Target; @@ -29,9 +29,9 @@ xcframework_target: XCFramework.Target = .universal, wasm_target: WasmTarget, /// Comptime interfaces -app_runtime: apprt.Runtime = .none, -renderer: rendererpkg.Impl = .opengl, -font_backend: font.Backend = .freetype, +app_runtime: ApprtRuntime = .none, +renderer: RendererBackend = .opengl, +font_backend: FontBackend = .freetype, /// Feature flags x11: bool = false, @@ -126,22 +126,22 @@ pub fn init(b: *std.Build) !Config { //--------------------------------------------------------------- // Comptime Interfaces config.font_backend = b.option( - font.Backend, + FontBackend, "font-backend", "The font backend to use for discovery and rasterization.", - ) orelse font.Backend.default(target.result, wasm_target); + ) orelse FontBackend.default(target.result, wasm_target); config.app_runtime = b.option( - apprt.Runtime, + ApprtRuntime, "app-runtime", "The app runtime to use. Not all values supported on all platforms.", - ) orelse apprt.Runtime.default(target.result); + ) orelse ApprtRuntime.default(target.result); config.renderer = b.option( - rendererpkg.Impl, + RendererBackend, "renderer", "The app runtime to use. Not all values supported on all platforms.", - ) orelse rendererpkg.Impl.default(target.result, wasm_target); + ) orelse RendererBackend.default(target.result, wasm_target); //--------------------------------------------------------------- // Feature Flags @@ -446,9 +446,9 @@ pub fn addOptions(self: *const Config, step: *std.Build.Step.Options) !void { step.addOption(bool, "wayland", self.wayland); step.addOption(bool, "sentry", self.sentry); step.addOption(bool, "i18n", self.i18n); - step.addOption(apprt.Runtime, "app_runtime", self.app_runtime); - step.addOption(font.Backend, "font_backend", self.font_backend); - step.addOption(rendererpkg.Impl, "renderer", self.renderer); + step.addOption(ApprtRuntime, "app_runtime", self.app_runtime); + step.addOption(FontBackend, "font_backend", self.font_backend); + step.addOption(RendererBackend, "renderer", self.renderer); step.addOption(ExeEntrypoint, "exe_entrypoint", self.exe_entrypoint); step.addOption(WasmTarget, "wasm_target", self.wasm_target); step.addOption(bool, "wasm_shared", self.wasm_shared); @@ -503,9 +503,9 @@ pub fn fromOptions() Config { .version = options.app_version, .flatpak = options.flatpak, - .app_runtime = std.meta.stringToEnum(apprt.Runtime, @tagName(options.app_runtime)).?, - .font_backend = std.meta.stringToEnum(font.Backend, @tagName(options.font_backend)).?, - .renderer = std.meta.stringToEnum(rendererpkg.Impl, @tagName(options.renderer)).?, + .app_runtime = std.meta.stringToEnum(ApprtRuntime, @tagName(options.app_runtime)).?, + .font_backend = std.meta.stringToEnum(FontBackend, @tagName(options.font_backend)).?, + .renderer = std.meta.stringToEnum(RendererBackend, @tagName(options.renderer)).?, .exe_entrypoint = std.meta.stringToEnum(ExeEntrypoint, @tagName(options.exe_entrypoint)).?, .wasm_target = std.meta.stringToEnum(WasmTarget, @tagName(options.wasm_target)).?, .wasm_shared = options.wasm_shared, diff --git a/src/build_config.zig b/src/build_config.zig index 903197717..ebd14bfe8 100644 --- a/src/build_config.zig +++ b/src/build_config.zig @@ -40,7 +40,7 @@ pub const exe_entrypoint = config.exe_entrypoint; pub const flatpak = options.flatpak; pub const app_runtime: apprt.Runtime = config.app_runtime; pub const font_backend: font.Backend = config.font_backend; -pub const renderer: rendererpkg.Impl = config.renderer; +pub const renderer: rendererpkg.Backend = config.renderer; pub const i18n: bool = config.i18n; /// The bundle ID for the app. This is used in many places and is currently diff --git a/src/font/backend.zig b/src/font/backend.zig new file mode 100644 index 000000000..37b3189b6 --- /dev/null +++ b/src/font/backend.zig @@ -0,0 +1,110 @@ +const std = @import("std"); + +pub const Backend = enum { + const WasmTarget = @import("../os/wasm/target.zig").Target; + + /// FreeType for font rendering with no font discovery enabled. + freetype, + + /// Fontconfig for font discovery and FreeType for font rendering. + fontconfig_freetype, + + /// CoreText for font discovery, rendering, and shaping (macOS). + coretext, + + /// CoreText for font discovery, FreeType for rendering, and + /// HarfBuzz for shaping (macOS). + coretext_freetype, + + /// CoreText for font discovery and rendering, HarfBuzz for shaping + coretext_harfbuzz, + + /// CoreText for font discovery and rendering, no shaping. + coretext_noshape, + + /// Use the browser font system and the Canvas API (wasm). This limits + /// the available fonts to browser fonts (anything Canvas natively + /// supports). + web_canvas, + + /// Returns the default backend for a build environment. This is + /// meant to be called at comptime by the build.zig script. To get the + /// backend look at build_options. + pub fn default( + target: std.Target, + wasm_target: WasmTarget, + ) Backend { + if (target.cpu.arch == .wasm32) { + return switch (wasm_target) { + .browser => .web_canvas, + }; + } + + // macOS also supports "coretext_freetype" but there is no scenario + // that is the default. It is only used by people who want to + // self-compile Ghostty and prefer the freetype aesthetic. + return if (target.os.tag.isDarwin()) .coretext else .fontconfig_freetype; + } + + // All the functions below can be called at comptime or runtime to + // determine if we have a certain dependency. + + pub fn hasFreetype(self: Backend) bool { + return switch (self) { + .freetype, + .fontconfig_freetype, + .coretext_freetype, + => true, + + .coretext, + .coretext_harfbuzz, + .coretext_noshape, + .web_canvas, + => false, + }; + } + + pub fn hasCoretext(self: Backend) bool { + return switch (self) { + .coretext, + .coretext_freetype, + .coretext_harfbuzz, + .coretext_noshape, + => true, + + .freetype, + .fontconfig_freetype, + .web_canvas, + => false, + }; + } + + pub fn hasFontconfig(self: Backend) bool { + return switch (self) { + .fontconfig_freetype => true, + + .freetype, + .coretext, + .coretext_freetype, + .coretext_harfbuzz, + .coretext_noshape, + .web_canvas, + => false, + }; + } + + pub fn hasHarfbuzz(self: Backend) bool { + return switch (self) { + .freetype, + .fontconfig_freetype, + .coretext_freetype, + .coretext_harfbuzz, + => true, + + .coretext, + .coretext_noshape, + .web_canvas, + => false, + }; + } +}; diff --git a/src/font/main.zig b/src/font/main.zig index 782b3e388..a8522afe1 100644 --- a/src/font/main.zig +++ b/src/font/main.zig @@ -5,6 +5,7 @@ const build_config = @import("../build_config.zig"); const library = @import("library.zig"); pub const Atlas = @import("Atlas.zig"); +pub const Backend = @import("backend.zig").Backend; pub const discovery = @import("discovery.zig"); pub const embedded = @import("embedded.zig"); pub const face = @import("face.zig"); @@ -48,115 +49,6 @@ pub const options: struct { .backend = if (builtin.target.cpu.arch.isWasm()) .web_canvas else build_config.font_backend, }; -pub const Backend = enum { - const WasmTarget = @import("../os/wasm/target.zig").Target; - - /// FreeType for font rendering with no font discovery enabled. - freetype, - - /// Fontconfig for font discovery and FreeType for font rendering. - fontconfig_freetype, - - /// CoreText for font discovery, rendering, and shaping (macOS). - coretext, - - /// CoreText for font discovery, FreeType for rendering, and - /// HarfBuzz for shaping (macOS). - coretext_freetype, - - /// CoreText for font discovery and rendering, HarfBuzz for shaping - coretext_harfbuzz, - - /// CoreText for font discovery and rendering, no shaping. - coretext_noshape, - - /// Use the browser font system and the Canvas API (wasm). This limits - /// the available fonts to browser fonts (anything Canvas natively - /// supports). - web_canvas, - - /// Returns the default backend for a build environment. This is - /// meant to be called at comptime by the build.zig script. To get the - /// backend look at build_options. - pub fn default( - target: std.Target, - wasm_target: WasmTarget, - ) Backend { - if (target.cpu.arch == .wasm32) { - return switch (wasm_target) { - .browser => .web_canvas, - }; - } - - // macOS also supports "coretext_freetype" but there is no scenario - // that is the default. It is only used by people who want to - // self-compile Ghostty and prefer the freetype aesthetic. - return if (target.os.tag.isDarwin()) .coretext else .fontconfig_freetype; - } - - // All the functions below can be called at comptime or runtime to - // determine if we have a certain dependency. - - pub fn hasFreetype(self: Backend) bool { - return switch (self) { - .freetype, - .fontconfig_freetype, - .coretext_freetype, - => true, - - .coretext, - .coretext_harfbuzz, - .coretext_noshape, - .web_canvas, - => false, - }; - } - - pub fn hasCoretext(self: Backend) bool { - return switch (self) { - .coretext, - .coretext_freetype, - .coretext_harfbuzz, - .coretext_noshape, - => true, - - .freetype, - .fontconfig_freetype, - .web_canvas, - => false, - }; - } - - pub fn hasFontconfig(self: Backend) bool { - return switch (self) { - .fontconfig_freetype => true, - - .freetype, - .coretext, - .coretext_freetype, - .coretext_harfbuzz, - .coretext_noshape, - .web_canvas, - => false, - }; - } - - pub fn hasHarfbuzz(self: Backend) bool { - return switch (self) { - .freetype, - .fontconfig_freetype, - .coretext_freetype, - .coretext_harfbuzz, - => true, - - .coretext, - .coretext_noshape, - .web_canvas, - => false, - }; - } -}; - /// The styles that a family can take. pub const Style = enum(u3) { regular = 0, diff --git a/src/renderer.zig b/src/renderer.zig index e3ed070b6..f09f717c4 100644 --- a/src/renderer.zig +++ b/src/renderer.zig @@ -10,12 +10,12 @@ const std = @import("std"); const builtin = @import("builtin"); const build_config = @import("build_config.zig"); -const WasmTarget = @import("os/wasm/target.zig").Target; const cursor = @import("renderer/cursor.zig"); const message = @import("renderer/message.zig"); const size = @import("renderer/size.zig"); pub const shadertoy = @import("renderer/shadertoy.zig"); +pub const Backend = @import("renderer/backend.zig").Backend; pub const GenericRenderer = @import("renderer/generic.zig").Renderer; pub const Metal = @import("renderer/Metal.zig"); pub const OpenGL = @import("renderer/OpenGL.zig"); @@ -33,27 +33,6 @@ pub const GridSize = size.GridSize; pub const Padding = size.Padding; pub const cursorStyle = cursor.style; -/// Possible implementations, used for build options. -pub const Impl = enum { - opengl, - metal, - webgl, - - pub fn default( - target: std.Target, - wasm_target: WasmTarget, - ) Impl { - if (target.cpu.arch == .wasm32) { - return switch (wasm_target) { - .browser => .webgl, - }; - } - - if (target.os.tag.isDarwin()) return .metal; - return .opengl; - } -}; - /// The implementation to use for the renderer. This is comptime chosen /// so that every build has exactly one renderer implementation. pub const Renderer = switch (build_config.renderer) { diff --git a/src/renderer/backend.zig b/src/renderer/backend.zig new file mode 100644 index 000000000..942e1f0ff --- /dev/null +++ b/src/renderer/backend.zig @@ -0,0 +1,23 @@ +const std = @import("std"); +const WasmTarget = @import("../os/wasm/target.zig").Target; + +/// Possible implementations, used for build options. +pub const Backend = enum { + opengl, + metal, + webgl, + + pub fn default( + target: std.Target, + wasm_target: WasmTarget, + ) Backend { + if (target.cpu.arch == .wasm32) { + return switch (wasm_target) { + .browser => .webgl, + }; + } + + if (target.os.tag.isDarwin()) return .metal; + return .opengl; + } +}; From d65466362d2370bd5395f38a9678b59f4994422d Mon Sep 17 00:00:00 2001 From: Mitchell Hashimoto Date: Fri, 19 Sep 2025 15:22:04 -0700 Subject: [PATCH 22/77] build: Command.expandPath can go in its own dedicated os/path.zig file --- src/Command.zig | 85 ------------------------------------------ src/build/Config.zig | 4 +- src/os/main.zig | 2 + src/os/path.zig | 89 ++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 93 insertions(+), 87 deletions(-) create mode 100644 src/os/path.zig diff --git a/src/Command.zig b/src/Command.zig index 1bddf8b82..b0d804327 100644 --- a/src/Command.zig +++ b/src/Command.zig @@ -404,91 +404,6 @@ pub fn getData(self: Command, comptime DT: type) ?*DT { return if (self.data) |ptr| @ptrCast(@alignCast(ptr)) else null; } -/// Search for "cmd" in the PATH and return the absolute path. This will -/// always allocate if there is a non-null result. The caller must free the -/// resulting value. -pub fn expandPath(alloc: Allocator, cmd: []const u8) !?[]u8 { - // If the command already contains a slash, then we return it as-is - // because it is assumed to be absolute or relative. - if (std.mem.indexOfScalar(u8, cmd, '/') != null) { - return try alloc.dupe(u8, cmd); - } - - const PATH = switch (builtin.os.tag) { - .windows => blk: { - const win_path = std.process.getenvW(std.unicode.utf8ToUtf16LeStringLiteral("PATH")) orelse return null; - const path = try std.unicode.utf16LeToUtf8Alloc(alloc, win_path); - break :blk path; - }, - else => std.posix.getenvZ("PATH") orelse return null, - }; - defer if (builtin.os.tag == .windows) alloc.free(PATH); - - var path_buf: [std.fs.max_path_bytes]u8 = undefined; - var it = std.mem.tokenizeScalar(u8, PATH, std.fs.path.delimiter); - var seen_eacces = false; - while (it.next()) |search_path| { - // We need enough space in our path buffer to store this - const path_len = search_path.len + cmd.len + 1; - if (path_buf.len < path_len) return error.PathTooLong; - - // Copy in the full path - @memcpy(path_buf[0..search_path.len], search_path); - path_buf[search_path.len] = std.fs.path.sep; - @memcpy(path_buf[search_path.len + 1 ..][0..cmd.len], cmd); - path_buf[path_len] = 0; - const full_path = path_buf[0..path_len :0]; - - // Stat it - const f = std.fs.cwd().openFile( - full_path, - .{}, - ) catch |err| switch (err) { - error.FileNotFound => continue, - error.AccessDenied => { - // Accumulate this and return it later so we can try other - // paths that we have access to. - seen_eacces = true; - continue; - }, - else => return err, - }; - defer f.close(); - const stat = try f.stat(); - if (stat.kind != .directory and isExecutable(stat.mode)) { - return try alloc.dupe(u8, full_path); - } - } - - if (seen_eacces) return error.AccessDenied; - - return null; -} - -fn isExecutable(mode: std.fs.File.Mode) bool { - if (builtin.os.tag == .windows) return true; - return mode & 0o0111 != 0; -} - -// `uname -n` is the *nix equivalent of `hostname.exe` on Windows -test "expandPath: hostname" { - const executable = if (builtin.os.tag == .windows) "hostname.exe" else "uname"; - const path = (try expandPath(testing.allocator, executable)).?; - defer testing.allocator.free(path); - try testing.expect(path.len > executable.len); -} - -test "expandPath: does not exist" { - const path = try expandPath(testing.allocator, "thisreallyprobablydoesntexist123"); - try testing.expect(path == null); -} - -test "expandPath: slash" { - const path = (try expandPath(testing.allocator, "foo/env")).?; - defer testing.allocator.free(path); - try testing.expect(path.len == 7); -} - // Copied from Zig. This is a publicly exported function but there is no // way to get it from the std package. fn createNullDelimitedEnvMap(arena: mem.Allocator, env_map: *const EnvMap) ![:null]?[*:0]u8 { diff --git a/src/build/Config.zig b/src/build/Config.zig index d1b7aa81f..9c74f14e8 100644 --- a/src/build/Config.zig +++ b/src/build/Config.zig @@ -8,9 +8,9 @@ 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 Command = @import("../Command.zig"); const XCFramework = @import("GhosttyXCFramework.zig"); const WasmTarget = @import("../os/wasm/target.zig").Target; +const expandPath = @import("../os/path.zig").expand; const gtk = @import("gtk.zig"); const GitVersion = @import("GitVersion.zig"); @@ -332,7 +332,7 @@ pub fn init(b: *std.Build) !Config { if (system_package) break :emit_docs true; // We only default to true if we can find pandoc. - const path = Command.expandPath(b.allocator, "pandoc") catch + const path = expandPath(b.allocator, "pandoc") catch break :emit_docs false; defer if (path) |p| b.allocator.free(p); break :emit_docs path != null; diff --git a/src/os/main.zig b/src/os/main.zig index 41dc6aa29..af851f673 100644 --- a/src/os/main.zig +++ b/src/os/main.zig @@ -23,6 +23,7 @@ pub const args = @import("args.zig"); pub const cgroup = @import("cgroup.zig"); pub const hostname = @import("hostname.zig"); pub const i18n = @import("i18n.zig"); +pub const path = @import("path.zig"); pub const passwd = @import("passwd.zig"); pub const xdg = @import("xdg.zig"); pub const windows = @import("windows.zig"); @@ -65,6 +66,7 @@ pub const getKernelInfo = kernel_info.getKernelInfo; test { _ = i18n; + _ = path; if (comptime builtin.os.tag == .linux) { _ = kernel_info; diff --git a/src/os/path.zig b/src/os/path.zig new file mode 100644 index 000000000..730ae692d --- /dev/null +++ b/src/os/path.zig @@ -0,0 +1,89 @@ +const std = @import("std"); +const builtin = @import("builtin"); +const Allocator = std.mem.Allocator; +const testing = std.testing; + +/// Search for "cmd" in the PATH and return the absolute path. This will +/// always allocate if there is a non-null result. The caller must free the +/// resulting value. +pub fn expand(alloc: Allocator, cmd: []const u8) !?[]u8 { + // If the command already contains a slash, then we return it as-is + // because it is assumed to be absolute or relative. + if (std.mem.indexOfScalar(u8, cmd, '/') != null) { + return try alloc.dupe(u8, cmd); + } + + const PATH = switch (builtin.os.tag) { + .windows => blk: { + const win_path = std.process.getenvW(std.unicode.utf8ToUtf16LeStringLiteral("PATH")) orelse return null; + const path = try std.unicode.utf16LeToUtf8Alloc(alloc, win_path); + break :blk path; + }, + else => std.posix.getenvZ("PATH") orelse return null, + }; + defer if (builtin.os.tag == .windows) alloc.free(PATH); + + var path_buf: [std.fs.max_path_bytes]u8 = undefined; + var it = std.mem.tokenizeScalar(u8, PATH, std.fs.path.delimiter); + var seen_eacces = false; + while (it.next()) |search_path| { + // We need enough space in our path buffer to store this + const path_len = search_path.len + cmd.len + 1; + if (path_buf.len < path_len) return error.PathTooLong; + + // Copy in the full path + @memcpy(path_buf[0..search_path.len], search_path); + path_buf[search_path.len] = std.fs.path.sep; + @memcpy(path_buf[search_path.len + 1 ..][0..cmd.len], cmd); + path_buf[path_len] = 0; + const full_path = path_buf[0..path_len :0]; + + // Stat it + const f = std.fs.cwd().openFile( + full_path, + .{}, + ) catch |err| switch (err) { + error.FileNotFound => continue, + error.AccessDenied => { + // Accumulate this and return it later so we can try other + // paths that we have access to. + seen_eacces = true; + continue; + }, + else => return err, + }; + defer f.close(); + const stat = try f.stat(); + if (stat.kind != .directory and isExecutable(stat.mode)) { + return try alloc.dupe(u8, full_path); + } + } + + if (seen_eacces) return error.AccessDenied; + + return null; +} + +fn isExecutable(mode: std.fs.File.Mode) bool { + if (builtin.os.tag == .windows) return true; + return mode & 0o0111 != 0; +} + +// `uname -n` is the *nix equivalent of `hostname.exe` on Windows +test "expand: hostname" { + const executable = if (builtin.os.tag == .windows) "hostname.exe" else "uname"; + const path = (try expand(testing.allocator, executable)).?; + defer testing.allocator.free(path); + try testing.expect(path.len > executable.len); +} + +test "expand: does not exist" { + const path = try expand(testing.allocator, "thisreallyprobablydoesntexist123"); + try testing.expect(path == null); +} + +test "expand: slash" { + const path = (try expand(testing.allocator, "foo/env")).?; + defer testing.allocator.free(path); + try testing.expect(path.len == 7); +} From 9feaec9c9c9bd74f0ad1627e73ac6cebf1c4c135 Mon Sep 17 00:00:00 2001 From: Mitchell Hashimoto Date: Fri, 19 Sep 2025 15:28:21 -0700 Subject: [PATCH 23/77] build: move locales out into dedicated file --- src/build/GhosttyI18n.zig | 6 ++--- src/os/i18n.zig | 51 +------------------------------------ src/os/i18n_locales.zig | 53 +++++++++++++++++++++++++++++++++++++++ 3 files changed, 57 insertions(+), 53 deletions(-) create mode 100644 src/os/i18n_locales.zig diff --git a/src/build/GhosttyI18n.zig b/src/build/GhosttyI18n.zig index 324cc94c2..b99e60426 100644 --- a/src/build/GhosttyI18n.zig +++ b/src/build/GhosttyI18n.zig @@ -4,7 +4,7 @@ const std = @import("std"); const builtin = @import("builtin"); const Config = @import("Config.zig"); const gresource = @import("../apprt/gtk/build/gresource.zig"); -const internal_os = @import("../os/main.zig"); +const locales = @import("../os/i18n_locales.zig").locales; const domain = "com.mitchellh.ghostty"; @@ -21,7 +21,7 @@ pub fn init(b: *std.Build, cfg: *const Config) !GhosttyI18n { var steps = std.ArrayList(*std.Build.Step).init(b.allocator); defer steps.deinit(); - inline for (internal_os.i18n.locales) |locale| { + inline for (locales) |locale| { // There is no encoding suffix in the LC_MESSAGES path on FreeBSD, // so we need to remove it from `locale` to have a correct destination string. // (/usr/local/share/locale/en_AU/LC_MESSAGES) @@ -155,7 +155,7 @@ fn createUpdateStep(b: *std.Build) !*std.Build.Step { "po/" ++ domain ++ ".pot", ); - inline for (internal_os.i18n.locales) |locale| { + inline for (locales) |locale| { const msgmerge = b.addSystemCommand(&.{ "msgmerge", "--quiet", "--no-fuzzy-matching" }); msgmerge.addFileArg(b.path("po/" ++ locale ++ ".po")); msgmerge.addFileArg(xgettext.captureStdOut()); diff --git a/src/os/i18n.zig b/src/os/i18n.zig index 917c34b4a..0f7790faa 100644 --- a/src/os/i18n.zig +++ b/src/os/i18n.zig @@ -1,59 +1,10 @@ const std = @import("std"); const builtin = @import("builtin"); const build_config = @import("../build_config.zig"); +const locales = @import("i18n_locales.zig"); const log = std.log.scoped(.i18n); -/// Supported locales for the application. This must be kept up to date -/// with the translations available in the `po/` directory; this is used -/// by our build process as well runtime libghostty APIs. -/// -/// The order also matters. For incomplete locale information (i.e. only -/// a language code available), the first match is used. For example, if -/// we know the user requested `zh` but has no script code, then we'd pick -/// the first locale that matches `zh`. -/// -/// For ordering, we prefer: -/// -/// 1. The most common locales first, since there are places in the code -/// where we do linear searches for a locale and we want to minimize -/// the number of iterations for the common case. -/// -/// 2. Alphabetical for otherwise equally common locales. -/// -/// 3. Most preferred locale for a language without a country code. -/// -/// Note for "most common" locales, this is subjective and based on -/// the perceived userbase of Ghostty, which may not be representative -/// of general populations or global language distribution. Also note -/// that ordering may be weird when we first merge a new locale since -/// we don't have a good way to determine this. We can always reorder -/// with some data. -pub const locales = [_][:0]const u8{ - "zh_CN.UTF-8", - "de_DE.UTF-8", - "fr_FR.UTF-8", - "ja_JP.UTF-8", - "nl_NL.UTF-8", - "nb_NO.UTF-8", - "ru_RU.UTF-8", - "uk_UA.UTF-8", - "pl_PL.UTF-8", - "ko_KR.UTF-8", - "mk_MK.UTF-8", - "tr_TR.UTF-8", - "id_ID.UTF-8", - "es_BO.UTF-8", - "es_AR.UTF-8", - "pt_BR.UTF-8", - "ca_ES.UTF-8", - "it_IT.UTF-8", - "bg_BG.UTF-8", - "ga_IE.UTF-8", - "hu_HU.UTF-8", - "he_IL.UTF-8", -}; - /// Set for faster membership lookup of locales. pub const locales_map = map: { var kvs: [locales.len]struct { []const u8 } = undefined; diff --git a/src/os/i18n_locales.zig b/src/os/i18n_locales.zig new file mode 100644 index 000000000..199a24526 --- /dev/null +++ b/src/os/i18n_locales.zig @@ -0,0 +1,53 @@ +// NOTE: This is in a separate file because our build depends on it and +// we want to minimize the transitive dependencies of the build binary +// itself. + +/// Supported locales for the application. This must be kept up to date +/// with the translations available in the `po/` directory; this is used +/// by our build process as well runtime libghostty APIs. +/// +/// The order also matters. For incomplete locale information (i.e. only +/// a language code available), the first match is used. For example, if +/// we know the user requested `zh` but has no script code, then we'd pick +/// the first locale that matches `zh`. +/// +/// For ordering, we prefer: +/// +/// 1. The most common locales first, since there are places in the code +/// where we do linear searches for a locale and we want to minimize +/// the number of iterations for the common case. +/// +/// 2. Alphabetical for otherwise equally common locales. +/// +/// 3. Most preferred locale for a language without a country code. +/// +/// Note for "most common" locales, this is subjective and based on +/// the perceived userbase of Ghostty, which may not be representative +/// of general populations or global language distribution. Also note +/// that ordering may be weird when we first merge a new locale since +/// we don't have a good way to determine this. We can always reorder +/// with some data. +pub const locales = [_][:0]const u8{ + "zh_CN.UTF-8", + "de_DE.UTF-8", + "fr_FR.UTF-8", + "ja_JP.UTF-8", + "nl_NL.UTF-8", + "nb_NO.UTF-8", + "ru_RU.UTF-8", + "uk_UA.UTF-8", + "pl_PL.UTF-8", + "ko_KR.UTF-8", + "mk_MK.UTF-8", + "tr_TR.UTF-8", + "id_ID.UTF-8", + "es_BO.UTF-8", + "es_AR.UTF-8", + "pt_BR.UTF-8", + "ca_ES.UTF-8", + "it_IT.UTF-8", + "bg_BG.UTF-8", + "ga_IE.UTF-8", + "hu_HU.UTF-8", + "he_IL.UTF-8", +}; From da2a3e2510e57a4ed9c9633982ab05afdd36ae68 Mon Sep 17 00:00:00 2001 From: Mitchell Hashimoto Date: Fri, 19 Sep 2025 15:40:35 -0700 Subject: [PATCH 24/77] very slightly improve helpgen dependencies --- src/helpgen.zig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/helpgen.zig b/src/helpgen.zig index e1628c218..57296fe86 100644 --- a/src/helpgen.zig +++ b/src/helpgen.zig @@ -4,7 +4,7 @@ const std = @import("std"); const Config = @import("config/Config.zig"); -const Action = @import("cli.zig").ghostty.Action; +const Action = @import("cli/ghostty.zig").Action; const KeybindAction = @import("input/Binding.zig").Action; pub fn main() !void { From 2de105e0353093b8dc966c244c281c77fdb97ce4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marco=20Trevisan=20=28Trevi=C3=B1o=29?= Date: Fri, 19 Sep 2025 07:19:29 +0200 Subject: [PATCH 25/77] snap: Do not leak the launcher into the ghostty $PATH Otherwise when launching the snap we'll get a "launcher" binary that is provided by the own snap --- snap/snapcraft.yaml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/snap/snapcraft.yaml b/snap/snapcraft.yaml index df8d6ae53..0962bf972 100644 --- a/snap/snapcraft.yaml +++ b/snap/snapcraft.yaml @@ -20,7 +20,7 @@ platforms: apps: ghostty: command: bin/ghostty - command-chain: [bin/launcher] + command-chain: [app/launcher] completer: share/bash-completion/completions/ghostty.bash desktop: share/applications/com.mitchellh.ghostty.desktop #refresh-mode: ignore-running # Store rejects this, needs fix in review-tools @@ -35,7 +35,7 @@ parts: source: snap/local source-type: local organize: - launcher: bin/ + launcher: app/ zig: plugin: nil From d55f3e5c4171efcdc0619a961fdbaea3f541c262 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marco=20Trevisan=20=28Trevi=C3=B1o=29?= Date: Fri, 19 Sep 2025 06:40:11 +0200 Subject: [PATCH 26/77] gtk/surface: Filter out the SNAP variables by their contents When running in a snap context we need to filtering out all the SNAP_* variables out there, but this is not enough, because it's also needed to sanitize them by ensuring that no variable containing a path pointing to a $SNAP folder is leaked there. Otherwise we might have (for example) XDG_RUNTIME_DIRS containing a "private" snap path, and that will be exposed to all the applications that will be started from ghostty --- snap/local/launcher | 6 -- src/apprt/gtk/class/surface.zig | 101 ++++++++++++++++++++++++++++---- 2 files changed, 89 insertions(+), 18 deletions(-) diff --git a/snap/local/launcher b/snap/local/launcher index b4141c7de..89e0d1709 100755 --- a/snap/local/launcher +++ b/snap/local/launcher @@ -61,10 +61,4 @@ fi [ "$needs_update" = true ] && echo "LAST_REVISION=$SNAP_REVISION" > "$SNAP_USER_DATA/.last_revision" -# Unset all SNAP specific environment variables to keep them from leaking -# into other snaps that might get executed from within the shell -for var in $(printenv | grep SNAP_ | cut -d= -f1); do - unset $var -done - exec "$@" diff --git a/src/apprt/gtk/class/surface.zig b/src/apprt/gtk/class/surface.zig index c26d0c1ef..fb2f2bd47 100644 --- a/src/apprt/gtk/class/surface.zig +++ b/src/apprt/gtk/class/surface.zig @@ -1228,18 +1228,7 @@ pub const Surface = extern struct { // Unset environment varies set by snaps if we're running in a snap. // This allows Ghostty to further launch additional snaps. if (env.get("SNAP")) |_| { - env.remove("SNAP"); - env.remove("DRIRC_CONFIGDIR"); - env.remove("__EGL_EXTERNAL_PLATFORM_CONFIG_DIRS"); - env.remove("__EGL_VENDOR_LIBRARY_DIRS"); - env.remove("LD_LIBRARY_PATH"); - env.remove("LIBGL_DRIVERS_PATH"); - env.remove("LIBVA_DRIVERS_PATH"); - env.remove("VK_LAYER_PATH"); - env.remove("XLOCALEDIR"); - env.remove("GDK_PIXBUF_MODULEDIR"); - env.remove("GDK_PIXBUF_MODULE_FILE"); - env.remove("GTK_PATH"); + try filterSnapPaths(alloc, &env); } // This is a hack because it ties ourselves (optionally) to the @@ -1253,6 +1242,94 @@ pub const Surface = extern struct { return env; } + /// Filter out environment variables that start with forbidden prefixes + fn filterSnapPaths(allocator: std.mem.Allocator, env_map: *std.process.EnvMap) !void { + const snap_paths_vars = [_][]const u8{ + "SNAP", + "SNAP_USER_COMMON", + "SNAP_USER_DATA", + "SNAP_DATA", + "SNAP_COMMON", + }; + + var env_to_remove = std.ArrayList([]const u8).init(allocator); + defer env_to_remove.deinit(); + + var env_to_update = std.ArrayList(struct { + key: []const u8, + value: []const u8, + }).init(allocator); + defer { + for (env_to_update.items) |item| { + allocator.free(item.value); + } + env_to_update.deinit(); + } + + var it = env_map.iterator(); + while (it.next()) |entry| { + const key = entry.key_ptr.*; + const value = entry.value_ptr.*; + + if (std.mem.eql(u8, key, "TERMINFO")) { + continue; + } + + if (std.mem.startsWith(u8, key, "GHOSTTY")) { + continue; + } + + if (std.mem.startsWith(u8, key, "SNAP_")) { + try env_to_remove.append(key); + continue; + } + + var paths = std.mem.splitAny(u8, value, ":"); + var filtered_paths = std.ArrayList([]const u8).init(allocator); + defer filtered_paths.deinit(); + + var modified = false; + while (paths.next()) |path| { + var include = true; + for (snap_paths_vars) |snap_path_var| { + const snap_path_val = env_map.get(snap_path_var); + + if (snap_path_val) |snap_path| { + if (snap_path.len == 0) { + continue; + } + + if (std.mem.startsWith(u8, path, snap_path)) { + include = false; + modified = true; + break; + } + } + } + if (include) { + try filtered_paths.append(path); + } + } + + if (modified) { + if (filtered_paths.items.len > 0) { + const new_value = try std.mem.join(allocator, ":", filtered_paths.items); + try env_to_update.append(.{ .key = key, .value = new_value }); + } else { + try env_to_remove.append(key); + } + } + } + + for (env_to_update.items) |item| { + try env_map.put(item.key, item.value); + } + + for (env_to_remove.items) |key| { + _ = env_map.remove(key); + } + } + pub fn clipboardRequest( self: *Self, clipboard_type: apprt.Clipboard, From bf3a607db622b90e113e43b8814df13689336515 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marco=20Trevisan=20=28Trevi=C3=B1o=29?= Date: Fri, 19 Sep 2025 06:46:56 +0200 Subject: [PATCH 27/77] build: Add a new snap option and use it to build the snap So we can limit the snap operations even at build time --- snap/snapcraft.yaml | 7 ++++++- src/apprt/gtk/class/surface.zig | 7 +++++-- src/build/Config.zig | 9 +++++++++ src/build_config.zig | 1 + 4 files changed, 21 insertions(+), 3 deletions(-) diff --git a/snap/snapcraft.yaml b/snap/snapcraft.yaml index 0962bf972..c5a86ade7 100644 --- a/snap/snapcraft.yaml +++ b/snap/snapcraft.yaml @@ -79,7 +79,12 @@ parts: # TODO: Remove -fno-sys=gtk4-layer-shell when we upgrade to a version that packages it Ubuntu 24.10+ override-build: | craftctl set version=$(cat VERSION) - $CRAFT_PART_SRC/../../zig/src/zig build -Dpatch-rpath=\$ORIGIN/../usr/lib/$CRAFT_ARCH_TRIPLET_BUILD_FOR:/snap/core24/current/lib/$CRAFT_ARCH_TRIPLET_BUILD_FOR -Doptimize=ReleaseFast -Dcpu=baseline -fno-sys=gtk4-layer-shell + $CRAFT_PART_SRC/../../zig/src/zig build \ + -Dsnap=true \ + -Dpatch-rpath=\$ORIGIN/../usr/lib/$CRAFT_ARCH_TRIPLET_BUILD_FOR:/snap/core24/current/lib/$CRAFT_ARCH_TRIPLET_BUILD_FOR \ + -Doptimize=ReleaseFast \ + -Dcpu=baseline \ + -fno-sys=gtk4-layer-shell cp -rp zig-out/* $CRAFT_PART_INSTALL/ sed -i 's|Icon=com.mitchellh.ghostty|Icon=${SNAP}/share/icons/hicolor/512x512/apps/com.mitchellh.ghostty.png|g' $CRAFT_PART_INSTALL/share/applications/com.mitchellh.ghostty.desktop diff --git a/src/apprt/gtk/class/surface.zig b/src/apprt/gtk/class/surface.zig index fb2f2bd47..e9aab43db 100644 --- a/src/apprt/gtk/class/surface.zig +++ b/src/apprt/gtk/class/surface.zig @@ -9,6 +9,7 @@ const gobject = @import("gobject"); const gtk = @import("gtk"); const apprt = @import("../../../apprt.zig"); +const build_config = @import("../../../build_config.zig"); const datastruct = @import("../../../datastruct/main.zig"); const font = @import("../../../font/main.zig"); const input = @import("../../../input.zig"); @@ -1227,8 +1228,10 @@ pub const Surface = extern struct { // Unset environment varies set by snaps if we're running in a snap. // This allows Ghostty to further launch additional snaps. - if (env.get("SNAP")) |_| { - try filterSnapPaths(alloc, &env); + if (comptime build_config.snap) { + if (env.get("SNAP")) |_| { + try filterSnapPaths(alloc, &env); + } } // This is a hack because it ties ourselves (optionally) to the diff --git a/src/build/Config.zig b/src/build/Config.zig index 9c74f14e8..746021930 100644 --- a/src/build/Config.zig +++ b/src/build/Config.zig @@ -51,6 +51,7 @@ patch_rpath: ?[]const u8 = null, /// Artifacts flatpak: bool = false, +snap: bool = false, emit_bench: bool = false, emit_docs: bool = false, emit_exe: bool = false, @@ -152,6 +153,12 @@ pub fn init(b: *std.Build) !Config { "Build for Flatpak (integrates with Flatpak APIs). Only has an effect targeting Linux.", ) orelse false; + config.snap = b.option( + bool, + "snap", + "Build for Snap (do specific Snap operations). Only has an effect targeting Linux.", + ) orelse false; + config.sentry = b.option( bool, "sentry", @@ -442,6 +449,7 @@ pub fn addOptions(self: *const Config, step: *std.Build.Step.Options) !void { // We need to break these down individual because addOption doesn't // support all types. step.addOption(bool, "flatpak", self.flatpak); + step.addOption(bool, "snap", self.snap); step.addOption(bool, "x11", self.x11); step.addOption(bool, "wayland", self.wayland); step.addOption(bool, "sentry", self.sentry); @@ -506,6 +514,7 @@ pub fn fromOptions() Config { .app_runtime = std.meta.stringToEnum(ApprtRuntime, @tagName(options.app_runtime)).?, .font_backend = std.meta.stringToEnum(FontBackend, @tagName(options.font_backend)).?, .renderer = std.meta.stringToEnum(RendererBackend, @tagName(options.renderer)).?, + .snap = options.snap, .exe_entrypoint = std.meta.stringToEnum(ExeEntrypoint, @tagName(options.exe_entrypoint)).?, .wasm_target = std.meta.stringToEnum(WasmTarget, @tagName(options.wasm_target)).?, .wasm_shared = options.wasm_shared, diff --git a/src/build_config.zig b/src/build_config.zig index ebd14bfe8..0d294c69e 100644 --- a/src/build_config.zig +++ b/src/build_config.zig @@ -38,6 +38,7 @@ pub const artifact = Artifact.detect(); const config = BuildConfig.fromOptions(); pub const exe_entrypoint = config.exe_entrypoint; pub const flatpak = options.flatpak; +pub const snap = options.snap; pub const app_runtime: apprt.Runtime = config.app_runtime; pub const font_backend: font.Backend = config.font_backend; pub const renderer: rendererpkg.Backend = config.renderer; From 7b8be344fcd5bec0ae23d5c1217c5f33b7a9963a Mon Sep 17 00:00:00 2001 From: Mitchell Hashimoto Date: Fri, 19 Sep 2025 16:03:45 -0700 Subject: [PATCH 28/77] stylistic changes --- src/apprt/gtk/class/surface.zig | 84 ++++++++++++++------------------- 1 file changed, 35 insertions(+), 49 deletions(-) diff --git a/src/apprt/gtk/class/surface.zig b/src/apprt/gtk/class/surface.zig index e9aab43db..616ec54f5 100644 --- a/src/apprt/gtk/class/surface.zig +++ b/src/apprt/gtk/class/surface.zig @@ -1229,9 +1229,10 @@ pub const Surface = extern struct { // Unset environment varies set by snaps if we're running in a snap. // This allows Ghostty to further launch additional snaps. if (comptime build_config.snap) { - if (env.get("SNAP")) |_| { - try filterSnapPaths(alloc, &env); - } + if (env.get("SNAP") != null) try filterSnapPaths( + alloc, + &env, + ); } // This is a hack because it ties ourselves (optionally) to the @@ -1245,9 +1246,11 @@ pub const Surface = extern struct { return env; } - /// Filter out environment variables that start with forbidden prefixes - fn filterSnapPaths(allocator: std.mem.Allocator, env_map: *std.process.EnvMap) !void { - const snap_paths_vars = [_][]const u8{ + /// Filter out environment variables that start with forbidden prefixes. + fn filterSnapPaths(gpa: std.mem.Allocator, env_map: *std.process.EnvMap) !void { + comptime assert(build_config.snap); + + const snap_vars = [_][]const u8{ "SNAP", "SNAP_USER_COMMON", "SNAP_USER_DATA", @@ -1255,68 +1258,53 @@ pub const Surface = extern struct { "SNAP_COMMON", }; - var env_to_remove = std.ArrayList([]const u8).init(allocator); - defer env_to_remove.deinit(); + // Use an arena because everything in this function is temporary. + var arena = std.heap.ArenaAllocator.init(gpa); + defer arena.deinit(); + const alloc = arena.allocator(); + var env_to_remove = std.ArrayList([]const u8).init(alloc); var env_to_update = std.ArrayList(struct { key: []const u8, value: []const u8, - }).init(allocator); - defer { - for (env_to_update.items) |item| { - allocator.free(item.value); - } - env_to_update.deinit(); - } + }).init(alloc); var it = env_map.iterator(); while (it.next()) |entry| { const key = entry.key_ptr.*; const value = entry.value_ptr.*; - if (std.mem.eql(u8, key, "TERMINFO")) { - continue; - } - - if (std.mem.startsWith(u8, key, "GHOSTTY")) { - continue; - } + // Ignore fields we set ourself + if (std.mem.eql(u8, key, "TERMINFO")) continue; + if (std.mem.startsWith(u8, key, "GHOSTTY")) continue; + // Any env var starting with SNAP must be removed if (std.mem.startsWith(u8, key, "SNAP_")) { try env_to_remove.append(key); continue; } - var paths = std.mem.splitAny(u8, value, ":"); - var filtered_paths = std.ArrayList([]const u8).init(allocator); + var filtered_paths = std.ArrayList([]const u8).init(alloc); defer filtered_paths.deinit(); var modified = false; + var paths = std.mem.splitAny(u8, value, ":"); while (paths.next()) |path| { var include = true; - for (snap_paths_vars) |snap_path_var| { - const snap_path_val = env_map.get(snap_path_var); - - if (snap_path_val) |snap_path| { - if (snap_path.len == 0) { - continue; - } - - if (std.mem.startsWith(u8, path, snap_path)) { - include = false; - modified = true; - break; - } + for (snap_vars) |k| if (env_map.get(k)) |snap_path| { + if (snap_path.len == 0) continue; + if (std.mem.startsWith(u8, path, snap_path)) { + include = false; + modified = true; + break; } - } - if (include) { - try filtered_paths.append(path); - } + }; + if (include) try filtered_paths.append(path); } if (modified) { if (filtered_paths.items.len > 0) { - const new_value = try std.mem.join(allocator, ":", filtered_paths.items); + const new_value = try std.mem.join(alloc, ":", filtered_paths.items); try env_to_update.append(.{ .key = key, .value = new_value }); } else { try env_to_remove.append(key); @@ -1324,13 +1312,11 @@ pub const Surface = extern struct { } } - for (env_to_update.items) |item| { - try env_map.put(item.key, item.value); - } - - for (env_to_remove.items) |key| { - _ = env_map.remove(key); - } + for (env_to_update.items) |item| try env_map.put( + item.key, + item.value, + ); + for (env_to_remove.items) |key| _ = env_map.remove(key); } pub fn clipboardRequest( From 270891eee182a48b8e2e1bc4dcf94a65790760f5 Mon Sep 17 00:00:00 2001 From: Mitchell Hashimoto Date: Fri, 19 Sep 2025 16:06:30 -0700 Subject: [PATCH 29/77] ci: add -Dsnap test --- .github/workflows/test.yml | 39 ++++++++++++++++++++++++++++++++++++-- snap/snapcraft.yaml | 2 +- 2 files changed, 38 insertions(+), 3 deletions(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 6c7093bc1..2099e1d42 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -19,6 +19,7 @@ jobs: - build-nix - build-macos - build-macos-matrix + - build-snap - build-windows - test - test-gtk @@ -118,7 +119,41 @@ jobs: run: | nix develop -c \ zig build \ - -Dflatpak=true + -Dflatpak + + build-snap: + strategy: + fail-fast: false + 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@7be5dee1421f63d07e71ce6e0a9f8a4b07c2a487 # v31.6.1 + with: + nix_path: nixpkgs=channel:nixos-unstable + - uses: cachix/cachix-action@0fc020193b5a1fa3ac4575aa3a7d3aa6a35435ad # v16 + with: + name: ghostty + authToken: "${{ secrets.CACHIX_AUTH_TOKEN }}" + + - name: Build with Snap + run: | + nix develop -c \ + zig build \ + -Dsnap build-linux: strategy: @@ -275,7 +310,7 @@ jobs: trigger-snap: if: github.event_name != 'pull_request' runs-on: namespace-profile-ghostty-xsm - needs: build-dist + needs: [build-dist, build-snap] steps: - name: Checkout code uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 diff --git a/snap/snapcraft.yaml b/snap/snapcraft.yaml index c5a86ade7..e48fa93c8 100644 --- a/snap/snapcraft.yaml +++ b/snap/snapcraft.yaml @@ -80,7 +80,7 @@ parts: override-build: | craftctl set version=$(cat VERSION) $CRAFT_PART_SRC/../../zig/src/zig build \ - -Dsnap=true \ + -Dsnap \ -Dpatch-rpath=\$ORIGIN/../usr/lib/$CRAFT_ARCH_TRIPLET_BUILD_FOR:/snap/core24/current/lib/$CRAFT_ARCH_TRIPLET_BUILD_FOR \ -Doptimize=ReleaseFast \ -Dcpu=baseline \ From fbaacc235bd8807384ca6a8f06b67b23ff9f5e21 Mon Sep 17 00:00:00 2001 From: "Jeffrey C. Ollie" Date: Sat, 20 Sep 2025 01:39:59 -0500 Subject: [PATCH 30/77] gtk: use zig-gobject generated from ghostty-org/zig-gobject --- build.zig.zon | 4 ++-- build.zig.zon.json | 6 +++--- build.zig.zon.nix | 6 +++--- build.zig.zon.txt | 2 +- flatpak/zig-packages.json | 6 +++--- 5 files changed, 12 insertions(+), 12 deletions(-) diff --git a/build.zig.zon b/build.zig.zon index efbe367d1..0e349cd6d 100644 --- a/build.zig.zon +++ b/build.zig.zon @@ -55,8 +55,8 @@ .gobject = .{ // https://github.com/jcollie/ghostty-gobject based on zig_gobject // Temporary until we generate them at build time automatically. - .url = "https://github.com/jcollie/ghostty-gobject/releases/download/0.15.1-2025-09-04-48-1/ghostty-gobject-0.15.1-2025-09-04-48-1.tar.zst", - .hash = "gobject-0.3.0-Skun7ET3nQAc0LzvO0NAvTiGGnmkF36cnmbeCAF6MB7Z", + .url = "https://github.com/ghostty-org/zig-gobject/releases/download/2025-09-20-20-1/ghostty-gobject-2025-09-20-20-1.tar.zst", + .hash = "gobject-0.3.0-Skun7ET3nQCqJhDL0KnF_X7M4L7o7JePsJBbrYpEr7UV", .lazy = true, }, diff --git a/build.zig.zon.json b/build.zig.zon.json index bd4a9fe5e..c9bc71296 100644 --- a/build.zig.zon.json +++ b/build.zig.zon.json @@ -24,10 +24,10 @@ "url": "https://deps.files.ghostty.org/glslang-12201278a1a05c0ce0b6eb6026c65cd3e9247aa041b1c260324bf29cee559dd23ba1.tar.gz", "hash": "sha256-FKLtu1Ccs+UamlPj9eQ12/WXFgS0uDPmPmB26MCpl7U=" }, - "gobject-0.3.0-Skun7ET3nQAc0LzvO0NAvTiGGnmkF36cnmbeCAF6MB7Z": { + "gobject-0.3.0-Skun7ET3nQCqJhDL0KnF_X7M4L7o7JePsJBbrYpEr7UV": { "name": "gobject", - "url": "https://github.com/jcollie/ghostty-gobject/releases/download/0.15.1-2025-09-04-48-1/ghostty-gobject-0.15.1-2025-09-04-48-1.tar.zst", - "hash": "sha256-h6aKUerGlX2ATVEeoN03eWaqDqvUmKdedgpxrSoHvrY=" + "url": "https://github.com/ghostty-org/zig-gobject/releases/download/2025-09-20-20-1/ghostty-gobject-2025-09-20-20-1.tar.zst", + "hash": "sha256-SXiqGm81aUn6yq1wFXgNTAULdKOHS/Rzkp5OgNkkcXo=" }, "N-V-__8AALiNBAA-_0gprYr92CjrMj1I5bqNu0TSJOnjFNSr": { "name": "gtk4_layer_shell", diff --git a/build.zig.zon.nix b/build.zig.zon.nix index 30e84f46f..85fdd67e4 100644 --- a/build.zig.zon.nix +++ b/build.zig.zon.nix @@ -123,11 +123,11 @@ in }; } { - name = "gobject-0.3.0-Skun7ET3nQAc0LzvO0NAvTiGGnmkF36cnmbeCAF6MB7Z"; + name = "gobject-0.3.0-Skun7ET3nQCqJhDL0KnF_X7M4L7o7JePsJBbrYpEr7UV"; path = fetchZigArtifact { name = "gobject"; - url = "https://github.com/jcollie/ghostty-gobject/releases/download/0.15.1-2025-09-04-48-1/ghostty-gobject-0.15.1-2025-09-04-48-1.tar.zst"; - hash = "sha256-h6aKUerGlX2ATVEeoN03eWaqDqvUmKdedgpxrSoHvrY="; + url = "https://github.com/ghostty-org/zig-gobject/releases/download/2025-09-20-20-1/ghostty-gobject-2025-09-20-20-1.tar.zst"; + hash = "sha256-SXiqGm81aUn6yq1wFXgNTAULdKOHS/Rzkp5OgNkkcXo="; }; } { diff --git a/build.zig.zon.txt b/build.zig.zon.txt index 3b3317ab1..3974ee9d5 100644 --- a/build.zig.zon.txt +++ b/build.zig.zon.txt @@ -28,7 +28,7 @@ https://deps.files.ghostty.org/wuffs-122037b39d577ec2db3fd7b2130e7b69ef6cc1807d6 https://deps.files.ghostty.org/zig_js-12205a66d423259567764fa0fc60c82be35365c21aeb76c5a7dc99698401f4f6fefc.tar.gz https://deps.files.ghostty.org/ziglyph-b89d43d1e3fb01b6074bc1f7fc980324b04d26a5.tar.gz https://deps.files.ghostty.org/zlib-1220fed0c74e1019b3ee29edae2051788b080cd96e90d56836eea857b0b966742efb.tar.gz -https://github.com/jcollie/ghostty-gobject/releases/download/0.15.1-2025-09-04-48-1/ghostty-gobject-0.15.1-2025-09-04-48-1.tar.zst +https://github.com/ghostty-org/zig-gobject/releases/download/2025-09-20-20-1/ghostty-gobject-2025-09-20-20-1.tar.zst https://github.com/mitchellh/libxev/archive/7f803181b158a10fec8619f793e3b4df515566cb.tar.gz https://github.com/mitchellh/zig-objc/archive/c9e917a4e15a983b672ca779c7985d738a2d517c.tar.gz https://github.com/natecraddock/zf/archive/7aacbe6d155d64d15937ca95ca6c014905eb531f.tar.gz diff --git a/flatpak/zig-packages.json b/flatpak/zig-packages.json index 0b5e95cce..d068596e4 100644 --- a/flatpak/zig-packages.json +++ b/flatpak/zig-packages.json @@ -31,9 +31,9 @@ }, { "type": "archive", - "url": "https://github.com/jcollie/ghostty-gobject/releases/download/0.15.1-2025-09-04-48-1/ghostty-gobject-0.15.1-2025-09-04-48-1.tar.zst", - "dest": "vendor/p/gobject-0.3.0-Skun7ET3nQAc0LzvO0NAvTiGGnmkF36cnmbeCAF6MB7Z", - "sha256": "87a68a51eac6957d804d511ea0dd377966aa0eabd498a75e760a71ad2a07beb6" + "url": "https://github.com/ghostty-org/zig-gobject/releases/download/2025-09-20-20-1/ghostty-gobject-2025-09-20-20-1.tar.zst", + "dest": "vendor/p/gobject-0.3.0-Skun7ET3nQCqJhDL0KnF_X7M4L7o7JePsJBbrYpEr7UV", + "sha256": "4978aa1a6f356949facaad7015780d4c050b74a3874bf473929e4e80d924717a" }, { "type": "archive", From f0e407de85fac529a76a1f353eacf4f209ae7c4c Mon Sep 17 00:00:00 2001 From: rhodes-b <59537185+rhodes-b@users.noreply.github.com> Date: Sat, 20 Sep 2025 02:28:07 -0500 Subject: [PATCH 31/77] nicer comment on why you shouldn't copy the defaults into your config specifically that some options will conflict with each other --- src/config/config-template | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/config/config-template b/src/config/config-template index c9b51deb8..63309137a 100644 --- a/src/config/config-template +++ b/src/config/config-template @@ -6,15 +6,15 @@ # {[path]s} # # The template does not set any default options, since Ghostty ships -# with sensible defaults for all options. Users should only need to set -# options that they want to change from the default. +# with sensible defaults for all options. +# Note that you should not paste the output of `ghostty +show-config +# --default` into your config: some default options actually conflict with each other +# when explicitly set in a configuration file. Instead, only set the +# options you actually need. # # Run `ghostty +show-config --default --docs` to view a list of # all available config options and their default values. # -# Do not copy the output of the defaults into your config, like stated above -# users only need to set options to change the defaults. -# # Additionally, each config option is also explained in detail # on Ghostty's website, at https://ghostty.org/docs/config. # From b34e22053d1011d427052c64b3c46693fdb8e505 Mon Sep 17 00:00:00 2001 From: rhodes-b <59537185+rhodes-b@users.noreply.github.com> Date: Sat, 20 Sep 2025 03:55:05 -0500 Subject: [PATCH 32/77] unfocused-split-fill working again though it can't detect when its actually a split yet --- src/apprt/gtk/class/surface.zig | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/src/apprt/gtk/class/surface.zig b/src/apprt/gtk/class/surface.zig index c26d0c1ef..d64f6fe0a 100644 --- a/src/apprt/gtk/class/surface.zig +++ b/src/apprt/gtk/class/surface.zig @@ -435,6 +435,7 @@ pub const Surface = extern struct { /// The current focus state of the terminal based on the /// focus events. focused: bool = true, + unfocused_widget: ?*gtk.Widget = null, /// Whether this surface is "zoomed" or not. A zoomed surface /// shows up taking the full bounds of a split view. @@ -1989,6 +1990,11 @@ pub const Surface = extern struct { _ = glib.idleAddOnce(idleFocus, self.ref()); self.as(gobject.Object).notifyByPspec(properties.focused.impl.param_spec); + if (priv.unfocused_widget) |widget| { + priv.terminal_page.removeOverlay(widget); + priv.unfocused_widget = null; + } + // Bell stops ringing as soon as we gain focus self.setBellRinging(false); } @@ -1999,6 +2005,16 @@ pub const Surface = extern struct { priv.im_context.as(gtk.IMContext).focusOut(); _ = glib.idleAddOnce(idleFocus, self.ref()); self.as(gobject.Object).notifyByPspec(properties.focused.impl.param_spec); + + if (priv.unfocused_widget) |_| return; + // add unfocused-split-fill + priv.unfocused_widget = unfocused_widget: { + const drawing_area = gtk.DrawingArea.new(); + const unfocused_widget = drawing_area.as(gtk.Widget); + unfocused_widget.addCssClass("unfocused-split"); + priv.terminal_page.addOverlay(unfocused_widget); + break :unfocused_widget unfocused_widget; + }; } /// The focus callback must be triggered on an idle loop source because From 6ee9a3767b13aea5a7212cf6ccba220268068aeb Mon Sep 17 00:00:00 2001 From: rhodes-b <59537185+rhodes-b@users.noreply.github.com> Date: Sat, 20 Sep 2025 04:32:09 -0500 Subject: [PATCH 33/77] worse way but its at least split aware, doesn't seem like the path forward --- src/apprt/gtk/class/split_tree.zig | 7 ++++++- src/apprt/gtk/class/surface.zig | 29 +++++++++++++++++++++-------- 2 files changed, 27 insertions(+), 9 deletions(-) diff --git a/src/apprt/gtk/class/split_tree.zig b/src/apprt/gtk/class/split_tree.zig index 3b6dcb4a9..0fe06a0b1 100644 --- a/src/apprt/gtk/class/split_tree.zig +++ b/src/apprt/gtk/class/split_tree.zig @@ -399,7 +399,12 @@ pub const SplitTree = extern struct { const tree = self.getTree() orelse return null; var it = tree.iterator(); while (it.next()) |entry| { - if (entry.view.getFocused()) return entry.handle; + if (!entry.view.getFocused() and it.nodes.len > 1) { + entry.view.setUnfocused(); + } + if (entry.view.getFocused()) { + return entry.handle; + } } // If none are currently focused, the most previously focused diff --git a/src/apprt/gtk/class/surface.zig b/src/apprt/gtk/class/surface.zig index d64f6fe0a..9906a1baf 100644 --- a/src/apprt/gtk/class/surface.zig +++ b/src/apprt/gtk/class/surface.zig @@ -1492,6 +1492,19 @@ pub const Surface = extern struct { return self.private().focused; } + pub fn setUnfocused(self: *Self) void { + const priv = self.private(); + if (!priv.focused and (priv.unfocused_widget == null)) { + priv.unfocused_widget = unfocused_widget: { + const drawing_area = gtk.DrawingArea.new(); + const unfocused_widget = drawing_area.as(gtk.Widget); + unfocused_widget.addCssClass("unfocused-split"); + priv.terminal_page.addOverlay(unfocused_widget); + break :unfocused_widget unfocused_widget; + }; + } + } + /// Change the configuration for this surface. pub fn setConfig(self: *Self, config: *Config) void { const priv = self.private(); @@ -2006,15 +2019,15 @@ pub const Surface = extern struct { _ = glib.idleAddOnce(idleFocus, self.ref()); self.as(gobject.Object).notifyByPspec(properties.focused.impl.param_spec); - if (priv.unfocused_widget) |_| return; + // if (priv.unfocused_widget) |_| return; // add unfocused-split-fill - priv.unfocused_widget = unfocused_widget: { - const drawing_area = gtk.DrawingArea.new(); - const unfocused_widget = drawing_area.as(gtk.Widget); - unfocused_widget.addCssClass("unfocused-split"); - priv.terminal_page.addOverlay(unfocused_widget); - break :unfocused_widget unfocused_widget; - }; + // priv.unfocused_widget = unfocused_widget: { + // const drawing_area = gtk.DrawingArea.new(); + // const unfocused_widget = drawing_area.as(gtk.Widget); + // unfocused_widget.addCssClass("unfocused-split"); + // priv.terminal_page.addOverlay(unfocused_widget); + // break :unfocused_widget unfocused_widget; + // }; } /// The focus callback must be triggered on an idle loop source because From bf1278deff54ec70bc0a8bbf6ff55638b993c0af Mon Sep 17 00:00:00 2001 From: Mitchell Hashimoto Date: Sat, 20 Sep 2025 14:57:37 -0700 Subject: [PATCH 34/77] unicode: isolate properties, tables, and ziglyph into separate files This makes it cleaner to add new sources of table generation and also avoids inadvertently depending on different modules (despite Zig's lazy analysis). This also fixes up terminal to only use our look up tables which avoids bringing ziglyph in for the terminal module. --- src/terminal/Terminal.zig | 4 +- src/unicode/Properties.zig | 75 +++++++++++++++++++++++++++ src/unicode/main.zig | 7 ++- src/unicode/props_table.zig | 18 +++++++ src/unicode/props_ziglyph.zig | 96 +++++++++++++++++++++++++++++++++++ 5 files changed, 194 insertions(+), 6 deletions(-) create mode 100644 src/unicode/Properties.zig create mode 100644 src/unicode/props_table.zig create mode 100644 src/unicode/props_ziglyph.zig diff --git a/src/terminal/Terminal.zig b/src/terminal/Terminal.zig index 162cfde38..0d659eb9a 100644 --- a/src/terminal/Terminal.zig +++ b/src/terminal/Terminal.zig @@ -344,7 +344,7 @@ pub fn print(self: *Terminal, c: u21) !void { // VS15 makes it narrow. if (c == 0xFE0F or c == 0xFE0E) { // This only applies to emoji - const prev_props = unicode.getProperties(prev.cell.content.codepoint); + const prev_props = unicode.table.get(prev.cell.content.codepoint); const emoji = prev_props.grapheme_boundary_class.isExtendedPictographic(); if (!emoji) return; @@ -470,7 +470,7 @@ pub fn print(self: *Terminal, c: u21) !void { // If this is a emoji variation selector, prev must be an emoji if (c == 0xFE0F or c == 0xFE0E) { - const prev_props = unicode.getProperties(prev.content.codepoint); + const prev_props = unicode.table.get(prev.content.codepoint); const emoji = prev_props.grapheme_boundary_class == .extended_pictographic; if (!emoji) return; } diff --git a/src/unicode/Properties.zig b/src/unicode/Properties.zig new file mode 100644 index 000000000..b7840743a --- /dev/null +++ b/src/unicode/Properties.zig @@ -0,0 +1,75 @@ +//! Property set per codepoint that Ghostty cares about. +//! +//! Adding to this lets you find new properties but also potentially makes +//! our lookup tables less efficient. Any changes to this should run the +//! benchmarks in src/bench to verify that we haven't regressed. +const Properties = @This(); + +const std = @import("std"); + +/// Codepoint width. We clamp to [0, 2] since Ghostty handles control +/// characters and we max out at 2 for wide characters (i.e. 3-em dash +/// becomes a 2-em dash). +width: u2 = 0, + +/// Grapheme boundary class. +grapheme_boundary_class: GraphemeBoundaryClass = .invalid, + +// Needed for lut.Generator +pub fn eql(a: Properties, b: Properties) bool { + return a.width == b.width and + a.grapheme_boundary_class == b.grapheme_boundary_class; +} + +// Needed for lut.Generator +pub fn format( + self: Properties, + comptime layout: []const u8, + opts: std.fmt.FormatOptions, + writer: anytype, +) !void { + _ = layout; + _ = opts; + try std.fmt.format(writer, + \\.{{ + \\ .width= {}, + \\ .grapheme_boundary_class= .{s}, + \\}} + , .{ + self.width, + @tagName(self.grapheme_boundary_class), + }); +} + +/// Possible grapheme boundary classes. This isn't an exhaustive list: +/// we omit control, CR, LF, etc. because in Ghostty's usage that are +/// impossible because they're handled by the terminal. +pub const GraphemeBoundaryClass = enum(u4) { + invalid, + L, + V, + T, + LV, + LVT, + prepend, + extend, + zwj, + spacing_mark, + regional_indicator, + extended_pictographic, + extended_pictographic_base, // \p{Extended_Pictographic} & \p{Emoji_Modifier_Base} + emoji_modifier, // \p{Emoji_Modifier} + + /// Returns true if this is an extended pictographic type. This + /// should be used instead of comparing the enum value directly + /// because we classify multiple. + pub fn isExtendedPictographic(self: GraphemeBoundaryClass) bool { + return switch (self) { + .extended_pictographic, + .extended_pictographic_base, + => true, + + else => false, + }; + } +}; diff --git a/src/unicode/main.zig b/src/unicode/main.zig index 17c86deca..ae50075ff 100644 --- a/src/unicode/main.zig +++ b/src/unicode/main.zig @@ -1,14 +1,13 @@ pub const lut = @import("lut.zig"); const grapheme = @import("grapheme.zig"); -const props = @import("props.zig"); -pub const table = props.table; -pub const Properties = props.Properties; -pub const getProperties = props.get; +pub const table = @import("props_table.zig").table; +pub const Properties = @import("Properties.zig"); pub const graphemeBreak = grapheme.graphemeBreak; pub const GraphemeBreakState = grapheme.BreakState; test { + _ = @import("props_ziglyph.zig"); _ = @import("symbols.zig"); @import("std").testing.refAllDecls(@This()); } diff --git a/src/unicode/props_table.zig b/src/unicode/props_table.zig new file mode 100644 index 000000000..80492346c --- /dev/null +++ b/src/unicode/props_table.zig @@ -0,0 +1,18 @@ +const Properties = @import("Properties.zig"); +const lut = @import("lut.zig"); + +/// The lookup tables for Ghostty. +pub const table = table: { + // This is only available after running a generator as part of the Ghostty + // build.zig process, but due to Zig's lazy analysis we can still reference + // it here. + // + // An example process is the `main` in `props_ziglyph.zig` + const generated = @import("unicode_tables").Tables(Properties); + const Tables = lut.Tables(Properties); + break :table Tables{ + .stage1 = &generated.stage1, + .stage2 = &generated.stage2, + .stage3 = &generated.stage3, + }; +}; diff --git a/src/unicode/props_ziglyph.zig b/src/unicode/props_ziglyph.zig new file mode 100644 index 000000000..fd123f3b5 --- /dev/null +++ b/src/unicode/props_ziglyph.zig @@ -0,0 +1,96 @@ +const props = @This(); + +const std = @import("std"); +const assert = std.debug.assert; +const ziglyph = @import("ziglyph"); +const lut = @import("lut.zig"); +const Properties = @import("Properties.zig"); +const GraphemeBoundaryClass = Properties.GraphemeBoundaryClass; + +/// Gets the grapheme boundary class for a codepoint. This is VERY +/// SLOW. The use case for this is only in generating lookup tables. +fn graphemeBoundaryClass(cp: u21) GraphemeBoundaryClass { + // We special-case modifier bases because we should not break + // if a modifier isn't next to a base. + if (ziglyph.emoji.isEmojiModifierBase(cp)) { + assert(ziglyph.emoji.isExtendedPictographic(cp)); + return .extended_pictographic_base; + } + + if (ziglyph.emoji.isEmojiModifier(cp)) return .emoji_modifier; + if (ziglyph.emoji.isExtendedPictographic(cp)) return .extended_pictographic; + if (ziglyph.grapheme_break.isL(cp)) return .L; + if (ziglyph.grapheme_break.isV(cp)) return .V; + if (ziglyph.grapheme_break.isT(cp)) return .T; + if (ziglyph.grapheme_break.isLv(cp)) return .LV; + if (ziglyph.grapheme_break.isLvt(cp)) return .LVT; + if (ziglyph.grapheme_break.isPrepend(cp)) return .prepend; + if (ziglyph.grapheme_break.isExtend(cp)) return .extend; + if (ziglyph.grapheme_break.isZwj(cp)) return .zwj; + if (ziglyph.grapheme_break.isSpacingmark(cp)) return .spacing_mark; + if (ziglyph.grapheme_break.isRegionalIndicator(cp)) return .regional_indicator; + + // This is obviously not INVALID invalid, there is SOME grapheme + // boundary class for every codepoint. But we don't care about + // anything that doesn't fit into the above categories. + return .invalid; +} + +pub fn get(cp: u21) Properties { + const zg_width = ziglyph.display_width.codePointWidth(cp, .half); + return .{ + .width = @intCast(@min(2, @max(0, zg_width))), + .grapheme_boundary_class = .init(cp), + }; +} + +/// Runnable binary to generate the lookup tables and output to stdout. +pub fn main() !void { + var arena_state = std.heap.ArenaAllocator.init(std.heap.page_allocator); + defer arena_state.deinit(); + const alloc = arena_state.allocator(); + + const gen: lut.Generator( + Properties, + struct { + pub fn get(ctx: @This(), cp: u21) !Properties { + _ = ctx; + return props.get(cp); + } + + pub fn eql(ctx: @This(), a: Properties, b: Properties) bool { + _ = ctx; + return a.eql(b); + } + }, + ) = .{}; + + const t = try gen.generate(alloc); + defer alloc.free(t.stage1); + defer alloc.free(t.stage2); + defer alloc.free(t.stage3); + try t.writeZig(std.io.getStdOut().writer()); + + // Uncomment when manually debugging to see our table sizes. + // std.log.warn("stage1={} stage2={} stage3={}", .{ + // t.stage1.len, + // t.stage2.len, + // t.stage3.len, + // }); +} + +// This is not very fast in debug modes, so its commented by default. +// IMPORTANT: UNCOMMENT THIS WHENEVER MAKING CODEPOINTWIDTH CHANGES. +// test "unicode props: tables match ziglyph" { +// const testing = std.testing; +// +// const min = 0xFF + 1; // start outside ascii +// for (min..std.math.maxInt(u21)) |cp| { +// const t = table.get(@intCast(cp)); +// const zg = @min(2, @max(0, ziglyph.display_width.codePointWidth(@intCast(cp), .half))); +// if (t.width != zg) { +// std.log.warn("mismatch cp=U+{x} t={} zg={}", .{ cp, t, zg }); +// try testing.expect(false); +// } +// } +// } From d4bc73a9d66e6ad327b1ec6e6717a2aa8621a335 Mon Sep 17 00:00:00 2001 From: "Jeffrey C. Ollie" Date: Sat, 20 Sep 2025 12:38:08 -0500 Subject: [PATCH 35/77] update to the latest zon2nix --- flake.lock | 18 +++++++++--------- flake.nix | 2 +- nix/build-support/check-zig-cache.sh | 3 +-- 3 files changed, 11 insertions(+), 12 deletions(-) diff --git a/flake.lock b/flake.lock index e4a5d0be8..bbd4567e3 100644 --- a/flake.lock +++ b/flake.lock @@ -49,15 +49,15 @@ }, "nixpkgs_2": { "locked": { - "lastModified": 1755972213, - "narHash": "sha256-VYK7aDAv8H1enXn1ECRHmGbeY6RqLnNwUJkOwloIsko=", - "rev": "73e96df7cff5783f45e21342a75a1540c4eddce4", + "lastModified": 1758360447, + "narHash": "sha256-XDY3A83bclygHDtesRoaRTafUd80Q30D/Daf9KSG6bs=", + "rev": "8eaee110344796db060382e15d3af0a9fc396e0e", "type": "tarball", - "url": "https://releases.nixos.org/nixos/unstable-small/nixos-25.11pre850642.73e96df7cff5/nixexprs.tar.xz" + "url": "https://releases.nixos.org/nixos/unstable/nixos-25.11pre864002.8eaee1103447/nixexprs.tar.xz" }, "original": { "type": "tarball", - "url": "https://channels.nixos.org/nixos-unstable-small/nixexprs.tar.xz" + "url": "https://channels.nixos.org/nixos-unstable/nixexprs.tar.xz" } }, "root": { @@ -115,17 +115,17 @@ "nixpkgs": "nixpkgs_2" }, "locked": { - "lastModified": 1757167408, - "narHash": "sha256-4XyJ6fmKd9wgJ7vHUQuULYy5ps2gUgkkDk/PrJb2OPY=", + "lastModified": 1758405547, + "narHash": "sha256-WgaDgvIZMPvlZcZrpPMjkaalTBnGF2lTG+62znXctWM=", "owner": "jcollie", "repo": "zon2nix", - "rev": "dc78177e2ad28d5a407c9e783ee781bd559d7dd5", + "rev": "bf983aa90ff169372b9fa8c02e57ea75e0b42245", "type": "github" }, "original": { "owner": "jcollie", "repo": "zon2nix", - "rev": "dc78177e2ad28d5a407c9e783ee781bd559d7dd5", + "rev": "bf983aa90ff169372b9fa8c02e57ea75e0b42245", "type": "github" } } diff --git a/flake.nix b/flake.nix index 23b07f734..7d72a9af3 100644 --- a/flake.nix +++ b/flake.nix @@ -24,7 +24,7 @@ }; zon2nix = { - url = "github:jcollie/zon2nix?rev=dc78177e2ad28d5a407c9e783ee781bd559d7dd5"; + url = "github:jcollie/zon2nix?rev=bf983aa90ff169372b9fa8c02e57ea75e0b42245"; inputs = { # Don't override nixpkgs until Zig 0.15 is available in the Nix branch # we are using for "normal" builds. diff --git a/nix/build-support/check-zig-cache.sh b/nix/build-support/check-zig-cache.sh index d6a9fdc30..e92a27b6f 100755 --- a/nix/build-support/check-zig-cache.sh +++ b/nix/build-support/check-zig-cache.sh @@ -79,7 +79,7 @@ elif [ "$1" != "--update" ]; then exit 1 fi -zon2nix "$BUILD_ZIG_ZON" --nix "$WORK_DIR/build.zig.zon.nix" --txt "$WORK_DIR/build.zig.zon.txt" --json "$WORK_DIR/build.zig.zon.json" --flatpak "$WORK_DIR/zig-packages.json" +zon2nix "$BUILD_ZIG_ZON" --14 --nix "$WORK_DIR/build.zig.zon.nix" --txt "$WORK_DIR/build.zig.zon.txt" --json "$WORK_DIR/build.zig.zon.json" --flatpak "$WORK_DIR/zig-packages.json" alejandra --quiet "$WORK_DIR/build.zig.zon.nix" prettier --log-level warn --write "$WORK_DIR/build.zig.zon.json" prettier --log-level warn --write "$WORK_DIR/zig-packages.json" @@ -118,4 +118,3 @@ else echo -e "OK: flatpak/zig-packages.json updated." exit 0 fi - From 6e1eb67d9471e970a8bc81e0f1fff0987020fcfb Mon Sep 17 00:00:00 2001 From: mitchellh <1299+mitchellh@users.noreply.github.com> Date: Sun, 21 Sep 2025 00:15:05 +0000 Subject: [PATCH 36/77] deps: Update iTerm2 color schemes --- build.zig.zon | 4 ++-- build.zig.zon.json | 6 +++--- build.zig.zon.nix | 6 +++--- build.zig.zon.txt | 2 +- flatpak/zig-packages.json | 6 +++--- 5 files changed, 12 insertions(+), 12 deletions(-) diff --git a/build.zig.zon b/build.zig.zon index 0e349cd6d..7f644457d 100644 --- a/build.zig.zon +++ b/build.zig.zon @@ -112,8 +112,8 @@ // Other .apple_sdk = .{ .path = "./pkg/apple-sdk" }, .iterm2_themes = .{ - .url = "https://deps.files.ghostty.org/ghostty-themes-20250915-162204-b1fe546.tgz", - .hash = "N-V-__8AANodAwDnyHwhlOv5cVRn2rx_dTvija-wy5YtTw1B", + .url = "https://github.com/mbadolato/iTerm2-Color-Schemes/releases/download/release-20250916-134637-76894f0/ghostty-themes.tgz", + .hash = "N-V-__8AAGsjAwAxRB3Y9Akv_HeLfvJA-tIqW6ACnBhWosM3", .lazy = true, }, }, diff --git a/build.zig.zon.json b/build.zig.zon.json index c9bc71296..702df5026 100644 --- a/build.zig.zon.json +++ b/build.zig.zon.json @@ -49,10 +49,10 @@ "url": "https://deps.files.ghostty.org/imgui-1220bc6b9daceaf7c8c60f3c3998058045ba0c5c5f48ae255ff97776d9cd8bfc6402.tar.gz", "hash": "sha256-oF/QHgTPEat4Hig4fGIdLkIPHmBEyOJ6JeYD6pnveGA=" }, - "N-V-__8AANodAwDnyHwhlOv5cVRn2rx_dTvija-wy5YtTw1B": { + "N-V-__8AAGsjAwAxRB3Y9Akv_HeLfvJA-tIqW6ACnBhWosM3": { "name": "iterm2_themes", - "url": "https://deps.files.ghostty.org/ghostty-themes-20250915-162204-b1fe546.tgz", - "hash": "sha256-6rKNFpaUvSbvNZ0/+u0h4I/RRaV5V7xIPQ9y7eNVbCA=" + "url": "https://github.com/mbadolato/iTerm2-Color-Schemes/releases/download/release-20250916-134637-76894f0/ghostty-themes.tgz", + "hash": "sha256-JPY9M50d/n6rGzWt0aQZIU7IBMWru2IAqe9Vu1x5CMw=" }, "N-V-__8AAIC5lwAVPJJzxnCAahSvZTIlG-HhtOvnM1uh-66x": { "name": "jetbrains_mono", diff --git a/build.zig.zon.nix b/build.zig.zon.nix index 85fdd67e4..c38b34e4d 100644 --- a/build.zig.zon.nix +++ b/build.zig.zon.nix @@ -163,11 +163,11 @@ in }; } { - name = "N-V-__8AANodAwDnyHwhlOv5cVRn2rx_dTvija-wy5YtTw1B"; + name = "N-V-__8AAGsjAwAxRB3Y9Akv_HeLfvJA-tIqW6ACnBhWosM3"; path = fetchZigArtifact { name = "iterm2_themes"; - url = "https://deps.files.ghostty.org/ghostty-themes-20250915-162204-b1fe546.tgz"; - hash = "sha256-6rKNFpaUvSbvNZ0/+u0h4I/RRaV5V7xIPQ9y7eNVbCA="; + url = "https://github.com/mbadolato/iTerm2-Color-Schemes/releases/download/release-20250916-134637-76894f0/ghostty-themes.tgz"; + hash = "sha256-JPY9M50d/n6rGzWt0aQZIU7IBMWru2IAqe9Vu1x5CMw="; }; } { diff --git a/build.zig.zon.txt b/build.zig.zon.txt index 3974ee9d5..1caa7b000 100644 --- a/build.zig.zon.txt +++ b/build.zig.zon.txt @@ -8,7 +8,6 @@ https://deps.files.ghostty.org/breakpad-b99f444ba5f6b98cac261cbb391d8766b34a5918 https://deps.files.ghostty.org/fontconfig-2.14.2.tar.gz https://deps.files.ghostty.org/freetype-1220b81f6ecfb3fd222f76cf9106fecfa6554ab07ec7fdc4124b9bb063ae2adf969d.tar.gz https://deps.files.ghostty.org/gettext-0.24.tar.gz -https://deps.files.ghostty.org/ghostty-themes-20250915-162204-b1fe546.tgz https://deps.files.ghostty.org/glslang-12201278a1a05c0ce0b6eb6026c65cd3e9247aa041b1c260324bf29cee559dd23ba1.tar.gz https://deps.files.ghostty.org/gtk4-layer-shell-1.1.0.tar.gz https://deps.files.ghostty.org/harfbuzz-11.0.0.tar.xz @@ -29,6 +28,7 @@ https://deps.files.ghostty.org/zig_js-12205a66d423259567764fa0fc60c82be35365c21a https://deps.files.ghostty.org/ziglyph-b89d43d1e3fb01b6074bc1f7fc980324b04d26a5.tar.gz https://deps.files.ghostty.org/zlib-1220fed0c74e1019b3ee29edae2051788b080cd96e90d56836eea857b0b966742efb.tar.gz https://github.com/ghostty-org/zig-gobject/releases/download/2025-09-20-20-1/ghostty-gobject-2025-09-20-20-1.tar.zst +https://github.com/mbadolato/iTerm2-Color-Schemes/releases/download/release-20250916-134637-76894f0/ghostty-themes.tgz https://github.com/mitchellh/libxev/archive/7f803181b158a10fec8619f793e3b4df515566cb.tar.gz https://github.com/mitchellh/zig-objc/archive/c9e917a4e15a983b672ca779c7985d738a2d517c.tar.gz https://github.com/natecraddock/zf/archive/7aacbe6d155d64d15937ca95ca6c014905eb531f.tar.gz diff --git a/flatpak/zig-packages.json b/flatpak/zig-packages.json index d068596e4..46f6c950d 100644 --- a/flatpak/zig-packages.json +++ b/flatpak/zig-packages.json @@ -61,9 +61,9 @@ }, { "type": "archive", - "url": "https://deps.files.ghostty.org/ghostty-themes-20250915-162204-b1fe546.tgz", - "dest": "vendor/p/N-V-__8AANodAwDnyHwhlOv5cVRn2rx_dTvija-wy5YtTw1B", - "sha256": "eab28d169694bd26ef359d3ffaed21e08fd145a57957bc483d0f72ede3556c20" + "url": "https://github.com/mbadolato/iTerm2-Color-Schemes/releases/download/release-20250916-134637-76894f0/ghostty-themes.tgz", + "dest": "vendor/p/N-V-__8AAGsjAwAxRB3Y9Akv_HeLfvJA-tIqW6ACnBhWosM3", + "sha256": "24f63d339d1dfe7eab1b35add1a419214ec804c5abbb6200a9ef55bb5c7908cc" }, { "type": "archive", From 52c2f02fa40f3f96dc2aa124a9e2fe8978bb0a48 Mon Sep 17 00:00:00 2001 From: rhodes-b <59537185+rhodes-b@users.noreply.github.com> Date: Sat, 20 Sep 2025 20:18:28 -0500 Subject: [PATCH 37/77] use focus signal in split_tree to determine if we apply unfocused-split-fill --- src/apprt/gtk/class/split_tree.zig | 15 ++++++++------- src/apprt/gtk/class/surface.zig | 11 +---------- 2 files changed, 9 insertions(+), 17 deletions(-) diff --git a/src/apprt/gtk/class/split_tree.zig b/src/apprt/gtk/class/split_tree.zig index 0fe06a0b1..6ea84d055 100644 --- a/src/apprt/gtk/class/split_tree.zig +++ b/src/apprt/gtk/class/split_tree.zig @@ -399,12 +399,7 @@ pub const SplitTree = extern struct { const tree = self.getTree() orelse return null; var it = tree.iterator(); while (it.next()) |entry| { - if (!entry.view.getFocused() and it.nodes.len > 1) { - entry.view.setUnfocused(); - } - if (entry.view.getFocused()) { - return entry.handle; - } + if (entry.view.getFocused()) return entry.handle; } // If none are currently focused, the most previously focused @@ -715,7 +710,13 @@ pub const SplitTree = extern struct { // We never CLEAR our last_focused because the property is specifically // the last focused surface. We let the weakref clear itself when // the surface is destroyed. - if (!surface.getFocused()) return; + if (!surface.getFocused()) { + // If we have more than 1 active surface and we aren't focused we want to apply unfocused-split-fill + if (self.getTree()) |tree| { + if (tree.nodes.len > 1) surface.setUnfocused(); + } + return; + } self.private().last_focused.set(surface); // Our active surface probably changed diff --git a/src/apprt/gtk/class/surface.zig b/src/apprt/gtk/class/surface.zig index 9906a1baf..eb1e17823 100644 --- a/src/apprt/gtk/class/surface.zig +++ b/src/apprt/gtk/class/surface.zig @@ -1492,6 +1492,7 @@ pub const Surface = extern struct { return self.private().focused; } + /// If unfocused add the unfocused-split widget for this surface pub fn setUnfocused(self: *Self) void { const priv = self.private(); if (!priv.focused and (priv.unfocused_widget == null)) { @@ -2018,16 +2019,6 @@ pub const Surface = extern struct { priv.im_context.as(gtk.IMContext).focusOut(); _ = glib.idleAddOnce(idleFocus, self.ref()); self.as(gobject.Object).notifyByPspec(properties.focused.impl.param_spec); - - // if (priv.unfocused_widget) |_| return; - // add unfocused-split-fill - // priv.unfocused_widget = unfocused_widget: { - // const drawing_area = gtk.DrawingArea.new(); - // const unfocused_widget = drawing_area.as(gtk.Widget); - // unfocused_widget.addCssClass("unfocused-split"); - // priv.terminal_page.addOverlay(unfocused_widget); - // break :unfocused_widget unfocused_widget; - // }; } /// The focus callback must be triggered on an idle loop source because From cfcd11863ee0ea9b225117d96213b7eb41b87801 Mon Sep 17 00:00:00 2001 From: rhodes-b <59537185+rhodes-b@users.noreply.github.com> Date: Sat, 20 Sep 2025 20:24:51 -0500 Subject: [PATCH 38/77] rename setUnfocused to setUnfocusedFill --- src/apprt/gtk/class/split_tree.zig | 2 +- src/apprt/gtk/class/surface.zig | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/apprt/gtk/class/split_tree.zig b/src/apprt/gtk/class/split_tree.zig index 6ea84d055..825aebeb3 100644 --- a/src/apprt/gtk/class/split_tree.zig +++ b/src/apprt/gtk/class/split_tree.zig @@ -713,7 +713,7 @@ pub const SplitTree = extern struct { if (!surface.getFocused()) { // If we have more than 1 active surface and we aren't focused we want to apply unfocused-split-fill if (self.getTree()) |tree| { - if (tree.nodes.len > 1) surface.setUnfocused(); + if (tree.nodes.len > 1) surface.setUnfocusedFill(); } return; } diff --git a/src/apprt/gtk/class/surface.zig b/src/apprt/gtk/class/surface.zig index eb1e17823..7e1ea057f 100644 --- a/src/apprt/gtk/class/surface.zig +++ b/src/apprt/gtk/class/surface.zig @@ -1493,7 +1493,7 @@ pub const Surface = extern struct { } /// If unfocused add the unfocused-split widget for this surface - pub fn setUnfocused(self: *Self) void { + pub fn setUnfocusedFill(self: *Self) void { const priv = self.private(); if (!priv.focused and (priv.unfocused_widget == null)) { priv.unfocused_widget = unfocused_widget: { From fa5a44e591a9bac62aafed64d988912f189e23f5 Mon Sep 17 00:00:00 2001 From: rhodes-b <59537185+rhodes-b@users.noreply.github.com> Date: Sat, 20 Sep 2025 21:37:59 -0500 Subject: [PATCH 39/77] apply unfocused-split with surface blueprint --- src/apprt/gtk/class/split_tree.zig | 2 +- src/apprt/gtk/class/surface.zig | 52 +++++++++++++++++++++--------- src/apprt/gtk/ui/1.2/surface.blp | 13 ++++++++ 3 files changed, 51 insertions(+), 16 deletions(-) diff --git a/src/apprt/gtk/class/split_tree.zig b/src/apprt/gtk/class/split_tree.zig index 825aebeb3..012db91f2 100644 --- a/src/apprt/gtk/class/split_tree.zig +++ b/src/apprt/gtk/class/split_tree.zig @@ -713,7 +713,7 @@ pub const SplitTree = extern struct { if (!surface.getFocused()) { // If we have more than 1 active surface and we aren't focused we want to apply unfocused-split-fill if (self.getTree()) |tree| { - if (tree.nodes.len > 1) surface.setUnfocusedFill(); + if (tree.nodes.len > 1) surface.setUnfocusedSplit(); } return; } diff --git a/src/apprt/gtk/class/surface.zig b/src/apprt/gtk/class/surface.zig index 7e1ea057f..9253e3981 100644 --- a/src/apprt/gtk/class/surface.zig +++ b/src/apprt/gtk/class/surface.zig @@ -153,6 +153,24 @@ pub const Surface = extern struct { ); }; + pub const @"unfocused-split" = struct { + pub const name = "unfocused-split"; + const impl = gobject.ext.defineProperty( + name, + Self, + bool, + .{ + .default = true, + .accessor = gobject.ext.privateFieldAccessor( + Self, + Private, + &Private.offset, + "unfocused_split", + ), + }, + ); + }; + pub const @"min-size" = struct { pub const name = "min-size"; const impl = gobject.ext.defineProperty( @@ -435,7 +453,7 @@ pub const Surface = extern struct { /// The current focus state of the terminal based on the /// focus events. focused: bool = true, - unfocused_widget: ?*gtk.Widget = null, + unfocused_split: bool = false, /// Whether this surface is "zoomed" or not. A zoomed surface /// shows up taking the full bounds of a split view. @@ -601,6 +619,15 @@ pub const Surface = extern struct { return @intFromBool(config.@"bell-features".border); } + /// Callback used to determine whether unfocused-split-fill / unfocused-split-opacity + /// should be applied to the surface + fn closureShouldUnfocusedSplitBeShown( + _: *Self, + unfocused_split_: c_int, + ) callconv(.c) c_int { + return @intFromBool(unfocused_split_ != 0); + } + pub fn toggleFullscreen(self: *Self) void { signals.@"toggle-fullscreen".impl.emit( self, @@ -1305,6 +1332,7 @@ pub const Surface = extern struct { priv.mouse_shape = .text; priv.mouse_hidden = false; priv.focused = true; + priv.unfocused_split = false; priv.size = .{ .width = 0, .height = 0 }; // If our configuration is null then we get the configuration @@ -1493,17 +1521,10 @@ pub const Surface = extern struct { } /// If unfocused add the unfocused-split widget for this surface - pub fn setUnfocusedFill(self: *Self) void { + pub fn setUnfocusedSplit(self: *Self) void { const priv = self.private(); - if (!priv.focused and (priv.unfocused_widget == null)) { - priv.unfocused_widget = unfocused_widget: { - const drawing_area = gtk.DrawingArea.new(); - const unfocused_widget = drawing_area.as(gtk.Widget); - unfocused_widget.addCssClass("unfocused-split"); - priv.terminal_page.addOverlay(unfocused_widget); - break :unfocused_widget unfocused_widget; - }; - } + priv.unfocused_split = !priv.focused; + self.as(gobject.Object).notifyByPspec(properties.@"unfocused-split".impl.param_spec); } /// Change the configuration for this surface. @@ -2004,10 +2025,9 @@ pub const Surface = extern struct { _ = glib.idleAddOnce(idleFocus, self.ref()); self.as(gobject.Object).notifyByPspec(properties.focused.impl.param_spec); - if (priv.unfocused_widget) |widget| { - priv.terminal_page.removeOverlay(widget); - priv.unfocused_widget = null; - } + // remove unfocused split fill and opacity + priv.unfocused_split = false; + self.as(gobject.Object).notifyByPspec(properties.@"unfocused-split".impl.param_spec); // Bell stops ringing as soon as we gain focus self.setBellRinging(false); @@ -2783,6 +2803,7 @@ pub const Surface = extern struct { class.bindTemplateCallback("notify_mouse_shape", &propMouseShape); class.bindTemplateCallback("notify_bell_ringing", &propBellRinging); class.bindTemplateCallback("should_border_be_shown", &closureShouldBorderBeShown); + class.bindTemplateCallback("should_unfocused_split_be_shown", &closureShouldUnfocusedSplitBeShown); // Properties gobject.ext.registerProperties(class, &.{ @@ -2793,6 +2814,7 @@ pub const Surface = extern struct { properties.@"error".impl, properties.@"font-size-request".impl, properties.focused.impl, + properties.@"unfocused-split".impl, properties.@"min-size".impl, properties.@"mouse-shape".impl, properties.@"mouse-hidden".impl, diff --git a/src/apprt/gtk/ui/1.2/surface.blp b/src/apprt/gtk/ui/1.2/surface.blp index f22f2c09a..ba17393b5 100644 --- a/src/apprt/gtk/ui/1.2/surface.blp +++ b/src/apprt/gtk/ui/1.2/surface.blp @@ -115,6 +115,19 @@ Overlay terminal_page { label: bind template.mouse-hover-url; } + [overlay] + // Apply unfocused-split-fill and unfocused-split opacity to current surface + // this is only applied when a tab has more than one surface + Revealer { + reveal-child: bind $should_unfocused_split_be_shown(template.unfocused-split) as ; + transition-duration: 0; + DrawingArea { + styles [ + "unfocused-split", + ] + } + } + // Event controllers for interactivity EventControllerFocus { enter => $focus_enter(); From 180cc31d874c27c6ce20b68ee500ef42ca4d3897 Mon Sep 17 00:00:00 2001 From: rhodes-b <59537185+rhodes-b@users.noreply.github.com> Date: Sat, 20 Sep 2025 21:41:15 -0500 Subject: [PATCH 40/77] fix comments to specific the config option --- src/apprt/gtk/class/surface.zig | 6 +++--- src/apprt/gtk/ui/1.2/surface.blp | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/apprt/gtk/class/surface.zig b/src/apprt/gtk/class/surface.zig index 9253e3981..dc6637655 100644 --- a/src/apprt/gtk/class/surface.zig +++ b/src/apprt/gtk/class/surface.zig @@ -623,9 +623,9 @@ pub const Surface = extern struct { /// should be applied to the surface fn closureShouldUnfocusedSplitBeShown( _: *Self, - unfocused_split_: c_int, + unfocused_split: c_int, ) callconv(.c) c_int { - return @intFromBool(unfocused_split_ != 0); + return @intFromBool(unfocused_split != 0); } pub fn toggleFullscreen(self: *Self) void { @@ -2025,7 +2025,7 @@ pub const Surface = extern struct { _ = glib.idleAddOnce(idleFocus, self.ref()); self.as(gobject.Object).notifyByPspec(properties.focused.impl.param_spec); - // remove unfocused split fill and opacity + // remove unfocused-split-fill and unfocused-split-opacity priv.unfocused_split = false; self.as(gobject.Object).notifyByPspec(properties.@"unfocused-split".impl.param_spec); diff --git a/src/apprt/gtk/ui/1.2/surface.blp b/src/apprt/gtk/ui/1.2/surface.blp index ba17393b5..ba1556a61 100644 --- a/src/apprt/gtk/ui/1.2/surface.blp +++ b/src/apprt/gtk/ui/1.2/surface.blp @@ -116,7 +116,7 @@ Overlay terminal_page { } [overlay] - // Apply unfocused-split-fill and unfocused-split opacity to current surface + // Apply unfocused-split-fill and unfocused-split-opacity to current surface // this is only applied when a tab has more than one surface Revealer { reveal-child: bind $should_unfocused_split_be_shown(template.unfocused-split) as ; From 42fc42de2d2ff108d4aa3ff309b246c1f3fc23b0 Mon Sep 17 00:00:00 2001 From: rhodes-b <59537185+rhodes-b@users.noreply.github.com> Date: Sat, 20 Sep 2025 21:45:01 -0500 Subject: [PATCH 41/77] fix surface blueprint formatting --- src/apprt/gtk/ui/1.2/surface.blp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/apprt/gtk/ui/1.2/surface.blp b/src/apprt/gtk/ui/1.2/surface.blp index ba1556a61..0b9a77133 100644 --- a/src/apprt/gtk/ui/1.2/surface.blp +++ b/src/apprt/gtk/ui/1.2/surface.blp @@ -121,6 +121,7 @@ Overlay terminal_page { Revealer { reveal-child: bind $should_unfocused_split_be_shown(template.unfocused-split) as ; transition-duration: 0; + DrawingArea { styles [ "unfocused-split", From 10dc9353b7b5d85179ef7b1305fe9d5a73ff392d Mon Sep 17 00:00:00 2001 From: Mitchell Hashimoto Date: Sat, 20 Sep 2025 19:49:29 -0700 Subject: [PATCH 42/77] unicode: delete props.zig and clean up symbols deps too Follow up to #8810 Same reasoning. --- src/benchmark/IsSymbol.zig | 5 +- src/build/UnicodeTables.zig | 4 +- src/main_ghostty.zig | 2 + src/renderer/cell.zig | 2 +- src/unicode/grapheme.zig | 5 +- src/unicode/main.zig | 2 - src/unicode/props.zig | 181 ------------------ src/unicode/props_ziglyph.zig | 2 +- src/unicode/symbols_table.zig | 17 ++ .../{symbols.zig => symbols_ziglyph.zig} | 14 +- 10 files changed, 29 insertions(+), 205 deletions(-) delete mode 100644 src/unicode/props.zig create mode 100644 src/unicode/symbols_table.zig rename src/unicode/{symbols.zig => symbols_ziglyph.zig} (85%) diff --git a/src/benchmark/IsSymbol.zig b/src/benchmark/IsSymbol.zig index 5b2ffd425..ce635626a 100644 --- a/src/benchmark/IsSymbol.zig +++ b/src/benchmark/IsSymbol.zig @@ -10,7 +10,8 @@ const Allocator = std.mem.Allocator; const Benchmark = @import("Benchmark.zig"); const options = @import("options.zig"); const UTF8Decoder = @import("../terminal/UTF8Decoder.zig"); -const symbols = @import("../unicode/symbols.zig"); +const symbols = @import("../unicode/symbols_ziglyph.zig"); +const symbols_table = @import("../unicode/symbols_table.zig").table; const log = std.log.scoped(.@"is-symbol-bench"); @@ -127,7 +128,7 @@ fn stepTable(ptr: *anyopaque) Benchmark.Error!void { const cp_, const consumed = d.next(c); assert(consumed); if (cp_) |cp| { - std.mem.doNotOptimizeAway(symbols.table.get(cp)); + std.mem.doNotOptimizeAway(symbols_table.get(cp)); } } } diff --git a/src/build/UnicodeTables.zig b/src/build/UnicodeTables.zig index 7c1229f7f..6733b5315 100644 --- a/src/build/UnicodeTables.zig +++ b/src/build/UnicodeTables.zig @@ -15,7 +15,7 @@ pub fn init(b: *std.Build) !UnicodeTables { const props_exe = b.addExecutable(.{ .name = "props-unigen", .root_module = b.createModule(.{ - .root_source_file = b.path("src/unicode/props.zig"), + .root_source_file = b.path("src/unicode/props_ziglyph.zig"), .target = b.graph.host, .strip = false, .omit_frame_pointer = false, @@ -26,7 +26,7 @@ pub fn init(b: *std.Build) !UnicodeTables { const symbols_exe = b.addExecutable(.{ .name = "symbols-unigen", .root_module = b.createModule(.{ - .root_source_file = b.path("src/unicode/symbols.zig"), + .root_source_file = b.path("src/unicode/symbols_ziglyph.zig"), .target = b.graph.host, .strip = false, .omit_frame_pointer = false, diff --git a/src/main_ghostty.zig b/src/main_ghostty.zig index aca33a510..555dd16bf 100644 --- a/src/main_ghostty.zig +++ b/src/main_ghostty.zig @@ -191,6 +191,8 @@ test { _ = @import("simd/main.zig"); _ = @import("synthetic/main.zig"); _ = @import("unicode/main.zig"); + _ = @import("unicode/props_ziglyph.zig"); + _ = @import("unicode/symbols_ziglyph.zig"); // Extra _ = @import("extra/bash.zig"); diff --git a/src/renderer/cell.zig b/src/renderer/cell.zig index 6ada849ed..3cf306f91 100644 --- a/src/renderer/cell.zig +++ b/src/renderer/cell.zig @@ -6,7 +6,7 @@ const terminal = @import("../terminal/main.zig"); const renderer = @import("../renderer.zig"); const shaderpkg = renderer.Renderer.API.shaders; const ArrayListCollection = @import("../datastruct/array_list_collection.zig").ArrayListCollection; -const symbols = @import("../unicode/symbols.zig").table; +const symbols = @import("../unicode/symbols_table.zig").table; /// The possible cell content keys that exist. pub const Key = enum { diff --git a/src/unicode/grapheme.zig b/src/unicode/grapheme.zig index 7847ef6f5..bfc09b854 100644 --- a/src/unicode/grapheme.zig +++ b/src/unicode/grapheme.zig @@ -1,7 +1,6 @@ const std = @import("std"); -const props = @import("props.zig"); -const GraphemeBoundaryClass = props.GraphemeBoundaryClass; -const table = props.table; +const table = @import("props_table.zig").table; +const GraphemeBoundaryClass = @import("Properties.zig").GraphemeBoundaryClass; /// Determines if there is a grapheme break between two codepoints. This /// must be called sequentially maintaining the state between calls. diff --git a/src/unicode/main.zig b/src/unicode/main.zig index ae50075ff..cb2fb567f 100644 --- a/src/unicode/main.zig +++ b/src/unicode/main.zig @@ -7,7 +7,5 @@ pub const graphemeBreak = grapheme.graphemeBreak; pub const GraphemeBreakState = grapheme.BreakState; test { - _ = @import("props_ziglyph.zig"); - _ = @import("symbols.zig"); @import("std").testing.refAllDecls(@This()); } diff --git a/src/unicode/props.zig b/src/unicode/props.zig deleted file mode 100644 index 7edb3761c..000000000 --- a/src/unicode/props.zig +++ /dev/null @@ -1,181 +0,0 @@ -const props = @This(); -const std = @import("std"); -const assert = std.debug.assert; -const ziglyph = @import("ziglyph"); -const lut = @import("lut.zig"); - -/// The lookup tables for Ghostty. -pub const table = table: { - // This is only available after running main() below as part of the Ghostty - // build.zig, but due to Zig's lazy analysis we can still reference it here. - const generated = @import("unicode_tables").Tables(Properties); - const Tables = lut.Tables(Properties); - break :table Tables{ - .stage1 = &generated.stage1, - .stage2 = &generated.stage2, - .stage3 = &generated.stage3, - }; -}; - -/// Property set per codepoint that Ghostty cares about. -/// -/// Adding to this lets you find new properties but also potentially makes -/// our lookup tables less efficient. Any changes to this should run the -/// benchmarks in src/bench to verify that we haven't regressed. -pub const Properties = struct { - /// Codepoint width. We clamp to [0, 2] since Ghostty handles control - /// characters and we max out at 2 for wide characters (i.e. 3-em dash - /// becomes a 2-em dash). - width: u2 = 0, - - /// Grapheme boundary class. - grapheme_boundary_class: GraphemeBoundaryClass = .invalid, - - // Needed for lut.Generator - pub fn eql(a: Properties, b: Properties) bool { - return a.width == b.width and - a.grapheme_boundary_class == b.grapheme_boundary_class; - } - - // Needed for lut.Generator - pub fn format( - self: Properties, - comptime layout: []const u8, - opts: std.fmt.FormatOptions, - writer: anytype, - ) !void { - _ = layout; - _ = opts; - try std.fmt.format(writer, - \\.{{ - \\ .width= {}, - \\ .grapheme_boundary_class= .{s}, - \\}} - , .{ - self.width, - @tagName(self.grapheme_boundary_class), - }); - } -}; - -/// Possible grapheme boundary classes. This isn't an exhaustive list: -/// we omit control, CR, LF, etc. because in Ghostty's usage that are -/// impossible because they're handled by the terminal. -pub const GraphemeBoundaryClass = enum(u4) { - invalid, - L, - V, - T, - LV, - LVT, - prepend, - extend, - zwj, - spacing_mark, - regional_indicator, - extended_pictographic, - extended_pictographic_base, // \p{Extended_Pictographic} & \p{Emoji_Modifier_Base} - emoji_modifier, // \p{Emoji_Modifier} - - /// Gets the grapheme boundary class for a codepoint. This is VERY - /// SLOW. The use case for this is only in generating lookup tables. - pub fn init(cp: u21) GraphemeBoundaryClass { - // We special-case modifier bases because we should not break - // if a modifier isn't next to a base. - if (ziglyph.emoji.isEmojiModifierBase(cp)) { - assert(ziglyph.emoji.isExtendedPictographic(cp)); - return .extended_pictographic_base; - } - - if (ziglyph.emoji.isEmojiModifier(cp)) return .emoji_modifier; - if (ziglyph.emoji.isExtendedPictographic(cp)) return .extended_pictographic; - if (ziglyph.grapheme_break.isL(cp)) return .L; - if (ziglyph.grapheme_break.isV(cp)) return .V; - if (ziglyph.grapheme_break.isT(cp)) return .T; - if (ziglyph.grapheme_break.isLv(cp)) return .LV; - if (ziglyph.grapheme_break.isLvt(cp)) return .LVT; - if (ziglyph.grapheme_break.isPrepend(cp)) return .prepend; - if (ziglyph.grapheme_break.isExtend(cp)) return .extend; - if (ziglyph.grapheme_break.isZwj(cp)) return .zwj; - if (ziglyph.grapheme_break.isSpacingmark(cp)) return .spacing_mark; - if (ziglyph.grapheme_break.isRegionalIndicator(cp)) return .regional_indicator; - - // This is obviously not INVALID invalid, there is SOME grapheme - // boundary class for every codepoint. But we don't care about - // anything that doesn't fit into the above categories. - return .invalid; - } - - /// Returns true if this is an extended pictographic type. This - /// should be used instead of comparing the enum value directly - /// because we classify multiple. - pub fn isExtendedPictographic(self: GraphemeBoundaryClass) bool { - return switch (self) { - .extended_pictographic, - .extended_pictographic_base, - => true, - - else => false, - }; - } -}; - -pub fn get(cp: u21) Properties { - const zg_width = ziglyph.display_width.codePointWidth(cp, .half); - - return .{ - .width = @intCast(@min(2, @max(0, zg_width))), - .grapheme_boundary_class = .init(cp), - }; -} - -/// Runnable binary to generate the lookup tables and output to stdout. -pub fn main() !void { - var arena_state = std.heap.ArenaAllocator.init(std.heap.page_allocator); - defer arena_state.deinit(); - const alloc = arena_state.allocator(); - - const gen: lut.Generator( - Properties, - struct { - pub fn get(ctx: @This(), cp: u21) !Properties { - _ = ctx; - return props.get(cp); - } - - pub fn eql(ctx: @This(), a: Properties, b: Properties) bool { - _ = ctx; - return a.eql(b); - } - }, - ) = .{}; - - const t = try gen.generate(alloc); - defer alloc.free(t.stage1); - defer alloc.free(t.stage2); - defer alloc.free(t.stage3); - try t.writeZig(std.io.getStdOut().writer()); - - // Uncomment when manually debugging to see our table sizes. - // std.log.warn("stage1={} stage2={} stage3={}", .{ - // t.stage1.len, - // t.stage2.len, - // t.stage3.len, - // }); -} - -// This is not very fast in debug modes, so its commented by default. -// IMPORTANT: UNCOMMENT THIS WHENEVER MAKING CODEPOINTWIDTH CHANGES. -// test "unicode props: tables match ziglyph" { -// const testing = std.testing; -// -// const min = 0xFF + 1; // start outside ascii -// for (min..std.math.maxInt(u21)) |cp| { -// const t = table.get(@intCast(cp)); -// const zg = @min(2, @max(0, ziglyph.display_width.codePointWidth(@intCast(cp), .half))); -// if (t.width != zg) { -// std.log.warn("mismatch cp=U+{x} t={} zg={}", .{ cp, t, zg }); -// try testing.expect(false); -// } -// } -// } diff --git a/src/unicode/props_ziglyph.zig b/src/unicode/props_ziglyph.zig index fd123f3b5..9af60e337 100644 --- a/src/unicode/props_ziglyph.zig +++ b/src/unicode/props_ziglyph.zig @@ -40,7 +40,7 @@ pub fn get(cp: u21) Properties { const zg_width = ziglyph.display_width.codePointWidth(cp, .half); return .{ .width = @intCast(@min(2, @max(0, zg_width))), - .grapheme_boundary_class = .init(cp), + .grapheme_boundary_class = graphemeBoundaryClass(cp), }; } diff --git a/src/unicode/symbols_table.zig b/src/unicode/symbols_table.zig new file mode 100644 index 000000000..28263b9be --- /dev/null +++ b/src/unicode/symbols_table.zig @@ -0,0 +1,17 @@ +const lut = @import("lut.zig"); + +/// The lookup tables for Ghostty. +pub const table = table: { + // This is only available after running a generator as part of the Ghostty + // build.zig process, but due to Zig's lazy analysis we can still reference + // it here. + // + // An example process is the `main` in `symbols_ziglyph.zig` + const generated = @import("symbols_tables").Tables(bool); + const Tables = lut.Tables(bool); + break :table Tables{ + .stage1 = &generated.stage1, + .stage2 = &generated.stage2, + .stage3 = &generated.stage3, + }; +}; diff --git a/src/unicode/symbols.zig b/src/unicode/symbols_ziglyph.zig similarity index 85% rename from src/unicode/symbols.zig rename to src/unicode/symbols_ziglyph.zig index 3c2a84e76..0b01e5398 100644 --- a/src/unicode/symbols.zig +++ b/src/unicode/symbols_ziglyph.zig @@ -4,19 +4,6 @@ const assert = std.debug.assert; const ziglyph = @import("ziglyph"); const lut = @import("lut.zig"); -/// The lookup tables for Ghostty. -pub const table = table: { - // This is only available after running main() below as part of the Ghostty - // build.zig, but due to Zig's lazy analysis we can still reference it here. - const generated = @import("symbols_tables").Tables(bool); - const Tables = lut.Tables(bool); - break :table Tables{ - .stage1 = &generated.stage1, - .stage2 = &generated.stage2, - .stage3 = &generated.stage3, - }; -}; - /// Returns true of the codepoint is a "symbol-like" character, which /// for now we define as anything in a private use area and anything /// in several unicode blocks: @@ -82,6 +69,7 @@ test "unicode symbols: tables match ziglyph" { if (std.valgrind.runningOnValgrind() > 0) return error.SkipZigTest; const testing = std.testing; + const table = @import("symbols_table.zig").table; for (0..std.math.maxInt(u21)) |cp| { const t = table.get(@intCast(cp)); From 3d3551d1edf0dee6ca4d0ec4f1956e025fdcb74a Mon Sep 17 00:00:00 2001 From: rhodes-b <59537185+rhodes-b@users.noreply.github.com> Date: Sat, 20 Sep 2025 22:45:17 -0500 Subject: [PATCH 43/77] add n_siblings member, and when splits are created / removed update the number of siblings for the remaining nodes --- src/apprt/gtk/class/split_tree.zig | 8 +--- src/apprt/gtk/class/surface.zig | 61 +++++++++++++++--------------- src/apprt/gtk/ui/1.2/surface.blp | 2 +- src/datastruct/split_tree.zig | 16 +++++++- 4 files changed, 47 insertions(+), 40 deletions(-) diff --git a/src/apprt/gtk/class/split_tree.zig b/src/apprt/gtk/class/split_tree.zig index 012db91f2..3b6dcb4a9 100644 --- a/src/apprt/gtk/class/split_tree.zig +++ b/src/apprt/gtk/class/split_tree.zig @@ -710,13 +710,7 @@ pub const SplitTree = extern struct { // We never CLEAR our last_focused because the property is specifically // the last focused surface. We let the weakref clear itself when // the surface is destroyed. - if (!surface.getFocused()) { - // If we have more than 1 active surface and we aren't focused we want to apply unfocused-split-fill - if (self.getTree()) |tree| { - if (tree.nodes.len > 1) surface.setUnfocusedSplit(); - } - return; - } + if (!surface.getFocused()) return; self.private().last_focused.set(surface); // Our active surface probably changed diff --git a/src/apprt/gtk/class/surface.zig b/src/apprt/gtk/class/surface.zig index dc6637655..165195469 100644 --- a/src/apprt/gtk/class/surface.zig +++ b/src/apprt/gtk/class/surface.zig @@ -153,24 +153,6 @@ pub const Surface = extern struct { ); }; - pub const @"unfocused-split" = struct { - pub const name = "unfocused-split"; - const impl = gobject.ext.defineProperty( - name, - Self, - bool, - .{ - .default = true, - .accessor = gobject.ext.privateFieldAccessor( - Self, - Private, - &Private.offset, - "unfocused_split", - ), - }, - ); - }; - pub const @"min-size" = struct { pub const name = "min-size"; const impl = gobject.ext.defineProperty( @@ -292,6 +274,26 @@ pub const Surface = extern struct { }, ); }; + + pub const @"n-siblings" = struct { + pub const name = "n-siblings"; + const impl = gobject.ext.defineProperty( + name, + Self, + u64, + .{ + .default = 0, + .minimum = 0, + .maximum = std.math.maxInt(c_uint), + .accessor = gobject.ext.privateFieldAccessor( + Self, + Private, + &Private.offset, + "n_siblings", + ), + }, + ); + }; }; pub const signals = struct { @@ -453,7 +455,6 @@ pub const Surface = extern struct { /// The current focus state of the terminal based on the /// focus events. focused: bool = true, - unfocused_split: bool = false, /// Whether this surface is "zoomed" or not. A zoomed surface /// shows up taking the full bounds of a split view. @@ -521,6 +522,8 @@ pub const Surface = extern struct { /// A weak reference to an inspector window. inspector: ?*InspectorWindow = null, + n_siblings: u64 = 0, + // Template binds child_exited_overlay: *ChildExited, context_menu: *gtk.PopoverMenu, @@ -623,9 +626,10 @@ pub const Surface = extern struct { /// should be applied to the surface fn closureShouldUnfocusedSplitBeShown( _: *Self, - unfocused_split: c_int, + focused: c_int, + n_siblings: c_int, ) callconv(.c) c_int { - return @intFromBool(unfocused_split != 0); + return @intFromBool(focused == 0 and n_siblings > 0); } pub fn toggleFullscreen(self: *Self) void { @@ -1332,7 +1336,6 @@ pub const Surface = extern struct { priv.mouse_shape = .text; priv.mouse_hidden = false; priv.focused = true; - priv.unfocused_split = false; priv.size = .{ .width = 0, .height = 0 }; // If our configuration is null then we get the configuration @@ -1520,11 +1523,11 @@ pub const Surface = extern struct { return self.private().focused; } - /// If unfocused add the unfocused-split widget for this surface - pub fn setUnfocusedSplit(self: *Self) void { + /// Set number of siblings related to this surface. + pub fn setNSiblings(self: *Self, siblings: u64) void { const priv = self.private(); - priv.unfocused_split = !priv.focused; - self.as(gobject.Object).notifyByPspec(properties.@"unfocused-split".impl.param_spec); + priv.n_siblings = siblings; + self.as(gobject.Object).notifyByPspec(properties.@"n-siblings".impl.param_spec); } /// Change the configuration for this surface. @@ -2025,10 +2028,6 @@ pub const Surface = extern struct { _ = glib.idleAddOnce(idleFocus, self.ref()); self.as(gobject.Object).notifyByPspec(properties.focused.impl.param_spec); - // remove unfocused-split-fill and unfocused-split-opacity - priv.unfocused_split = false; - self.as(gobject.Object).notifyByPspec(properties.@"unfocused-split".impl.param_spec); - // Bell stops ringing as soon as we gain focus self.setBellRinging(false); } @@ -2814,7 +2813,6 @@ pub const Surface = extern struct { properties.@"error".impl, properties.@"font-size-request".impl, properties.focused.impl, - properties.@"unfocused-split".impl, properties.@"min-size".impl, properties.@"mouse-shape".impl, properties.@"mouse-hidden".impl, @@ -2823,6 +2821,7 @@ pub const Surface = extern struct { properties.title.impl, properties.@"title-override".impl, properties.zoom.impl, + properties.@"n-siblings".impl, }); // Signals diff --git a/src/apprt/gtk/ui/1.2/surface.blp b/src/apprt/gtk/ui/1.2/surface.blp index 0b9a77133..35d897525 100644 --- a/src/apprt/gtk/ui/1.2/surface.blp +++ b/src/apprt/gtk/ui/1.2/surface.blp @@ -119,7 +119,7 @@ Overlay terminal_page { // Apply unfocused-split-fill and unfocused-split-opacity to current surface // this is only applied when a tab has more than one surface Revealer { - reveal-child: bind $should_unfocused_split_be_shown(template.unfocused-split) as ; + reveal-child: bind $should_unfocused_split_be_shown(template.focused, template.n-siblings) as ; transition-duration: 0; DrawingArea { diff --git a/src/datastruct/split_tree.zig b/src/datastruct/split_tree.zig index 28b45ceed..212711e3d 100644 --- a/src/datastruct/split_tree.zig +++ b/src/datastruct/split_tree.zig @@ -507,12 +507,16 @@ pub fn SplitTree(comptime V: type) type { // We need to increase the reference count of all the nodes. try refNodes(gpa, nodes); - return .{ + const result: Self = .{ .arena = arena, .nodes = nodes, // Splitting always resets zoom state. .zoomed = null, }; + + result.updateNodesNumberSiblings(); + + return result; } /// Remove a node from the tree. @@ -556,6 +560,8 @@ pub fn SplitTree(comptime V: type) type { // Increase the reference count of all the nodes. try refNodes(gpa, nodes); + result.updateNodesNumberSiblings(); + return result; } @@ -865,6 +871,14 @@ pub fn SplitTree(comptime V: type) type { }; } + /// Set the number of siblings for each split in the tree + fn updateNodesNumberSiblings(self: *const Self) void { + var it = self.iterator(); + while (it.next()) |entry| { + entry.view.setNSiblings(self.nodes.len - 1); + } + } + /// Spatial representation of the split tree. See spatial. pub const Spatial = struct { /// The slots of the spatial representation in the same order From 1c59ed5d605b8cd9ddcccdd7d54a3fb2fdcc9ea7 Mon Sep 17 00:00:00 2001 From: rhodes-b <59537185+rhodes-b@users.noreply.github.com> Date: Sat, 20 Sep 2025 22:47:50 -0500 Subject: [PATCH 44/77] comment for the n_siblings surface member --- src/apprt/gtk/class/surface.zig | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/apprt/gtk/class/surface.zig b/src/apprt/gtk/class/surface.zig index 165195469..527a6136b 100644 --- a/src/apprt/gtk/class/surface.zig +++ b/src/apprt/gtk/class/surface.zig @@ -522,6 +522,9 @@ pub const Surface = extern struct { /// A weak reference to an inspector window. inspector: ?*InspectorWindow = null, + /// Number of siblings related to this surface. This is used for + /// the unfocused-split-* options which are only applied when ther is + /// more than once surface (split) in a tab n_siblings: u64 = 0, // Template binds From 3254bb41d5437196e69fba70a00f4538ff2e5b59 Mon Sep 17 00:00:00 2001 From: rhodes-b <59537185+rhodes-b@users.noreply.github.com> Date: Sat, 20 Sep 2025 22:49:35 -0500 Subject: [PATCH 45/77] fix typo --- src/apprt/gtk/class/surface.zig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/apprt/gtk/class/surface.zig b/src/apprt/gtk/class/surface.zig index 527a6136b..087f2d286 100644 --- a/src/apprt/gtk/class/surface.zig +++ b/src/apprt/gtk/class/surface.zig @@ -523,7 +523,7 @@ pub const Surface = extern struct { inspector: ?*InspectorWindow = null, /// Number of siblings related to this surface. This is used for - /// the unfocused-split-* options which are only applied when ther is + /// the unfocused-split-* options which are only applied when their is /// more than once surface (split) in a tab n_siblings: u64 = 0, From cf0557a093cd235be9f56f7ec63e5a902d5137de Mon Sep 17 00:00:00 2001 From: Leorize Date: Sun, 21 Sep 2025 02:03:12 -0500 Subject: [PATCH 46/77] gtk: restore flatpak-aware resource directory support This was not ported to gtk-ng before old runtime was removed, breaking shell integration on Flatpak. --- src/apprt/gtk.zig | 2 +- src/apprt/gtk/flatpak.zig | 29 +++++++++++++++++++++++++++++ 2 files changed, 30 insertions(+), 1 deletion(-) create mode 100644 src/apprt/gtk/flatpak.zig diff --git a/src/apprt/gtk.zig b/src/apprt/gtk.zig index 212892094..aa2404566 100644 --- a/src/apprt/gtk.zig +++ b/src/apprt/gtk.zig @@ -3,7 +3,7 @@ const internal_os = @import("../os/main.zig"); // The required comptime API for any apprt. pub const App = @import("gtk/App.zig"); pub const Surface = @import("gtk/Surface.zig"); -pub const resourcesDir = internal_os.resourcesDir; +pub const resourcesDir = @import("gtk/flatpak.zig").resourcesDir; // The exported API, custom for the apprt. pub const class = @import("gtk/class.zig"); diff --git a/src/apprt/gtk/flatpak.zig b/src/apprt/gtk/flatpak.zig new file mode 100644 index 000000000..dc47c671b --- /dev/null +++ b/src/apprt/gtk/flatpak.zig @@ -0,0 +1,29 @@ +const std = @import("std"); +const Allocator = std.mem.Allocator; +const build_config = @import("../../build_config.zig"); +const internal_os = @import("../../os/main.zig"); +const glib = @import("glib"); + +pub fn resourcesDir(alloc: Allocator) !internal_os.ResourcesDir { + if (comptime build_config.flatpak) { + // Only consult Flatpak runtime data for host case. + if (internal_os.isFlatpak()) { + var result: internal_os.ResourcesDir = .{ + .app_path = try alloc.dupe(u8, "/app/share/ghostty"), + }; + errdefer alloc.free(result.app_path.?); + + const keyfile = glib.KeyFile.new(); + defer keyfile.unref(); + + if (keyfile.loadFromFile("/.flatpak-info", .{}, null) == 0) return result; + const app_dir = std.mem.span(keyfile.getString("Instance", "app-path", null)) orelse return result; + defer glib.free(app_dir.ptr); + + result.host_path = try std.fs.path.join(alloc, &[_][]const u8{ app_dir, "share", "ghostty" }); + return result; + } + } + + return try internal_os.resourcesDir(alloc); +} From f6c1653dee2389962825f36235d25cab58c229f0 Mon Sep 17 00:00:00 2001 From: Kat <65649991+00-kat@users.noreply.github.com> Date: Sun, 21 Sep 2025 11:42:32 +0000 Subject: [PATCH 47/77] Update README_TRANSLATORS to reflect the new i18n locales struct path. It was moved in 9feaec9c9c9bd74f0ad1627e73ac6cebf1c4c135, but the documentation seems to have been forgotten. --- po/README_TRANSLATORS.md | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/po/README_TRANSLATORS.md b/po/README_TRANSLATORS.md index c02a5bd48..582d5037c 100644 --- a/po/README_TRANSLATORS.md +++ b/po/README_TRANSLATORS.md @@ -131,12 +131,11 @@ which should be filled in accordingly. You can then add your translations within the newly created translation file. Afterwards, you need to update the list of known locales within Ghostty's -build system. To do so, open `src/os/i18n.zig` and find the list -of locales under the `locales` variable, then add the full locale name -into the list. +build system. To do so, open `src/os/i18n_locales.zig` and find the list +of locales after the comments, then add the full locale name into the list. The order matters, so make sure to place your locale in the correct position. -Read the comment above the variable for more details on the order. If you're +Read the comments present in the file for more details on the order. If you're unsure, place it at the end of the list. ```zig @@ -146,7 +145,7 @@ const locales = [_][]const u8{ } ``` -You should then be able to run `zig build` and see your translations in action. +You should then be able to run `zig build` and see your translations in action! Before opening a pull request with the new translation file, you should also add your locale to the `CODEOWNERS` file. Find the `# Localization` section near the From 1a189787ae6d1d99781834d45bf6b00d3b509083 Mon Sep 17 00:00:00 2001 From: Peter Dave Hello Date: Sun, 21 Sep 2025 19:06:55 +0800 Subject: [PATCH 48/77] Add zh_TW Traditional Chinese locale --- CODEOWNERS | 1 + po/zh_TW.UTF-8.po | 314 ++++++++++++++++++++++++++++++++++++++++ src/os/i18n_locales.zig | 1 + 3 files changed, 316 insertions(+) create mode 100644 po/zh_TW.UTF-8.po diff --git a/CODEOWNERS b/CODEOWNERS index 801066686..630296980 100644 --- a/CODEOWNERS +++ b/CODEOWNERS @@ -184,6 +184,7 @@ /po/ko_KR.UTF-8.po @ghostty-org/ko_KR /po/he_IL.UTF-8.po @ghostty-org/he_IL /po/it_IT.UTF-8.po @ghostty-org/it_IT +/po/zh_TW.UTF-8.po @ghostty-org/zh_TW # Packaging - Snap /snap/ @ghostty-org/snap diff --git a/po/zh_TW.UTF-8.po b/po/zh_TW.UTF-8.po new file mode 100644 index 000000000..b92b286b0 --- /dev/null +++ b/po/zh_TW.UTF-8.po @@ -0,0 +1,314 @@ +# Traditional Chinese (Taiwan) translation for com.mitchellh.ghostty package. +# Copyright (C) 2025 Mitchell Hashimoto +# This file is distributed under the same license as the com.mitchellh.ghostty package. +# Peter Dave Hello , 2025. +# +msgid "" +msgstr "" +"Project-Id-Version: com.mitchellh.ghostty\n" +"Report-Msgid-Bugs-To: m@mitchellh.com\n" +"POT-Creation-Date: 2025-07-22 17:18+0000\n" +"PO-Revision-Date: 2025-09-21 18:59+0800\n" +"Last-Translator: Peter Dave Hello \n" +"Language-Team: Chinese (traditional)\n" +"Language: zh_TW\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" + +#: src/apprt/gtk/ui/1.5/prompt-title-dialog.blp:5 +msgid "Change Terminal Title" +msgstr "變更終端機標題" + +#: src/apprt/gtk/ui/1.5/prompt-title-dialog.blp:6 +msgid "Leave blank to restore the default title." +msgstr "留空即可還原為預設標題。" + +#: src/apprt/gtk/ui/1.5/prompt-title-dialog.blp:9 +#: src/apprt/gtk/ui/1.5/ccw-paste.blp:10 src/apprt/gtk/ui/1.2/ccw-paste.blp:10 +#: src/apprt/gtk/CloseDialog.zig:44 +msgid "Cancel" +msgstr "取消" + +#: src/apprt/gtk/ui/1.5/prompt-title-dialog.blp:10 +msgid "OK" +msgstr "確定" + +#: src/apprt/gtk/ui/1.5/config-errors-dialog.blp:5 +#: src/apprt/gtk/ui/1.2/config-errors-dialog.blp:5 +msgid "Configuration Errors" +msgstr "設定錯誤" + +#: src/apprt/gtk/ui/1.5/config-errors-dialog.blp:6 +#: src/apprt/gtk/ui/1.2/config-errors-dialog.blp:6 +msgid "" +"One or more configuration errors were found. Please review the errors below, " +"and either reload your configuration or ignore these errors." +msgstr "" +"發現有設定錯誤。請檢視以下錯誤,並重新載入設定或忽略這些錯誤。" + +#: src/apprt/gtk/ui/1.5/config-errors-dialog.blp:9 +#: src/apprt/gtk/ui/1.2/config-errors-dialog.blp:9 +msgid "Ignore" +msgstr "忽略" + +#: src/apprt/gtk/ui/1.5/config-errors-dialog.blp:10 +#: src/apprt/gtk/ui/1.0/menu-surface-context_menu.blp:97 +#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:100 +#: src/apprt/gtk/ui/1.2/config-errors-dialog.blp:10 +msgid "Reload Configuration" +msgstr "重新載入設定" + +#: src/apprt/gtk/ui/1.0/menu-headerbar-split_menu.blp:6 +#: src/apprt/gtk/ui/1.0/menu-surface-context_menu.blp:38 +#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:50 +msgid "Split Up" +msgstr "向上分割" + +#: src/apprt/gtk/ui/1.0/menu-headerbar-split_menu.blp:11 +#: src/apprt/gtk/ui/1.0/menu-surface-context_menu.blp:43 +#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:55 +msgid "Split Down" +msgstr "向下分割" + +#: src/apprt/gtk/ui/1.0/menu-headerbar-split_menu.blp:16 +#: src/apprt/gtk/ui/1.0/menu-surface-context_menu.blp:48 +#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:60 +msgid "Split Left" +msgstr "向左分割" + +#: src/apprt/gtk/ui/1.0/menu-headerbar-split_menu.blp:21 +#: src/apprt/gtk/ui/1.0/menu-surface-context_menu.blp:53 +#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:65 +msgid "Split Right" +msgstr "向右分割" + +#: src/apprt/gtk/ui/1.5/command-palette.blp:16 +msgid "Execute a command…" +msgstr "執行命令…" + +#: src/apprt/gtk/ui/1.0/menu-surface-context_menu.blp:6 +#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:6 +msgid "Copy" +msgstr "複製" + +#: src/apprt/gtk/ui/1.0/menu-surface-context_menu.blp:11 +#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:11 +#: src/apprt/gtk/ui/1.5/ccw-paste.blp:11 src/apprt/gtk/ui/1.2/ccw-paste.blp:11 +msgid "Paste" +msgstr "貼上" + +#: src/apprt/gtk/ui/1.0/menu-surface-context_menu.blp:18 +#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:73 +msgid "Clear" +msgstr "清除" + +#: src/apprt/gtk/ui/1.0/menu-surface-context_menu.blp:23 +#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:78 +msgid "Reset" +msgstr "重設" + +#: src/apprt/gtk/ui/1.0/menu-surface-context_menu.blp:30 +#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:42 +msgid "Split" +msgstr "分割" + +#: src/apprt/gtk/ui/1.0/menu-surface-context_menu.blp:33 +#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:45 +msgid "Change Title…" +msgstr "變更標題…" + +#: src/apprt/gtk/ui/1.0/menu-surface-context_menu.blp:59 +msgid "Tab" +msgstr "分頁" + +#: src/apprt/gtk/ui/1.0/menu-surface-context_menu.blp:62 +#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:30 +#: src/apprt/gtk/Window.zig:265 +msgid "New Tab" +msgstr "開新分頁" + +#: src/apprt/gtk/ui/1.0/menu-surface-context_menu.blp:67 +#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:35 +msgid "Close Tab" +msgstr "關閉分頁" + +#: src/apprt/gtk/ui/1.0/menu-surface-context_menu.blp:73 +msgid "Window" +msgstr "視窗" + +#: src/apprt/gtk/ui/1.0/menu-surface-context_menu.blp:76 +#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:18 +msgid "New Window" +msgstr "開新視窗" + +#: src/apprt/gtk/ui/1.0/menu-surface-context_menu.blp:81 +#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:23 +msgid "Close Window" +msgstr "關閉視窗" + +#: src/apprt/gtk/ui/1.0/menu-surface-context_menu.blp:89 +msgid "Config" +msgstr "設定" + +#: src/apprt/gtk/ui/1.0/menu-surface-context_menu.blp:92 +#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:95 +msgid "Open Configuration" +msgstr "開啟設定" + +#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:85 +msgid "Command Palette" +msgstr "命令面板" + +#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:90 +msgid "Terminal Inspector" +msgstr "終端機檢查工具" + +#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:107 +#: src/apprt/gtk/Window.zig:1038 +msgid "About Ghostty" +msgstr "關於 Ghostty" + +#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:112 +msgid "Quit" +msgstr "結束" + +#: src/apprt/gtk/ui/1.5/ccw-osc-52-read.blp:6 +#: src/apprt/gtk/ui/1.5/ccw-osc-52-write.blp:6 +#: src/apprt/gtk/ui/1.2/ccw-osc-52-read.blp:6 +#: src/apprt/gtk/ui/1.2/ccw-osc-52-write.blp:6 +msgid "Authorize Clipboard Access" +msgstr "授權存取剪貼簿" + +#: src/apprt/gtk/ui/1.5/ccw-osc-52-read.blp:7 +#: src/apprt/gtk/ui/1.2/ccw-osc-52-read.blp:7 +msgid "" +"An application is attempting to read from the clipboard. The current " +"clipboard contents are shown below." +msgstr "" +"有應用程式正嘗試讀取剪貼簿,目前的剪貼簿內容顯示如下。" + +#: src/apprt/gtk/ui/1.5/ccw-osc-52-read.blp:10 +#: src/apprt/gtk/ui/1.5/ccw-osc-52-write.blp:10 +#: src/apprt/gtk/ui/1.2/ccw-osc-52-read.blp:10 +#: src/apprt/gtk/ui/1.2/ccw-osc-52-write.blp:10 +msgid "Deny" +msgstr "拒絕" + +#: src/apprt/gtk/ui/1.5/ccw-osc-52-read.blp:11 +#: src/apprt/gtk/ui/1.5/ccw-osc-52-write.blp:11 +#: src/apprt/gtk/ui/1.2/ccw-osc-52-read.blp:11 +#: src/apprt/gtk/ui/1.2/ccw-osc-52-write.blp:11 +msgid "Allow" +msgstr "允許" + +#: src/apprt/gtk/ui/1.5/ccw-osc-52-read.blp:81 +#: src/apprt/gtk/ui/1.5/ccw-osc-52-write.blp:77 +msgid "Remember choice for this split" +msgstr "記住此窗格的選擇" + +#: src/apprt/gtk/ui/1.5/ccw-osc-52-read.blp:82 +#: src/apprt/gtk/ui/1.5/ccw-osc-52-write.blp:78 +msgid "Reload configuration to show this prompt again" +msgstr "重新載入設定以再次顯示此提示" + +#: src/apprt/gtk/ui/1.5/ccw-osc-52-write.blp:7 +#: src/apprt/gtk/ui/1.2/ccw-osc-52-write.blp:7 +msgid "" +"An application is attempting to write to the clipboard. The current " +"clipboard contents are shown below." +msgstr "" +"有應用程式正嘗試寫入剪貼簿,目前的剪貼簿內容顯示如下。" + +#: src/apprt/gtk/ui/1.5/ccw-paste.blp:6 src/apprt/gtk/ui/1.2/ccw-paste.blp:6 +msgid "Warning: Potentially Unsafe Paste" +msgstr "警告:可能有潛在安全風險的貼上操作" + +#: src/apprt/gtk/ui/1.5/ccw-paste.blp:7 src/apprt/gtk/ui/1.2/ccw-paste.blp:7 +msgid "" +"Pasting this text into the terminal may be dangerous as it looks like some " +"commands may be executed." +msgstr "" +"將這段文字貼到終端機具有潛在風險,因為它看起來像是可能會被執行的命令。" + +#: src/apprt/gtk/CloseDialog.zig:47 src/apprt/gtk/Surface.zig:2531 +msgid "Close" +msgstr "關閉" + +#: src/apprt/gtk/CloseDialog.zig:87 +msgid "Quit Ghostty?" +msgstr "要結束 Ghostty 嗎?" + +#: src/apprt/gtk/CloseDialog.zig:88 +msgid "Close Window?" +msgstr "是否要關閉視窗?" + +#: src/apprt/gtk/CloseDialog.zig:89 +msgid "Close Tab?" +msgstr "是否要關閉分頁?" + +#: src/apprt/gtk/CloseDialog.zig:90 +msgid "Close Split?" +msgstr "是否要關閉窗格?" + +#: src/apprt/gtk/CloseDialog.zig:96 +msgid "All terminal sessions will be terminated." +msgstr "所有終端機工作階段都將被終止。" + +#: src/apprt/gtk/CloseDialog.zig:97 +msgid "All terminal sessions in this window will be terminated." +msgstr "此視窗中的所有終端機工作階段都將被終止。" + +#: src/apprt/gtk/CloseDialog.zig:98 +msgid "All terminal sessions in this tab will be terminated." +msgstr "此分頁中的所有終端機工作階段都將被終止。" + +#: src/apprt/gtk/CloseDialog.zig:99 +msgid "The currently running process in this split will be terminated." +msgstr "此窗格中目前執行的處理程序將被終止。" + +#: src/apprt/gtk/Surface.zig:1266 +msgid "Copied to clipboard" +msgstr "已複製到剪貼簿" + +#: src/apprt/gtk/Surface.zig:1268 +msgid "Cleared clipboard" +msgstr "已清除剪貼簿" + +#: src/apprt/gtk/Surface.zig:2525 +msgid "Command succeeded" +msgstr "命令執行成功" + +#: src/apprt/gtk/Surface.zig:2527 +msgid "Command failed" +msgstr "命令執行失敗" + +#: src/apprt/gtk/Window.zig:216 +msgid "Main Menu" +msgstr "主選單" + +#: src/apprt/gtk/Window.zig:239 +msgid "View Open Tabs" +msgstr "檢視已開啟的分頁" + +#: src/apprt/gtk/Window.zig:266 +msgid "New Split" +msgstr "新增窗格" + +#: src/apprt/gtk/Window.zig:329 +msgid "" +"⚠️ You're running a debug build of Ghostty! Performance will be degraded." +msgstr "" +"⚠️ 您正在執行 Ghostty 的除錯版本!程式運作效能將會受到影響。" + +#: src/apprt/gtk/Window.zig:775 +msgid "Reloaded the configuration" +msgstr "已重新載入設定" + +#: src/apprt/gtk/Window.zig:1019 +msgid "Ghostty Developers" +msgstr "Ghostty 開發者" + +#: src/apprt/gtk/inspector.zig:144 +msgid "Ghostty: Terminal Inspector" +msgstr "Ghostty:終端機檢查工具" diff --git a/src/os/i18n_locales.zig b/src/os/i18n_locales.zig index 199a24526..c01b15106 100644 --- a/src/os/i18n_locales.zig +++ b/src/os/i18n_locales.zig @@ -50,4 +50,5 @@ pub const locales = [_][:0]const u8{ "ga_IE.UTF-8", "hu_HU.UTF-8", "he_IL.UTF-8", + "zh_TW.UTF-8", }; From 4ff74fdfae64d4cfda5f4fa16a3e1f197b4e65ba Mon Sep 17 00:00:00 2001 From: Leorize Date: Sun, 21 Sep 2025 14:15:12 -0500 Subject: [PATCH 49/77] flatpak: update GNOME runtime to 49 Notable dependencies changes: - blueprint-compiler is dropped as it has been bundled in the SDK - GTK 4.18.6 -> 4.20.1 - libadwaita 1.7.7 -> 1.8.0 --- flatpak/com.mitchellh.ghostty-debug.yml | 2 +- flatpak/com.mitchellh.ghostty.yml | 2 +- flatpak/dependencies.yml | 13 ------------- 3 files changed, 2 insertions(+), 15 deletions(-) diff --git a/flatpak/com.mitchellh.ghostty-debug.yml b/flatpak/com.mitchellh.ghostty-debug.yml index 51c41931b..559f5a487 100644 --- a/flatpak/com.mitchellh.ghostty-debug.yml +++ b/flatpak/com.mitchellh.ghostty-debug.yml @@ -1,6 +1,6 @@ app-id: com.mitchellh.ghostty-debug runtime: org.gnome.Platform -runtime-version: "48" +runtime-version: "49" sdk: org.gnome.Sdk default-branch: tip command: ghostty diff --git a/flatpak/com.mitchellh.ghostty.yml b/flatpak/com.mitchellh.ghostty.yml index f5af4235d..af321d00f 100644 --- a/flatpak/com.mitchellh.ghostty.yml +++ b/flatpak/com.mitchellh.ghostty.yml @@ -1,6 +1,6 @@ app-id: com.mitchellh.ghostty runtime: org.gnome.Platform -runtime-version: "48" +runtime-version: "49" sdk: org.gnome.Sdk default-branch: tip command: ghostty diff --git a/flatpak/dependencies.yml b/flatpak/dependencies.yml index 0ff0784c2..082107923 100644 --- a/flatpak/dependencies.yml +++ b/flatpak/dependencies.yml @@ -30,19 +30,6 @@ modules: contents: INPUT(libbz2.so) dest-filename: libbzip2.so - - name: blueprint-compiler - buildsystem: meson - cleanup: - - "*" - sources: - - type: git - url: https://gitlab.gnome.org/jwestman/blueprint-compiler.git - tag: v0.16.0 - commit: 04ef0944db56ab01307a29aaa7303df6067cb3c0 - x-checker-data: - type: git - tag-pattern: ^v([\d.]+)$ - - name: gtk4-layer-shell buildsystem: meson sources: From 17498ce122ca02ba23497e0a8606888c32ef81d2 Mon Sep 17 00:00:00 2001 From: Mitchell Hashimoto Date: Sun, 21 Sep 2025 10:36:37 -0700 Subject: [PATCH 50/77] build: many more lazy dependencies, defer deps add unless needed This makes more dependencies lazy. This has a practical effect of reducing the number of dependencies that need to be downloaded when running certain zig build steps. This is all limited because we're blocked on an upstream Zig issue: https://github.com/ziglang/zig/issues/21525 This prevents us from fully avoiding downloading many dependencies, but at least they're relatively small. One major improvement here is the usage of `lazyImport` for `zig-wayland` that prevents downloading `zig_wayland` unconditionally on all platforms. On macOS, we don't download this at all anymore. Another, weirder change is that all our transitive dependencies are now marked lazy (e.g. glslang's upstream source) even if the glslang build always requires it. This was necessary because without this, even if we simply referenced glslang in the root build.zig, it would force the source package to download unconditionally. This no longer happens. --- build.zig.zon | 3 + pkg/cimgui/build.zig | 45 +++++----- pkg/cimgui/build.zig.zon | 1 + pkg/glslang/build.zig | 158 +++++++++++++++++----------------- pkg/glslang/build.zig.zon | 1 + pkg/highway/build.zig | 46 +++++----- pkg/highway/build.zig.zon | 1 + pkg/libxml2/build.zig | 34 ++++---- pkg/libxml2/build.zig.zon | 1 + pkg/spirv-cross/build.zig | 7 +- pkg/spirv-cross/build.zig.zon | 1 + src/build/SharedDeps.zig | 75 ++++++++-------- 12 files changed, 198 insertions(+), 175 deletions(-) diff --git a/build.zig.zon b/build.zig.zon index 0e349cd6d..6968d0ab3 100644 --- a/build.zig.zon +++ b/build.zig.zon @@ -45,6 +45,7 @@ // codeberg ifreund/zig-wayland .url = "https://codeberg.org/ifreund/zig-wayland/archive/f3c5d503e540ada8cbcb056420de240af0c094f7.tar.gz", .hash = "wayland-0.4.0-dev-lQa1kjfIAQCmhhQu3xF0KH-94-TzeMXOqfnP0-Dg6Wyy", + .lazy = true, }, .zf = .{ // natecraddock/zf @@ -103,10 +104,12 @@ .jetbrains_mono = .{ .url = "https://deps.files.ghostty.org/JetBrainsMono-2.304.tar.gz", .hash = "N-V-__8AAIC5lwAVPJJzxnCAahSvZTIlG-HhtOvnM1uh-66x", + .lazy = true, }, .nerd_fonts_symbols_only = .{ .url = "https://deps.files.ghostty.org/NerdFontsSymbolsOnly-3.4.0.tar.gz", .hash = "N-V-__8AAMVLTABmYkLqhZPLXnMl-KyN38R8UVYqGrxqO26s", + .lazy = true, }, // Other diff --git a/pkg/cimgui/build.zig b/pkg/cimgui/build.zig index 83d60737e..f14bc1242 100644 --- a/pkg/cimgui/build.zig +++ b/pkg/cimgui/build.zig @@ -11,7 +11,7 @@ pub fn build(b: *std.Build) !void { .optimize = optimize, }); - const imgui = b.dependency("imgui", .{}); + const imgui_ = b.lazyDependency("imgui", .{}); const lib = b.addLibrary(.{ .name = "cimgui", .root_module = b.createModule(.{ @@ -52,7 +52,7 @@ pub fn build(b: *std.Build) !void { } } - lib.addIncludePath(imgui.path("")); + if (imgui_) |imgui| lib.addIncludePath(imgui.path("")); module.addIncludePath(b.path("vendor")); var flags = std.ArrayList([]const u8).init(b.allocator); @@ -72,32 +72,33 @@ pub fn build(b: *std.Build) !void { }); } - lib.addCSourceFile(.{ .file = b.path("vendor/cimgui.cpp"), .flags = flags.items }); - lib.addCSourceFile(.{ .file = imgui.path("imgui.cpp"), .flags = flags.items }); - lib.addCSourceFile(.{ .file = imgui.path("imgui_draw.cpp"), .flags = flags.items }); - lib.addCSourceFile(.{ .file = imgui.path("imgui_demo.cpp"), .flags = flags.items }); - lib.addCSourceFile(.{ .file = imgui.path("imgui_widgets.cpp"), .flags = flags.items }); - lib.addCSourceFile(.{ .file = imgui.path("imgui_tables.cpp"), .flags = flags.items }); - lib.addCSourceFile(.{ .file = imgui.path("misc/freetype/imgui_freetype.cpp"), .flags = flags.items }); - - lib.addCSourceFile(.{ - .file = imgui.path("backends/imgui_impl_opengl3.cpp"), - .flags = flags.items, - }); - - if (target.result.os.tag.isDarwin()) { - if (!target.query.isNative()) { - try @import("apple_sdk").addPaths(b, lib); - } + if (imgui_) |imgui| { + lib.addCSourceFile(.{ .file = b.path("vendor/cimgui.cpp"), .flags = flags.items }); + lib.addCSourceFile(.{ .file = imgui.path("imgui.cpp"), .flags = flags.items }); + lib.addCSourceFile(.{ .file = imgui.path("imgui_draw.cpp"), .flags = flags.items }); + lib.addCSourceFile(.{ .file = imgui.path("imgui_demo.cpp"), .flags = flags.items }); + lib.addCSourceFile(.{ .file = imgui.path("imgui_widgets.cpp"), .flags = flags.items }); + lib.addCSourceFile(.{ .file = imgui.path("imgui_tables.cpp"), .flags = flags.items }); + lib.addCSourceFile(.{ .file = imgui.path("misc/freetype/imgui_freetype.cpp"), .flags = flags.items }); lib.addCSourceFile(.{ - .file = imgui.path("backends/imgui_impl_metal.mm"), + .file = imgui.path("backends/imgui_impl_opengl3.cpp"), .flags = flags.items, }); - if (target.result.os.tag == .macos) { + + if (target.result.os.tag.isDarwin()) { + if (!target.query.isNative()) { + try @import("apple_sdk").addPaths(b, lib); + } lib.addCSourceFile(.{ - .file = imgui.path("backends/imgui_impl_osx.mm"), + .file = imgui.path("backends/imgui_impl_metal.mm"), .flags = flags.items, }); + if (target.result.os.tag == .macos) { + lib.addCSourceFile(.{ + .file = imgui.path("backends/imgui_impl_osx.mm"), + .flags = flags.items, + }); + } } } diff --git a/pkg/cimgui/build.zig.zon b/pkg/cimgui/build.zig.zon index 2d62f6e84..f539a8fd6 100644 --- a/pkg/cimgui/build.zig.zon +++ b/pkg/cimgui/build.zig.zon @@ -10,6 +10,7 @@ // ocornut/imgui .url = "https://deps.files.ghostty.org/imgui-1220bc6b9daceaf7c8c60f3c3998058045ba0c5c5f48ae255ff97776d9cd8bfc6402.tar.gz", .hash = "N-V-__8AAH0GaQC8a52s6vfIxg88OZgFgEW6DFxfSK4lX_l3", + .lazy = true, }, .apple_sdk = .{ .path = "../apple-sdk" }, diff --git a/pkg/glslang/build.zig b/pkg/glslang/build.zig index c5e76008a..52993a662 100644 --- a/pkg/glslang/build.zig +++ b/pkg/glslang/build.zig @@ -10,11 +10,11 @@ pub fn build(b: *std.Build) !void { .optimize = optimize, }); - const upstream = b.dependency("glslang", .{}); + const upstream = b.lazyDependency("glslang", .{}); const lib = try buildGlslang(b, upstream, target, optimize); b.installArtifact(lib); - module.addIncludePath(upstream.path("")); + if (upstream) |v| module.addIncludePath(v.path("")); module.addIncludePath(b.path("override")); if (target.query.isNative()) { @@ -38,7 +38,7 @@ pub fn build(b: *std.Build) !void { fn buildGlslang( b: *std.Build, - upstream: *std.Build.Dependency, + upstream_: ?*std.Build.Dependency, target: std.Build.ResolvedTarget, optimize: std.builtin.OptimizeMode, ) !*std.Build.Step.Compile { @@ -52,7 +52,7 @@ fn buildGlslang( }); lib.linkLibC(); lib.linkLibCpp(); - lib.addIncludePath(upstream.path("")); + if (upstream_) |upstream| lib.addIncludePath(upstream.path("")); lib.addIncludePath(b.path("override")); if (target.result.os.tag.isDarwin()) { const apple_sdk = @import("apple_sdk"); @@ -66,87 +66,89 @@ fn buildGlslang( "-fno-sanitize-trap=undefined", }); - lib.addCSourceFiles(.{ - .root = upstream.path(""), - .flags = flags.items, - .files = &.{ - // GenericCodeGen - "glslang/GenericCodeGen/CodeGen.cpp", - "glslang/GenericCodeGen/Link.cpp", - - // MachineIndependent - //"MachineIndependent/glslang.y", - "glslang/MachineIndependent/glslang_tab.cpp", - "glslang/MachineIndependent/attribute.cpp", - "glslang/MachineIndependent/Constant.cpp", - "glslang/MachineIndependent/iomapper.cpp", - "glslang/MachineIndependent/InfoSink.cpp", - "glslang/MachineIndependent/Initialize.cpp", - "glslang/MachineIndependent/IntermTraverse.cpp", - "glslang/MachineIndependent/Intermediate.cpp", - "glslang/MachineIndependent/ParseContextBase.cpp", - "glslang/MachineIndependent/ParseHelper.cpp", - "glslang/MachineIndependent/PoolAlloc.cpp", - "glslang/MachineIndependent/RemoveTree.cpp", - "glslang/MachineIndependent/Scan.cpp", - "glslang/MachineIndependent/ShaderLang.cpp", - "glslang/MachineIndependent/SpirvIntrinsics.cpp", - "glslang/MachineIndependent/SymbolTable.cpp", - "glslang/MachineIndependent/Versions.cpp", - "glslang/MachineIndependent/intermOut.cpp", - "glslang/MachineIndependent/limits.cpp", - "glslang/MachineIndependent/linkValidate.cpp", - "glslang/MachineIndependent/parseConst.cpp", - "glslang/MachineIndependent/reflection.cpp", - "glslang/MachineIndependent/preprocessor/Pp.cpp", - "glslang/MachineIndependent/preprocessor/PpAtom.cpp", - "glslang/MachineIndependent/preprocessor/PpContext.cpp", - "glslang/MachineIndependent/preprocessor/PpScanner.cpp", - "glslang/MachineIndependent/preprocessor/PpTokens.cpp", - "glslang/MachineIndependent/propagateNoContraction.cpp", - - // C Interface - "glslang/CInterface/glslang_c_interface.cpp", - - // ResourceLimits - "glslang/ResourceLimits/ResourceLimits.cpp", - "glslang/ResourceLimits/resource_limits_c.cpp", - - // SPIRV - "SPIRV/GlslangToSpv.cpp", - "SPIRV/InReadableOrder.cpp", - "SPIRV/Logger.cpp", - "SPIRV/SpvBuilder.cpp", - "SPIRV/SpvPostProcess.cpp", - "SPIRV/doc.cpp", - "SPIRV/disassemble.cpp", - "SPIRV/CInterface/spirv_c_interface.cpp", - }, - }); - - if (target.result.os.tag != .windows) { + if (upstream_) |upstream| { lib.addCSourceFiles(.{ .root = upstream.path(""), .flags = flags.items, .files = &.{ - "glslang/OSDependent/Unix/ossource.cpp", - }, - }); - } else { - lib.addCSourceFiles(.{ - .root = upstream.path(""), - .flags = flags.items, - .files = &.{ - "glslang/OSDependent/Windows/ossource.cpp", + // GenericCodeGen + "glslang/GenericCodeGen/CodeGen.cpp", + "glslang/GenericCodeGen/Link.cpp", + + // MachineIndependent + //"MachineIndependent/glslang.y", + "glslang/MachineIndependent/glslang_tab.cpp", + "glslang/MachineIndependent/attribute.cpp", + "glslang/MachineIndependent/Constant.cpp", + "glslang/MachineIndependent/iomapper.cpp", + "glslang/MachineIndependent/InfoSink.cpp", + "glslang/MachineIndependent/Initialize.cpp", + "glslang/MachineIndependent/IntermTraverse.cpp", + "glslang/MachineIndependent/Intermediate.cpp", + "glslang/MachineIndependent/ParseContextBase.cpp", + "glslang/MachineIndependent/ParseHelper.cpp", + "glslang/MachineIndependent/PoolAlloc.cpp", + "glslang/MachineIndependent/RemoveTree.cpp", + "glslang/MachineIndependent/Scan.cpp", + "glslang/MachineIndependent/ShaderLang.cpp", + "glslang/MachineIndependent/SpirvIntrinsics.cpp", + "glslang/MachineIndependent/SymbolTable.cpp", + "glslang/MachineIndependent/Versions.cpp", + "glslang/MachineIndependent/intermOut.cpp", + "glslang/MachineIndependent/limits.cpp", + "glslang/MachineIndependent/linkValidate.cpp", + "glslang/MachineIndependent/parseConst.cpp", + "glslang/MachineIndependent/reflection.cpp", + "glslang/MachineIndependent/preprocessor/Pp.cpp", + "glslang/MachineIndependent/preprocessor/PpAtom.cpp", + "glslang/MachineIndependent/preprocessor/PpContext.cpp", + "glslang/MachineIndependent/preprocessor/PpScanner.cpp", + "glslang/MachineIndependent/preprocessor/PpTokens.cpp", + "glslang/MachineIndependent/propagateNoContraction.cpp", + + // C Interface + "glslang/CInterface/glslang_c_interface.cpp", + + // ResourceLimits + "glslang/ResourceLimits/ResourceLimits.cpp", + "glslang/ResourceLimits/resource_limits_c.cpp", + + // SPIRV + "SPIRV/GlslangToSpv.cpp", + "SPIRV/InReadableOrder.cpp", + "SPIRV/Logger.cpp", + "SPIRV/SpvBuilder.cpp", + "SPIRV/SpvPostProcess.cpp", + "SPIRV/doc.cpp", + "SPIRV/disassemble.cpp", + "SPIRV/CInterface/spirv_c_interface.cpp", }, }); + + if (target.result.os.tag != .windows) { + lib.addCSourceFiles(.{ + .root = upstream.path(""), + .flags = flags.items, + .files = &.{ + "glslang/OSDependent/Unix/ossource.cpp", + }, + }); + } else { + lib.addCSourceFiles(.{ + .root = upstream.path(""), + .flags = flags.items, + .files = &.{ + "glslang/OSDependent/Windows/ossource.cpp", + }, + }); + } + + lib.installHeadersDirectory( + upstream.path(""), + "", + .{ .include_extensions = &.{".h"} }, + ); } - lib.installHeadersDirectory( - upstream.path(""), - "", - .{ .include_extensions = &.{".h"} }, - ); - return lib; } diff --git a/pkg/glslang/build.zig.zon b/pkg/glslang/build.zig.zon index cbcb08e5d..252237e58 100644 --- a/pkg/glslang/build.zig.zon +++ b/pkg/glslang/build.zig.zon @@ -8,6 +8,7 @@ .glslang = .{ .url = "https://deps.files.ghostty.org/glslang-12201278a1a05c0ce0b6eb6026c65cd3e9247aa041b1c260324bf29cee559dd23ba1.tar.gz", .hash = "N-V-__8AABzkUgISeKGgXAzgtutgJsZc0-kkeqBBscJgMkvy", + .lazy = true, }, .apple_sdk = .{ .path = "../apple-sdk" }, diff --git a/pkg/highway/build.zig b/pkg/highway/build.zig index c8ef2d18e..1013f1643 100644 --- a/pkg/highway/build.zig +++ b/pkg/highway/build.zig @@ -4,7 +4,7 @@ pub fn build(b: *std.Build) !void { const target = b.standardTargetOptions(.{}); const optimize = b.standardOptimizeOption(.{}); - const upstream = b.dependency("highway", .{}); + const upstream_ = b.lazyDependency("highway", .{}); const module = b.addModule("highway", .{ .root_source_file = b.path("main.zig"), @@ -21,8 +21,10 @@ pub fn build(b: *std.Build) !void { .linkage = .static, }); lib.linkLibCpp(); - lib.addIncludePath(upstream.path("")); - module.addIncludePath(upstream.path("")); + if (upstream_) |upstream| { + lib.addIncludePath(upstream.path("")); + module.addIncludePath(upstream.path("")); + } if (target.result.os.tag.isDarwin()) { const apple_sdk = @import("apple_sdk"); @@ -74,24 +76,26 @@ pub fn build(b: *std.Build) !void { } lib.addCSourceFiles(.{ .flags = flags.items, .files = &.{"bridge.cpp"} }); - lib.addCSourceFiles(.{ - .root = upstream.path(""), - .flags = flags.items, - .files = &.{ - "hwy/abort.cc", - "hwy/aligned_allocator.cc", - "hwy/nanobenchmark.cc", - "hwy/per_target.cc", - "hwy/print.cc", - "hwy/targets.cc", - "hwy/timer.cc", - }, - }); - lib.installHeadersDirectory( - upstream.path("hwy"), - "hwy", - .{ .include_extensions = &.{".h"} }, - ); + if (upstream_) |upstream| { + lib.addCSourceFiles(.{ + .root = upstream.path(""), + .flags = flags.items, + .files = &.{ + "hwy/abort.cc", + "hwy/aligned_allocator.cc", + "hwy/nanobenchmark.cc", + "hwy/per_target.cc", + "hwy/print.cc", + "hwy/targets.cc", + "hwy/timer.cc", + }, + }); + lib.installHeadersDirectory( + upstream.path("hwy"), + "hwy", + .{ .include_extensions = &.{".h"} }, + ); + } b.installArtifact(lib); diff --git a/pkg/highway/build.zig.zon b/pkg/highway/build.zig.zon index 8fc05641e..0777fcb7a 100644 --- a/pkg/highway/build.zig.zon +++ b/pkg/highway/build.zig.zon @@ -8,6 +8,7 @@ .highway = .{ .url = "https://deps.files.ghostty.org/highway-66486a10623fa0d72fe91260f96c892e41aceb06.tar.gz", .hash = "N-V-__8AAGmZhABbsPJLfbqrh6JTHsXhY6qCaLAQyx25e0XE", + .lazy = true, }, .apple_sdk = .{ .path = "../apple-sdk" }, diff --git a/pkg/libxml2/build.zig b/pkg/libxml2/build.zig index 7c3c2b607..acebfaf63 100644 --- a/pkg/libxml2/build.zig +++ b/pkg/libxml2/build.zig @@ -4,7 +4,7 @@ pub fn build(b: *std.Build) !void { const target = b.standardTargetOptions(.{}); const optimize = b.standardOptimizeOption(.{}); - const upstream = b.dependency("libxml2", .{}); + const upstream_ = b.lazyDependency("libxml2", .{}); const lib = b.addLibrary(.{ .name = "xml2", @@ -16,7 +16,7 @@ pub fn build(b: *std.Build) !void { }); lib.linkLibC(); - lib.addIncludePath(upstream.path("include")); + if (upstream_) |upstream| lib.addIncludePath(upstream.path("include")); lib.addIncludePath(b.path("override/include")); if (target.result.os.tag == .windows) { lib.addIncludePath(b.path("override/config/win32")); @@ -97,21 +97,23 @@ pub fn build(b: *std.Build) !void { } } - lib.addCSourceFiles(.{ - .root = upstream.path(""), - .files = srcs, - .flags = flags.items, - }); + if (upstream_) |upstream| { + lib.addCSourceFiles(.{ + .root = upstream.path(""), + .files = srcs, + .flags = flags.items, + }); - lib.installHeader( - b.path("override/include/libxml/xmlversion.h"), - "libxml/xmlversion.h", - ); - lib.installHeadersDirectory( - upstream.path("include"), - "", - .{ .include_extensions = &.{".h"} }, - ); + lib.installHeader( + b.path("override/include/libxml/xmlversion.h"), + "libxml/xmlversion.h", + ); + lib.installHeadersDirectory( + upstream.path("include"), + "", + .{ .include_extensions = &.{".h"} }, + ); + } b.installArtifact(lib); } diff --git a/pkg/libxml2/build.zig.zon b/pkg/libxml2/build.zig.zon index 3f6906a50..f932835aa 100644 --- a/pkg/libxml2/build.zig.zon +++ b/pkg/libxml2/build.zig.zon @@ -7,6 +7,7 @@ .libxml2 = .{ .url = "https://deps.files.ghostty.org/libxml2-2.11.5.tar.gz", .hash = "N-V-__8AAG3RoQEyRC2Vw7Qoro5SYBf62IHn3HjqtNVY6aWK", + .lazy = true, }, }, } diff --git a/pkg/spirv-cross/build.zig b/pkg/spirv-cross/build.zig index b359ccd9c..9e84689ca 100644 --- a/pkg/spirv-cross/build.zig +++ b/pkg/spirv-cross/build.zig @@ -4,10 +4,10 @@ pub fn build(b: *std.Build) !void { const target = b.standardTargetOptions(.{}); const optimize = b.standardOptimizeOption(.{}); - const upstream = b.dependency("spirv_cross", .{}); + const upstream = b.lazyDependency("spirv_cross", .{}); const module = b.addModule("spirv_cross", .{ .root_source_file = b.path("main.zig") }); - module.addIncludePath(upstream.path("")); + if (upstream) |v| module.addIncludePath(v.path("")); const lib = try buildSpirvCross(b, upstream, target, optimize); b.installArtifact(lib); @@ -33,7 +33,7 @@ pub fn build(b: *std.Build) !void { fn buildSpirvCross( b: *std.Build, - upstream: *std.Build.Dependency, + upstream_: ?*std.Build.Dependency, target: std.Build.ResolvedTarget, optimize: std.builtin.OptimizeMode, ) !*std.Build.Step.Compile { @@ -62,6 +62,7 @@ fn buildSpirvCross( "-fno-sanitize-trap=undefined", }); + const upstream = upstream_ orelse return lib; lib.addCSourceFiles(.{ .root = upstream.path(""), .flags = flags.items, diff --git a/pkg/spirv-cross/build.zig.zon b/pkg/spirv-cross/build.zig.zon index a7ad7133d..30eea9501 100644 --- a/pkg/spirv-cross/build.zig.zon +++ b/pkg/spirv-cross/build.zig.zon @@ -8,6 +8,7 @@ .spirv_cross = .{ .url = "https://deps.files.ghostty.org/spirv_cross-1220fb3b5586e8be67bc3feb34cbe749cf42a60d628d2953632c2f8141302748c8da.tar.gz", .hash = "N-V-__8AANb6pwD7O1WG6L5nvD_rNMvnSc9Cpg1ijSlTYywv", + .lazy = true, }, .apple_sdk = .{ .path = "../apple-sdk" }, diff --git a/src/build/SharedDeps.zig b/src/build/SharedDeps.zig index 77dec3350..ab5b0d8bf 100644 --- a/src/build/SharedDeps.zig +++ b/src/build/SharedDeps.zig @@ -502,38 +502,40 @@ pub fn add( // Fonts { // JetBrains Mono - const jb_mono = b.dependency("jetbrains_mono", .{}); - step.root_module.addAnonymousImport( - "jetbrains_mono_regular", - .{ .root_source_file = jb_mono.path("fonts/ttf/JetBrainsMono-Regular.ttf") }, - ); - step.root_module.addAnonymousImport( - "jetbrains_mono_bold", - .{ .root_source_file = jb_mono.path("fonts/ttf/JetBrainsMono-Bold.ttf") }, - ); - step.root_module.addAnonymousImport( - "jetbrains_mono_italic", - .{ .root_source_file = jb_mono.path("fonts/ttf/JetBrainsMono-Italic.ttf") }, - ); - step.root_module.addAnonymousImport( - "jetbrains_mono_bold_italic", - .{ .root_source_file = jb_mono.path("fonts/ttf/JetBrainsMono-BoldItalic.ttf") }, - ); - step.root_module.addAnonymousImport( - "jetbrains_mono_variable", - .{ .root_source_file = jb_mono.path("fonts/variable/JetBrainsMono[wght].ttf") }, - ); - step.root_module.addAnonymousImport( - "jetbrains_mono_variable_italic", - .{ .root_source_file = jb_mono.path("fonts/variable/JetBrainsMono-Italic[wght].ttf") }, - ); + if (b.lazyDependency("jetbrains_mono", .{})) |jb_mono| { + step.root_module.addAnonymousImport( + "jetbrains_mono_regular", + .{ .root_source_file = jb_mono.path("fonts/ttf/JetBrainsMono-Regular.ttf") }, + ); + step.root_module.addAnonymousImport( + "jetbrains_mono_bold", + .{ .root_source_file = jb_mono.path("fonts/ttf/JetBrainsMono-Bold.ttf") }, + ); + step.root_module.addAnonymousImport( + "jetbrains_mono_italic", + .{ .root_source_file = jb_mono.path("fonts/ttf/JetBrainsMono-Italic.ttf") }, + ); + step.root_module.addAnonymousImport( + "jetbrains_mono_bold_italic", + .{ .root_source_file = jb_mono.path("fonts/ttf/JetBrainsMono-BoldItalic.ttf") }, + ); + step.root_module.addAnonymousImport( + "jetbrains_mono_variable", + .{ .root_source_file = jb_mono.path("fonts/variable/JetBrainsMono[wght].ttf") }, + ); + step.root_module.addAnonymousImport( + "jetbrains_mono_variable_italic", + .{ .root_source_file = jb_mono.path("fonts/variable/JetBrainsMono-Italic[wght].ttf") }, + ); + } // Symbols-only nerd font - const nf_symbols = b.dependency("nerd_fonts_symbols_only", .{}); - step.root_module.addAnonymousImport( - "nerd_fonts_symbols_only", - .{ .root_source_file = nf_symbols.path("SymbolsNerdFont-Regular.ttf") }, - ); + if (b.lazyDependency("nerd_fonts_symbols_only", .{})) |nf_symbols| { + step.root_module.addAnonymousImport( + "nerd_fonts_symbols_only", + .{ .root_source_file = nf_symbols.path("SymbolsNerdFont-Regular.ttf") }, + ); + } } // If we're building an exe then we have additional dependencies. @@ -615,17 +617,20 @@ fn addGtkNg( "plasma_wayland_protocols", .{}, ); + const zig_wayland_import_ = b.lazyImport( + @import("../../build.zig"), + "zig_wayland", + ); + const zig_wayland_dep_ = b.lazyDependency("zig_wayland", .{}); // Unwrap or return, there are no more dependencies below. const wayland_dep = wayland_dep_ orelse break :wayland; const wayland_protocols_dep = wayland_protocols_dep_ orelse break :wayland; const plasma_wayland_protocols_dep = plasma_wayland_protocols_dep_ orelse break :wayland; + const zig_wayland_import = zig_wayland_import_ orelse break :wayland; + const zig_wayland_dep = zig_wayland_dep_ orelse break :wayland; - // Note that zig_wayland cannot be lazy because lazy dependencies - // can't be imported since they don't exist and imports are - // resolved at compile time of the build. - const zig_wayland_dep = b.dependency("zig_wayland", .{}); - const Scanner = @import("zig_wayland").Scanner; + const Scanner = zig_wayland_import.Scanner; const scanner = Scanner.create(zig_wayland_dep.builder, .{ .wayland_xml = wayland_dep.path("protocol/wayland.xml"), .wayland_protocols = wayland_protocols_dep.path(""), From 3a4f7b3d0f960866e9d1038c4f4ee79ffcbab2af Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 22 Sep 2025 00:06:51 +0000 Subject: [PATCH 51/77] build(deps): bump vmactions/freebsd-vm from 1.2.3 to 1.2.4 Bumps [vmactions/freebsd-vm](https://github.com/vmactions/freebsd-vm) from 1.2.3 to 1.2.4. - [Release notes](https://github.com/vmactions/freebsd-vm/releases) - [Commits](https://github.com/vmactions/freebsd-vm/compare/05856381fab64eeee9b038a0818f6cec649ca17a...487ce35b96fae3e60d45b521735f5aa436ecfade) --- updated-dependencies: - dependency-name: vmactions/freebsd-vm dependency-version: 1.2.4 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- .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 2099e1d42..3dc2cd6c2 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -1000,7 +1000,7 @@ jobs: sudo systemctl start ssh - name: Set up FreeBSD VM - uses: vmactions/freebsd-vm@05856381fab64eeee9b038a0818f6cec649ca17a # v1.2.3 + uses: vmactions/freebsd-vm@487ce35b96fae3e60d45b521735f5aa436ecfade # v1.2.4 with: release: ${{ matrix.release }} copyback: false From a63864d8dfca1372be91472ad65d8503718bb239 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 22 Sep 2025 00:07:00 +0000 Subject: [PATCH 52/77] build(deps): bump cachix/install-nix-action from 31.6.1 to 31.6.2 Bumps [cachix/install-nix-action](https://github.com/cachix/install-nix-action) from 31.6.1 to 31.6.2. - [Release notes](https://github.com/cachix/install-nix-action/releases) - [Changelog](https://github.com/cachix/install-nix-action/blob/master/RELEASE.md) - [Commits](https://github.com/cachix/install-nix-action/compare/7be5dee1421f63d07e71ce6e0a9f8a4b07c2a487...a809471b5c7c913aa67bec8f459a11a0decc3fce) --- updated-dependencies: - dependency-name: cachix/install-nix-action dependency-version: 31.6.2 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- .github/workflows/nix.yml | 2 +- .github/workflows/release-tag.yml | 2 +- .github/workflows/release-tip.yml | 4 +-- .github/workflows/test.yml | 40 +++++++++++------------ .github/workflows/update-colorschemes.yml | 2 +- 5 files changed, 25 insertions(+), 25 deletions(-) diff --git a/.github/workflows/nix.yml b/.github/workflows/nix.yml index a3d87f04c..d6e06170c 100644 --- a/.github/workflows/nix.yml +++ b/.github/workflows/nix.yml @@ -42,7 +42,7 @@ jobs: /nix /zig - name: Setup Nix - uses: cachix/install-nix-action@7be5dee1421f63d07e71ce6e0a9f8a4b07c2a487 # v31.6.1 + uses: cachix/install-nix-action@a809471b5c7c913aa67bec8f459a11a0decc3fce # v31.6.2 with: nix_path: nixpkgs=channel:nixos-unstable - uses: cachix/cachix-action@0fc020193b5a1fa3ac4575aa3a7d3aa6a35435ad # v16 diff --git a/.github/workflows/release-tag.yml b/.github/workflows/release-tag.yml index 89b4c2f49..e90e79261 100644 --- a/.github/workflows/release-tag.yml +++ b/.github/workflows/release-tag.yml @@ -89,7 +89,7 @@ jobs: /nix /zig - - uses: cachix/install-nix-action@7be5dee1421f63d07e71ce6e0a9f8a4b07c2a487 # v31.6.1 + - uses: cachix/install-nix-action@a809471b5c7c913aa67bec8f459a11a0decc3fce # v31.6.2 with: nix_path: nixpkgs=channel:nixos-unstable diff --git a/.github/workflows/release-tip.yml b/.github/workflows/release-tip.yml index 015e42c89..ec4cf5a07 100644 --- a/.github/workflows/release-tip.yml +++ b/.github/workflows/release-tip.yml @@ -34,7 +34,7 @@ jobs: with: # Important so that build number generation works fetch-depth: 0 - - uses: cachix/install-nix-action@7be5dee1421f63d07e71ce6e0a9f8a4b07c2a487 # v31.6.1 + - uses: cachix/install-nix-action@a809471b5c7c913aa67bec8f459a11a0decc3fce # v31.6.2 with: nix_path: nixpkgs=channel:nixos-unstable - uses: cachix/cachix-action@0fc020193b5a1fa3ac4575aa3a7d3aa6a35435ad # v16 @@ -168,7 +168,7 @@ jobs: path: | /nix /zig - - uses: cachix/install-nix-action@7be5dee1421f63d07e71ce6e0a9f8a4b07c2a487 # v31.6.1 + - uses: cachix/install-nix-action@a809471b5c7c913aa67bec8f459a11a0decc3fce # v31.6.2 with: nix_path: nixpkgs=channel:nixos-unstable - uses: cachix/cachix-action@0fc020193b5a1fa3ac4575aa3a7d3aa6a35435ad # v16 diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 2099e1d42..23fc4d2bc 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -76,7 +76,7 @@ jobs: /zig # Install Nix and use that to run our tests so our environment matches exactly. - - uses: cachix/install-nix-action@7be5dee1421f63d07e71ce6e0a9f8a4b07c2a487 # v31.6.1 + - uses: cachix/install-nix-action@a809471b5c7c913aa67bec8f459a11a0decc3fce # v31.6.2 with: nix_path: nixpkgs=channel:nixos-unstable - uses: cachix/cachix-action@0fc020193b5a1fa3ac4575aa3a7d3aa6a35435ad # v16 @@ -107,7 +107,7 @@ jobs: /zig # Install Nix and use that to run our tests so our environment matches exactly. - - uses: cachix/install-nix-action@7be5dee1421f63d07e71ce6e0a9f8a4b07c2a487 # v31.6.1 + - uses: cachix/install-nix-action@a809471b5c7c913aa67bec8f459a11a0decc3fce # v31.6.2 with: nix_path: nixpkgs=channel:nixos-unstable - uses: cachix/cachix-action@0fc020193b5a1fa3ac4575aa3a7d3aa6a35435ad # v16 @@ -141,7 +141,7 @@ jobs: /zig # Install Nix and use that to run our tests so our environment matches exactly. - - uses: cachix/install-nix-action@7be5dee1421f63d07e71ce6e0a9f8a4b07c2a487 # v31.6.1 + - uses: cachix/install-nix-action@a809471b5c7c913aa67bec8f459a11a0decc3fce # v31.6.2 with: nix_path: nixpkgs=channel:nixos-unstable - uses: cachix/cachix-action@0fc020193b5a1fa3ac4575aa3a7d3aa6a35435ad # v16 @@ -177,7 +177,7 @@ jobs: /zig # Install Nix and use that to run our tests so our environment matches exactly. - - uses: cachix/install-nix-action@7be5dee1421f63d07e71ce6e0a9f8a4b07c2a487 # v31.6.1 + - uses: cachix/install-nix-action@a809471b5c7c913aa67bec8f459a11a0decc3fce # v31.6.2 with: nix_path: nixpkgs=channel:nixos-unstable - uses: cachix/cachix-action@0fc020193b5a1fa3ac4575aa3a7d3aa6a35435ad # v16 @@ -206,7 +206,7 @@ jobs: /zig # Install Nix and use that to run our tests so our environment matches exactly. - - uses: cachix/install-nix-action@7be5dee1421f63d07e71ce6e0a9f8a4b07c2a487 # v31.6.1 + - uses: cachix/install-nix-action@a809471b5c7c913aa67bec8f459a11a0decc3fce # v31.6.2 with: nix_path: nixpkgs=channel:nixos-unstable - uses: cachix/cachix-action@0fc020193b5a1fa3ac4575aa3a7d3aa6a35435ad # v16 @@ -239,7 +239,7 @@ jobs: /zig # Install Nix and use that to run our tests so our environment matches exactly. - - uses: cachix/install-nix-action@7be5dee1421f63d07e71ce6e0a9f8a4b07c2a487 # v31.6.1 + - uses: cachix/install-nix-action@a809471b5c7c913aa67bec8f459a11a0decc3fce # v31.6.2 with: nix_path: nixpkgs=channel:nixos-unstable - uses: cachix/cachix-action@0fc020193b5a1fa3ac4575aa3a7d3aa6a35435ad # v16 @@ -285,7 +285,7 @@ jobs: /zig # Install Nix and use that to run our tests so our environment matches exactly. - - uses: cachix/install-nix-action@7be5dee1421f63d07e71ce6e0a9f8a4b07c2a487 # v31.6.1 + - uses: cachix/install-nix-action@a809471b5c7c913aa67bec8f459a11a0decc3fce # v31.6.2 with: nix_path: nixpkgs=channel:nixos-unstable - uses: cachix/cachix-action@0fc020193b5a1fa3ac4575aa3a7d3aa6a35435ad # v16 @@ -497,7 +497,7 @@ jobs: /zig # Install Nix and use that to run our tests so our environment matches exactly. - - uses: cachix/install-nix-action@7be5dee1421f63d07e71ce6e0a9f8a4b07c2a487 # v31.6.1 + - uses: cachix/install-nix-action@a809471b5c7c913aa67bec8f459a11a0decc3fce # v31.6.2 with: nix_path: nixpkgs=channel:nixos-unstable - uses: cachix/cachix-action@0fc020193b5a1fa3ac4575aa3a7d3aa6a35435ad # v16 @@ -539,7 +539,7 @@ jobs: /zig # Install Nix and use that to run our tests so our environment matches exactly. - - uses: cachix/install-nix-action@7be5dee1421f63d07e71ce6e0a9f8a4b07c2a487 # v31.6.1 + - uses: cachix/install-nix-action@a809471b5c7c913aa67bec8f459a11a0decc3fce # v31.6.2 with: nix_path: nixpkgs=channel:nixos-unstable - uses: cachix/cachix-action@0fc020193b5a1fa3ac4575aa3a7d3aa6a35435ad # v16 @@ -587,7 +587,7 @@ jobs: /zig # Install Nix and use that to run our tests so our environment matches exactly. - - uses: cachix/install-nix-action@7be5dee1421f63d07e71ce6e0a9f8a4b07c2a487 # v31.6.1 + - uses: cachix/install-nix-action@a809471b5c7c913aa67bec8f459a11a0decc3fce # v31.6.2 with: nix_path: nixpkgs=channel:nixos-unstable - uses: cachix/cachix-action@0fc020193b5a1fa3ac4575aa3a7d3aa6a35435ad # v16 @@ -643,7 +643,7 @@ jobs: path: | /nix /zig - - uses: cachix/install-nix-action@7be5dee1421f63d07e71ce6e0a9f8a4b07c2a487 # v31.6.1 + - uses: cachix/install-nix-action@a809471b5c7c913aa67bec8f459a11a0decc3fce # v31.6.2 with: nix_path: nixpkgs=channel:nixos-unstable - uses: cachix/cachix-action@0fc020193b5a1fa3ac4575aa3a7d3aa6a35435ad # v16 @@ -671,7 +671,7 @@ jobs: path: | /nix /zig - - uses: cachix/install-nix-action@7be5dee1421f63d07e71ce6e0a9f8a4b07c2a487 # v31.6.1 + - uses: cachix/install-nix-action@a809471b5c7c913aa67bec8f459a11a0decc3fce # v31.6.2 with: nix_path: nixpkgs=channel:nixos-unstable - uses: cachix/cachix-action@0fc020193b5a1fa3ac4575aa3a7d3aa6a35435ad # v16 @@ -698,7 +698,7 @@ jobs: path: | /nix /zig - - uses: cachix/install-nix-action@7be5dee1421f63d07e71ce6e0a9f8a4b07c2a487 # v31.6.1 + - uses: cachix/install-nix-action@a809471b5c7c913aa67bec8f459a11a0decc3fce # v31.6.2 with: nix_path: nixpkgs=channel:nixos-unstable - uses: cachix/cachix-action@0fc020193b5a1fa3ac4575aa3a7d3aa6a35435ad # v16 @@ -725,7 +725,7 @@ jobs: path: | /nix /zig - - uses: cachix/install-nix-action@7be5dee1421f63d07e71ce6e0a9f8a4b07c2a487 # v31.6.1 + - uses: cachix/install-nix-action@a809471b5c7c913aa67bec8f459a11a0decc3fce # v31.6.2 with: nix_path: nixpkgs=channel:nixos-unstable - uses: cachix/cachix-action@0fc020193b5a1fa3ac4575aa3a7d3aa6a35435ad # v16 @@ -752,7 +752,7 @@ jobs: path: | /nix /zig - - uses: cachix/install-nix-action@7be5dee1421f63d07e71ce6e0a9f8a4b07c2a487 # v31.6.1 + - uses: cachix/install-nix-action@a809471b5c7c913aa67bec8f459a11a0decc3fce # v31.6.2 with: nix_path: nixpkgs=channel:nixos-unstable - uses: cachix/cachix-action@0fc020193b5a1fa3ac4575aa3a7d3aa6a35435ad # v16 @@ -779,7 +779,7 @@ jobs: path: | /nix /zig - - uses: cachix/install-nix-action@7be5dee1421f63d07e71ce6e0a9f8a4b07c2a487 # v31.6.1 + - uses: cachix/install-nix-action@a809471b5c7c913aa67bec8f459a11a0decc3fce # v31.6.2 with: nix_path: nixpkgs=channel:nixos-unstable - uses: cachix/cachix-action@0fc020193b5a1fa3ac4575aa3a7d3aa6a35435ad # v16 @@ -813,7 +813,7 @@ jobs: path: | /nix /zig - - uses: cachix/install-nix-action@7be5dee1421f63d07e71ce6e0a9f8a4b07c2a487 # v31.6.1 + - uses: cachix/install-nix-action@a809471b5c7c913aa67bec8f459a11a0decc3fce # v31.6.2 with: nix_path: nixpkgs=channel:nixos-unstable - uses: cachix/cachix-action@0fc020193b5a1fa3ac4575aa3a7d3aa6a35435ad # v16 @@ -840,7 +840,7 @@ jobs: path: | /nix /zig - - uses: cachix/install-nix-action@7be5dee1421f63d07e71ce6e0a9f8a4b07c2a487 # v31.6.1 + - uses: cachix/install-nix-action@a809471b5c7c913aa67bec8f459a11a0decc3fce # v31.6.2 with: nix_path: nixpkgs=channel:nixos-unstable - uses: cachix/cachix-action@0fc020193b5a1fa3ac4575aa3a7d3aa6a35435ad # v16 @@ -877,7 +877,7 @@ jobs: /zig # Install Nix and use that to run our tests so our environment matches exactly. - - uses: cachix/install-nix-action@7be5dee1421f63d07e71ce6e0a9f8a4b07c2a487 # v31.6.1 + - uses: cachix/install-nix-action@a809471b5c7c913aa67bec8f459a11a0decc3fce # v31.6.2 with: nix_path: nixpkgs=channel:nixos-unstable - uses: cachix/cachix-action@0fc020193b5a1fa3ac4575aa3a7d3aa6a35435ad # v16 @@ -965,7 +965,7 @@ jobs: /zig # Install Nix and use that to run our tests so our environment matches exactly. - - uses: cachix/install-nix-action@7be5dee1421f63d07e71ce6e0a9f8a4b07c2a487 # v31.6.1 + - uses: cachix/install-nix-action@a809471b5c7c913aa67bec8f459a11a0decc3fce # v31.6.2 with: nix_path: nixpkgs=channel:nixos-unstable - uses: cachix/cachix-action@0fc020193b5a1fa3ac4575aa3a7d3aa6a35435ad # v16 diff --git a/.github/workflows/update-colorschemes.yml b/.github/workflows/update-colorschemes.yml index 119f96563..5226b9ef5 100644 --- a/.github/workflows/update-colorschemes.yml +++ b/.github/workflows/update-colorschemes.yml @@ -29,7 +29,7 @@ jobs: /zig - name: Setup Nix - uses: cachix/install-nix-action@7be5dee1421f63d07e71ce6e0a9f8a4b07c2a487 # v31.6.1 + uses: cachix/install-nix-action@a809471b5c7c913aa67bec8f459a11a0decc3fce # v31.6.2 with: nix_path: nixpkgs=channel:nixos-unstable - uses: cachix/cachix-action@0fc020193b5a1fa3ac4575aa3a7d3aa6a35435ad # v16 From fdcaeebb9943f8057963bb97df94cfffecf8c011 Mon Sep 17 00:00:00 2001 From: rhodes-b <59537185+rhodes-b@users.noreply.github.com> Date: Sun, 21 Sep 2025 20:35:20 -0500 Subject: [PATCH 53/77] bind is-split property between split_tree class and surface class --- src/apprt/gtk/class/split_tree.zig | 47 ++++++++++++++++++++++++++++++ src/apprt/gtk/class/surface.zig | 38 +++++++++++------------- src/apprt/gtk/ui/1.2/surface.blp | 2 +- src/datastruct/split_tree.zig | 16 +--------- 4 files changed, 66 insertions(+), 37 deletions(-) diff --git a/src/apprt/gtk/class/split_tree.zig b/src/apprt/gtk/class/split_tree.zig index 3b6dcb4a9..35161b4d6 100644 --- a/src/apprt/gtk/class/split_tree.zig +++ b/src/apprt/gtk/class/split_tree.zig @@ -112,6 +112,25 @@ pub const SplitTree = extern struct { }, ); }; + + pub const @"is-split" = struct { + pub const name = "is-split"; + const impl = gobject.ext.defineProperty( + name, + Self, + bool, + .{ + .default = false, + .accessor = gobject.ext.typedAccessor( + Self, + bool, + .{ + .setter = setIsSplit, + }, + ), + }, + ); + }; }; pub const signals = struct { @@ -153,6 +172,9 @@ pub const SplitTree = extern struct { /// close dialog. pending_close: ?Surface.Tree.Node.Handle, + /// True if the current split tree contains more than one surface + is_split: bool = false, + pub var offset: c_int = 0; }; @@ -210,6 +232,14 @@ pub const SplitTree = extern struct { } } + // Bind is-split property for new surface + _ = self.as(gobject.Object).bindProperty( + "is-split", + surface.as(gobject.Object), + "is-split", + .{ .sync_create = true }, + ); + // Create our tree var single_tree = try Surface.Tree.init(alloc, surface); defer single_tree.deinit(); @@ -511,6 +541,12 @@ pub const SplitTree = extern struct { )); } + fn setIsSplit(self: *Self, v: bool) void { + const priv = self.private(); + priv.is_split = v; + self.as(gobject.Object).notifyByPspec(properties.@"is-split".impl.param_spec); + } + //--------------------------------------------------------------- // Virtual methods @@ -808,6 +844,16 @@ pub const SplitTree = extern struct { )); } + // Determine if tree has more than one surface + const root_handle: Surface.Tree.Node.Handle = .root; + const root = tree.nodes[root_handle.idx()]; + const is_split: bool = switch (root) { + .leaf => false, + .split => true, + }; + + self.setIsSplit(is_split); + // If we have a last focused surface, we need to refocus it, because // during the frame between setting the bin to null and rebuilding, // GTK will reset our focus state (as it should!) @@ -873,6 +919,7 @@ pub const SplitTree = extern struct { properties.@"has-surfaces".impl, properties.@"is-zoomed".impl, properties.tree.impl, + properties.@"is-split".impl, }); // Bindings diff --git a/src/apprt/gtk/class/surface.zig b/src/apprt/gtk/class/surface.zig index 087f2d286..e1efab620 100644 --- a/src/apprt/gtk/class/surface.zig +++ b/src/apprt/gtk/class/surface.zig @@ -275,21 +275,19 @@ pub const Surface = extern struct { ); }; - pub const @"n-siblings" = struct { - pub const name = "n-siblings"; + pub const @"is-split" = struct { + pub const name = "is-split"; const impl = gobject.ext.defineProperty( name, Self, - u64, + bool, .{ - .default = 0, - .minimum = 0, - .maximum = std.math.maxInt(c_uint), + .default = false, .accessor = gobject.ext.privateFieldAccessor( Self, Private, &Private.offset, - "n_siblings", + "is_split", ), }, ); @@ -522,10 +520,9 @@ pub const Surface = extern struct { /// A weak reference to an inspector window. inspector: ?*InspectorWindow = null, - /// Number of siblings related to this surface. This is used for - /// the unfocused-split-* options which are only applied when their is - /// more than once surface (split) in a tab - n_siblings: u64 = 0, + // True if the current surface is a split, this is used to apply + // unfocused-split-* options + is_split: bool = false, // Template binds child_exited_overlay: *ChildExited, @@ -630,9 +627,9 @@ pub const Surface = extern struct { fn closureShouldUnfocusedSplitBeShown( _: *Self, focused: c_int, - n_siblings: c_int, + is_split: c_int, ) callconv(.c) c_int { - return @intFromBool(focused == 0 and n_siblings > 0); + return @intFromBool(focused == 0 and is_split != 0); } pub fn toggleFullscreen(self: *Self) void { @@ -1526,13 +1523,6 @@ pub const Surface = extern struct { return self.private().focused; } - /// Set number of siblings related to this surface. - pub fn setNSiblings(self: *Self, siblings: u64) void { - const priv = self.private(); - priv.n_siblings = siblings; - self.as(gobject.Object).notifyByPspec(properties.@"n-siblings".impl.param_spec); - } - /// Change the configuration for this surface. pub fn setConfig(self: *Self, config: *Config) void { const priv = self.private(); @@ -1630,6 +1620,12 @@ pub const Surface = extern struct { self.as(gobject.Object).notifyByPspec(properties.@"error".impl.param_spec); } + // pub fn setIsSplit(self: *Self, v: bool) void { + // const priv = self.private(); + // priv.is_split = v; + // self.as(gobject.Object).notifyByPspec(properties.@"is-split".impl.param_spec); + // } + fn propConfig( self: *Self, _: *gobject.ParamSpec, @@ -2824,7 +2820,7 @@ pub const Surface = extern struct { properties.title.impl, properties.@"title-override".impl, properties.zoom.impl, - properties.@"n-siblings".impl, + properties.@"is-split".impl, }); // Signals diff --git a/src/apprt/gtk/ui/1.2/surface.blp b/src/apprt/gtk/ui/1.2/surface.blp index 35d897525..ad971e991 100644 --- a/src/apprt/gtk/ui/1.2/surface.blp +++ b/src/apprt/gtk/ui/1.2/surface.blp @@ -119,7 +119,7 @@ Overlay terminal_page { // Apply unfocused-split-fill and unfocused-split-opacity to current surface // this is only applied when a tab has more than one surface Revealer { - reveal-child: bind $should_unfocused_split_be_shown(template.focused, template.n-siblings) as ; + reveal-child: bind $should_unfocused_split_be_shown(template.focused, template.is-split) as ; transition-duration: 0; DrawingArea { diff --git a/src/datastruct/split_tree.zig b/src/datastruct/split_tree.zig index 212711e3d..28b45ceed 100644 --- a/src/datastruct/split_tree.zig +++ b/src/datastruct/split_tree.zig @@ -507,16 +507,12 @@ pub fn SplitTree(comptime V: type) type { // We need to increase the reference count of all the nodes. try refNodes(gpa, nodes); - const result: Self = .{ + return .{ .arena = arena, .nodes = nodes, // Splitting always resets zoom state. .zoomed = null, }; - - result.updateNodesNumberSiblings(); - - return result; } /// Remove a node from the tree. @@ -560,8 +556,6 @@ pub fn SplitTree(comptime V: type) type { // Increase the reference count of all the nodes. try refNodes(gpa, nodes); - result.updateNodesNumberSiblings(); - return result; } @@ -871,14 +865,6 @@ pub fn SplitTree(comptime V: type) type { }; } - /// Set the number of siblings for each split in the tree - fn updateNodesNumberSiblings(self: *const Self) void { - var it = self.iterator(); - while (it.next()) |entry| { - entry.view.setNSiblings(self.nodes.len - 1); - } - } - /// Spatial representation of the split tree. See spatial. pub const Spatial = struct { /// The slots of the spatial representation in the same order From 4e7f847d039bf4b3be721ffded46ef75521f3a3d Mon Sep 17 00:00:00 2001 From: rhodes-b <59537185+rhodes-b@users.noreply.github.com> Date: Sun, 21 Sep 2025 20:37:47 -0500 Subject: [PATCH 54/77] remove setIsSplit in surface class --- src/apprt/gtk/class/surface.zig | 6 ------ 1 file changed, 6 deletions(-) diff --git a/src/apprt/gtk/class/surface.zig b/src/apprt/gtk/class/surface.zig index e1efab620..24f247137 100644 --- a/src/apprt/gtk/class/surface.zig +++ b/src/apprt/gtk/class/surface.zig @@ -1620,12 +1620,6 @@ pub const Surface = extern struct { self.as(gobject.Object).notifyByPspec(properties.@"error".impl.param_spec); } - // pub fn setIsSplit(self: *Self, v: bool) void { - // const priv = self.private(); - // priv.is_split = v; - // self.as(gobject.Object).notifyByPspec(properties.@"is-split".impl.param_spec); - // } - fn propConfig( self: *Self, _: *gobject.ParamSpec, From e9c18ff6db5af72992b98cc14bb89fa6cf0dddc5 Mon Sep 17 00:00:00 2001 From: "Jeffrey C. Ollie" Date: Sun, 21 Sep 2025 20:49:59 -0500 Subject: [PATCH 55/77] xdg: treat empty env vars as not existing --- src/os/env.zig | 15 +++++ src/os/xdg.zig | 154 ++++++++++++++++++++++++++++++++++++++++++------- 2 files changed, 149 insertions(+), 20 deletions(-) diff --git a/src/os/env.zig b/src/os/env.zig index 1916053b3..8f01a14d0 100644 --- a/src/os/env.zig +++ b/src/os/env.zig @@ -95,6 +95,21 @@ pub fn getenv(alloc: Allocator, key: []const u8) Error!?GetEnvResult { }; } +/// Gets the value of an environment variable. Returns null if not found or the +/// value is empty. This will allocate on Windows but not on other platforms. +/// The returned value should have deinit called to do the proper cleanup no +/// matter what platform you are on. +pub fn getenvNotEmpty(alloc: Allocator, key: []const u8) !?GetEnvResult { + const result_ = try getenv(alloc, key); + if (result_) |result| { + if (result.value.len == 0) { + result.deinit(alloc); + return null; + } + } + return result_; +} + pub fn setenv(key: [:0]const u8, value: [:0]const u8) c_int { return switch (builtin.os.tag) { .windows => c._putenv_s(key.ptr, value.ptr), diff --git a/src/os/xdg.zig b/src/os/xdg.zig index 1383679fe..e120ed857 100644 --- a/src/os/xdg.zig +++ b/src/os/xdg.zig @@ -7,6 +7,7 @@ const assert = std.debug.assert; const Allocator = std.mem.Allocator; const posix = std.posix; const homedir = @import("homedir.zig"); +const env_os = @import("env.zig"); pub const Options = struct { /// Subdirectories to join to the base. This avoids extra allocations @@ -70,36 +71,22 @@ fn dir( // First check the env var. On Windows we have to allocate so this tracks // both whether we have the env var and whether we own it. // on Windows we treat `LOCALAPPDATA` as a fallback for `XDG_CONFIG_HOME` - const env_, const owned = switch (builtin.os.tag) { - else => .{ posix.getenv(internal_opts.env), false }, - .windows => windows: { - if (std.process.getEnvVarOwned(alloc, internal_opts.env)) |env| { - break :windows .{ env, true }; - } else |err| switch (err) { - error.EnvironmentVariableNotFound => { - if (std.process.getEnvVarOwned(alloc, internal_opts.windows_env)) |env| { - break :windows .{ env, true }; - } else |err2| switch (err2) { - error.EnvironmentVariableNotFound => break :windows .{ null, false }, - else => return err, - } - }, - else => return err, - } - }, + const env_ = try env_os.getenvNotEmpty(alloc, internal_opts.env) orelse switch (builtin.os.tag) { + else => null, + .windows => try env_os.getenvNotEmpty(alloc, internal_opts.windows_env), }; - defer if (owned) if (env_) |v| alloc.free(v); + defer if (env_) |env| env.deinit(alloc); if (env_) |env| { // If we have a subdir, then we use the env as-is to avoid a copy. if (opts.subdir) |subdir| { return try std.fs.path.join(alloc, &[_][]const u8{ - env, + env.value, subdir, }); } - return try alloc.dupe(u8, env); + return try alloc.dupe(u8, env.value); } // Get our home dir @@ -169,6 +156,133 @@ test "cache directory paths" { } } +test "fallback when xdg env empty" { + if (builtin.os.tag == .windows) return error.SkipZigTest; + + const alloc = std.testing.allocator; + + const saved_home = home: { + const home = std.posix.getenv("HOME") orelse break :home null; + break :home try alloc.dupeZ(u8, home); + }; + defer env: { + const home = saved_home orelse { + _ = env_os.unsetenv("HOME"); + break :env; + }; + _ = env_os.setenv("HOME", home); + std.testing.allocator.free(home); + } + const temp_home = "/tmp/ghostty-test-home"; + _ = env_os.setenv("HOME", temp_home); + + const DirCase = struct { + name: [:0]const u8, + func: fn (Allocator, Options) anyerror![]u8, + default_subdir: []const u8, + }; + + const cases = [_]DirCase{ + .{ .name = "XDG_CONFIG_HOME", .func = config, .default_subdir = ".config" }, + .{ .name = "XDG_CACHE_HOME", .func = cache, .default_subdir = ".cache" }, + .{ .name = "XDG_STATE_HOME", .func = state, .default_subdir = ".local/state" }, + }; + + inline for (cases) |case| { + // Save and restore each environment variable + const saved_env = blk: { + const value = std.posix.getenv(case.name) orelse break :blk null; + break :blk try alloc.dupeZ(u8, value); + }; + defer env: { + const value = saved_env orelse { + _ = env_os.unsetenv(case.name); + break :env; + }; + _ = env_os.setenv(case.name, value); + alloc.free(value); + } + + const expected = try std.fs.path.join(alloc, &[_][]const u8{ + temp_home, + case.default_subdir, + }); + defer alloc.free(expected); + + // Test with empty string - should fallback to home + _ = env_os.setenv(case.name, ""); + const actual = try case.func(alloc, .{}); + defer alloc.free(actual); + + try std.testing.expectEqualStrings(expected, actual); + } +} + +test "fallback when xdg env empty and subdir" { + if (builtin.os.tag == .windows) return error.SkipZigTest; + + const env = @import("env.zig"); + const alloc = std.testing.allocator; + + const saved_home = home: { + const home = std.posix.getenv("HOME") orelse break :home null; + break :home try alloc.dupeZ(u8, home); + }; + defer env: { + const home = saved_home orelse { + _ = env.unsetenv("HOME"); + break :env; + }; + _ = env.setenv("HOME", home); + std.testing.allocator.free(home); + } + + const temp_home = "/tmp/ghostty-test-home"; + _ = env.setenv("HOME", temp_home); + + const DirCase = struct { + name: [:0]const u8, + func: fn (Allocator, Options) anyerror![]u8, + default_subdir: []const u8, + }; + + const cases = [_]DirCase{ + .{ .name = "XDG_CONFIG_HOME", .func = config, .default_subdir = ".config" }, + .{ .name = "XDG_CACHE_HOME", .func = cache, .default_subdir = ".cache" }, + .{ .name = "XDG_STATE_HOME", .func = state, .default_subdir = ".local/state" }, + }; + + inline for (cases) |case| { + // Save and restore each environment variable + const saved_env = blk: { + const value = std.posix.getenv(case.name) orelse break :blk null; + break :blk try alloc.dupeZ(u8, value); + }; + defer env: { + const value = saved_env orelse { + _ = env.unsetenv(case.name); + break :env; + }; + _ = env.setenv(case.name, value); + alloc.free(value); + } + + const expected = try std.fs.path.join(alloc, &[_][]const u8{ + temp_home, + case.default_subdir, + "ghostty", + }); + defer alloc.free(expected); + + // Test with empty string - should fallback to home + _ = env.setenv(case.name, ""); + const actual = try case.func(alloc, .{ .subdir = "ghostty" }); + defer alloc.free(actual); + + try std.testing.expectEqualStrings(expected, actual); + } +} + test parseTerminalExec { const testing = std.testing; From a42193b997b562467fd714dd3405d1eaf709951a Mon Sep 17 00:00:00 2001 From: Mitchell Hashimoto Date: Sat, 20 Sep 2025 14:37:04 -0700 Subject: [PATCH 56/77] 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 57/77] 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 58/77] 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 59/77] 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 60/77] 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 61/77] 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 62/77] 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 63/77] 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 64/77] 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 65/77] 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 66/77] 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 67/77] 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 68/77] 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 fd9014952fce6151bd0070cabd648dbdc7c7227a Mon Sep 17 00:00:00 2001 From: rhodes-b <59537185+rhodes-b@users.noreply.github.com> Date: Sun, 21 Sep 2025 22:59:42 -0500 Subject: [PATCH 69/77] use getter to notify is-split property --- src/apprt/gtk/class/split_tree.zig | 29 ++++++++++++++--------------- 1 file changed, 14 insertions(+), 15 deletions(-) diff --git a/src/apprt/gtk/class/split_tree.zig b/src/apprt/gtk/class/split_tree.zig index 35161b4d6..69a4e40f3 100644 --- a/src/apprt/gtk/class/split_tree.zig +++ b/src/apprt/gtk/class/split_tree.zig @@ -125,7 +125,7 @@ pub const SplitTree = extern struct { Self, bool, .{ - .setter = setIsSplit, + .getter = getIsSplit, }, ), }, @@ -541,10 +541,16 @@ pub const SplitTree = extern struct { )); } - fn setIsSplit(self: *Self, v: bool) void { - const priv = self.private(); - priv.is_split = v; - self.as(gobject.Object).notifyByPspec(properties.@"is-split".impl.param_spec); + fn getIsSplit(self: *Self) bool { + const tree: *const Surface.Tree = self.private().tree orelse &.empty; + if (tree.isEmpty()) return false; + + const root_handle: Surface.Tree.Node.Handle = .root; + const root = tree.nodes[root_handle.idx()]; + return switch (root) { + .leaf => false, + .split => true, + }; } //--------------------------------------------------------------- @@ -844,16 +850,6 @@ pub const SplitTree = extern struct { )); } - // Determine if tree has more than one surface - const root_handle: Surface.Tree.Node.Handle = .root; - const root = tree.nodes[root_handle.idx()]; - const is_split: bool = switch (root) { - .leaf => false, - .split => true, - }; - - self.setIsSplit(is_split); - // If we have a last focused surface, we need to refocus it, because // during the frame between setting the bin to null and rebuilding, // GTK will reset our focus state (as it should!) @@ -862,6 +858,9 @@ pub const SplitTree = extern struct { v.grabFocus(); } + // Our split status may have changed + self.as(gobject.Object).notifyByPspec(properties.@"is-split".impl.param_spec); + // Our active surface may have changed self.as(gobject.Object).notifyByPspec(properties.@"active-surface".impl.param_spec); From 8aa4373aaf103d5e84aa78feed37493916c48b03 Mon Sep 17 00:00:00 2001 From: Mitchell Hashimoto Date: Mon, 22 Sep 2025 06:47:30 -0700 Subject: [PATCH 70/77] 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 71/77] 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 72/77] 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 73/77] 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 74/77] 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 75/77] 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, From f36ccc48662c9296c8b18fc3bd1329ba7c3d9de1 Mon Sep 17 00:00:00 2001 From: rhodes-b <59537185+rhodes-b@users.noreply.github.com> Date: Mon, 22 Sep 2025 21:22:53 -0500 Subject: [PATCH 76/77] remove is_split properity in priv since it has a getter method --- pkg/opengl/Shader.zig | 1 + src/apprt/gtk/class/split_tree.zig | 3 --- 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/pkg/opengl/Shader.zig b/pkg/opengl/Shader.zig index 8973ace30..1105e0745 100644 --- a/pkg/opengl/Shader.zig +++ b/pkg/opengl/Shader.zig @@ -23,6 +23,7 @@ pub inline fn create(typ: c.GLenum) errors.Error!Shader { /// Set the source and compile a shader. pub inline fn setSourceAndCompile(s: Shader, source: [:0]const u8) !void { + log.info("shader source:{s}", .{source}); glad.context.ShaderSource.?(s.id, 1, &@as([*c]const u8, @ptrCast(source)), null); glad.context.CompileShader.?(s.id); diff --git a/src/apprt/gtk/class/split_tree.zig b/src/apprt/gtk/class/split_tree.zig index 69a4e40f3..755b51e9a 100644 --- a/src/apprt/gtk/class/split_tree.zig +++ b/src/apprt/gtk/class/split_tree.zig @@ -172,9 +172,6 @@ pub const SplitTree = extern struct { /// close dialog. pending_close: ?Surface.Tree.Node.Handle, - /// True if the current split tree contains more than one surface - is_split: bool = false, - pub var offset: c_int = 0; }; From 36e09cdbe1e314c3ad565d7286e1265684071992 Mon Sep 17 00:00:00 2001 From: rhodes-b <59537185+rhodes-b@users.noreply.github.com> Date: Mon, 22 Sep 2025 21:30:03 -0500 Subject: [PATCH 77/77] remove debug print from helping something with graphics issues --- pkg/opengl/Shader.zig | 1 - 1 file changed, 1 deletion(-) diff --git a/pkg/opengl/Shader.zig b/pkg/opengl/Shader.zig index 1105e0745..8973ace30 100644 --- a/pkg/opengl/Shader.zig +++ b/pkg/opengl/Shader.zig @@ -23,7 +23,6 @@ pub inline fn create(typ: c.GLenum) errors.Error!Shader { /// Set the source and compile a shader. pub inline fn setSourceAndCompile(s: Shader, source: [:0]const u8) !void { - log.info("shader source:{s}", .{source}); glad.context.ShaderSource.?(s.id, 1, &@as([*c]const u8, @ptrCast(source)), null); glad.context.CompileShader.?(s.id);

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 Q{IYgOLiSenjR#Nv7ZOC=+5i9m diff --git a/test/cases/vttest/launch.sh.xterm.png b/test/cases/vttest/launch.sh.xterm.png index 59256f40e085e1c3b8d6810b6b78e39e7415a237..399e7089b88ac09976d7d279730bba00c8e95730 100644 GIT binary patch delta 4024 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 diff --git a/test/cases/wraptest.sh.alacritty.png b/test/cases/wraptest.sh.alacritty.png index 543d0356c1c45cc06c7aa64bc8a22fcd02b1b990..cc6001140dbd0300ac3a5427219ef090e1d1ba9e 100644 GIT binary patch literal 14544 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 Cvk)Nw literal 15314 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 diff --git a/test/cases/wraptest.sh.ghostty.png b/test/cases/wraptest.sh.ghostty.png index 2aa6797fe1012ccf267618265e1bb290bc259486..fff26df9ad56bb0fc6686876ecf700c9953f7307 100644 GIT binary patch literal 50414 zcma&O1z40@+crFi0tTQWBCR5zq_lJ>CEZ=pAfTi)DvE$~cXxM(q7p-QBQXpxbT{9c zLEY}>ecu0n_uj|hc5RjB9zzN{eD&A-V#AK(NKdp2OgPbA%O{~iZfk3_)i$4=od^5T{aoJW;sd{&#f>|I^=&t0w_J`Ny z-aqJWf8TQb*=0R;kHqT&0s--zGoO7*rrfghjv*pDfe>}6QtCn7h<)=rzy9;-;A<|> z{rN8NKiTP+s{AMI+;*F8ux*PA^|YZXE#-f|K6CSuYKGTyw5Hs?3Qk_1E2HSX5Z}MQ zB|8>E`>nF=Uc&vxzaLI^n}*PaN@nN!$>28p{ecf@UU>|_N?WsOdZ}qcKlJSh{4*;s zCuub0Pt%IsrV}-xO!<#>m4!Y2n)NN=54UvVS{<_@(f>7uD;b!|jrEF35qeB$xBq^< zQvJUNn~YWXud!qw|NHgAN@F)2LMbz^(a)qhb6cW=%LD=ufK|SlB1p$7q*1W1<|z&y zLp=(S<-BlFwI|40zuHBMM&a!n}Mzt3^5@0S6j)HPxKf(W%VES-`%%uzayc zFkX$G+6NYLzsfm?)wgV_-Yz>g=I*6F*wzcjBlf7lhU5&rcC!0cF9%Ld<`W;StXPnA zc5^opxh1(M-6!PD<=0|RW0CG!f!^edrj-zR?&-^T&n!1n?7*br^U7l1j3oEYow)mq z@K%DOxvUshBma~%)L3i7I5Cx#FjYATH@&`BKX#A&@l@Pfp7y!hlLvW38UY1_ymKv1 zj(Tyal+be1Xvr!z)5J#_FG)>F8F8oXV!}s{SaE;Mi|iben!g zWHF5d=HJxO8I%dt|8Nt}f?qen?qfUz!2vhvW_R^)ePScgA>A(5ez3RrAm_(A_A~4X zMhTqbaWSdc!&=ot`{L8(5jp?0-ra%1{2v`_Yk?R{rMHkn7JxLUda#ve*ylcOZ(4~N zGmy7h485DMQpO=BGr%Ctg0W;h_?H>WMD>?^ybZ)db}Ukbk7On__bTWYZ4iBFgWZDI^{ zxXOBL$Ia8_@9M`tVNk)Sj@+>zjbn_rb?v0PC&hnAI2P*#hdXw=8kN-vI%V5uWRtF( z{iv+2-U!+m)oEIu-l5;k&QpN-U)oKODHx=uwI*u5VmPnstiR8bbsRn98@CwXI5PYW`|DT1 zC%i{3ktS8^QmBBDK#j{VG$}vnE#s6eqL@+Rkj3NRyS+x|?YB*jgEq*L<9g`e`I_i# zltBfzn8VH9FPD@Y{1m)}?QVRG;dAV0>?WiIyd|ea!tfJ4Bl7+?X*P3%3R~KBWm<=J z6yT7adp_o%4T-&UG zo|cSDEn7jMDvE`Uw$VCZe=FXd=5ya0lMgSezpDH5v61fJyS__EGRC2^;aj_9(tTUj znwa!$WN1sob+++L-|dL&3}zWCP;Rek*ZR&yvRm}18}TQ(Zj~m{Nu(3KPKFZuRfZ{l zT=JDcuhvA~7@^m%@{c*2iR5ivBIaLE)Trf*E2K6wP&8g9=?I&lBh@n?GuIivn{a!i zj=fxZpie?#kaKA0b6-|2(NF=nh{Xp;aU^?5=cNW&+id8(Shg>!&a0gSNX!*f?e_O` z5+0U(q$ghVhDrBtC}1NtDW74h&^{kqTq9`PHRUVV<5Q{UzH9Swp@1Q^bO^0B{*7-q z64fB<^W?gIVuLPiHMjlN9h>|KH#f)-Gk;!e|>cs^+%S$b@%+G&NqwCjfeJLa6P>!xWCN#xPhsgTWhB)Egk zKxrMf(8)INtV+C|CJ5I7;ki(j(iKh|6iz3T+uM?E9mat^$}f6a`7HW}8D+)6hqcRS zw^8rR#BsThyC4R3OBLK;3?^$q^8~*Dr2qzXm3Yf9$O5c&0tv z*0cGwI-6@<>nbIG-`V$ya%kaI+k4zvDIwehVnfQC+hzy59?Ow>7JVu2c}mo!Z$YVr zt@rMm-ZpP=MJTFq2y*+oYSURwQS}K)yp!i%C>pnGJ>bjHMDE=VJBHpO&d9Bsb|0ss zrrp$~R+Q0r?Zyr z@|Ex+URR=e(~Kk++$IwzdHZ<}}f{qa9KR=V26NG{RG-JC0_+r?PSijHr; zlL=KLfO=}9*}oX9uWmiHK`2(ixy(7griB!D5v%(vaPcBHsNL7nUtbs1R1<5ZsFp)wzwl~P;7)IF8D4me zIeh&pY~q5S@_RSjCi7oEcXm63mS5pCc9tc%&>BEPzKAsq)5v3SD9-|4$>`)=UZom^ zI6hw&O|6Oj7N?a0z1{W0+s*@nS=P-Lj=C~b5aCJOyp2A2DJi!aXnNvJqFl?)#AN5E zk89AQo2w2C1sLIKq`Bie9d2r`tGdR}aqii=si<+Z=_#pk+wwWyz19=NHR>Q6%s?PL z6z`GbQuO;mAfkKaVb>vx{V|#&_ba-nNK31{DIO#Fa_AR$>w9P!yr-Vd`Te${U#7If zn!Mxc?Zqjzo5YJ6Bo}gxm5;X9u$HzV&^)_ZO>WI25nel+b?-Or82lu~M_gb`?qiuO zN2Q-iaf)!O7#EFw3!;)DfsoLqURk5;&aEp6-@*<*Q5e>PdW`z*6 zK_zrHe6z6!>%;(fLpVp>vuFHsBR){fZM=;8bfTK{vNJR-V$>XZMMpZktug`b8Q)s~ zeqkE!9Ev^H@I=dT5+u$wu-;)ljV69ViJO$Jp?>|wB< znxtt9WPbq&USLDRQ<+BC*w&0m{w?E0EQ&4FqZtgTIG#TkayfPIb01+D(Gad1kDC}yE^~Fq`HprUs&wsFJVgt4ls#T7 z)S4n&?<%x!4-DAb|BQZRY*TJ?_Fk1!AOnBV^N2CFGG)VzF?gYgXIITRsx*E0jVdnd ze^8~)M}>W<<(sUgb$u6QO!U@P|Bfs7qPMGBa>UEq<6HX|mAKWP8zBnv>Re+am(v1P zCkeY3Zgu>W4mVRSGy8mYQ3(y5&dY&w{Gpc;_}#%J$%8q+wD(FNLbkzcnvEB^@&Zyy z^AA=VMBHq2(K4wR*79$J`8wtzpMmJzYrG&^)+y1?S;)hWgL+87aUc_7K5OtOveWpA zA_dq*sD*>=n110;J-{EdOv@L^l+5qWi}uXxzY1}PqPekz2R{BIza^yt1?#F*arFAP zsE>pQ#?qrHv&ByFQmMOf(ZMUO6pwIr*s(ZtkQ~$2tTZfzV4_|(;OXuW)~iicF9_fz zz+R$tnP#o5Kf8z|mKNMOR=dz1&8YpYwNR-gi!?Hw@D^HPLzqbxsYPB}SE+K`!|;er zgI2MXwp;xL9F4&W6U~w*Y!%EbiJng!U42>ebzl){_`fiwljamndG%TAa?aB+F3J`K z4rrVb;UTMUn8Q_rA*J4=D5^&xPEaYrL7I}|Qygr*rRJ8v{LMl8kqATZWuZqAYB?B` zts7d!ub!>zpJb!cRkU?@jIs@+Bor}yzNm_t&E1#MPq7M?8QrHeKQvF;h4Buk@GM0?y>i{WP88i4HkWiMQFbCr~c#&XaKQX4p zC?ageQCh^i(y^+Zd9)G9`)qQUMkk_;C8rD?y;n5&IYdc+u1;v8saS58CPHFR3S5&W z4~(@7-gpe8yeFH`?57rXqK*E3NCJ)hST)QjQR*-j9CUNTMx|`1VwmDcawP$8iPKg( z5HkW{ykYrvISyu1S-kqOsnt2dXY%#rCxecM9cod;Z03a|)gpXjIa6;FD+mSxx8Shj zGSu$UnAZ-;G0pX-tUWEJ;o05LiVnIoN1)qL_Y9qgV-1p{p>eP$t@fBFHDkeQ7vVOu zw6x1l7QA&cPl=a%DeBrH4K|{!^wen_gK03^Rn1yAzf6<%`TLmqxLp3`oqh%8HJ<`T z1a(`Hke@D3^I@r&HS;!^^a}M9d8z1&PI4;p)o?Ve?J#-;ntP3Ay#jl;HAK~$5pcU# z`E_Q``FV3vpJ|O{giv9T1>NY~=wDXsAU2aGn7*=jk!WZrreur8^hSo24!3pz@502Z zCyrha1VUa4zkn_I%2CB9Tmyv(&g_ zX0FSWDDksw5^a#Pqs&=xv8&E=lLa=0PJ|9_<_X_$zbke)x%_nHXUFh7u7dEfX~$98 zwpkgD);YdGYxUw?LhsMruxSFb3W}~GGPSJBp&E**BD(PoQTn`vUjUEUGbjrbFE#wgknWZ%H{37IrM-Di(_VQLz-F)MDO^1B+ zy`93*uH*L|MI-YNIdR29+qcmKnv+v%UdDYcJqlVndadmvsEZ%1r zl#ABWwj=BvlTAfJ3D4%E21c9bw)LZ$t!<(vMwg1AlvAYL5;i%Z5Ze6wmyr)d2hAsq z^JkEpZJ6tD!&ND{X@mL5442sopov$0kaPak+O}!SC$TP77jhl0yc^e6l=*utq-}Jo zM5E&RYP0=MrY%Y3Z*`|m9`0r`!T^HKAb9^F53Q?WRFqv&oZduLAgEd(6 zb2_yb@xU%aKlgH4BeEO|CP(v`e3~1|5fF|5E;#irR>biuF{N0c*?H+a#m8BjREAMmy?lI_k&2kX!P$368&Qj)D!37zGbd%JW&2 zTg+_D%&ec3UKVOlHiZHzNVRmR$Z?cgCmxg z4GHanq?ujixL4?BNFltXLhM?4^r8vTt0z8uUlN9Ore1Uj!&cwlcJi<@aP_#hV2~yK zV2(Xa#{&YTuks_KebnQYW>;H3!+X_PmR1yTiY^@qd&NN_?FPMdWXy26(2T~bi*{iM z19fS0BtUZXv`D|RBt>*)xmaFxt!0HZ^B6>n%C3p0d>yP!N*Aio$|6*&8wCo>3O+3U z#iMVK9I4vQT`gq}hK7s<86N`!j=IvA=A~mbdSbO4r-U4eqxow+liC1jpT#?fD9}D{ zethbd^fF<-q=_lZi57!u5oe3aymn@>0=E9G-o92k)lQDPZg)ycqaK2YN2D5*ccxDE zbzoD*mjv6+`hxA;fW4S({pg#zIe5H$z+P16zaz8AQHZUM4fZCG!BSIlxQ2cuN4>e z89HvwEFCuJHD5b;6VRnw?PD^a>MZA4s9+rL#3_UMrK(2Z!yR2hVrugTiu_dj3bus2aV$Ng4Te*!qVews#7#t_uiMTu9#&%f9^OKyw)HCNZ&nk{eBuHA0Q&q;mCB4t6f z6CT5yt8@@$ea7tV6MD$R{7~F~jSCNMQ_Vu6TV|der4@oPFcULvEuP|J-Fm?63hB6r z`pn~CAW5Q!%%x1o7ubi9I}a%t{&)&LXG;F4tA?O;Eg!qMqUQEe&2ep+)<-Q}`Yxnw z7*-$wiy8>-ot&iN*3wV;H(f2*jGYElCg*1Bg5JrZb!+tN&0UL4L+@Qu4QBcKLJJgw z0J2Y>6}iZ#5)9A{YVRE0&gqM)+3mVqUvZ#PGD+LN$3QF$edpuTzt%Jy&$rU= zqQN7Q(E@ec{LY8nQ3sE?THt!l6|wal)SQKWKQ9@lXCh+F^U>IBR+#}ONj&)h zVuQ4#araeldzm6<-6^76?Y3!P)H2yy-!Q1=rmog?GDR z*3JfLFQZ=2iwZC4Z_V-TI(HaGheR>SMwBpwU*?zj4#O#|F70Qj8srevK(gY6TqQjg zFK4@uE?O9=(3AUW+R&j75}iX5?1y%PWB6@FZPf-PO(RcpVSI76G3s)s&R6f~{wfI8 zstd9GuF}w}aq9_-ENre{wd*g;peK(vrq1}0U|FnT_5H*}_QRZl+~S0cu-1>_>hrA!Q3Hdc`X88W3hRm-d8wOD z`!weXj#76`@j{F<5T3BJ3MJ>Deeb-K+0A;I9zmBVSM*dKwC@80ctDNhj)^RBb@lBU zeSW#HUElp-GYulx*T{^3XKV3UrGZWQv8#>8EXK9MRaIT&FQsH_E;0Mg$G^Wb;C--d z)vIdzy{$K#G7VAWtK~~EC&e?HSIQWX%OfBKBiD_h{?X;`mU=uL$dJHSq-e7QG3UtnCsq10~;Ty|DYTT2jEWAnz@qJZb zzdwmQ3M9#tkVCv#iP{OE=UQe66?ETY2m>fE%up1xTK*iJ4z3?&*J@{GY666Sx~PJe z*IeM23uPJp5osHe$p9 zWxT*W5>-t2(zDt8>ts3sxkKc%E<764bo|Phq@RF_o9FaLt}WWeuYZa~dV!7;zq?i; zQCwD_)q=HH{P{JvkJJ)&>WEXfuYi*)Il*Nsx`sF>-e0NvbI*rVI@i`yHeMInTkCV|(!?vD$KH9nTTYv1 zfw$tww0vR2wd@D^46$yR_fS?FbSVe6@>BD`#-B}Oai0NuRK&hS*-w0cg*-Afq!KPQ z7~0%7)Wn-|aKydc?Zy;E-N-C6;jWpiPs1A`2{%~Kl%ppWpFIrbmJ=0X%OyU(7BK(( zb-2;H`KaUX*wGgq9XLTj91`p7T|ZnG$J^ne77K_jxZyX$PRcODt8VXMPItUqjQTd= zqB^-o+4%0gy4+#h!HLiaUk7|=628Q!)k&DFaGFs%bfX~t4Q=f%N>t6vY9rNMiM&U? zwn2!gcq5O2M-T60@)PTy_KrR^Rw#g zM;=bJw#u(0!zN-VxV6v;9O#LrOP6IxW&&%BQ`-mF|j-Vw42oR?Iej6JK| zrY7L6(*+yhqf&S70OI#P09Hj58Rm;ny0Pa6$klSJ2x%2}L-&T6dmM5M z5D%Zbji|4I2$YFa+U9cL0T%UnB1_Klg%Y6HNNM`_uc=O0$}*O zegOr*b=|s#r+xPwlopqv&c>~$oKB%1?F?JR4yqML*^87OL8R`xqVj24|yCqR`Xk>f@#5|+rILb7eTo`cqHUdA3m7ls4 z$QofYOiiw;KRk#!Wvu@T{|6$M|3BdWqAIYs3Z6em@!H9NQkws09jj=KptNRHL9fJ8 zSr1w65e#rkR^@vXTtgsUqUt<=&~Q1d2MpcCYTkaLL9*ibO~7RS)1ek)XT!o9v|55T|FVuqeViqo#bs)S=NBG!7Dp8Dx& zp(?>VZeJ+PBRMnSR$Q-CC4JY|nlc@)KiY=v9~QeMlhBr8eu)x=eI~OusH-iMZf>@S zp+Zop=J22mT6Ok}%}fxq#ukovb3T7by4WXP5+loMdKbNVK|{USyrTHM&59CW>_t^Z zPdkX00FVSAD1vvMi)OS8ytmDT?N5mr>C{;X2EbmmQkJkiU+9+P_XU)yQS*%FYk!6? z+6B6;|7&cWi=QW7Hv0u>i z*Q1u4EzI3xAiIdJPBGz5mqdSarwY6B^uw=pC9LiTuPW?|ALHh@a*gD)E1364VjF5t z-RB4xXia+es~#ww8m9_zlE}EY5;V8l@_dB(ySl$mfAf5+>+)WDhM6_1ej?})XKMQDpfcRYUL;Ic~S(!&KZ220cRM0y{m>85=uL8 zjB$&?JE&ijXW_#dDm>5z(V;6{owbOs?5qr#NFNn;YHYCoVbk*Me1@eLe55sNBO_*6 zS#9IjCMX{3_MuRYSL%LsSzfmOT3lMnu=+Rgqx8|L#ge*Ff+mgGL+b&711SBdW43wD zU1vmWVqEHHAg?t&px>H1ZZ|VuDH4iWWTWb-jStZ~i;B;FA8D4r&g5ucEv{_Cutf`&!ds~ma zKsP&vzFVsp*6ECuv@zy**y2=;6=9_6Y=kkQVc;1{7skGEIQHRvR|pWfUdqP*T+|t} zi;Zh8F*jIwbJVrn-^k*Qss~)O=~~}b-zxJTidQ=uPHtKiBHTU~=}+pue-o)5qronW z4Nw}S9Lh>d010mAX-UvtM^s z+oMKn_#-X#!`jLxQt|CQtJ3&z0^Jp8Z&k&GYW=t4eEj=30ly{r!eiAW`@8B+S!GK} z_{ED?%sCJHzxAr@0~Z3Ta86NROZqL9AR1*w4{=!No#SgV;Y%+yEfo$Ayq?d$o>*>n zF1IrV0JDXvA#)-&ZQm6hG8vLZfN?S}-9I_;^c^+L+3rk|OsO~5Td(k%{O8&)v&){7 z?st;}mQ;P(=7Qg;)vGhUxV?5Zy)kYHcR@xPd1K4^?fal&J>@ubs!5Md0^+p(ofy{c zM^W_*VN6+H9NwI}!70EE#;`!T!R=!mQMi)5;^Tnnx6LjhrsI2#Pe`4p7^bwz;=#pW zclO%*m~ANDfQ$O64AAaL;U=rY-Y?=lab>1d$;YNOrL?mg_!6^T-dwf5Nti^ZkCsC*5hlrLpT*_di`*Q z{vp*VPe3I!O+kmZL|unpExREUKB3X}1ttHRXa2;?v8~cla9$~v<9b^_R^S+0rMMUeS3;SYD?HFf`BARd$t6Ez*LD>{dBW!ty!!W%i^!E*S&$ zzv9I&xB0);3zwqMuNsG8Mfl&@*?za!Et%1My24|5jb>?cl}N5CvKbY%xPJQr-SB-) zF0GTW6T1t!TxD~$&qzO3SrBnx;J>IB0}S_aT_qk0EFRy`{n8w%Xf76!1xOg{WN?BAfTOZXlFaRormwoWYt4J%1x4 z?2&-SK)LsE^UV{sYKN=Yua;m3O>-Gdr*_5t#xYZ!eFTi0Q}FMgZ14k|81S_d?gab< z1)p5ap~!g#F(1@*T$*Qb!U%CP_pqxDngH(?rd1+w=wcM;CU;)^8aoHX)oJP#;> z-;>Pbe+W)kJe$!NGaSBD9T=BC(*1u9E0yJpg2JKn6s7oo?jvZR3reYqE_O_CS0nKU zqCtY2*%AEWR7@2$(13tukdmgvJ+%%a4~Zs5z8_qD z?EI;=NJ-yh>w~0e*95BCy9kmM6Ln&P{t*)@=Ji|4M1)R)VF`k2Xv(j{$0PGyi-DGN zQv2hw6Q(Ml`i|_`1asH_C`Q$jJ1T36k9ERJ06bRS{J1#8CF;=Pc@o3gS zG_42a{-ypy(>|E+L!NN=BAI-`Y|(~O=7ZBjTN9&%fg&MZA4mNJ>B9xGD_;6hG2Q2N zf|(J)a}xIZY6Z5oKAOB@^&^ZZy#SV0i>#H1L7_0t8ez)d*d@vNcnJP!mCrWe_9d*s zcHeml6CzrLqeZ_fhmJ{9ulFy2T-A*wRIbX|HCnl8Ujca;2?(5`4W8xqHMf|5G?PY} zIZE;{^z926szEobT_S9yyJ5*u#fCn0W@~hQMnFS9iD}Q;UA%RCUEkSE=HYCkCQ#$a zP-4L*$WXm8`5~ayS*=R7eWehuWOqP{F95cuX-qF#X}f7HbC!-Q3f^|At5}=kE7!usyr&i zO(P$3JjXWWaW9%i^@t*;6T;@luiYOorn(iWw_;gccL%&$w^H5?&M&A=f0@do9+ zpCmPX6FI!?1u)3j`QvC+nSX@27nHwzp|D04{JPCA6zCijbL z*bK1sVZE7#1{_ir<92KE++>?q3wI4$$s;cEw}I$d*fMb9|G<7-d2Y)*(DM6cftDYI z7Vf;Q(3mhMVVNScEbjfKt9x42ng)mEXd~WYA_{#Q^6@(A*1Z4}At&4JY5m14uAa?Jxx*$sY{X&hmlFzGw>m!>FwC62s%T8d zJ@vNgVITcDMUOIff4<8cpMoS9dr#G7-SLheV#3=JY;2!fH!UBxl3=%tkN1Vg*gQV6 zJ+Kesiq5fVZ653)SprnPvp>gzKRiYwC_HydrhqUbqo=aIjE4Ft+{bK0Os6$2Q-Aw- zRZjq?IandCrG0u{JDJhmiohk`9B3HRsyGg_ZKtE?P)%PoSTmCEyAEIC1ALzg%ISjk zBXz05NjI21xwiH2Wc#!eWwrdACf6lY+3tC31?2Y)PS^UCa}?*lsw$X)sTz|XI0iqe z?Jf7_+lzO|Chwb6tA4rU>&i86@}eNnzt|=8_)QB@!S**AEz6;P^{_b0mG1ugQ2UiPUhSq8%PAxT; zJY71M<)3ha?MZgBd9y^&Q=+=GwC1~=NxDM+nLU}#xkfDu!z%o0dmBSFfdKLF>md_Y z%n{J=ul4ahKtVJl@%ati52mvQCt2T0+9DO>cn}6zgZx%u$C6UT$O{$%$tL<0)PiKQ z{bT3q%cO#2g; zMB2laBko*S3zjpGbU+5}c<9QAV^|mQUT5%$jqU6|Z2ll@!uHo-J-Ruu?~Swc@$+O~ z`3=0R3ssdlwJMoK(an=;@?6b;gN2ggwtkum#Odc0B-3O_Ab{3fstz$K8bt7NwXo!{ zWgn%At!f)ISiX#-0kk}u$q5IfybM!>Mw6Jhgta?E7J^#;tyfqtuA^ zalKvUv55{IY-tJeZ1alm%`|laijnR$HE9fVbmOMZl=?vG+iMHSq#eNij{NrC#x=f< zpFTMDnkf?5TK6zl^f{LcQLOi)?Ev44zC(l&_6rwjDqRo5e3)v|1IneS?Zs5wW5FoA zqox;Hk^GVrkgZ9u4o&w=2UK-ztAJ`jqQ=OW8-hx&g=EPx9Qe9gcgWWDA{hH5R=YnN zy<6vGO$J_o5F7pX(zqSGog;F*4s6t|c~RELqwHlUPtlTOEQkxyG7GUJc3!U5WK}4a zEK*sCOVjJ{s$tV%k*Rg%`d}N15Hah=$0sx>Aw-7(VCf}A`R!_m@*GlOVD+eh(Hh1S>~-Y-Dzq^o3)^y)I^ z%dO>!Jd1VG`q+#kpdcs#j|)HI=;igtjm%xUAOrF{e|#i=X@FA@*C5i_kl~A>dNIy- zWRb9{SeDXMYcLBSmGU~fmxyg{cgDTQ0!wKO4wUnCUEn8#mRBi(K82#|8{x%kg;&xM zu~G@QOy=jr&9~!tXctI8ZF5-TXE9?J3j4WbE5u-PdQ|-F$mZG;9+qzs z_QqEx>smcFtxcYt2b?QFVT|+rJTGhuf)Z!ik2nIbk3WK1#=xJgvOqqT45Wy;A}tL# zOo#fjog+q>d~`g@7$r_CAMDF1`wvD^={~S6R)o*Ij_GCWhd}kbfL6UYKuV%UKBs~e zGPY0@eDl3d#K^$c8=G&+rN6o5$^z-2S7N2i@RDkh&gO>JXa_b{%u|Zr`niAqqsanY ztb544?rtCiO?gOp^eD?PrP1m!Zq)pZ(wojOFs2oNht>5h0 z4<~V+0Vgi@9+#Tkb7#_b@Ccg;o4C;S!4+=y3Z3@WZXE-biiz5IAb#&6#qVmI&M(=pozC za1J$n^M-mKWny6Eg!E?#4AOn-kv4ik0tIYmIE?Xc_%nR~00i7^u|4Pt@Em+(b=0@$hd2`usJ>$TLbKhd>61(3B~;Gpdel zhqI&JSCOOM1Hs3?+o=9T2&i|cD3zhCJU-dcLD}X6n(0W(;Z{%>vwLKjCcg-JqNRm< z*d8m5JffiLHztNP@;6pH1=cFuofs2;Nvg&wR8JSQf2d@)3?FJc;x-t#gXki{)2;eV za22ndL2_*UUnUq8oMu0BO3+Yhc5}9UME)%xRExg~Ll-~Li)bz}~ z)%KVU^r6R+X9QED3{4E(AC_(FxAU zCf_fU@>^Nla%Ir$0{#H3dMDisaObPt`Uc zIj>z;ddvR7Bm2D~RJM6Vc@X95;&hfx8IooE3y{*}>V9&gnool7X{G6DVSBXyMkIi8 zB($Na&v--l;+7|kaoW94K%P1>X3H+CzCt+^M_-&NuOi{(@ z#L%ggG`i=uEG4M0-zGFT&*vOD7M(WTEWPoe=e&)AEz;cs^qgqD0fED#h}JXc&~nNW zP|&G%gLm-qJkn>-20^6CTwc*2u*2wDs0zo3yJZ{=5{5eZiaA$5SiD>B05l4|6Lm>dgDcnpa$CJ%x}W!&|>}%7(!;C55^A? zt9I4pzA$Fnyd!IQ^GJpfi9!C@+y8+yj+wIW0rj!6 z3|T~9rtUh^%6K}Q4dMuPiGds4SK^?H^=bIng*aV(UXvcHS~Oh~_fNPbUQn!9+4}*RR{Z8+wfus{yWXDzL(+Pww1KGbzN_zYRr|pjv>4fi^oeF! zf<0bsrSAqtrshAE?4cclCk?6B^ zQFYeI?3Mk{S04;jT2XUJymi4ngDkS|9VD#Zeqj%u{VN04K%IM%mMP88f#<4aq;gfX zWp;$?#!->bNbDmC#i(38C4Rw=wk4z|NtbUC{@szjl z)cnKo-t)LZo^t;mi_iB6n zJb-ELX;M>`*g4y<@LDq)>|Q5jG}Z2k%bd+18pL+f0^YN#^xkmJYz?ab$w-Gf3<*2D ze_)3*oe~kd4PfW9dOYF+jaJ^nlfx6Yq%Ou-E{^2&^R6sZWTJic#q03&2UE*K{Y|8g z9mklS@=eaN;5>W@gx$wonf#=?xP`Sj2KHh{%Y({fb#ib|rwjofqtT)WM;^XnZTIhM zBW#Dm$3XNXndm@H%ro~O?)a|=pKY-ey^HVvnJpkTp+;j|!P z;L}%gR1Xel+u(2fI?@PIc!}9slUfus1Y4@8>*lMFhaLO<#;;Mf|8B#f0_nbwO6%l>aoIR7BhV3dut&B0=!5(}mc|2ZNF&5-K~3%4D5 zZ=T{DWIsFA_h$9Y`>N01pbUDOK$Om%uULK_wzVnX|4Ph zIEl#K>-00(y$-;~MJrpUC3JV39{IZoAa8ElR1q>)?vWh+G4r&0O4A2r%=sC7gXwW? z+1ad(fG3qy#i@wr1bXHE;b8W^yKa7JCK#{D_&%V13R;))_f7;&6&d$&ob5wr zYYfCxOjT9T@0O^&zmpIGrXjUR-F$`ekz7}*40VluG`h_Tch%gh^YyM;*=u?Dl>8*Y z%6>b-5faS5vQKqQzkn$w#{EBu(*3?;{ztvxFGf2Ly$??UyyrijQ^57Lx4?mAKv?Ga z`t;wWDzQ=`1*HjdQ3PLQwL&Ctpz?{cv_jhPIb)D1;JK~klSXTE&T@aUy|3)RdwCO2 zicjcXEl#z!F#=@0GGsDk4crrk4en8s;r|1O02z9m5LXrQ|3ij6fOpHPOa>h!$2>NvXeUg*3a`jUUC_-P zgt&R#mt$5n%rJpiqA`1A0^DPuCZqQv&?Sw}*pL-KF{7ZJjabBUs#?3%bE)rHaC&sf2S(TEeQV zxjhQRW@v<(_KmKfo#JD7RYKF%!haZ&Ok+o^%qI{c!Ldpx7@BF+^xrDDPF2yPPf3Z< zz)+I&Us`(#g&O9-MSTc4UtKcwdolTi;VBestPSt(fd+q|UkY5nR26}W93pfxy4(%O zm^&y;(ze?+K&WnH2P~tWDeC7=W3Y;A<1;B(1Q_RFAO z<%kK~`4o{L=8PvDutIn|GNy;z{II>-TN}a)8mJdI{w7S3QXDpZGP%Kw65G4c9|Xnk zY4vZ)amhqElY~1)sQr>0r;>#!Tqa>ItpSFJSDkp@H<1b>mZGN(g*tni*?fSpS3m4J za;;w3gTNwC6l-SzL;j3ze6NA?m$&Bj8qG=f`!gGjPVHZuC9(RE4Gvvw9J_S*yT$SI zu(zz=^}mw4|Act{p-_l+&i^D%_by-86&7vtTimqEl3av0*cs`7JsCLcqRP+5sPK7r zC)Jdrw>HQe_c0cyMzq65zjQi{vlT^@WxIVo9m!iM*t8cFHalSh-Yjwskh`F#O4$t4 z@sSKD4JK)~QQEYkxx5untsLkA2?o8PN=YE5KzRf=N$e{G*pbD(=lNn40O?UejmlylhRgWOtqSiVehg+68^z`lrM#XLtuY+Q474}- zEFBcFh3u8>@93?IJBtF^izWl_;O|5aUfn0%gP;G|z-rb1FOv^zF?dKS@ZF-5*1SRb zPKIBi5TM1&_eQg}5b`H~%YrsIxqaxl5nBe+SXyE-Vb~$82CvTu*+C-$2_kO=oC&aF zoQA0i+IIo}ge!p*HWzzD*(_y!eOb0Ry59;&+9KYNwgO`wh*BBC!68X;o$0%vy>!%g zp|B~Q6t>R*;=9g)Qiy^Ww)MI|;Ko#;|3Ny}pSW$Y!{oOSUyt>O&?5H+fAzB-CPOJv z=N7EcMugM-cM2wXoexMB`57Xa>1mPWC2q-XXZp!iddRi+fVADv1*v)+?^mEBk!Xr1 z+ye9d^a!_vegv+Ac>=}O@@Pg#9SH43DXmu9yse|Dg&?YfhysO$F-Bhg5O4&^*^)hU zDAMh68vi8=@;S_-`fB)y!E*dMVnD^;7o>CapPl<}{;SJ>PBHi!{E*IDOxNLG=trjZ zNF!Ypn*NA%3O0348eh?hdKi*1X6*Jkj$4tL^SUVWG=ib+>Y7a{rsHgdL7U4&q=eKN@{!L;giMa@7Y=ovjMpf} z*9g0#GyMnLtuAzc!v>CC{(S81jCcdiYB<*Sm5#@^#mQ~KIuUMR-x%ezTzBNU7r}Yv zs)lR@CX)N$+PW&4^p1(L(;CNbL1zrMB)A(sKNVg!``1c?qzmiZM};_VKtCRPAI-3m zY7KMV>(@WJq-u2LuK9vq#mS@0y7UJt8bwk_8W%x8Ox4_V5d0*aHR6yoN+Yers~1g$jxWM{~h;`JT1N84^Jcg5-~2K zJ)Vds?aU>~$>YquT)0;SbfzelXQF)Rr9=1LxN#2g4vDwEoT%5gIr<)Z?L-)qQQJG9 ztEISWqOW7*OVuWvBrZ`)+Hb>!Sri$yt)hPI?(Ws)b*GIoriqij1{0&~hvDf`SB*S93O{+BS@jZ;Xx#nV!K8jAPE0zTix+V6Qj;XdeidyZJ^z7&n`aDTZ%vJ=-qHszeA zAzuxAt{eZ|-8z338Ankn{!gDvRt^n$c0m=B7DzUMly!x@D*ne~N!kU#en472IB3RN zEoacbLjSHqT;H*ZjZDh@vVUlp>}Ax!HPMv3$a8BJ6685^ugJKik2gq`#Q$nT3I0Hl zt8|0G)m4b`ptPm!y_?-{D5Lq{?!lJmi!WUlzV_#x75%4MtHPT#=C15_h7{0qtruhO z;xa^Z`GW3vuy00xS1;IGxZ9OGn6I61Yw;~l0WmnjBKmc)*=G!!|D&C?Vtae~inXu< zeLpb_{`(}Ip;goWA{_#!!7eH!YB1rWNA}Eky%BB@N4Z&s^p=*?pO}d9Jc%mKBPFGa zsuQDa;8>V<(|p9C97s|&IdzY_Ao%ucknr?>`nkX=5A<%LR}OQXH-X@E?l?BGi?+4~ zrWXNn3QoHr8n{{yfT|2S9GKr*n2#Y~RD!|8M-6mO=Dn3a?v>2WKkik+R)@3s?__EZ zEcka0wKv!hnKKcpnggC5+tZ!r1r3snRZm$)FJyZ@Jz~Z_4!LjfEL|-xAybNiDw-Ho zEMfg5z$vWfy$g<8SQWFHO4nl1te*&KBi7a8kguV-L~8X!Ke4vD6^?fF7B*=8l60lp zRxjo!HxD?+#^*Et#DkEdeWc;@`!obj2D6tkD>;TFk+eWD6R%5Cc;`|+ggmpLYeX|N z$gar0<{IpmLTGCH#Ok31n$p)KSKeZIV3vhT(Q?;A8*ZT3;?Lcyn5wu_iE%OQXA z!-=*3iwX#a2FRB}sbk~nAp1TJ=-oVVsT|7&oz*^2S9Xx2h{D_lO-(A4Tn8#fIx7|y2MMj7i*%Iq(kKygBY&j5 zh^I$HA=y(+Z^aLJ+hcP3nhxyrQF2ye2Y(|`P_9hmB*-t8Wi`=Mpwbk*1vVf8fm8U| zF9d8mS?)^}$AkWR{Gj*w>1c){yW6%%99|pGwSQSkT#{LPRa`mS!|`9p3rUf+b59^x z3o56aANyTGVWAJ*tAqpg_c{)b{vUDg9Zz)||BsW3QYfL6R6=&y4pNBhLiS4b-mK-g_P6P%@7#WS$C#;~3f5zv~<{?z{W*{rtYaKYoAee%ze*`@G-R^Lnn=Wp3pm z*bIV{-LCdYtsml(-?E$Sbum7-R3TUoruBg901&Z)in|uRXD7YlFUvDbD(;0!EI)R- zTfO&k7^iXik|iEp0t0q%Pe(k2t`>5B-e;&#SO3b~|uXPY~ zxCaFG3>t0<*JTNpyiTlK9GV0J%7Q5w9aV8SNMK?ZRhB>3RH~2{u(PGy7e43uM9BSF z^w0+l!yTdftoA;4wX{u<%0L8*rODYVLted%?+aFL2DRS)}x?yu=sh3EV6Lk$Iiu+iKT-V^Lu1^ebJ#0n!y~ zD3_7XkO#Pd1Mi{(+nH?HOoNhZF@jCRSo-hK8 zK5(w<_?eX4{sby*+M3NhS)gQJ_(Q?K#8OCrf(N<5tCZ3)$yr$jq9~SRNBt5$IUTae)kGP12`nD+M!fjCQHv zXA-Ju4>dOq8P4^-@1QtOFDYZVsSLX&0cpUz%`Lyyks98{UFvVeYB}a`=5uVMXUAyV z{HJR<4~k`HSVZQ!-s|5c{hX8(NPK?yP844kUeiopb`Y{&?Wh{cik2zplX!LTXw32x zk!$u3N!dHY1jKj_T}N7yT^5-Q<1N@oK+vm?Onf;SK+V-{fVnD{8qK}_gFTW*T+?-k zXK;MH&w>1Tdn$PVI^k3%nkjYO;%r*Yu0+sYjL`eVy+heeHtRA$Br)kpQw?DIL|Ngg`@0uNTpm*GKP zfuU&&UQWY zZVPoTYx$uA+%NQHe-)*(gs-LvYi^Z5<7%{32*J8LOOFqD_Bgss|)~oJlZN2KY3U|((#~;#q(C_q~ z^l|yEH)HK1t&1a8>aICRl5j9OrqoLh-q+-1P++juRiJ!31Df35~#%mwH&uYmy6KilG0m{r|alGZriiiHOl5mmZLY1`AZbdLK|is@!UalKDMC#^Mphmm*+0 z+5&JI&K{n`<1j4K+c4pbF9kOhS%!AIT&1Iyq-2ZRjqq#F9?H%j;GQw*@7}>k4ZL5uiIkjY}bUV(7VsDst7*Lk6uv}E7o_wUK?G@j}s2gfJ9G{k3s_W1baji>f zE)Yk4y)+M&m>;~kX(|p@1F|e;9-2%^-NKqwBoSW2DZ8&tuf%ZlQA5JeL%yPcuOR;lpXj@TP8@`)1vxqW!mQxPX zcRTINk#Vg}D(QNMk(x(U^L16M)yJsHIy;sc(XDWl+|x4i4%wJ?m}77*ElUrc?PJvr z2Io_2NhzLQ;*4^scI2zAjGNnZxr-^I37V!}j+}slp)$tZ z+xJpntu-A>G^MWIhG*p8lKRtU-v7=O)revY$Dmv77u!uCMIAYsgfxxImMQIe(~cQF zhDmORy;e&F;-j<0ysqgEtr!LMC6K0zhDD_>(YKvL4kqUr*<*U7cJf78dZ2D5Do0Zx z6#+65O&xB+NxiLQt*)CYv2w6TO6(PSa;nbfuiMw?q;ru!smPxf_m?!;v5T5|EE7_t<)p{9(`?`Ei~}KZDC+34fN2ZPf@zS)hrf+9WSF;;^Sx z?4viKO+L1TXak!^ePEJ@(6#i>*90_}htgW^+~~fc)2Gd7dp}l=4Qk3uHKI1yfUcj9 zM6Y>ougf(e>SDzy zsCkp9=;0{1H`j+$FMyZmOtg5aX5@}lg+$U_E8OB;E1E-)P1WDh;Rcop8N=TD4vz)| z2wA6>I|FF=#>P97hhcmm0%T( z>X!k*83f}B=8miq5xg5xMio^$*W{?Dt|dST(dmh=xz`;ezl+VrOdt#oedG=b7;{YS z?oy0-u(oPcLpb9$xe=S#M&NV+kdJa(s@=;p!*wua&kTXE`lZcdGgb7WdiIfeYVpI? z%F<6`n;w_kg6dJ)^Tq1U4!s{{w@;#$@cC>oR%k>NCv)>%d@7g+ZC8SNfwXz@=>)2`srsT zmEoSW>`iZtmmEIcGigql-(h$Ebzmze%WcdU>-mfu0ftu{5*43a z=j&nj#Sd@8Z%Y{!>6p_eu_9We{7`&VSQUVy;3Evuw7S#`+3P!rSqJ2k78IiPGf zI{wIz6DHz;Z~Re`hfFMzK&NJ3FHXJrOCmXd(5er9h$5FB?O{7TxVERq=Pn%YqK@rq*;e7&Fj)V zWDK?WiHz`?& zlxOu$%JeX{P9wG+!qeKQ`psG$vSpoylj*|`g~|tc4byulU5NQS(cP`uk=M5&$H-iw zSn2%zg-d8o6uQh_nJ$fsvaM)=9I^5a_3-f|H%;|KU(U0@N1Rl&cRjnQ zH*}%%?0}ru75fEiO7!Mog3Nm<4AaSX?HkH?(VP9l8xFxD*>Ce$mL(#?o@4~h^#-5P z;71A%w74TcMq*+h6l%H1n^*XR);c&+#y#%KW!qG1~7^u_ZQgvDs2a#NSE?(T)@7P?t|mH{muQpfwvMsEZ4#+ zjY|rw5pSfk!BjPs=BkG)_HzL79u|bkg^l-}KA+P3sfD$JVG|EylF@MMet>}um5ViW zrbVF93Ucs^?7=VEZI2zEZoA@-XMQWwy;LlUH#^QgLN2T^Lf!f}wVn&0gSz2@5N+wF zTTXs+U^wfrM^S^Z)kw(1dhg-`*p_{o&~@Y*tiUia`y3sMglV)fHT?1OBm!!>%I2?! zEbHyF#{a;+PeF#hixYicPos`^CvHwk-FN!pJ8v115P^}lN)1%1w9a)fr6W{9tUXYK z)ZY*3f74rOIcUgkq$sjMBuaHEm&VwEw1zfkJ>bYJ(`5%j+?VN+-9W7tj^8(L71Eo8 znH_Fy8E>FoJT-~m*Sed)vrs8#k27 zGKu`G>N!lu7Ijnv;N4*Hd+lTwauBezYNKA)eht>zxz(W4QgWYI&?8bxMe(gKgv)QK zqE7TO#i1%sUKvlThTQ0(!8dS>cy@k#VkJ0;L6gyxb0WDJh3cSAWUHQ~wzRV|uQ(=J z#v++1zg^opzl5+u_b@$HIF=xYdurMrl@R4ul=gIyu|d%rkIH0>Tw~;iixUD#r;!7$ zS#@}r;KwxZ`vP=7(3B+o2~wxN-gbg=-Wn~hTkBvWpXj2GbzHh+$^PS2@)yEkz9A}# za|(H($EvrT@`0~s&_q}tOs3@T#$Vw}B7Y;(sHIYKrQJdLEyvvItlo|UDoQTtb##`2 zg@U9Uuk#Qa7UlYHSlw#k>~5P<`--WMk&xu;6$`P93&RhIe2yF?rNAvL*;7lSTz| z-bXhgb%XLiForo3Lm%RJH9jQvw5T)g)Q|fIu<`m9;vY-E@w@2s&}9DV%g@+*o@${svLcE*WY?fp>O&0YJMvb~ z(-Az6xAWOT8H{ADl}aH)HI_p)91osmN_-V}d!#)IS=uzd1CdUwIC5^$B9?^MZYtMQ zLmAPn`)V9zcB@OnJmt0h)C4kEbTj^Ct$r;z_~3(;CSPk>S8aI|Vk2My>g7qU{P>mW2wdq(F7`fd28X#)8WNJ?q{vKTsRD+$ICM zb5jDV&bq>8%A1uQn7O1HsiFMJ05o1%egF&PvLj}zm44afA`30#nY!Vt;hLlJ&{;5) zV?uzs0fa+^T(e>v36af7xC-i(@m7nI6_?tk6&N@LUsKf#nN zp{BqqZt}e3x#G0veKfddV=@cGkkz6ZxO*ek>saAN=k&s`xHiFe=UO^%0rh+LLTv={ z0()n63r)#$-{#CNjrn!)ly?0kc&V)D$^3DHQyYxo=5pzzuM7daNurEmqe-ng%YIbn zOT?wqV)1Rn;t-Gzz`AI9*MNPe?TW_}jaw9%pTyUDG=#@Aq08GoR;dAAY6*smZNl6v zb5XZ%vz<$zcyC3WjzMV}ReP{>qz<=I@4j5c626N%$wBWiFCbi}(kn9~`#3DqGk&|2 zpKLFks$VAqjIM>KU@y}9E%5e8@hPWA4E;0+%)!|Lhq3>BN&K+dccneFyJyX?(qm>T zplZvA{ZDuabhU?Uj`FNNM)=fg^=X}VFvntdHNYHJ*yfFRq zIo!SHf77c*fZ(j%$kf_dQd!^RT_3RoH5*6awE|99fscFgC_(n;YjVg^g)o2prWxnu_bMv+R3*%NaEpiP#2eKgXHEusVG?i z(?ZyKk&lUtb)^Ip5Id`Pa47EZCWM;$fCz7SSXfiXM3P<#2F^s$5My@s@Ay`?fto+{MAqctq$fbV(=Z z%$E12(PrY6F?1MbLK#*z?0b4*Jznj!zL_nl%nGdQN+2_ck)O--6n3 zT#NpZ8^o*-He~gXef@D|D^B;s!d>|0E`_RYLLCL@6#V`jT&c~>y`v;2QBg{~{qcUl zGSRkTcG=OB`999Q2?}%d&BKY+MeZ->`(``6&XsHQO;G^WOo~!=4-)oq8 zNM3l&hxdgI(!%3n>2l{47uy^OQ$IE^?-d6Yc@$>r7p>t&;i)G9>N0&B<(0RBY3x*} z%N#m#67`{OTs-A!J=**Np?2yKSnJAs%fjs2NGt8q)`uYhld78mLHMHg1jIb;3+H;> zh8!3QmtqyO4xU>u^s~e|#Z-RMfBUA^+shp&bp9pZxv12VV%F`HyH>fB3m1kj$;eaO zBW0`A;8lD?jWGT~9>$4M4l?aAz|pt)$fU4L%Xg^HH7~BSNp*xpovqSF-COc$R)Rs^ zEZ+6AXz4SJ)!{j!)(&;gmStE=gT~8CY)Ov}T&Xe36X}}PW-w96u-xAUAkqmPKO z(xzcp+p99Yws5~-5&6c=;(!oes%CNo!JCx<5|4I=n|h3J*v-ySm!x9z3_1=U9d<#h zMddJ!*o<@GF5fIi#eIo99^_6s{wJ(K44Z`*YYOjYnY;Kt`FvQ7mvF{0W9uG0*HMf( z!ivV>xX!Ki60Zbh+5T<8hRvI;h+y=yiEoq}Fjz-wbL#Bv*+{02ahFs>n*S0urD_g@ zO}S@8+X35~LP-7=ux1qR-+SF7N7d@Oxl=RXt+c3t63b}#QoE2;lyO&e5vyH5H`C&q z%B@tQBfShNbng^O&DWuIN1`6UlES}VSLe~d2*;&=QnwiG50^^E5AQ08@v&-jHnp9K z>2ZJuLtX4{mfuExTl+xmk?85*M=9xCbPUJOpm1L9=;MG`|8L?W~BQ`W`yHO;Ij)9r4b zC|7Bd5uBcB1JATQewkespC{kj)pj-v3}H#%KL7-ro&ki-gi-DAbe{Z%)p2>;(kUwL zeMIC1dGce?!ugvqOMQXnZf}E}JQC|8-0IAl>;T`ylP_T?EQ-!j=Ez zcb~%UfF=|>0*tJdh9y{k8J*Q=0WX?vIKsDnL-m%>EpNnI> zGw_5KUMAW2qHt ztb{O%YP-W1UTVAec@}IPkOZrfg7h3R8g~#M;frGzO}n^%;JZ150^O$EKkyRtlY+B3 z3Q2~*LkxG*(FaGRt9Dn0-0USZWS@C|q=M5p{pKWep7-V3xYg-P`~s0L4gba08l9W7 zFAsJP<#sVJmZfrhd7Y2eedKCVVFn38tDJ8z?Ke5oyjRdxOTXj2g2b#Gv+pB2DG0(m z*38oo|4te`kBYjYVZQz{reZwvuQn(9uY7nm!)xeWW$Oz*ev*t3rYm5jO7-dykuSh& zN^g4Xnj$+ji`DZ=E{WZ|7XJL52DjP&+Ob<)aN2%$$oQ$;uB&^b1^j)HmFqx3VXZuF zhv%)yb|{-~uJf3=4%lvu=0jqJX!PjI`WEDj76K7(?-6AG6S9h?0c5Rtd(3Mgl^j-< z2KNyQ{tK~y=t%o6ZvaW>Pha^aFy%Ni{cQzoO8i?PZHCvi)C`Ptu856x!;Q z%pHq9#=DKV>!(Y5qh`8_^+4AJAB!N%5ih9!Q5hn$%Ms#St#EmmPjl?D3@KYMRlju2 z8K90O1zb1^7Ebq^dn}vfNqlSF#R*6f-aErX4b5z-2wgt&h3t5q{C$LKW*jo?G}L&D z(Av$tfFy}TgOKI0fwRp$5AJjK-T>JXS=KB^;Nb?(moP@-#4Vc&jl*h&O54-ds*CPe zEpzNtUlNOL>p3Mx((4AA_sI?1;X$2#(ro2pMuQXAYYPRw2-_D|RRlac|Fr5~V5ISK z8w*C^|94WNc?guEKjTNLTcP{|gls>|Q$}J+us(`!K``89hg%`7y>YRefYqLC?OfZp zfLFu#eLSiy^b4^QR|p-GPU{ylET>wWbPfLIAg?=<5rz4~Su zj-5=8@df&KUMSwsUYkEVzj>WQMz_+*mUvspE4qD#xZF2-O#v?7-En299Yh~kKPcx@HVri?&&d&i|l%5>2Pnm z)f4=_d~S~q+3?mpm8t2CQOLrqcnXSXRJv6sMQNPYSqgb3ZPJNQtv4dk0+@H+4?Hs7 z%}u>S4gBz%pe~N|{TkEbUZ4u(&Or2#bWG|ejA9P6aE0V|LW=`NHP-;WvvKpiH?wkv z-(p&c>)$0qY8>G7bNwzEZbuv+{QpNX%ruVph~U^1LKNRV2*p$s{)04GWO78=au6tD z9OjnCYY74|=z-;K$aWgcr;Jz1C9pU^Fk;SByqw*u{ea-46aFC&0-x)81Y^_%l)B;x3);NVM@#!bHUcK2HaoQx0X)}I)YIhSi%=wYUP z05YzoFr#$m-c^8B#0~-5eEdzwt`6;%Hx6?`O8!BdEC6w8mvEnP8sO?#V_V|Kd1ApTU7Q7Z zTji4H&n|llLs|+r&kf&^d@DDdR>`wu{Ss(|R_MQKgaTpv8eum>-%@m3uQrL*+lYR! zTw25=H;0BW01@~%;shKqebqqan2p)UxVeal?lh(E@@GU9a2ufLMi9ZEeDhW$JKfhF z%)?Z0ejL7u+TcBMSgpu+>U(N>*#Q?HIcdnZ2g(c)ZkuWYeWOEUuE+|mJ zHI@bPQf7!>nBx}Qb0}LtYz4-b{#WF|ktH`~L4Trtndt*nunIloTxp0d!DU*y0vvgf zd=!gK`pt7m1d30kr8>#aI_pcpJJQ7yYiPUF+IOCu=pVgE1qi7y0Qru-__A#*;c$-@FI}c?yTOxh3_Sz zIbCCcqr);iKAwV~&)8a@XDriV^BT!^^m?kYdW$kQuqe16LeQmnhvYRi3GA3Q+x7)R%i!kUl!8`(nB-ZD8D@H<)?Gpq+Wu=Cw zl;O~bw1Sb@ur))vJ5?K(NEzjlMBE?ZFTdQRNz@a(td-&Se#mg&*?RFAc)zI@fMFy1 zq7Jc6%H3392-)nRvPpgYBdn_Ej;^+uXLYZeQm4G~(Ee+JWen^Q4AfX}3&9MfP%R;B z2X?fuGgVps&AvUkPwk?!cW;&79*KA=mfi*^)yUUv0MvW$;Wbq<t^1ZkraeZ&Vb4^$xw*2)_5 zphX!rFTZysXq#LgbJz(r^}Gj$)pNPT!c-euxalv9_7*j3f7~`P{i4fkvgc%(cjui; zqA01FJv1GIZbD72%`X`YU9IT=&!fry4Tb~#$S1}0sgg&=&9FR+%#oLV2NY<)ejk2P zBl^%HZFRGPng)~HF`DD|`kfX(+T|Quxm|#yY8zX4e{zGehN^Gs(NdC3F@FVA4x7CJ zBG5@cd1bTDW%|l`|4{WjAg0@!IM<58`C)u~`0KZEYb|mFjw8QptKTq)xN6U~$}~&e z5eMhWY*nSopV8QV?eol{MNKj+ql?X(GutS!}RsxUIOG+ z%-=asUrqZzV;{Ar{J~5jt#IR(vM@U_WNr22$&fNWOe%;*)PAan-Ar+$o_Lp3T_V+D zpKKY8?E6#s(^5c|p-7izoyu>aP6!)YIsbuVHq8GBemM5r0+LRy1xHr^k0@}+z9mjO z%tiDyfB4#cNmTK)!P<%Sd^M2GvM{5`*=2zC*wd|Wx?=$4SmV6e8qiq3upl7#>H7S*9?iD z$+BCYly}jC&)Yvjh^uo+sJsSYk0P4FeG3fz0_d6@Io(Yh-iF>2c4*jWjZ(;av2{C) zO*P}{Ke-g7cJ|-8;44P+%GP?>X-V4KF`u0ifjkhy7JEBp1Y%Q$+gtUSWj}EQ1)xh} zgvQ##qWzl=-Hq)GC&7*JzQ*hoy|w1rv4PbG@h^WBh~5bj9e z&VnLsADJcEvfm^mM6*YZ3<8zsPW1&fx3qWgqKDBtJLm7%)!{CU64*5_e9>gFIP+&Q zBC$63!DXVCiAJPdH>f3gd>{_#UX#={j_wiefNH&)e8`C3_u(sqo9T*BlapPj7qq$yGmkfAgrWOnf*N=8oprspI4!Pk*z~Wf}@6J^_vn~cq)4B#S zK0+Z>{Q2pnhp=Gh$R2yD_imisX3D1@ITT3_!y#@r`q5Ww2L%xkh{G>Uubgkh+)YVJ zfn?3iwt=+jTKkHy9yALFe_-}V)<{?mw5;H^EK8EiyHO#1&01`JiOG?hWNHumS_ERrPkFsOLlHv{mqGfw5Ox{;0YpZ zsPhF+?23Z(lm#6l(vBZ176$mT;xI7FMO~km#&R6TfXrWLEH|Dnh)gjRtD&)YRbCbl zqL~|BW7YRf{kA#y&YJzCrC#+o^N>`?65B;$kYQs(m$|g*GT%aH+RtRZVIVL=q>^uY zK;hIM5DvSJ{kHpGc=S=VlUJ6T?VBdx3aw(M6DMl+aZv58SZ`9gPtal+TcKI;WSp~H z2y%pSOYHFN<5|Sn=O}|6Aq(e1vGR<8up@){|oC&*X-EyTJVYfH$g~@vc%FZ zTiC8f>JdcJdGjsXL`7tYYRn!%Bb=!!mS>RyXxKkKtDFAdYjtnT7}WfNJA@kV-24x9_>Ja&uSaBxSaDUdl&V>;#@O)lhY7 zJDZa}VM#@H2)udB+Flj}iYtvO*KeEG9(nx$rx(<+U9Y7MPgQu=OJ%Kb=6p&?J*w-^qKWW?QXt$G)z|`t#LO&Iw=e2ftlKlmijy~>jssvb2d-f9qiMtCmd1p zak22!hxI+@>}c*)=*K2LHcAzZudh@n6U)DuI|XXrC~QiO`ZP#XUa+Z8ul=3AWexmF zd|ZseCO!`68!6%!bS_9b{3G$PAAy_@>`{tsapWG~D}6uwDH-C{7QCH)FoYSHVYr|8 zhk!Gt@bxfLZ0r6R48}iOZ`iow-v5G)dElr7E*FW>oeX}wZWw1A$@_ADyyKUbzYBtS z$lOz33m-;bU<(5an21$aUl;Idz@qyk&<%EVw5&ufdnS?z>=S|2o#1}1zh`M(24k>u z9ckrDY|!3`HNV_U!bK*@^>BNBJbqxorZ6J1j)3jRdiqt+isF(084-5N@o$ucUI|8O zj%QHa+{P9P>+Wfc0}Ey}Y_yaz1IkiXYz6l@;St%bix!YH0#?3*I^X2)5y-wS#mL9g zA*(s#lhwgzR7q8@r}`dM!*5A#8AD{Rk?!k>Apgii4HQKrQQ=(k;+EMuu%ci}Afe7z zXn_z9nEgBa1+xqh>iGQxKzMHFDdRGde(#Ra?WN>vg5T@bN}D?oj`Vy=ge4<xcYZ;ty{3g4EZQ9r7NOM)bZ zbRGi6*vT&kl485gYyU+HvjN#hl~WDfyz(HXI?3i5$!KYBiL=G(Du20RI=f%kyQ};_ zZLZ8HV2izhvzF6&^R8bq!*tm4Tylo`e&7*B;;xyoR}bhNh?pa~lvN2V4UW8s*W3dT zsSqYcxtnkqqmy0XqfP<50x+JD!wExSbPv)z^-yc;hOl`rI^N$rCV`Xruk%_aqF976 zr@n5CM~4r9%bJRvM1WI1Mt4&jqw=wsw^iPF-@C-7oJ213rc76NDE?vt4cyBr z^4c5rg={FHsr`fhQC}Rc0I+BC>KE*p1=x=bxiFS^wnIO+N6OofeH8jT?ooGx zKtY))LLBCtYb^Y2{A_XV>{D8tQ+B@Km+tt>DeE)Hzb*b<;*T}}?1>JF6pYX3etn{# zx#3A~1tVEulTAzpRK)nncMA?+jN<96f6EZG=^6CH=@+?02FOU!v z?9)M-Sl&nZeYfZTmimvpsWzXp4x~x>9JA4@k1KK7q)<;`V3?^le^r)oNaf4TE=AxU zfoLQ02A$k5LMYmEN!07n?oEYKxy8-l)Zd~KKT{vmrXW@v=~iNN1r@aDfKw&cWPi=ZwgKWPnRGCX$Cm5#*kwPIs36ORUY}vLfS!C=lkikhWJHvO0n{sg74A0K zg22>IWcI*D@Ku%=V$~X1M+r&;!%6*9EHbZ_g@3*#j0RE3RC`FR-2uScu-hC~Sy_7l zf>lgm{ka!l#(~D$eiM-Enf+i9D-*1JWoA&2VUbC)Sa`7qDf^Zp7U{Eb3tvU^?s)=s!>@zId5PW8p(dX(Y%S%S}msCl3b65CFH#MOLY2$m`C#MQgq5OqaeeOStjkmeHB0MueY7N#JH?SFCS` z>#_V`O$?Y{_PEhdoTs~EGeyk{10Fg^^EL%YER0|K$ruv}T1c!q6BKpB5JS-I*y{Nh zj9V?QYHx}5cY=%Tonw#bN`Iv&TZ^^{mP*`r==@h0_+Ao?{@;*BH9|EYP^X_l4qNxv z9f8bDz2Jdx$;+o+H?}(dHBFG4wdl;?nGYUCJQoZ10wyTKKLRFQwALU09We1XK9chU z2*}pYWncBYx7|-nI#2w-67ZMI;|!HtFCYz}<+TG2iJ;}7D)BgSw=BCdaBspuzTPQ4 zIhuGsiOTRNm2)j!+~cbu&-|kJ3a)*FUlKE>O1;W2Tqfu3*v}2(QhmtdxP-}h!*j;~ z<l18)8oRs(4I|~5^Y_Xgm8ztvHxrn-rIwL7P-hO^X8dN9yr)SHX z?QZ}Ab?k-)yDPRXCuIvs<5*R0TM=7Vj7{SD(H%S<7NB7>D5%$h!m=n_T5?&w)FhKb zWr+Xg^`E5xoRVr}D(rWGu zLopb3`KC>QwLj_}O27pOt^<>M&42*chXFtK=UNYp;cs z2c(%+rKz97m9(v;R#`GYgHzOV6cg!d2siAj_KFymMFzyoiwyL@o560c&VM=LyK6$b z?BVGTaPqxwfPxF?2D}x+^1NEm4Y)E_e*I@R;D;{IM@9D2j$bUqenm-ev@rV4-}&MG z)Jo77$o7hn`8E;Z5oN=a|Jw_XB>HwuLR^$pu+aUu&ao zp0J$o@}xW8utFP`AarY(h5p)7Ia=0vi>})-D8hjp0%zQprq`BxROS6)8jM55#_{~Xu;u`saXNflo8Z2`<_cbx zxga(vSPl6B(@$FV{;wWg^P@6MXu~wNcOF{BYD&RIzS;7|E%{E*7s8pY`%vC;e{SnU z{I>%+>U1^!;A&dgg#Qhg_C98Z_25I7L_G(y$hjsAu7qQ4!_G6D|LoC~X(!3aTgmN} zw%=VG%=;e!^CNnizSeB;UL)bkyhU{hI0Rj)D$po1`s=#!{ZbN!4F}&qW!GJKn$EAu zNB>h(<@i6B3<7&O_eut-j(>|?F7CXDUAZ2CdWK_{KnY&{!8zdm%y`5h<&oi&J<|rS zjG7=DJUa{>))EP-)rZwU=JI~2?yHr)g=!#HL@ClBQ|kCyQq8_hROf@Pxvc`KW>lHw z@5bWV3^vk2Pzw9QMdUSE}WCYbrSn(*lMFl?IKd-_HZ(ljH-Ye~%6hTXCK?#{#2+bWqAd z^>XiXs`@F5ByW6`QKsjp8$TL_A-WxYzrp1{@|az;_6wu+P&jPhHi>rzuTSRH*LKeOXwwq?jjq$svbXZaH@K?XhT+g{cM0(w5vcyio>CD{vtATGII zH6QQP?iqJ31C^ijCl9n&sKE(<(`1(!m53q&K1rxch=M*B-fU8-K{iuyL-xbYxm%Hiwdd=fqL<&VCyH!HmweI+@3F^R z)fU-PQsFhKD$dmbX}f=i$p2PSeoF%QL#WcNV@Ecg*tCyrGPubwhzHWvOhVj1{~n%xetG}13ut~em?b z&>({f5CeeP;#@g#4{ojG@Q4XIy}lJ7XwXdLM?|`lQxs?VLVYJ%VSjuxySOKqR$9&= z$agZ-C}4cCbWx-x=;WBt=77cV0U*MDwJ{~T%yg{K%?FeUsOlf{!m#@^p@9H(@O-BB zbyXPusjF_3X>#jh+zX0Ln8ny58m%H^IF9e+*dLT7z-A&4yt7M|n!JiSI`f-pZK<8W zCjic8wl8eFM3gD|%X%7)Q!eD}^$`d>m9OyilP!F9N9f?HcOb^S-ao=;PKN3eR*%(X z1ABfE=N5t`kGS)i3@uSN3iU&EI(~7>kh&w_U^SsK>0Ari$Mm43jYydU>-lTg*hf#4VWh8r3q`i46snw2e4uJhR*vATOpP`+wCKrZS3MlL_1EqHsSZ+Y{$y$tNK0WpENx$mrNZ7c4h#R;CH zHAO4mQFBJ-zW)@(cr4(UHf2tK=Ozhdy6r06 zS0fJ}B^gZPfdUfEa92t|kG1;Wy-0-_tQQ#$RdTkZ+Vb`#UgjTdovR!vT-KiE3kN>jZeiHPvvo9UJr-(CUv5Cmxtc} z-pGrkC_W0xi?~Lf$K}6GX1SUOCbMWYSya^RO=gi@({-lVJ10o*{gv7%$gLtjCpNa# z(t)dtX+^@&Gy?YvnHRBX?HbE27cVPb{5~9j3P9j47I0(voSFwCg+YTl2&^rs^4+#F zA+HD9X+tT_#~C}{AmlsjLi|u8IF^Oy2G~d@piYLQ*_DuO2Av)VW%Ku(9nw(po~UYW zY%#F&f>1qm@co}zrZ|peMzk^T;VS1bq}48_F@4X?$P&o6S2;dK1i7Rguh=J=J~tQI zcBmRBYpW2vM_=yX^D)_(7ZF`S05b| z^&rnU*rap@(hW1K2~sU$KU?mHc&rOyJNtzOL#zA0MzvU?fnL0{WeaAY3>U|*wtkX| z*JMP4NJ0ROuk(t99hI$!MyBfAVh!FV1GL6dB1&aUhf9LR%w^~WakQNC^^u+}3oxst zBUSIIiaqgJ$Nh2CdfqD!U^gGSM$BiqGrehJDBHu+yfH;3j+~yct$Qh5ya099bK_; z#|aZZ_70x&$wi@>y_d5WJF!K-OaPmb_Yp^ZL$Y?S9XqO=AT9SvDhP#bH&9i;R?t_y z)GmW5O)-2d1WGg`>-2PBhZ;Me`Ln<$ixkeg`JT%pB(62gmkRx6d_^=Sl87Ho0%o>M z2rfar01f?e8;hQMG}PN3bR2MCiZ^` zYYbbId*NOohOpy%y*xXZ^GwL8(rUxPS6McKQV!#a&DC&hjt@z@n1_T;-W}pcrY;+d zD0={(@*mD6G8Ke&+W{bD9Rax(Ti8=Cj4tbCiP2Hkg8N&mdw=x80x>89@(jRC>TBZ=!CJFX@hcyM{rO&jY>!(w zw&PAs5HL^AQX~Wgv4x=e3NU5h+&gCQ&Wz@NL2gi)Bc-86R&@KJ%z1%) z4R~H~HxnGprvoi_Fa>U`ie+f?rZdc-?W_w9W(nSF`kG^gL5iL)+hXlRP0t?Byle^r zu?tqlbDU;&yF%5z_@hG%VjQG)=SD(SqH3`1j88+OkioST5S86lqiI_+gy~?56cxmG z#mh-PUl^&I=QHv=ZTzht$5i>>4D{AAzl$e`lJ95Mm^?k|B&Xe>EnFKMLRYo3sjLIs z2hbe)(W>}6X)UvOmo}9>XJ_;5sLMIiLdRgE8&)9UbA!;i>!E(gMst@UO)1K0U%ov( zqUP!xOp)YHc!D$}aAB|*^n5LJwW?zO(e%dnf98P-n#pdg0oEJ)pnp`%7 zEu$SIJgc$a8)&luEHfzIO1ay3_{d}19MBb#QHi9PzILe=oB?=~c_Di*`${?QP!CqK zrJa}@Qnk>Wx~Hu>;3fPVP){dBPC8p-$ibyuBWUQII|<5u3J=-`K`kD67FUZG#^8pd zH%C0`8YU+WIjY;k6CX(IRP_J(_z zAf-D?z6~$v=;R0=!hD@{JYKYqugDYTB6T^im+?hN<&pP;P_~Zo^|osc<}_>|;1O3g zEn5INj>BeOO+IJuuwjiX{m6RF>o+rlJV!a|H@s0%w3XUxe7iZ>yn-D&nyVnuig$lS ze-)$y92%ne^fz&&wTP*rU^LpA*;lY_Wyy+@`3MK)9I#wIUY+`OSxeFdidi=o;9 zx1Be;;1CIhP6UPzhLLY^UerhyTiQsut53ZBO3r%)Bx!H+m6IvAzePr8yRD4!qM>%F z2anCWJKj8w-bcx1H3mIq3&rIg9$Hn$)ef&+^aW!BPtr|TYl4t%hlu5&eLMB0-X7`I zqn$UPhguJ0F%<&KCp?LSnN8|^aMaYAtkum79n|pbn#@EXMi>*c>*cm~h)q?S)^*Fv z?(}J?OP9Y=NQu^pzK*|r=o*>MBH5LQ@7MKC;Jdth9zk~T4t1==r5nj#DTvMzNvTn~ zX*-sfRc0dmOW>|Ou6K${Q%afdFvFRdNlQkzAITe`E=s7Jv^@XjE!mzqkq$a!DP=mr)WN(3wYF!4`#!0n+ zjG%eQXD{a(-9V2=TaHip{--*7^W z^EI9xtDHSsk}|mQ<7>;07#MoYypMyK*r;JVUYOw{r&O=PFiQEoL~SO?pils6ew0R{ zvE$2-!kdr_0zx~tMq7$p+lz$taS>5MR}L~--j=ErSc*#MTR z$MURrpDqM&l7WjaS$Z^W@+h`n$yqWe8rBakJd3Zs&_uI_S)-1QFCuPu2(mu0^v#2Y zi*2<3r1cw$lFX&AYtk#o$17n!kn?P1F}(Rm9dH|TGB%E8Py2qezGz|Dk!SiKmVDLE zRKFuPFt=baTWvM{4TW(i?MRRLt9#We{@=)YIX+vnajeDCkiU$g#?SK5gp{pJJum1| zhkL2AMlDT!dsoyq#WahbRcIj3n%R4yp%2JE+$tFbRyX&lr5Rchsz%`I+r@6@2 zg^P_mCq`xcscyK|miF;4f^7pfGWZYR28fDa#E6+{FcKOlcs+RKO*rBE&#M zO;7~&{o$NBGv{3AT<3ky`>%fi&yS0X=YHbjbSUEXC&Qi=(~< z%cUp5;khBr5we?|Q_dandV}5DMGn)@LD>BLTUpVIAp6n&-svjDCA)~;$}|;Ia#QD^@~%d8Xe@zL7P(? z50iOXdC4oR2$ptY%+jxLc83-56v=~FsZ-$Gq~cPZp{MxRb(NJ>$0|UksmZ|>@_Ykg zsPrp#V__g_yX18pPxR>KL~SyD@+C4YukToCiwV*s=z?KXP#kxLUPYf4>KC`Ww>L8H zSH*oH8|`>_j=2}gPu82Rc4iA8{k)O1E5{&i&Xx+vfmt0%cKBFxFSP*&0^ylX;oxVg zWv3eWX_rS#sk2$414r4-s5wDeM~6V-!^N*G4lq$Yzp_}TG+J@fC!QqCEze7f>ON%9 z%j(PXt(5ai$Cd5E1i#ft+FHrG!}ORP9a8D)_FMUV88M96;X02lvc{Qa#`}rLSm1^a zm7he7i-m2*y>J@3}Q|^OeN;l|)(R>&JxdMt4U(J=`EcL39|U3qOI{OuZaJjh;)pQav1% zaLCrS$4OT?%E5|I1Rpr|02A@v)qvoXiNQpCAh3@bSiUm$bHNK6?iufvbR6;cJZtJ* zFdVooSIg-ot})f#KSygu$3EtJS7Nm~4k3*S<7!;CVz*9TD$G_VIrc+ogYWL2=fO`5ex3>pr=mZdP?^PVBTpOT;MAD~sMjB4Xbr&%%s}?*{NEjH=?3 z;7DeNX;1vABN}vp12(>xM(|hvTQfE8vSC~o*;x_EtiG5_b+?~X?~j!HNTLC|pbUOXS>D-=3VMv&GDtz~PspMIhXynr^8Rpi@+S zjpsfAZ}-nq&RRqzeqP9o1L_>WHSjuC;<_pt^*Fgxv-Nl$JZvf1pkqOfcdN`>BX*4kP_qCHkTgw@UBdWn&a-x?sr`x#e)sis#k zCK%z-l`>`0`6ZyIrYeM-XkcWmY(WFQ;jc+w=Hz3t&mG+yqXq(G%M)`yZ>V3(i>3}6 zk7N7nG9peE9HaCK?!EW1#oQa$bfrhG<;=}d=g;e-kXJ)USJGqLmv=z3nYDADvFl9= z!Q*H@R4+C%`c^+D8xFaNmjxz3-A=(3pd66ulN)JoI*`lh5}&(emhDTz)|Qnqn954_ z!VV}6l_*X{j)CpBqspkoZ^T=Qfp?y-h%N{0Cr}26f3HU8;8bP&dEsxTfi!yu6ikYrmEQ9Ot#tdc z1rwUWzgL8KKXgCo1y|IjqIG}n>1N(FnTFRUISQu|IWNtHawxx@H+sQe;kI7x&Bdcn}Ah`3PKGY3j9Gb3Zn2JatP` z&=+)5f6_HKP$TwcV{{TaWzyiZ5 zPmxg15#eT_Gs`90ISGWJ6q< z=h4W|fGh!~JO8fN&Izbi02;aa@j2pEkEaEC;(P;Hls9#W~J+>j9XwM`i$-H&vk58$?=qDSfRThK*5 znVL$daHhV&wd-&;)Pw<*4^fj6Xo4kcg#HY(!QRCMzzX0nzIBe5+j zPb>D&-OS}+IKUl?sIquC3c#N&_JL@CUAKa&vktv#6Y4cVsw^Akz)mzd76`{G`Mn3I6l@=~+cFMd|7h-4Ky)0nfwCiU!aT7Vvc=iAQDL2&k+c}JW0+d&Eviw3{Kq#{>yHdmDLf)?|o zBO}awu&9@n3us96l4H1LdY|YaPbww${q4AZh z9H5u|E97G_Iu_J5f;1{K3HL8-wI5k_V5f|;DiDC!%ol+^)bNiRSw3h~e%>rlzF!gl zBD~D|ovU!?;ndwjfkQ3tDho{GXJM4nhbeXTh;_LE?OSW-y;d=I>Ud#M&vHK%+~&~k z0#^Vck8OvZU-)S^gtxflCQ^4->#;&|YvmXF7HgOYezkX`M@EGUF*=#aeM5HQl$nIvdeeLupqHFF|4HmcLt! z5eAUE`)XidMs`5a@g_jsFCN5>X*=Rqdw%LIu^86!DoOqk=3Zmj8MOaFn(j0{`QvQM z+B-&c(u?PjK2g_%Qou0|XX`?m{6E|P2qBB9B{F3_Y)R~MCI5E7u@4B0juzDkGe!EG z6y#XGy1fSRFuj#qNz}emO8EYkU046iMT=f#^?QR;RL1`NMd}QG+#d*zwfkRZys)PQ zGEjYMnvmg0$+H!2H|X`xYf`&`~jf;|$Xr~Xe(xyC& z!|1h=FVVZQ9*p?!&P-|KiA?W4HT=%+PKclxCzTeQ zFpxHHO*Lt4@$aD*H3JG-^lcS;@CXRLp|OQDP>N=UN4 zliK@6O9p|21am6CNc#?u9x6RD3bHwfPCB?26mlhQET@ADBHD6ti3Gwoj-o)#ZKon) zv07Kuopj@289ec?@Q(7GB4r#Q(e-r!tXjAG>B#0-HIRcX09*7~%z6zJk(#yWGGYr_ zIxZ>Gm}#(<4+kR6%t3Y`&3B+>sqJA}hc2C3tc76bf8RD6K!@H69s_?xfjC z)Sxg9DW20ybcfbEb*z%#r0L!BePs|d`YiUaeN52!$#A!~gTcDi$%($=cgBcNMP3#g z!;I?$bSt?!n}Bz5^!ey=5};FFwR5cx>8$8A7s{=CKcrfd;vgnx&iNnG^iXkP-8ZHj zi}c9~8i96J7oLYE?@mtvs{l0ihs|XeWU{|`G;VCEYGimc`QAj-5AubDXLOC;_^(z9 zU=IHd5z*qz+FHTfYCo)6CT+0PZ7+42>+UaN9`hS>$VVA*KDE7+Z<$o}KzO4;B5sIx z;Aidw(~j@|Hz0x?Klc9sB5yNR!zK2kVjok%q{PJ-QeHI?@A5W@J5yPDa`C~KUc8KM zgZJP(lKyPcg})$C4H;+(=|~HA2Lx|GH&K(g!rZZE%A`}sfZfFbD^Jh7)MH#|ZC#vJ z`C)KqJCr{*fUmLoR}qQN`o9n<^jLs9UOIf{J$E%tS)_Ihe753^U87`0pbaGD>E)&K zlS}AgS)XLz4J(uNyn>HA1|YaWb~_t8dO zT+v7V2T{5L6wJV#>x>uEzC>pxttaID|0E>IQq=z>DEM}0*kd=KJB9|ItTXATj)LQ5 zqeq+MixlK|AW43jZpMLaGaiJ5+m~hg3p>5I2XJOd&f?zN9ZjUXKfX(lgI#oTP7F0% zoYik=bBnp=e5x%5*CBIUgAa+8fvZQ5$h)V`A@umgIt32rQlJ=TmjlaJ(}ocMkJvE6h7mS2VM7=E|u=??r!N8=?3XiK#*?fZei1cbcfR2aBc;B)aR}5 zjCY*xY=1b|dB<97&TGzjtw3o>Aw)PFI1mVgC?d=+3j#qu2Z12pJh%ru<3MYA2>f^7 z=!L`!5U3;^{z3-|`1`S*u&e|K`Me0^l}7*x3+oo z$Jlb>RM|r&;&xhza2B6s^JIGHID+S6l3{$ve_uskE_VOC zRW7>~1fzmeHnzy2G`2c*ylQ9VwpG}3Y(INUkC0q)59Rg|sTKpvW_Oef{gVIoVfn(M zPL z@Mt)5PLV(FG<++3!M@zMO&)2xxK5i!!Mq$7eqG9O_s&REDu{epA5jvTtMk-rN%F`C z7mh)9zbxDyQ|UWkIr2@=I=792`qyVn<-af%duZA#1RB{_)!x1Ps{yR`WnJv|tkvI!f#BQk5EgiA8*q+D zf~0%B-Bv2QF_TrH^yKy-YZD7n%rVO`?J81_G4Xl@9&~+KBIh-qKZZz+oO`XYOH+s!%K=f8r}*;kM`(WtYx%M+NQ%e{-d6qI?lQR%XI*Tt2sBUMN($Q55USQMuA(URe0#lA9+{ zkkM#;@jbEAK7C6nsTl^W7}j`3E*R8tw4na%)QpWG$xCt6^|Q%5?cqKN>uVuSwFVr7 zURY8cSauZt{^e8N1?_=#vP$ac$Z`w>#PS52_r&>HFfb1p(>A{FgIi{Y6AKe=PwX0u z({#3gzI}Z@_K|@UqR0>weHPW|ceFLaFhBF=E58?OB_k8M73-5uMkC6eV^yU$m(~dp z$ku6Zwh@xo_oOCwhDWa2NQZ3UbZS*DsS1)5ap5qJk_$-(2 z7#&yY^vIL)7a#J*z9p-ruOV|^ooDghMH$JHC{Za&oB9M7{M93*86vi*Li}LgU|*(Z z>^ZGsn2zbwt!O7l!ZhE3cVULNL-Xx7PwN2JUMR6w;4#vc9rb{G4g2yF=9x7F2#yQuxQ+yb8 zcki-(I+&Y%?CV3QhYhodUq2EsLJ#(1Rtk<3fj@{R3GKmCVYVCgeXx!bi%GPpH|JwLhmo@Q6bdk`S(8JW}ej6vI<9H@cOZw`%o_*xrkG(jvr#HniTdvD?5iSs~B zg2CcUf9Za;qV!&~J(|-AK~_G=oPnV^RS_H{I)+jXHk81qr#U1vWSHPNb=~gVYbn?U zLSE#ggM2POzlHsKwPB2A&tNnMyLoJrD62|>i_w~huSPF@SV>1XIls|O@0qa2kkm5C z-OQ9saaNQj7fX;xiaaVG2U=2BApA)M6^WNZ?hL+@8H|4e8GU_S^ooRF zoqC{Hp)6yARJw*;Pen!~OCg5oJfhff@fj%1Z*HbaU-2bQupPM z)kVc};2qq})SowA@@5&`iD=eVvEH3UWOI*%z_%$3PJTqG*h!Xf2Hk3NF!Ot z@kW)D=PFAStlSVMgS;#4s-En$NWTa7)uYz~-t(yP_;dw^=dyipq=@_TS4}1>aWpbN zMwh_!8gu_q0FZRj>!U@6x=!hcy=5aR_VNUN=8#pqNO0GjaE3^C9v* z8qoP=9|nfwnsv%N>>lx8skG#H>4LDMZ1mgZH{pgG6zL0V*TK;f;be3r$g7wrc)|lO3-y6pJlSA4gTx}f^b+gXbSjmb&<+))YFz~<{v`dRtSU6p=Mdm}u zohWqyyY(WfpU(o9)LVD67f*iObM#F=2`g6fGpl;c_rzb>R6NBa)%qTLN>V?wD@eat zT7^&Dl#I>``&djK^Jn@^ZAz{Q8=9A&irl}QR7uO$uCEqdh;oz;$Iz>NLpGY@%Hogd z2?++ZZ@(aBij=bWCC@;b?9%AoJj$r2h)jv#E#T&gsyz_M6kNhIMz|e@E>omx53F85 zLpm}^FAChQ;<=&_R98bjVm&6xMTx-$77Kf|uZ(2|&y(0nOc=)Vx}CzicCQ!dtH(R; z@M{Eb{ZUI_!Re~pD^r0jdlrI~(?j)h_YII}_k#S;bwk-Um%y}Yc_Q>cUF6K|0)c`8 zF9zxv?D|YkHPfCp(^5u$eau?AcXFOJ+x~DP#L(#Ax&a%a!08-~#t0(z`VO2Q@LCa3 zJ!`o(P{f}z<(VZZ{tmiyGt2!9mQ&f$?`}J3Kd8r?i+S9;KF*Zjs%q`TGDfU&q}0Qm zqGqShqNEggML;N#kx+KHJAhJmilrkJT@mz#BxFP8ee5gKQ0MyP;aVSw*yg5WZPeHZ zv=;~Jsn^6v(C1J%2*A6QS^~9tmpn-9egl;<{laeH$m+KYJubP)-V|hc$@hA!>bfN8 zu|?FH2c9Pd5^|)!+}0tKhvihxc)d-C=Nb*+L50(u6s|&0mjQwNskNHMvATGbWb|_3-NykG{UXDc zgg9eHXT<1*8TMsx%pLk|`cD_@qagCLYog2F9&NFWeaK^F^q2owF5)ht(d@Hnte)m8 zrK4%ZEl4pC+_OEjPJlD2r;i*JH~21$gwl;Ehw_n4^J;`#;YNtKt!#kO)%H^atKsUfe-UCAiUHlQ{m@*N0R3$iG}so>R$tcTKi#j6u+rSmTohO&iL|tIH{*R=?>E@P{w#+u)GwdX732 zP=Tmzuo|~l=Cw{bHxWT@#vb=lnk*Gp+7JUecjD>?fZ4{u^KsCdJwrPmaA#>>*(0F$ z^5IK3#zLqoi#BjAAXnPoU~S!!`+x*oKLZS958(Q}e;2UXi8U1nN#@*^Mi#5M)?U~) za>L3aCsQRrW+QwT7NGho8C#oS#D2ubY!Nc^Zk{Eg3Xd@CC<2L60wtE(pe|HVlav{L z!W~vg2;VHEek}eaJ@&5c^0fOGIu2M9U~OoQcH_iMTOo-HjFC29@ke)?$_Jl(Sllgl zq^)lHT=XFnX&TH1B2TkrG2sY7uh&mvEN_mojfar|kM&yEtdJ zLI`^@cqP2moe>M88Wn)vQKlWJgIhTz^*LNd}(ns4*o_X2S1C!57u@_hK{j4J8 zpEIlMoHKD`b-CG`-LxzyH~IIeWi<*Kos=4wN!bs67LfTkYAPU#K3_sexL?QU74yiM z#yyQmTP}jfERi%81rYghF#Cf{>bSB$u~91YzXQHWE5RaHsuT<5a1F+10s0%QvHAak zxyyT6*Srp%oy`eum(Yan2K!y}Y_Bot8(2leRCptk&Dat*FqQlMm|v?dM1-EL1J6IX zDGdI8E_VMZ3Ra^^-@?-C{|E)IuHM~Z90}VL!E}|T@OOnvW&ukgV%MEzsulNMe<3EU z8=4?XQrQicAAx+3jb2^h=Je)JOIAKV^5M_<5}7*$6pT42r%*VMHxnp_ptAc>i*0-e zQ=z9BbGPu>V#_g>fQ-t?7_SSl}vc@1Krt$ zZJ(S?<8IZROp^8Q6b(uJ`<`vuRVmjjMl|zmsGX7gok~U}mZ5BA5u}oh-FINywH*PB z=DFviZp~?}#tUtUC3T!ZopB@b1>j_M4uAaFohCE=rJ-X@w?s8NT7w~727A2f+2DYZ zavKBrDw6dwE9|-mj<8pz?JGIxkIL4xD)-Z}i$9+AfaH8CC9Fsd+Q%0 z@~@*t@{$|6g50N8ReUP?U{~}}7ZvSjd@0Axxq6ceSXj{?MW*yOp!Lqa09M3TW#duy zb5FIB(~}(AIZU*hqt!J8T2QafA|yuVK)Nf@^@$%trxVSJOX@YJuwHblbSAXJe3rBJa=>2ggN@ycN=V$9{`$$`LV*rF(#p3C0V zeFi0llJLv<7&Ylr&mz$}mRs^!tMD0HSt7+bmopD(M7w|wQpNG(OUFk^U+dZKSRF~=2(d(TB=$2H&b9z#Ky28pICoZSrS!C*IaWe~+juaWZ4!^9c zs|vc|!1LziP^^!wgh5|ek6)!&s3&~&-|WmMcL&JD3(5POn%d3TZ#E01L(|-Q_UiSQ zO7$^$)k!}_len9Dwj7sj-%qIKCwM}W;C&UF4;DI=6AD2Bac{4f63E!Z0*iDYTUP^G zrosOAM|hzK-^>drDZ<9ps*~G~^sw-&dfKCSK4JD8@3oT;*#S(^6szM;?l794h4_pm zI+9P3KqlMSJ&8H*<5yHy3W}`aE}X9vv%|=?^%31>B7JikB%0&mst&$_8K`~PrI%Q| zS+?{(z~Rux2p(=A7fmI8K66z#HzU5e^OdY}f!mO?9R(;w$a;(Vetx6EF|3lBta11p zCM)9K;l8uUDz|mCay8B*+V4CijxDp~3j9`gDI#E2r)XTy;~uFfK|S_oG1_zZC#H`= z&u;d0w8pNtJn7SHIhQm$RdJ3Do?7=Z*iLPJ&dDmN{;^NTTs|DzXKgiDjrjZ6ifk6M z*%t_4&>i9Pgd6aoCxzSA7mM1Ty6%Bbhx*GYJehKLeaVfSmSYu0XV;aS?rx@oEQ41} zlz`}?{`&p|-*TJf-Vfi47&z0)&AF0dt0CwPDH>>P3cNz5qHGGypq?55W23>t$H4XE z`-a5W)||G6gFf9(pJeQ2#fs+Tx7kT3RtFS^g(eY#-POPkqpom4=BfsCbH?RzInAGD zOiL{96(S~-#@dnJw_m7+7|s8iZaBo4vSNwOcBxbkJ{-Ke;H>TMM@A+{z3xq7u=XR) z^^EP<x^WXoxjF*F zJ1yC4G^rBLz#4SytjmCEKaqIlj=Je_2Idzcwonh0D3`M;Ng$NX=QFD5_RNdpK&t25 z8AU>Jm(t}(aQ-kA5z(=rao>OFLjgFPYvzH#^vJ{qG|Zj-XO}3o88W7e!C>Rfk!=+c z(#V^|{~}f8o-*RPjXp~_w^uNl#rD%z_gxznJLQwqv|!WoSczTb`3e|W7uTDk8VB}} zzK>;X*XKK}th8{@dUm-}JLjtTT5hfO5OOXowB>~_40%ZiQGEkSdi16$O{PMr=aegm zm4SmBS7D@w&dzjdVG~qZs()76=91qidOBJ|*4y1vt6208%UD^}d9#MVNu-ia)v9Px zTKdn0lGhhjUvxd+GJbwJ5t~0oU|>$0$eI<1)><2pA|+dM*qr&QP@j=0;;dr#IDcS% z90kV4qzRxNz1YZ@h6w3_asombBOPgC&DrdNFnFO`Ue-<0i;hjqqPixkN3{vdjF z^K4&AJok_EfHOE1;Bw%70bekf+-h^5R@cocDz?<)3HzA!MSJY$bzip&L_Wyzy%-6T zziM`HO+jhhl_zkSd>Bv95P8mmdZ&`sHpG(F23}{0zd~AP5sMryW-gm3GQ>)$8(&>ha zUqV!~g2DuILbdjx0+rY*yl6EIW?`cknb177C|Cn;7tQ0m>Edqy*%@PdYZ}3u{b=ey zP~e7eprGVDx+#{Dm>wEbPo@k+_I_2KK_r9p{Qd;RHQ>{g%PiK{8r9hbQ}MsK2+UgO;v zMZL~1E?gGL{F^28sQ$xo%ju6IP2CYzZBruHl%D-U6E1v+!D z9I9)yJMIGzi-k~moz`4{0$j1SZ?Ts8qK~qps0K!Oq-fo#V6x zjf80pT@yCyutwriGilFPL`jcIw3OI2ET#Q-1~UuZow&=!GFnyHFL73Uq6%g#%65cF zihUENElJ1dZ*47Z?2UA+?nF@iuc-%~a zuFcPm_Mf)Do3F#=hf#kU3?r$9II829&Q8p&^03%4ZbFXhse4~Un?u+zwdsH&9(1(8#HQU^o~^FnFwRk?AG z5JI`?_~w<2i+Irtm!oxx>>iDY(xZo~vOq-##td1LEYLEiqoztP{&*0}-%jsJ8CUkz z10e&_vD(-cwh8!L4zVDNSE{2ObNEL#vC)yMH`_+DuncyAT>R<`ke7K(jd#S&5K*R% zDImZnQxnSgySk6U4BOjjb%*$sIT1lBqiHA9VdrzSbEuA|%J-CyolAG=@YSLcdb;_= zwx+ktxy-9+s1`Oz>bA?BxmIy-(?KoAlbM`2-!ahFMxyjl>$zg;@{?nZcZgcLC9KdeFfJ$7 zb5DIPfHmEI^xT=QE3KrSN(*;ne%R{wv(fNA4B#bpji`A&f-&Wa8M!FNuAHk1)Z4M4 zM#BtNRf^ATp=mAWaxCw=jMMJ)l86g(sax9{j@evr8Bd3NO}nQICBV|m-~%C~*M0Q% ztj7gP02l~!=ezsGBK@EBjGyt)7O%6F`Pt6J!1#+Sx=#U+%K7+!yLSf{Ay zk$Yk?9a4_5#81~0o*irAARL2^{)5ePs$3nHo_+)~xfzk+XQ}Z}XP4?L#jM;~c2hI? zl*OtNWi<2bT*2dN<7b3PYH7I7tsiH!oL=cFm`$G%rfzi9c*Z&QSMu(?Ko1rivR8EO zsqjkIl_a6hWGo3xuJY0n(?tX7`|W7s<6$X04jhw37qmu`s#nMs+e^a_x6(v(Yb1X9 z05&^MXZzZ-tL>YWR9qaj+Zd4Cks}h6L@_@$RERB)Da2aNs8eRn8;c8;?lUuI;{2|h zj2`@uR>;^hdSR>_e$6c~PzlPCc4Nm%$=^SQ@qE9G zKT;$y>#DMgK&sb0sd*J~uDU1B`eStcsj%cPyJ8u^BA>wbU~L(x63`!73hzf_T;`oce;P3)CBxU^0oX{lB6uYKlacvTlIqLT|+; zX}^Jf@|Or>p~YwggG*{l6mnj_#u%4u7W=y{!{D)A{Ixf&^%>1dD|zgLz8S34HPNY; zeN>rwtl?CT8OJ>0gnSpbMLyfM2r)Wf$k-elm#sX)*gru9WMX?LvyS;q#Sin;*@d<> zb%(r9v!c&vpdtZW>g*q`D4CH2_no@JQWk)t`sZKhy zVD3*UW88hKX3Iwb3ohUtBjG%#p3fV@9>mY)7%33I7sC0nxTg>rB;P%~^(JiT3$;U7 z$*p5go+iTg_<2b}BbCvp^o%?7WAYT>TG^FB3sP9=BR>k&KZ9{|;`brC0Xl_rP^_}~ zd7_1u8CK@RPbnwX_EX9Y?dbx`g2ebu+dQw6KioVcyu5~xKQul5z*7p*=aw6FU8mkt z{(yVqY-=yla#xin`yDc&-cgmjQt0BEb8StlOLcWspNc{}y_{uHHdoDb|8VA>YMSk^ zCkE_eqqch%FQIiAX0AM;D+K}n2Q6EzCX!qwS#%-s$oH0pbrtojAmocBl*gM_7k*2t z59exQ+?Hu%$+&JxjoWedCX|Cv44dy0Vr_puZIAQ^M&{w z26bZb3cT4_pRt3W+2^|xDJocc)Y9^#Cp*iNvljtiIV+{cm=)sXj+L3mJ37-uk|dF- zt*P5PP`jS&&Z=$)4#6k^= z-<+&%h%~<-JEXX?@ElAIL3eAIIOA}%oY`B0==ZxdB}S-{_E#ua@8FDO3@}a{TC*Uh z-K%PX!qZke+b_&GEVlETMU}#Iz*0Ji*)?d5@g0ZMTC7sbwWnMIE2N^Xn=+rcVd!#b zPtAN)g zVxx97$szJXj-57T5;+*tIepjjJw;Db)GqT6sdEjUn8h$Z#aU}#cKl|KjJQr;3e(+V zES)X7FLnd=cLt1_l6FdC??yrIWV6?4rhdt#6_(lFo8x(805y{z%$zZ{whH%`Wb&f* zMY19FE%m-ML~JjJyiC`n8K}X2{tmM{;lz1v{OyJtjXDI@SWV`a6@Fa-@8_8F zc7*4s_iFFUc!+wSJr@oQD9SK&j)EG(Xr z>p2_|E_`FRt>JdAC!tVxi6u8CGZyJTQO5X2XjW$y)+?W@BVYea5OAPplX5P<@g$*P zex{@#ZANXX>5mTe2Vxez>XM|Yw%ZOyi#k2_Iw(f8^A@#LRR2SU;&&D>;>JLeVz0@CDlux#P`k!$m z#j_`Q2Y7HnRb?`Wipfdvgx1Y^3LUB?e}k{*k)wiqB?jDh zeo|BGF`WT51TCYU9{5UTb5y}JE}MU-2HWHZ)Ak~iq8{Fepdf#ydrlASc+aUV4J>4l zHUC>EBKIGSWj* zfZXXu2(F~PX*U8-uZ}|?HlgPVs5<^a8*z`Kn~Ki^!^lYBg@}>MO9XRbw+%-4xJC#t z$!45F>h66aJkLRd7VGWOFW+jUoVVKE2P3=T=!RwhMcw~JX2k4u*xwHXh0v^ar@0tx zVKwFVMsMAyLwT-J7^p~f^^QC~Cx;IPu7lw@b^F+W|EB{BE9P{hBj{VUX?Fg>J?{C~ zC%kZ&0EtX7H8YUe#Zm}baJL6lxVFWf{GO1RC4KVH@w0Vw4o=I zEaA64>e%5|T6kn@NTgBktPhb;eWdm;Nr$=eV|-^Eu;}MdDl;N&=Th5I{zqi#BHP{w zs3spry%q*M@G%6qC)nr3D`8(9>m$M&b&MaYHI$0*;tB0M={P1eAzvqpvP0}l3tPLCYNtob;Kr9hMPv~%SYjupMej}Y2AH3xLbC@+LKB2@ZHy5tymylw9Nw< z@wV?%Q9`u}BykLDDNL{+!=(=#z8=}lyJeA}iraK2$1pf7#WP>?aJ8J#Qa2XgMrUL( z;IspULr=ET%5HN|Ie01FB)7lwq>>4$I1}gM158}(aB=EgVuU|8O#+m+jBoCl`olfh z-DqW2Sk7#SAB($KDk!NoYUS@;|2ExBYO{>h16FDo-$&(k^T6~Z`kNws3c007!V<UrvxK3DnvB zDi-OmO_ak|uZ6D?am<$rTFb~+4yOj^VvR$ZpD&&rY&8udn|{CLO2VQ0z=f{mn8abl z8BZC>yKqN~W2m*913uNrN)|I@5^?X=;&XL0O|Z6lY5t@sX%ZVJs1i4FF`+DG*;S;!gzKc$;3ZF! zJ8A=?bzu*$MTRyI156U`A%C-Jcvx0$X(-}Ziksm&i!c z3&goTShldGB1#G-ulg;Wbx$W7NFAxNODwb}SYwkvPP=2Fao{~viqX)L%994b)TXDT zR?$jpwRsvw+}%t4fkf_XUc2d-B&$GgYY|Y0u#eAWN8umhb=A#>I3pj6Y=j$h!jIUD z7~jsi1i+J3l)yfONnbo|#pNf^J)gZ|#XSf?`jMrO2?_$_7$MHdB_vO;5umEy8BN0` zFbpkzOS1Bsqy~LWz?Rg5z=?%~GYwt|)N2?71|lF|Egb~y7VZu1#=`t5^-QAIvicdg z3ir=%N(uKEdZm%n{}G{7d`}Z6rzBHiV4*5gVh>K#_>aUOBc_^igH58o4?tQokrrz( zMU`~jhjnxyhT;z^On`Cg_(MMC-(nSq+1-5?A7$g8R;8M3E#(G@9q(+k-nZ8sZ1mWK z<{n915^rdHP`pg3$kjSKQ@LWv+c9E4V!!nMXaiw>(DAEddfkxjkA(F9IJ)V{QBe1_ zw;Fw&w?_&8T`jWF?EJnm3xCP!voZKh$LfokT;FEt!5UHgP`+%ep}<3}DA&;UDL|%C zx)C5;JwRye-Ai1GWe4C+TK|#!WLCXh+epnol*B+CJsR>h{~GL9B*eM6DA?f&f`;s~ z2V#OHgjChefLjH+uuf<=W_TZ-0{T7T`3B)B5xCTI$7uZY!-d;S4J=@gd{*uI@Ngt> z75c4;FT^^8riwEH;xY}U-z(iwY0{(j=jP`og*1kAe9Gs7q(5nJGRT0o|98&Q=r$7*cg^71PW*f(62dA z$_H@tRQE6eeHl^vQq}|FhjgGU-<$K)?-eOaB;YTZiJ0ql1A*_~WSgU%n?MXp;2(Jy zOt)!s4c2tMFBJ|suP-Uy-_RJG=*SH>FiuV`pc0Ku*=`zVhOS?0mt^0pix+;%{Y|R& zUPLLd-}x8M-XLTa5??#^u8bccuM# zr#lCpk6uoCB+$bGQtq0QY^gQV-g8_tP>*);eLr!*b<$c~$-h0O(J3B$tU3Q+v?8SU zv4P=@C7J($s8f7V6E##F1s-_*eXL`)EZ0Z_m?i8P^E2@iq^6vz$C9eoPoTvG#RWky zeB}K>7nT1KkeDd`871qyt4o^;uB3)>`E zK$;LKd4fwzPv*sY;;J%~*0>AJvvuvJ$J7QKBN;G*0!8?&%L*~0&RpSU(UVSlYyrYQZ3K!M z8b4xYWL+1yNz?pz<2_|o>Ls69jkrp8@Ta1~ILzDGaE)j|bW1e=KPvH_@*UT(6_W$4 zj}3HS?7Q?By^;#`zY{nlic`H0x1Mzzm3E)E;^J|sTq;O@?}=)BE8a`{Zfkh72$ytk zweTRJX9mk`;WItgK8)7^Uf5+*asl4iRVDrBpTU{Ab=HH=w{#<53JajsQ_1U<~l0B4ku^mLQbIF@PxcnPTsu!y(3ItHiIY3 z3kWtW^EBUl6KV#eM!i_0krO73 z`urO9`3Gj3g*oxQ?1f7%?oM&MW*QIME-xZUWDGZ-n`9u3mRQZb#o7khrdpO#>U42%I6Gp41jKgJACTKzXJWR zgXRi&8M%6K;>bJy4v2grp**C}N`68a{)UN#e=w&4>?32-JM(#&>Jwq>T9XFN5q$DQ z+Rh~)kr>iM`Ui*^zH7XE#PWv8Uv@ zX9l~C_u2_?YJYTS@Jc+)i7F)>teWA+)1QSMDs{Gp4-@ozHTsLzh?6vMV#N<6eZ##r zLIfPq?gTea6zv|Rd?&xgdMog>M@Y{4$Mr70O~9|o*e>3FlXCBp`*g+a+o}|EZfD4g zgZ=gbltVK+@?p~BRs6TrW7NcYmCt#Rp-Pq<?B*#@o2;c>{fxzqrX9!fVNNn|{D1gJ|8O!<=wfIn>B&fo z>(eymwZXoVs>odeuVybhjeDv#8!%#)nh@RCAYOGKBq6@0#|v~Se8nq16#FZ{`uG|3wNOG-(%)m@()UTRcD2*c$eR@Tg+j{r=E2 z;p7At7}+R2#|+%1b{BHMgkNn=X?kr+J1Z1p%R@*l= zI_mhkkveIQN65P6Q0az0?(;Wx18D zJlj=jCKcc?>nWjN2zfSAU^uab%?X5TOAN`5NU0n7+}Z=B+50~AlISPWfRTVd&7aC8)!X1l zq!vRtE(< zKg*w~*I(Agl&v_37u>nhf`;bI|0of!w=PyO^X-G%~MZXH(3&Y0_cYuUk!-9NCE&F?qGfy zWYrfPBed2?=T)hOs93j5nR*I|5OSq+jraJ|spDNLh$%PbCtURo4U^9G@5` zGUGq^!#QYz!+3yz^w^MRJTEZOx6#Nq(dduZhH>Nef8BwI@qI5T9OZ~fB~MtnrHdf( zo-DDr;E*C6)4+;5626Wns)BCT%_Z!z=*MXax{6FaR{nHozfZ~@y+&wOyZ~7;!ZO%j z=^|>j(AJ!gEY*JQOyCAg_n;tZ6(IPy1UW@E&k4C&b1}^Fl<5N@611C^?gYmQkL2Rn z5j?`*(a^6}^U>2-)6ot4)=5n#559lN`f9!!8GpYn5kmaC*cHx1tz6F=S2SHTh?%Lr z0qMHw0KER>0;*Xt7fIh5t_t3g!1CmmUo91R#nufIp=2-rZZ15J{)ozWvx4wjx&pEC z1r0oo_5@!*fXGW*em~Y-ujzwO(V@Pz7Q@$zc2TN6O3yyp}uHdvQ&RW_fVGxB@I9}x!(!?H^e`M|qo)JkqM(7KOE z?^ytHIEWu_X$|k{NXXEtASVbB+M}x1TUn4>9`X7)GgiLZg{U$s#F(GBN>4TVYmVJ1 zuiQt*w_(gIb#R%Mwju!^Uv-Z!QA#}X+d%g@)^Lxz;RgyNa1tor_sL+g3eqDrbd^Fp_Vq~cw`aCdnrH~zP3 z2)9!lo-Zz?t|uOX$4`siK--O9f0Y#0 z1G@Y8z70J}TXC3>{Bm5r04Pr-a2}xK5INSOaYSL`_HbfJ-hfRT z4Gd!QHo!t}F zcr;95QKJbCf@);sIGlW^9wngo#Y1QmBy*qoiv4nw0<~3{y`!co|M!BDCAjaU5D;Qa z;H#>7TaHo3R{Rp`o)2U|g4B^|y5an`%KMc+<>?8+*#EV9vgCd-UT77|l6nxy;e|or z%5b4GqN3a5*a_0J(@`hnBsLps(p9-#k5m{fGIpPIU9nN*IM`FrvB*hZQ#H+XIU=mY zH-8_9*|_*mVb$ToRSlQ-AnTRc{c<9!q!y;#-5$O4;W$z|(PtGr&fMmjBBkSb?NUL` zGU@#EzwhUdN|k$0Bef}I{)9UF;isf8{X;bgqyh3GD$&o_BAi>X_X)P5zY_L@VSZfv zICvWfVgTaZP(ZMBxUDtPz6etxD+&zYhL@XbPQT8GBue>5OC9c4nhd9};7#k)Whpx-s$z?@ zDi2T6XC zmlXaYd;t=1COGHvoJZmxkl)x4y7`ebp&{9qpBdL0$SpJ`$ z{;!h89(5rb!BMszz0cMiD>dKIiFnX-oaPPJG{XoOjA(XSl0%(s>jG zZ>;Z8KG6e&p7_>i&V;KYOj3&r>#y4BzoUr?EA%q*j>hpvRWmw%`cluxNXXG z9Hl$!C9=`i!H=Il{Q&eFir;J9BI8JXONAH8HPC@`j}D9KFfjzn99P;S?$1311kr$u z*Is>yOMw5x;zAp4c%)L(ksi+Nl20Bj0Rm!L(dWD1By*15A?|;=4Ss>;=v!yP{bn5= zXYVBgAYFTX+Lk@ewYR(9MqTcMs+vc{x+GGEwbNto27x=PDJIzl4k5Aqs{AVMZ--}zsuq3)^ zEKtLIpaITqf4aUsa905aOu?CddPw1N=;}}(F_MP^eOp>qFUK?8x8>`Cx$B2Ssm5S8 zesBjtf9=VG-gL%XZqr^jvxhw`w|JYZdxZ{u|E5k=DO4{YERb;w-wYdVjDb>S9O}~w?`J4q=%?& zZwh9;em4fJZg1;y?93EH=eLt~;$MDO_{8JiEd3>j7XIa82ob=^)Zcz@K`hIHd`}#Y*4s;@t}Z$O zr-`Th{+@R;L|ZSJE3-`5&T+oCPG>0P2Texw`A^AuG6p zg)VHbcam=Qv2r5!T@=*d{T%08Fv3!EatK)d&~Bjx+GFzxY0&l{wxV}ZyzMluOmI;X zhmc_)8))e*@a+h*ZQReHpj}FA5#)$%(%NdzPpIBN+iz6vbX$gOiOf1zNoc#>KQxsy zr!~a6*KZjAly7r{Y%jQuPWBZvLpr)>3=sh=KrD;2^6-` z&0Y{!Q!(81>fN7c*m8q5JL7A@YQnfiQd5Yy&XCR}mF*ynqFnLkR9`4i?j0{B?SDw) z{qon=IaB#*pJZo@yZa~4K9djh`@Fac*)%wvc!!kcVbNhD#(HTI(v}jf1u$~pf}aL6_GOnVoeSE zAfTm8R8fJlkMc1);OzV0-t`*2LqcB+%yvE6Ys&B?xYp{ zOR#kz7aCJaZ@S69x1M!Z8`|-)!wixA79!)cc=pF$J(>1pz)l;o3dKF7#F~X|BxbLH zhz(Dm18@COnBYW};@aj7OhwL8|1e6MfXzAXTmRT~=Y(9a%#Bteg+1nt8DH#W3?PXx zPJ14SKGdkU+Hzb+&}JBVhvZok{@y#kjGK36P1_`-TbV)rRUEv9I&~T+?s(C&g~v3A zPUo4nowv-8*Pt zC0sd@hEPgdm#~la30uTFU-jP@Pe_flw*jvDpr3 zVBe72V)a<`7X33Pl#y+=M-l@{)cc-rXD>-C>nltc%`!L<+2eg12?EQJQyC66f;6XF z@(Z{o5_XKL^zfeR3|bj7dGblz5;T<4g5tuaT&3VsPNx$IhJDc)c}c|&K#cgurUBm3 z!2T_kGqDG{K-V5RCM5c!X@23Z|4jurz^A#7`2SP`miwHhrRQox^Y(%nFG1ot<*z!V z^LF33+JhwEde#7qW?QZAxAWwM(a3--wHw7u|Nh+iQzL14^X{{G1|q^a9@trIwz1{3 zPekv@FRkh3&QXU)>5px2#wxY6-(gaA(lMhRi`3PI_rElj?(~39+vr$JJxKANyx$=t zUBuFE_``3T`+}e?tF<=A}v51F-AZrr?s(in+n5=K5LHUhTitU%AhT zTK~B<`pwfJz*S4@Cz6I?0tsK8+C2G*|38(nWzS7TRrbyPYRCI6;gof)&<-QTpvw;Q zs>b(CrpZ?@c}g{~Yn^$t{!84wEGK6;=J?;PTIr!8O_fG3Y9>=c{i(-%1(NIE9H;!^ zFT>YVUiJlEO9+}%O=DKY=Ezzp1+pg4KK8*{u>S=ZVzA**{lBSC6Xm4ejGHrN*1+QxJs$wH?w2F*UcuNfSO9`s^sIp@gselIl%GBn3&p=0h>LuQgbJ zj1mcrO4)M{i&?V4t?c93L1El6xcaZRi(;(-qBb@{d`Nr<2nopYm`Ud(=i~mYL`gh{ zww95ri%6vG&vRY?ui@c=%sw~>;I(~#08%`RMqKK^4ojqxvH8Q8*aIl5H7Cvw86r4w zq#GS#;MD7a-+?*~({0@EsnT0Hb+e6y=e*hn8rn4rN8A3@-hOG=_Gd5JbssBGc3vH) zWn9o4e`^8^=VSnYD#YC`LJhqyCjJ%29{zYM9sURv{=E;~QJLk}+dlU!s9zoJ5b$Lo9_y@YV4z`dO>`qwU`FgFEuDD?BFf*#GKC*NTDT`ZIMbG#UE;aQEJE zO=fEssLBX478u8|AP6dLq$*WvbP$xTLg+=MNf#m@9YsY!L29H1rAhB#XhD%0k|4cD zge3GpLWhvMQO6n7bLO1$o$tH%cmJASgbCSs-*-RjS!+FOKNE3yp}0Hz4WRq9t<^q! zJ2EC#{ax!)?UfDoZ&b?7)qT}zhNBOE7KVJATER-*cMw;O1mgo*_YL$u99H{tV2bU1 zg-qOp48s?lF$F|nEvx}b>@QvAiqL7BAAR*e65VIE^4V)sxV{_eLt4D(2MPCGEM2GCVTRskz(D1Q9pAm#lx zRnnJ@!9+g=uJK1{6$KNaU%FAbIN4o6vwks9rdP2z_n)$5&O-2+U46BIu7PKw&U-R@ zRVU+&)#jV8UhOqAm_13J0i*Ps!qjG~Y8gA9R{OO4hg04_zzNpAMa{kBs^B=a=eXU0 zN7u616~(O8JpVelo;`kc>__4cVz3_%!NW`M9%9mcdG_j;ajSKCfeyKVJJPSY1&{OH z9Ye~|FR)ML2=@Okw5t64rKVEZ7hIH~cC;m%w0Y7UNuG9cRj_2P{lh}D-y5Pq#%Jr& zBH4bcu4?D*``753bcc&KR3YqpmaE?uySDhm*Dp*TIy_d_d|LgVktklS;P~y+4Sf=iIr?Gd2KR6Np{NYo9Naw^H%OxZhCl;F zXFCfOr_NvBuUq=ZC|)!s0#Ur043n+(V)sLQSmkRc{62RM4dssax}0 zJx*;g1K0W9`8tTT4F6_p77p#gbz%J%YFlUBYwXi{)ElCKZ`)d&Pgox}#E(LInd_GZ z&a)3~+$*+cT>jjo*DvsXI0oYNqA^)UH^oI$ij+S;{>>KU85JaE5(TR3Yuag8L^)g( zKF;>juB+ZoX^ZJ=_Ml9RZM&quCx2FKXf6KG#`%WmE+&>li?=RaPxwwJltD5snQSC_ z!>Z@GULM&xJYE&A<6j4}EwAp4o-UB)$P#2!jM;0tRixb|Q4#;2_PPq)yZG^z44sRC z2Twjv`mw0j>cg2M5`WlT(}En2voHMY$96W)FVeUOR{Pni#NU2*b6QH!S_wqtup$@T zb3aGra5DzbC|brfxa4{BcV6!AbB?mFCcd2y2aRv;mc}<=EB`EB*8X7YD7vAP0Ba3D zbZ3RV=m&zWw1HVlpAX`E1;W&2GhRnve(@7U-bjw#k~5n#{QS=(zAi7{@y&@Ty?OV^ z?@dT;%RMl=DmmnP_jtk$olrN-PxJg$PvMZ!>S(!6jIZneiI)4($+U)sTvsX|NM~SJ zzv=v;^LU3SwDy|yiPWzWczS%*lRukWEx}ar>IxXbKF1BBN{(JQ$F03)PzaW?I1_JX zfjlnt!eWnI`@S|<539*@em`|W0`9iswx8613#Eufj6dGN%*f@CZ+#1JI9UMDEs)y4J+lM{D*H&ROx)ae@=7)$?LC8^L!gG2=kqQ0*if} z!VERrHb>rD-~FMs3b4qLWLH~wgjs=ZitIkK$S_z5-WHA08ZplM-E#FW(RVyQFy8vh zG&d%ed29O2)%&}CVEhu8j=G+FZHt-ef2Wo1#}0nZ)B{3+AHqu24-oO9RoCQO0Ao4m zvkfG~Q}-V*ywmyi5vZbwpd~7ppKoIQ^?*^~KSKfo<+6qG|2@gr5RL_MO$P0eMhf9q zkOQ-7U?|lN{3%zu)^{;m4Bf1+3|!-0Y$zPrIdR7J%LtB?^TRd0JeUnDXb0A_GfNb< z4qfvMB87J*6Kl0|t-B216S z&98&?7L9tgMA8(|FSh($X8dHY5yAZ{3-YE_#S)YE&-iQK$(k}}ySJ0IJ!fK`KZj;Y z2!x&%h^Yqozx7LC!nhm<;^>cbaq%HUP^83z^W}klepC>X$B!nv&z%T`t1+lQiX|l74p(NIx5J$K9>a zK2L&Rn@HOM0MU_V6JZd4ll@$MN^z;z&28V;3B7`AOn%V`xRSfgfYpu}{53=RqazvC z{1->E^uQEDiN>~_rD_q0Y&Gz_;St@KgTKZ}$6c3Jo>1Pl8(6fNg_f6WL}AY2eGpC( z2-lTUg&eGMXBz5z{hX|#E<*5LRsHq0T;k#kx3xY*y4&9I6#Qtk>c4Er5^5j?ug88g zBa=~|MCO7|9V0L!AE^=DOp#~Z&JLRV!+W-UHwo{`$A(|YuMJxSKr(5L38dl59ywKd z=-hVi+i$OQKj~Bt-cWk49xm3{xP40GP0*Q#Y7C%eT48U$I%WQ|M!cXwx`=2J7uI!- zdd%XOyLghX!`c(U^#7swyh`>CczuP8^UFYhXMF3x(mTPYX8r#}e3tO<#KG@g+;w8k z*?juU=9Cc2F)=uxI)}BmAMBF|22EPehwxPUPYLw`I)v}dLoe6u0#ErmiT$dg+ak){kkD97+>&Ce&hh-ISOxUXou+{E2d1TZWbN|)?F>I#= zvCpaA{ijng2!Yi0LUQ$KPS zAN7<)obhwrqp&3(*fJ>eg=N@uGt-Xry}EAdwDNc+WA5_+(mv!*lG_C@aEUO5p&q1{ z!(ApfBkXh>4wQWzygStiQgntE{rtG5Y|sm{!qJB>Y5q{)G`IA+!)@K+G38HhGvN<7 z;TW>;^O9!Hqr+%|U>i&of;==L^mP&i0nOKFD2cbncf9tD_Nb+--9r}9_UBqd=)&a_0?f2Pg^5>&m5lhd1N#B zZ0*dG$$pVjt-(>|&yGA=;~pApus$yS(j0YP%gy|j)+)BvVaEv9OTD=3MF|(K|1xXK z_-C@qjK)KaA8x~B6&2^)xLo95rG?&ku27Q|lf*tm&v`@5dqkt+TOP4iyzlNf$)p~2Wo849^9jTSheggue;1m6Ro*LWU6{NjB|rVA6H#R= zzxho(e78O6a~{f;H6>=8kgEDK3a*oXFXJ{?sxDL<#_PJ%l^u+;ja*AKbE5D2#Gvof z0Um1epK0FCcIRn*#?8e|m{l7A%Nf_2^3aU<9W*&GN!4Q-ows*lcD!uS=+(D5_rSHT zwrx^DOOgX5=ZV6kV{X8}@gtJwx8Eb@-GEa+ANHbe?gkDO*kX?c32<<+zusYb&$o4P zZTxyrta3LP^gka0g8oIa^DLrzS5hoTdLtF_@Ngr0BAjpN@Sb1k*AZ7Ipx$O547al) z5A40ey2o-x+<0q0{`aQo(v0tzrbQZ749^iN?2~?%6<2D$veh&lbLG+a=VOz~s&+XX zx0l#UCXJs;U~Ye;W!c;pZk-E}@)t3yZOD01;z(oBaublBye=aYtB>-0rC(Y%c9Chw=1cAmOe!rB`kVttxyt|0f~_2*rZ|J^RZ zf*&`n)}7FPf$<9mSX?2j^zBwyhb;x)>}5CO&B5|a$;ncK@!sjMvQL#|8rP(n;A#3fq`b=RR1 zsLyu?&li4a^&hzI)U7gX!N0C`3XjoS&AG1>t<~wLYp;2VFXC`nEbOFllhw#IqJ7R- zky2e(^sjn?k;IXD?9YX|VTbFRPm9A!Q{4ac{u^KPJ4Wmm1tJIKEuXtFbb>iNRKp)QhP(b_-uVWU%yJj6_rvt$bv(R;2qfHSjN)CJaz8t*HGJsVPwp=Z{sJ_o=GtSqC_BFf)TRtP&@ z6w1+#b?=U;j2_*CHT@8UNwG94ys{;^wO{V=frhCZV=RcSddxgPxQ?pHp#6jgCmmQ2 zfAM(u%7SsV-|5uCOrIe+@cDPOTtIKeJJ#(On~ zb}(1wtUD*Rx|UR6|L{8Xa_*r%V59#k@vLtk0`_F@#ZB-^JW=^vG#Whj}bAwBPN5?N>E>+#{q>r0fB zMS)&!>w)vGfISa%%lUV$+x;Eiv2MdhymOK$CX$!-1|~F-4PHMnxtDO}X8475kLxz~ ztyFo^J_ke&EIN7$Bw1^-KZ!3J+_pTht=fApXIap}!Uc$2Z_a#n@Obf!>$HjC>%9l{ zY(9C$q+7oX`Fh4&=*H`8nR9yJ(v|Qfc+8G2#Txu~6TUn~A>h=AHM!HQk7RuIixJZP z{A`;C(ro4;?W=k1-*lsQk_j+&Gb6WOf%(yEejsB-lczV5^3gT+!F|%|>m=64sS}NU z)HetqH$PYaITb)#lQT}`Q2xKr);CYmxk479KRht*f?(b=TU+-?FYprjZ3F%W@O}Oz z$Ugf8zjd09qs-^NavDUdO_0>iaqkRUepTSczL@}K-Ly)wF1EuyDqD8sU`75Q!f()= z_GviyMTu!M_f6g>6LW}e1Q~cdh;bgsXEibC-SuN@xH-v2x7UIe_{4IqdXp9 zAng5LB-rw-I#zA)qc3l+%c~e@F5jrnJ;5Kc;S1%Ty~+MM7)1Z2q-G;7VkOuemTpuR zKVlZTxXax7M-4xjJHG#N)qalQEI47JkXZ9pA>Qo#&12_wBg1okIspYr`ImGtk-sk8 zA@`5S_={sdN@{kUx+uXmip$u^qqpNTov!orQ{XBuINP)1X~p1AN1Gl$iK2I2{;Z|* zJ3p)#$OW+-p3vH3omSr_$Y-7x$bWlcb7EL0{o{ZXy4US<>kS3WI~ZPG-|@#Zu@1{u z0UrN~&CGD<^&$zxUtK?pQ!wr{1X1Vpo{k{;t|pxDH)F)$Serj<^pH+}n7l{o}7-4H@rki3ma6aYQ{@JVS`F_ovd?n z&Rn;C81#M>+km~XQT-@V&>x#)KshvHbMD&dHLX*=B|KoH_?#}sP9^m*4Wa#1H!wuA zxEs*mvqbaTl0X58=$gfNtZi0e`AC$)`TcxY?)@GQ-QBL(3zI=H21kY*>gwmN7qOc6 z0ynkZ-P=BgIXSLjC3QoNCmj%gSpR;HCQLF;{+L)U28TnqDNn(e+(QbfyT?@B?;i2V z^5O;F+~FRUBd0#=#}TflI}fGbrsGrb9r#chpZ?sQxnOX%kHXTB%OE)N=dWYNli|5r zOx!Cen1KHvfwQ%U~+OSO1+N?N1@>YpgypccE@71*<&7qT9U3D`;?<77+>hJ)()JD`19{4#*VL}LQ*LeN27Pfx&NM5tm6J}o$^1g} z;jv@a{F9O_ll(_@e5=k}PCI7$5y0I`+d;^Ls%@eoMN28dGSeYl=~)J}{gR z`PKO>=GhNF#4tzfAuR=lDsbF|G2bn1Us_wJyggmi#nEMo8}gg=$SFy@uO@a=Utv%t zaIr~=0XE^=Yj;t;=tr}dsLbYD_6cr6l$s(|?@MV|Aq=Ot)a!KKs3V=7f00pF=6_2wr;LikZx3*tJ3L>o7~GU-ROdnO~*E&udfZQ?$Ea`DS!0x&sow1tBiC+Jb74A_wRd=sgmShlwd+n| zVgnyZE8E2%dO0k!SqI9ik{qN1P5UsoY}LUfeXD!VScFiV)$F<6Z08NqxS_SQ-`T~n zXmeD)Z+EV}PWg2xAr_nmXk=aCmWt~VnuK&dyUky&^&e5h*(4;?Vx5&D! z<`i7ZAx0PDGCGrC8qG?baH@ZsAw5NnImJ_SD9zc@tv`32z8)0R=8C6lNQ_1=^`E49 zrMVWZ&$ilMi86zX2)$2sYgd$ZBu`bD8%m*51Fgq{2G)vAw{P2aHKBQX*LL~B>-M^j zHI^2U(<#}9zb-9@pQCZ>`}mJs)Vbw7p*N4woO(lQqW@Uj=_d_9Yx2L-VAA1RHd&2 z;{wM2xkpyt=H=GYA_T3uG-Sj`$|1h0d!<<&b6`TmXkA5K$05WIwINMi zLa@;V&&~7Qm!(?GZ@C_M#dr|B*tVYaW4?mHkZFu`@GS=LdX}7`ddU05o{boV%^z=I z4&T{4{r&9opYk_f|0ce@OS#CTqT{iEPYC{k-{!yBvzP41u8)#-IvYJ0n>P)$OGj|% zg;))(OjV6Anv`h4CA4n8bxh4n7uLYM60DFAp`S^vj?yaIC>w9qvr3&Su<^F%Ri85k z*KM1MxuMo6Puxlzkzr2f08Y?!;Y%qLhxA$MHgNjkCn~IZEA+5 z;+ocoD0=*T@Z^<%w?UMq5q;oB31xc3R4EE(Ukr*HKaEc+a&J4P zeu#>v>*0osBr)&2h!2<`FY3W!^AOl-*-n&omX*i+-AV<%L2UCOk*1av!f_KnKd}J6 zXy)|P2Bb}afv>UbFRP2&ZFIso@VJ;V5{0YKvVB#nr_9b#`ndIDjlgzFJ7m;7pxwKD z)#&zoqO>n!%1@~e5gyTCLFF|t(Z(I$pPpvd&n@jh2Nzk^t&tZx-pU`5#@A%IWc5D( zmK|br%p9?8n^CID`Exo2e54OvF71kh=P*}1g_X&wZT{A(+XKk6cX+U|4egMuj>>W& zw@atEkK;5lUCxFM&@5;o@0f0DgX_B7V}w!~2*vYhRYgB)m&BHsp(J6-7TAXauB$Rj zF^jr=W!ZEc{PJ~hU$;Aqzp8AfXLE;m(}m;>2<$;_mXWuIcmQTFzBXI9-b)8kj_^1Q*@3sYk`D`9kSn z!BK6g)h1%FbDnPMBuTK1**Nj2XlUqmTaYwaH?Gbgo|4j|x`#5?qB&!qvH2l9f?*3z zqGd8PFVEe}m%x&$D`EU>JWUFSrWdKK5ab4YjG^)*SfTe6RKmMk`GB+~J|0F=u5iQe zE*zcaHmJUyu%@FUeq&uJ59>i(C=of==|Tk?G4oj1qELIWij~ky=-QBRqq`wx$Rbrn zv!}?Mc_wQATGWPpwT$~ z6J#x4hgY7e>QV@XlS1ZHL@C1$hA4&ZUS6&mrg1cKvAP1?lq2?;@)OGa8IRHX>;nR* zWi^kqn@9h0c|x~Mz8|t_JA+!CRIXT@x}RaHi&IGGk7Q);%z5#mOLUg(zIM{4OsU$( z$TTityALJdLC#C?%?t2TBGzCdiiB{bz54s?huikBM{AW~pZmDHtBEf+TRd__OLD0> z8x%3~$zr=OrbNv908v**n~nEgneZH*4ZCF_J&T00pV)5H$rk;%HX3$_5@jkq@qn@F zJm-52u*1AJcal&0IkDPLSt0&_9b4pl!o~{q{`inDmsGCG$esa-C9Ri!I8r*OW+ftv zm1IriM77-Fl{B0YdUc-j{XLv!Q^-+KnC}X8$mwKtveh8HH}O9x)PaOUTEwSAy{WKF zez6V0!tF<0lb=3b9{W|OPD-XIG)krIP+=Rg z>2+4)y{7|MnsqVl#Z8O}v*k>pN$#2xaG|)grBdXFMhRH1UrSTsU|Xg^d8xo5)8)?i z9uY*JXihAlaZtNTP>k4#fBZ-r)GR~6 zE)1nsu}B5#OM6`A&w>uXr9#`|-7osiS>#;SajiVhIrVX|BRT9>kG66N)LYf{+;T$n zYc>ZJNRRkaeACGYFN7(H&Q10_K|LsS<7LMh28Fy;cfcIhd6_`rhbhT(fXVAmF3 zy<8vhbiHlvyNDF8xP`T=74^MXUW(x*Ylg@f0ZIq#dJ zoSkOd|j;Yk%ThKHw5YHWt7X-9Qs2JAEH2g@C!BdwbVVr8CTz6_2$=5cJN1PR!=hN z`;?EyaHis|#hm71Wog}X^b&LPaCho-6OuZ&?sn5qs=swNsQ5x5IK5mIXtLaCZlf~6 zs4|BzJ`wB(LhtmOVu%EsE;9&Oa2^|r$|`h;BJBn5eYGlzAsZvr6tzTv2&3<&+Re=0 zKk9-rqkuD7Uy0XlNF7iqTV(Sb?#u#vVdcDXwe$%pe6)h5MmWUMyj#qrZLCsK)(J|& zHo)fO**tS*reXB=g6vV_wJ`KgHvKPjs_o$5vji(!4q;XZF$4-X09w z*|nDrQ*qhw?|6(hNhcNckIo(U@UnMYw+e7vDXbM+XEQj%ubqc0Fq?JDKR4m~2%zci z2T_c!i$l6j;6h%4|A7d~787{axz@ZT!BecVI29eUTXdL{EoWzz9c41Th^(0kVOqpY zhdQ*#+II?unm+9&rSu!DeBgwFgdM7m**|ryIv=nKS_;@3%=k@1j>O0{EH>@Q!X})Z>_}1?$n!cDS_N)U zVi_Ji=444$1C{eh??W4>R39|AO&_*IBT#<3YNSi|!C_?5|;xd^e*#7g9;C541$Wy1aPi8I3hx{TJY z)KU%d!Es0E(HQBMdNd*XcDXD&Q9tK{!kA?^tSN5-V)3E)N_j__ot5xKT*&wUZzo!G zI)^(WqiG^`YTzWmu(bV@^>6p^AA6w?}4_R4sCLJ)b7ZxKYr>|jPDImMN%F_|@TPhOVz-c-84Y#c|7 zBbNDPq3$PhG?@-kC$uOHDoAth8DCMSylm3bN7`!JyMz;9q>)~v_Cdj>-R*YMMYla> z4kNg^I334?M2s%?>6=7!Tje2NDP-q?%ZM0%D$6P2kY^mFXPw&L^=UP>m;4us+Fjm> zP^o<37A?shln>rZYOF3eWxMkv$<*hH;HxW>N$4LffOl1sUZloIqlyP>B;E<|H*2qV z-TVqxY_NI02?|;t-56NDl*8C<_Z>um6MO^OkWA5|M(HNOa%2p7oX84C2x%H4#M|lb0eMRe%V|%jWtR%=@@ELzf5za8aKj!{}W4Ha>4R zRq!~(P|=7wwB7WjhWCZwwi{$%6&I{ki^o+G1x_RpFASb%nMzal0;6u;vPYH*-dI8 z(<4^0H)+4=(pkoNtO^Y@74t)qdhAFm>_Vt?Z;_Fqgj%;7;mvMT?EW=^wow|ih#d*A zoMnCGYTRjOTjn)yUiGG_`!>cggQWr&wjDT-I$6EMQ=LBZEz~%4kEKq7h48AXXeq>I zP!K%dsRE#f_(aU`GwCzUHwG0LoR%EyCzVD3ZUB2GNoN63OI?izySLMZI0TRquPiZi zhoMbAKsfY;?ZdB-hL}gu!4&dN8>GjEr^?WgnCE8bB5lbV!u@R2B3vp!bEa(3bBb*x z4w4@3L!-`I?O8BT0>c_eZ!fb#q?r~6lJ+YoNC)I%n%1o9_p-X%9u(0U>4S-*{Pf)V zc*P!&HeTDbztCB3eal{QftLj%pjdRF%$pD^sDH&zEHN%tz7$ua9d6M!KUM7`T_Zz& zx=v{+?tjq*?|EwE>t?GtD3WIucg{!b>W!hyMQ}eXcWNU)R1Y}YrtQU%Dy&fGZuYEA zR6*7&sJ%ww_L!RySg7M0$Tu%^MYDTUC4wJq3wqHoHX&}YS8(&i@}Xa@UZyNIw-}@V zE@_+pn~b)dmFAmh0=&9(Uis?B|K8Z~@t1dL_%B@U$u+U9k5XtLCqp*hpi41lTb8pW zmhGu!8PU$Gvo9l46e4p%%&8^(G;%4s*rDLLUe$cQOA-|eXeL6RgCSutLToKf5G4ef z<$V=V&4_aGe-}B-w(c2A@P#zH;Wacg92Kr9=B?J6rOXvbe^>?Iq^g@~3^dcW|Adxl zd>y)||Gtf%tuWoS+;3u}^__s8C4nEexz-v_0Ve%8r*Hu>+Rr$8r&{;GxDh=J?Uz7G z2RCQDhgWr>noQ|XQdaIJrC?AcvyyH>`f$$UnzH7Rgl;QR&cwjVZQ*KbMW;fqHGnI3 zU$9)A1!dCXhu&NhKvoDIiSm#l!L7TF7)VY%GnV`95PPhYW8=WSm7#NcWv+!QdRl*o z%HT+tJCv$NVwA{xaRQ)`j>)3i>b%B@Mb(kY2Nu{}mROO*F^S#j#&8-0&P`&uh