FEATURE: introduce a ProseMirror editor (#30815)

This is the first in a series of PRs to introduce a
ProseMirror-based
WYSIWYM editor experience
alongside our current textarea Markdown editor.

Behind a hidden site setting, this PR adds a toggle to the composer
toolbar, allowing users to switch between the two options.

Our implementation builds upon the excellent ProseMirror and its
non-core Markdown
module, using the
module's schema, parsing, and serialization definitions as the base for
further Discourse-specific features.

An extension API is included to enable further customizations.

The necessary extensions to support all Discourse's core and core
plugins features **will be implemented in subsequent PRs**.

---------

Co-authored-by: David Taylor <david@taylorhq.com>
This commit is contained in:
Renato Atilio
2025-02-04 14:37:18 -03:00
committed by GitHub
parent 6d6e9c174d
commit 0e61565b2b
49 changed files with 3200 additions and 130 deletions

View File

@ -658,7 +658,11 @@ export default class ChatChannel extends Component {
return;
}
if (!target || /^(INPUT|TEXTAREA|SELECT)$/.test(target.tagName)) {
if (
!target ||
/^(INPUT|TEXTAREA|SELECT)$/.test(target.tagName) ||
target.closest('[contenteditable="true"]')
) {
return;
}

View File

@ -58,10 +58,10 @@ export default {
const inputs = ["input", "textarea", "select", "button"];
const elementTagName = el?.tagName.toLowerCase();
if (inputs.includes(elementTagName)) {
return false;
}
return true;
return (
inputs.includes(elementTagName) ||
!!el?.closest('[contenteditable="true"]')
);
};
const modifyComposerSelection = (event, type) => {
if (!isChatComposer(event.target)) {
@ -87,7 +87,7 @@ export default {
};
const openChatDrawer = (event) => {
if (!isInputSelection(event.target)) {
if (isInputSelection(event.target)) {
return;
}
event.preventDefault();