From 8a0f72dab42ea0d2ace177d2c3b03a6c37412b28 Mon Sep 17 00:00:00 2001 From: Ian Sanders Date: Wed, 6 Dec 2023 14:48:24 +0000 Subject: [PATCH 1/8] Enable `postCreateCommand` --- .devcontainer/devcontainer.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json index bf736f9..fe835c2 100644 --- a/.devcontainer/devcontainer.json +++ b/.devcontainer/devcontainer.json @@ -22,7 +22,7 @@ // "forwardPorts": [], // Use 'postCreateCommand' to run commands after the container is created. - // "postCreateCommand": "yarn install", + "postCreateCommand": "npm install", // Comment out to connect as root instead. More info: https://aka.ms/vscode-remote/containers/non-root. "remoteUser": "node", From ad58d5788a796ee673cd181e89fb8e16ab291583 Mon Sep 17 00:00:00 2001 From: Ian Sanders Date: Wed, 6 Dec 2023 14:50:33 +0000 Subject: [PATCH 2/8] Update hotkey string generation to include `Shift` --- src/hotkey.ts | 10 ++-------- test/test.js | 10 ++++++---- 2 files changed, 8 insertions(+), 12 deletions(-) diff --git a/src/hotkey.ts b/src/hotkey.ts index cb35c23..649c1bb 100644 --- a/src/hotkey.ts +++ b/src/hotkey.ts @@ -38,9 +38,9 @@ export function eventToHotkeyString( event: KeyboardEvent, platform: string = navigator.platform ): NormalizedHotkeyString { - const {ctrlKey, altKey, metaKey, key} = event + const {ctrlKey, altKey, metaKey, shiftKey, key} = event const hotkeyString: string[] = [] - const modifiers: boolean[] = [ctrlKey, altKey, metaKey, showShift(event)] + const modifiers: boolean[] = [ctrlKey, altKey, metaKey, shiftKey] for (const [i, mod] of modifiers.entries()) { if (mod) hotkeyString.push(modifierKeyNames[i]) @@ -58,12 +58,6 @@ export function eventToHotkeyString( const modifierKeyNames: string[] = ['Control', 'Alt', 'Meta', 'Shift'] -// We don't want to show `Shift` when `event.key` is capital -function showShift(event: KeyboardEvent): boolean { - const {shiftKey, code, key} = event - return shiftKey && !(code.startsWith('Key') && key.toUpperCase() === key) -} - /** * Normalizes a hotkey string before comparing it to the serialized event * string produced by `eventToHotkeyString`. diff --git a/test/test.js b/test/test.js index e478ec6..d1fdcd0 100644 --- a/test/test.js +++ b/test/test.js @@ -98,13 +98,13 @@ describe('hotkey', function () { }) it('triggers elements with capitalised key', function () { - setHTML('') + setHTML('') document.dispatchEvent(new KeyboardEvent('keydown', {shiftKey: true, code: 'KeyB', key: 'B'})) assert.include(elementsActivated, 'button1') }) it('dispatches an event on the element once fired', function () { - setHTML('') + setHTML('') let fired = false document.querySelector('#button1').addEventListener('hotkey-fire', event => { fired = true @@ -116,7 +116,7 @@ describe('hotkey', function () { }) it('wont trigger action if the hotkey-fire event is cancelled', function () { - setHTML('') + setHTML('') document.querySelector('#button1').addEventListener('hotkey-fire', event => event.preventDefault()) document.dispatchEvent(new KeyboardEvent('keydown', {shiftKey: true, code: 'KeyB', key: 'B'})) assert.notInclude(elementsActivated, 'button1') @@ -286,7 +286,9 @@ describe('hotkey', function () { ['Alt+Shift+ArrowLeft', {altKey: true, shiftKey: true, key: 'ArrowLeft'}], ['Alt+Shift+ArrowLeft', {altKey: true, shiftKey: true, key: 'ArrowLeft'}, 'mac'], ['Control+Space', {ctrlKey: true, key: ' '}], - ['Shift+Plus', {shiftKey: true, key: '+'}] + ['Shift+Plus', {shiftKey: true, key: '+'}], + ['Shift+S', {shiftKey: true, key: 'S'}], + ['s', {shiftKey: true, key: 's'}] ] for (const [expected, keyEvent, platform = 'win / linux'] of tests) { it(`${JSON.stringify(keyEvent)} => ${expected}`, function (done) { From ecb4f0f5bb8b4da211f41625c0fc43bc00f28be8 Mon Sep 17 00:00:00 2001 From: Ian Sanders Date: Wed, 6 Dec 2023 14:52:07 +0000 Subject: [PATCH 3/8] Update docs --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index f012049..57485a0 100644 --- a/README.md +++ b/README.md @@ -111,6 +111,7 @@ for (const el of document.querySelectorAll('[data-shortcut]')) { 3. Due to the inconsistent lowercasing of `event.key` on Mac and iOS when `Meta` is pressed along with `Shift`, it is recommended to avoid hotkey strings containing both `Mod` and `Shift`. 7. `"Plus"` and `"Space"` are special key names to represent the `+` and ` ` keys respectively, because these symbols cannot be represented in the normal hotkey string syntax. 8. You can use the comma key `,` as a hotkey, e.g. `a,,` would activate if the user typed `a` or `,`. `Control+,,x` would activate for `Control+,` or `x`. +9. `"Shift"` should be included if it would be held, and the key name should match the 'uppercase' key name: `Shift+?`, `Shift+A`, `Shift+$` ### Example From 41234aad8da98f54e8de0cbad6cf276b42a7fad3 Mon Sep 17 00:00:00 2001 From: Ian Sanders Date: Wed, 6 Dec 2023 15:14:41 +0000 Subject: [PATCH 4/8] Update tests --- test/test.js | 15 ++++++--------- 1 file changed, 6 insertions(+), 9 deletions(-) diff --git a/test/test.js b/test/test.js index d1fdcd0..59570bb 100644 --- a/test/test.js +++ b/test/test.js @@ -108,7 +108,7 @@ describe('hotkey', function () { let fired = false document.querySelector('#button1').addEventListener('hotkey-fire', event => { fired = true - assert.deepEqual(event.detail.path, ['B']) + assert.deepEqual(event.detail.path, ['Shift+B']) assert.equal(event.cancelable, true) }) document.dispatchEvent(new KeyboardEvent('keydown', {shiftKey: true, code: 'KeyB', key: 'B'})) @@ -262,19 +262,18 @@ describe('hotkey', function () { describe('eventToHotkeyString', function () { const tests = [ - ['Control+J', {ctrlKey: true, shiftKey: true, code: 'KeyJ', key: 'J'}], - ['Control+Shift+j', {ctrlKey: true, shiftKey: true, code: 'KeyJ', key: 'j'}], + ['Control+Shift+J', {ctrlKey: true, shiftKey: true, code: 'KeyJ', key: 'J'}], ['Control+j', {ctrlKey: true, code: 'KeyJ', key: 'j'}], ['Meta+Shift+p', {key: 'p', metaKey: true, shiftKey: true, code: 'KeyP'}], ['Meta+Shift+8', {key: '8', metaKey: true, shiftKey: true, code: 'Digit8'}], ['Control+Shift+7', {key: '7', ctrlKey: true, shiftKey: true, code: 'Digit7'}], - ['J', {shiftKey: true, code: 'KeyJ', key: 'J'}], + ['Shift+J', {shiftKey: true, code: 'KeyJ', key: 'J'}], ['/', {key: '/', code: ''}], ['1', {key: '1', code: 'Digit1'}], ['Control+Shift+`', {ctrlKey: true, shiftKey: true, key: '`'}], ['c', {key: 'c', code: 'KeyC'}], - ['S', {key: 'S', shiftKey: true, code: 'KeyS'}], - ['!', {key: '!', shiftKey: true, code: 'KeyS'}], + ['Shift+S', {key: 'S', shiftKey: true, code: 'KeyS'}], + ['Shift+!', {key: '!', shiftKey: true, code: 'Digit1'}], ['Control+Shift', {ctrlKey: true, shiftKey: true, key: 'Shift'}], ['Control+Shift', {ctrlKey: true, shiftKey: true, key: 'Control'}], ['Alt+s', {altKey: true, key: 's'}], @@ -286,9 +285,7 @@ describe('hotkey', function () { ['Alt+Shift+ArrowLeft', {altKey: true, shiftKey: true, key: 'ArrowLeft'}], ['Alt+Shift+ArrowLeft', {altKey: true, shiftKey: true, key: 'ArrowLeft'}, 'mac'], ['Control+Space', {ctrlKey: true, key: ' '}], - ['Shift+Plus', {shiftKey: true, key: '+'}], - ['Shift+S', {shiftKey: true, key: 'S'}], - ['s', {shiftKey: true, key: 's'}] + ['Shift+Plus', {shiftKey: true, key: '+'}] ] for (const [expected, keyEvent, platform = 'win / linux'] of tests) { it(`${JSON.stringify(keyEvent)} => ${expected}`, function (done) { From bb17f9a0045896bce1680eda137bbcbfc07ca8eb Mon Sep 17 00:00:00 2001 From: Ian Sanders Date: Thu, 7 Dec 2023 17:17:24 +0000 Subject: [PATCH 5/8] Add deleted test back --- test/test.js | 1 + 1 file changed, 1 insertion(+) diff --git a/test/test.js b/test/test.js index 59570bb..17b33cd 100644 --- a/test/test.js +++ b/test/test.js @@ -263,6 +263,7 @@ describe('hotkey', function () { describe('eventToHotkeyString', function () { const tests = [ ['Control+Shift+J', {ctrlKey: true, shiftKey: true, code: 'KeyJ', key: 'J'}], + ['Control+Shift+j', {ctrlKey: true, shiftKey: true, code: 'KeyJ', key: 'j'}], ['Control+j', {ctrlKey: true, code: 'KeyJ', key: 'j'}], ['Meta+Shift+p', {key: 'p', metaKey: true, shiftKey: true, code: 'KeyP'}], ['Meta+Shift+8', {key: '8', metaKey: true, shiftKey: true, code: 'Digit8'}], From 0405990c432613109403b1459d4c72c609563614 Mon Sep 17 00:00:00 2001 From: Ian Sanders Date: Thu, 7 Dec 2023 19:32:29 +0000 Subject: [PATCH 6/8] Clarify the point in the readme --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 57485a0..a61ad11 100644 --- a/README.md +++ b/README.md @@ -111,7 +111,7 @@ for (const el of document.querySelectorAll('[data-shortcut]')) { 3. Due to the inconsistent lowercasing of `event.key` on Mac and iOS when `Meta` is pressed along with `Shift`, it is recommended to avoid hotkey strings containing both `Mod` and `Shift`. 7. `"Plus"` and `"Space"` are special key names to represent the `+` and ` ` keys respectively, because these symbols cannot be represented in the normal hotkey string syntax. 8. You can use the comma key `,` as a hotkey, e.g. `a,,` would activate if the user typed `a` or `,`. `Control+,,x` would activate for `Control+,` or `x`. -9. `"Shift"` should be included if it would be held, and the key name should match the 'uppercase' key name: `Shift+?`, `Shift+A`, `Shift+$` +9. `"Shift"` should be included if it would be held and the key is uppercase: ie, `Shift+A` not `a`. Note however that MacOS outputs lowercase keys when `Command+Shift` is held; see 6.3 above. ### Example From ac13a24c171c525fbbae930b71dc9c903b122c00 Mon Sep 17 00:00:00 2001 From: Ian Sanders Date: Thu, 7 Dec 2023 19:33:00 +0000 Subject: [PATCH 7/8] typo --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index a61ad11..36f2d9f 100644 --- a/README.md +++ b/README.md @@ -111,7 +111,7 @@ for (const el of document.querySelectorAll('[data-shortcut]')) { 3. Due to the inconsistent lowercasing of `event.key` on Mac and iOS when `Meta` is pressed along with `Shift`, it is recommended to avoid hotkey strings containing both `Mod` and `Shift`. 7. `"Plus"` and `"Space"` are special key names to represent the `+` and ` ` keys respectively, because these symbols cannot be represented in the normal hotkey string syntax. 8. You can use the comma key `,` as a hotkey, e.g. `a,,` would activate if the user typed `a` or `,`. `Control+,,x` would activate for `Control+,` or `x`. -9. `"Shift"` should be included if it would be held and the key is uppercase: ie, `Shift+A` not `a`. Note however that MacOS outputs lowercase keys when `Command+Shift` is held; see 6.3 above. +9. `"Shift"` should be included if it would be held and the key is uppercase: ie, `Shift+A` not `A`. Note however that MacOS outputs lowercase keys when `Command+Shift` is held; see 6.3 above. ### Example From ea1c9c7e4ef8ddb98f59083298125bf99db71bea Mon Sep 17 00:00:00 2001 From: Ian Sanders Date: Thu, 7 Dec 2023 19:35:05 +0000 Subject: [PATCH 8/8] Replace `Command` with `Meta` --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 36f2d9f..9b0e68e 100644 --- a/README.md +++ b/README.md @@ -111,7 +111,7 @@ for (const el of document.querySelectorAll('[data-shortcut]')) { 3. Due to the inconsistent lowercasing of `event.key` on Mac and iOS when `Meta` is pressed along with `Shift`, it is recommended to avoid hotkey strings containing both `Mod` and `Shift`. 7. `"Plus"` and `"Space"` are special key names to represent the `+` and ` ` keys respectively, because these symbols cannot be represented in the normal hotkey string syntax. 8. You can use the comma key `,` as a hotkey, e.g. `a,,` would activate if the user typed `a` or `,`. `Control+,,x` would activate for `Control+,` or `x`. -9. `"Shift"` should be included if it would be held and the key is uppercase: ie, `Shift+A` not `A`. Note however that MacOS outputs lowercase keys when `Command+Shift` is held; see 6.3 above. +9. `"Shift"` should be included if it would be held and the key is uppercase: ie, `Shift+A` not `A`. Note however that MacOS outputs lowercase keys when `Meta+Shift` is held (ie, `Meta+Shift+a`); see 6.3 above. ### Example