Skip to content

Commit

Permalink
rename to $onNormalize
Browse files Browse the repository at this point in the history
  • Loading branch information
zurfyx committed May 4, 2024
1 parent 3f96a80 commit 4032f5c
Show file tree
Hide file tree
Showing 4 changed files with 71 additions and 69 deletions.
27 changes: 22 additions & 5 deletions packages/lexical-playground/src/Editor.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,10 @@
*/

import {AutoFocusPlugin} from '@lexical/react/LexicalAutoFocusPlugin';
import {LexicalBlockNodeNormalizerPlugin__EXPERIMENTAL} from '@lexical/react/LexicalBlockNodeNormalizerPlugin__EXPERIMENTAL';
import {
BlockNode,
LexicalBlockNodeNormalizerPlugin__EXPERIMENTAL,
} from '@lexical/react/LexicalBlockNodeNormalizerPlugin__EXPERIMENTAL';
import {CharacterLimitPlugin} from '@lexical/react/LexicalCharacterLimitPlugin';
import {CheckListPlugin} from '@lexical/react/LexicalCheckListPlugin';
import {ClearEditorPlugin} from '@lexical/react/LexicalClearEditorPlugin';
Expand All @@ -23,8 +26,9 @@ import {RichTextPlugin} from '@lexical/react/LexicalRichTextPlugin';
import {TabIndentationPlugin} from '@lexical/react/LexicalTabIndentationPlugin';
import {TablePlugin} from '@lexical/react/LexicalTablePlugin';
import useLexicalEditable from '@lexical/react/useLexicalEditable';
import {ElementNode} from 'lexical';
import * as React from 'react';
import {useEffect, useState} from 'react';
import {useCallback, useEffect, useState} from 'react';
import {CAN_USE_DOM} from 'shared/canUseDOM';

import {createWebsocketProvider} from './collaboration';
Expand Down Expand Up @@ -72,7 +76,6 @@ import TwitterPlugin from './plugins/TwitterPlugin';
import YouTubePlugin from './plugins/YouTubePlugin';
import ContentEditable from './ui/ContentEditable';
import Placeholder from './ui/Placeholder';
import onError from './utils/onError';
import onWarn from './utils/onWarn';

const skipCollaborationInit =
Expand Down Expand Up @@ -157,8 +160,22 @@ export default function Editor(): JSX.Element {
/>
<LexicalBlockNodeNormalizerPlugin__EXPERIMENTAL
blockNodes={BLOCK_NODES}
onError={onError}
onWarn={onWarn}
$onNormalize={useCallback(
(
node: BlockNode<JSX.Element>,
parent: ElementNode,
event?: 'paste',
) => {
onWarn(
`Found top level node ${node.getKey()} ${
node.constructor.name
} inside ${parent.getKey()} ${parent.constructor.name}${
event != null ? ` (${event})` : ''
}`,
);
},
[],
)}
/>
{isRichText ? (
<>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,17 +13,19 @@ import * as React from 'react';

export type BlockNode<T> = ElementNode | DecoratorNode<T>;
export type BlockNodeKlass<T> = Class<BlockNode<T>>;
export type OnNormalizeFn<T> = (
node: BlockNode<T>,
previousParent: ElementNode,
event?: 'paste',
) => void;

declare export function LexicalBlockNodeNormalizerPlugin__EXPERIMENTAL(props: {
onError?: (message: string) => void;
onWarn?: (message: string) => void;
blockNodes: Array<Class<React.Node>>;
$onNormalize?: OnNormalizeFn<React.Node>;
}): React$Node;

declare export function registerBlockNodeNormalizerPlugin__EXPERIMENTAL<T>(
editor: LexicalEditor,
nodes: Array<Class<T>>, {
onError?: (message: string) => void;
onWarn?: (message: string) => void;
},
nodes: Array<Class<T>>,
$onNormalize?: OnNormalizeFn<React.Node>
): () => void;
Original file line number Diff line number Diff line change
Expand Up @@ -27,9 +27,15 @@ import {
PASTE_COMMAND,
} from 'lexical';
import {useEffect} from 'react';
import invariant from 'shared/invariant';

export type BlockNode<T> = ElementNode | DecoratorNode<T>;
export type BlockNodeKlass<T> = Klass<BlockNode<T>>;
export type OnNormalizeFn<T> = (
node: BlockNode<T>,
previousParent: ElementNode,
event?: 'paste',
) => void;

const emptyFunction = () => {};

Expand All @@ -46,52 +52,43 @@ const emptyFunction = () => {};
*/
export function LexicalBlockNodeNormalizerPlugin__EXPERIMENTAL({
blockNodes,
onError,
onWarn,
$onNormalize,
}: {
onError?: (message: string) => void;
onWarn?: (message: string) => void;
blockNodes: Array<BlockNodeKlass<JSX.Element>>;
$onNormalize?: OnNormalizeFn<JSX.Element>;
}): null {
const [editor] = useLexicalComposerContext();

useEffect(() => {
return registerBlockNodeNormalizerPlugin__EXPERIMENTAL(editor, blockNodes, {
onError,
onWarn,
});
}, [editor, blockNodes, onError, onWarn]);
return registerBlockNodeNormalizerPlugin__EXPERIMENTAL(
editor,
blockNodes,
$onNormalize,
);
}, [editor, blockNodes, $onNormalize]);

return null;
}

export function registerBlockNodeNormalizerPlugin__EXPERIMENTAL<T>(
editor: LexicalEditor,
nodes: Array<BlockNodeKlass<T>>,
optional: {
onError?: (message: string) => void;
onWarn?: (message: string) => void;
} = {},
$onNormalize?: OnNormalizeFn<T>,
): () => void {
const {onError = emptyFunction, onWarn = emptyFunction} = optional;
let lastPasteCommand = 0;

const nodeTransform = (node: BlockNode<T>) => {
const parent = node.getParent<ElementNode>();

if (parent === null || $isRootOrShadowRoot(parent)) {
return;
}

if (node.isInline()) {
// TODO throw an invariant (check internal)
onError(
`Node ${node.getKey()} ${
node.constructor.name
} is not a top level node (isInline() === true). Revise the BlockNodeNormalizer configuration`,
);
return;
}
invariant(
!node.isInline(),
'Node %s %s is not a top level node (isInline() === true). Revise the BlockNodeNormalizerPlugin configuration',
node.getKey(),
node.constructor.name,
);

// Valid list nesting
if (
Expand All @@ -101,16 +98,7 @@ export function registerBlockNodeNormalizerPlugin__EXPERIMENTAL<T>(
return;
}

// Log structural issues only once, and then separate events if it's
// related to copy-pasting
const isPasting = lastPasteCommand + 250 > Date.now();
onWarn(
`Found top level node ${node.getKey()} ${
node.constructor.name
} inside ${parent.getKey()} ${parent.constructor.name}${
isPasting ? ' (paste event)' : ''
}`,
);
const event = lastPasteCommand + 250 > Date.now() ? 'paste' : undefined;

// For unexpected nesting within list items flatten its content by appending
// all children of current node. It's different from other element nodes,
Expand All @@ -125,6 +113,9 @@ export function registerBlockNodeNormalizerPlugin__EXPERIMENTAL<T>(
node.remove();
}

if ($onNormalize != null) {
$onNormalize(node, parent, event);
}
return;
}

Expand Down Expand Up @@ -163,11 +154,14 @@ export function registerBlockNodeNormalizerPlugin__EXPERIMENTAL<T>(
}

parent.remove();
if ($onNormalize != null) {
$onNormalize(node, parent, event);
}
};

let unregisterListeners = emptyFunction;
function registerListeners() {
unregisterListeners = mergeRegister(
return mergeRegister(
editor.registerCommand(
PASTE_COMMAND,
() => {
Expand All @@ -182,16 +176,15 @@ export function registerBlockNodeNormalizerPlugin__EXPERIMENTAL<T>(
);
}
if (editor.isEditable()) {
registerListeners();
unregisterListeners = registerListeners();
}

return mergeRegister(
editor.registerEditableListener((editable) => {
unregisterListeners();
unregisterListeners = emptyFunction;
if (editable) {
registerListeners();
} else {
unregisterListeners();
unregisterListeners = emptyFunction;
unregisterListeners = registerListeners();
}
}),
unregisterListeners,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,6 @@
*
*/



import type {LexicalEditor, SerializedLexicalNode} from 'lexical';

import {createHeadlessEditor} from '@lexical/headless';
Expand Down Expand Up @@ -88,22 +86,14 @@ describe('NestingEnforcementPlugin', () => {
throw error;
},
});
registerBlockNodeNormalizerPlugin__EXPERIMENTAL(
editor,
[
HeadingNode,
QuoteNode,
ListNode,
ListItemNode,
BlockDecorator,
ParagraphNode,
],
{
onError: (errorMessage) => {
throw new Error(errorMessage);
},
},
);
registerBlockNodeNormalizerPlugin__EXPERIMENTAL(editor, [
HeadingNode,
QuoteNode,
ListNode,
ListItemNode,
BlockDecorator,
ParagraphNode,
]);
});

test('p > h1 > text unwraps into h1 > text', () => {
Expand Down

0 comments on commit 4032f5c

Please sign in to comment.