From 9b83bc56802afa3578a11fe45d2bf7c9a4b0ea0b Mon Sep 17 00:00:00 2001 From: bdbch Date: Sat, 6 Apr 2024 13:09:42 +0200 Subject: [PATCH 1/2] refactor(core): refactor extension manager --- packages/core/src/ExtensionManager.ts | 170 +++++++++--------- .../core/src/helpers/getExtensionField.ts | 7 + .../helpers/getSchemaByResolvedExtensions.ts | 6 + 3 files changed, 98 insertions(+), 85 deletions(-) diff --git a/packages/core/src/ExtensionManager.ts b/packages/core/src/ExtensionManager.ts index 3c82d4e8df2..67f76a13a7e 100644 --- a/packages/core/src/ExtensionManager.ts +++ b/packages/core/src/ExtensionManager.ts @@ -13,8 +13,8 @@ import { getSchemaTypeByName } from './helpers/getSchemaTypeByName.js' import { isExtensionRulesEnabled } from './helpers/isExtensionRulesEnabled.js' import { splitExtensions } from './helpers/splitExtensions.js' import { Mark, NodeConfig } from './index.js' -import { inputRulesPlugin } from './InputRule.js' -import { pasteRulesPlugin } from './PasteRule.js' +import { InputRule, inputRulesPlugin } from './InputRule.js' +import { PasteRule, pasteRulesPlugin } from './PasteRule.js' import { AnyConfig, Extensions, RawCommands } from './types.js' import { callOrReturn } from './utilities/callOrReturn.js' import { findDuplicates } from './utilities/findDuplicates.js' @@ -32,87 +32,7 @@ export class ExtensionManager { this.editor = editor this.extensions = ExtensionManager.resolve(extensions) this.schema = getSchemaByResolvedExtensions(this.extensions, editor) - - this.extensions.forEach(extension => { - // store extension storage in editor - this.editor.extensionStorage[extension.name] = extension.storage - - const context = { - name: extension.name, - options: extension.options, - storage: extension.storage, - editor: this.editor, - type: getSchemaTypeByName(extension.name, this.schema), - } - - if (extension.type === 'mark') { - const keepOnSplit = callOrReturn(getExtensionField(extension, 'keepOnSplit', context)) ?? true - - if (keepOnSplit) { - this.splittableMarks.push(extension.name) - } - } - - const onBeforeCreate = getExtensionField( - extension, - 'onBeforeCreate', - context, - ) - - if (onBeforeCreate) { - this.editor.on('beforeCreate', onBeforeCreate) - } - - const onCreate = getExtensionField(extension, 'onCreate', context) - - if (onCreate) { - this.editor.on('create', onCreate) - } - - const onUpdate = getExtensionField(extension, 'onUpdate', context) - - if (onUpdate) { - this.editor.on('update', onUpdate) - } - - const onSelectionUpdate = getExtensionField( - extension, - 'onSelectionUpdate', - context, - ) - - if (onSelectionUpdate) { - this.editor.on('selectionUpdate', onSelectionUpdate) - } - - const onTransaction = getExtensionField( - extension, - 'onTransaction', - context, - ) - - if (onTransaction) { - this.editor.on('transaction', onTransaction) - } - - const onFocus = getExtensionField(extension, 'onFocus', context) - - if (onFocus) { - this.editor.on('focus', onFocus) - } - - const onBlur = getExtensionField(extension, 'onBlur', context) - - if (onBlur) { - this.editor.on('blur', onBlur) - } - - const onDestroy = getExtensionField(extension, 'onDestroy', context) - - if (onDestroy) { - this.editor.on('destroy', onDestroy) - } - }) + this.setupExtensions() } static resolve(extensions: Extensions): Extensions { @@ -213,8 +133,8 @@ export class ExtensionManager { // based on the `priority` option. const extensions = ExtensionManager.sort([...this.extensions].reverse()) - const inputRules: any[] = [] - const pasteRules: any[] = [] + const inputRules: InputRule[] = [] + const pasteRules: PasteRule[] = [] const allPlugins = extensions .map(extension => { @@ -358,4 +278,84 @@ export class ExtensionManager { }), ) } + + /** + * Map through all extensions, create extension storages & setup marks + * & bind editor event listener. + */ + private setupExtensions() { + this.extensions.forEach(extension => { + // store extension storage in editor + this.editor.extensionStorage[extension.name] = extension.storage + + const context = { + name: extension.name, + options: extension.options, + storage: extension.storage, + editor: this.editor, + type: getSchemaTypeByName(extension.name, this.schema), + } + + if (extension.type === 'mark') { + const keepOnSplit = callOrReturn(getExtensionField(extension, 'keepOnSplit', context)) ?? true + + if (keepOnSplit) { + this.splittableMarks.push(extension.name) + } + } + + const onBeforeCreate = getExtensionField( + extension, + 'onBeforeCreate', + context, + ) + const onCreate = getExtensionField(extension, 'onCreate', context) + const onUpdate = getExtensionField(extension, 'onUpdate', context) + const onSelectionUpdate = getExtensionField( + extension, + 'onSelectionUpdate', + context, + ) + const onTransaction = getExtensionField( + extension, + 'onTransaction', + context, + ) + const onFocus = getExtensionField(extension, 'onFocus', context) + const onBlur = getExtensionField(extension, 'onBlur', context) + const onDestroy = getExtensionField(extension, 'onDestroy', context) + + if (onBeforeCreate) { + this.editor.on('beforeCreate', onBeforeCreate) + } + + if (onCreate) { + this.editor.on('create', onCreate) + } + + if (onUpdate) { + this.editor.on('update', onUpdate) + } + + if (onSelectionUpdate) { + this.editor.on('selectionUpdate', onSelectionUpdate) + } + + if (onTransaction) { + this.editor.on('transaction', onTransaction) + } + + if (onFocus) { + this.editor.on('focus', onFocus) + } + + if (onBlur) { + this.editor.on('blur', onBlur) + } + + if (onDestroy) { + this.editor.on('destroy', onDestroy) + } + }) + } } diff --git a/packages/core/src/helpers/getExtensionField.ts b/packages/core/src/helpers/getExtensionField.ts index ff5a1c24d13..45fe174af66 100644 --- a/packages/core/src/helpers/getExtensionField.ts +++ b/packages/core/src/helpers/getExtensionField.ts @@ -1,5 +1,12 @@ import { AnyExtension, MaybeThisParameterType, RemoveThis } from '../types.js' +/** + * Returns a field from an extension + * @param extension The Tiptap extension + * @param field The field, for example `renderHTML` or `priority` + * @param context The context object that should be passed as `this` into the function + * @returns The field value + */ export function getExtensionField( extension: AnyExtension, field: string, diff --git a/packages/core/src/helpers/getSchemaByResolvedExtensions.ts b/packages/core/src/helpers/getSchemaByResolvedExtensions.ts index 3fca356b82e..72ada083d70 100644 --- a/packages/core/src/helpers/getSchemaByResolvedExtensions.ts +++ b/packages/core/src/helpers/getSchemaByResolvedExtensions.ts @@ -23,6 +23,12 @@ function cleanUpSchemaItem(data: T) { ) as T } +/** + * Get a Prosemirror schema from an array of Tiptap extensions. + * @param extensions A list of Tiptap extensions. + * @param editor The editor instance. + * @returns A Prosemirror schema. + */ export function getSchemaByResolvedExtensions(extensions: Extensions, editor?: Editor): Schema { const allAttributes = getAttributesFromExtensions(extensions) const { nodeExtensions, markExtensions } = splitExtensions(extensions) From f1e321f318bef515edae3683210f1a8d15742e85 Mon Sep 17 00:00:00 2001 From: bdbch Date: Sat, 6 Apr 2024 13:10:27 +0200 Subject: [PATCH 2/2] refactor(core): update comment for setupExtensions function --- packages/core/src/ExtensionManager.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/core/src/ExtensionManager.ts b/packages/core/src/ExtensionManager.ts index 67f76a13a7e..882a8160af7 100644 --- a/packages/core/src/ExtensionManager.ts +++ b/packages/core/src/ExtensionManager.ts @@ -280,7 +280,7 @@ export class ExtensionManager { } /** - * Map through all extensions, create extension storages & setup marks + * Go through all extensions, create extension storages & setup marks * & bind editor event listener. */ private setupExtensions() {