Skip to content

Commit

Permalink
Merge remote-tracking branch 'origin/master' into TINY-4528
Browse files Browse the repository at this point in the history
  • Loading branch information
lnewson committed Dec 19, 2019
2 parents c095fdb + 4e40bed commit 92b572e
Show file tree
Hide file tree
Showing 8 changed files with 123 additions and 33 deletions.
2 changes: 2 additions & 0 deletions modules/tinymce/changelog.txt
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
Version 5.1.5 (TBD)
Fixed the `charmap` dialog initially focusing the first tab of the dialog instead of the search input field #TINY-4342
Fixed an exception being raised when inserting content if the caret was directly before or after a `contenteditable="false"` element #TINY-4528
Fixed bug with pasting image URLs when paste as text is enabled #TINY-4523
Version 5.1.4 (2019-12-11)
Fixed dialog contents disappearing when clicking a checkbox for right-to-left languages #TINY-4518
Fixed the `legacyoutput` plugin registering legacy formats after editior initialization, causing legacy content to be stripped on the initial load #TINY-4447
Expand Down
5 changes: 3 additions & 2 deletions modules/tinymce/src/plugins/charmap/main/ts/ui/Dialog.ts
Original file line number Diff line number Diff line change
Expand Up @@ -99,9 +99,10 @@ const open = function (editor: Editor, charMap: CharMap[]) {
}
}
};
editor.windowManager.open(bridgeSpec);
const dialogApi = editor.windowManager.open(bridgeSpec);
dialogApi.focus(patternName);
};

export default {
open
};
};
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import { Chain, FocusTools, Guard, Keyboard, Keys, Log, Pipeline, UiFinder, NamedChain } from '@ephox/agar';
import { Chain, FocusTools, Guard, Log, NamedChain, Pipeline, UiFinder } from '@ephox/agar';
import { UnitTest } from '@ephox/bedrock';
import { document } from '@ephox/dom-globals';
import { Result } from '@ephox/katamari';
import { TinyApis, TinyLoader, TinyUi } from '@ephox/mcagar';
import { Body, Element, Css, Traverse } from '@ephox/sugar';
import { Body, Css, Element, Traverse } from '@ephox/sugar';
import CharmapPlugin from 'tinymce/plugins/charmap/Plugin';
import SilverTheme from 'tinymce/themes/silver/Theme';

Expand Down Expand Up @@ -39,9 +39,7 @@ UnitTest.asynctest('browser.tinymce.plugins.charmap.DialogHeightTest', (success,
Chain.asStep({}, [
tinyUi.cWaitForPopup('wait for popup', 'div[role="dialog"]'),
]),
FocusTools.sTryOnSelector('Focus should start on', doc, '[role="tab"]'),
Keyboard.sKeydown(doc, Keys.tab(), { }),
FocusTools.sTryOnSelector('Focus should have moved to input', doc, 'input'),
FocusTools.sTryOnSelector('Focus should start on', doc, 'input'),
Chain.asStep(Body.body() , [
NamedChain.asChain([
NamedChain.direct(NamedChain.inputName(), Chain.identity, 'body'),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,9 +35,7 @@ UnitTest.asynctest('browser.tinymce.plugins.charmap.SearchTest', (success, failu
Chain.asStep({}, [
tinyUi.cWaitForPopup('wait for popup', 'div[role="dialog"]'),
]),
FocusTools.sTryOnSelector('Focus should start on', doc, '[role="tab"]'), // TODO: Remove duped startup of these tests
Keyboard.sKeydown(doc, Keys.tab(), { }),
FocusTools.sTryOnSelector('Focus should have moved to input', doc, 'input'),
FocusTools.sTryOnSelector('Focus should start on', doc, 'input'), // TODO: Remove duped startup of these tests
FocusTools.sSetActiveValue(doc, 'euro'),
Chain.asStep(doc, [
FocusTools.cGetFocused,
Expand Down
26 changes: 15 additions & 11 deletions modules/tinymce/src/plugins/paste/main/ts/core/Clipboard.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,14 @@ import Utils from './Utils';

declare let window: any;

const doPaste = (editor: Editor, content: string, internal: boolean, pasteAsText: boolean) => {
const args = ProcessFilters.process(editor, content, internal);

if (args.cancelled === false) {
SmartPaste.insertContent(editor, args.content, pasteAsText);
}
};

/**
* Pastes the specified HTML. This means that the HTML is filtered and then
* inserted at the current selection in the editor. It will also fire paste events
Expand All @@ -34,11 +42,7 @@ declare let window: any;
*/
const pasteHtml = (editor: Editor, html: string, internalFlag: boolean) => {
const internal = internalFlag ? internalFlag : InternalHtml.isMarked(html);
const args = ProcessFilters.process(editor, InternalHtml.unmark(html), internal);

if (args.cancelled === false) {
SmartPaste.insertContent(editor, args.content);
}
doPaste(editor, InternalHtml.unmark(html), internal, false);
};

/**
Expand All @@ -51,8 +55,7 @@ const pasteText = (editor: Editor, text: string) => {
const encodedText = editor.dom.encode(text).replace(/\r\n/g, '\n');
const normalizedText = Whitespace.normalizeWhitespace(encodedText);
const html = Newlines.convert(normalizedText, editor.settings.forced_root_block, editor.settings.forced_root_block_attrs);

pasteHtml(editor, html, false);
doPaste(editor, html, false, true);
};

export interface ClipboardContents {
Expand Down Expand Up @@ -297,8 +300,8 @@ const registerEventHandlers = (editor: Editor, pasteBin: PasteBin, pasteFormat:
}
});

function insertClipboardContent(clipboardContent, isKeyBoardPaste, plainTextMode, internal) {
let content, isPlainTextHtml;
function insertClipboardContent(clipboardContent: ClipboardContents, isKeyBoardPaste: boolean, plainTextMode: boolean, internal: boolean) {
let content, isPlainTextHtml, isImage;

// Grab HTML from Clipboard API or paste bin as a fallback
if (hasContentType(clipboardContent, 'text/html')) {
Expand All @@ -319,15 +322,16 @@ const registerEventHandlers = (editor: Editor, pasteBin: PasteBin, pasteFormat:
pasteBin.remove();

isPlainTextHtml = (internal === false && Newlines.isPlainText(content));
isImage = SmartPaste.isImageUrl(content);

// If we got nothing from clipboard API and pastebin or the content is a plain text (with only
// some BRs, Ps or DIVs as newlines) then we fallback to plain/text
if (!content.length || isPlainTextHtml) {
if (!content.length || (isPlainTextHtml && !isImage)) {
plainTextMode = true;
}

// Grab plain text from Clipboard API or convert existing HTML to plain text
if (plainTextMode) {
if (plainTextMode || isImage) {
// Use plain text contents from Clipboard API unless the HTML contains paragraphs then
// we should convert the HTML to plain text since works better when pasting HTML/Word contents as plain text
if (hasContentType(clipboardContent, 'text/plain') && isPlainTextHtml) {
Expand Down
5 changes: 1 addition & 4 deletions modules/tinymce/src/plugins/paste/main/ts/core/CutCopy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,6 @@ import Delay from 'tinymce/core/api/util/Delay';
import InternalHtml from './InternalHtml';
import Utils from './Utils';

const noop = function () {
};

interface SelectionContentData {
html: string;
text: string;
Expand Down Expand Up @@ -122,7 +119,7 @@ const cut = (editor: Editor) => (evt: ClipboardEvent) => {

const copy = (editor: Editor) => (evt: ClipboardEvent) => {
if (hasSelectedContent(editor)) {
setClipboardData(evt, getData(editor), fallback(editor), noop);
setClipboardData(evt, getData(editor), fallback(editor), () => {});
}
};

Expand Down
4 changes: 2 additions & 2 deletions modules/tinymce/src/plugins/paste/main/ts/core/SmartPaste.ts
Original file line number Diff line number Diff line change
Expand Up @@ -73,8 +73,8 @@ const smartInsertContent = function (editor: Editor, html: string) {
});
};

const insertContent = function (editor: Editor, html: string) {
if (Settings.isSmartPasteEnabled(editor) === false) {
const insertContent = function (editor: Editor, html: string, pasteAsText: boolean) {
if (pasteAsText || Settings.isSmartPasteEnabled(editor) === false) {
pasteHtml(editor, html);
} else {
smartInsertContent(editor, html);
Expand Down
102 changes: 96 additions & 6 deletions modules/tinymce/src/plugins/paste/test/ts/browser/SmartPasteTest.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,22 @@
import { Pipeline, Log } from '@ephox/agar';
import { Log, Pipeline } from '@ephox/agar';
import { UnitTest } from '@ephox/bedrock';
import { LegacyUnit, TinyLoader } from '@ephox/mcagar';

import SmartPaste from 'tinymce/plugins/paste/core/SmartPaste';
import Plugin from 'tinymce/plugins/paste/Plugin';
import Theme from 'tinymce/themes/silver/Theme';

UnitTest.asynctest('tinymce.plugins.paste.browser.ImagePasteTest', (success, failure) => {
// Test cases for TINY-4523 - image url/anchor link paste smartpaste/pasteAsText interactions
// Pasting an image anchor link (<a href=”….jpg”>):
// | | smart_paste: true | smart_paste: false |
// |Paste as text turned off | paste image link -> anchor link | paste image link -> anchor link |
// |Paste as text turned on | paste image link -> text | paste image link -> text |
//
// Pasting an image URL (“https…….jpg”):
// | | smart_paste: true | smart_paste: false |
// |Paste as text turned off | paste image URL -> image | paste image URL -> text |
// |Paste as text turned on | paste image URL -> text | paste image URL -> text |

UnitTest.asynctest('tinymce.plugins.paste.browser.SmartPasteTest', (success, failure) => {

const suite = LegacyUnit.createSuite();

Expand Down Expand Up @@ -39,31 +49,33 @@ UnitTest.asynctest('tinymce.plugins.paste.browser.ImagePasteTest', (success, fai
LegacyUnit.equal(SmartPaste.isImageUrl(''), false);
});

suite.test('TestCase-TBA: Paste: smart paste url on selection', function (editor) {
suite.test('TestCase-TBA: Paste: smart paste enabled, paste as content, paste url on selection', function (editor) {
editor.focus();
editor.undoManager.clear();
editor.setContent('<p>abc</p>');
LegacyUnit.setSelection(editor, 'p', 0, 'p', 3);
editor.undoManager.add();
editor.settings.smart_paste = true;

editor.execCommand('mceInsertClipboardContent', false, { content: 'http://www.site.com' });
LegacyUnit.equal(editor.getContent(), '<p><a href="http://www.site.com">abc</a></p>');
LegacyUnit.equal(editor.undoManager.data.length, 3);
});

suite.test('TestCase-TBA: Paste: smart paste image url', function (editor) {
suite.test('TestCase-TBA: Paste: smart paste enabled, paste as content, paste image url', function (editor) {
editor.focus();
editor.undoManager.clear();
editor.setContent('<p>abc</p>');
LegacyUnit.setSelection(editor, 'p', 1);
editor.undoManager.add();
editor.settings.smart_paste = true;

editor.execCommand('mceInsertClipboardContent', false, { content: 'http://www.site.com/my.jpg' });
LegacyUnit.equal(editor.getContent(), '<p>a<img src="http://www.site.com/my.jpg" />bc</p>');
LegacyUnit.equal(editor.undoManager.data.length, 3);
});

suite.test('TestCase-TBA: Paste: smart paste option disabled', function (editor) {
suite.test('TestCase-TBA: Paste: smart paste disabled, paste as content, paste image url', function (editor) {
editor.focus();
editor.undoManager.clear();
editor.setContent('<p>abc</p>');
Expand All @@ -76,6 +88,84 @@ UnitTest.asynctest('tinymce.plugins.paste.browser.ImagePasteTest', (success, fai
LegacyUnit.equal(editor.undoManager.data.length, 2);
});

suite.test('TINY-4523: Paste: smart paste enabled, paste as text, paste image url', function (editor) {
editor.focus();
editor.undoManager.clear();
editor.setContent('<p>abc</p>');
LegacyUnit.setSelection(editor, 'p', 1);
editor.undoManager.add();
editor.settings.smart_paste = true;

editor.execCommand('mceInsertClipboardContent', false, { text: 'http://www.site.com/my.jpg' });
LegacyUnit.equal(editor.getContent(), '<p>ahttp://www.site.com/my.jpgbc</p>');
LegacyUnit.equal(editor.undoManager.data.length, 2);
});

suite.test('TINY-4523: Paste: smart paste disabled, paste as text, paste image url', function (editor) {
editor.focus();
editor.undoManager.clear();
editor.setContent('<p>abc</p>');
LegacyUnit.setSelection(editor, 'p', 1);
editor.undoManager.add();
editor.settings.smart_paste = false;

editor.execCommand('mceInsertClipboardContent', false, { text: 'http://www.site.com/my.jpg' });
LegacyUnit.equal(editor.getContent(), '<p>ahttp://www.site.com/my.jpgbc</p>');
LegacyUnit.equal(editor.undoManager.data.length, 2);
});

suite.test('TINY-4523: Paste: smart paste enabled, paste as content, paste link html', function (editor) {
editor.focus();
editor.undoManager.clear();
editor.setContent('<p>abc</p>');
LegacyUnit.setSelection(editor, 'p', 1);
editor.undoManager.add();
editor.settings.smart_paste = true;

editor.execCommand('mceInsertClipboardContent', false, { content: '<img src="http://www.site.com/my.jpg" />' });
LegacyUnit.equal(editor.getContent(), '<p>a<img src="http://www.site.com/my.jpg" />bc</p>');
LegacyUnit.equal(editor.undoManager.data.length, 2);
});

suite.test('TINY-4523: Paste: smart paste disabled, paste as content, paste link html', function (editor) {
editor.focus();
editor.undoManager.clear();
editor.setContent('<p>abc</p>');
LegacyUnit.setSelection(editor, 'p', 1);
editor.undoManager.add();
editor.settings.smart_paste = false;

editor.execCommand('mceInsertClipboardContent', false, { content: '<img src="http://www.site.com/my.jpg" />' });
LegacyUnit.equal(editor.getContent(), '<p>a<img src="http://www.site.com/my.jpg" />bc</p>');
LegacyUnit.equal(editor.undoManager.data.length, 2);
});

suite.test('TINY-4523: Paste: smart paste enabled, paste as text, paste link html', function (editor) {
editor.focus();
editor.undoManager.clear();
editor.setContent('<p>abc</p>');
LegacyUnit.setSelection(editor, 'p', 1);
editor.undoManager.add();
editor.settings.smart_paste = true;

editor.execCommand('mceInsertClipboardContent', false, { text: '<img src="http://www.site.com/my.jpg" />' });
LegacyUnit.equal(editor.getContent(), '<p>a&lt;img src=\"http://www.site.com/my.jpg\" /&gt;bc</p>');
LegacyUnit.equal(editor.undoManager.data.length, 2);
});

suite.test('TINY-4523: Paste: smart paste disabled, paste as text, paste link html', function (editor) {
editor.focus();
editor.undoManager.clear();
editor.setContent('<p>abc</p>');
LegacyUnit.setSelection(editor, 'p', 1);
editor.undoManager.add();
editor.settings.smart_paste = false;

editor.execCommand('mceInsertClipboardContent', false, { text: '<img src="http://www.site.com/my.jpg" />' });
LegacyUnit.equal(editor.getContent(), '<p>a&lt;img src=\"http://www.site.com/my.jpg\" /&gt;bc</p>');
LegacyUnit.equal(editor.undoManager.data.length, 2);
});

TinyLoader.setupLight(function (editor, onSuccess, onFailure) {
Pipeline.async({}, Log.steps('TBA', 'Paste: Test smart paste', suite.toSteps(editor)), onSuccess, onFailure);
}, {
Expand Down

0 comments on commit 92b572e

Please sign in to comment.