@udecode/plate-core
Version:
The core of Plate – a plugin system for slate
1 lines • 669 kB
Source Map (JSON)
{"version":3,"sources":["../src/lib/editor/withSlate.ts","../src/internal/plugin/resolvePlugins.ts","../src/lib/plugin/createSlatePlugin.ts","../src/internal/utils/isFunction.ts","../src/internal/utils/mergePlugins.ts","../src/lib/plugin/getEditorPlugin.ts","../src/internal/plugin/resolvePlugin.ts","../src/lib/plugin/getSlatePlugin.ts","../src/lib/plugins/AstPlugin.ts","../src/lib/plugins/HistoryPlugin.ts","../src/lib/plugins/paragraph/BaseParagraphPlugin.ts","../src/lib/plugins/override/withBreakRules.ts","../src/lib/plugins/override/withDeleteRules.ts","../src/lib/plugins/override/withMergeRules.ts","../src/lib/plugins/override/withNormalizeRules.ts","../src/lib/plugins/override/OverridePlugin.ts","../src/internal/plugin/pipeInsertFragment.ts","../src/internal/plugin/pipeTransformData.ts","../src/internal/plugin/pipeTransformFragment.ts","../src/lib/utils/applyDeepToNodes.ts","../src/lib/utils/defaultsDeepToNodes.ts","../src/lib/utils/getInjectMatch.ts","../src/lib/utils/getKeysByTypes.ts","../src/lib/utils/getInjectedPlugins.ts","../src/lib/utils/getPluginNodeProps.ts","../src/lib/static/pipeRenderElementStatic.tsx","../src/lib/static/components/slate-nodes.tsx","../src/lib/static/pluginRenderElementStatic.tsx","../src/lib/static/utils/createStaticString.ts","../src/lib/static/utils/getNodeDataAttributes.ts","../src/lib/static/utils/getRenderNodeStaticProps.ts","../src/internal/plugin/pipeInjectNodeProps.tsx","../src/internal/plugin/isEditOnlyDisabled.ts","../src/internal/plugin/pluginInjectNodeProps.ts","../src/lib/static/utils/pipeDecorate.ts","../src/lib/static/utils/stripHtmlClassNames.ts","../src/lib/static/utils/stripSlateDataAttributes.ts","../src/lib/static/pluginRenderLeafStatic.tsx","../src/lib/static/components/PlateStatic.tsx","../src/lib/static/pluginRenderTextStatic.tsx","../src/lib/static/serializeHtml.tsx","../src/lib/static/deserialize/checkUtils.ts","../src/lib/static/deserialize/htmlStringToEditorDOM.ts","../src/lib/utils/getSlateClass.ts","../src/lib/utils/hotkeys.ts","../src/lib/utils/isType.ts","../src/lib/utils/mergeDeepToNodes.ts","../src/lib/utils/normalizeDescendantsToDocumentFragment.ts","../src/lib/plugins/affinity/AffinityPlugin.ts","../src/lib/plugins/affinity/queries/getEdgeNodes.ts","../../../node_modules/is-plain-object/dist/is-plain-object.mjs","../../../node_modules/immer/src/utils/env.ts","../../../node_modules/immer/src/utils/errors.ts","../../../node_modules/immer/src/utils/common.ts","../../../node_modules/immer/src/utils/plugins.ts","../../../node_modules/immer/src/core/scope.ts","../../../node_modules/immer/src/core/finalize.ts","../../../node_modules/immer/src/core/proxy.ts","../../../node_modules/immer/src/core/immerClass.ts","../../../node_modules/immer/src/core/current.ts","../../../node_modules/immer/src/plugins/patches.ts","../../../node_modules/immer/src/plugins/mapset.ts","../../../node_modules/immer/src/immer.ts","../../../node_modules/slate/src/interfaces/path-ref.ts","../../../node_modules/slate/src/interfaces/point-ref.ts","../../../node_modules/slate/src/interfaces/range-ref.ts","../../../node_modules/slate/src/utils/weak-maps.ts","../../../node_modules/slate/src/interfaces/path.ts","../../../../../../.yarn/berry/cache/@babel-runtime-npm-7.23.2-d013d6cf7e-10.zip/node_modules/@babel/runtime/helpers/esm/typeof.js","../../../../../../.yarn/berry/cache/@babel-runtime-npm-7.23.2-d013d6cf7e-10.zip/node_modules/@babel/runtime/helpers/esm/toPrimitive.js","../../../../../../.yarn/berry/cache/@babel-runtime-npm-7.23.2-d013d6cf7e-10.zip/node_modules/@babel/runtime/helpers/esm/toPropertyKey.js","../../../../../../.yarn/berry/cache/@babel-runtime-npm-7.23.2-d013d6cf7e-10.zip/node_modules/@babel/runtime/helpers/esm/defineProperty.js","../../../node_modules/slate/src/interfaces/transforms/general.ts","../../../node_modules/slate/src/interfaces/transforms/node.ts","../../../node_modules/slate/src/interfaces/transforms/selection.ts","../../../node_modules/slate/src/utils/deep-equal.ts","../../../../../../.yarn/berry/cache/@babel-runtime-npm-7.23.2-d013d6cf7e-10.zip/node_modules/@babel/runtime/helpers/esm/objectWithoutPropertiesLoose.js","../../../../../../.yarn/berry/cache/@babel-runtime-npm-7.23.2-d013d6cf7e-10.zip/node_modules/@babel/runtime/helpers/esm/objectWithoutProperties.js","../../../node_modules/slate/src/interfaces/range.ts","../../../node_modules/slate/src/interfaces/element.ts","../../../node_modules/slate/src/interfaces/node.ts","../../../node_modules/slate/src/interfaces/operation.ts","../../../node_modules/slate/src/editor/is-editor.ts","../../../node_modules/slate/src/interfaces/editor.ts","../../../node_modules/slate/src/interfaces/location.ts","../../../node_modules/slate/src/interfaces/point.ts","../../../node_modules/slate/src/interfaces/scrubber.ts","../../../node_modules/slate/src/interfaces/text.ts","../../../node_modules/slate/src/utils/get-default-insert-location.ts","../../../node_modules/slate/src/utils/match-path.ts","../../../node_modules/slate/src/utils/string.ts","../../../node_modules/slate/src/interfaces/transforms/text.ts","../../../node_modules/slate/src/interfaces/transforms/index.ts","../../../node_modules/slate/src/core/batch-dirty-paths.ts","../../../node_modules/slate/src/core/update-dirty-paths.ts","../../../node_modules/slate/src/core/apply.ts","../../../node_modules/slate/src/core/get-dirty-paths.ts","../../../node_modules/slate/src/core/get-fragment.ts","../../../node_modules/slate/src/core/normalize-node.ts","../../../node_modules/slate/src/core/should-normalize.ts","../../../node_modules/slate/src/editor/above.ts","../../../node_modules/slate/src/editor/add-mark.ts","../../../node_modules/slate/src/editor/after.ts","../../../node_modules/slate/src/editor/before.ts","../../../node_modules/slate/src/editor/delete-backward.ts","../../../node_modules/slate/src/editor/delete-forward.ts","../../../node_modules/slate/src/editor/delete-fragment.ts","../../../node_modules/slate/src/editor/edges.ts","../../../node_modules/slate/src/editor/element-read-only.ts","../../../node_modules/slate/src/editor/end.ts","../../../node_modules/slate/src/editor/first.ts","../../../node_modules/slate/src/editor/fragment.ts","../../../node_modules/slate/src/editor/get-void.ts","../../../node_modules/slate/src/editor/has-blocks.ts","../../../node_modules/slate/src/editor/has-inlines.ts","../../../node_modules/slate/src/editor/has-path.ts","../../../node_modules/slate/src/editor/has-texts.ts","../../../node_modules/slate/src/editor/insert-break.ts","../../../node_modules/slate/src/editor/insert-node.ts","../../../node_modules/slate/src/editor/insert-soft-break.ts","../../../node_modules/slate/src/editor/insert-text.ts","../../../node_modules/slate/src/editor/is-block.ts","../../../node_modules/slate/src/editor/is-edge.ts","../../../node_modules/slate/src/editor/is-empty.ts","../../../node_modules/slate/src/editor/is-end.ts","../../../node_modules/slate/src/editor/is-normalizing.ts","../../../node_modules/slate/src/editor/is-start.ts","../../../node_modules/slate/src/editor/last.ts","../../../node_modules/slate/src/editor/leaf.ts","../../../node_modules/slate/src/editor/levels.ts","../../../node_modules/slate/src/editor/marks.ts","../../../node_modules/slate/src/editor/next.ts","../../../node_modules/slate/src/editor/node.ts","../../../node_modules/slate/src/editor/nodes.ts","../../../node_modules/slate/src/editor/normalize.ts","../../../node_modules/slate/src/editor/parent.ts","../../../node_modules/slate/src/editor/path-ref.ts","../../../node_modules/slate/src/editor/path-refs.ts","../../../node_modules/slate/src/editor/path.ts","../../../node_modules/slate/src/editor/point-ref.ts","../../../node_modules/slate/src/editor/point-refs.ts","../../../node_modules/slate/src/editor/point.ts","../../../node_modules/slate/src/editor/positions.ts","../../../node_modules/slate/src/editor/previous.ts","../../../node_modules/slate/src/editor/range-ref.ts","../../../node_modules/slate/src/editor/range-refs.ts","../../../node_modules/slate/src/editor/range.ts","../../../node_modules/slate/src/editor/remove-mark.ts","../../../node_modules/slate/src/editor/set-normalizing.ts","../../../node_modules/slate/src/editor/start.ts","../../../node_modules/slate/src/editor/string.ts","../../../node_modules/slate/src/editor/unhang-range.ts","../../../node_modules/slate/src/editor/without-normalizing.ts","../../../node_modules/slate/src/editor/should-merge-nodes-remove-prev-node.ts","../../../node_modules/slate/src/transforms-text/delete-text.ts","../../../node_modules/slate/src/transforms-text/insert-fragment.ts","../../../node_modules/slate/src/transforms-selection/collapse.ts","../../../node_modules/slate/src/transforms-selection/deselect.ts","../../../node_modules/slate/src/transforms-selection/move.ts","../../../node_modules/slate/src/transforms-selection/select.ts","../../../node_modules/slate/src/transforms-selection/set-point.ts","../../../node_modules/slate/src/transforms-selection/set-selection.ts","../../../node_modules/slate/src/transforms-node/insert-nodes.ts","../../../node_modules/slate/src/transforms-node/lift-nodes.ts","../../../node_modules/slate/src/transforms-node/merge-nodes.ts","../../../node_modules/slate/src/transforms-node/move-nodes.ts","../../../node_modules/slate/src/transforms-node/remove-nodes.ts","../../../node_modules/slate/src/transforms-node/set-nodes.ts","../../../node_modules/slate/src/transforms-node/split-nodes.ts","../../../node_modules/slate/src/transforms-node/unset-nodes.ts","../../../node_modules/slate/src/transforms-node/unwrap-nodes.ts","../../../node_modules/slate/src/transforms-node/wrap-nodes.ts","../../../node_modules/slate/src/create-editor.ts","../src/lib/plugins/affinity/queries/getMarkBoundaryAffinity.ts","../src/lib/plugins/affinity/queries/isNodeAffinity.ts","../src/lib/plugins/affinity/transforms/setAffinitySelection.ts","../src/lib/plugins/debug/DebugPlugin.ts","../src/lib/plugins/dom/DOMPlugin.ts","../src/lib/plugins/dom/withScrolling.ts","../src/lib/plugins/html/HtmlPlugin.ts","../src/lib/plugins/html/constants.ts","../src/lib/plugins/html/utils/isHtmlElement.ts","../src/lib/plugins/html/utils/traverseHtmlNode.ts","../src/lib/plugins/html/utils/traverseHtmlElements.ts","../src/lib/plugins/html/utils/cleanHtmlBrElements.ts","../src/lib/plugins/html/utils/cleanHtmlCrLf.ts","../src/lib/plugins/html/utils/cleanHtmlEmptyElements.ts","../src/lib/plugins/html/utils/replaceTagName.ts","../src/lib/plugins/html/utils/cleanHtmlFontElements.ts","../src/lib/plugins/html/utils/isHtmlFragmentHref.ts","../src/lib/plugins/html/utils/unwrapHtmlElement.ts","../src/lib/plugins/html/utils/cleanHtmlLinkElements.ts","../src/lib/plugins/html/utils/isHtmlText.ts","../src/lib/plugins/html/utils/traverseHtmlTexts.ts","../src/lib/plugins/html/utils/cleanHtmlTextNodes.ts","../src/lib/plugins/html/utils/inlineTagNames.ts","../src/lib/plugins/html/utils/isHtmlInlineElement.ts","../src/lib/plugins/html/utils/isHtmlBlockElement.ts","../src/lib/plugins/html/utils/isHtmlTable.ts","../src/lib/plugins/html/utils/copyBlockMarksToSpanChild.ts","../src/lib/plugins/html/utils/collapse-white-space/collapseString.ts","../src/lib/plugins/html/utils/collapse-white-space/isLastNonEmptyTextOfInlineFormattingContext.ts","../src/lib/plugins/html/utils/collapse-white-space/stateTransforms.ts","../src/lib/plugins/html/utils/collapse-white-space/collapseWhiteSpaceText.ts","../src/lib/plugins/html/utils/collapse-white-space/collapseWhiteSpaceNode.ts","../src/lib/plugins/html/utils/collapse-white-space/collapseWhiteSpaceChildren.ts","../src/lib/plugins/html/utils/collapse-white-space/inferWhiteSpaceRule.ts","../src/lib/plugins/html/utils/collapse-white-space/collapseWhiteSpaceElement.ts","../src/lib/plugins/html/utils/collapse-white-space/collapseWhiteSpace.ts","../src/lib/plugins/html/utils/htmlBodyToFragment.ts","../src/lib/plugins/html/utils/deserializeHtmlNodeChildren.ts","../src/lib/plugins/html/utils/htmlBrToNewLine.ts","../src/lib/plugins/html/utils/htmlElementToElement.ts","../src/lib/plugins/html/utils/pluginDeserializeHtml.ts","../src/lib/plugins/html/utils/getDataNodeProps.ts","../src/lib/plugins/html/utils/pipeDeserializeHtmlElement.ts","../src/lib/plugins/html/utils/htmlElementToLeaf.ts","../src/lib/plugins/html/utils/pipeDeserializeHtmlLeaf.ts","../src/lib/plugins/html/utils/htmlTextNodeToString.ts","../src/lib/plugins/html/utils/deserializeHtmlNode.ts","../src/lib/plugins/html/utils/deserializeHtmlElement.ts","../src/lib/plugins/html/utils/htmlStringToDOMNode.ts","../src/lib/plugins/html/utils/deserializeHtml.ts","../src/lib/plugins/html/utils/findHtmlElement.ts","../src/lib/plugins/html/utils/getHtmlComments.ts","../src/lib/plugins/html/utils/isHtmlComment.ts","../src/lib/plugins/html/utils/isOlSymbol.ts","../src/lib/plugins/html/utils/parseHtmlDocument.ts","../src/lib/plugins/html/utils/parseHtmlElement.ts","../src/lib/plugins/html/utils/postCleanHtml.ts","../src/lib/plugins/html/utils/removeHtmlSurroundings.ts","../src/lib/plugins/html/utils/preCleanHtml.ts","../src/lib/plugins/html/utils/traverseHtmlComments.ts","../src/lib/plugins/html/utils/removeHtmlNodesBetweenComments.ts","../src/lib/plugins/length/LengthPlugin.ts","../src/lib/plugins/node-id/NodeIdPlugin.ts","../src/lib/plugins/node-id/withNodeId.ts","../src/lib/plugins/slate-extension/SlateExtensionPlugin.ts","../src/internal/plugin/pipeNormalizeInitialValue.ts","../src/lib/plugins/slate-extension/transforms/init.ts","../src/lib/plugins/slate-extension/transforms/insertExitBreak.ts","../src/lib/plugins/slate-extension/transforms/resetBlock.ts","../src/lib/plugins/slate-extension/transforms/setValue.ts","../src/lib/utils/omitPluginContext.ts","../src/lib/utils/overridePluginsByKey.ts","../src/lib/utils/pipeInsertDataQuery.ts","../src/lib/plugins/ParserPlugin.ts","../src/lib/plugins/getCorePlugins.ts","../src/lib/libs/nanoid.ts","../src/lib/libs/zustand.ts"],"sourcesContent":["import {\n type Editor,\n type TSelection,\n type Value,\n createEditor,\n} from '@udecode/slate';\nimport { nanoid } from 'nanoid';\n\nimport type { AnyPluginConfig, NodeComponents } from '../plugin/BasePlugin';\nimport type { AnySlatePlugin } from '../plugin/SlatePlugin';\nimport type { NodeIdConfig } from '../plugins/node-id/NodeIdPlugin';\nimport type { InferPlugins, SlateEditor, TSlateEditor } from './SlateEditor';\n\nimport { resolvePlugins } from '../../internal/plugin/resolvePlugins';\nimport { createSlatePlugin } from '../plugin/createSlatePlugin';\nimport { getPluginType, getSlatePlugin } from '../plugin/getSlatePlugin';\nimport { type CorePlugin, getCorePlugins } from '../plugins/getCorePlugins';\n\nexport type BaseWithSlateOptions<P extends AnyPluginConfig = CorePlugin> = {\n /**\n * Unique identifier for the editor instance.\n *\n * @default nanoid()\n */\n id?: string;\n /**\n * Determines which mark/element to apply at boundaries between different\n * marks, based on cursor movement using the left/right arrow keys.\n *\n * Example: <text bold>Bold</text><cursor><text italic>Italic</text>\n *\n * If the cursor moved here from the left (via → key), typing applies\n * **bold**.\n *\n * If the cursor moved here from the right (via ← key), typing applies\n * _italic_.\n *\n * Without mark affinity, the preceding mark (**bold**) is always applied\n * regardless of direction.\n *\n * @default true\n */\n affinity?: boolean;\n /**\n * Select the editor after initialization.\n *\n * @default false\n *\n * - `true` | 'end': Select the end of the editor\n * - `false`: Do not select anything\n * - `'start'`: Select the start of the editor\n */\n autoSelect?: boolean | 'end' | 'start';\n /** Specifies the component for each plugin key. */\n components?: NodeComponents;\n /** Specifies the component for each plugin key. */\n // components?: Partial<\n // Record<KeyofNodePlugins<InferPlugins<P[]>>, NodeComponent | null>\n // >;\n /**\n * Specifies the maximum number of characters allowed in the editor. When the\n * limit is reached, further input will be prevented.\n */\n maxLength?: number;\n /**\n * Configuration for automatic node ID generation and management.\n *\n * Unless set to `false`, the editor automatically adds unique IDs to nodes\n * through the core NodeIdPlugin:\n *\n * - Normalizes the initial value for missing IDs\n * - Adds IDs to new nodes during insertion\n * - Preserves or reuses IDs on undo/redo and copy/paste operations\n * - Handles ID conflicts and duplicates\n *\n * @default { idKey: 'id', filterInline: true, filterText: true, idCreator: () => nanoid(10) }\n */\n nodeId?: NodeIdConfig['options'] | boolean;\n // override?: {\n // components?: Partial<\n // Record<KeyofNodePlugins<InferPlugins<P[]>>, NodeComponent | null>\n // >;\n // };\n /**\n * Array of plugins to be loaded into the editor. Plugins extend the editor's\n * functionality and define custom behavior.\n */\n plugins?: P[];\n /**\n * Editor read-only initial state. For dynamic read-only control, use the\n * `Plate.readOnly` prop instead.\n *\n * @default false\n */\n readOnly?: boolean;\n /**\n * Initial selection state for the editor. Defines where the cursor should be\n * positioned when the editor loads.\n */\n selection?: TSelection;\n /**\n * When `true`, normalizes the initial `value` passed to the editor. This is\n * useful when adding normalization rules to already existing content or when\n * the initial value might not conform to the current schema.\n *\n * Note: Normalization may take time for large documents.\n *\n * @default false\n */\n shouldNormalizeEditor?: boolean;\n /**\n * When `true`, skips the initial value, selection, and normalization logic.\n * Useful when the editor state is managed externally (e.g., with Yjs\n * collaboration) or when you want to manually control the initialization\n * process.\n *\n * @default false\n */\n skipInitialization?: boolean;\n};\n\nexport type WithSlateOptions<\n V extends Value = Value,\n P extends AnyPluginConfig = CorePlugin,\n> = BaseWithSlateOptions<P> &\n Pick<\n Partial<AnySlatePlugin>,\n | 'api'\n | 'decorate'\n | 'extendEditor'\n | 'inject'\n | 'normalizeInitialValue'\n | 'options'\n | 'override'\n | 'transforms'\n > & {\n // override?: {\n // /** Enable or disable plugins */\n // enabled?: Partial<Record<KeyofPlugins<InferPlugins<P[]>>, boolean>>;\n // plugins?: Partial<\n // Record<\n // KeyofPlugins<InferPlugins<P[]>>,\n // PartialEditorPlugin<AnyPluginConfig>\n // >\n // >;\n // };\n /**\n * Initial content for the editor.\n *\n * Can be:\n *\n * - A static value (array of nodes)\n * - An HTML string that will be deserialized\n * - A function that returns a value or Promise<value>\n * - `null` for an empty editor\n *\n * @default [{ type: 'p'; children: [{ text: '' }] }]\n */\n value?: ((editor: SlateEditor) => Promise<V> | V) | V | string | null;\n /** Function to configure the root plugin */\n rootPlugin?: (plugin: AnySlatePlugin) => AnySlatePlugin;\n };\n\n/**\n * Applies Plate enhancements to an editor instance (non-React version).\n *\n * @remarks\n * This function supports server-side usage as it doesn't include React-specific\n * features like component rendering or hooks integration.\n * @see {@link createSlateEditor} for a higher-level non-React editor creation function.\n * @see {@link createPlateEditor} for a React-specific version of editor creation.\n * @see {@link usePlateEditor} for a memoized React version.\n * @see {@link withPlate} for the React-specific enhancement function.\n */\nexport const withSlate = <\n V extends Value = Value,\n P extends AnyPluginConfig = CorePlugin,\n>(\n e: Editor,\n {\n id,\n affinity = true,\n autoSelect,\n maxLength,\n nodeId,\n plugins = [],\n readOnly = false,\n rootPlugin,\n selection,\n shouldNormalizeEditor,\n skipInitialization,\n value,\n ...pluginConfig\n }: WithSlateOptions<V, P> = {}\n): TSlateEditor<V, InferPlugins<P[]>> => {\n const editor = e as SlateEditor;\n\n editor.id = id ?? editor.id ?? nanoid();\n editor.meta.key = editor.meta.key ?? nanoid();\n editor.meta.isFallback = false;\n editor.dom = {\n composing: false,\n currentKeyboardEvent: null,\n focused: false,\n prevSelection: null,\n readOnly,\n };\n\n editor.getApi = () => editor.api as any;\n editor.getTransforms = () => editor.transforms as any;\n editor.getPlugin = (plugin) => getSlatePlugin(editor, plugin) as any;\n editor.getType = (pluginKey) => getPluginType(editor, pluginKey);\n editor.getInjectProps = (plugin) => {\n const nodeProps =\n editor.getPlugin<AnySlatePlugin>(plugin).inject?.nodeProps ?? ({} as any);\n\n nodeProps.nodeKey = nodeProps.nodeKey ?? editor.getType(plugin.key);\n nodeProps.styleKey = nodeProps.styleKey ?? nodeProps.nodeKey;\n\n return nodeProps;\n };\n editor.getOptionsStore = (plugin) => {\n return editor.getPlugin(plugin).optionsStore;\n };\n editor.getOptions = (plugin) => {\n const store = editor.getOptionsStore(plugin);\n\n if (!store) return editor.getPlugin(plugin).options;\n\n return editor.getOptionsStore(plugin).get('state');\n };\n editor.getOption = (plugin, key, ...args) => {\n const store = editor.getOptionsStore(plugin);\n\n if (!store) return editor.getPlugin(plugin).options[key];\n\n if (!(key in store.get('state')) && !(key in store.selectors)) {\n editor.api.debug.error(\n `editor.getOption: ${key as string} option is not defined in plugin ${plugin.key}.`,\n 'OPTION_UNDEFINED'\n );\n return;\n }\n\n return (store.get as any)(key, ...args);\n };\n editor.setOption = (plugin: any, key: any, ...args: any) => {\n const store = editor.getOptionsStore(plugin);\n\n if (!store) return;\n\n if (!(key in store.get('state'))) {\n editor.api.debug.error(\n `editor.setOption: ${key} option is not defined in plugin ${plugin.key}.`,\n 'OPTION_UNDEFINED'\n );\n return;\n }\n\n (store.set as any)(key, ...args);\n };\n editor.setOptions = (plugin: any, options: any) => {\n const store = editor.getOptionsStore(plugin);\n\n if (!store) return;\n if (typeof options === 'object') {\n store.set('state', (draft: any) => {\n Object.assign(draft, options);\n });\n } else if (typeof options === 'function') {\n store.set('state', options);\n }\n };\n\n // Plugin initialization code\n const corePlugins = getCorePlugins({\n affinity,\n maxLength,\n nodeId,\n plugins,\n });\n\n let rootPluginInstance = createSlatePlugin({\n key: 'root',\n priority: 10_000,\n ...pluginConfig,\n override: {\n ...pluginConfig.override,\n components: {\n ...pluginConfig.components,\n ...pluginConfig.override?.components,\n },\n },\n plugins: [...corePlugins, ...plugins],\n });\n\n // Apply rootPlugin configuration if provided\n if (rootPlugin) {\n rootPluginInstance = rootPlugin(rootPluginInstance) as any;\n }\n\n resolvePlugins(editor, [rootPluginInstance]);\n\n /** Ignore normalizeNode overrides if shouldNormalizeNode returns false */\n const normalizeNode = editor.tf.normalizeNode;\n editor.tf.normalizeNode = (...args) => {\n if (!editor.api.shouldNormalizeNode(args[0])) {\n return;\n }\n\n return normalizeNode(...args);\n };\n editor.normalizeNode = editor.tf.normalizeNode;\n\n if (!skipInitialization) {\n void editor.tf.init({\n autoSelect,\n selection,\n shouldNormalizeEditor,\n value,\n });\n }\n\n return editor as any;\n};\n\nexport type CreateSlateEditorOptions<\n V extends Value = Value,\n P extends AnyPluginConfig = CorePlugin,\n> = WithSlateOptions<V, P> & {\n /**\n * Initial editor to be extended with `withSlate`.\n *\n * @default createEditor()\n */\n editor?: Editor;\n};\n\n/**\n * Creates a Slate editor (non-React version).\n *\n * This function creates a fully configured Plate editor instance that can be\n * used in non-React environments or server-side contexts. It applies all the\n * specified plugins and configurations to create a functional editor.\n *\n * Examples:\n *\n * ```ts\n * const editor = createSlateEditor({\n * plugins: [ParagraphPlugin, HeadingPlugin],\n * value: [{ type: 'p', children: [{ text: 'Hello world!' }] }],\n * });\n *\n * // Editor with custom configuration\n * const editor = createSlateEditor({\n * plugins: [ParagraphPlugin],\n * maxLength: 1000,\n * nodeId: { idCreator: () => uuidv4() },\n * autoSelect: 'end',\n * });\n *\n * // Server-side editor\n * const editor = createSlateEditor({\n * plugins: [ParagraphPlugin],\n * value: '<p>HTML content</p>',\n * skipInitialization: true,\n * });\n * ```\n *\n * @see {@link createPlateEditor} for a React-specific version of editor creation.\n * @see {@link usePlateEditor} for a memoized React version.\n * @see {@link withSlate} for the underlying function that applies Slate enhancements to an editor.\n */\nexport const createSlateEditor = <\n V extends Value = Value,\n P extends AnyPluginConfig = CorePlugin,\n>({\n editor = createEditor(),\n ...options\n}: CreateSlateEditorOptions<V, P> = {}) => {\n return withSlate<V, P>(editor, options);\n};\n","import {\n assignLegacyApi,\n assignLegacyTransforms,\n syncLegacyMethods,\n} from '@udecode/slate';\nimport { isDefined } from '@udecode/utils';\nimport merge from 'lodash/merge.js';\nimport { createZustandStore } from 'zustand-x';\n\nimport type { SlateEditor, SlatePlugin, SlatePlugins } from '../../lib';\n\nimport { getEditorPlugin } from '../../lib/plugin';\nimport { mergePlugins } from '../utils/mergePlugins';\nimport { resolvePlugin } from './resolvePlugin';\n\n/**\n * Initialize and configure the editor's plugin system. This function sets up\n * the editor's plugins, resolving core and custom plugins, and applying any\n * overrides specified in the plugins.\n */\nexport const resolvePlugins = (\n editor: SlateEditor,\n plugins: SlatePlugins = []\n) => {\n editor.plugins = {};\n editor.meta.pluginList = [];\n editor.meta.shortcuts = {} as Record<\n string,\n SlatePlugin['shortcuts'][string]\n >;\n editor.meta.components = {};\n editor.meta.pluginCache = {\n decorate: [],\n handlers: {\n onChange: [],\n },\n inject: {\n nodeProps: [],\n },\n node: {\n isContainer: [],\n isElement: [],\n isInline: [],\n isLeaf: [],\n isMarkableVoid: [],\n isNotSelectable: [],\n isStrictSiblings: [],\n isVoid: [],\n types: {},\n },\n normalizeInitialValue: [],\n render: {\n aboveEditable: [],\n aboveNodes: [],\n aboveSlate: [],\n afterContainer: [],\n afterEditable: [],\n beforeContainer: [],\n beforeEditable: [],\n belowNodes: [],\n belowRootNodes: [],\n },\n rules: {\n match: [],\n },\n useHooks: [],\n };\n\n const resolvedPlugins = resolveAndSortPlugins(editor, plugins);\n\n applyPluginsToEditor(editor, resolvedPlugins);\n\n resolvePluginOverrides(editor);\n\n resolvePluginStores(editor);\n\n // Last pass\n editor.meta.pluginList.forEach((plugin: SlatePlugin) => {\n if (plugin.extendEditor) {\n editor = plugin.extendEditor(getEditorPlugin(editor, plugin) as any);\n\n // Sync any editor methods that were modified by extendEditor\n syncLegacyMethods(editor);\n }\n\n // Sync overridden plugin methods to legacy editor methods\n resolvePluginMethods(editor, plugin);\n\n if (plugin.node?.isContainer) {\n editor.meta.pluginCache.node.isContainer.push(plugin.key);\n }\n\n editor.meta.pluginCache.node.types[plugin.node.type] = plugin.key;\n\n if (plugin.inject?.nodeProps) {\n editor.meta.pluginCache.inject.nodeProps.push(plugin.key);\n }\n\n if (plugin.render?.node) {\n editor.meta.components[plugin.key] = plugin.render.node;\n }\n\n if (plugin.node?.isLeaf) {\n editor.meta.pluginCache.node.isLeaf.push(plugin.key);\n }\n\n if (plugin.node?.isElement) {\n editor.meta.pluginCache.node.isElement.push(plugin.key);\n }\n\n if (plugin.node?.isInline) {\n editor.meta.pluginCache.node.isInline.push(plugin.key);\n }\n\n if (plugin.node?.isVoid) {\n editor.meta.pluginCache.node.isVoid.push(plugin.key);\n }\n\n if (plugin.node?.isMarkableVoid) {\n editor.meta.pluginCache.node.isMarkableVoid.push(plugin.key);\n }\n\n if (plugin.node?.isStrictSiblings) {\n editor.meta.pluginCache.node.isStrictSiblings.push(plugin.key);\n }\n\n if (plugin.node?.isSelectable === false) {\n editor.meta.pluginCache.node.isNotSelectable.push(plugin.key);\n }\n\n if (plugin.render.aboveEditable) {\n editor.meta.pluginCache.render.aboveEditable.push(plugin.key);\n }\n\n if (plugin.render.aboveSlate) {\n editor.meta.pluginCache.render.aboveSlate.push(plugin.key);\n }\n\n if (plugin.render.afterEditable) {\n editor.meta.pluginCache.render.afterEditable.push(plugin.key);\n }\n\n if (plugin.render.beforeEditable) {\n editor.meta.pluginCache.render.beforeEditable.push(plugin.key);\n }\n\n if (plugin.rules?.match) {\n editor.meta.pluginCache.rules.match.push(plugin.key);\n }\n\n if (plugin.render.afterContainer) {\n editor.meta.pluginCache.render.afterContainer.push(plugin.key);\n }\n\n if (plugin.render.beforeContainer) {\n editor.meta.pluginCache.render.beforeContainer.push(plugin.key);\n }\n\n if (plugin.render.belowRootNodes) {\n editor.meta.pluginCache.render.belowRootNodes.push(plugin.key);\n }\n\n if (plugin.normalizeInitialValue) {\n editor.meta.pluginCache.normalizeInitialValue.push(plugin.key);\n }\n\n if (plugin.decorate) {\n editor.meta.pluginCache.decorate.push(plugin.key);\n }\n\n if (plugin.render.aboveNodes) {\n editor.meta.pluginCache.render.aboveNodes.push(plugin.key);\n }\n\n if (plugin.render.belowNodes) {\n editor.meta.pluginCache.render.belowNodes.push(plugin.key);\n }\n\n if ((plugin as any).useHooks) {\n editor.meta.pluginCache.useHooks.push(plugin.key);\n }\n\n if ((plugin as any).handlers?.onChange) {\n editor.meta.pluginCache.handlers.onChange.push(plugin.key);\n }\n });\n\n resolvePluginShortcuts(editor);\n\n return editor;\n};\n\nconst resolvePluginStores = (editor: SlateEditor) => {\n // Create zustand stores for each plugin\n editor.meta.pluginList.forEach((plugin) => {\n let store = createZustandStore(plugin.options, {\n mutative: true,\n name: plugin.key,\n });\n\n // Apply option extensions\n if (\n (plugin as any).__selectorExtensions &&\n (plugin as any).__selectorExtensions.length > 0\n ) {\n (plugin as any).__selectorExtensions.forEach((extension: any) => {\n const extendedOptions = extension(getEditorPlugin(editor, plugin));\n\n store = store.extendSelectors(() => extendedOptions);\n });\n }\n\n plugin.optionsStore = store;\n });\n};\n\nconst resolvePluginMethods = (editor: SlateEditor, plugin: any) => {\n // Merge APIs\n Object.entries(plugin.api).forEach(([apiKey, apiFunction]) => {\n (editor.api as any)[apiKey] = apiFunction;\n });\n\n // Apply API and transform extensions\n if (plugin.__apiExtensions && plugin.__apiExtensions.length > 0) {\n plugin.__apiExtensions.forEach(\n ({ extension, isOverride, isPluginSpecific, isTransform }: any) => {\n const newExtensions = extension(getEditorPlugin(editor, plugin) as any);\n\n if (isOverride) {\n // Handle combined API and transforms override\n if (newExtensions.api) {\n merge(editor.api, newExtensions.api);\n merge(plugin.api, newExtensions.api);\n assignLegacyApi(editor, editor.api);\n }\n if (newExtensions.transforms) {\n merge(editor.transforms, newExtensions.transforms);\n merge(plugin.transforms, newExtensions.transforms);\n assignLegacyTransforms(editor, newExtensions.transforms);\n }\n } else if (isTransform) {\n // Handle transforms\n if (isPluginSpecific) {\n // Plugin-specific transform\n if (!(editor.transforms as any)[plugin.key]) {\n (editor.transforms as any)[plugin.key] = {};\n }\n if (!(plugin.transforms as any)[plugin.key]) {\n (plugin.transforms as any)[plugin.key] = {};\n }\n\n merge((editor.transforms as any)[plugin.key], newExtensions);\n merge((plugin.transforms as any)[plugin.key], newExtensions);\n } else {\n // Editor-wide transform\n merge(editor.transforms, newExtensions);\n merge(plugin.transforms, newExtensions);\n assignLegacyTransforms(editor, newExtensions);\n }\n } else {\n // Handle APIs\n if (isPluginSpecific) {\n // Plugin-specific API\n if (!(editor.api as any)[plugin.key]) {\n (editor.api as any)[plugin.key] = {};\n }\n if (!(plugin.api as any)[plugin.key]) {\n (plugin.api as any)[plugin.key] = {};\n }\n\n merge((editor.api as any)[plugin.key], newExtensions);\n merge((plugin.api as any)[plugin.key], newExtensions);\n } else {\n // Editor-wide API\n merge(editor.api, newExtensions);\n merge(plugin.api, newExtensions);\n assignLegacyApi(editor, editor.api);\n }\n }\n }\n );\n delete plugin.__apiExtensions;\n }\n};\n\nconst resolvePluginShortcuts = (editor: SlateEditor) => {\n editor.meta.shortcuts = {} as Record<\n string,\n SlatePlugin['shortcuts'][string]\n >; // Initialize with a more specific type\n\n editor.meta.pluginList.forEach((plugin) => {\n Object.entries(plugin.shortcuts).forEach(([originalKey, hotkey]) => {\n const namespacedKey = `${plugin.key}.${originalKey}`;\n\n if (hotkey === null) {\n // If hotkey is null, remove the namespaced shortcut\n delete (\n editor.meta.shortcuts as Record<\n string,\n SlatePlugin['shortcuts'][string]\n >\n )[namespacedKey];\n } else if (hotkey && typeof hotkey === 'object') {\n const resolvedHotkey = { ...hotkey } as NonNullable<\n SlatePlugin['shortcuts'][string]\n >;\n\n // If no custom handler is provided, try to use plugin transform method as handler\n if (!resolvedHotkey.handler) {\n const pluginSpecificTransforms = (plugin.transforms as any)?.[\n plugin.key\n ];\n const pluginSpecificApi = (plugin.api as any)?.[plugin.key];\n\n if (pluginSpecificTransforms?.[originalKey]) {\n resolvedHotkey.handler = () => {\n return pluginSpecificTransforms[originalKey]();\n };\n } else if (pluginSpecificApi?.[originalKey]) {\n resolvedHotkey.handler = () => {\n return pluginSpecificApi[originalKey]();\n };\n }\n }\n\n // Set shortcut priority, falling back to plugin priority\n resolvedHotkey.priority = resolvedHotkey.priority ?? plugin.priority;\n\n (\n editor.meta.shortcuts as Record<\n string,\n SlatePlugin['shortcuts'][string]\n >\n )[namespacedKey] = resolvedHotkey;\n }\n });\n });\n};\n\nconst flattenAndResolvePlugins = (\n editor: SlateEditor,\n plugins: SlatePlugins\n): Map<string, SlatePlugin> => {\n const pluginMap = new Map<string, SlatePlugin>();\n\n const processPlugin = (plugin: SlatePlugin) => {\n const resolvedPlugin = resolvePlugin(editor, plugin);\n\n if (resolvedPlugin.key) {\n const existingPlugin = pluginMap.get(resolvedPlugin.key);\n\n if (existingPlugin) {\n pluginMap.set(\n resolvedPlugin.key,\n mergePlugins(existingPlugin, resolvedPlugin)\n );\n } else {\n pluginMap.set(resolvedPlugin.key, resolvedPlugin);\n }\n } else {\n // If the plugin has no key, we just just skip it.\n }\n\n if (resolvedPlugin.plugins && resolvedPlugin.plugins.length > 0) {\n resolvedPlugin.plugins.forEach(processPlugin);\n }\n };\n\n plugins.forEach(processPlugin);\n\n return pluginMap;\n};\n\nexport const resolveAndSortPlugins = (\n editor: SlateEditor,\n plugins: SlatePlugins\n): SlatePlugins => {\n // Step 1: Resolve, flatten, and merge all plugins\n const pluginMap = flattenAndResolvePlugins(editor, plugins);\n\n // Step 2: Filter out disabled plugins\n const enabledPlugins = Array.from(pluginMap.values()).filter(\n (plugin) => plugin.enabled !== false\n );\n\n // Step 3: Sort plugins by priority\n enabledPlugins.sort((a, b) => b.priority - a.priority);\n\n // Step 4: Reorder based on dependencies\n const orderedPlugins: SlatePlugins = [];\n const visited = new Set<string>();\n\n const visit = (plugin: SlatePlugin) => {\n if (visited.has(plugin.key)) return;\n\n visited.add(plugin.key);\n\n plugin.dependencies?.forEach((depKey) => {\n const depPlugin = pluginMap.get(depKey);\n\n if (depPlugin) {\n visit(depPlugin);\n } else {\n editor.api.debug.warn(\n `Plugin \"${plugin.key}\" depends on missing plugin \"${depKey}\"`,\n 'PLUGIN_DEPENDENCY_MISSING'\n );\n }\n });\n\n orderedPlugins.push(plugin);\n };\n\n enabledPlugins.forEach(visit);\n\n return orderedPlugins;\n};\n\nexport const applyPluginsToEditor = (\n editor: SlateEditor,\n plugins: SlatePlugins\n) => {\n editor.meta.pluginList = plugins;\n editor.plugins = Object.fromEntries(\n plugins.map((plugin) => [plugin.key, plugin])\n );\n};\n\nexport const resolvePluginOverrides = (editor: SlateEditor) => {\n const applyOverrides = (plugins: SlatePlugin[]): SlatePlugin[] => {\n let overriddenPlugins = [...plugins];\n\n const enabledOverrides: Record<string, boolean> = {};\n const componentOverrides: Record<\n string,\n { component: any; priority: number }\n > = {};\n const pluginOverrides: Record<string, Partial<SlatePlugin>> = {};\n\n // Collect all overrides\n for (const plugin of plugins) {\n if (plugin.override.enabled) {\n Object.assign(enabledOverrides, plugin.override.enabled);\n }\n // TODO react\n if ((plugin.override as any).components) {\n Object.entries((plugin.override as any).components).forEach(\n ([key, component]) => {\n if (\n !componentOverrides[key] ||\n plugin.priority > componentOverrides[key].priority\n ) {\n componentOverrides[key] = {\n component,\n priority: plugin.priority,\n };\n }\n }\n );\n }\n if (plugin.override.plugins) {\n Object.entries(plugin.override.plugins).forEach(([key, value]) => {\n pluginOverrides[key] = mergePlugins(pluginOverrides[key], value);\n\n if (value.enabled !== undefined) {\n enabledOverrides[key] = value.enabled;\n }\n });\n }\n }\n\n // Apply overrides\n overriddenPlugins = overriddenPlugins.map((p) => {\n let updatedPlugin = { ...p };\n\n // Apply plugin overrides\n if (pluginOverrides[p.key]) {\n updatedPlugin = mergePlugins(updatedPlugin, pluginOverrides[p.key]);\n }\n // Apply component overrides\n // TODO react\n if (\n componentOverrides[p.key] &&\n ((!(p as any).render.node && !(p as any).node.component) ||\n componentOverrides[p.key].priority > p.priority)\n ) {\n (updatedPlugin as any).render.node =\n componentOverrides[p.key].component;\n (updatedPlugin as any).node.component =\n componentOverrides[p.key].component;\n }\n\n // Apply enabled overrides\n const enabled = enabledOverrides[p.key] ?? updatedPlugin.enabled;\n\n if (isDefined(enabled)) {\n updatedPlugin.enabled = enabled;\n }\n\n return updatedPlugin;\n });\n\n return overriddenPlugins\n .filter((p) => p.enabled !== false)\n .map((plugin) => ({\n ...plugin,\n plugins: applyOverrides(plugin.plugins || []),\n }));\n };\n\n applyPluginsToEditor;\n\n editor.meta.pluginList = applyOverrides(editor.meta.pluginList as any);\n editor.plugins = Object.fromEntries(\n editor.meta.pluginList.map((plugin) => [plugin.key, plugin])\n );\n};\n","import { type Modify, isDefined } from '@udecode/utils';\n\nimport type { SlateEditor } from '../editor/SlateEditor';\nimport type { AnyPluginConfig, PluginConfig } from './BasePlugin';\nimport type {\n SlatePlugin,\n SlatePluginMethods,\n SlatePlugins,\n} from './SlatePlugin';\n\nimport { isFunction } from '../../internal/utils/isFunction';\nimport { mergePlugins } from '../../internal/utils/mergePlugins';\n\ntype SlatePluginConfig<\n K extends string = any,\n O = {},\n A = {},\n T = {},\n S = {},\n> = Omit<\n Partial<\n Modify<\n SlatePlugin<PluginConfig<K, O, A, T, S>>,\n { node?: Partial<SlatePlugin<PluginConfig<K, O, A, T, S>>['node']> }\n >\n >,\n keyof SlatePluginMethods | 'optionsStore'\n>;\n\ntype TSlatePluginConfig<C extends AnyPluginConfig = PluginConfig> = Omit<\n Partial<\n Modify<\n SlatePlugin<C>,\n {\n node?: Partial<SlatePlugin<C>['node']>;\n }\n >\n >,\n keyof SlatePluginMethods | 'optionsStore'\n>;\n\n/**\n * Creates a new Plate plugin with the given configuration.\n *\n * @remarks\n * - The plugin's key is required and specified by the K generic.\n * - The `__extensions` array stores functions to be applied when `resolvePlugin`\n * is called with an editor.\n * - The `extend` method adds new extensions to be applied later.\n * - The `extendPlugin` method extends an existing plugin (including nested\n * plugins) or adds a new one if not found.\n *\n * @example\n * const myPlugin = createSlatePlugin<\n * 'myPlugin',\n * MyOptions,\n * MyApi,\n * MyTransforms\n * >({\n * key: 'myPlugin',\n * options: { someOption: true },\n * transforms: { someTransform: () => {} },\n * });\n *\n * const extendedPlugin = myPlugin.extend({\n * options: { anotherOption: false },\n * });\n *\n * const pluginWithNestedExtension = extendedPlugin.extendPlugin(\n * nestedPlugin,\n * { options: { nestedOption: true } }\n * );\n *\n * @template K - The literal type of the plugin key.\n * @template O - The type of the plugin options.\n * @template A - The type of the plugin utilities.\n * @template T - The type of the plugin transforms.\n * @template S - The type of the plugin storage.\n * @param {Partial<SlatePlugin<K, O, A, T, S>>} config - The configuration\n * object for the plugin.\n * @returns {SlatePlugin<K, O, A, T, S>} A new Plate plugin instance with the\n * following properties and methods:\n *\n * - All properties from the input config, merged with default values.\n * - `configure`: A method to create a new plugin instance with updated options.\n * - `extend`: A method to create a new plugin instance with additional\n * configuration.\n * - `extendPlugin`: A method to extend an existing plugin (including nested\n * plugins) or add a new one if not found.\n */\nexport function createSlatePlugin<\n K extends string = any,\n O = {},\n A = {},\n T = {},\n S = {},\n>(\n config:\n | ((editor: SlateEditor) => SlatePluginConfig<K, O, A, T, S>)\n | SlatePluginConfig<K, O, A, T, S> = {}\n): SlatePlugin<PluginConfig<K, O, A, T, S>> {\n let baseConfig: Partial<SlatePlugin<PluginConfig<K, O, A, T, S>>>;\n let initialExtension: any;\n\n if (isFunction(config)) {\n baseConfig = { key: '' as K };\n initialExtension = (editor: any) => config(editor);\n } else {\n baseConfig = config as any;\n }\n\n const key = baseConfig.key ?? '';\n\n const plugin = mergePlugins(\n {\n key,\n __apiExtensions: [],\n __configuration: null,\n __extensions: initialExtension ? [initialExtension] : [],\n __selectorExtensions: [],\n api: {},\n dependencies: [],\n editor: {},\n handlers: {},\n inject: {},\n node: { type: key },\n options: {},\n override: {},\n parser: {},\n parsers: {},\n plugins: [],\n priority: 100,\n render: {},\n rules: {},\n shortcuts: {},\n transforms: {},\n },\n config\n ) as unknown as SlatePlugin<PluginConfig<K, O, A, T, S>>;\n\n if (plugin.node.isLeaf && !isDefined(plugin.node.isDecoration)) {\n plugin.node.isDecoration = true;\n }\n\n plugin.configure = (config) => {\n const newPlugin = { ...plugin };\n newPlugin.__configuration = (ctx) =>\n isFunction(config) ? config(ctx as any) : config;\n\n return createSlatePlugin(newPlugin) as any;\n };\n\n plugin.configurePlugin = (p, config) => {\n const newPlugin = { ...plugin };\n\n const configureNestedPlugin = (\n plugins: SlatePlugins\n ): { found: boolean; plugins: SlatePlugins } => {\n let found = false;\n\n const updatedPlugins = plugins.map((nestedPlugin) => {\n if (nestedPlugin.key === p.key) {\n found = true;\n\n return createSlatePlugin({\n ...nestedPlugin,\n __configuration: (ctx: any) =>\n isFunction(config) ? config(ctx) : config,\n } as any);\n }\n if (nestedPlugin.plugins && nestedPlugin.plugins.length > 0) {\n const result = configureNestedPlugin(nestedPlugin.plugins);\n\n if (result.found) {\n found = true;\n\n return { ...nestedPlugin, plugins: result.plugins };\n }\n }\n\n return nestedPlugin;\n });\n\n return { found, plugins: updatedPlugins };\n };\n\n const result = configureNestedPlugin(newPlugin.plugins as any);\n newPlugin.plugins = result.plugins as any;\n\n // We're not adding a new plugin if not found\n\n return createSlatePlugin(newPlugin);\n };\n\n plugin.extendEditorApi = (extension) => {\n const newPlugin = { ...plugin };\n newPlugin.__apiExtensions = [\n ...(newPlugin.__apiExtensions as any),\n { extension, isPluginSpecific: false },\n ];\n\n return createSlatePlugin(newPlugin) as any;\n };\n\n plugin.extendSelectors = (extension) => {\n const newPlugin = { ...plugin };\n newPlugin.__selectorExtensions = [\n ...(newPlugin.__selectorExtensions as any),\n extension,\n ];\n\n return createSlatePlugin(newPlugin) as any;\n };\n\n plugin.extendApi = (extension) => {\n const newPlugin = { ...plugin };\n newPlugin.__apiExtensions = [\n ...(newPlugin.__apiExtensions as any),\n { extension, isPluginSpecific: true },\n ];\n\n return createSlatePlugin(newPlugin) as any;\n };\n\n plugin.extendEditorTransforms = (extension) => {\n const newPlugin = { ...plugin };\n newPlugin.__apiExtensions = [\n ...(newPlugin.__apiExtensions as any),\n { extension, isPluginSpecific: false, isTransform: true },\n ];\n\n return createSlatePlugin(newPlugin) as any;\n };\n\n plugin.extendTransforms = (extension) => {\n const newPlugin = { ...plugin };\n newPlugin.__apiExtensions = [\n ...(newPlugin.__apiExtensions as any),\n { extension, isPluginSpecific: true, isTransform: true },\n ];\n\n return createSlatePlugin(newPlugin) as any;\n };\n\n plugin.overrideEditor = (extension) => {\n const newPlugin = { ...plugin };\n newPlugin.__apiExtensions = [\n ...(newPlugin.__apiExtensions as any),\n {\n extension,\n isOverride: true,\n isPluginSpecific: false,\n isTransform: true,\n },\n ];\n\n return createSlatePlugin(newPlugin) as any;\n };\n\n plugin.extend = (extendConfig) => {\n let newPlugin = { ...plugin };\n\n if (isFunction(extendConfig)) {\n newPlugin.__extensions = [\n ...(newPlugin.__extensions as any),\n extendConfig,\n ];\n } else {\n newPlugin = mergePlugins(newPlugin, extendConfig as any);\n }\n\n return createSlatePlugin(newPlugin) as any;\n };\n\n plugin.clone = () => mergePlugins(plugin);\n\n plugin.extendPlugin = (p, extendConfig) => {\n const newPlugin = { ...plugin };\n\n const extendNestedPlugin = (\n plugins: SlatePlugins\n ): { found: boolean; plugins: SlatePlugins } => {\n let found = false;\n const updatedPlugins = plugins.map((nestedPlugin) => {\n if (nestedPlugin.key === p.key) {\n found = true;\n\n return createSlatePlugin({\n ...nestedPlugin,\n __extensions: [\n ...(nestedPlugin.__extensions as any),\n (ctx: any) =>\n isFunction(extendConfig) ? extendConfig(ctx) : extendConfig,\n ],\n } as any);\n }\n if (nestedPlugin.plugins && nestedPlugin.plugins.length > 0) {\n const result = extendNestedPlugin(nestedPlugin.plugins);\n\n if (result.found) {\n found = true;\n\n return { ...nestedPlugin, plugins: result.plugins };\n }\n }\n\n return nestedPlugin;\n });\n\n return { found, plugins: updatedPlugins };\n };\