Skip to content

fix: support GitLab's rich text editor - #29

Open
nicanor-romero wants to merge 4 commits into
pullpo-io:mainfrom
nicanor-romero:fix/gitlab-rich-text-editor
Open

fix: support GitLab's rich text editor#29
nicanor-romero wants to merge 4 commits into
pullpo-io:mainfrom
nicanor-romero:fix/gitlab-rich-text-editor

Conversation

@nicanor-romero

Copy link
Copy Markdown

Closes #25

📑 Description

Adds support for GitLab's rich text editor (Tiptap/ProseMirror), where the <textarea> is swapped for a contenteditable and no toolbar was attached.

Comment inputs are now driven through an editor-handle abstraction:

  • TextareaHandle keeps the existing behaviour for GitHub and GitLab's markdown mode.
  • RichTextHandle reads the current prefix straight from the rendered ProseMirror DOM and writes through the editor instead of around it: badges are inserted with a synthetic text/x-gfm paste (which GitLab's copyPaste content-editor extension turns into real nodes), plain prefixes are typed with insertText, and removals go through ProseMirror's deleteSelection.

The label/badge/regex definitions moved to content/conventional-comments.js so both handles can share them.

Follow-up fixes on the same branch:

  • Keep the toolbar clear of GitLab's rich text placeholder.
  • Stop GitLab stacking badges when a decoration is picked.
  • Replace the GitLab badge instead of losing it (delete the old prefix before pasting; write the trailing separator as a non-breaking space since the renderer strips ASCII whitespace).

✅ Checks

  • My pull request adheres to the code style of this project
  • I have updated the documentation if required
  • All the CI workflows have passed

ℹ️ Additional Information

Tested manually on gitlab.com with rich text editing enabled and disabled, and on github.com to confirm the existing textarea behaviour is unchanged. No breaking changes, no new dependencies.

The extension only ever targeted `<textarea>` elements. When GitLab
switches to "rich text editing" the textarea is swapped for a
Tiptap/ProseMirror `contenteditable`, so no toolbar was attached and
labels could not be inserted (pullpo-io#25).

Comment inputs are now driven through an editor-handle abstraction:

* `TextareaHandle` keeps the existing behaviour for GitHub and GitLab's
  markdown mode.
* `RichTextHandle` reads the current prefix straight from the rendered
  ProseMirror DOM (a leading `pullpo.io/cc` link for badges, leading text
  matching `PLAIN_CC_REGEX` otherwise) and writes through the editor
  instead of around it: badges are inserted with a synthetic `text/x-gfm`
  paste, which GitLab's `copyPaste` content-editor extension turns into
  real nodes, plain prefixes are typed with `insertText`, and removals go
  through ProseMirror's own `deleteSelection`.

The label/badge/regex definitions moved to `content/conventional-comments.js`
so both handles can share them.
`content_editor.vue` renders the "Write a comment…" empty state as an
absolutely positioned sibling of the editable box, so its top edge is
pinned to wherever the editor header ends. Mounting the toolbar between
the header and the editable box therefore drew the two on top of each
other.

Mount into the header instead. Placement is now the handle's
responsibility (`mountToolbar`) rather than something the toolbar code
derives from a single anchor node.
`pasteContent` drops the selection a microtask after the paste event and
only inserts the rendered markdown once the renderer has answered, so the
badge being replaced is still on screen when the paste handler returns.
`awaitBadge` matched it, concluded the write was done and collapsed the
caret — clearing the selection that GitLab was about to delete. The old
badge survived and the new one landed next to it.

Wait for a badge anchored to a different node than the one we set out to
replace.
Selecting a decoration on top of a label deleted the existing badge and
left the comment empty, with no error.

`pasteContent` anchors the rendered markdown to a loader widget added in
the same transaction that clears the selection, and that widget never
reaches the document when there is a selection to clear — `findLoader`
then returns null and the insert is silently skipped. Delete the old
prefix ourselves so the paste always runs against an empty selection,
which is the path that works.

The trailing space separating the badge from the comment body is written
as a non-breaking space too: the renderer strips ASCII whitespace at the
end of the markdown, so the `insertText` fallback was the only thing
producing it and it does not survive on gitlab.com either.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[BUG]: GitLab: not working for Rich Text Editor

2 participants