diff --git a/packages/core/src/ExtensionManager.ts b/packages/core/src/ExtensionManager.ts index a8e73bf423..53d861cf25 100644 --- a/packages/core/src/ExtensionManager.ts +++ b/packages/core/src/ExtensionManager.ts @@ -205,8 +205,12 @@ export default class ExtensionManager { } get plugins(): Plugin[] { - return [...this.extensions] - .reverse() + // With ProseMirror, first plugins within an array are executed first. + // In tiptap, we provide the ability to override plugins, + // so it feels more natural to run plugins at the end of an array first. + // That’s why we have to reverse the `extensions` array and sort again + // based on the `priority` option. + return ExtensionManager.sort([...this.extensions].reverse()) .map(extension => { const context = { name: extension.name, diff --git a/tests/cypress/integration/core/pluginOrder.spec.ts b/tests/cypress/integration/core/pluginOrder.spec.ts new file mode 100644 index 0000000000..ddc50c3525 --- /dev/null +++ b/tests/cypress/integration/core/pluginOrder.spec.ts @@ -0,0 +1,69 @@ +/// + +import { Editor, Extension } from '@tiptap/core' +import Document from '@tiptap/extension-document' +import Paragraph from '@tiptap/extension-paragraph' +import Text from '@tiptap/extension-text' + +describe('pluginOrder', () => { + it('should run keyboard shortcuts in correct order', () => { + const order: number[] = [] + + cy.window().then(({ document }) => { + const element = document.createElement('div') + + document.body.append(element) + + const editor = new Editor({ + element, + extensions: [ + Document, + Paragraph, + Text, + Extension.create({ + priority: 1000, + addKeyboardShortcuts() { + return { + a: () => { + order.push(1) + + return false + }, + } + }, + }), + Extension.create({ + addKeyboardShortcuts() { + return { + a: () => { + order.push(3) + + return false + }, + } + }, + }), + Extension.create({ + addKeyboardShortcuts() { + return { + a: () => { + order.push(2) + + return false + }, + } + }, + }), + ], + }) + + cy.get('.ProseMirror') + .type('a') + .wait(100).then(() => { + expect(order).to.deep.eq([1, 2, 3]) + + editor.destroy() + }) + }) + }) +})