hotkey-router 0.2.2 → 0.3.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/ADDITIONAL_TERMS.md +122 -122
- package/LICENSE +694 -694
- package/README.md +103 -3
- package/data/browser-hotkeys.json +349 -349
- package/data/site-hotkeys.json +4571 -0
- package/data/site-hotkeys.runtime.json +1 -0
- package/dist/auto.js +57 -8
- package/dist/auto.js.map +2 -2
- package/dist/auto.min.js +2 -2
- package/dist/hotkey-router.cjs +60 -9
- package/dist/hotkey-router.cjs.map +2 -2
- package/dist/hotkey-router.js +60 -9
- package/dist/hotkey-router.js.map +2 -2
- package/dist/hotkey-router.min.js +2 -2
- package/dist/reservations.js +1 -1
- package/dist/reservations.js.map +1 -1
- package/dist/sites.js +185 -0
- package/dist/sites.js.map +7 -0
- package/dist/types/auto.d.ts +2 -0
- package/dist/types/hotkey-router.d.ts +196 -0
- package/dist/types/reservations.d.ts +80 -0
- package/dist/types/sites.d.ts +109 -0
- package/dist/types/validate.d.ts +42 -0
- package/dist/validate.js +106 -0
- package/dist/validate.js.map +7 -0
- package/package.json +18 -7
- package/robots.txt +79 -79
package/dist/reservations.js.map
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../data/browser-hotkeys.json", "../reservations.js"],
|
|
4
|
-
"sourcesContent": ["{\n \"$comment\": \"Machine-readable companion to docs/browser-hotkeys.md. Each combo entry describes who claims the binding and how strongly. Intended for runtime conflict warnings in keyboard-routing libraries (e.g. hotkey-router) and dev-time validation in apps like WebRadar. Update both this file and the markdown together \u2014 the markdown is the human source of truth, this file is the machine projection.\",\n \"version\": {\n \"generated\": \"2026-05-17\",\n \"schema\": \"1.0\",\n \"sources\": [\n \"https://support.mozilla.org/en-US/kb/keyboard-shortcuts-perform-firefox-tasks-quickly\",\n \"https://firefox-source-docs.mozilla.org/devtools-user/keyboard_shortcuts/index.html\",\n \"https://support.google.com/chrome/answer/157179\",\n \"https://developer.chrome.com/docs/devtools/shortcuts\",\n \"https://support.apple.com/guide/safari/keyboard-shortcuts-and-gestures-cpsh003/mac\",\n \"https://developer.apple.com/documentation/safari-developer-tools/web-inspector\",\n \"https://support.microsoft.com/en-us/microsoft-edge/keyboard-shortcuts-in-microsoft-edge-50d3edab-30d9-c7e4-21ce-37fe2713cfad\",\n \"https://support.apple.com/en-us/102650\",\n \"https://support.microsoft.com/en-us/windows/keyboard-shortcuts-in-windows-dcc61a57-8ff0-cffe-9796-cb9706c75eec\",\n \"https://help.gnome.org/gnome-help/shell-keyboard-shortcuts.html\"\n ]\n },\n \"severityLevels\": {\n \"hard\": \"Browser or OS intercepts before page-world keydown fires. preventDefault() can't recover it.\",\n \"find-bar-only\": \"Reserved only when the browser's find bar has focus. Fires in page world during normal browsing.\",\n \"menu-activation\": \"Win/Linux Alt+letter activates the browser menu bar. Hard to suppress reliably.\",\n \"system-text\": \"Only reserved while a text input has focus (terminal-style cursor controls on macOS).\",\n \"compose\": \"macOS Option+letter types a special character in text inputs. Outside inputs, free for page world.\",\n \"os\": \"Operating system intercepts globally, before any application sees it.\",\n \"devtools-open\": \"Only relevant when DevTools is already open; outside DevTools it fires normally.\"\n },\n \"$keyFormat\": \"Each combo key uses hotkey-router-compatible syntax: modifiers in canonical order (ctrl|meta|alt|shift) joined by '+', then the key (lowercased letter, or symbolic name). Per-platform tables use the platform's native modifier name \u2014 `meta` on macOS = Cmd, `meta` on Windows = Win, `ctrl` on Linux/Windows = the primary modifier.\",\n \"platforms\": {\n \"mac\": {\n \"browsers\": {\n \"firefox\": {\n \"meta+a\": { \"action\": \"Select all\", \"severity\": \"hard\" },\n \"meta+b\": { \"action\": \"Bookmarks sidebar\", \"severity\": \"hard\" },\n \"meta+c\": { \"action\": \"Copy\", \"severity\": \"hard\" },\n \"meta+d\": { \"action\": \"Bookmark this page\", \"severity\": \"hard\" },\n \"meta+e\": { \"action\": \"Search from page\", \"severity\": \"hard\" },\n \"meta+f\": { \"action\": \"Find in page\", \"severity\": \"hard\" },\n \"meta+g\": { \"action\": \"Find next\", \"severity\": \"hard\" },\n \"meta+j\": { \"action\": \"Downloads\", \"severity\": \"hard\" },\n \"meta+l\": { \"action\": \"Focus address bar\", \"severity\": \"hard\" },\n \"meta+n\": { \"action\": \"New window\", \"severity\": \"hard\" },\n \"meta+o\": { \"action\": \"Open file\", \"severity\": \"hard\" },\n \"meta+p\": { \"action\": \"Print\", \"severity\": \"hard\" },\n \"meta+r\": { \"action\": \"Reload\", \"severity\": \"hard\" },\n \"meta+s\": { \"action\": \"Save page\", \"severity\": \"hard\" },\n \"meta+t\": { \"action\": \"New tab\", \"severity\": \"hard\" },\n \"meta+u\": { \"action\": \"View source\", \"severity\": \"hard\" },\n \"meta+v\": { \"action\": \"Paste\", \"severity\": \"hard\" },\n \"meta+w\": { \"action\": \"Close tab\", \"severity\": \"hard\" },\n \"meta+x\": { \"action\": \"Cut\", \"severity\": \"hard\" },\n \"meta+y\": { \"action\": \"Redo\", \"severity\": \"hard\" },\n \"meta+z\": { \"action\": \"Undo\", \"severity\": \"hard\" },\n \"meta+shift+a\": { \"action\": \"Add-ons manager\", \"severity\": \"hard\" },\n \"meta+shift+b\": { \"action\": \"Bookmarks toolbar\", \"severity\": \"hard\" },\n \"meta+shift+c\": { \"action\": \"Inspector (element picker)\", \"severity\": \"hard\" },\n \"meta+shift+d\": { \"action\": \"Bookmark all tabs\", \"severity\": \"hard\" },\n \"meta+shift+e\": { \"action\": \"Network Monitor\", \"severity\": \"hard\" },\n \"meta+shift+f\": { \"action\": \"Toggle fullscreen\", \"severity\": \"hard\" },\n \"meta+shift+g\": { \"action\": \"Find previous\", \"severity\": \"find-bar-only\" },\n \"meta+shift+j\": { \"action\": \"Browser Console\", \"severity\": \"hard\" },\n \"meta+shift+n\": { \"action\": \"New private window\", \"severity\": \"hard\" },\n \"meta+shift+o\": { \"action\": \"Bookmarks library\", \"severity\": \"hard\" },\n \"meta+shift+p\": { \"action\": \"New private window (alt)\", \"severity\": \"hard\" },\n \"meta+shift+q\": { \"action\": \"Quit (with confirm)\", \"severity\": \"hard\" },\n \"meta+shift+s\": { \"action\": \"Firefox Screenshot\", \"severity\": \"hard\" },\n \"meta+shift+t\": { \"action\": \"Reopen closed tab\", \"severity\": \"hard\" },\n \"meta+shift+v\": { \"action\": \"Paste as plain text\", \"severity\": \"hard\" },\n \"meta+shift+w\": { \"action\": \"Close window\", \"severity\": \"hard\" },\n \"meta+shift+z\": { \"action\": \"Redo\", \"severity\": \"hard\" },\n \"meta+alt+c\": { \"action\": \"Inspector\", \"severity\": \"hard\" },\n \"meta+alt+e\": { \"action\": \"Network Monitor\", \"severity\": \"hard\" },\n \"meta+alt+i\": { \"action\": \"DevTools Toolbox\", \"severity\": \"hard\" },\n \"meta+alt+j\": { \"action\": \"Browser Console\", \"severity\": \"hard\" },\n \"meta+alt+k\": { \"action\": \"Web Console\", \"severity\": \"hard\" },\n \"meta+alt+m\": { \"action\": \"Responsive Design Mode\", \"severity\": \"hard\" },\n \"meta+alt+z\": { \"action\": \"Debugger\", \"severity\": \"hard\" }\n },\n \"chrome\": {\n \"meta+a\": { \"action\": \"Select all\", \"severity\": \"hard\" },\n \"meta+c\": { \"action\": \"Copy\", \"severity\": \"hard\" },\n \"meta+d\": { \"action\": \"Bookmark this page\", \"severity\": \"hard\" },\n \"meta+e\": { \"action\": \"Search selected text\", \"severity\": \"find-bar-only\" },\n \"meta+f\": { \"action\": \"Find in page\", \"severity\": \"hard\" },\n \"meta+g\": { \"action\": \"Find next\", \"severity\": \"hard\" },\n \"meta+l\": { \"action\": \"Focus address bar\", \"severity\": \"hard\" },\n \"meta+n\": { \"action\": \"New window\", \"severity\": \"hard\" },\n \"meta+o\": { \"action\": \"Open file\", \"severity\": \"hard\" },\n \"meta+p\": { \"action\": \"Print\", \"severity\": \"hard\" },\n \"meta+r\": { \"action\": \"Reload\", \"severity\": \"hard\" },\n \"meta+s\": { \"action\": \"Save page\", \"severity\": \"hard\" },\n \"meta+t\": { \"action\": \"New tab\", \"severity\": \"hard\" },\n \"meta+v\": { \"action\": \"Paste\", \"severity\": \"hard\" },\n \"meta+w\": { \"action\": \"Close tab\", \"severity\": \"hard\" },\n \"meta+x\": { \"action\": \"Cut\", \"severity\": \"hard\" },\n \"meta+y\": { \"action\": \"History page\", \"severity\": \"hard\" },\n \"meta+z\": { \"action\": \"Undo\", \"severity\": \"hard\" },\n \"meta+shift+b\": { \"action\": \"Bookmarks bar toggle\", \"severity\": \"hard\" },\n \"meta+shift+c\": { \"action\": \"DevTools Inspector\", \"severity\": \"hard\" },\n \"meta+shift+d\": { \"action\": \"Bookmark all tabs\", \"severity\": \"hard\" },\n \"meta+shift+g\": { \"action\": \"Find previous\", \"severity\": \"find-bar-only\" },\n \"meta+shift+j\": { \"action\": \"Downloads page\", \"severity\": \"hard\" },\n \"meta+shift+m\": { \"action\": \"Switch user / guest\", \"severity\": \"hard\" },\n \"meta+shift+n\": { \"action\": \"New incognito window\", \"severity\": \"hard\" },\n \"meta+shift+r\": { \"action\": \"Hard reload\", \"severity\": \"hard\" },\n \"meta+shift+t\": { \"action\": \"Reopen closed tab\", \"severity\": \"hard\" },\n \"meta+shift+v\": { \"action\": \"Paste as plain text\", \"severity\": \"hard\" },\n \"meta+shift+w\": { \"action\": \"Close window\", \"severity\": \"hard\" },\n \"meta+shift+z\": { \"action\": \"Redo\", \"severity\": \"hard\" },\n \"meta+alt+i\": { \"action\": \"DevTools\", \"severity\": \"hard\" },\n \"meta+alt+j\": { \"action\": \"DevTools (console)\", \"severity\": \"hard\" },\n \"meta+alt+u\": { \"action\": \"View source\", \"severity\": \"hard\" }\n },\n \"safari\": {\n \"meta+a\": { \"action\": \"Select all\", \"severity\": \"hard\" },\n \"meta+c\": { \"action\": \"Copy\", \"severity\": \"hard\" },\n \"meta+d\": { \"action\": \"Add to Reading List\", \"severity\": \"hard\" },\n \"meta+f\": { \"action\": \"Find in page\", \"severity\": \"hard\" },\n \"meta+g\": { \"action\": \"Find next\", \"severity\": \"hard\" },\n \"meta+j\": { \"action\": \"Downloads\", \"severity\": \"hard\" },\n \"meta+l\": { \"action\": \"Focus Smart Search\", \"severity\": \"hard\" },\n \"meta+n\": { \"action\": \"New window\", \"severity\": \"hard\" },\n \"meta+p\": { \"action\": \"Print\", \"severity\": \"hard\" },\n \"meta+r\": { \"action\": \"Reload\", \"severity\": \"hard\" },\n \"meta+s\": { \"action\": \"Save page\", \"severity\": \"hard\" },\n \"meta+t\": { \"action\": \"New tab\", \"severity\": \"hard\" },\n \"meta+v\": { \"action\": \"Paste\", \"severity\": \"hard\" },\n \"meta+w\": { \"action\": \"Close tab\", \"severity\": \"hard\" },\n \"meta+x\": { \"action\": \"Cut\", \"severity\": \"hard\" },\n \"meta+z\": { \"action\": \"Undo\", \"severity\": \"hard\" },\n \"meta+shift+c\": { \"action\": \"Inspector pick element\", \"severity\": \"hard\" },\n \"meta+shift+d\": { \"action\": \"Add Reading List item\", \"severity\": \"hard\" },\n \"meta+shift+g\": { \"action\": \"Find previous\", \"severity\": \"find-bar-only\" },\n \"meta+shift+h\": { \"action\": \"Go to homepage\", \"severity\": \"hard\" },\n \"meta+shift+n\": { \"action\": \"New private window\", \"severity\": \"hard\" },\n \"meta+shift+r\": { \"action\": \"Reader mode\", \"severity\": \"hard\" },\n \"meta+shift+t\": { \"action\": \"Reopen last closed tab\", \"severity\": \"hard\" },\n \"meta+shift+v\": { \"action\": \"Paste as plain text\", \"severity\": \"hard\" },\n \"meta+shift+w\": { \"action\": \"Close window\", \"severity\": \"hard\" },\n \"meta+shift+z\": { \"action\": \"Redo\", \"severity\": \"hard\" },\n \"meta+alt+c\": { \"action\": \"Web Inspector pick\", \"severity\": \"hard\" },\n \"meta+alt+i\": { \"action\": \"Web Inspector\", \"severity\": \"hard\" }\n }\n },\n \"system\": {\n \"meta+space\": { \"action\": \"Spotlight\", \"severity\": \"os\" },\n \"meta+tab\": { \"action\": \"App switcher\", \"severity\": \"os\" },\n \"meta+h\": { \"action\": \"Hide app\", \"severity\": \"os\" },\n \"meta+m\": { \"action\": \"Minimize window\", \"severity\": \"os\" },\n \"meta+q\": { \"action\": \"Quit app\", \"severity\": \"os\" },\n \"meta+shift+3\": { \"action\": \"Screenshot full screen\", \"severity\": \"os\" },\n \"meta+shift+4\": { \"action\": \"Screenshot selection\", \"severity\": \"os\" },\n \"meta+shift+5\": { \"action\": \"Screen recording tool\", \"severity\": \"os\" },\n \"meta+shift+q\": { \"action\": \"Log out\", \"severity\": \"os\" },\n \"meta+ctrl+q\": { \"action\": \"Lock screen\", \"severity\": \"os\" },\n \"meta+ctrl+space\": { \"action\": \"Character Viewer\", \"severity\": \"os\" },\n \"meta+alt+esc\": { \"action\": \"Force-quit dialog\", \"severity\": \"os\" }\n },\n \"noteForLetterCombos\": {\n \"alt+a..z\": { \"behavior\": \"compose\", \"note\": \"Option+letter types special characters in text inputs (Option+E\u2192\u00B4, Option+A\u2192\u00E5, Option+F\u2192\u0192). Outside inputs, free for page world.\" },\n \"ctrl+a..z\": { \"behavior\": \"system-text\", \"note\": \"Mac uses Ctrl+letter as terminal-style cursor controls inside text inputs (Ctrl+A=line start, Ctrl+E=line end, Ctrl+K=delete-to-end, etc.). Outside inputs, free for page world.\" }\n }\n },\n \"windows\": {\n \"browsers\": {\n \"firefox\": {\n \"ctrl+a\": { \"action\": \"Select all\", \"severity\": \"hard\" },\n \"ctrl+b\": { \"action\": \"Bookmarks sidebar\", \"severity\": \"hard\" },\n \"ctrl+c\": { \"action\": \"Copy\", \"severity\": \"hard\" },\n \"ctrl+d\": { \"action\": \"Bookmark this page\", \"severity\": \"hard\" },\n \"ctrl+f\": { \"action\": \"Find in page\", \"severity\": \"hard\" },\n \"ctrl+g\": { \"action\": \"Find next\", \"severity\": \"hard\" },\n \"ctrl+h\": { \"action\": \"History sidebar\", \"severity\": \"hard\" },\n \"ctrl+j\": { \"action\": \"Downloads\", \"severity\": \"hard\" },\n \"ctrl+l\": { \"action\": \"Focus address bar\", \"severity\": \"hard\" },\n \"ctrl+n\": { \"action\": \"New window\", \"severity\": \"hard\" },\n \"ctrl+o\": { \"action\": \"Open file\", \"severity\": \"hard\" },\n \"ctrl+p\": { \"action\": \"Print\", \"severity\": \"hard\" },\n \"ctrl+r\": { \"action\": \"Reload\", \"severity\": \"hard\" },\n \"ctrl+s\": { \"action\": \"Save page\", \"severity\": \"hard\" },\n \"ctrl+t\": { \"action\": \"New tab\", \"severity\": \"hard\" },\n \"ctrl+u\": { \"action\": \"View source\", \"severity\": \"hard\" },\n \"ctrl+v\": { \"action\": \"Paste\", \"severity\": \"hard\" },\n \"ctrl+w\": { \"action\": \"Close tab\", \"severity\": \"hard\" },\n \"ctrl+x\": { \"action\": \"Cut\", \"severity\": \"hard\" },\n \"ctrl+y\": { \"action\": \"Redo\", \"severity\": \"hard\" },\n \"ctrl+z\": { \"action\": \"Undo\", \"severity\": \"hard\" },\n \"ctrl+shift+a\": { \"action\": \"Add-ons manager\", \"severity\": \"hard\" },\n \"ctrl+shift+b\": { \"action\": \"Bookmarks toolbar\", \"severity\": \"hard\" },\n \"ctrl+shift+c\": { \"action\": \"Inspector (element picker)\", \"severity\": \"hard\" },\n \"ctrl+shift+d\": { \"action\": \"Bookmark all tabs\", \"severity\": \"hard\" },\n \"ctrl+shift+e\": { \"action\": \"Network Monitor\", \"severity\": \"hard\" },\n \"ctrl+shift+g\": { \"action\": \"Find previous\", \"severity\": \"find-bar-only\" },\n \"ctrl+shift+i\": { \"action\": \"Developer Tools\", \"severity\": \"hard\" },\n \"ctrl+shift+j\": { \"action\": \"Browser Console\", \"severity\": \"hard\" },\n \"ctrl+shift+k\": { \"action\": \"Web Console\", \"severity\": \"hard\" },\n \"ctrl+shift+m\": { \"action\": \"Responsive Design Mode\", \"severity\": \"hard\" },\n \"ctrl+shift+n\": { \"action\": \"New private window\", \"severity\": \"hard\" },\n \"ctrl+shift+o\": { \"action\": \"Bookmarks library\", \"severity\": \"hard\" },\n \"ctrl+shift+p\": { \"action\": \"New private window (alt)\", \"severity\": \"hard\" },\n \"ctrl+shift+s\": { \"action\": \"Firefox Screenshot\", \"severity\": \"hard\" },\n \"ctrl+shift+t\": { \"action\": \"Reopen closed tab\", \"severity\": \"hard\" },\n \"ctrl+shift+v\": { \"action\": \"Paste as plain text\", \"severity\": \"hard\" },\n \"ctrl+shift+w\": { \"action\": \"Close window\", \"severity\": \"hard\" },\n \"ctrl+shift+y\": { \"action\": \"Downloads (alt)\", \"severity\": \"hard\" },\n \"ctrl+shift+z\": { \"action\": \"Debugger\", \"severity\": \"hard\" },\n \"alt+f\": { \"action\": \"File menu\", \"severity\": \"menu-activation\" },\n \"alt+e\": { \"action\": \"Edit menu\", \"severity\": \"menu-activation\" },\n \"alt+v\": { \"action\": \"View menu\", \"severity\": \"menu-activation\" },\n \"alt+b\": { \"action\": \"Bookmarks menu\", \"severity\": \"menu-activation\" },\n \"alt+t\": { \"action\": \"Tools menu\", \"severity\": \"menu-activation\" },\n \"alt+h\": { \"action\": \"Help menu\", \"severity\": \"menu-activation\" },\n \"alt+d\": { \"action\": \"Focus address bar\", \"severity\": \"hard\" }\n },\n \"chrome\": {\n \"ctrl+a\": { \"action\": \"Select all\", \"severity\": \"hard\" },\n \"ctrl+c\": { \"action\": \"Copy\", \"severity\": \"hard\" },\n \"ctrl+d\": { \"action\": \"Bookmark this page\", \"severity\": \"hard\" },\n \"ctrl+e\": { \"action\": \"Search from page\", \"severity\": \"hard\" },\n \"ctrl+f\": { \"action\": \"Find in page\", \"severity\": \"hard\" },\n \"ctrl+g\": { \"action\": \"Find next\", \"severity\": \"hard\" },\n \"ctrl+h\": { \"action\": \"History page\", \"severity\": \"hard\" },\n \"ctrl+j\": { \"action\": \"Downloads\", \"severity\": \"hard\" },\n \"ctrl+k\": { \"action\": \"Search from page\", \"severity\": \"hard\" },\n \"ctrl+l\": { \"action\": \"Focus address bar\", \"severity\": \"hard\" },\n \"ctrl+n\": { \"action\": \"New window\", \"severity\": \"hard\" },\n \"ctrl+o\": { \"action\": \"Open file\", \"severity\": \"hard\" },\n \"ctrl+p\": { \"action\": \"Print\", \"severity\": \"hard\" },\n \"ctrl+r\": { \"action\": \"Reload\", \"severity\": \"hard\" },\n \"ctrl+s\": { \"action\": \"Save page\", \"severity\": \"hard\" },\n \"ctrl+t\": { \"action\": \"New tab\", \"severity\": \"hard\" },\n \"ctrl+u\": { \"action\": \"View source\", \"severity\": \"hard\" },\n \"ctrl+v\": { \"action\": \"Paste\", \"severity\": \"hard\" },\n \"ctrl+w\": { \"action\": \"Close tab\", \"severity\": \"hard\" },\n \"ctrl+x\": { \"action\": \"Cut\", \"severity\": \"hard\" },\n \"ctrl+z\": { \"action\": \"Undo\", \"severity\": \"hard\" },\n \"ctrl+shift+b\": { \"action\": \"Bookmarks bar toggle\", \"severity\": \"hard\" },\n \"ctrl+shift+d\": { \"action\": \"Bookmark all tabs\", \"severity\": \"hard\" },\n \"ctrl+shift+g\": { \"action\": \"Find previous\", \"severity\": \"find-bar-only\" },\n \"ctrl+shift+i\": { \"action\": \"DevTools\", \"severity\": \"hard\" },\n \"ctrl+shift+j\": { \"action\": \"DevTools (console)\", \"severity\": \"hard\" },\n \"ctrl+shift+m\": { \"action\": \"Switch user / guest\", \"severity\": \"hard\" },\n \"ctrl+shift+n\": { \"action\": \"Incognito window\", \"severity\": \"hard\" },\n \"ctrl+shift+r\": { \"action\": \"Hard reload\", \"severity\": \"hard\" },\n \"ctrl+shift+t\": { \"action\": \"Reopen closed tab\", \"severity\": \"hard\" },\n \"ctrl+shift+v\": { \"action\": \"Paste as plain text\", \"severity\": \"hard\" },\n \"ctrl+shift+w\": { \"action\": \"Close window\", \"severity\": \"hard\" },\n \"alt+d\": { \"action\": \"Focus address bar\", \"severity\": \"hard\" },\n \"alt+e\": { \"action\": \"Customize menu\", \"severity\": \"menu-activation\" },\n \"alt+f\": { \"action\": \"Customize menu (alt)\", \"severity\": \"menu-activation\" }\n },\n \"edge\": {\n \"ctrl+a\": { \"action\": \"Select all\", \"severity\": \"hard\" },\n \"ctrl+c\": { \"action\": \"Copy\", \"severity\": \"hard\" },\n \"ctrl+d\": { \"action\": \"Favorite this page\", \"severity\": \"hard\" },\n \"ctrl+e\": { \"action\": \"Search from page\", \"severity\": \"hard\" },\n \"ctrl+f\": { \"action\": \"Find in page\", \"severity\": \"hard\" },\n \"ctrl+g\": { \"action\": \"Find next\", \"severity\": \"hard\" },\n \"ctrl+h\": { \"action\": \"History\", \"severity\": \"hard\" },\n \"ctrl+j\": { \"action\": \"Downloads\", \"severity\": \"hard\" },\n \"ctrl+k\": { \"action\": \"Search from page\", \"severity\": \"hard\" },\n \"ctrl+l\": { \"action\": \"Focus address bar\", \"severity\": \"hard\" },\n \"ctrl+m\": { \"action\": \"Mute current tab\", \"severity\": \"hard\" },\n \"ctrl+n\": { \"action\": \"New window\", \"severity\": \"hard\" },\n \"ctrl+o\": { \"action\": \"Open file\", \"severity\": \"hard\" },\n \"ctrl+p\": { \"action\": \"Print\", \"severity\": \"hard\" },\n \"ctrl+r\": { \"action\": \"Reload\", \"severity\": \"hard\" },\n \"ctrl+s\": { \"action\": \"Save page\", \"severity\": \"hard\" },\n \"ctrl+t\": { \"action\": \"New tab\", \"severity\": \"hard\" },\n \"ctrl+u\": { \"action\": \"View source\", \"severity\": \"hard\" },\n \"ctrl+v\": { \"action\": \"Paste\", \"severity\": \"hard\" },\n \"ctrl+w\": { \"action\": \"Close tab\", \"severity\": \"hard\" },\n \"ctrl+x\": { \"action\": \"Cut\", \"severity\": \"hard\" },\n \"ctrl+z\": { \"action\": \"Undo\", \"severity\": \"hard\" },\n \"ctrl+shift+b\": { \"action\": \"Favorites bar toggle\", \"severity\": \"hard\" },\n \"ctrl+shift+d\": { \"action\": \"Bookmark all tabs in folder\", \"severity\": \"hard\" },\n \"ctrl+shift+e\": { \"action\": \"Search in sidebar\", \"severity\": \"hard\" },\n \"ctrl+shift+g\": { \"action\": \"Find previous\", \"severity\": \"find-bar-only\" },\n \"ctrl+shift+i\": { \"action\": \"DevTools\", \"severity\": \"hard\" },\n \"ctrl+shift+j\": { \"action\": \"DevTools (console)\", \"severity\": \"hard\" },\n \"ctrl+shift+k\": { \"action\": \"Duplicate tab\", \"severity\": \"hard\" },\n \"ctrl+shift+l\": { \"action\": \"Paste and search\", \"severity\": \"hard\" },\n \"ctrl+shift+m\": { \"action\": \"Switch user / guest\", \"severity\": \"hard\" },\n \"ctrl+shift+n\": { \"action\": \"InPrivate window\", \"severity\": \"hard\" },\n \"ctrl+shift+o\": { \"action\": \"Open favorites\", \"severity\": \"hard\" },\n \"ctrl+shift+p\": { \"action\": \"Print (system dialog)\", \"severity\": \"hard\" },\n \"ctrl+shift+r\": { \"action\": \"Hard reload\", \"severity\": \"hard\" },\n \"ctrl+shift+t\": { \"action\": \"Reopen closed tab\", \"severity\": \"hard\" },\n \"ctrl+shift+u\": { \"action\": \"Read Aloud toggle\", \"severity\": \"hard\" },\n \"ctrl+shift+v\": { \"action\": \"Paste without formatting\", \"severity\": \"hard\" },\n \"ctrl+shift+w\": { \"action\": \"Close window\", \"severity\": \"hard\" },\n \"ctrl+shift+y\": { \"action\": \"Collections\", \"severity\": \"hard\" },\n \"alt+d\": { \"action\": \"Focus address bar\", \"severity\": \"hard\" },\n \"alt+e\": { \"action\": \"Settings menu\", \"severity\": \"menu-activation\" },\n \"alt+f\": { \"action\": \"Settings menu (alt)\", \"severity\": \"menu-activation\" },\n \"alt+shift+b\": { \"action\": \"Focus favorites bar\", \"severity\": \"hard\" },\n \"alt+shift+i\": { \"action\": \"Send feedback dialog\", \"severity\": \"hard\" },\n \"alt+shift+t\": { \"action\": \"Focus app bar toolbar\", \"severity\": \"hard\" }\n }\n },\n \"system\": {\n \"meta+a\": { \"action\": \"Action Center\", \"severity\": \"os\" },\n \"meta+c\": { \"action\": \"Windows search\", \"severity\": \"os\" },\n \"meta+d\": { \"action\": \"Show desktop\", \"severity\": \"os\" },\n \"meta+e\": { \"action\": \"File Explorer\", \"severity\": \"os\" },\n \"meta+g\": { \"action\": \"Game bar\", \"severity\": \"os\" },\n \"meta+h\": { \"action\": \"Voice dictation\", \"severity\": \"os\" },\n \"meta+i\": { \"action\": \"Settings\", \"severity\": \"os\" },\n \"meta+l\": { \"action\": \"Lock\", \"severity\": \"os\" },\n \"meta+n\": { \"action\": \"Notification center\", \"severity\": \"os\" },\n \"meta+p\": { \"action\": \"Project / display mode\", \"severity\": \"os\" },\n \"meta+r\": { \"action\": \"Run dialog\", \"severity\": \"os\" },\n \"meta+s\": { \"action\": \"Search\", \"severity\": \"os\" },\n \"meta+v\": { \"action\": \"Clipboard history\", \"severity\": \"os\" },\n \"meta+w\": { \"action\": \"Widgets\", \"severity\": \"os\" },\n \"meta+x\": { \"action\": \"Quick Link menu\", \"severity\": \"os\" },\n \"meta+z\": { \"action\": \"Snap layouts\", \"severity\": \"os\" },\n \"meta+tab\": { \"action\": \"Task View\", \"severity\": \"os\" },\n \"meta+shift+s\": { \"action\": \"Screenshot region\", \"severity\": \"os\" },\n \"ctrl+shift+esc\": { \"action\": \"Task Manager\", \"severity\": \"os\" },\n \"ctrl+alt+del\": { \"action\": \"Security screen\", \"severity\": \"os\" },\n \"alt+tab\": { \"action\": \"Switch windows\", \"severity\": \"os\" },\n \"alt+f4\": { \"action\": \"Close active window\", \"severity\": \"os\" }\n }\n },\n \"linux\": {\n \"browsers\": {\n \"firefox\": \"$ref:platforms.windows.browsers.firefox\",\n \"chrome\": \"$ref:platforms.windows.browsers.chrome\",\n \"edge\": \"$ref:platforms.windows.browsers.edge\"\n },\n \"system\": {\n \"$comment\": \"GNOME defaults. KDE and other DEs have similar-shaped reservations but vary; this is a conservative baseline.\",\n \"meta+tab\": { \"action\": \"Switch windows\", \"severity\": \"os\" },\n \"meta+a\": { \"action\": \"Show applications\", \"severity\": \"os\" },\n \"meta+l\": { \"action\": \"Lock screen\", \"severity\": \"os\" },\n \"meta+v\": { \"action\": \"Notification list\", \"severity\": \"os\" },\n \"alt+tab\": { \"action\": \"Switch applications\", \"severity\": \"os\" },\n \"alt+esc\": { \"action\": \"Cycle windows\", \"severity\": \"os\" },\n \"alt+f2\": { \"action\": \"Run command\", \"severity\": \"os\" },\n \"alt+f4\": { \"action\": \"Close window\", \"severity\": \"os\" },\n \"ctrl+alt+tab\": { \"action\": \"Top-bar accessibility switcher\", \"severity\": \"os\" },\n \"ctrl+alt+del\": { \"action\": \"Power-off dialog\", \"severity\": \"os\" },\n \"ctrl+shift+alt+r\": { \"action\": \"Toggle screencast recording\", \"severity\": \"os\" }\n },\n \"noteForCtrlAlt\": \"Some Linux setups map right-Alt (AltGr) to 'compose' for typing accented characters, in which case AltGr+letter is reported as ctrl+alt+letter and types a special character. Avoid the ctrl+alt+letter namespace on Linux.\"\n }\n }\n}\n", "// reservations.js\n// Browser/OS hotkey reservation lookup for hotkey-router.\n//\n// At bind time, we look up the requested combo against a table of known\n// browser- and OS-level shortcuts and emit a console.warn/info if the host\n// will intercept it before the page sees the keydown. Soft warning only \u2014\n// never throws, never blocks the bind.\n//\n// Data file: data/browser-hotkeys.json. Schema documented in that file's\n// `$keyFormat` / `$comment` fields. Severity tiers determine warn vs info.\n\nimport HOTKEY_DATA from './data/browser-hotkeys.json' with { type: 'json' }\n\nconst SUPPORTED_SCHEMA = '1.0'\n\n// Severities that mean \"combo will not reach page world.\"\nconst HARD_SEVERITIES = new Set(['hard', 'os', 'menu-activation'])\n\n// Severities that mean \"combo fires in normal browsing, only intercepted in\n// narrow contexts (find bar focused, text input focused, devtools open).\"\nconst SOFT_SEVERITIES = new Set(['find-bar-only', 'compose', 'system-text', 'devtools-open'])\n\n// --- platform / browser detection ---------------------------------------------\n\nexport function detectPlatform(nav = (typeof navigator !== 'undefined' ? navigator : null)) {\n if (!nav) return null\n const platform = nav.platform || ''\n if (/Mac|iPhone|iPad|iPod/.test(platform)) return 'mac'\n if (/Win/i.test(platform)) return 'windows'\n if (/Linux|X11/i.test(platform)) return 'linux'\n // Fall back to userAgent sniffing when navigator.platform is unhelpful\n // (e.g. some Chromium builds report empty platform).\n const ua = nav.userAgent || ''\n if (/Mac OS X/i.test(ua)) return 'mac'\n if (/Windows/i.test(ua)) return 'windows'\n if (/Linux|X11/i.test(ua)) return 'linux'\n return null\n}\n\nexport function detectBrowser(nav = (typeof navigator !== 'undefined' ? navigator : null)) {\n if (!nav) return null\n const ua = nav.userAgent || ''\n // Order matters: Edge UA contains 'Chrome', Chrome UA contains 'Safari'.\n if (/Edg\\//.test(ua)) return 'edge'\n if (/Firefox/.test(ua)) return 'firefox'\n if (/Chrome/.test(ua)) return 'chrome'\n if (/Safari/.test(ua)) return 'safari'\n return null\n}\n\n// --- data normalization -------------------------------------------------------\n\n// Canonical modifier order for lookup keys: ctrl, meta, alt, shift, key.\n// The data file mostly follows this but has at least one entry that doesn't\n// (`ctrl+shift+alt+r` on Linux). Normalize both sides at load and lookup so\n// minor inconsistencies don't cause silent misses.\nfunction canonicalize(rawKey) {\n const parts = String(rawKey).toLowerCase().split('+').map(p => p.trim()).filter(Boolean)\n if (!parts.length) return ''\n const base = parts[parts.length - 1]\n const mods = new Set(parts.slice(0, -1))\n const out = []\n if (mods.has('ctrl')) out.push('ctrl')\n if (mods.has('meta')) out.push('meta')\n if (mods.has('alt')) out.push('alt')\n if (mods.has('shift')) out.push('shift')\n out.push(base)\n return out.join('+')\n}\n\n// Resolve $ref pointers (\"$ref:platforms.windows.browsers.chrome\") used by\n// the Linux section to dedupe against Windows browser tables.\nfunction resolveRef(value, root) {\n if (typeof value !== 'string' || !value.startsWith('$ref:')) return value\n const path = value.slice('$ref:'.length).split('.')\n let node = root\n for (const step of path) node = node?.[step]\n return node\n}\n\nfunction normalizeTable(table) {\n if (!table || typeof table !== 'object') return null\n const out = Object.create(null)\n for (const [k, v] of Object.entries(table)) {\n if (!v || typeof v !== 'object' || !('severity' in v)) continue\n out[canonicalize(k)] = v\n }\n return out\n}\n\n// Precompute normalized lookup tables once at module load. Browsers ship the\n// table inline; this keeps per-bind lookup to two Map-ish reads.\nfunction buildIndex(data) {\n const idx = { platforms: {} }\n const platforms = data?.platforms || {}\n for (const [platform, pdata] of Object.entries(platforms)) {\n const browsers = {}\n for (const [name, btable] of Object.entries(pdata.browsers || {})) {\n browsers[name] = normalizeTable(resolveRef(btable, data))\n }\n idx.platforms[platform] = {\n browsers,\n system: normalizeTable(pdata.system),\n }\n }\n return idx\n}\n\nconst SCHEMA_OK = HOTKEY_DATA?.version?.schema === SUPPORTED_SCHEMA\nconst INDEX = SCHEMA_OK ? buildIndex(HOTKEY_DATA) : { platforms: {} }\n\n// --- lookup-key construction --------------------------------------------------\n\n// Strip a `KeyboardEvent.code` value down to the bare letter/digit used in the\n// data tables. `KeyA` -> `a`, `Digit1` -> `1`. Other codes (`ArrowLeft`,\n// `Space`, `F5`) are lowercased as a best-effort fallback.\nfunction codeToKey(code) {\n if (!code) return null\n const letter = /^Key([A-Za-z])$/.exec(code)\n if (letter) return letter[1].toLowerCase()\n const digit = /^Digit(\\d)$/.exec(code)\n if (digit) return digit[1]\n return code.toLowerCase()\n}\n\n// Build the canonical lookup key from a hotkey-router parsed combo. Mirrors\n// WebRadar's `lookupKey()` but works against the parsed structure rather than\n// the raw string, so `mod` is already resolved and `code:KeyX` is normalized.\nexport function lookupKeyFromCombo(combo) {\n if (!combo) return null\n if (combo.bareModifier) return null // bare modifiers aren't tracked in the data\n const base = combo.code ? codeToKey(combo.code) : combo.key\n if (!base) return null\n const parts = []\n if (combo.ctrl) parts.push('ctrl')\n if (combo.meta) parts.push('meta')\n if (combo.alt) parts.push('alt')\n if (combo.shift) parts.push('shift')\n parts.push(base)\n return parts.join('+')\n}\n\n// --- public lookup ------------------------------------------------------------\n\n/**\n * @typedef {'mac' | 'windows' | 'linux'} Platform\n * @typedef {'chrome' | 'firefox' | 'safari' | 'edge'} Browser\n * @typedef {'hard' | 'hard-fullscreen' | 'soft' | 'soft-warn'} Severity\n *\n * @typedef {{\n * source: 'browser' | 'system',\n * platform: Platform,\n * browser: Browser | undefined,\n * lookupKey: string,\n * action: string,\n * severity: Severity\n * }} Reservation\n */\n\n/**\n * Look up whether a parsed hotkey combo is reserved by the host platform\n * or browser. Returns `null` when not reserved or when the data table\n * hasn't loaded.\n *\n * @param {object | null} combo parsed combo from `hotkey-router`'s `parseHotkey`\n * @param {{ platform?: Platform, browser?: Browser }} [opts]\n * @returns {Reservation | null}\n */\nexport function lookupReservation(combo, { platform, browser } = {}) {\n if (!SCHEMA_OK) return null\n const lookupKey = lookupKeyFromCombo(combo)\n if (!lookupKey) return null\n\n const pdata = platform && INDEX.platforms[platform]\n if (!pdata) return null\n\n const btable = browser ? pdata.browsers?.[browser] : null\n const bclaim = btable?.[lookupKey]\n if (bclaim) {\n return {\n source: 'browser',\n platform,\n browser,\n lookupKey,\n action: bclaim.action,\n severity: bclaim.severity,\n }\n }\n const sclaim = pdata.system?.[lookupKey]\n if (sclaim) {\n return {\n source: 'system',\n platform,\n browser,\n lookupKey,\n action: sclaim.action,\n severity: sclaim.severity,\n }\n }\n return null\n}\n\n// --- warning emission ---------------------------------------------------------\n\nconst PLATFORM_LABEL = { mac: 'macOS', windows: 'Windows', linux: 'Linux' }\n\n/** @param {Severity | string} severity @returns {boolean} */\nexport function severityIsHard(severity) {\n return HARD_SEVERITIES.has(severity)\n}\n\n/** @param {Severity | string} severity @returns {boolean} */\nexport function severityIsSoft(severity) {\n return SOFT_SEVERITIES.has(severity)\n}\n\n/**\n * Render a console-friendly warning string for a reservation.\n *\n * @param {Reservation} reservation\n * @param {string} rawHotkey\n * @returns {string}\n */\nexport function formatReservationWarning(reservation, rawHotkey) {\n const platformLabel = PLATFORM_LABEL[reservation.platform] || reservation.platform\n const sourceLabel = reservation.source === 'browser'\n ? `${reservation.browser} on ${platformLabel}`\n : `${platformLabel}`\n const tag = severityIsHard(reservation.severity)\n ? 'will not fire'\n : 'fires in normal browsing'\n return `[hotkey-router] \"${rawHotkey}\" (${reservation.lookupKey}) reserved by ${sourceLabel}: \"${reservation.action}\" [${reservation.severity}] \u2014 ${tag}.`\n}\n\n/**\n * Emit a reservation warning via the given console (or the global `console`\n * by default). Hard reservations log via `warn`; soft ones via `info`.\n *\n * @param {Reservation} reservation\n * @param {string} rawHotkey\n * @param {Console} [console_]\n * @returns {void}\n */\nexport function emitReservationWarning(reservation, rawHotkey, console_ = console) {\n const msg = formatReservationWarning(reservation, rawHotkey)\n const fn = severityIsHard(reservation.severity) ? console_.warn : console_.info\n fn.call(console_, msg)\n}\n\n// --- installer ----------------------------------------------------------------\n//\n// Wire reservation warnings into a hotkey-router instance. Importing this\n// function is the opt-in: bundlers that don't see this import tree-shake the\n// entire ~5 KB data table out of the build.\n//\n// import hotkeys from 'hotkey-router'\n// import { installReservationWarnings } from 'hotkey-router/reservations'\n// installReservationWarnings(hotkeys)\n//\n// Returns an `uninstall()` function. Per-bind opt-out still works:\n// hotkeys.bind('meta+shift+f', fn, null, { warnOnReserved: false })\n//\n// Options:\n// platform \u2014 override auto-detected 'mac' | 'windows' | 'linux'\n// browser \u2014 override auto-detected 'firefox' | 'chrome' | 'safari' | 'edge'\n// console \u2014 inject a custom console-like object (used by tests)\n/**\n * @param {object} hotkeys a hotkey-router default-export instance\n * @param {{\n * platform?: Platform,\n * browser?: Browser,\n * console?: Console\n * }} [opts]\n * @returns {() => void} uninstall function\n */\nexport function installReservationWarnings(hotkeys, opts = {}) {\n if (!hotkeys || typeof hotkeys.onBind !== 'function') {\n throw new TypeError(\n 'installReservationWarnings(hotkeys) requires a hotkey-router instance with onBind() (>= v0.2.0)'\n )\n }\n const platform = opts.platform !== undefined ? opts.platform : detectPlatform()\n const browser = opts.browser !== undefined ? opts.browser : detectBrowser()\n const console_ = opts.console || console\n\n return hotkeys.onBind(({ combo, raw, options }) => {\n if (options?.warnOnReserved === false) return\n if (!platform || !browser) return\n const reservation = lookupReservation(combo, { platform, browser })\n if (reservation) emitReservationWarning(reservation, raw, console_)\n })\n}\n\nexport const SCHEMA_VERSION = HOTKEY_DATA?.version?.schema\nexport const DATA_GENERATED = HOTKEY_DATA?.version?.generated\nexport { HOTKEY_DATA }\n"],
|
|
4
|
+
"sourcesContent": ["{\r\n \"$comment\": \"Machine-readable companion to docs/browser-hotkeys.md. Each combo entry describes who claims the binding and how strongly. Intended for runtime conflict warnings in keyboard-routing libraries (e.g. hotkey-router) and dev-time validation in apps like WebRadar. Update both this file and the markdown together \u2014 the markdown is the human source of truth, this file is the machine projection.\",\r\n \"version\": {\r\n \"generated\": \"2026-05-17\",\r\n \"schema\": \"1.0\",\r\n \"sources\": [\r\n \"https://support.mozilla.org/en-US/kb/keyboard-shortcuts-perform-firefox-tasks-quickly\",\r\n \"https://firefox-source-docs.mozilla.org/devtools-user/keyboard_shortcuts/index.html\",\r\n \"https://support.google.com/chrome/answer/157179\",\r\n \"https://developer.chrome.com/docs/devtools/shortcuts\",\r\n \"https://support.apple.com/guide/safari/keyboard-shortcuts-and-gestures-cpsh003/mac\",\r\n \"https://developer.apple.com/documentation/safari-developer-tools/web-inspector\",\r\n \"https://support.microsoft.com/en-us/microsoft-edge/keyboard-shortcuts-in-microsoft-edge-50d3edab-30d9-c7e4-21ce-37fe2713cfad\",\r\n \"https://support.apple.com/en-us/102650\",\r\n \"https://support.microsoft.com/en-us/windows/keyboard-shortcuts-in-windows-dcc61a57-8ff0-cffe-9796-cb9706c75eec\",\r\n \"https://help.gnome.org/gnome-help/shell-keyboard-shortcuts.html\"\r\n ]\r\n },\r\n \"severityLevels\": {\r\n \"hard\": \"Browser or OS intercepts before page-world keydown fires. preventDefault() can't recover it.\",\r\n \"find-bar-only\": \"Reserved only when the browser's find bar has focus. Fires in page world during normal browsing.\",\r\n \"menu-activation\": \"Win/Linux Alt+letter activates the browser menu bar. Hard to suppress reliably.\",\r\n \"system-text\": \"Only reserved while a text input has focus (terminal-style cursor controls on macOS).\",\r\n \"compose\": \"macOS Option+letter types a special character in text inputs. Outside inputs, free for page world.\",\r\n \"os\": \"Operating system intercepts globally, before any application sees it.\",\r\n \"devtools-open\": \"Only relevant when DevTools is already open; outside DevTools it fires normally.\"\r\n },\r\n \"$keyFormat\": \"Each combo key uses hotkey-router-compatible syntax: modifiers in canonical order (ctrl|meta|alt|shift) joined by '+', then the key (lowercased letter, or symbolic name). Per-platform tables use the platform's native modifier name \u2014 `meta` on macOS = Cmd, `meta` on Windows = Win, `ctrl` on Linux/Windows = the primary modifier.\",\r\n \"platforms\": {\r\n \"mac\": {\r\n \"browsers\": {\r\n \"firefox\": {\r\n \"meta+a\": { \"action\": \"Select all\", \"severity\": \"hard\" },\r\n \"meta+b\": { \"action\": \"Bookmarks sidebar\", \"severity\": \"hard\" },\r\n \"meta+c\": { \"action\": \"Copy\", \"severity\": \"hard\" },\r\n \"meta+d\": { \"action\": \"Bookmark this page\", \"severity\": \"hard\" },\r\n \"meta+e\": { \"action\": \"Search from page\", \"severity\": \"hard\" },\r\n \"meta+f\": { \"action\": \"Find in page\", \"severity\": \"hard\" },\r\n \"meta+g\": { \"action\": \"Find next\", \"severity\": \"hard\" },\r\n \"meta+j\": { \"action\": \"Downloads\", \"severity\": \"hard\" },\r\n \"meta+l\": { \"action\": \"Focus address bar\", \"severity\": \"hard\" },\r\n \"meta+n\": { \"action\": \"New window\", \"severity\": \"hard\" },\r\n \"meta+o\": { \"action\": \"Open file\", \"severity\": \"hard\" },\r\n \"meta+p\": { \"action\": \"Print\", \"severity\": \"hard\" },\r\n \"meta+r\": { \"action\": \"Reload\", \"severity\": \"hard\" },\r\n \"meta+s\": { \"action\": \"Save page\", \"severity\": \"hard\" },\r\n \"meta+t\": { \"action\": \"New tab\", \"severity\": \"hard\" },\r\n \"meta+u\": { \"action\": \"View source\", \"severity\": \"hard\" },\r\n \"meta+v\": { \"action\": \"Paste\", \"severity\": \"hard\" },\r\n \"meta+w\": { \"action\": \"Close tab\", \"severity\": \"hard\" },\r\n \"meta+x\": { \"action\": \"Cut\", \"severity\": \"hard\" },\r\n \"meta+y\": { \"action\": \"Redo\", \"severity\": \"hard\" },\r\n \"meta+z\": { \"action\": \"Undo\", \"severity\": \"hard\" },\r\n \"meta+shift+a\": { \"action\": \"Add-ons manager\", \"severity\": \"hard\" },\r\n \"meta+shift+b\": { \"action\": \"Bookmarks toolbar\", \"severity\": \"hard\" },\r\n \"meta+shift+c\": { \"action\": \"Inspector (element picker)\", \"severity\": \"hard\" },\r\n \"meta+shift+d\": { \"action\": \"Bookmark all tabs\", \"severity\": \"hard\" },\r\n \"meta+shift+e\": { \"action\": \"Network Monitor\", \"severity\": \"hard\" },\r\n \"meta+shift+f\": { \"action\": \"Toggle fullscreen\", \"severity\": \"hard\" },\r\n \"meta+shift+g\": { \"action\": \"Find previous\", \"severity\": \"find-bar-only\" },\r\n \"meta+shift+j\": { \"action\": \"Browser Console\", \"severity\": \"hard\" },\r\n \"meta+shift+n\": { \"action\": \"New private window\", \"severity\": \"hard\" },\r\n \"meta+shift+o\": { \"action\": \"Bookmarks library\", \"severity\": \"hard\" },\r\n \"meta+shift+p\": { \"action\": \"New private window (alt)\", \"severity\": \"hard\" },\r\n \"meta+shift+q\": { \"action\": \"Quit (with confirm)\", \"severity\": \"hard\" },\r\n \"meta+shift+s\": { \"action\": \"Firefox Screenshot\", \"severity\": \"hard\" },\r\n \"meta+shift+t\": { \"action\": \"Reopen closed tab\", \"severity\": \"hard\" },\r\n \"meta+shift+v\": { \"action\": \"Paste as plain text\", \"severity\": \"hard\" },\r\n \"meta+shift+w\": { \"action\": \"Close window\", \"severity\": \"hard\" },\r\n \"meta+shift+z\": { \"action\": \"Redo\", \"severity\": \"hard\" },\r\n \"meta+alt+c\": { \"action\": \"Inspector\", \"severity\": \"hard\" },\r\n \"meta+alt+e\": { \"action\": \"Network Monitor\", \"severity\": \"hard\" },\r\n \"meta+alt+i\": { \"action\": \"DevTools Toolbox\", \"severity\": \"hard\" },\r\n \"meta+alt+j\": { \"action\": \"Browser Console\", \"severity\": \"hard\" },\r\n \"meta+alt+k\": { \"action\": \"Web Console\", \"severity\": \"hard\" },\r\n \"meta+alt+m\": { \"action\": \"Responsive Design Mode\", \"severity\": \"hard\" },\r\n \"meta+alt+z\": { \"action\": \"Debugger\", \"severity\": \"hard\" }\r\n },\r\n \"chrome\": {\r\n \"meta+a\": { \"action\": \"Select all\", \"severity\": \"hard\" },\r\n \"meta+c\": { \"action\": \"Copy\", \"severity\": \"hard\" },\r\n \"meta+d\": { \"action\": \"Bookmark this page\", \"severity\": \"hard\" },\r\n \"meta+e\": { \"action\": \"Search selected text\", \"severity\": \"find-bar-only\" },\r\n \"meta+f\": { \"action\": \"Find in page\", \"severity\": \"hard\" },\r\n \"meta+g\": { \"action\": \"Find next\", \"severity\": \"hard\" },\r\n \"meta+l\": { \"action\": \"Focus address bar\", \"severity\": \"hard\" },\r\n \"meta+n\": { \"action\": \"New window\", \"severity\": \"hard\" },\r\n \"meta+o\": { \"action\": \"Open file\", \"severity\": \"hard\" },\r\n \"meta+p\": { \"action\": \"Print\", \"severity\": \"hard\" },\r\n \"meta+r\": { \"action\": \"Reload\", \"severity\": \"hard\" },\r\n \"meta+s\": { \"action\": \"Save page\", \"severity\": \"hard\" },\r\n \"meta+t\": { \"action\": \"New tab\", \"severity\": \"hard\" },\r\n \"meta+v\": { \"action\": \"Paste\", \"severity\": \"hard\" },\r\n \"meta+w\": { \"action\": \"Close tab\", \"severity\": \"hard\" },\r\n \"meta+x\": { \"action\": \"Cut\", \"severity\": \"hard\" },\r\n \"meta+y\": { \"action\": \"History page\", \"severity\": \"hard\" },\r\n \"meta+z\": { \"action\": \"Undo\", \"severity\": \"hard\" },\r\n \"meta+shift+b\": { \"action\": \"Bookmarks bar toggle\", \"severity\": \"hard\" },\r\n \"meta+shift+c\": { \"action\": \"DevTools Inspector\", \"severity\": \"hard\" },\r\n \"meta+shift+d\": { \"action\": \"Bookmark all tabs\", \"severity\": \"hard\" },\r\n \"meta+shift+g\": { \"action\": \"Find previous\", \"severity\": \"find-bar-only\" },\r\n \"meta+shift+j\": { \"action\": \"Downloads page\", \"severity\": \"hard\" },\r\n \"meta+shift+m\": { \"action\": \"Switch user / guest\", \"severity\": \"hard\" },\r\n \"meta+shift+n\": { \"action\": \"New incognito window\", \"severity\": \"hard\" },\r\n \"meta+shift+r\": { \"action\": \"Hard reload\", \"severity\": \"hard\" },\r\n \"meta+shift+t\": { \"action\": \"Reopen closed tab\", \"severity\": \"hard\" },\r\n \"meta+shift+v\": { \"action\": \"Paste as plain text\", \"severity\": \"hard\" },\r\n \"meta+shift+w\": { \"action\": \"Close window\", \"severity\": \"hard\" },\r\n \"meta+shift+z\": { \"action\": \"Redo\", \"severity\": \"hard\" },\r\n \"meta+alt+i\": { \"action\": \"DevTools\", \"severity\": \"hard\" },\r\n \"meta+alt+j\": { \"action\": \"DevTools (console)\", \"severity\": \"hard\" },\r\n \"meta+alt+u\": { \"action\": \"View source\", \"severity\": \"hard\" }\r\n },\r\n \"safari\": {\r\n \"meta+a\": { \"action\": \"Select all\", \"severity\": \"hard\" },\r\n \"meta+c\": { \"action\": \"Copy\", \"severity\": \"hard\" },\r\n \"meta+d\": { \"action\": \"Add to Reading List\", \"severity\": \"hard\" },\r\n \"meta+f\": { \"action\": \"Find in page\", \"severity\": \"hard\" },\r\n \"meta+g\": { \"action\": \"Find next\", \"severity\": \"hard\" },\r\n \"meta+j\": { \"action\": \"Downloads\", \"severity\": \"hard\" },\r\n \"meta+l\": { \"action\": \"Focus Smart Search\", \"severity\": \"hard\" },\r\n \"meta+n\": { \"action\": \"New window\", \"severity\": \"hard\" },\r\n \"meta+p\": { \"action\": \"Print\", \"severity\": \"hard\" },\r\n \"meta+r\": { \"action\": \"Reload\", \"severity\": \"hard\" },\r\n \"meta+s\": { \"action\": \"Save page\", \"severity\": \"hard\" },\r\n \"meta+t\": { \"action\": \"New tab\", \"severity\": \"hard\" },\r\n \"meta+v\": { \"action\": \"Paste\", \"severity\": \"hard\" },\r\n \"meta+w\": { \"action\": \"Close tab\", \"severity\": \"hard\" },\r\n \"meta+x\": { \"action\": \"Cut\", \"severity\": \"hard\" },\r\n \"meta+z\": { \"action\": \"Undo\", \"severity\": \"hard\" },\r\n \"meta+shift+c\": { \"action\": \"Inspector pick element\", \"severity\": \"hard\" },\r\n \"meta+shift+d\": { \"action\": \"Add Reading List item\", \"severity\": \"hard\" },\r\n \"meta+shift+g\": { \"action\": \"Find previous\", \"severity\": \"find-bar-only\" },\r\n \"meta+shift+h\": { \"action\": \"Go to homepage\", \"severity\": \"hard\" },\r\n \"meta+shift+n\": { \"action\": \"New private window\", \"severity\": \"hard\" },\r\n \"meta+shift+r\": { \"action\": \"Reader mode\", \"severity\": \"hard\" },\r\n \"meta+shift+t\": { \"action\": \"Reopen last closed tab\", \"severity\": \"hard\" },\r\n \"meta+shift+v\": { \"action\": \"Paste as plain text\", \"severity\": \"hard\" },\r\n \"meta+shift+w\": { \"action\": \"Close window\", \"severity\": \"hard\" },\r\n \"meta+shift+z\": { \"action\": \"Redo\", \"severity\": \"hard\" },\r\n \"meta+alt+c\": { \"action\": \"Web Inspector pick\", \"severity\": \"hard\" },\r\n \"meta+alt+i\": { \"action\": \"Web Inspector\", \"severity\": \"hard\" }\r\n }\r\n },\r\n \"system\": {\r\n \"meta+space\": { \"action\": \"Spotlight\", \"severity\": \"os\" },\r\n \"meta+tab\": { \"action\": \"App switcher\", \"severity\": \"os\" },\r\n \"meta+h\": { \"action\": \"Hide app\", \"severity\": \"os\" },\r\n \"meta+m\": { \"action\": \"Minimize window\", \"severity\": \"os\" },\r\n \"meta+q\": { \"action\": \"Quit app\", \"severity\": \"os\" },\r\n \"meta+shift+3\": { \"action\": \"Screenshot full screen\", \"severity\": \"os\" },\r\n \"meta+shift+4\": { \"action\": \"Screenshot selection\", \"severity\": \"os\" },\r\n \"meta+shift+5\": { \"action\": \"Screen recording tool\", \"severity\": \"os\" },\r\n \"meta+shift+q\": { \"action\": \"Log out\", \"severity\": \"os\" },\r\n \"meta+ctrl+q\": { \"action\": \"Lock screen\", \"severity\": \"os\" },\r\n \"meta+ctrl+space\": { \"action\": \"Character Viewer\", \"severity\": \"os\" },\r\n \"meta+alt+esc\": { \"action\": \"Force-quit dialog\", \"severity\": \"os\" }\r\n },\r\n \"noteForLetterCombos\": {\r\n \"alt+a..z\": { \"behavior\": \"compose\", \"note\": \"Option+letter types special characters in text inputs (Option+E\u2192\u00B4, Option+A\u2192\u00E5, Option+F\u2192\u0192). Outside inputs, free for page world.\" },\r\n \"ctrl+a..z\": { \"behavior\": \"system-text\", \"note\": \"Mac uses Ctrl+letter as terminal-style cursor controls inside text inputs (Ctrl+A=line start, Ctrl+E=line end, Ctrl+K=delete-to-end, etc.). Outside inputs, free for page world.\" }\r\n }\r\n },\r\n \"windows\": {\r\n \"browsers\": {\r\n \"firefox\": {\r\n \"ctrl+a\": { \"action\": \"Select all\", \"severity\": \"hard\" },\r\n \"ctrl+b\": { \"action\": \"Bookmarks sidebar\", \"severity\": \"hard\" },\r\n \"ctrl+c\": { \"action\": \"Copy\", \"severity\": \"hard\" },\r\n \"ctrl+d\": { \"action\": \"Bookmark this page\", \"severity\": \"hard\" },\r\n \"ctrl+f\": { \"action\": \"Find in page\", \"severity\": \"hard\" },\r\n \"ctrl+g\": { \"action\": \"Find next\", \"severity\": \"hard\" },\r\n \"ctrl+h\": { \"action\": \"History sidebar\", \"severity\": \"hard\" },\r\n \"ctrl+j\": { \"action\": \"Downloads\", \"severity\": \"hard\" },\r\n \"ctrl+l\": { \"action\": \"Focus address bar\", \"severity\": \"hard\" },\r\n \"ctrl+n\": { \"action\": \"New window\", \"severity\": \"hard\" },\r\n \"ctrl+o\": { \"action\": \"Open file\", \"severity\": \"hard\" },\r\n \"ctrl+p\": { \"action\": \"Print\", \"severity\": \"hard\" },\r\n \"ctrl+r\": { \"action\": \"Reload\", \"severity\": \"hard\" },\r\n \"ctrl+s\": { \"action\": \"Save page\", \"severity\": \"hard\" },\r\n \"ctrl+t\": { \"action\": \"New tab\", \"severity\": \"hard\" },\r\n \"ctrl+u\": { \"action\": \"View source\", \"severity\": \"hard\" },\r\n \"ctrl+v\": { \"action\": \"Paste\", \"severity\": \"hard\" },\r\n \"ctrl+w\": { \"action\": \"Close tab\", \"severity\": \"hard\" },\r\n \"ctrl+x\": { \"action\": \"Cut\", \"severity\": \"hard\" },\r\n \"ctrl+y\": { \"action\": \"Redo\", \"severity\": \"hard\" },\r\n \"ctrl+z\": { \"action\": \"Undo\", \"severity\": \"hard\" },\r\n \"ctrl+shift+a\": { \"action\": \"Add-ons manager\", \"severity\": \"hard\" },\r\n \"ctrl+shift+b\": { \"action\": \"Bookmarks toolbar\", \"severity\": \"hard\" },\r\n \"ctrl+shift+c\": { \"action\": \"Inspector (element picker)\", \"severity\": \"hard\" },\r\n \"ctrl+shift+d\": { \"action\": \"Bookmark all tabs\", \"severity\": \"hard\" },\r\n \"ctrl+shift+e\": { \"action\": \"Network Monitor\", \"severity\": \"hard\" },\r\n \"ctrl+shift+g\": { \"action\": \"Find previous\", \"severity\": \"find-bar-only\" },\r\n \"ctrl+shift+i\": { \"action\": \"Developer Tools\", \"severity\": \"hard\" },\r\n \"ctrl+shift+j\": { \"action\": \"Browser Console\", \"severity\": \"hard\" },\r\n \"ctrl+shift+k\": { \"action\": \"Web Console\", \"severity\": \"hard\" },\r\n \"ctrl+shift+m\": { \"action\": \"Responsive Design Mode\", \"severity\": \"hard\" },\r\n \"ctrl+shift+n\": { \"action\": \"New private window\", \"severity\": \"hard\" },\r\n \"ctrl+shift+o\": { \"action\": \"Bookmarks library\", \"severity\": \"hard\" },\r\n \"ctrl+shift+p\": { \"action\": \"New private window (alt)\", \"severity\": \"hard\" },\r\n \"ctrl+shift+s\": { \"action\": \"Firefox Screenshot\", \"severity\": \"hard\" },\r\n \"ctrl+shift+t\": { \"action\": \"Reopen closed tab\", \"severity\": \"hard\" },\r\n \"ctrl+shift+v\": { \"action\": \"Paste as plain text\", \"severity\": \"hard\" },\r\n \"ctrl+shift+w\": { \"action\": \"Close window\", \"severity\": \"hard\" },\r\n \"ctrl+shift+y\": { \"action\": \"Downloads (alt)\", \"severity\": \"hard\" },\r\n \"ctrl+shift+z\": { \"action\": \"Debugger\", \"severity\": \"hard\" },\r\n \"alt+f\": { \"action\": \"File menu\", \"severity\": \"menu-activation\" },\r\n \"alt+e\": { \"action\": \"Edit menu\", \"severity\": \"menu-activation\" },\r\n \"alt+v\": { \"action\": \"View menu\", \"severity\": \"menu-activation\" },\r\n \"alt+b\": { \"action\": \"Bookmarks menu\", \"severity\": \"menu-activation\" },\r\n \"alt+t\": { \"action\": \"Tools menu\", \"severity\": \"menu-activation\" },\r\n \"alt+h\": { \"action\": \"Help menu\", \"severity\": \"menu-activation\" },\r\n \"alt+d\": { \"action\": \"Focus address bar\", \"severity\": \"hard\" }\r\n },\r\n \"chrome\": {\r\n \"ctrl+a\": { \"action\": \"Select all\", \"severity\": \"hard\" },\r\n \"ctrl+c\": { \"action\": \"Copy\", \"severity\": \"hard\" },\r\n \"ctrl+d\": { \"action\": \"Bookmark this page\", \"severity\": \"hard\" },\r\n \"ctrl+e\": { \"action\": \"Search from page\", \"severity\": \"hard\" },\r\n \"ctrl+f\": { \"action\": \"Find in page\", \"severity\": \"hard\" },\r\n \"ctrl+g\": { \"action\": \"Find next\", \"severity\": \"hard\" },\r\n \"ctrl+h\": { \"action\": \"History page\", \"severity\": \"hard\" },\r\n \"ctrl+j\": { \"action\": \"Downloads\", \"severity\": \"hard\" },\r\n \"ctrl+k\": { \"action\": \"Search from page\", \"severity\": \"hard\" },\r\n \"ctrl+l\": { \"action\": \"Focus address bar\", \"severity\": \"hard\" },\r\n \"ctrl+n\": { \"action\": \"New window\", \"severity\": \"hard\" },\r\n \"ctrl+o\": { \"action\": \"Open file\", \"severity\": \"hard\" },\r\n \"ctrl+p\": { \"action\": \"Print\", \"severity\": \"hard\" },\r\n \"ctrl+r\": { \"action\": \"Reload\", \"severity\": \"hard\" },\r\n \"ctrl+s\": { \"action\": \"Save page\", \"severity\": \"hard\" },\r\n \"ctrl+t\": { \"action\": \"New tab\", \"severity\": \"hard\" },\r\n \"ctrl+u\": { \"action\": \"View source\", \"severity\": \"hard\" },\r\n \"ctrl+v\": { \"action\": \"Paste\", \"severity\": \"hard\" },\r\n \"ctrl+w\": { \"action\": \"Close tab\", \"severity\": \"hard\" },\r\n \"ctrl+x\": { \"action\": \"Cut\", \"severity\": \"hard\" },\r\n \"ctrl+z\": { \"action\": \"Undo\", \"severity\": \"hard\" },\r\n \"ctrl+shift+b\": { \"action\": \"Bookmarks bar toggle\", \"severity\": \"hard\" },\r\n \"ctrl+shift+d\": { \"action\": \"Bookmark all tabs\", \"severity\": \"hard\" },\r\n \"ctrl+shift+g\": { \"action\": \"Find previous\", \"severity\": \"find-bar-only\" },\r\n \"ctrl+shift+i\": { \"action\": \"DevTools\", \"severity\": \"hard\" },\r\n \"ctrl+shift+j\": { \"action\": \"DevTools (console)\", \"severity\": \"hard\" },\r\n \"ctrl+shift+m\": { \"action\": \"Switch user / guest\", \"severity\": \"hard\" },\r\n \"ctrl+shift+n\": { \"action\": \"Incognito window\", \"severity\": \"hard\" },\r\n \"ctrl+shift+r\": { \"action\": \"Hard reload\", \"severity\": \"hard\" },\r\n \"ctrl+shift+t\": { \"action\": \"Reopen closed tab\", \"severity\": \"hard\" },\r\n \"ctrl+shift+v\": { \"action\": \"Paste as plain text\", \"severity\": \"hard\" },\r\n \"ctrl+shift+w\": { \"action\": \"Close window\", \"severity\": \"hard\" },\r\n \"alt+d\": { \"action\": \"Focus address bar\", \"severity\": \"hard\" },\r\n \"alt+e\": { \"action\": \"Customize menu\", \"severity\": \"menu-activation\" },\r\n \"alt+f\": { \"action\": \"Customize menu (alt)\", \"severity\": \"menu-activation\" }\r\n },\r\n \"edge\": {\r\n \"ctrl+a\": { \"action\": \"Select all\", \"severity\": \"hard\" },\r\n \"ctrl+c\": { \"action\": \"Copy\", \"severity\": \"hard\" },\r\n \"ctrl+d\": { \"action\": \"Favorite this page\", \"severity\": \"hard\" },\r\n \"ctrl+e\": { \"action\": \"Search from page\", \"severity\": \"hard\" },\r\n \"ctrl+f\": { \"action\": \"Find in page\", \"severity\": \"hard\" },\r\n \"ctrl+g\": { \"action\": \"Find next\", \"severity\": \"hard\" },\r\n \"ctrl+h\": { \"action\": \"History\", \"severity\": \"hard\" },\r\n \"ctrl+j\": { \"action\": \"Downloads\", \"severity\": \"hard\" },\r\n \"ctrl+k\": { \"action\": \"Search from page\", \"severity\": \"hard\" },\r\n \"ctrl+l\": { \"action\": \"Focus address bar\", \"severity\": \"hard\" },\r\n \"ctrl+m\": { \"action\": \"Mute current tab\", \"severity\": \"hard\" },\r\n \"ctrl+n\": { \"action\": \"New window\", \"severity\": \"hard\" },\r\n \"ctrl+o\": { \"action\": \"Open file\", \"severity\": \"hard\" },\r\n \"ctrl+p\": { \"action\": \"Print\", \"severity\": \"hard\" },\r\n \"ctrl+r\": { \"action\": \"Reload\", \"severity\": \"hard\" },\r\n \"ctrl+s\": { \"action\": \"Save page\", \"severity\": \"hard\" },\r\n \"ctrl+t\": { \"action\": \"New tab\", \"severity\": \"hard\" },\r\n \"ctrl+u\": { \"action\": \"View source\", \"severity\": \"hard\" },\r\n \"ctrl+v\": { \"action\": \"Paste\", \"severity\": \"hard\" },\r\n \"ctrl+w\": { \"action\": \"Close tab\", \"severity\": \"hard\" },\r\n \"ctrl+x\": { \"action\": \"Cut\", \"severity\": \"hard\" },\r\n \"ctrl+z\": { \"action\": \"Undo\", \"severity\": \"hard\" },\r\n \"ctrl+shift+b\": { \"action\": \"Favorites bar toggle\", \"severity\": \"hard\" },\r\n \"ctrl+shift+d\": { \"action\": \"Bookmark all tabs in folder\", \"severity\": \"hard\" },\r\n \"ctrl+shift+e\": { \"action\": \"Search in sidebar\", \"severity\": \"hard\" },\r\n \"ctrl+shift+g\": { \"action\": \"Find previous\", \"severity\": \"find-bar-only\" },\r\n \"ctrl+shift+i\": { \"action\": \"DevTools\", \"severity\": \"hard\" },\r\n \"ctrl+shift+j\": { \"action\": \"DevTools (console)\", \"severity\": \"hard\" },\r\n \"ctrl+shift+k\": { \"action\": \"Duplicate tab\", \"severity\": \"hard\" },\r\n \"ctrl+shift+l\": { \"action\": \"Paste and search\", \"severity\": \"hard\" },\r\n \"ctrl+shift+m\": { \"action\": \"Switch user / guest\", \"severity\": \"hard\" },\r\n \"ctrl+shift+n\": { \"action\": \"InPrivate window\", \"severity\": \"hard\" },\r\n \"ctrl+shift+o\": { \"action\": \"Open favorites\", \"severity\": \"hard\" },\r\n \"ctrl+shift+p\": { \"action\": \"Print (system dialog)\", \"severity\": \"hard\" },\r\n \"ctrl+shift+r\": { \"action\": \"Hard reload\", \"severity\": \"hard\" },\r\n \"ctrl+shift+t\": { \"action\": \"Reopen closed tab\", \"severity\": \"hard\" },\r\n \"ctrl+shift+u\": { \"action\": \"Read Aloud toggle\", \"severity\": \"hard\" },\r\n \"ctrl+shift+v\": { \"action\": \"Paste without formatting\", \"severity\": \"hard\" },\r\n \"ctrl+shift+w\": { \"action\": \"Close window\", \"severity\": \"hard\" },\r\n \"ctrl+shift+y\": { \"action\": \"Collections\", \"severity\": \"hard\" },\r\n \"alt+d\": { \"action\": \"Focus address bar\", \"severity\": \"hard\" },\r\n \"alt+e\": { \"action\": \"Settings menu\", \"severity\": \"menu-activation\" },\r\n \"alt+f\": { \"action\": \"Settings menu (alt)\", \"severity\": \"menu-activation\" },\r\n \"alt+shift+b\": { \"action\": \"Focus favorites bar\", \"severity\": \"hard\" },\r\n \"alt+shift+i\": { \"action\": \"Send feedback dialog\", \"severity\": \"hard\" },\r\n \"alt+shift+t\": { \"action\": \"Focus app bar toolbar\", \"severity\": \"hard\" }\r\n }\r\n },\r\n \"system\": {\r\n \"meta+a\": { \"action\": \"Action Center\", \"severity\": \"os\" },\r\n \"meta+c\": { \"action\": \"Windows search\", \"severity\": \"os\" },\r\n \"meta+d\": { \"action\": \"Show desktop\", \"severity\": \"os\" },\r\n \"meta+e\": { \"action\": \"File Explorer\", \"severity\": \"os\" },\r\n \"meta+g\": { \"action\": \"Game bar\", \"severity\": \"os\" },\r\n \"meta+h\": { \"action\": \"Voice dictation\", \"severity\": \"os\" },\r\n \"meta+i\": { \"action\": \"Settings\", \"severity\": \"os\" },\r\n \"meta+l\": { \"action\": \"Lock\", \"severity\": \"os\" },\r\n \"meta+n\": { \"action\": \"Notification center\", \"severity\": \"os\" },\r\n \"meta+p\": { \"action\": \"Project / display mode\", \"severity\": \"os\" },\r\n \"meta+r\": { \"action\": \"Run dialog\", \"severity\": \"os\" },\r\n \"meta+s\": { \"action\": \"Search\", \"severity\": \"os\" },\r\n \"meta+v\": { \"action\": \"Clipboard history\", \"severity\": \"os\" },\r\n \"meta+w\": { \"action\": \"Widgets\", \"severity\": \"os\" },\r\n \"meta+x\": { \"action\": \"Quick Link menu\", \"severity\": \"os\" },\r\n \"meta+z\": { \"action\": \"Snap layouts\", \"severity\": \"os\" },\r\n \"meta+tab\": { \"action\": \"Task View\", \"severity\": \"os\" },\r\n \"meta+shift+s\": { \"action\": \"Screenshot region\", \"severity\": \"os\" },\r\n \"ctrl+shift+esc\": { \"action\": \"Task Manager\", \"severity\": \"os\" },\r\n \"ctrl+alt+del\": { \"action\": \"Security screen\", \"severity\": \"os\" },\r\n \"alt+tab\": { \"action\": \"Switch windows\", \"severity\": \"os\" },\r\n \"alt+f4\": { \"action\": \"Close active window\", \"severity\": \"os\" }\r\n }\r\n },\r\n \"linux\": {\r\n \"browsers\": {\r\n \"firefox\": \"$ref:platforms.windows.browsers.firefox\",\r\n \"chrome\": \"$ref:platforms.windows.browsers.chrome\",\r\n \"edge\": \"$ref:platforms.windows.browsers.edge\"\r\n },\r\n \"system\": {\r\n \"$comment\": \"GNOME defaults. KDE and other DEs have similar-shaped reservations but vary; this is a conservative baseline.\",\r\n \"meta+tab\": { \"action\": \"Switch windows\", \"severity\": \"os\" },\r\n \"meta+a\": { \"action\": \"Show applications\", \"severity\": \"os\" },\r\n \"meta+l\": { \"action\": \"Lock screen\", \"severity\": \"os\" },\r\n \"meta+v\": { \"action\": \"Notification list\", \"severity\": \"os\" },\r\n \"alt+tab\": { \"action\": \"Switch applications\", \"severity\": \"os\" },\r\n \"alt+esc\": { \"action\": \"Cycle windows\", \"severity\": \"os\" },\r\n \"alt+f2\": { \"action\": \"Run command\", \"severity\": \"os\" },\r\n \"alt+f4\": { \"action\": \"Close window\", \"severity\": \"os\" },\r\n \"ctrl+alt+tab\": { \"action\": \"Top-bar accessibility switcher\", \"severity\": \"os\" },\r\n \"ctrl+alt+del\": { \"action\": \"Power-off dialog\", \"severity\": \"os\" },\r\n \"ctrl+shift+alt+r\": { \"action\": \"Toggle screencast recording\", \"severity\": \"os\" }\r\n },\r\n \"noteForCtrlAlt\": \"Some Linux setups map right-Alt (AltGr) to 'compose' for typing accented characters, in which case AltGr+letter is reported as ctrl+alt+letter and types a special character. Avoid the ctrl+alt+letter namespace on Linux.\"\r\n }\r\n }\r\n}\r\n", "// reservations.js\r\n// Browser/OS hotkey reservation lookup for hotkey-router.\r\n//\r\n// At bind time, we look up the requested combo against a table of known\r\n// browser- and OS-level shortcuts and emit a console.warn/info if the host\r\n// will intercept it before the page sees the keydown. Soft warning only \u2014\r\n// never throws, never blocks the bind.\r\n//\r\n// Data file: data/browser-hotkeys.json. Schema documented in that file's\r\n// `$keyFormat` / `$comment` fields. Severity tiers determine warn vs info.\r\n\r\nimport HOTKEY_DATA from './data/browser-hotkeys.json' with { type: 'json' }\r\n\r\nconst SUPPORTED_SCHEMA = '1.0'\r\n\r\n// Severities that mean \"combo will not reach page world.\"\r\nconst HARD_SEVERITIES = new Set(['hard', 'os', 'menu-activation'])\r\n\r\n// Severities that mean \"combo fires in normal browsing, only intercepted in\r\n// narrow contexts (find bar focused, text input focused, devtools open).\"\r\nconst SOFT_SEVERITIES = new Set(['find-bar-only', 'compose', 'system-text', 'devtools-open'])\r\n\r\n// --- platform / browser detection ---------------------------------------------\r\n\r\nexport function detectPlatform(nav = (typeof navigator !== 'undefined' ? navigator : null)) {\r\n if (!nav) return null\r\n const platform = nav.platform || ''\r\n if (/Mac|iPhone|iPad|iPod/.test(platform)) return 'mac'\r\n if (/Win/i.test(platform)) return 'windows'\r\n if (/Linux|X11/i.test(platform)) return 'linux'\r\n // Fall back to userAgent sniffing when navigator.platform is unhelpful\r\n // (e.g. some Chromium builds report empty platform).\r\n const ua = nav.userAgent || ''\r\n if (/Mac OS X/i.test(ua)) return 'mac'\r\n if (/Windows/i.test(ua)) return 'windows'\r\n if (/Linux|X11/i.test(ua)) return 'linux'\r\n return null\r\n}\r\n\r\nexport function detectBrowser(nav = (typeof navigator !== 'undefined' ? navigator : null)) {\r\n if (!nav) return null\r\n const ua = nav.userAgent || ''\r\n // Order matters: Edge UA contains 'Chrome', Chrome UA contains 'Safari'.\r\n if (/Edg\\//.test(ua)) return 'edge'\r\n if (/Firefox/.test(ua)) return 'firefox'\r\n if (/Chrome/.test(ua)) return 'chrome'\r\n if (/Safari/.test(ua)) return 'safari'\r\n return null\r\n}\r\n\r\n// --- data normalization -------------------------------------------------------\r\n\r\n// Canonical modifier order for lookup keys: ctrl, meta, alt, shift, key.\r\n// The data file mostly follows this but has at least one entry that doesn't\r\n// (`ctrl+shift+alt+r` on Linux). Normalize both sides at load and lookup so\r\n// minor inconsistencies don't cause silent misses.\r\nfunction canonicalize(rawKey) {\r\n const parts = String(rawKey).toLowerCase().split('+').map(p => p.trim()).filter(Boolean)\r\n if (!parts.length) return ''\r\n const base = parts[parts.length - 1]\r\n const mods = new Set(parts.slice(0, -1))\r\n const out = []\r\n if (mods.has('ctrl')) out.push('ctrl')\r\n if (mods.has('meta')) out.push('meta')\r\n if (mods.has('alt')) out.push('alt')\r\n if (mods.has('shift')) out.push('shift')\r\n out.push(base)\r\n return out.join('+')\r\n}\r\n\r\n// Resolve $ref pointers (\"$ref:platforms.windows.browsers.chrome\") used by\r\n// the Linux section to dedupe against Windows browser tables.\r\nfunction resolveRef(value, root) {\r\n if (typeof value !== 'string' || !value.startsWith('$ref:')) return value\r\n const path = value.slice('$ref:'.length).split('.')\r\n let node = root\r\n for (const step of path) node = node?.[step]\r\n return node\r\n}\r\n\r\nfunction normalizeTable(table) {\r\n if (!table || typeof table !== 'object') return null\r\n const out = Object.create(null)\r\n for (const [k, v] of Object.entries(table)) {\r\n if (!v || typeof v !== 'object' || !('severity' in v)) continue\r\n out[canonicalize(k)] = v\r\n }\r\n return out\r\n}\r\n\r\n// Precompute normalized lookup tables once at module load. Browsers ship the\r\n// table inline; this keeps per-bind lookup to two Map-ish reads.\r\nfunction buildIndex(data) {\r\n const idx = { platforms: {} }\r\n const platforms = data?.platforms || {}\r\n for (const [platform, pdata] of Object.entries(platforms)) {\r\n const browsers = {}\r\n for (const [name, btable] of Object.entries(pdata.browsers || {})) {\r\n browsers[name] = normalizeTable(resolveRef(btable, data))\r\n }\r\n idx.platforms[platform] = {\r\n browsers,\r\n system: normalizeTable(pdata.system),\r\n }\r\n }\r\n return idx\r\n}\r\n\r\nconst SCHEMA_OK = HOTKEY_DATA?.version?.schema === SUPPORTED_SCHEMA\r\nconst INDEX = SCHEMA_OK ? buildIndex(HOTKEY_DATA) : { platforms: {} }\r\n\r\n// --- lookup-key construction --------------------------------------------------\r\n\r\n// Strip a `KeyboardEvent.code` value down to the bare letter/digit used in the\r\n// data tables. `KeyA` -> `a`, `Digit1` -> `1`. Other codes (`ArrowLeft`,\r\n// `Space`, `F5`) are lowercased as a best-effort fallback.\r\nfunction codeToKey(code) {\r\n if (!code) return null\r\n const letter = /^Key([A-Za-z])$/.exec(code)\r\n if (letter) return letter[1].toLowerCase()\r\n const digit = /^Digit(\\d)$/.exec(code)\r\n if (digit) return digit[1]\r\n return code.toLowerCase()\r\n}\r\n\r\n// Build the canonical lookup key from a hotkey-router parsed combo. Mirrors\r\n// WebRadar's `lookupKey()` but works against the parsed structure rather than\r\n// the raw string, so `mod` is already resolved and `code:KeyX` is normalized.\r\nexport function lookupKeyFromCombo(combo) {\r\n if (!combo) return null\r\n if (combo.bareModifier) return null // bare modifiers aren't tracked in the data\r\n const base = combo.code ? codeToKey(combo.code) : combo.key\r\n if (!base) return null\r\n const parts = []\r\n if (combo.ctrl) parts.push('ctrl')\r\n if (combo.meta) parts.push('meta')\r\n if (combo.alt) parts.push('alt')\r\n if (combo.shift) parts.push('shift')\r\n parts.push(base)\r\n return parts.join('+')\r\n}\r\n\r\n// --- public lookup ------------------------------------------------------------\r\n\r\n/**\r\n * @typedef {'mac' | 'windows' | 'linux'} Platform\r\n * @typedef {'chrome' | 'firefox' | 'safari' | 'edge'} Browser\r\n * @typedef {'hard' | 'hard-fullscreen' | 'soft' | 'soft-warn'} Severity\r\n *\r\n * @typedef {{\r\n * source: 'browser' | 'system',\r\n * platform: Platform,\r\n * browser: Browser | undefined,\r\n * lookupKey: string,\r\n * action: string,\r\n * severity: Severity\r\n * }} Reservation\r\n */\r\n\r\n/**\r\n * Look up whether a parsed hotkey combo is reserved by the host platform\r\n * or browser. Returns `null` when not reserved or when the data table\r\n * hasn't loaded.\r\n *\r\n * @param {object | null} combo parsed combo from `hotkey-router`'s `parseHotkey`\r\n * @param {{ platform?: Platform, browser?: Browser }} [opts]\r\n * @returns {Reservation | null}\r\n */\r\nexport function lookupReservation(combo, { platform, browser } = {}) {\r\n if (!SCHEMA_OK) return null\r\n const lookupKey = lookupKeyFromCombo(combo)\r\n if (!lookupKey) return null\r\n\r\n const pdata = platform && INDEX.platforms[platform]\r\n if (!pdata) return null\r\n\r\n const btable = browser ? pdata.browsers?.[browser] : null\r\n const bclaim = btable?.[lookupKey]\r\n if (bclaim) {\r\n return {\r\n source: 'browser',\r\n platform,\r\n browser,\r\n lookupKey,\r\n action: bclaim.action,\r\n severity: bclaim.severity,\r\n }\r\n }\r\n const sclaim = pdata.system?.[lookupKey]\r\n if (sclaim) {\r\n return {\r\n source: 'system',\r\n platform,\r\n browser,\r\n lookupKey,\r\n action: sclaim.action,\r\n severity: sclaim.severity,\r\n }\r\n }\r\n return null\r\n}\r\n\r\n// --- warning emission ---------------------------------------------------------\r\n\r\nconst PLATFORM_LABEL = { mac: 'macOS', windows: 'Windows', linux: 'Linux' }\r\n\r\n/** @param {Severity | string} severity @returns {boolean} */\r\nexport function severityIsHard(severity) {\r\n return HARD_SEVERITIES.has(severity)\r\n}\r\n\r\n/** @param {Severity | string} severity @returns {boolean} */\r\nexport function severityIsSoft(severity) {\r\n return SOFT_SEVERITIES.has(severity)\r\n}\r\n\r\n/**\r\n * Render a console-friendly warning string for a reservation.\r\n *\r\n * @param {Reservation} reservation\r\n * @param {string} rawHotkey\r\n * @returns {string}\r\n */\r\nexport function formatReservationWarning(reservation, rawHotkey) {\r\n const platformLabel = PLATFORM_LABEL[reservation.platform] || reservation.platform\r\n const sourceLabel = reservation.source === 'browser'\r\n ? `${reservation.browser} on ${platformLabel}`\r\n : `${platformLabel}`\r\n const tag = severityIsHard(reservation.severity)\r\n ? 'will not fire'\r\n : 'fires in normal browsing'\r\n return `[hotkey-router] \"${rawHotkey}\" (${reservation.lookupKey}) reserved by ${sourceLabel}: \"${reservation.action}\" [${reservation.severity}] \u2014 ${tag}.`\r\n}\r\n\r\n/**\r\n * Emit a reservation warning via the given console (or the global `console`\r\n * by default). Hard reservations log via `warn`; soft ones via `info`.\r\n *\r\n * @param {Reservation} reservation\r\n * @param {string} rawHotkey\r\n * @param {Console} [console_]\r\n * @returns {void}\r\n */\r\nexport function emitReservationWarning(reservation, rawHotkey, console_ = console) {\r\n const msg = formatReservationWarning(reservation, rawHotkey)\r\n const fn = severityIsHard(reservation.severity) ? console_.warn : console_.info\r\n fn.call(console_, msg)\r\n}\r\n\r\n// --- installer ----------------------------------------------------------------\r\n//\r\n// Wire reservation warnings into a hotkey-router instance. Importing this\r\n// function is the opt-in: bundlers that don't see this import tree-shake the\r\n// entire ~5 KB data table out of the build.\r\n//\r\n// import hotkeys from 'hotkey-router'\r\n// import { installReservationWarnings } from 'hotkey-router/reservations'\r\n// installReservationWarnings(hotkeys)\r\n//\r\n// Returns an `uninstall()` function. Per-bind opt-out still works:\r\n// hotkeys.bind('meta+shift+f', fn, null, { warnOnReserved: false })\r\n//\r\n// Options:\r\n// platform \u2014 override auto-detected 'mac' | 'windows' | 'linux'\r\n// browser \u2014 override auto-detected 'firefox' | 'chrome' | 'safari' | 'edge'\r\n// console \u2014 inject a custom console-like object (used by tests)\r\n/**\r\n * @param {object} hotkeys a hotkey-router default-export instance\r\n * @param {{\r\n * platform?: Platform,\r\n * browser?: Browser,\r\n * console?: Console\r\n * }} [opts]\r\n * @returns {() => void} uninstall function\r\n */\r\nexport function installReservationWarnings(hotkeys, opts = {}) {\r\n if (!hotkeys || typeof hotkeys.onBind !== 'function') {\r\n throw new TypeError(\r\n 'installReservationWarnings(hotkeys) requires a hotkey-router instance with onBind() (>= v0.2.0)'\r\n )\r\n }\r\n const platform = opts.platform !== undefined ? opts.platform : detectPlatform()\r\n const browser = opts.browser !== undefined ? opts.browser : detectBrowser()\r\n const console_ = opts.console || console\r\n\r\n return hotkeys.onBind(({ combo, raw, options }) => {\r\n if (options?.warnOnReserved === false) return\r\n if (!platform || !browser) return\r\n const reservation = lookupReservation(combo, { platform, browser })\r\n if (reservation) emitReservationWarning(reservation, raw, console_)\r\n })\r\n}\r\n\r\nexport const SCHEMA_VERSION = HOTKEY_DATA?.version?.schema\r\nexport const DATA_GENERATED = HOTKEY_DATA?.version?.generated\r\nexport { HOTKEY_DATA }\r\n"],
|
|
5
5
|
"mappings": "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",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
package/dist/sites.js
ADDED
|
@@ -0,0 +1,185 @@
|
|
|
1
|
+
// hotkey-router v0.3.0 | SEE LICENSE IN LICENSE
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
// data/site-hotkeys.runtime.json
|
|
5
|
+
var site_hotkeys_runtime_default = { $comment: "Generated from data/site-hotkeys.json (the full, sourced table). Runtime projection used by sites.js; do not edit by hand.", version: { researched: "2026-10-03", schema: "1.0", method: "Vendor help pages and keymap source, read by research agents (often through a summarizing fetch). verified=true means read on the vendor page or source in that session; false means a secondary source or inference. Sites the agents could not read have researched=false and no rows." }, sites: [{ id: "google-docs", name: "Google Docs", hosts: ["docs.google.com"], pathPrefixes: ["/document/"], shortcuts: [["ctrl+shift+v", "meta+shift+v", "ctrl+shift+v", "Paste without formatting", 1], ["ctrl+shift+z", "meta+shift+z", "ctrl+shift+z", "Redo", 1], ["ctrl+shift+g", "meta+shift+g", "ctrl+shift+g", "Find previous", 1], ["ctrl+shift+f", "ctrl+shift+f", "ctrl+shift+f", "Hide menus (compact mode)", 1], ["ctrl+shift+period", "meta+shift+period", "ctrl+shift+period", "Increase font size", 1], ["ctrl+shift+comma", "meta+shift+comma", "ctrl+shift+comma", "Decrease font size", 1], ["ctrl+shift+k", "alt+shift+k", null, "Small caps", 1], ["ctrl+shift+l", "meta+shift+l", "ctrl+shift+l", "Left align", 1], ["ctrl+shift+e", "meta+shift+e", "ctrl+shift+e", "Center align", 1], ["ctrl+shift+r", "meta+shift+r", "ctrl+shift+r", "Right align", 1], ["ctrl+shift+j", "meta+shift+j", "ctrl+shift+j", "Justify", 1], ["ctrl+shift+7", "meta+shift+7", "ctrl+shift+7", "Numbered list", 1], ["ctrl+shift+8", "meta+shift+8", "ctrl+shift+8", "Bulleted list", 1], ["ctrl+shift+9", "meta+shift+9", null, "Checklist", 1], ["ctrl+shift+arrowup", "ctrl+shift+arrowup", null, "Move paragraph up", 1], ["ctrl+shift+arrowdown", "ctrl+shift+arrowdown", null, "Move paragraph down", 1], ["ctrl+shift+x", null, "ctrl+shift+x", "Context (right-click) menu", 1], ["ctrl+shift+backslash", "meta+shift+backslash", null, "Context (right-click) menu (alternate)", 1], ["ctrl+shift+y", "meta+shift+y", "ctrl+shift+y", "Open dictionary", 1], ["ctrl+shift+c", "meta+shift+c", "ctrl+shift+c", "Word count", 1], ["ctrl+shift+s", "meta+shift+s", "ctrl+shift+s", "Start voice typing", 1], [null, "meta+shift+h", null, "Find and replace (Mac form)", 1], ["ctrl+shift+arrowleft", null, "ctrl+shift+arrowleft", "Extend selection one word left", 1], ["ctrl+shift+arrowright", null, "ctrl+shift+arrowright", "Extend selection one word right", 1], ["ctrl+shift+home", "meta+shift+arrowup", null, "Extend selection to document start", 1], ["ctrl+shift+end", "meta+shift+arrowdown", null, "Extend selection to document end", 1], ["ctrl+shift+pagedown", null, null, "Move to next tab", 1], ["ctrl+shift+pageup", null, null, "Move to previous tab", 1], [null, "meta+shift+k", null, "Toggle input controls", 1], ["ctrl+alt+1", "meta+alt+1", "ctrl+alt+1", "Apply heading style 1", 1], ["ctrl+alt+2", "meta+alt+2", "ctrl+alt+2", "Apply heading style 2", 1], ["ctrl+alt+3", "meta+alt+3", "ctrl+alt+3", "Apply heading style 3", 1], ["ctrl+alt+4", "meta+alt+4", "ctrl+alt+4", "Apply heading style 4", 1], ["ctrl+alt+5", "meta+alt+5", "ctrl+alt+5", "Apply heading style 5", 1], ["ctrl+alt+6", "meta+alt+6", "ctrl+alt+6", "Apply heading style 6", 1], ["ctrl+alt+0", "meta+alt+0", "ctrl+alt+0", "Apply normal text style", 1], ["ctrl+alt+y", "meta+alt+y", "ctrl+alt+y", "Alt text", 1], ["ctrl+alt+k", "ctrl+meta+k", "ctrl+alt+k", "Resize larger (drawing)", 1], ["ctrl+alt+b", "ctrl+meta+b", "ctrl+alt+b", "Resize larger horizontally (drawing)", 1], ["ctrl+alt+i", "ctrl+meta+i", "ctrl+alt+i", "Resize larger vertically (drawing)", 1], ["ctrl+alt+j", "ctrl+meta+j", "ctrl+alt+j", "Resize smaller (drawing)", 1], ["ctrl+alt+w", "ctrl+meta+w", "ctrl+alt+w", "Resize smaller horizontally (drawing)", 1], ["ctrl+alt+q", "ctrl+meta+q", "ctrl+alt+q", "Resize smaller vertically (drawing)", 1], ["ctrl+alt+m", "meta+alt+m", "ctrl+alt+m", "Insert comment", 1], ["ctrl+alt+f", "meta+alt+f", "ctrl+alt+f", "Insert footnote", 1], ["ctrl+alt+c", "meta+alt+c", "ctrl+alt+c", "Copy text formatting", 1], ["ctrl+alt+v", "meta+alt+v", "ctrl+alt+v", "Paste text formatting", 1], ["ctrl+alt+x", "meta+alt+x", null, "Open spelling and grammar", 1], ["ctrl+alt+z", "meta+alt+z", "ctrl+alt+z", "Enable screen reader support", 1], ["ctrl+alt+h", "meta+alt+h", "ctrl+alt+h", "Enable braille support", 1], ["ctrl+alt+enter", "meta+alt+enter", "ctrl+alt+enter", "Toggle checkbox", 1], ["ctrl+alt+period", "meta+alt+period", "alt+shift+period", "Go to side panel", 1], ["ctrl+alt+comma", "meta+alt+comma", "alt+shift+comma", "Go to side panel (alternate)", 1], ["ctrl+alt+k", null, "ctrl+alt+k", "Move to next edit", 1], ["ctrl+alt+j", null, "ctrl+alt+j", "Move to previous edit", 1], ["alt+shift+5", "meta+shift+x", "alt+shift+5", "Strikethrough", 1], ["alt+shift+arrowleft", "alt+shift+arrowleft", "alt+shift+arrowleft", "Rotate counterclockwise 1 degree (drawing)", 1], ["alt+shift+arrowright", "alt+shift+arrowright", "alt+shift+arrowright", "Rotate clockwise 1 degree (drawing)", 1], ["alt+shift+backquote", null, "alt+shift+backquote", "Enable screen reader support (alternate)", 1], [null, "alt+shift+arrowup", null, "Extend selection one paragraph up", 1], [null, "alt+shift+arrowdown", null, "Extend selection one paragraph down", 1], ["alt+shift+f", "ctrl+alt+f", null, "File menu", 1], ["alt+shift+e", "ctrl+alt+e", null, "Edit menu", 1], ["alt+shift+v", "ctrl+alt+v", null, "View menu", 1], ["alt+shift+i", "ctrl+alt+i", null, "Insert menu", 1], ["alt+shift+o", "ctrl+alt+o", null, "Format menu", 1], ["alt+shift+t", "ctrl+alt+t", null, "Tools menu", 1], ["alt+shift+h", "ctrl+alt+h", null, "Help menu", 1], ["alt+shift+a", "ctrl+alt+a", null, "Accessibility menu", 1], ["ctrl+alt+shift+a", "meta+alt+shift+a", "ctrl+alt+shift+a", "Open discussion thread / comment history", 1], ["ctrl+alt+shift+k", "meta+alt+shift+k", "ctrl+alt+shift+k", "Input Tools menu", 1], ["ctrl+alt+shift+r", "meta+alt+shift+r", "ctrl+alt+shift+r", "Show live edits", 1], ["ctrl+alt+shift+m", "meta+alt+shift+m", "ctrl+alt+shift+m", "Move focus out of editing area", 1], ["ctrl+alt+shift+z", "meta+alt+shift+z", "ctrl+alt+shift+z", "Switch to editing", 1], ["ctrl+alt+shift+x", "meta+alt+shift+x", "ctrl+alt+shift+x", "Switch to suggesting", 1], ["ctrl+alt+shift+c", "meta+alt+shift+c", "ctrl+alt+shift+c", "Switch to viewing", 1], ["ctrl+alt+shift+h", "meta+alt+shift+h", "ctrl+alt+shift+h", "Open revision history", 1], ["ctrl+alt+shift+i", "meta+alt+shift+i", "ctrl+alt+shift+i", "Open Explore tool", 1], ["ctrl+alt+shift+arrowleft", "ctrl+meta+shift+arrowleft", "ctrl+alt+shift+arrowleft", "Select multiple text sections (left)", 1], ["ctrl+alt+shift+arrowright", "ctrl+meta+shift+arrowright", "ctrl+alt+shift+arrowright", "Select multiple text sections (right)", 1]] }, { id: "google-slides", name: "Google Slides", hosts: ["docs.google.com"], pathPrefixes: ["/presentation/"], shortcuts: [["ctrl+shift+z", "meta+shift+z", "ctrl+shift+z", "Redo", 1], ["ctrl+shift+g", "meta+shift+g", "ctrl+shift+g", "Find previous", 1], ["ctrl+shift+f", "ctrl+shift+f", "ctrl+shift+f", "Hide or show menus", 1], ["ctrl+shift+c", "meta+shift+c", "ctrl+shift+c", "Turn on captions", 1], ["ctrl+shift+backslash", "meta+shift+backslash", null, "Context menu", 1], ["ctrl+shift+x", null, "ctrl+shift+x", "Context menu (alternate)", 1], ["ctrl+shift+arrowup", "meta+shift+arrowup", "ctrl+shift+arrowup", "Move slide to beginning / Bring to front", 1], ["ctrl+shift+arrowdown", "meta+shift+arrowdown", "ctrl+shift+arrowdown", "Move slide to end / Send to back", 1], ["ctrl+shift+period", "meta+shift+period", "ctrl+shift+period", "Increase font size / playback rate", 1], ["ctrl+shift+comma", "meta+shift+comma", "ctrl+shift+comma", "Decrease font size / playback rate", 1], ["ctrl+shift+l", "meta+shift+l", null, "Left align", 1], ["ctrl+shift+r", "meta+shift+r", "ctrl+shift+r", "Right align", 1], ["ctrl+shift+e", "meta+shift+e", "ctrl+shift+e", "Center align", 1], ["ctrl+shift+j", "meta+shift+j", "ctrl+shift+j", "Justify", 1], ["ctrl+shift+8", "meta+shift+8", "ctrl+shift+8", "Bulleted list", 1], ["ctrl+shift+7", "meta+shift+7", "ctrl+shift+7", "Numbered list", 1], ["ctrl+shift+k", "meta+shift+k", "ctrl+shift+k", "Toggle input controls", 1], [null, "meta+shift+h", null, "Find and replace (Mac form)", 1], [null, "meta+shift+f", null, "Toggle full screen (present, Mac form)", 1], ["ctrl+alt+c", "meta+alt+c", "ctrl+alt+c", "Copy formatting", 1], ["ctrl+alt+v", "meta+alt+v", "ctrl+alt+v", "Paste formatting", 1], ["ctrl+alt+y", "meta+alt+y", "ctrl+alt+y", "Alt text", 1], ["ctrl+alt+m", "meta+alt+m", "ctrl+alt+m", "Insert comment", 1], ["ctrl+alt+g", "meta+alt+g", "ctrl+alt+g", "Group", 1], ["ctrl+alt+b", "ctrl+meta+b", "ctrl+alt+b", "Resize larger horizontally", 1], ["ctrl+alt+i", "ctrl+meta+i", "ctrl+alt+i", "Resize larger vertically", 1], ["ctrl+alt+j", "ctrl+meta+j", "ctrl+alt+j", "Resize smaller", 1], ["ctrl+alt+k", "ctrl+meta+k", "ctrl+alt+k", "Resize larger", 1], ["ctrl+alt+w", "ctrl+meta+w", "ctrl+alt+w", "Resize smaller horizontally", 1], ["ctrl+alt+9", null, "ctrl+alt+9", "Resize smaller vertically", 1], ["ctrl+alt+x", "ctrl+meta+x", "ctrl+alt+x", "Verbalize selection", 1], ["ctrl+alt+r", "ctrl+meta+r", "ctrl+alt+r", "Verbalize from cursor", 1], ["ctrl+alt+z", "meta+alt+z", "ctrl+alt+z", "Enable screen reader", 1], ["ctrl+alt+h", "meta+alt+h", "ctrl+alt+h", "Enable braille", 1], ["ctrl+alt+period", "meta+alt+period", "alt+shift+period", "Go to side panel", 1], ["ctrl+alt+comma", "meta+alt+comma", "alt+shift+comma", "Go to side panel (alternate)", 1], ["alt+shift+5", "meta+shift+x", "alt+shift+5", "Strikethrough", 1], ["alt+shift+arrowdown", "alt+shift+arrowdown", null, "Move paragraph down", 1], ["alt+shift+arrowup", "alt+shift+arrowup", null, "Move paragraph up", 1], ["alt+shift+arrowleft", "alt+shift+arrowleft", "alt+shift+arrowleft", "Rotate counterclockwise 1 degree", 1], ["alt+shift+arrowright", "alt+shift+arrowright", "alt+shift+arrowright", "Rotate clockwise 1 degree", 1], ["alt+shift+backquote", null, "alt+shift+backquote", "Enable screen reader (alternate)", 1], ["alt+shift+f", null, null, "File menu", 1], ["alt+shift+e", null, null, "Edit menu", 1], ["alt+shift+v", null, null, "View menu", 1], ["alt+shift+i", null, null, "Insert menu", 1], ["alt+shift+o", null, null, "Format menu", 1], ["alt+shift+t", null, null, "Tools menu", 1], ["alt+shift+h", null, null, "Help menu", 1], ["alt+shift+a", null, null, "Accessibility menu", 1], ["ctrl+alt+shift+f", "meta+alt+shift+f", "ctrl+alt+shift+f", "Move to filmstrip", 1], ["ctrl+alt+shift+c", "meta+alt+shift+c", "ctrl+alt+shift+c", "Move to canvas", 1], ["ctrl+alt+shift+s", "meta+alt+shift+s", "ctrl+alt+shift+s", "Open speaker notes", 1], ["ctrl+alt+shift+p", "meta+alt+shift+p", "ctrl+alt+shift+p", "HTML view", 1], ["ctrl+alt+shift+b", "meta+alt+shift+b", "ctrl+alt+shift+b", "Open animations", 1], ["ctrl+alt+shift+i", "meta+alt+shift+i", "ctrl+alt+shift+i", "Open Explore", 1], ["ctrl+alt+shift+a", "meta+alt+shift+a", "ctrl+alt+shift+a", "Open comment thread", 1], ["ctrl+alt+shift+j", "meta+alt+shift+j", "ctrl+alt+shift+j", "Hide comment", 1], ["ctrl+alt+shift+g", "meta+alt+shift+g", "ctrl+alt+shift+g", "Ungroup", 1], ["ctrl+alt+shift+k", "meta+alt+shift+k", "ctrl+alt+shift+k", "Input tools menu", 1], ["ctrl+alt+shift+h", "meta+alt+shift+h", null, "Revision history", 1]] }, { id: "gmail", name: "Gmail", hosts: ["mail.google.com"], pathPrefixes: [], shortcuts: [["ctrl+shift+c", "meta+shift+c", "ctrl+shift+c", "Add cc recipients", 1], ["ctrl+shift+b", "meta+shift+b", "ctrl+shift+b", "Add bcc recipients", 1], ["ctrl+shift+f", "meta+shift+f", "ctrl+shift+f", "Access custom From", 1], ["ctrl+shift+5", "meta+shift+5", "ctrl+shift+5", "Previous font", 1], ["ctrl+shift+6", "meta+shift+6", "ctrl+shift+6", "Next font", 1], ["ctrl+shift+minus", "meta+shift+minus", "ctrl+shift+minus", "Decrease text size", 1], ["ctrl+shift+equal", "meta+shift+equal", "ctrl+shift+equal", "Increase text size", 1], ["ctrl+shift+7", "meta+shift+7", "ctrl+shift+7", "Numbered list", 1], ["ctrl+shift+8", "meta+shift+8", "ctrl+shift+8", "Bulleted list", 1], ["ctrl+shift+9", "meta+shift+9", "ctrl+shift+9", "Quote", 1], ["ctrl+shift+l", "meta+shift+l", "ctrl+shift+l", "Align left", 1], ["ctrl+shift+e", "meta+shift+e", "ctrl+shift+e", "Align center", 1], ["ctrl+shift+r", "meta+shift+r", "ctrl+shift+r", "Align right", 1], ["ctrl+alt+comma", "meta+alt+comma", "ctrl+alt+comma", "Switch between Calendar/Keep/Tasks sidebar and inbox", 1], ["ctrl+alt+period", "meta+alt+period", "ctrl+alt+period", "Switch between Calendar/Keep/Tasks sidebar and inbox (alternate)", 1]] }, { id: "google-keep", name: "Google Keep", hosts: ["keep.google.com"], pathPrefixes: [], shortcuts: [["ctrl+shift+8", "meta+shift+8", "ctrl+shift+8", "Toggle checkboxes", 1]] }, { id: "word-web", name: "Word for the web", hosts: ["word.cloud.microsoft", "*.officeapps.live.com", "onedrive.live.com", "sharepoint.com"], pathPrefixes: [], shortcuts: [["ctrl+shift+f6", null, null, "Move between ribbon and document content (Ctrl+F6 also)", 1], ["ctrl+shift+arrowright", null, null, "Select right one word", 1], ["ctrl+shift+arrowleft", null, null, "Select left one word", 1], ["ctrl+shift+arrowup", null, null, "Select up one paragraph", 1], ["ctrl+shift+arrowdown", null, null, "Select down one paragraph", 1], ["ctrl+shift+home", null, null, "Select to beginning of document", 1], ["ctrl+shift+end", null, null, "Select to end of document", 1], ["ctrl+alt+g", null, null, "Select image", 0], ["alt+shift+arrowleft", null, null, "Outdent / select left by word", 0], ["alt+shift+arrowright", null, null, "Indent", 0], ["ctrl+alt+shift+tab", null, null, "Task Switcher", 0]] }, { id: "outlook-web", name: "Outlook on the web", hosts: ["outlook.office.com", "outlook.live.com", "outlook.cloud.microsoft", "outlook.office365.com"], pathPrefixes: [], shortcuts: [["ctrl+shift+r", null, null, "Reply all", 1], ["ctrl+shift+f", null, null, "Forward message", 1], ["ctrl+shift+2", null, null, "Go to calendar", 1], ["ctrl+shift+1", null, null, "Go to mail / Inbox", 0], ["ctrl+alt+arrowleft", null, null, "Calendar: previous day/period", 1], ["ctrl+alt+arrowright", null, null, "Calendar: next day/period", 1], ["ctrl+alt+1", null, null, "Calendar: Day view", 1], ["ctrl+alt+2", null, null, "Calendar: Week / work week view", 1], ["ctrl+alt+4", null, null, "Calendar: Month view", 1], ["alt+shift+y", null, null, "Calendar: go to today", 1], ["alt+shift+1", null, null, "Calendar: Day view (shift+alt set)", 1], ["alt+shift+2", null, null, "Calendar: Work week view", 1], ["alt+shift+3", null, null, "Calendar: Full week view", 1], ["alt+shift+4", null, null, "Calendar: Month view", 1]] }, { id: "teams-web", name: "Microsoft Teams (web)", hosts: ["teams.microsoft.com", "teams.live.com", "teams.cloud.microsoft"], pathPrefixes: [], shortcuts: [["ctrl+shift+f", "meta+shift+f", null, "Open filter", 0], ["ctrl+shift+n", "meta+shift+n", null, "Start chat in new window (desktop; browser reserves new incognito window)", 0], ["ctrl+shift+x", "meta+shift+x", null, "Expand compose box", 0], ["ctrl+shift+c", "meta+shift+c", null, "Insert inline code", 0], ["ctrl+shift+b", "meta+shift+b", null, "Insert code block", 0], ["ctrl+shift+i", "meta+shift+i", null, "Mark message important", 0], ["ctrl+shift+a", "meta+shift+a", null, "Accept video call", 0], ["ctrl+shift+s", null, null, "Accept audio call", 0], ["ctrl+shift+d", "meta+shift+d", null, "Decline call", 0], ["ctrl+shift+m", "meta+shift+m", null, "Toggle mute", 0], ["ctrl+shift+u", null, null, "Toggle speaker", 0], ["ctrl+shift+o", "meta+shift+o", null, "Toggle video", 0], ["ctrl+shift+e", "meta+shift+e", null, "Toggle share tray", 0], ["ctrl+shift+h", "meta+shift+h", null, "End call", 0], ["ctrl+shift+k", "meta+shift+k", null, "Raise/lower hand", 0], ["ctrl+shift+l", "meta+shift+l", null, "Announce raised hands", 0], ["ctrl+shift+y", "meta+shift+y", null, "Admit from lobby", 0], ["ctrl+shift+j", null, null, "Join from meeting toast", 0], ["ctrl+shift+r", null, null, "Open meeting chat from notification", 0], ["ctrl+shift+q", null, null, "Create meeting request", 0], ["ctrl+shift+1", null, null, "Download diagnostic logs (also: opens 1st app on web per page note)", 0], ["ctrl+alt+enter", null, null, "Move focus to pane divider", 0], ["ctrl+alt+r", "meta+alt+r", null, "React to last message", 0], ["ctrl+alt+u", "meta+alt+u", null, "See all unread chats", 0], ["ctrl+alt+c", "meta+alt+c", null, "See all chats", 0], ["ctrl+alt+a", "meta+alt+a", null, "See all channel conversations", 0], ["ctrl+alt+b", "meta+alt+b", null, "See all meeting chats", 0], ["ctrl+alt+z", "meta+alt+z", null, "Clear all filters", 0], ["ctrl+alt+p", "meta+alt+p", null, "Paragraph style", 0], ["ctrl+alt+4", null, null, "Insert block quote", 0], ["ctrl+alt+x", null, null, "Strikethrough", 0], ["ctrl+alt+l", "meta+alt+l", null, "Add Loop paragraph", 0], ["ctrl+alt+5", "meta+alt+4", null, "Insert code", 0], ["ctrl+alt+1", "meta+alt+1", null, "Heading 1", 0], ["ctrl+alt+2", "meta+alt+2", null, "Heading 2", 0], ["ctrl+alt+3", "meta+alt+3", null, "Heading 3", 0], ["ctrl+alt+f", null, null, "Forward an event", 0], ["ctrl+alt+k", null, null, "Mark all as read (Activity)", 0], ["ctrl+alt+m", null, null, "Filter activity to mentions", 0], ["ctrl+alt+arrowleft", null, null, "Calendar previous day/week", 0], ["ctrl+alt+arrowright", null, null, "Calendar next day/week", 0], ["alt+shift+r", "meta+shift+r", null, "Reply to last message", 0], ["alt+shift+o", "meta+alt+o", null, "Attach file", 0], ["alt+shift+e", null, null, "Open video recorder", 0], ["alt+shift+a", null, null, "Start audio call", 0], ["alt+shift+v", null, null, "Start video call", 0], ["alt+shift+equal", "meta+alt+equal", null, "Zoom in shared content", 0], ["alt+shift+minus", "meta+alt+minus", null, "Zoom out shared content", 0], ["alt+shift+0", "meta+alt+0", null, "Reset zoom", 0], ["alt+shift+arrowup", "meta+alt+arrowup", null, "Pan up", 0], ["alt+shift+arrowdown", "meta+alt+arrowdown", null, "Pan down", 0], ["alt+shift+arrowleft", "meta+alt+arrowleft", null, "Pan left", 0], ["alt+shift+arrowright", "meta+alt+arrowright", null, "Pan right", 0], ["alt+shift+j", null, null, "Join from meeting details", 0], ["alt+shift+s", null, null, "Go to suggested time", 0], ["alt+shift+1", null, null, "Day view", 0], ["alt+shift+2", null, null, "Work week view", 0], ["alt+shift+3", null, null, "Week view", 0], ["alt+shift+4", null, null, "Month view", 0], ["alt+shift+5", null, null, "Agenda in month view", 0], ["alt+shift+y", null, null, "Go to today", 0], ["ctrl+alt+shift+r", "meta+alt+shift+r", null, "Report a problem", 0], ["ctrl+alt+shift+1", null, null, "Download diagnostic logs", 0]] }, { id: "onenote-web", name: "OneNote for the web", hosts: ["onenote.cloud.microsoft", "www.onenote.com", "*.officeapps.live.com", "onedrive.live.com"], pathPrefixes: [], shortcuts: [["ctrl+shift+f", null, null, "Create a new outline", 1], ["alt+shift+arrowright", null, null, "Increase paragraph indent", 1], ["alt+shift+arrowleft", null, null, "Decrease paragraph indent", 1]] }, { id: "notion", name: "Notion", hosts: ["www.notion.so", "www.notion.com"], pathPrefixes: [], shortcuts: [["ctrl+shift+n", "meta+shift+n", "ctrl+shift+n", "Open a new Notion window", 1], ["ctrl+shift+l", "meta+shift+l", "ctrl+shift+l", "Toggle dark/light mode", 1], ["ctrl+shift+m", "meta+shift+m", "ctrl+shift+m", "Create a comment", 1], ["ctrl+shift+s", "meta+shift+s", "ctrl+shift+s", "Strikethrough", 1], ["ctrl+shift+u", "meta+shift+u", "ctrl+shift+u", "Go up one level in page hierarchy", 1], ["ctrl+shift+h", "meta+shift+h", "ctrl+shift+h", "Apply last used text or highlight color", 1], [null, "ctrl+shift+k", null, "Previous database page in peek view", 1], [null, "ctrl+shift+j", null, "Next database page in peek view", 1], ["ctrl+shift+arrowup", "meta+shift+arrowup", "ctrl+shift+arrowup", "Move selected block(s) up", 1], ["ctrl+shift+arrowdown", "meta+shift+arrowdown", "ctrl+shift+arrowdown", "Move selected block(s) down", 1], ["ctrl+shift+arrowleft", "meta+shift+arrowleft", "ctrl+shift+arrowleft", "Move/outdent selected block(s)", 0], ["ctrl+shift+arrowright", "meta+shift+arrowright", "ctrl+shift+arrowright", "Move/indent selected block(s)", 0], ["ctrl+shift+t", "meta+alt+t", "ctrl+shift+t", "Expand or close all toggles in a toggle list", 1], ["ctrl+shift+0", "meta+alt+0", "ctrl+shift+0", "Turn block into text/heading/to-do/list/code/page (digit)", 1], ["ctrl+shift+1", "meta+alt+1", "ctrl+shift+1", "Turn block into text/heading/to-do/list/code/page (digit)", 1], ["ctrl+shift+2", "meta+alt+2", "ctrl+shift+2", "Turn block into text/heading/to-do/list/code/page (digit)", 1], ["ctrl+shift+3", "meta+alt+3", "ctrl+shift+3", "Turn block into text/heading/to-do/list/code/page (digit)", 1], ["ctrl+shift+4", "meta+alt+4", "ctrl+shift+4", "Turn block into text/heading/to-do/list/code/page (digit)", 1], ["ctrl+shift+5", "meta+alt+5", "ctrl+shift+5", "Turn block into text/heading/to-do/list/code/page (digit)", 1], ["ctrl+shift+6", "meta+alt+6", "ctrl+shift+6", "Turn block into text/heading/to-do/list/code/page (digit)", 1], ["ctrl+shift+7", "meta+alt+7", "ctrl+shift+7", "Turn block into text/heading/to-do/list/code/page (digit)", 1], ["ctrl+shift+8", "meta+alt+8", "ctrl+shift+8", "Turn block into text/heading/to-do/list/code/page (digit)", 1], ["ctrl+shift+9", "meta+alt+9", "ctrl+shift+9", "Turn block into text/heading/to-do/list/code/page (digit)", 1]] }, { id: "slack", name: "Slack", hosts: ["app.slack.com"], pathPrefixes: ["/client/"], shortcuts: [["ctrl+shift+k", "meta+shift+k", "ctrl+shift+k", "Compose new message / Browse DMs", 1], ["ctrl+shift+2", null, "ctrl+shift+2", "Browse DMs (Windows row)", 1], ["ctrl+shift+y", "meta+shift+y", "ctrl+shift+y", "Set status", 1], ["ctrl+shift+n", "meta+shift+n", "ctrl+shift+n", "Create new canvas", 1], ["ctrl+shift+j", "meta+shift+j", "ctrl+shift+j", "View downloaded files", 1], ["ctrl+shift+enter", "meta+shift+enter", "ctrl+shift+enter", "Create snippet", 1], ["ctrl+shift+backquote", "meta+shift+backquote", "ctrl+shift+backquote", "Add emoji reaction", 1], ["ctrl+shift+backslash", "meta+shift+backslash", "ctrl+shift+backslash", "Add emoji reaction (layout variant)", 1], ["ctrl+shift+h", "meta+shift+h", "ctrl+shift+h", "Start/join/leave huddle (canvas: find and replace)", 1], ["ctrl+shift+space", "meta+shift+space", "ctrl+shift+space", "Toggle huddle mute", 1], ["ctrl+shift+w", "meta+shift+w", "ctrl+shift+w", "Reopen last closed window", 1], ["ctrl+shift+e", "meta+shift+e", "ctrl+shift+e", "Open People view", 1], ["ctrl+shift+m", "meta+shift+m", "ctrl+shift+m", "Open Activity view", 1], ["ctrl+shift+t", "meta+shift+t", "ctrl+shift+t", "Open Threads view", 1], ["ctrl+shift+l", "meta+shift+l", "ctrl+shift+l", "Browse channels", 1], ["ctrl+shift+i", "meta+shift+i", "ctrl+shift+i", "Open conversation details", 1], ["ctrl+shift+a", "meta+shift+a", "ctrl+shift+a", "Open All unreads view", 1], ["ctrl+shift+s", "meta+shift+s", "ctrl+shift+s", "Expand/collapse workspace switcher", 1], ["ctrl+shift+x", "meta+shift+x", "ctrl+shift+x", "Strikethrough text", 1], ["ctrl+shift+u", "meta+shift+u", "ctrl+shift+u", "Hyperlink text", 1], ["ctrl+shift+9", "meta+shift+9", "ctrl+shift+9", "Quote text", 1], ["ctrl+shift+8", "meta+shift+8", "ctrl+shift+8", "Bulleted list", 1], ["ctrl+shift+7", "meta+shift+7", "ctrl+shift+7", "Numbered list", 1], ["ctrl+shift+c", "meta+shift+c", "ctrl+shift+c", "Code text", 1], ["ctrl+shift+f", "meta+shift+f", "ctrl+shift+f", "Apply markdown formatting", 1], ["ctrl+shift+0", "meta+shift+0", "ctrl+shift+0", "Format as checklist (canvas)", 1], ["ctrl+shift+g", "meta+shift+g", "ctrl+shift+g", "Find previous (canvas)", 1], ["ctrl+shift+z", "meta+shift+z", "ctrl+shift+z", "Redo (canvas)", 1], [null, "meta+shift+slash", null, "Open context menu (canvas), Mac", 1], ["ctrl+shift+1", null, "ctrl+shift+1", "Switch to tab by number (Shift Ctrl [number], digits 1-9)", 1], ["alt+shift+arrowup", "alt+shift+arrowup", "alt+shift+arrowup", "Jump to previous unread channel/DM", 1], ["alt+shift+arrowdown", "alt+shift+arrowdown", "alt+shift+arrowdown", "Jump to next unread channel/DM", 1], ["ctrl+alt+shift+c", "meta+alt+shift+c", "ctrl+alt+shift+c", "Codeblock text", 1], ["ctrl+alt+0", "meta+alt+0", "ctrl+alt+0", "Paragraph (canvas)", 1], ["ctrl+alt+1", "meta+alt+1", "ctrl+alt+1", "Big heading (canvas)", 1], ["ctrl+alt+2", "meta+alt+2", "ctrl+alt+2", "Medium heading (canvas)", 1], ["ctrl+alt+3", "meta+alt+3", "ctrl+alt+3", "Small heading (canvas)", 1], ["ctrl+alt+t", "meta+alt+t", "ctrl+alt+t", "View comment thread (canvas)", 1], ["ctrl+alt+r", "meta+alt+r", "ctrl+alt+r", "Show reader/edit view (canvas)", 1], ["ctrl+alt+arrowup", "meta+alt+arrowup", "ctrl+alt+arrowup", "Move list item up (canvas)", 1], ["ctrl+alt+arrowdown", "meta+alt+arrowdown", "ctrl+alt+arrowdown", "Move list item down (canvas)", 1], ["ctrl+alt+q", "ctrl+alt+q", "ctrl+alt+q", "Copy anchor link (canvas)", 1]] }, { id: "discord", name: "Discord", hosts: ["discord.com"], pathPrefixes: ["/channels/"], shortcuts: [["ctrl+shift+m", "meta+shift+m", "ctrl+shift+m", "Toggle mute", 1], ["ctrl+shift+d", "meta+shift+d", "ctrl+shift+d", "Toggle deafen", 1], ["ctrl+shift+u", "meta+shift+u", "ctrl+shift+u", "Attach a file to your message", 1], ["ctrl+shift+b", "meta+shift+b", "ctrl+shift+b", "Open soundboard during voice call", 1], ["ctrl+alt+shift+v", "meta+alt+shift+v", "ctrl+alt+shift+v", "Return to your active voice call", 1]] }, { id: "confluence", name: "Confluence Cloud", hosts: ["*.atlassian.net"], pathPrefixes: ["/wiki/"], shortcuts: [["ctrl+shift+7", "meta+shift+7", "ctrl+shift+7", "Numbered list", 1], ["ctrl+shift+8", "meta+shift+8", "ctrl+shift+8", "Bullet list", 1], ["ctrl+shift+9", "meta+shift+9", "ctrl+shift+9", "Quote", 1], ["ctrl+shift+m", "meta+shift+m", "ctrl+shift+m", "Code", 1], ["ctrl+shift+s", "alt+shift+s", "ctrl+shift+s", "Strikethrough", 1], ["ctrl+shift+comma", "alt+shift+comma", "ctrl+shift+comma", "Subscript", 1], ["ctrl+shift+period", "alt+shift+period", "ctrl+shift+period", "Superscript", 1], ["ctrl+shift+enter", "meta+shift+enter", "ctrl+shift+enter", "Publish with note", 1], ["ctrl+shift+i", "ctrl+shift+i", "ctrl+shift+i", "Open details panel", 1], ["ctrl+shift+u", "meta+shift+u", "ctrl+shift+u", "Next unread comment", 1], ["ctrl+shift+d", "meta+shift+d", "ctrl+shift+d", "Insert markup", 1], ["ctrl+shift+a", "meta+shift+a", "ctrl+shift+a", "Macro", 1], [null, "meta+shift+i", null, "Insert table (Mac only per page)", 0], ["ctrl+alt+shift+b", "meta+alt+shift+b", "ctrl+alt+shift+b", "Blog post", 1], ["ctrl+alt+o", "meta+alt+o", "ctrl+alt+o", "Open notifications", 1], ["ctrl+alt+h", "meta+alt+h", "ctrl+alt+h", "Go Home", 1], ["ctrl+alt+g", "meta+alt+g", "ctrl+alt+g", "Open recent", 1], ["ctrl+alt+8", "meta+alt+8", "ctrl+alt+8", "Open starred", 1], ["ctrl+alt+v", "meta+alt+v", "ctrl+alt+v", "Go to space overview", 1], ["ctrl+alt+0", "meta+alt+0", "ctrl+alt+0", "Paragraph", 1], ["ctrl+alt+1", "meta+alt+1", "ctrl+alt+1", "Heading 1", 1], ["ctrl+alt+2", "meta+alt+2", "ctrl+alt+2", "Heading 2", 1], ["ctrl+alt+3", "meta+alt+3", "ctrl+alt+3", "Heading 3", 1], ["ctrl+alt+4", "meta+alt+4", "ctrl+alt+4", "Heading 4", 1], ["ctrl+alt+5", "meta+alt+5", "ctrl+alt+5", "Heading 5", 1], ["ctrl+alt+6", "meta+alt+6", "ctrl+alt+6", "Heading 6", 1], ["ctrl+alt+y", "meta+alt+y", "ctrl+alt+y", "Highlight yellow", 1], ["ctrl+alt+c", "meta+alt+c", "ctrl+alt+c", "Comment", 1], ["ctrl+alt+w", "meta+alt+w", "ctrl+alt+w", "Watch", 1], ["ctrl+alt+s", "meta+alt+s", "ctrl+alt+s", "Share", 1], ["ctrl+alt+e", "meta+alt+e", "ctrl+alt+e", "Align center", 1], ["ctrl+alt+t", "meta+alt+t", "ctrl+alt+t", "Align right", 1], ["ctrl+alt+a", "ctrl+alt+a", "ctrl+alt+a", "Edit labels", 1], ["ctrl+alt+f", "ctrl+alt+f", "ctrl+alt+f", "Favorite content", 1], [null, "ctrl+alt+c", null, "Create page (Mac)", 1], [null, "ctrl+alt+t", null, "Attachments (Mac)", 1], ["ctrl+alt+p", null, "ctrl+alt+p", "Presenter mode", 1], ["ctrl+alt+arrowup", null, "ctrl+alt+arrowup", "Table row/column operations (Ctrl+Alt+Arrow keys)", 1], ["ctrl+alt+equal", null, "ctrl+alt+equal", "Table insert row/column", 1], ["ctrl+alt+minus", null, "ctrl+alt+minus", "Table delete row/column", 1], ["alt+shift+z", "ctrl+alt+z", "alt+shift+z", "Quick search", 1], ["ctrl+alt+shift+r", "meta+alt+shift+r", "ctrl+alt+shift+r", "Table resize (whiteboard/table)", 1], ["ctrl+alt+shift+arrowup", "meta+alt+shift+arrowup", "ctrl+alt+shift+arrowup", "Table column selection (Up/Down arrows)", 1], ["ctrl+alt+shift+arrowdown", "meta+alt+shift+arrowdown", "ctrl+alt+shift+arrowdown", "Table column selection", 1], ["ctrl+alt+shift+arrowleft", "meta+alt+shift+arrowleft", "ctrl+alt+shift+arrowleft", "Table row selection (Left/Right arrows)", 1], ["ctrl+alt+shift+arrowright", "meta+alt+shift+arrowright", "ctrl+alt+shift+arrowright", "Table row selection", 1], ["ctrl+shift+1", "meta+shift+1", "ctrl+shift+1", "Whiteboard: zoom to fit", 1], ["ctrl+shift+2", null, "ctrl+shift+2", "Whiteboard: zoom to selection", 1]] }, { id: "jira", name: "Jira Cloud", hosts: ["*.atlassian.net"], pathPrefixes: ["/jira/", "/browse/"], shortcuts: [] }, { id: "linear", name: "Linear", hosts: ["linear.app"], pathPrefixes: [], shortcuts: [["ctrl+shift+o", "meta+shift+o", "ctrl+shift+o", "Create sub-issue", 0], ["ctrl+shift+arrowup", "meta+shift+arrowup", "ctrl+shift+arrowup", "Open parent issue", 0], ["ctrl+shift+s", "meta+shift+s", "ctrl+shift+s", "Manage subscribers", 0], ["ctrl+shift+m", "meta+shift+m", "ctrl+shift+m", "Move to another team", 0], ["ctrl+shift+period", "meta+shift+period", "ctrl+shift+period", "Copy Git branch name", 0], ["ctrl+shift+comma", "meta+shift+comma", "ctrl+shift+comma", "Copy issue URL", 0], ["ctrl+shift+d", "meta+shift+d", "ctrl+shift+d", "Remove due date", 0], ["alt+shift+f", "alt+shift+f", "alt+shift+f", "Clear all filters", 0], ["ctrl+shift+1", "meta+shift+1", "ctrl+shift+1", "Go to team 1", 0], ["ctrl+shift+2", "meta+shift+2", "ctrl+shift+2", "Go to team 2", 0], ["ctrl+shift+3", "meta+shift+3", "ctrl+shift+3", "Go to team 3", 0], ["ctrl+shift+4", "meta+shift+4", "ctrl+shift+4", "Go to team 4", 0], ["ctrl+shift+5", "meta+shift+5", "ctrl+shift+5", "Go to team 5", 0], ["ctrl+shift+6", "meta+shift+6", "ctrl+shift+6", "Go to team 6", 0], ["ctrl+shift+7", "meta+shift+7", "ctrl+shift+7", "Go to team 7", 0], ["ctrl+shift+8", "meta+shift+8", "ctrl+shift+8", "Go to team 8", 0], ["ctrl+shift+9", "meta+shift+9", "ctrl+shift+9", "Go to team 9", 0], ["ctrl+alt+1", "meta+alt+1", "ctrl+alt+1", "Set status by position 1", 0], ["ctrl+alt+2", "meta+alt+2", "ctrl+alt+2", "Set status by position 2", 0], ["ctrl+alt+3", "meta+alt+3", "ctrl+alt+3", "Set status by position 3", 0], ["ctrl+alt+4", "meta+alt+4", "ctrl+alt+4", "Set status by position 4", 0], ["ctrl+alt+5", "meta+alt+5", "ctrl+alt+5", "Set status by position 5", 0], ["ctrl+alt+6", "meta+alt+6", "ctrl+alt+6", "Set status by position 6", 0], ["ctrl+alt+7", "meta+alt+7", "ctrl+alt+7", "Set status by position 7", 0], ["ctrl+alt+8", "meta+alt+8", "ctrl+alt+8", "Set status by position 8", 0], ["ctrl+alt+9", "meta+alt+9", "ctrl+alt+9", "Set status by position 9", 0]] }, { id: "github", name: "GitHub", hosts: ["github.com"], pathPrefixes: [], shortcuts: [["ctrl+shift+7", "meta+shift+7", null, "Ordered list markdown (comment box, file editor)", 1], ["ctrl+shift+8", "meta+shift+8", null, "Unordered list markdown (comment box, file editor)", 1], ["ctrl+shift+period", "meta+shift+period", null, "Quote markdown (comment box, file editor)", 1], ["ctrl+shift+g", "meta+shift+g", null, "Find previous (code editor)", 1], ["ctrl+shift+r", "meta+alt+shift+f", null, "Replace all (code editor)", 1], ["ctrl+shift+p", "meta+shift+p", null, "Toggle Write/Preview tabs (comments, issues, PRs, editor)", 1], ["ctrl+shift+v", "meta+shift+v", null, "Paste HTML link as plain text", 1], ["ctrl+alt+shift+v", "meta+alt+shift+v", null, "Paste HTML link as plain text (alternate chord)", 1], ["ctrl+shift+enter", "meta+shift+enter", null, "Submit a review comment (Files changed tab)", 1], ["ctrl+shift+backslash", "meta+shift+backslash", null, "Open row actions menu (Projects)", 1], ["alt+shift+c", "alt+shift+c", null, "Open line menu for selected code (code view/editor)", 1], ["alt+shift+c", "alt+shift+c", null, "Create a new sub-issue (issues)", 1], ["alt+shift+a", "alt+shift+a", null, "Add an existing issue as sub-issue", 1], ["alt+shift+p", "alt+shift+p", null, "Edit parent issue", 1]] }, { id: "gutenberg", name: "WordPress block editor (Gutenberg)", hosts: ["*"], pathPrefixes: ["/wp-admin/post.php", "/wp-admin/post-new.php"], shortcuts: [["ctrl+alt+shift+m", "meta+alt+shift+m", null, "Switch visual editor / code editor", 1], ["ctrl+alt+shift+f", "meta+alt+shift+f", null, "Toggle fullscreen mode", 1], ["alt+shift+o", "ctrl+alt+o", null, "Open block list view", 1], ["ctrl+shift+comma", "meta+shift+comma", null, "Show/hide settings sidebar", 1], ["alt+shift+n", "ctrl+alt+n", null, "Navigate to next part of editor", 1], ["ctrl+shift+backquote", "ctrl+shift+backquote", null, "Navigate to previous part of editor", 1], ["alt+shift+p", "ctrl+alt+p", null, "Navigate to previous part of editor (alternate)", 1], ["ctrl+shift+z", "meta+shift+z", null, "Redo", 1], ["ctrl+shift+0", "meta+shift+0", null, "Zoom out toggle", 1], ["ctrl+shift+d", "meta+shift+d", null, "Duplicate selected block(s)", 1], ["alt+shift+z", "ctrl+alt+z", null, "Remove selected block(s)", 1], ["ctrl+alt+t", "meta+alt+t", null, "Insert block before selection", 1], ["ctrl+alt+y", "meta+alt+y", null, "Insert block after selection", 1], ["ctrl+alt+shift+t", "meta+alt+shift+t", null, "Move selected block(s) up", 1], ["ctrl+alt+shift+y", "meta+alt+shift+y", null, "Move selected block(s) down", 1], ["ctrl+alt+v", "meta+alt+v", null, "Paste styles from copied block", 1], ["ctrl+shift+k", "meta+shift+k", null, "Remove link", 1], ["ctrl+alt+x", "meta+alt+x", null, "Inline code", 1], ["alt+shift+1", "meta+alt+1", null, "Convert paragraph/heading to heading level 1", 1], ["alt+shift+2", "meta+alt+2", null, "Convert paragraph/heading to heading level 2", 1], ["alt+shift+3", "meta+alt+3", null, "Convert paragraph/heading to heading level 3", 1], ["alt+shift+4", "meta+alt+4", null, "Convert paragraph/heading to heading level 4", 1], ["alt+shift+5", "meta+alt+5", null, "Convert paragraph/heading to heading level 5", 1], ["alt+shift+6", "meta+alt+6", null, "Convert paragraph/heading to heading level 6", 1], ["alt+shift+0", "meta+alt+0", null, "Convert heading to paragraph", 1], ["alt+shift+h", "ctrl+alt+h", null, "Show list of all editor shortcuts", 1]] }, { id: "medium", name: "Medium", hosts: ["medium.com"], pathPrefixes: [], shortcuts: [] }, { id: "reddit", name: "Reddit", hosts: ["www.reddit.com"], pathPrefixes: [], shortcuts: [] }, { id: "linkedin", name: "LinkedIn", hosts: ["www.linkedin.com"], pathPrefixes: [], shortcuts: [] }, { id: "x", name: "X / Twitter", hosts: ["x.com", "twitter.com"], pathPrefixes: [], shortcuts: [] }, { id: "substack", name: "Substack", hosts: ["substack.com"], pathPrefixes: [], shortcuts: [] }] };
|
|
6
|
+
|
|
7
|
+
// sites.js
|
|
8
|
+
var COL = { windows: 0, mac: 1, chromeos: 2, action: 3, verified: 4 };
|
|
9
|
+
var SUPPORTED_SCHEMA = "1.0";
|
|
10
|
+
var SCHEMA_OK = site_hotkeys_runtime_default?.version?.schema === SUPPORTED_SCHEMA;
|
|
11
|
+
function detectSitePlatform(nav = typeof navigator !== "undefined" ? navigator : null) {
|
|
12
|
+
if (!nav) return null;
|
|
13
|
+
const ua = nav.userAgent || "";
|
|
14
|
+
if (/\bCrOS\b/.test(ua)) return "chromeos";
|
|
15
|
+
const platform = nav.userAgentData?.platform || nav.platform || "";
|
|
16
|
+
if (/Mac|iPhone|iPad|iPod/i.test(platform)) return "mac";
|
|
17
|
+
if (/Win/i.test(platform)) return "windows";
|
|
18
|
+
if (/Linux|X11|Chrome OS/i.test(platform)) return /Chrome OS/i.test(platform) ? "chromeos" : "linux";
|
|
19
|
+
return null;
|
|
20
|
+
}
|
|
21
|
+
var PUNCT_KEYS = {
|
|
22
|
+
".": "period",
|
|
23
|
+
",": "comma",
|
|
24
|
+
";": "semicolon",
|
|
25
|
+
"'": "quote",
|
|
26
|
+
"/": "slash",
|
|
27
|
+
"\\": "backslash",
|
|
28
|
+
"[": "bracketleft",
|
|
29
|
+
"]": "bracketright",
|
|
30
|
+
"-": "minus",
|
|
31
|
+
"=": "equal",
|
|
32
|
+
"`": "backquote",
|
|
33
|
+
" ": "space"
|
|
34
|
+
};
|
|
35
|
+
var NAMED_KEYS = /* @__PURE__ */ new Set([
|
|
36
|
+
"period",
|
|
37
|
+
"comma",
|
|
38
|
+
"semicolon",
|
|
39
|
+
"quote",
|
|
40
|
+
"slash",
|
|
41
|
+
"backslash",
|
|
42
|
+
"bracketleft",
|
|
43
|
+
"bracketright",
|
|
44
|
+
"minus",
|
|
45
|
+
"equal",
|
|
46
|
+
"backquote",
|
|
47
|
+
"enter",
|
|
48
|
+
"space",
|
|
49
|
+
"tab",
|
|
50
|
+
"backspace",
|
|
51
|
+
"delete",
|
|
52
|
+
"escape",
|
|
53
|
+
"arrowup",
|
|
54
|
+
"arrowdown",
|
|
55
|
+
"arrowleft",
|
|
56
|
+
"arrowright",
|
|
57
|
+
"home",
|
|
58
|
+
"end",
|
|
59
|
+
"pageup",
|
|
60
|
+
"pagedown"
|
|
61
|
+
]);
|
|
62
|
+
var KEY_ALIASES = { esc: "escape", del: "delete", spacebar: "space", return: "enter", up: "arrowup", down: "arrowdown", left: "arrowleft", right: "arrowright" };
|
|
63
|
+
function codeToBase(code) {
|
|
64
|
+
const letter = /^Key([A-Z])$/.exec(code);
|
|
65
|
+
if (letter) return letter[1].toLowerCase();
|
|
66
|
+
const digit = /^(?:Digit|Numpad)(\d)$/.exec(code);
|
|
67
|
+
if (digit) return digit[1];
|
|
68
|
+
return code.toLowerCase();
|
|
69
|
+
}
|
|
70
|
+
function keyToBase(key) {
|
|
71
|
+
if (key == null) return null;
|
|
72
|
+
if (PUNCT_KEYS[key]) return PUNCT_KEYS[key];
|
|
73
|
+
const k = String(key).toLowerCase();
|
|
74
|
+
if (KEY_ALIASES[k]) return KEY_ALIASES[k];
|
|
75
|
+
if (/^[a-z0-9]$/.test(k) || /^f\d{1,2}$/.test(k) || NAMED_KEYS.has(k)) return k;
|
|
76
|
+
return k;
|
|
77
|
+
}
|
|
78
|
+
function parseComboString(str, platform) {
|
|
79
|
+
const flags = { ctrl: false, meta: false, alt: false, shift: false };
|
|
80
|
+
let base = null;
|
|
81
|
+
const tokens = String(str).trim().toLowerCase().replace(/\s+up$/, "").split("+");
|
|
82
|
+
for (let i = 0; i < tokens.length; i++) {
|
|
83
|
+
const t = tokens[i];
|
|
84
|
+
if (t === "" && i === tokens.length - 1) {
|
|
85
|
+
base = "equal";
|
|
86
|
+
continue;
|
|
87
|
+
}
|
|
88
|
+
if (t === "mod") flags[platform === "mac" ? "meta" : "ctrl"] = true;
|
|
89
|
+
else if (t === "ctrl" || t === "control") flags.ctrl = true;
|
|
90
|
+
else if (t === "cmd" || t === "command" || t === "meta" || t === "win") flags.meta = true;
|
|
91
|
+
else if (t === "alt" || t === "option" || t === "opt") flags.alt = true;
|
|
92
|
+
else if (t === "shift") flags.shift = true;
|
|
93
|
+
else if (t.startsWith("code:")) base = codeToBase(String(str).match(/code:([A-Za-z0-9_]+)/)[1]);
|
|
94
|
+
else base = keyToBase(t);
|
|
95
|
+
}
|
|
96
|
+
return { ...flags, base };
|
|
97
|
+
}
|
|
98
|
+
function siteLookupKey(combo, platform = detectSitePlatform() || "windows") {
|
|
99
|
+
const c = typeof combo === "string" ? parseComboString(combo, platform) : { ...combo, base: combo?.code ? codeToBase(combo.code) : keyToBase(combo?.key) };
|
|
100
|
+
if (!c?.base) return null;
|
|
101
|
+
const parts = [];
|
|
102
|
+
if (c.ctrl) parts.push("ctrl");
|
|
103
|
+
if (c.meta) parts.push("meta");
|
|
104
|
+
if (c.alt) parts.push("alt");
|
|
105
|
+
if (c.shift) parts.push("shift");
|
|
106
|
+
parts.push(c.base);
|
|
107
|
+
return parts.join("+");
|
|
108
|
+
}
|
|
109
|
+
function hostMatches(pattern, host) {
|
|
110
|
+
if (pattern === "*") return true;
|
|
111
|
+
if (pattern.startsWith("*.")) {
|
|
112
|
+
const suffix = pattern.slice(1);
|
|
113
|
+
return host.endsWith(suffix) && host.length > suffix.length;
|
|
114
|
+
}
|
|
115
|
+
return host === pattern;
|
|
116
|
+
}
|
|
117
|
+
function toUrl(url) {
|
|
118
|
+
if (url instanceof URL) return url;
|
|
119
|
+
try {
|
|
120
|
+
return new URL(String(url));
|
|
121
|
+
} catch {
|
|
122
|
+
return null;
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
function matchSites(url = typeof location !== "undefined" ? location.href : "") {
|
|
126
|
+
if (!SCHEMA_OK) return [];
|
|
127
|
+
const u = toUrl(url);
|
|
128
|
+
if (!u) return [];
|
|
129
|
+
const host = u.hostname.toLowerCase();
|
|
130
|
+
return site_hotkeys_runtime_default.sites.filter(
|
|
131
|
+
(site) => site.hosts.some((h) => hostMatches(h.toLowerCase(), host)) && (!site.pathPrefixes?.length || site.pathPrefixes.some((p) => u.pathname.startsWith(p)))
|
|
132
|
+
);
|
|
133
|
+
}
|
|
134
|
+
function lookupSiteConflicts(combo, { url, platform, verifiedOnly = false } = {}) {
|
|
135
|
+
const plat = platform || detectSitePlatform() || "windows";
|
|
136
|
+
const lookupKey = siteLookupKey(combo, plat);
|
|
137
|
+
if (!lookupKey) return [];
|
|
138
|
+
const field = plat === "mac" ? "mac" : plat === "chromeos" ? "chromeos" : "windows";
|
|
139
|
+
const conflicts = [];
|
|
140
|
+
for (const site of matchSites(url)) {
|
|
141
|
+
for (const row of site.shortcuts) {
|
|
142
|
+
const verified = row[COL.verified] === 1;
|
|
143
|
+
if (verifiedOnly && !verified) continue;
|
|
144
|
+
const key = row[COL[field]] ?? (field === "chromeos" ? row[COL.windows] : null);
|
|
145
|
+
if (key === lookupKey) {
|
|
146
|
+
conflicts.push({ siteId: site.id, siteName: site.name, action: row[COL.action], verified, lookupKey });
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
return conflicts;
|
|
151
|
+
}
|
|
152
|
+
function siteAware(combo, { engaged, url, platform, verifiedOnly = false, onYield } = {}) {
|
|
153
|
+
if (typeof engaged !== "function") throw new Error("siteAware() needs an engaged() callback");
|
|
154
|
+
const currentUrl = url || (() => typeof location !== "undefined" ? location.href : "");
|
|
155
|
+
let cachedUrl = null;
|
|
156
|
+
let cached = [];
|
|
157
|
+
return (e) => {
|
|
158
|
+
const href = currentUrl();
|
|
159
|
+
if (href !== cachedUrl) {
|
|
160
|
+
cachedUrl = href;
|
|
161
|
+
cached = lookupSiteConflicts(combo, { url: href, platform, verifiedOnly });
|
|
162
|
+
}
|
|
163
|
+
if (!cached.length) return true;
|
|
164
|
+
if (engaged(e)) return true;
|
|
165
|
+
onYield?.(cached, e);
|
|
166
|
+
return false;
|
|
167
|
+
};
|
|
168
|
+
}
|
|
169
|
+
function listSites() {
|
|
170
|
+
return SCHEMA_OK ? site_hotkeys_runtime_default.sites : [];
|
|
171
|
+
}
|
|
172
|
+
var SITE_DATA_RESEARCHED = site_hotkeys_runtime_default?.version?.researched;
|
|
173
|
+
var SITE_SCHEMA_VERSION = site_hotkeys_runtime_default?.version?.schema;
|
|
174
|
+
export {
|
|
175
|
+
SITE_DATA_RESEARCHED,
|
|
176
|
+
SITE_SCHEMA_VERSION,
|
|
177
|
+
detectSitePlatform,
|
|
178
|
+
listSites,
|
|
179
|
+
lookupSiteConflicts,
|
|
180
|
+
matchSites,
|
|
181
|
+
parseComboString,
|
|
182
|
+
siteAware,
|
|
183
|
+
siteLookupKey
|
|
184
|
+
};
|
|
185
|
+
//# sourceMappingURL=sites.js.map
|