0
Fork 0
mirror of https://github.com/TryGhost/Ghost.git synced 2025-02-24 23:48:13 -05:00

Koenig - Parse pasted plain text as markdown

refs https://github.com/TryGhost/Ghost/issues/9623
- plain text that's pasted will be run through our markdown parser then mobiledoc-kit will perform it's usual rich-text paste handling on the resulting HTML
- add a <kbd>Cmd/Ctrl+V+Shift</kbd> escape valve that will skip markdown parsing so mobiledoc-kit's default plain text parsing is invoked
- will not work with IE or Edge <= 16 due to missing browser support for distinguishing plain text vs html pastes
This commit is contained in:
Kevin Ansfield 2018-05-16 13:08:11 +01:00
parent 54cb053fa5
commit 772675d294

View file

@ -6,9 +6,11 @@
import Component from '@ember/component';
import Editor from 'mobiledoc-kit/editor/editor';
import EmberObject, {computed} from '@ember/object';
import Key from 'mobiledoc-kit/utils/key';
import MobiledocRange from 'mobiledoc-kit/utils/cursor/range';
import defaultAtoms from '../options/atoms';
import defaultCards from '../options/cards';
import formatMarkdown from 'ghost-admin/utils/format-markdown';
import layout from '../templates/components/koenig-editor';
import registerKeyCommands from '../options/key-commands';
import registerTextExpansions from '../options/text-expansions';
@ -109,6 +111,7 @@ export default Component.extend({
_lastIsEditingDisabled: false,
_isRenderingEditor: false,
_skipCursorChange: false,
_modifierKeys: null,
// closure actions
willCreateEditor() {},
@ -156,6 +159,12 @@ export default Component.extend({
this.set('activeMarkupTagNames', {});
this.set('activeSectionTagNames', {});
this._modifierKeys = {
shift: false,
alt: false,
ctrl: false
};
this._startedRunLoop = false;
},
@ -605,12 +614,11 @@ export default Component.extend({
/* custom event handlers ------------------------------------------------ */
// if a URL is pasted and we have a selection, make that selection a link
handlePaste(event) {
let editor = this.editor;
let range = editor.range;
// only attempt link if we have a text selection in a single section
// if a URL is pasted and we have a selection, make that selection a link
if (range && !range.isCollapsed && range.headSection === range.tailSection && range.headSection.isMarkerable) {
let {text} = getContentFromPasteEvent(event);
if (text && validator.isURL(text)) {
@ -622,8 +630,37 @@ export default Component.extend({
// prevent mobiledoc's default paste event handler firing
event.preventDefault();
event.stopImmediatePropagation();
return;
}
}
// if plain text is pasted we run it through our markdown parser so that
// we get better output than mobiledoc's default text parsing and we can
// provide an easier MD->Mobiledoc conversion route
// NOTE: will not work in IE/Edge which only ever expose `html`
let {html, text} = getContentFromPasteEvent(event);
if (text && !html && !this._modifierKeys.shift) {
// prevent mobiledoc's default paste event handler firing
event.preventDefault();
event.stopImmediatePropagation();
// we can't modify the paste event itself so we trigger a mock
// paste event with our own data
let pasteEvent = {
type: 'paste',
preventDefault() {},
target: editor.element,
clipboardData: {
getData(type) {
if (type === 'text/html') {
return formatMarkdown(text, false);
}
}
}
};
editor.triggerEvent(editor.element, 'paste', pasteEvent);
}
},
/* Ember event handlers ------------------------------------------------- */
@ -634,6 +671,19 @@ export default Component.extend({
event.preventDefault();
},
// we keep track of the modifier keys that are pressed so that in other event
// handlers we can adjust the behaviour. Necessary because the browser doesn't
// natively provide any info on non-key events about which keys are pressed
keyDown(event) {
let key = Key.fromEvent(event);
this._updateModifiersFromKey(key, {isDown: true});
},
keyUp(event) {
let key = Key.fromEvent(event);
this._updateModifiersFromKey(key, {isDown: false});
},
/* public methods ------------------------------------------------------- */
selectCard(card, isEditing = false) {
@ -767,6 +817,16 @@ export default Component.extend({
this.editor.element.style.caretColor = 'auto';
},
_updateModifiersFromKey(key, {isDown}) {
if (key.isShiftKey()) {
this._modifierKeys.shift = isDown;
} else if (key.isAltKey()) {
this._modifierKeys.alt = isDown;
} else if (key.isCtrlKey()) {
this._modifierKeys.ctrl = isDown;
}
},
// store a reference to the editor for the acceptance test helpers
_setExpandoProperty(editor) {
let config = getOwner(this).resolveRegistration('config:environment');