From f5fb6748048b3e7c106dfd3c1cd5823d47631246 Mon Sep 17 00:00:00 2001 From: Kevin Ansfield Date: Fri, 13 Apr 2018 17:53:40 +0100 Subject: [PATCH] Koenig - Apply link to selected text when pasting a URL refs https://github.com/TryGhost/Ghost/issues/9505 - add a `paste` event handler to the editor element so that we can override the default mobiledoc-kit paste handling when required - detect a paste when we have a plain text selection and if it's a valid url convert the selection to a link using the pasted url as the `href` --- .../addon/components/koenig-editor.js | 34 +++++++++++++++++++ 1 file changed, 34 insertions(+) diff --git a/ghost/admin/lib/koenig-editor/addon/components/koenig-editor.js b/ghost/admin/lib/koenig-editor/addon/components/koenig-editor.js index fe07a5f52b..950055bcae 100644 --- a/ghost/admin/lib/koenig-editor/addon/components/koenig-editor.js +++ b/ghost/admin/lib/koenig-editor/addon/components/koenig-editor.js @@ -12,12 +12,14 @@ import defaultCards from '../options/cards'; import layout from '../templates/components/koenig-editor'; import registerKeyCommands from '../options/key-commands'; import registerTextExpansions from '../options/text-expansions'; +import validator from 'npm:validator'; import {A} from '@ember/array'; import {MOBILEDOC_VERSION} from 'mobiledoc-kit/renderers/mobiledoc'; import {assign} from '@ember/polyfills'; import {camelize, capitalize} from '@ember/string'; import {computed} from '@ember/object'; import {copy} from '@ember/object/internals'; +import {getContentFromPasteEvent} from 'mobiledoc-kit/utils/parse-utils'; import {run} from '@ember/runloop'; export const ADD_CARD_HOOK = 'addComponent'; @@ -327,6 +329,14 @@ export default Component.extend({ this.didCreateEditor(editor); }, + didInsertElement() { + this._super(...arguments); + let editorElement = this.element.querySelector('.koenig-editor__editor'); + + this._pasteHandler = run.bind(this, this.handlePaste); + editorElement.addEventListener('paste', this._pasteHandler); + }, + // our ember component has rendered, now we need to render the mobiledoc // editor itself if necessary didRender() { @@ -342,6 +352,9 @@ export default Component.extend({ willDestroyElement() { let editor = this.get('editor'); + let editorElement = this.element.querySelector('.koenig-editor__editor'); + + editorElement.removeEventListener('paste', this._pasteHandler); editor.destroy(); this._super(...arguments); }, @@ -748,6 +761,27 @@ export default Component.extend({ return false; }, + // if a URL is pasted and we have a selection, make that selection a link + handlePaste(event) { + let editor = this.get('editor'); + let range = editor.range; + + // only attempt link if we have a text selection in a single section + if (range && !range.isCollapsed && range.headSection === range.tailSection && range.headSection.isMarkerable) { + let {text} = getContentFromPasteEvent(event); + if (text && validator.isURL(text)) { + let linkMarkup = editor.builder.createMarkup('a', {href: text}); + editor.run((postEditor) => { + postEditor.addMarkupToRange(range, linkMarkup); + }); + editor.selectRange(range.tail); + // prevent mobiledoc's default paste event handler firing + event.preventDefault(); + event.stopImmediatePropagation(); + } + } + }, + selectCard(card, isEditing = false) { // no-op if card is already selected if (card === this._selectedCard && isEditing === card.isEditing) {