Skip to content

Commit

Permalink
refactor(core): clean up constructor & extension setup in extension m…
Browse files Browse the repository at this point in the history
…anager (#5035)

* refactor(core): refactor extension manager

* refactor(core): update comment for setupExtensions function
  • Loading branch information
bdbch authored May 14, 2024
1 parent 1ff58ae commit 6049985
Show file tree
Hide file tree
Showing 2 changed files with 92 additions and 85 deletions.
170 changes: 85 additions & 85 deletions packages/core/src/ExtensionManager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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'
Expand All @@ -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<AnyConfig['onBeforeCreate']>(
extension,
'onBeforeCreate',
context,
)

if (onBeforeCreate) {
this.editor.on('beforeCreate', onBeforeCreate)
}

const onCreate = getExtensionField<AnyConfig['onCreate']>(extension, 'onCreate', context)

if (onCreate) {
this.editor.on('create', onCreate)
}

const onUpdate = getExtensionField<AnyConfig['onUpdate']>(extension, 'onUpdate', context)

if (onUpdate) {
this.editor.on('update', onUpdate)
}

const onSelectionUpdate = getExtensionField<AnyConfig['onSelectionUpdate']>(
extension,
'onSelectionUpdate',
context,
)

if (onSelectionUpdate) {
this.editor.on('selectionUpdate', onSelectionUpdate)
}

const onTransaction = getExtensionField<AnyConfig['onTransaction']>(
extension,
'onTransaction',
context,
)

if (onTransaction) {
this.editor.on('transaction', onTransaction)
}

const onFocus = getExtensionField<AnyConfig['onFocus']>(extension, 'onFocus', context)

if (onFocus) {
this.editor.on('focus', onFocus)
}

const onBlur = getExtensionField<AnyConfig['onBlur']>(extension, 'onBlur', context)

if (onBlur) {
this.editor.on('blur', onBlur)
}

const onDestroy = getExtensionField<AnyConfig['onDestroy']>(extension, 'onDestroy', context)

if (onDestroy) {
this.editor.on('destroy', onDestroy)
}
})
this.setupExtensions()
}

/**
Expand Down Expand Up @@ -237,8 +157,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 => {
Expand Down Expand Up @@ -390,4 +310,84 @@ export class ExtensionManager {
}),
)
}

/**
* Go 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<AnyConfig['onBeforeCreate']>(
extension,
'onBeforeCreate',
context,
)
const onCreate = getExtensionField<AnyConfig['onCreate']>(extension, 'onCreate', context)
const onUpdate = getExtensionField<AnyConfig['onUpdate']>(extension, 'onUpdate', context)
const onSelectionUpdate = getExtensionField<AnyConfig['onSelectionUpdate']>(
extension,
'onSelectionUpdate',
context,
)
const onTransaction = getExtensionField<AnyConfig['onTransaction']>(
extension,
'onTransaction',
context,
)
const onFocus = getExtensionField<AnyConfig['onFocus']>(extension, 'onFocus', context)
const onBlur = getExtensionField<AnyConfig['onBlur']>(extension, 'onBlur', context)
const onDestroy = getExtensionField<AnyConfig['onDestroy']>(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)
}
})
}
}
7 changes: 7 additions & 0 deletions packages/core/src/helpers/getExtensionField.ts
Original file line number Diff line number Diff line change
@@ -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<T = any>(
extension: AnyExtension,
field: string,
Expand Down

0 comments on commit 6049985

Please sign in to comment.