From 032a8def9e8db39f1927817a69a37af199c35274 Mon Sep 17 00:00:00 2001 From: Kevin Ansfield Date: Tue, 29 May 2018 15:23:50 +0100 Subject: [PATCH] =?UTF-8?q?=E2=9C=A8=20Koenig=20-=20Create=20image=20cards?= =?UTF-8?q?=20when=20pasting=20image=20files?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit refs https://github.com/TryGhost/Ghost/issues/9623 - detect pastes that contain image files and insert a card for each, setting `payload.files` to the `File` instance grabbed from the clipboard - update the `addComponent` hook to ensure the `payload.files` array is preserved, browsers do not allow `File` instances to be copied - update `{{koenig-card-image}}` to look for a `payload.files` value to auto-upload it via it's internal `{{gh-uploader}}` - NOTE: browser support for accessing image files on paste varies: - Safari: will paste all images - Chrome: will only paste the first image - Firefox: will not paste any images --- .../addon/components/koenig-card-image.js | 20 +++++++++- .../addon/components/koenig-editor.js | 37 ++++++++++++++++++- .../components/koenig-card-image.hbs | 1 + 3 files changed, 54 insertions(+), 4 deletions(-) diff --git a/ghost/admin/lib/koenig-editor/addon/components/koenig-card-image.js b/ghost/admin/lib/koenig-editor/addon/components/koenig-card-image.js index 726fe346d3..8833e259bb 100644 --- a/ghost/admin/lib/koenig-editor/addon/components/koenig-card-image.js +++ b/ghost/admin/lib/koenig-editor/addon/components/koenig-card-image.js @@ -5,17 +5,18 @@ import { IMAGE_EXTENSIONS, IMAGE_MIME_TYPES } from 'ghost-admin/components/gh-image-uploader'; -import {computed} from '@ember/object'; +import {computed, set} from '@ember/object'; import {htmlSafe} from '@ember/string'; +import {isEmpty} from '@ember/utils'; import {run} from '@ember/runloop'; import {inject as service} from '@ember/service'; -import {set} from '@ember/object'; export default Component.extend({ ui: service(), layout, // attrs + files: null, payload: null, isSelected: false, isEditing: false, @@ -92,6 +93,21 @@ export default Component.extend({ } }, + didReceiveAttrs() { + this._super(...arguments); + + // `payload.files` can be set if we have an externaly set image that + // should be uploaded. Typical example would be from a paste or drag/drop + if (!isEmpty(this.payload.files)) { + run.schedule('afterRender', this, function () { + this.set('files', this.payload.files); + + // we don't want to persist any file data in the document + delete this.payload.files; + }); + } + }, + willDestroyElement() { this._super(...arguments); this._detachHandlers(); 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 469bf88e17..2e28326985 100644 --- a/ghost/admin/lib/koenig-editor/addon/components/koenig-editor.js +++ b/ghost/admin/lib/koenig-editor/addon/components/koenig-editor.js @@ -243,7 +243,11 @@ export default Component.extend({ let componentName = CARD_COMPONENT_MAP[cardName]; // the payload must be copied to avoid sharing the reference - payload = copy(payload, true); + // `payload.files` is special because it's set by paste/drag-n-drop + // events and can't be copied for security reasons + let {files} = payload; + let payloadCopy = copy(payload, true); + payloadCopy.files = files; // all of the properties that will be passed through to the // component cards via the template @@ -251,7 +255,7 @@ export default Component.extend({ cardName, componentName, koenigOptions, - payload, + payload: payloadCopy, env, options, editor, @@ -646,6 +650,35 @@ export default Component.extend({ return; } + // if we have image files pasted, create an image card for each and set + // the payload.files property which will cause the image to be auto-uploaded + // NOTE: browser support varies as of May 2018: + // - Safari: will paste all images + // - Chrome: will only paste the first image + // - Firefox: will not paste any images + let images = Array.from(event.clipboardData.files).filter(file => file.type.indexOf('image') > -1); + if (images.length > 0) { + event.preventDefault(); + event.stopImmediatePropagation(); + + editor.run((postEditor) => { + let {builder} = postEditor; + + if (editor.activeSection.isBlank) { + postEditor.removeSection(editor.activeSection); + } + + images.forEach((image) => { + let payload = { + files: [image] + }; + let imageCard = builder.createCardSection('image', payload); + postEditor.insertSection(imageCard); + }); + }); + return; + } + let range = editor.range; let {html, text} = getContentFromPasteEvent(event); diff --git a/ghost/admin/lib/koenig-editor/addon/templates/components/koenig-card-image.hbs b/ghost/admin/lib/koenig-editor/addon/templates/components/koenig-card-image.hbs index f633c16931..2b9d212d8f 100644 --- a/ghost/admin/lib/koenig-editor/addon/templates/components/koenig-card-image.hbs +++ b/ghost/admin/lib/koenig-editor/addon/templates/components/koenig-card-image.hbs @@ -12,6 +12,7 @@ hasEditMode=false }} {{#gh-uploader + files=files accept=imageMimeTypes extensions=imageExtensions onStart=(action "setPreviewSrc")