From 1d07dc5a09e6eff28739ff70f31201303201481c Mon Sep 17 00:00:00 2001 From: Bob Ippolito <bob@redivi.com> Date: Sun, 16 Mar 2025 14:02:43 -0700 Subject: [PATCH 01/10] WIP split nodes --- .../lexical-utils/flow/LexicalUtils.js.flow | 7 +- ...xicalUtilsInsertNodeToNearestRoot.test.tsx | 6 +- packages/lexical-utils/src/index.ts | 103 +++++++++++------- packages/lexical/flow/Lexical.js.flow | 4 +- .../lexical/src/__tests__/utils/index.tsx | 45 +++++++- packages/lexical/src/caret/LexicalCaret.ts | 9 ++ .../lexical/src/caret/LexicalCaretUtils.ts | 95 +++++++++++++++- packages/lexical/src/index.ts | 3 + 8 files changed, 224 insertions(+), 48 deletions(-) diff --git a/packages/lexical-utils/flow/LexicalUtils.js.flow b/packages/lexical-utils/flow/LexicalUtils.js.flow index 38f2c3107d9..512d10c0847 100644 --- a/packages/lexical-utils/flow/LexicalUtils.js.flow +++ b/packages/lexical-utils/flow/LexicalUtils.js.flow @@ -102,7 +102,12 @@ declare export function $restoreEditorState( editorState: EditorState, ): void; -declare export function $insertNodeToNearestRoot<T: LexicalNode>(node: T): T; + +export interface InsertNodeToNearestRootOptions { + skipEmptyParagraph?: boolean; + preventEmptyElements?: boolean; +} +declare export function $insertNodeToNearestRoot<T: LexicalNode>(node: T, options?: InsertNodeToNearestRootOptions): T; declare export function $wrapNodeInElement( node: LexicalNode, diff --git a/packages/lexical-utils/src/__tests__/unit/LexicalUtilsInsertNodeToNearestRoot.test.tsx b/packages/lexical-utils/src/__tests__/unit/LexicalUtilsInsertNodeToNearestRoot.test.tsx index 51902c01532..3fbf8204de4 100644 --- a/packages/lexical-utils/src/__tests__/unit/LexicalUtilsInsertNodeToNearestRoot.test.tsx +++ b/packages/lexical-utils/src/__tests__/unit/LexicalUtilsInsertNodeToNearestRoot.test.tsx @@ -86,7 +86,7 @@ describe('LexicalUtils#insertNodeToNearestRoot', () => { '<test-decorator></test-decorator>' + '<p><br></p>', initialHtml: '<p>Hello world</p>', - selectionOffset: 12, // Selection on text node after "Hello" world + selectionOffset: 'Hello world'.length, // Selection on text node after "Hello" world selectionPath: [0, 0], }, { @@ -96,7 +96,7 @@ describe('LexicalUtils#insertNodeToNearestRoot', () => { '<test-decorator></test-decorator>' + '<p><span style="white-space: pre-wrap;">Hello world</span></p>', initialHtml: '<p>Hello world</p>', - selectionOffset: 0, // Selection on text node after "Hello" world + selectionOffset: 0, // Selection on text node before "Hello" world selectionPath: [0, 0], }, { @@ -175,7 +175,7 @@ describe('LexicalUtils#insertNodeToNearestRoot', () => { ); $setSelection(selection); - $insertNodeToNearestRoot($createTestDecoratorNode()); + $insertNodeToNearestRoot($createTestDecoratorNode().setIsInline(false)); // Cleaning up list value attributes as it's not really needed in this test // and it clutters expected output diff --git a/packages/lexical-utils/src/index.ts b/packages/lexical-utils/src/index.ts index e7f994829bd..4710d632ee2 100644 --- a/packages/lexical-utils/src/index.ts +++ b/packages/lexical-utils/src/index.ts @@ -7,12 +7,14 @@ */ import { + $caretFromPoint, $cloneWithProperties, + $copyNode, $createParagraphNode, $getAdjacentChildCaret, $getChildCaret, - $getChildCaretAtIndex, $getChildCaretOrSelf, + $getCollapsedCaretRange, $getPreviousSelection, $getRoot, $getSelection, @@ -21,13 +23,13 @@ import { $isChildCaret, $isElementNode, $isRangeSelection, - $isRootOrShadowRoot, $isSiblingCaret, - $isTextNode, + $normalizeCaret, $rewindSiblingCaret, $setSelection, + $setSelectionFromCaretRange, $setState, - $splitNode, + $splitAtPointCaretNext, type CaretDirection, type EditorState, ElementNode, @@ -37,8 +39,10 @@ import { makeStepwiseIterator, type NodeCaret, type NodeKey, + PointCaret, RootMode, type SiblingCaret, + SplitAtPointCaretNextOptions, StateConfig, ValueOrUpdater, } from 'lexical'; @@ -546,53 +550,76 @@ export function $restoreEditorState( $setSelection(selection === null ? null : selection.clone()); } +export interface InsertNodeToNearestRootOptions { + /** If true (default false), do not insert an empty paragraph before the inserted node at the root */ + skipEmptyParagraph?: boolean; + /** If true (default false), do not split an ElementNode even if it can be empty */ + preventEmptyElements?: boolean; +} + /** * If the selected insertion area is the root/shadow root node (see {@link lexical!$isRootOrShadowRoot}), * the node will be appended there, otherwise, it will be inserted before the insertion area. * If there is no selection where the node is to be inserted, it will be appended after any current nodes - * within the tree, as a child of the root node. A paragraph node will then be added after the inserted node and selected. + * within the tree, as a child of the root node. A paragraph node will then be added after the inserted + * node and selected unless skipEmptyParagraph is true. * @param node - The node to be inserted + * @param options - see {@link InsertNodeToNearestRootOptions} * @returns The node after its insertion */ -export function $insertNodeToNearestRoot<T extends LexicalNode>(node: T): T { +export function $insertNodeToNearestRoot<T extends LexicalNode>( + node: T, + { + skipEmptyParagraph = false, + preventEmptyElements = false, + }: InsertNodeToNearestRootOptions = {}, +): T { const selection = $getSelection() || $getPreviousSelection(); - + let initialCaret: undefined | PointCaret<'next'>; if ($isRangeSelection(selection)) { - const {focus} = selection; - const focusNode = focus.getNode(); - const focusOffset = focus.offset; - - if ($isRootOrShadowRoot(focusNode)) { - $getChildCaretAtIndex(focusNode, focusOffset, 'next').insert(node); - node.selectNext(); - } else { - let splitNode: ElementNode; - let splitOffset: number; - if ($isTextNode(focusNode)) { - splitNode = focusNode.getParentOrThrow(); - splitOffset = focusNode.getIndexWithinParent(); - if (focusOffset > 0) { - splitOffset += 1; - focusNode.splitText(focusOffset); - } - } else { - splitNode = focusNode; - splitOffset = focusOffset; - } - const [, rightTree] = $splitNode(splitNode, splitOffset); - rightTree.insertBefore(node); - rightTree.selectStart(); - } + initialCaret = $caretFromPoint(selection.focus, 'next'); } else { if (selection != null) { const nodes = selection.getNodes(); - nodes[nodes.length - 1].getTopLevelElementOrThrow().insertAfter(node); - } else { - $getRoot().append(node); + const lastNode = nodes[nodes.length - 1]; + if (lastNode) { + initialCaret = $getSiblingCaret(lastNode, 'next'); + } } - const paragraphNode = $createParagraphNode(); - node.insertAfter(paragraphNode); - paragraphNode.select(); + } + const splitOptions: SplitAtPointCaretNextOptions = { + $copyElementNode: $copyNode, + allowEmptyLeftSplit: !preventEmptyElements, + allowEmptyRightSplit: !preventEmptyElements, + rootMode: 'shadowRoot', + }; + let insertCaret = + initialCaret || $getChildCaret($getRoot(), 'previous').getFlipped(); + for ( + let nextCaret: null | PointCaret<'next'> = insertCaret; + nextCaret; + nextCaret = $splitAtPointCaretNext(nextCaret, splitOptions) + ) { + insertCaret = nextCaret; + } + const emptyParagraphAfter = !( + skipEmptyParagraph || + initialCaret || + node.isInline() + ) + ? $createParagraphNode() + : null; + if (emptyParagraphAfter) { + insertCaret.insert(emptyParagraphAfter); + emptyParagraphAfter.select(); + } + insertCaret.insert( + node.isInline() ? $createParagraphNode().append(node) : node, + ); + if (!emptyParagraphAfter) { + $setSelectionFromCaretRange( + $getCollapsedCaretRange($normalizeCaret($getSiblingCaret(node, 'next'))), + ); } return node.getLatest(); } diff --git a/packages/lexical/flow/Lexical.js.flow b/packages/lexical/flow/Lexical.js.flow index 4078d8802d8..e988981c883 100644 --- a/packages/lexical/flow/Lexical.js.flow +++ b/packages/lexical/flow/Lexical.js.flow @@ -1227,7 +1227,9 @@ declare export function $getCommonAncestor< declare export function $extendCaretToRange<D: CaretDirection>( anchor: PointCaret<D>, ): CaretRange<D>; - +declare export function $getCollapsedCaretRange<D: CaretDirection>( + anchor: PointCaret<D>, +): CaretRange<D>; declare export function $isExtendableTextPointCaret<D: CaretDirection>( caret: PointCaret<D> ): implies caret is TextPointCaret<TextNode, D>; diff --git a/packages/lexical/src/__tests__/utils/index.tsx b/packages/lexical/src/__tests__/utils/index.tsx index 8206d550579..3eeecec272d 100644 --- a/packages/lexical/src/__tests__/utils/index.tsx +++ b/packages/lexical/src/__tests__/utils/index.tsx @@ -36,10 +36,12 @@ import { Klass, LexicalEditor, LexicalNode, + LexicalUpdateJSON, RangeSelection, SerializedElementNode, SerializedLexicalNode, SerializedTextNode, + Spread, TextNode, } from 'lexical'; import path from 'path'; @@ -335,9 +337,13 @@ export function $createTestExcludeFromCopyElementNode(): TestExcludeFromCopyElem return new TestExcludeFromCopyElementNode(); } -export type SerializedTestDecoratorNode = SerializedLexicalNode; +export type SerializedTestDecoratorNode = Spread< + SerializedLexicalNode, + {block?: boolean} +>; export class TestDecoratorNode extends DecoratorNode<JSX.Element> { + __block: boolean = false; static getType(): string { return 'test_decorator'; } @@ -362,6 +368,37 @@ export class TestDecoratorNode extends DecoratorNode<JSX.Element> { }; } + updateFromJSON( + serializedNode: LexicalUpdateJSON<SerializedTestDecoratorNode>, + ): this { + return super + .updateFromJSON(serializedNode) + .setIsInline(!serializedNode.block); + } + + afterCloneFrom(prevNode: this): void { + super.afterCloneFrom(prevNode); + this.__block = prevNode.__block; + } + + isInline(): boolean { + return !this.getLatest().__block; + } + + setIsInline(inline: boolean): this { + const self = this.getWritable(); + self.__block = !inline; + return self; + } + + exportJSON(): SerializedTestDecoratorNode { + const json: SerializedTestDecoratorNode = super.exportJSON(); + if (this.__block) { + json.block = this.__block; + } + return json; + } + exportDOM() { return { element: document.createElement('test-decorator'), @@ -373,11 +410,11 @@ export class TestDecoratorNode extends DecoratorNode<JSX.Element> { } createDOM() { - return document.createElement('span'); + return document.createElement(this.__block ? 'div' : 'span'); } - updateDOM() { - return false; + updateDOM(prevNode: this) { + return this.__block !== prevNode.__block; } decorate() { diff --git a/packages/lexical/src/caret/LexicalCaret.ts b/packages/lexical/src/caret/LexicalCaret.ts index b86fd87f281..c1af5986087 100644 --- a/packages/lexical/src/caret/LexicalCaret.ts +++ b/packages/lexical/src/caret/LexicalCaret.ts @@ -1121,6 +1121,15 @@ export function $extendCaretToRange<D extends CaretDirection>( return $getCaretRange(anchor, $getSiblingCaret($getRoot(), anchor.direction)); } +/** + * Construct a collapsed CaretRange that starts and ends at anchor. + */ +export function $getCollapsedCaretRange<D extends CaretDirection>( + anchor: PointCaret<D>, +): CaretRange<D> { + return $getCaretRange(anchor, anchor); +} + /** * Construct a CaretRange from anchor and focus carets pointing in the * same direction. In order to get the expected behavior, diff --git a/packages/lexical/src/caret/LexicalCaretUtils.ts b/packages/lexical/src/caret/LexicalCaretUtils.ts index b509464af97..830b3e09f37 100644 --- a/packages/lexical/src/caret/LexicalCaretUtils.ts +++ b/packages/lexical/src/caret/LexicalCaretUtils.ts @@ -43,6 +43,7 @@ import { $getAdjacentChildCaret, $getCaretRange, $getChildCaret, + $getCollapsedCaretRange, $getSiblingCaret, $getTextNodeOffset, $getTextPointCaret, @@ -357,7 +358,7 @@ export function $removeTextFromCaretRange<D extends CaretDirection>( $normalizeCaret(bestCandidate), initialRange.direction, ); - return $getCaretRange(anchor, anchor); + return $getCollapsedCaretRange(anchor); } invariant( false, @@ -610,3 +611,95 @@ export function $getAdjacentSiblingOrParentSiblingCaret< } return nextCaret && [nextCaret, depthDiff]; } + +/** + * Get the adjacent nodes to initialCaret in the given direction. + * + * @example + * ```ts + * expect($getAdjacentNodes($getChildCaret(parent, 'next'))).toEqual(parent.getChildren()); + * expect($getAdjacentNodes($getChildCaret(parent, 'previous'))).toEqual(parent.getChildren().reverse()); + * expect($getAdjacentNodes($getSiblingCaret(node, 'next'))).toEqual(node.getNextSiblings()); + * expect($getAdjacentNodes($getSiblingCaret(node, 'previous'))).toEqual(node.getPreviousSiblings().reverse()); + * ``` + * + * @param initialCaret The caret to start at (the origin will not be included) + * @returns An array of siblings. + */ +export function $getAdjacentNodes( + initialCaret: NodeCaret<CaretDirection>, +): LexicalNode[] { + const siblings = []; + for ( + let caret = initialCaret.getAdjacentCaret(); + caret; + caret = caret.getAdjacentCaret() + ) { + siblings.push(caret.origin); + } + return siblings; +} + +export interface SplitAtPointCaretNextOptions { + /** The function to create the right side of a split ElementNode */ + $copyElementNode: (node: ElementNode) => ElementNode; + /** If the parent matches rootMode a split will not occur, default is 'shadowRoot' */ + rootMode?: RootMode; + /** If true (default false), the parent may be split before its first child when parent.canBeEmpty() is true */ + allowEmptyLeftSplit?: boolean; + /** If true (default false), the parent may be split after its last child when parent.canBeEmpty() is true */ + allowEmptyRightSplit?: boolean; +} + +/** + * Split a node at a PointCaret and return a NodeCaret at that point, or null if the + * node can't be split. This is non-recursive and will only perform at most one split. + * + * @returns The NodeCaret pointing to the location of the split (or null if a split is not possible) + */ +export function $splitAtPointCaretNext( + pointCaret: PointCaret<'next'>, + { + $copyElementNode, + rootMode = 'shadowRoot', + allowEmptyLeftSplit = false, + allowEmptyRightSplit = false, + }: SplitAtPointCaretNextOptions, +): null | NodeCaret<'next'> { + if ($isTextPointCaret(pointCaret)) { + if ( + pointCaret.offset === $getTextNodeOffset(pointCaret.origin, 'previous') + ) { + return $rewindSiblingCaret(pointCaret.getSiblingCaret()); + } + const origin = $isExtendableTextPointCaret(pointCaret) + ? pointCaret.origin.splitText(pointCaret.offset)[0] + : pointCaret.origin; + invariant( + $isTextNode(origin), + '$splitTextAtPointCaretNext: splitText must return at least one TextNode', + ); + return $getSiblingCaret(origin, 'next'); + } + const parentCaret = pointCaret.getParentCaret(rootMode); + if (parentCaret) { + if ( + $isChildCaret(pointCaret) && + !(allowEmptyLeftSplit && parentCaret.origin.canBeEmpty()) + ) { + // No split necessary, the left side would be empty + return $rewindSiblingCaret(parentCaret); + } + const siblings = $getAdjacentNodes(pointCaret); + if ( + siblings.length > 0 || + (allowEmptyRightSplit && parentCaret.origin.canBeEmpty()) + ) { + // Split and insert the siblings into the new tree + parentCaret.insert( + $copyElementNode(parentCaret.origin).splice(0, 0, siblings), + ); + } + } + return parentCaret; +} diff --git a/packages/lexical/src/index.ts b/packages/lexical/src/index.ts index 4b15162d8b6..f26e603a6df 100644 --- a/packages/lexical/src/index.ts +++ b/packages/lexical/src/index.ts @@ -34,6 +34,7 @@ export { $getCaretRange, $getChildCaret, $getChildCaretOrSelf, + $getCollapsedCaretRange, $getCommonAncestor, $getCommonAncestorResultBranchOrder, $getSiblingCaret, @@ -61,7 +62,9 @@ export { $rewindSiblingCaret, $setPointFromCaret, $setSelectionFromCaretRange, + $splitAtPointCaretNext, $updateRangeSelectionFromCaretRange, + type SplitAtPointCaretNextOptions, } from './caret/LexicalCaretUtils'; export type {PasteCommandType} from './LexicalCommands'; export { From 9dac15d3ad47a0ec38b41da71c87b44bac8b79f2 Mon Sep 17 00:00:00 2001 From: Bob Ippolito <bob@redivi.com> Date: Mon, 17 Mar 2025 00:14:26 -0700 Subject: [PATCH 02/10] $insertNodeToNearestRootAtCaret --- .../__tests__/e2e/HorizontalRule.spec.mjs | 2 + .../lexical-utils/flow/LexicalUtils.js.flow | 9 +- packages/lexical-utils/src/index.ts | 88 +++++++++---------- packages/lexical/flow/Lexical.js.flow | 13 +++ .../lexical/src/caret/LexicalCaretUtils.ts | 71 +++++++++------ 5 files changed, 106 insertions(+), 77 deletions(-) diff --git a/packages/lexical-playground/__tests__/e2e/HorizontalRule.spec.mjs b/packages/lexical-playground/__tests__/e2e/HorizontalRule.spec.mjs index fbcc79eb489..545d5575bd3 100644 --- a/packages/lexical-playground/__tests__/e2e/HorizontalRule.spec.mjs +++ b/packages/lexical-playground/__tests__/e2e/HorizontalRule.spec.mjs @@ -245,6 +245,7 @@ test.describe('HorizontalRule', () => { focusPath: [0, 0, 0], }); + await page.pause(); await selectFromInsertDropdown(page, '.horizontal-rule'); await waitForSelector(page, 'hr'); @@ -269,6 +270,7 @@ test.describe('HorizontalRule', () => { `, ); + await page.pause(); await assertSelection(page, { anchorOffset: 0, anchorPath: [2, 0, 0], diff --git a/packages/lexical-utils/flow/LexicalUtils.js.flow b/packages/lexical-utils/flow/LexicalUtils.js.flow index 512d10c0847..79bd89ec897 100644 --- a/packages/lexical-utils/flow/LexicalUtils.js.flow +++ b/packages/lexical-utils/flow/LexicalUtils.js.flow @@ -15,6 +15,8 @@ import type { CaretDirection, SiblingCaret, RootMode, + SplitAtPointCaretNextOptions, + PointCaret, } from 'lexical'; declare export function addClassNamesToElement( element: HTMLElement, @@ -103,11 +105,8 @@ declare export function $restoreEditorState( ): void; -export interface InsertNodeToNearestRootOptions { - skipEmptyParagraph?: boolean; - preventEmptyElements?: boolean; -} -declare export function $insertNodeToNearestRoot<T: LexicalNode>(node: T, options?: InsertNodeToNearestRootOptions): T; +declare export function $insertNodeToNearestRoot<T: LexicalNode>(node: T): T; +declare export function $insertNodeToNearestRootAtCaret<T: LexicalNode>(node: T, caret: PointCaret<CaretDirection>, options?: SplitAtPointCaretNextOptions): T; declare export function $wrapNodeInElement( node: LexicalNode, diff --git a/packages/lexical-utils/src/index.ts b/packages/lexical-utils/src/index.ts index 4710d632ee2..4426cec0295 100644 --- a/packages/lexical-utils/src/index.ts +++ b/packages/lexical-utils/src/index.ts @@ -9,9 +9,9 @@ import { $caretFromPoint, $cloneWithProperties, - $copyNode, $createParagraphNode, $getAdjacentChildCaret, + $getCaretInDirection, $getChildCaret, $getChildCaretOrSelf, $getCollapsedCaretRange, @@ -24,6 +24,7 @@ import { $isElementNode, $isRangeSelection, $isSiblingCaret, + $isTextPointCaret, $normalizeCaret, $rewindSiblingCaret, $setSelection, @@ -550,30 +551,15 @@ export function $restoreEditorState( $setSelection(selection === null ? null : selection.clone()); } -export interface InsertNodeToNearestRootOptions { - /** If true (default false), do not insert an empty paragraph before the inserted node at the root */ - skipEmptyParagraph?: boolean; - /** If true (default false), do not split an ElementNode even if it can be empty */ - preventEmptyElements?: boolean; -} - /** * If the selected insertion area is the root/shadow root node (see {@link lexical!$isRootOrShadowRoot}), * the node will be appended there, otherwise, it will be inserted before the insertion area. * If there is no selection where the node is to be inserted, it will be appended after any current nodes - * within the tree, as a child of the root node. A paragraph node will then be added after the inserted - * node and selected unless skipEmptyParagraph is true. + * within the tree, as a child of the root node. A paragraph will then be added after the inserted node and selected. * @param node - The node to be inserted - * @param options - see {@link InsertNodeToNearestRootOptions} * @returns The node after its insertion */ -export function $insertNodeToNearestRoot<T extends LexicalNode>( - node: T, - { - skipEmptyParagraph = false, - preventEmptyElements = false, - }: InsertNodeToNearestRootOptions = {}, -): T { +export function $insertNodeToNearestRoot<T extends LexicalNode>(node: T): T { const selection = $getSelection() || $getPreviousSelection(); let initialCaret: undefined | PointCaret<'next'>; if ($isRangeSelection(selection)) { @@ -586,42 +572,56 @@ export function $insertNodeToNearestRoot<T extends LexicalNode>( initialCaret = $getSiblingCaret(lastNode, 'next'); } } + initialCaret = + initialCaret || + $getChildCaret($getRoot(), 'previous') + .getFlipped() + .insert($createParagraphNode()); } - const splitOptions: SplitAtPointCaretNextOptions = { - $copyElementNode: $copyNode, - allowEmptyLeftSplit: !preventEmptyElements, - allowEmptyRightSplit: !preventEmptyElements, - rootMode: 'shadowRoot', - }; - let insertCaret = - initialCaret || $getChildCaret($getRoot(), 'previous').getFlipped(); + const insertCaret = $insertNodeToNearestRootAtCaret(node, initialCaret); + const adjacent = $getAdjacentChildCaret(insertCaret); + const selectionCaret = $isChildCaret(adjacent) + ? $normalizeCaret(adjacent) + : insertCaret; + $setSelectionFromCaretRange($getCollapsedCaretRange(selectionCaret)); + return node.getLatest(); +} + +/** + * If the insertion caret is the root/shadow root node (see {@link lexical!$isRootOrShadowRoot}), + * the node will be inserted there, otherwise the parent nodes will be split according to the + * given options. + * @param node - The node to be inserted + * @param caret - The location to insert or split from + * @returns The node after its insertion + */ +export function $insertNodeToNearestRootAtCaret< + T extends LexicalNode, + D extends CaretDirection, +>( + node: T, + caret: PointCaret<D>, + options?: SplitAtPointCaretNextOptions, +): NodeCaret<D> { + let insertCaret: PointCaret<'next'> = $getCaretInDirection(caret, 'next'); for ( let nextCaret: null | PointCaret<'next'> = insertCaret; nextCaret; - nextCaret = $splitAtPointCaretNext(nextCaret, splitOptions) + nextCaret = $splitAtPointCaretNext(nextCaret, options) ) { insertCaret = nextCaret; } - const emptyParagraphAfter = !( - skipEmptyParagraph || - initialCaret || - node.isInline() - ) - ? $createParagraphNode() - : null; - if (emptyParagraphAfter) { - insertCaret.insert(emptyParagraphAfter); - emptyParagraphAfter.select(); - } + invariant( + !$isTextPointCaret(insertCaret), + '$insertNodeToNearestRootAtCaret: An unattached TextNode can not be split', + ); insertCaret.insert( node.isInline() ? $createParagraphNode().append(node) : node, ); - if (!emptyParagraphAfter) { - $setSelectionFromCaretRange( - $getCollapsedCaretRange($normalizeCaret($getSiblingCaret(node, 'next'))), - ); - } - return node.getLatest(); + return $getCaretInDirection( + $getSiblingCaret(node.getLatest(), 'next'), + caret.direction, + ); } /** diff --git a/packages/lexical/flow/Lexical.js.flow b/packages/lexical/flow/Lexical.js.flow index e988981c883..73e57102482 100644 --- a/packages/lexical/flow/Lexical.js.flow +++ b/packages/lexical/flow/Lexical.js.flow @@ -1233,3 +1233,16 @@ declare export function $getCollapsedCaretRange<D: CaretDirection>( declare export function $isExtendableTextPointCaret<D: CaretDirection>( caret: PointCaret<D> ): implies caret is TextPointCaret<TextNode, D>; + +export interface SplitAtPointCaretNextOptions { + $copyElementNode?: (node: ElementNode) => ElementNode; + $splitTextPointCaretNext?: ( + caret: TextPointCaret<TextNode, 'next'>, + ) => NodeCaret<'next'>; + rootMode?: RootMode; + $shouldSplit?: (node: ElementNode, edge: 'first' | 'last') => boolean; +} +declare export function $splitAtPointCaretNext( + pointCaret: PointCaret<'next'>, + options?: SplitAtPointCaretNextOptions, +): null | NodeCaret<'next'>; diff --git a/packages/lexical/src/caret/LexicalCaretUtils.ts b/packages/lexical/src/caret/LexicalCaretUtils.ts index 830b3e09f37..ac5668356db 100644 --- a/packages/lexical/src/caret/LexicalCaretUtils.ts +++ b/packages/lexical/src/caret/LexicalCaretUtils.ts @@ -27,6 +27,7 @@ import { type RangeSelection, } from '../LexicalSelection'; import { + $copyNode, $getNodeByKeyOrThrow, $isRootOrShadowRoot, $setSelection, @@ -640,15 +641,42 @@ export function $getAdjacentNodes( return siblings; } +export function $splitTextPointCaret<D extends CaretDirection>( + textPointCaret: TextPointCaret<TextNode, D>, +): NodeCaret<D> { + const {origin, offset, direction} = textPointCaret; + if (offset === $getTextNodeOffset(origin, direction)) { + return textPointCaret.getSiblingCaret(); + } else if (offset === $getTextNodeOffset(origin, flipDirection(direction))) { + return $rewindSiblingCaret(textPointCaret.getSiblingCaret()); + } + const [textNode] = origin.splitText(offset); + invariant( + $isTextNode(textNode), + '$splitTextPointCaret: splitText must return at least one TextNode', + ); + return $getCaretInDirection($getSiblingCaret(textNode, 'next'), direction); +} + export interface SplitAtPointCaretNextOptions { - /** The function to create the right side of a split ElementNode */ - $copyElementNode: (node: ElementNode) => ElementNode; + /** The function to create the right side of a split ElementNode (default {@link $copyNode}) */ + $copyElementNode?: (node: ElementNode) => ElementNode; + /** The function to split a TextNode (default {@link $splitTextPointCaret}) */ + $splitTextPointCaretNext?: ( + caret: TextPointCaret<TextNode, 'next'>, + ) => NodeCaret<'next'>; /** If the parent matches rootMode a split will not occur, default is 'shadowRoot' */ rootMode?: RootMode; - /** If true (default false), the parent may be split before its first child when parent.canBeEmpty() is true */ - allowEmptyLeftSplit?: boolean; - /** If true (default false), the parent may be split after its last child when parent.canBeEmpty() is true */ - allowEmptyRightSplit?: boolean; + /** + * If element.canBeEmpty() and would create an empty split, this function will be + * called with the element and 'first' | 'last'. If it returns false, the empty + * split will not be created. Default is `() => true` to always split when possible. + */ + $shouldSplit?: (node: ElementNode, edge: 'first' | 'last') => boolean; +} + +function $alwaysSplit(_node: ElementNode, _edge: 'first' | 'last'): true { + return true; } /** @@ -660,32 +688,21 @@ export interface SplitAtPointCaretNextOptions { export function $splitAtPointCaretNext( pointCaret: PointCaret<'next'>, { - $copyElementNode, + $copyElementNode = $copyNode, + $splitTextPointCaretNext = $splitTextPointCaret, rootMode = 'shadowRoot', - allowEmptyLeftSplit = false, - allowEmptyRightSplit = false, - }: SplitAtPointCaretNextOptions, + $shouldSplit = $alwaysSplit, + }: SplitAtPointCaretNextOptions = {}, ): null | NodeCaret<'next'> { if ($isTextPointCaret(pointCaret)) { - if ( - pointCaret.offset === $getTextNodeOffset(pointCaret.origin, 'previous') - ) { - return $rewindSiblingCaret(pointCaret.getSiblingCaret()); - } - const origin = $isExtendableTextPointCaret(pointCaret) - ? pointCaret.origin.splitText(pointCaret.offset)[0] - : pointCaret.origin; - invariant( - $isTextNode(origin), - '$splitTextAtPointCaretNext: splitText must return at least one TextNode', - ); - return $getSiblingCaret(origin, 'next'); + return $splitTextPointCaretNext(pointCaret); } const parentCaret = pointCaret.getParentCaret(rootMode); if (parentCaret) { + const {origin} = parentCaret; if ( $isChildCaret(pointCaret) && - !(allowEmptyLeftSplit && parentCaret.origin.canBeEmpty()) + !(origin.canBeEmpty() && $shouldSplit(origin, 'first')) ) { // No split necessary, the left side would be empty return $rewindSiblingCaret(parentCaret); @@ -693,12 +710,10 @@ export function $splitAtPointCaretNext( const siblings = $getAdjacentNodes(pointCaret); if ( siblings.length > 0 || - (allowEmptyRightSplit && parentCaret.origin.canBeEmpty()) + (origin.canBeEmpty() && $shouldSplit(origin, 'last')) ) { // Split and insert the siblings into the new tree - parentCaret.insert( - $copyElementNode(parentCaret.origin).splice(0, 0, siblings), - ); + parentCaret.insert($copyElementNode(origin).splice(0, 0, siblings)); } } return parentCaret; From edeb0d31710ebdf147f1649a00bbf8b9cfe83ef6 Mon Sep 17 00:00:00 2001 From: Bob Ippolito <bob@redivi.com> Date: Mon, 17 Mar 2025 09:33:41 -0700 Subject: [PATCH 03/10] e2e test --- .../__tests__/e2e/HorizontalRule.spec.mjs | 146 +++++++++++++++++- 1 file changed, 143 insertions(+), 3 deletions(-) diff --git a/packages/lexical-playground/__tests__/e2e/HorizontalRule.spec.mjs b/packages/lexical-playground/__tests__/e2e/HorizontalRule.spec.mjs index 545d5575bd3..070580d9cb0 100644 --- a/packages/lexical-playground/__tests__/e2e/HorizontalRule.spec.mjs +++ b/packages/lexical-playground/__tests__/e2e/HorizontalRule.spec.mjs @@ -15,6 +15,7 @@ import { import { assertHTML, assertSelection, + click, copyToClipboard, focusEditor, html, @@ -26,6 +27,11 @@ import { withExclusiveClipboardAccess, } from '../utils/index.mjs'; +async function toggleBulletList(page) { + await click(page, '.block-controls'); + await click(page, '.dropdown .icon.bullet-list'); +} + test.describe('HorizontalRule', () => { test.beforeEach(({isCollab, page}) => initialize({isCollab, page})); test( @@ -209,7 +215,7 @@ test.describe('HorizontalRule', () => { }); }); - test('Will add a horizontal rule and split a TextNode across 2 paragraphs if the carat is in the middle of the TextNode, moving selection to the start of the new ParagraphNode.', async ({ + test('Will add a horizontal rule and split a TextNode across 2 paragraphs if the caret is in the middle of the TextNode, moving selection to the start of the new ParagraphNode.', async ({ page, isPlainText, }) => { @@ -245,7 +251,6 @@ test.describe('HorizontalRule', () => { focusPath: [0, 0, 0], }); - await page.pause(); await selectFromInsertDropdown(page, '.horizontal-rule'); await waitForSelector(page, 'hr'); @@ -270,7 +275,6 @@ test.describe('HorizontalRule', () => { `, ); - await page.pause(); await assertSelection(page, { anchorOffset: 0, anchorPath: [2, 0, 0], @@ -279,6 +283,142 @@ test.describe('HorizontalRule', () => { }); }); + test('Will add a horizontal rule and split a TextNode across 2 ListItemNode if the caret is in the middle of the TextNode, moving selection to the start of the new ParagraphNode', async ({ + page, + isPlainText, + }) => { + test.skip(isPlainText); + await focusEditor(page); + await toggleBulletList(page); + + await page.keyboard.type('Test'); + + await assertSelection(page, { + anchorOffset: 4, + anchorPath: [0, 0, 0, 0], + focusOffset: 4, + focusPath: [0, 0, 0, 0], + }); + + await assertHTML( + page, + html` + <ul class="PlaygroundEditorTheme__ul"> + <li + class="PlaygroundEditorTheme__listItem PlaygroundEditorTheme__ltr" + dir="ltr" + value="1"> + <span data-lexical-text="true">Test</span> + </li> + </ul> + `, + ); + + await moveLeft(page, 2); + + await assertSelection(page, { + anchorOffset: 2, + anchorPath: [0, 0, 0, 0], + focusOffset: 2, + focusPath: [0, 0, 0, 0], + }); + + await selectFromInsertDropdown(page, '.horizontal-rule'); + + await waitForSelector(page, 'hr'); + + await assertHTML( + page, + html` + <ul class="PlaygroundEditorTheme__ul"> + <li + class="PlaygroundEditorTheme__listItem PlaygroundEditorTheme__ltr" + dir="ltr" + value="1"> + <span data-lexical-text="true">Te</span> + </li> + </ul> + <hr + class="PlaygroundEditorTheme__hr" + contenteditable="false" + data-lexical-decorator="true" /> + <ul class="PlaygroundEditorTheme__ul"> + <li + class="PlaygroundEditorTheme__listItem PlaygroundEditorTheme__ltr" + dir="ltr" + value="1"> + <span data-lexical-text="true">st</span> + </li> + </ul> + `, + ); + + await assertSelection(page, { + anchorOffset: 0, + anchorPath: [2, 0, 0, 0], + focusOffset: 0, + focusPath: [2, 0, 0, 0], + }); + }); + + test('Will add a horizontal rule and split a TextNode across 2 ListItemNode if the caret is in an empty ListItemNode, moving selection to the start of the new ListItemNode (#6849)', async ({ + page, + isPlainText, + }) => { + test.skip(isPlainText); + await focusEditor(page); + await toggleBulletList(page); + + await assertSelection(page, { + anchorOffset: 0, + anchorPath: [0, 0], + focusOffset: 0, + focusPath: [0, 0], + }); + + await assertHTML( + page, + html` + <ul class="PlaygroundEditorTheme__ul"> + <li class="PlaygroundEditorTheme__listItem" value="1"> + <br /> + </li> + </ul> + `, + ); + + await selectFromInsertDropdown(page, '.horizontal-rule'); + + await waitForSelector(page, 'hr'); + + await assertHTML( + page, + html` + <ul class="PlaygroundEditorTheme__ul"> + <li class="PlaygroundEditorTheme__listItem" value="1"> + <br /> + </li> + </ul> + <hr + class="PlaygroundEditorTheme__hr" + contenteditable="false" + data-lexical-decorator="true" /> + <ul class="PlaygroundEditorTheme__ul"> + <li class="PlaygroundEditorTheme__listItem" value="1"> + <br /> + </li> + </ul> + `, + ); + + await assertSelection(page, { + anchorOffset: 0, + anchorPath: [2, 0], + focusOffset: 0, + focusPath: [2, 0], + }); + }); + test('Can copy and paste a horizontal rule', async ({page, isPlainText}) => { test.skip(isPlainText); From 3e60e64af629bf1ebff247eb8a53db3f77a326cb Mon Sep 17 00:00:00 2001 From: Bob Ippolito <bob@redivi.com> Date: Mon, 17 Mar 2025 09:39:16 -0700 Subject: [PATCH 04/10] trigger vercel re-deploy From 5bea1a6e957ee00bfef2737fa6d0ddfc623edccc Mon Sep 17 00:00:00 2001 From: Bob Ippolito <bob@redivi.com> Date: Mon, 17 Mar 2025 09:53:52 -0700 Subject: [PATCH 05/10] unit tests for $splitAtPointCaretNext --- .../caret/__tests__/unit/LexicalCaret.test.ts | 64 +++++++++++++++++++ 1 file changed, 64 insertions(+) diff --git a/packages/lexical/src/caret/__tests__/unit/LexicalCaret.test.ts b/packages/lexical/src/caret/__tests__/unit/LexicalCaret.test.ts index 84e357baa1a..40886b1533c 100644 --- a/packages/lexical/src/caret/__tests__/unit/LexicalCaret.test.ts +++ b/packages/lexical/src/caret/__tests__/unit/LexicalCaret.test.ts @@ -31,6 +31,7 @@ import { $getSelection, $getSiblingCaret, $getTextPointCaret, + $isParagraphNode, $isSiblingCaret, $isTextNode, $isTextPointCaret, @@ -41,6 +42,7 @@ import { $setPointFromCaret, $setSelection, $setSelectionFromCaretRange, + $splitAtPointCaretNext, ChildCaret, ElementNode, LexicalNode, @@ -1947,3 +1949,65 @@ describe('LexicalSelectionHelpers', () => { }); }); }); + +describe('$splitAtPointCaretNext', () => { + initializeUnitTest((testEnv) => { + test('Does not split a TextNode at the beginning', () => { + testEnv.editor.update( + () => { + const textNode = $createTextNode('test'); + const paragraphNode = $createParagraphNode(); + $getRoot().clear().append(paragraphNode.append(textNode)); + const caret = $getTextPointCaret(textNode, 'next', 0); + const after = $splitAtPointCaretNext(caret); + expect(textNode.getTextContent()).toEqual('test'); + expect( + $getChildCaret(paragraphNode, 'next').isSamePointCaret(after), + ).toBe(true); + }, + {discrete: true}, + ); + }); + test('Splits a TextNode in the middle', () => { + testEnv.editor.update( + () => { + const textNode = $createTextNode('test'); + const paragraphNode = $createParagraphNode(); + $getRoot().clear().append(paragraphNode.append(textNode)); + const caret = $getTextPointCaret(textNode, 'next', 2); + const after = $splitAtPointCaretNext(caret); + expect(textNode.getTextContent()).toEqual('te'); + const nextCaret = $getSiblingCaret(textNode, 'next'); + expect(nextCaret.isSamePointCaret(after)).toBe(true); + const splitNode = nextCaret.getNodeAtCaret(); + expect( + $isTextNode(splitNode) ? splitNode.getTextContent() : null, + ).toEqual('st'); + }, + {discrete: true}, + ); + }); + test('Splits a ParagraphNode', () => { + testEnv.editor.update( + () => { + const beforeTextNode = $createTextNode('before'); + const afterTextNode = $createTextNode('after'); + const paragraphNode = $createParagraphNode(); + $getRoot() + .clear() + .append(paragraphNode.append(beforeTextNode, afterTextNode)); + const caret = $getSiblingCaret(beforeTextNode, 'next'); + const after = $splitAtPointCaretNext(caret); + expect(paragraphNode.getAllTextNodes()).toEqual([beforeTextNode]); + const nextCaret = $getSiblingCaret(paragraphNode, 'next'); + expect(nextCaret.isSamePointCaret(after)).toBe(true); + const splitNode = nextCaret.getNodeAtCaret(); + expect( + $isParagraphNode(splitNode) ? splitNode.getAllTextNodes() : null, + ).toEqual([afterTextNode]); + }, + {discrete: true}, + ); + }); + }); +}); From f13380c9918c2950c1dcd0f7060b13c4229e8061 Mon Sep 17 00:00:00 2001 From: Bob Ippolito <bob@redivi.com> Date: Mon, 17 Mar 2025 11:43:54 -0700 Subject: [PATCH 06/10] update prettier --- .eslintignore | 1 + .prettierignore | 1 + package-lock.json | 157 +++++++++--------- package.json | 8 +- .../__tests__/unit/rules-of-lexical.test.ts | 4 +- packages/lexical-list/src/__tests__/utils.ts | 4 +- .../__tests__/utils/index.mjs | 2 +- packages/lexical-playground/package.json | 2 +- packages/lexical-website/package.json | 2 +- .../lexical/src/__tests__/utils/index.tsx | 6 +- .../unit/transform-error-messages.test.js | 14 +- .../error-codes/transform-error-messages.js | 6 +- 12 files changed, 110 insertions(+), 97 deletions(-) diff --git a/.eslintignore b/.eslintignore index 568a2cf9313..5b987a70346 100644 --- a/.eslintignore +++ b/.eslintignore @@ -13,3 +13,4 @@ **/.docusaurus /playwright-report test-results +/libdefs/*.js diff --git a/.prettierignore b/.prettierignore index 580080b429f..0e75361aeac 100644 --- a/.prettierignore +++ b/.prettierignore @@ -23,3 +23,4 @@ flow-typed **/.docusaurus /playwright-report test-results +/libdefs/*.js diff --git a/package-lock.json b/package-lock.json index 2593e2c90b8..80fc0981e68 100644 --- a/package-lock.json +++ b/package-lock.json @@ -12,6 +12,7 @@ "packages/*" ], "dependencies": { + "@prettier/sync": "^0.5.2", "yjs": "^13.5.42" }, "devDependencies": { @@ -35,7 +36,6 @@ "@types/jsdom": "^21.1.6", "@types/katex": "^0.16.7", "@types/node": "^17.0.31", - "@types/prettier": "^2.7.3", "@types/prismjs": "^1.26.0", "@types/proper-lockfile": "^4.1.4", "@types/react": "^18.0.8", @@ -79,10 +79,10 @@ "lint-staged": "^11.1.0", "minimist": "^1.2.5", "npm-run-all": "^4.1.5", - "prettier": "^2.3.2", + "prettier": "^3.5.3", "prettier-plugin-hermes-parser": "^0.26.0", - "prettier-plugin-organize-attributes": "^0.0.5", - "prettier-plugin-tailwindcss": "^0.4.1", + "prettier-plugin-organize-attributes": "^1.0.0", + "prettier-plugin-tailwindcss": "^0.6.11", "proper-lockfile": "^4.1.2", "react-test-renderer": "^17.0.2", "rollup": "^4.22.4", @@ -7786,6 +7786,20 @@ "url": "https://opencollective.com/popperjs" } }, + "node_modules/@prettier/sync": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/@prettier/sync/-/sync-0.5.2.tgz", + "integrity": "sha512-Yb569su456XNx5BsH/Vyem7xD6g/y9iLmLUzRKM1a/dhU/D7HqqvkAG72znulXlMXztbV0iiu9O5AL8K98TzZQ==", + "dependencies": { + "make-synchronized": "^0.2.8" + }, + "funding": { + "url": "https://github.com/prettier/prettier-synchronized?sponsor=1" + }, + "peerDependencies": { + "prettier": "*" + } + }, "node_modules/@radix-ui/primitive": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/@radix-ui/primitive/-/primitive-1.0.1.tgz", @@ -10058,12 +10072,6 @@ "resolved": "https://registry.npmjs.org/@types/parse5/-/parse5-5.0.3.tgz", "integrity": "sha512-kUNnecmtkunAoQ3CnjmMkzNU/gtxG8guhi+Fk2U/kOpIKjIMKnXGp4IJCgQJrXSgMsWYimYG4TGjz/UzbGEBTw==" }, - "node_modules/@types/prettier": { - "version": "2.7.3", - "resolved": "https://registry.npmjs.org/@types/prettier/-/prettier-2.7.3.tgz", - "integrity": "sha512-+68kP9yzs4LMp7VNh8gdzMSPZFL44MLGqiHWvttYJe+6qnuVr4Ek9wSBQoveqY/r+LwjCcU29kNVkidwim+kYA==", - "dev": true - }, "node_modules/@types/prismjs": { "version": "1.26.0", "resolved": "https://registry.npmjs.org/@types/prismjs/-/prismjs-1.26.0.tgz", @@ -25692,6 +25700,14 @@ "integrity": "sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==", "dev": true }, + "node_modules/make-synchronized": { + "version": "0.2.9", + "resolved": "https://registry.npmjs.org/make-synchronized/-/make-synchronized-0.2.9.tgz", + "integrity": "sha512-4wczOs8SLuEdpEvp3vGo83wh8rjJ78UsIk7DIX5fxdfmfMJGog4bQzxfvOwq7Q3yCHLC4jp1urPHIxRS/A93gA==", + "funding": { + "url": "https://github.com/fisker/make-synchronized?sponsor=1" + } + }, "node_modules/makeerror": { "version": "1.0.12", "resolved": "https://registry.npmjs.org/makeerror/-/makeerror-1.0.12.tgz", @@ -32021,15 +32037,14 @@ } }, "node_modules/prettier": { - "version": "2.7.1", - "resolved": "https://registry.npmjs.org/prettier/-/prettier-2.7.1.tgz", - "integrity": "sha512-ujppO+MkdPqoVINuDFDRLClm7D78qbDt0/NR+wp5FqEZOoTNAjPHWj17QRhu7geIHJfcNhRk1XVQmF8Bp3ye+g==", - "dev": true, + "version": "3.5.3", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.5.3.tgz", + "integrity": "sha512-QQtaxnoDJeAkDvDKWCLiwIXkTgRhwYDEQCghU9Z6q03iyek/rxRh/2lC3HB7P8sWT2xC/y5JDctPLBIGzHKbhw==", "bin": { - "prettier": "bin-prettier.js" + "prettier": "bin/prettier.cjs" }, "engines": { - "node": ">=10.13.0" + "node": ">=14" }, "funding": { "url": "https://github.com/prettier/prettier?sponsor=1" @@ -32050,42 +32065,43 @@ } }, "node_modules/prettier-plugin-organize-attributes": { - "version": "0.0.5", - "resolved": "https://registry.npmjs.org/prettier-plugin-organize-attributes/-/prettier-plugin-organize-attributes-0.0.5.tgz", - "integrity": "sha512-dSts16q8wd+oq8Zwk5mwmYXo1aN3B+ZkEJqx/ar5fedNHdOvx7S4XDMH/pNK7rmBW0bPXkp/kJX5gAANsWzh3A==", + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/prettier-plugin-organize-attributes/-/prettier-plugin-organize-attributes-1.0.0.tgz", + "integrity": "sha512-+NmameaLxbCcylEXsKPmawtzla5EE6ECqvGkpfQz4KM847fXDifB1gFnPQEpoADAq6IXg+cMI8Z0ISJEXa6fhg==", "dev": true, "engines": { - "node": ">=11.0.0" + "node": ">=14.0.0" }, "peerDependencies": { - "prettier": "^2.0.0" + "prettier": "^3.0.0" } }, "node_modules/prettier-plugin-tailwindcss": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/prettier-plugin-tailwindcss/-/prettier-plugin-tailwindcss-0.4.1.tgz", - "integrity": "sha512-hwn2EiJmv8M+AW4YDkbjJ6HlZCTzLyz1QlySn9sMuKV/Px0fjwldlB7tol8GzdgqtkdPtzT3iJ4UzdnYXP25Ag==", + "version": "0.6.11", + "resolved": "https://registry.npmjs.org/prettier-plugin-tailwindcss/-/prettier-plugin-tailwindcss-0.6.11.tgz", + "integrity": "sha512-YxaYSIvZPAqhrrEpRtonnrXdghZg1irNg4qrjboCXrpybLWVs55cW2N3juhspVJiO0JBvYJT8SYsJpc8OQSnsA==", "dev": true, "engines": { - "node": ">=12.17.0" + "node": ">=14.21.3" }, "peerDependencies": { "@ianvs/prettier-plugin-sort-imports": "*", "@prettier/plugin-pug": "*", "@shopify/prettier-plugin-liquid": "*", - "@shufo/prettier-plugin-blade": "*", "@trivago/prettier-plugin-sort-imports": "*", - "prettier": "^2.2 || ^3.0", + "@zackad/prettier-plugin-twig": "*", + "prettier": "^3.0", "prettier-plugin-astro": "*", "prettier-plugin-css-order": "*", "prettier-plugin-import-sort": "*", "prettier-plugin-jsdoc": "*", "prettier-plugin-marko": "*", + "prettier-plugin-multiline-arrays": "*", "prettier-plugin-organize-attributes": "*", "prettier-plugin-organize-imports": "*", + "prettier-plugin-sort-imports": "*", "prettier-plugin-style-order": "*", - "prettier-plugin-svelte": "*", - "prettier-plugin-twig-melody": "*" + "prettier-plugin-svelte": "*" }, "peerDependenciesMeta": { "@ianvs/prettier-plugin-sort-imports": { @@ -32097,10 +32113,10 @@ "@shopify/prettier-plugin-liquid": { "optional": true }, - "@shufo/prettier-plugin-blade": { + "@trivago/prettier-plugin-sort-imports": { "optional": true }, - "@trivago/prettier-plugin-sort-imports": { + "@zackad/prettier-plugin-twig": { "optional": true }, "prettier-plugin-astro": { @@ -32118,19 +32134,22 @@ "prettier-plugin-marko": { "optional": true }, + "prettier-plugin-multiline-arrays": { + "optional": true + }, "prettier-plugin-organize-attributes": { "optional": true }, "prettier-plugin-organize-imports": { "optional": true }, - "prettier-plugin-style-order": { + "prettier-plugin-sort-imports": { "optional": true }, - "prettier-plugin-svelte": { + "prettier-plugin-style-order": { "optional": true }, - "prettier-plugin-twig-melody": { + "prettier-plugin-svelte": { "optional": true } } @@ -40225,6 +40244,7 @@ "version": "0.27.2", "license": "MIT", "dependencies": { + "@lexical/selection": "0.27.2", "@lexical/utils": "0.27.2", "lexical": "0.27.2" } @@ -40300,7 +40320,7 @@ "katex": "^0.16.10", "lexical": "0.27.2", "lodash-es": "^4.17.21", - "prettier": "^3.4.2", + "prettier": "^3.5.3", "react": "^18.2.0", "react-dom": "^18.2.0", "react-error-boundary": "^3.1.4", @@ -40319,21 +40339,6 @@ "vite-plugin-static-copy": "^2.1.0" } }, - "packages/lexical-playground/node_modules/prettier": { - "version": "3.4.2", - "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.4.2.tgz", - "integrity": "sha512-e9MewbtFo+Fevyuxn/4rrcDAaq0IYxPGLvObpQjiZBMAzB9IGmzlnG9RZy3FFas+eBMu2vA0CszMeduow5dIuQ==", - "license": "MIT", - "bin": { - "prettier": "bin/prettier.cjs" - }, - "engines": { - "node": ">=14" - }, - "funding": { - "url": "https://github.com/prettier/prettier?sponsor=1" - } - }, "packages/lexical-react": { "name": "@lexical/react", "version": "0.27.2", @@ -40434,7 +40439,7 @@ }, "devDependencies": { "buffer": "^6.0.3", - "prettier-plugin-tailwindcss": "^0.4.1", + "prettier-plugin-tailwindcss": "^0.6.11", "tailwindcss": "^3.3.3", "typedoc": "^0.25.12", "typescript": "^5.4.5", @@ -45274,6 +45279,7 @@ "@lexical/list": { "version": "file:packages/lexical-list", "requires": { + "@lexical/selection": "0.27.2", "@lexical/utils": "0.27.2", "lexical": "0.27.2" } @@ -45393,7 +45399,7 @@ "docusaurus-plugin-internaldocs-fb": "1.19.0", "docusaurus-plugin-typedoc": "^0.22.0", "fs-extra": "^10.0.0", - "prettier-plugin-tailwindcss": "^0.4.1", + "prettier-plugin-tailwindcss": "^0.6.11", "prism-react-renderer": "^2.3.1", "react": "^18.2.0", "react-dom": "^18.2.0", @@ -45581,6 +45587,14 @@ "resolved": "https://registry.npmjs.org/@popperjs/core/-/core-2.11.8.tgz", "integrity": "sha512-P1st0aksCrn9sGZhp8GMYwBnQsbvAWsZAX44oXNNvLHGqAOcoVxmjZiohstwQ7SqKnbR47akdNi+uleWD8+g6A==" }, + "@prettier/sync": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/@prettier/sync/-/sync-0.5.2.tgz", + "integrity": "sha512-Yb569su456XNx5BsH/Vyem7xD6g/y9iLmLUzRKM1a/dhU/D7HqqvkAG72znulXlMXztbV0iiu9O5AL8K98TzZQ==", + "requires": { + "make-synchronized": "^0.2.8" + } + }, "@radix-ui/primitive": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/@radix-ui/primitive/-/primitive-1.0.1.tgz", @@ -46960,12 +46974,6 @@ "resolved": "https://registry.npmjs.org/@types/parse5/-/parse5-5.0.3.tgz", "integrity": "sha512-kUNnecmtkunAoQ3CnjmMkzNU/gtxG8guhi+Fk2U/kOpIKjIMKnXGp4IJCgQJrXSgMsWYimYG4TGjz/UzbGEBTw==" }, - "@types/prettier": { - "version": "2.7.3", - "resolved": "https://registry.npmjs.org/@types/prettier/-/prettier-2.7.3.tgz", - "integrity": "sha512-+68kP9yzs4LMp7VNh8gdzMSPZFL44MLGqiHWvttYJe+6qnuVr4Ek9wSBQoveqY/r+LwjCcU29kNVkidwim+kYA==", - "dev": true - }, "@types/prismjs": { "version": "1.26.0", "resolved": "https://registry.npmjs.org/@types/prismjs/-/prismjs-1.26.0.tgz", @@ -57313,7 +57321,7 @@ "katex": "^0.16.10", "lexical": "0.27.2", "lodash-es": "^4.17.21", - "prettier": "^3.4.2", + "prettier": "^3.5.3", "react": "^18.2.0", "react-dom": "^18.2.0", "react-error-boundary": "^3.1.4", @@ -57322,13 +57330,6 @@ "vite-plugin-static-copy": "^2.1.0", "y-websocket": "^1.5.4", "yjs": ">=13.5.42" - }, - "dependencies": { - "prettier": { - "version": "3.4.2", - "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.4.2.tgz", - "integrity": "sha512-e9MewbtFo+Fevyuxn/4rrcDAaq0IYxPGLvObpQjiZBMAzB9IGmzlnG9RZy3FFas+eBMu2vA0CszMeduow5dIuQ==" - } } }, "lib0": { @@ -57844,6 +57845,11 @@ "integrity": "sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==", "dev": true }, + "make-synchronized": { + "version": "0.2.9", + "resolved": "https://registry.npmjs.org/make-synchronized/-/make-synchronized-0.2.9.tgz", + "integrity": "sha512-4wczOs8SLuEdpEvp3vGo83wh8rjJ78UsIk7DIX5fxdfmfMJGog4bQzxfvOwq7Q3yCHLC4jp1urPHIxRS/A93gA==" + }, "makeerror": { "version": "1.0.12", "resolved": "https://registry.npmjs.org/makeerror/-/makeerror-1.0.12.tgz", @@ -61547,10 +61553,9 @@ "dev": true }, "prettier": { - "version": "2.7.1", - "resolved": "https://registry.npmjs.org/prettier/-/prettier-2.7.1.tgz", - "integrity": "sha512-ujppO+MkdPqoVINuDFDRLClm7D78qbDt0/NR+wp5FqEZOoTNAjPHWj17QRhu7geIHJfcNhRk1XVQmF8Bp3ye+g==", - "dev": true + "version": "3.5.3", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.5.3.tgz", + "integrity": "sha512-QQtaxnoDJeAkDvDKWCLiwIXkTgRhwYDEQCghU9Z6q03iyek/rxRh/2lC3HB7P8sWT2xC/y5JDctPLBIGzHKbhw==" }, "prettier-plugin-hermes-parser": { "version": "0.26.0", @@ -61564,15 +61569,15 @@ } }, "prettier-plugin-organize-attributes": { - "version": "0.0.5", - "resolved": "https://registry.npmjs.org/prettier-plugin-organize-attributes/-/prettier-plugin-organize-attributes-0.0.5.tgz", - "integrity": "sha512-dSts16q8wd+oq8Zwk5mwmYXo1aN3B+ZkEJqx/ar5fedNHdOvx7S4XDMH/pNK7rmBW0bPXkp/kJX5gAANsWzh3A==", + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/prettier-plugin-organize-attributes/-/prettier-plugin-organize-attributes-1.0.0.tgz", + "integrity": "sha512-+NmameaLxbCcylEXsKPmawtzla5EE6ECqvGkpfQz4KM847fXDifB1gFnPQEpoADAq6IXg+cMI8Z0ISJEXa6fhg==", "dev": true }, "prettier-plugin-tailwindcss": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/prettier-plugin-tailwindcss/-/prettier-plugin-tailwindcss-0.4.1.tgz", - "integrity": "sha512-hwn2EiJmv8M+AW4YDkbjJ6HlZCTzLyz1QlySn9sMuKV/Px0fjwldlB7tol8GzdgqtkdPtzT3iJ4UzdnYXP25Ag==", + "version": "0.6.11", + "resolved": "https://registry.npmjs.org/prettier-plugin-tailwindcss/-/prettier-plugin-tailwindcss-0.6.11.tgz", + "integrity": "sha512-YxaYSIvZPAqhrrEpRtonnrXdghZg1irNg4qrjboCXrpybLWVs55cW2N3juhspVJiO0JBvYJT8SYsJpc8OQSnsA==", "dev": true }, "pretty-error": { diff --git a/package.json b/package.json index 20e3d93c8d3..cd177852564 100644 --- a/package.json +++ b/package.json @@ -130,7 +130,6 @@ "@types/jsdom": "^21.1.6", "@types/katex": "^0.16.7", "@types/node": "^17.0.31", - "@types/prettier": "^2.7.3", "@types/prismjs": "^1.26.0", "@types/proper-lockfile": "^4.1.4", "@types/react": "^18.0.8", @@ -174,10 +173,10 @@ "lint-staged": "^11.1.0", "minimist": "^1.2.5", "npm-run-all": "^4.1.5", - "prettier": "^2.3.2", + "prettier": "^3.5.3", "prettier-plugin-hermes-parser": "^0.26.0", - "prettier-plugin-organize-attributes": "^0.0.5", - "prettier-plugin-tailwindcss": "^0.4.1", + "prettier-plugin-organize-attributes": "^1.0.0", + "prettier-plugin-tailwindcss": "^0.6.11", "proper-lockfile": "^4.1.2", "react-test-renderer": "^17.0.2", "rollup": "^4.22.4", @@ -190,6 +189,7 @@ "vite": "^5.2.11" }, "dependencies": { + "@prettier/sync": "^0.5.2", "yjs": "^13.5.42" } } diff --git a/packages/lexical-eslint-plugin/src/__tests__/unit/rules-of-lexical.test.ts b/packages/lexical-eslint-plugin/src/__tests__/unit/rules-of-lexical.test.ts index 5845696dc83..bebee3e8a58 100644 --- a/packages/lexical-eslint-plugin/src/__tests__/unit/rules-of-lexical.test.ts +++ b/packages/lexical-eslint-plugin/src/__tests__/unit/rules-of-lexical.test.ts @@ -6,10 +6,10 @@ * */ +import * as prettierSync from '@prettier/sync'; import {RuleTester} from 'eslint'; import * as fs from 'node:fs'; import * as path from 'node:path'; -import * as prettier from 'prettier'; import plugin from '../../LexicalEslintPlugin.js'; import {type RulesOfLexicalOptions} from '../../rules/rules-of-lexical.js'; @@ -39,7 +39,7 @@ function fmt( keys.forEach((key, i) => { result.push(key(name), strings[i + 1]); }); - return prettier.format(result.join(''), {parser: 'typescript'}); + return prettierSync.format(result.join(''), {parser: 'typescript'}); }; rval.keys = keys; rval.setOptions = (opts: RulesOfLexicalOptions) => { diff --git a/packages/lexical-list/src/__tests__/utils.ts b/packages/lexical-list/src/__tests__/utils.ts index aa95a7a01b0..13b75de4338 100644 --- a/packages/lexical-list/src/__tests__/utils.ts +++ b/packages/lexical-list/src/__tests__/utils.ts @@ -6,7 +6,7 @@ * */ import {expect} from '@playwright/test'; -import prettier from 'prettier'; +import * as prettierSync from '@prettier/sync'; // This tag function is just used to trigger prettier auto-formatting. // (https://prettier.io/blog/2020/08/24/2.1.0.html#api) @@ -29,5 +29,5 @@ export function expectHtmlToBeEqual(expected: string, actual: string): void { } export function prettifyHtml(s: string): string { - return prettier.format(s.replace(/\n/g, ''), {parser: 'html'}); + return prettierSync.format(s.replace(/\n/g, ''), {parser: 'html'}); } diff --git a/packages/lexical-playground/__tests__/utils/index.mjs b/packages/lexical-playground/__tests__/utils/index.mjs index deb209bfda9..ad4d9052a30 100644 --- a/packages/lexical-playground/__tests__/utils/index.mjs +++ b/packages/lexical-playground/__tests__/utils/index.mjs @@ -9,7 +9,7 @@ import {expect, test as base} from '@playwright/test'; import * as glob from 'glob'; import {randomUUID} from 'node:crypto'; -import prettier from 'prettier'; +import * as prettier from 'prettier'; import * as lockfile from 'proper-lockfile'; import {URLSearchParams} from 'url'; diff --git a/packages/lexical-playground/package.json b/packages/lexical-playground/package.json index 34e991c45c8..609947f4bd9 100644 --- a/packages/lexical-playground/package.json +++ b/packages/lexical-playground/package.json @@ -29,7 +29,7 @@ "katex": "^0.16.10", "lexical": "0.27.2", "lodash-es": "^4.17.21", - "prettier": "^3.4.2", + "prettier": "^3.5.3", "react": "^18.2.0", "react-dom": "^18.2.0", "react-error-boundary": "^3.1.4", diff --git a/packages/lexical-website/package.json b/packages/lexical-website/package.json index 54294b27479..3145e16ceb7 100644 --- a/packages/lexical-website/package.json +++ b/packages/lexical-website/package.json @@ -34,7 +34,7 @@ }, "devDependencies": { "buffer": "^6.0.3", - "prettier-plugin-tailwindcss": "^0.4.1", + "prettier-plugin-tailwindcss": "^0.6.11", "tailwindcss": "^3.3.3", "typedoc": "^0.25.12", "typescript": "^5.4.5", diff --git a/packages/lexical/src/__tests__/utils/index.tsx b/packages/lexical/src/__tests__/utils/index.tsx index 3eeecec272d..31204e47258 100644 --- a/packages/lexical/src/__tests__/utils/index.tsx +++ b/packages/lexical/src/__tests__/utils/index.tsx @@ -26,6 +26,7 @@ import { import {HeadingNode, QuoteNode} from '@lexical/rich-text'; import {TableCellNode, TableNode, TableRowNode} from '@lexical/table'; import {expect} from '@playwright/test'; +import * as prettierSync from '@prettier/sync'; import { $isRangeSelection, createEditor, @@ -45,7 +46,6 @@ import { TextNode, } from 'lexical'; import path from 'path'; -import * as prettier from 'prettier'; import * as React from 'react'; import {createRef} from 'react'; import {createRoot} from 'react-dom/client'; @@ -58,7 +58,7 @@ import { } from '../../LexicalEditor'; import {resetRandomKey} from '../../LexicalUtils'; -const prettierConfig = prettier.resolveConfig.sync( +const prettierConfig = prettierSync.resolveConfig( path.resolve(__dirname, '../../../../.prettierrc'), ); @@ -784,7 +784,7 @@ export function expectHtmlToBeEqual(actual: string, expected: string): void { } export function prettifyHtml(s: string): string { - return prettier.format(s.replace(/\n/g, ''), { + return prettierSync.format(s.replace(/\n/g, ''), { ...prettierConfig, parser: 'html', }); diff --git a/scripts/error-codes/__tests__/unit/transform-error-messages.test.js b/scripts/error-codes/__tests__/unit/transform-error-messages.test.js index 20f51881876..6e2d1b30147 100644 --- a/scripts/error-codes/__tests__/unit/transform-error-messages.test.js +++ b/scripts/error-codes/__tests__/unit/transform-error-messages.test.js @@ -12,9 +12,9 @@ const fs = require('fs-extra'); const path = require('node:path'); const transformErrorMessages = require('../../transform-error-messages'); const babel = require('@babel/core'); -const prettier = require('prettier'); +const prettierSync = require('@prettier/sync'); -const prettierConfig = prettier.resolveConfig.sync('./') || {}; +const prettierConfig = prettierSync.resolveConfig('./') || {}; /** @returns {Promise<void>} */ function waitTick() { @@ -39,7 +39,13 @@ async function withCodes(before, after, cb) { } } -function fmt(strings: TemplateStringsArray, ...keys: unknown[]) { +/** + * + * @param {TemplateStringsArray} strings + * @param {...unknown} keys + * @returns + */ +function fmt(strings, ...keys) { const result = [strings[0]]; keys.forEach((key, i) => { result.push(String(key), strings[i + 1]); @@ -59,7 +65,7 @@ function fmt(strings: TemplateStringsArray, ...keys: unknown[]) { 'format$1ErrorMessage', ) .trim(); - return prettier.format(before, { + return prettierSync.format(before, { ...prettierConfig, filepath: 'test.js', }); diff --git a/scripts/error-codes/transform-error-messages.js b/scripts/error-codes/transform-error-messages.js index 3ccfd24a957..cb9ea1a882a 100644 --- a/scripts/error-codes/transform-error-messages.js +++ b/scripts/error-codes/transform-error-messages.js @@ -13,7 +13,7 @@ const fs = require('fs-extra'); const ErrorMap = require('./ErrorMap'); const evalToString = require('./evalToString'); const helperModuleImports = require('@babel/helper-module-imports'); -const prettier = require('prettier'); +const prettierSync = require('@prettier/sync'); /** @type {Map<string, ErrorMap>} */ const errorMaps = new Map(); @@ -29,13 +29,13 @@ function getErrorMap(filepath) { let errorMap = errorMaps.get(filepath); if (!errorMap) { const prettierConfig = { - ...(prettier.resolveConfig.sync('./') || {}), + ...(prettierSync.resolveConfig('./') || {}), filepath, }; errorMap = new ErrorMap(fs.readJsonSync(filepath), (newErrorMap) => fs.writeFileSync( filepath, - prettier.format(JSON.stringify(newErrorMap), prettierConfig), + prettierSync.format(JSON.stringify(newErrorMap), prettierConfig), ), ); errorMaps.set(filepath, errorMap); From 108af6757559f924b57b8816b73433d6911fe7d0 Mon Sep 17 00:00:00 2001 From: Bob Ippolito <bob@redivi.com> Date: Mon, 17 Mar 2025 12:14:20 -0700 Subject: [PATCH 07/10] npm run prettier:fix --- examples/react-plain-text/index.html | 2 +- examples/react-plain-text/src/styles.css | 6 +- examples/react-rich-collab/app.html | 2 +- examples/react-rich-collab/index.html | 2 +- examples/react-rich-collab/src/styles.css | 6 +- examples/react-rich/index.html | 2 +- examples/react-rich/src/styles.css | 6 +- examples/react-table/index.html | 2 +- examples/react-table/src/styles.css | 6 +- examples/vanilla-js-iframe/index.html | 2 +- examples/vanilla-js-plugin/index.html | 2 +- examples/vanilla-js/index.html | 2 +- .../src/generateContent.ts | 8 +- .../Base.lproj/Main.html | 2 +- .../src/entrypoints/devtools-panel/index.html | 2 +- .../src/entrypoints/devtools/index.html | 2 +- .../src/entrypoints/popup/index.html | 2 +- packages/lexical-headless/src/index.ts | 2 +- .../lexical-list/src/LexicalListItemNode.ts | 4 +- .../src/MarkdownTransformers.ts | 4 +- .../html/ListsHTMLCopyAndPaste.spec.mjs | 5 +- .../__tests__/e2e/Extensions.spec.mjs | 112 +++++++----------- .../__tests__/e2e/Links.spec.mjs | 24 ++-- packages/lexical-playground/esm/index.html | 2 +- packages/lexical-playground/index.html | 2 +- packages/lexical-playground/split/index.html | 2 +- packages/lexical-playground/src/App.tsx | 4 +- packages/lexical-playground/src/Editor.tsx | 4 +- packages/lexical-playground/src/index.css | 10 +- .../src/plugins/TableCellResizer/index.tsx | 4 +- .../plugins/TableOfContentsPlugin/index.tsx | 3 +- .../src/plugins/ToolbarPlugin/index.tsx | 4 +- .../lexical-playground/src/ui/ColorPicker.css | 3 +- .../lexical-playground/src/ui/ColorPicker.tsx | 6 +- .../src/ui/ExcalidrawModal.css | 4 +- .../src/ui/ImageResizer.tsx | 4 +- .../lexical-selection/src/lexical-node.ts | 4 +- .../lexical-table/src/LexicalTableCellNode.ts | 2 +- packages/lexical-yjs/src/SyncCursors.ts | 5 +- packages/lexical/src/LexicalEditor.ts | 9 +- packages/lexical/src/LexicalNodeState.ts | 16 +-- packages/lexical/src/LexicalReconciler.ts | 4 +- packages/lexical/src/LexicalSelection.ts | 4 +- packages/lexical/src/LexicalUpdates.ts | 2 +- packages/lexical/src/LexicalUtils.ts | 4 +- .../__tests__/unit/LexicalNodeState.test.ts | 9 +- .../__tests__/unit/LexicalSelection.test.ts | 4 +- packages/lexical/src/caret/LexicalCaret.ts | 19 +-- .../caret/__tests__/unit/LexicalCaret.test.ts | 4 +- packages/shared/lexicalMonorepoPlugin.ts | 4 +- scripts/lint-flow-types.js | 4 +- 51 files changed, 173 insertions(+), 180 deletions(-) diff --git a/examples/react-plain-text/index.html b/examples/react-plain-text/index.html index ce9878e6d4a..58fb43978dd 100644 --- a/examples/react-plain-text/index.html +++ b/examples/react-plain-text/index.html @@ -1,4 +1,4 @@ -<!DOCTYPE html> +<!doctype html> <html lang="en"> <head> <meta charset="UTF-8" /> diff --git a/examples/react-plain-text/src/styles.css b/examples/react-plain-text/src/styles.css index bf79e1f4e71..b6046673eba 100644 --- a/examples/react-plain-text/src/styles.css +++ b/examples/react-plain-text/src/styles.css @@ -9,7 +9,11 @@ body { margin: 0; background: #eee; - font-family: system-ui, -apple-system, BlinkMacSystemFont, '.SFNSText-Regular', + font-family: + system-ui, + -apple-system, + BlinkMacSystemFont, + '.SFNSText-Regular', sans-serif; font-weight: 500; -webkit-font-smoothing: antialiased; diff --git a/examples/react-rich-collab/app.html b/examples/react-rich-collab/app.html index 8dbc32d5238..60a0fc531fe 100644 --- a/examples/react-rich-collab/app.html +++ b/examples/react-rich-collab/app.html @@ -1,4 +1,4 @@ -<!DOCTYPE html> +<!doctype html> <html lang="en"> <head> <meta charset="UTF-8" /> diff --git a/examples/react-rich-collab/index.html b/examples/react-rich-collab/index.html index 4096ec03812..62d6948c5b1 100644 --- a/examples/react-rich-collab/index.html +++ b/examples/react-rich-collab/index.html @@ -1,4 +1,4 @@ -<!DOCTYPE html> +<!doctype html> <html lang="en"> <head> <meta charset="UTF-8" /> diff --git a/examples/react-rich-collab/src/styles.css b/examples/react-rich-collab/src/styles.css index 79e45348998..2f55096faa3 100644 --- a/examples/react-rich-collab/src/styles.css +++ b/examples/react-rich-collab/src/styles.css @@ -10,7 +10,11 @@ body { margin: 0; font-size: 14px; background: #eee; - font-family: system-ui, -apple-system, BlinkMacSystemFont, '.SFNSText-Regular', + font-family: + system-ui, + -apple-system, + BlinkMacSystemFont, + '.SFNSText-Regular', sans-serif; font-weight: 500; -webkit-font-smoothing: antialiased; diff --git a/examples/react-rich/index.html b/examples/react-rich/index.html index 34bb34c5064..4c5c8f08d5a 100644 --- a/examples/react-rich/index.html +++ b/examples/react-rich/index.html @@ -1,4 +1,4 @@ -<!DOCTYPE html> +<!doctype html> <html lang="en"> <head> <meta charset="UTF-8" /> diff --git a/examples/react-rich/src/styles.css b/examples/react-rich/src/styles.css index 071a794fc76..3071e94a118 100644 --- a/examples/react-rich/src/styles.css +++ b/examples/react-rich/src/styles.css @@ -9,7 +9,11 @@ body { margin: 0; background: #eee; - font-family: system-ui, -apple-system, BlinkMacSystemFont, '.SFNSText-Regular', + font-family: + system-ui, + -apple-system, + BlinkMacSystemFont, + '.SFNSText-Regular', sans-serif; font-weight: 500; -webkit-font-smoothing: antialiased; diff --git a/examples/react-table/index.html b/examples/react-table/index.html index 8243eabc6b9..2f73f6bbf24 100644 --- a/examples/react-table/index.html +++ b/examples/react-table/index.html @@ -1,4 +1,4 @@ -<!DOCTYPE html> +<!doctype html> <html lang="en"> <head> <meta charset="UTF-8" /> diff --git a/examples/react-table/src/styles.css b/examples/react-table/src/styles.css index 32b80315539..a6dd01a6fd7 100644 --- a/examples/react-table/src/styles.css +++ b/examples/react-table/src/styles.css @@ -9,7 +9,11 @@ body { margin: 0; background: #eee; - font-family: system-ui, -apple-system, BlinkMacSystemFont, '.SFNSText-Regular', + font-family: + system-ui, + -apple-system, + BlinkMacSystemFont, + '.SFNSText-Regular', sans-serif; font-weight: 500; -webkit-font-smoothing: antialiased; diff --git a/examples/vanilla-js-iframe/index.html b/examples/vanilla-js-iframe/index.html index a730616c401..41e6c0c674a 100644 --- a/examples/vanilla-js-iframe/index.html +++ b/examples/vanilla-js-iframe/index.html @@ -1,4 +1,4 @@ -<!DOCTYPE html> +<!doctype html> <html lang="en"> <head> <meta charset="UTF-8" /> diff --git a/examples/vanilla-js-plugin/index.html b/examples/vanilla-js-plugin/index.html index ef397bcc4d1..8b639835237 100644 --- a/examples/vanilla-js-plugin/index.html +++ b/examples/vanilla-js-plugin/index.html @@ -1,4 +1,4 @@ -<!DOCTYPE html> +<!doctype html> <html lang="en"> <head> <meta charset="UTF-8" /> diff --git a/examples/vanilla-js/index.html b/examples/vanilla-js/index.html index 23cdfeba208..396a39da2d9 100644 --- a/examples/vanilla-js/index.html +++ b/examples/vanilla-js/index.html @@ -1,4 +1,4 @@ -<!DOCTYPE html> +<!doctype html> <html lang="en"> <head> <meta charset="UTF-8" /> diff --git a/packages/lexical-devtools-core/src/generateContent.ts b/packages/lexical-devtools-core/src/generateContent.ts index 5e431558d26..89a0eb7178d 100644 --- a/packages/lexical-devtools-core/src/generateContent.ts +++ b/packages/lexical-devtools-core/src/generateContent.ts @@ -145,10 +145,10 @@ export function generateContent( return selection === null ? ': null' : $isRangeSelection(selection) - ? printRangeSelection(selection) - : $isTableSelection(selection) - ? printTableSelection(selection) - : printNodeSelection(selection); + ? printRangeSelection(selection) + : $isTableSelection(selection) + ? printTableSelection(selection) + : printNodeSelection(selection); }); res += '\n selection' + selectionString; diff --git a/packages/lexical-devtools/safari-xcode/Lexical Developer Tools/Lexical Developer Tools/Base.lproj/Main.html b/packages/lexical-devtools/safari-xcode/Lexical Developer Tools/Lexical Developer Tools/Base.lproj/Main.html index 105450678fa..d76d438dbfc 100644 --- a/packages/lexical-devtools/safari-xcode/Lexical Developer Tools/Lexical Developer Tools/Base.lproj/Main.html +++ b/packages/lexical-devtools/safari-xcode/Lexical Developer Tools/Lexical Developer Tools/Base.lproj/Main.html @@ -1,4 +1,4 @@ -<!DOCTYPE html> +<!doctype html> <html> <head> <meta content="text/html; charset=utf-8" http-equiv="Content-Type" /> diff --git a/packages/lexical-devtools/src/entrypoints/devtools-panel/index.html b/packages/lexical-devtools/src/entrypoints/devtools-panel/index.html index 7db58aef1f0..9986ce8289b 100644 --- a/packages/lexical-devtools/src/entrypoints/devtools-panel/index.html +++ b/packages/lexical-devtools/src/entrypoints/devtools-panel/index.html @@ -1,4 +1,4 @@ -<!DOCTYPE html> +<!doctype html> <html lang="en"> <head> <meta charset="UTF-8" /> diff --git a/packages/lexical-devtools/src/entrypoints/devtools/index.html b/packages/lexical-devtools/src/entrypoints/devtools/index.html index b9a88d871cf..6e4ffeb705f 100644 --- a/packages/lexical-devtools/src/entrypoints/devtools/index.html +++ b/packages/lexical-devtools/src/entrypoints/devtools/index.html @@ -1,4 +1,4 @@ -<!DOCTYPE html> +<!doctype html> <html lang="en"> <head> <meta charset="UTF-8" /> diff --git a/packages/lexical-devtools/src/entrypoints/popup/index.html b/packages/lexical-devtools/src/entrypoints/popup/index.html index 68dd7ec9dc5..fffc2284f9f 100644 --- a/packages/lexical-devtools/src/entrypoints/popup/index.html +++ b/packages/lexical-devtools/src/entrypoints/popup/index.html @@ -1,4 +1,4 @@ -<!DOCTYPE html> +<!doctype html> <html lang="en"> <head> <meta charset="UTF-8" /> diff --git a/packages/lexical-headless/src/index.ts b/packages/lexical-headless/src/index.ts index 2b8eddb8ed3..04a18d356b7 100644 --- a/packages/lexical-headless/src/index.ts +++ b/packages/lexical-headless/src/index.ts @@ -33,7 +33,7 @@ export function createHeadlessEditor( 'blur', ] as const; - unsupportedMethods.forEach((method: typeof unsupportedMethods[number]) => { + unsupportedMethods.forEach((method: (typeof unsupportedMethods)[number]) => { editor[method] = () => { throw new Error(`${method} is not supported in headless mode`); }; diff --git a/packages/lexical-list/src/LexicalListItemNode.ts b/packages/lexical-list/src/LexicalListItemNode.ts index 757d706715b..0f03bf5701a 100644 --- a/packages/lexical-list/src/LexicalListItemNode.ts +++ b/packages/lexical-list/src/LexicalListItemNode.ts @@ -563,8 +563,8 @@ function $convertListItemElement(domNode: HTMLElement): DOMConversionOutput { ariaCheckedAttr === 'true' ? true : ariaCheckedAttr === 'false' - ? false - : undefined; + ? false + : undefined; return {node: $createListItemNode(checked)}; } diff --git a/packages/lexical-markdown/src/MarkdownTransformers.ts b/packages/lexical-markdown/src/MarkdownTransformers.ts index f22067abc0c..21ba7642a65 100644 --- a/packages/lexical-markdown/src/MarkdownTransformers.ts +++ b/packages/lexical-markdown/src/MarkdownTransformers.ts @@ -299,8 +299,8 @@ const listExport = ( listType === 'number' ? `${listNode.getStart() + index}. ` : listType === 'check' - ? `- [${listItemNode.getChecked() ? 'x' : ' '}] ` - : '- '; + ? `- [${listItemNode.getChecked() ? 'x' : ' '}] ` + : '- '; output.push(indent + prefix + exportChildren(listItemNode)); index++; } diff --git a/packages/lexical-playground/__tests__/e2e/CopyAndPaste/html/ListsHTMLCopyAndPaste.spec.mjs b/packages/lexical-playground/__tests__/e2e/CopyAndPaste/html/ListsHTMLCopyAndPaste.spec.mjs index 8d695141c17..87af282c4e0 100644 --- a/packages/lexical-playground/__tests__/e2e/CopyAndPaste/html/ListsHTMLCopyAndPaste.spec.mjs +++ b/packages/lexical-playground/__tests__/e2e/CopyAndPaste/html/ListsHTMLCopyAndPaste.spec.mjs @@ -322,9 +322,8 @@ test.describe('HTML Lists CopyAndPaste', () => { await focusEditor(page); // Ensure we preserve checked status. - clipboard[ - 'text/html' - ] = `<meta charset='utf-8'><ul __lexicallisttype="check"><li role="checkbox" tabindex="-1" aria-checked="true" value="1" class="PlaygroundEditorTheme__listItem PlaygroundEditorTheme__listItemChecked"><span>Hello</span></li><li role="checkbox" tabindex="-1" aria-checked="false" value="2" class="PlaygroundEditorTheme__listItem PlaygroundEditorTheme__listItemUnchecked"><span>world</span></li></ul>`; + clipboard['text/html'] = + `<meta charset='utf-8'><ul __lexicallisttype="check"><li role="checkbox" tabindex="-1" aria-checked="true" value="1" class="PlaygroundEditorTheme__listItem PlaygroundEditorTheme__listItemChecked"><span>Hello</span></li><li role="checkbox" tabindex="-1" aria-checked="false" value="2" class="PlaygroundEditorTheme__listItem PlaygroundEditorTheme__listItemUnchecked"><span>world</span></li></ul>`; await pasteFromClipboard(page, clipboard); diff --git a/packages/lexical-playground/__tests__/e2e/Extensions.spec.mjs b/packages/lexical-playground/__tests__/e2e/Extensions.spec.mjs index ba54a73aae1..6b8c6517948 100644 --- a/packages/lexical-playground/__tests__/e2e/Extensions.spec.mjs +++ b/packages/lexical-playground/__tests__/e2e/Extensions.spec.mjs @@ -25,13 +25,9 @@ test.describe('Extensions', () => { test(`document.execCommand("insertText")`, async ({page}) => { await focusEditor(page); - await evaluate( - page, - () => { - document.execCommand('insertText', false, 'foo'); - }, - [], - ); + await evaluate(page, () => { + document.execCommand('insertText', false, 'foo'); + }, []); await assertHTML( page, html` @@ -58,31 +54,27 @@ test.describe('Extensions', () => { } await focusEditor(page); - await evaluate( - page, - () => { - function paste() { - const dataTransfer = new DataTransfer(); - function dispatchPaste(target, text) { - dataTransfer.setData('text/plain', text); - target.dispatchEvent( - new ClipboardEvent('paste', { - bubbles: true, - cancelable: true, - clipboardData: dataTransfer, - }), - ); - dataTransfer.clearData(); - } - return dispatchPaste; + await evaluate(page, () => { + function paste() { + const dataTransfer = new DataTransfer(); + function dispatchPaste(target, text) { + dataTransfer.setData('text/plain', text); + target.dispatchEvent( + new ClipboardEvent('paste', { + bubbles: true, + cancelable: true, + clipboardData: dataTransfer, + }), + ); + dataTransfer.clearData(); } + return dispatchPaste; + } - const editor = document.querySelector('div[contenteditable="true"]'); - const dispatchPaste = paste(); - dispatchPaste(editor, 'foo'); - }, - [], - ); + const editor = document.querySelector('div[contenteditable="true"]'); + const dispatchPaste = paste(); + dispatchPaste(editor, 'foo'); + }, []); await assertHTML( page, html` @@ -214,29 +206,25 @@ test.describe('Extensions', () => { await page.keyboard.press('ArrowUp'); // Selection is on the last paragraph - await evaluate( - page, - async () => { - const editor = document.querySelector('div[contenteditable="true"]'); - const selection = window.getSelection(); - const secondParagraphTextNode = - editor.firstChild.nextSibling.firstChild.firstChild; - selection.setBaseAndExtent( - secondParagraphTextNode, - 0, - secondParagraphTextNode, - 3, - ); + await evaluate(page, async () => { + const editor = document.querySelector('div[contenteditable="true"]'); + const selection = window.getSelection(); + const secondParagraphTextNode = + editor.firstChild.nextSibling.firstChild.firstChild; + selection.setBaseAndExtent( + secondParagraphTextNode, + 0, + secondParagraphTextNode, + 3, + ); - await new Promise((resolve) => { - setTimeout(() => { - document.execCommand('insertText', false, 'and'); - resolve(); - }, 50); - }); - }, - [], - ); + await new Promise((resolve) => { + setTimeout(() => { + document.execCommand('insertText', false, 'and'); + resolve(); + }, 50); + }); + }, []); await assertHTML( page, html` @@ -278,13 +266,9 @@ test.describe('Extensions', () => { focusPath: [0, 0, 0], }); - await evaluate( - page, - () => { - document.execCommand('insertText', false, 'New text'); - }, - [], - ); + await evaluate(page, () => { + document.execCommand('insertText', false, 'New text'); + }, []); await assertHTML( page, html` @@ -321,13 +305,9 @@ test.describe('Extensions', () => { focusPath: [0, 0, 0], }); - await evaluate( - page, - () => { - document.execCommand('insertText', false, 'New text'); - }, - [], - ); + await evaluate(page, () => { + document.execCommand('insertText', false, 'New text'); + }, []); await assertHTML( page, html` diff --git a/packages/lexical-playground/__tests__/e2e/Links.spec.mjs b/packages/lexical-playground/__tests__/e2e/Links.spec.mjs index 98fa7139d48..22a271cd360 100644 --- a/packages/lexical-playground/__tests__/e2e/Links.spec.mjs +++ b/packages/lexical-playground/__tests__/e2e/Links.spec.mjs @@ -741,8 +741,8 @@ test.describe.parallel('Links', () => { insertMethod === 'paste:plain' ? clipboardData.plain : insertMethod === 'paste:html' - ? clipboardData.html - : clipboardData.lexical; + ? clipboardData.html + : clipboardData.lexical; await pasteFromClipboard(page, data); } @@ -818,8 +818,8 @@ test.describe.parallel('Links', () => { insertMethod === 'paste:plain' ? clipboardData.plain : insertMethod === 'paste:html' - ? clipboardData.html - : clipboardData.lexical; + ? clipboardData.html + : clipboardData.lexical; await pasteFromClipboard(page, data); } @@ -892,8 +892,8 @@ test.describe.parallel('Links', () => { insertMethod === 'paste:plain' ? clipboardData.plain : insertMethod === 'paste:html' - ? clipboardData.html - : clipboardData.lexical; + ? clipboardData.html + : clipboardData.lexical; await pasteFromClipboard(page, data); } @@ -970,8 +970,8 @@ test.describe.parallel('Links', () => { insertMethod === 'paste:plain' ? clipboardData.plain : insertMethod === 'paste:html' - ? clipboardData.html - : clipboardData.lexical; + ? clipboardData.html + : clipboardData.lexical; await pasteFromClipboard(page, data); } @@ -1046,8 +1046,8 @@ test.describe.parallel('Links', () => { insertMethod === 'paste:plain' ? clipboardData.plain : insertMethod === 'paste:html' - ? clipboardData.html - : clipboardData.lexical; + ? clipboardData.html + : clipboardData.lexical; await pasteFromClipboard(page, data); } @@ -1122,8 +1122,8 @@ test.describe.parallel('Links', () => { insertMethod === 'paste:plain' ? clipboardData.plain : insertMethod === 'paste:html' - ? clipboardData.html - : clipboardData.lexical; + ? clipboardData.html + : clipboardData.lexical; await pasteFromClipboard(page, data); } diff --git a/packages/lexical-playground/esm/index.html b/packages/lexical-playground/esm/index.html index 211ce77ab43..08dbd4a342a 100644 --- a/packages/lexical-playground/esm/index.html +++ b/packages/lexical-playground/esm/index.html @@ -1,4 +1,4 @@ -<!DOCTYPE html> +<!doctype html> <html lang="en"> <head> <meta charset="utf-8" /> diff --git a/packages/lexical-playground/index.html b/packages/lexical-playground/index.html index d810340cd24..7b546d00562 100644 --- a/packages/lexical-playground/index.html +++ b/packages/lexical-playground/index.html @@ -1,4 +1,4 @@ -<!DOCTYPE html> +<!doctype html> <html lang="en"> <head> <meta charset="utf-8" /> diff --git a/packages/lexical-playground/split/index.html b/packages/lexical-playground/split/index.html index d98f0a12996..e800b478d9f 100644 --- a/packages/lexical-playground/split/index.html +++ b/packages/lexical-playground/split/index.html @@ -1,4 +1,4 @@ -<!DOCTYPE html> +<!doctype html> <html lang="en"> <head> <meta charset="utf-8" /> diff --git a/packages/lexical-playground/src/App.tsx b/packages/lexical-playground/src/App.tsx index d667ed12c32..5ab43df6e92 100644 --- a/packages/lexical-playground/src/App.tsx +++ b/packages/lexical-playground/src/App.tsx @@ -197,8 +197,8 @@ function App(): JSX.Element { editorState: isCollab ? null : emptyEditor - ? undefined - : $prepopulatedRichText, + ? undefined + : $prepopulatedRichText, html: {import: buildImportMap()}, namespace: 'Playground', nodes: [...PlaygroundNodes], diff --git a/packages/lexical-playground/src/Editor.tsx b/packages/lexical-playground/src/Editor.tsx index 2b97ddd63ac..d3939b4b285 100644 --- a/packages/lexical-playground/src/Editor.tsx +++ b/packages/lexical-playground/src/Editor.tsx @@ -106,8 +106,8 @@ export default function Editor(): JSX.Element { const placeholder = isCollab ? 'Enter some collaborative rich text...' : isRichText - ? 'Enter some rich text...' - : 'Enter some plain text...'; + ? 'Enter some rich text...' + : 'Enter some plain text...'; const [floatingAnchorElem, setFloatingAnchorElem] = useState<HTMLDivElement | null>(null); const [isSmallWidthViewport, setIsSmallWidthViewport] = diff --git a/packages/lexical-playground/src/index.css b/packages/lexical-playground/src/index.css index 90c3841900d..1b9c3986c28 100644 --- a/packages/lexical-playground/src/index.css +++ b/packages/lexical-playground/src/index.css @@ -10,7 +10,11 @@ body { margin: 0; - font-family: system-ui, -apple-system, BlinkMacSystemFont, '.SFNSText-Regular', + font-family: + system-ui, + -apple-system, + BlinkMacSystemFont, + '.SFNSText-Regular', sans-serif; -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; @@ -757,7 +761,9 @@ i.page-break, z-index: 100; display: block; position: fixed; - box-shadow: 0 12px 28px 0 rgba(0, 0, 0, 0.2), 0 2px 4px 0 rgba(0, 0, 0, 0.1), + box-shadow: + 0 12px 28px 0 rgba(0, 0, 0, 0.2), + 0 2px 4px 0 rgba(0, 0, 0, 0.1), inset 0 0 0 1px rgba(255, 255, 255, 0.5); border-radius: 8px; min-height: 40px; diff --git a/packages/lexical-playground/src/plugins/TableCellResizer/index.tsx b/packages/lexical-playground/src/plugins/TableCellResizer/index.tsx index e1a05a61ec8..025e877e858 100644 --- a/packages/lexical-playground/src/plugins/TableCellResizer/index.tsx +++ b/packages/lexical-playground/src/plugins/TableCellResizer/index.tsx @@ -346,8 +346,8 @@ function TableCellResizer({editor}: {editor: LexicalEditor}): JSX.Element { const toggleResize = useCallback( ( - direction: PointerDraggingDirection, - ): PointerEventHandler<HTMLDivElement> => + direction: PointerDraggingDirection, + ): PointerEventHandler<HTMLDivElement> => (event) => { event.preventDefault(); event.stopPropagation(); diff --git a/packages/lexical-playground/src/plugins/TableOfContentsPlugin/index.tsx b/packages/lexical-playground/src/plugins/TableOfContentsPlugin/index.tsx index e8d3256a590..9f22f494d77 100644 --- a/packages/lexical-playground/src/plugins/TableOfContentsPlugin/index.tsx +++ b/packages/lexical-playground/src/plugins/TableOfContentsPlugin/index.tsx @@ -171,8 +171,7 @@ function TableOfContentsList({ <li className={`normal-heading ${ selectedKey === key ? 'selected-heading' : '' - } - `}> + } `}> {('' + text).length > 27 ? text.substring(0, 27) + '...' : text} diff --git a/packages/lexical-playground/src/plugins/ToolbarPlugin/index.tsx b/packages/lexical-playground/src/plugins/ToolbarPlugin/index.tsx index 44f353bcb31..d08dc79548f 100644 --- a/packages/lexical-playground/src/plugins/ToolbarPlugin/index.tsx +++ b/packages/lexical-playground/src/plugins/ToolbarPlugin/index.tsx @@ -597,8 +597,8 @@ export default function ToolbarPlugin({ $isElementNode(matchingParent) ? matchingParent.getFormatType() : $isElementNode(node) - ? node.getFormatType() - : parent?.getFormatType() || 'left', + ? node.getFormatType() + : parent?.getFormatType() || 'left', ); } if ($isRangeSelection(selection) || $isTableSelection(selection)) { diff --git a/packages/lexical-playground/src/ui/ColorPicker.css b/packages/lexical-playground/src/ui/ColorPicker.css index 63217ba3784..a10c5b8243f 100644 --- a/packages/lexical-playground/src/ui/ColorPicker.css +++ b/packages/lexical-playground/src/ui/ColorPicker.css @@ -36,7 +36,8 @@ position: relative; margin-top: 15px; height: 150px; - background-image: linear-gradient(transparent, black), + background-image: + linear-gradient(transparent, black), linear-gradient(to right, white, transparent); user-select: none; } diff --git a/packages/lexical-playground/src/ui/ColorPicker.tsx b/packages/lexical-playground/src/ui/ColorPicker.tsx index 6593c02389f..d647a700211 100644 --- a/packages/lexical-playground/src/ui/ColorPicker.tsx +++ b/packages/lexical-playground/src/ui/ColorPicker.tsx @@ -124,7 +124,7 @@ export default function ColorPicker({ <div className="color-picker-basic-color"> {basicColors.map((basicColor) => ( <button - className={basicColor === selfColor.hex ? ' active' : ''} + className={basicColor === selfColor.hex ? 'active' : ''} key={basicColor} style={{backgroundColor: basicColor}} onClick={() => { @@ -307,8 +307,8 @@ function rgb2hsv({r, g, b}: RGB): HSV { ? (max === r ? (g - b) / d + (g < b ? 6 : 0) : max === g - ? 2 + (b - r) / d - : 4 + (r - g) / d) * 60 + ? 2 + (b - r) / d + : 4 + (r - g) / d) * 60 : 0; const s = max ? (d / max) * 100 : 0; const v = max * 100; diff --git a/packages/lexical-playground/src/ui/ExcalidrawModal.css b/packages/lexical-playground/src/ui/ExcalidrawModal.css index 7438d60ecae..6e83f9e759a 100644 --- a/packages/lexical-playground/src/ui/ExcalidrawModal.css +++ b/packages/lexical-playground/src/ui/ExcalidrawModal.css @@ -38,7 +38,9 @@ width: 70vw; height: 70vh; border-radius: 8px; - box-shadow: 0 12px 28px 0 rgba(0, 0, 0, 0.2), 0 2px 4px 0 rgba(0, 0, 0, 0.1), + box-shadow: + 0 12px 28px 0 rgba(0, 0, 0, 0.2), + 0 2px 4px 0 rgba(0, 0, 0, 0.1), inset 0 0 0 1px rgba(255, 255, 255, 0.5); } .ExcalidrawModal__row > div { diff --git a/packages/lexical-playground/src/ui/ImageResizer.tsx b/packages/lexical-playground/src/ui/ImageResizer.tsx index e2c52ebfbc9..e38afdcafb1 100644 --- a/packages/lexical-playground/src/ui/ImageResizer.tsx +++ b/packages/lexical-playground/src/ui/ImageResizer.tsx @@ -76,8 +76,8 @@ export default function ImageResizer({ const maxWidthContainer = maxWidth ? maxWidth : editorRootElement !== null - ? editorRootElement.getBoundingClientRect().width - 20 - : 100; + ? editorRootElement.getBoundingClientRect().width - 20 + : 100; const maxHeightContainer = editorRootElement !== null ? editorRootElement.getBoundingClientRect().height - 20 diff --git a/packages/lexical-selection/src/lexical-node.ts b/packages/lexical-selection/src/lexical-node.ts index 91b5d9a3df3..404f81400a4 100644 --- a/packages/lexical-selection/src/lexical-node.ts +++ b/packages/lexical-selection/src/lexical-node.ts @@ -269,8 +269,8 @@ export function $patchStyle( $isRangeSelection(target) ? target.style : $isTextNode(target) - ? target.getStyle() - : target.getTextStyle(), + ? target.getStyle() + : target.getTextStyle(), ); const newStyles = Object.entries(patch).reduce<Record<string, string>>( (styles, [key, value]) => { diff --git a/packages/lexical-table/src/LexicalTableCellNode.ts b/packages/lexical-table/src/LexicalTableCellNode.ts index 987ba11d51d..9ba1a49947c 100644 --- a/packages/lexical-table/src/LexicalTableCellNode.ts +++ b/packages/lexical-table/src/LexicalTableCellNode.ts @@ -41,7 +41,7 @@ export const TableCellHeaderStates = { }; export type TableCellHeaderState = - typeof TableCellHeaderStates[keyof typeof TableCellHeaderStates]; + (typeof TableCellHeaderStates)[keyof typeof TableCellHeaderStates]; export type SerializedTableCellNode = Spread< { diff --git a/packages/lexical-yjs/src/SyncCursors.ts b/packages/lexical-yjs/src/SyncCursors.ts index 31cf7010c6d..21dd80a573b 100644 --- a/packages/lexical-yjs/src/SyncCursors.ts +++ b/packages/lexical-yjs/src/SyncCursors.ts @@ -277,9 +277,8 @@ function updateCursor( const style = `position:absolute;top:${top}px;left:${left}px;height:${selectionRect.height}px;width:${selectionRect.width}px;pointer-events:none;z-index:5;`; selection.style.cssText = style; - ( - selection.firstChild as HTMLSpanElement - ).style.cssText = `${style}left:0;top:0;background-color:${color};opacity:0.3;`; + (selection.firstChild as HTMLSpanElement).style.cssText = + `${style}left:0;top:0;background-color:${color};opacity:0.3;`; if (i === selectionRectsLength - 1) { if (caret.parentNode !== selection) { diff --git a/packages/lexical/src/LexicalEditor.ts b/packages/lexical/src/LexicalEditor.ts index c4b0be353d7..7f8e4f9f2dc 100644 --- a/packages/lexical/src/LexicalEditor.ts +++ b/packages/lexical/src/LexicalEditor.ts @@ -58,11 +58,10 @@ export type KlassConstructor<Cls extends GenericConstructor<any>> = // eslint-disable-next-line @typescript-eslint/no-explicit-any type GenericConstructor<T> = new (...args: any[]) => T; -export type Klass<T extends LexicalNode> = InstanceType< - T['constructor'] -> extends T - ? T['constructor'] - : GenericConstructor<T> & T['constructor']; +export type Klass<T extends LexicalNode> = + InstanceType<T['constructor']> extends T + ? T['constructor'] + : GenericConstructor<T> & T['constructor']; export type EditorThemeClassName = string; diff --git a/packages/lexical/src/LexicalNodeState.ts b/packages/lexical/src/LexicalNodeState.ts index d0b746e715c..6129b344006 100644 --- a/packages/lexical/src/LexicalNodeState.ts +++ b/packages/lexical/src/LexicalNodeState.ts @@ -75,21 +75,13 @@ export type AnyStateConfig = StateConfig<any, any>; /** * Get the value type (V) from a StateConfig */ -export type StateConfigValue<S extends AnyStateConfig> = S extends StateConfig< - infer _K, - infer V -> - ? V - : never; +export type StateConfigValue<S extends AnyStateConfig> = + S extends StateConfig<infer _K, infer V> ? V : never; /** * Get the key type (K) from a StateConfig */ -export type StateConfigKey<S extends AnyStateConfig> = S extends StateConfig< - infer K, - infer _V -> - ? K - : never; +export type StateConfigKey<S extends AnyStateConfig> = + S extends StateConfig<infer K, infer _V> ? K : never; /** * A value type, or an updater for that value type. For use with * {@link $setState} or any user-defined wrappers around it. diff --git a/packages/lexical/src/LexicalReconciler.ts b/packages/lexical/src/LexicalReconciler.ts index 0bff573024c..af97f01b100 100644 --- a/packages/lexical/src/LexicalReconciler.ts +++ b/packages/lexical/src/LexicalReconciler.ts @@ -303,8 +303,8 @@ function isLastChildLineBreakOrDecorator( return $isLineBreakNode(node) ? 'line-break' : $isDecoratorNode(node) && node.isInline() - ? 'decorator' - : null; + ? 'decorator' + : null; } } return 'empty'; diff --git a/packages/lexical/src/LexicalSelection.ts b/packages/lexical/src/LexicalSelection.ts index 96e4634db8d..5a29cfd56d5 100644 --- a/packages/lexical/src/LexicalSelection.ts +++ b/packages/lexical/src/LexicalSelection.ts @@ -3075,8 +3075,8 @@ export function updateDOMSelection( ? (nextAnchorNode.childNodes[nextAnchorOffset] as HTMLElement | Text) || null : domSelection.rangeCount > 0 - ? domSelection.getRangeAt(0) - : null; + ? domSelection.getRangeAt(0) + : null; if (selectionTarget !== null) { let selectionRect: DOMRect; if (selectionTarget instanceof Text) { diff --git a/packages/lexical/src/LexicalUpdates.ts b/packages/lexical/src/LexicalUpdates.ts index fb151f5fb7f..0e1012e4e88 100644 --- a/packages/lexical/src/LexicalUpdates.ts +++ b/packages/lexical/src/LexicalUpdates.ts @@ -133,7 +133,7 @@ function collectBuildInformation(): string { } else if (editor) { let version = String( ( - editor.constructor as typeof editor['constructor'] & + editor.constructor as (typeof editor)['constructor'] & Record<string, unknown> ).version || '<0.17.1', ); diff --git a/packages/lexical/src/LexicalUtils.ts b/packages/lexical/src/LexicalUtils.ts index 691b4be0bcc..8ed1031c145 100644 --- a/packages/lexical/src/LexicalUtils.ts +++ b/packages/lexical/src/LexicalUtils.ts @@ -1333,8 +1333,8 @@ export function getDOMOwnerDocument( return isDOMDocumentNode(target) ? target : isHTMLElement(target) - ? target.ownerDocument - : null; + ? target.ownerDocument + : null; } export function scrollIntoViewIfNeeded( diff --git a/packages/lexical/src/__tests__/unit/LexicalNodeState.test.ts b/packages/lexical/src/__tests__/unit/LexicalNodeState.test.ts index 0a47cd24477..d06211b6ba4 100644 --- a/packages/lexical/src/__tests__/unit/LexicalNodeState.test.ts +++ b/packages/lexical/src/__tests__/unit/LexicalNodeState.test.ts @@ -27,11 +27,10 @@ import {TestNode} from './LexicalNode.test'; // https://www.totaltypescript.com/how-to-test-your-types type Expect<T extends true> = T; -type Equal<X, Y> = (<T>() => T extends X ? 1 : 2) extends <T>() => T extends Y - ? 1 - : 2 - ? true - : false; +type Equal<X, Y> = + (<T>() => T extends X ? 1 : 2) extends <T>() => T extends Y ? 1 : 2 + ? true + : false; const numberState = createState('numberState', { parse: (v) => (typeof v === 'number' ? v : 0), diff --git a/packages/lexical/src/__tests__/unit/LexicalSelection.test.ts b/packages/lexical/src/__tests__/unit/LexicalSelection.test.ts index b936c3d346a..f2fdf226f8c 100644 --- a/packages/lexical/src/__tests__/unit/LexicalSelection.test.ts +++ b/packages/lexical/src/__tests__/unit/LexicalSelection.test.ts @@ -88,8 +88,8 @@ describe('LexicalSelection tests', () => { mode === 'start-of-paragraph' ? '<div contenteditable="true" style="user-select: text; white-space: pre-wrap; word-break: break-word;" data-lexical-editor="true"><p dir="ltr"><a href="https://" dir="ltr"><span data-lexical-text="true">a</span></a><span data-lexical-text="true">b</span></p></div>' : mode === 'mid-paragraph' - ? '<div contenteditable="true" style="user-select: text; white-space: pre-wrap; word-break: break-word;" data-lexical-editor="true"><p dir="ltr"><span data-lexical-text="true">a</span><a href="https://" dir="ltr"><span data-lexical-text="true">b</span></a><span data-lexical-text="true">c</span></p></div>' - : '<div contenteditable="true" style="user-select: text; white-space: pre-wrap; word-break: break-word;" data-lexical-editor="true"><p dir="ltr"><span data-lexical-text="true">a</span><a href="https://" dir="ltr"><span data-lexical-text="true">b</span></a></p></div>'; + ? '<div contenteditable="true" style="user-select: text; white-space: pre-wrap; word-break: break-word;" data-lexical-editor="true"><p dir="ltr"><span data-lexical-text="true">a</span><a href="https://" dir="ltr"><span data-lexical-text="true">b</span></a><span data-lexical-text="true">c</span></p></div>' + : '<div contenteditable="true" style="user-select: text; white-space: pre-wrap; word-break: break-word;" data-lexical-editor="true"><p dir="ltr"><span data-lexical-text="true">a</span><a href="https://" dir="ltr"><span data-lexical-text="true">b</span></a></p></div>'; expect(container.innerHTML).toBe(expectation); diff --git a/packages/lexical/src/caret/LexicalCaret.ts b/packages/lexical/src/caret/LexicalCaret.ts index c1af5986087..5389c7970a3 100644 --- a/packages/lexical/src/caret/LexicalCaret.ts +++ b/packages/lexical/src/caret/LexicalCaret.ts @@ -22,7 +22,8 @@ export type CaretDirection = 'next' | 'previous'; /** * A type utility to flip next and previous */ -export type FlipDirection<D extends CaretDirection> = typeof FLIP_DIRECTION[D]; +export type FlipDirection<D extends CaretDirection> = + (typeof FLIP_DIRECTION)[D]; /** * A sibling caret type points from a LexicalNode origin to its next or previous sibling, * and a child caret type points from an ElementNode origin to its first or last child. @@ -1235,14 +1236,14 @@ export function $comparePointCaretNext( return aIsText && bIsText ? compareNumber(a.offset, b.offset) : a.type === b.type - ? 0 - : aIsText - ? -1 - : bIsText - ? 1 - : a.type === 'child' - ? -1 - : 1; + ? 0 + : aIsText + ? -1 + : bIsText + ? 1 + : a.type === 'child' + ? -1 + : 1; } case 'ancestor': { return a.type === 'child' ? -1 : 1; diff --git a/packages/lexical/src/caret/__tests__/unit/LexicalCaret.test.ts b/packages/lexical/src/caret/__tests__/unit/LexicalCaret.test.ts index 40886b1533c..3ec82345db6 100644 --- a/packages/lexical/src/caret/__tests__/unit/LexicalCaret.test.ts +++ b/packages/lexical/src/caret/__tests__/unit/LexicalCaret.test.ts @@ -1205,8 +1205,8 @@ describe('LexicalCaret', () => { anchorBias === 'outside' && focusBias === 'outside' ? [] : (anchorBias === 'inside') === (direction === 'next') - ? [{caret: {offset: 0}, distance: size}] - : [{caret: {offset: size}, distance: -size}], + ? [{caret: {offset: 0}, distance: size}] + : [{caret: {offset: size}, distance: -size}], ); const resultRange = $removeTextFromCaretRange(range); $setSelection(null); diff --git a/packages/shared/lexicalMonorepoPlugin.ts b/packages/shared/lexicalMonorepoPlugin.ts index fd0660304a8..458d0e0e60c 100644 --- a/packages/shared/lexicalMonorepoPlugin.ts +++ b/packages/shared/lexicalMonorepoPlugin.ts @@ -26,8 +26,8 @@ export default function lexicalMonorepoPlugin(): Plugin { env.mode === 'production' ? 'production' : env.command === 'serve' - ? 'source' - : 'development', + ? 'source' + : 'development', ), }, }), diff --git a/scripts/lint-flow-types.js b/scripts/lint-flow-types.js index eb6804a6740..b61d89ac4d4 100644 --- a/scripts/lint-flow-types.js +++ b/scripts/lint-flow-types.js @@ -47,8 +47,8 @@ function collectFlowExports(flowAst) { node.type === 'Identifier' ? node : 'id' in node && node.id.type === 'Identifier' - ? node.id - : null; + ? node.id + : null; if (identifier) { exportNames.set(identifier.name, identifier); return true; From 7685f2f48e13f303a74378d3a7549af6462bf805 Mon Sep 17 00:00:00 2001 From: Bob Ippolito <bob@redivi.com> Date: Mon, 17 Mar 2025 12:34:12 -0700 Subject: [PATCH 08/10] Revert "npm run prettier:fix" This reverts commit 108af6757559f924b57b8816b73433d6911fe7d0. --- examples/react-plain-text/index.html | 2 +- examples/react-plain-text/src/styles.css | 6 +- examples/react-rich-collab/app.html | 2 +- examples/react-rich-collab/index.html | 2 +- examples/react-rich-collab/src/styles.css | 6 +- examples/react-rich/index.html | 2 +- examples/react-rich/src/styles.css | 6 +- examples/react-table/index.html | 2 +- examples/react-table/src/styles.css | 6 +- examples/vanilla-js-iframe/index.html | 2 +- examples/vanilla-js-plugin/index.html | 2 +- examples/vanilla-js/index.html | 2 +- .../src/generateContent.ts | 8 +- .../Base.lproj/Main.html | 2 +- .../src/entrypoints/devtools-panel/index.html | 2 +- .../src/entrypoints/devtools/index.html | 2 +- .../src/entrypoints/popup/index.html | 2 +- packages/lexical-headless/src/index.ts | 2 +- .../lexical-list/src/LexicalListItemNode.ts | 4 +- .../src/MarkdownTransformers.ts | 4 +- .../html/ListsHTMLCopyAndPaste.spec.mjs | 5 +- .../__tests__/e2e/Extensions.spec.mjs | 112 +++++++++++------- .../__tests__/e2e/Links.spec.mjs | 24 ++-- packages/lexical-playground/esm/index.html | 2 +- packages/lexical-playground/index.html | 2 +- packages/lexical-playground/split/index.html | 2 +- packages/lexical-playground/src/App.tsx | 4 +- packages/lexical-playground/src/Editor.tsx | 4 +- packages/lexical-playground/src/index.css | 10 +- .../src/plugins/TableCellResizer/index.tsx | 4 +- .../plugins/TableOfContentsPlugin/index.tsx | 3 +- .../src/plugins/ToolbarPlugin/index.tsx | 4 +- .../lexical-playground/src/ui/ColorPicker.css | 3 +- .../lexical-playground/src/ui/ColorPicker.tsx | 6 +- .../src/ui/ExcalidrawModal.css | 4 +- .../src/ui/ImageResizer.tsx | 4 +- .../lexical-selection/src/lexical-node.ts | 4 +- .../lexical-table/src/LexicalTableCellNode.ts | 2 +- packages/lexical-yjs/src/SyncCursors.ts | 5 +- packages/lexical/src/LexicalEditor.ts | 9 +- packages/lexical/src/LexicalNodeState.ts | 16 ++- packages/lexical/src/LexicalReconciler.ts | 4 +- packages/lexical/src/LexicalSelection.ts | 4 +- packages/lexical/src/LexicalUpdates.ts | 2 +- packages/lexical/src/LexicalUtils.ts | 4 +- .../__tests__/unit/LexicalNodeState.test.ts | 9 +- .../__tests__/unit/LexicalSelection.test.ts | 4 +- packages/lexical/src/caret/LexicalCaret.ts | 19 ++- .../caret/__tests__/unit/LexicalCaret.test.ts | 4 +- packages/shared/lexicalMonorepoPlugin.ts | 4 +- scripts/lint-flow-types.js | 4 +- 51 files changed, 180 insertions(+), 173 deletions(-) diff --git a/examples/react-plain-text/index.html b/examples/react-plain-text/index.html index 58fb43978dd..ce9878e6d4a 100644 --- a/examples/react-plain-text/index.html +++ b/examples/react-plain-text/index.html @@ -1,4 +1,4 @@ -<!doctype html> +<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8" /> diff --git a/examples/react-plain-text/src/styles.css b/examples/react-plain-text/src/styles.css index b6046673eba..bf79e1f4e71 100644 --- a/examples/react-plain-text/src/styles.css +++ b/examples/react-plain-text/src/styles.css @@ -9,11 +9,7 @@ body { margin: 0; background: #eee; - font-family: - system-ui, - -apple-system, - BlinkMacSystemFont, - '.SFNSText-Regular', + font-family: system-ui, -apple-system, BlinkMacSystemFont, '.SFNSText-Regular', sans-serif; font-weight: 500; -webkit-font-smoothing: antialiased; diff --git a/examples/react-rich-collab/app.html b/examples/react-rich-collab/app.html index 60a0fc531fe..8dbc32d5238 100644 --- a/examples/react-rich-collab/app.html +++ b/examples/react-rich-collab/app.html @@ -1,4 +1,4 @@ -<!doctype html> +<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8" /> diff --git a/examples/react-rich-collab/index.html b/examples/react-rich-collab/index.html index 62d6948c5b1..4096ec03812 100644 --- a/examples/react-rich-collab/index.html +++ b/examples/react-rich-collab/index.html @@ -1,4 +1,4 @@ -<!doctype html> +<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8" /> diff --git a/examples/react-rich-collab/src/styles.css b/examples/react-rich-collab/src/styles.css index 2f55096faa3..79e45348998 100644 --- a/examples/react-rich-collab/src/styles.css +++ b/examples/react-rich-collab/src/styles.css @@ -10,11 +10,7 @@ body { margin: 0; font-size: 14px; background: #eee; - font-family: - system-ui, - -apple-system, - BlinkMacSystemFont, - '.SFNSText-Regular', + font-family: system-ui, -apple-system, BlinkMacSystemFont, '.SFNSText-Regular', sans-serif; font-weight: 500; -webkit-font-smoothing: antialiased; diff --git a/examples/react-rich/index.html b/examples/react-rich/index.html index 4c5c8f08d5a..34bb34c5064 100644 --- a/examples/react-rich/index.html +++ b/examples/react-rich/index.html @@ -1,4 +1,4 @@ -<!doctype html> +<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8" /> diff --git a/examples/react-rich/src/styles.css b/examples/react-rich/src/styles.css index 3071e94a118..071a794fc76 100644 --- a/examples/react-rich/src/styles.css +++ b/examples/react-rich/src/styles.css @@ -9,11 +9,7 @@ body { margin: 0; background: #eee; - font-family: - system-ui, - -apple-system, - BlinkMacSystemFont, - '.SFNSText-Regular', + font-family: system-ui, -apple-system, BlinkMacSystemFont, '.SFNSText-Regular', sans-serif; font-weight: 500; -webkit-font-smoothing: antialiased; diff --git a/examples/react-table/index.html b/examples/react-table/index.html index 2f73f6bbf24..8243eabc6b9 100644 --- a/examples/react-table/index.html +++ b/examples/react-table/index.html @@ -1,4 +1,4 @@ -<!doctype html> +<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8" /> diff --git a/examples/react-table/src/styles.css b/examples/react-table/src/styles.css index a6dd01a6fd7..32b80315539 100644 --- a/examples/react-table/src/styles.css +++ b/examples/react-table/src/styles.css @@ -9,11 +9,7 @@ body { margin: 0; background: #eee; - font-family: - system-ui, - -apple-system, - BlinkMacSystemFont, - '.SFNSText-Regular', + font-family: system-ui, -apple-system, BlinkMacSystemFont, '.SFNSText-Regular', sans-serif; font-weight: 500; -webkit-font-smoothing: antialiased; diff --git a/examples/vanilla-js-iframe/index.html b/examples/vanilla-js-iframe/index.html index 41e6c0c674a..a730616c401 100644 --- a/examples/vanilla-js-iframe/index.html +++ b/examples/vanilla-js-iframe/index.html @@ -1,4 +1,4 @@ -<!doctype html> +<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8" /> diff --git a/examples/vanilla-js-plugin/index.html b/examples/vanilla-js-plugin/index.html index 8b639835237..ef397bcc4d1 100644 --- a/examples/vanilla-js-plugin/index.html +++ b/examples/vanilla-js-plugin/index.html @@ -1,4 +1,4 @@ -<!doctype html> +<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8" /> diff --git a/examples/vanilla-js/index.html b/examples/vanilla-js/index.html index 396a39da2d9..23cdfeba208 100644 --- a/examples/vanilla-js/index.html +++ b/examples/vanilla-js/index.html @@ -1,4 +1,4 @@ -<!doctype html> +<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8" /> diff --git a/packages/lexical-devtools-core/src/generateContent.ts b/packages/lexical-devtools-core/src/generateContent.ts index 89a0eb7178d..5e431558d26 100644 --- a/packages/lexical-devtools-core/src/generateContent.ts +++ b/packages/lexical-devtools-core/src/generateContent.ts @@ -145,10 +145,10 @@ export function generateContent( return selection === null ? ': null' : $isRangeSelection(selection) - ? printRangeSelection(selection) - : $isTableSelection(selection) - ? printTableSelection(selection) - : printNodeSelection(selection); + ? printRangeSelection(selection) + : $isTableSelection(selection) + ? printTableSelection(selection) + : printNodeSelection(selection); }); res += '\n selection' + selectionString; diff --git a/packages/lexical-devtools/safari-xcode/Lexical Developer Tools/Lexical Developer Tools/Base.lproj/Main.html b/packages/lexical-devtools/safari-xcode/Lexical Developer Tools/Lexical Developer Tools/Base.lproj/Main.html index d76d438dbfc..105450678fa 100644 --- a/packages/lexical-devtools/safari-xcode/Lexical Developer Tools/Lexical Developer Tools/Base.lproj/Main.html +++ b/packages/lexical-devtools/safari-xcode/Lexical Developer Tools/Lexical Developer Tools/Base.lproj/Main.html @@ -1,4 +1,4 @@ -<!doctype html> +<!DOCTYPE html> <html> <head> <meta content="text/html; charset=utf-8" http-equiv="Content-Type" /> diff --git a/packages/lexical-devtools/src/entrypoints/devtools-panel/index.html b/packages/lexical-devtools/src/entrypoints/devtools-panel/index.html index 9986ce8289b..7db58aef1f0 100644 --- a/packages/lexical-devtools/src/entrypoints/devtools-panel/index.html +++ b/packages/lexical-devtools/src/entrypoints/devtools-panel/index.html @@ -1,4 +1,4 @@ -<!doctype html> +<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8" /> diff --git a/packages/lexical-devtools/src/entrypoints/devtools/index.html b/packages/lexical-devtools/src/entrypoints/devtools/index.html index 6e4ffeb705f..b9a88d871cf 100644 --- a/packages/lexical-devtools/src/entrypoints/devtools/index.html +++ b/packages/lexical-devtools/src/entrypoints/devtools/index.html @@ -1,4 +1,4 @@ -<!doctype html> +<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8" /> diff --git a/packages/lexical-devtools/src/entrypoints/popup/index.html b/packages/lexical-devtools/src/entrypoints/popup/index.html index fffc2284f9f..68dd7ec9dc5 100644 --- a/packages/lexical-devtools/src/entrypoints/popup/index.html +++ b/packages/lexical-devtools/src/entrypoints/popup/index.html @@ -1,4 +1,4 @@ -<!doctype html> +<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8" /> diff --git a/packages/lexical-headless/src/index.ts b/packages/lexical-headless/src/index.ts index 04a18d356b7..2b8eddb8ed3 100644 --- a/packages/lexical-headless/src/index.ts +++ b/packages/lexical-headless/src/index.ts @@ -33,7 +33,7 @@ export function createHeadlessEditor( 'blur', ] as const; - unsupportedMethods.forEach((method: (typeof unsupportedMethods)[number]) => { + unsupportedMethods.forEach((method: typeof unsupportedMethods[number]) => { editor[method] = () => { throw new Error(`${method} is not supported in headless mode`); }; diff --git a/packages/lexical-list/src/LexicalListItemNode.ts b/packages/lexical-list/src/LexicalListItemNode.ts index 0f03bf5701a..757d706715b 100644 --- a/packages/lexical-list/src/LexicalListItemNode.ts +++ b/packages/lexical-list/src/LexicalListItemNode.ts @@ -563,8 +563,8 @@ function $convertListItemElement(domNode: HTMLElement): DOMConversionOutput { ariaCheckedAttr === 'true' ? true : ariaCheckedAttr === 'false' - ? false - : undefined; + ? false + : undefined; return {node: $createListItemNode(checked)}; } diff --git a/packages/lexical-markdown/src/MarkdownTransformers.ts b/packages/lexical-markdown/src/MarkdownTransformers.ts index 21ba7642a65..f22067abc0c 100644 --- a/packages/lexical-markdown/src/MarkdownTransformers.ts +++ b/packages/lexical-markdown/src/MarkdownTransformers.ts @@ -299,8 +299,8 @@ const listExport = ( listType === 'number' ? `${listNode.getStart() + index}. ` : listType === 'check' - ? `- [${listItemNode.getChecked() ? 'x' : ' '}] ` - : '- '; + ? `- [${listItemNode.getChecked() ? 'x' : ' '}] ` + : '- '; output.push(indent + prefix + exportChildren(listItemNode)); index++; } diff --git a/packages/lexical-playground/__tests__/e2e/CopyAndPaste/html/ListsHTMLCopyAndPaste.spec.mjs b/packages/lexical-playground/__tests__/e2e/CopyAndPaste/html/ListsHTMLCopyAndPaste.spec.mjs index 87af282c4e0..8d695141c17 100644 --- a/packages/lexical-playground/__tests__/e2e/CopyAndPaste/html/ListsHTMLCopyAndPaste.spec.mjs +++ b/packages/lexical-playground/__tests__/e2e/CopyAndPaste/html/ListsHTMLCopyAndPaste.spec.mjs @@ -322,8 +322,9 @@ test.describe('HTML Lists CopyAndPaste', () => { await focusEditor(page); // Ensure we preserve checked status. - clipboard['text/html'] = - `<meta charset='utf-8'><ul __lexicallisttype="check"><li role="checkbox" tabindex="-1" aria-checked="true" value="1" class="PlaygroundEditorTheme__listItem PlaygroundEditorTheme__listItemChecked"><span>Hello</span></li><li role="checkbox" tabindex="-1" aria-checked="false" value="2" class="PlaygroundEditorTheme__listItem PlaygroundEditorTheme__listItemUnchecked"><span>world</span></li></ul>`; + clipboard[ + 'text/html' + ] = `<meta charset='utf-8'><ul __lexicallisttype="check"><li role="checkbox" tabindex="-1" aria-checked="true" value="1" class="PlaygroundEditorTheme__listItem PlaygroundEditorTheme__listItemChecked"><span>Hello</span></li><li role="checkbox" tabindex="-1" aria-checked="false" value="2" class="PlaygroundEditorTheme__listItem PlaygroundEditorTheme__listItemUnchecked"><span>world</span></li></ul>`; await pasteFromClipboard(page, clipboard); diff --git a/packages/lexical-playground/__tests__/e2e/Extensions.spec.mjs b/packages/lexical-playground/__tests__/e2e/Extensions.spec.mjs index 6b8c6517948..ba54a73aae1 100644 --- a/packages/lexical-playground/__tests__/e2e/Extensions.spec.mjs +++ b/packages/lexical-playground/__tests__/e2e/Extensions.spec.mjs @@ -25,9 +25,13 @@ test.describe('Extensions', () => { test(`document.execCommand("insertText")`, async ({page}) => { await focusEditor(page); - await evaluate(page, () => { - document.execCommand('insertText', false, 'foo'); - }, []); + await evaluate( + page, + () => { + document.execCommand('insertText', false, 'foo'); + }, + [], + ); await assertHTML( page, html` @@ -54,27 +58,31 @@ test.describe('Extensions', () => { } await focusEditor(page); - await evaluate(page, () => { - function paste() { - const dataTransfer = new DataTransfer(); - function dispatchPaste(target, text) { - dataTransfer.setData('text/plain', text); - target.dispatchEvent( - new ClipboardEvent('paste', { - bubbles: true, - cancelable: true, - clipboardData: dataTransfer, - }), - ); - dataTransfer.clearData(); + await evaluate( + page, + () => { + function paste() { + const dataTransfer = new DataTransfer(); + function dispatchPaste(target, text) { + dataTransfer.setData('text/plain', text); + target.dispatchEvent( + new ClipboardEvent('paste', { + bubbles: true, + cancelable: true, + clipboardData: dataTransfer, + }), + ); + dataTransfer.clearData(); + } + return dispatchPaste; } - return dispatchPaste; - } - const editor = document.querySelector('div[contenteditable="true"]'); - const dispatchPaste = paste(); - dispatchPaste(editor, 'foo'); - }, []); + const editor = document.querySelector('div[contenteditable="true"]'); + const dispatchPaste = paste(); + dispatchPaste(editor, 'foo'); + }, + [], + ); await assertHTML( page, html` @@ -206,25 +214,29 @@ test.describe('Extensions', () => { await page.keyboard.press('ArrowUp'); // Selection is on the last paragraph - await evaluate(page, async () => { - const editor = document.querySelector('div[contenteditable="true"]'); - const selection = window.getSelection(); - const secondParagraphTextNode = - editor.firstChild.nextSibling.firstChild.firstChild; - selection.setBaseAndExtent( - secondParagraphTextNode, - 0, - secondParagraphTextNode, - 3, - ); + await evaluate( + page, + async () => { + const editor = document.querySelector('div[contenteditable="true"]'); + const selection = window.getSelection(); + const secondParagraphTextNode = + editor.firstChild.nextSibling.firstChild.firstChild; + selection.setBaseAndExtent( + secondParagraphTextNode, + 0, + secondParagraphTextNode, + 3, + ); - await new Promise((resolve) => { - setTimeout(() => { - document.execCommand('insertText', false, 'and'); - resolve(); - }, 50); - }); - }, []); + await new Promise((resolve) => { + setTimeout(() => { + document.execCommand('insertText', false, 'and'); + resolve(); + }, 50); + }); + }, + [], + ); await assertHTML( page, html` @@ -266,9 +278,13 @@ test.describe('Extensions', () => { focusPath: [0, 0, 0], }); - await evaluate(page, () => { - document.execCommand('insertText', false, 'New text'); - }, []); + await evaluate( + page, + () => { + document.execCommand('insertText', false, 'New text'); + }, + [], + ); await assertHTML( page, html` @@ -305,9 +321,13 @@ test.describe('Extensions', () => { focusPath: [0, 0, 0], }); - await evaluate(page, () => { - document.execCommand('insertText', false, 'New text'); - }, []); + await evaluate( + page, + () => { + document.execCommand('insertText', false, 'New text'); + }, + [], + ); await assertHTML( page, html` diff --git a/packages/lexical-playground/__tests__/e2e/Links.spec.mjs b/packages/lexical-playground/__tests__/e2e/Links.spec.mjs index 22a271cd360..98fa7139d48 100644 --- a/packages/lexical-playground/__tests__/e2e/Links.spec.mjs +++ b/packages/lexical-playground/__tests__/e2e/Links.spec.mjs @@ -741,8 +741,8 @@ test.describe.parallel('Links', () => { insertMethod === 'paste:plain' ? clipboardData.plain : insertMethod === 'paste:html' - ? clipboardData.html - : clipboardData.lexical; + ? clipboardData.html + : clipboardData.lexical; await pasteFromClipboard(page, data); } @@ -818,8 +818,8 @@ test.describe.parallel('Links', () => { insertMethod === 'paste:plain' ? clipboardData.plain : insertMethod === 'paste:html' - ? clipboardData.html - : clipboardData.lexical; + ? clipboardData.html + : clipboardData.lexical; await pasteFromClipboard(page, data); } @@ -892,8 +892,8 @@ test.describe.parallel('Links', () => { insertMethod === 'paste:plain' ? clipboardData.plain : insertMethod === 'paste:html' - ? clipboardData.html - : clipboardData.lexical; + ? clipboardData.html + : clipboardData.lexical; await pasteFromClipboard(page, data); } @@ -970,8 +970,8 @@ test.describe.parallel('Links', () => { insertMethod === 'paste:plain' ? clipboardData.plain : insertMethod === 'paste:html' - ? clipboardData.html - : clipboardData.lexical; + ? clipboardData.html + : clipboardData.lexical; await pasteFromClipboard(page, data); } @@ -1046,8 +1046,8 @@ test.describe.parallel('Links', () => { insertMethod === 'paste:plain' ? clipboardData.plain : insertMethod === 'paste:html' - ? clipboardData.html - : clipboardData.lexical; + ? clipboardData.html + : clipboardData.lexical; await pasteFromClipboard(page, data); } @@ -1122,8 +1122,8 @@ test.describe.parallel('Links', () => { insertMethod === 'paste:plain' ? clipboardData.plain : insertMethod === 'paste:html' - ? clipboardData.html - : clipboardData.lexical; + ? clipboardData.html + : clipboardData.lexical; await pasteFromClipboard(page, data); } diff --git a/packages/lexical-playground/esm/index.html b/packages/lexical-playground/esm/index.html index 08dbd4a342a..211ce77ab43 100644 --- a/packages/lexical-playground/esm/index.html +++ b/packages/lexical-playground/esm/index.html @@ -1,4 +1,4 @@ -<!doctype html> +<!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8" /> diff --git a/packages/lexical-playground/index.html b/packages/lexical-playground/index.html index 7b546d00562..d810340cd24 100644 --- a/packages/lexical-playground/index.html +++ b/packages/lexical-playground/index.html @@ -1,4 +1,4 @@ -<!doctype html> +<!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8" /> diff --git a/packages/lexical-playground/split/index.html b/packages/lexical-playground/split/index.html index e800b478d9f..d98f0a12996 100644 --- a/packages/lexical-playground/split/index.html +++ b/packages/lexical-playground/split/index.html @@ -1,4 +1,4 @@ -<!doctype html> +<!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8" /> diff --git a/packages/lexical-playground/src/App.tsx b/packages/lexical-playground/src/App.tsx index 5ab43df6e92..d667ed12c32 100644 --- a/packages/lexical-playground/src/App.tsx +++ b/packages/lexical-playground/src/App.tsx @@ -197,8 +197,8 @@ function App(): JSX.Element { editorState: isCollab ? null : emptyEditor - ? undefined - : $prepopulatedRichText, + ? undefined + : $prepopulatedRichText, html: {import: buildImportMap()}, namespace: 'Playground', nodes: [...PlaygroundNodes], diff --git a/packages/lexical-playground/src/Editor.tsx b/packages/lexical-playground/src/Editor.tsx index d3939b4b285..2b97ddd63ac 100644 --- a/packages/lexical-playground/src/Editor.tsx +++ b/packages/lexical-playground/src/Editor.tsx @@ -106,8 +106,8 @@ export default function Editor(): JSX.Element { const placeholder = isCollab ? 'Enter some collaborative rich text...' : isRichText - ? 'Enter some rich text...' - : 'Enter some plain text...'; + ? 'Enter some rich text...' + : 'Enter some plain text...'; const [floatingAnchorElem, setFloatingAnchorElem] = useState<HTMLDivElement | null>(null); const [isSmallWidthViewport, setIsSmallWidthViewport] = diff --git a/packages/lexical-playground/src/index.css b/packages/lexical-playground/src/index.css index 1b9c3986c28..90c3841900d 100644 --- a/packages/lexical-playground/src/index.css +++ b/packages/lexical-playground/src/index.css @@ -10,11 +10,7 @@ body { margin: 0; - font-family: - system-ui, - -apple-system, - BlinkMacSystemFont, - '.SFNSText-Regular', + font-family: system-ui, -apple-system, BlinkMacSystemFont, '.SFNSText-Regular', sans-serif; -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; @@ -761,9 +757,7 @@ i.page-break, z-index: 100; display: block; position: fixed; - box-shadow: - 0 12px 28px 0 rgba(0, 0, 0, 0.2), - 0 2px 4px 0 rgba(0, 0, 0, 0.1), + box-shadow: 0 12px 28px 0 rgba(0, 0, 0, 0.2), 0 2px 4px 0 rgba(0, 0, 0, 0.1), inset 0 0 0 1px rgba(255, 255, 255, 0.5); border-radius: 8px; min-height: 40px; diff --git a/packages/lexical-playground/src/plugins/TableCellResizer/index.tsx b/packages/lexical-playground/src/plugins/TableCellResizer/index.tsx index 025e877e858..e1a05a61ec8 100644 --- a/packages/lexical-playground/src/plugins/TableCellResizer/index.tsx +++ b/packages/lexical-playground/src/plugins/TableCellResizer/index.tsx @@ -346,8 +346,8 @@ function TableCellResizer({editor}: {editor: LexicalEditor}): JSX.Element { const toggleResize = useCallback( ( - direction: PointerDraggingDirection, - ): PointerEventHandler<HTMLDivElement> => + direction: PointerDraggingDirection, + ): PointerEventHandler<HTMLDivElement> => (event) => { event.preventDefault(); event.stopPropagation(); diff --git a/packages/lexical-playground/src/plugins/TableOfContentsPlugin/index.tsx b/packages/lexical-playground/src/plugins/TableOfContentsPlugin/index.tsx index 9f22f494d77..e8d3256a590 100644 --- a/packages/lexical-playground/src/plugins/TableOfContentsPlugin/index.tsx +++ b/packages/lexical-playground/src/plugins/TableOfContentsPlugin/index.tsx @@ -171,7 +171,8 @@ function TableOfContentsList({ <li className={`normal-heading ${ selectedKey === key ? 'selected-heading' : '' - } `}> + } + `}> {('' + text).length > 27 ? text.substring(0, 27) + '...' : text} diff --git a/packages/lexical-playground/src/plugins/ToolbarPlugin/index.tsx b/packages/lexical-playground/src/plugins/ToolbarPlugin/index.tsx index d08dc79548f..44f353bcb31 100644 --- a/packages/lexical-playground/src/plugins/ToolbarPlugin/index.tsx +++ b/packages/lexical-playground/src/plugins/ToolbarPlugin/index.tsx @@ -597,8 +597,8 @@ export default function ToolbarPlugin({ $isElementNode(matchingParent) ? matchingParent.getFormatType() : $isElementNode(node) - ? node.getFormatType() - : parent?.getFormatType() || 'left', + ? node.getFormatType() + : parent?.getFormatType() || 'left', ); } if ($isRangeSelection(selection) || $isTableSelection(selection)) { diff --git a/packages/lexical-playground/src/ui/ColorPicker.css b/packages/lexical-playground/src/ui/ColorPicker.css index a10c5b8243f..63217ba3784 100644 --- a/packages/lexical-playground/src/ui/ColorPicker.css +++ b/packages/lexical-playground/src/ui/ColorPicker.css @@ -36,8 +36,7 @@ position: relative; margin-top: 15px; height: 150px; - background-image: - linear-gradient(transparent, black), + background-image: linear-gradient(transparent, black), linear-gradient(to right, white, transparent); user-select: none; } diff --git a/packages/lexical-playground/src/ui/ColorPicker.tsx b/packages/lexical-playground/src/ui/ColorPicker.tsx index d647a700211..6593c02389f 100644 --- a/packages/lexical-playground/src/ui/ColorPicker.tsx +++ b/packages/lexical-playground/src/ui/ColorPicker.tsx @@ -124,7 +124,7 @@ export default function ColorPicker({ <div className="color-picker-basic-color"> {basicColors.map((basicColor) => ( <button - className={basicColor === selfColor.hex ? 'active' : ''} + className={basicColor === selfColor.hex ? ' active' : ''} key={basicColor} style={{backgroundColor: basicColor}} onClick={() => { @@ -307,8 +307,8 @@ function rgb2hsv({r, g, b}: RGB): HSV { ? (max === r ? (g - b) / d + (g < b ? 6 : 0) : max === g - ? 2 + (b - r) / d - : 4 + (r - g) / d) * 60 + ? 2 + (b - r) / d + : 4 + (r - g) / d) * 60 : 0; const s = max ? (d / max) * 100 : 0; const v = max * 100; diff --git a/packages/lexical-playground/src/ui/ExcalidrawModal.css b/packages/lexical-playground/src/ui/ExcalidrawModal.css index 6e83f9e759a..7438d60ecae 100644 --- a/packages/lexical-playground/src/ui/ExcalidrawModal.css +++ b/packages/lexical-playground/src/ui/ExcalidrawModal.css @@ -38,9 +38,7 @@ width: 70vw; height: 70vh; border-radius: 8px; - box-shadow: - 0 12px 28px 0 rgba(0, 0, 0, 0.2), - 0 2px 4px 0 rgba(0, 0, 0, 0.1), + box-shadow: 0 12px 28px 0 rgba(0, 0, 0, 0.2), 0 2px 4px 0 rgba(0, 0, 0, 0.1), inset 0 0 0 1px rgba(255, 255, 255, 0.5); } .ExcalidrawModal__row > div { diff --git a/packages/lexical-playground/src/ui/ImageResizer.tsx b/packages/lexical-playground/src/ui/ImageResizer.tsx index e38afdcafb1..e2c52ebfbc9 100644 --- a/packages/lexical-playground/src/ui/ImageResizer.tsx +++ b/packages/lexical-playground/src/ui/ImageResizer.tsx @@ -76,8 +76,8 @@ export default function ImageResizer({ const maxWidthContainer = maxWidth ? maxWidth : editorRootElement !== null - ? editorRootElement.getBoundingClientRect().width - 20 - : 100; + ? editorRootElement.getBoundingClientRect().width - 20 + : 100; const maxHeightContainer = editorRootElement !== null ? editorRootElement.getBoundingClientRect().height - 20 diff --git a/packages/lexical-selection/src/lexical-node.ts b/packages/lexical-selection/src/lexical-node.ts index 404f81400a4..91b5d9a3df3 100644 --- a/packages/lexical-selection/src/lexical-node.ts +++ b/packages/lexical-selection/src/lexical-node.ts @@ -269,8 +269,8 @@ export function $patchStyle( $isRangeSelection(target) ? target.style : $isTextNode(target) - ? target.getStyle() - : target.getTextStyle(), + ? target.getStyle() + : target.getTextStyle(), ); const newStyles = Object.entries(patch).reduce<Record<string, string>>( (styles, [key, value]) => { diff --git a/packages/lexical-table/src/LexicalTableCellNode.ts b/packages/lexical-table/src/LexicalTableCellNode.ts index 9ba1a49947c..987ba11d51d 100644 --- a/packages/lexical-table/src/LexicalTableCellNode.ts +++ b/packages/lexical-table/src/LexicalTableCellNode.ts @@ -41,7 +41,7 @@ export const TableCellHeaderStates = { }; export type TableCellHeaderState = - (typeof TableCellHeaderStates)[keyof typeof TableCellHeaderStates]; + typeof TableCellHeaderStates[keyof typeof TableCellHeaderStates]; export type SerializedTableCellNode = Spread< { diff --git a/packages/lexical-yjs/src/SyncCursors.ts b/packages/lexical-yjs/src/SyncCursors.ts index 21dd80a573b..31cf7010c6d 100644 --- a/packages/lexical-yjs/src/SyncCursors.ts +++ b/packages/lexical-yjs/src/SyncCursors.ts @@ -277,8 +277,9 @@ function updateCursor( const style = `position:absolute;top:${top}px;left:${left}px;height:${selectionRect.height}px;width:${selectionRect.width}px;pointer-events:none;z-index:5;`; selection.style.cssText = style; - (selection.firstChild as HTMLSpanElement).style.cssText = - `${style}left:0;top:0;background-color:${color};opacity:0.3;`; + ( + selection.firstChild as HTMLSpanElement + ).style.cssText = `${style}left:0;top:0;background-color:${color};opacity:0.3;`; if (i === selectionRectsLength - 1) { if (caret.parentNode !== selection) { diff --git a/packages/lexical/src/LexicalEditor.ts b/packages/lexical/src/LexicalEditor.ts index 7f8e4f9f2dc..c4b0be353d7 100644 --- a/packages/lexical/src/LexicalEditor.ts +++ b/packages/lexical/src/LexicalEditor.ts @@ -58,10 +58,11 @@ export type KlassConstructor<Cls extends GenericConstructor<any>> = // eslint-disable-next-line @typescript-eslint/no-explicit-any type GenericConstructor<T> = new (...args: any[]) => T; -export type Klass<T extends LexicalNode> = - InstanceType<T['constructor']> extends T - ? T['constructor'] - : GenericConstructor<T> & T['constructor']; +export type Klass<T extends LexicalNode> = InstanceType< + T['constructor'] +> extends T + ? T['constructor'] + : GenericConstructor<T> & T['constructor']; export type EditorThemeClassName = string; diff --git a/packages/lexical/src/LexicalNodeState.ts b/packages/lexical/src/LexicalNodeState.ts index 6129b344006..d0b746e715c 100644 --- a/packages/lexical/src/LexicalNodeState.ts +++ b/packages/lexical/src/LexicalNodeState.ts @@ -75,13 +75,21 @@ export type AnyStateConfig = StateConfig<any, any>; /** * Get the value type (V) from a StateConfig */ -export type StateConfigValue<S extends AnyStateConfig> = - S extends StateConfig<infer _K, infer V> ? V : never; +export type StateConfigValue<S extends AnyStateConfig> = S extends StateConfig< + infer _K, + infer V +> + ? V + : never; /** * Get the key type (K) from a StateConfig */ -export type StateConfigKey<S extends AnyStateConfig> = - S extends StateConfig<infer K, infer _V> ? K : never; +export type StateConfigKey<S extends AnyStateConfig> = S extends StateConfig< + infer K, + infer _V +> + ? K + : never; /** * A value type, or an updater for that value type. For use with * {@link $setState} or any user-defined wrappers around it. diff --git a/packages/lexical/src/LexicalReconciler.ts b/packages/lexical/src/LexicalReconciler.ts index af97f01b100..0bff573024c 100644 --- a/packages/lexical/src/LexicalReconciler.ts +++ b/packages/lexical/src/LexicalReconciler.ts @@ -303,8 +303,8 @@ function isLastChildLineBreakOrDecorator( return $isLineBreakNode(node) ? 'line-break' : $isDecoratorNode(node) && node.isInline() - ? 'decorator' - : null; + ? 'decorator' + : null; } } return 'empty'; diff --git a/packages/lexical/src/LexicalSelection.ts b/packages/lexical/src/LexicalSelection.ts index 5a29cfd56d5..96e4634db8d 100644 --- a/packages/lexical/src/LexicalSelection.ts +++ b/packages/lexical/src/LexicalSelection.ts @@ -3075,8 +3075,8 @@ export function updateDOMSelection( ? (nextAnchorNode.childNodes[nextAnchorOffset] as HTMLElement | Text) || null : domSelection.rangeCount > 0 - ? domSelection.getRangeAt(0) - : null; + ? domSelection.getRangeAt(0) + : null; if (selectionTarget !== null) { let selectionRect: DOMRect; if (selectionTarget instanceof Text) { diff --git a/packages/lexical/src/LexicalUpdates.ts b/packages/lexical/src/LexicalUpdates.ts index 0e1012e4e88..fb151f5fb7f 100644 --- a/packages/lexical/src/LexicalUpdates.ts +++ b/packages/lexical/src/LexicalUpdates.ts @@ -133,7 +133,7 @@ function collectBuildInformation(): string { } else if (editor) { let version = String( ( - editor.constructor as (typeof editor)['constructor'] & + editor.constructor as typeof editor['constructor'] & Record<string, unknown> ).version || '<0.17.1', ); diff --git a/packages/lexical/src/LexicalUtils.ts b/packages/lexical/src/LexicalUtils.ts index 8ed1031c145..691b4be0bcc 100644 --- a/packages/lexical/src/LexicalUtils.ts +++ b/packages/lexical/src/LexicalUtils.ts @@ -1333,8 +1333,8 @@ export function getDOMOwnerDocument( return isDOMDocumentNode(target) ? target : isHTMLElement(target) - ? target.ownerDocument - : null; + ? target.ownerDocument + : null; } export function scrollIntoViewIfNeeded( diff --git a/packages/lexical/src/__tests__/unit/LexicalNodeState.test.ts b/packages/lexical/src/__tests__/unit/LexicalNodeState.test.ts index d06211b6ba4..0a47cd24477 100644 --- a/packages/lexical/src/__tests__/unit/LexicalNodeState.test.ts +++ b/packages/lexical/src/__tests__/unit/LexicalNodeState.test.ts @@ -27,10 +27,11 @@ import {TestNode} from './LexicalNode.test'; // https://www.totaltypescript.com/how-to-test-your-types type Expect<T extends true> = T; -type Equal<X, Y> = - (<T>() => T extends X ? 1 : 2) extends <T>() => T extends Y ? 1 : 2 - ? true - : false; +type Equal<X, Y> = (<T>() => T extends X ? 1 : 2) extends <T>() => T extends Y + ? 1 + : 2 + ? true + : false; const numberState = createState('numberState', { parse: (v) => (typeof v === 'number' ? v : 0), diff --git a/packages/lexical/src/__tests__/unit/LexicalSelection.test.ts b/packages/lexical/src/__tests__/unit/LexicalSelection.test.ts index f2fdf226f8c..b936c3d346a 100644 --- a/packages/lexical/src/__tests__/unit/LexicalSelection.test.ts +++ b/packages/lexical/src/__tests__/unit/LexicalSelection.test.ts @@ -88,8 +88,8 @@ describe('LexicalSelection tests', () => { mode === 'start-of-paragraph' ? '<div contenteditable="true" style="user-select: text; white-space: pre-wrap; word-break: break-word;" data-lexical-editor="true"><p dir="ltr"><a href="https://" dir="ltr"><span data-lexical-text="true">a</span></a><span data-lexical-text="true">b</span></p></div>' : mode === 'mid-paragraph' - ? '<div contenteditable="true" style="user-select: text; white-space: pre-wrap; word-break: break-word;" data-lexical-editor="true"><p dir="ltr"><span data-lexical-text="true">a</span><a href="https://" dir="ltr"><span data-lexical-text="true">b</span></a><span data-lexical-text="true">c</span></p></div>' - : '<div contenteditable="true" style="user-select: text; white-space: pre-wrap; word-break: break-word;" data-lexical-editor="true"><p dir="ltr"><span data-lexical-text="true">a</span><a href="https://" dir="ltr"><span data-lexical-text="true">b</span></a></p></div>'; + ? '<div contenteditable="true" style="user-select: text; white-space: pre-wrap; word-break: break-word;" data-lexical-editor="true"><p dir="ltr"><span data-lexical-text="true">a</span><a href="https://" dir="ltr"><span data-lexical-text="true">b</span></a><span data-lexical-text="true">c</span></p></div>' + : '<div contenteditable="true" style="user-select: text; white-space: pre-wrap; word-break: break-word;" data-lexical-editor="true"><p dir="ltr"><span data-lexical-text="true">a</span><a href="https://" dir="ltr"><span data-lexical-text="true">b</span></a></p></div>'; expect(container.innerHTML).toBe(expectation); diff --git a/packages/lexical/src/caret/LexicalCaret.ts b/packages/lexical/src/caret/LexicalCaret.ts index 5389c7970a3..c1af5986087 100644 --- a/packages/lexical/src/caret/LexicalCaret.ts +++ b/packages/lexical/src/caret/LexicalCaret.ts @@ -22,8 +22,7 @@ export type CaretDirection = 'next' | 'previous'; /** * A type utility to flip next and previous */ -export type FlipDirection<D extends CaretDirection> = - (typeof FLIP_DIRECTION)[D]; +export type FlipDirection<D extends CaretDirection> = typeof FLIP_DIRECTION[D]; /** * A sibling caret type points from a LexicalNode origin to its next or previous sibling, * and a child caret type points from an ElementNode origin to its first or last child. @@ -1236,14 +1235,14 @@ export function $comparePointCaretNext( return aIsText && bIsText ? compareNumber(a.offset, b.offset) : a.type === b.type - ? 0 - : aIsText - ? -1 - : bIsText - ? 1 - : a.type === 'child' - ? -1 - : 1; + ? 0 + : aIsText + ? -1 + : bIsText + ? 1 + : a.type === 'child' + ? -1 + : 1; } case 'ancestor': { return a.type === 'child' ? -1 : 1; diff --git a/packages/lexical/src/caret/__tests__/unit/LexicalCaret.test.ts b/packages/lexical/src/caret/__tests__/unit/LexicalCaret.test.ts index 3ec82345db6..40886b1533c 100644 --- a/packages/lexical/src/caret/__tests__/unit/LexicalCaret.test.ts +++ b/packages/lexical/src/caret/__tests__/unit/LexicalCaret.test.ts @@ -1205,8 +1205,8 @@ describe('LexicalCaret', () => { anchorBias === 'outside' && focusBias === 'outside' ? [] : (anchorBias === 'inside') === (direction === 'next') - ? [{caret: {offset: 0}, distance: size}] - : [{caret: {offset: size}, distance: -size}], + ? [{caret: {offset: 0}, distance: size}] + : [{caret: {offset: size}, distance: -size}], ); const resultRange = $removeTextFromCaretRange(range); $setSelection(null); diff --git a/packages/shared/lexicalMonorepoPlugin.ts b/packages/shared/lexicalMonorepoPlugin.ts index 458d0e0e60c..fd0660304a8 100644 --- a/packages/shared/lexicalMonorepoPlugin.ts +++ b/packages/shared/lexicalMonorepoPlugin.ts @@ -26,8 +26,8 @@ export default function lexicalMonorepoPlugin(): Plugin { env.mode === 'production' ? 'production' : env.command === 'serve' - ? 'source' - : 'development', + ? 'source' + : 'development', ), }, }), diff --git a/scripts/lint-flow-types.js b/scripts/lint-flow-types.js index b61d89ac4d4..eb6804a6740 100644 --- a/scripts/lint-flow-types.js +++ b/scripts/lint-flow-types.js @@ -47,8 +47,8 @@ function collectFlowExports(flowAst) { node.type === 'Identifier' ? node : 'id' in node && node.id.type === 'Identifier' - ? node.id - : null; + ? node.id + : null; if (identifier) { exportNames.set(identifier.name, identifier); return true; From 219e692c4ea10acdcc7d231848e427b579a2d67c Mon Sep 17 00:00:00 2001 From: Bob Ippolito <bob@redivi.com> Date: Mon, 17 Mar 2025 12:34:15 -0700 Subject: [PATCH 09/10] Revert "update prettier" This reverts commit f13380c9918c2950c1dcd0f7060b13c4229e8061. --- .eslintignore | 1 - .prettierignore | 1 - package-lock.json | 157 +++++++++--------- package.json | 8 +- .../__tests__/unit/rules-of-lexical.test.ts | 4 +- packages/lexical-list/src/__tests__/utils.ts | 4 +- .../__tests__/utils/index.mjs | 2 +- packages/lexical-playground/package.json | 2 +- packages/lexical-website/package.json | 2 +- .../lexical/src/__tests__/utils/index.tsx | 6 +- .../unit/transform-error-messages.test.js | 14 +- .../error-codes/transform-error-messages.js | 6 +- 12 files changed, 97 insertions(+), 110 deletions(-) diff --git a/.eslintignore b/.eslintignore index 5b987a70346..568a2cf9313 100644 --- a/.eslintignore +++ b/.eslintignore @@ -13,4 +13,3 @@ **/.docusaurus /playwright-report test-results -/libdefs/*.js diff --git a/.prettierignore b/.prettierignore index 0e75361aeac..580080b429f 100644 --- a/.prettierignore +++ b/.prettierignore @@ -23,4 +23,3 @@ flow-typed **/.docusaurus /playwright-report test-results -/libdefs/*.js diff --git a/package-lock.json b/package-lock.json index 80fc0981e68..2593e2c90b8 100644 --- a/package-lock.json +++ b/package-lock.json @@ -12,7 +12,6 @@ "packages/*" ], "dependencies": { - "@prettier/sync": "^0.5.2", "yjs": "^13.5.42" }, "devDependencies": { @@ -36,6 +35,7 @@ "@types/jsdom": "^21.1.6", "@types/katex": "^0.16.7", "@types/node": "^17.0.31", + "@types/prettier": "^2.7.3", "@types/prismjs": "^1.26.0", "@types/proper-lockfile": "^4.1.4", "@types/react": "^18.0.8", @@ -79,10 +79,10 @@ "lint-staged": "^11.1.0", "minimist": "^1.2.5", "npm-run-all": "^4.1.5", - "prettier": "^3.5.3", + "prettier": "^2.3.2", "prettier-plugin-hermes-parser": "^0.26.0", - "prettier-plugin-organize-attributes": "^1.0.0", - "prettier-plugin-tailwindcss": "^0.6.11", + "prettier-plugin-organize-attributes": "^0.0.5", + "prettier-plugin-tailwindcss": "^0.4.1", "proper-lockfile": "^4.1.2", "react-test-renderer": "^17.0.2", "rollup": "^4.22.4", @@ -7786,20 +7786,6 @@ "url": "https://opencollective.com/popperjs" } }, - "node_modules/@prettier/sync": { - "version": "0.5.2", - "resolved": "https://registry.npmjs.org/@prettier/sync/-/sync-0.5.2.tgz", - "integrity": "sha512-Yb569su456XNx5BsH/Vyem7xD6g/y9iLmLUzRKM1a/dhU/D7HqqvkAG72znulXlMXztbV0iiu9O5AL8K98TzZQ==", - "dependencies": { - "make-synchronized": "^0.2.8" - }, - "funding": { - "url": "https://github.com/prettier/prettier-synchronized?sponsor=1" - }, - "peerDependencies": { - "prettier": "*" - } - }, "node_modules/@radix-ui/primitive": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/@radix-ui/primitive/-/primitive-1.0.1.tgz", @@ -10072,6 +10058,12 @@ "resolved": "https://registry.npmjs.org/@types/parse5/-/parse5-5.0.3.tgz", "integrity": "sha512-kUNnecmtkunAoQ3CnjmMkzNU/gtxG8guhi+Fk2U/kOpIKjIMKnXGp4IJCgQJrXSgMsWYimYG4TGjz/UzbGEBTw==" }, + "node_modules/@types/prettier": { + "version": "2.7.3", + "resolved": "https://registry.npmjs.org/@types/prettier/-/prettier-2.7.3.tgz", + "integrity": "sha512-+68kP9yzs4LMp7VNh8gdzMSPZFL44MLGqiHWvttYJe+6qnuVr4Ek9wSBQoveqY/r+LwjCcU29kNVkidwim+kYA==", + "dev": true + }, "node_modules/@types/prismjs": { "version": "1.26.0", "resolved": "https://registry.npmjs.org/@types/prismjs/-/prismjs-1.26.0.tgz", @@ -25700,14 +25692,6 @@ "integrity": "sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==", "dev": true }, - "node_modules/make-synchronized": { - "version": "0.2.9", - "resolved": "https://registry.npmjs.org/make-synchronized/-/make-synchronized-0.2.9.tgz", - "integrity": "sha512-4wczOs8SLuEdpEvp3vGo83wh8rjJ78UsIk7DIX5fxdfmfMJGog4bQzxfvOwq7Q3yCHLC4jp1urPHIxRS/A93gA==", - "funding": { - "url": "https://github.com/fisker/make-synchronized?sponsor=1" - } - }, "node_modules/makeerror": { "version": "1.0.12", "resolved": "https://registry.npmjs.org/makeerror/-/makeerror-1.0.12.tgz", @@ -32037,14 +32021,15 @@ } }, "node_modules/prettier": { - "version": "3.5.3", - "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.5.3.tgz", - "integrity": "sha512-QQtaxnoDJeAkDvDKWCLiwIXkTgRhwYDEQCghU9Z6q03iyek/rxRh/2lC3HB7P8sWT2xC/y5JDctPLBIGzHKbhw==", + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-2.7.1.tgz", + "integrity": "sha512-ujppO+MkdPqoVINuDFDRLClm7D78qbDt0/NR+wp5FqEZOoTNAjPHWj17QRhu7geIHJfcNhRk1XVQmF8Bp3ye+g==", + "dev": true, "bin": { - "prettier": "bin/prettier.cjs" + "prettier": "bin-prettier.js" }, "engines": { - "node": ">=14" + "node": ">=10.13.0" }, "funding": { "url": "https://github.com/prettier/prettier?sponsor=1" @@ -32065,43 +32050,42 @@ } }, "node_modules/prettier-plugin-organize-attributes": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/prettier-plugin-organize-attributes/-/prettier-plugin-organize-attributes-1.0.0.tgz", - "integrity": "sha512-+NmameaLxbCcylEXsKPmawtzla5EE6ECqvGkpfQz4KM847fXDifB1gFnPQEpoADAq6IXg+cMI8Z0ISJEXa6fhg==", + "version": "0.0.5", + "resolved": "https://registry.npmjs.org/prettier-plugin-organize-attributes/-/prettier-plugin-organize-attributes-0.0.5.tgz", + "integrity": "sha512-dSts16q8wd+oq8Zwk5mwmYXo1aN3B+ZkEJqx/ar5fedNHdOvx7S4XDMH/pNK7rmBW0bPXkp/kJX5gAANsWzh3A==", "dev": true, "engines": { - "node": ">=14.0.0" + "node": ">=11.0.0" }, "peerDependencies": { - "prettier": "^3.0.0" + "prettier": "^2.0.0" } }, "node_modules/prettier-plugin-tailwindcss": { - "version": "0.6.11", - "resolved": "https://registry.npmjs.org/prettier-plugin-tailwindcss/-/prettier-plugin-tailwindcss-0.6.11.tgz", - "integrity": "sha512-YxaYSIvZPAqhrrEpRtonnrXdghZg1irNg4qrjboCXrpybLWVs55cW2N3juhspVJiO0JBvYJT8SYsJpc8OQSnsA==", + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/prettier-plugin-tailwindcss/-/prettier-plugin-tailwindcss-0.4.1.tgz", + "integrity": "sha512-hwn2EiJmv8M+AW4YDkbjJ6HlZCTzLyz1QlySn9sMuKV/Px0fjwldlB7tol8GzdgqtkdPtzT3iJ4UzdnYXP25Ag==", "dev": true, "engines": { - "node": ">=14.21.3" + "node": ">=12.17.0" }, "peerDependencies": { "@ianvs/prettier-plugin-sort-imports": "*", "@prettier/plugin-pug": "*", "@shopify/prettier-plugin-liquid": "*", + "@shufo/prettier-plugin-blade": "*", "@trivago/prettier-plugin-sort-imports": "*", - "@zackad/prettier-plugin-twig": "*", - "prettier": "^3.0", + "prettier": "^2.2 || ^3.0", "prettier-plugin-astro": "*", "prettier-plugin-css-order": "*", "prettier-plugin-import-sort": "*", "prettier-plugin-jsdoc": "*", "prettier-plugin-marko": "*", - "prettier-plugin-multiline-arrays": "*", "prettier-plugin-organize-attributes": "*", "prettier-plugin-organize-imports": "*", - "prettier-plugin-sort-imports": "*", "prettier-plugin-style-order": "*", - "prettier-plugin-svelte": "*" + "prettier-plugin-svelte": "*", + "prettier-plugin-twig-melody": "*" }, "peerDependenciesMeta": { "@ianvs/prettier-plugin-sort-imports": { @@ -32113,10 +32097,10 @@ "@shopify/prettier-plugin-liquid": { "optional": true }, - "@trivago/prettier-plugin-sort-imports": { + "@shufo/prettier-plugin-blade": { "optional": true }, - "@zackad/prettier-plugin-twig": { + "@trivago/prettier-plugin-sort-imports": { "optional": true }, "prettier-plugin-astro": { @@ -32134,23 +32118,20 @@ "prettier-plugin-marko": { "optional": true }, - "prettier-plugin-multiline-arrays": { - "optional": true - }, "prettier-plugin-organize-attributes": { "optional": true }, "prettier-plugin-organize-imports": { "optional": true }, - "prettier-plugin-sort-imports": { - "optional": true - }, "prettier-plugin-style-order": { "optional": true }, "prettier-plugin-svelte": { "optional": true + }, + "prettier-plugin-twig-melody": { + "optional": true } } }, @@ -40244,7 +40225,6 @@ "version": "0.27.2", "license": "MIT", "dependencies": { - "@lexical/selection": "0.27.2", "@lexical/utils": "0.27.2", "lexical": "0.27.2" } @@ -40320,7 +40300,7 @@ "katex": "^0.16.10", "lexical": "0.27.2", "lodash-es": "^4.17.21", - "prettier": "^3.5.3", + "prettier": "^3.4.2", "react": "^18.2.0", "react-dom": "^18.2.0", "react-error-boundary": "^3.1.4", @@ -40339,6 +40319,21 @@ "vite-plugin-static-copy": "^2.1.0" } }, + "packages/lexical-playground/node_modules/prettier": { + "version": "3.4.2", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.4.2.tgz", + "integrity": "sha512-e9MewbtFo+Fevyuxn/4rrcDAaq0IYxPGLvObpQjiZBMAzB9IGmzlnG9RZy3FFas+eBMu2vA0CszMeduow5dIuQ==", + "license": "MIT", + "bin": { + "prettier": "bin/prettier.cjs" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/prettier/prettier?sponsor=1" + } + }, "packages/lexical-react": { "name": "@lexical/react", "version": "0.27.2", @@ -40439,7 +40434,7 @@ }, "devDependencies": { "buffer": "^6.0.3", - "prettier-plugin-tailwindcss": "^0.6.11", + "prettier-plugin-tailwindcss": "^0.4.1", "tailwindcss": "^3.3.3", "typedoc": "^0.25.12", "typescript": "^5.4.5", @@ -45279,7 +45274,6 @@ "@lexical/list": { "version": "file:packages/lexical-list", "requires": { - "@lexical/selection": "0.27.2", "@lexical/utils": "0.27.2", "lexical": "0.27.2" } @@ -45399,7 +45393,7 @@ "docusaurus-plugin-internaldocs-fb": "1.19.0", "docusaurus-plugin-typedoc": "^0.22.0", "fs-extra": "^10.0.0", - "prettier-plugin-tailwindcss": "^0.6.11", + "prettier-plugin-tailwindcss": "^0.4.1", "prism-react-renderer": "^2.3.1", "react": "^18.2.0", "react-dom": "^18.2.0", @@ -45587,14 +45581,6 @@ "resolved": "https://registry.npmjs.org/@popperjs/core/-/core-2.11.8.tgz", "integrity": "sha512-P1st0aksCrn9sGZhp8GMYwBnQsbvAWsZAX44oXNNvLHGqAOcoVxmjZiohstwQ7SqKnbR47akdNi+uleWD8+g6A==" }, - "@prettier/sync": { - "version": "0.5.2", - "resolved": "https://registry.npmjs.org/@prettier/sync/-/sync-0.5.2.tgz", - "integrity": "sha512-Yb569su456XNx5BsH/Vyem7xD6g/y9iLmLUzRKM1a/dhU/D7HqqvkAG72znulXlMXztbV0iiu9O5AL8K98TzZQ==", - "requires": { - "make-synchronized": "^0.2.8" - } - }, "@radix-ui/primitive": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/@radix-ui/primitive/-/primitive-1.0.1.tgz", @@ -46974,6 +46960,12 @@ "resolved": "https://registry.npmjs.org/@types/parse5/-/parse5-5.0.3.tgz", "integrity": "sha512-kUNnecmtkunAoQ3CnjmMkzNU/gtxG8guhi+Fk2U/kOpIKjIMKnXGp4IJCgQJrXSgMsWYimYG4TGjz/UzbGEBTw==" }, + "@types/prettier": { + "version": "2.7.3", + "resolved": "https://registry.npmjs.org/@types/prettier/-/prettier-2.7.3.tgz", + "integrity": "sha512-+68kP9yzs4LMp7VNh8gdzMSPZFL44MLGqiHWvttYJe+6qnuVr4Ek9wSBQoveqY/r+LwjCcU29kNVkidwim+kYA==", + "dev": true + }, "@types/prismjs": { "version": "1.26.0", "resolved": "https://registry.npmjs.org/@types/prismjs/-/prismjs-1.26.0.tgz", @@ -57321,7 +57313,7 @@ "katex": "^0.16.10", "lexical": "0.27.2", "lodash-es": "^4.17.21", - "prettier": "^3.5.3", + "prettier": "^3.4.2", "react": "^18.2.0", "react-dom": "^18.2.0", "react-error-boundary": "^3.1.4", @@ -57330,6 +57322,13 @@ "vite-plugin-static-copy": "^2.1.0", "y-websocket": "^1.5.4", "yjs": ">=13.5.42" + }, + "dependencies": { + "prettier": { + "version": "3.4.2", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.4.2.tgz", + "integrity": "sha512-e9MewbtFo+Fevyuxn/4rrcDAaq0IYxPGLvObpQjiZBMAzB9IGmzlnG9RZy3FFas+eBMu2vA0CszMeduow5dIuQ==" + } } }, "lib0": { @@ -57845,11 +57844,6 @@ "integrity": "sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==", "dev": true }, - "make-synchronized": { - "version": "0.2.9", - "resolved": "https://registry.npmjs.org/make-synchronized/-/make-synchronized-0.2.9.tgz", - "integrity": "sha512-4wczOs8SLuEdpEvp3vGo83wh8rjJ78UsIk7DIX5fxdfmfMJGog4bQzxfvOwq7Q3yCHLC4jp1urPHIxRS/A93gA==" - }, "makeerror": { "version": "1.0.12", "resolved": "https://registry.npmjs.org/makeerror/-/makeerror-1.0.12.tgz", @@ -61553,9 +61547,10 @@ "dev": true }, "prettier": { - "version": "3.5.3", - "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.5.3.tgz", - "integrity": "sha512-QQtaxnoDJeAkDvDKWCLiwIXkTgRhwYDEQCghU9Z6q03iyek/rxRh/2lC3HB7P8sWT2xC/y5JDctPLBIGzHKbhw==" + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-2.7.1.tgz", + "integrity": "sha512-ujppO+MkdPqoVINuDFDRLClm7D78qbDt0/NR+wp5FqEZOoTNAjPHWj17QRhu7geIHJfcNhRk1XVQmF8Bp3ye+g==", + "dev": true }, "prettier-plugin-hermes-parser": { "version": "0.26.0", @@ -61569,15 +61564,15 @@ } }, "prettier-plugin-organize-attributes": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/prettier-plugin-organize-attributes/-/prettier-plugin-organize-attributes-1.0.0.tgz", - "integrity": "sha512-+NmameaLxbCcylEXsKPmawtzla5EE6ECqvGkpfQz4KM847fXDifB1gFnPQEpoADAq6IXg+cMI8Z0ISJEXa6fhg==", + "version": "0.0.5", + "resolved": "https://registry.npmjs.org/prettier-plugin-organize-attributes/-/prettier-plugin-organize-attributes-0.0.5.tgz", + "integrity": "sha512-dSts16q8wd+oq8Zwk5mwmYXo1aN3B+ZkEJqx/ar5fedNHdOvx7S4XDMH/pNK7rmBW0bPXkp/kJX5gAANsWzh3A==", "dev": true }, "prettier-plugin-tailwindcss": { - "version": "0.6.11", - "resolved": "https://registry.npmjs.org/prettier-plugin-tailwindcss/-/prettier-plugin-tailwindcss-0.6.11.tgz", - "integrity": "sha512-YxaYSIvZPAqhrrEpRtonnrXdghZg1irNg4qrjboCXrpybLWVs55cW2N3juhspVJiO0JBvYJT8SYsJpc8OQSnsA==", + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/prettier-plugin-tailwindcss/-/prettier-plugin-tailwindcss-0.4.1.tgz", + "integrity": "sha512-hwn2EiJmv8M+AW4YDkbjJ6HlZCTzLyz1QlySn9sMuKV/Px0fjwldlB7tol8GzdgqtkdPtzT3iJ4UzdnYXP25Ag==", "dev": true }, "pretty-error": { diff --git a/package.json b/package.json index cd177852564..20e3d93c8d3 100644 --- a/package.json +++ b/package.json @@ -130,6 +130,7 @@ "@types/jsdom": "^21.1.6", "@types/katex": "^0.16.7", "@types/node": "^17.0.31", + "@types/prettier": "^2.7.3", "@types/prismjs": "^1.26.0", "@types/proper-lockfile": "^4.1.4", "@types/react": "^18.0.8", @@ -173,10 +174,10 @@ "lint-staged": "^11.1.0", "minimist": "^1.2.5", "npm-run-all": "^4.1.5", - "prettier": "^3.5.3", + "prettier": "^2.3.2", "prettier-plugin-hermes-parser": "^0.26.0", - "prettier-plugin-organize-attributes": "^1.0.0", - "prettier-plugin-tailwindcss": "^0.6.11", + "prettier-plugin-organize-attributes": "^0.0.5", + "prettier-plugin-tailwindcss": "^0.4.1", "proper-lockfile": "^4.1.2", "react-test-renderer": "^17.0.2", "rollup": "^4.22.4", @@ -189,7 +190,6 @@ "vite": "^5.2.11" }, "dependencies": { - "@prettier/sync": "^0.5.2", "yjs": "^13.5.42" } } diff --git a/packages/lexical-eslint-plugin/src/__tests__/unit/rules-of-lexical.test.ts b/packages/lexical-eslint-plugin/src/__tests__/unit/rules-of-lexical.test.ts index bebee3e8a58..5845696dc83 100644 --- a/packages/lexical-eslint-plugin/src/__tests__/unit/rules-of-lexical.test.ts +++ b/packages/lexical-eslint-plugin/src/__tests__/unit/rules-of-lexical.test.ts @@ -6,10 +6,10 @@ * */ -import * as prettierSync from '@prettier/sync'; import {RuleTester} from 'eslint'; import * as fs from 'node:fs'; import * as path from 'node:path'; +import * as prettier from 'prettier'; import plugin from '../../LexicalEslintPlugin.js'; import {type RulesOfLexicalOptions} from '../../rules/rules-of-lexical.js'; @@ -39,7 +39,7 @@ function fmt( keys.forEach((key, i) => { result.push(key(name), strings[i + 1]); }); - return prettierSync.format(result.join(''), {parser: 'typescript'}); + return prettier.format(result.join(''), {parser: 'typescript'}); }; rval.keys = keys; rval.setOptions = (opts: RulesOfLexicalOptions) => { diff --git a/packages/lexical-list/src/__tests__/utils.ts b/packages/lexical-list/src/__tests__/utils.ts index 13b75de4338..aa95a7a01b0 100644 --- a/packages/lexical-list/src/__tests__/utils.ts +++ b/packages/lexical-list/src/__tests__/utils.ts @@ -6,7 +6,7 @@ * */ import {expect} from '@playwright/test'; -import * as prettierSync from '@prettier/sync'; +import prettier from 'prettier'; // This tag function is just used to trigger prettier auto-formatting. // (https://prettier.io/blog/2020/08/24/2.1.0.html#api) @@ -29,5 +29,5 @@ export function expectHtmlToBeEqual(expected: string, actual: string): void { } export function prettifyHtml(s: string): string { - return prettierSync.format(s.replace(/\n/g, ''), {parser: 'html'}); + return prettier.format(s.replace(/\n/g, ''), {parser: 'html'}); } diff --git a/packages/lexical-playground/__tests__/utils/index.mjs b/packages/lexical-playground/__tests__/utils/index.mjs index ad4d9052a30..deb209bfda9 100644 --- a/packages/lexical-playground/__tests__/utils/index.mjs +++ b/packages/lexical-playground/__tests__/utils/index.mjs @@ -9,7 +9,7 @@ import {expect, test as base} from '@playwright/test'; import * as glob from 'glob'; import {randomUUID} from 'node:crypto'; -import * as prettier from 'prettier'; +import prettier from 'prettier'; import * as lockfile from 'proper-lockfile'; import {URLSearchParams} from 'url'; diff --git a/packages/lexical-playground/package.json b/packages/lexical-playground/package.json index 609947f4bd9..34e991c45c8 100644 --- a/packages/lexical-playground/package.json +++ b/packages/lexical-playground/package.json @@ -29,7 +29,7 @@ "katex": "^0.16.10", "lexical": "0.27.2", "lodash-es": "^4.17.21", - "prettier": "^3.5.3", + "prettier": "^3.4.2", "react": "^18.2.0", "react-dom": "^18.2.0", "react-error-boundary": "^3.1.4", diff --git a/packages/lexical-website/package.json b/packages/lexical-website/package.json index 3145e16ceb7..54294b27479 100644 --- a/packages/lexical-website/package.json +++ b/packages/lexical-website/package.json @@ -34,7 +34,7 @@ }, "devDependencies": { "buffer": "^6.0.3", - "prettier-plugin-tailwindcss": "^0.6.11", + "prettier-plugin-tailwindcss": "^0.4.1", "tailwindcss": "^3.3.3", "typedoc": "^0.25.12", "typescript": "^5.4.5", diff --git a/packages/lexical/src/__tests__/utils/index.tsx b/packages/lexical/src/__tests__/utils/index.tsx index 31204e47258..3eeecec272d 100644 --- a/packages/lexical/src/__tests__/utils/index.tsx +++ b/packages/lexical/src/__tests__/utils/index.tsx @@ -26,7 +26,6 @@ import { import {HeadingNode, QuoteNode} from '@lexical/rich-text'; import {TableCellNode, TableNode, TableRowNode} from '@lexical/table'; import {expect} from '@playwright/test'; -import * as prettierSync from '@prettier/sync'; import { $isRangeSelection, createEditor, @@ -46,6 +45,7 @@ import { TextNode, } from 'lexical'; import path from 'path'; +import * as prettier from 'prettier'; import * as React from 'react'; import {createRef} from 'react'; import {createRoot} from 'react-dom/client'; @@ -58,7 +58,7 @@ import { } from '../../LexicalEditor'; import {resetRandomKey} from '../../LexicalUtils'; -const prettierConfig = prettierSync.resolveConfig( +const prettierConfig = prettier.resolveConfig.sync( path.resolve(__dirname, '../../../../.prettierrc'), ); @@ -784,7 +784,7 @@ export function expectHtmlToBeEqual(actual: string, expected: string): void { } export function prettifyHtml(s: string): string { - return prettierSync.format(s.replace(/\n/g, ''), { + return prettier.format(s.replace(/\n/g, ''), { ...prettierConfig, parser: 'html', }); diff --git a/scripts/error-codes/__tests__/unit/transform-error-messages.test.js b/scripts/error-codes/__tests__/unit/transform-error-messages.test.js index 6e2d1b30147..20f51881876 100644 --- a/scripts/error-codes/__tests__/unit/transform-error-messages.test.js +++ b/scripts/error-codes/__tests__/unit/transform-error-messages.test.js @@ -12,9 +12,9 @@ const fs = require('fs-extra'); const path = require('node:path'); const transformErrorMessages = require('../../transform-error-messages'); const babel = require('@babel/core'); -const prettierSync = require('@prettier/sync'); +const prettier = require('prettier'); -const prettierConfig = prettierSync.resolveConfig('./') || {}; +const prettierConfig = prettier.resolveConfig.sync('./') || {}; /** @returns {Promise<void>} */ function waitTick() { @@ -39,13 +39,7 @@ async function withCodes(before, after, cb) { } } -/** - * - * @param {TemplateStringsArray} strings - * @param {...unknown} keys - * @returns - */ -function fmt(strings, ...keys) { +function fmt(strings: TemplateStringsArray, ...keys: unknown[]) { const result = [strings[0]]; keys.forEach((key, i) => { result.push(String(key), strings[i + 1]); @@ -65,7 +59,7 @@ function fmt(strings, ...keys) { 'format$1ErrorMessage', ) .trim(); - return prettierSync.format(before, { + return prettier.format(before, { ...prettierConfig, filepath: 'test.js', }); diff --git a/scripts/error-codes/transform-error-messages.js b/scripts/error-codes/transform-error-messages.js index cb9ea1a882a..3ccfd24a957 100644 --- a/scripts/error-codes/transform-error-messages.js +++ b/scripts/error-codes/transform-error-messages.js @@ -13,7 +13,7 @@ const fs = require('fs-extra'); const ErrorMap = require('./ErrorMap'); const evalToString = require('./evalToString'); const helperModuleImports = require('@babel/helper-module-imports'); -const prettierSync = require('@prettier/sync'); +const prettier = require('prettier'); /** @type {Map<string, ErrorMap>} */ const errorMaps = new Map(); @@ -29,13 +29,13 @@ function getErrorMap(filepath) { let errorMap = errorMaps.get(filepath); if (!errorMap) { const prettierConfig = { - ...(prettierSync.resolveConfig('./') || {}), + ...(prettier.resolveConfig.sync('./') || {}), filepath, }; errorMap = new ErrorMap(fs.readJsonSync(filepath), (newErrorMap) => fs.writeFileSync( filepath, - prettierSync.format(JSON.stringify(newErrorMap), prettierConfig), + prettier.format(JSON.stringify(newErrorMap), prettierConfig), ), ); errorMaps.set(filepath, errorMap); From 35349e18b11e925ef67c1be5b92fb285392c1403 Mon Sep 17 00:00:00 2001 From: Bob Ippolito <bob@redivi.com> Date: Mon, 17 Mar 2025 12:39:44 -0700 Subject: [PATCH 10/10] downgrade playground prettier --- package-lock.json | 23 ++++++++++--------- package.json | 2 +- packages/lexical-headless/src/index.ts | 2 +- packages/lexical-playground/package.json | 2 +- .../lexical-table/src/LexicalTableCellNode.ts | 2 +- packages/lexical/src/LexicalUpdates.ts | 2 +- packages/lexical/src/caret/LexicalCaret.ts | 3 ++- 7 files changed, 19 insertions(+), 17 deletions(-) diff --git a/package-lock.json b/package-lock.json index 2593e2c90b8..cdc0a35bc58 100644 --- a/package-lock.json +++ b/package-lock.json @@ -79,7 +79,7 @@ "lint-staged": "^11.1.0", "minimist": "^1.2.5", "npm-run-all": "^4.1.5", - "prettier": "^2.3.2", + "prettier": "^2.8.8", "prettier-plugin-hermes-parser": "^0.26.0", "prettier-plugin-organize-attributes": "^0.0.5", "prettier-plugin-tailwindcss": "^0.4.1", @@ -32021,9 +32021,9 @@ } }, "node_modules/prettier": { - "version": "2.7.1", - "resolved": "https://registry.npmjs.org/prettier/-/prettier-2.7.1.tgz", - "integrity": "sha512-ujppO+MkdPqoVINuDFDRLClm7D78qbDt0/NR+wp5FqEZOoTNAjPHWj17QRhu7geIHJfcNhRk1XVQmF8Bp3ye+g==", + "version": "2.8.8", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-2.8.8.tgz", + "integrity": "sha512-tdN8qQGvNjw4CHbY+XXk0JgCXn9QiF21a55rBe5LJAU+kDyC4WQn4+awm2Xfk2lQMk5fKup9XgzTZtGkjBdP9Q==", "dev": true, "bin": { "prettier": "bin-prettier.js" @@ -40225,6 +40225,7 @@ "version": "0.27.2", "license": "MIT", "dependencies": { + "@lexical/selection": "0.27.2", "@lexical/utils": "0.27.2", "lexical": "0.27.2" } @@ -40300,7 +40301,7 @@ "katex": "^0.16.10", "lexical": "0.27.2", "lodash-es": "^4.17.21", - "prettier": "^3.4.2", + "prettier": "^2.8.8", "react": "^18.2.0", "react-dom": "^18.2.0", "react-error-boundary": "^3.1.4", @@ -45274,6 +45275,7 @@ "@lexical/list": { "version": "file:packages/lexical-list", "requires": { + "@lexical/selection": "0.27.2", "@lexical/utils": "0.27.2", "lexical": "0.27.2" } @@ -57313,7 +57315,7 @@ "katex": "^0.16.10", "lexical": "0.27.2", "lodash-es": "^4.17.21", - "prettier": "^3.4.2", + "prettier": "^2.8.8", "react": "^18.2.0", "react-dom": "^18.2.0", "react-error-boundary": "^3.1.4", @@ -57325,8 +57327,7 @@ }, "dependencies": { "prettier": { - "version": "3.4.2", - "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.4.2.tgz", + "version": "https://registry.npmjs.org/prettier/-/prettier-3.4.2.tgz", "integrity": "sha512-e9MewbtFo+Fevyuxn/4rrcDAaq0IYxPGLvObpQjiZBMAzB9IGmzlnG9RZy3FFas+eBMu2vA0CszMeduow5dIuQ==" } } @@ -61547,9 +61548,9 @@ "dev": true }, "prettier": { - "version": "2.7.1", - "resolved": "https://registry.npmjs.org/prettier/-/prettier-2.7.1.tgz", - "integrity": "sha512-ujppO+MkdPqoVINuDFDRLClm7D78qbDt0/NR+wp5FqEZOoTNAjPHWj17QRhu7geIHJfcNhRk1XVQmF8Bp3ye+g==", + "version": "2.8.8", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-2.8.8.tgz", + "integrity": "sha512-tdN8qQGvNjw4CHbY+XXk0JgCXn9QiF21a55rBe5LJAU+kDyC4WQn4+awm2Xfk2lQMk5fKup9XgzTZtGkjBdP9Q==", "dev": true }, "prettier-plugin-hermes-parser": { diff --git a/package.json b/package.json index 20e3d93c8d3..36abab2201f 100644 --- a/package.json +++ b/package.json @@ -174,7 +174,7 @@ "lint-staged": "^11.1.0", "minimist": "^1.2.5", "npm-run-all": "^4.1.5", - "prettier": "^2.3.2", + "prettier": "^2.8.8", "prettier-plugin-hermes-parser": "^0.26.0", "prettier-plugin-organize-attributes": "^0.0.5", "prettier-plugin-tailwindcss": "^0.4.1", diff --git a/packages/lexical-headless/src/index.ts b/packages/lexical-headless/src/index.ts index 2b8eddb8ed3..04a18d356b7 100644 --- a/packages/lexical-headless/src/index.ts +++ b/packages/lexical-headless/src/index.ts @@ -33,7 +33,7 @@ export function createHeadlessEditor( 'blur', ] as const; - unsupportedMethods.forEach((method: typeof unsupportedMethods[number]) => { + unsupportedMethods.forEach((method: (typeof unsupportedMethods)[number]) => { editor[method] = () => { throw new Error(`${method} is not supported in headless mode`); }; diff --git a/packages/lexical-playground/package.json b/packages/lexical-playground/package.json index 34e991c45c8..7fd63ccb16a 100644 --- a/packages/lexical-playground/package.json +++ b/packages/lexical-playground/package.json @@ -29,7 +29,7 @@ "katex": "^0.16.10", "lexical": "0.27.2", "lodash-es": "^4.17.21", - "prettier": "^3.4.2", + "prettier": "^2.8.8", "react": "^18.2.0", "react-dom": "^18.2.0", "react-error-boundary": "^3.1.4", diff --git a/packages/lexical-table/src/LexicalTableCellNode.ts b/packages/lexical-table/src/LexicalTableCellNode.ts index 987ba11d51d..9ba1a49947c 100644 --- a/packages/lexical-table/src/LexicalTableCellNode.ts +++ b/packages/lexical-table/src/LexicalTableCellNode.ts @@ -41,7 +41,7 @@ export const TableCellHeaderStates = { }; export type TableCellHeaderState = - typeof TableCellHeaderStates[keyof typeof TableCellHeaderStates]; + (typeof TableCellHeaderStates)[keyof typeof TableCellHeaderStates]; export type SerializedTableCellNode = Spread< { diff --git a/packages/lexical/src/LexicalUpdates.ts b/packages/lexical/src/LexicalUpdates.ts index fb151f5fb7f..0e1012e4e88 100644 --- a/packages/lexical/src/LexicalUpdates.ts +++ b/packages/lexical/src/LexicalUpdates.ts @@ -133,7 +133,7 @@ function collectBuildInformation(): string { } else if (editor) { let version = String( ( - editor.constructor as typeof editor['constructor'] & + editor.constructor as (typeof editor)['constructor'] & Record<string, unknown> ).version || '<0.17.1', ); diff --git a/packages/lexical/src/caret/LexicalCaret.ts b/packages/lexical/src/caret/LexicalCaret.ts index c1af5986087..25ca9c53c78 100644 --- a/packages/lexical/src/caret/LexicalCaret.ts +++ b/packages/lexical/src/caret/LexicalCaret.ts @@ -22,7 +22,8 @@ export type CaretDirection = 'next' | 'previous'; /** * A type utility to flip next and previous */ -export type FlipDirection<D extends CaretDirection> = typeof FLIP_DIRECTION[D]; +export type FlipDirection<D extends CaretDirection> = + (typeof FLIP_DIRECTION)[D]; /** * A sibling caret type points from a LexicalNode origin to its next or previous sibling, * and a child caret type points from an ElementNode origin to its first or last child.