GithubHelp home page GithubHelp logo

facebook / lexical Goto Github PK

View Code? Open in Web Editor NEW
17.2K 109.0 1.4K 42.56 MB

Lexical is an extensible text editor framework that provides excellent reliability, accessibility and performance.

Home Page: https://lexical.dev

License: MIT License

JavaScript 25.87% HTML 0.11% CSS 2.03% Shell 0.02% TypeScript 71.96% MDX 0.01%

lexical's Issues

Request: Add support for copy and pasting HTML content

This is a good first feature as it is a self-contained feature that has a fixed scope.

We don't support pasting HTML content into Outline currently. We only support plain-text and content that has come from Outline directly. Given that Draft supports HTML, we should also strive to support it. This will involve parsing HTML content and creating the respective Outline nodes for the content where possible (rich means it's really only for rich text mode). If we find invalid nodes, we should normalize/skip them if needed.

Doing a test

"Every one of us is, the cosmic perspective, precious. The human disagrees with you, let him love. In a hundred billion galaxies, you will not find another."
– Carl Sagan, cosmos

#this is a list:
*item 1
*item 2
*item 3

Request: Check for queueMicroTask

We should use this before falling back to Promise.resolve for Outline updates. Arguably, we should maybe only use queueMicroTask if we can.

Bug: Selection across paragraphs selects a ghost character

When the selection boundary crosses over to another line, looks like a ghost character is getting selected before the first/last character gets selected in the paragraph where selection is entering.

Steps (from the screencast below):

  • Place the caret after character B.
  • Use Shift+Arrow Right twice to select two characters.

Expected: 'B' & 'A' to be both selected.
Actual: 'B' & a ghost character are selected.

Screen.Recording.2021-03-11.at.12.15.22.PM.mov

Blocks break apart unexpectedly when text contains tabs

Repro

  • copy('ABD\tEFG') to your clipboard
  • Paste it into the Outline editor
  • NOTICE: you end up with two blocks (edit: text node) after you paste, instead of one.
  • Add the missing ‘C’
  • NOTICE: the text is now split among three blocks. Bad.
  • Press Fn-Option-Delete to delete forward

Chrome

You now have an empty block.

Screen.Recording.2021-03-01.at.4.12.08.PM.mov

Firefox

You fataled with Expected node _5 to have a parent.

Screen.Recording.2021-03-01.at.4.12.52.PM.mov

Fatal when deleting word forward before preceding tab

Repro

  1. Type Hello\u0009World
  2. Move cursor to end of word ‘Hello’
  3. Press fn-option-delete

Observe fatal.

Outline.js:1723 Uncaught Error: Expected node _4 to have a parent.
    at TextNode.getParentOrThrow (Outline.js:1723)
    at TextNode.getNextSibling (Outline.js:1791)
    at Selection.deleteWordForward (Outline.js:605)
    at onKeyDown (useOutlineInputEvents.js:161)
    at useOutlineEventWrapper.js:27
    at Outline.js:3214
    at enterViewModelScope (Outline.js:2760)
    at updateEditor (Outline.js:3209)
    at OutlineEditor.update (Outline.js:3405)
    at HTMLDivElement.<anonymous> (useOutlineEventWrapper.js:27)

Bug: Spellcheck triggers early because of custom insertText logic

By default (Chrome) spellchecker waits for 1-2 seconds before triggering, so if you're typing hous you can still type house without the error underline showing. This works fine when native event handler triggers:

<div texteditable="true" spellcheck="true"></div>

Outline handles the events itself (OutlineEventHandlers):

event.preventDefault(); <--
...
      case 'insertText':
      case 'insertFromComposition': {
        if (data) {
          insertText(selection, data); <-- type it manually
        }
        break;
      }

Repro: https://codepen.io/zurfyx/pen/zYoVdRx?editors=1010

The logic for insertText(selection: Selection, text: string) is quite complex but I believe that ultimately we could compare trees and determine whether the native input would equal the computed input, and if that's the case favor the native over ours.

(Handling the spellchecker API ourselves doesn't look possible in Chrome and we would also have to handle each browser separately.)

cc @trueadm

Bug: deleteWordBackward/deleteWordForward getTargetRanges handling of tab whitespace

I believe this is soemwhat related to #66.

When executing a deleteWordBackward and deleteWordForward on text that contains a tab when using getTargetRanges on Chrome (maybe Safari), it removes the tab as part of the word. Our polyfill doesn't do this, which @steveluscher mentioned was the expected behavior.

What do we do with this? If native beforeinput does this in all browsers, then maybe that is the correct thing to do, and we should update our polyfills?

Multiple classes applied when multiple flags are set on Text Node

If a text node has underline and strikethrough, Outline currently applies three classes if specified in the theme - underline, strikethrough, underlineStrikethrough. If these classes are set as below, one could be overriden by another depending on the order in the CSS file and cause text node to not have underlineStrikethrough in case it gets overriden by one of the other two.

# myStyles.css

.underlineStrikethrough {
  text-decoration: 'underline line-through';
}

.underline {
  text-decoration: 'underline';
}

.strikethrough {
  text-decoration: 'line-through';
}

Bug: segment error with empty text nodes

Steps to reproduce:

  • Insert '#foo'
  • Move selection to start
  • Type 'a'
  • Press Backspace
  • Manually move selection to end
  • Hold down Backspace

Notice that we have an editor error.

Move forward command can't escape empty block

Repro

  1. Enter the following text: \nHello
  2. Put your cursor at the beginning of the input
  3. Press the right arrow key

Observe that the cursor does not advance.

Screen.Recording.2021-01-27.at.10.37.07.AM.mov

Supporting Grammarly and Google Translate

DraftJS doesn't work with either because of many reasons that either: conflict with React's rendering, or just don't support Draft's internal model. I feel that we should do better here.

These browser plugins are not only heavily used by a large majority of the Internet, they also provide a much better experience for users that depend on these for accessibility reasons (which includes plugins other than these two).

I feel like we should spent some effort on investigating and possibly implementing support for these browser plugins. We can obviously disable them (you can use DOM attributes and classes to do so) but I feel like we should at least explore this space.

Bug: Ctrl+A/E unable to skip over mentions

Ideally Ctrl+A/E should behave the same as Cmd+ Left/Right and move the cursor Home/End, but when there's a mention in the editor Ctrl+A/E stops at the edge of the mention. Cmd + Left/Right works correctly.

This is due to a browser issue, and other editors like gmail behave the same way. Therefore this is a feature request.

Repro:

  1. Type a mention
  2. Type some text
  3. Press Ctrl+A and notice the cursor moves to the end of the mention, not the beginning of the line.
Screen.Recording.2021-04-01.at.11.53.54.AM.mov

Same is true if you type another mention and move the cursor between the two. Ctrl+A/E are blocked by the mentions on both sides.

Request: Adding newlines to <code> blocks should make new lines

Currently when you press enter on a code block, it exists the code block and creates a paragraph below. We should instead add a line break. If there are two consecutive line breaks, then we should break out of the code block and create a paragraph. This behavior would then be consistent with how code blocks work with Quip/Draft.

Bug: Copy + Paste creates unnecessary empty text nodes

When pasting in content from two blocks in Outline (rich text mode), and pasting that content, we end up with empty text nodes. I feel like this issue is likely to do with the fact we aren't calling block.normalizeTextNodes somewhere.

Steps:

  • Ensure in rich text mode
  • Type some text into the first block
  • Hit enter to create a new block and type some more text
  • Select all text and cut the content
  • Paste content into the editor
  • Notice the empty text nodes
Screen.Recording.2021-03-02.at.15.04.15.mov

Build broken

After merging the latest PRs, it seems that the build is broken. After looking into it, it looks related to usage of flatMap, which the CI node version does not support. We should probably upgrade the Node version on CI to a version that doesn support flatMap.

Ensure that all forms of whitespace (en spaces, em spaces, etc) are handled by the backward/forward word delete functions

When you press fn-Option-delete on a Mac keyboard to delete a word, the OS counts leading whitespace as part of the range to be deleted. This must include other kinds of whitespace, other than just U+0020.

Repro:

  1. Consider the string Hello\u2002World.
  2. Place the caret after the word ‘Hello’
  3. Press fn-Option-delete

The en space and the word ‘World’ should be deleted.

Then, consider all types of whitespace other than just \u2002.

selection: moving word backward/forward on the extremities of text that has siblings is glitchy

Steps to repro:

  • type foo bar baz

  • make bar a separate node by making it bold

  • move the caret so that the offset is positionned at the end of foo or the start of baz, spaces included, and try to move forward or backward respectively.

  • observe that the caret goes at the start of bar and not at the end as expected or only at the end when moving backward.

This is because in OutlineSelection:moveWordForward:1070 we do this, which basically does the selection if we looked ahead already.

 if (hasNewLine || lookAhead) {
              node.select(s, s);
              return;
            }

I tried to fix very naively but I broke other things doing so.

Delete backward/forward and move backward/forward should operate over whole graphemes

Consider these multi codepoint graphemes:

// 👨‍👩‍👧‍👧
const family = '\uD83D\uDC68\u200D\uD83D\uDC69\u200D\uD83D\uDC67\u200D\uD83D\uDC67';

// 👏🏽
const clappingHandsWithMediumSkinTone = '\uD83D\uDC4F\uD83C\uDFFD';

Right now you need to press the left/right arrow key four times to skip over the clapping Emoji:

Screen.Recording.2021-01-20.at.1.46.00.PM.mov

…and you need to press delete or fn-delete four times to eliminate it:

Screen.Recording.2021-01-20.at.1.44.39.PM.mov

Selecting a sticker in comment editor causes an automatic post

  1. turn on NVDA (I was using nvda at the time I don't know if that is relevant)
  2. select a post
  3. put cursor inside of comment editor
  4. select sticker

Result:
Comment is posted without selected sticker

Expected result:
sticker should be attached to comment

stickers.mp4

Plan: Set up an E2E test-suite

It occured to me that we should start to write down test cases that we feel help cover many of the weak/complex parts of Outline. It's always best to add regression tests as we add features or fix issues, but I'm well aware that this isn't necessarily do-able right now, as we are lacking testing infra to do so. So maybe we can update this issue with suggested e2e test flows so that we don't forget to add them later.

I've added the various permutations of keyboard controls we'd want to test in brackets (if there's more than one, or if it differs between platforms).

Test Cases

Test Case 1

  • Enter no text into editor. Press (Enter) to create a new paragraph, then press (Space) and type some text into the new paragraph. It should be possible to use keyboard arrows to return to the previous paragraph (All: Left, Right, Up, Down) and then move back to the new paragraph. It should also be possible to select all (Windows: CTRL+A, Mac: CMD+A) and delete (All: Backspace/Delete), removing the second paragraph and clearing out the first paragraph.

Bug: entering space in a hashtag is broken

Hashtags don't seem to function correctly when spaces are inserted anywhere in the hashtag. This includes

  • Add the end of a hashtag
  • In the middle of a hashtag
  • At the start of the hashtag

In fact, entering any text at the start of a hashtag also doesn't seem to work properly. It should be possible to enter text at the start and then delete that text again.

Plan: Handling Text Selection/Deletion

This is an umbrella issue to cover all the various use-cases for keyboard text selection and text deletion.

Note: we may change parts of this plan.

Keyboard Text Selection

Moving backward/forward

  • We should listen to left and right arrow events (without the relevant modifier for the OS)
  • We may have to apply some polyfills around moving selection between blocks
  • We may need to apply some custom logic around segmented/immutable nodes for accessibility purposes
  • Otherwise, should use the default native browser behavior

Deleting backward/forward

  • If beforeinput is supported we should attempt to use the boundary from getTargetRanges()
  • If beforeinput is not supported, we should apply a naive (and cheap) boundary implementation
  • We may need to apply some custom logic around the deletion of adjacent segmented/immutable nodes

Moving/Deleting a word backward/forward

  • If Intl.Segmenter is supported, we should always use this to work out the right word boundary
  • If Intl.Segmenter is not supported, we should check if native beforeinput is supported.
  • If beforeinput is supported we should attempt to use the boundary from getTargetRanges()
  • If beforeinput is not supported, we should apply a naive (and cheap) word boundary implementation

Moving/Deleting a line backward/forward

  • If beforeinput is supported we should attempt to use the line boundary from getTargetRanges()
  • If beforeinput is not supported, we should apply a naive approach and move the selection to the start of the current block.

Moving a block backward/forward

  • Should use the default native browser behavior

[outline-mentions-plugin] Creates paragraph erroneously upon detecting mention

Repro

  1. Fire up the Outline example (yarn install && yarn start)
  2. Type ‘Hello’
  3. Press option-enter for a newline
  4. Type something that triggers the mentions autocomplete (eg. ‘The’)

Observe that the newline gets erroneously converted into a paragraph as soon as a mentionable run of text is detected.

Untitled.mov

Code + Bold/Italic formatting buggy

Repro Steps

  1. Type some text, e.g. "Hello World"
  2. Select entire text
  3. Format with Bold
  4. Format with Code
  5. Unformat Bold

Expected Result

Code isn't bold anymore

Actual Result

See that the TextNode in the TreeView.js only has the code flag but the visual result is still bold, because the underlying tag is still <strong>.

image

Emoticons not working on return/enter

OS: Windows 10
Browser: Chrome

Test Steps:

  • Enter emoticon command ie :)
  • press enter

Expected results:
Emoticon turns into emojii

Actual results:
Emoticon stays emote

Actually run unit tests in parallel

Right now we have Circle CI set up to run tests in parallel but we're not actually distributing batches of tests across workers; we're just running all the tests 20 times.

image

Either de-configure this and use one worker, or look up a blog post on the internet that explains how to actually do test splitting with Jest, Circle CI, and jest-junit.

Bug: Outline doesn't work with Dragon Naturally Speaking

OS: Windows 10
Browser: Chrome 88
AT: Dragon Naturally Speaking Professional Group 15.61

Test Steps:

  1. Place focus in input field
  2. dictate some text

Expected results:
Placeholder text should disappear

Actual results:
dictated text is appended to placeholder text

dragon.mp4

Bug: Text cursor indicator not following cursor

OS: Windows 10
Browser: Chrome 88
AT: NVDA 2020.4, Text Cursor indicator

I have text cursor indicator turned on in windows and I noticed the indicator was not following the cursor when using up and down arrows to navigate between two paragraphs.

To turn on text cursor indicator:

  • Hit Windows Key
  • Type accessibility
  • Open the ease of access center
  • Navigate to "text cursor"
  • select the switch to "Turn on text cursor indicator"
  • adjust settings to make it easily to see, I attached a screenshot of mine

image

Test Steps
Write two paragraphs
Use the up arrow to navigate to the space between both paragraphs

Expected Results
The cursor indicator should follow the cursor

Actual Results
the cursor indicator stays in place and the cursor moves to the space between the paragraphs

Notes

  • hitting the up arrow a second time will rejoin the cursor with the cursor indicator
  • I noticed this is also an issue in github's text editor so it may be browser or OS related.

Screenshot
I couldn't find a way to actually screenshot the cursor so the red line shows where the cursor was when I took the screenshot.
image

Bug: Emotes do not change to emojii when dictated

OS: Windows 10
Browser: Chrome 88
AT: Dragon Naturally Speaking Professional Group 15.61

Test Steps:

  1. Place focus in input field
  2. Dictate: "Winky Face" "Frowny face", "Smiley face"

Actual Results
Emotes are written but stay emotes

Expected results
Emotes should convert to emojii

dragon.mp4

Recent regression with textNode.splitText

Since merging #121, we now encounter issues with focus restoration. Here's a repro using the playground:

  • Toggle on character limit
  • Type text until you hit limit
  • Should fatal

Unhandled Rejection (IndexSizeError): Failed to execute 'setBaseAndExtent' on 'Selection': The offset 31 is larger than the node's length (30).

Request: setup Playwright for e2e testing

Playwright seems like a better option for us, especially with its support for more browsers. Plus we can run Playwright in headless and have it work on our existing CI pipeline. We need to hook it up to Jest or some other test runner too and insert a basic typing + text selection test.

I was thinking this can use our Github playground for now, running on localhost:3000, so it will require some fiddling around to setup. In terms of commands, I was thinking:

  • yarn test runs all unit and e2e tests (in headless mode)
  • yarn test-unit runs unit tests
  • yarn test-unit --debug runs unit tests in debug mode (see yarn debug-test)
  • yarn test-e2e runs e2e tests (in headless mode)
  • yarn test-e2e --debug runs e2e tests without headless mode, so we can debug issues. The browser should not close after running the test.

We should aim to support as many of the browsers they support. I believe that gives us WebKit, Chromium, Firefox and possibly Android.

cmd + delete goes too far on chromium browsers

repro:

  • type foobar
  • hit enter
  • type baz
  • cmd+delete to delete line while cursor is at the end of baz

results:

foo

expected:

foobar

Browser tested:
chromium/edge: repro the errors
safari: deleteHardLineBackward not supported error
firefox: does it correctly

Screen.Recording.2021-01-29.at.11.41.20.mov

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.