Skip to content

Commit

Permalink
Make root selectable
Browse files Browse the repository at this point in the history
More changes

fix e2e

Ensure HR has text content
  • Loading branch information
trueadm committed Feb 17, 2022
1 parent 18f6ef9 commit 4d32c0a
Show file tree
Hide file tree
Showing 36 changed files with 412 additions and 492 deletions.
3 changes: 1 addition & 2 deletions .flowconfig
Original file line number Diff line number Diff line change
Expand Up @@ -73,15 +73,14 @@ module.name_mapper='^@lexical/react/LexicalCollaborationPlugin' -> '<PROJECT_ROO
module.name_mapper='^@lexical/react/LexicalTablePlugin' -> '<PROJECT_ROOT>/packages/lexical-react/src/LexicalTablePlugin.js'
module.name_mapper='^@lexical/react/LexicalLinkPlugin' -> '<PROJECT_ROOT>/packages/lexical-react/src/LexicalLinkPlugin.js'
module.name_mapper='^@lexical/react/LexicalAutoLinkPlugin' -> '<PROJECT_ROOT>/packages/lexical-react/src/LexicalAutoLinkPlugin.js'
module.name_mapper='^@lexical/react/LexicalHorizontalRulePlugin' -> '<PROJECT_ROOT>/packages/lexical-react/src/LexicalHorizontalRulePlugin.js'
module.name_mapper='^@lexical/react/LexicalListPlugin' -> '<PROJECT_ROOT>/packages/lexical-react/src/LexicalListPlugin.js'
module.name_mapper='^@lexical/react/LexicalOnChangePlugin' -> '<PROJECT_ROOT>/packages/lexical-react/src/LexicalOnChangePlugin.js'

module.name_mapper='^@lexical/yjs$' -> '<PROJECT_ROOT>/packages/lexical-yjs/src/index.js'

module.name_mapper='^shared/invariant' -> '<PROJECT_ROOT>/packages/shared/src/invariant.js'
module.name_mapper='^shared/environment' -> '<PROJECT_ROOT>/packages/shared/src/environment.js'
module.name_mapper='^shared/getPossibleDecoratorOrHorizontalRuleNode' -> '<PROJECT_ROOT>/packages/shared/src/getPossibleDecoratorOrHorizontalRuleNode.js'
module.name_mapper='^shared/getPossibleDecoratorNode' -> '<PROJECT_ROOT>/packages/shared/src/getPossibleDecoratorNode.js'
module.name_mapper='^shared/useLayoutEffect' -> '<PROJECT_ROOT>/packages/shared/src/useLayoutEffect.js'
module.name_mapper='^shared/canUseDOM' -> '<PROJECT_ROOT>/packages/shared/src/canUseDOM.js'

Expand Down
4 changes: 2 additions & 2 deletions jest.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -86,8 +86,8 @@ module.exports = {
'<rootDir>/packages/lexical/src/nodes/extended/LexicalQuoteNode.js',
'^shared/canUseDOM$': '<rootDir>/packages/shared/src/canUseDOM.js',
'^shared/environment$': '<rootDir>/packages/shared/src/environment.js',
'^shared/getPossibleDecoratorOrHorizontalRuleNode$':
'<rootDir>/packages/shared/src/getPossibleDecoratorOrHorizontalRuleNode.js',
'^shared/getPossibleDecoratorNode$':
'<rootDir>/packages/shared/src/getPossibleDecoratorNode.js',
'^shared/invariant$': '<rootDir>/packages/shared/src/invariant.js',
'^shared/useLayoutEffect$':
'<rootDir>/packages/shared/src/useLayoutEffect.js',
Expand Down
10 changes: 3 additions & 7 deletions packages/lexical-helpers/src/LexicalEventHelpers.js
Original file line number Diff line number Diff line change
Expand Up @@ -27,14 +27,13 @@ import {
$getSelection,
$isDecoratorNode,
$isElementNode,
$isHorizontalRuleNode,
$isTextNode,
$log,
} from 'lexical';
import {$createCodeNode} from 'lexical/CodeNode';
import {$createHeadingNode} from 'lexical/HeadingNode';
import {$createLinkNode} from 'lexical/LinkNode';
import getPossibleDecoratorOrHorizontalRuleNode from 'shared/getPossibleDecoratorOrHorizontalRuleNode';
import getPossibleDecoratorNode from 'shared/getPossibleDecoratorNode';

// TODO the Flow types here needs fixing
export type EventHandler = (
Expand Down Expand Up @@ -351,11 +350,8 @@ export function $shouldOverrideDefaultCharacterSelection(
selection: RangeSelection,
isBackward: boolean,
): boolean {
const possibleNode = getPossibleDecoratorOrHorizontalRuleNode(
selection.focus,
isBackward,
);
return $isDecoratorNode(possibleNode) || $isHorizontalRuleNode(possibleNode);
const possibleNode = getPossibleDecoratorNode(selection.focus, isBackward);
return $isDecoratorNode(possibleNode) && !possibleNode.isIsolated();
}

export function onPasteForPlainText(
Expand Down
9 changes: 7 additions & 2 deletions packages/lexical-helpers/src/LexicalSelectionHelpers.js
Original file line number Diff line number Diff line change
Expand Up @@ -155,7 +155,10 @@ export function $cloneContents(selection: RangeSelection): {
let nodesLength = nodes.length;
const firstNode = nodes[0];
const firstNodeParent = firstNode.getParent();
if (firstNodeParent !== null && !firstNodeParent.canBeEmpty()) {
if (
firstNodeParent !== null &&
(!firstNodeParent.canBeEmpty() || $isRootNode(firstNodeParent))
) {
const parentChildren = firstNodeParent.__children;
const parentChildrenLength = parentChildren.length;
if (parentChildrenLength === nodesLength) {
Expand Down Expand Up @@ -397,7 +400,9 @@ export function $moveCaretSelection(

export function $isParentElementRTL(selection: RangeSelection): boolean {
const anchorNode = selection.anchor.getNode();
const parent = anchorNode.getParentOrThrow();
const parent = $isRootNode(anchorNode)
? anchorNode
: anchorNode.getParentOrThrow();
return parent.getDirection() === 'rtl';
}

Expand Down
80 changes: 78 additions & 2 deletions packages/lexical-playground/__tests__/e2e/HorizontalRule-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import {
waitForSelector,
click,
E2E_BROWSER,
repeat,
} from '../utils';

describe('HorizontalRule', () => {
Expand All @@ -38,6 +39,11 @@ describe('HorizontalRule', () => {
'<p class="PlaygroundEditorTheme__paragraph m8h3af8h l7ghb35v kmwttqpk mfn553m3 om3e55n1 gjezrb0y"><br /></p><hr contenteditable="false" /><p class="PlaygroundEditorTheme__paragraph m8h3af8h l7ghb35v kmwttqpk mfn553m3 om3e55n1 gjezrb0y"><br /></p>',
);

await assertHTML(
page,
'<p class="PlaygroundEditorTheme__paragraph m8h3af8h l7ghb35v kmwttqpk mfn553m3 om3e55n1 gjezrb0y"><br></p><div data-lexical-decorator="true" contenteditable="false" style="display: contents;"><hr></div><p class="PlaygroundEditorTheme__paragraph m8h3af8h l7ghb35v kmwttqpk mfn553m3 om3e55n1 gjezrb0y"><br></p>',
);

await assertSelection(page, {
anchorPath: [2],
anchorOffset: 0,
Expand Down Expand Up @@ -85,6 +91,73 @@ describe('HorizontalRule', () => {

await page.keyboard.type('Some more text');

await assertHTML(
page,
'<p class="PlaygroundEditorTheme__paragraph m8h3af8h l7ghb35v kmwttqpk mfn553m3 om3e55n1 gjezrb0y PlaygroundEditorTheme__ltr gkum2dnh" dir="ltr"><span data-lexical-text="true">Some text</span></p><div data-lexical-decorator="true" contenteditable="false" style="display: contents;"><hr></div><p class="PlaygroundEditorTheme__paragraph m8h3af8h l7ghb35v kmwttqpk mfn553m3 om3e55n1 gjezrb0y PlaygroundEditorTheme__ltr gkum2dnh" dir="ltr"><span data-lexical-text="true">Some more text</span></p>',
);

await assertSelection(page, {
anchorPath: [0],
anchorOffset: 0,
focusPath: [0],
focusOffset: 0,
});

await page.keyboard.press('ArrowRight');

await assertSelection(page, {
anchorPath: [2],
anchorOffset: 0,
focusPath: [2],
focusOffset: 0,
});

await page.keyboard.press('ArrowLeft');

await assertSelection(page, {
anchorPath: [0],
anchorOffset: 0,
focusPath: [0],
focusOffset: 0,
});

await repeat(10, async () => {
await page.keyboard.press('Backspace');
});

await assertHTML(
page,
'<div data-lexical-decorator="true" contenteditable="false" style="display: contents;"><hr></div><p class="PlaygroundEditorTheme__paragraph m8h3af8h l7ghb35v kmwttqpk mfn553m3 om3e55n1 gjezrb0y PlaygroundEditorTheme__ltr gkum2dnh" dir="ltr"><span data-lexical-text="true">Some more text</span></p>',
);

await assertSelection(page, {
anchorPath: [],
anchorOffset: 0,
focusPath: [],
focusOffset: 0,
});
},
);

it.skipIf(
e2e.isPlainText,
'Will add a horizontal rule at the end of a current TextNode and move selection to the new ParagraphNode.',
async () => {
const {page} = e2e;

await page.keyboard.type('Some text');

await page.keyboard.press('ArrowRight');

await assertSelection(page, {
anchorPath: [2],
anchorOffset: 0,
focusPath: [2],
focusOffset: 0,
});

await page.keyboard.type('Some more text');

await assertHTML(
page,
'<p class="PlaygroundEditorTheme__paragraph m8h3af8h l7ghb35v kmwttqpk mfn553m3 om3e55n1 gjezrb0y PlaygroundEditorTheme__ltr gkum2dnh" dir="ltr"><span data-lexical-text="true">Some text</span></p><hr contenteditable="false"><p class="PlaygroundEditorTheme__paragraph m8h3af8h l7ghb35v kmwttqpk mfn553m3 om3e55n1 gjezrb0y PlaygroundEditorTheme__ltr gkum2dnh" dir="ltr"><span data-lexical-text="true">Some more text</span></p>',
Expand Down Expand Up @@ -138,7 +211,10 @@ describe('HorizontalRule', () => {

await click(page, 'button .horizontal-rule');

await waitForSelector(page, 'hr');
await assertHTML(
page,
'<p class="PlaygroundEditorTheme__paragraph m8h3af8h l7ghb35v kmwttqpk mfn553m3 om3e55n1 gjezrb0y PlaygroundEditorTheme__ltr gkum2dnh" dir="ltr"><span data-lexical-text="true">Test</span></p><div data-lexical-decorator="true" contenteditable="false" style="display: contents;"><hr></div><p class="PlaygroundEditorTheme__paragraph m8h3af8h l7ghb35v kmwttqpk mfn553m3 om3e55n1 gjezrb0y"><br></p>',
);

await assertHTML(
page,
Expand Down Expand Up @@ -194,7 +270,7 @@ describe('HorizontalRule', () => {

await assertHTML(
page,
'<p class="PlaygroundEditorTheme__paragraph m8h3af8h l7ghb35v kmwttqpk mfn553m3 om3e55n1 gjezrb0y PlaygroundEditorTheme__ltr gkum2dnh" dir="ltr"><span data-lexical-text="true">Te</span></p><hr contenteditable="false"><p class="PlaygroundEditorTheme__paragraph m8h3af8h l7ghb35v kmwttqpk mfn553m3 om3e55n1 gjezrb0y PlaygroundEditorTheme__ltr gkum2dnh" dir="ltr"><span data-lexical-text="true">st</span></p>',
'<p class="PlaygroundEditorTheme__paragraph m8h3af8h l7ghb35v kmwttqpk mfn553m3 om3e55n1 gjezrb0y PlaygroundEditorTheme__ltr gkum2dnh" dir="ltr"><span data-lexical-text="true">Te</span></p><div data-lexical-decorator="true" contenteditable="false" style="display: contents;"><hr></div><p class="PlaygroundEditorTheme__paragraph m8h3af8h l7ghb35v kmwttqpk mfn553m3 om3e55n1 gjezrb0y PlaygroundEditorTheme__ltr gkum2dnh" dir="ltr"><span data-lexical-text="true">st</span></p>',
);

await assertSelection(page, {
Expand Down
8 changes: 8 additions & 0 deletions packages/lexical-playground/__tests__/utils/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -167,6 +167,14 @@ export function initializeE2E(runTests, config: Config = {}) {
newIt(description, test);
}
};
} else {
it.skipIf = async (condition, description, test) => {
if (typeof condition === 'function' ? condition() : !!condition) {
it.skip(description, test);
} else {
it(description, test);
}
};
}

runTests(e2e);
Expand Down
1 change: 0 additions & 1 deletion packages/lexical-playground/craco.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,6 @@ module.exports = {
'LexicalAutoFormatterPlugin',
'LexicalCharacterLimitPlugin',
'LexicalHashtagPlugin',
'LexicalHorizontalRulePlugin',
'LexicalPlainTextPlugin',
'LexicalRichTextPlugin',
'LexicalBootstrapPlugin',
Expand Down
2 changes: 1 addition & 1 deletion packages/lexical-playground/src/Editor.js
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,6 @@ import TableCellActionMenuPlugin from './plugins/TableActionMenuPlugin';
import ImagesPlugin from './plugins/ImagesPlugin';
import ExcalidrawPlugin from './plugins/ExcalidrawPlugin';
import LinkPlugin from '@lexical/react/LexicalLinkPlugin';
import HorizontalRulePlugin from '@lexical/react/LexicalHorizontalRulePlugin';
import SpeechToTextPlugin from './plugins/SpeechToTextPlugin';
import CodeHighlightPlugin from './plugins/CodeHighlightPlugin';
import Placeholder from './ui/Placeholder';
Expand All @@ -39,6 +38,7 @@ import {useSharedHistoryContext} from './context/SharedHistoryContext';
import ContentEditable from './ui/ContentEditable';
import AutoLinkPlugin from './plugins/AutoLinkPlugin';
import PollPlugin from './plugins/PollPlugin';
import HorizontalRulePlugin from './plugins/HorizontalRulePlugin';

import CharacterStylesPopupPlugin from './plugins/CharacterStylesPopupPlugin';
import {useSettings} from './context/SettingsContext';
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,36 +7,40 @@
* @flow strict
*/

import type {NodeKey} from '../../LexicalNode';
import type {LexicalNode} from 'lexical';

import {LexicalNode} from '../../LexicalNode';
import {DecoratorNode} from 'lexical';
import * as React from 'react';

export class HorizontalRuleNode extends LexicalNode {
function HorizontalRuleComponent() {
return <hr />;
}

export class HorizontalRuleNode extends DecoratorNode {
static getType(): string {
return 'horizontalrule';
}

static clone(node: HorizontalRuleNode): HorizontalRuleNode {
return new HorizontalRuleNode(node.__key);
return new HorizontalRuleNode(node.__state, node.__key);
}

constructor(key?: NodeKey): void {
super(key);
createDOM(): HTMLElement {
const div = document.createElement('div');
div.style.display = 'contents';
return div;
}

getTextContent(): '\n' {
return '\n';
}

createDOM(): HTMLElement {
const element = document.createElement('hr');
element.setAttribute('contenteditable', 'false');
return element;
}

updateDOM(): false {
return false;
}
decorate(): React$Node {
return <HorizontalRuleComponent />;
}
}

export function $createHorizontalRuleNode(): HorizontalRuleNode {
Expand Down
2 changes: 2 additions & 0 deletions packages/lexical-playground/src/nodes/PlaygroundNodes.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ import {TypeaheadNode} from './TypeaheadNode';
import {ImageNode} from './ImageNode';
import {KeywordNode} from './KeywordNode';
import {ExcalidrawNode} from './ExcalidrawNode';
import {HorizontalRuleNode} from './HorizontalRuleNode';
import ExtendedNodes from 'lexical/ExtendedNodes';

const PlaygroundNodes: Array<Class<LexicalNode>> = [
Expand All @@ -29,6 +30,7 @@ const PlaygroundNodes: Array<Class<LexicalNode>> = [
ExcalidrawNode,
TypeaheadNode,
KeywordNode,
HorizontalRuleNode,
];

export default PlaygroundNodes;
5 changes: 4 additions & 1 deletion packages/lexical-playground/src/nodes/PollNode.js
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ const styles = stylex.create({
padding: 15,
borderRadius: 10,
maxWidth: 600,
minWidth: 400,
},
heading: {
marginLeft: 0,
Expand Down Expand Up @@ -332,7 +333,9 @@ export class PollNode extends DecoratorNode {
}

createDOM(): HTMLElement {
return document.createElement('div');
const elem = document.createElement('span');
elem.style.display = 'inline-block';
return elem;
}

updateDOM(): false {
Expand Down
4 changes: 4 additions & 0 deletions packages/lexical-playground/src/nodes/StickyNode.js
Original file line number Diff line number Diff line change
Expand Up @@ -372,6 +372,10 @@ export class StickyNode extends DecoratorNode {
document.body,
);
}

isIsolated(): true {
return true;
}
}

export function $isStickyNode(node: ?LexicalNode): boolean %checks {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,11 @@
import type {CommandListenerEditorPriority} from 'lexical';

import {useLexicalComposerContext} from '@lexical/react/LexicalComposerContext';
import {$createHorizontalRuleNode, $getSelection, $log} from 'lexical';
import {$getSelection, $log} from 'lexical';
import {useEffect} from 'react';

import {$createHorizontalRuleNode} from '../nodes/HorizontalRuleNode';

const EditorPriority: CommandListenerEditorPriority = 0;

export default function HorizontalRulePlugin(): null {
Expand Down
5 changes: 4 additions & 1 deletion packages/lexical-playground/src/plugins/ImagesPlugin.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import type {CommandListenerEditorPriority} from 'lexical';

import {useLexicalComposerContext} from '@lexical/react/LexicalComposerContext';
import {useEffect} from 'react';
import {$log, $getSelection} from 'lexical';
import {$log, $getSelection, $isRootNode} from 'lexical';
import {$createImageNode, ImageNode} from '../nodes/ImageNode';

import yellowFlowerImage from '../images/image/yellow-flower.jpg';
Expand All @@ -33,6 +33,9 @@ export default function ImagesPlugin(): React$Node {
$log('insertImage');
const selection = $getSelection();
if (selection !== null) {
if ($isRootNode(selection.anchor.getNode())) {
selection.insertParagraph();
}
const imageNode = $createImageNode(
yellowFlowerImage,
'Yellow flower in tilt shift lens',
Expand Down
3 changes: 1 addition & 2 deletions packages/lexical-playground/src/plugins/ToolbarPlugin.js
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,6 @@ import {$createHeadingNode} from 'lexical/HeadingNode';
import {$isListNode, ListNode} from '@lexical/list';
import {$createQuoteNode} from 'lexical/QuoteNode';
import {$createCodeNode, $isCodeNode} from 'lexical/CodeNode';
import {$isHorizontalRuleNode} from 'lexical';
import {
$log,
$getNodeByKey,
Expand Down Expand Up @@ -530,7 +529,7 @@ export default function ToolbarPlugin(): React$Node {
if (selection !== null) {
const anchorNode = selection.anchor.getNode();
const element =
anchorNode.getKey() === 'root' || $isHorizontalRuleNode(anchorNode)
anchorNode.getKey() === 'root'
? anchorNode
: anchorNode.getTopLevelElementOrThrow();
const elementKey = element.getKey();
Expand Down
4 changes: 0 additions & 4 deletions packages/lexical-table/src/LexicalTableCellNode.js
Original file line number Diff line number Diff line change
Expand Up @@ -51,10 +51,6 @@ export class TableCellNode extends ElementNode {
collapseAtStart(): true {
return true;
}

canSelectionRemove(): boolean {
return false;
}
}

export function $createTableCellNode(isHeader: boolean): TableCellNode {
Expand Down
Loading

0 comments on commit 4d32c0a

Please sign in to comment.