waybetter 0.1.1 → 0.6.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 +140 -6
- package/bin/waybetter.mjs +46 -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/privacy.mjs +768 -0
- package/cli/release.mjs +444 -0
- package/cli/remote.mjs +260 -0
- package/cli/store.mjs +326 -0
- package/cli/strings.mjs +121 -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 +59 -0
- package/dist/runtime/stringPackTranslate.js +264 -0
- package/dist/runtime/stringPackTranslate.js.map +1 -0
- package/dist/runtime/stringPacks.d.ts +200 -0
- package/dist/runtime/stringPacks.js +474 -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/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 +463 -0
- package/dist/runtime/themeComponents.js.map +1 -0
- package/dist/runtime/themeDecor.d.ts +73 -0
- package/dist/runtime/themeDecor.js +131 -0
- package/dist/runtime/themeDecor.js.map +1 -0
- package/dist/runtime/themeDoctor.d.ts +11 -0
- package/dist/runtime/themeDoctor.js +51 -0
- package/dist/runtime/themeDoctor.js.map +1 -0
- package/dist/runtime/themeIcons.d.ts +130 -0
- package/dist/runtime/themeIcons.js +263 -0
- package/dist/runtime/themeIcons.js.map +1 -0
- package/dist/runtime/themeRuntime.d.ts +100 -0
- package/dist/runtime/themeRuntime.js +497 -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 +259 -0
- package/dist/runtime/themeSpec.js +439 -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 +170 -0
- package/dist/shell/InstallDialog.js.map +1 -0
- package/dist/shell/StoreView.d.ts +66 -0
- package/dist/shell/StoreView.js +103 -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 +21 -0
- package/dist/shell/frame/AppMenu.js +642 -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 +8 -0
- package/dist/shell/frame/Shell.js +1131 -0
- package/dist/shell/frame/Shell.js.map +1 -0
- package/dist/shell/frame/Titlebar.d.ts +16 -0
- package/dist/shell/frame/Titlebar.js +77 -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 +182 -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 +121 -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 +35 -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 +29 -0
- package/dist/shell/frame/chromeTheme.js +81 -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/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 +34 -0
- package/dist/shell/frame/mediaModel.js +53 -0
- package/dist/shell/frame/mediaModel.js.map +1 -0
- package/dist/shell/frame/menuMessages.en.json +54 -0
- package/dist/shell/frame/menuModel.d.ts +277 -0
- package/dist/shell/frame/menuModel.js +293 -0
- package/dist/shell/frame/menuModel.js.map +1 -0
- package/dist/shell/frame/paletteModel.d.ts +139 -0
- package/dist/shell/frame/paletteModel.js +112 -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 +629 -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 +99 -0
- package/dist/shell/frame/state.js +284 -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 +252 -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 +122 -0
- package/dist/shell/installController.js +146 -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 +256 -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 +116 -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 +6 -0
- package/dist/shell/panel/StoreSection.js +48 -0
- package/dist/shell/panel/StoreSection.js.map +1 -0
- package/dist/shell/panel/StringPacks.d.ts +11 -0
- package/dist/shell/panel/StringPacks.js +106 -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 +232 -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 +72 -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 +763 -0
- package/dist/shell/panel/panelMessages.js +767 -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 +230 -0
- package/dist/shell/storeMessages.d.ts +169 -0
- package/dist/shell/storeMessages.js +172 -0
- package/dist/shell/storeMessages.js.map +1 -0
- package/dist/shell/storeModel.d.ts +181 -0
- package/dist/shell/storeModel.js +133 -0
- package/dist/shell/storeModel.js.map +1 -0
- package/dist/shell/stringPacksModel.d.ts +44 -0
- package/dist/shell/stringPacksModel.js +94 -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 +646 -0
- package/languages.schema.json +23 -0
- package/locales/ar-x-fm.json +11 -0
- package/locales/ar.json +1281 -0
- package/locales/bg.json +1280 -0
- package/locales/bn.json +1280 -0
- package/locales/ca.json +1280 -0
- package/locales/cs.json +1280 -0
- package/locales/da.json +1280 -0
- package/locales/de.json +1280 -0
- package/locales/el.json +1280 -0
- package/locales/en-GB.json +27 -0
- package/locales/en.json +1280 -0
- package/locales/en.meta.json +51 -0
- package/locales/es.json +1280 -0
- package/locales/eu.json +1280 -0
- package/locales/fa.json +1281 -0
- package/locales/fi.json +1280 -0
- package/locales/fil.json +1280 -0
- package/locales/fr.json +1280 -0
- package/locales/ga.json +1280 -0
- package/locales/gl.json +1280 -0
- package/locales/gu.json +1280 -0
- package/locales/ha.json +1280 -0
- package/locales/he.json +1281 -0
- package/locales/hi.json +1280 -0
- package/locales/hr.json +1280 -0
- package/locales/hu.json +1279 -0
- package/locales/id.json +1280 -0
- package/locales/ig.json +1280 -0
- package/locales/it.json +1280 -0
- package/locales/ja.json +1280 -0
- package/locales/kn.json +1280 -0
- package/locales/ko.json +1280 -0
- package/locales/mr.json +1280 -0
- package/locales/ms.json +1280 -0
- package/locales/nb.json +1280 -0
- package/locales/nl.json +1280 -0
- package/locales/pl.json +1280 -0
- package/locales/pt.json +1280 -0
- package/locales/ro.json +1280 -0
- package/locales/ru.json +1280 -0
- package/locales/sk.json +1280 -0
- package/locales/sr.json +1280 -0
- package/locales/sv.json +1280 -0
- package/locales/ta.json +1280 -0
- package/locales/th.json +1280 -0
- package/locales/tr.json +1280 -0
- package/locales/uk.json +1280 -0
- package/locales/ur.json +1281 -0
- package/locales/vi.json +1280 -0
- package/locales/yo.json +1280 -0
- package/locales/zh-Hans.json +1280 -0
- package/locales/zh-Hant.json +1280 -0
- package/package.json +139 -5
- package/store-catalog.schema.json +65 -0
- package/theme.schema.json +4659 -0
- package/windows/installer.nsi +926 -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,84 @@
|
|
|
1
|
+
import { type EngineStats, type PackReport, type PageInventory, type StringEngine, type StringInventory } from './stringPacks.ts';
|
|
2
|
+
/** What an adapter reports to and asks from the framework. None of these throw. */
|
|
3
|
+
export type CatalogSink = {
|
|
4
|
+
/** A catalog file of this adapter was seen loading (whether or not the hook then matches). */
|
|
5
|
+
seen(group?: string): void;
|
|
6
|
+
/** The hook matched: the site is about to register values in `language`. */
|
|
7
|
+
matched(language: string, group?: string): void;
|
|
8
|
+
/** The value to register for `id`: a pack's, or exactly `original`. */
|
|
9
|
+
resolve(id: string, original: unknown): unknown;
|
|
10
|
+
};
|
|
11
|
+
export type CatalogHookAdapter = {
|
|
12
|
+
/** The catalog (key space) this adapter hooks; packs and the inventory name the same one. */
|
|
13
|
+
catalog: string;
|
|
14
|
+
/** Installs the hook at document start; returns its removal. Must not change the site's objects. */
|
|
15
|
+
install(win: Window, sink: CatalogSink): () => void;
|
|
16
|
+
};
|
|
17
|
+
export type CatalogSetup = {
|
|
18
|
+
adapter: CatalogHookAdapter;
|
|
19
|
+
inventory: StringInventory | PageInventory;
|
|
20
|
+
/** Pack documents in application order (a later one wins). Untrusted data: validated here. */
|
|
21
|
+
packs: readonly unknown[];
|
|
22
|
+
};
|
|
23
|
+
/**
|
|
24
|
+
* `ok`: the hook matched and keys went through it.
|
|
25
|
+
* `not-matched`: a catalog file was seen but the hook did not match it (the site changed).
|
|
26
|
+
* `no-catalog`: no catalog file was seen at all (another build of the site, or not loaded yet).
|
|
27
|
+
*/
|
|
28
|
+
export type HookStatus = 'pending' | 'ok' | 'not-matched' | 'no-catalog';
|
|
29
|
+
export type CatalogReport = {
|
|
30
|
+
catalog: string;
|
|
31
|
+
status: HookStatus;
|
|
32
|
+
/** Languages the site registered through the hook. */
|
|
33
|
+
languages: string[];
|
|
34
|
+
/** Catalog files seen, per group. */
|
|
35
|
+
seen: Record<string, number>;
|
|
36
|
+
packs: {
|
|
37
|
+
name: string;
|
|
38
|
+
language: string;
|
|
39
|
+
report: PackReport;
|
|
40
|
+
}[];
|
|
41
|
+
/** Pack documents that were refused as a whole. */
|
|
42
|
+
refused: string[];
|
|
43
|
+
engine: EngineStats;
|
|
44
|
+
};
|
|
45
|
+
export type StringPacksHandle = {
|
|
46
|
+
status(catalog?: string): HookStatus;
|
|
47
|
+
report(): CatalogReport[];
|
|
48
|
+
/** The engines, per catalog (the originals they keep are what a restore needs). */
|
|
49
|
+
engine(catalog: string): StringEngine | undefined;
|
|
50
|
+
dispose(): void;
|
|
51
|
+
};
|
|
52
|
+
export type StringPacksOptions = {
|
|
53
|
+
/** When the self-check decides (default 15 s after install). */
|
|
54
|
+
settleMs?: number;
|
|
55
|
+
/** Called once per catalog when its status is decided (`ok` as soon as it is reached). */
|
|
56
|
+
onStatus?: (report: CatalogReport) => void;
|
|
57
|
+
/**
|
|
58
|
+
* Translate mode: every value passes through here after the packs (the marker of
|
|
59
|
+
* stringPackTranslate.ts), and the catalog is hooked even without a usable pack.
|
|
60
|
+
*/
|
|
61
|
+
mark?: (id: string, value: unknown) => unknown;
|
|
62
|
+
};
|
|
63
|
+
/**
|
|
64
|
+
* Installs the adapters that have at least one usable pack. A catalog without packs is not hooked
|
|
65
|
+
* (the site runs untouched), so its status stays `pending`.
|
|
66
|
+
*/
|
|
67
|
+
export declare function installStringPacks(win: Window, setups: readonly CatalogSetup[], options?: StringPacksOptions): StringPacksHandle;
|
|
68
|
+
type Chunk = [unknown, Record<string, unknown> | unknown[], ...unknown[]];
|
|
69
|
+
/**
|
|
70
|
+
* Calls `onChunk(chunk, script)` for every chunk pushed onto `win[name]`, before the site's own
|
|
71
|
+
* `push` gets it; `script` is the URL of the script doing the push (`''` when unknown). Install at
|
|
72
|
+
* document start. The array and webpack's own `push` replacement keep working unchanged: the
|
|
73
|
+
* wrapper calls exactly the `push` that was current when it was read, with the same arguments. An
|
|
74
|
+
* exception in `onChunk` is swallowed. Returns the removal.
|
|
75
|
+
*/
|
|
76
|
+
export declare function watchChunkArray(win: object, name: string, onChunk: (chunk: Chunk, script: string) => void): () => void;
|
|
77
|
+
/**
|
|
78
|
+
* Wraps the module factories of one chunk so that what they `require` passes through `map`:
|
|
79
|
+
* `map(exports)` returns a replacement for that one call, or `undefined` to hand out the module's
|
|
80
|
+
* own exports. The module itself is never changed (return a shadow, e.g. `Object.create(exports)`).
|
|
81
|
+
* Only call this for a chunk you have identified; other chunks must stay untouched.
|
|
82
|
+
*/
|
|
83
|
+
export declare function mapChunkRequires(chunk: Chunk, map: (exports: unknown) => unknown): void;
|
|
84
|
+
export {};
|
|
@@ -0,0 +1,220 @@
|
|
|
1
|
+
// String packs in the page (published as `waybetter/runtime/stringPackHook`): the per-site
|
|
2
|
+
// "catalog hook adapter" interface, the installer that connects adapters to the engine of
|
|
3
|
+
// stringPacks.ts, a self-check that says when a hook did not match, and the generic half of a
|
|
4
|
+
// common hook point (a webpack chunk array).
|
|
5
|
+
//
|
|
6
|
+
// How a site hands its strings to its own code is that site's implementation detail, so the hook
|
|
7
|
+
// is an adapter the app supplies. One site can have several catalogs (different builds of the
|
|
8
|
+
// site, different key spaces); each gets its own adapter, inventory and packs.
|
|
9
|
+
//
|
|
10
|
+
// Everything here fails open: an exception inside a wrapper leaves the site's own behaviour as it
|
|
11
|
+
// was, and with no pack installed nothing is hooked at all.
|
|
12
|
+
import { compilePack, createStringEngine, } from "./stringPacks.js";
|
|
13
|
+
/**
|
|
14
|
+
* Installs the adapters that have at least one usable pack. A catalog without packs is not hooked
|
|
15
|
+
* (the site runs untouched), so its status stays `pending`.
|
|
16
|
+
*/
|
|
17
|
+
export function installStringPacks(win, setups, options = {}) {
|
|
18
|
+
const timers = win;
|
|
19
|
+
const states = setups.map(setup => {
|
|
20
|
+
const packs = [];
|
|
21
|
+
const refused = [];
|
|
22
|
+
for (const document of setup.packs) {
|
|
23
|
+
try {
|
|
24
|
+
packs.push(compilePack(document, setup.inventory));
|
|
25
|
+
}
|
|
26
|
+
catch (error) {
|
|
27
|
+
refused.push(error instanceof Error ? error.message : String(error));
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
const usable = packs.filter(pack => pack.values.size > 0);
|
|
31
|
+
return {
|
|
32
|
+
catalog: setup.adapter.catalog, adapter: setup.adapter, packs, refused, usable,
|
|
33
|
+
engine: usable.length || options.mark ? createStringEngine(setup.inventory, usable) : null,
|
|
34
|
+
seen: {}, languages: new Set(), keys: 0, settled: false, told: false,
|
|
35
|
+
remove: null,
|
|
36
|
+
};
|
|
37
|
+
});
|
|
38
|
+
const status = (state) => {
|
|
39
|
+
if (state.languages.size && state.keys > 0)
|
|
40
|
+
return 'ok';
|
|
41
|
+
if (!state.settled)
|
|
42
|
+
return 'pending';
|
|
43
|
+
return Object.keys(state.seen).length ? 'not-matched' : 'no-catalog';
|
|
44
|
+
};
|
|
45
|
+
const reportOf = (state) => ({
|
|
46
|
+
catalog: state.catalog,
|
|
47
|
+
status: status(state),
|
|
48
|
+
languages: [...state.languages],
|
|
49
|
+
seen: { ...state.seen },
|
|
50
|
+
packs: state.packs.map(pack => ({ name: pack.name, language: pack.language, report: pack.report })),
|
|
51
|
+
refused: [...state.refused],
|
|
52
|
+
engine: state.engine?.stats() ?? { seen: 0, applied: 0, unlisted: [], mismatched: [] },
|
|
53
|
+
});
|
|
54
|
+
const tell = (state) => {
|
|
55
|
+
if (state.told || status(state) === 'pending')
|
|
56
|
+
return;
|
|
57
|
+
state.told = true;
|
|
58
|
+
try {
|
|
59
|
+
options.onStatus?.(reportOf(state));
|
|
60
|
+
}
|
|
61
|
+
catch { /* a reporter must not break the page */ }
|
|
62
|
+
};
|
|
63
|
+
for (const state of states) {
|
|
64
|
+
const engine = state.engine;
|
|
65
|
+
if (!engine)
|
|
66
|
+
continue;
|
|
67
|
+
const sink = {
|
|
68
|
+
seen(group = 'main') { state.seen[group] = (state.seen[group] ?? 0) + 1; },
|
|
69
|
+
matched(language) { state.languages.add(String(language)); },
|
|
70
|
+
resolve(id, original) {
|
|
71
|
+
try {
|
|
72
|
+
state.keys += 1;
|
|
73
|
+
const resolved = engine.resolve(id, original);
|
|
74
|
+
const value = options.mark ? options.mark(id, resolved) : resolved;
|
|
75
|
+
if (state.keys === 1)
|
|
76
|
+
tell(state);
|
|
77
|
+
return value;
|
|
78
|
+
}
|
|
79
|
+
catch {
|
|
80
|
+
return original;
|
|
81
|
+
}
|
|
82
|
+
},
|
|
83
|
+
};
|
|
84
|
+
try {
|
|
85
|
+
state.remove = state.adapter.install(win, sink);
|
|
86
|
+
}
|
|
87
|
+
catch {
|
|
88
|
+
state.remove = null;
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
const hooked = states.filter(state => state.engine);
|
|
92
|
+
const timer = hooked.length
|
|
93
|
+
? timers.setTimeout(() => { for (const state of hooked) {
|
|
94
|
+
state.settled = true;
|
|
95
|
+
tell(state);
|
|
96
|
+
} }, options.settleMs ?? 15000)
|
|
97
|
+
: null;
|
|
98
|
+
return {
|
|
99
|
+
status: catalog => {
|
|
100
|
+
const state = catalog ? states.find(item => item.catalog === catalog) : hooked[0] ?? states[0];
|
|
101
|
+
return state ? status(state) : 'pending';
|
|
102
|
+
},
|
|
103
|
+
report: () => states.map(reportOf),
|
|
104
|
+
engine: catalog => states.find(item => item.catalog === catalog)?.engine ?? undefined,
|
|
105
|
+
dispose() {
|
|
106
|
+
if (timer !== null)
|
|
107
|
+
timers.clearTimeout(timer);
|
|
108
|
+
for (const state of states) {
|
|
109
|
+
try {
|
|
110
|
+
state.remove?.();
|
|
111
|
+
}
|
|
112
|
+
catch { /* the hook is gone either way */ }
|
|
113
|
+
state.remove = null;
|
|
114
|
+
}
|
|
115
|
+
},
|
|
116
|
+
};
|
|
117
|
+
}
|
|
118
|
+
/**
|
|
119
|
+
* Calls `onChunk(chunk, script)` for every chunk pushed onto `win[name]`, before the site's own
|
|
120
|
+
* `push` gets it; `script` is the URL of the script doing the push (`''` when unknown). Install at
|
|
121
|
+
* document start. The array and webpack's own `push` replacement keep working unchanged: the
|
|
122
|
+
* wrapper calls exactly the `push` that was current when it was read, with the same arguments. An
|
|
123
|
+
* exception in `onChunk` is swallowed. Returns the removal.
|
|
124
|
+
*/
|
|
125
|
+
export function watchChunkArray(win, name, onChunk) {
|
|
126
|
+
const holder = win;
|
|
127
|
+
const existing = holder[name];
|
|
128
|
+
const array = Array.isArray(existing) ? existing : [];
|
|
129
|
+
if (!Array.isArray(existing))
|
|
130
|
+
holder[name] = array;
|
|
131
|
+
const done = new WeakSet();
|
|
132
|
+
let current = array.push;
|
|
133
|
+
let active = true;
|
|
134
|
+
const look = (items) => {
|
|
135
|
+
if (!active)
|
|
136
|
+
return;
|
|
137
|
+
for (let index = 0; index < items.length; index += 1) {
|
|
138
|
+
const chunk = items[index];
|
|
139
|
+
if (typeof chunk !== 'object' || chunk === null || done.has(chunk))
|
|
140
|
+
continue;
|
|
141
|
+
done.add(chunk);
|
|
142
|
+
try {
|
|
143
|
+
onChunk(chunk, holder.document?.currentScript?.src ?? '');
|
|
144
|
+
}
|
|
145
|
+
catch {
|
|
146
|
+
// Fail open: the chunk goes on to the site exactly as it came.
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
};
|
|
150
|
+
try {
|
|
151
|
+
Object.defineProperty(array, 'push', {
|
|
152
|
+
configurable: true,
|
|
153
|
+
enumerable: false,
|
|
154
|
+
get() {
|
|
155
|
+
const target = current;
|
|
156
|
+
return function push(...items) {
|
|
157
|
+
look(items);
|
|
158
|
+
return target.apply(this, items);
|
|
159
|
+
};
|
|
160
|
+
},
|
|
161
|
+
set(next) { current = next; },
|
|
162
|
+
});
|
|
163
|
+
}
|
|
164
|
+
catch {
|
|
165
|
+
return () => { };
|
|
166
|
+
}
|
|
167
|
+
return () => {
|
|
168
|
+
active = false;
|
|
169
|
+
try {
|
|
170
|
+
if (current === Array.prototype.push)
|
|
171
|
+
delete array.push;
|
|
172
|
+
else
|
|
173
|
+
Object.defineProperty(array, 'push', { configurable: true, enumerable: false, writable: true, value: current });
|
|
174
|
+
}
|
|
175
|
+
catch {
|
|
176
|
+
// Left as the pass-through wrapper.
|
|
177
|
+
}
|
|
178
|
+
};
|
|
179
|
+
}
|
|
180
|
+
/**
|
|
181
|
+
* Wraps the module factories of one chunk so that what they `require` passes through `map`:
|
|
182
|
+
* `map(exports)` returns a replacement for that one call, or `undefined` to hand out the module's
|
|
183
|
+
* own exports. The module itself is never changed (return a shadow, e.g. `Object.create(exports)`).
|
|
184
|
+
* Only call this for a chunk you have identified; other chunks must stay untouched.
|
|
185
|
+
*/
|
|
186
|
+
export function mapChunkRequires(chunk, map) {
|
|
187
|
+
const modules = chunk[1];
|
|
188
|
+
if (typeof modules !== 'object' || modules === null)
|
|
189
|
+
return;
|
|
190
|
+
const table = modules;
|
|
191
|
+
for (const id of Object.keys(table)) {
|
|
192
|
+
const factory = table[id];
|
|
193
|
+
if (typeof factory !== 'function')
|
|
194
|
+
continue;
|
|
195
|
+
table[id] = function (module, exports, require, ...rest) {
|
|
196
|
+
let through = require;
|
|
197
|
+
if (typeof require === 'function') {
|
|
198
|
+
try {
|
|
199
|
+
through = new Proxy(require, {
|
|
200
|
+
apply(target, self, args) {
|
|
201
|
+
const result = Reflect.apply(target, self, args);
|
|
202
|
+
try {
|
|
203
|
+
const replaced = map(result);
|
|
204
|
+
return replaced === undefined ? result : replaced;
|
|
205
|
+
}
|
|
206
|
+
catch {
|
|
207
|
+
return result;
|
|
208
|
+
}
|
|
209
|
+
},
|
|
210
|
+
});
|
|
211
|
+
}
|
|
212
|
+
catch {
|
|
213
|
+
through = require;
|
|
214
|
+
}
|
|
215
|
+
}
|
|
216
|
+
return factory.call(this, module, exports, through, ...rest);
|
|
217
|
+
};
|
|
218
|
+
}
|
|
219
|
+
}
|
|
220
|
+
//# sourceMappingURL=stringPackHook.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"stringPackHook.js","sourceRoot":"","sources":["../../../runtime/src/stringPackHook.ts"],"names":[],"mappings":"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","sourcesContent":["// String packs in the page (published as `waybetter/runtime/stringPackHook`): the per-site\n// \"catalog hook adapter\" interface, the installer that connects adapters to the engine of\n// stringPacks.ts, a self-check that says when a hook did not match, and the generic half of a\n// common hook point (a webpack chunk array).\n//\n// How a site hands its strings to its own code is that site's implementation detail, so the hook\n// is an adapter the app supplies. One site can have several catalogs (different builds of the\n// site, different key spaces); each gets its own adapter, inventory and packs.\n//\n// Everything here fails open: an exception inside a wrapper leaves the site's own behaviour as it\n// was, and with no pack installed nothing is hooked at all.\nimport {\n compilePack, createStringEngine, type CompiledPack, type EngineStats, type PackReport, type PageInventory, type StringEngine,\n type StringInventory,\n} from './stringPacks.ts';\n\n// -------------------------------------------------------------------------------------------\n// The adapter interface\n\n/** What an adapter reports to and asks from the framework. None of these throw. */\nexport type CatalogSink = {\n /** A catalog file of this adapter was seen loading (whether or not the hook then matches). */\n seen(group?: string): void;\n /** The hook matched: the site is about to register values in `language`. */\n matched(language: string, group?: string): void;\n /** The value to register for `id`: a pack's, or exactly `original`. */\n resolve(id: string, original: unknown): unknown;\n};\n\nexport type CatalogHookAdapter = {\n /** The catalog (key space) this adapter hooks; packs and the inventory name the same one. */\n catalog: string;\n /** Installs the hook at document start; returns its removal. Must not change the site's objects. */\n install(win: Window, sink: CatalogSink): () => void;\n};\n\nexport type CatalogSetup = {\n adapter: CatalogHookAdapter;\n inventory: StringInventory | PageInventory;\n /** Pack documents in application order (a later one wins). Untrusted data: validated here. */\n packs: readonly unknown[];\n};\n\n/**\n * `ok`: the hook matched and keys went through it.\n * `not-matched`: a catalog file was seen but the hook did not match it (the site changed).\n * `no-catalog`: no catalog file was seen at all (another build of the site, or not loaded yet).\n */\nexport type HookStatus = 'pending' | 'ok' | 'not-matched' | 'no-catalog';\n\nexport type CatalogReport = {\n catalog: string;\n status: HookStatus;\n /** Languages the site registered through the hook. */\n languages: string[];\n /** Catalog files seen, per group. */\n seen: Record<string, number>;\n packs: { name: string; language: string; report: PackReport }[];\n /** Pack documents that were refused as a whole. */\n refused: string[];\n engine: EngineStats;\n};\n\nexport type StringPacksHandle = {\n status(catalog?: string): HookStatus;\n report(): CatalogReport[];\n /** The engines, per catalog (the originals they keep are what a restore needs). */\n engine(catalog: string): StringEngine | undefined;\n dispose(): void;\n};\n\nexport type StringPacksOptions = {\n /** When the self-check decides (default 15 s after install). */\n settleMs?: number;\n /** Called once per catalog when its status is decided (`ok` as soon as it is reached). */\n onStatus?: (report: CatalogReport) => void;\n /**\n * Translate mode: every value passes through here after the packs (the marker of\n * stringPackTranslate.ts), and the catalog is hooked even without a usable pack.\n */\n mark?: (id: string, value: unknown) => unknown;\n};\n\ntype TimerWindow = { setTimeout(handler: () => void, ms: number): unknown; clearTimeout(id: never): void };\n\n/**\n * Installs the adapters that have at least one usable pack. A catalog without packs is not hooked\n * (the site runs untouched), so its status stays `pending`.\n */\nexport function installStringPacks(win: Window, setups: readonly CatalogSetup[], options: StringPacksOptions = {}): StringPacksHandle {\n const timers = win as unknown as TimerWindow;\n const states = setups.map(setup => {\n const packs: CompiledPack[] = [];\n const refused: string[] = [];\n for (const document of setup.packs) {\n try {\n packs.push(compilePack(document, setup.inventory));\n } catch (error) {\n refused.push(error instanceof Error ? error.message : String(error));\n }\n }\n const usable = packs.filter(pack => pack.values.size > 0);\n return {\n catalog: setup.adapter.catalog, adapter: setup.adapter, packs, refused, usable,\n engine: usable.length || options.mark ? createStringEngine(setup.inventory, usable) : null,\n seen: {} as Record<string, number>, languages: new Set<string>(), keys: 0, settled: false, told: false,\n remove: null as null | (() => void),\n };\n });\n type State = (typeof states)[number];\n\n const status = (state: State): HookStatus => {\n if (state.languages.size && state.keys > 0) return 'ok';\n if (!state.settled) return 'pending';\n return Object.keys(state.seen).length ? 'not-matched' : 'no-catalog';\n };\n const reportOf = (state: State): CatalogReport => ({\n catalog: state.catalog,\n status: status(state),\n languages: [...state.languages],\n seen: { ...state.seen },\n packs: state.packs.map(pack => ({ name: pack.name, language: pack.language, report: pack.report })),\n refused: [...state.refused],\n engine: state.engine?.stats() ?? { seen: 0, applied: 0, unlisted: [], mismatched: [] },\n });\n const tell = (state: State) => {\n if (state.told || status(state) === 'pending') return;\n state.told = true;\n try { options.onStatus?.(reportOf(state)); } catch { /* a reporter must not break the page */ }\n };\n\n for (const state of states) {\n const engine = state.engine;\n if (!engine) continue;\n const sink: CatalogSink = {\n seen(group = 'main') { state.seen[group] = (state.seen[group] ?? 0) + 1; },\n matched(language) { state.languages.add(String(language)); },\n resolve(id, original) {\n try {\n state.keys += 1;\n const resolved = engine.resolve(id, original);\n const value = options.mark ? options.mark(id, resolved) : resolved;\n if (state.keys === 1) tell(state);\n return value;\n } catch {\n return original;\n }\n },\n };\n try {\n state.remove = state.adapter.install(win, sink);\n } catch {\n state.remove = null;\n }\n }\n\n const hooked = states.filter(state => state.engine);\n const timer = hooked.length\n ? timers.setTimeout(() => { for (const state of hooked) { state.settled = true; tell(state); } }, options.settleMs ?? 15000)\n : null;\n\n return {\n status: catalog => {\n const state = catalog ? states.find(item => item.catalog === catalog) : hooked[0] ?? states[0];\n return state ? status(state) : 'pending';\n },\n report: () => states.map(reportOf),\n engine: catalog => states.find(item => item.catalog === catalog)?.engine ?? undefined,\n dispose() {\n if (timer !== null) timers.clearTimeout(timer as never);\n for (const state of states) {\n try { state.remove?.(); } catch { /* the hook is gone either way */ }\n state.remove = null;\n }\n },\n };\n}\n\n// -------------------------------------------------------------------------------------------\n// A webpack chunk array as the hook point\n//\n// A webpack site loads its code as chunks pushed onto a global array\n// (`(globalThis.webpackChunk_x ||= []).push([ids, modules, runtime?])`); webpack's runtime later\n// replaces the array's `push` with its own and replays what is already there. Watching the array\n// therefore sees every chunk before its modules are installed, whichever loads first.\n\ntype Chunk = [unknown, Record<string, unknown> | unknown[], ...unknown[]];\n\n/**\n * Calls `onChunk(chunk, script)` for every chunk pushed onto `win[name]`, before the site's own\n * `push` gets it; `script` is the URL of the script doing the push (`''` when unknown). Install at\n * document start. The array and webpack's own `push` replacement keep working unchanged: the\n * wrapper calls exactly the `push` that was current when it was read, with the same arguments. An\n * exception in `onChunk` is swallowed. Returns the removal.\n */\nexport function watchChunkArray(win: object, name: string, onChunk: (chunk: Chunk, script: string) => void): () => void {\n const holder = win as Record<string, unknown> & { document?: { currentScript?: { src?: string } | null } };\n const existing = holder[name];\n const array: unknown[] = Array.isArray(existing) ? existing : [];\n if (!Array.isArray(existing)) holder[name] = array;\n const done = new WeakSet<object>();\n let current: (...items: unknown[]) => number = array.push;\n let active = true;\n const look = (items: ArrayLike<unknown>) => {\n if (!active) return;\n for (let index = 0; index < items.length; index += 1) {\n const chunk = items[index];\n if (typeof chunk !== 'object' || chunk === null || done.has(chunk)) continue;\n done.add(chunk);\n try {\n onChunk(chunk as Chunk, holder.document?.currentScript?.src ?? '');\n } catch {\n // Fail open: the chunk goes on to the site exactly as it came.\n }\n }\n };\n try {\n Object.defineProperty(array, 'push', {\n configurable: true,\n enumerable: false,\n get() {\n const target = current;\n return function push(this: unknown, ...items: unknown[]) {\n look(items);\n return target.apply(this, items);\n };\n },\n set(next: (...items: unknown[]) => number) { current = next; },\n });\n } catch {\n return () => {};\n }\n return () => {\n active = false;\n try {\n if (current === Array.prototype.push) delete (array as { push?: unknown }).push;\n else Object.defineProperty(array, 'push', { configurable: true, enumerable: false, writable: true, value: current });\n } catch {\n // Left as the pass-through wrapper.\n }\n };\n}\n\n/**\n * Wraps the module factories of one chunk so that what they `require` passes through `map`:\n * `map(exports)` returns a replacement for that one call, or `undefined` to hand out the module's\n * own exports. The module itself is never changed (return a shadow, e.g. `Object.create(exports)`).\n * Only call this for a chunk you have identified; other chunks must stay untouched.\n */\nexport function mapChunkRequires(chunk: Chunk, map: (exports: unknown) => unknown): void {\n const modules = chunk[1];\n if (typeof modules !== 'object' || modules === null) return;\n const table = modules as Record<string, unknown>;\n for (const id of Object.keys(table)) {\n const factory = table[id];\n if (typeof factory !== 'function') continue;\n table[id] = function (this: unknown, module: unknown, exports: unknown, require: unknown, ...rest: unknown[]) {\n let through = require;\n if (typeof require === 'function') {\n try {\n through = new Proxy(require, {\n apply(target, self, args) {\n const result = Reflect.apply(target as (...a: unknown[]) => unknown, self, args);\n try {\n const replaced = map(result);\n return replaced === undefined ? result : replaced;\n } catch {\n return result;\n }\n },\n });\n } catch {\n through = require;\n }\n }\n return (factory as (...a: unknown[]) => unknown).call(this, module, exports, through, ...rest);\n };\n }\n}\n"]}
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import { type InventoryLookup, type PageInventory, type StringPack } from './stringPacks.ts';
|
|
2
|
+
export type Marker = {
|
|
3
|
+
/** The value with its key's marker (strings, and functions whose result is a string). */
|
|
4
|
+
mark(id: string, value: unknown): unknown;
|
|
5
|
+
/** The keys marked in a text, in order. */
|
|
6
|
+
ids(text: string): string[];
|
|
7
|
+
/** The text without markers. */
|
|
8
|
+
strip(text: string): string;
|
|
9
|
+
};
|
|
10
|
+
export declare function createMarker(): Marker;
|
|
11
|
+
/** The author's edits in this tab. */
|
|
12
|
+
export type TranslateDraft = {
|
|
13
|
+
language: string;
|
|
14
|
+
name: string;
|
|
15
|
+
strings: Record<string, string>;
|
|
16
|
+
};
|
|
17
|
+
export declare const DRAFT_KEY = "wayBetter.translateDraft";
|
|
18
|
+
export declare function readDraft(storage: Pick<Storage, 'getItem'>): TranslateDraft | null;
|
|
19
|
+
/** The draft as a pack document for `site`/`catalog`. */
|
|
20
|
+
export declare function draftPack(draft: TranslateDraft, site: string, catalog: string): StringPack;
|
|
21
|
+
/** Checks one edit against the key's shape; `null` when it can be used. */
|
|
22
|
+
export declare function checkEdit(lookup: InventoryLookup, id: string, value: string): string | null;
|
|
23
|
+
export type TranslateWords = {
|
|
24
|
+
bar: string;
|
|
25
|
+
hint: string;
|
|
26
|
+
edits(count: number): string;
|
|
27
|
+
exportPack: string;
|
|
28
|
+
copied: string;
|
|
29
|
+
exit: string;
|
|
30
|
+
reload: string;
|
|
31
|
+
key: string;
|
|
32
|
+
original: string;
|
|
33
|
+
parameters: string;
|
|
34
|
+
save: string;
|
|
35
|
+
cancel: string;
|
|
36
|
+
remove: string;
|
|
37
|
+
notTranslatable: string;
|
|
38
|
+
choose: string;
|
|
39
|
+
};
|
|
40
|
+
/** English defaults (the app passes its own words). */
|
|
41
|
+
export declare const TRANSLATE_WORDS: TranslateWords;
|
|
42
|
+
export type TranslateUiOptions = {
|
|
43
|
+
inventory: PageInventory;
|
|
44
|
+
marker: Marker;
|
|
45
|
+
site: string;
|
|
46
|
+
catalog: string;
|
|
47
|
+
words?: Partial<TranslateWords>;
|
|
48
|
+
/** Leaves translate mode (the app drops the flag and reloads). */
|
|
49
|
+
exit(): void;
|
|
50
|
+
};
|
|
51
|
+
/**
|
|
52
|
+
* The page part of translate mode: a bar (edits, copy the pack file, leave) and an editor for the
|
|
53
|
+
* string under a click. Clicks on marked text are the editor's while the mode is on.
|
|
54
|
+
*/
|
|
55
|
+
export declare function installTranslateUi(win: Window, options: TranslateUiOptions): {
|
|
56
|
+
dispose(): void;
|
|
57
|
+
};
|
|
58
|
+
/** The draft as the last pack of a delivery (it applies over the others), when it has any string. */
|
|
59
|
+
export declare function withDraft(packs: readonly unknown[], storage: Pick<Storage, 'getItem'>, site: string, catalog: string, inventory: PageInventory): unknown[];
|
|
@@ -0,0 +1,264 @@
|
|
|
1
|
+
// Translate mode for string packs (published as `waybetter/runtime/stringPackTranslate`): the site's
|
|
2
|
+
// strings carry an invisible marker naming their key, so clicking a word on the page tells which
|
|
3
|
+
// key it is. The author types a replacement (checked with the pack rules right there), the edits
|
|
4
|
+
// collect in the tab as a draft pack that applies on the next reload, and Export copies the pack
|
|
5
|
+
// file. Nothing leaves the page; the draft lives in the tab's session storage.
|
|
6
|
+
//
|
|
7
|
+
// The markers change the site's text (invisible characters at the end of each string), so exact
|
|
8
|
+
// comparisons in the site's own code may notice: translate mode is for authors, never on by default,
|
|
9
|
+
// and leaving it reloads the page without markers.
|
|
10
|
+
import { compilePack, inventoryLookup, validateString } from "./stringPacks.js";
|
|
11
|
+
const START = '';
|
|
12
|
+
const DIGITS = ['', '', '', ''];
|
|
13
|
+
const MARKED = /([]+)/g;
|
|
14
|
+
export function createMarker() {
|
|
15
|
+
const ids = [];
|
|
16
|
+
const index = new Map();
|
|
17
|
+
const code = (id) => {
|
|
18
|
+
let n = index.get(id);
|
|
19
|
+
if (n === undefined) {
|
|
20
|
+
n = ids.length;
|
|
21
|
+
ids.push(id);
|
|
22
|
+
index.set(id, n);
|
|
23
|
+
}
|
|
24
|
+
let digits = '';
|
|
25
|
+
do {
|
|
26
|
+
digits = DIGITS[n % 4] + digits;
|
|
27
|
+
n = Math.floor(n / 4);
|
|
28
|
+
} while (n);
|
|
29
|
+
return START + digits + START;
|
|
30
|
+
};
|
|
31
|
+
return {
|
|
32
|
+
mark(id, value) {
|
|
33
|
+
if (typeof value === 'string')
|
|
34
|
+
return value + code(id);
|
|
35
|
+
if (typeof value === 'function') {
|
|
36
|
+
const original = value;
|
|
37
|
+
return function (...args) {
|
|
38
|
+
const out = original.apply(this, args);
|
|
39
|
+
return typeof out === 'string' ? out + code(id) : out;
|
|
40
|
+
};
|
|
41
|
+
}
|
|
42
|
+
return value;
|
|
43
|
+
},
|
|
44
|
+
ids(text) {
|
|
45
|
+
const out = [];
|
|
46
|
+
for (const match of text.matchAll(MARKED)) {
|
|
47
|
+
let n = 0;
|
|
48
|
+
for (const ch of match[1])
|
|
49
|
+
n = n * 4 + DIGITS.indexOf(ch);
|
|
50
|
+
const id = ids[n];
|
|
51
|
+
if (id && !out.includes(id))
|
|
52
|
+
out.push(id);
|
|
53
|
+
}
|
|
54
|
+
return out;
|
|
55
|
+
},
|
|
56
|
+
strip: text => text.replace(MARKED, ''),
|
|
57
|
+
};
|
|
58
|
+
}
|
|
59
|
+
export const DRAFT_KEY = 'wayBetter.translateDraft';
|
|
60
|
+
export function readDraft(storage) {
|
|
61
|
+
try {
|
|
62
|
+
const value = JSON.parse(storage.getItem(DRAFT_KEY) ?? 'null');
|
|
63
|
+
return value && typeof value === 'object' && typeof value.strings === 'object' && value.strings !== null ? value : null;
|
|
64
|
+
}
|
|
65
|
+
catch {
|
|
66
|
+
return null;
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
/** The draft as a pack document for `site`/`catalog`. */
|
|
70
|
+
export function draftPack(draft, site, catalog) {
|
|
71
|
+
return {
|
|
72
|
+
format: 1, site, catalog, language: draft.language || 'en-x-draft', name: draft.name || 'My strings', authors: ['Me'],
|
|
73
|
+
version: '0.1.0', strings: { ...draft.strings },
|
|
74
|
+
};
|
|
75
|
+
}
|
|
76
|
+
/** Checks one edit against the key's shape; `null` when it can be used. */
|
|
77
|
+
export function checkEdit(lookup, id, value) {
|
|
78
|
+
const shape = lookup(id);
|
|
79
|
+
if (!shape)
|
|
80
|
+
return 'this key is not in the inventory';
|
|
81
|
+
const result = validateString(shape, value);
|
|
82
|
+
return 'reason' in result ? result.reason : null;
|
|
83
|
+
}
|
|
84
|
+
/** English defaults (the app passes its own words). */
|
|
85
|
+
export const TRANSLATE_WORDS = {
|
|
86
|
+
bar: 'Translate mode', hint: 'Click a word to change it.', edits: count => `${count} ${count === 1 ? 'edit' : 'edits'}`,
|
|
87
|
+
exportPack: 'Copy pack file', copied: 'Pack file copied', exit: 'Leave', reload: 'Reload to see it',
|
|
88
|
+
key: 'Key', original: 'Now', parameters: 'Parameters', save: 'Save', cancel: 'Cancel', remove: 'Remove edit',
|
|
89
|
+
notTranslatable: 'This string cannot be changed by a pack yet.', choose: 'Which one?',
|
|
90
|
+
};
|
|
91
|
+
const CSS = `
|
|
92
|
+
:host { all: initial; }
|
|
93
|
+
.bar { position: fixed; left: 50%; bottom: 16px; transform: translateX(-50%); z-index: 2147483646; display: flex; gap: 10px; align-items: center;
|
|
94
|
+
padding: 8px 12px; border-radius: 12px; background: #111827; color: #f9fafb; font: 13px/1.3 system-ui, sans-serif; box-shadow: 0 8px 24px rgba(0,0,0,.35); }
|
|
95
|
+
.bar b { font-weight: 600; } .bar span { color: #cbd5e1; }
|
|
96
|
+
button { font: inherit; border: 0; border-radius: 8px; padding: 6px 10px; cursor: pointer; background: #334155; color: #f9fafb; }
|
|
97
|
+
button.primary { background: #2563eb; }
|
|
98
|
+
.pop { position: fixed; z-index: 2147483647; width: 360px; max-width: calc(100vw - 24px); padding: 12px; border-radius: 12px; background: #fff; color: #111827;
|
|
99
|
+
font: 13px/1.4 system-ui, sans-serif; box-shadow: 0 12px 32px rgba(0,0,0,.3); display: grid; gap: 8px; }
|
|
100
|
+
.pop small { color: #475569; } .pop code { font-size: 12px; color: #334155; }
|
|
101
|
+
.pop textarea { width: 100%; box-sizing: border-box; min-height: 64px; font: inherit; padding: 6px; border: 1px solid #cbd5e1; border-radius: 8px; }
|
|
102
|
+
.pop .row { display: flex; gap: 8px; justify-content: flex-end; } .pop .err { color: #b91c1c; }
|
|
103
|
+
.pop .pick { display: grid; gap: 4px; } .pop .pick button { text-align: left; background: #e2e8f0; color: #111827; }
|
|
104
|
+
`;
|
|
105
|
+
/**
|
|
106
|
+
* The page part of translate mode: a bar (edits, copy the pack file, leave) and an editor for the
|
|
107
|
+
* string under a click. Clicks on marked text are the editor's while the mode is on.
|
|
108
|
+
*/
|
|
109
|
+
export function installTranslateUi(win, options) {
|
|
110
|
+
const doc = win.document;
|
|
111
|
+
const words = { ...TRANSLATE_WORDS, ...options.words };
|
|
112
|
+
const lookup = inventoryLookup(options.inventory);
|
|
113
|
+
const storage = win.sessionStorage;
|
|
114
|
+
const draft = () => readDraft(storage) ?? { language: '', name: '', strings: {} };
|
|
115
|
+
const save = (next) => { try {
|
|
116
|
+
storage.setItem(DRAFT_KEY, JSON.stringify(next));
|
|
117
|
+
}
|
|
118
|
+
catch { /* storage full or blocked */ } };
|
|
119
|
+
const host = doc.createElement('wb-translate');
|
|
120
|
+
const root = host.attachShadow({ mode: 'open' });
|
|
121
|
+
const style = doc.createElement('style');
|
|
122
|
+
style.textContent = CSS;
|
|
123
|
+
root.append(style);
|
|
124
|
+
const bar = doc.createElement('div');
|
|
125
|
+
bar.className = 'bar';
|
|
126
|
+
root.append(bar);
|
|
127
|
+
let pop = null;
|
|
128
|
+
let changed = false;
|
|
129
|
+
const button = (label, onClick, primary = false) => {
|
|
130
|
+
const el = doc.createElement('button');
|
|
131
|
+
el.textContent = label;
|
|
132
|
+
if (primary)
|
|
133
|
+
el.className = 'primary';
|
|
134
|
+
el.addEventListener('click', event => { event.preventDefault(); event.stopPropagation(); onClick(); });
|
|
135
|
+
return el;
|
|
136
|
+
};
|
|
137
|
+
const renderBar = () => {
|
|
138
|
+
bar.replaceChildren();
|
|
139
|
+
const title = doc.createElement('b');
|
|
140
|
+
title.textContent = words.bar;
|
|
141
|
+
const hint = doc.createElement('span');
|
|
142
|
+
hint.textContent = `${words.hint} · ${words.edits(Object.keys(draft().strings).length)}`;
|
|
143
|
+
bar.append(title, hint);
|
|
144
|
+
if (changed)
|
|
145
|
+
bar.append(button(words.reload, () => win.location.reload(), true));
|
|
146
|
+
bar.append(button(words.exportPack, () => {
|
|
147
|
+
const text = JSON.stringify(draftPack(draft(), options.site, options.catalog), null, 2);
|
|
148
|
+
void win.navigator.clipboard?.writeText(text).then(() => { hint.textContent = words.copied; }).catch(() => { });
|
|
149
|
+
}));
|
|
150
|
+
bar.append(button(words.exit, options.exit));
|
|
151
|
+
};
|
|
152
|
+
const closePop = () => { pop?.remove(); pop = null; };
|
|
153
|
+
const edit = (id, x, y, now) => {
|
|
154
|
+
closePop();
|
|
155
|
+
pop = doc.createElement('div');
|
|
156
|
+
pop.className = 'pop';
|
|
157
|
+
pop.style.left = `${Math.max(12, Math.min(x, win.innerWidth - 372))}px`;
|
|
158
|
+
pop.style.top = `${Math.max(12, Math.min(y + 12, win.innerHeight - 260))}px`;
|
|
159
|
+
const shape = lookup(id);
|
|
160
|
+
const head = doc.createElement('small');
|
|
161
|
+
head.textContent = `${words.key}: `;
|
|
162
|
+
const code = doc.createElement('code');
|
|
163
|
+
code.textContent = id;
|
|
164
|
+
head.append(code);
|
|
165
|
+
const current = doc.createElement('div');
|
|
166
|
+
current.textContent = `${words.original}: ${now}`;
|
|
167
|
+
pop.append(head, current);
|
|
168
|
+
if (!shape || (shape.kind !== 'text' && shape.kind !== 'message')) {
|
|
169
|
+
const note = doc.createElement('div');
|
|
170
|
+
note.textContent = words.notTranslatable;
|
|
171
|
+
pop.append(note, button(words.cancel, closePop));
|
|
172
|
+
root.append(pop);
|
|
173
|
+
return;
|
|
174
|
+
}
|
|
175
|
+
if (shape.params?.length) {
|
|
176
|
+
const params = doc.createElement('small');
|
|
177
|
+
params.textContent = `${words.parameters}: ${shape.params.map(name => `{${name}}${shape.plural?.includes(name) ? ' (plural)' : ''}`).join(', ')}`;
|
|
178
|
+
pop.append(params);
|
|
179
|
+
}
|
|
180
|
+
const input = doc.createElement('textarea');
|
|
181
|
+
input.value = draft().strings[id] ?? now;
|
|
182
|
+
const error = doc.createElement('div');
|
|
183
|
+
error.className = 'err';
|
|
184
|
+
const row = doc.createElement('div');
|
|
185
|
+
row.className = 'row';
|
|
186
|
+
if (draft().strings[id] !== undefined) {
|
|
187
|
+
row.append(button(words.remove, () => { const next = draft(); delete next.strings[id]; save(next); changed = true; closePop(); renderBar(); }));
|
|
188
|
+
}
|
|
189
|
+
row.append(button(words.cancel, closePop), button(words.save, () => {
|
|
190
|
+
const value = input.value.trim();
|
|
191
|
+
const problem = checkEdit(lookup, id, value);
|
|
192
|
+
if (problem) {
|
|
193
|
+
error.textContent = problem;
|
|
194
|
+
return;
|
|
195
|
+
}
|
|
196
|
+
const next = draft();
|
|
197
|
+
next.strings[id] = value;
|
|
198
|
+
save(next);
|
|
199
|
+
changed = true;
|
|
200
|
+
closePop();
|
|
201
|
+
renderBar();
|
|
202
|
+
}, true));
|
|
203
|
+
pop.append(input, error, row);
|
|
204
|
+
root.append(pop);
|
|
205
|
+
input.focus();
|
|
206
|
+
};
|
|
207
|
+
/** The marked keys at a click: the element's own text and labels, then up to three parents. */
|
|
208
|
+
const keysAt = (target) => {
|
|
209
|
+
for (let el = target, depth = 0; el && depth < 4; el = el.parentElement, depth += 1) {
|
|
210
|
+
const texts = [el.textContent ?? '', el.getAttribute('aria-label') ?? '', el.getAttribute('placeholder') ?? '', el.getAttribute('title') ?? ''];
|
|
211
|
+
const found = texts.flatMap(text => options.marker.ids(text).map(id => ({ id, text: options.marker.strip(text) })));
|
|
212
|
+
if (found.length)
|
|
213
|
+
return found.filter((item, i) => found.findIndex(other => other.id === item.id) === i).slice(0, 8);
|
|
214
|
+
}
|
|
215
|
+
return [];
|
|
216
|
+
};
|
|
217
|
+
const onClick = (event) => {
|
|
218
|
+
if (event.composedPath().includes(host))
|
|
219
|
+
return;
|
|
220
|
+
const found = keysAt(event.target);
|
|
221
|
+
if (!found.length)
|
|
222
|
+
return;
|
|
223
|
+
event.preventDefault();
|
|
224
|
+
event.stopPropagation();
|
|
225
|
+
if (found.length === 1) {
|
|
226
|
+
edit(found[0].id, event.clientX, event.clientY, found[0].text);
|
|
227
|
+
return;
|
|
228
|
+
}
|
|
229
|
+
closePop();
|
|
230
|
+
pop = doc.createElement('div');
|
|
231
|
+
pop.className = 'pop';
|
|
232
|
+
pop.style.left = `${Math.max(12, Math.min(event.clientX, win.innerWidth - 372))}px`;
|
|
233
|
+
pop.style.top = `${Math.max(12, Math.min(event.clientY + 12, win.innerHeight - 260))}px`;
|
|
234
|
+
const pick = doc.createElement('div');
|
|
235
|
+
pick.className = 'pick';
|
|
236
|
+
const label = doc.createElement('small');
|
|
237
|
+
label.textContent = words.choose;
|
|
238
|
+
pick.append(label, ...found.map(item => button(`${item.text.slice(0, 60)} · ${item.id}`, () => edit(item.id, event.clientX, event.clientY, item.text))));
|
|
239
|
+
pop.append(pick, button(words.cancel, closePop));
|
|
240
|
+
root.append(pop);
|
|
241
|
+
};
|
|
242
|
+
const mount = () => { (doc.body ?? doc.documentElement).append(host); renderBar(); };
|
|
243
|
+
if (doc.body)
|
|
244
|
+
mount();
|
|
245
|
+
else
|
|
246
|
+
doc.addEventListener('DOMContentLoaded', mount, { once: true });
|
|
247
|
+
win.addEventListener('click', onClick, true);
|
|
248
|
+
return { dispose() { win.removeEventListener('click', onClick, true); host.remove(); } };
|
|
249
|
+
}
|
|
250
|
+
/** The draft as the last pack of a delivery (it applies over the others), when it has any string. */
|
|
251
|
+
export function withDraft(packs, storage, site, catalog, inventory) {
|
|
252
|
+
const draft = readDraft(storage);
|
|
253
|
+
if (!draft || !Object.keys(draft.strings).length)
|
|
254
|
+
return [...packs];
|
|
255
|
+
const pack = draftPack(draft, site, catalog);
|
|
256
|
+
try {
|
|
257
|
+
compilePack(pack, inventory);
|
|
258
|
+
}
|
|
259
|
+
catch {
|
|
260
|
+
return [...packs];
|
|
261
|
+
}
|
|
262
|
+
return [...packs, pack];
|
|
263
|
+
}
|
|
264
|
+
//# sourceMappingURL=stringPackTranslate.js.map
|