Skip to content

Commit

Permalink
Merge pull request #110 from github/mac-alt-support
Browse files Browse the repository at this point in the history
Add support for alt/option on Mac via symbol map
  • Loading branch information
iansan5653 authored Oct 30, 2023
2 parents 49b6479 + 955474c commit 8b64334
Show file tree
Hide file tree
Showing 3 changed files with 114 additions and 5 deletions.
9 changes: 7 additions & 2 deletions src/hotkey.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import {NormalizedSequenceString} from './sequence'
import {macosSymbolLayerKeys} from './macos-symbol-layer'

const normalizedHotkeyBrand = Symbol('normalizedHotkey')

Expand Down Expand Up @@ -28,7 +29,10 @@ export type NormalizedHotkeyString = NormalizedSequenceString & {[normalizedHotk
* if (eventToHotkeyString(event) === 'h') ...
* })
*/
export function eventToHotkeyString(event: KeyboardEvent): NormalizedHotkeyString {
export function eventToHotkeyString(
event: KeyboardEvent,
platform: string = navigator.platform
): NormalizedHotkeyString {
const {ctrlKey, altKey, metaKey, key} = event
const hotkeyString: string[] = []
const modifiers: boolean[] = [ctrlKey, altKey, metaKey, showShift(event)]
Expand All @@ -38,7 +42,8 @@ export function eventToHotkeyString(event: KeyboardEvent): NormalizedHotkeyStrin
}

if (!modifierKeyNames.includes(key)) {
hotkeyString.push(key)
const nonOptionPlaneKey = matchApplePlatform.test(platform) ? macosSymbolLayerKeys[key] ?? key : key
hotkeyString.push(nonOptionPlaneKey)
}

return hotkeyString.join('+') as NormalizedHotkeyString
Expand Down
96 changes: 96 additions & 0 deletions src/macos-symbol-layer.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
/**
* Map of special symbols to the keys that would be pressed (while holding `Option`) to type them on MacOS on an
* English layout. Most of these are standardized across most language layouts, so this won't work 100% in every
* language but it should work most of the time.
*/
export const macosSymbolLayerKeys: Record<string, string> = {
['¡']: '1',
['™']: '2',
['£']: '3',
['¢']: '4',
['∞']: '5',
['§']: '6',
['¶']: '7',
['•']: '8',
['ª']: '9',
['º']: '0',
['–']: '-',
['≠']: '=',
['`']: '~',
['⁄']: '!',
['€']: '@',
['‹']: '#',
['›']: '$',
['fi']: '%',
['fl']: '^',
['‡']: '&',
['°']: '*',
['·']: '(',
['‚']: ')',
['—']: '_',
['±']: '+',
['œ']: 'q',
['∑']: 'w',
['®']: 'r',
['†']: 't',
['¥']: 'y',
['ø']: 'o',
['π']: 'p',
['“']: '[',
['‘']: ']',
['«']: '\\',
['Œ']: 'Q',
['„']: 'W',
['´']: 'E',
['‰']: 'R',
['ˇ']: 'T',
['Á']: 'Y',
['¨']: 'U',
['ˆ']: 'I',
['Ø']: 'O',
['∏']: 'P',
['”']: '{',
['’']: '}',
['»']: '|',
['å']: 'a',
['ß']: 's',
['∂']: 'd',
['ƒ']: 'f',
['©']: 'g',
['˙']: 'h',
['∆']: 'j',
['˚']: 'k',
['¬']: 'l',
['…']: ';',
['æ']: "'",
['Å']: 'A',
['Í']: 'S',
['Î']: 'D',
['Ï']: 'F',
['˝']: 'G',
['Ó']: 'H',
['Ô']: 'J',
['']: 'K',
['Ò']: 'L',
['Ú']: ':',
['Æ']: '"',
['Ω']: 'z',
['≈']: 'x',
['ç']: 'c',
['√']: 'v',
['∫']: 'b',
['µ']: 'm',
['≤']: ',',
['≥']: '.',
['÷']: '/',
['¸']: 'Z',
['˛']: 'X',
['Ç']: 'C',
['◊']: 'V',
['ı']: 'B',
['˜']: 'N',
['Â']: 'M',
['¯']: '<',
['˘']: '>',
['¿']: '?'
}
14 changes: 11 additions & 3 deletions test/test.js
Original file line number Diff line number Diff line change
Expand Up @@ -276,13 +276,21 @@ describe('hotkey', function () {
['S', {key: 'S', shiftKey: true, code: 'KeyS'}],
['!', {key: '!', shiftKey: true, code: 'KeyS'}],
['Control+Shift', {ctrlKey: true, shiftKey: true, key: 'Shift'}],
['Control+Shift', {ctrlKey: true, shiftKey: true, key: 'Control'}]
['Control+Shift', {ctrlKey: true, shiftKey: true, key: 'Control'}],
['Alt+s', {altKey: true, key: 's'}],
['Alt+s', {altKey: true, key: 'ß'}, 'mac'],
['Alt+Shift+S', {altKey: true, shiftKey: true, key: 'S'}],
['Alt+Shift+S', {altKey: true, shiftKey: true, key: 'Í'}, 'mac'],
['Alt+ArrowLeft', {altKey: true, key: 'ArrowLeft'}],
['Alt+ArrowLeft', {altKey: true, key: 'ArrowLeft'}, 'mac'],
['Alt+Shift+ArrowLeft', {altKey: true, shiftKey: true, key: 'ArrowLeft'}],
['Alt+Shift+ArrowLeft', {altKey: true, shiftKey: true, key: 'ArrowLeft'}, 'mac']
]
for (const [expected, keyEvent] of tests) {
for (const [expected, keyEvent, platform = 'win / linux'] of tests) {
it(`${JSON.stringify(keyEvent)} => ${expected}`, function (done) {
document.body.addEventListener('keydown', function handler(event) {
document.body.removeEventListener('keydown', handler)
assert.equal(eventToHotkeyString(event), expected)
assert.equal(eventToHotkeyString(event, platform), expected)
done()
})
document.body.dispatchEvent(new KeyboardEvent('keydown', keyEvent))
Expand Down

0 comments on commit 8b64334

Please sign in to comment.