waybetter 0.1.1 → 0.7.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +139 -6
- package/bin/waybetter.mjs +43 -0
- package/build/runtime.mjs +105 -0
- package/cli/buildenv.mjs +130 -0
- package/cli/dev.mjs +97 -0
- package/cli/i18n.mjs +382 -0
- package/cli/manifests.mjs +383 -0
- package/cli/release.mjs +437 -0
- package/cli/releasecheck.mjs +15 -0
- package/cli/remote.mjs +260 -0
- package/cli/store.mjs +378 -0
- package/cli/strings.mjs +123 -0
- package/dist/runtime/column.d.ts +93 -0
- package/dist/runtime/column.js +451 -0
- package/dist/runtime/column.js.map +1 -0
- package/dist/runtime/commandReport.d.ts +19 -0
- package/dist/runtime/commandReport.js +47 -0
- package/dist/runtime/commandReport.js.map +1 -0
- package/dist/runtime/commands.d.ts +72 -0
- package/dist/runtime/commands.js +214 -0
- package/dist/runtime/commands.js.map +1 -0
- package/dist/runtime/devErrors.d.ts +16 -0
- package/dist/runtime/devErrors.js +30 -0
- package/dist/runtime/devErrors.js.map +1 -0
- package/dist/runtime/domHub.d.ts +21 -0
- package/dist/runtime/domHub.js +139 -4
- package/dist/runtime/domHub.js.map +1 -1
- package/dist/runtime/featureModules.d.ts +157 -0
- package/dist/runtime/featureModules.js +484 -0
- package/dist/runtime/featureModules.js.map +1 -0
- package/dist/runtime/featureTable.d.ts +144 -0
- package/dist/runtime/featureTable.js +223 -0
- package/dist/runtime/featureTable.js.map +1 -0
- package/dist/runtime/fonts.d.ts +22 -0
- package/dist/runtime/fonts.js +72 -0
- package/dist/runtime/fonts.js.map +1 -0
- package/dist/runtime/i18n.d.ts +138 -0
- package/dist/runtime/i18n.js +614 -0
- package/dist/runtime/i18n.js.map +1 -0
- package/dist/runtime/i18nCheck.d.ts +30 -0
- package/dist/runtime/i18nCheck.js +224 -0
- package/dist/runtime/i18nCheck.js.map +1 -0
- package/dist/runtime/pageLang.d.ts +8 -0
- package/dist/runtime/pageLang.js +64 -0
- package/dist/runtime/pageLang.js.map +1 -0
- package/dist/runtime/pageStrings.d.ts +35 -0
- package/dist/runtime/pageStrings.js +76 -0
- package/dist/runtime/pageStrings.js.map +1 -0
- package/dist/runtime/panelButton.d.ts +33 -0
- package/dist/runtime/panelButton.js +83 -0
- package/dist/runtime/panelButton.js.map +1 -0
- package/dist/runtime/permissions.d.ts +47 -0
- package/dist/runtime/permissions.js +141 -0
- package/dist/runtime/permissions.js.map +1 -0
- package/dist/runtime/pluginApi.d.ts +51 -2
- package/dist/runtime/pluginApi.js +137 -22
- package/dist/runtime/pluginApi.js.map +1 -1
- package/dist/runtime/pluginI18n.d.ts +29 -0
- package/dist/runtime/pluginI18n.js +119 -0
- package/dist/runtime/pluginI18n.js.map +1 -0
- package/dist/runtime/settingsForm.d.ts +66 -0
- package/dist/runtime/settingsForm.js +114 -0
- package/dist/runtime/settingsForm.js.map +1 -0
- package/dist/runtime/site.d.ts +5 -0
- package/dist/runtime/site.js +1 -1
- package/dist/runtime/site.js.map +1 -1
- package/dist/runtime/siteRuntime.d.ts +144 -0
- package/dist/runtime/siteRuntime.js +175 -0
- package/dist/runtime/siteRuntime.js.map +1 -0
- package/dist/runtime/stringPackHook.d.ts +84 -0
- package/dist/runtime/stringPackHook.js +220 -0
- package/dist/runtime/stringPackHook.js.map +1 -0
- package/dist/runtime/stringPackTranslate.d.ts +61 -0
- package/dist/runtime/stringPackTranslate.js +267 -0
- package/dist/runtime/stringPackTranslate.js.map +1 -0
- package/dist/runtime/stringPacks.d.ts +248 -0
- package/dist/runtime/stringPacks.js +610 -0
- package/dist/runtime/stringPacks.js.map +1 -0
- package/dist/runtime/styles.d.ts +15 -0
- package/dist/runtime/styles.js +81 -0
- package/dist/runtime/styles.js.map +1 -0
- package/dist/runtime/textNet.d.ts +15 -0
- package/dist/runtime/textNet.js +131 -0
- package/dist/runtime/textNet.js.map +1 -0
- package/dist/runtime/themeApi.d.ts +121 -0
- package/dist/runtime/themeApi.js +220 -0
- package/dist/runtime/themeApi.js.map +1 -0
- package/dist/runtime/themeBar.d.ts +28 -0
- package/dist/runtime/themeBar.js +82 -0
- package/dist/runtime/themeBar.js.map +1 -0
- package/dist/runtime/themeChoice.d.ts +52 -0
- package/dist/runtime/themeChoice.js +69 -0
- package/dist/runtime/themeChoice.js.map +1 -0
- package/dist/runtime/themeComponents.d.ts +435 -0
- package/dist/runtime/themeComponents.js +476 -0
- package/dist/runtime/themeComponents.js.map +1 -0
- package/dist/runtime/themeDecor.d.ts +73 -0
- package/dist/runtime/themeDecor.js +133 -0
- package/dist/runtime/themeDecor.js.map +1 -0
- package/dist/runtime/themeDerive.d.ts +69 -0
- package/dist/runtime/themeDerive.js +117 -0
- package/dist/runtime/themeDerive.js.map +1 -0
- package/dist/runtime/themeDoctor.d.ts +52 -0
- package/dist/runtime/themeDoctor.js +112 -0
- package/dist/runtime/themeDoctor.js.map +1 -0
- package/dist/runtime/themeGuards.d.ts +60 -0
- package/dist/runtime/themeGuards.js +235 -0
- package/dist/runtime/themeGuards.js.map +1 -0
- package/dist/runtime/themeIcons.d.ts +130 -0
- package/dist/runtime/themeIcons.js +271 -0
- package/dist/runtime/themeIcons.js.map +1 -0
- package/dist/runtime/themeInk.d.ts +37 -0
- package/dist/runtime/themeInk.js +111 -0
- package/dist/runtime/themeInk.js.map +1 -0
- package/dist/runtime/themeInvariants.d.ts +39 -0
- package/dist/runtime/themeInvariants.js +273 -0
- package/dist/runtime/themeInvariants.js.map +1 -0
- package/dist/runtime/themeRuntime.d.ts +114 -0
- package/dist/runtime/themeRuntime.js +570 -0
- package/dist/runtime/themeRuntime.js.map +1 -0
- package/dist/runtime/themeSchema.d.ts +10 -0
- package/dist/runtime/themeSchema.js +150 -0
- package/dist/runtime/themeSchema.js.map +1 -0
- package/dist/runtime/themeSpec.d.ts +263 -0
- package/dist/runtime/themeSpec.js +435 -0
- package/dist/runtime/themeSpec.js.map +1 -0
- package/dist/runtime/themeTokens.d.ts +12 -0
- package/dist/runtime/themeTokens.js +14 -6
- package/dist/runtime/themeTokens.js.map +1 -1
- package/dist/runtime/themeVariants.d.ts +30 -0
- package/dist/runtime/themeVariants.js +53 -0
- package/dist/runtime/themeVariants.js.map +1 -0
- package/dist/runtime/ui.d.ts +192 -0
- package/dist/runtime/ui.js +926 -0
- package/dist/runtime/ui.js.map +1 -0
- package/dist/shell/InstallDialog.d.ts +40 -0
- package/dist/shell/InstallDialog.js +176 -0
- package/dist/shell/InstallDialog.js.map +1 -0
- package/dist/shell/StoreView.d.ts +78 -0
- package/dist/shell/StoreView.js +108 -0
- package/dist/shell/StoreView.js.map +1 -0
- package/dist/shell/addressModel.js.map +1 -1
- package/dist/shell/chrome.js.map +1 -1
- package/dist/shell/deckModel.d.ts +117 -0
- package/dist/shell/deckModel.js +267 -0
- package/dist/shell/deckModel.js.map +1 -0
- package/dist/shell/frame/AccountSwitcher.d.ts +42 -0
- package/dist/shell/frame/AccountSwitcher.js +243 -0
- package/dist/shell/frame/AccountSwitcher.js.map +1 -0
- package/dist/shell/frame/AddColumnDialog.d.ts +8 -0
- package/dist/shell/frame/AddColumnDialog.js +81 -0
- package/dist/shell/frame/AddColumnDialog.js.map +1 -0
- package/dist/shell/frame/AppMenu.d.ts +44 -0
- package/dist/shell/frame/AppMenu.js +721 -0
- package/dist/shell/frame/AppMenu.js.map +1 -0
- package/dist/shell/frame/CommandPalette.d.ts +7 -0
- package/dist/shell/frame/CommandPalette.js +118 -0
- package/dist/shell/frame/CommandPalette.js.map +1 -0
- package/dist/shell/frame/DeckView.d.ts +13 -0
- package/dist/shell/frame/DeckView.js +287 -0
- package/dist/shell/frame/DeckView.js.map +1 -0
- package/dist/shell/frame/FindBar.d.ts +10 -0
- package/dist/shell/frame/FindBar.js +108 -0
- package/dist/shell/frame/FindBar.js.map +1 -0
- package/dist/shell/frame/MediaPanel.d.ts +8 -0
- package/dist/shell/frame/MediaPanel.js +76 -0
- package/dist/shell/frame/MediaPanel.js.map +1 -0
- package/dist/shell/frame/NewTabPage.d.ts +9 -0
- package/dist/shell/frame/NewTabPage.js +71 -0
- package/dist/shell/frame/NewTabPage.js.map +1 -0
- package/dist/shell/frame/PaneTheme.d.ts +16 -0
- package/dist/shell/frame/PaneTheme.js +67 -0
- package/dist/shell/frame/PaneTheme.js.map +1 -0
- package/dist/shell/frame/ReportDialog.d.ts +3 -0
- package/dist/shell/frame/ReportDialog.js +95 -0
- package/dist/shell/frame/ReportDialog.js.map +1 -0
- package/dist/shell/frame/Shell.d.ts +9 -0
- package/dist/shell/frame/Shell.js +1139 -0
- package/dist/shell/frame/Shell.js.map +1 -0
- package/dist/shell/frame/Titlebar.d.ts +17 -0
- package/dist/shell/frame/Titlebar.js +79 -0
- package/dist/shell/frame/Titlebar.js.map +1 -0
- package/dist/shell/frame/TitlebarExtras.d.ts +4 -0
- package/dist/shell/frame/TitlebarExtras.js +202 -0
- package/dist/shell/frame/TitlebarExtras.js.map +1 -0
- package/dist/shell/frame/WebPanel.d.ts +4 -0
- package/dist/shell/frame/WebPanel.js +185 -0
- package/dist/shell/frame/WebPanel.js.map +1 -0
- package/dist/shell/frame/accountModel.d.ts +49 -0
- package/dist/shell/frame/accountModel.js +67 -0
- package/dist/shell/frame/accountModel.js.map +1 -0
- package/dist/shell/frame/accountSwitcher.css +91 -0
- package/dist/shell/frame/appI18n.d.ts +44 -0
- package/dist/shell/frame/appI18n.js +64 -0
- package/dist/shell/frame/appI18n.js.map +1 -0
- package/dist/shell/frame/appMenu.css +127 -0
- package/dist/shell/frame/backupModel.d.ts +38 -0
- package/dist/shell/frame/backupModel.js +192 -0
- package/dist/shell/frame/backupModel.js.map +1 -0
- package/dist/shell/frame/boot.d.ts +8 -0
- package/dist/shell/frame/boot.js +37 -0
- package/dist/shell/frame/boot.js.map +1 -0
- package/dist/shell/frame/brand.d.ts +1 -0
- package/dist/shell/frame/brand.js +4 -0
- package/dist/shell/frame/brand.js.map +1 -0
- package/dist/shell/frame/bridge.d.ts +35 -0
- package/dist/shell/frame/bridge.js +70 -0
- package/dist/shell/frame/bridge.js.map +1 -0
- package/dist/shell/frame/chromeTheme.d.ts +47 -0
- package/dist/shell/frame/chromeTheme.js +118 -0
- package/dist/shell/frame/chromeTheme.js.map +1 -0
- package/dist/shell/frame/deck.css +209 -0
- package/dist/shell/frame/deckStore.d.ts +89 -0
- package/dist/shell/frame/deckStore.js +239 -0
- package/dist/shell/frame/deckStore.js.map +1 -0
- package/dist/shell/frame/devHost.d.ts +35 -0
- package/dist/shell/frame/devHost.js +80 -0
- package/dist/shell/frame/devHost.js.map +1 -0
- package/dist/shell/frame/devModel.d.ts +7 -0
- package/dist/shell/frame/devModel.js +17 -0
- package/dist/shell/frame/devModel.js.map +1 -0
- package/dist/shell/frame/diag.d.ts +7 -0
- package/dist/shell/frame/diag.js +39 -0
- package/dist/shell/frame/diag.js.map +1 -0
- package/dist/shell/frame/edges.css +159 -0
- package/dist/shell/frame/findBar.css +14 -0
- package/dist/shell/frame/frameMessages.d.ts +248 -0
- package/dist/shell/frame/frameMessages.js +252 -0
- package/dist/shell/frame/frameMessages.js.map +1 -0
- package/dist/shell/frame/hooks.d.ts +39 -0
- package/dist/shell/frame/hooks.js +97 -0
- package/dist/shell/frame/hooks.js.map +1 -0
- package/dist/shell/frame/i18n.d.ts +27 -0
- package/dist/shell/frame/i18n.js +66 -0
- package/dist/shell/frame/i18n.js.map +1 -0
- package/dist/shell/frame/iconPack.d.ts +11 -0
- package/dist/shell/frame/iconPack.js +45 -0
- package/dist/shell/frame/iconPack.js.map +1 -0
- package/dist/shell/frame/icons.d.ts +71 -0
- package/dist/shell/frame/icons.js +75 -0
- package/dist/shell/frame/icons.js.map +1 -0
- package/dist/shell/frame/index.d.ts +34 -0
- package/dist/shell/frame/index.js +43 -0
- package/dist/shell/frame/index.js.map +1 -0
- package/dist/shell/frame/language.d.ts +58 -0
- package/dist/shell/frame/language.js +165 -0
- package/dist/shell/frame/language.js.map +1 -0
- package/dist/shell/frame/mediaModel.d.ts +47 -0
- package/dist/shell/frame/mediaModel.js +67 -0
- package/dist/shell/frame/mediaModel.js.map +1 -0
- package/dist/shell/frame/menuMessages.en.json +96 -0
- package/dist/shell/frame/menuModel.d.ts +319 -0
- package/dist/shell/frame/menuModel.js +301 -0
- package/dist/shell/frame/menuModel.js.map +1 -0
- package/dist/shell/frame/nativeMenu.d.ts +5 -0
- package/dist/shell/frame/nativeMenu.js +178 -0
- package/dist/shell/frame/nativeMenu.js.map +1 -0
- package/dist/shell/frame/nativeMenuModel.d.ts +102 -0
- package/dist/shell/frame/nativeMenuModel.js +186 -0
- package/dist/shell/frame/nativeMenuModel.js.map +1 -0
- package/dist/shell/frame/paletteModel.d.ts +139 -0
- package/dist/shell/frame/paletteModel.js +114 -0
- package/dist/shell/frame/paletteModel.js.map +1 -0
- package/dist/shell/frame/paneTheme.css +9 -0
- package/dist/shell/frame/pluginCommandStore.d.ts +23 -0
- package/dist/shell/frame/pluginCommandStore.js +70 -0
- package/dist/shell/frame/pluginCommandStore.js.map +1 -0
- package/dist/shell/frame/reportModel.d.ts +52 -0
- package/dist/shell/frame/reportModel.js +105 -0
- package/dist/shell/frame/reportModel.js.map +1 -0
- package/dist/shell/frame/safeStore.d.ts +7 -0
- package/dist/shell/frame/safeStore.js +40 -0
- package/dist/shell/frame/safeStore.js.map +1 -0
- package/dist/shell/frame/searchInput.d.ts +2 -0
- package/dist/shell/frame/searchInput.js +11 -0
- package/dist/shell/frame/searchInput.js.map +1 -0
- package/dist/shell/frame/shell.css +634 -0
- package/dist/shell/frame/site.d.ts +206 -0
- package/dist/shell/frame/site.js +22 -0
- package/dist/shell/frame/site.js.map +1 -0
- package/dist/shell/frame/state.d.ts +101 -0
- package/dist/shell/frame/state.js +286 -0
- package/dist/shell/frame/state.js.map +1 -0
- package/dist/shell/frame/syncGate.d.ts +10 -0
- package/dist/shell/frame/syncGate.js +36 -0
- package/dist/shell/frame/syncGate.js.map +1 -0
- package/dist/shell/frame/syncHost.d.ts +35 -0
- package/dist/shell/frame/syncHost.js +85 -0
- package/dist/shell/frame/syncHost.js.map +1 -0
- package/dist/shell/frame/tabStill.d.ts +2 -0
- package/dist/shell/frame/tabStill.js +62 -0
- package/dist/shell/frame/tabStill.js.map +1 -0
- package/dist/shell/frame/themeScopes.d.ts +29 -0
- package/dist/shell/frame/themeScopes.js +61 -0
- package/dist/shell/frame/themeScopes.js.map +1 -0
- package/dist/shell/frame/themeStore.d.ts +99 -0
- package/dist/shell/frame/themeStore.js +267 -0
- package/dist/shell/frame/themeStore.js.map +1 -0
- package/dist/shell/frame/windowBinding.d.ts +2 -0
- package/dist/shell/frame/windowBinding.js +7 -0
- package/dist/shell/frame/windowBinding.js.map +1 -0
- package/dist/shell/frame/workspaceModel.d.ts +82 -0
- package/dist/shell/frame/workspaceModel.js +250 -0
- package/dist/shell/frame/workspaceModel.js.map +1 -0
- package/dist/shell/frame/workspaces.css +84 -0
- package/dist/shell/frame/workspaces.d.ts +22 -0
- package/dist/shell/frame/workspaces.js +125 -0
- package/dist/shell/frame/workspaces.js.map +1 -0
- package/dist/shell/frame/zoomStore.d.ts +10 -0
- package/dist/shell/frame/zoomStore.js +65 -0
- package/dist/shell/frame/zoomStore.js.map +1 -0
- package/dist/shell/installController.d.ts +137 -0
- package/dist/shell/installController.js +172 -0
- package/dist/shell/installController.js.map +1 -0
- package/dist/shell/installerMessages.d.ts +30 -0
- package/dist/shell/installerMessages.js +36 -0
- package/dist/shell/installerMessages.js.map +1 -0
- package/dist/shell/linkDrop.js.map +1 -1
- package/dist/shell/messages.d.ts +16 -0
- package/dist/shell/messages.js +27 -0
- package/dist/shell/messages.js.map +1 -0
- package/dist/shell/palette.js.map +1 -1
- package/dist/shell/paneModel.d.ts +22 -0
- package/dist/shell/paneModel.js +24 -1
- package/dist/shell/paneModel.js.map +1 -1
- package/dist/shell/panel/Appearance.d.ts +8 -0
- package/dist/shell/panel/Appearance.js +265 -0
- package/dist/shell/panel/Appearance.js.map +1 -0
- package/dist/shell/panel/BackupPanel.d.ts +5 -0
- package/dist/shell/panel/BackupPanel.js +198 -0
- package/dist/shell/panel/BackupPanel.js.map +1 -0
- package/dist/shell/panel/DeveloperPanel.d.ts +4 -0
- package/dist/shell/panel/DeveloperPanel.js +51 -0
- package/dist/shell/panel/DeveloperPanel.js.map +1 -0
- package/dist/shell/panel/FeatureToggles.d.ts +13 -0
- package/dist/shell/panel/FeatureToggles.js +42 -0
- package/dist/shell/panel/FeatureToggles.js.map +1 -0
- package/dist/shell/panel/Home.d.ts +3 -0
- package/dist/shell/panel/Home.js +23 -0
- package/dist/shell/panel/Home.js.map +1 -0
- package/dist/shell/panel/IconPackInstall.d.ts +15 -0
- package/dist/shell/panel/IconPackInstall.js +41 -0
- package/dist/shell/panel/IconPackInstall.js.map +1 -0
- package/dist/shell/panel/LanguageSettings.d.ts +1 -0
- package/dist/shell/panel/LanguageSettings.js +54 -0
- package/dist/shell/panel/LanguageSettings.js.map +1 -0
- package/dist/shell/panel/MakePanel.d.ts +3 -0
- package/dist/shell/panel/MakePanel.js +237 -0
- package/dist/shell/panel/MakePanel.js.map +1 -0
- package/dist/shell/panel/MarkdownDoc.d.ts +6 -0
- package/dist/shell/panel/MarkdownDoc.js +35 -0
- package/dist/shell/panel/MarkdownDoc.js.map +1 -0
- package/dist/shell/panel/Modes.d.ts +40 -0
- package/dist/shell/panel/Modes.js +270 -0
- package/dist/shell/panel/Modes.js.map +1 -0
- package/dist/shell/panel/NavIcon.d.ts +4 -0
- package/dist/shell/panel/NavIcon.js +6 -0
- package/dist/shell/panel/NavIcon.js.map +1 -0
- package/dist/shell/panel/Panel.d.ts +7 -0
- package/dist/shell/panel/Panel.js +139 -0
- package/dist/shell/panel/Panel.js.map +1 -0
- package/dist/shell/panel/PluginFeatures.d.ts +24 -0
- package/dist/shell/panel/PluginFeatures.js +165 -0
- package/dist/shell/panel/PluginFeatures.js.map +1 -0
- package/dist/shell/panel/Plugins.d.ts +33 -0
- package/dist/shell/panel/Plugins.js +112 -0
- package/dist/shell/panel/Plugins.js.map +1 -0
- package/dist/shell/panel/PowerSettings.d.ts +4 -0
- package/dist/shell/panel/PowerSettings.js +52 -0
- package/dist/shell/panel/PowerSettings.js.map +1 -0
- package/dist/shell/panel/Settings.d.ts +23 -0
- package/dist/shell/panel/Settings.js +117 -0
- package/dist/shell/panel/Settings.js.map +1 -0
- package/dist/shell/panel/ShareSetup.d.ts +8 -0
- package/dist/shell/panel/ShareSetup.js +130 -0
- package/dist/shell/panel/ShareSetup.js.map +1 -0
- package/dist/shell/panel/StoreSection.d.ts +7 -0
- package/dist/shell/panel/StoreSection.js +78 -0
- package/dist/shell/panel/StoreSection.js.map +1 -0
- package/dist/shell/panel/StringPacks.d.ts +20 -0
- package/dist/shell/panel/StringPacks.js +131 -0
- package/dist/shell/panel/StringPacks.js.map +1 -0
- package/dist/shell/panel/ThemeBuilder.d.ts +5 -0
- package/dist/shell/panel/ThemeBuilder.js +205 -0
- package/dist/shell/panel/ThemeBuilder.js.map +1 -0
- package/dist/shell/panel/backup.css +34 -0
- package/dist/shell/panel/builder.css +240 -0
- package/dist/shell/panel/builderModel.d.ts +55 -0
- package/dist/shell/panel/builderModel.js +95 -0
- package/dist/shell/panel/builderModel.js.map +1 -0
- package/dist/shell/panel/compare.d.ts +10 -0
- package/dist/shell/panel/compare.js +51 -0
- package/dist/shell/panel/compare.js.map +1 -0
- package/dist/shell/panel/controls.d.ts +135 -0
- package/dist/shell/panel/controls.js +213 -0
- package/dist/shell/panel/controls.js.map +1 -0
- package/dist/shell/panel/featureModel.d.ts +69 -0
- package/dist/shell/panel/featureModel.js +79 -0
- package/dist/shell/panel/featureModel.js.map +1 -0
- package/dist/shell/panel/fonts/FontBrowser.d.ts +10 -0
- package/dist/shell/panel/fonts/FontBrowser.js +189 -0
- package/dist/shell/panel/fonts/FontBrowser.js.map +1 -0
- package/dist/shell/panel/fonts/FontRoles.d.ts +20 -0
- package/dist/shell/panel/fonts/FontRoles.js +77 -0
- package/dist/shell/panel/fonts/FontRoles.js.map +1 -0
- package/dist/shell/panel/fonts/catalog.d.ts +37 -0
- package/dist/shell/panel/fonts/catalog.js +68 -0
- package/dist/shell/panel/fonts/catalog.js.map +1 -0
- package/dist/shell/panel/fonts/googleFontsCatalog.json +1 -0
- package/dist/shell/panel/index.d.ts +20 -0
- package/dist/shell/panel/index.js +34 -0
- package/dist/shell/panel/index.js.map +1 -0
- package/dist/shell/panel/languageModel.d.ts +5 -0
- package/dist/shell/panel/languageModel.js +7 -0
- package/dist/shell/panel/languageModel.js.map +1 -0
- package/dist/shell/panel/make.css +73 -0
- package/dist/shell/panel/makeModel.d.ts +32 -0
- package/dist/shell/panel/makeModel.js +84 -0
- package/dist/shell/panel/makeModel.js.map +1 -0
- package/dist/shell/panel/markdown.d.ts +46 -0
- package/dist/shell/panel/markdown.js +100 -0
- package/dist/shell/panel/markdown.js.map +1 -0
- package/dist/shell/panel/nav.d.ts +12 -0
- package/dist/shell/panel/nav.js +50 -0
- package/dist/shell/panel/nav.js.map +1 -0
- package/dist/shell/panel/panel.css +401 -0
- package/dist/shell/panel/panelMessages.d.ts +803 -0
- package/dist/shell/panel/panelMessages.js +779 -0
- package/dist/shell/panel/panelMessages.js.map +1 -0
- package/dist/shell/panel/plugins.css +59 -0
- package/dist/shell/panel/setupModel.d.ts +87 -0
- package/dist/shell/panel/setupModel.js +152 -0
- package/dist/shell/panel/setupModel.js.map +1 -0
- package/dist/shell/panel/site.d.ts +259 -0
- package/dist/shell/panel/site.js +25 -0
- package/dist/shell/panel/site.js.map +1 -0
- package/dist/shell/panel/strings.css +7 -0
- package/dist/shell/panel/themes.d.ts +10 -0
- package/dist/shell/panel/themes.js +8 -0
- package/dist/shell/panel/themes.js.map +1 -0
- package/dist/shell/profileModel.d.ts +3 -2
- package/dist/shell/profileModel.js +7 -5
- package/dist/shell/profileModel.js.map +1 -1
- package/dist/shell/store.css +250 -0
- package/dist/shell/storeMessages.d.ts +193 -0
- package/dist/shell/storeMessages.js +196 -0
- package/dist/shell/storeMessages.js.map +1 -0
- package/dist/shell/storeModel.d.ts +205 -0
- package/dist/shell/storeModel.js +146 -0
- package/dist/shell/storeModel.js.map +1 -0
- package/dist/shell/stringPacksModel.d.ts +44 -0
- package/dist/shell/stringPacksModel.js +99 -0
- package/dist/shell/stringPacksModel.js.map +1 -0
- package/dist/shell/updateModel.d.ts +2 -1
- package/dist/shell/updateModel.js +5 -4
- package/dist/shell/updateModel.js.map +1 -1
- package/dist/shell/windowControls.d.ts +4 -0
- package/dist/shell/windowControls.js +5 -0
- package/dist/shell/windowControls.js.map +1 -1
- package/i18n-config.schema.json +29 -0
- package/i18n-meta.schema.json +26 -0
- package/i18n.schema.json +42 -0
- package/icons.schema.json +655 -0
- package/languages.schema.json +23 -0
- package/locales/ar-x-fm.json +11 -0
- package/locales/ar.json +1388 -0
- package/locales/bg.json +1387 -0
- package/locales/bn.json +1387 -0
- package/locales/ca.json +1387 -0
- package/locales/cs.json +1387 -0
- package/locales/da.json +1387 -0
- package/locales/de.json +1387 -0
- package/locales/el.json +1387 -0
- package/locales/en-GB.json +27 -0
- package/locales/en.json +1386 -0
- package/locales/en.meta.json +51 -0
- package/locales/es.json +1387 -0
- package/locales/eu.json +1387 -0
- package/locales/fa.json +1388 -0
- package/locales/fi.json +1387 -0
- package/locales/fil.json +1387 -0
- package/locales/fr.json +1387 -0
- package/locales/ga.json +1387 -0
- package/locales/gl.json +1387 -0
- package/locales/gu.json +1387 -0
- package/locales/ha.json +1387 -0
- package/locales/he.json +1388 -0
- package/locales/hi.json +1387 -0
- package/locales/hr.json +1387 -0
- package/locales/hu.json +1387 -0
- package/locales/id.json +1387 -0
- package/locales/ig.json +1387 -0
- package/locales/it.json +1387 -0
- package/locales/ja.json +1387 -0
- package/locales/kn.json +1387 -0
- package/locales/ko.json +1387 -0
- package/locales/mr.json +1387 -0
- package/locales/ms.json +1387 -0
- package/locales/nb.json +1387 -0
- package/locales/nl.json +1387 -0
- package/locales/pl.json +1387 -0
- package/locales/pt.json +1387 -0
- package/locales/ro.json +1387 -0
- package/locales/ru.json +1387 -0
- package/locales/sk.json +1387 -0
- package/locales/sr.json +1387 -0
- package/locales/sv.json +1387 -0
- package/locales/ta.json +1387 -0
- package/locales/th.json +1387 -0
- package/locales/tr.json +1387 -0
- package/locales/uk.json +1387 -0
- package/locales/ur.json +1388 -0
- package/locales/vi.json +1387 -0
- package/locales/yo.json +1387 -0
- package/locales/zh-Hans.json +1387 -0
- package/locales/zh-Hant.json +1387 -0
- package/package.json +138 -5
- package/store-catalog.schema.json +78 -0
- package/theme.schema.json +4668 -0
- package/windows/installer.nsi +946 -0
- package/windows/languages/Basque.nsh +28 -0
- package/windows/languages/Catalan.nsh +28 -0
- package/windows/languages/Croatian.nsh +28 -0
- package/windows/languages/Czech.nsh +28 -0
- package/windows/languages/Danish.nsh +28 -0
- package/windows/languages/Finnish.nsh +28 -0
- package/windows/languages/Galician.nsh +28 -0
- package/windows/languages/Greek.nsh +28 -0
- package/windows/languages/Hungarian.nsh +28 -0
- package/windows/languages/Indonesian.nsh +28 -0
- package/windows/languages/Irish.nsh +28 -0
- package/windows/languages/Malay.nsh +28 -0
- package/windows/languages/Polish.nsh +28 -0
- package/windows/languages/Romanian.nsh +28 -0
- package/windows/languages/Serbian.nsh +28 -0
- package/windows/languages/Slovak.nsh +28 -0
- package/windows/languages/Thai.nsh +28 -0
|
@@ -0,0 +1,273 @@
|
|
|
1
|
+
// Theme invariants (theme engine v3, plan 6.2): a pure measurement over a rendered document that
|
|
2
|
+
// says, with numbers, whether a theme is correct. Runs in the page (fixtures over Playwright, the live
|
|
3
|
+
// app over CDP); it never changes the page. Grew out of verification/theme-qa/probe.js.
|
|
4
|
+
//
|
|
5
|
+
// I1 text contrast 4.5:1 (3:1 large; 7:1 with access high) of ink over its painted backdrop
|
|
6
|
+
// I1b non-text contrast icons (svg, masked glyphs) 3:1 over their backdrop
|
|
7
|
+
// I2 X colour leakage computed colours equal to an X palette key that is not whitelisted
|
|
8
|
+
// I3 truncated labels in bar, nav, tabs, buttons and menu rows (X's own long-name truncation allowed)
|
|
9
|
+
// I4 bar geometry a horizontal bar: equal item widths with labels, gaps <= one item, hit-testable
|
|
10
|
+
// I5 icon provenance in pack contexts: X's own line paths still visible (xLine)
|
|
11
|
+
// I6 empty frames a framed box (edge or own fill) with nothing rendered inside, taller than 2px
|
|
12
|
+
// I7 frame nesting a framed box holding another framed box of the same fill, or a whole column
|
|
13
|
+
// I8 popover bounds menus, hover cards, dropdowns, tooltips inside the viewport minus the bar inset
|
|
14
|
+
// I10 targets interactive elements in bar, action bar, composer >= 24px (44 with access high)
|
|
15
|
+
// I9 (forced :hover) needs CDP and I11 is static; both live in the runners.
|
|
16
|
+
export const INVARIANT_IDS = ['I1', 'I1b', 'I2', 'I3', 'I4', 'I5', 'I6', 'I7', 'I8', 'I10'];
|
|
17
|
+
/** X's own palette (Default and Lights out neutrals, X blue): the leak list until the engine exports X_COLOUR_KEYS. */
|
|
18
|
+
export const DEFAULT_X_KEYS = ['rgb(29, 155, 240)', 'rgb(26, 140, 216)', 'rgb(15, 20, 25)', 'rgb(83, 100, 113)', 'rgb(113, 118, 123)', 'rgb(239, 243, 244)',
|
|
19
|
+
'rgb(247, 249, 249)', 'rgb(231, 233, 234)', 'rgb(22, 24, 28)', 'rgb(32, 35, 39)', 'rgb(47, 51, 54)', 'rgb(20, 20, 20)', 'rgb(207, 217, 222)', 'rgb(51, 54, 57)'];
|
|
20
|
+
const parse = (c) => { const m = /rgba?\(([\d.]+),? ([\d.]+),? ([\d.]+)(?:,? ?\/? ?([\d.]+))?/.exec(c || ''); return m ? [+m[1], +m[2], +m[3], m[4] === undefined ? 1 : +m[4]] : null; };
|
|
21
|
+
const lum = ([r, g, b]) => { const f = (v) => { v /= 255; return v <= 0.03928 ? v / 12.92 : ((v + 0.055) / 1.055) ** 2.4; }; return 0.2126 * f(r) + 0.7152 * f(g) + 0.0722 * f(b); };
|
|
22
|
+
export const contrast = (a, b) => { const [x, y] = [lum(a), lum(b)].sort((m, n) => n - m); return (x + 0.05) / (y + 0.05); };
|
|
23
|
+
const blend = (top, under) => top[3] >= 1 ? top : [0, 1, 2].map(i => top[i] * top[3] + under[i] * (1 - top[3])).concat(1);
|
|
24
|
+
const css = (c) => `rgb(${c.slice(0, 3).map(Math.round).join(', ')})`;
|
|
25
|
+
export function runInvariants(doc = document, opts = {}) {
|
|
26
|
+
const win = doc.defaultView;
|
|
27
|
+
const vw = win.innerWidth, vh = win.innerHeight;
|
|
28
|
+
const keep = opts.keep ?? 12;
|
|
29
|
+
const high = opts.access === 'high';
|
|
30
|
+
const counts = Object.fromEntries(INVARIANT_IDS.map(id => [id, 0]));
|
|
31
|
+
const findings = [];
|
|
32
|
+
const notes = { unknownBackdrop: 0, allowedTruncation: 0, bar: 'none' };
|
|
33
|
+
const cs = (e) => win.getComputedStyle(e);
|
|
34
|
+
const up = (e) => e.parentElement ?? (e.parentNode?.host ?? null);
|
|
35
|
+
const rectOf = (e) => { const r = e.getBoundingClientRect(); return [Math.round(r.left), Math.round(r.top), Math.round(r.width), Math.round(r.height)]; };
|
|
36
|
+
const sel = (el) => {
|
|
37
|
+
const p = [];
|
|
38
|
+
for (let e = el; e && e !== doc.body && p.length < 4; e = up(e)) {
|
|
39
|
+
let s = e.tagName.toLowerCase();
|
|
40
|
+
const t = e.getAttribute('data-testid');
|
|
41
|
+
if (t) {
|
|
42
|
+
p.unshift(`${s}[data-testid="${t}"]`);
|
|
43
|
+
break;
|
|
44
|
+
}
|
|
45
|
+
if (e.id) {
|
|
46
|
+
p.unshift(`#${e.id}`);
|
|
47
|
+
break;
|
|
48
|
+
}
|
|
49
|
+
const c = [...e.classList].filter(c => !/^(css|r)-/.test(c)).slice(0, 2);
|
|
50
|
+
if (c.length)
|
|
51
|
+
s += '.' + c.join('.');
|
|
52
|
+
const role = e.getAttribute('role');
|
|
53
|
+
if (role)
|
|
54
|
+
s += `[role="${role}"]`;
|
|
55
|
+
p.unshift(s);
|
|
56
|
+
}
|
|
57
|
+
return p.join(' > ');
|
|
58
|
+
};
|
|
59
|
+
const add = (id, el, detail, value) => {
|
|
60
|
+
counts[id]++;
|
|
61
|
+
if (findings.filter(f => f.id === id).length < keep)
|
|
62
|
+
findings.push({ id, sel: sel(el), rect: rectOf(el), detail, ...(value === undefined ? {} : { value: +value.toFixed(2) }) });
|
|
63
|
+
};
|
|
64
|
+
const hidden = (el) => { for (let e = el; e; e = up(e)) {
|
|
65
|
+
const s = cs(e);
|
|
66
|
+
if (s.display === 'none' || s.visibility === 'hidden' || +s.opacity < 0.05)
|
|
67
|
+
return true;
|
|
68
|
+
} return false; };
|
|
69
|
+
const onScreen = (el) => { const r = el.getBoundingClientRect(); return r.width > 1 && r.height > 1 && r.bottom > 0 && r.top < vh && r.right > 0 && r.left < vw; };
|
|
70
|
+
const visible = (el) => onScreen(el) && !hidden(el);
|
|
71
|
+
const pageColor = () => { for (const e of [doc.body, doc.documentElement]) {
|
|
72
|
+
const c = parse(cs(e).backgroundColor);
|
|
73
|
+
if (c && c[3] > 0)
|
|
74
|
+
return blend(c, [255, 255, 255, 1]);
|
|
75
|
+
} return [255, 255, 255, 1]; };
|
|
76
|
+
/** The painted backdrop under an element: the alpha stack up to the first opaque fill; `image` when an image or gradient paints first. */
|
|
77
|
+
const backdrop = (el) => {
|
|
78
|
+
const stack = [];
|
|
79
|
+
for (let e = el; e && e !== doc.documentElement; e = up(e)) {
|
|
80
|
+
const s = cs(e);
|
|
81
|
+
if (s.backgroundImage !== 'none' && !/^linear-gradient\(rgba?\([^)]*\), rgba?\([^)]*\)\)$/.test(s.backgroundImage))
|
|
82
|
+
return { color: pageColor(), image: true };
|
|
83
|
+
const c = parse(s.backgroundColor);
|
|
84
|
+
if (c && c[3] > 0) {
|
|
85
|
+
stack.push(c);
|
|
86
|
+
if (c[3] >= 1)
|
|
87
|
+
break;
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
let base = pageColor();
|
|
91
|
+
for (const c of stack.reverse())
|
|
92
|
+
base = blend(c, base);
|
|
93
|
+
return { color: base, image: false };
|
|
94
|
+
};
|
|
95
|
+
const ownText = (el) => [...el.childNodes].filter(n => n.nodeType === 3).map(n => n.textContent).join('').trim();
|
|
96
|
+
const all = [...doc.querySelectorAll('body *')];
|
|
97
|
+
// I1 text contrast, I2 leakage, I3 truncation
|
|
98
|
+
const xKeys = new Set(opts.xColourKeys ?? DEFAULT_X_KEYS);
|
|
99
|
+
const whitelisted = (el) => !!el.closest('[data-testid="icon-verified"],[data-testid="unlike"],[data-testid="unretweet"],[data-testid="removeBookmark"],img,video,canvas');
|
|
100
|
+
const LABEL_CONTEXT = 'nav[role="navigation"], header[role="banner"], [role="tablist"], [role="tab"], button, [role="button"], [role="menuitem"], .dv-tab';
|
|
101
|
+
const ALLOWED_TRUNC = '[data-testid="User-Name"], [data-testid="trend"], .bt-exact-time, [data-testid="UserName"], [data-testid="UserCell"]';
|
|
102
|
+
for (const el of all) {
|
|
103
|
+
if (el.closest('[aria-hidden="true"]') || el.closest('svg') && el.tagName.toLowerCase() !== 'svg')
|
|
104
|
+
continue;
|
|
105
|
+
const text = ownText(el);
|
|
106
|
+
if (!visible(el))
|
|
107
|
+
continue;
|
|
108
|
+
const st = cs(el);
|
|
109
|
+
if (!opts.exemptLeak && !whitelisted(el)) {
|
|
110
|
+
for (const prop of ['color', 'backgroundColor', 'borderTopColor', 'borderBottomColor', 'fill', 'outlineColor']) {
|
|
111
|
+
const v = st[prop];
|
|
112
|
+
if (!xKeys.has(v))
|
|
113
|
+
continue;
|
|
114
|
+
if (prop.startsWith('border') && parseFloat(prop === 'borderTopColor' ? st.borderTopWidth : st.borderBottomWidth) === 0)
|
|
115
|
+
continue;
|
|
116
|
+
if (prop === 'outlineColor' && (st.outlineStyle === 'none' || parseFloat(st.outlineWidth) === 0))
|
|
117
|
+
continue;
|
|
118
|
+
if (prop === 'color' && !text)
|
|
119
|
+
continue;
|
|
120
|
+
if (prop === 'fill' && el.tagName.toLowerCase() !== 'svg')
|
|
121
|
+
continue;
|
|
122
|
+
add('I2', el, `${v} as ${prop}`);
|
|
123
|
+
break;
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
if (!text)
|
|
127
|
+
continue;
|
|
128
|
+
const fg = parse(st.color);
|
|
129
|
+
if (!fg)
|
|
130
|
+
continue;
|
|
131
|
+
const back = backdrop(el);
|
|
132
|
+
if (back.image)
|
|
133
|
+
notes.unknownBackdrop++;
|
|
134
|
+
else {
|
|
135
|
+
const size = parseFloat(st.fontSize), bold = +st.fontWeight >= 700;
|
|
136
|
+
const large = size >= 24 || (size >= 18.66 && bold);
|
|
137
|
+
const need = high ? (large ? 4.5 : 7) : (large ? 3 : 4.5);
|
|
138
|
+
const ink = blend([fg[0], fg[1], fg[2], fg[3] * Math.min(1, +st.opacity || 1)], back.color);
|
|
139
|
+
const r = contrast(ink, back.color);
|
|
140
|
+
if (r < need - 0.005)
|
|
141
|
+
add('I1', el, `${r.toFixed(2)}:1 < ${need} ${st.color} on ${css(back.color)} "${text.slice(0, 24)}"`, r);
|
|
142
|
+
}
|
|
143
|
+
if (el.closest(LABEL_CONTEXT)) {
|
|
144
|
+
const cut = el.scrollWidth > el.clientWidth + 1 && (st.textOverflow === 'ellipsis' || st.overflow === 'hidden' || st.overflowX === 'hidden');
|
|
145
|
+
const barLabel = !!el.closest('nav[role="navigation"]') && st.textOverflow === 'ellipsis' && el.scrollWidth > el.clientWidth + 1;
|
|
146
|
+
if (cut || barLabel) {
|
|
147
|
+
if (el.closest(ALLOWED_TRUNC))
|
|
148
|
+
notes.allowedTruncation++;
|
|
149
|
+
else
|
|
150
|
+
add('I3', el, `"${text.slice(0, 24)}" shown in ${el.clientWidth}px of ${el.scrollWidth}px`, el.clientWidth);
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
// I1b non-text contrast and I5 icon provenance
|
|
155
|
+
const PACK_CONTEXT = 'nav[role="navigation"], header[role="banner"], [role="group"], [data-testid="toolBar"], #layers [role="menu"], [data-testid="GrokDrawer"], [data-testid="DMDrawer"], [data-testid="app-bar-back"], [data-testid="app-bar-close"]';
|
|
156
|
+
for (const svg of doc.querySelectorAll('svg')) {
|
|
157
|
+
if (!visible(svg) || svg.closest('[data-testid="icon-verified"]'))
|
|
158
|
+
continue;
|
|
159
|
+
const s = cs(svg);
|
|
160
|
+
const painted = [...svg.querySelectorAll('path, circle, rect, polygon, ellipse, line')].filter(p => { const ps = cs(p); return +ps.opacity > 0.05 && (ps.fill !== 'none' || ps.stroke !== 'none'); });
|
|
161
|
+
const masked = (e) => { const es = cs(e); return (es.maskImage && es.maskImage !== 'none') || (es.webkitMaskImage ?? 'none') !== 'none' || es.backgroundImage !== 'none'; };
|
|
162
|
+
if (opts.pack && svg.closest(PACK_CONTEXT) && painted.length && !masked(svg) && !(svg.parentElement && masked(svg.parentElement)))
|
|
163
|
+
add('I5', svg, `X's own drawing in ${svg.closest(PACK_CONTEXT).tagName.toLowerCase()}`);
|
|
164
|
+
const ink = parse(masked(svg) ? s.backgroundColor : s.color);
|
|
165
|
+
if (!ink || ink[3] === 0 || (!painted.length && !masked(svg)))
|
|
166
|
+
continue;
|
|
167
|
+
const back = backdrop(svg.parentElement ?? svg);
|
|
168
|
+
if (back.image)
|
|
169
|
+
continue;
|
|
170
|
+
const r = contrast(blend(ink, back.color), back.color);
|
|
171
|
+
if (r < 3 - 0.005)
|
|
172
|
+
add('I1b', svg, `${r.toFixed(2)}:1 < 3 icon ${css(ink)} on ${css(back.color)}`, r);
|
|
173
|
+
}
|
|
174
|
+
// I6 empty frames, I7 nesting
|
|
175
|
+
const framed = (el) => {
|
|
176
|
+
const s = cs(el), r = el.getBoundingClientRect();
|
|
177
|
+
if (r.width < 60 || r.height <= 2 || s.position === 'fixed' && r.width >= vw - 2 && r.height >= vh - 2)
|
|
178
|
+
return false;
|
|
179
|
+
if (s.backgroundImage !== 'none')
|
|
180
|
+
return false;
|
|
181
|
+
const edge = ['Top', 'Right', 'Bottom', 'Left'].filter(k => parseFloat(s[`border${k}Width`]) > 0 && s[`border${k}Style`] !== 'none' && (parse(s[`border${k}Color`])?.[3] ?? 0) > 0).length >= 3 || /inset/.test(s.boxShadow);
|
|
182
|
+
const fill = parse(s.backgroundColor);
|
|
183
|
+
const parent = up(el);
|
|
184
|
+
const own = !!fill && fill[3] > 0.05 && !!parent && css(blend(fill, backdrop(parent).color)) !== css(backdrop(parent).color);
|
|
185
|
+
return edge || own;
|
|
186
|
+
};
|
|
187
|
+
const MEDIA = 'img, svg, video, canvas, input, textarea, select, iframe, [role="img"], [role="textbox"], [role="progressbar"]';
|
|
188
|
+
const frames = [];
|
|
189
|
+
for (const el of all) {
|
|
190
|
+
if (!visible(el) || el.closest('#layers [data-testid="mask"]') || el.matches('[data-testid="mask"]'))
|
|
191
|
+
continue;
|
|
192
|
+
if (el.matches(MEDIA) || !framed(el))
|
|
193
|
+
continue;
|
|
194
|
+
frames.push(el);
|
|
195
|
+
const content = (el.textContent ?? '').trim() || [...el.querySelectorAll(MEDIA)].some(m => visible(m)) || [...el.querySelectorAll('*')].some(c => cs(c).backgroundImage !== 'none' && visible(c));
|
|
196
|
+
if (!content)
|
|
197
|
+
add('I6', el, `empty frame ${rectOf(el)[2]}x${rectOf(el)[3]} ${cs(el).backgroundColor}`, rectOf(el)[3]);
|
|
198
|
+
}
|
|
199
|
+
for (const el of frames) {
|
|
200
|
+
const fill = cs(el).backgroundColor;
|
|
201
|
+
const column = el.querySelector('[data-testid="sidebarColumn"], [data-testid="primaryColumn"]');
|
|
202
|
+
// Controls (a bevelled button on a bevelled bar, a pill in a card) are not frames: only boxes nest wrongly.
|
|
203
|
+
const inner = frames.find(f => f !== el && el.contains(f) && !f.closest('a, button, [role="button"], [role="link"], [role="tab"], input, label') && cs(f).backgroundColor === fill && parse(fill)[3] > 0 && /solid|inset/.test(cs(f).borderTopStyle + cs(f).boxShadow));
|
|
204
|
+
if (column)
|
|
205
|
+
add('I7', el, `frame holds the ${column.getAttribute('data-testid')}`);
|
|
206
|
+
else if (inner)
|
|
207
|
+
add('I7', el, `frame holds a frame of the same fill (${sel(inner)})`);
|
|
208
|
+
}
|
|
209
|
+
// I4 bar geometry and I10 targets
|
|
210
|
+
const nav = doc.querySelector('header[role="banner"] nav[role="navigation"]');
|
|
211
|
+
if (nav && visible(nav)) {
|
|
212
|
+
const items = [...nav.children].filter(c => visible(c));
|
|
213
|
+
const rects = items.map(i => i.getBoundingClientRect());
|
|
214
|
+
const horizontal = rects.length > 2 && rects.every(r => Math.abs(r.top - rects[0].top) < 6);
|
|
215
|
+
notes.bar = horizontal ? 'horizontal' : 'rail';
|
|
216
|
+
const labelled = items.some(i => [...i.querySelectorAll('span, div')].some(s => ownText(s) && visible(s)));
|
|
217
|
+
if (horizontal) {
|
|
218
|
+
notes.barMode = labelled ? 'labels' : 'icons';
|
|
219
|
+
const widths = rects.map(r => r.width);
|
|
220
|
+
if (labelled && Math.max(...widths) - Math.min(...widths) > 2)
|
|
221
|
+
add('I4', nav, `item widths ${Math.round(Math.min(...widths))}..${Math.round(Math.max(...widths))}px`, Math.max(...widths) - Math.min(...widths));
|
|
222
|
+
const sorted = [...rects].sort((a, b) => a.left - b.left);
|
|
223
|
+
const unit = Math.max(...widths);
|
|
224
|
+
for (let i = 1; i < sorted.length; i++) {
|
|
225
|
+
const gap = sorted[i].left - sorted[i - 1].right;
|
|
226
|
+
if (gap > unit + 1) {
|
|
227
|
+
add('I4', nav, `gap ${Math.round(gap)}px > one item ${Math.round(unit)}px`, gap);
|
|
228
|
+
break;
|
|
229
|
+
}
|
|
230
|
+
}
|
|
231
|
+
}
|
|
232
|
+
for (const [i, item] of items.entries()) {
|
|
233
|
+
const r = rects[i];
|
|
234
|
+
const x = r.left + r.width / 2, y = r.top + r.height / 2;
|
|
235
|
+
if (x < 0 || y < 0 || x > vw || y > vh) {
|
|
236
|
+
add('I4', item, 'item off screen');
|
|
237
|
+
continue;
|
|
238
|
+
}
|
|
239
|
+
const hit = doc.elementFromPoint(x, y);
|
|
240
|
+
// A layer over the bar (modal mask, menu, hover card) is I8's business, not the bar's.
|
|
241
|
+
if (hit?.closest('#layers'))
|
|
242
|
+
continue;
|
|
243
|
+
if (!hit || !(item === hit || item.contains(hit)))
|
|
244
|
+
add('I4', item, `item not hit-testable (under ${hit ? sel(hit) : 'nothing'})`);
|
|
245
|
+
}
|
|
246
|
+
}
|
|
247
|
+
const minTarget = high ? 44 : 24;
|
|
248
|
+
const TARGET_CONTEXT = 'header[role="banner"] nav[role="navigation"] > *, header[role="banner"] [data-testid="SideNav_NewTweet_Button"], header[role="banner"] [data-testid="SideNav_AccountSwitcher_Button"], article [role="group"] button, article [role="group"] a, [data-testid="toolBar"] button, [data-testid="toolBar"] [role="button"]';
|
|
249
|
+
for (const el of doc.querySelectorAll(TARGET_CONTEXT)) {
|
|
250
|
+
if (!visible(el))
|
|
251
|
+
continue;
|
|
252
|
+
const r = el.getBoundingClientRect();
|
|
253
|
+
if (r.width < minTarget - 0.5 || r.height < minTarget - 0.5)
|
|
254
|
+
add('I10', el, `${Math.round(r.width)}x${Math.round(r.height)} < ${minTarget}`, Math.min(r.width, r.height));
|
|
255
|
+
}
|
|
256
|
+
// I8 popover bounds
|
|
257
|
+
const root = cs(doc.documentElement);
|
|
258
|
+
const insetTop = parseFloat(root.getPropertyValue('--wb-bar-inset-top')) || 0, insetBottom = parseFloat(root.getPropertyValue('--wb-bar-inset-bottom')) || 0;
|
|
259
|
+
for (const el of doc.querySelectorAll('[data-testid="hoverCardParent"], [role="menu"], [role="listbox"], [data-testid="HoverCard"], [data-testid="Dropdown"], [data-testid="HoverLabel"]')) {
|
|
260
|
+
if (!visible(el) && !(el.getBoundingClientRect().width > 1 && !hidden(el)))
|
|
261
|
+
continue;
|
|
262
|
+
if (el.parentElement?.closest('[data-testid="hoverCardParent"], [role="menu"], [data-testid="HoverCard"]'))
|
|
263
|
+
continue;
|
|
264
|
+
const r = el.getBoundingClientRect();
|
|
265
|
+
if (r.width < 2 || r.height < 2)
|
|
266
|
+
continue;
|
|
267
|
+
const out = Math.max(-r.left, -(r.top - insetTop), r.right - vw, r.bottom - (vh - insetBottom));
|
|
268
|
+
if (out > 1)
|
|
269
|
+
add('I8', el, `${Math.round(out)}px outside the viewport`, out);
|
|
270
|
+
}
|
|
271
|
+
return { counts, findings, notes, viewport: [vw, vh] };
|
|
272
|
+
}
|
|
273
|
+
//# sourceMappingURL=themeInvariants.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"themeInvariants.js","sourceRoot":"","sources":["../../../runtime/src/themeInvariants.ts"],"names":[],"mappings":"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","sourcesContent":["// Theme invariants (theme engine v3, plan 6.2): a pure measurement over a rendered document that\n// says, with numbers, whether a theme is correct. Runs in the page (fixtures over Playwright, the live\n// app over CDP); it never changes the page. Grew out of verification/theme-qa/probe.js.\n//\n// I1 text contrast 4.5:1 (3:1 large; 7:1 with access high) of ink over its painted backdrop\n// I1b non-text contrast icons (svg, masked glyphs) 3:1 over their backdrop\n// I2 X colour leakage computed colours equal to an X palette key that is not whitelisted\n// I3 truncated labels in bar, nav, tabs, buttons and menu rows (X's own long-name truncation allowed)\n// I4 bar geometry a horizontal bar: equal item widths with labels, gaps <= one item, hit-testable\n// I5 icon provenance in pack contexts: X's own line paths still visible (xLine)\n// I6 empty frames a framed box (edge or own fill) with nothing rendered inside, taller than 2px\n// I7 frame nesting a framed box holding another framed box of the same fill, or a whole column\n// I8 popover bounds menus, hover cards, dropdowns, tooltips inside the viewport minus the bar inset\n// I10 targets interactive elements in bar, action bar, composer >= 24px (44 with access high)\n// I9 (forced :hover) needs CDP and I11 is static; both live in the runners.\n\nexport type InvariantId = 'I1' | 'I1b' | 'I2' | 'I3' | 'I4' | 'I5' | 'I6' | 'I7' | 'I8' | 'I10';\nexport const INVARIANT_IDS: InvariantId[] = ['I1', 'I1b', 'I2', 'I3', 'I4', 'I5', 'I6', 'I7', 'I8', 'I10'];\n\nexport type Rect = [number, number, number, number];\nexport interface Finding { id: InvariantId; sel: string; rect: Rect; detail: string; value?: number }\nexport interface InvariantOptions {\n /** Colours (`rgb(r, g, b)`) that are X's own palette; default: X's light and dark neutrals and blue. */\n xColourKeys?: string[];\n /** The X default theme keeps X's colours: I2 off. */\n exemptLeak?: boolean;\n /** The theme draws an icon pack: I5 on. */\n pack?: boolean;\n access?: 'standard' | 'high';\n /** Cap of findings kept per invariant (counts are always complete). */\n keep?: number;\n}\nexport interface InvariantReport {\n counts: Record<InvariantId, number>;\n findings: Finding[];\n /** Measured but not failures: text over images, X icons with no slot, X's allowed truncation. */\n notes: { unknownBackdrop: number; allowedTruncation: number; bar: 'none' | 'rail' | 'horizontal'; barMode?: 'labels' | 'icons' };\n viewport: [number, number];\n}\n\n/** X's own palette (Default and Lights out neutrals, X blue): the leak list until the engine exports X_COLOUR_KEYS. */\nexport const DEFAULT_X_KEYS = ['rgb(29, 155, 240)', 'rgb(26, 140, 216)', 'rgb(15, 20, 25)', 'rgb(83, 100, 113)', 'rgb(113, 118, 123)', 'rgb(239, 243, 244)',\n 'rgb(247, 249, 249)', 'rgb(231, 233, 234)', 'rgb(22, 24, 28)', 'rgb(32, 35, 39)', 'rgb(47, 51, 54)', 'rgb(20, 20, 20)', 'rgb(207, 217, 222)', 'rgb(51, 54, 57)'];\n\ntype RGBA = [number, number, number, number];\nconst parse = (c: string | null | undefined): RGBA | null => { const m = /rgba?\\(([\\d.]+),? ([\\d.]+),? ([\\d.]+)(?:,? ?\\/? ?([\\d.]+))?/.exec(c || ''); return m ? [+m[1], +m[2], +m[3], m[4] === undefined ? 1 : +m[4]] : null; };\nconst lum = ([r, g, b]: RGBA) => { const f = (v: number) => { v /= 255; return v <= 0.03928 ? v / 12.92 : ((v + 0.055) / 1.055) ** 2.4; }; return 0.2126 * f(r) + 0.7152 * f(g) + 0.0722 * f(b); };\nexport const contrast = (a: RGBA, b: RGBA) => { const [x, y] = [lum(a), lum(b)].sort((m, n) => n - m); return (x + 0.05) / (y + 0.05); };\nconst blend = (top: RGBA, under: RGBA): RGBA => top[3] >= 1 ? top : [0, 1, 2].map(i => top[i] * top[3] + under[i] * (1 - top[3])).concat(1) as RGBA;\nconst css = (c: RGBA) => `rgb(${c.slice(0, 3).map(Math.round).join(', ')})`;\n\nexport function runInvariants(doc: Document = document, opts: InvariantOptions = {}): InvariantReport {\n const win = doc.defaultView as Window & typeof globalThis;\n const vw = win.innerWidth, vh = win.innerHeight;\n const keep = opts.keep ?? 12;\n const high = opts.access === 'high';\n const counts = Object.fromEntries(INVARIANT_IDS.map(id => [id, 0])) as Record<InvariantId, number>;\n const findings: Finding[] = [];\n const notes: InvariantReport['notes'] = { unknownBackdrop: 0, allowedTruncation: 0, bar: 'none' };\n const cs = (e: Element) => win.getComputedStyle(e);\n const up = (e: Element): Element | null => e.parentElement ?? ((e.parentNode as ShadowRoot | null)?.host ?? null);\n const rectOf = (e: Element): Rect => { const r = e.getBoundingClientRect(); return [Math.round(r.left), Math.round(r.top), Math.round(r.width), Math.round(r.height)]; };\n const sel = (el: Element) => {\n const p: string[] = [];\n for (let e: Element | null = el; e && e !== doc.body && p.length < 4; e = up(e)) {\n let s = e.tagName.toLowerCase(); const t = e.getAttribute('data-testid');\n if (t) { p.unshift(`${s}[data-testid=\"${t}\"]`); break; }\n if (e.id) { p.unshift(`#${e.id}`); break; }\n const c = [...e.classList].filter(c => !/^(css|r)-/.test(c)).slice(0, 2); if (c.length) s += '.' + c.join('.');\n const role = e.getAttribute('role'); if (role) s += `[role=\"${role}\"]`;\n p.unshift(s);\n }\n return p.join(' > ');\n };\n const add = (id: InvariantId, el: Element, detail: string, value?: number) => {\n counts[id]++;\n if (findings.filter(f => f.id === id).length < keep) findings.push({ id, sel: sel(el), rect: rectOf(el), detail, ...(value === undefined ? {} : { value: +value.toFixed(2) }) });\n };\n const hidden = (el: Element) => { for (let e: Element | null = el; e; e = up(e)) { const s = cs(e); if (s.display === 'none' || s.visibility === 'hidden' || +s.opacity < 0.05) return true; } return false; };\n const onScreen = (el: Element) => { const r = el.getBoundingClientRect(); return r.width > 1 && r.height > 1 && r.bottom > 0 && r.top < vh && r.right > 0 && r.left < vw; };\n const visible = (el: Element) => onScreen(el) && !hidden(el);\n const pageColor = (): RGBA => { for (const e of [doc.body, doc.documentElement]) { const c = parse(cs(e).backgroundColor); if (c && c[3] > 0) return blend(c, [255, 255, 255, 1]); } return [255, 255, 255, 1]; };\n /** The painted backdrop under an element: the alpha stack up to the first opaque fill; `image` when an image or gradient paints first. */\n const backdrop = (el: Element): { color: RGBA; image: boolean } => {\n const stack: RGBA[] = [];\n for (let e: Element | null = el; e && e !== doc.documentElement; e = up(e)) {\n const s = cs(e);\n if (s.backgroundImage !== 'none' && !/^linear-gradient\\(rgba?\\([^)]*\\), rgba?\\([^)]*\\)\\)$/.test(s.backgroundImage)) return { color: pageColor(), image: true };\n const c = parse(s.backgroundColor);\n if (c && c[3] > 0) { stack.push(c); if (c[3] >= 1) break; }\n }\n let base = pageColor();\n for (const c of stack.reverse()) base = blend(c, base);\n return { color: base, image: false };\n };\n const ownText = (el: Element) => [...el.childNodes].filter(n => n.nodeType === 3).map(n => n.textContent).join('').trim();\n const all = [...doc.querySelectorAll('body *')];\n\n // I1 text contrast, I2 leakage, I3 truncation\n const xKeys = new Set(opts.xColourKeys ?? DEFAULT_X_KEYS);\n const whitelisted = (el: Element) => !!el.closest('[data-testid=\"icon-verified\"],[data-testid=\"unlike\"],[data-testid=\"unretweet\"],[data-testid=\"removeBookmark\"],img,video,canvas');\n const LABEL_CONTEXT = 'nav[role=\"navigation\"], header[role=\"banner\"], [role=\"tablist\"], [role=\"tab\"], button, [role=\"button\"], [role=\"menuitem\"], .dv-tab';\n const ALLOWED_TRUNC = '[data-testid=\"User-Name\"], [data-testid=\"trend\"], .bt-exact-time, [data-testid=\"UserName\"], [data-testid=\"UserCell\"]';\n for (const el of all) {\n if (el.closest('[aria-hidden=\"true\"]') || el.closest('svg') && el.tagName.toLowerCase() !== 'svg') continue;\n const text = ownText(el);\n if (!visible(el)) continue;\n const st = cs(el);\n if (!opts.exemptLeak && !whitelisted(el)) {\n for (const prop of ['color', 'backgroundColor', 'borderTopColor', 'borderBottomColor', 'fill', 'outlineColor'] as const) {\n const v = st[prop] as string; if (!xKeys.has(v)) continue;\n if (prop.startsWith('border') && parseFloat(prop === 'borderTopColor' ? st.borderTopWidth : st.borderBottomWidth) === 0) continue;\n if (prop === 'outlineColor' && (st.outlineStyle === 'none' || parseFloat(st.outlineWidth) === 0)) continue;\n if (prop === 'color' && !text) continue;\n if (prop === 'fill' && el.tagName.toLowerCase() !== 'svg') continue;\n add('I2', el, `${v} as ${prop}`); break;\n }\n }\n if (!text) continue;\n const fg = parse(st.color); if (!fg) continue;\n const back = backdrop(el);\n if (back.image) notes.unknownBackdrop++;\n else {\n const size = parseFloat(st.fontSize), bold = +st.fontWeight >= 700;\n const large = size >= 24 || (size >= 18.66 && bold);\n const need = high ? (large ? 4.5 : 7) : (large ? 3 : 4.5);\n const ink = blend([fg[0], fg[1], fg[2], fg[3] * Math.min(1, +st.opacity || 1)], back.color);\n const r = contrast(ink, back.color);\n if (r < need - 0.005) add('I1', el, `${r.toFixed(2)}:1 < ${need} ${st.color} on ${css(back.color)} \"${text.slice(0, 24)}\"`, r);\n }\n if (el.closest(LABEL_CONTEXT)) {\n const cut = el.scrollWidth > el.clientWidth + 1 && (st.textOverflow === 'ellipsis' || st.overflow === 'hidden' || st.overflowX === 'hidden');\n const barLabel = !!el.closest('nav[role=\"navigation\"]') && st.textOverflow === 'ellipsis' && el.scrollWidth > el.clientWidth + 1;\n if (cut || barLabel) {\n if (el.closest(ALLOWED_TRUNC)) notes.allowedTruncation++;\n else add('I3', el, `\"${text.slice(0, 24)}\" shown in ${el.clientWidth}px of ${el.scrollWidth}px`, el.clientWidth);\n }\n }\n }\n\n // I1b non-text contrast and I5 icon provenance\n const PACK_CONTEXT = 'nav[role=\"navigation\"], header[role=\"banner\"], [role=\"group\"], [data-testid=\"toolBar\"], #layers [role=\"menu\"], [data-testid=\"GrokDrawer\"], [data-testid=\"DMDrawer\"], [data-testid=\"app-bar-back\"], [data-testid=\"app-bar-close\"]';\n for (const svg of doc.querySelectorAll('svg')) {\n if (!visible(svg) || svg.closest('[data-testid=\"icon-verified\"]')) continue;\n const s = cs(svg);\n const painted = [...svg.querySelectorAll('path, circle, rect, polygon, ellipse, line')].filter(p => { const ps = cs(p); return +ps.opacity > 0.05 && (ps.fill !== 'none' || ps.stroke !== 'none'); });\n const masked = (e: Element) => { const es = cs(e); return (es.maskImage && es.maskImage !== 'none') || ((es as unknown as Record<string, string>).webkitMaskImage ?? 'none') !== 'none' || es.backgroundImage !== 'none'; };\n if (opts.pack && svg.closest(PACK_CONTEXT) && painted.length && !masked(svg) && !(svg.parentElement && masked(svg.parentElement))) add('I5', svg, `X's own drawing in ${svg.closest(PACK_CONTEXT)!.tagName.toLowerCase()}`);\n const ink = parse(masked(svg) ? s.backgroundColor : s.color);\n if (!ink || ink[3] === 0 || (!painted.length && !masked(svg))) continue;\n const back = backdrop(svg.parentElement ?? svg);\n if (back.image) continue;\n const r = contrast(blend(ink, back.color), back.color);\n if (r < 3 - 0.005) add('I1b', svg, `${r.toFixed(2)}:1 < 3 icon ${css(ink)} on ${css(back.color)}`, r);\n }\n\n // I6 empty frames, I7 nesting\n const framed = (el: Element) => {\n const s = cs(el), r = el.getBoundingClientRect();\n if (r.width < 60 || r.height <= 2 || s.position === 'fixed' && r.width >= vw - 2 && r.height >= vh - 2) return false;\n if (s.backgroundImage !== 'none') return false;\n const edge = ['Top', 'Right', 'Bottom', 'Left'].filter(k => parseFloat(s[`border${k}Width` as 'borderTopWidth']) > 0 && s[`border${k}Style` as 'borderTopStyle'] !== 'none' && (parse(s[`border${k}Color` as 'borderTopColor'])?.[3] ?? 0) > 0).length >= 3 || /inset/.test(s.boxShadow);\n const fill = parse(s.backgroundColor); const parent = up(el);\n const own = !!fill && fill[3] > 0.05 && !!parent && css(blend(fill, backdrop(parent).color)) !== css(backdrop(parent).color);\n return edge || own;\n };\n const MEDIA = 'img, svg, video, canvas, input, textarea, select, iframe, [role=\"img\"], [role=\"textbox\"], [role=\"progressbar\"]';\n const frames: Element[] = [];\n for (const el of all) {\n if (!visible(el) || el.closest('#layers [data-testid=\"mask\"]') || el.matches('[data-testid=\"mask\"]')) continue;\n if (el.matches(MEDIA) || !framed(el)) continue;\n frames.push(el);\n const content = (el.textContent ?? '').trim() || [...el.querySelectorAll(MEDIA)].some(m => visible(m)) || [...el.querySelectorAll('*')].some(c => cs(c).backgroundImage !== 'none' && visible(c));\n if (!content) add('I6', el, `empty frame ${rectOf(el)[2]}x${rectOf(el)[3]} ${cs(el).backgroundColor}`, rectOf(el)[3]);\n }\n for (const el of frames) {\n const fill = cs(el).backgroundColor;\n const column = el.querySelector('[data-testid=\"sidebarColumn\"], [data-testid=\"primaryColumn\"]');\n // Controls (a bevelled button on a bevelled bar, a pill in a card) are not frames: only boxes nest wrongly.\n const inner = frames.find(f => f !== el && el.contains(f) && !f.closest('a, button, [role=\"button\"], [role=\"link\"], [role=\"tab\"], input, label') && cs(f).backgroundColor === fill && parse(fill)![3] > 0 && /solid|inset/.test(cs(f).borderTopStyle + cs(f).boxShadow));\n if (column) add('I7', el, `frame holds the ${column.getAttribute('data-testid')}`);\n else if (inner) add('I7', el, `frame holds a frame of the same fill (${sel(inner)})`);\n }\n\n // I4 bar geometry and I10 targets\n const nav = doc.querySelector('header[role=\"banner\"] nav[role=\"navigation\"]');\n if (nav && visible(nav)) {\n const items = [...nav.children].filter(c => visible(c)) as HTMLElement[];\n const rects = items.map(i => i.getBoundingClientRect());\n const horizontal = rects.length > 2 && rects.every(r => Math.abs(r.top - rects[0].top) < 6);\n notes.bar = horizontal ? 'horizontal' : 'rail';\n const labelled = items.some(i => [...i.querySelectorAll('span, div')].some(s => ownText(s) && visible(s)));\n if (horizontal) {\n notes.barMode = labelled ? 'labels' : 'icons';\n const widths = rects.map(r => r.width);\n if (labelled && Math.max(...widths) - Math.min(...widths) > 2) add('I4', nav, `item widths ${Math.round(Math.min(...widths))}..${Math.round(Math.max(...widths))}px`, Math.max(...widths) - Math.min(...widths));\n const sorted = [...rects].sort((a, b) => a.left - b.left);\n const unit = Math.max(...widths);\n for (let i = 1; i < sorted.length; i++) { const gap = sorted[i].left - sorted[i - 1].right; if (gap > unit + 1) { add('I4', nav, `gap ${Math.round(gap)}px > one item ${Math.round(unit)}px`, gap); break; } }\n }\n for (const [i, item] of items.entries()) {\n const r = rects[i]; const x = r.left + r.width / 2, y = r.top + r.height / 2;\n if (x < 0 || y < 0 || x > vw || y > vh) { add('I4', item, 'item off screen'); continue; }\n const hit = doc.elementFromPoint(x, y);\n // A layer over the bar (modal mask, menu, hover card) is I8's business, not the bar's.\n if (hit?.closest('#layers')) continue;\n if (!hit || !(item === hit || item.contains(hit))) add('I4', item, `item not hit-testable (under ${hit ? sel(hit) : 'nothing'})`);\n }\n }\n const minTarget = high ? 44 : 24;\n const TARGET_CONTEXT = 'header[role=\"banner\"] nav[role=\"navigation\"] > *, header[role=\"banner\"] [data-testid=\"SideNav_NewTweet_Button\"], header[role=\"banner\"] [data-testid=\"SideNav_AccountSwitcher_Button\"], article [role=\"group\"] button, article [role=\"group\"] a, [data-testid=\"toolBar\"] button, [data-testid=\"toolBar\"] [role=\"button\"]';\n for (const el of doc.querySelectorAll(TARGET_CONTEXT)) {\n if (!visible(el)) continue;\n const r = el.getBoundingClientRect();\n if (r.width < minTarget - 0.5 || r.height < minTarget - 0.5) add('I10', el, `${Math.round(r.width)}x${Math.round(r.height)} < ${minTarget}`, Math.min(r.width, r.height));\n }\n\n // I8 popover bounds\n const root = cs(doc.documentElement);\n const insetTop = parseFloat(root.getPropertyValue('--wb-bar-inset-top')) || 0, insetBottom = parseFloat(root.getPropertyValue('--wb-bar-inset-bottom')) || 0;\n for (const el of doc.querySelectorAll('[data-testid=\"hoverCardParent\"], [role=\"menu\"], [role=\"listbox\"], [data-testid=\"HoverCard\"], [data-testid=\"Dropdown\"], [data-testid=\"HoverLabel\"]')) {\n if (!visible(el) && !(el.getBoundingClientRect().width > 1 && !hidden(el))) continue;\n if (el.parentElement?.closest('[data-testid=\"hoverCardParent\"], [role=\"menu\"], [data-testid=\"HoverCard\"]')) continue;\n const r = el.getBoundingClientRect();\n if (r.width < 2 || r.height < 2) continue;\n const out = Math.max(-r.left, -(r.top - insetTop), r.right - vw, r.bottom - (vh - insetBottom));\n if (out > 1) add('I8', el, `${Math.round(out)}px outside the viewport`, out);\n }\n\n return { counts, findings, notes, viewport: [vw, vh] };\n}\n"]}
|
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
import { type ResolvedFonts, type ResolvedTheme } from './themeApi.ts';
|
|
2
|
+
import type { ThemeCatalog, ThemeChoice } from './themeChoice.ts';
|
|
3
|
+
import { type FontSpec, type ThemeSpec } from './themeSpec.ts';
|
|
4
|
+
/** A style rule as the engine reads it (CSSStyleRule, or a plain object in tests). */
|
|
5
|
+
export type RuleLike = {
|
|
6
|
+
selectorText: string;
|
|
7
|
+
style: {
|
|
8
|
+
getPropertyValue(name: string): string;
|
|
9
|
+
length?: number;
|
|
10
|
+
};
|
|
11
|
+
};
|
|
12
|
+
/** The font roles as the plugin API reports them in a site's page; an inheriting interface uses `siteStack` (the site's own font). */
|
|
13
|
+
export declare function resolvedFonts(font: FontSpec, siteStack: string): ResolvedFonts;
|
|
14
|
+
/**
|
|
15
|
+
* Every style rule of `doc`'s stylesheets (inside media/supports groups too), except `own`'s (the
|
|
16
|
+
* engine's own sheets: read as the site's, their radii and colors would be re-declared), each as it
|
|
17
|
+
* takes effect (`effectiveRule`). A `@supports` group the browser does not pass is left out.
|
|
18
|
+
*/
|
|
19
|
+
export declare function collectRules(doc: Document, own: HTMLStyleElement | null | ReadonlyArray<HTMLStyleElement | null>): RuleLike[];
|
|
20
|
+
type SheetLike = {
|
|
21
|
+
cssRules: CSSRuleList | ArrayLike<unknown>;
|
|
22
|
+
};
|
|
23
|
+
/**
|
|
24
|
+
* The same for an open shadow root the site renders a part of itself in (X's chat embed): its adopted
|
|
25
|
+
* sheets and its `<style>` elements, except the engine's own adopted `own` sheet.
|
|
26
|
+
*/
|
|
27
|
+
export declare function collectRootRules(root: {
|
|
28
|
+
adoptedStyleSheets?: readonly SheetLike[];
|
|
29
|
+
styleSheets?: ArrayLike<SheetLike>;
|
|
30
|
+
}, own: SheetLike | null, css?: {
|
|
31
|
+
supports?(condition: string): boolean;
|
|
32
|
+
}): RuleLike[];
|
|
33
|
+
/**
|
|
34
|
+
* The last theme CSS a tab showed, kept in the page's own storage so the next document paints it
|
|
35
|
+
* from its first frame: native code only hands the theme over once the page has finished loading,
|
|
36
|
+
* and the live CSS needs the site's rules, which it inserts while it renders. sessionStorage is per
|
|
37
|
+
* tab and survives reloads and navigations; localStorage (smaller cap: the site uses it too) is per
|
|
38
|
+
* account and covers a tab's first document.
|
|
39
|
+
*/
|
|
40
|
+
export type ThemeSnapshot = {
|
|
41
|
+
key: string;
|
|
42
|
+
choice: unknown;
|
|
43
|
+
css: string;
|
|
44
|
+
};
|
|
45
|
+
export declare const SNAPSHOT_SESSION_MAX = 1000000;
|
|
46
|
+
export declare const SNAPSHOT_LOCAL_MAX = 200000;
|
|
47
|
+
export type SnapshotStores = {
|
|
48
|
+
session?: Storage | null;
|
|
49
|
+
local?: Storage | null;
|
|
50
|
+
};
|
|
51
|
+
export declare function readSnapshot({ session, local }: SnapshotStores): ThemeSnapshot | null;
|
|
52
|
+
/** Stores `snapshot` (null clears it: the site's own look needs none), each store within its cap. */
|
|
53
|
+
export declare function writeSnapshot({ session, local }: SnapshotStores, snapshot: ThemeSnapshot | null): void;
|
|
54
|
+
/** What the engine needs to know about a site. `Mode` is the site's own color mode (X: light, dim, dark). */
|
|
55
|
+
export type ThemeRuntimeSite<Mode extends string = string> = {
|
|
56
|
+
/** The site's built-in themes (themeChoice.ts). */
|
|
57
|
+
catalog: ThemeCatalog;
|
|
58
|
+
/** The mode before the page has a body. */
|
|
59
|
+
initialMode: Mode;
|
|
60
|
+
/** The site's color mode as the page paints it now (read before the theme's own override: e.g. the body's inline style). */
|
|
61
|
+
readMode(win: Window): Mode;
|
|
62
|
+
/** The theme's CSS for the site's current `rules` (the engine's own sheet excluded) in `mode`; `vars` are `siteVars` as the site sets them. */
|
|
63
|
+
css(rules: RuleLike[], choice: ThemeChoice, mode: Mode, vars: Record<string, string>, flags: readonly string[]): string;
|
|
64
|
+
/** The active theme resolved for plugins and the UI kit (the site's own palette when the theme keeps its colors). */
|
|
65
|
+
resolved(choice: ThemeChoice, mode: Mode): ResolvedTheme;
|
|
66
|
+
/** Custom properties of the site's root read with the theme's sheet disabled (their unthemed values). */
|
|
67
|
+
siteVars?: readonly string[];
|
|
68
|
+
/**
|
|
69
|
+
* The theme's CSS that does not depend on the site's stylesheet: components, variants, decoration,
|
|
70
|
+
* icons. It lives in its own sheet (`staticId`), so the site inserting rules never rebuilds it; it is
|
|
71
|
+
* rebuilt when the theme or the site's mode changes and on `refresh()` (the owner's switches, the
|
|
72
|
+
* icon choice, the language).
|
|
73
|
+
*/
|
|
74
|
+
staticCss?(choice: ThemeChoice, mode: Mode): string;
|
|
75
|
+
/** Id of that sheet's `<style>` (default `wb-theme-static`). */
|
|
76
|
+
staticId?: string;
|
|
77
|
+
/** Id of the theme's `<style>` (default `wb-theme-css`). */
|
|
78
|
+
styleId?: string;
|
|
79
|
+
/** Name in console errors. */
|
|
80
|
+
name?: string;
|
|
81
|
+
/**
|
|
82
|
+
* Page states the theme's CSS keys on, as `html[data-wb-<name>]` attributes kept by the engine:
|
|
83
|
+
* set while `selector` matches in the page or one of its open shadow roots (domHub `shadowHosts`).
|
|
84
|
+
* A theme rule gated by `html[data-wb-chat]` costs nothing when the page changes; the same gate
|
|
85
|
+
* as `html:has(...)` makes the browser re-match the whole page on every insertion (seen on x.com:
|
|
86
|
+
* 10-100 ms per inserted node under a theme instead of 0.1 ms).
|
|
87
|
+
*/
|
|
88
|
+
flags?: Readonly<Record<string, string>>;
|
|
89
|
+
};
|
|
90
|
+
/** The attribute a page flag sets on `<html>`. */
|
|
91
|
+
export declare const flagAttribute: (name: string) => string;
|
|
92
|
+
/** Which of `flags` hold in `roots` now (pure, for tests). */
|
|
93
|
+
export declare function pageFlags(roots: ReadonlyArray<{
|
|
94
|
+
querySelector(selector: string): unknown;
|
|
95
|
+
}>, flags: Readonly<Record<string, string>>): string[];
|
|
96
|
+
export type ThemeHandle<Mode extends string = string> = {
|
|
97
|
+
apply(choice: unknown): void;
|
|
98
|
+
current(): ThemeChoice;
|
|
99
|
+
theme(): ThemeSpec;
|
|
100
|
+
/** The site's color mode the theme was last rendered for. */
|
|
101
|
+
mode(): Mode;
|
|
102
|
+
/** The active theme as values for plugins (`api.theme.current()`). */
|
|
103
|
+
resolved(): ResolvedTheme;
|
|
104
|
+
/** Calls `listener` after the theme or the site's color mode changes. */
|
|
105
|
+
onChange(listener: () => void): () => void;
|
|
106
|
+
/** Rebuilds the theme's CSS now: something it depends on besides the theme changed (the owner's switches, the icon choice). */
|
|
107
|
+
refresh(): void;
|
|
108
|
+
};
|
|
109
|
+
export type ThemeRuntimeOptions = {
|
|
110
|
+
loadFonts?(names: string[]): void;
|
|
111
|
+
};
|
|
112
|
+
/** Keeps the site's page in the owner's theme (see the top of this file). */
|
|
113
|
+
export declare function installThemeRuntime<Mode extends string>(win: Window, site: ThemeRuntimeSite<Mode>, options?: ThemeRuntimeOptions): ThemeHandle<Mode>;
|
|
114
|
+
export {};
|