mirror of
https://github.com/TryGhost/Ghost.git
synced 2025-02-24 23:48:13 -05:00
✨ Koenig - Auto-convert URLs pasted on blank lines to embed cards
refs https://github.com/TryGhost/Ghost/issues/9724 - if a URL is pasted in a blank paragraph, insert an embed card configured to switch immediately to a link if the embed fails - if <kbd>Shift</kbd> is pressed when pasting insert a linked URL with no auto-embed - added `payload.linkOnError` handling to the embed card - if that option is set, immediately convert the embed card section to a linked URL on embed failure - skip adding an undo step when auto-converting to a URL so that no undo loop is created. Without this an undo would convert from link to embed card which would automatically look up the url then convert back to a link meaning it's impossible to undo back past the URL paste - ensure that the cursor position doesn't jump if the user has continued writing whilst the oembed lookup is in progress
This commit is contained in:
parent
b46d60b820
commit
54cc17707f
2 changed files with 52 additions and 6 deletions
|
@ -104,7 +104,9 @@ export default Component.extend({
|
|||
this.set('hasError', false);
|
||||
},
|
||||
|
||||
insertAsLink() {
|
||||
insertAsLink(options = {linkOnError: false}) {
|
||||
let {range} = this.editor;
|
||||
|
||||
this.editor.run((postEditor) => {
|
||||
let {builder} = postEditor;
|
||||
let cardSection = this.env.postModel;
|
||||
|
@ -113,6 +115,20 @@ export default Component.extend({
|
|||
|
||||
postEditor.replaceSection(cardSection, p);
|
||||
postEditor.insertTextWithMarkup(p.toRange().head, this.payload.url, [link]);
|
||||
|
||||
// if a user is typing further on in the doc (possible if embed
|
||||
// was created automatically via paste of URL) then return the
|
||||
// cursor so the card->link change doesn't cause a cursor jump
|
||||
if (range.headSection !== cardSection) {
|
||||
postEditor.setRange(range);
|
||||
}
|
||||
|
||||
// avoid adding an extra undo step when automatically creating
|
||||
// link after an error so that an Undo after pasting a URL
|
||||
// doesn't get stuck in a loop going through link->embed->link
|
||||
if (options.linkOnError) {
|
||||
postEditor.cancelSnapshot();
|
||||
}
|
||||
});
|
||||
}
|
||||
},
|
||||
|
@ -135,12 +151,17 @@ export default Component.extend({
|
|||
throw 'No HTML returned';
|
||||
}
|
||||
|
||||
set(this.payload.linkOnError, undefined);
|
||||
set(this.payload, 'html', response.html);
|
||||
set(this.payload, 'type', response.type);
|
||||
this.saveCard(this.payload, false);
|
||||
|
||||
run.schedule('afterRender', this, this._populateIframe);
|
||||
} catch (err) {
|
||||
if (this.payload.linkOnError) {
|
||||
this.send('insertAsLink', {linkOnError: true});
|
||||
return;
|
||||
}
|
||||
this.set('hasError', true);
|
||||
}
|
||||
}),
|
||||
|
|
|
@ -176,7 +176,6 @@ function insertImageCards(files, postEditor) {
|
|||
|
||||
export default Component.extend({
|
||||
layout,
|
||||
|
||||
tagName: 'article',
|
||||
classNames: ['koenig-editor', 'w-100', 'flex-grow', 'relative', 'center', 'mb0', 'mt0'],
|
||||
|
||||
|
@ -784,14 +783,40 @@ export default Component.extend({
|
|||
let range = editor.range;
|
||||
let {html, text} = getContentFromPasteEvent(event);
|
||||
|
||||
// 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) {
|
||||
if (text && validator.isURL(text)) {
|
||||
// if we have a text selection, make that selection a link
|
||||
if (range && !range.isCollapsed && range.headSection === range.tailSection && range.headSection.isMarkerable) {
|
||||
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();
|
||||
return;
|
||||
}
|
||||
|
||||
// if there's no selection and cursor is on an empty paragraph,
|
||||
// insert the url as an embed card, unless SHIFT is pressed. Setting
|
||||
// the `linkOnError` option results in an immediate switch to a
|
||||
// plain link if the embed fails for any reason (eg, unknown provider)
|
||||
if (range && range.isCollapsed && range.headSection.isBlank && !range.headSection.isListItem) {
|
||||
if (!this._modifierKeys.shift) {
|
||||
editor.run((postEditor) => {
|
||||
let payload = {url: text, linkOnError: true};
|
||||
let card = postEditor.builder.createCardSection('embed', payload);
|
||||
postEditor.replaceSection(range.headSection, card);
|
||||
});
|
||||
} else {
|
||||
// ensure the pasted URL is still auto-linked when Shift is pressed
|
||||
editor.run((postEditor) => {
|
||||
let linkMarkup = editor.builder.createMarkup('a', {href: text});
|
||||
postEditor.insertTextWithMarkup(range.head, text, [linkMarkup]);
|
||||
});
|
||||
}
|
||||
|
||||
// prevent mobiledoc's default paste event handler firing
|
||||
event.preventDefault();
|
||||
event.stopImmediatePropagation();
|
||||
|
@ -802,7 +827,7 @@ export default Component.extend({
|
|||
// 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`
|
||||
// NOTE: will not work in Edge which only ever exposes `html`
|
||||
if (text && !html && !this._modifierKeys.shift) {
|
||||
// prevent mobiledoc's default paste event handler firing
|
||||
event.preventDefault();
|
||||
|
|
Loading…
Add table
Reference in a new issue