diff --git a/.eslintrc.js b/.eslintrc.js index a836582d46e4..f9e558f81ef5 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -83,6 +83,13 @@ module.exports = { 'header/header': OFF, }, }, + { + // These aren't compiled, but they're written in module JS + files: ['packages/lexical-playground/esm/*.js'], + parserOptions: { + sourceType: 'module', + }, + }, { files: [ 'packages/**/src/__tests__/**', diff --git a/package-lock.json b/package-lock.json index be3383a7b3a1..c7d30caec415 100644 --- a/package-lock.json +++ b/package-lock.json @@ -4447,6 +4447,25 @@ "@types/range-parser": "*" } }, + "node_modules/@types/fs-extra": { + "version": "8.1.5", + "resolved": "https://registry.npmjs.org/@types/fs-extra/-/fs-extra-8.1.5.tgz", + "integrity": "sha512-0dzKcwO+S8s2kuF5Z9oUWatQJj5Uq/iqphEtE3GQJVRRYm/tD1LglU2UnXi2A8jLq5umkGouOXOR9y0n613ZwQ==", + "dev": true, + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/glob": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/@types/glob/-/glob-7.2.0.tgz", + "integrity": "sha512-ZUxbzKl0IfJILTS6t7ip5fQQM/J3TJYubDm3nMbgubNNYS62eXeUpoLUC8/7fJNiFYHTrGPQn7hspDUzIHX3UA==", + "dev": true, + "dependencies": { + "@types/minimatch": "*", + "@types/node": "*" + } + }, "node_modules/@types/graceful-fs": { "version": "4.1.6", "resolved": "https://registry.npmjs.org/@types/graceful-fs/-/graceful-fs-4.1.6.tgz", @@ -4595,6 +4614,12 @@ "resolved": "https://registry.npmjs.org/@types/mime/-/mime-1.3.2.tgz", "integrity": "sha512-YATxVxgRqNH6nHEIsvg6k2Boc1JHI9ZbH5iWFFv/MTkchz3b1ieGDa5T0a9RznNdI0KhVbdbWSN+KWWrQZRxTw==" }, + "node_modules/@types/minimatch": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/@types/minimatch/-/minimatch-5.1.2.tgz", + "integrity": "sha512-K0VQKziLUWkVKiRVrx4a40iPaxTUefQmjtkQofBkYRcoaaL/8rhwDWww9qWbrgicNOgnpIsMxyNIUM4+n6dUIA==", + "dev": true + }, "node_modules/@types/node": { "version": "17.0.45", "resolved": "https://registry.npmjs.org/@types/node/-/node-17.0.45.tgz", @@ -18905,6 +18930,82 @@ "fsevents": "~2.3.2" } }, + "node_modules/rollup-plugin-copy": { + "version": "3.5.0", + "resolved": "https://registry.npmjs.org/rollup-plugin-copy/-/rollup-plugin-copy-3.5.0.tgz", + "integrity": "sha512-wI8D5dvYovRMx/YYKtUNt3Yxaw4ORC9xo6Gt9t22kveWz1enG9QrhVlagzwrxSC455xD1dHMKhIJkbsQ7d48BA==", + "dev": true, + "dependencies": { + "@types/fs-extra": "^8.0.1", + "colorette": "^1.1.0", + "fs-extra": "^8.1.0", + "globby": "10.0.1", + "is-plain-object": "^3.0.0" + }, + "engines": { + "node": ">=8.3" + } + }, + "node_modules/rollup-plugin-copy/node_modules/fs-extra": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-8.1.0.tgz", + "integrity": "sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g==", + "dev": true, + "dependencies": { + "graceful-fs": "^4.2.0", + "jsonfile": "^4.0.0", + "universalify": "^0.1.0" + }, + "engines": { + "node": ">=6 <7 || >=8" + } + }, + "node_modules/rollup-plugin-copy/node_modules/globby": { + "version": "10.0.1", + "resolved": "https://registry.npmjs.org/globby/-/globby-10.0.1.tgz", + "integrity": "sha512-sSs4inE1FB2YQiymcmTv6NWENryABjUNPeWhOvmn4SjtKybglsyPZxFB3U1/+L1bYi0rNZDqCLlHyLYDl1Pq5A==", + "dev": true, + "dependencies": { + "@types/glob": "^7.1.1", + "array-union": "^2.1.0", + "dir-glob": "^3.0.1", + "fast-glob": "^3.0.3", + "glob": "^7.1.3", + "ignore": "^5.1.1", + "merge2": "^1.2.3", + "slash": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/rollup-plugin-copy/node_modules/is-plain-object": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-3.0.1.tgz", + "integrity": "sha512-Xnpx182SBMrr/aBik8y+GuR4U1L9FqMSojwDQwPMmxyC6bvEqly9UBCxhauBF5vNh2gwWJNX6oDV7O+OM4z34g==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/rollup-plugin-copy/node_modules/jsonfile": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz", + "integrity": "sha512-m6F1R3z8jjlf2imQHS2Qez5sjKWQzbuuhuJ/FKYFRZvPE3PuHcSMVZzfsLhGVOkfd20obL5SWEBew5ShlquNxg==", + "dev": true, + "optionalDependencies": { + "graceful-fs": "^4.1.6" + } + }, + "node_modules/rollup-plugin-copy/node_modules/universalify": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz", + "integrity": "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==", + "dev": true, + "engines": { + "node": ">= 4.0.0" + } + }, "node_modules/rrweb-cssom": { "version": "0.6.0", "resolved": "https://registry.npmjs.org/rrweb-cssom/-/rrweb-cssom-0.6.0.tgz", @@ -23158,6 +23259,7 @@ "devDependencies": { "@types/lodash-es": "^4.14.182", "@vitejs/plugin-react": "^1.0.7", + "rollup-plugin-copy": "^3.5.0", "vite": "^2.9.16", "vite-plugin-replace": "0.1.1" } @@ -28213,6 +28315,25 @@ "@types/range-parser": "*" } }, + "@types/fs-extra": { + "version": "8.1.5", + "resolved": "https://registry.npmjs.org/@types/fs-extra/-/fs-extra-8.1.5.tgz", + "integrity": "sha512-0dzKcwO+S8s2kuF5Z9oUWatQJj5Uq/iqphEtE3GQJVRRYm/tD1LglU2UnXi2A8jLq5umkGouOXOR9y0n613ZwQ==", + "dev": true, + "requires": { + "@types/node": "*" + } + }, + "@types/glob": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/@types/glob/-/glob-7.2.0.tgz", + "integrity": "sha512-ZUxbzKl0IfJILTS6t7ip5fQQM/J3TJYubDm3nMbgubNNYS62eXeUpoLUC8/7fJNiFYHTrGPQn7hspDUzIHX3UA==", + "dev": true, + "requires": { + "@types/minimatch": "*", + "@types/node": "*" + } + }, "@types/graceful-fs": { "version": "4.1.6", "resolved": "https://registry.npmjs.org/@types/graceful-fs/-/graceful-fs-4.1.6.tgz", @@ -28354,6 +28475,12 @@ "resolved": "https://registry.npmjs.org/@types/mime/-/mime-1.3.2.tgz", "integrity": "sha512-YATxVxgRqNH6nHEIsvg6k2Boc1JHI9ZbH5iWFFv/MTkchz3b1ieGDa5T0a9RznNdI0KhVbdbWSN+KWWrQZRxTw==" }, + "@types/minimatch": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/@types/minimatch/-/minimatch-5.1.2.tgz", + "integrity": "sha512-K0VQKziLUWkVKiRVrx4a40iPaxTUefQmjtkQofBkYRcoaaL/8rhwDWww9qWbrgicNOgnpIsMxyNIUM4+n6dUIA==", + "dev": true + }, "@types/node": { "version": "17.0.45", "resolved": "https://registry.npmjs.org/@types/node/-/node-17.0.45.tgz", @@ -35756,6 +35883,7 @@ "react": "^18.2.0", "react-dom": "^18.2.0", "react-error-boundary": "^3.1.4", + "rollup-plugin-copy": "^3.5.0", "vite": "^2.9.16", "vite-plugin-replace": "0.1.1", "y-websocket": ">=1.3.x", @@ -38656,6 +38784,69 @@ "fsevents": "~2.3.2" } }, + "rollup-plugin-copy": { + "version": "3.5.0", + "resolved": "https://registry.npmjs.org/rollup-plugin-copy/-/rollup-plugin-copy-3.5.0.tgz", + "integrity": "sha512-wI8D5dvYovRMx/YYKtUNt3Yxaw4ORC9xo6Gt9t22kveWz1enG9QrhVlagzwrxSC455xD1dHMKhIJkbsQ7d48BA==", + "dev": true, + "requires": { + "@types/fs-extra": "^8.0.1", + "colorette": "^1.1.0", + "fs-extra": "^8.1.0", + "globby": "10.0.1", + "is-plain-object": "^3.0.0" + }, + "dependencies": { + "fs-extra": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-8.1.0.tgz", + "integrity": "sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g==", + "dev": true, + "requires": { + "graceful-fs": "^4.2.0", + "jsonfile": "^4.0.0", + "universalify": "^0.1.0" + } + }, + "globby": { + "version": "10.0.1", + "resolved": "https://registry.npmjs.org/globby/-/globby-10.0.1.tgz", + "integrity": "sha512-sSs4inE1FB2YQiymcmTv6NWENryABjUNPeWhOvmn4SjtKybglsyPZxFB3U1/+L1bYi0rNZDqCLlHyLYDl1Pq5A==", + "dev": true, + "requires": { + "@types/glob": "^7.1.1", + "array-union": "^2.1.0", + "dir-glob": "^3.0.1", + "fast-glob": "^3.0.3", + "glob": "^7.1.3", + "ignore": "^5.1.1", + "merge2": "^1.2.3", + "slash": "^3.0.0" + } + }, + "is-plain-object": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-3.0.1.tgz", + "integrity": "sha512-Xnpx182SBMrr/aBik8y+GuR4U1L9FqMSojwDQwPMmxyC6bvEqly9UBCxhauBF5vNh2gwWJNX6oDV7O+OM4z34g==", + "dev": true + }, + "jsonfile": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz", + "integrity": "sha512-m6F1R3z8jjlf2imQHS2Qez5sjKWQzbuuhuJ/FKYFRZvPE3PuHcSMVZzfsLhGVOkfd20obL5SWEBew5ShlquNxg==", + "dev": true, + "requires": { + "graceful-fs": "^4.1.6" + } + }, + "universalify": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz", + "integrity": "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==", + "dev": true + } + } + }, "rrweb-cssom": { "version": "0.6.0", "resolved": "https://registry.npmjs.org/rrweb-cssom/-/rrweb-cssom-0.6.0.tgz", diff --git a/packages/lexical-playground/esm/index.esm.js b/packages/lexical-playground/esm/index.esm.js new file mode 100644 index 000000000000..b7b02270cd39 --- /dev/null +++ b/packages/lexical-playground/esm/index.esm.js @@ -0,0 +1,46 @@ +/** + * Copyright (c) Meta Platforms, Inc. and affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + * + */ + +import {registerDragonSupport} from '@lexical/dragon'; +import {createEmptyHistoryState, registerHistory} from '@lexical/history'; +import {HeadingNode, QuoteNode, registerRichText} from '@lexical/rich-text'; +import {mergeRegister} from '@lexical/utils'; +import {createEditor} from 'lexical'; + +import prepopulatedRichText from './prepopulatedRichText.esm.js'; + +const editorRef = document.getElementById('lexical-editor'); +const stateRef = document.getElementById('lexical-state'); + +const initialConfig = { + namespace: 'Vanilla JS Demo', + // Register nodes specific for @lexical/rich-text + nodes: [HeadingNode, QuoteNode], + onError: (error) => { + throw error; + }, + theme: { + // Adding styling to Quote node, see styles.css + quote: 'PlaygroundEditorTheme__quote', + }, +}; +const editor = createEditor(initialConfig); +editor.setRootElement(editorRef); + +// Registering Plugins +mergeRegister( + registerRichText(editor), + registerDragonSupport(editor), + registerHistory(editor, createEmptyHistoryState(), 300), +); + +editor.update(prepopulatedRichText, {tag: 'history-merge'}); + +editor.registerUpdateListener(({editorState}) => { + stateRef.value = JSON.stringify(editorState.toJSON(), undefined, 2); +}); diff --git a/packages/lexical-playground/esm/index.html b/packages/lexical-playground/esm/index.html new file mode 100644 index 000000000000..58cce82f2dbf --- /dev/null +++ b/packages/lexical-playground/esm/index.html @@ -0,0 +1,37 @@ + + + + + + + + + + + Lexical Basic - Vanilla JS with ESM + + + +

Lexical Basic - Vanilla JS with ESM

+
+
+
+

Editor state:

+ + + + + diff --git a/packages/lexical-playground/esm/prepopulatedRichText.esm.js b/packages/lexical-playground/esm/prepopulatedRichText.esm.js new file mode 100644 index 000000000000..35b3e0e3870c --- /dev/null +++ b/packages/lexical-playground/esm/prepopulatedRichText.esm.js @@ -0,0 +1,39 @@ +/** + * Copyright (c) Meta Platforms, Inc. and affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + * + */ +import {$createHeadingNode, $createQuoteNode} from '@lexical/rich-text'; +import {$createParagraphNode, $createTextNode, $getRoot} from 'lexical'; + +export default function prepopulatedRichText() { + const root = $getRoot(); + if (root.getFirstChild() !== null) { + return; + } + + const heading = $createHeadingNode('h1'); + heading.append($createTextNode('Welcome to the Vanilla JS Lexical Demo!')); + root.append(heading); + const quote = $createQuoteNode(); + quote.append( + $createTextNode( + `In case you were wondering what the text area at the bottom is – it's the debug view, showing the current state of the editor. `, + ), + ); + root.append(quote); + const paragraph = $createParagraphNode(); + paragraph.append( + $createTextNode('This is a demo environment built with '), + $createTextNode('lexical').toggleFormat('code'), + $createTextNode('.'), + $createTextNode(' Try typing in '), + $createTextNode('some text').toggleFormat('bold'), + $createTextNode(' with '), + $createTextNode('different').toggleFormat('italic'), + $createTextNode(' formats.'), + ); + root.append(paragraph); +} diff --git a/packages/lexical-playground/esm/styles.css b/packages/lexical-playground/esm/styles.css new file mode 100644 index 000000000000..73636e090514 --- /dev/null +++ b/packages/lexical-playground/esm/styles.css @@ -0,0 +1,27 @@ +/** + * Copyright (c) Meta Platforms, Inc. and affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + * + */ + +.editor-wrapper { + border: 2px solid gray; +} +#lexical-state { + width: 100%; + height: 300px; +} + +.PlaygroundEditorTheme__quote { + margin: 0; + margin-left: 20px; + margin-bottom: 10px; + font-size: 15px; + color: rgb(101, 103, 107); + border-left-color: rgb(206, 208, 212); + border-left-width: 4px; + border-left-style: solid; + padding-left: 16px; +} diff --git a/packages/lexical-playground/package.json b/packages/lexical-playground/package.json index 69cd786554af..c9495c8bb8e2 100644 --- a/packages/lexical-playground/package.json +++ b/packages/lexical-playground/package.json @@ -38,6 +38,7 @@ "devDependencies": { "@types/lodash-es": "^4.14.182", "@vitejs/plugin-react": "^1.0.7", + "rollup-plugin-copy": "^3.5.0", "vite": "^2.9.16", "vite-plugin-replace": "0.1.1" } diff --git a/packages/lexical-playground/vite.config.js b/packages/lexical-playground/vite.config.js index c14fd8391acd..8e6562b8b909 100644 --- a/packages/lexical-playground/vite.config.js +++ b/packages/lexical-playground/vite.config.js @@ -13,6 +13,7 @@ import path from 'path'; import fs from 'fs'; import {replaceCodePlugin} from 'vite-plugin-replace'; import babel from '@rollup/plugin-babel'; +import copy from 'rollup-plugin-copy'; const moduleResolution = [ { @@ -199,6 +200,23 @@ export default defineConfig({ presets: ['@babel/preset-react'], }), react(), + copy({ + hook: 'writeBundle', + targets: [ + {src: './esm/*', dest: './build/esm/'}, + ...((() => { + const res = []; + const m = /