lexical icon indicating copy to clipboard operation
lexical copied to clipboard

Quick start guide that requires HTML file only

Open StyleT opened this issue 1 year ago • 11 comments

See background here: #1845

Would be nice to have something like https://github.com/quilljs/quill#quickstart - a small, self-contained vanilla HTML/JS snippet loading the editor from CDN + also a way to grab the release tar and serve the JS contents from a static hosting (such as GitHub Pages).

Lexical already has quick start guide, however it requires typescript/nodejs/npm installed locally as well as TS knowledge.

This, even more minimalistic approach would allow Lexical to be run on the websites that doesn't have any compiler/bundler.

CC @vadimkantorov - idea creator

StyleT avatar Apr 05 '24 22:04 StyleT

A somewhat working attempt of building a markdown editor that I put together (stripped off live collaboration features and made playground-derived UI much simpler and embeddable): https://github.com/vadimkantorov/lexical-playground-only

Problems with it:

  1. There is only a version for ES Modules, requires usage as <script type="module" ...>. There should also be a simpler synchronous variant <scrip ...>, optionally defining some (potentially awaitable) init function
  2. Markdown plugin of lexical has some issues: https://github.com/facebook/lexical/issues/5474
  3. React optimizes away Lexical's classes and method names. Ideally, the LexicalComposer object model should be properly available even without React. Issue example: https://github.com/facebook/lexical/issues/5473
  4. assets files are too many. By default it should be only lexical.js and lexical.css with all other resources embedded.
3-columns.4734495c.svg
EquationComponent.04e5f40a.css
EquationComponent.207a82bc.js
EquationComponent.2ae445bf.css
EquationComponent.7c5710a9.js
ExcalidrawComponent.0962d1ef.js
ExcalidrawComponent.09670137.css
ExcalidrawComponent.0c3dc28f.css
ExcalidrawComponent.d2cb4bc2.js
ImageComponent.210226de.css
ImageComponent.5c3ed33d.js
ImageComponent.8314e11b.js
ImageComponent.fc90b599.css
ImageResizer.2ff261bf.js
ImageResizer.c2987cf7.js
InlineImageComponent.72081c3a.js
InlineImageComponent.b2a19f6f.js
InlineImageComponent.b9345ede.css
InlineImageComponent.bbf49c2e.css
KaTeX_AMS-Regular.0cdd387c.woff2
KaTeX_AMS-Regular.30da91e8.woff
KaTeX_AMS-Regular.68534840.ttf
KaTeX_Caligraphic-Bold.07d8e303.ttf
KaTeX_Caligraphic-Bold.1ae6bd74.woff
KaTeX_Caligraphic-Bold.de7701e4.woff2
KaTeX_Caligraphic-Regular.3398dd02.woff
KaTeX_Caligraphic-Regular.5d53e70a.woff2
KaTeX_Caligraphic-Regular.ed0b7437.ttf
KaTeX_Fraktur-Bold.74444efd.woff2
KaTeX_Fraktur-Bold.9163df9c.ttf
KaTeX_Fraktur-Bold.9be7ceb8.woff
KaTeX_Fraktur-Regular.1e6f9579.ttf
KaTeX_Fraktur-Regular.51814d27.woff2
KaTeX_Fraktur-Regular.5e28753b.woff
KaTeX_Main-Bold.0f60d1b8.woff2
KaTeX_Main-Bold.138ac28d.ttf
KaTeX_Main-Bold.c76c5d69.woff
KaTeX_Main-BoldItalic.70ee1f64.ttf
KaTeX_Main-BoldItalic.99cd42a3.woff2
KaTeX_Main-BoldItalic.a6f7ec0d.woff
KaTeX_Main-Italic.0d85ae7c.ttf
KaTeX_Main-Italic.97479ca6.woff2
KaTeX_Main-Italic.f1d6ef86.woff
KaTeX_Main-Regular.c2342cd8.woff2
KaTeX_Main-Regular.c6368d87.woff
KaTeX_Main-Regular.d0332f52.ttf
KaTeX_Math-BoldItalic.850c0af5.woff
KaTeX_Math-BoldItalic.dc47344d.woff2
KaTeX_Math-BoldItalic.f9377ab0.ttf
KaTeX_Math-Italic.08ce98e5.ttf
KaTeX_Math-Italic.7af58c5e.woff2
KaTeX_Math-Italic.8a8d2445.woff
KaTeX_SansSerif-Bold.1ece03f7.ttf
KaTeX_SansSerif-Bold.e99ae511.woff2
KaTeX_SansSerif-Bold.ece03cfd.woff
KaTeX_SansSerif-Italic.00b26ac8.woff2
KaTeX_SansSerif-Italic.3931dd81.ttf
KaTeX_SansSerif-Italic.91ee6750.woff
KaTeX_SansSerif-Regular.11e4dc8a.woff
KaTeX_SansSerif-Regular.68e8c73e.woff2
KaTeX_SansSerif-Regular.f36ea897.ttf
KaTeX_Script-Regular.036d4e95.woff2
KaTeX_Script-Regular.1c67f068.ttf
KaTeX_Script-Regular.d96cdf2b.woff
KaTeX_Size1-Regular.6b47c401.woff2
KaTeX_Size1-Regular.95b6d2f1.ttf
KaTeX_Size1-Regular.c943cc98.woff
KaTeX_Size2-Regular.2014c523.woff
KaTeX_Size2-Regular.a6b2099f.ttf
KaTeX_Size2-Regular.d04c5421.woff2
KaTeX_Size3-Regular.500e04d5.ttf
KaTeX_Size3-Regular.6ab6b62e.woff
KaTeX_Size4-Regular.99f9c675.woff
KaTeX_Size4-Regular.a4af7d41.woff2
KaTeX_Size4-Regular.c647367d.ttf
KaTeX_Typewriter-Regular.71d517d6.woff2
KaTeX_Typewriter-Regular.e14fed02.woff
KaTeX_Typewriter-Regular.f01f3e87.ttf
LexicalNestedComposer.1db42776.js
LexicalNestedComposer.7960692b.js
PollComponent.2797c38d.js
PollComponent.953828cb.css
PollComponent.d31c73b6.js
PollComponent.e519dbaf.css
StickyComponent.112465ca.js
StickyComponent.57b767d9.css
StickyComponent.935a6122.css
StickyComponent.bad9c4c2.js
arrow-clockwise.2a5cb240.svg
arrow-counterclockwise.7bfcc198.svg
bg-color.507cd4d9.svg
camera.30598594.svg
card-checklist.4b2c9bb6.svg
caret-right-fill.a00c19e8.svg
cat-typing.29244fe9.gif
chat-left-text.6b95a11e.svg
chat-square-quote.11c47cee.svg
chevron-down.7ab1bec2.svg
clipboard.af70d3df.svg
close.5a175ff6.svg
code.211c00f3.svg
collaboration.c3051c8d.js
comments.832aaea0.svg
copy.0a348586.svg
diagram-2.109ff72d.svg
download.86c52f35.svg
draggable-block-menu.a5121e96.svg
dropdown-more.e77cf0f5.svg
figma.73378f91.svg
file-earmark-text.ca11f66a.svg
file-image.92c4290c.svg
filetype-gif.6c82f677.svg
font-color.babef7e0.svg
font-family.6d11828a.svg
gear.9752af63.svg
horizontal-rule.f2611cd6.svg
indent.9b11e20c.svg
journal-code.281f8e59.svg
justify.e3d375bb.svg
landscape.21352c66.jpg
link.dabc7da5.svg
list-ol.03c2349b.svg
list-ul.d6a7f4ba.svg
lock-fill.b10c3357.svg
lock.9d41d1f2.svg
logo.a7000acb.svg
main.css
main.js
markdown.5082cb8f.svg
mic.507b1f72.svg
outdent.b795c01f.svg
paint-bucket.407066ee.svg
palette.a72cd2c3.svg
parser-babel.1711e47d.js
parser-babel.9489f1fd.js
parser-html.02e10cfd.js
parser-html.d58717f2.js
parser-markdown.79dba7a4.js
parser-markdown.cc957227.js
parser-postcss.6f2e5cc4.js
parser-postcss.c2aa688e.js
pencil-fill.633b2c8d.svg
plug-fill.0098ed23.svg
plug.d8731872.svg
plus-slash-minus.6e1f16e9.svg
plus.cc33d039.svg
prettier-error.0ed0d492.svg
prettier.6c905155.svg
scissors.fe13738f.svg
send.3616a219.svg
square-check.f4543561.svg
standalone.1c72ffad.js
standalone.38cb2176.js
sticky.35cbc445.svg
success-alt.33b01110.svg
success.e7e6caa5.svg
table.5b346097.svg
text-center.3b97a1ce.svg
text-left.37eb3c07.svg
text-paragraph.f17ec370.svg
text-right.69b7b3bf.svg
trash.e93c6b1b.svg
trash3.0a864fe5.svg
tweet.9fbf1564.svg
type-bold.1f17e5da.svg
type-h1.83dd5e3b.svg
type-h2.bb6b6d69.svg
type-h3.27eb870e.svg
type-h4.b9ba31db.svg
type-h5.f6d2d205.svg
type-h6.34dc2c46.svg
type-italic.f9cdcec5.svg
type-strikethrough.ea22e2f6.svg
type-subscript.84ecc6bb.svg
type-superscript.fd5795bc.svg
type-underline.9639e1cd.svg
upload.0365f49c.svg
user.085d4653.svg
yellow-flower.a2a7c7a2.jpg
youtube.42d173dd.svg

vadimkantorov avatar Apr 06 '24 20:04 vadimkantorov

https://playground.lexical.dev/esm/ is a bare bones vanilla js implementation that doesn't use a compiler or bundler. Would need to use a different importmap to pull lexical from a cdn (mostly depends on which cdn, and to pick the dev or prod build)

etrepum avatar Apr 09 '24 05:04 etrepum

It's not a public API, but the root element gets a __lexicalEditor property which is basically what LexicalComposer gives you. Maybe some of the functionality that is being built for devtools could be exposed as a public API somewhere.

https://github.com/facebook/lexical/blob/main/packages/lexical-devtools/src/entrypoints/injected/utils/queryLexicalNodes.ts

etrepum avatar Apr 09 '24 05:04 etrepum

In https://github.com/vadimkantorov/moncms I also hacked a basic variant of the playground as a ready component - to be renderable/responsive in a user-provided div: image

As opposed to the current demo in /esm: image

I think it should also ship as a basic deliverable (especially given that it exists already!), without having to use React as the end user. Quill allows configuring basic RTF toolbar even as basic HTML - and this is a very useful feature, would be nice for it to exist for Lexical as well. This is very useful for users who are not web developers themselves and are looking for a simple RTF/Markdown editor with a wish to have some toolbar design out-of-the-box

vadimkantorov avatar Apr 09 '24 08:04 vadimkantorov

The current /esm/ is really more of a test in its current state, which is why it's not linked to or documented, but if you view source you can see that it doesn't use a bundler and doesn't have any precompiled artifacts other than lexical's modules themselves. I am just showing you that it's possible to do without using a bundler or importing a precompiled React project, although a fair bit of the playground functionality would have to be rewritten if it needed to target vanilla JS.

etrepum avatar Apr 09 '24 14:04 etrepum

Yeah, either playground rewrite or somehow enabling the ESM version to reuse precompiled playground code would be needed (which is the approach in my attempt in https://github.com/vadimkantorov/lexical-playground-only/ - after the compilation, the playground/editor is available to the vanilla JS code as showcased in https://github.com/vadimkantorov/lexical-playground-only/blob/objectorientededitor/index.html)

vadimkantorov avatar Apr 09 '24 14:04 vadimkantorov

I would personally prefer to see script type="module" and esm used for this sort of use case, it provides more flexibility and is forward-looking. The big problem someone would eventually run into is that lexical uses module globals and class identity so you can only have one imported, and if you were using some pre-bundled cjs version you would just not really have access to the modules (at least in a convenient way) to start extending it.

IMO the three.js examples do this pretty well, which is what inspired the importmap approach for /esm/ - they are in a 'hackable' one file state, but still use imports so you can use normal code and abstract things easily.

  • https://threejs.org/examples/#webgl_animation_keyframes
  • https://github.com/mrdoob/three.js/blob/master/examples/webgl_animation_keyframes.html

etrepum avatar Apr 09 '24 15:04 etrepum

I hope this can still allow at the end to have a super-compact distribution in just two assets: one JS file and one CSS file - this is ideal for CDN-less self-hosting as well on GitHub Pages

vadimkantorov avatar Apr 09 '24 16:04 vadimkantorov

I'm not sure that a single JS file is really an option if you want to actually use the library directly, have it be compatible with plugins, etc. without some sort of bundler. It would have to be a folder of files plus a single importmap. JS just hasn't standardized enough functionality yet.

The only way to get a single JS file would be to run the whole set of dependencies through a bundler, either on your machine or using a CDN like esm.sh to do it and then saving the result locally for CDN-less usage.

etrepum avatar Apr 09 '24 18:04 etrepum

After thinking about it a little more maybe there's a possible strategy that would bring it down to one mjs file, if we had a package like @lexical/all that was all of lexical's exports in a flat namespace that would be shipped as a single bundle and designed to be used with an importmap that aliases all public lexical modules to the same file. The caveat for that would be that we would have to deprecate modules that use default exports as their entry points (only the lexical/react/* modules do this) and we would have to commit to having a global flat namespace (I think may already be the case? maybe due to www constraints or just style choices, although I don't believe there is a linter to guarantee this)

It might be worth considering having 'lexical/react' be a barrel module to expose its contents with named exports, deprecate 'lexical/react/*' usage, and have consumers rely on tree-shaking… that would resolve that issue but it would take some time for the ecosystem to change their imports to that style.

etrepum avatar Apr 09 '24 19:04 etrepum

I'm most interested in the following setups:

  1. include lexical+something playground-like into HTML as only two files: <script src=... type="module"></script><link rel="stylesheet" href="..." />
  2. ideally, it should also be possible to embed it directly as <script>...</script><style>...</style>

For the kinds of quick hacks I'm interested in (e.g. single-file CMS/markdown editor for GitHub API/Pages, workable both from file:/// and fom a drop-in to a GitHub Pages blog) - distribution of a single HTML file is ideal, that's why I'm interested in embedding everything into a single HTML. So I'm not interested much in hacking the editor itself, but mainly in just using it as a working RTF editor within some other hacked simple HTML/JS app (which itself does not use react/npm etc).

Even if you are not releasing such playground-like full-featured editors at the moment, providing simple scripts to obtain this would be awesome for non-webdev professionals. I would assume this would entail providing a script and a GitHub Workflow with properly configuring vite, then doing npm install and collecting artifacts. This should package a copy of React with Lexical Playground into a pair of js/css. A lexical-only package could similarly be provided (maybe both would use your idea of collecting all modules into a single mjs file?)

So maybe what is needed is just some examples/scripts of running bundler for some above-like/quill-like setups (including GitHub Actions pipelines). And then you could also include these artifacts as releases and provide them as GitHub Actions pipelines. This is essentially what I did in https://github.com/vadimkantorov/lexical-playground-only/, but as I'm not a webdev, I could not properly configure the bundler at the current point and am also struggling with https://github.com/facebook/lexical/issues/5473.

Related:

  • https://github.com/facebook/lexical/issues/5964

vadimkantorov avatar May 11 '24 10:05 vadimkantorov