UX: keep marks when using emoji input rules on rich editor (#33058)

When typing `:emoji:` or `:)` to create emoji nodes through ProseMirror
inputrules, this PR changes the handler to enforce the use of the
existing marks in the current caret position (if it's a link, bold, etc)
so the newly created emoji is marked with the same marks(s).
This commit is contained in:
Renato Atilio
2025-06-04 07:18:47 -03:00
committed by GitHub
parent 72326aad65
commit 1633d7788a
2 changed files with 59 additions and 11 deletions

View File

@ -131,11 +131,16 @@ const extension = {
handler: (state, match, start, end) => {
if (emojiExists(match[2])) {
const emojiStart = start + match[1].length;
return state.tr.replaceWith(
emojiStart,
end,
state.schema.nodes.emoji.create({ code: match[2] })
);
const emojiNode = state.schema.nodes.emoji.create({ code: match[2] });
const tr = state.tr.replaceWith(emojiStart, end, emojiNode);
state.doc
.resolve(emojiStart)
.marks()
.forEach((mark) => {
tr.addMark(emojiStart, emojiStart + 1, mark);
});
return tr;
}
},
options: { undoable: false },
@ -148,13 +153,20 @@ const extension = {
),
handler: (state, match, start, end) => {
const emojiStart = start + match[1].length;
return state.tr
.replaceWith(
emojiStart,
end,
state.schema.nodes.emoji.create({ code: translations[match[2]] })
)
const emojiNode = state.schema.nodes.emoji.create({
code: translations[match[2]],
});
const tr = state.tr
.replaceWith(emojiStart, end, emojiNode)
.insertText(" ");
state.doc
.resolve(emojiStart)
.marks()
.forEach((mark) => {
tr.addMark(emojiStart, emojiStart + 2, mark);
});
return tr;
},
},
],

View File

@ -806,5 +806,41 @@ describe "Composer - ProseMirror editor", type: :system do
expect(rich).to have_no_css(".only-emoji")
end
it "preserves formatting marks when replacing text with emojis using :code: pattern" do
open_composer_and_toggle_rich_editor
composer.type_content("**bold :smile:**")
expect(rich).to have_css("strong img.emoji")
expect(rich).to have_css("strong", text: "bold")
composer.toggle_rich_editor
expect(composer).to have_value("**bold :smile:**")
end
it "preserves formatting marks when replacing text with emojis using text shortcuts" do
open_composer_and_toggle_rich_editor
composer.type_content("*italics :) *")
expect(rich).to have_css("em img.emoji")
expect(rich).to have_css("em", text: "italics")
composer.toggle_rich_editor
expect(composer).to have_value("*italics :slight_smile:* ")
end
it "preserves link marks when replacing text with emojis" do
open_composer_and_toggle_rich_editor
composer.type_content("[link text :heart:](https://example.com)")
expect(rich).to have_css("a img.emoji")
expect(rich).to have_css("a", text: "link text")
composer.toggle_rich_editor
expect(composer).to have_value("[link text :heart:](https://example.com)")
end
end
end