feat(editor): experimental Tiptap-based message composer#876
Draft
Just-Insane wants to merge 6 commits into
Draft
feat(editor): experimental Tiptap-based message composer#876Just-Insane wants to merge 6 commits into
Just-Insane wants to merge 6 commits into
Conversation
Adds an opt-in Tiptap-based message composer gated behind
Settings > Experimental > 'Tiptap Composer'.
New packages:
@tiptap/core @tiptap/react @tiptap/pm @tiptap/starter-kit
@tiptap/extension-mention @tiptap/extension-link
@tiptap/extension-placeholder @tiptap/suggestion
New files:
src/app/components/editor-tiptap/
extensions/MentionExtension.ts – Matrix mention node
extensions/EmoticonExtension.ts – custom emoji node
extensions/CommandExtension.ts – /command node
TiptapEditor.tsx – drop-in editor component
TiptapEditor.css.ts – vanilla-extract styles
output.ts – Matrix HTML + plain-text serializers
index.ts – public barrel
src/app/features/room/
RoomInputTiptap.tsx – experimental composer component
tiptap-autocomplete/
TiptapAutocompleteMenu.tsx – shared popup shell (no Slate dep)
TiptapMentionAutocomplete.tsx – @user mention popup
TiptapRoomMentionAutocomplete.tsx – #room mention popup
TiptapEmoticonAutocomplete.tsx – :emoticon: popup
Modified files:
src/app/state/settings.ts – add useTiptapComposer: boolean
src/app/features/settings/experimental/Experimental.tsx
– add TiptapComposerToggle
src/app/features/room/RoomView.tsx – conditional render of
RoomInputTiptap vs RoomInput
Not yet implemented in Tiptap composer:
file uploads, reply drafts, scheduled messages, voice recording,
emoji board, message draft persistence, command autocomplete popup
…TiptapEditor
vanilla-extract selectors{} only supports &-anchored self-selectors.
Descendant selectors like '& .ProseMirror' must use globalStyle() instead.
- Remove unused Icon, Icons, JoinRule, isRoomAlias, getMxIdServer, getViaServers, mDirectAtom imports from TiptapRoomMentionAutocomplete - Remove unused viaServers and isDM variables from TiptapRoomMentionAutocomplete - Remove unused useEffect from TiptapAutocompleteMenu and RoomInputTiptap - Remove unused Box and useMediaAuthentication from TiptapEmoticonAutocomplete - Remove unused label/highlight destructure in output.ts mention case - Fix roomId shadow in insertRoomMention callback (rename to mentionRoomId) - Fix \0 control character in regex → \u0000 with eslint-disable comment - Add eslint-disable for no-redundant-type-constituents on TiptapEditorInstance - Consolidate editor-tiptap imports in RoomInputTiptap to go through index.ts - Remove unused @tiptap/pm and @tiptap/suggestion from package.json
Contributor
Author
|
This is likely not going forward, in theory it works, but rebuilding all the integrations like the emoji picker, audio, etc is a lot of work that I don't have time for. Not sure if this should be left as a POC that others can pick up and tinker with or...? |
…dings Replaces manual tag-stripping regex + chained entity unescaping with DOMParser.parseFromString, which handles both safely. Resolves two CodeQL security warnings in tiptapCustomHtmlEqualsPlainText: - CWE-116: double-unescaping via chained & → & replacement - CWE-80: incomplete tag sanitization leaving <script paths open
…dundant cast - Move getKey (renamed getEmoticonKey) out of TiptapEmoticonAutocomplete to module scope to satisfy oxlint consistent-function-scoping. - Move getSearchStr (renamed getRoomSearchStr) out of TiptapRoomMentionAutocomplete to module scope for the same reason. - Remove redundant 'as' cast on prefix in RoomInputTiptap — the type guard at line 84 already narrows the type to '@' | '#' | ':'.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Description
Add an experimental Tiptap (ProseMirror) message composer as a drop-in replacement for the Slate composer, gated behind Settings > Experimental > "Tiptap Composer". Supports @mention, #room, and :emoticon: autocomplete with inline formatting. Uploads, replies, scheduled messages, and voice messages are not yet implemented.
Fixes #
Type of change
Checklist:
AI disclosure:
The Tiptap extension wiring and
tiptapToMatrixCustomHTMLserialiser were drafted with AI assistance. Each autocomplete type (@mention,#room,:emoticon:) is implemented as a TiptapSuggestionplugin that delegates query/render to the existing Sable autocomplete state machines. The serialiser walks the ProseMirror document tree and emits<a>pill markup for mention and room nodes. ThetiptapCustomHtmlEqualsPlainTextfunction usesDOMParser.parseFromString(replacing a manual regex chain flagged by CodeQL) to extract plain text from the HTML output for the equality check.