Lexical: Range of bug fixes, Updated lexical version

- Updated selection change detection to be more accurate
- Added UI refresh for extra actions
- Fixed remove link deleting contents
This commit is contained in:
Dan Brown 2024-09-08 15:54:59 +01:00
parent bed2c29a33
commit 16518a4f89
No known key found for this signature in database
GPG Key ID: 46D9F943C24A2EF9
8 changed files with 195 additions and 173 deletions

287
package-lock.json generated
View File

@ -18,20 +18,20 @@
"@codemirror/state": "^6.3.3", "@codemirror/state": "^6.3.3",
"@codemirror/theme-one-dark": "^6.1.2", "@codemirror/theme-one-dark": "^6.1.2",
"@codemirror/view": "^6.22.2", "@codemirror/view": "^6.22.2",
"@lexical/history": "^0.16.0", "@lexical/history": "^0.17.0",
"@lexical/html": "^0.16.0", "@lexical/html": "^0.17.0",
"@lexical/link": "^0.16.0", "@lexical/link": "^0.17.0",
"@lexical/list": "^0.16.0", "@lexical/list": "^0.17.0",
"@lexical/rich-text": "^0.16.0", "@lexical/rich-text": "^0.17.0",
"@lexical/selection": "^0.16.0", "@lexical/selection": "^0.17.0",
"@lexical/table": "^0.16.0", "@lexical/table": "^0.17.0",
"@lexical/utils": "^0.16.0", "@lexical/utils": "^0.17.0",
"@lezer/highlight": "^1.2.0", "@lezer/highlight": "^1.2.0",
"@ssddanbrown/codemirror-lang-smarty": "^1.0.0", "@ssddanbrown/codemirror-lang-smarty": "^1.0.0",
"@ssddanbrown/codemirror-lang-twig": "^1.0.0", "@ssddanbrown/codemirror-lang-twig": "^1.0.0",
"codemirror": "^6.0.1", "codemirror": "^6.0.1",
"idb-keyval": "^6.2.1", "idb-keyval": "^6.2.1",
"lexical": "^0.16.0", "lexical": "^0.17.0",
"markdown-it": "^14.1.0", "markdown-it": "^14.1.0",
"markdown-it-task-lists": "^2.1.1", "markdown-it-task-lists": "^2.1.1",
"snabbdom": "^3.5.1", "snabbdom": "^3.5.1",
@ -51,9 +51,9 @@
} }
}, },
"node_modules/@codemirror/autocomplete": { "node_modules/@codemirror/autocomplete": {
"version": "6.16.3", "version": "6.18.0",
"resolved": "https://registry.npmjs.org/@codemirror/autocomplete/-/autocomplete-6.16.3.tgz", "resolved": "https://registry.npmjs.org/@codemirror/autocomplete/-/autocomplete-6.18.0.tgz",
"integrity": "sha512-Vl/tIeRVVUCRDuOG48lttBasNQu8usGgXQawBXI7WJAiUDSFOfzflmEsZFZo48mAvAaa4FZ/4/yLLxFtdJaKYA==", "integrity": "sha512-5DbOvBbY4qW5l57cjDsmmpDh3/TeK1vXfTHa+BUMrRzdWdcxKZ4U4V7vQaTtOpApNU4kLS4FQ6cINtLg245LXA==",
"dependencies": { "dependencies": {
"@codemirror/language": "^6.0.0", "@codemirror/language": "^6.0.0",
"@codemirror/state": "^6.0.0", "@codemirror/state": "^6.0.0",
@ -68,9 +68,9 @@
} }
}, },
"node_modules/@codemirror/commands": { "node_modules/@codemirror/commands": {
"version": "6.6.0", "version": "6.6.1",
"resolved": "https://registry.npmjs.org/@codemirror/commands/-/commands-6.6.0.tgz", "resolved": "https://registry.npmjs.org/@codemirror/commands/-/commands-6.6.1.tgz",
"integrity": "sha512-qnY+b7j1UNcTS31Eenuc/5YJB6gQOzkUoNmJQc0rznwqSRpeaWWpjkWy2C/MPTcePpsKJEM26hXrOXl1+nceXg==", "integrity": "sha512-iBfKbyIoXS1FGdsKcZmnrxmbc8VcbMrSgD7AVrsnX+WyAYjmUDWvE93dt5D874qS4CCVu4O1JpbagHdXbbLiOw==",
"dependencies": { "dependencies": {
"@codemirror/language": "^6.0.0", "@codemirror/language": "^6.0.0",
"@codemirror/state": "^6.4.0", "@codemirror/state": "^6.4.0",
@ -79,15 +79,15 @@
} }
}, },
"node_modules/@codemirror/lang-css": { "node_modules/@codemirror/lang-css": {
"version": "6.2.1", "version": "6.3.0",
"resolved": "https://registry.npmjs.org/@codemirror/lang-css/-/lang-css-6.2.1.tgz", "resolved": "https://registry.npmjs.org/@codemirror/lang-css/-/lang-css-6.3.0.tgz",
"integrity": "sha512-/UNWDNV5Viwi/1lpr/dIXJNWiwDxpw13I4pTUAsNxZdg6E0mI2kTQb0P2iHczg1Tu+H4EBgJR+hYhKiHKko7qg==", "integrity": "sha512-CyR4rUNG9OYcXDZwMPvJdtb6PHbBDKUc/6Na2BIwZ6dKab1JQqKa4di+RNRY9Myn7JB81vayKwJeQ7jEdmNVDA==",
"dependencies": { "dependencies": {
"@codemirror/autocomplete": "^6.0.0", "@codemirror/autocomplete": "^6.0.0",
"@codemirror/language": "^6.0.0", "@codemirror/language": "^6.0.0",
"@codemirror/state": "^6.0.0", "@codemirror/state": "^6.0.0",
"@lezer/common": "^1.0.2", "@lezer/common": "^1.0.2",
"@lezer/css": "^1.0.0" "@lezer/css": "^1.1.7"
} }
}, },
"node_modules/@codemirror/lang-html": { "node_modules/@codemirror/lang-html": {
@ -182,9 +182,9 @@
} }
}, },
"node_modules/@codemirror/legacy-modes": { "node_modules/@codemirror/legacy-modes": {
"version": "6.4.0", "version": "6.4.1",
"resolved": "https://registry.npmjs.org/@codemirror/legacy-modes/-/legacy-modes-6.4.0.tgz", "resolved": "https://registry.npmjs.org/@codemirror/legacy-modes/-/legacy-modes-6.4.1.tgz",
"integrity": "sha512-5m/K+1A6gYR0e+h/dEde7LoGimMjRtWXZFg4Lo70cc8HzjSdHe3fLwjWMR0VRl5KFT1SxalSap7uMgPKF28wBA==", "integrity": "sha512-vdg3XY7OAs5uLDx2Iw+cGfnwtd7kM+Et/eMsqAGTfT/JKiVBQZXosTzjEbWAi/FrY6DcQIz8mQjBozFHZEUWQA==",
"dependencies": { "dependencies": {
"@codemirror/language": "^6.0.0" "@codemirror/language": "^6.0.0"
} }
@ -226,9 +226,9 @@
} }
}, },
"node_modules/@codemirror/view": { "node_modules/@codemirror/view": {
"version": "6.28.2", "version": "6.33.0",
"resolved": "https://registry.npmjs.org/@codemirror/view/-/view-6.28.2.tgz", "resolved": "https://registry.npmjs.org/@codemirror/view/-/view-6.33.0.tgz",
"integrity": "sha512-A3DmyVfjgPsGIjiJqM/zvODUAPQdQl3ci0ghehYNnbt5x+o76xq+dL5+mMBuysDXnI3kapgOkoeJ0sbtL/3qPw==", "integrity": "sha512-AroaR3BvnjRW8fiZBalAaK+ZzB5usGgI014YKElYZvQdNH5ZIidHlO+cyf/2rWzyBFRkvG6VhiXeAEbC53P2YQ==",
"dependencies": { "dependencies": {
"@codemirror/state": "^6.4.0", "@codemirror/state": "^6.4.0",
"style-mod": "^4.1.0", "style-mod": "^4.1.0",
@ -619,9 +619,9 @@
} }
}, },
"node_modules/@eslint-community/regexpp": { "node_modules/@eslint-community/regexpp": {
"version": "4.10.1", "version": "4.11.0",
"resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.10.1.tgz", "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.11.0.tgz",
"integrity": "sha512-Zm2NGpWELsQAD1xsJzGQpYfvICSsFkEpU0jxBjfdC6uNEWXcHnfs9hScFWtXVDVl+rBQJGrl4g1vcKIejpH9dA==", "integrity": "sha512-G/M/tIiMrTAxEWRfLfQJMmGNX28IxBg4PBz8XqQhqUHLFI6TL2htpIB1iQCj144V5ee/JaKyT9/WZ0MGZWfA7A==",
"dev": true, "dev": true,
"engines": { "engines": {
"node": "^12.0.0 || ^14.0.0 || >=16.0.0" "node": "^12.0.0 || ^14.0.0 || >=16.0.0"
@ -695,91 +695,91 @@
"dev": true "dev": true
}, },
"node_modules/@lexical/clipboard": { "node_modules/@lexical/clipboard": {
"version": "0.16.0", "version": "0.17.1",
"resolved": "https://registry.npmjs.org/@lexical/clipboard/-/clipboard-0.16.0.tgz", "resolved": "https://registry.npmjs.org/@lexical/clipboard/-/clipboard-0.17.1.tgz",
"integrity": "sha512-eYMJ6jCXpWBVC05Mu9HLMysrBbfi++xFfsm+Yo7A6kYGrqYUhpXqjJkYnw1xdZYL3bV73Oe4ByVJuq42GU+Mqw==", "integrity": "sha512-OVqnEfWX8XN5xxuMPo6BfgGKHREbz++D5V5ISOiml0Z8fV/TQkdgwqbBJcUdJHGRHWSUwdK7CWGs/VALvVvZyw==",
"dependencies": { "dependencies": {
"@lexical/html": "0.16.0", "@lexical/html": "0.17.1",
"@lexical/list": "0.16.0", "@lexical/list": "0.17.1",
"@lexical/selection": "0.16.0", "@lexical/selection": "0.17.1",
"@lexical/utils": "0.16.0", "@lexical/utils": "0.17.1",
"lexical": "0.16.0" "lexical": "0.17.1"
} }
}, },
"node_modules/@lexical/history": { "node_modules/@lexical/history": {
"version": "0.16.0", "version": "0.17.1",
"resolved": "https://registry.npmjs.org/@lexical/history/-/history-0.16.0.tgz", "resolved": "https://registry.npmjs.org/@lexical/history/-/history-0.17.1.tgz",
"integrity": "sha512-xwFxgDZGviyGEqHmgt6A6gPhsyU/yzlKRk9TBUVByba3khuTknlJ1a80H5jb+OYcrpiElml7iVuGYt+oC7atCA==", "integrity": "sha512-OU/ohajz4FXchUhghsWC7xeBPypFe50FCm5OePwo767G7P233IztgRKIng2pTT4zhCPW7S6Mfl53JoFHKehpWA==",
"dependencies": { "dependencies": {
"@lexical/utils": "0.16.0", "@lexical/utils": "0.17.1",
"lexical": "0.16.0" "lexical": "0.17.1"
} }
}, },
"node_modules/@lexical/html": { "node_modules/@lexical/html": {
"version": "0.16.0", "version": "0.17.1",
"resolved": "https://registry.npmjs.org/@lexical/html/-/html-0.16.0.tgz", "resolved": "https://registry.npmjs.org/@lexical/html/-/html-0.17.1.tgz",
"integrity": "sha512-okxn3q/1qkUpCZNEFRI39XeJj4YRjb6prm3WqZgP4d39DI1W24feeTZJjYRCW+dc3NInwFaolU3pNA2MGkjRtg==", "integrity": "sha512-yGG+K2DXl7Wn2DpNuZ0Y3uCHJgfHkJN3/MmnFb4jLnH1FoJJiuy7WJb/BRRh9H+6xBJ9v70iv+kttDJ0u1xp5w==",
"dependencies": { "dependencies": {
"@lexical/selection": "0.16.0", "@lexical/selection": "0.17.1",
"@lexical/utils": "0.16.0", "@lexical/utils": "0.17.1",
"lexical": "0.16.0" "lexical": "0.17.1"
} }
}, },
"node_modules/@lexical/link": { "node_modules/@lexical/link": {
"version": "0.16.0", "version": "0.17.1",
"resolved": "https://registry.npmjs.org/@lexical/link/-/link-0.16.0.tgz", "resolved": "https://registry.npmjs.org/@lexical/link/-/link-0.17.1.tgz",
"integrity": "sha512-ppvJSh/XGqlzbeymOiwcXJcUcrqgQqTK2QXTBAZq7JThtb0WsJxYd2CSLSN+Ycu23prnwqOqILcU0+34+gAVFw==", "integrity": "sha512-qFJEKBesZAtR8kfJfIVXRFXVw6dwcpmGCW7duJbtBRjdLjralOxrlVKyFhW9PEXGhi4Mdq2Ux16YnnDncpORdQ==",
"dependencies": { "dependencies": {
"@lexical/utils": "0.16.0", "@lexical/utils": "0.17.1",
"lexical": "0.16.0" "lexical": "0.17.1"
} }
}, },
"node_modules/@lexical/list": { "node_modules/@lexical/list": {
"version": "0.16.0", "version": "0.17.1",
"resolved": "https://registry.npmjs.org/@lexical/list/-/list-0.16.0.tgz", "resolved": "https://registry.npmjs.org/@lexical/list/-/list-0.17.1.tgz",
"integrity": "sha512-nBx/DMM7nCgnOzo1JyNnVaIrk/Xi5wIPNi8jixrEV6w9Om2K6dHutn/79Xzp2dQlNGSLHEDjky6N2RyFgmXh0g==", "integrity": "sha512-k9ZnmQuBvW+xVUtWJZwoGtiVG2cy+hxzkLGU4jTq1sqxRIoSeGcjvhFAK8JSEj4i21SgkB1FmkWXoYK5kbwtRA==",
"dependencies": { "dependencies": {
"@lexical/utils": "0.16.0", "@lexical/utils": "0.17.1",
"lexical": "0.16.0" "lexical": "0.17.1"
} }
}, },
"node_modules/@lexical/rich-text": { "node_modules/@lexical/rich-text": {
"version": "0.16.0", "version": "0.17.1",
"resolved": "https://registry.npmjs.org/@lexical/rich-text/-/rich-text-0.16.0.tgz", "resolved": "https://registry.npmjs.org/@lexical/rich-text/-/rich-text-0.17.1.tgz",
"integrity": "sha512-AGTD6yJZ+kj2TNah1r7/6vyufs6fZANeSvv9x5eG+WjV4uyUJYkd1qR8C5gFZHdkyr+bhAcsAXvS039VzAxRrQ==", "integrity": "sha512-T3kvj4P1OpedX9jvxN3WN8NP1Khol6mCW2ScFIRNRz2dsXgyN00thH1Q1J/uyu7aKyGS7rzcY0rb1Pz1qFufqQ==",
"dependencies": { "dependencies": {
"@lexical/clipboard": "0.16.0", "@lexical/clipboard": "0.17.1",
"@lexical/selection": "0.16.0", "@lexical/selection": "0.17.1",
"@lexical/utils": "0.16.0", "@lexical/utils": "0.17.1",
"lexical": "0.16.0" "lexical": "0.17.1"
} }
}, },
"node_modules/@lexical/selection": { "node_modules/@lexical/selection": {
"version": "0.16.0", "version": "0.17.1",
"resolved": "https://registry.npmjs.org/@lexical/selection/-/selection-0.16.0.tgz", "resolved": "https://registry.npmjs.org/@lexical/selection/-/selection-0.17.1.tgz",
"integrity": "sha512-trT9gQVJ2j6AwAe7tHJ30SRuxCpV6yR9LFtggxphHsXSvJYnoHC0CXh1TF2jHl8Gd5OsdWseexGLBE4Y0V3gwQ==", "integrity": "sha512-qBKVn+lMV2YIoyRELNr1/QssXx/4c0id9NCB/BOuYlG8du5IjviVJquEF56NEv2t0GedDv4BpUwkhXT2QbNAxA==",
"dependencies": { "dependencies": {
"lexical": "0.16.0" "lexical": "0.17.1"
} }
}, },
"node_modules/@lexical/table": { "node_modules/@lexical/table": {
"version": "0.16.0", "version": "0.17.1",
"resolved": "https://registry.npmjs.org/@lexical/table/-/table-0.16.0.tgz", "resolved": "https://registry.npmjs.org/@lexical/table/-/table-0.17.1.tgz",
"integrity": "sha512-A66K779kxdr0yH2RwT2itsMnkzyFLFNPXyiWGLobCH8ON4QPuBouZvjbRHBe8Pe64yJ0c1bRDxSbTqUi9Wt3Gg==", "integrity": "sha512-2fUYPmxhyuMQX3MRvSsNaxbgvwGNJpHaKx1Ldc+PT2MvDZ6ALZkfsxbi0do54Q3i7dOon8/avRp4TuVaCnqvoA==",
"dependencies": { "dependencies": {
"@lexical/utils": "0.16.0", "@lexical/utils": "0.17.1",
"lexical": "0.16.0" "lexical": "0.17.1"
} }
}, },
"node_modules/@lexical/utils": { "node_modules/@lexical/utils": {
"version": "0.16.0", "version": "0.17.1",
"resolved": "https://registry.npmjs.org/@lexical/utils/-/utils-0.16.0.tgz", "resolved": "https://registry.npmjs.org/@lexical/utils/-/utils-0.17.1.tgz",
"integrity": "sha512-GWmFEmd7o3GHqJBaEwzuZQbfTNI3Gg8ReGuHMHABgrkhZ8j2NggoRBlxsQLG0f7BewfTMVwbye22yBPq78775w==", "integrity": "sha512-jCQER5EsvhLNxKH3qgcpdWj/necUb82Xjp8qWQ3c0tyL07hIRm2tDRA/s9mQmvcP855HEZSmGVmR5SKtkcEAVg==",
"dependencies": { "dependencies": {
"@lexical/list": "0.16.0", "@lexical/list": "0.17.1",
"@lexical/selection": "0.16.0", "@lexical/selection": "0.17.1",
"@lexical/table": "0.16.0", "@lexical/table": "0.17.1",
"lexical": "0.16.0" "lexical": "0.17.1"
} }
}, },
"node_modules/@lezer/common": { "node_modules/@lezer/common": {
@ -811,9 +811,9 @@
} }
}, },
"node_modules/@lezer/highlight": { "node_modules/@lezer/highlight": {
"version": "1.2.0", "version": "1.2.1",
"resolved": "https://registry.npmjs.org/@lezer/highlight/-/highlight-1.2.0.tgz", "resolved": "https://registry.npmjs.org/@lezer/highlight/-/highlight-1.2.1.tgz",
"integrity": "sha512-WrS5Mw51sGrpqjlh3d4/fOwpEV2Hd3YOkp9DBt4k8XZQcoTHZFB7sx030A6OcahF4J1nDQAa3jXlTVVYH50IFA==", "integrity": "sha512-Z5duk4RN/3zuVO7Jq0pGLJ3qynpxUVsh7IbUbGj88+uV2ApSAn6kWg2au3iJb+0Zi7kKtqffIESgNcRXWZWmSA==",
"dependencies": { "dependencies": {
"@lezer/common": "^1.0.0" "@lezer/common": "^1.0.0"
} }
@ -849,17 +849,17 @@
} }
}, },
"node_modules/@lezer/lr": { "node_modules/@lezer/lr": {
"version": "1.4.1", "version": "1.4.2",
"resolved": "https://registry.npmjs.org/@lezer/lr/-/lr-1.4.1.tgz", "resolved": "https://registry.npmjs.org/@lezer/lr/-/lr-1.4.2.tgz",
"integrity": "sha512-CHsKq8DMKBf9b3yXPDIU4DbH+ZJd/sJdYOW2llbW/HudP5u0VS6Bfq1hLYfgU7uAYGFIyGGQIsSOXGPEErZiJw==", "integrity": "sha512-pu0K1jCIdnQ12aWNaAVU5bzi7Bd1w54J3ECgANPmYLtQKP0HBj2cE/5coBD66MT10xbtIuUr7tg0Shbsvk0mDA==",
"dependencies": { "dependencies": {
"@lezer/common": "^1.0.0" "@lezer/common": "^1.0.0"
} }
}, },
"node_modules/@lezer/markdown": { "node_modules/@lezer/markdown": {
"version": "1.3.0", "version": "1.3.1",
"resolved": "https://registry.npmjs.org/@lezer/markdown/-/markdown-1.3.0.tgz", "resolved": "https://registry.npmjs.org/@lezer/markdown/-/markdown-1.3.1.tgz",
"integrity": "sha512-ErbEQ15eowmJUyT095e9NJc3BI9yZ894fjSDtHftD0InkfUBGgnKSU6dvan9jqsZuNHg2+ag/1oyDRxNsENupQ==", "integrity": "sha512-DGlzU/i8DC8k0uz1F+jeePrkATl0jWakauTzftMQOcbaMkHbNSRki/4E2tOzJWsVpoKYhe7iTJ03aepdwVUXUA==",
"dependencies": { "dependencies": {
"@lezer/common": "^1.0.0", "@lezer/common": "^1.0.0",
"@lezer/highlight": "^1.0.0" "@lezer/highlight": "^1.0.0"
@ -920,6 +920,12 @@
"node": ">= 8" "node": ">= 8"
} }
}, },
"node_modules/@rtsao/scc": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/@rtsao/scc/-/scc-1.1.0.tgz",
"integrity": "sha512-zt6OdqaDoOnJ1ZYsCYGt9YmWzDXl4vQdKTyJev62gFhRGKdx7mcT54V9KIjg+d2wi9EXsPvAPKe7i7WjfVWB8g==",
"dev": true
},
"node_modules/@ssddanbrown/codemirror-lang-smarty": { "node_modules/@ssddanbrown/codemirror-lang-smarty": {
"version": "1.0.0", "version": "1.0.0",
"resolved": "https://registry.npmjs.org/@ssddanbrown/codemirror-lang-smarty/-/codemirror-lang-smarty-1.0.0.tgz", "resolved": "https://registry.npmjs.org/@ssddanbrown/codemirror-lang-smarty/-/codemirror-lang-smarty-1.0.0.tgz",
@ -948,9 +954,9 @@
"dev": true "dev": true
}, },
"node_modules/acorn": { "node_modules/acorn": {
"version": "8.12.0", "version": "8.12.1",
"resolved": "https://registry.npmjs.org/acorn/-/acorn-8.12.0.tgz", "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.12.1.tgz",
"integrity": "sha512-RTvkC4w+KNXrM39/lWCUaG0IbRkWdCv7W/IOW9oU6SawyxulvkQy5HQPVTKxEjczcUvapcrw3cFx/60VN/NRNw==", "integrity": "sha512-tcpGyI9zbizT9JbV6oYE477V6mTlXvvi0T0G3SNIYE2apm/G5huBa1+K89VGeovbg+jycCrfhl3ADxErOuO6Jg==",
"dev": true, "dev": true,
"bin": { "bin": {
"acorn": "bin/acorn" "acorn": "bin/acorn"
@ -1437,12 +1443,12 @@
} }
}, },
"node_modules/debug": { "node_modules/debug": {
"version": "4.3.5", "version": "4.3.7",
"resolved": "https://registry.npmjs.org/debug/-/debug-4.3.5.tgz", "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.7.tgz",
"integrity": "sha512-pt0bNEmneDIvdL1Xsd9oDQ/wrQRkXDT4AUWlNZNPKvW5x/jyO9VFXkJUP07vQ2upmw5PlaITaPKc31jK13V+jg==", "integrity": "sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ==",
"dev": true, "dev": true,
"dependencies": { "dependencies": {
"ms": "2.1.2" "ms": "^2.1.3"
}, },
"engines": { "engines": {
"node": ">=6.0" "node": ">=6.0"
@ -1818,9 +1824,9 @@
} }
}, },
"node_modules/eslint-module-utils": { "node_modules/eslint-module-utils": {
"version": "2.8.1", "version": "2.11.0",
"resolved": "https://registry.npmjs.org/eslint-module-utils/-/eslint-module-utils-2.8.1.tgz", "resolved": "https://registry.npmjs.org/eslint-module-utils/-/eslint-module-utils-2.11.0.tgz",
"integrity": "sha512-rXDXR3h7cs7dy9RNpUlQf80nX31XWJEyGq1tRMo+6GsO5VmTe4UTwtmonAD4ZkAsrfMVDA2wlGJ3790Ys+D49Q==", "integrity": "sha512-gbBE5Hitek/oG6MUVj6sFuzEjA/ClzNflVrLovHi/JgLdC7fiN5gLAY1WIPW1a0V5I999MnsrvVrCOGmmVqDBQ==",
"dev": true, "dev": true,
"dependencies": { "dependencies": {
"debug": "^3.2.7" "debug": "^3.2.7"
@ -1844,26 +1850,27 @@
} }
}, },
"node_modules/eslint-plugin-import": { "node_modules/eslint-plugin-import": {
"version": "2.29.1", "version": "2.30.0",
"resolved": "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.29.1.tgz", "resolved": "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.30.0.tgz",
"integrity": "sha512-BbPC0cuExzhiMo4Ff1BTVwHpjjv28C5R+btTOGaCRC7UEz801up0JadwkeSk5Ued6TG34uaczuVuH6qyy5YUxw==", "integrity": "sha512-/mHNE9jINJfiD2EKkg1BKyPyUk4zdnT54YgbOgfjSakWT5oyX/qQLVNTkehyfpcMxZXMy1zyonZ2v7hZTX43Yw==",
"dev": true, "dev": true,
"dependencies": { "dependencies": {
"array-includes": "^3.1.7", "@rtsao/scc": "^1.1.0",
"array.prototype.findlastindex": "^1.2.3", "array-includes": "^3.1.8",
"array.prototype.findlastindex": "^1.2.5",
"array.prototype.flat": "^1.3.2", "array.prototype.flat": "^1.3.2",
"array.prototype.flatmap": "^1.3.2", "array.prototype.flatmap": "^1.3.2",
"debug": "^3.2.7", "debug": "^3.2.7",
"doctrine": "^2.1.0", "doctrine": "^2.1.0",
"eslint-import-resolver-node": "^0.3.9", "eslint-import-resolver-node": "^0.3.9",
"eslint-module-utils": "^2.8.0", "eslint-module-utils": "^2.9.0",
"hasown": "^2.0.0", "hasown": "^2.0.2",
"is-core-module": "^2.13.1", "is-core-module": "^2.15.1",
"is-glob": "^4.0.3", "is-glob": "^4.0.3",
"minimatch": "^3.1.2", "minimatch": "^3.1.2",
"object.fromentries": "^2.0.7", "object.fromentries": "^2.0.8",
"object.groupby": "^1.0.1", "object.groupby": "^1.0.3",
"object.values": "^1.1.7", "object.values": "^1.2.0",
"semver": "^6.3.1", "semver": "^6.3.1",
"tsconfig-paths": "^3.15.0" "tsconfig-paths": "^3.15.0"
}, },
@ -1953,9 +1960,9 @@
} }
}, },
"node_modules/esquery": { "node_modules/esquery": {
"version": "1.5.0", "version": "1.6.0",
"resolved": "https://registry.npmjs.org/esquery/-/esquery-1.5.0.tgz", "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.6.0.tgz",
"integrity": "sha512-YQLXUplAwJgCydQ78IMJywZCceoqk1oH01OERdSAJc/7U2AylwjhSCLDEtqwg811idIS/9fIU5GjG73IgjKMVg==", "integrity": "sha512-ca9pw9fomFcKPvFLXhBKUK90ZvGibiGOvRJNbjljY7s7uq/5YO4BOzcYtJqExdx99rF6aAcnRxHmcUHcz6sQsg==",
"dev": true, "dev": true,
"dependencies": { "dependencies": {
"estraverse": "^5.1.0" "estraverse": "^5.1.0"
@ -2372,18 +2379,18 @@
"integrity": "sha512-8Sb3veuYCyrZL+VBt9LJfZjLUPWVvqn8tG28VqYNFCo43KHcKuq+b4EiXGeuaLAQWL2YmyDgMp2aSpH9JHsEQg==" "integrity": "sha512-8Sb3veuYCyrZL+VBt9LJfZjLUPWVvqn8tG28VqYNFCo43KHcKuq+b4EiXGeuaLAQWL2YmyDgMp2aSpH9JHsEQg=="
}, },
"node_modules/ignore": { "node_modules/ignore": {
"version": "5.3.1", "version": "5.3.2",
"resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.1.tgz", "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.2.tgz",
"integrity": "sha512-5Fytz/IraMjqpwfd34ke28PTVMjZjJG2MPn5t7OE4eUCUNf8BAa7b5WUS9/Qvr6mwOQS7Mk6vdsMno5he+T8Xw==", "integrity": "sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==",
"dev": true, "dev": true,
"engines": { "engines": {
"node": ">= 4" "node": ">= 4"
} }
}, },
"node_modules/immutable": { "node_modules/immutable": {
"version": "4.3.6", "version": "4.3.7",
"resolved": "https://registry.npmjs.org/immutable/-/immutable-4.3.6.tgz", "resolved": "https://registry.npmjs.org/immutable/-/immutable-4.3.7.tgz",
"integrity": "sha512-Ju0+lEMyzMVZarkTn/gqRpdqd5dOPaz1mCZ0SH3JV6iFw81PldE/PEB1hWVEA288HPt4WXW8O7AWxB10M+03QQ==", "integrity": "sha512-1hqclzwYwjRDFLjcFxOM5AYkkG0rpFPpr1RLPMEuGczoS7YA8gLhy8SWXYRAA/XwfEHpfo3cw5JGioS32fnMRw==",
"dev": true "dev": true
}, },
"node_modules/import-fresh": { "node_modules/import-fresh": {
@ -2517,9 +2524,9 @@
} }
}, },
"node_modules/is-core-module": { "node_modules/is-core-module": {
"version": "2.14.0", "version": "2.15.1",
"resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.14.0.tgz", "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.15.1.tgz",
"integrity": "sha512-a5dFJih5ZLYlRtDc0dZWP7RiKr6xIKzmn/oAYCDvdLThadVgyJwlaoQPmRtMSpz+rk0OGAgIu+TcM9HUF0fk1A==", "integrity": "sha512-z0vtXSwucUJtANQWldhbtbt7BnL0vxiFjIdDLAatwhDYty2bad6s+rijD6Ri4YuYJubLzIJLUidCh09e1djEVQ==",
"dev": true, "dev": true,
"dependencies": { "dependencies": {
"hasown": "^2.0.2" "hasown": "^2.0.2"
@ -2807,9 +2814,9 @@
} }
}, },
"node_modules/lexical": { "node_modules/lexical": {
"version": "0.16.0", "version": "0.17.1",
"resolved": "https://registry.npmjs.org/lexical/-/lexical-0.16.0.tgz", "resolved": "https://registry.npmjs.org/lexical/-/lexical-0.17.1.tgz",
"integrity": "sha512-Skn45Qhriazq4fpAtwnAB11U//GKc4vjzx54xsV3TkDLDvWpbL4Z9TNRwRoN3g7w8AkWnqjeOSODKkrjgfRSrg==" "integrity": "sha512-72/MhR7jqmyqD10bmJw8gztlCm4KDDT+TPtU4elqXrEvHoO5XENi34YAEUD9gIkPfqSwyLa9mwAX1nKzIr5xEA=="
}, },
"node_modules/linkify-it": { "node_modules/linkify-it": {
"version": "5.0.0", "version": "5.0.0",
@ -2948,9 +2955,9 @@
} }
}, },
"node_modules/ms": { "node_modules/ms": {
"version": "2.1.2", "version": "2.1.3",
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz",
"integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==",
"dev": true "dev": true
}, },
"node_modules/natural-compare": { "node_modules/natural-compare": {
@ -3659,9 +3666,9 @@
} }
}, },
"node_modules/sass": { "node_modules/sass": {
"version": "1.77.6", "version": "1.78.0",
"resolved": "https://registry.npmjs.org/sass/-/sass-1.77.6.tgz", "resolved": "https://registry.npmjs.org/sass/-/sass-1.78.0.tgz",
"integrity": "sha512-ByXE1oLD79GVq9Ht1PeHWCPMPB8XHpBuz1r85oByKHjZY6qV6rWnQovQzXJXuQ/XyE1Oj3iPk3lo28uzaRA2/Q==", "integrity": "sha512-AaIqGSrjo5lA2Yg7RvFZrlXDBCp3nV4XP73GrLGvdRWWwk+8H3l0SDvq/5bA4eF+0RFPLuWUk3E+P1U/YqnpsQ==",
"dev": true, "dev": true,
"dependencies": { "dependencies": {
"chokidar": ">=3.0.0 <4.0.0", "chokidar": ">=3.0.0 <4.0.0",
@ -3779,9 +3786,9 @@
} }
}, },
"node_modules/sortablejs": { "node_modules/sortablejs": {
"version": "1.15.2", "version": "1.15.3",
"resolved": "https://registry.npmjs.org/sortablejs/-/sortablejs-1.15.2.tgz", "resolved": "https://registry.npmjs.org/sortablejs/-/sortablejs-1.15.3.tgz",
"integrity": "sha512-FJF5jgdfvoKn1MAKSdGs33bIqLi3LmsgVTliuX6iITj834F+JRQZN90Z93yql8h0K2t0RwDPBmxwlbZfDcxNZA==" "integrity": "sha512-zdK3/kwwAK1cJgy1rwl1YtNTbRmc8qW/+vgXf75A7NHag5of4pyI6uK86ktmQETyWRH7IGaE73uZOOBcGxgqZg=="
}, },
"node_modules/source-map-js": { "node_modules/source-map-js": {
"version": "1.2.0", "version": "1.2.0",
@ -3819,9 +3826,9 @@
} }
}, },
"node_modules/spdx-license-ids": { "node_modules/spdx-license-ids": {
"version": "3.0.18", "version": "3.0.20",
"resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.18.tgz", "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.20.tgz",
"integrity": "sha512-xxRs31BqRYHwiMzudOrpSiHtZ8i/GeionCBDSilhYRj+9gIcI8wCZTlXZKu9vZIVqViP3dcp9qE5G6AlIaD+TQ==", "integrity": "sha512-jg25NiDV/1fLtSgEgyvVyDunvaNHbuwF9lfNV17gSmPFAlYzdfNBlLtLzXTevwkPj7DhGbmN9VnmJIgLnhvaBw==",
"dev": true "dev": true
}, },
"node_modules/string-width": { "node_modules/string-width": {
@ -4116,9 +4123,9 @@
} }
}, },
"node_modules/typescript": { "node_modules/typescript": {
"version": "5.5.2", "version": "5.5.4",
"resolved": "https://registry.npmjs.org/typescript/-/typescript-5.5.2.tgz", "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.5.4.tgz",
"integrity": "sha512-NcRtPEOsPFFWjobJEtfihkLCZCXZt/os3zf8nTxjVH3RvTSxjrCamJpbExGvYOF+tFHc3pA65qpdwPbzjohhew==", "integrity": "sha512-Mtq29sKDAEYP7aljRgtPOpTvOfbwRWlS6dPRzwjdE+C0R4brX/GUyhHSecbHMFLNBLcJIPt9nl9yG5TZ1weH+Q==",
"dev": true, "dev": true,
"bin": { "bin": {
"tsc": "bin/tsc", "tsc": "bin/tsc",

View File

@ -43,20 +43,20 @@
"@codemirror/state": "^6.3.3", "@codemirror/state": "^6.3.3",
"@codemirror/theme-one-dark": "^6.1.2", "@codemirror/theme-one-dark": "^6.1.2",
"@codemirror/view": "^6.22.2", "@codemirror/view": "^6.22.2",
"@lexical/history": "^0.16.0", "@lexical/history": "^0.17.0",
"@lexical/html": "^0.16.0", "@lexical/html": "^0.17.0",
"@lexical/link": "^0.16.0", "@lexical/link": "^0.17.0",
"@lexical/list": "^0.16.0", "@lexical/list": "^0.17.0",
"@lexical/rich-text": "^0.16.0", "@lexical/rich-text": "^0.17.0",
"@lexical/selection": "^0.16.0", "@lexical/selection": "^0.17.0",
"@lexical/table": "^0.16.0", "@lexical/table": "^0.17.0",
"@lexical/utils": "^0.16.0", "@lexical/utils": "^0.17.0",
"@lezer/highlight": "^1.2.0", "@lezer/highlight": "^1.2.0",
"@ssddanbrown/codemirror-lang-smarty": "^1.0.0", "@ssddanbrown/codemirror-lang-smarty": "^1.0.0",
"@ssddanbrown/codemirror-lang-twig": "^1.0.0", "@ssddanbrown/codemirror-lang-twig": "^1.0.0",
"codemirror": "^6.0.1", "codemirror": "^6.0.1",
"idb-keyval": "^6.2.1", "idb-keyval": "^6.2.1",
"lexical": "^0.16.0", "lexical": "^0.17.0",
"markdown-it": "^14.1.0", "markdown-it": "^14.1.0",
"markdown-it-task-lists": "^2.1.1", "markdown-it-task-lists": "^2.1.1",
"snabbdom": "^3.5.1", "snabbdom": "^3.5.1",

View File

@ -1,4 +1,4 @@
import {createEditor, CreateEditorArgs, LexicalEditor} from 'lexical'; import {$getSelection, createEditor, CreateEditorArgs, isCurrentlyReadOnlyMode, LexicalEditor} from 'lexical';
import {createEmptyHistoryState, registerHistory} from '@lexical/history'; import {createEmptyHistoryState, registerHistory} from '@lexical/history';
import {registerRichText} from '@lexical/rich-text'; import {registerRichText} from '@lexical/rich-text';
import {mergeRegister} from '@lexical/utils'; import {mergeRegister} from '@lexical/utils';
@ -69,7 +69,19 @@ export function createPageEditorInstance(container: HTMLElement, htmlContent: st
} }
let changeFromLoading = true; let changeFromLoading = true;
editor.registerUpdateListener(({editorState, dirtyElements, dirtyLeaves}) => { editor.registerUpdateListener(({dirtyElements, dirtyLeaves, editorState, prevEditorState}) => {
// Watch for selection changes to update the UI on change
// Used to be done via SELECTION_CHANGE_COMMAND but this would not always emit
// for all selection changes, so this proved more reliable.
const selectionChange = !(prevEditorState._selection?.is(editorState._selection) || false);
if (selectionChange) {
editor.update(() => {
const selection = $getSelection();
context.manager.triggerStateUpdate({
editor, selection,
});
});
}
// Emit change event to component system (for draft detection) on actual user content change // Emit change event to component system (for draft detection) on actual user content change
if (dirtyElements.size > 0 || dirtyLeaves.size > 0) { if (dirtyElements.size > 0 || dirtyLeaves.size > 0) {

View File

@ -40,7 +40,7 @@ export class ImageNode extends ElementNode {
alt: node.__alt, alt: node.__alt,
width: node.__width, width: node.__width,
height: node.__height, height: node.__height,
}); }, node.__key);
newNode.__alignment = node.__alignment; newNode.__alignment = node.__alignment;
return newNode; return newNode;
} }

View File

@ -16,6 +16,4 @@
## Bugs ## Bugs
- Removing link around image via button deletes image, not just link
- `SELECTION_CHANGE_COMMAND` not fired when clicking out of a table cell. Prevents toolbar hiding on table unselect.
- Template drag/drop not handled when outside core editor area (ignored in margin area). - Template drag/drop not handled when outside core editor area (ignored in margin area).

View File

@ -19,6 +19,7 @@ export const undo: EditorButtonDefinition = {
icon: undoIcon, icon: undoIcon,
action(context: EditorUiContext) { action(context: EditorUiContext) {
context.editor.dispatchCommand(UNDO_COMMAND, undefined); context.editor.dispatchCommand(UNDO_COMMAND, undefined);
context.manager.triggerFutureStateRefresh();
}, },
isActive(selection: BaseSelection|null): boolean { isActive(selection: BaseSelection|null): boolean {
return false; return false;
@ -38,6 +39,7 @@ export const redo: EditorButtonDefinition = {
icon: redoIcon, icon: redoIcon,
action(context: EditorUiContext) { action(context: EditorUiContext) {
context.editor.dispatchCommand(REDO_COMMAND, undefined); context.editor.dispatchCommand(REDO_COMMAND, undefined);
context.manager.triggerFutureStateRefresh();
}, },
isActive(selection: BaseSelection|null): boolean { isActive(selection: BaseSelection|null): boolean {
return false; return false;

View File

@ -6,7 +6,7 @@ import {
$getRoot, $getRoot,
$getSelection, $insertNodes, $getSelection, $insertNodes,
BaseSelection, BaseSelection,
ElementNode ElementNode, isCurrentlyReadOnlyMode
} from "lexical"; } from "lexical";
import {$isLinkNode, LinkNode} from "@lexical/link"; import {$isLinkNode, LinkNode} from "@lexical/link";
import unlinkIcon from "@icons/editor/unlink.svg"; import unlinkIcon from "@icons/editor/unlink.svg";
@ -54,16 +54,17 @@ export const unlink: EditorButtonDefinition = {
context.editor.update(() => { context.editor.update(() => {
const selection = getLastSelection(context.editor); const selection = getLastSelection(context.editor);
const selectedLink = $getNodeFromSelection(selection, $isLinkNode) as LinkNode | null; const selectedLink = $getNodeFromSelection(selection, $isLinkNode) as LinkNode | null;
const selectionPoints = selection?.getStartEndPoints();
if (selectedLink) { if (selectedLink) {
const newNode = $createTextNode(selectedLink.getTextContent()); const contents = selectedLink.getChildren().reverse();
selectedLink.replace(newNode); for (const child of contents) {
if (selectionPoints?.length === 2) { selectedLink.insertAfter(child);
newNode.select(selectionPoints[0].offset, selectionPoints[1].offset);
} else {
newNode.select();
} }
selectedLink.remove();
contents[contents.length - 1].selectStart();
context.manager.triggerFutureStateRefresh();
} }
}); });
}, },

View File

@ -108,7 +108,7 @@ export class EditorUIManager {
this.contextToolbarDefinitionsByKey[key] = definition; this.contextToolbarDefinitionsByKey[key] = definition;
} }
protected triggerStateUpdate(update: EditorUiStateUpdate): void { triggerStateUpdate(update: EditorUiStateUpdate): void {
setLastSelection(update.editor, update.selection); setLastSelection(update.editor, update.selection);
this.toolbar?.updateState(update); this.toolbar?.updateState(update);
this.updateContextToolbars(update); this.updateContextToolbars(update);
@ -120,9 +120,20 @@ export class EditorUIManager {
triggerStateRefresh(): void { triggerStateRefresh(): void {
const editor = this.getContext().editor; const editor = this.getContext().editor;
this.triggerStateUpdate({ const update = {
editor, editor,
selection: getLastSelection(editor), selection: getLastSelection(editor),
};
this.triggerStateUpdate(update);
this.updateContextToolbars(update);
}
triggerFutureStateRefresh(): void {
requestAnimationFrame(() => {
this.getContext().editor.getEditorState().read(() => {
this.triggerStateRefresh();
});
}); });
} }
@ -195,15 +206,6 @@ export class EditorUIManager {
} }
protected setupEditor(editor: LexicalEditor) { protected setupEditor(editor: LexicalEditor) {
// Update button states on editor selection change
editor.registerCommand(SELECTION_CHANGE_COMMAND, () => {
this.triggerStateUpdate({
editor: editor,
selection: $getSelection(),
});
return false;
}, COMMAND_PRIORITY_LOW);
// Register our DOM decorate listener with the editor // Register our DOM decorate listener with the editor
const domDecorateListener: DecoratorListener<EditorDecoratorAdapter> = (decorators: Record<NodeKey, EditorDecoratorAdapter>) => { const domDecorateListener: DecoratorListener<EditorDecoratorAdapter> = (decorators: Record<NodeKey, EditorDecoratorAdapter>) => {
editor.getEditorState().read(() => { editor.getEditorState().read(() => {