mirror of
https://github.com/TryGhost/Ghost.git
synced 2024-12-26 12:21:36 +03:00
Koenig - Convert pasted <img> and <hr> elements to cards
refs https://github.com/TryGhost/Ghost/issues/9623 - use our custom paste event to intercept and modify pasted HTML before passing to mobiledoc - wrap the html in a `<div>` so that all elements get parsed by mobiledoc-kit - when pasting results in the last pasted section being a card, insert a blank paragraph - fixes immediate breaking of the undo stack
This commit is contained in:
parent
0fa0068f6a
commit
fb226ac956
@ -523,6 +523,8 @@ export default Component.extend({
|
||||
|
||||
cursorDidChange(editor) {
|
||||
let {head, tail, direction, isCollapsed, head: {section}} = editor.range;
|
||||
let isPasting = this._isPasting;
|
||||
this._isPasting = false;
|
||||
|
||||
// sometimes we perform a programatic edit that causes a cursor change
|
||||
// but we actually want to skip the default behaviour because we've
|
||||
@ -543,6 +545,29 @@ export default Component.extend({
|
||||
|
||||
// select the card if the cursor is on the before/after ‌ char
|
||||
if (section && isCollapsed && section.type === 'card-section') {
|
||||
if (isPasting) {
|
||||
// when pasting, if the last section added is a card we don't want to
|
||||
// select it (it breaks the undo stack) but rather create an empty
|
||||
// paragraph underneath
|
||||
// TODO: why does the undo stack break?
|
||||
let collection = section.parent.sections;
|
||||
let nextSection = section.next;
|
||||
editor.run((postEditor) => {
|
||||
let newSection = postEditor.builder.createMarkupSection('p');
|
||||
|
||||
if (nextSection) {
|
||||
postEditor.insertSectionBefore(collection, newSection, nextSection);
|
||||
} else {
|
||||
postEditor.insertSectionAtEnd(newSection);
|
||||
}
|
||||
|
||||
postEditor.setRange(newSection.tailPosition());
|
||||
this.set('selectedRange', newSection.tailPosition());
|
||||
this._skipCursorChange = true;
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
if (head.offset === 0 || head.offset === 1) {
|
||||
// select card after render to ensure that our componentCards
|
||||
// attr is populated
|
||||
@ -620,6 +645,11 @@ export default Component.extend({
|
||||
let editor = this.editor;
|
||||
let range = editor.range;
|
||||
|
||||
// when pasting, if the last section added is a card we don't want to
|
||||
// select it (it breaks the undo stack) but rather create an empty
|
||||
// paragraph underneath
|
||||
this._isPasting = true;
|
||||
|
||||
// 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);
|
||||
@ -689,7 +719,14 @@ export default Component.extend({
|
||||
return text;
|
||||
}
|
||||
if (type === 'text/html') {
|
||||
return normalizedHtml;
|
||||
// HACK: mobiledoc-kit won't parse top-level <img> or
|
||||
// other "unknown" elements so we wrap everything here
|
||||
// so that we don't get blank posts and elements are
|
||||
// passed through to our parser plugins correctly
|
||||
// TODO: fix parsing in mobiledoc, related issues:
|
||||
// https://github.com/bustle/mobiledoc-kit/issues/619
|
||||
// https://github.com/bustle/mobiledoc-kit/issues/494
|
||||
return `<div>${normalizedHtml}</div>`;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -21,7 +21,30 @@ export function removeLeadingNewline(node) {
|
||||
node.nodeValue = node.nodeValue.replace(/^\n/, '');
|
||||
}
|
||||
|
||||
export function imgToCard(node, builder, {addSection, nodeFinished}) {
|
||||
if (node.nodeType !== 1 || node.tagName !== 'IMG') {
|
||||
return;
|
||||
}
|
||||
|
||||
let payload = {src: node.src};
|
||||
let cardSection = builder.createCardSection('image', payload);
|
||||
addSection(cardSection);
|
||||
nodeFinished();
|
||||
}
|
||||
|
||||
export function hrToCard(node, builder, {addSection, nodeFinished}) {
|
||||
if (node.nodeType !== 1 || node.tagName !== 'HR') {
|
||||
return;
|
||||
}
|
||||
|
||||
let cardSection = builder.createCardSection('hr');
|
||||
addSection(cardSection);
|
||||
nodeFinished();
|
||||
}
|
||||
|
||||
export default [
|
||||
brToSoftBreakAtom,
|
||||
removeLeadingNewline,
|
||||
imgToCard,
|
||||
hrToCard
|
||||
];
|
||||
|
Loading…
Reference in New Issue
Block a user