diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..8361f81 --- /dev/null +++ b/.gitignore @@ -0,0 +1,3 @@ +dist +node_modules +*.map diff --git a/HyperTab.xcodeproj/project.pbxproj b/HyperTab.xcodeproj/project.pbxproj deleted file mode 100644 index f52e82b..0000000 --- a/HyperTab.xcodeproj/project.pbxproj +++ /dev/null @@ -1,963 +0,0 @@ -// !$*UTF8*$! -{ - archiveVersion = 1; - classes = { - }; - objectVersion = 56; - objects = { - -/* Begin PBXBuildFile section */ - 53BF83D92B0910510035E5BA /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 53BF83D82B0910510035E5BA /* AppDelegate.swift */; }; - 53BF83DB2B0910510035E5BA /* SceneDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 53BF83DA2B0910510035E5BA /* SceneDelegate.swift */; }; - 53BF83DE2B0910510035E5BA /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 53BF83DC2B0910510035E5BA /* LaunchScreen.storyboard */; }; - 53BF83E12B0910510035E5BA /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 53BF83DF2B0910510035E5BA /* Main.storyboard */; }; - 53BF83EA2B0910510035E5BA /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 53BF83E92B0910510035E5BA /* AppDelegate.swift */; }; - 53BF83ED2B0910510035E5BA /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 53BF83EB2B0910510035E5BA /* Main.storyboard */; }; - 53BF83F42B0910510035E5BA /* HyperTab Extension.appex in Embed Foundation Extensions */ = {isa = PBXBuildFile; fileRef = 53BF83F32B0910510035E5BA /* HyperTab Extension.appex */; settings = {ATTRIBUTES = (RemoveHeadersOnCopy, ); }; }; - 53BF83FE2B0910510035E5BA /* HyperTab Extension.appex in Embed Foundation Extensions */ = {isa = PBXBuildFile; fileRef = 53BF83FD2B0910510035E5BA /* HyperTab Extension.appex */; settings = {ATTRIBUTES = (RemoveHeadersOnCopy, ); }; }; - 53BF84042B0910510035E5BA /* Main.html in Resources */ = {isa = PBXBuildFile; fileRef = 53BF83BF2B0910510035E5BA /* Main.html */; }; - 53BF84052B0910510035E5BA /* Main.html in Resources */ = {isa = PBXBuildFile; fileRef = 53BF83BF2B0910510035E5BA /* Main.html */; }; - 53BF84062B0910510035E5BA /* Icon.png in Resources */ = {isa = PBXBuildFile; fileRef = 53BF83C12B0910510035E5BA /* Icon.png */; }; - 53BF84072B0910510035E5BA /* Icon.png in Resources */ = {isa = PBXBuildFile; fileRef = 53BF83C12B0910510035E5BA /* Icon.png */; }; - 53BF84082B0910510035E5BA /* Style.css in Resources */ = {isa = PBXBuildFile; fileRef = 53BF83C22B0910510035E5BA /* Style.css */; }; - 53BF84092B0910510035E5BA /* Style.css in Resources */ = {isa = PBXBuildFile; fileRef = 53BF83C22B0910510035E5BA /* Style.css */; }; - 53BF840A2B0910510035E5BA /* Script.js in Resources */ = {isa = PBXBuildFile; fileRef = 53BF83C32B0910510035E5BA /* Script.js */; }; - 53BF840B2B0910510035E5BA /* Script.js in Resources */ = {isa = PBXBuildFile; fileRef = 53BF83C32B0910510035E5BA /* Script.js */; }; - 53BF840C2B0910510035E5BA /* ViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 53BF83C42B0910510035E5BA /* ViewController.swift */; }; - 53BF840D2B0910510035E5BA /* ViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 53BF83C42B0910510035E5BA /* ViewController.swift */; }; - 53BF840E2B0910510035E5BA /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 53BF83C52B0910510035E5BA /* Assets.xcassets */; }; - 53BF840F2B0910510035E5BA /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 53BF83C52B0910510035E5BA /* Assets.xcassets */; }; - 53BF84102B0910510035E5BA /* SafariWebExtensionHandler.swift in Sources */ = {isa = PBXBuildFile; fileRef = 53BF83C72B0910510035E5BA /* SafariWebExtensionHandler.swift */; }; - 53BF84112B0910510035E5BA /* SafariWebExtensionHandler.swift in Sources */ = {isa = PBXBuildFile; fileRef = 53BF83C72B0910510035E5BA /* SafariWebExtensionHandler.swift */; }; - 53BF84122B0910510035E5BA /* _locales in Resources */ = {isa = PBXBuildFile; fileRef = 53BF83C92B0910510035E5BA /* _locales */; }; - 53BF84132B0910510035E5BA /* _locales in Resources */ = {isa = PBXBuildFile; fileRef = 53BF83C92B0910510035E5BA /* _locales */; }; - 53BF84142B0910510035E5BA /* images in Resources */ = {isa = PBXBuildFile; fileRef = 53BF83CA2B0910510035E5BA /* images */; }; - 53BF84152B0910510035E5BA /* images in Resources */ = {isa = PBXBuildFile; fileRef = 53BF83CA2B0910510035E5BA /* images */; }; - 53BF84162B0910510035E5BA /* manifest.json in Resources */ = {isa = PBXBuildFile; fileRef = 53BF83CB2B0910510035E5BA /* manifest.json */; }; - 53BF84172B0910510035E5BA /* manifest.json in Resources */ = {isa = PBXBuildFile; fileRef = 53BF83CB2B0910510035E5BA /* manifest.json */; }; - 53BF84182B0910510035E5BA /* background.js in Resources */ = {isa = PBXBuildFile; fileRef = 53BF83CC2B0910510035E5BA /* background.js */; }; - 53BF84192B0910510035E5BA /* background.js in Resources */ = {isa = PBXBuildFile; fileRef = 53BF83CC2B0910510035E5BA /* background.js */; }; - 53BF841A2B0910510035E5BA /* content.js in Resources */ = {isa = PBXBuildFile; fileRef = 53BF83CD2B0910510035E5BA /* content.js */; }; - 53BF841B2B0910510035E5BA /* content.js in Resources */ = {isa = PBXBuildFile; fileRef = 53BF83CD2B0910510035E5BA /* content.js */; }; - 53BF841C2B0910510035E5BA /* popup.html in Resources */ = {isa = PBXBuildFile; fileRef = 53BF83CE2B0910510035E5BA /* popup.html */; }; - 53BF841D2B0910510035E5BA /* popup.html in Resources */ = {isa = PBXBuildFile; fileRef = 53BF83CE2B0910510035E5BA /* popup.html */; }; - 53BF841E2B0910510035E5BA /* popup.css in Resources */ = {isa = PBXBuildFile; fileRef = 53BF83CF2B0910510035E5BA /* popup.css */; }; - 53BF841F2B0910510035E5BA /* popup.css in Resources */ = {isa = PBXBuildFile; fileRef = 53BF83CF2B0910510035E5BA /* popup.css */; }; - 53BF84202B0910510035E5BA /* popup.js in Resources */ = {isa = PBXBuildFile; fileRef = 53BF83D02B0910510035E5BA /* popup.js */; }; - 53BF84212B0910510035E5BA /* popup.js in Resources */ = {isa = PBXBuildFile; fileRef = 53BF83D02B0910510035E5BA /* popup.js */; }; -/* End PBXBuildFile section */ - -/* Begin PBXContainerItemProxy section */ - 53BF83F52B0910510035E5BA /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = 53BF83B92B0910500035E5BA /* Project object */; - proxyType = 1; - remoteGlobalIDString = 53BF83F22B0910510035E5BA; - remoteInfo = "HyperTab Extension (iOS)"; - }; - 53BF83FF2B0910510035E5BA /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = 53BF83B92B0910500035E5BA /* Project object */; - proxyType = 1; - remoteGlobalIDString = 53BF83FC2B0910510035E5BA; - remoteInfo = "HyperTab Extension (macOS)"; - }; -/* End PBXContainerItemProxy section */ - -/* Begin PBXCopyFilesBuildPhase section */ - 53BF84272B0910510035E5BA /* Embed Foundation Extensions */ = { - isa = PBXCopyFilesBuildPhase; - buildActionMask = 2147483647; - dstPath = ""; - dstSubfolderSpec = 13; - files = ( - 53BF83F42B0910510035E5BA /* HyperTab Extension.appex in Embed Foundation Extensions */, - ); - name = "Embed Foundation Extensions"; - runOnlyForDeploymentPostprocessing = 0; - }; - 53BF842E2B0910510035E5BA /* Embed Foundation Extensions */ = { - isa = PBXCopyFilesBuildPhase; - buildActionMask = 2147483647; - dstPath = ""; - dstSubfolderSpec = 13; - files = ( - 53BF83FE2B0910510035E5BA /* HyperTab Extension.appex in Embed Foundation Extensions */, - ); - name = "Embed Foundation Extensions"; - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXCopyFilesBuildPhase section */ - -/* Begin PBXFileReference section */ - 53BF83C02B0910510035E5BA /* Base */ = {isa = PBXFileReference; lastKnownFileType = text.html; name = Base; path = ../Base.lproj/Main.html; sourceTree = ""; }; - 53BF83C12B0910510035E5BA /* Icon.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = Icon.png; sourceTree = ""; }; - 53BF83C22B0910510035E5BA /* Style.css */ = {isa = PBXFileReference; lastKnownFileType = text.css; path = Style.css; sourceTree = ""; }; - 53BF83C32B0910510035E5BA /* Script.js */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.javascript; path = Script.js; sourceTree = ""; }; - 53BF83C42B0910510035E5BA /* ViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ViewController.swift; sourceTree = ""; }; - 53BF83C52B0910510035E5BA /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; - 53BF83C72B0910510035E5BA /* SafariWebExtensionHandler.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SafariWebExtensionHandler.swift; sourceTree = ""; }; - 53BF83C92B0910510035E5BA /* _locales */ = {isa = PBXFileReference; lastKnownFileType = folder; path = _locales; sourceTree = ""; }; - 53BF83CA2B0910510035E5BA /* images */ = {isa = PBXFileReference; lastKnownFileType = folder; path = images; sourceTree = ""; }; - 53BF83CB2B0910510035E5BA /* manifest.json */ = {isa = PBXFileReference; lastKnownFileType = text.json; path = manifest.json; sourceTree = ""; }; - 53BF83CC2B0910510035E5BA /* background.js */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.javascript; path = background.js; sourceTree = ""; }; - 53BF83CD2B0910510035E5BA /* content.js */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.javascript; path = content.js; sourceTree = ""; }; - 53BF83CE2B0910510035E5BA /* popup.html */ = {isa = PBXFileReference; lastKnownFileType = text.html; path = popup.html; sourceTree = ""; }; - 53BF83CF2B0910510035E5BA /* popup.css */ = {isa = PBXFileReference; lastKnownFileType = text.css; path = popup.css; sourceTree = ""; }; - 53BF83D02B0910510035E5BA /* popup.js */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.javascript; path = popup.js; sourceTree = ""; }; - 53BF83D52B0910510035E5BA /* HyperTab.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = HyperTab.app; sourceTree = BUILT_PRODUCTS_DIR; }; - 53BF83D82B0910510035E5BA /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; - 53BF83DA2B0910510035E5BA /* SceneDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SceneDelegate.swift; sourceTree = ""; }; - 53BF83DD2B0910510035E5BA /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; }; - 53BF83E02B0910510035E5BA /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; - 53BF83E22B0910510035E5BA /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; - 53BF83E72B0910510035E5BA /* HyperTab.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = HyperTab.app; sourceTree = BUILT_PRODUCTS_DIR; }; - 53BF83E92B0910510035E5BA /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; - 53BF83EC2B0910510035E5BA /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; - 53BF83EE2B0910510035E5BA /* HyperTab.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = HyperTab.entitlements; sourceTree = ""; }; - 53BF83F32B0910510035E5BA /* HyperTab Extension.appex */ = {isa = PBXFileReference; explicitFileType = "wrapper.app-extension"; includeInIndex = 0; path = "HyperTab Extension.appex"; sourceTree = BUILT_PRODUCTS_DIR; }; - 53BF83F82B0910510035E5BA /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; - 53BF83FD2B0910510035E5BA /* HyperTab Extension.appex */ = {isa = PBXFileReference; explicitFileType = "wrapper.app-extension"; includeInIndex = 0; path = "HyperTab Extension.appex"; sourceTree = BUILT_PRODUCTS_DIR; }; - 53BF84022B0910510035E5BA /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; - 53BF84032B0910510035E5BA /* HyperTab.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = HyperTab.entitlements; sourceTree = ""; }; -/* End PBXFileReference section */ - -/* Begin PBXFrameworksBuildPhase section */ - 53BF83D22B0910510035E5BA /* Frameworks */ = { - isa = PBXFrameworksBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - runOnlyForDeploymentPostprocessing = 0; - }; - 53BF83E42B0910510035E5BA /* Frameworks */ = { - isa = PBXFrameworksBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - runOnlyForDeploymentPostprocessing = 0; - }; - 53BF83F02B0910510035E5BA /* Frameworks */ = { - isa = PBXFrameworksBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - runOnlyForDeploymentPostprocessing = 0; - }; - 53BF83FA2B0910510035E5BA /* Frameworks */ = { - isa = PBXFrameworksBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXFrameworksBuildPhase section */ - -/* Begin PBXGroup section */ - 53BF83B82B0910500035E5BA = { - isa = PBXGroup; - children = ( - 53BF83BD2B0910510035E5BA /* Shared (App) */, - 53BF83C62B0910510035E5BA /* Shared (Extension) */, - 53BF83D72B0910510035E5BA /* iOS (App) */, - 53BF83E82B0910510035E5BA /* macOS (App) */, - 53BF83F72B0910510035E5BA /* iOS (Extension) */, - 53BF84012B0910510035E5BA /* macOS (Extension) */, - 53BF83D62B0910510035E5BA /* Products */, - ); - sourceTree = ""; - }; - 53BF83BD2B0910510035E5BA /* Shared (App) */ = { - isa = PBXGroup; - children = ( - 53BF83C42B0910510035E5BA /* ViewController.swift */, - 53BF83C52B0910510035E5BA /* Assets.xcassets */, - 53BF83BE2B0910510035E5BA /* Resources */, - ); - path = "Shared (App)"; - sourceTree = ""; - }; - 53BF83BE2B0910510035E5BA /* Resources */ = { - isa = PBXGroup; - children = ( - 53BF83BF2B0910510035E5BA /* Main.html */, - 53BF83C12B0910510035E5BA /* Icon.png */, - 53BF83C22B0910510035E5BA /* Style.css */, - 53BF83C32B0910510035E5BA /* Script.js */, - ); - path = Resources; - sourceTree = ""; - }; - 53BF83C62B0910510035E5BA /* Shared (Extension) */ = { - isa = PBXGroup; - children = ( - 53BF83C72B0910510035E5BA /* SafariWebExtensionHandler.swift */, - 53BF83C82B0910510035E5BA /* Resources */, - ); - path = "Shared (Extension)"; - sourceTree = ""; - }; - 53BF83C82B0910510035E5BA /* Resources */ = { - isa = PBXGroup; - children = ( - 53BF83C92B0910510035E5BA /* _locales */, - 53BF83CA2B0910510035E5BA /* images */, - 53BF83CB2B0910510035E5BA /* manifest.json */, - 53BF83CC2B0910510035E5BA /* background.js */, - 53BF83CD2B0910510035E5BA /* content.js */, - 53BF83CE2B0910510035E5BA /* popup.html */, - 53BF83CF2B0910510035E5BA /* popup.css */, - 53BF83D02B0910510035E5BA /* popup.js */, - ); - path = Resources; - sourceTree = ""; - }; - 53BF83D62B0910510035E5BA /* Products */ = { - isa = PBXGroup; - children = ( - 53BF83D52B0910510035E5BA /* HyperTab.app */, - 53BF83E72B0910510035E5BA /* HyperTab.app */, - 53BF83F32B0910510035E5BA /* HyperTab Extension.appex */, - 53BF83FD2B0910510035E5BA /* HyperTab Extension.appex */, - ); - name = Products; - sourceTree = ""; - }; - 53BF83D72B0910510035E5BA /* iOS (App) */ = { - isa = PBXGroup; - children = ( - 53BF83D82B0910510035E5BA /* AppDelegate.swift */, - 53BF83DA2B0910510035E5BA /* SceneDelegate.swift */, - 53BF83DC2B0910510035E5BA /* LaunchScreen.storyboard */, - 53BF83DF2B0910510035E5BA /* Main.storyboard */, - 53BF83E22B0910510035E5BA /* Info.plist */, - ); - path = "iOS (App)"; - sourceTree = ""; - }; - 53BF83E82B0910510035E5BA /* macOS (App) */ = { - isa = PBXGroup; - children = ( - 53BF83E92B0910510035E5BA /* AppDelegate.swift */, - 53BF83EB2B0910510035E5BA /* Main.storyboard */, - 53BF83EE2B0910510035E5BA /* HyperTab.entitlements */, - ); - path = "macOS (App)"; - sourceTree = ""; - }; - 53BF83F72B0910510035E5BA /* iOS (Extension) */ = { - isa = PBXGroup; - children = ( - 53BF83F82B0910510035E5BA /* Info.plist */, - ); - path = "iOS (Extension)"; - sourceTree = ""; - }; - 53BF84012B0910510035E5BA /* macOS (Extension) */ = { - isa = PBXGroup; - children = ( - 53BF84022B0910510035E5BA /* Info.plist */, - 53BF84032B0910510035E5BA /* HyperTab.entitlements */, - ); - path = "macOS (Extension)"; - sourceTree = ""; - }; -/* End PBXGroup section */ - -/* Begin PBXNativeTarget section */ - 53BF83D42B0910510035E5BA /* HyperTab (iOS) */ = { - isa = PBXNativeTarget; - buildConfigurationList = 53BF84282B0910510035E5BA /* Build configuration list for PBXNativeTarget "HyperTab (iOS)" */; - buildPhases = ( - 53BF83D12B0910510035E5BA /* Sources */, - 53BF83D22B0910510035E5BA /* Frameworks */, - 53BF83D32B0910510035E5BA /* Resources */, - 53BF84272B0910510035E5BA /* Embed Foundation Extensions */, - ); - buildRules = ( - ); - dependencies = ( - 53BF83F62B0910510035E5BA /* PBXTargetDependency */, - ); - name = "HyperTab (iOS)"; - productName = "HyperTab (iOS)"; - productReference = 53BF83D52B0910510035E5BA /* HyperTab.app */; - productType = "com.apple.product-type.application"; - }; - 53BF83E62B0910510035E5BA /* HyperTab (macOS) */ = { - isa = PBXNativeTarget; - buildConfigurationList = 53BF842F2B0910510035E5BA /* Build configuration list for PBXNativeTarget "HyperTab (macOS)" */; - buildPhases = ( - 53BF83E32B0910510035E5BA /* Sources */, - 53BF83E42B0910510035E5BA /* Frameworks */, - 53BF83E52B0910510035E5BA /* Resources */, - 53BF842E2B0910510035E5BA /* Embed Foundation Extensions */, - ); - buildRules = ( - ); - dependencies = ( - 53BF84002B0910510035E5BA /* PBXTargetDependency */, - ); - name = "HyperTab (macOS)"; - productName = "HyperTab (macOS)"; - productReference = 53BF83E72B0910510035E5BA /* HyperTab.app */; - productType = "com.apple.product-type.application"; - }; - 53BF83F22B0910510035E5BA /* HyperTab Extension (iOS) */ = { - isa = PBXNativeTarget; - buildConfigurationList = 53BF84242B0910510035E5BA /* Build configuration list for PBXNativeTarget "HyperTab Extension (iOS)" */; - buildPhases = ( - 53BF83EF2B0910510035E5BA /* Sources */, - 53BF83F02B0910510035E5BA /* Frameworks */, - 53BF83F12B0910510035E5BA /* Resources */, - ); - buildRules = ( - ); - dependencies = ( - ); - name = "HyperTab Extension (iOS)"; - productName = "HyperTab Extension (iOS)"; - productReference = 53BF83F32B0910510035E5BA /* HyperTab Extension.appex */; - productType = "com.apple.product-type.app-extension"; - }; - 53BF83FC2B0910510035E5BA /* HyperTab Extension (macOS) */ = { - isa = PBXNativeTarget; - buildConfigurationList = 53BF842B2B0910510035E5BA /* Build configuration list for PBXNativeTarget "HyperTab Extension (macOS)" */; - buildPhases = ( - 53BF83F92B0910510035E5BA /* Sources */, - 53BF83FA2B0910510035E5BA /* Frameworks */, - 53BF83FB2B0910510035E5BA /* Resources */, - ); - buildRules = ( - ); - dependencies = ( - ); - name = "HyperTab Extension (macOS)"; - productName = "HyperTab Extension (macOS)"; - productReference = 53BF83FD2B0910510035E5BA /* HyperTab Extension.appex */; - productType = "com.apple.product-type.app-extension"; - }; -/* End PBXNativeTarget section */ - -/* Begin PBXProject section */ - 53BF83B92B0910500035E5BA /* Project object */ = { - isa = PBXProject; - attributes = { - BuildIndependentTargetsInParallel = 1; - LastSwiftUpdateCheck = 1500; - LastUpgradeCheck = 1500; - TargetAttributes = { - 53BF83D42B0910510035E5BA = { - CreatedOnToolsVersion = 15.0.1; - }; - 53BF83E62B0910510035E5BA = { - CreatedOnToolsVersion = 15.0.1; - }; - 53BF83F22B0910510035E5BA = { - CreatedOnToolsVersion = 15.0.1; - }; - 53BF83FC2B0910510035E5BA = { - CreatedOnToolsVersion = 15.0.1; - }; - }; - }; - buildConfigurationList = 53BF83BC2B0910500035E5BA /* Build configuration list for PBXProject "HyperTab" */; - compatibilityVersion = "Xcode 14.0"; - developmentRegion = en; - hasScannedForEncodings = 0; - knownRegions = ( - en, - Base, - ); - mainGroup = 53BF83B82B0910500035E5BA; - productRefGroup = 53BF83D62B0910510035E5BA /* Products */; - projectDirPath = ""; - projectRoot = ""; - targets = ( - 53BF83D42B0910510035E5BA /* HyperTab (iOS) */, - 53BF83E62B0910510035E5BA /* HyperTab (macOS) */, - 53BF83F22B0910510035E5BA /* HyperTab Extension (iOS) */, - 53BF83FC2B0910510035E5BA /* HyperTab Extension (macOS) */, - ); - }; -/* End PBXProject section */ - -/* Begin PBXResourcesBuildPhase section */ - 53BF83D32B0910510035E5BA /* Resources */ = { - isa = PBXResourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - 53BF84062B0910510035E5BA /* Icon.png in Resources */, - 53BF83DE2B0910510035E5BA /* LaunchScreen.storyboard in Resources */, - 53BF84042B0910510035E5BA /* Main.html in Resources */, - 53BF840A2B0910510035E5BA /* Script.js in Resources */, - 53BF840E2B0910510035E5BA /* Assets.xcassets in Resources */, - 53BF83E12B0910510035E5BA /* Main.storyboard in Resources */, - 53BF84082B0910510035E5BA /* Style.css in Resources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; - 53BF83E52B0910510035E5BA /* Resources */ = { - isa = PBXResourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - 53BF84072B0910510035E5BA /* Icon.png in Resources */, - 53BF84092B0910510035E5BA /* Style.css in Resources */, - 53BF83ED2B0910510035E5BA /* Main.storyboard in Resources */, - 53BF840B2B0910510035E5BA /* Script.js in Resources */, - 53BF840F2B0910510035E5BA /* Assets.xcassets in Resources */, - 53BF84052B0910510035E5BA /* Main.html in Resources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; - 53BF83F12B0910510035E5BA /* Resources */ = { - isa = PBXResourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - 53BF84182B0910510035E5BA /* background.js in Resources */, - 53BF841E2B0910510035E5BA /* popup.css in Resources */, - 53BF841C2B0910510035E5BA /* popup.html in Resources */, - 53BF84142B0910510035E5BA /* images in Resources */, - 53BF84162B0910510035E5BA /* manifest.json in Resources */, - 53BF84122B0910510035E5BA /* _locales in Resources */, - 53BF841A2B0910510035E5BA /* content.js in Resources */, - 53BF84202B0910510035E5BA /* popup.js in Resources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; - 53BF83FB2B0910510035E5BA /* Resources */ = { - isa = PBXResourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - 53BF84192B0910510035E5BA /* background.js in Resources */, - 53BF841F2B0910510035E5BA /* popup.css in Resources */, - 53BF841D2B0910510035E5BA /* popup.html in Resources */, - 53BF84152B0910510035E5BA /* images in Resources */, - 53BF84172B0910510035E5BA /* manifest.json in Resources */, - 53BF84132B0910510035E5BA /* _locales in Resources */, - 53BF841B2B0910510035E5BA /* content.js in Resources */, - 53BF84212B0910510035E5BA /* popup.js in Resources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXResourcesBuildPhase section */ - -/* Begin PBXSourcesBuildPhase section */ - 53BF83D12B0910510035E5BA /* Sources */ = { - isa = PBXSourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - 53BF840C2B0910510035E5BA /* ViewController.swift in Sources */, - 53BF83D92B0910510035E5BA /* AppDelegate.swift in Sources */, - 53BF83DB2B0910510035E5BA /* SceneDelegate.swift in Sources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; - 53BF83E32B0910510035E5BA /* Sources */ = { - isa = PBXSourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - 53BF840D2B0910510035E5BA /* ViewController.swift in Sources */, - 53BF83EA2B0910510035E5BA /* AppDelegate.swift in Sources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; - 53BF83EF2B0910510035E5BA /* Sources */ = { - isa = PBXSourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - 53BF84102B0910510035E5BA /* SafariWebExtensionHandler.swift in Sources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; - 53BF83F92B0910510035E5BA /* Sources */ = { - isa = PBXSourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - 53BF84112B0910510035E5BA /* SafariWebExtensionHandler.swift in Sources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXSourcesBuildPhase section */ - -/* Begin PBXTargetDependency section */ - 53BF83F62B0910510035E5BA /* PBXTargetDependency */ = { - isa = PBXTargetDependency; - target = 53BF83F22B0910510035E5BA /* HyperTab Extension (iOS) */; - targetProxy = 53BF83F52B0910510035E5BA /* PBXContainerItemProxy */; - }; - 53BF84002B0910510035E5BA /* PBXTargetDependency */ = { - isa = PBXTargetDependency; - target = 53BF83FC2B0910510035E5BA /* HyperTab Extension (macOS) */; - targetProxy = 53BF83FF2B0910510035E5BA /* PBXContainerItemProxy */; - }; -/* End PBXTargetDependency section */ - -/* Begin PBXVariantGroup section */ - 53BF83BF2B0910510035E5BA /* Main.html */ = { - isa = PBXVariantGroup; - children = ( - 53BF83C02B0910510035E5BA /* Base */, - ); - name = Main.html; - sourceTree = ""; - }; - 53BF83DC2B0910510035E5BA /* LaunchScreen.storyboard */ = { - isa = PBXVariantGroup; - children = ( - 53BF83DD2B0910510035E5BA /* Base */, - ); - name = LaunchScreen.storyboard; - sourceTree = ""; - }; - 53BF83DF2B0910510035E5BA /* Main.storyboard */ = { - isa = PBXVariantGroup; - children = ( - 53BF83E02B0910510035E5BA /* Base */, - ); - name = Main.storyboard; - sourceTree = ""; - }; - 53BF83EB2B0910510035E5BA /* Main.storyboard */ = { - isa = PBXVariantGroup; - children = ( - 53BF83EC2B0910510035E5BA /* Base */, - ); - name = Main.storyboard; - sourceTree = ""; - }; -/* End PBXVariantGroup section */ - -/* Begin XCBuildConfiguration section */ - 53BF84222B0910510035E5BA /* Debug */ = { - isa = XCBuildConfiguration; - buildSettings = { - ALWAYS_SEARCH_USER_PATHS = NO; - ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES; - CLANG_ANALYZER_NONNULL = YES; - CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++20"; - CLANG_ENABLE_MODULES = YES; - CLANG_ENABLE_OBJC_ARC = YES; - CLANG_ENABLE_OBJC_WEAK = YES; - CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; - CLANG_WARN_BOOL_CONVERSION = YES; - CLANG_WARN_COMMA = YES; - CLANG_WARN_CONSTANT_CONVERSION = YES; - CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; - CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; - CLANG_WARN_DOCUMENTATION_COMMENTS = YES; - CLANG_WARN_EMPTY_BODY = YES; - CLANG_WARN_ENUM_CONVERSION = YES; - CLANG_WARN_INFINITE_RECURSION = YES; - CLANG_WARN_INT_CONVERSION = YES; - CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; - CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; - CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; - CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; - CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; - CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; - CLANG_WARN_STRICT_PROTOTYPES = YES; - CLANG_WARN_SUSPICIOUS_MOVE = YES; - CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; - CLANG_WARN_UNREACHABLE_CODE = YES; - CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; - COPY_PHASE_STRIP = NO; - DEBUG_INFORMATION_FORMAT = dwarf; - ENABLE_STRICT_OBJC_MSGSEND = YES; - ENABLE_TESTABILITY = YES; - ENABLE_USER_SCRIPT_SANDBOXING = YES; - GCC_C_LANGUAGE_STANDARD = gnu17; - GCC_DYNAMIC_NO_PIC = NO; - GCC_NO_COMMON_BLOCKS = YES; - GCC_OPTIMIZATION_LEVEL = 0; - GCC_PREPROCESSOR_DEFINITIONS = ( - "DEBUG=1", - "$(inherited)", - ); - GCC_WARN_64_TO_32_BIT_CONVERSION = YES; - GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; - GCC_WARN_UNDECLARED_SELECTOR = YES; - GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; - GCC_WARN_UNUSED_FUNCTION = YES; - GCC_WARN_UNUSED_VARIABLE = YES; - LOCALIZATION_PREFERS_STRING_CATALOGS = YES; - MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; - MTL_FAST_MATH = YES; - ONLY_ACTIVE_ARCH = YES; - SWIFT_ACTIVE_COMPILATION_CONDITIONS = "DEBUG $(inherited)"; - SWIFT_OPTIMIZATION_LEVEL = "-Onone"; - }; - name = Debug; - }; - 53BF84232B0910510035E5BA /* Release */ = { - isa = XCBuildConfiguration; - buildSettings = { - ALWAYS_SEARCH_USER_PATHS = NO; - ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES; - CLANG_ANALYZER_NONNULL = YES; - CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++20"; - CLANG_ENABLE_MODULES = YES; - CLANG_ENABLE_OBJC_ARC = YES; - CLANG_ENABLE_OBJC_WEAK = YES; - CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; - CLANG_WARN_BOOL_CONVERSION = YES; - CLANG_WARN_COMMA = YES; - CLANG_WARN_CONSTANT_CONVERSION = YES; - CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; - CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; - CLANG_WARN_DOCUMENTATION_COMMENTS = YES; - CLANG_WARN_EMPTY_BODY = YES; - CLANG_WARN_ENUM_CONVERSION = YES; - CLANG_WARN_INFINITE_RECURSION = YES; - CLANG_WARN_INT_CONVERSION = YES; - CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; - CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; - CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; - CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; - CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; - CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; - CLANG_WARN_STRICT_PROTOTYPES = YES; - CLANG_WARN_SUSPICIOUS_MOVE = YES; - CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; - CLANG_WARN_UNREACHABLE_CODE = YES; - CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; - COPY_PHASE_STRIP = NO; - DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; - ENABLE_NS_ASSERTIONS = NO; - ENABLE_STRICT_OBJC_MSGSEND = YES; - ENABLE_USER_SCRIPT_SANDBOXING = YES; - GCC_C_LANGUAGE_STANDARD = gnu17; - GCC_NO_COMMON_BLOCKS = YES; - GCC_WARN_64_TO_32_BIT_CONVERSION = YES; - GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; - GCC_WARN_UNDECLARED_SELECTOR = YES; - GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; - GCC_WARN_UNUSED_FUNCTION = YES; - GCC_WARN_UNUSED_VARIABLE = YES; - LOCALIZATION_PREFERS_STRING_CATALOGS = YES; - MTL_ENABLE_DEBUG_INFO = NO; - MTL_FAST_MATH = YES; - SWIFT_COMPILATION_MODE = wholemodule; - }; - name = Release; - }; - 53BF84252B0910510035E5BA /* Debug */ = { - isa = XCBuildConfiguration; - buildSettings = { - CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 1; - GENERATE_INFOPLIST_FILE = YES; - INFOPLIST_FILE = "iOS (Extension)/Info.plist"; - INFOPLIST_KEY_CFBundleDisplayName = "HyperTab Extension"; - INFOPLIST_KEY_NSHumanReadableCopyright = ""; - IPHONEOS_DEPLOYMENT_TARGET = 15.0; - LD_RUNPATH_SEARCH_PATHS = ( - "$(inherited)", - "@executable_path/Frameworks", - "@executable_path/../../Frameworks", - ); - MARKETING_VERSION = 1.0; - OTHER_LDFLAGS = ( - "-framework", - SafariServices, - ); - PRODUCT_BUNDLE_IDENTIFIER = net.heliosia.HyperTab.Extension; - PRODUCT_NAME = "HyperTab Extension"; - SDKROOT = iphoneos; - SKIP_INSTALL = YES; - SWIFT_EMIT_LOC_STRINGS = YES; - SWIFT_VERSION = 5.0; - TARGETED_DEVICE_FAMILY = "1,2"; - }; - name = Debug; - }; - 53BF84262B0910510035E5BA /* Release */ = { - isa = XCBuildConfiguration; - buildSettings = { - CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 1; - GENERATE_INFOPLIST_FILE = YES; - INFOPLIST_FILE = "iOS (Extension)/Info.plist"; - INFOPLIST_KEY_CFBundleDisplayName = "HyperTab Extension"; - INFOPLIST_KEY_NSHumanReadableCopyright = ""; - IPHONEOS_DEPLOYMENT_TARGET = 15.0; - LD_RUNPATH_SEARCH_PATHS = ( - "$(inherited)", - "@executable_path/Frameworks", - "@executable_path/../../Frameworks", - ); - MARKETING_VERSION = 1.0; - OTHER_LDFLAGS = ( - "-framework", - SafariServices, - ); - PRODUCT_BUNDLE_IDENTIFIER = net.heliosia.HyperTab.Extension; - PRODUCT_NAME = "HyperTab Extension"; - SDKROOT = iphoneos; - SKIP_INSTALL = YES; - SWIFT_EMIT_LOC_STRINGS = YES; - SWIFT_VERSION = 5.0; - TARGETED_DEVICE_FAMILY = "1,2"; - VALIDATE_PRODUCT = YES; - }; - name = Release; - }; - 53BF84292B0910510035E5BA /* Debug */ = { - isa = XCBuildConfiguration; - buildSettings = { - ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; - ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; - ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; - CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 1; - GENERATE_INFOPLIST_FILE = YES; - INFOPLIST_FILE = "iOS (App)/Info.plist"; - INFOPLIST_KEY_CFBundleDisplayName = HyperTab; - INFOPLIST_KEY_UIApplicationSupportsIndirectInputEvents = YES; - INFOPLIST_KEY_UILaunchStoryboardName = LaunchScreen; - INFOPLIST_KEY_UIMainStoryboardFile = Main; - INFOPLIST_KEY_UISupportedInterfaceOrientations = "UIInterfaceOrientationPortrait UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight"; - INFOPLIST_KEY_UISupportedInterfaceOrientations_iPad = "UIInterfaceOrientationPortrait UIInterfaceOrientationPortraitUpsideDown UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight"; - IPHONEOS_DEPLOYMENT_TARGET = 15.0; - LD_RUNPATH_SEARCH_PATHS = ( - "$(inherited)", - "@executable_path/Frameworks", - ); - MARKETING_VERSION = 1.0; - OTHER_LDFLAGS = ( - "-framework", - SafariServices, - "-framework", - WebKit, - ); - PRODUCT_BUNDLE_IDENTIFIER = net.heliosia.HyperTab; - PRODUCT_NAME = HyperTab; - SDKROOT = iphoneos; - SWIFT_EMIT_LOC_STRINGS = YES; - SWIFT_VERSION = 5.0; - TARGETED_DEVICE_FAMILY = "1,2"; - }; - name = Debug; - }; - 53BF842A2B0910510035E5BA /* Release */ = { - isa = XCBuildConfiguration; - buildSettings = { - ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; - ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; - ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; - CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 1; - GENERATE_INFOPLIST_FILE = YES; - INFOPLIST_FILE = "iOS (App)/Info.plist"; - INFOPLIST_KEY_CFBundleDisplayName = HyperTab; - INFOPLIST_KEY_UIApplicationSupportsIndirectInputEvents = YES; - INFOPLIST_KEY_UILaunchStoryboardName = LaunchScreen; - INFOPLIST_KEY_UIMainStoryboardFile = Main; - INFOPLIST_KEY_UISupportedInterfaceOrientations = "UIInterfaceOrientationPortrait UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight"; - INFOPLIST_KEY_UISupportedInterfaceOrientations_iPad = "UIInterfaceOrientationPortrait UIInterfaceOrientationPortraitUpsideDown UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight"; - IPHONEOS_DEPLOYMENT_TARGET = 15.0; - LD_RUNPATH_SEARCH_PATHS = ( - "$(inherited)", - "@executable_path/Frameworks", - ); - MARKETING_VERSION = 1.0; - OTHER_LDFLAGS = ( - "-framework", - SafariServices, - "-framework", - WebKit, - ); - PRODUCT_BUNDLE_IDENTIFIER = net.heliosia.HyperTab; - PRODUCT_NAME = HyperTab; - SDKROOT = iphoneos; - SWIFT_EMIT_LOC_STRINGS = YES; - SWIFT_VERSION = 5.0; - TARGETED_DEVICE_FAMILY = "1,2"; - VALIDATE_PRODUCT = YES; - }; - name = Release; - }; - 53BF842C2B0910510035E5BA /* Debug */ = { - isa = XCBuildConfiguration; - buildSettings = { - CODE_SIGN_ENTITLEMENTS = "macOS (Extension)/HyperTab.entitlements"; - CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 1; - ENABLE_HARDENED_RUNTIME = YES; - GENERATE_INFOPLIST_FILE = YES; - INFOPLIST_FILE = "macOS (Extension)/Info.plist"; - INFOPLIST_KEY_CFBundleDisplayName = "HyperTab Extension"; - INFOPLIST_KEY_NSHumanReadableCopyright = ""; - LD_RUNPATH_SEARCH_PATHS = ( - "$(inherited)", - "@executable_path/../Frameworks", - "@executable_path/../../../../Frameworks", - ); - MACOSX_DEPLOYMENT_TARGET = 10.14; - MARKETING_VERSION = 1.0; - OTHER_LDFLAGS = ( - "-framework", - SafariServices, - ); - PRODUCT_BUNDLE_IDENTIFIER = net.heliosia.HyperTab.Extension; - PRODUCT_NAME = "HyperTab Extension"; - SDKROOT = macosx; - SKIP_INSTALL = YES; - SWIFT_EMIT_LOC_STRINGS = YES; - SWIFT_VERSION = 5.0; - }; - name = Debug; - }; - 53BF842D2B0910510035E5BA /* Release */ = { - isa = XCBuildConfiguration; - buildSettings = { - CODE_SIGN_ENTITLEMENTS = "macOS (Extension)/HyperTab.entitlements"; - CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 1; - ENABLE_HARDENED_RUNTIME = YES; - GENERATE_INFOPLIST_FILE = YES; - INFOPLIST_FILE = "macOS (Extension)/Info.plist"; - INFOPLIST_KEY_CFBundleDisplayName = "HyperTab Extension"; - INFOPLIST_KEY_NSHumanReadableCopyright = ""; - LD_RUNPATH_SEARCH_PATHS = ( - "$(inherited)", - "@executable_path/../Frameworks", - "@executable_path/../../../../Frameworks", - ); - MACOSX_DEPLOYMENT_TARGET = 10.14; - MARKETING_VERSION = 1.0; - OTHER_LDFLAGS = ( - "-framework", - SafariServices, - ); - PRODUCT_BUNDLE_IDENTIFIER = net.heliosia.HyperTab.Extension; - PRODUCT_NAME = "HyperTab Extension"; - SDKROOT = macosx; - SKIP_INSTALL = YES; - SWIFT_EMIT_LOC_STRINGS = YES; - SWIFT_VERSION = 5.0; - }; - name = Release; - }; - 53BF84302B0910510035E5BA /* Debug */ = { - isa = XCBuildConfiguration; - buildSettings = { - ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; - ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; - ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; - CODE_SIGN_ENTITLEMENTS = "macOS (App)/HyperTab.entitlements"; - CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 1; - ENABLE_HARDENED_RUNTIME = YES; - GENERATE_INFOPLIST_FILE = YES; - INFOPLIST_KEY_CFBundleDisplayName = HyperTab; - INFOPLIST_KEY_NSMainStoryboardFile = Main; - INFOPLIST_KEY_NSPrincipalClass = NSApplication; - LD_RUNPATH_SEARCH_PATHS = ( - "$(inherited)", - "@executable_path/../Frameworks", - ); - MACOSX_DEPLOYMENT_TARGET = 10.14; - MARKETING_VERSION = 1.0; - OTHER_LDFLAGS = ( - "-framework", - SafariServices, - "-framework", - WebKit, - ); - PRODUCT_BUNDLE_IDENTIFIER = net.heliosia.HyperTab; - PRODUCT_NAME = HyperTab; - SDKROOT = macosx; - SWIFT_EMIT_LOC_STRINGS = YES; - SWIFT_VERSION = 5.0; - }; - name = Debug; - }; - 53BF84312B0910510035E5BA /* Release */ = { - isa = XCBuildConfiguration; - buildSettings = { - ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; - ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; - ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; - CODE_SIGN_ENTITLEMENTS = "macOS (App)/HyperTab.entitlements"; - CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 1; - ENABLE_HARDENED_RUNTIME = YES; - GENERATE_INFOPLIST_FILE = YES; - INFOPLIST_KEY_CFBundleDisplayName = HyperTab; - INFOPLIST_KEY_NSMainStoryboardFile = Main; - INFOPLIST_KEY_NSPrincipalClass = NSApplication; - LD_RUNPATH_SEARCH_PATHS = ( - "$(inherited)", - "@executable_path/../Frameworks", - ); - MACOSX_DEPLOYMENT_TARGET = 10.14; - MARKETING_VERSION = 1.0; - OTHER_LDFLAGS = ( - "-framework", - SafariServices, - "-framework", - WebKit, - ); - PRODUCT_BUNDLE_IDENTIFIER = net.heliosia.HyperTab; - PRODUCT_NAME = HyperTab; - SDKROOT = macosx; - SWIFT_EMIT_LOC_STRINGS = YES; - SWIFT_VERSION = 5.0; - }; - name = Release; - }; -/* End XCBuildConfiguration section */ - -/* Begin XCConfigurationList section */ - 53BF83BC2B0910500035E5BA /* Build configuration list for PBXProject "HyperTab" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - 53BF84222B0910510035E5BA /* Debug */, - 53BF84232B0910510035E5BA /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; - 53BF84242B0910510035E5BA /* Build configuration list for PBXNativeTarget "HyperTab Extension (iOS)" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - 53BF84252B0910510035E5BA /* Debug */, - 53BF84262B0910510035E5BA /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; - 53BF84282B0910510035E5BA /* Build configuration list for PBXNativeTarget "HyperTab (iOS)" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - 53BF84292B0910510035E5BA /* Debug */, - 53BF842A2B0910510035E5BA /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; - 53BF842B2B0910510035E5BA /* Build configuration list for PBXNativeTarget "HyperTab Extension (macOS)" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - 53BF842C2B0910510035E5BA /* Debug */, - 53BF842D2B0910510035E5BA /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; - 53BF842F2B0910510035E5BA /* Build configuration list for PBXNativeTarget "HyperTab (macOS)" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - 53BF84302B0910510035E5BA /* Debug */, - 53BF84312B0910510035E5BA /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; -/* End XCConfigurationList section */ - }; - rootObject = 53BF83B92B0910500035E5BA /* Project object */; -} diff --git a/HyperTab.xcodeproj/project.xcworkspace/contents.xcworkspacedata b/HyperTab.xcodeproj/project.xcworkspace/contents.xcworkspacedata deleted file mode 100644 index 919434a..0000000 --- a/HyperTab.xcodeproj/project.xcworkspace/contents.xcworkspacedata +++ /dev/null @@ -1,7 +0,0 @@ - - - - - diff --git a/HyperTab.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/HyperTab.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist deleted file mode 100644 index 18d9810..0000000 --- a/HyperTab.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist +++ /dev/null @@ -1,8 +0,0 @@ - - - - - IDEDidComputeMac32BitWarning - - - diff --git a/HyperTab.xcodeproj/xcuserdata/nkcmr.xcuserdatad/xcschemes/xcschememanagement.plist b/HyperTab.xcodeproj/xcuserdata/nkcmr.xcuserdatad/xcschemes/xcschememanagement.plist deleted file mode 100644 index 53fd3eb..0000000 --- a/HyperTab.xcodeproj/xcuserdata/nkcmr.xcuserdatad/xcschemes/xcschememanagement.plist +++ /dev/null @@ -1,19 +0,0 @@ - - - - - SchemeUserState - - HyperTab (iOS).xcscheme_^#shared#^_ - - orderHint - 1 - - HyperTab (macOS).xcscheme_^#shared#^_ - - orderHint - 0 - - - - diff --git a/Shared (App)/Assets.xcassets/AccentColor.colorset/Contents.json b/Shared (App)/Assets.xcassets/AccentColor.colorset/Contents.json deleted file mode 100644 index eb87897..0000000 --- a/Shared (App)/Assets.xcassets/AccentColor.colorset/Contents.json +++ /dev/null @@ -1,11 +0,0 @@ -{ - "colors" : [ - { - "idiom" : "universal" - } - ], - "info" : { - "author" : "xcode", - "version" : 1 - } -} diff --git a/Shared (App)/Assets.xcassets/AppIcon.appiconset/Contents.json b/Shared (App)/Assets.xcassets/AppIcon.appiconset/Contents.json deleted file mode 100644 index 532cd72..0000000 --- a/Shared (App)/Assets.xcassets/AppIcon.appiconset/Contents.json +++ /dev/null @@ -1,63 +0,0 @@ -{ - "images" : [ - { - "idiom" : "universal", - "platform" : "ios", - "size" : "1024x1024" - }, - { - "idiom" : "mac", - "scale" : "1x", - "size" : "16x16" - }, - { - "idiom" : "mac", - "scale" : "2x", - "size" : "16x16" - }, - { - "idiom" : "mac", - "scale" : "1x", - "size" : "32x32" - }, - { - "idiom" : "mac", - "scale" : "2x", - "size" : "32x32" - }, - { - "idiom" : "mac", - "scale" : "1x", - "size" : "128x128" - }, - { - "idiom" : "mac", - "scale" : "2x", - "size" : "128x128" - }, - { - "idiom" : "mac", - "scale" : "1x", - "size" : "256x256" - }, - { - "idiom" : "mac", - "scale" : "2x", - "size" : "256x256" - }, - { - "idiom" : "mac", - "scale" : "1x", - "size" : "512x512" - }, - { - "idiom" : "mac", - "scale" : "2x", - "size" : "512x512" - } - ], - "info" : { - "author" : "xcode", - "version" : 1 - } -} diff --git a/Shared (App)/Assets.xcassets/Contents.json b/Shared (App)/Assets.xcassets/Contents.json deleted file mode 100644 index 73c0059..0000000 --- a/Shared (App)/Assets.xcassets/Contents.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "info" : { - "author" : "xcode", - "version" : 1 - } -} diff --git a/Shared (App)/Assets.xcassets/LargeIcon.imageset/Contents.json b/Shared (App)/Assets.xcassets/LargeIcon.imageset/Contents.json deleted file mode 100644 index a19a549..0000000 --- a/Shared (App)/Assets.xcassets/LargeIcon.imageset/Contents.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "images" : [ - { - "idiom" : "universal", - "scale" : "1x" - }, - { - "idiom" : "universal", - "scale" : "2x" - }, - { - "idiom" : "universal", - "scale" : "3x" - } - ], - "info" : { - "author" : "xcode", - "version" : 1 - } -} diff --git a/Shared (App)/Base.lproj/Main.html b/Shared (App)/Base.lproj/Main.html deleted file mode 100644 index 77f4f0d..0000000 --- a/Shared (App)/Base.lproj/Main.html +++ /dev/null @@ -1,20 +0,0 @@ - - - - - - - - - - - - - HyperTab Icon -

You can turn on HyperTab’s Safari extension in Settings.

-

You can turn on HyperTab’s extension in Safari Extensions preferences.

-

HyperTab’s extension is currently on. You can turn it off in Safari Extensions preferences.

-

HyperTab’s extension is currently off. You can turn it on in Safari Extensions preferences.

- - - diff --git a/Shared (App)/Resources/Icon.png b/Shared (App)/Resources/Icon.png deleted file mode 100644 index 423b491..0000000 Binary files a/Shared (App)/Resources/Icon.png and /dev/null differ diff --git a/Shared (App)/Resources/Script.js b/Shared (App)/Resources/Script.js deleted file mode 100644 index 2eb8098..0000000 --- a/Shared (App)/Resources/Script.js +++ /dev/null @@ -1,24 +0,0 @@ -function show(platform, enabled, useSettingsInsteadOfPreferences) { - document.body.classList.add(`platform-${platform}`); - - if (useSettingsInsteadOfPreferences) { - document.getElementsByClassName('platform-mac state-on')[0].innerText = "HyperTab’s extension is currently on. You can turn it off in the Extensions section of Safari Settings."; - document.getElementsByClassName('platform-mac state-off')[0].innerText = "HyperTab’s extension is currently off. You can turn it on in the Extensions section of Safari Settings."; - document.getElementsByClassName('platform-mac state-unknown')[0].innerText = "You can turn on HyperTab’s extension in the Extensions section of Safari Settings."; - document.getElementsByClassName('platform-mac open-preferences')[0].innerText = "Quit and Open Safari Settings…"; - } - - if (typeof enabled === "boolean") { - document.body.classList.toggle(`state-on`, enabled); - document.body.classList.toggle(`state-off`, !enabled); - } else { - document.body.classList.remove(`state-on`); - document.body.classList.remove(`state-off`); - } -} - -function openPreferences() { - webkit.messageHandlers.controller.postMessage("open-preferences"); -} - -document.querySelector("button.open-preferences").addEventListener("click", openPreferences); diff --git a/Shared (App)/Resources/Style.css b/Shared (App)/Resources/Style.css deleted file mode 100644 index b6d0608..0000000 --- a/Shared (App)/Resources/Style.css +++ /dev/null @@ -1,61 +0,0 @@ -* { - -webkit-user-select: none; - -webkit-user-drag: none; - cursor: default; -} - -:root { - color-scheme: light dark; - - --spacing: 20px; -} - -html { - height: 100%; -} - -body { - display: flex; - align-items: center; - justify-content: center; - flex-direction: column; - - gap: var(--spacing); - margin: 0 calc(var(--spacing) * 2); - height: 100%; - - font: -apple-system-short-body; - text-align: center; -} - -body:not(.platform-mac, .platform-ios) :is(.platform-mac, .platform-ios) { - display: none; -} - -body.platform-ios .platform-mac { - display: none; -} - -body.platform-mac .platform-ios { - display: none; -} - -body.platform-ios .platform-mac { - display: none; -} - -body:not(.state-on, .state-off) :is(.state-on, .state-off) { - display: none; -} - -body.state-on :is(.state-off, .state-unknown) { - display: none; -} - -body.state-off :is(.state-on, .state-unknown) { - display: none; -} - -button { - font-size: 1em; -} diff --git a/Shared (App)/ViewController.swift b/Shared (App)/ViewController.swift deleted file mode 100644 index 5ee882c..0000000 --- a/Shared (App)/ViewController.swift +++ /dev/null @@ -1,81 +0,0 @@ -// -// ViewController.swift -// Shared (App) -// -// Created by Nicholas Comer on 11/18/23. -// - -import WebKit - -#if os(iOS) -import UIKit -typealias PlatformViewController = UIViewController -#elseif os(macOS) -import Cocoa -import SafariServices -typealias PlatformViewController = NSViewController -#endif - -let extensionBundleIdentifier = "net.heliosia.HyperTab.Extension" - -class ViewController: PlatformViewController, WKNavigationDelegate, WKScriptMessageHandler { - - @IBOutlet var webView: WKWebView! - - override func viewDidLoad() { - super.viewDidLoad() - - self.webView.navigationDelegate = self - -#if os(iOS) - self.webView.scrollView.isScrollEnabled = false -#endif - - self.webView.configuration.userContentController.add(self, name: "controller") - - self.webView.loadFileURL(Bundle.main.url(forResource: "Main", withExtension: "html")!, allowingReadAccessTo: Bundle.main.resourceURL!) - } - - func webView(_ webView: WKWebView, didFinish navigation: WKNavigation!) { -#if os(iOS) - webView.evaluateJavaScript("show('ios')") -#elseif os(macOS) - webView.evaluateJavaScript("show('mac')") - - SFSafariExtensionManager.getStateOfSafariExtension(withIdentifier: extensionBundleIdentifier) { (state, error) in - guard let state = state, error == nil else { - // Insert code to inform the user that something went wrong. - return - } - - DispatchQueue.main.async { - if #available(macOS 13, *) { - webView.evaluateJavaScript("show('mac', \(state.isEnabled), true)") - } else { - webView.evaluateJavaScript("show('mac', \(state.isEnabled), false)") - } - } - } -#endif - } - - func userContentController(_ userContentController: WKUserContentController, didReceive message: WKScriptMessage) { -#if os(macOS) - if (message.body as! String != "open-preferences") { - return - } - - SFSafariApplication.showPreferencesForExtension(withIdentifier: extensionBundleIdentifier) { error in - guard error == nil else { - // Insert code to inform the user that something went wrong. - return - } - - DispatchQueue.main.async { - NSApp.terminate(self) - } - } -#endif - } - -} diff --git a/Shared (Extension)/Resources/background.js b/Shared (Extension)/Resources/background.js deleted file mode 100644 index ff39b3b..0000000 --- a/Shared (Extension)/Resources/background.js +++ /dev/null @@ -1,6 +0,0 @@ -browser.runtime.onMessage.addListener((request, sender, sendResponse) => { - console.log("Received request: ", request); - - if (request.greeting === "hello") - sendResponse({ farewell: "goodbye" }); -}); diff --git a/Shared (Extension)/Resources/content.js b/Shared (Extension)/Resources/content.js deleted file mode 100644 index d4c3f2b..0000000 --- a/Shared (Extension)/Resources/content.js +++ /dev/null @@ -1,7 +0,0 @@ -browser.runtime.sendMessage({ greeting: "hello" }).then((response) => { - console.log("Received response: ", response); -}); - -browser.runtime.onMessage.addListener((request, sender, sendResponse) => { - console.log("Received request: ", request); -}); diff --git a/Shared (Extension)/Resources/images/icon-128.png b/Shared (Extension)/Resources/images/icon-128.png deleted file mode 100644 index c919eb0..0000000 Binary files a/Shared (Extension)/Resources/images/icon-128.png and /dev/null differ diff --git a/Shared (Extension)/Resources/images/icon-256.png b/Shared (Extension)/Resources/images/icon-256.png deleted file mode 100644 index 6bd3d20..0000000 Binary files a/Shared (Extension)/Resources/images/icon-256.png and /dev/null differ diff --git a/Shared (Extension)/Resources/images/icon-48.png b/Shared (Extension)/Resources/images/icon-48.png deleted file mode 100644 index 353e8fb..0000000 Binary files a/Shared (Extension)/Resources/images/icon-48.png and /dev/null differ diff --git a/Shared (Extension)/Resources/images/icon-512.png b/Shared (Extension)/Resources/images/icon-512.png deleted file mode 100644 index 2200828..0000000 Binary files a/Shared (Extension)/Resources/images/icon-512.png and /dev/null differ diff --git a/Shared (Extension)/Resources/images/icon-64.png b/Shared (Extension)/Resources/images/icon-64.png deleted file mode 100644 index 995689f..0000000 Binary files a/Shared (Extension)/Resources/images/icon-64.png and /dev/null differ diff --git a/Shared (Extension)/Resources/images/icon-96.png b/Shared (Extension)/Resources/images/icon-96.png deleted file mode 100644 index cb079d2..0000000 Binary files a/Shared (Extension)/Resources/images/icon-96.png and /dev/null differ diff --git a/Shared (Extension)/Resources/images/toolbar-icon-16.png b/Shared (Extension)/Resources/images/toolbar-icon-16.png deleted file mode 100644 index ad014f6..0000000 Binary files a/Shared (Extension)/Resources/images/toolbar-icon-16.png and /dev/null differ diff --git a/Shared (Extension)/Resources/images/toolbar-icon-19.png b/Shared (Extension)/Resources/images/toolbar-icon-19.png deleted file mode 100644 index 33eb01e..0000000 Binary files a/Shared (Extension)/Resources/images/toolbar-icon-19.png and /dev/null differ diff --git a/Shared (Extension)/Resources/images/toolbar-icon-32.png b/Shared (Extension)/Resources/images/toolbar-icon-32.png deleted file mode 100644 index a71914b..0000000 Binary files a/Shared (Extension)/Resources/images/toolbar-icon-32.png and /dev/null differ diff --git a/Shared (Extension)/Resources/images/toolbar-icon-38.png b/Shared (Extension)/Resources/images/toolbar-icon-38.png deleted file mode 100644 index 990e7f4..0000000 Binary files a/Shared (Extension)/Resources/images/toolbar-icon-38.png and /dev/null differ diff --git a/Shared (Extension)/Resources/images/toolbar-icon-48.png b/Shared (Extension)/Resources/images/toolbar-icon-48.png deleted file mode 100644 index f4c70ad..0000000 Binary files a/Shared (Extension)/Resources/images/toolbar-icon-48.png and /dev/null differ diff --git a/Shared (Extension)/Resources/images/toolbar-icon-72.png b/Shared (Extension)/Resources/images/toolbar-icon-72.png deleted file mode 100644 index 9bf6d4e..0000000 Binary files a/Shared (Extension)/Resources/images/toolbar-icon-72.png and /dev/null differ diff --git a/Shared (Extension)/Resources/manifest.json b/Shared (Extension)/Resources/manifest.json deleted file mode 100644 index b621d37..0000000 --- a/Shared (Extension)/Resources/manifest.json +++ /dev/null @@ -1,39 +0,0 @@ -{ - "manifest_version": 3, - "default_locale": "en", - - "name": "__MSG_extension_name__", - "description": "__MSG_extension_description__", - "version": "1.0", - - "icons": { - "48": "images/icon-48.png", - "96": "images/icon-96.png", - "128": "images/icon-128.png", - "256": "images/icon-256.png", - "512": "images/icon-512.png" - }, - - "background": { - "service_worker": "background.js" - }, - - "content_scripts": [{ - "js": [ "content.js" ], - "matches": [ "*://example.com/*" ] - }], - - "action": { - "default_popup": "popup.html", - "default_icon": { - "16": "images/toolbar-icon-16.png", - "19": "images/toolbar-icon-19.png", - "32": "images/toolbar-icon-32.png", - "38": "images/toolbar-icon-38.png", - "48": "images/toolbar-icon-48.png", - "72": "images/toolbar-icon-72.png" - } - }, - - "permissions": [ ] -} diff --git a/Shared (Extension)/Resources/popup.css b/Shared (Extension)/Resources/popup.css deleted file mode 100644 index 5b149b9..0000000 --- a/Shared (Extension)/Resources/popup.css +++ /dev/null @@ -1,15 +0,0 @@ -:root { - color-scheme: light dark; -} - -body { - width: 100px; - padding: 10px; - - font-family: system-ui; - text-align: center; -} - -@media (prefers-color-scheme: dark) { - /* Dark Mode styles go here. */ -} diff --git a/Shared (Extension)/Resources/popup.html b/Shared (Extension)/Resources/popup.html deleted file mode 100644 index ac52319..0000000 --- a/Shared (Extension)/Resources/popup.html +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - - - - Hello World! - - diff --git a/Shared (Extension)/Resources/popup.js b/Shared (Extension)/Resources/popup.js deleted file mode 100644 index 5c1aa86..0000000 --- a/Shared (Extension)/Resources/popup.js +++ /dev/null @@ -1 +0,0 @@ -console.log("Hello World!", browser); diff --git a/Shared (Extension)/SafariWebExtensionHandler.swift b/Shared (Extension)/SafariWebExtensionHandler.swift deleted file mode 100644 index de9face..0000000 --- a/Shared (Extension)/SafariWebExtensionHandler.swift +++ /dev/null @@ -1,38 +0,0 @@ -// -// SafariWebExtensionHandler.swift -// Shared (Extension) -// -// Created by Nicholas Comer on 11/18/23. -// - -import SafariServices -import os.log - -class SafariWebExtensionHandler: NSObject, NSExtensionRequestHandling { - - func beginRequest(with context: NSExtensionContext) { - let request = context.inputItems.first as? NSExtensionItem - - let profile: UUID? - if #available(iOS 17.0, macOS 14.0, *) { - profile = request?.userInfo?[SFExtensionProfileKey] as? UUID - } else { - profile = request?.userInfo?["profile"] as? UUID - } - - let message: Any? - if #available(iOS 17.0, macOS 14.0, *) { - message = request?.userInfo?[SFExtensionMessageKey] - } else { - message = request?.userInfo?["message"] - } - - os_log(.default, "Received message from browser.runtime.sendNativeMessage: %@ (profile: %@)", String(describing: message), profile?.uuidString ?? "none") - - let response = NSExtensionItem() - response.userInfo = [ SFExtensionMessageKey: [ "echo": message ] ] - - context.completeRequest(returningItems: [ response ], completionHandler: nil) - } - -} diff --git a/Shared (Extension)/Resources/_locales/en/messages.json b/_locales/en/messages.json similarity index 71% rename from Shared (Extension)/Resources/_locales/en/messages.json rename to _locales/en/messages.json index 986ae95..4b1bf9e 100644 --- a/Shared (Extension)/Resources/_locales/en/messages.json +++ b/_locales/en/messages.json @@ -4,7 +4,7 @@ "description": "The display name for the extension." }, "extension_description": { - "message": "This is HyperTab. You should tell us what your extension does here.", + "message": "Quick Tab Search and Switch for Safari", "description": "Description of what the extension does." } } diff --git a/iOS (App)/AppDelegate.swift b/iOS (App)/AppDelegate.swift deleted file mode 100644 index a7b3f64..0000000 --- a/iOS (App)/AppDelegate.swift +++ /dev/null @@ -1,24 +0,0 @@ -// -// AppDelegate.swift -// iOS (App) -// -// Created by Nicholas Comer on 11/18/23. -// - -import UIKit - -@main -class AppDelegate: UIResponder, UIApplicationDelegate { - - var window: UIWindow? - - func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool { - // Override point for customization after application launch. - return true - } - - func application(_ application: UIApplication, configurationForConnecting connectingSceneSession: UISceneSession, options: UIScene.ConnectionOptions) -> UISceneConfiguration { - return UISceneConfiguration(name: "Default Configuration", sessionRole: connectingSceneSession.role) - } - -} diff --git a/iOS (App)/Base.lproj/LaunchScreen.storyboard b/iOS (App)/Base.lproj/LaunchScreen.storyboard deleted file mode 100644 index 620a70c..0000000 --- a/iOS (App)/Base.lproj/LaunchScreen.storyboard +++ /dev/null @@ -1,36 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/iOS (App)/Base.lproj/Main.storyboard b/iOS (App)/Base.lproj/Main.storyboard deleted file mode 100644 index 618dfce..0000000 --- a/iOS (App)/Base.lproj/Main.storyboard +++ /dev/null @@ -1,38 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/iOS (App)/Info.plist b/iOS (App)/Info.plist deleted file mode 100644 index dd3c9af..0000000 --- a/iOS (App)/Info.plist +++ /dev/null @@ -1,25 +0,0 @@ - - - - - UIApplicationSceneManifest - - UIApplicationSupportsMultipleScenes - - UISceneConfigurations - - UIWindowSceneSessionRoleApplication - - - UISceneConfigurationName - Default Configuration - UISceneDelegateClassName - $(PRODUCT_MODULE_NAME).SceneDelegate - UISceneStoryboardFile - Main - - - - - - diff --git a/iOS (App)/SceneDelegate.swift b/iOS (App)/SceneDelegate.swift deleted file mode 100644 index ec59c9e..0000000 --- a/iOS (App)/SceneDelegate.swift +++ /dev/null @@ -1,18 +0,0 @@ -// -// SceneDelegate.swift -// iOS (App) -// -// Created by Nicholas Comer on 11/18/23. -// - -import UIKit - -class SceneDelegate: UIResponder, UIWindowSceneDelegate { - - var window: UIWindow? - - func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) { - guard let _ = (scene as? UIWindowScene) else { return } - } - -} diff --git a/iOS (Extension)/Info.plist b/iOS (Extension)/Info.plist deleted file mode 100644 index 9ee504d..0000000 --- a/iOS (Extension)/Info.plist +++ /dev/null @@ -1,13 +0,0 @@ - - - - - NSExtension - - NSExtensionPointIdentifier - com.apple.Safari.web-extension - NSExtensionPrincipalClass - $(PRODUCT_MODULE_NAME).SafariWebExtensionHandler - - - diff --git a/images/icon-128.png b/images/icon-128.png new file mode 100644 index 0000000..11ac17d Binary files /dev/null and b/images/icon-128.png differ diff --git a/images/icon-256.png b/images/icon-256.png new file mode 100644 index 0000000..1dbbcf1 Binary files /dev/null and b/images/icon-256.png differ diff --git a/images/icon-48.png b/images/icon-48.png new file mode 100644 index 0000000..c425c1a Binary files /dev/null and b/images/icon-48.png differ diff --git a/images/icon-512.png b/images/icon-512.png new file mode 100644 index 0000000..df86f87 Binary files /dev/null and b/images/icon-512.png differ diff --git a/images/icon-64.png b/images/icon-64.png new file mode 100644 index 0000000..480b0a6 Binary files /dev/null and b/images/icon-64.png differ diff --git a/images/icon-96.png b/images/icon-96.png new file mode 100644 index 0000000..644b8ac Binary files /dev/null and b/images/icon-96.png differ diff --git a/images/toolbar-icon-16.png b/images/toolbar-icon-16.png new file mode 100755 index 0000000..bb5f047 Binary files /dev/null and b/images/toolbar-icon-16.png differ diff --git a/images/toolbar-icon-19.png b/images/toolbar-icon-19.png new file mode 100755 index 0000000..72ce424 Binary files /dev/null and b/images/toolbar-icon-19.png differ diff --git a/images/toolbar-icon-32.png b/images/toolbar-icon-32.png new file mode 100755 index 0000000..af98e22 Binary files /dev/null and b/images/toolbar-icon-32.png differ diff --git a/images/toolbar-icon-38.png b/images/toolbar-icon-38.png new file mode 100755 index 0000000..148fc3e Binary files /dev/null and b/images/toolbar-icon-38.png differ diff --git a/images/toolbar-icon-48.png b/images/toolbar-icon-48.png new file mode 100755 index 0000000..f187034 Binary files /dev/null and b/images/toolbar-icon-48.png differ diff --git a/images/toolbar-icon-72.png b/images/toolbar-icon-72.png new file mode 100755 index 0000000..957cdc4 Binary files /dev/null and b/images/toolbar-icon-72.png differ diff --git a/macOS (App)/AppDelegate.swift b/macOS (App)/AppDelegate.swift deleted file mode 100644 index 32b4df6..0000000 --- a/macOS (App)/AppDelegate.swift +++ /dev/null @@ -1,21 +0,0 @@ -// -// AppDelegate.swift -// macOS (App) -// -// Created by Nicholas Comer on 11/18/23. -// - -import Cocoa - -@main -class AppDelegate: NSObject, NSApplicationDelegate { - - func applicationDidFinishLaunching(_ notification: Notification) { - // Override point for customization after application launch. - } - - func applicationShouldTerminateAfterLastWindowClosed(_ sender: NSApplication) -> Bool { - return true - } - -} diff --git a/macOS (App)/Base.lproj/Main.storyboard b/macOS (App)/Base.lproj/Main.storyboard deleted file mode 100644 index 4659e83..0000000 --- a/macOS (App)/Base.lproj/Main.storyboard +++ /dev/null @@ -1,124 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/macOS (App)/HyperTab.entitlements b/macOS (App)/HyperTab.entitlements deleted file mode 100644 index 625af03..0000000 --- a/macOS (App)/HyperTab.entitlements +++ /dev/null @@ -1,12 +0,0 @@ - - - - - com.apple.security.app-sandbox - - com.apple.security.files.user-selected.read-only - - com.apple.security.network.client - - - diff --git a/macOS (Extension)/HyperTab.entitlements b/macOS (Extension)/HyperTab.entitlements deleted file mode 100644 index f2ef3ae..0000000 --- a/macOS (Extension)/HyperTab.entitlements +++ /dev/null @@ -1,10 +0,0 @@ - - - - - com.apple.security.app-sandbox - - com.apple.security.files.user-selected.read-only - - - diff --git a/macOS (Extension)/Info.plist b/macOS (Extension)/Info.plist deleted file mode 100644 index 9ee504d..0000000 --- a/macOS (Extension)/Info.plist +++ /dev/null @@ -1,13 +0,0 @@ - - - - - NSExtension - - NSExtensionPointIdentifier - com.apple.Safari.web-extension - NSExtensionPrincipalClass - $(PRODUCT_MODULE_NAME).SafariWebExtensionHandler - - - diff --git a/manifest.json b/manifest.json new file mode 100644 index 0000000..f43e6fa --- /dev/null +++ b/manifest.json @@ -0,0 +1,40 @@ +{ + "manifest_version": 2, + "default_locale": "en", + + "name": "HyperTab", + "description": "Quick tabs search and switch", + "version": "0.1", + + "icons": { + "48": "images/icon-48.png", + "96": "images/icon-96.png", + "128": "images/icon-128.png", + "256": "images/icon-256.png", + "512": "images/icon-512.png" + }, + "background": { + "scripts": ["dist/bg/main.js"] + }, + "commands": { + "openTabSwitcher": { + "suggested_key": { + "default": "Ctrl+Shift+E" + }, + "description": "Open HyperTab Switcher" + } + }, + "browser_action": { + "default_popup": "popup.html", + "default_icon": { + "16": "images/toolbar-icon-16.png", + "19": "images/toolbar-icon-19.png", + "32": "images/toolbar-icon-32.png", + "38": "images/toolbar-icon-38.png", + "48": "images/toolbar-icon-48.png", + "72": "images/toolbar-icon-72.png" + } + }, + + "permissions": ["tabs", "*://*/*"] +} diff --git a/package-lock.json b/package-lock.json new file mode 100644 index 0000000..8ff0997 --- /dev/null +++ b/package-lock.json @@ -0,0 +1,1874 @@ +{ + "name": "Resources", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "dependencies": { + "@types/lodash.uniq": "^4.5.9", + "@types/react": "^18.2.37", + "@types/react-dom": "^18.2.15", + "fuse.js": "^7.0.0", + "lodash.uniq": "^4.5.0", + "react": "^18.2.0", + "react-dom": "^18.2.0", + "react-hotkeys-hook": "^4.4.1" + }, + "devDependencies": { + "@types/chrome": "^0.0.251", + "esbuild": "^0.19.5", + "npm-run-all": "^4.1.5", + "typescript": "^5.2.2" + } + }, + "node_modules/@esbuild/android-arm": { + "version": "0.19.5", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.19.5.tgz", + "integrity": "sha512-bhvbzWFF3CwMs5tbjf3ObfGqbl/17ict2/uwOSfr3wmxDE6VdS2GqY/FuzIPe0q0bdhj65zQsvqfArI9MY6+AA==", + "cpu": [ + "arm" + ], + "dev": true, + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/android-arm64": { + "version": "0.19.5", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.19.5.tgz", + "integrity": "sha512-5d1OkoJxnYQfmC+Zd8NBFjkhyCNYwM4n9ODrycTFY6Jk1IGiZ+tjVJDDSwDt77nK+tfpGP4T50iMtVi4dEGzhQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/android-x64": { + "version": "0.19.5", + "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.19.5.tgz", + "integrity": "sha512-9t+28jHGL7uBdkBjL90QFxe7DVA+KGqWlHCF8ChTKyaKO//VLuoBricQCgwhOjA1/qOczsw843Fy4cbs4H3DVA==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/darwin-arm64": { + "version": "0.19.5", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.19.5.tgz", + "integrity": "sha512-mvXGcKqqIqyKoxq26qEDPHJuBYUA5KizJncKOAf9eJQez+L9O+KfvNFu6nl7SCZ/gFb2QPaRqqmG0doSWlgkqw==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/darwin-x64": { + "version": "0.19.5", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.19.5.tgz", + "integrity": "sha512-Ly8cn6fGLNet19s0X4unjcniX24I0RqjPv+kurpXabZYSXGM4Pwpmf85WHJN3lAgB8GSth7s5A0r856S+4DyiA==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/freebsd-arm64": { + "version": "0.19.5", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.19.5.tgz", + "integrity": "sha512-GGDNnPWTmWE+DMchq1W8Sd0mUkL+APvJg3b11klSGUDvRXh70JqLAO56tubmq1s2cgpVCSKYywEiKBfju8JztQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/freebsd-x64": { + "version": "0.19.5", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.19.5.tgz", + "integrity": "sha512-1CCwDHnSSoA0HNwdfoNY0jLfJpd7ygaLAp5EHFos3VWJCRX9DMwWODf96s9TSse39Br7oOTLryRVmBoFwXbuuQ==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-arm": { + "version": "0.19.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.19.5.tgz", + "integrity": "sha512-lrWXLY/vJBzCPC51QN0HM71uWgIEpGSjSZZADQhq7DKhPcI6NH1IdzjfHkDQws2oNpJKpR13kv7/pFHBbDQDwQ==", + "cpu": [ + "arm" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-arm64": { + "version": "0.19.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.19.5.tgz", + "integrity": "sha512-o3vYippBmSrjjQUCEEiTZ2l+4yC0pVJD/Dl57WfPwwlvFkrxoSO7rmBZFii6kQB3Wrn/6GwJUPLU5t52eq2meA==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-ia32": { + "version": "0.19.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.19.5.tgz", + "integrity": "sha512-MkjHXS03AXAkNp1KKkhSKPOCYztRtK+KXDNkBa6P78F8Bw0ynknCSClO/ztGszILZtyO/lVKpa7MolbBZ6oJtQ==", + "cpu": [ + "ia32" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-loong64": { + "version": "0.19.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.19.5.tgz", + "integrity": "sha512-42GwZMm5oYOD/JHqHska3Jg0r+XFb/fdZRX+WjADm3nLWLcIsN27YKtqxzQmGNJgu0AyXg4HtcSK9HuOk3v1Dw==", + "cpu": [ + "loong64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-mips64el": { + "version": "0.19.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.19.5.tgz", + "integrity": "sha512-kcjndCSMitUuPJobWCnwQ9lLjiLZUR3QLQmlgaBfMX23UEa7ZOrtufnRds+6WZtIS9HdTXqND4yH8NLoVVIkcg==", + "cpu": [ + "mips64el" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-ppc64": { + "version": "0.19.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.19.5.tgz", + "integrity": "sha512-yJAxJfHVm0ZbsiljbtFFP1BQKLc8kUF6+17tjQ78QjqjAQDnhULWiTA6u0FCDmYT1oOKS9PzZ2z0aBI+Mcyj7Q==", + "cpu": [ + "ppc64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-riscv64": { + "version": "0.19.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.19.5.tgz", + "integrity": "sha512-5u8cIR/t3gaD6ad3wNt1MNRstAZO+aNyBxu2We8X31bA8XUNyamTVQwLDA1SLoPCUehNCymhBhK3Qim1433Zag==", + "cpu": [ + "riscv64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-s390x": { + "version": "0.19.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.19.5.tgz", + "integrity": "sha512-Z6JrMyEw/EmZBD/OFEFpb+gao9xJ59ATsoTNlj39jVBbXqoZm4Xntu6wVmGPB/OATi1uk/DB+yeDPv2E8PqZGw==", + "cpu": [ + "s390x" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-x64": { + "version": "0.19.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.19.5.tgz", + "integrity": "sha512-psagl+2RlK1z8zWZOmVdImisMtrUxvwereIdyJTmtmHahJTKb64pAcqoPlx6CewPdvGvUKe2Jw+0Z/0qhSbG1A==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/netbsd-x64": { + "version": "0.19.5", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.19.5.tgz", + "integrity": "sha512-kL2l+xScnAy/E/3119OggX8SrWyBEcqAh8aOY1gr4gPvw76la2GlD4Ymf832UCVbmuWeTf2adkZDK+h0Z/fB4g==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "netbsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/openbsd-x64": { + "version": "0.19.5", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.19.5.tgz", + "integrity": "sha512-sPOfhtzFufQfTBgRnE1DIJjzsXukKSvZxloZbkJDG383q0awVAq600pc1nfqBcl0ice/WN9p4qLc39WhBShRTA==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/sunos-x64": { + "version": "0.19.5", + "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.19.5.tgz", + "integrity": "sha512-dGZkBXaafuKLpDSjKcB0ax0FL36YXCvJNnztjKV+6CO82tTYVDSH2lifitJ29jxRMoUhgkg9a+VA/B03WK5lcg==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "sunos" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/win32-arm64": { + "version": "0.19.5", + "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.19.5.tgz", + "integrity": "sha512-dWVjD9y03ilhdRQ6Xig1NWNgfLtf2o/STKTS+eZuF90fI2BhbwD6WlaiCGKptlqXlURVB5AUOxUj09LuwKGDTg==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/win32-ia32": { + "version": "0.19.5", + "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.19.5.tgz", + "integrity": "sha512-4liggWIA4oDgUxqpZwrDhmEfAH4d0iljanDOK7AnVU89T6CzHon/ony8C5LeOdfgx60x5cnQJFZwEydVlYx4iw==", + "cpu": [ + "ia32" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/win32-x64": { + "version": "0.19.5", + "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.19.5.tgz", + "integrity": "sha512-czTrygUsB/jlM8qEW5MD8bgYU2Xg14lo6kBDXW6HdxKjh8M5PzETGiSHaz9MtbXBYDloHNUAUW2tMiKW4KM9Mw==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@types/chrome": { + "version": "0.0.251", + "resolved": "https://registry.npmjs.org/@types/chrome/-/chrome-0.0.251.tgz", + "integrity": "sha512-UF+yr0LEKWWGsKxQ5A3XOSF5SNoU1ctW3pXcWJPpT8OOUTEspYeaLU8spDKe+6xalXeMTS0TBrX1g0b6qlWmkw==", + "dev": true, + "dependencies": { + "@types/filesystem": "*", + "@types/har-format": "*" + } + }, + "node_modules/@types/filesystem": { + "version": "0.0.35", + "resolved": "https://registry.npmjs.org/@types/filesystem/-/filesystem-0.0.35.tgz", + "integrity": "sha512-1eKvCaIBdrD2mmMgy5dwh564rVvfEhZTWVQQGRNn0Nt4ZEnJ0C8oSUCzvMKRA4lGde5oEVo+q2MrTTbV/GHDCQ==", + "dev": true, + "dependencies": { + "@types/filewriter": "*" + } + }, + "node_modules/@types/filewriter": { + "version": "0.0.32", + "resolved": "https://registry.npmjs.org/@types/filewriter/-/filewriter-0.0.32.tgz", + "integrity": "sha512-Kpi2GXQyYJdjL8mFclL1eDgihn1SIzorMZjD94kdPZh9E4VxGOeyjPxi5LpsM4Zku7P0reqegZTt2GxhmA9VBg==", + "dev": true + }, + "node_modules/@types/har-format": { + "version": "1.2.15", + "resolved": "https://registry.npmjs.org/@types/har-format/-/har-format-1.2.15.tgz", + "integrity": "sha512-RpQH4rXLuvTXKR0zqHq3go0RVXYv/YVqv4TnPH95VbwUxZdQlK1EtcMvQvMpDngHbt13Csh9Z4qT9AbkiQH5BA==", + "dev": true + }, + "node_modules/@types/lodash": { + "version": "4.14.201", + "resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.14.201.tgz", + "integrity": "sha512-y9euML0cim1JrykNxADLfaG0FgD1g/yTHwUs/Jg9ZIU7WKj2/4IW9Lbb1WZbvck78W/lfGXFfe+u2EGfIJXdLQ==" + }, + "node_modules/@types/lodash.uniq": { + "version": "4.5.9", + "resolved": "https://registry.npmjs.org/@types/lodash.uniq/-/lodash.uniq-4.5.9.tgz", + "integrity": "sha512-2Vd5avnDMNLbDSnUwwgwExKXvX9W3CN72rodT+ikGqGHXn7gVK6BM6Z+kHonbpGgCI2BzM+QDMHrkgKoofOi6A==", + "dependencies": { + "@types/lodash": "*" + } + }, + "node_modules/@types/prop-types": { + "version": "15.7.10", + "resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.10.tgz", + "integrity": "sha512-mxSnDQxPqsZxmeShFH+uwQ4kO4gcJcGahjjMFeLbKE95IAZiiZyiEepGZjtXJ7hN/yfu0bu9xN2ajcU0JcxX6A==" + }, + "node_modules/@types/react": { + "version": "18.2.37", + "resolved": "https://registry.npmjs.org/@types/react/-/react-18.2.37.tgz", + "integrity": "sha512-RGAYMi2bhRgEXT3f4B92WTohopH6bIXw05FuGlmJEnv/omEn190+QYEIYxIAuIBdKgboYYdVved2p1AxZVQnaw==", + "dependencies": { + "@types/prop-types": "*", + "@types/scheduler": "*", + "csstype": "^3.0.2" + } + }, + "node_modules/@types/react-dom": { + "version": "18.2.15", + "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-18.2.15.tgz", + "integrity": "sha512-HWMdW+7r7MR5+PZqJF6YFNSCtjz1T0dsvo/f1BV6HkV+6erD/nA7wd9NM00KVG83zf2nJ7uATPO9ttdIPvi3gg==", + "dependencies": { + "@types/react": "*" + } + }, + "node_modules/@types/scheduler": { + "version": "0.16.6", + "resolved": "https://registry.npmjs.org/@types/scheduler/-/scheduler-0.16.6.tgz", + "integrity": "sha512-Vlktnchmkylvc9SnwwwozTv04L/e1NykF5vgoQ0XTmI8DD+wxfjQuHuvHS3p0r2jz2x2ghPs2h1FVeDirIteWA==" + }, + "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/array-buffer-byte-length": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/array-buffer-byte-length/-/array-buffer-byte-length-1.0.0.tgz", + "integrity": "sha512-LPuwb2P+NrQw3XhxGc36+XSvuBPopovXYTR9Ew++Du9Yb/bx5AzBfrIsBoj0EZUifjQU+sHL21sseZ3jerWO/A==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "is-array-buffer": "^3.0.1" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/arraybuffer.prototype.slice": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/arraybuffer.prototype.slice/-/arraybuffer.prototype.slice-1.0.2.tgz", + "integrity": "sha512-yMBKppFur/fbHu9/6USUe03bZ4knMYiwFBcyiaXB8Go0qNehwX6inYPzK9U0NeQvGxKthcmHcaR8P5MStSRBAw==", + "dev": true, + "dependencies": { + "array-buffer-byte-length": "^1.0.0", + "call-bind": "^1.0.2", + "define-properties": "^1.2.0", + "es-abstract": "^1.22.1", + "get-intrinsic": "^1.2.1", + "is-array-buffer": "^3.0.2", + "is-shared-array-buffer": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/available-typed-arrays": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.5.tgz", + "integrity": "sha512-DMD0KiN46eipeziST1LPP/STfDU0sufISXmjSgvVsoU2tqxctQeASejWcfNtxYKqETM1UxQ8sp2OrSBWpHY6sw==", + "dev": true, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", + "dev": true + }, + "node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/call-bind": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.5.tgz", + "integrity": "sha512-C3nQxfFZxFRVoJoGKKI8y3MOEo129NQ+FgQ08iye+Mk4zNZZGdjfs06bVTr+DBSlA66Q2VEcMki/cUCP4SercQ==", + "dev": true, + "dependencies": { + "function-bind": "^1.1.2", + "get-intrinsic": "^1.2.1", + "set-function-length": "^1.1.1" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "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/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/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/concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", + "dev": true + }, + "node_modules/cross-spawn": { + "version": "6.0.5", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-6.0.5.tgz", + "integrity": "sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ==", + "dev": true, + "dependencies": { + "nice-try": "^1.0.4", + "path-key": "^2.0.1", + "semver": "^5.5.0", + "shebang-command": "^1.2.0", + "which": "^1.2.9" + }, + "engines": { + "node": ">=4.8" + } + }, + "node_modules/csstype": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.2.tgz", + "integrity": "sha512-I7K1Uu0MBPzaFKg4nI5Q7Vs2t+3gWWW648spaF+Rg7pI9ds18Ugn+lvg4SHczUdKlHI5LWBXyqfS8+DufyBsgQ==" + }, + "node_modules/define-data-property": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.1.tgz", + "integrity": "sha512-E7uGkTzkk1d0ByLeSc6ZsFS79Axg+m1P/VsgYsxHgiuc3tFSj+MjMIwe90FC4lOAZzNBdY7kkO2P2wKdsQ1vgQ==", + "dev": true, + "dependencies": { + "get-intrinsic": "^1.2.1", + "gopd": "^1.0.1", + "has-property-descriptors": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/define-properties": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.2.1.tgz", + "integrity": "sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg==", + "dev": true, + "dependencies": { + "define-data-property": "^1.0.1", + "has-property-descriptors": "^1.0.0", + "object-keys": "^1.1.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "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/es-abstract": { + "version": "1.22.3", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.22.3.tgz", + "integrity": "sha512-eiiY8HQeYfYH2Con2berK+To6GrK2RxbPawDkGq4UiCQQfZHb6wX9qQqkbpPqaxQFcl8d9QzZqo0tGE0VcrdwA==", + "dev": true, + "dependencies": { + "array-buffer-byte-length": "^1.0.0", + "arraybuffer.prototype.slice": "^1.0.2", + "available-typed-arrays": "^1.0.5", + "call-bind": "^1.0.5", + "es-set-tostringtag": "^2.0.1", + "es-to-primitive": "^1.2.1", + "function.prototype.name": "^1.1.6", + "get-intrinsic": "^1.2.2", + "get-symbol-description": "^1.0.0", + "globalthis": "^1.0.3", + "gopd": "^1.0.1", + "has-property-descriptors": "^1.0.0", + "has-proto": "^1.0.1", + "has-symbols": "^1.0.3", + "hasown": "^2.0.0", + "internal-slot": "^1.0.5", + "is-array-buffer": "^3.0.2", + "is-callable": "^1.2.7", + "is-negative-zero": "^2.0.2", + "is-regex": "^1.1.4", + "is-shared-array-buffer": "^1.0.2", + "is-string": "^1.0.7", + "is-typed-array": "^1.1.12", + "is-weakref": "^1.0.2", + "object-inspect": "^1.13.1", + "object-keys": "^1.1.1", + "object.assign": "^4.1.4", + "regexp.prototype.flags": "^1.5.1", + "safe-array-concat": "^1.0.1", + "safe-regex-test": "^1.0.0", + "string.prototype.trim": "^1.2.8", + "string.prototype.trimend": "^1.0.7", + "string.prototype.trimstart": "^1.0.7", + "typed-array-buffer": "^1.0.0", + "typed-array-byte-length": "^1.0.0", + "typed-array-byte-offset": "^1.0.0", + "typed-array-length": "^1.0.4", + "unbox-primitive": "^1.0.2", + "which-typed-array": "^1.1.13" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/es-set-tostringtag": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.0.2.tgz", + "integrity": "sha512-BuDyupZt65P9D2D2vA/zqcI3G5xRsklm5N3xCwuiy+/vKy8i0ifdsQP1sLgO4tZDSCaQUSnmC48khknGMV3D2Q==", + "dev": true, + "dependencies": { + "get-intrinsic": "^1.2.2", + "has-tostringtag": "^1.0.0", + "hasown": "^2.0.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-to-primitive": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.1.tgz", + "integrity": "sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==", + "dev": true, + "dependencies": { + "is-callable": "^1.1.4", + "is-date-object": "^1.0.1", + "is-symbol": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/esbuild": { + "version": "0.19.5", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.19.5.tgz", + "integrity": "sha512-bUxalY7b1g8vNhQKdB24QDmHeY4V4tw/s6Ak5z+jJX9laP5MoQseTOMemAr0gxssjNcH0MCViG8ONI2kksvfFQ==", + "dev": true, + "hasInstallScript": true, + "bin": { + "esbuild": "bin/esbuild" + }, + "engines": { + "node": ">=12" + }, + "optionalDependencies": { + "@esbuild/android-arm": "0.19.5", + "@esbuild/android-arm64": "0.19.5", + "@esbuild/android-x64": "0.19.5", + "@esbuild/darwin-arm64": "0.19.5", + "@esbuild/darwin-x64": "0.19.5", + "@esbuild/freebsd-arm64": "0.19.5", + "@esbuild/freebsd-x64": "0.19.5", + "@esbuild/linux-arm": "0.19.5", + "@esbuild/linux-arm64": "0.19.5", + "@esbuild/linux-ia32": "0.19.5", + "@esbuild/linux-loong64": "0.19.5", + "@esbuild/linux-mips64el": "0.19.5", + "@esbuild/linux-ppc64": "0.19.5", + "@esbuild/linux-riscv64": "0.19.5", + "@esbuild/linux-s390x": "0.19.5", + "@esbuild/linux-x64": "0.19.5", + "@esbuild/netbsd-x64": "0.19.5", + "@esbuild/openbsd-x64": "0.19.5", + "@esbuild/sunos-x64": "0.19.5", + "@esbuild/win32-arm64": "0.19.5", + "@esbuild/win32-ia32": "0.19.5", + "@esbuild/win32-x64": "0.19.5" + } + }, + "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/for-each": { + "version": "0.3.3", + "resolved": "https://registry.npmjs.org/for-each/-/for-each-0.3.3.tgz", + "integrity": "sha512-jqYfLp7mo9vIyQf8ykW2v7A+2N4QjeCeI5+Dz9XraiO1ign81wjiH7Fb9vSOWvQfNtmSa4H2RoQTrrXivdUZmw==", + "dev": true, + "dependencies": { + "is-callable": "^1.1.3" + } + }, + "node_modules/function-bind": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", + "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", + "dev": true, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/function.prototype.name": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/function.prototype.name/-/function.prototype.name-1.1.6.tgz", + "integrity": "sha512-Z5kx79swU5P27WEayXM1tBi5Ze/lbIyiNgU3qyXUOf9b2rgXYyF9Dy9Cx+IQv/Lc8WCG6L82zwUPpSS9hGehIg==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.2.0", + "es-abstract": "^1.22.1", + "functions-have-names": "^1.2.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/functions-have-names": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/functions-have-names/-/functions-have-names-1.2.3.tgz", + "integrity": "sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ==", + "dev": true, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/fuse.js": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/fuse.js/-/fuse.js-7.0.0.tgz", + "integrity": "sha512-14F4hBIxqKvD4Zz/XjDc3y94mNZN6pRv3U13Udo0lNLCWRBUsrMv2xwcF/y/Z5sV6+FQW+/ow68cHpm4sunt8Q==", + "engines": { + "node": ">=10" + } + }, + "node_modules/get-intrinsic": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.2.tgz", + "integrity": "sha512-0gSo4ml/0j98Y3lngkFEot/zhiCeWsbYIlZ+uZOVgzLyLaUw7wxUL+nCTP0XJvJg1AXulJRI3UJi8GsbDuxdGA==", + "dev": true, + "dependencies": { + "function-bind": "^1.1.2", + "has-proto": "^1.0.1", + "has-symbols": "^1.0.3", + "hasown": "^2.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/get-symbol-description": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/get-symbol-description/-/get-symbol-description-1.0.0.tgz", + "integrity": "sha512-2EmdH1YvIQiZpltCNgkuiUnyukzxM/R6NDJX31Ke3BG1Nq5b0S2PhX59UKi9vZpPDQVdqn+1IcaAwnzTT5vCjw==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "get-intrinsic": "^1.1.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/globalthis": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/globalthis/-/globalthis-1.0.3.tgz", + "integrity": "sha512-sFdI5LyBiNTHjRd7cGPWapiHWMOXKyuBNX/cWJ3NfzrZQVa8GI/8cofCl74AOVqq9W5kNmguTIzJ/1s2gyI9wA==", + "dev": true, + "dependencies": { + "define-properties": "^1.1.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/gopd": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.0.1.tgz", + "integrity": "sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==", + "dev": true, + "dependencies": { + "get-intrinsic": "^1.1.3" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/graceful-fs": { + "version": "4.2.11", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", + "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==", + "dev": true + }, + "node_modules/has-bigints": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-bigints/-/has-bigints-1.0.2.tgz", + "integrity": "sha512-tSvCKtBr9lkF0Ex0aQiP9N+OpV4zi2r/Nee5VkRDbaqv35RLYMzbwQfFSZZH0kR+Rd6302UJZ2p/bJCEoR3VoQ==", + "dev": true, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "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/has-property-descriptors": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.1.tgz", + "integrity": "sha512-VsX8eaIewvas0xnvinAe9bw4WfIeODpGYikiWYLH+dma0Jw6KHYqWiWfhQlgOVK8D6PvjubK5Uc4P0iIhIcNVg==", + "dev": true, + "dependencies": { + "get-intrinsic": "^1.2.2" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-proto": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.0.1.tgz", + "integrity": "sha512-7qE+iP+O+bgF9clE5+UoBFzE65mlBiVj3tKCrlNQ0Ogwm0BjpT/gK4SlLYDMybDh5I3TCTKnPPa0oMG7JDYrhg==", + "dev": true, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-symbols": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz", + "integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==", + "dev": true, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-tostringtag": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.0.tgz", + "integrity": "sha512-kFjcSNhnlGV1kyoGk7OXKSawH5JOb/LzUc5w9B02hOTO0dfFRjbHQKvg1d6cf3HbeUmtU9VbbV3qzZ2Teh97WQ==", + "dev": true, + "dependencies": { + "has-symbols": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/hasown": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.0.tgz", + "integrity": "sha512-vUptKVTpIJhcczKBbgnS+RtcuYMB8+oNzPK2/Hp3hanz8JmpATdmmgLgSaadVREkDm+e2giHwY3ZRkyjSIDDFA==", + "dev": true, + "dependencies": { + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/hosted-git-info": { + "version": "2.8.9", + "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.8.9.tgz", + "integrity": "sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw==", + "dev": true + }, + "node_modules/internal-slot": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.0.6.tgz", + "integrity": "sha512-Xj6dv+PsbtwyPpEflsejS+oIZxmMlV44zAhG479uYu89MsjcYOhCFnNyKrkJrihbsiasQyY0afoCl/9BLR65bg==", + "dev": true, + "dependencies": { + "get-intrinsic": "^1.2.2", + "hasown": "^2.0.0", + "side-channel": "^1.0.4" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/is-array-buffer": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/is-array-buffer/-/is-array-buffer-3.0.2.tgz", + "integrity": "sha512-y+FyyR/w8vfIRq4eQcM1EYgSTnmHXPqaF+IgzgraytCFq5Xh8lllDVmAZolPJiZttZLeFSINPYMaEJ7/vWUa1w==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "get-intrinsic": "^1.2.0", + "is-typed-array": "^1.1.10" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "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-bigint": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/is-bigint/-/is-bigint-1.0.4.tgz", + "integrity": "sha512-zB9CruMamjym81i2JZ3UMn54PKGsQzsJeo6xvN3HJJ4CAsQNB6iRutp2To77OfCNuoxspsIhzaPoO1zyCEhFOg==", + "dev": true, + "dependencies": { + "has-bigints": "^1.0.1" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-boolean-object": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/is-boolean-object/-/is-boolean-object-1.1.2.tgz", + "integrity": "sha512-gDYaKHJmnj4aWxyj6YHyXVpdQawtVLHU5cb+eztPGczf6cjuTdwve5ZIEfgXqH4e57An1D1AKf8CZ3kYrQRqYA==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-callable": { + "version": "1.2.7", + "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.7.tgz", + "integrity": "sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA==", + "dev": true, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-core-module": { + "version": "2.13.1", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.13.1.tgz", + "integrity": "sha512-hHrIjvZsftOsvKSn2TRYl63zvxsgE0K+0mYMoH6gD4omR5IWB2KynivBQczo3+wF1cCkjzvptnI9Q0sPU66ilw==", + "dev": true, + "dependencies": { + "hasown": "^2.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-date-object": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.5.tgz", + "integrity": "sha512-9YQaSxsAiSwcvS33MBk3wTCVnWK+HhF8VZR2jRxehM16QcVOdHqPn4VPHmRK4lSr38n9JriurInLcP90xsYNfQ==", + "dev": true, + "dependencies": { + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-negative-zero": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.2.tgz", + "integrity": "sha512-dqJvarLawXsFbNDeJW7zAz8ItJ9cd28YufuuFzh0G8pNHjJMnY08Dv7sYX2uF5UpQOwieAeOExEYAWWfu7ZZUA==", + "dev": true, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-number-object": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/is-number-object/-/is-number-object-1.0.7.tgz", + "integrity": "sha512-k1U0IRzLMo7ZlYIfzRu23Oh6MiIFasgpb9X76eqfFZAqwH44UI4KTBvBYIZ1dSL9ZzChTB9ShHfLkR4pdW5krQ==", + "dev": true, + "dependencies": { + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-regex": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.4.tgz", + "integrity": "sha512-kvRdxDsxZjhzUX07ZnLydzS1TU/TJlTUHHY4YLL87e37oUA49DfkLqgy+VjFocowy29cKvcSiu+kIv728jTTVg==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-shared-array-buffer": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-shared-array-buffer/-/is-shared-array-buffer-1.0.2.tgz", + "integrity": "sha512-sqN2UDu1/0y6uvXyStCOzyhAjCSlHceFoMKJW8W9EU9cvic/QdsZ0kEU93HEy3IUEFZIiH/3w+AH/UQbPHNdhA==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-string": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/is-string/-/is-string-1.0.7.tgz", + "integrity": "sha512-tE2UXzivje6ofPW7l23cjDOMa09gb7xlAqG6jG5ej6uPV32TlWP3NKPigtaGeHNu9fohccRYvIiZMfOOnOYUtg==", + "dev": true, + "dependencies": { + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-symbol": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.4.tgz", + "integrity": "sha512-C/CPBqKWnvdcxqIARxyOh4v1UUEOCHpgDa0WYgpKDFMszcrPcffg5uhwSgPCLD2WWxmq6isisz87tzT01tuGhg==", + "dev": true, + "dependencies": { + "has-symbols": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-typed-array": { + "version": "1.1.12", + "resolved": "https://registry.npmjs.org/is-typed-array/-/is-typed-array-1.1.12.tgz", + "integrity": "sha512-Z14TF2JNG8Lss5/HMqt0//T9JeHXttXy5pH/DBU4vi98ozO2btxzq9MwYDZYnKwU8nRsz/+GVFVRDq3DkVuSPg==", + "dev": true, + "dependencies": { + "which-typed-array": "^1.1.11" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-weakref": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-weakref/-/is-weakref-1.0.2.tgz", + "integrity": "sha512-qctsuLZmIQ0+vSSMfoVvyFe2+GSEvnmZ2ezTup1SBse9+twCCeial6EEi3Nc2KFcf6+qz2FBPnjXsk8xhKSaPQ==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/isarray": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.5.tgz", + "integrity": "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==", + "dev": true + }, + "node_modules/isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", + "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==" + }, + "node_modules/json-parse-better-errors": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz", + "integrity": "sha512-mrqyZKfX5EhL7hvqcV6WG1yYjnjeuYDzDhhcAAUrq8Po85NBQBJP+ZDUT75qZQ98IkUoBqdkExkukOU7Ts2wrw==", + "dev": true + }, + "node_modules/load-json-file": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-4.0.0.tgz", + "integrity": "sha512-Kx8hMakjX03tiGTLAIdJ+lL0htKnXjEZN6hk/tozf/WOuYGdZBJrZ+rCJRbVCugsjB3jMLn9746NsQIf5VjBMw==", + "dev": true, + "dependencies": { + "graceful-fs": "^4.1.2", + "parse-json": "^4.0.0", + "pify": "^3.0.0", + "strip-bom": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/lodash.uniq": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/lodash.uniq/-/lodash.uniq-4.5.0.tgz", + "integrity": "sha512-xfBaXQd9ryd9dlSDvnvI0lvxfLJlYAZzXomUYzLKtUeOQvOP5piqAWuGtrhWeqaXK9hhoM/iyJc5AV+XfsX3HQ==" + }, + "node_modules/loose-envify": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz", + "integrity": "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==", + "dependencies": { + "js-tokens": "^3.0.0 || ^4.0.0" + }, + "bin": { + "loose-envify": "cli.js" + } + }, + "node_modules/memorystream": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/memorystream/-/memorystream-0.3.1.tgz", + "integrity": "sha512-S3UwM3yj5mtUSEfP41UZmt/0SCoVYUcU1rkXv+BQ5Ig8ndL4sPoJNBUJERafdPb5jjHJGuMgytgKvKIf58XNBw==", + "dev": true, + "engines": { + "node": ">= 0.10.0" + } + }, + "node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/nice-try": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/nice-try/-/nice-try-1.0.5.tgz", + "integrity": "sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ==", + "dev": true + }, + "node_modules/normalize-package-data": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.5.0.tgz", + "integrity": "sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==", + "dev": true, + "dependencies": { + "hosted-git-info": "^2.1.4", + "resolve": "^1.10.0", + "semver": "2 || 3 || 4 || 5", + "validate-npm-package-license": "^3.0.1" + } + }, + "node_modules/npm-run-all": { + "version": "4.1.5", + "resolved": "https://registry.npmjs.org/npm-run-all/-/npm-run-all-4.1.5.tgz", + "integrity": "sha512-Oo82gJDAVcaMdi3nuoKFavkIHBRVqQ1qvMb+9LHk/cF4P6B2m8aP04hGf7oL6wZ9BuGwX1onlLhpuoofSyoQDQ==", + "dev": true, + "dependencies": { + "ansi-styles": "^3.2.1", + "chalk": "^2.4.1", + "cross-spawn": "^6.0.5", + "memorystream": "^0.3.1", + "minimatch": "^3.0.4", + "pidtree": "^0.3.0", + "read-pkg": "^3.0.0", + "shell-quote": "^1.6.1", + "string.prototype.padend": "^3.0.0" + }, + "bin": { + "npm-run-all": "bin/npm-run-all/index.js", + "run-p": "bin/run-p/index.js", + "run-s": "bin/run-s/index.js" + }, + "engines": { + "node": ">= 4" + } + }, + "node_modules/object-inspect": { + "version": "1.13.1", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.1.tgz", + "integrity": "sha512-5qoj1RUiKOMsCCNLV1CBiPYE10sziTsnmNxkAI/rZhiD63CF7IqdFGC/XzjWjpSgLf0LxXX3bDFIh0E18f6UhQ==", + "dev": true, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/object-keys": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", + "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", + "dev": true, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/object.assign": { + "version": "4.1.4", + "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.4.tgz", + "integrity": "sha512-1mxKf0e58bvyjSCtKYY4sRe9itRk3PJpquJOjeIkz885CczcI4IvJJDLPS72oowuSh+pBxUFROpX+TU++hxhZQ==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.4", + "has-symbols": "^1.0.3", + "object-keys": "^1.1.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/parse-json": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-4.0.0.tgz", + "integrity": "sha512-aOIos8bujGN93/8Ox/jPLh7RwVnPEysynVFE+fQZyg6jKELEHwzgKdLRFHUgXJL6kylijVSBC4BvN9OmsB48Rw==", + "dev": true, + "dependencies": { + "error-ex": "^1.3.1", + "json-parse-better-errors": "^1.0.1" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/path-key": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-2.0.1.tgz", + "integrity": "sha512-fEHGKCSmUSDPv4uoj8AlD+joPlq3peND+HRYyxFz4KPw4z926S/b8rIuFs2FYJg3BwsxJf6A9/3eIdLaYC+9Dw==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/path-parse": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", + "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", + "dev": true + }, + "node_modules/path-type": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-3.0.0.tgz", + "integrity": "sha512-T2ZUsdZFHgA3u4e5PfPbjd7HDDpxPnQb5jN0SrDsjNSuVXHJqtwTnWqG0B1jZrgmJ/7lj1EmVIByWt1gxGkWvg==", + "dev": true, + "dependencies": { + "pify": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/pidtree": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/pidtree/-/pidtree-0.3.1.tgz", + "integrity": "sha512-qQbW94hLHEqCg7nhby4yRC7G2+jYHY4Rguc2bjw7Uug4GIJuu1tvf2uHaZv5Q8zdt+WKJ6qK1FOI6amaWUo5FA==", + "dev": true, + "bin": { + "pidtree": "bin/pidtree.js" + }, + "engines": { + "node": ">=0.10" + } + }, + "node_modules/pify": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", + "integrity": "sha512-C3FsVNH1udSEX48gGX1xfvwTWfsYWj5U+8/uK15BGzIGrKoUpghX8hWZwa/OFnakBiiVNmBvemTJR5mcy7iPcg==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/react": { + "version": "18.2.0", + "resolved": "https://registry.npmjs.org/react/-/react-18.2.0.tgz", + "integrity": "sha512-/3IjMdb2L9QbBdWiW5e3P2/npwMBaU9mHCSCUzNln0ZCYbcfTsGbTJrU/kGemdH2IWmB2ioZ+zkxtmq6g09fGQ==", + "dependencies": { + "loose-envify": "^1.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/react-dom": { + "version": "18.2.0", + "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-18.2.0.tgz", + "integrity": "sha512-6IMTriUmvsjHUjNtEDudZfuDQUoWXVxKHhlEGSk81n4YFS+r/Kl99wXiwlVXtPBtJenozv2P+hxDsw9eA7Xo6g==", + "dependencies": { + "loose-envify": "^1.1.0", + "scheduler": "^0.23.0" + }, + "peerDependencies": { + "react": "^18.2.0" + } + }, + "node_modules/react-hotkeys-hook": { + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/react-hotkeys-hook/-/react-hotkeys-hook-4.4.1.tgz", + "integrity": "sha512-sClBMBioFEgFGYLTWWRKvhxcCx1DRznd+wkFHwQZspnRBkHTgruKIHptlK/U/2DPX8BhHoRGzpMVWUXMmdZlmw==", + "peerDependencies": { + "react": ">=16.8.1", + "react-dom": ">=16.8.1" + } + }, + "node_modules/read-pkg": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-3.0.0.tgz", + "integrity": "sha512-BLq/cCO9two+lBgiTYNqD6GdtK8s4NpaWrl6/rCO9w0TUS8oJl7cmToOZfRYllKTISY6nt1U7jQ53brmKqY6BA==", + "dev": true, + "dependencies": { + "load-json-file": "^4.0.0", + "normalize-package-data": "^2.3.2", + "path-type": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/regexp.prototype.flags": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.5.1.tgz", + "integrity": "sha512-sy6TXMN+hnP/wMy+ISxg3krXx7BAtWVO4UouuCN/ziM9UEne0euamVNafDfvC83bRNr95y0V5iijeDQFUNpvrg==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.2.0", + "set-function-name": "^2.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/resolve": { + "version": "1.22.8", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.8.tgz", + "integrity": "sha512-oKWePCxqpd6FlLvGV1VU0x7bkPmmCNolxzjMf4NczoDnQcIWrAF+cPtZn5i6n+RfD2d9i0tzpKnG6Yk168yIyw==", + "dev": true, + "dependencies": { + "is-core-module": "^2.13.0", + "path-parse": "^1.0.7", + "supports-preserve-symlinks-flag": "^1.0.0" + }, + "bin": { + "resolve": "bin/resolve" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/safe-array-concat": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/safe-array-concat/-/safe-array-concat-1.0.1.tgz", + "integrity": "sha512-6XbUAseYE2KtOuGueyeobCySj9L4+66Tn6KQMOPQJrAJEowYKW/YR/MGJZl7FdydUdaFu4LYyDZjxf4/Nmo23Q==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "get-intrinsic": "^1.2.1", + "has-symbols": "^1.0.3", + "isarray": "^2.0.5" + }, + "engines": { + "node": ">=0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/safe-regex-test": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/safe-regex-test/-/safe-regex-test-1.0.0.tgz", + "integrity": "sha512-JBUUzyOgEwXQY1NuPtvcj/qcBDbDmEvWufhlnXZIm75DEHp+afM1r1ujJpJsV/gSM4t59tpDyPi1sd6ZaPFfsA==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "get-intrinsic": "^1.1.3", + "is-regex": "^1.1.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/scheduler": { + "version": "0.23.0", + "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.23.0.tgz", + "integrity": "sha512-CtuThmgHNg7zIZWAXi3AsyIzA3n4xx7aNyjwC2VJldO2LMVDhFK+63xGqq6CsJH4rTAt6/M+N4GhZiDYPx9eUw==", + "dependencies": { + "loose-envify": "^1.1.0" + } + }, + "node_modules/semver": { + "version": "5.7.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz", + "integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==", + "dev": true, + "bin": { + "semver": "bin/semver" + } + }, + "node_modules/set-function-length": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.1.1.tgz", + "integrity": "sha512-VoaqjbBJKiWtg4yRcKBQ7g7wnGnLV3M8oLvVWwOk2PdYY6PEFegR1vezXR0tw6fZGF9csVakIRjrJiy2veSBFQ==", + "dev": true, + "dependencies": { + "define-data-property": "^1.1.1", + "get-intrinsic": "^1.2.1", + "gopd": "^1.0.1", + "has-property-descriptors": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/set-function-name": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/set-function-name/-/set-function-name-2.0.1.tgz", + "integrity": "sha512-tMNCiqYVkXIZgc2Hnoy2IvC/f8ezc5koaRFkCjrpWzGpCd3qbZXPzVy9MAZzK1ch/X0jvSkojys3oqJN0qCmdA==", + "dev": true, + "dependencies": { + "define-data-property": "^1.0.1", + "functions-have-names": "^1.2.3", + "has-property-descriptors": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/shebang-command": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-1.2.0.tgz", + "integrity": "sha512-EV3L1+UQWGor21OmnvojK36mhg+TyIKDh3iFBKBohr5xeXIhNBcx8oWdgkTEEQ+BEFFYdLRuqMfd5L84N1V5Vg==", + "dev": true, + "dependencies": { + "shebang-regex": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/shebang-regex": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-1.0.0.tgz", + "integrity": "sha512-wpoSFAxys6b2a2wHZ1XpDSgD7N9iVjg29Ph9uV/uaP9Ex/KXlkTZTeddxDPSYQpgvzKLGJke2UU0AzoGCjNIvQ==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/shell-quote": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/shell-quote/-/shell-quote-1.8.1.tgz", + "integrity": "sha512-6j1W9l1iAs/4xYBI1SYOVZyFcCis9b4KCLQ8fgAGG07QvzaRLVVRQvAy85yNmmZSjYjg4MWh4gNvlPujU/5LpA==", + "dev": true, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/side-channel": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.4.tgz", + "integrity": "sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.0", + "get-intrinsic": "^1.0.2", + "object-inspect": "^1.9.0" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/spdx-correct": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.2.0.tgz", + "integrity": "sha512-kN9dJbvnySHULIluDHy32WHRUu3Og7B9sbY7tsFLctQkIqnMh3hErYgdMjTYuqmcXX+lK5T1lnUt3G7zNswmZA==", + "dev": true, + "dependencies": { + "spdx-expression-parse": "^3.0.0", + "spdx-license-ids": "^3.0.0" + } + }, + "node_modules/spdx-exceptions": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.3.0.tgz", + "integrity": "sha512-/tTrYOC7PPI1nUAgx34hUpqXuyJG+DTHJTnIULG4rDygi4xu/tfgmq1e1cIRwRzwZgo4NLySi+ricLkZkw4i5A==", + "dev": true + }, + "node_modules/spdx-expression-parse": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-3.0.1.tgz", + "integrity": "sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q==", + "dev": true, + "dependencies": { + "spdx-exceptions": "^2.1.0", + "spdx-license-ids": "^3.0.0" + } + }, + "node_modules/spdx-license-ids": { + "version": "3.0.16", + "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.16.tgz", + "integrity": "sha512-eWN+LnM3GR6gPu35WxNgbGl8rmY1AEmoMDvL/QD6zYmPWgywxWqJWNdLGT+ke8dKNWrcYgYjPpG5gbTfghP8rw==", + "dev": true + }, + "node_modules/string.prototype.padend": { + "version": "3.1.5", + "resolved": "https://registry.npmjs.org/string.prototype.padend/-/string.prototype.padend-3.1.5.tgz", + "integrity": "sha512-DOB27b/2UTTD+4myKUFh+/fXWcu/UDyASIXfg+7VzoCNNGOfWvoyU/x5pvVHr++ztyt/oSYI1BcWBBG/hmlNjA==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.2.0", + "es-abstract": "^1.22.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/string.prototype.trim": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/string.prototype.trim/-/string.prototype.trim-1.2.8.tgz", + "integrity": "sha512-lfjY4HcixfQXOfaqCvcBuOIapyaroTXhbkfJN3gcB1OtyupngWK4sEET9Knd0cXd28kTUqu/kHoV4HKSJdnjiQ==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.2.0", + "es-abstract": "^1.22.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/string.prototype.trimend": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.7.tgz", + "integrity": "sha512-Ni79DqeB72ZFq1uH/L6zJ+DKZTkOtPIHovb3YZHQViE+HDouuU4mBrLOLDn5Dde3RF8qw5qVETEjhu9locMLvA==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.2.0", + "es-abstract": "^1.22.1" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/string.prototype.trimstart": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.7.tgz", + "integrity": "sha512-NGhtDFu3jCEm7B4Fy0DpLewdJQOZcQ0rGbwQ/+stjnrp2i+rlKeCvos9hOIeCmqwratM47OBxY7uFZzjxHXmrg==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.2.0", + "es-abstract": "^1.22.1" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/strip-bom": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", + "integrity": "sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "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/supports-preserve-symlinks-flag": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", + "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", + "dev": true, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/typed-array-buffer": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/typed-array-buffer/-/typed-array-buffer-1.0.0.tgz", + "integrity": "sha512-Y8KTSIglk9OZEr8zywiIHG/kmQ7KWyjseXs1CbSo8vC42w7hg2HgYTxSWwP0+is7bWDc1H+Fo026CpHFwm8tkw==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "get-intrinsic": "^1.2.1", + "is-typed-array": "^1.1.10" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/typed-array-byte-length": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/typed-array-byte-length/-/typed-array-byte-length-1.0.0.tgz", + "integrity": "sha512-Or/+kvLxNpeQ9DtSydonMxCx+9ZXOswtwJn17SNLvhptaXYDJvkFFP5zbfU/uLmvnBJlI4yrnXRxpdWH/M5tNA==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "for-each": "^0.3.3", + "has-proto": "^1.0.1", + "is-typed-array": "^1.1.10" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/typed-array-byte-offset": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/typed-array-byte-offset/-/typed-array-byte-offset-1.0.0.tgz", + "integrity": "sha512-RD97prjEt9EL8YgAgpOkf3O4IF9lhJFr9g0htQkm0rchFp/Vx7LW5Q8fSXXub7BXAODyUQohRMyOc3faCPd0hg==", + "dev": true, + "dependencies": { + "available-typed-arrays": "^1.0.5", + "call-bind": "^1.0.2", + "for-each": "^0.3.3", + "has-proto": "^1.0.1", + "is-typed-array": "^1.1.10" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/typed-array-length": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/typed-array-length/-/typed-array-length-1.0.4.tgz", + "integrity": "sha512-KjZypGq+I/H7HI5HlOoGHkWUUGq+Q0TPhQurLbyrVrvnKTBgzLhIJ7j6J/XTQOi0d1RjyZ0wdas8bKs2p0x3Ng==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "for-each": "^0.3.3", + "is-typed-array": "^1.1.9" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/typescript": { + "version": "5.2.2", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.2.2.tgz", + "integrity": "sha512-mI4WrpHsbCIcwT9cF4FZvr80QUeKvsUsUvKDoR+X/7XHQH98xYD8YHZg7ANtz2GtZt/CBq2QJ0thkGJMHfqc1w==", + "dev": true, + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" + }, + "engines": { + "node": ">=14.17" + } + }, + "node_modules/unbox-primitive": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.0.2.tgz", + "integrity": "sha512-61pPlCD9h51VoreyJ0BReideM3MDKMKnh6+V9L08331ipq6Q8OFXZYiqP6n/tbHx4s5I9uRhcye6BrbkizkBDw==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "has-bigints": "^1.0.2", + "has-symbols": "^1.0.3", + "which-boxed-primitive": "^1.0.2" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/validate-npm-package-license": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz", + "integrity": "sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==", + "dev": true, + "dependencies": { + "spdx-correct": "^3.0.0", + "spdx-expression-parse": "^3.0.0" + } + }, + "node_modules/which": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", + "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", + "dev": true, + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "which": "bin/which" + } + }, + "node_modules/which-boxed-primitive": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/which-boxed-primitive/-/which-boxed-primitive-1.0.2.tgz", + "integrity": "sha512-bwZdv0AKLpplFY2KZRX6TvyuN7ojjr7lwkg6ml0roIy9YeuSr7JS372qlNW18UQYzgYK9ziGcerWqZOmEn9VNg==", + "dev": true, + "dependencies": { + "is-bigint": "^1.0.1", + "is-boolean-object": "^1.1.0", + "is-number-object": "^1.0.4", + "is-string": "^1.0.5", + "is-symbol": "^1.0.3" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/which-typed-array": { + "version": "1.1.13", + "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.13.tgz", + "integrity": "sha512-P5Nra0qjSncduVPEAr7xhoF5guty49ArDTwzJ/yNuPIbZppyRxFQsRCWrocxIY+CnMVG+qfbU2FmDKyvSGClow==", + "dev": true, + "dependencies": { + "available-typed-arrays": "^1.0.5", + "call-bind": "^1.0.4", + "for-each": "^0.3.3", + "gopd": "^1.0.1", + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + } + } +} diff --git a/package.json b/package.json new file mode 100644 index 0000000..2855f7a --- /dev/null +++ b/package.json @@ -0,0 +1,27 @@ +{ + "scripts": { + "clean": "rm -rf dist", + "dev": "npm run clean && run-p dev:**", + "dev:bg": "esbuild --bundle ./src/background/main.ts --outdir=dist/bg --sourcemap --watch", + "dev:popup": "esbuild --bundle ./src/popup/main.tsx --outdir=dist/popup --sourcemap --watch", + "build": "npm run clean && run-p build:**", + "build:bg": "esbuild --bundle ./src/background/main.ts --outdir=dist/bg --minify", + "build:popup": "esbuild --bundle ./src/popup/main.tsx --outdir=dist/popup --minify" + }, + "devDependencies": { + "@types/chrome": "^0.0.251", + "esbuild": "^0.19.5", + "npm-run-all": "^4.1.5", + "typescript": "^5.2.2" + }, + "dependencies": { + "@types/lodash.uniq": "^4.5.9", + "@types/react": "^18.2.37", + "@types/react-dom": "^18.2.15", + "fuse.js": "^7.0.0", + "lodash.uniq": "^4.5.0", + "react": "^18.2.0", + "react-dom": "^18.2.0", + "react-hotkeys-hook": "^4.4.1" + } +} diff --git a/popup.css b/popup.css new file mode 100644 index 0000000..806a525 --- /dev/null +++ b/popup.css @@ -0,0 +1,145 @@ +html, +body, +div, +span, +applet, +object, +iframe, +h1, +h2, +h3, +h4, +h5, +h6, +p, +blockquote, +pre, +a, +abbr, +acronym, +address, +big, +cite, +code, +del, +dfn, +em, +img, +ins, +kbd, +q, +s, +samp, +small, +strike, +strong, +sub, +sup, +tt, +var, +b, +u, +i, +center, +dl, +dt, +dd, +ol, +ul, +li, +fieldset, +form, +label, +legend, +table, +caption, +tbody, +tfoot, +thead, +tr, +th, +td, +article, +aside, +canvas, +details, +embed, +figure, +figcaption, +footer, +header, +hgroup, +menu, +nav, +output, +ruby, +section, +summary, +time, +mark, +audio, +video { + margin: 0; + padding: 0; + border: 0; + font-size: 100%; + font: inherit; + vertical-align: baseline +} + +article, +aside, +details, +figcaption, +figure, +footer, +header, +hgroup, +menu, +nav, +section { + display: block +} + +body { + line-height: 1 +} + +ol, +ul { + list-style: none +} + +blockquote, +q { + quotes: none +} + +blockquote:before, +blockquote:after, +q:before, +q:after { + content: ''; + content: none +} + +table { + border-collapse: collapse; + border-spacing: 0 +} + +:root { + color-scheme: light dark; +} + +body { + width: 500px; + color: black; + font-family: system-ui; + font-size: 12px; + background-color: white; +} + +@media (prefers-color-scheme: dark) { + /* Dark Mode styles go here. */ +} diff --git a/popup.html b/popup.html new file mode 100644 index 0000000..891fbc1 --- /dev/null +++ b/popup.html @@ -0,0 +1,11 @@ + + + + + + + + +
+ + diff --git a/src/background/main.ts b/src/background/main.ts new file mode 100644 index 0000000..e7b48ad --- /dev/null +++ b/src/background/main.ts @@ -0,0 +1,132 @@ +declare const browser: typeof chrome; + +// tabSwitches is a stack of all tab activations. every time a tab becomes +// active it is prepended (unshift) to the front of the array. this means that +// there will be duplicate IDs in the array. +// +// this is handled in 2 ways: +// 1. when the popup opens and asks for a list of tabs, we will only insert the tab +// in the result when it is _first_ seen and ignored thereafter. however, over +// time this will lead to a lot of wasted work since most of the iteration will +// be just skipping elements in this array. +// +// 2. the array is periodically "compacted" by simply running it through a uniq() +// operation, therefore reducing most wasted work most of the time. +let tabSwitches: number[] = []; + +function uniq(array: T[]): T[] { + if (array.length <= 1) { + return array; + } + const seen = new Set(); + const result = []; + for (let ele of array) { + if (seen.has(ele)) { + continue; + } + seen.add(ele); + result.push(ele); + } + return result; +} + +setInterval(() => { + // periodically compact tabSwitches + tabSwitches = uniq(tabSwitches); +}, 1000); + +try { + browser.runtime.onConnect.addListener((port) => { + port.onMessage.addListener((message) => { + switch (message.rpc) { + case "listTabs": + console.time(`rpc:listTabs:${message.id}`); + browser.tabs + .query({}) + .then((tabs) => { + // filter out file:///... things, safari does not really have + // safari://... things like chrome + tabs = tabs.filter((t) => t.url || t.title); + + const hit = new Map( + tabs.filter((t) => !!t.id).map((t) => [t.id!, false]) + ); + const tabsById = new Map( + tabs.filter((t) => !!t.id).map((t) => [t.id!, t]) + ); + const resultTabs = []; + for (let tabId of tabSwitches.slice(1)) { + if (hit.get(tabId)) { + continue; + } + hit.set(tabId, true); + const tab = tabsById.get(tabId); + if (!tab) { + continue; + } + resultTabs.push(tab); + } + for (let [tabId, didHit] of hit.entries()) { + if (didHit) { + continue; + } + const tab = tabsById.get(tabId); + if (!tab) { + continue; + } + resultTabs.push(tab); + } + port.postMessage({ + result: resultTabs, + id: message.id, + }); + }) + .finally(() => { + console.timeEnd(`rpc:listTabs:${message.id}`); + }); + return; + default: + port.postMessage({ + error: `unknown rpc method: ${message.rpc}`, + id: message.id, + }); + } + }); + }); + + type Command = () => Promise | void; + + browser.tabs.onActivated.addListener((activeInfo) => { + if (activeInfo.tabId) { + tabSwitches.unshift(activeInfo.tabId); + } + }); + + const commands = new Map([ + [ + "openTabSwitcher", + async () => { + console.log("open that tab switcher!"); + await (browser as any).browserAction.openPopup(); + // await browser.action.openPopup(); + }, + ], + ]); + + browser.commands.onCommand.addListener(async (command) => { + console.log(`received keyboard shortcut: ${command}`); + const fn = commands.get(command); + if (!fn) { + throw new Error(`unmapped command: ${command}`); + } + try { + await Promise.resolve(fn()); + } catch (e) { + console.error(`command function failed: ${e}`); + } + }); +} catch (e) { + // wrapping everything in a try/catch because F-ING SAFARI refuses to + // help you understand why background scripts fail. (https://developer.apple.com/forums/thread/705321) + console.error(`background startup failure: ${e}`); +} diff --git a/src/popup/main.tsx b/src/popup/main.tsx new file mode 100644 index 0000000..4789217 --- /dev/null +++ b/src/popup/main.tsx @@ -0,0 +1,387 @@ +import Fuse, { FuseResult, FuseResultMatch, RangeTuple } from "fuse.js"; +import React, { + FunctionComponent, + useCallback, + useEffect, + useMemo, + useRef, + useState, +} from "react"; +import ReactDOM from "react-dom/client"; +import { useHotkeys } from "react-hotkeys-hook"; +import "./scrollIntoViewIfNeededPolyfill"; + +function hostname(url: string): string { + try { + const u = new URL(url); + return u.hostname; + } catch { + return ""; + } +} + +const browser = chrome; + +interface BackgroundPage { + listTabs(): Promise; +} + +function useBackgroundPage(): BackgroundPage { + const msgId = useRef(1); + const port = useRef(browser.runtime.connect()); + type PromiseFinishers = { + resolve: (value: T | PromiseLike) => void; + reject: (reason?: any) => void; + }; + const waiter = new Map>(); + useEffect(() => { + const msgListener: Parameters< + typeof port.current.onMessage.addListener + >["0"] = (message) => { + if (!("id" in message) || typeof message.id !== "number") { + return; + } + const promfinishers = waiter.get(message.id); + if (!promfinishers) { + return; + } + waiter.delete(message.id); + if (message.error) { + promfinishers.reject(message.error); + } else { + promfinishers.resolve(message.result); + } + }; + + port.current.onMessage.addListener(msgListener); + return () => { + port.current.onMessage.removeListener(msgListener); + port.current.disconnect(); + }; + }, []); + + return { + listTabs() { + return new Promise((resolve, reject) => { + const id = ++msgId.current; + waiter.set(id, { + reject, + resolve(value) { + console.timeEnd(`bgpage:rpc:listTabs:${id}`); + resolve(value as chrome.tabs.Tab[]); + }, + }); + console.time(`bgpage:rpc:listTabs:${id}`); + port.current.postMessage({ rpc: "listTabs", id }); + }); + }, + }; +} + +const focusTab = (tabId: number, windowId: number): void => { + browser.tabs.update(tabId, { active: true }); + browser.windows.update(windowId, { focused: true }); + window.close(); +}; + +const HighlightMatches: FunctionComponent<{ + text: string; + match?: FuseResultMatch; +}> = ({ text, match }) => { + if (!match) { + return <>{text}; + } + const parts: JSX.Element[] = []; + const indicies = structuredClone(match.indices) as RangeTuple[]; + let currentPart = ""; + let currentMatchIndicy: RangeTuple | undefined; + for (let i = 0; i < text.length; i++) { + if (indicies.length > 0 && indicies[0][0] === i) { + currentMatchIndicy = indicies.shift(); + if (currentPart.length > 0) { + parts.push(<>{currentPart}); + currentPart = ""; + } + } + currentPart += text[i]; + if ( + currentMatchIndicy && + (currentMatchIndicy[1] === i || i === text.length - 1) + ) { + currentMatchIndicy = undefined; + parts.push({currentPart}); + currentPart = ""; + } + } + if (currentPart) { + parts.push(<>{currentPart}); + } + return ( + <> + {parts.map((p, i) => ( + {p} + ))} + + ); +}; + +// ... +function faviconsWork(tabURL: string, size: number): Promise { + return new Promise((resolve) => { + const hiddenDiv = document.createElement("div", {}); + hiddenDiv.setAttribute("style", "display:none;"); + const testImg = document.createElement("img"); + testImg.src = faviconURL({ url: tabURL } as chrome.tabs.Tab, 32)!; + testImg.onerror = () => { + document.body.removeChild(hiddenDiv); + resolve(false); + }; + testImg.onload = () => { + document.body.removeChild(hiddenDiv); + resolve(true); + }; + hiddenDiv.appendChild(testImg); + document.body.appendChild(hiddenDiv); + }); +} + +function faviconURL(t: chrome.tabs.Tab, size: number): string | undefined { + if (t.favIconUrl) { + return t.favIconUrl; + } + if (!t.url) { + return; + } + const url = new URL(browser.runtime.getURL("/_favicon/")); + url.searchParams.set("pageUrl", t.url); + url.searchParams.set("size", `${size}`); + return url.toString(); +} + +const Popup: FunctionComponent = () => { + const [tabSelector, setTabSelector] = useState(0); + const [tabs, setTabs] = useState([]); + const [searchQuery, setSearchQuery] = useState(""); + + const FAVICON_NOT_SUPPORTED = 0; + const FAVICON_SUPPORTED_VIA_EXT_URL = 1; + const FAVICON_SUPPORTED_VIA_TAB_DATA = 2; + const [enableFavicons, setEnabledFavicons] = useState(FAVICON_NOT_SUPPORTED); + useEffect(() => { + faviconsWork("https://www.google.com", 32).then((ok) => { + if (enableFavicons === 0) { + setEnabledFavicons(FAVICON_SUPPORTED_VIA_EXT_URL); + } + }); + }, []); + + useEffect(() => { + if (tabs.length === 0) { + return; + } + console.log({ tabs }); + }, [tabs]); + + useEffect(() => { + setTabSelector(0); + }, [setTabSelector, searchQuery]); + const searchIndex = useMemo(() => { + const result = new Fuse(tabs, { + keys: ["title", "url"], + includeMatches: true, + }); + return result; + }, [tabs]); + const searchResults = useMemo(() => { + if (!searchQuery) { + return tabs.map( + (t, i): FuseResult => ({ + item: t, + refIndex: i, + }) + ); + } + return searchIndex.search(searchQuery); + }, [tabs, searchIndex, searchQuery]); + + const selectedTab = Math.max( + 0, + Math.min(searchResults.length - 1, tabSelector) + ); + + const selectNext = useCallback(() => { + setTabSelector((n) => Math.min(searchResults.length - 1, n + 1)); + }, [searchResults]); + const selectPrev = useCallback(() => { + setTabSelector((n) => Math.max(0, n - 1)); + }, [setTabSelector]); + + const goToTab = useCallback(() => { + focusTab( + searchResults[tabSelector].item.id!, + searchResults[tabSelector].item.windowId + ); + }, [searchResults, tabSelector]); + useHotkeys( + "Down", + () => { + selectNext(); + }, + [selectNext] + ); + useHotkeys( + "Up", + () => { + selectPrev(); + }, + [selectPrev] + ); + useHotkeys( + "Enter", + () => { + goToTab(); + }, + [goToTab] + ); + + const bgpage = useBackgroundPage(); + useEffect(() => { + console.time("queryTabs"); + bgpage + .listTabs() + .then((returnedTabs) => { + if (returnedTabs.find((t) => !!t.favIconUrl)) { + setEnabledFavicons(FAVICON_SUPPORTED_VIA_TAB_DATA); + } + setTabs(returnedTabs); + }) + .finally(() => { + console.timeEnd("queryTabs"); + }); + }, []); + + const selectedTabEle = useRef(null); + useEffect(() => { + if (!selectedTabEle.current) { + return; + } + + // scrollIntoViewIfNeeded is non standard but for just safari it works + // great! + (selectedTabEle as any).current.scrollIntoViewIfNeeded(false); + }, [selectedTabEle.current]); + + return ( +
+
+ { + if (e.key === "ArrowDown") { + selectNext(); + } else if (e.key === "ArrowUp") { + selectPrev(); + } else if (e.key === "Enter") { + goToTab(); + } + }} + spellCheck="false" + autoCorrect="false" + onChange={(e) => { + setSearchQuery(e.target.value); + }} + /> +
+
+
+ {searchResults.length === 0 ? ( +
+ No Results Found +
+ ) : null} + {searchResults.map((t, i) => { + const favicURL = enableFavicons !== 0 ? faviconURL(t.item, 32) : null; + return ( +
{ + focusTab(t.item.id!, t.item.windowId); + }} + ref={i === tabSelector ? selectedTabEle : undefined} + style={{ + padding: "10px", + backgroundColor: i === selectedTab ? "#e9e9e9" : undefined, + + // favicon support + ...(enableFavicons + ? { + display: "flex", + alignItems: "center", + } + : {}), + }} + > + {favicURL && ( +
+ +
+ )} +
+
+ { + m.key === "title")} + /> + } +
+
+ {t.item.url ? hostname(t.item.url) : ""} +
+
+
+ ); + })} +
+
+ ); +}; + +const root = ReactDOM.createRoot(document.getElementById("main")!); +root.render(); diff --git a/src/popup/scrollIntoViewIfNeededPolyfill.ts b/src/popup/scrollIntoViewIfNeededPolyfill.ts new file mode 100644 index 0000000..03fc60f --- /dev/null +++ b/src/popup/scrollIntoViewIfNeededPolyfill.ts @@ -0,0 +1,54 @@ +if (!(Element as any).prototype.scrollIntoViewIfNeeded) { + console.log("scrollIntoViewIfNeeded polyfill installing..."); + (Element.prototype as any).scrollIntoViewIfNeeded = function ( + centerIfNeeded: boolean + ) { + centerIfNeeded = arguments.length === 0 ? true : !!centerIfNeeded; + /** @this {Element} */ + var parent = this.parentNode, + parentComputedStyle = window.getComputedStyle(parent, null), + parentBorderTopWidth = parseInt( + parentComputedStyle.getPropertyValue("border-top-width") + ), + parentBorderLeftWidth = parseInt( + parentComputedStyle.getPropertyValue("border-left-width") + ), + overTop = this.offsetTop - parent.offsetTop < parent.scrollTop, + overBottom = + this.offsetTop - + parent.offsetTop + + this.clientHeight - + parentBorderTopWidth > + parent.scrollTop + parent.clientHeight, + overLeft = this.offsetLeft - parent.offsetLeft < parent.scrollLeft, + overRight = + this.offsetLeft - + parent.offsetLeft + + this.clientWidth - + parentBorderLeftWidth > + parent.scrollLeft + parent.clientWidth, + alignWithTop = overTop && !overBottom; + + if ((overTop || overBottom) && centerIfNeeded) { + parent.scrollTop = + this.offsetTop - + parent.offsetTop - + parent.clientHeight / 2 - + parentBorderTopWidth + + this.clientHeight / 2; + } + + if ((overLeft || overRight) && centerIfNeeded) { + parent.scrollLeft = + this.offsetLeft - + parent.offsetLeft - + parent.clientWidth / 2 - + parentBorderLeftWidth + + this.clientWidth / 2; + } + + if ((overTop || overBottom || overLeft || overRight) && !centerIfNeeded) { + this.scrollIntoView(alignWithTop); + } + }; +} diff --git a/tsconfig.json b/tsconfig.json new file mode 100644 index 0000000..779ad5e --- /dev/null +++ b/tsconfig.json @@ -0,0 +1,20 @@ +{ + "compilerOptions": { + "target": "es6", + "lib": ["dom", "dom.iterable", "esnext"], + "allowJs": false, + "skipLibCheck": true, + "esModuleInterop": true, + "allowSyntheticDefaultImports": true, + "strict": true, + "forceConsistentCasingInFileNames": true, + "noFallthroughCasesInSwitch": true, + "module": "esnext", + "moduleResolution": "node", + "resolveJsonModule": true, + "noEmit": false, + "jsx": "react" + }, + "include": ["src"], + "exclude": ["build", "node_modules"] +}