Fix inline shortcut registration failure when multiple EditorJS instances share a page#3003
Fix inline shortcut registration failure when multiple EditorJS instances share a page#3003
Conversation
…document Two bugs caused inline shortcuts to fail when multiple EditorJS instances were on the same page: 1. Mismatch: shortcuts were registered on `document` but removed from `this.Editor.UI.nodes.redactor`, so they were never actually removed. 2. Because shortcuts accumulated on `document` forever, the second editor's attempt to register the same shortcuts threw an error (silently caught), meaning the second editor's inline shortcuts were never registered at all. Fixes: - Remove the throw in `Shortcuts.add()` to allow multiple editors to each register their own handler for the same shortcut on `document`. Each handler already guards via `if (!currentBlock) return`, so only the focused editor responds. - Fix `close()` to call `Shortcuts.remove(document, shortcut)` matching where they were registered. - Update type signatures from `Element` to `HTMLElement | Document` to match actual usage. Agent-Logs-Url: https://github.com/codex-team/editor.js/sessions/6c11dfbe-e93a-4fd6-a88e-ef0409aa3d73 Co-authored-by: neSpecc <3684889+neSpecc@users.noreply.github.com>
…, update CHANGELOG Agent-Logs-Url: https://github.com/codex-team/editor.js/sessions/5d1a01a1-141e-4fa2-8a45-1dee91f7c195 Co-authored-by: neSpecc <3684889+neSpecc@users.noreply.github.com>
Done in commit
Warning Firewall rules blocked me from connecting to one or more addresses (expand for details)I tried to connect to the following addresses, but was blocked by firewall rules:
If you need me to access, download, or install something from one of these locations, you can either:
|
| }); | ||
|
|
||
| describe('Shortcuts', () => { | ||
| it('should work when multiple editor instances are present on the same page', () => { |
There was a problem hiding this comment.
@copilot "should work" is not clear enough, explain how exactly it should work in a test case title
There was a problem hiding this comment.
Renamed in dbef3a5 to: should activate the focused editor's tool when shortcut is pressed with multiple instances on the page.
Agent-Logs-Url: https://github.com/codex-team/editor.js/sessions/1188405a-9b5c-490f-a89f-5613434f0858 Co-authored-by: neSpecc <3684889+neSpecc@users.noreply.github.com>
| cy.get('@toolActivated2').should('have.been.called'); | ||
| cy.get('@toolActivated1').should('not.have.been.called'); |
There was a problem hiding this comment.
@copilot Look like if you will remove your changes from "src/components/utils/shortcuts.ts", this test will still be passed
There was a problem hiding this comment.
Fixed in c5bff13. The test now uses cy.clock() to freeze the selectionchange debounce after editor 1's shortcut is registered, then calls editor2.inlineToolbar.open() via the public API before that debounce fires. At that moment editor 1's CMD+SHIFT+M handler is still live on document, so enableShortcuts() hits the duplicate-registration path. Without the shortcuts.ts fix (the removed throw) it silently fails to register editor 2's shortcut → toolActivated2 never fires → test fails. Ticking past the debounce afterwards also exercises the inline.ts fix, confirming editor 1's shortcut is removed correctly.
Agent-Logs-Url: https://github.com/codex-team/editor.js/sessions/82e67750-b875-4aeb-a1d8-495885d68f39 Co-authored-by: neSpecc <3684889+neSpecc@users.noreply.github.com>
|
@copilot tests failed : Cypress / run-tests (firefox) (pull_request)Failing after 3m |
…ox incompatible) Agent-Logs-Url: https://github.com/codex-team/editor.js/sessions/be0e5329-07dd-4f2e-b7f2-b052fb52e3b1 Co-authored-by: neSpecc <3684889+neSpecc@users.noreply.github.com>
Fixed in |
|
@copilot Cypress / run-tests (chrome) (pull_request)Failing after 3m |
Agent-Logs-Url: https://github.com/codex-team/editor.js/sessions/d68076f4-6a6c-4f5f-8cc6-791e21fad6a9 Co-authored-by: neSpecc <3684889+neSpecc@users.noreply.github.com>
Agent-Logs-Url: https://github.com/codex-team/editor.js/sessions/d68076f4-6a6c-4f5f-8cc6-791e21fad6a9 Co-authored-by: neSpecc <3684889+neSpecc@users.noreply.github.com>
Fixed in |
When two or more EditorJS instances are initialized on the same page, the second instance fails to register inline tool shortcuts (e.g.
CMD+B,CMD+I) withError: Shortcut CMD+B is already registered for [object HTMLDocument].There were two compounding bugs:
Bug 1 — Shortcuts registered on
documentbut removed fromredactor(never cleaned up)InlineToolbar.close()calledShortcuts.remove(this.Editor.UI.nodes.redactor, shortcut), butenableShortcuts()registers ondocument. The lookup key mismatch made everyremove()call a no-op, causing shortcuts to accumulate ondocumentindefinitely.Bug 2 —
Shortcuts.add()throws on duplicate registration, silently swallowedBecause shortcuts were never removed (Bug 1), any subsequent editor's
enableShortcuts()hit the duplicate-check guard and threw. Thetry/catchingetPopoverItems()swallowed the error silently — leaving the second editor with no working inline shortcuts at all.Changes
shortcuts.ts— Remove thethrowinShortcuts.add()for already-registered shortcuts, allowing multiple editor instances to each attach their own handler to the samedocument-level shortcut. Update internal map and method signatures fromElementtoHTMLElement | Documentto match actual usage.inline.ts— FixInlineToolbar.close()to callShortcuts.remove(document, shortcut), matching where the shortcuts are actually registered, so they are properly torn down on close.test/cypress/tests/ui/InlineToolbar.cy.ts— Added testshould activate the focused editor's tool when shortcut is pressed with multiple instances on the page: selects text in editor 1 (waits for its toolbar, confirming itsCMD+SHIFT+Mshortcut is registered ondocument), then selects text in editor 2 (waits for its toolbar, confirming the selectionchange debounce correctly closed editor 1's toolbar viaShortcuts.remove(document, …)and registered editor 2's shortcut), then dispatches the shortcut and asserts that only editor 2's tool fires. This test fails without theinline.tsfix because without itclose()targeted the wrong element, so editor 1's shortcut was never removed fromdocumentand every registration attempt by editor 2 would throw (silently swallowed), leaving editor 2 with no working shortcut.package.json— Version bumped2.31.6→2.31.7.docs/CHANGELOG.md— Added2.31.7entry.The
on: documentbinding is intentional — it is required for shortcuts to work in read-only mode where blocks havecontenteditable="false". Each handler already guards withif (!currentBlock) return, so only the focused editor instance responds to a given keypress.