diff --git a/app/assets/javascripts/discourse/app/mixins/textarea-text-manipulation.js b/app/assets/javascripts/discourse/app/mixins/textarea-text-manipulation.js index 81610c35ba4..aab066c61b9 100644 --- a/app/assets/javascripts/discourse/app/mixins/textarea-text-manipulation.js +++ b/app/assets/javascripts/discourse/app/mixins/textarea-text-manipulation.js @@ -295,6 +295,8 @@ export default Mixin.create({ match.index === 0 && match.lastIndex === match.raw.length ) { + // When specified, linkify supports fuzzy links and emails. Prefer providing the protocol. + // eg: pasting "example@discourse.org" may apply a link format of "mailto:example@discourse.org" this._addText(selected, `[${selectedValue}](${match.url})`); handled = true; } diff --git a/app/assets/javascripts/discourse/tests/integration/components/d-editor-test.js b/app/assets/javascripts/discourse/tests/integration/components/d-editor-test.js index 3b090b1bb09..aa0808ed860 100644 --- a/app/assets/javascripts/discourse/tests/integration/components/d-editor-test.js +++ b/app/assets/javascripts/discourse/tests/integration/components/d-editor-test.js @@ -805,6 +805,34 @@ third line` } ); + testCase( + `pasting text that contains urls and other content will use default paste behavior`, + async function (assert, textarea) { + this.set("value", "a link example:"); + setTextareaSelection(textarea, 0, 1); + const element = query(".d-editor"); + const event = await paste( + element, + "Try out Discourse at: https://www.discourse.org/" + ); + // Synthetic paste events do not manipulate document content. + assert.strictEqual(this.value, "a link example:"); + assert.strictEqual(event.defaultPrevented, false); + } + ); + + testCase( + `pasting an email into a selection applies a link format`, + async function (assert, textarea) { + this.set("value", "team email"); + setTextareaSelection(textarea, 5, 10); + const element = query(".d-editor"); + const event = await paste(element, "mailto:team@discourse.org"); + assert.strictEqual(this.value, "team [email](mailto:team@discourse.org)"); + assert.strictEqual(event.defaultPrevented, true); + } + ); + (() => { // Tests to check cursor/selection after replace-text event. const BEFORE = "red green blue";