Lexical – a web text editor framework that powers Facebook(playground.lexical.dev) |
Lexical – a web text editor framework that powers Facebook(playground.lexical.dev) |
For those of you looking for the sourcecode for the playground, you can find it here:
https://github.com/facebook/lexical/tree/main/packages/lexic...
We also have a Discord channel you can check out:
I don’t use Facebook, but AFAIK, there are no “blog features” in the platform, are there?
Other than a WYSIWYG editor [1], what other use cases do you intend this project for?
> The competition has no choice but to spend all their time porting and keeping up, time that they can’t spend writing new features. Look closely at the software landscape. The companies that do well are the ones who rely least on big companies and don’t have to spend all their cycles catching up and reimplementing and fixing bugs that crop up [only on Windows XP.]
so it is the same with the modern day web frameworks as it is in the old days of windows and microsoft's dominance.
Joel Spolsky was as right in early 2002 as he is right in 2022.
A recruiter called me from your company recently, and I kind of cringed hearing him talk about the meta verse.
I realize now they probably would be much more effective with engineers if they skipped that part and just focused on all the cool work that’s being done.
https://discuss.prosemirror.net/t/differences-between-prosem...
Ultimately though, there are many similarities between the two – intentionally so. We were inspired by ProseMirror and some of its APIs and approaches. I think the biggest underlying differences are in how we tackle things from a DX perspective. We tried to bring a more composable API to making text editors work – from the plugin patterns, how updates and reads work, to how you listen for changes and react to them. Much of this was inspired by my prior work working on the React core team and from creating Inferno.
It’s so frustrating posting code snippets to friends threads on FB
Can you talk a bit more about how this is achieved? Is it DOM obfuscation?
[1] https://discuss.prosemirror.net/t/differences-between-prosem...
Does Lexical have a feature to set arbitrary CSS on a particular selection range? I've been looking for a solution to do this since the WebKit's -[WebView applyStyle:] is deprecated as part of WebView Legacy. It isn't clear to me from glancing at the docs if RangeSelection.formatText() or other methods can handle anything or just a subset of styling code. Thanks!
Thanks for great framework and design ;)
Lexical is awesome!
Maybe such a page would pull the JS from a CDN, maybe it would refer to filepaths on the server.
I don't know how to form a working web page from the snippets in the docu because I do not know the relevant javascript. I would just like a working example, on my own computer, with a minimum number of moving parts, that I can play around with.
https://github.com/facebook/lexical/blob/main/packages/lexic...
I tried so hard to avoid adding timeouts/timestamp logic for Android because it feels like a nondeterministic hack. In the end I gave up and did something similar.
I also found beforeInput doesn’t offer much solace on Android or with CJK language, because messing around with preventDefault or the DOM during composition disturbs the user.
One weird thing I never figured out is that if the user puts the selection in an empty block, GBoard wants to jump to the nearest word in a different paragraph. We do some brutal hacks to get around that :-/
I read your comment on ProseMirror forum about preventing interference from Granmarly, etc. Do you do this by reverting MutationRecords? Where is the code/docs for that?
I select some text and then try to change the font size. The selection is lost when tapping on the font size menu.
ProseMirror does keep the selection intact.
Example: https://www.slatejs.org/examples/richtext
Code: https://github.com/ianstormtaylor/slate/blob/main/site/examp...
I wanted to see if Lexical was a good fit. My app is plain javascript with a bit of Alpine and htmx. I just couldn’t figure out how to <link> to the appropriate js file in my html file. And I’m not a frontend dev so I have no idea how to browserify (or whatever the technical term is) the right npm modules.
I ended up using MediumEditor which is ancient in relative terms. Anyway, now composing email feels like writing a Medium post, fwiw.
Curious whether the team is looking at improving the support of having images in tables cell? I played with the playground and it seems to work, but there seems to be some (relatively minor) glitches/bugs (e.g. difficult to place an image in a cell, moving images across cells seems difficult, and cannot Ctrl-x an image and Ctrl-v to paste it).
Just looking at the top level package.json [1], I wonder at which point you abstract all those copy/pasted targets into a script that takes an argument.
[1] https://github.com/facebook/lexical/blob/main/package.json#L...
Good tip.
[1] https://github.com/Vanessa219/vditor/blob/master/README_en_U...
Is there a general timeline goal for the V1.0 release?
Also, how do you guys design to reduce latency in Lexical? Esp considering the fluidity of modern chat clients ex. Telegram which are much more performant.
What does "handling reconciliation rather than delegating" mean here?
How do people search for jobs that work in this problem domains - parsers / editors / compilers?
• Inserting emoji with my Compose key: some (e.g. U+1F641) get turned into image-backed emoji and then duplicated unless preceded by another image-backed emoji; some (e.g. U+1F928) get ignored and left as normal text.
• If I type an emoji that gets duplicated while inside a link (but not inside bold/italic), one goes where the caret is, and the other goes immediately before the link, and it leaves the caret there.
• The image-backed emoji are incompatible with inline text formatting: if you type them in the middle of formatted text, instead of ending up with the likes of <u>text EMOJI text</u>, you end up with <u>text </u>EMOJI<u> text</u>, and although you can subsequently apply the formatting so that it shows in the debug tree, it doesn’t change the HTML markup (e.g. subscript/superscript/underline/code should certainly be visible, and even italic and bold can change emoji rendering).
• If I select part of a link starting outside the end of a link (that is, go one character past the link and then press the Left arrow key—Firefox has valid caret positions for both inside and outside the start and end of an element, depending on which direction you came from, which my faint recollection was a major trouble point on WebKit many years ago, that you couldn’t do that and so literally couldn’t model various reasonable, kinda like multiple selection which is also Firefox-only and extremely useful on tables) and delete that, instead of just deleting the selected characters, it deletes the entire link. (As above, this seems to be specific to links, not affecting bold/italic.)
• Very early on (before I had done any editing at all) when I tried the time travel feature, I somehow activated the autocomplete popup on the words “The playground” by clicking or something, even though autocomplete was not turned on (I only confirmed that that was what it was, and not a spelling corrector, by later enabling it and typing “the”) and it was supposed to be read-only.
• Resizing table rows and columns is very buggy, with things like the grippies easily getting lost, the table-cell-action-button not updating its position, and it sometimes failing to act on mouse up. (Props for including the functionality, though, as it’s normally overlooked.)
• Clicking in table cells always moves the caret to the start of the cell rather than where you clicked, meaning you have to use arrow keys to get to the right place, and can’t select properly by mouse either.
• Pop-up menus don’t scroll with the document while open.
• Autocomplete popup doesn’t close when you move the caret by mouse, though they will no longer work if you click on them.
• Incidentally, who thought it a good idea to apply `list-style-position: inside`?
And this was from a fairly quick test. I found most of this stuff immediately and would expect to hit most of these issues in real life.
I honestly wish people would try to be less fancy with WYSIWYG components, because the web platform just isn’t well-adapted to it.
There is an official (and mature) binding with React, but there are also unofficial bindings with Solid, Vue and Svelte.
Each has a dedicated channel in the Discord (including repo links).
I'm more excited about this than you'd expect LOL
It's 2022 and we're reinventing every wheel, but in the browser.
GitHub has a Markdown editor with a paste handler (converting tables and such). It once had a bug. I had to disable handlers in the browser to be able to paste.
The major issue for both Android and CJK input is dealing with “composition” of characters by an “input method editor”. https://en.m.wikipedia.org/wiki/Input_method
In English, usually it’s okay to assume one key press event = one letter input. The opposite is true on Android generally, and for CJK languages on all platforms. These use input systems (like handwriting) where keypresses never occur, or many keypresses compose to produce one character. There are also new rules for IME composition input like “you can’t touch the DOM or change the selection during composition or the input will cancel and your user will be mad”. It turns the problem from “Hard” difficulty to “Nightmare” difficulty.
The baffling thing on Android is that each keyboard (Gboard, Samsung Keyboard, Swiftkey, Simeji, Sogou, Naver) have different composition behaviors with different event patterns… and GBoard’s ENGLISH input is probably the most strange! It composes whole English words like they were Chinese characters, and it wants to compose SO badly it will move text selection from wherever the user tapped to the nearest English word. And as an added bonus on Android only, the browsers selection APIs report the wrong selection during different phases of the event flow. Hah. Like when you tap a key, Android will send a selectionChange event before the first input-related event, and that selectionChange will probably report some weird lie about the selection position.
also, opting to use a big old plaintext textbox and something markdown-ish avoids these problems, right? (I'm trying to figure out why typing becomes slow on discord/slack in Firefox routinely. though I guess those are not real textboxes, but also contenteditable things :/)
https://github.com/facebook/lexical/blob/main/packages/lexic...
> // Check for any random auto-added <br> elements, and remove them.
> // These get added by the browser when we undo the above mutations
> // and this can lead to a broken UI.
This made me laugh out loud. Browsers!
Until here our approach looked quite similar. Leave the observer connected during reverts and avoiding double-peocessing using .takeRecords never occurred to me, I always disconnect it. Maybe some of these brs are causing chaos…
As for this particular article, what is your criticism? That FB makes a rich text editor available as open source (under the MIT license)? How on earth does that mean "companies have to spend all their cycles catching up and reimplementing and fixing bugs"?
You can always roll your own, or use one of the many others available if this one doesn't taste right? (Also: Who on earth gains a competitive advantage from having a text editor, in 2022?)
The fact that there's draft.js, and a myriad of other existing editor libraries out there already, all of which could've been contributed to instead.
If a startup chose to base their technology on a library that is released by a major corporation, they face the risk of getting "rug pulled" (or the library updates incompatibly and now you're locked in either to using the old version, or painful upgrade to the new version).
Of course, they don't have to choose to use such a library, but if they don't then there's a community of people who then questions them on why they are spending time replicating a technology.
The point is, if a startup chose to use this library, they face the risk of having to expend time keeping up in pace (and associated cost of doing so) with facebook.
This equivalent scenario exists in someone writing against libraries released by microsoft on windows, and that's what spolsky is complaining about.
That is no different from something you do yourself, either. What you call "rug pull" is merely the point where the solution you got for free suddenly costs as much to maintain as your inhouse solution.
Going to have to have a play with Lexical, excited to see Yjs support!
[0]: http://tiptap.dev
It does apparently have the best live editing / collaboration features of all text editors out there.
the big difference with a true volunteer based OSS solution, like for example, linux, is that there's many individuals involved. The decision making in that project then won't turn into what spolsky said. I wouldn't imagine the linux maintainers "rug pull", but i can imagine facebook doing a rug pull.
Major controversies that come to mind around Linux pretty much immediately are systemd, Wayland, the sound server wars. I also vaguely recall major back and forth around memory management. That's normal and expected. That's why you make "buy vs build" decisions, and any third party package is susceptible to that.
And "many individuals involved" means absolutely nothing - do you honestly believe that somehow this editor is a lone work of genius? Or that companies somehow have a coherent vision for every single detail? Have you ever worked in a large company?
2. Building an editor is so complicated that most organizations want to do it only once. They build a web editor, and wrap it in a native app. The shell like file browser, sharing screens, etc are “native” but the editor surface is a webview. This is how Quip, Dropbox Paper, Google Docs, Notion, etc work. Even iOS worked this way initially for all editable styled text (per https://twitter.com/kocienda/status/1400484473540513792?s=21...)
3. If you are going to bet the core competency of your business on a framework, it’s important to understand the motivations and limitations of said framework.
Btw I'd love to see any public posts about the architecture of the Notion editor!
I co-wrote a post about our editor internals after finishing up the recent re-work but we decided not to publish it to conserve our Competitive Advantage.
Guess I'll just have to get a job at Notion some day and dig it up...