UNPKG

@udecode/plate-core

Version:

The core of Plate – a plugin system for slate

1,585 lines (1,526 loc) 118 kB
"use strict"; var __create = Object.create; var __defProp = Object.defineProperty; var __getOwnPropDesc = Object.getOwnPropertyDescriptor; var __getOwnPropNames = Object.getOwnPropertyNames; var __getProtoOf = Object.getPrototypeOf; var __hasOwnProp = Object.prototype.hasOwnProperty; var __export = (target, all) => { for (var name in all) __defProp(target, name, { get: all[name], enumerable: true }); }; var __copyProps = (to, from, except, desc) => { if (from && typeof from === "object" || typeof from === "function") { for (let key of __getOwnPropNames(from)) if (!__hasOwnProp.call(to, key) && key !== except) __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable }); } return to; }; var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps( // If the importer is in node compatibility mode or this is not an ESM // file that has been converted to a CommonJS file using a Babel- // compatible transform (i.e. "__esModule" has not been set), then set // "default" to the CommonJS "module.exports" for node compatibility. isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target, mod )); var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod); // src/react/index.ts var react_exports = {}; __export(react_exports, { BLUR_EDITOR_EVENT: () => BLUR_EDITOR_EVENT, DOM_HANDLERS: () => DOM_HANDLERS, DefaultElement: () => import_slate_react.DefaultElement, DefaultLeaf: () => DefaultLeaf, DefaultPlaceholder: () => import_slate_react.DefaultPlaceholder, Editable: () => import_slate_react.Editable, EditorHotkeysEffect: () => EditorHotkeysEffect, EditorMethodsEffect: () => EditorMethodsEffect, EditorRefEffect: () => EditorRefEffect, EditorRefPluginEffect: () => EditorRefPluginEffect, EditorStateEffect: () => EditorStateEffect, ElementProvider: () => ElementProvider, EventEditorPlugin: () => EventEditorPlugin, EventEditorStore: () => EventEditorStore, FOCUS_EDITOR_EVENT: () => FOCUS_EDITOR_EVENT, GLOBAL_PLATE_SCOPE: () => GLOBAL_PLATE_SCOPE, PLATE_SCOPE: () => PLATE_SCOPE, ParagraphPlugin: () => ParagraphPlugin, Plate: () => Plate, PlateContent: () => PlateContent, PlateController: () => PlateController, PlateControllerEffect: () => PlateControllerEffect, PlateSlate: () => PlateSlate, PlateStoreProvider: () => PlateStoreProvider, PlateTest: () => PlateTest, ReactPlugin: () => ReactPlugin, SCOPE_ELEMENT: () => SCOPE_ELEMENT, Slate: () => import_slate_react.Slate, SlateReactExtensionPlugin: () => SlateReactExtensionPlugin, atom: () => import_jotai.atom, convertDomEventToSyntheticEvent: () => convertDomEventToSyntheticEvent, createAtomStore: () => import_jotai_x.createAtomStore, createPlateEditor: () => createPlateEditor, createPlateFallbackEditor: () => createPlateFallbackEditor, createPlatePlugin: () => createPlatePlugin, createPlateStore: () => createPlateStore, createTPlatePlugin: () => createTPlatePlugin, elementStore: () => elementStore, getEditorPlugin: () => getEditorPlugin2, getEventPlateId: () => getEventPlateId, getPlateCorePlugins: () => getPlateCorePlugins, getPlugin: () => getPlugin, getRenderNodeProps: () => getRenderNodeProps, isEventHandled: () => isEventHandled, omitPluginContext: () => omitPluginContext, pipeHandler: () => pipeHandler, pipeOnChange: () => pipeOnChange, pipeRenderElement: () => pipeRenderElement, pipeRenderLeaf: () => pipeRenderLeaf, plateControllerStore: () => plateControllerStore, plateStore: () => plateStore, pluginRenderElement: () => pluginRenderElement, pluginRenderLeaf: () => pluginRenderLeaf, toPlatePlugin: () => toPlatePlugin, toTPlatePlugin: () => toTPlatePlugin, useComposing: () => import_slate_react2.useComposing, useEditableProps: () => useEditableProps, useEditorContainerRef: () => useEditorContainerRef, useEditorId: () => useEditorId, useEditorMounted: () => useEditorMounted, useEditorPlugin: () => useEditorPlugin, useEditorPluginOption: () => useEditorPluginOption, useEditorPluginOptions: () => useEditorPluginOptions, useEditorReadOnly: () => useEditorReadOnly, useEditorRef: () => useEditorRef, useEditorScrollRef: () => useEditorScrollRef, useEditorSelection: () => useEditorSelection, useEditorSelector: () => useEditorSelector, useEditorState: () => useEditorState, useEditorValue: () => useEditorValue, useEditorVersion: () => useEditorVersion, useElement: () => useElement, useElementSelector: () => useElementSelector, useElementStore: () => useElementStore, useEventEditorValue: () => useEventEditorValue, useEventPlateId: () => useEventPlateId, useFocusEditorEvents: () => useFocusEditorEvents, useFocused: () => import_slate_react2.useFocused, useIncrementVersion: () => useIncrementVersion, useNodePath: () => useNodePath, usePath: () => usePath, usePlateControllerExists: () => usePlateControllerExists, usePlateControllerLocalStore: () => usePlateControllerLocalStore, usePlateControllerStore: () => usePlateControllerStore, usePlateEditor: () => usePlateEditor, usePlateLocalStore: () => usePlateLocalStore, usePlateSet: () => usePlateSet, usePlateState: () => usePlateState, usePlateStore: () => usePlateStore, usePlateValue: () => usePlateValue, usePluginOption: () => usePluginOption, usePluginOptions: () => usePluginOptions, useReadOnly: () => import_slate_react2.useReadOnly, useRedecorate: () => useRedecorate, useScrollRef: () => useScrollRef, useSelected: () => import_slate_react2.useSelected, useSelectionVersion: () => useSelectionVersion, useSlateProps: () => useSlateProps, useStoreAtomState: () => import_jotai_x.useStoreAtomState, useStoreAtomValue: () => import_jotai_x.useStoreAtomValue, useStoreSelect: () => import_zustand_x3.useStoreSelect, useStoreSetAtom: () => import_jotai_x.useStoreSetAtom, useStoreState: () => import_zustand_x3.useStoreState, useStoreValue: () => import_zustand_x3.useStoreValue, useTracked: () => import_zustand_x3.useTracked, useTrackedStore: () => import_zustand_x3.useTrackedStore, useValueVersion: () => useValueVersion, withHOC: () => withHOC, withPlate: () => withPlate, withPlateReact: () => withPlateReact, withReact: () => import_slate_react3.withReact }); module.exports = __toCommonJS(react_exports); // src/react/slate-react.ts var import_slate_react = require("slate-react"); var import_slate_react2 = require("slate-react"); var import_slate_react3 = require("slate-react"); // src/react/components/DefaultLeaf.tsx var import_react = __toESM(require("react")); var import_clsx2 = require("clsx"); // src/lib/editor/withSlate.ts var import_slate8 = require("@udecode/slate"); var import_nanoid = require("nanoid"); // src/internal/utils/isFunction.ts function isFunction(value) { return typeof value === "function"; } // src/internal/utils/mergePlugins.ts var import_mergeWith = __toESM(require("lodash/mergeWith.js")); function mergePlugins(basePlugin, ...sourcePlugins) { return (0, import_mergeWith.default)( {}, basePlugin, ...sourcePlugins, (objValue, srcValue, key) => { if (Array.isArray(srcValue)) { return srcValue; } if (key === "options") { return { ...objValue, ...srcValue }; } } ); } // src/lib/plugin/createSlatePlugin.ts function createSlatePlugin(config = {}) { let baseConfig; let initialExtension; if (isFunction(config)) { baseConfig = { key: "" }; initialExtension = (editor) => config(editor); } else { baseConfig = config; } const key = baseConfig.key ?? ""; const plugin = mergePlugins( { key, __apiExtensions: [], __configuration: null, __extensions: initialExtension ? [initialExtension] : [], __selectorExtensions: [], api: {}, dependencies: [], editor: {}, handlers: {}, inject: {}, node: { type: key }, options: {}, override: {}, parser: {}, parsers: {}, plugins: [], priority: 100, render: {}, shortcuts: {}, transforms: {} }, config ); plugin.configure = (config2) => { const newPlugin = { ...plugin }; newPlugin.__configuration = (ctx) => isFunction(config2) ? config2(ctx) : config2; return createSlatePlugin(newPlugin); }; plugin.configurePlugin = (p, config2) => { const newPlugin = { ...plugin }; const configureNestedPlugin = (plugins) => { let found = false; const updatedPlugins = plugins.map((nestedPlugin) => { if (nestedPlugin.key === p.key) { found = true; return createSlatePlugin({ ...nestedPlugin, __configuration: (ctx) => isFunction(config2) ? config2(ctx) : config2 }); } if (nestedPlugin.plugins && nestedPlugin.plugins.length > 0) { const result2 = configureNestedPlugin(nestedPlugin.plugins); if (result2.found) { found = true; return { ...nestedPlugin, plugins: result2.plugins }; } } return nestedPlugin; }); return { found, plugins: updatedPlugins }; }; const result = configureNestedPlugin(newPlugin.plugins); newPlugin.plugins = result.plugins; return createSlatePlugin(newPlugin); }; plugin.extendEditorApi = (extension) => { const newPlugin = { ...plugin }; newPlugin.__apiExtensions = [ ...newPlugin.__apiExtensions, { extension, isPluginSpecific: false } ]; return createSlatePlugin(newPlugin); }; plugin.extendSelectors = (extension) => { const newPlugin = { ...plugin }; newPlugin.__selectorExtensions = [ ...newPlugin.__selectorExtensions, extension ]; return createSlatePlugin(newPlugin); }; plugin.extendApi = (extension) => { const newPlugin = { ...plugin }; newPlugin.__apiExtensions = [ ...newPlugin.__apiExtensions, { extension, isPluginSpecific: true } ]; return createSlatePlugin(newPlugin); }; plugin.extendEditorTransforms = (extension) => { const newPlugin = { ...plugin }; newPlugin.__apiExtensions = [ ...newPlugin.__apiExtensions, { extension, isPluginSpecific: false, isTransform: true } ]; return createSlatePlugin(newPlugin); }; plugin.extendTransforms = (extension) => { const newPlugin = { ...plugin }; newPlugin.__apiExtensions = [ ...newPlugin.__apiExtensions, { extension, isPluginSpecific: true, isTransform: true } ]; return createSlatePlugin(newPlugin); }; plugin.overrideEditor = (extension) => { const newPlugin = { ...plugin }; newPlugin.__apiExtensions = [ ...newPlugin.__apiExtensions, { extension, isOverride: true, isPluginSpecific: false, isTransform: true } ]; return createSlatePlugin(newPlugin); }; plugin.extend = (extendConfig) => { let newPlugin = { ...plugin }; if (isFunction(extendConfig)) { newPlugin.__extensions = [ ...newPlugin.__extensions, extendConfig ]; } else { newPlugin = mergePlugins(newPlugin, extendConfig); } return createSlatePlugin(newPlugin); }; plugin.clone = () => mergePlugins(plugin); plugin.extendPlugin = (p, extendConfig) => { const newPlugin = { ...plugin }; const extendNestedPlugin = (plugins) => { let found = false; const updatedPlugins = plugins.map((nestedPlugin) => { if (nestedPlugin.key === p.key) { found = true; return createSlatePlugin({ ...nestedPlugin, __extensions: [ ...nestedPlugin.__extensions, (ctx) => isFunction(extendConfig) ? extendConfig(ctx) : extendConfig ] }); } if (nestedPlugin.plugins && nestedPlugin.plugins.length > 0) { const result2 = extendNestedPlugin(nestedPlugin.plugins); if (result2.found) { found = true; return { ...nestedPlugin, plugins: result2.plugins }; } } return nestedPlugin; }); return { found, plugins: updatedPlugins }; }; const result = extendNestedPlugin(newPlugin.plugins); newPlugin.plugins = result.plugins; if (!result.found) { newPlugin.plugins.push( createSlatePlugin({ key: p.key, __extensions: [ (ctx) => isFunction(extendConfig) ? extendConfig(ctx) : extendConfig ] }) ); } return createSlatePlugin(newPlugin); }; return plugin; } function createTSlatePlugin(config = {}) { return createSlatePlugin(config); } // src/lib/plugin/getEditorPlugin.ts function getEditorPlugin(editor, p) { const plugin = editor.getPlugin(p); return { api: editor.api, editor, plugin, setOption: (keyOrOptions, value) => editor.setOption(plugin, keyOrOptions, value), setOptions: (options) => editor.setOptions(plugin, options), tf: editor.transforms, type: plugin.node.type, getOption: (key, ...args) => editor.getOption(plugin, key, ...args), getOptions: () => editor.getOptions(plugin) }; } // src/internal/plugin/resolvePlugin.ts var import_merge = __toESM(require("lodash/merge.js")); var resolvePlugin = (editor, _plugin) => { let plugin = mergePlugins({}, _plugin); plugin.__resolved = true; if (plugin.__configuration) { const configResult = plugin.__configuration( getEditorPlugin(editor, plugin) ); plugin = mergePlugins(plugin, configResult); delete plugin.__configuration; } if (plugin.__extensions && plugin.__extensions.length > 0) { plugin.__extensions.forEach((extension) => { plugin = mergePlugins( plugin, extension(getEditorPlugin(editor, plugin)) ); }); plugin.__extensions = []; } const targetPluginToInject = plugin.inject?.targetPluginToInject; const targetPlugins = plugin.inject?.targetPlugins; if (targetPluginToInject && targetPlugins && targetPlugins.length > 0) { plugin.inject = plugin.inject || {}; plugin.inject.plugins = (0, import_merge.default)( {}, plugin.inject.plugins, Object.fromEntries( targetPlugins.map((targetPlugin) => { const injectedPlugin = targetPluginToInject({ ...getEditorPlugin(editor, plugin), targetPlugin }); return [targetPlugin, injectedPlugin]; }) ) ); } if (plugin.node?.component) { plugin.render.node = plugin.node.component; } if (plugin.render?.node) { plugin.node.component = plugin.render.node; } validatePlugin(editor, plugin); return plugin; }; var validatePlugin = (editor, plugin) => { if (!plugin.__extensions) { editor.api.debug.error( `Invalid plugin '${plugin.key}', you should use createSlatePlugin.`, "USE_CREATE_PLUGIN" ); } if (plugin.node.isElement && plugin.node.isLeaf) { editor.api.debug.error( `Plugin ${plugin.key} cannot be both an element and a leaf.`, "PLUGIN_NODE_TYPE" ); } }; // src/lib/plugin/getSlatePlugin.ts function getSlatePlugin(editor, p) { let plugin = p; const editorPlugin = editor.plugins[p.key]; if (!editorPlugin) { if (!plugin.node) { plugin = createSlatePlugin(plugin); } return plugin.__resolved ? plugin : resolvePlugin(editor, plugin); } return editorPlugin; } function getPluginType(editor, plugin) { const p = editor.getPlugin(plugin); return p.node.type ?? p.key ?? ""; } // src/internal/plugin/pipeNormalizeInitialValue.ts var pipeNormalizeInitialValue = (editor) => { editor.pluginList.forEach((p) => { p.normalizeInitialValue?.({ ...getEditorPlugin(editor, p), value: editor.children }); }); }; // src/internal/plugin/resolvePlugins.ts var import_slate = require("@udecode/slate"); var import_utils = require("@udecode/utils"); var import_merge2 = __toESM(require("lodash/merge.js")); var import_zustand_x = require("zustand-x"); var resolvePlugins = (editor, plugins = []) => { editor.pluginList = []; editor.plugins = {}; editor.shortcuts = {}; const resolvedPlugins = resolveAndSortPlugins(editor, plugins); applyPluginsToEditor(editor, resolvedPlugins); resolvePluginOverrides(editor); resolvePluginStores(editor); editor.pluginList.forEach((plugin) => { if (plugin.extendEditor) { editor = plugin.extendEditor(getEditorPlugin(editor, plugin)); (0, import_slate.syncLegacyMethods)(editor); } resolvePluginMethods(editor, plugin); }); resolvePluginShortcuts(editor); return editor; }; var resolvePluginStores = (editor) => { editor.pluginList.forEach((plugin) => { let store = (0, import_zustand_x.createZustandStore)(plugin.options, { mutative: true, name: plugin.key }); if (plugin.__selectorExtensions && plugin.__selectorExtensions.length > 0) { plugin.__selectorExtensions.forEach((extension) => { const extendedOptions = extension(getEditorPlugin(editor, plugin)); store = store.extendSelectors(() => extendedOptions); }); } plugin.optionsStore = store; }); }; var resolvePluginMethods = (editor, plugin) => { Object.entries(plugin.api).forEach(([apiKey, apiFunction]) => { editor.api[apiKey] = apiFunction; }); if (plugin.__apiExtensions && plugin.__apiExtensions.length > 0) { plugin.__apiExtensions.forEach( ({ extension, isOverride, isPluginSpecific, isTransform }) => { const newExtensions = extension(getEditorPlugin(editor, plugin)); if (isOverride) { if (newExtensions.api) { (0, import_merge2.default)(editor.api, newExtensions.api); (0, import_merge2.default)(plugin.api, newExtensions.api); (0, import_slate.assignLegacyApi)(editor, editor.api); } if (newExtensions.transforms) { (0, import_merge2.default)(editor.transforms, newExtensions.transforms); (0, import_merge2.default)(plugin.transforms, newExtensions.transforms); (0, import_slate.assignLegacyTransforms)(editor, newExtensions.transforms); } } else if (isTransform) { if (isPluginSpecific) { if (!editor.transforms[plugin.key]) { editor.transforms[plugin.key] = {}; } if (!plugin.transforms[plugin.key]) { plugin.transforms[plugin.key] = {}; } (0, import_merge2.default)(editor.transforms[plugin.key], newExtensions); (0, import_merge2.default)(plugin.transforms[plugin.key], newExtensions); } else { (0, import_merge2.default)(editor.transforms, newExtensions); (0, import_merge2.default)(plugin.transforms, newExtensions); (0, import_slate.assignLegacyTransforms)(editor, newExtensions); } } else { if (isPluginSpecific) { if (!editor.api[plugin.key]) { editor.api[plugin.key] = {}; } if (!plugin.api[plugin.key]) { plugin.api[plugin.key] = {}; } (0, import_merge2.default)(editor.api[plugin.key], newExtensions); (0, import_merge2.default)(plugin.api[plugin.key], newExtensions); } else { (0, import_merge2.default)(editor.api, newExtensions); (0, import_merge2.default)(plugin.api, newExtensions); (0, import_slate.assignLegacyApi)(editor, editor.api); } } } ); delete plugin.__apiExtensions; } }; var resolvePluginShortcuts = (editor) => { const shortcutsByPriority = []; editor.pluginList.forEach((plugin) => { Object.entries(plugin.shortcuts).forEach(([key, hotkey]) => { if (hotkey === null) { const index = shortcutsByPriority.findIndex((item) => item.key === key); if (index !== -1) { shortcutsByPriority.splice(index, 1); } } else { const priority = hotkey.priority ?? plugin.priority; const existingIndex = shortcutsByPriority.findIndex( (item) => item.key === key ); if (existingIndex === -1 || priority >= shortcutsByPriority[existingIndex].priority) { if (existingIndex !== -1) { shortcutsByPriority.splice(existingIndex, 1); } shortcutsByPriority.push({ key, hotkey, priority }); } } }); }); shortcutsByPriority.sort((a, b) => b.hotkey.priority - a.hotkey.priority); editor.shortcuts = Object.fromEntries( shortcutsByPriority.map(({ key, hotkey }) => { const { priority, ...hotkeyWithoutPriority } = hotkey; return [key, hotkeyWithoutPriority]; }) ); }; var flattenAndResolvePlugins = (editor, plugins) => { const pluginMap = /* @__PURE__ */ new Map(); const processPlugin = (plugin) => { const resolvedPlugin = resolvePlugin(editor, plugin); const existingPlugin = pluginMap.get(resolvedPlugin.key); if (existingPlugin) { pluginMap.set( resolvedPlugin.key, mergePlugins(existingPlugin, resolvedPlugin) ); } else { pluginMap.set(resolvedPlugin.key, resolvedPlugin); } if (resolvedPlugin.plugins && resolvedPlugin.plugins.length > 0) { resolvedPlugin.plugins.forEach(processPlugin); } }; plugins.forEach(processPlugin); return pluginMap; }; var resolveAndSortPlugins = (editor, plugins) => { const pluginMap = flattenAndResolvePlugins(editor, plugins); const enabledPlugins = Array.from(pluginMap.values()).filter( (plugin) => plugin.enabled !== false ); enabledPlugins.sort((a, b) => b.priority - a.priority); const orderedPlugins = []; const visited = /* @__PURE__ */ new Set(); const visit = (plugin) => { if (visited.has(plugin.key)) return; visited.add(plugin.key); plugin.dependencies?.forEach((depKey) => { const depPlugin = pluginMap.get(depKey); if (depPlugin) { visit(depPlugin); } else { editor.api.debug.warn( `Plugin "${plugin.key}" depends on missing plugin "${depKey}"`, "PLUGIN_DEPENDENCY_MISSING" ); } }); orderedPlugins.push(plugin); }; enabledPlugins.forEach(visit); return orderedPlugins; }; var applyPluginsToEditor = (editor, plugins) => { editor.pluginList = plugins; editor.plugins = Object.fromEntries( plugins.map((plugin) => [plugin.key, plugin]) ); }; var resolvePluginOverrides = (editor) => { const applyOverrides = (plugins) => { let overriddenPlugins = [...plugins]; const enabledOverrides = {}; const componentOverrides = {}; const pluginOverrides = {}; for (const plugin of plugins) { if (plugin.override.enabled) { Object.assign(enabledOverrides, plugin.override.enabled); } if (plugin.override.components) { Object.entries(plugin.override.components).forEach( ([key, component]) => { if (!componentOverrides[key] || plugin.priority > componentOverrides[key].priority) { componentOverrides[key] = { component, priority: plugin.priority }; } } ); } if (plugin.override.plugins) { Object.entries(plugin.override.plugins).forEach(([key, value]) => { pluginOverrides[key] = mergePlugins(pluginOverrides[key], value); if (value.enabled !== void 0) { enabledOverrides[key] = value.enabled; } }); } } overriddenPlugins = overriddenPlugins.map((p) => { let updatedPlugin = { ...p }; if (pluginOverrides[p.key]) { updatedPlugin = mergePlugins(updatedPlugin, pluginOverrides[p.key]); } if (componentOverrides[p.key] && (!p.render.node && !p.node.component || componentOverrides[p.key].priority > p.priority)) { updatedPlugin.render.node = componentOverrides[p.key].component; updatedPlugin.node.component = componentOverrides[p.key].component; } const enabled = enabledOverrides[p.key] ?? updatedPlugin.enabled; if ((0, import_utils.isDefined)(enabled)) { updatedPlugin.enabled = enabled; } return updatedPlugin; }); return overriddenPlugins.filter((p) => p.enabled !== false).map((plugin) => ({ ...plugin, plugins: applyOverrides(plugin.plugins || []) })); }; editor.pluginList = applyOverrides(editor.pluginList); editor.plugins = Object.fromEntries( editor.pluginList.map((plugin) => [plugin.key, plugin]) ); }; // src/lib/plugins/AstPlugin.ts var AstPlugin = createSlatePlugin({ key: "ast", parser: { format: "application/x-slate-fragment", deserialize: ({ data }) => { const decoded = decodeURIComponent(window.atob(data)); let parsed; try { parsed = JSON.parse(decoded); } catch { } return parsed; } } }); // src/lib/plugins/DOMPlugin.ts var DOMPlugin = createSlatePlugin({ key: "dom" }); // src/lib/plugins/HistoryPlugin.ts var import_slate2 = require("@udecode/slate"); var withPlateHistory = ({ editor }) => (0, import_slate2.withHistory)(editor); var HistoryPlugin = createSlatePlugin({ key: "history", extendEditor: withPlateHistory }); // src/lib/plugins/InlineVoidPlugin.ts var withInlineVoid = ({ api: { isInline, isSelectable, isVoid, markableVoid }, editor }) => { const voidTypes = []; const inlineTypes = []; const markableVoidTypes = []; const nonSelectableTypes = []; editor.pluginList.forEach((plugin) => { if (plugin.node.isInline) { inlineTypes.push(plugin.node.type); } if (plugin.node.isVoid) { voidTypes.push(plugin.node.type); } if (plugin.node.isMarkableVoid) { markableVoidTypes.push(plugin.node.type); } if (plugin.node.isSelectable === false) { nonSelectableTypes.push(plugin.node.type); } }); return { api: { isInline(element) { return inlineTypes.includes(element.type) ? true : isInline(element); }, isSelectable(element) { return nonSelectableTypes.includes(element.type) ? false : isSelectable(element); }, isVoid(element) { return voidTypes.includes(element.type) ? true : isVoid(element); }, markableVoid(element) { return markableVoidTypes.includes(element.type) ? true : markableVoid(element); } } }; }; var InlineVoidPlugin = createSlatePlugin({ key: "inlineVoid" }).overrideEditor(withInlineVoid); // src/internal/plugin/pipeInsertFragment.ts var pipeInsertFragment = (editor, injectedPlugins, { fragment, ...options }) => { editor.tf.withoutNormalizing(() => { injectedPlugins.some((p) => { return p.parser?.preInsert?.({ ...getEditorPlugin(editor, p), fragment, ...options }) === true; }); editor.tf.insertFragment(fragment); }); }; // src/internal/plugin/pipeTransformData.ts var pipeTransformData = (editor, plugins, { data, dataTransfer }) => { plugins.forEach((p) => { const transformData = p.parser?.transformData; if (!transformData) return; data = transformData({ ...getEditorPlugin(editor, p), data, dataTransfer }); }); return data; }; // src/internal/plugin/pipeTransformFragment.ts var pipeTransformFragment = (editor, plugins, { fragment, ...options }) => { plugins.forEach((p) => { const transformFragment = p.parser?.transformFragment; if (!transformFragment) return; fragment = transformFragment({ fragment, ...options, ...getEditorPlugin(editor, p) }); }); return fragment; }; // src/lib/utils/applyDeepToNodes.ts var import_slate3 = require("@udecode/slate"); var applyDeepToNodes = ({ apply, node, path = [], query, source }) => { const entry = [node, path]; if ((0, import_slate3.queryNode)(entry, query)) { if (source instanceof Function) { apply(node, source()); } else { apply(node, source); } } if (!import_slate3.NodeApi.isAncestor(node)) return; node.children.forEach((child, index) => { applyDeepToNodes({ apply, node: child, path: path.concat([index]), query, source }); }); }; // src/lib/utils/getInjectMatch.ts var import_slate4 = require("@udecode/slate"); // src/lib/utils/getKeysByTypes.ts var getKeysByTypes = (editor, types) => { return Object.values(editor.plugins).filter((plugin) => types.includes(plugin.node.type)).map((plugin) => plugin.key); }; var getKeyByType = (editor, type) => { const plugin = Object.values(editor.plugins).find( (plugin2) => plugin2.node.type === type ); return plugin?.key ?? type; }; // src/lib/utils/getInjectMatch.ts var getInjectMatch = (editor, plugin) => { return (node, path) => { const { inject: { excludeBelowPlugins, excludePlugins, isBlock: _isBlock, isElement: _isElement, isLeaf, maxLevel, targetPlugins } } = plugin; const element = import_slate4.ElementApi.isElement(node) ? node : void 0; if (_isElement && !element) return false; if (_isBlock && (!element || !editor.api.isBlock(element))) return false; if (isLeaf && element) return false; if (element?.type) { if (excludePlugins?.includes(getKeyByType(editor, element.type))) { return false; } if (targetPlugins && !targetPlugins.includes(getKeyByType(editor, element.type))) { return false; } } if (excludeBelowPlugins || maxLevel) { if (maxLevel && path.length > maxLevel) { return false; } if (excludeBelowPlugins) { const excludeTypes = getKeysByTypes(editor, excludeBelowPlugins); const isBelow = editor.api.above({ at: path, match: (n) => import_slate4.ElementApi.isElement(n) && excludeTypes.includes(n.type) }); if (isBelow) return false; } } return true; }; }; // src/lib/utils/getInjectedPlugins.ts var getInjectedPlugins = (editor, plugin) => { const injectedPlugins = []; [...editor.pluginList].reverse().forEach((p) => { const injectedPlugin = p.inject.plugins?.[plugin.key]; if (injectedPlugin) injectedPlugins.push(injectedPlugin); }); return [plugin, ...injectedPlugins]; }; // src/lib/utils/getPluginNodeProps.ts var import_pick = __toESM(require("lodash/pick.js")); // src/lib/static/utils/getNodeDataAttributes.ts var import_slate5 = require("@udecode/slate"); var import_kebabCase = __toESM(require("lodash/kebabCase.js")); var getNodeDataAttributeKeys = (node) => { return Object.keys(node).filter( (key) => typeof node[key] !== "object" && (!import_slate5.TextApi.isText(node) || key !== "text") ).map((key) => keyToDataAttribute(key)); }; var keyToDataAttribute = (key) => { return `data-slate-${(0, import_kebabCase.default)(key)}`; }; // src/internal/plugin/pipeInjectNodeProps.tsx var import_clsx = __toESM(require("clsx")); // src/internal/plugin/pluginInjectNodeProps.ts var import_utils2 = require("@udecode/utils"); var pluginInjectNodeProps = (editor, plugin, nodeProps, getElementPath) => { const { key, inject: { nodeProps: injectNodeProps } } = plugin; const { element, text } = nodeProps; const node = element ?? text; if (!node) return; if (!injectNodeProps) return; const { classNames, defaultNodeValue, nodeKey = key, query, styleKey = nodeKey, transformClassName, transformNodeValue, transformProps, transformStyle, validNodeValues } = injectNodeProps; const injectMatch = getInjectMatch(editor, plugin); if (!injectMatch(node, getElementPath(node))) return; const queryResult = query?.({ ...injectNodeProps, ...getEditorPlugin(editor, plugin), nodeProps }); if (query && !queryResult) { return; } const nodeValue = node[nodeKey]; if (!transformProps && (!(0, import_utils2.isDefined)(nodeValue) || validNodeValues && !validNodeValues.includes(nodeValue) || nodeValue === defaultNodeValue)) { return; } const transformOptions = { ...nodeProps, ...getEditorPlugin(editor, plugin), nodeValue }; const value = transformNodeValue?.(transformOptions) ?? nodeValue; transformOptions.value = value; let newProps = {}; if (element && nodeKey) { newProps.className = `slate-${nodeKey}-${nodeValue}`; } if (classNames?.[nodeValue] || transformClassName) { newProps.className = transformClassName?.(transformOptions) ?? classNames?.[value]; } if (styleKey) { newProps.style = transformStyle?.(transformOptions) ?? { [styleKey]: value }; } if (transformProps) { newProps = transformProps({ ...transformOptions, props: newProps }) ?? newProps; } return newProps; }; // src/internal/plugin/pipeInjectNodeProps.tsx var pipeInjectNodeProps = (editor, nodeProps, getElementPath) => { editor.pluginList.forEach((plugin) => { if (plugin.inject.nodeProps) { const newProps = pluginInjectNodeProps( editor, plugin, nodeProps, getElementPath ); if (!newProps) return; nodeProps = { ...nodeProps, ...newProps, className: (0, import_clsx.default)(nodeProps.className, newProps.className), style: { ...nodeProps.style, ...newProps.style } }; } }); return nodeProps; }; // src/lib/static/utils/pipeDecorate.ts var pipeDecorate = (editor, decorateProp) => { const relevantPlugins = editor.pluginList.filter((plugin) => plugin.decorate); if (relevantPlugins.length === 0 && !decorateProp) return; return (entry) => { let ranges = []; const addRanges = (newRanges) => { if (newRanges?.length) ranges = [...ranges, ...newRanges]; }; relevantPlugins.forEach((plugin) => { addRanges( plugin.decorate({ ...getEditorPlugin(editor, plugin), entry }) ); }); if (decorateProp) { addRanges( decorateProp({ editor, entry }) ); } return ranges; }; }; // src/lib/static/deserialize/checkUtils.ts var isSlateVoid = (element) => { return element.dataset.slateVoid === "true"; }; var isSlateElement = (element) => { return element.dataset.slateNode === "element"; }; var isSlateText = (element) => { return element.dataset.slateNode === "text"; }; var isSlateString = (element) => { return element.dataset.slateString === "true"; }; var isSlateLeaf = (element) => { return element.dataset.slateLeaf === "true"; }; var isSlateNode = (element) => { return isSlateLeaf(element) || isSlateElement(element) || isSlateVoid(element) || isSlateString(element) || isSlateText(element); }; var isSlatePluginNode = (element, pluginKey) => { return element.classList.contains(`slate-${pluginKey}`); }; // src/lib/utils/getPluginNodeProps.ts var getPluginNodeProps = ({ attributes, node, plugin, props }) => { let newProps = {}; if (plugin?.node.props) { newProps = (typeof plugin.node.props === "function" ? plugin.node.props(props) : plugin.node.props) ?? {}; } if (!newProps.nodeProps && attributes && plugin) { newProps.nodeProps = (0, import_pick.default)(attributes, [ ...plugin.node.dangerouslyAllowAttributes ?? [], ...node ? getNodeDataAttributeKeys(node) : [] ]); } else if (newProps.nodeProps && attributes && plugin) { newProps.nodeProps = { ...newProps.nodeProps, ...(0, import_pick.default)(attributes, [...node ? getNodeDataAttributeKeys(node) : []]) }; } props = { ...props, ...newProps }; if (props.nodeProps) { Object.keys(props.nodeProps).forEach((key) => { if (props.nodeProps?.[key] === void 0) { delete props.nodeProps?.[key]; } }); } return props; }; // src/lib/utils/getSlateClass.ts var getSlateClass = (type) => type ? `slate-${type}` : ""; // src/lib/utils/mergeDeepToNodes.ts var import_merge3 = __toESM(require("lodash/merge.js")); var mergeDeepToNodes = (options) => { applyDeepToNodes({ ...options, apply: import_merge3.default }); }; // src/lib/utils/normalizeDescendantsToDocumentFragment.ts var import_slate7 = require("@udecode/slate"); // src/lib/plugins/debug/DebugPlugin.ts var PlateError = class extends Error { constructor(message, type = "DEFAULT") { super(`[${type}] ${message}`); this.type = type; this.name = "PlateError"; } }; var DebugPlugin = createTSlatePlugin({ key: "debug", options: { isProduction: process.env.NODE_ENV === "production", logger: { error: (message, type, details) => console.error(`${type ? `[${type}] ` : ""}${message}`, details), info: (message, type, details) => console.info(`${type ? `[${type}] ` : ""}${message}`, details), log: (message, type, details) => console.log(`${type ? `[${type}] ` : ""}${message}`, details), warn: (message, type, details) => console.warn(`${type ? `[${type}] ` : ""}${message}`, details) }, logLevel: process.env.NODE_ENV === "production" ? "error" : "log", throwErrors: true } }).extendEditorApi(({ getOptions }) => { const logLevels = ["error", "warn", "info", "log"]; const log = (level, message, type, details) => { if (process.env.NODE_ENV === "production") return; const options = getOptions(); if (options.isProduction && level === "log") return; if (logLevels.indexOf(level) <= logLevels.indexOf(options.logLevel)) { if (level === "error" && options.throwErrors) { throw new PlateError(message, type); } else { options.logger[level]?.(message, type, details); } } }; return { debug: { error: (message, type, details) => log("error", message, type, details), info: (message, type, details) => log("info", message, type, details), log: (message, type, details) => log("log", message, type, details), warn: (message, type, details) => log("warn", message, type, details) } }; }); // src/lib/plugins/html/HtmlPlugin.ts var import_utils5 = require("@udecode/utils"); // src/lib/plugins/html/utils/isHtmlElement.ts var isHtmlElement = (node) => node.nodeType === Node.ELEMENT_NODE; // src/lib/plugins/html/utils/isHtmlText.ts var isHtmlText = (node) => node.nodeType === Node.TEXT_NODE; // src/lib/plugins/html/utils/inlineTagNames.ts var inlineTagNames = /* @__PURE__ */ new Set([ "A", "ABBR", "ACRONYM", "B", "BDI", "BDO", "BIG", "BR", "BUTTON", "CANVAS", "CITE", "CODE", "CONTENT", "DATA", "DEL", "DFN", "EM", "EMBED", "FONT", "I", "IFRAME", "IMG", "IMG", "INPUT", "INS", "KBD", "LABEL", "MAP", "MARK", "MARQUEE", "math", "MENUITEM", "METER", "NOBR", "OBJECT", "OUTPUT", "PICTURE", "PORTAL", "PROGRESS", "Q", "S", "SAMP", "SELECT", "SHADOW", "SMALL", "SOURCE", "SPAN", "STRIKE", "STRONG", "SUB", "SUP", "svg", "TEXTAREA", "TIME", "TRACK", "TT", "U", "VAR", "VIDEO", "WBR" ]); // src/lib/plugins/html/utils/isHtmlInlineElement.ts var isHtmlInlineElement = (node) => { if (!isHtmlElement(node)) return false; const element = node; const tagNameIsInline = inlineTagNames.has(element.tagName); const displayProperty = element.style.display.split(" ")[0]; if (displayProperty === "") { return tagNameIsInline; } if (displayProperty.startsWith("inline")) { return true; } if (displayProperty === "inherit" && element.parentElement) { return isHtmlInlineElement(element.parentElement); } if (["contents", "initial", "none", "revert", "revert-layer", "unset"].includes( displayProperty )) { return tagNameIsInline; } return false; }; // src/lib/plugins/html/utils/isHtmlBlockElement.ts var isHtmlBlockElement = (node) => { if (!isHtmlElement(node)) return false; const element = node; return !isHtmlInlineElement(element); }; // src/lib/plugins/html/utils/collapse-white-space/collapseString.ts var collapseString = (text, { shouldCollapseWhiteSpace = true, trimEnd = "collapse", trimStart = "collapse", whiteSpaceIncludesNewlines = true } = {}) => { if (trimStart === "all") { text = text.replace(/^\s+/, ""); } if (trimEnd === "single-newline") { text = text.replace(/\n$/, ""); } if (shouldCollapseWhiteSpace) { if (whiteSpaceIncludesNewlines) { text = text.replaceAll(/\s+/g, " "); } else { text = text.replaceAll(/[^\S\n\r]+/g, " "); text = text.replaceAll(/^[^\S\n\r]+/gm, ""); text = text.replaceAll(/[^\S\n\r]+$/gm, ""); } } return text; }; // src/lib/plugins/html/utils/collapse-white-space/isLastNonEmptyTextOfInlineFormattingContext.ts var isLastNonEmptyTextOfInlineFormattingContext = (initialText) => { let currentNode = initialText; while (true) { if (currentNode.nextSibling) { currentNode = currentNode.nextSibling; } else { currentNode = currentNode.parentElement; if (currentNode && isHtmlBlockElement(currentNode)) { return true; } currentNode = currentNode?.nextSibling || null; } if (!currentNode) { return true; } if (isHtmlBlockElement(currentNode)) { return true; } if ((currentNode.textContent || "").length > 0) { return false; } } }; // src/lib/plugins/html/utils/collapse-white-space/stateTransforms.ts var upsertInlineFormattingContext = (state) => { if (state.inlineFormattingContext) { state.inlineFormattingContext.atStart = false; } else { state.inlineFormattingContext = { atStart: true, lastHasTrailingWhiteSpace: false }; } }; var endInlineFormattingContext = (state) => { state.inlineFormattingContext = null; }; // src/lib/plugins/html/utils/collapse-white-space/collapseWhiteSpaceText.ts var collapseWhiteSpaceText = (text, state) => { const textContent = text.textContent || ""; const isWhiteSpaceOnly = textContent.trim() === ""; if (state.inlineFormattingContext || !isWhiteSpaceOnly) { upsertInlineFormattingContext(state); } const { whiteSpaceRule } = state; const trimStart = (() => { if (whiteSpaceRule !== "normal") return "collapse"; if (!state.inlineFormattingContext || state.inlineFormattingContext.atStart || state.inlineFormattingContext.lastHasTrailingWhiteSpace) return "all"; return "collapse"; })(); const trimEnd = (() => { if (whiteSpaceRule === "normal") return "collapse"; if (isLastNonEmptyTextOfInlineFormattingContext(text)) return "single-newline"; return "collapse"; })(); const shouldCollapseWhiteSpace = { normal: true, pre: false, "pre-line": true }[whiteSpaceRule]; const whiteSpaceIncludesNewlines = whiteSpaceRule !== "pre-line"; const collapsedTextContent = collapseString(textContent || "", { shouldCollapseWhiteSpace, trimEnd, trimStart, whiteSpaceIncludesNewlines }); if (state.inlineFormattingContext && shouldCollapseWhiteSpace) { state.inlineFormattingContext.lastHasTrailingWhiteSpace = collapsedTextContent.endsWith(" "); } text.textContent = collapsedTextContent; }; // src/lib/plugins/html/utils/collapse-white-space/collapseWhiteSpaceNode.ts var collapseWhiteSpaceNode = (node, state) => { if (isHtmlElement(node)) { collapseWhiteSpaceElement(node, state); return; } if (isHtmlText(node)) { collapseWhiteSpaceText(node, state); return; } collapseWhiteSpaceChildren(node, state); }; // src/lib/plugins/html/utils/collapse-white-space/collapseWhiteSpaceChildren.ts var collapseWhiteSpaceChildren = (node, state) => { const childNodes = Array.from(node.childNodes); for (const childNode of childNodes) { collapseWhiteSpaceNode(childNode, state); } }; // src/lib/plugins/html/utils/collapse-white-space/inferWhiteSpaceRule.ts var inferWhiteSpaceRule = (element) => { const whiteSpaceProperty = element.style.whiteSpace; switch (whiteSpaceProperty) { case "break-spaces": case "pre": case "pre-wrap": { return "pre"; } case "normal": case "nowrap": { return "normal"; } case "pre-line": { return "pre-line"; } } if (element.tagName === "PRE") { return "pre"; } if (whiteSpaceProperty === "initial") { return "normal"; } return null; }; // src/lib/plugins/html/utils/collapse-white-space/collapseWhiteSpaceElement.ts var collapseWhiteSpaceElement = (element, state) => { const isInlineElement = isHtmlInlineElement(element); const previousWhiteSpaceRule = state.whiteSpaceRule; const inferredWhiteSpaceRule = inferWhiteSpaceRule(element); if (inferredWhiteSpaceRule) { state.whiteSpaceRule = inferredWhiteSpaceRule; } if (!isInlineElement) { endInlineFormattingContext(state); } collapseWhiteSpaceChildren(element, state); if (!isInlineElement) { endInlineFormattingContext(state); } state.whiteSpaceRule = previousWhiteSpaceRule; }; // src/lib/plugins/html/utils/collapse-white-space/collapseWhiteSpace.ts var collapseWhiteSpace = (element) => { const clonedElement = element.cloneNode(true); const state = { inlineFormattingContext: null, whiteSpaceRule: "normal" }; collapseWhiteSpaceElement(clonedElement, state); return clonedElement; }; // src/lib/plugins/html/utils/htmlBodyToFragment.ts var import_slate_hyperscript = require("slate-hyperscript"); // src/lib/plugins/html/utils/deserializeHtmlNodeChildren.ts var deserializeHtmlNodeChildren = (editor, node, isSlateParent = false) => { return Array.from(node.childNodes).flatMap((child) => { if (child.nodeType === 1 && !isSlateNode(child) && isSlateParent) { return deserializeHtmlNodeChildren( editor, child, isSlateParent ); } return deserializeHtmlNode(editor)(child); }); }; // src/lib/plugins/html/utils/htmlBodyToFragment.ts var htmlBodyToFragment = (editor, element) => { if (element.nodeName === "BODY") { return (0, import_slate_hyperscript.jsx)( "fragment", {}, deserializeHtmlNodeChildren(editor, element) ); } }; // src/lib/plugins/html/utils/htmlBrToNewLine.ts var htmlBrToNewLine = (node) => { if (node.nodeName === "BR") { return "\n"; } }; // src/lib/plugins/html/utils/htmlElementToElement.ts var import_slate_hyperscript2 = require("slate-hyperscript"); // src/lib/plugins/html/utils/pluginDeserializeHtml.ts var import_utils3 = require("@udecode/utils"); var import_castArray = __toESM(require("lodash/castArray.js")); // src/lib/plugins/html/utils/getDataNodeProps.ts var getDefaultNodeProps = ({ element, type }) => { if (!isSlatePluginNode(element, type) && !isSlateLeaf(element)) return; const dataAttributes = {}; Object.entries(element.dataset).forEach(([key, value]) => { if (key.startsWith("slate") && value && // Ignore slate default attributes !["slateInline", "slateLeaf", "slateNode", "slateVoid"].includes(key)) { const attributeKey = key.slice(5).charAt(0).toLowerCase() + key.slice(6); if (value === void 0) return; let parsedValue = value; if (value === "true") parsedValue = true; else if (value === "false") parsedValue = false; else if (!Number.isNaN(Number(value))) parsedValue = Number(value); dataAttributes[attributeKey] = parsedValue; } }); if (Object.keys(dataAttributes).length > 0) { return dataAttributes; } }; var getDataNodeProps = ({ editor, element, plugin }) => { const toNodeProps = plugin.parsers.html?.deserializer?.toNodeProps; const disableDefaultNodeProps = plugin.parsers.html?.deserializer?.disableDefaultNodeProps ?? false; const defaultNodeProps = disableDefaultNodeProps ? {} : getDefaultNodeProps({ ...getEditorPlugin(editor, plugin), element }); if (!toNodeProps) return defaultNodeProps; const customNodeProps = toNodeProps({ ...getEditorPlugin(editor, plugin), element }) ?? {}; return { ...defaultNodeProps, ...customNodeProps }; }; // src/lib/plugins/html/utils/pluginDeserializeHtml.ts var getDeserializedWithStaticRules = (plugin) => { let deserializer = plugin.parsers?.html?.deserializer; const rules = deserializer?.rules ?? []; const hasSlateRule = rules.some( (rule) => rule.validClassName?.includes(`slate-${plugin.key}`) ); const staticRules = hasSlateRule ? rules : [ { validClassName: `slate-${plugin.key}`, validNodeName: "*" }, ...rules ]; if (!deserializer) deserializer = { rules: staticRules }; deserializer.rules = staticRules; return deserializer; }; var pluginDeserializeHtml = (editor, plugin, { deserializeLeaf, element: el }) => { const { node: { isElement: isElementRoot, isLeaf: isLeafRoot } } = plugin; const deserializer = getDeserializedWithStaticRules(plugin); if (!deserializer) return; const { attributeNames, isElement: isElementRule, isLeaf: isLeafRule, query, rules } = deserializer; let { parse } = deserializer; const isElement = isElementRule || isElementRoot; const isLeaf = isLeafRule || isLeafRoot; if (!deserializeLeaf && !isElement) { return; } if (deserializeLeaf && !isLeaf) { return; } if (rules) { const isValid = rules.some( ({ validAttribute, validClassName, validNodeName = "*", validStyle }) => { if (validNodeName) { const validNodeNames = (0, import_castArray.default)(validNodeName); if (validNodeNames.length > 0 && !validNodeNames.includes(el.nodeN