Support pasting URLs over markdown text (#29566)

Support pasting URLs over selection text in the textarea editor. Does
not work in EasyMDE and I don't intend to support it. Image paste works
as usual in both Textarea and EasyMDE.

The new `replaceTextareaSelection` function changes textarea content via
[`insertText`](https://developer.mozilla.org/en-US/docs/Web/API/Document/execCommand#using_inserttext)
command, which preserves history, e.g. `CTRL-Z` works and is also
demostrated below. We should later refactor the image paste code to use
the same function because it currently destroys history.

Overriding the formatting via `Shift` key is supported as well, e.g.
`Ctrl+Shift+V` will insert the URL as-is, like on GitHub.

![urlpaste](522b1023-6797-401c-9e4a-498570adfc88)

(cherry picked from commit a3cfe6f39ba33cea305de592a006727857014c53)
This commit is contained in:
silverwind 2024-03-08 16:15:58 +01:00 committed by Earl Warren
parent 18e0647c84
commit 4511287676
No known key found for this signature in database
GPG key ID: 0579CB2928A78A00
5 changed files with 103 additions and 31 deletions

View file

@ -3,7 +3,7 @@ import '@github/text-expander-element';
import $ from 'jquery';
import {attachTribute} from '../tribute.js';
import {hideElem, showElem, autosize, isElemVisible} from '../../utils/dom.js';
import {initEasyMDEImagePaste, initTextareaImagePaste} from './ImagePaste.js';
import {initEasyMDEPaste, initTextareaPaste} from './Paste.js';
import {handleGlobalEnterQuickSubmit} from './QuickSubmit.js';
import {renderPreviewPanelContent} from '../repo-editor.js';
import {easyMDEToolbarActions} from './EasyMDEToolbarActions.js';
@ -84,6 +84,17 @@ class ComboMarkdownEditor {
if (el.nodeName === 'BUTTON' && !el.getAttribute('type')) el.setAttribute('type', 'button');
}
this.textarea.addEventListener('keydown', (e) => {
if (e.shiftKey) {
e.target._shiftDown = true;
}
});
this.textarea.addEventListener('keyup', (e) => {
if (!e.shiftKey) {
e.target._shiftDown = false;
}
});
const monospaceButton = this.container.querySelector('.markdown-switch-monospace');
const monospaceEnabled = localStorage?.getItem('markdown-editor-monospace') === 'true';
const monospaceText = monospaceButton.getAttribute(monospaceEnabled ? 'data-disable-text' : 'data-enable-text');
@ -108,7 +119,7 @@ class ComboMarkdownEditor {
});
if (this.dropzone) {
initTextareaImagePaste(this.textarea, this.dropzone);
initTextareaPaste(this.textarea, this.dropzone);
}
}
@ -241,7 +252,7 @@ class ComboMarkdownEditor {
});
this.applyEditorHeights(this.container.querySelector('.CodeMirror-scroll'), this.options.editorHeights);
await attachTribute(this.easyMDE.codemirror.getInputField(), {mentions: true, emoji: true});
initEasyMDEImagePaste(this.easyMDE, this.dropzone);
initEasyMDEPaste(this.easyMDE, this.dropzone);
hideElem(this.textareaMarkdownToolbar);
}