Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@
"dependencies": {
"@types/react": "^18.3.0",
"@types/react-dom": "^18.3.0",
"@udecode/plate": "^42.1.2",
"react": "^18.3.0",
"react-dom": "^18.3.0"
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ import { PlaceholdersManager } from '../PlaceholdersManager';
import { InputPlaceholderElement } from './InputPlaceholderElement';

const extensions = [PlaceholdersExtension()];
const editor = createEditor(createPlateEditor(), () => extensions);
const editor = createEditor({ editor: createPlateEditor(), getExtensions: () => extensions });

const placeholder: PlaceholderNode = {
type: PlaceholderNode.Type.EMBED,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ import { PlaceholderNode } from '../PlaceholderNode';
import { PlaceholderElement } from './PlaceholderElement';

const extensions = [PlaceholdersExtension()];
const editor = createEditor(createPlateEditor(), () => extensions);
const editor = createEditor({ editor: createPlateEditor(), getExtensions: () => extensions });

const placeholder: PlaceholderNode = {
type: PlaceholderNode.Type.ATTACHMENT,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import { PlaceholderNode } from '../PlaceholderNode';
import { AttachmentPlaceholderElement } from './AttachmentPlaceholderElement';

const extensions = [PlaceholdersExtension()];
const editor = createEditor(createPlateEditor(), () => extensions);
const editor = createEditor({ editor: createPlateEditor(), getExtensions: () => extensions });

const placeholder: PlaceholderNode<PlaceholderNode.Type.ATTACHMENT> = {
type: PlaceholderNode.Type.ATTACHMENT,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import { PlaceholderNode } from '../PlaceholderNode';
import { ContactPlaceholderElement } from './ContactPlaceholderElement';

const extensions = [PlaceholdersExtension()];
const editor = createEditor(createPlateEditor(), () => extensions);
const editor = createEditor({ editor: createPlateEditor(), getExtensions: () => extensions });

const placeholder: PlaceholderNode<PlaceholderNode.Type.CONTACT> = {
type: PlaceholderNode.Type.CONTACT,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import { PlaceholderNode } from '../PlaceholderNode';
import { EmbedPlaceholderElement } from './EmbedPlaceholderElement';

const extensions = [PlaceholdersExtension()];
const editor = createEditor(createPlateEditor(), () => extensions);
const editor = createEditor({ editor: createPlateEditor(), getExtensions: () => extensions });

const placeholder: PlaceholderNode<PlaceholderNode.Type.EMBED> = {
type: PlaceholderNode.Type.EMBED,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import { PlaceholderNode } from '../PlaceholderNode';
import { GalleryPlaceholderElement } from './GalleryPlaceholderElement';

const extensions = [PlaceholdersExtension()];
const editor = createEditor(createPlateEditor(), () => extensions);
const editor = createEditor({ editor: createPlateEditor(), getExtensions: () => extensions });

const placeholder: PlaceholderNode<PlaceholderNode.Type.GALLERY> = {
type: PlaceholderNode.Type.GALLERY,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import { PlaceholderNode } from '../PlaceholderNode';
import { ImagePlaceholderElement } from './ImagePlaceholderElement';

const extensions = [PlaceholdersExtension()];
const editor = createEditor(createPlateEditor(), () => extensions);
const editor = createEditor({ editor: createPlateEditor(), getExtensions: () => extensions });

const placeholder: PlaceholderNode<PlaceholderNode.Type.IMAGE> = {
type: PlaceholderNode.Type.IMAGE,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import { PlaceholderNode } from '../PlaceholderNode';
import { MediaPlaceholderElement } from './MediaPlaceholderElement';

const extensions = [PlaceholdersExtension()];
const editor = createEditor(createPlateEditor(), () => extensions);
const editor = createEditor({ editor: createPlateEditor(), getExtensions: () => extensions });

const placeholder: PlaceholderNode<PlaceholderNode.Type.MEDIA> = {
type: PlaceholderNode.Type.MEDIA,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import { PlaceholderNode } from '../PlaceholderNode';
import { SocialPostPlaceholderElement } from './SocialPostPlaceholderElement';

const extensions = [PlaceholdersExtension()];
const editor = createEditor(createPlateEditor(), () => extensions);
const editor = createEditor({ editor: createPlateEditor(), getExtensions: () => extensions });

const placeholder: PlaceholderNode<PlaceholderNode.Type.SOCIAL_POST> = {
type: PlaceholderNode.Type.SOCIAL_POST,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import { PlaceholderNode } from '../PlaceholderNode';
import { StoryBookmarkPlaceholderElement } from './StoryBookmarkPlaceholderElement';

const extensions = [PlaceholdersExtension()];
const editor = createEditor(createPlateEditor(), () => extensions);
const editor = createEditor({ editor: createPlateEditor(), getExtensions: () => extensions });

const placeholder: PlaceholderNode<PlaceholderNode.Type.STORY_BOOKMARK> = {
type: PlaceholderNode.Type.STORY_BOOKMARK,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import { PlaceholderNode } from '../PlaceholderNode';
import { StoryEmbedPlaceholderElement } from './StoryEmbedPlaceholderElement';

const extensions = [PlaceholdersExtension()];
const editor = createEditor(createPlateEditor(), () => extensions);
const editor = createEditor({ editor: createPlateEditor(), getExtensions: () => extensions });

const placeholder: PlaceholderNode<PlaceholderNode.Type.STORY_EMBED> = {
type: PlaceholderNode.Type.STORY_EMBED,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import { PlaceholderNode } from '../PlaceholderNode';
import { VideoPlaceholderElement } from './VideoPlaceholderElement';

const extensions = [PlaceholdersExtension()];
const editor = createEditor(createPlateEditor(), () => extensions);
const editor = createEditor({ editor: createPlateEditor(), getExtensions: () => extensions });

const placeholder: PlaceholderNode<PlaceholderNode.Type.VIDEO> = {
type: PlaceholderNode.Type.VIDEO,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import { PlaceholderNode } from '../PlaceholderNode';
import { WebBookmarkPlaceholderElement } from './WebBookmarkPlaceholderElement';

const extensions = [PlaceholdersExtension()];
const editor = createEditor(createPlateEditor(), () => extensions);
const editor = createEditor({ editor: createPlateEditor(), getExtensions: () => extensions });

const placeholder: PlaceholderNode<PlaceholderNode.Type.WEB_BOOKMARK> = {
type: PlaceholderNode.Type.WEB_BOOKMARK,
Expand Down
6 changes: 5 additions & 1 deletion packages/slate-editor/src/hyperscript.ts
Original file line number Diff line number Diff line change
Expand Up @@ -124,7 +124,11 @@ const extensions = [

const creators: Record<keyof HElements, HyperscriptCreators[string]> = {
editor: createEditorFactory(() =>
createEditor(createSlateEditor(), () => extensions, [withReact, withHistory]),
createEditor({
editor: createSlateEditor(),
getExtensions: () => extensions,
withOverrides: [withReact, withHistory],
}),
),
'editor-pure': createEditorFactory(() => withReact(createSlateEditor())),
'h:text': createText,
Expand Down
72 changes: 58 additions & 14 deletions packages/slate-editor/src/modules/editor/createEditor.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,32 +8,76 @@ import {
import type { Extension, WithOverrides } from '@prezly/slate-commons';
import { isNotUndefined } from '@technically/is-not-undefined';
import { flow } from '@technically/lodash';
import type { SlateEditor } from '@udecode/plate';
import { type SlateEditor } from '@udecode/plate';
import { createPlateEditor } from '@udecode/plate/react';
import { type PlatePlugin } from '@udecode/plate/react';

import { createParagraph } from '#extensions/paragraphs';
import { withNodesHierarchy, hierarchySchema } from '#modules/nodes-hierarchy';

import { withDeserializeHtml, withElementsEqualityCheck, withRichBlocks } from './plugins';
import {
DefaultTextBlockPlugin,
withDeserializeHtml,
RichBlocksPlugin,
ElementsEqualityCheckPlugin,
} from './plugins';
import { type Value } from './types';

type Params = {
initialValue?: Value;
plugins?: PlatePlugin[];
baseEditor?: SlateEditor;
/**
* @deprecated It is planned to migrate extensions to become Plate Plugins
*/
getExtensions?: () => Extension[];
/**
* @deprecated It is recommended to migrate these overrides to become Plate Plugins
*/
withOverrides?: WithOverrides[];
};

export function createEditor({
initialValue,
plugins = [],
baseEditor,
getExtensions = noExtensions,
withOverrides = [],
}: Params) {
const editor = createPlateEditor({
editor: baseEditor,
plugins: [
...plugins,
DefaultTextBlockPlugin.configure({
options: {
createDefaultTextBlock: createParagraph,
},
}),
ElementsEqualityCheckPlugin,
RichBlocksPlugin.configure({
options: { getExtensions },
}),
],
value: initialValue,
});

export function createEditor(
baseEditor: SlateEditor,
getExtensions: () => Extension[],
plugins: WithOverrides[] = [],
) {
const overrides = getExtensions()
.map(({ withOverrides }) => withOverrides)
const extensionsOverrides = getExtensions()
.map((extension) => extension.withOverrides)
.filter(isNotUndefined);

return flow([
...plugins,
...withOverrides,
withNodesHierarchy(hierarchySchema),
withBreaksOnExpandedSelection,
withBreaksOnVoidNodes,
withInlineVoid(getExtensions),
withNormalization(getExtensions),
withUserFriendlyDeleteBehavior,
withDeserializeHtml(getExtensions),
withRichBlocks(getExtensions),
withElementsEqualityCheck,
...overrides,
])(baseEditor);
...extensionsOverrides,
])(editor);
}

function noExtensions(): Extension[] {
return [];
}
2 changes: 0 additions & 2 deletions packages/slate-editor/src/modules/editor/index.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
export { Editor } from './Editor';
export { createEditor } from './createEditor';
export { createEmptyValue } from './lib';
export { withDeserializeHtml, withElementsEqualityCheck, withRichBlocks } from './plugins';
export type { ElementsEqualityCheckEditor, RichBlocksAwareEditor } from './plugins';
export type { EditorRef, EditorProps, Value } from './types';
export { useEditorEvents } from './useEditorEvents';
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import { isEditorValueEqual } from './isEditorValueEqual';

describe('isEditorValueEqual', () => {
it('should return true for equivalent values', () => {
const editor = createEditor(createSlateEditor(), () => []);
const editor = createEditor({ editor: createSlateEditor() });

const a = [
{
Expand All @@ -25,7 +25,7 @@ describe('isEditorValueEqual', () => {
});

it('should return false for non-equivalent values', () => {
const editor = createEditor(createSlateEditor(), () => []);
const editor = createEditor({ editor: createSlateEditor() });

const a = [
{
Expand All @@ -44,7 +44,7 @@ describe('isEditorValueEqual', () => {
});

it('should consider structural equality', () => {
const editor = createEditor(createSlateEditor(), () => []);
const editor = createEditor({ editor: createSlateEditor() });

const a = [
{
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import { type TElement } from '@udecode/plate';
import { createPlatePlugin } from '@udecode/plate/react';

type TextBlockFactory<T extends TElement> = (props?: Partial<T>) => T;

type Options<T> = {
createDefaultTextBlock(): TextBlockFactory<T>;
};

export const DefaultTextBlockPlugin = {
configure<T extends TElement>(config: { options: Options<T> }) {
return createPlatePlugin<'DefaultTextBlock', Options<T>>({
key: 'DefaultTextBlock',
options: config.options,
}).overrideEditor(({ getOptions }) => {
const { createDefaultTextBlock } = getOptions();
return {
api: {
createDefaultTextBlock,
},
};
});
},
};
Original file line number Diff line number Diff line change
Expand Up @@ -10,31 +10,30 @@ import {
VideoNode,
} from '@prezly/slate-types';
import { isEqual } from '@technically/lodash';
import type { Element, SlateEditor } from '@udecode/plate';
import type { Element } from '@udecode/plate';
import { createPlatePlugin } from '@udecode/plate/react';

import { EmbedNode } from '#extensions/embed';
import { PlaceholderNode } from '#extensions/placeholders';

export interface ElementsEqualityCheckEditor {
/**
* Compare two elements.
*
* This is useful to implement smarter comparison rules to,
* for example, ignore data-independent properties like `uuid`.
*
* `children` arrays can be omitted from the comparison,
* as the outer code will compare them anyway.
*/
isElementEqual(node: Element, another: Element): boolean | undefined;
}

export function withElementsEqualityCheck<T extends SlateEditor>(
editor: T,
): T & ElementsEqualityCheckEditor {
return Object.assign(editor, {
isElementEqual,
});
}
/**
* Compare two elements.
*
* This is useful to implement smarter comparison rules to,
* for example, ignore data-independent properties like `uuid`.
*
* `children` arrays can be omitted from the comparison,
* as the outer code will compare them anyway.
*/
export const ElementsEqualityCheckPlugin = createPlatePlugin({
key: 'withElementsEqualityCheck',
}).overrideEditor(() => {
return {
api: {
isElementEqual,
},
};
});

function isElementEqual(node: Element, another: Element): boolean | undefined {
if (isAttachmentNode(node) && isAttachmentNode(another)) {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
import type { Extension } from '@prezly/slate-commons';
import type { Node } from '@udecode/plate';
import { createPlatePlugin, type PlatePlugin } from '@udecode/plate/react';

type Configuration = {
key: 'RichBlocks';
options: {
getExtensions(): Extension[];
};
api: never;
transforms: never;
};

export const RichBlocksPlugin: PlatePlugin<Configuration> = createPlatePlugin<
Configuration['key'],
Configuration['options'],
Configuration['api'],
Configuration['transforms']
>({
key: 'RichBlocks',
options: {
getExtensions: () => [],
},
}).overrideEditor(({ getOptions }) => {
const { getExtensions } = getOptions();
function isRichBlock(node: Node) {
for (const extension of getExtensions()) {
if (extension.isRichBlock?.(node)) return true;
}
return false;
}
return {
api: {
isRichBlock,
},
};
});
9 changes: 3 additions & 6 deletions packages/slate-editor/src/modules/editor/plugins/index.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,4 @@
export { type DefaultTextBlockEditor, withDefaultTextBlock } from './withDefaultTextBlock';
export { DefaultTextBlockPlugin } from './DefaultTextBlockPlugin';
export { ElementsEqualityCheckPlugin } from './ElementsEqualityCheckPlugin';
export { RichBlocksPlugin } from './RichBlocksPlugin';
export { withDeserializeHtml } from './withDeserializeHtml';
export {
type ElementsEqualityCheckEditor,
withElementsEqualityCheck,
} from './withElementsEqualityCheck';
export { type RichBlocksAwareEditor, withRichBlocks } from './withRichBlocks';
Loading