diff -r 490d5cc509ed -r cf61fcea0001 wp/wp-includes/js/tinymce/plugins/paste/plugin.js --- a/wp/wp-includes/js/tinymce/plugins/paste/plugin.js Tue Jun 09 11:14:17 2015 +0000 +++ b/wp/wp-includes/js/tinymce/plugins/paste/plugin.js Mon Oct 14 17:39:30 2019 +0200 @@ -1,1606 +1,1497 @@ -/** - * Compiled inline version. (Library mode) - */ - -/*jshint smarttabs:true, undef:true, latedef:true, curly:true, bitwise:true, camelcase:true */ -/*globals $code */ - -(function(exports, undefined) { - "use strict"; - - var modules = {}; - - function require(ids, callback) { - var module, defs = []; - - for (var i = 0; i < ids.length; ++i) { - module = modules[ids[i]] || resolve(ids[i]); - if (!module) { - throw 'module definition dependecy not found: ' + ids[i]; - } +(function () { +var paste = (function () { + 'use strict'; - defs.push(module); - } - - callback.apply(null, defs); - } - - function define(id, dependencies, definition) { - if (typeof id !== 'string') { - throw 'invalid module definition, module id must be defined and be a string'; - } + var Cell = function (initial) { + var value = initial; + var get = function () { + return value; + }; + var set = function (v) { + value = v; + }; + var clone = function () { + return Cell(get()); + }; + return { + get: get, + set: set, + clone: clone + }; + }; - if (dependencies === undefined) { - throw 'invalid module definition, dependencies must be specified'; - } - - if (definition === undefined) { - throw 'invalid module definition, definition function must be specified'; - } - - require(dependencies, function() { - modules[id] = definition.apply(null, arguments); - }); - } + var global = tinymce.util.Tools.resolve('tinymce.PluginManager'); - function defined(id) { - return !!modules[id]; - } - - function resolve(id) { - var target = exports; - var fragments = id.split(/[.\/]/); + var hasProPlugin = function (editor) { + if (/(^|[ ,])powerpaste([, ]|$)/.test(editor.settings.plugins) && global.get('powerpaste')) { + if (typeof window.console !== 'undefined' && window.console.log) { + window.console.log('PowerPaste is incompatible with Paste plugin! Remove \'paste\' from the \'plugins\' option.'); + } + return true; + } else { + return false; + } + }; + var $_15bf6siejjgwect1 = { hasProPlugin: hasProPlugin }; - for (var fi = 0; fi < fragments.length; ++fi) { - if (!target[fragments[fi]]) { - return; - } - - target = target[fragments[fi]]; - } - - return target; - } + var get = function (clipboard, quirks) { + return { + clipboard: clipboard, + quirks: quirks + }; + }; + var $_6gtliyigjjgwecte = { get: get }; - function expose(ids) { - for (var i = 0; i < ids.length; i++) { - var target = exports; - var id = ids[i]; - var fragments = id.split(/[.\/]/); - - for (var fi = 0; fi < fragments.length - 1; ++fi) { - if (target[fragments[fi]] === undefined) { - target[fragments[fi]] = {}; - } - - target = target[fragments[fi]]; - } - - target[fragments[fragments.length - 1]] = modules[id]; - } - } - -// Included from: js/tinymce/plugins/paste/classes/Utils.js - -/** - * Utils.js - * - * Copyright, Moxiecode Systems AB - * Released under LGPL License. - * - * License: http://www.tinymce.com/license - * Contributing: http://www.tinymce.com/contributing - */ + var firePastePreProcess = function (editor, html, internal, isWordHtml) { + return editor.fire('PastePreProcess', { + content: html, + internal: internal, + wordContent: isWordHtml + }); + }; + var firePastePostProcess = function (editor, node, internal, isWordHtml) { + return editor.fire('PastePostProcess', { + node: node, + internal: internal, + wordContent: isWordHtml + }); + }; + var firePastePlainTextToggle = function (editor, state) { + return editor.fire('PastePlainTextToggle', { state: state }); + }; + var firePaste = function (editor, ieFake) { + return editor.fire('paste', { ieFake: ieFake }); + }; + var $_8tki3zijjjgwectj = { + firePastePreProcess: firePastePreProcess, + firePastePostProcess: firePastePostProcess, + firePastePlainTextToggle: firePastePlainTextToggle, + firePaste: firePaste + }; -/** - * This class contails various utility functions for the paste plugin. - * - * @class tinymce.pasteplugin.Utils - */ -define("tinymce/pasteplugin/Utils", [ - "tinymce/util/Tools", - "tinymce/html/DomParser", - "tinymce/html/Schema" -], function(Tools, DomParser, Schema) { - function filter(content, items) { - Tools.each(items, function(v) { - if (v.constructor == RegExp) { - content = content.replace(v, ''); - } else { - content = content.replace(v[0], v[1]); - } - }); - - return content; - } - - /** - * Gets the innerText of the specified element. It will handle edge cases - * and works better than textContent on Gecko. - * - * @param {String} html HTML string to get text from. - * @return {String} String of text with line feeds. - */ - function innerText(html) { - var schema = new Schema(), domParser = new DomParser({}, schema), text = ''; - var shortEndedElements = schema.getShortEndedElements(); - var ignoreElements = Tools.makeMap('script noscript style textarea video audio iframe object', ' '); - var blockElements = schema.getBlockElements(); - - function walk(node) { - var name = node.name, currentNode = node; - - if (name === 'br') { - text += '\n'; - return; - } - - // img/input/hr - if (shortEndedElements[name]) { - text += ' '; - } + var shouldPlainTextInform = function (editor) { + return editor.getParam('paste_plaintext_inform', true); + }; + var shouldBlockDrop = function (editor) { + return editor.getParam('paste_block_drop', false); + }; + var shouldPasteDataImages = function (editor) { + return editor.getParam('paste_data_images', false); + }; + var shouldFilterDrop = function (editor) { + return editor.getParam('paste_filter_drop', true); + }; + var getPreProcess = function (editor) { + return editor.getParam('paste_preprocess'); + }; + var getPostProcess = function (editor) { + return editor.getParam('paste_postprocess'); + }; + var getWebkitStyles = function (editor) { + return editor.getParam('paste_webkit_styles'); + }; + var shouldRemoveWebKitStyles = function (editor) { + return editor.getParam('paste_remove_styles_if_webkit', true); + }; + var shouldMergeFormats = function (editor) { + return editor.getParam('paste_merge_formats', true); + }; + var isSmartPasteEnabled = function (editor) { + return editor.getParam('smart_paste', true); + }; + var isPasteAsTextEnabled = function (editor) { + return editor.getParam('paste_as_text', false); + }; + var getRetainStyleProps = function (editor) { + return editor.getParam('paste_retain_style_properties'); + }; + var getWordValidElements = function (editor) { + var defaultValidElements = '-strong/b,-em/i,-u,-span,-p,-ol,-ul,-li,-h1,-h2,-h3,-h4,-h5,-h6,' + '-p/div,-a[href|name],sub,sup,strike,br,del,table[width],tr,' + 'td[colspan|rowspan|width],th[colspan|rowspan|width],thead,tfoot,tbody'; + return editor.getParam('paste_word_valid_elements', defaultValidElements); + }; + var shouldConvertWordFakeLists = function (editor) { + return editor.getParam('paste_convert_word_fake_lists', true); + }; + var shouldUseDefaultFilters = function (editor) { + return editor.getParam('paste_enable_default_filters', true); + }; + var $_xr8b0ikjjgwectl = { + shouldPlainTextInform: shouldPlainTextInform, + shouldBlockDrop: shouldBlockDrop, + shouldPasteDataImages: shouldPasteDataImages, + shouldFilterDrop: shouldFilterDrop, + getPreProcess: getPreProcess, + getPostProcess: getPostProcess, + getWebkitStyles: getWebkitStyles, + shouldRemoveWebKitStyles: shouldRemoveWebKitStyles, + shouldMergeFormats: shouldMergeFormats, + isSmartPasteEnabled: isSmartPasteEnabled, + isPasteAsTextEnabled: isPasteAsTextEnabled, + getRetainStyleProps: getRetainStyleProps, + getWordValidElements: getWordValidElements, + shouldConvertWordFakeLists: shouldConvertWordFakeLists, + shouldUseDefaultFilters: shouldUseDefaultFilters + }; - // Ingore script, video contents - if (ignoreElements[name]) { - text += ' '; - return; - } - - if (node.type == 3) { - text += node.value; - } - - // Walk all children - if (!node.shortEnded) { - if ((node = node.firstChild)) { - do { - walk(node); - } while ((node = node.next)); - } - } - - // Add \n or \n\n for blocks or P - if (blockElements[name] && currentNode.next) { - text += '\n'; - - if (name == 'p') { - text += '\n'; - } - } - } - - html = filter(html, [ - //g // Conditional comments - ]); - - walk(domParser.parse(html)); - - return text; - } - - /** - * Trims the specified HTML by removing all WebKit fragments, all elements wrapping the body trailing BR elements etc. - * - * @param {String} html Html string to trim contents on. - * @return {String} Html contents that got trimmed. - */ - function trimHtml(html) { - function trimSpaces(all, s1, s2) { - // WebKit   meant to preserve multiple spaces but instead inserted around all inline tags, - // including the spans with inline styles created on paste - if (!s1 && !s2) { - return ' '; - } - - return '\u00a0'; - } + var shouldInformUserAboutPlainText = function (editor, userIsInformedState) { + return userIsInformedState.get() === false && $_xr8b0ikjjgwectl.shouldPlainTextInform(editor); + }; + var displayNotification = function (editor, message) { + editor.notificationManager.open({ + text: editor.translate(message), + type: 'info' + }); + }; + var togglePlainTextPaste = function (editor, clipboard, userIsInformedState) { + if (clipboard.pasteFormat.get() === 'text') { + clipboard.pasteFormat.set('html'); + $_8tki3zijjjgwectj.firePastePlainTextToggle(editor, false); + } else { + clipboard.pasteFormat.set('text'); + $_8tki3zijjjgwectj.firePastePlainTextToggle(editor, true); + if (shouldInformUserAboutPlainText(editor, userIsInformedState)) { + displayNotification(editor, 'Paste is now in plain text mode. Contents will now be pasted as plain text until you toggle this option off.'); + userIsInformedState.set(true); + } + } + editor.focus(); + }; + var $_2j7vw7iijjgwecti = { togglePlainTextPaste: togglePlainTextPaste }; - html = filter(html, [ - /^[\s\S]*]*>\s*|\s*<\/body[^>]*>[\s\S]*$/g, // Remove anything but the contents within the BODY element - /|/g, // Inner fragments (tables from excel on mac) - [/( ?)\u00a0<\/span>( ?)/g, trimSpaces], - /
$/i // Trailing BR elements - ]); + var register = function (editor, clipboard, userIsInformedState) { + editor.addCommand('mceTogglePlainTextPaste', function () { + $_2j7vw7iijjgwecti.togglePlainTextPaste(editor, clipboard, userIsInformedState); + }); + editor.addCommand('mceInsertClipboardContent', function (ui, value) { + if (value.content) { + clipboard.pasteHtml(value.content, value.internal); + } + if (value.text) { + clipboard.pasteText(value.text); + } + }); + }; + var $_fldd1mihjjgwecth = { register: register }; - return html; - } + var global$1 = tinymce.util.Tools.resolve('tinymce.Env'); + + var global$2 = tinymce.util.Tools.resolve('tinymce.util.Delay'); + + var global$3 = tinymce.util.Tools.resolve('tinymce.util.Tools'); - return { - filter: filter, - innerText: innerText, - trimHtml: trimHtml - }; -}); - -// Included from: js/tinymce/plugins/paste/classes/Clipboard.js + var global$4 = tinymce.util.Tools.resolve('tinymce.util.VK'); -/** - * Clipboard.js - * - * Copyright, Moxiecode Systems AB - * Released under LGPL License. - * - * License: http://www.tinymce.com/license - * Contributing: http://www.tinymce.com/contributing - */ + var internalMimeType = 'x-tinymce/html'; + var internalMark = ''; + var mark = function (html) { + return internalMark + html; + }; + var unmark = function (html) { + return html.replace(internalMark, ''); + }; + var isMarked = function (html) { + return html.indexOf(internalMark) !== -1; + }; + var $_4x13hjirjjgwecu1 = { + mark: mark, + unmark: unmark, + isMarked: isMarked, + internalHtmlMime: function () { + return internalMimeType; + } + }; + + var global$5 = tinymce.util.Tools.resolve('tinymce.html.Entities'); -/** - * This class contains logic for getting HTML contents out of the clipboard. - * - * We need to make a lot of ugly hacks to get the contents out of the clipboard since - * the W3C Clipboard API is broken in all browsers that have it: Gecko/WebKit/Blink. - * We might rewrite this the way those API:s stabilize. Browsers doesn't handle pasting - * from applications like Word the same way as it does when pasting into a contentEditable area - * so we need to do lots of extra work to try to get to this clipboard data. - * - * Current implementation steps: - * 1. On keydown with paste keys Ctrl+V or Shift+Insert create - * a paste bin element and move focus to that element. - * 2. Wait for the browser to fire a "paste" event and get the contents out of the paste bin. - * 3. Check if the paste was successful if true, process the HTML. - * (4). If the paste was unsuccessful use IE execCommand, Clipboard API, document.dataTransfer old WebKit API etc. - * - * @class tinymce.pasteplugin.Clipboard - * @private - */ -define("tinymce/pasteplugin/Clipboard", [ - "tinymce/Env", - "tinymce/dom/RangeUtils", - "tinymce/util/VK", - "tinymce/pasteplugin/Utils" -], function(Env, RangeUtils, VK, Utils) { - return function(editor) { - var self = this, pasteBinElm, lastRng, keyboardPasteTimeStamp = 0, draggingInternally = false; - var pasteBinDefaultContent = '%MCEPASTEBIN%', keyboardPastePlainTextState; - var mceInternalUrlPrefix = 'data:text/mce-internal,'; + var isPlainText = function (text) { + return !/<(?:\/?(?!(?:div|p|br|span)>)\w+|(?:(?!(?:span style="white-space:\s?pre;?">)|br\s?\/>))\w+\s[^>]+)>/i.test(text); + }; + var toBRs = function (text) { + return text.replace(/\r?\n/g, '
'); + }; + var openContainer = function (rootTag, rootAttrs) { + var key; + var attrs = []; + var tag = '<' + rootTag; + if (typeof rootAttrs === 'object') { + for (key in rootAttrs) { + if (rootAttrs.hasOwnProperty(key)) { + attrs.push(key + '="' + global$5.encodeAllRaw(rootAttrs[key]) + '"'); + } + } + if (attrs.length) { + tag += ' ' + attrs.join(' '); + } + } + return tag + '>'; + }; + var toBlockElements = function (text, rootTag, rootAttrs) { + var blocks = text.split(/\n\n/); + var tagOpen = openContainer(rootTag, rootAttrs); + var tagClose = ''; + var paragraphs = global$3.map(blocks, function (p) { + return p.split(/\n/).join('
'); + }); + var stitch = function (p) { + return tagOpen + p + tagClose; + }; + return paragraphs.length === 1 ? paragraphs[0] : global$3.map(paragraphs, stitch).join(''); + }; + var convert = function (text, rootTag, rootAttrs) { + return rootTag ? toBlockElements(text, rootTag, rootAttrs) : toBRs(text); + }; + var $_4h3hnrisjjgwecu2 = { + isPlainText: isPlainText, + convert: convert, + toBRs: toBRs, + toBlockElements: toBlockElements + }; - /** - * 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 - * for custom user filtering. - * - * @param {String} html HTML code to paste into the current selection. - */ - function pasteHtml(html) { - var args, dom = editor.dom; - - args = editor.fire('BeforePastePreProcess', {content: html}); // Internal event used by Quirks - args = editor.fire('PastePreProcess', args); - html = args.content; - - if (!args.isDefaultPrevented()) { - // User has bound PastePostProcess events then we need to pass it through a DOM node - // This is not ideal but we don't want to let the browser mess up the HTML for example - // some browsers add   to P tags etc - if (editor.hasEventListeners('PastePostProcess') && !args.isDefaultPrevented()) { - // We need to attach the element to the DOM so Sizzle selectors work on the contents - var tempBody = dom.add(editor.getBody(), 'div', {style: 'display:none'}, html); - args = editor.fire('PastePostProcess', {node: tempBody}); - dom.remove(tempBody); - html = args.node.innerHTML; - } - - if (!args.isDefaultPrevented()) { - editor.insertContent(html, {merge: editor.settings.paste_merge_formats !== false}); - } - } - } - - /** - * Pastes the specified text. This means that the plain text is processed - * and converted into BR and P elements. It will fire paste events for custom filtering. - * - * @param {String} text Text to paste as the current selection location. - */ - function pasteText(text) { - text = editor.dom.encode(text).replace(/\r\n/g, '\n'); - - var startBlock = editor.dom.getParent(editor.selection.getStart(), editor.dom.isBlock); + var global$6 = tinymce.util.Tools.resolve('tinymce.html.DomParser'); - // Create start block html for example

- var forcedRootBlockName = editor.settings.forced_root_block; - var forcedRootBlockStartHtml; - if (forcedRootBlockName) { - forcedRootBlockStartHtml = editor.dom.createHTML(forcedRootBlockName, editor.settings.forced_root_block_attrs); - forcedRootBlockStartHtml = forcedRootBlockStartHtml.substr(0, forcedRootBlockStartHtml.length - 3) + '>'; - } - - if ((startBlock && /^(PRE|DIV)$/.test(startBlock.nodeName)) || !forcedRootBlockName) { - text = Utils.filter(text, [ - [/\n/g, "
"] - ]); - } else { - text = Utils.filter(text, [ - [/\n\n/g, "

" + forcedRootBlockStartHtml], - [/^(.*<\/p>)(

)$/, forcedRootBlockStartHtml + '$1'], - [/\n/g, "
"] - ]); - - if (text.indexOf('

') != -1) { - text = forcedRootBlockStartHtml + text; - } - } + var global$7 = tinymce.util.Tools.resolve('tinymce.html.Node'); - pasteHtml(text); - } + var global$8 = tinymce.util.Tools.resolve('tinymce.html.Schema'); - /** - * Creates a paste bin element as close as possible to the current caret location and places the focus inside that element - * so that when the real paste event occurs the contents gets inserted into this element - * instead of the current editor selection element. - */ - function createPasteBin() { - var dom = editor.dom, body = editor.getBody(); - var viewport = editor.dom.getViewPort(editor.getWin()), scrollTop = viewport.y, top = 20; - var scrollContainer; - - lastRng = editor.selection.getRng(); - - if (editor.inline) { - scrollContainer = editor.selection.getScrollContainer(); - - // Can't always rely on scrollTop returning a useful value. - // It returns 0 if the browser doesn't support scrollTop for the element or is non-scrollable - if (scrollContainer && scrollContainer.scrollTop > 0) { - scrollTop = scrollContainer.scrollTop; - } - } + var global$9 = tinymce.util.Tools.resolve('tinymce.html.Serializer'); - /** - * Returns the rect of the current caret if the caret is in an empty block before a - * BR we insert a temporary invisible character that we get the rect this way we always get a proper rect. - * - * TODO: This might be useful in core. - */ - function getCaretRect(rng) { - var rects, textNode, node, container = rng.startContainer; - - rects = rng.getClientRects(); - if (rects.length) { - return rects[0]; - } - - if (!rng.collapsed || container.nodeType != 1) { - return; - } - - node = container.childNodes[lastRng.startOffset]; - - // Skip empty whitespace nodes - while (node && node.nodeType == 3 && !node.data.length) { - node = node.nextSibling; - } - - if (!node) { - return; - } - - // Check if the location is |
- // TODO: Might need to expand this to say | - if (node.tagName == 'BR') { - textNode = dom.doc.createTextNode('\uFEFF'); - node.parentNode.insertBefore(textNode, node); - - rng = dom.createRng(); - rng.setStartBefore(textNode); - rng.setEndAfter(textNode); - - rects = rng.getClientRects(); - dom.remove(textNode); - } - - if (rects.length) { - return rects[0]; - } - } - - // Calculate top cordinate this is needed to avoid scrolling to top of document - // We want the paste bin to be as close to the caret as possible to avoid scrolling - if (lastRng.getClientRects) { - var rect = getCaretRect(lastRng); + function filter(content, items) { + global$3.each(items, function (v) { + if (v.constructor === RegExp) { + content = content.replace(v, ''); + } else { + content = content.replace(v[0], v[1]); + } + }); + return content; + } + function innerText(html) { + var schema = global$8(); + var domParser = global$6({}, schema); + var text = ''; + var shortEndedElements = schema.getShortEndedElements(); + var ignoreElements = global$3.makeMap('script noscript style textarea video audio iframe object', ' '); + var blockElements = schema.getBlockElements(); + function walk(node) { + var name$$1 = node.name, currentNode = node; + if (name$$1 === 'br') { + text += '\n'; + return; + } + if (shortEndedElements[name$$1]) { + text += ' '; + } + if (ignoreElements[name$$1]) { + text += ' '; + return; + } + if (node.type === 3) { + text += node.value; + } + if (!node.shortEnded) { + if (node = node.firstChild) { + do { + walk(node); + } while (node = node.next); + } + } + if (blockElements[name$$1] && currentNode.next) { + text += '\n'; + if (name$$1 === 'p') { + text += '\n'; + } + } + } + html = filter(html, [//g]); + walk(domParser.parse(html)); + return text; + } + function trimHtml(html) { + function trimSpaces(all, s1, s2) { + if (!s1 && !s2) { + return ' '; + } + return '\xA0'; + } + html = filter(html, [ + /^[\s\S]*]*>\s*|\s*<\/body[^>]*>[\s\S]*$/ig, + /|/g, + [ + /( ?)\u00a0<\/span>( ?)/g, + trimSpaces + ], + /
/g, + /
$/i + ]); + return html; + } + function createIdGenerator(prefix) { + var count = 0; + return function () { + return prefix + count++; + }; + } + var isMsEdge = function () { + return navigator.userAgent.indexOf(' Edge/') !== -1; + }; + var $_4bi2o9j0jjgwecui = { + filter: filter, + innerText: innerText, + trimHtml: trimHtml, + createIdGenerator: createIdGenerator, + isMsEdge: isMsEdge + }; - if (rect) { - // Client rects gets us closes to the actual - // caret location in for example a wrapped paragraph block - top = scrollTop + (rect.top - dom.getPos(body).y); - } else { - top = scrollTop; - - // Check if we can find a closer location by checking the range element - var container = lastRng.startContainer; - if (container) { - if (container.nodeType == 3 && container.parentNode != body) { - container = container.parentNode; - } - - if (container.nodeType == 1) { - top = dom.getPos(container, scrollContainer || body).y; - } - } - } - } - - // Create a pastebin - pasteBinElm = dom.add(editor.getBody(), 'div', { - id: "mcepastebin", - contentEditable: true, - "data-mce-bogus": "all", - style: 'position: absolute; top: ' + top + 'px;' + - 'width: 10px; height: 10px; overflow: hidden; opacity: 0' - }, pasteBinDefaultContent); - - // Move paste bin out of sight since the controlSelection rect gets displayed otherwise on IE and Gecko - if (Env.ie || Env.gecko) { - dom.setStyle(pasteBinElm, 'left', dom.getStyle(body, 'direction', true) == 'rtl' ? 0xFFFF : -0xFFFF); - } - - // Prevent focus events from bubbeling fixed FocusManager issues - dom.bind(pasteBinElm, 'beforedeactivate focusin focusout', function(e) { - e.stopPropagation(); - }); - - pasteBinElm.focus(); - editor.selection.select(pasteBinElm, true); - } - - /** - * Removes the paste bin if it exists. - */ - function removePasteBin() { - if (pasteBinElm) { - var pasteBinClone; - - // WebKit/Blink might clone the div so - // lets make sure we remove all clones - // TODO: Man o man is this ugly. WebKit is the new IE! Remove this if they ever fix it! - while ((pasteBinClone = editor.dom.get('mcepastebin'))) { - editor.dom.remove(pasteBinClone); - editor.dom.unbind(pasteBinClone); - } - - if (lastRng) { - editor.selection.setRng(lastRng); - } - } - - pasteBinElm = lastRng = null; - } - - /** - * Returns the contents of the paste bin as a HTML string. - * - * @return {String} Get the contents of the paste bin. - */ - function getPasteBinHtml() { - var html = '', pasteBinClones, i, clone, cloneHtml; - - // Since WebKit/Chrome might clone the paste bin when pasting - // for example: we need to check if any of them contains some useful html. - // TODO: Man o man is this ugly. WebKit is the new IE! Remove this if they ever fix it! - pasteBinClones = editor.dom.select('div[id=mcepastebin]'); - for (i = 0; i < pasteBinClones.length; i++) { - clone = pasteBinClones[i]; - - // Pasting plain text produces pastebins in pastebinds makes sence right!? - if (clone.firstChild && clone.firstChild.id == 'mcepastebin') { - clone = clone.firstChild; - } - - cloneHtml = clone.innerHTML; - if (html != pasteBinDefaultContent) { - html += cloneHtml; - } - } - - return html; - } - - /** - * Gets various content types out of a datatransfer object. - * - * @param {DataTransfer} dataTransfer Event fired on paste. - * @return {Object} Object with mime types and data for those mime types. - */ - function getDataTransferItems(dataTransfer) { - var data = {}; - - if (dataTransfer) { - // Use old WebKit/IE API - if (dataTransfer.getData) { - var legacyText = dataTransfer.getData('Text'); - if (legacyText && legacyText.length > 0) { - if (legacyText.indexOf(mceInternalUrlPrefix) == -1) { - data['text/plain'] = legacyText; - } - } - } - - if (dataTransfer.types) { - for (var i = 0; i < dataTransfer.types.length; i++) { - var contentType = dataTransfer.types[i]; - data[contentType] = dataTransfer.getData(contentType); - } - } - } - - return data; - } - - /** - * Gets various content types out of the Clipboard API. It will also get the - * plain text using older IE and WebKit API:s. - * - * @param {ClipboardEvent} clipboardEvent Event fired on paste. - * @return {Object} Object with mime types and data for those mime types. - */ - function getClipboardContent(clipboardEvent) { - return getDataTransferItems(clipboardEvent.clipboardData || editor.getDoc().dataTransfer); - } - - /** - * Checks if the clipboard contains image data if it does it will take that data - * and convert it into a data url image and paste that image at the caret location. - * - * @param {ClipboardEvent} e Paste/drop event object. - * @param {DOMRange} rng Optional rng object to move selection to. - * @return {Boolean} true/false if the image data was found or not. - */ - function pasteImageData(e, rng) { - var dataTransfer = e.clipboardData || e.dataTransfer; - - function processItems(items) { - var i, item, reader, hadImage = false; - - function pasteImage(reader) { - if (rng) { - editor.selection.setRng(rng); - rng = null; - } - - pasteHtml(''); - } - - if (items) { - for (i = 0; i < items.length; i++) { - item = items[i]; - - if (/^image\/(jpeg|png|gif|bmp)$/.test(item.type)) { - reader = new FileReader(); - reader.onload = pasteImage.bind(null, reader); - reader.readAsDataURL(item.getAsFile ? item.getAsFile() : item); - - e.preventDefault(); - hadImage = true; - } - } - } - - return hadImage; - } - - if (editor.settings.paste_data_images && dataTransfer) { - return processItems(dataTransfer.items) || processItems(dataTransfer.files); - } - } - - /** - * Chrome on Android doesn't support proper clipboard access so we have no choice but to allow the browser default behavior. - * - * @param {Event} e Paste event object to check if it contains any data. - * @return {Boolean} true/false if the clipboard is empty or not. - */ - function isBrokenAndroidClipboardEvent(e) { - var clipboardData = e.clipboardData; - - return navigator.userAgent.indexOf('Android') != -1 && clipboardData && clipboardData.items && clipboardData.items.length === 0; - } - - function getCaretRangeFromEvent(e) { - return RangeUtils.getCaretRangeFromPoint(e.clientX, e.clientY, editor.getDoc()); - } + function isWordContent(content) { + return / 1) { + currentListNode.attr('start', '' + start); + } + paragraphNode.wrap(currentListNode); + } else { + currentListNode.append(paragraphNode); + } + paragraphNode.name = 'li'; + if (level > lastLevel && prevListNode) { + prevListNode.lastChild.append(currentListNode); + } + lastLevel = level; + removeIgnoredNodes(paragraphNode); + trimListStart(paragraphNode, /^\u00a0+/); + trimListStart(paragraphNode, /^\s*([\u2022\u00b7\u00a7\u25CF]|\w+\.)/); + trimListStart(paragraphNode, /^\u00a0+/); + } + var elements = []; + var child = node.firstChild; + while (typeof child !== 'undefined' && child !== null) { + elements.push(child); + child = child.walk(); + if (child !== null) { + while (typeof child !== 'undefined' && child.parent !== node) { + child = child.walk(); + } + } + } + for (var i = 0; i < elements.length; i++) { + node = elements[i]; + if (node.name === 'p' && node.firstChild) { + var nodeText = getText(node); + if (isBulletList(nodeText)) { + convertParagraphToLi(node, 'ul'); + continue; + } + if (isNumericList(nodeText)) { + var matches = /([0-9]+)\./.exec(nodeText); + var start = 1; + if (matches) { + start = parseInt(matches[1], 10); + } + convertParagraphToLi(node, 'ol', start); + continue; + } + if (node._listLevel) { + convertParagraphToLi(node, 'ul', 1); + continue; + } + currentListNode = null; + } else { + prevListNode = currentListNode; + currentListNode = null; + } + } + } + function filterStyles(editor, validStyles, node, styleValue) { + var outputStyles = {}, matches; + var styles = editor.dom.parseStyle(styleValue); + global$3.each(styles, function (value, name) { + switch (name) { + case 'mso-list': + matches = /\w+ \w+([0-9]+)/i.exec(styleValue); + if (matches) { + node._listLevel = parseInt(matches[1], 10); + } + if (/Ignore/i.test(value) && node.firstChild) { + node._listIgnore = true; + node.firstChild._listIgnore = true; + } + break; + case 'horiz-align': + name = 'text-align'; + break; + case 'vert-align': + name = 'vertical-align'; + break; + case 'font-color': + case 'mso-foreground': + name = 'color'; + break; + case 'mso-background': + case 'mso-highlight': + name = 'background'; + break; + case 'font-weight': + case 'font-style': + if (value !== 'normal') { + outputStyles[name] = value; + } + return; + case 'mso-element': + if (/^(comment|comment-list)$/i.test(value)) { + node.remove(); + return; + } + break; + } + if (name.indexOf('mso-comment') === 0) { + node.remove(); + return; + } + if (name.indexOf('mso-') === 0) { + return; + } + if ($_xr8b0ikjjgwectl.getRetainStyleProps(editor) === 'all' || validStyles && validStyles[name]) { + outputStyles[name] = value; + } + }); + if (/(bold)/i.test(outputStyles['font-weight'])) { + delete outputStyles['font-weight']; + node.wrap(new global$7('b', 1)); + } + if (/(italic)/i.test(outputStyles['font-style'])) { + delete outputStyles['font-style']; + node.wrap(new global$7('i', 1)); + } + outputStyles = editor.dom.serializeStyle(outputStyles, node.name); + if (outputStyles) { + return outputStyles; + } + return null; + } + var filterWordContent = function (editor, content) { + var retainStyleProperties, validStyles; + retainStyleProperties = $_xr8b0ikjjgwectl.getRetainStyleProps(editor); + if (retainStyleProperties) { + validStyles = global$3.makeMap(retainStyleProperties.split(/[, ]/)); + } + content = $_4bi2o9j0jjgwecui.filter(content, [ + /
/gi, + /]+id="?docs-internal-[^>]*>/gi, + //gi, + /<(!|script[^>]*>.*?<\/script(?=[>\s])|\/?(\?xml(:\w+)?|img|meta|link|style|\w:\w+)(?=[\s\/>]))[^>]*>/gi, + [ + /<(\/?)s>/gi, + '<$1strike>' + ], + [ + / /gi, + '\xA0' + ], + [ + /([\s\u00a0]*)<\/span>/gi, + function (str, spaces) { + return spaces.length > 0 ? spaces.replace(/./, ' ').slice(Math.floor(spaces.length / 2)).split('').join('\xA0') : ''; + } + ] + ]); + var validElements = $_xr8b0ikjjgwectl.getWordValidElements(editor); + var schema = global$8({ + valid_elements: validElements, + valid_children: '-li[p]' + }); + global$3.each(schema.elements, function (rule) { + if (!rule.attributes.class) { + rule.attributes.class = {}; + rule.attributesOrder.push('class'); + } + if (!rule.attributes.style) { + rule.attributes.style = {}; + rule.attributesOrder.push('style'); + } + }); + var domParser = global$6({}, schema); + domParser.addAttributeFilter('style', function (nodes) { + var i = nodes.length, node; + while (i--) { + node = nodes[i]; + node.attr('style', filterStyles(editor, validStyles, node, node.attr('style'))); + if (node.name === 'span' && node.parent && !node.attributes.length) { + node.unwrap(); + } + } + }); + domParser.addAttributeFilter('class', function (nodes) { + var i = nodes.length, node, className; + while (i--) { + node = nodes[i]; + className = node.attr('class'); + if (/^(MsoCommentReference|MsoCommentText|msoDel)$/i.test(className)) { + node.remove(); + } + node.attr('class', null); + } + }); + domParser.addNodeFilter('del', function (nodes) { + var i = nodes.length; + while (i--) { + nodes[i].remove(); + } + }); + domParser.addNodeFilter('a', function (nodes) { + var i = nodes.length, node, href, name; + while (i--) { + node = nodes[i]; + href = node.attr('href'); + name = node.attr('name'); + if (href && href.indexOf('#_msocom_') !== -1) { + node.remove(); + continue; + } + if (href && href.indexOf('file://') === 0) { + href = href.split('#')[1]; + if (href) { + href = '#' + href; + } + } + if (!href && !name) { + node.unwrap(); + } else { + if (name && !/^_?(?:toc|edn|ftn)/i.test(name)) { + node.unwrap(); + continue; + } + node.attr({ + href: href, + name: name + }); + } + } + }); + var rootNode = domParser.parse(content); + if ($_xr8b0ikjjgwectl.shouldConvertWordFakeLists(editor)) { + convertFakeListsToProperLists(rootNode); + } + content = global$9({ validate: editor.settings.validate }, schema).serialize(rootNode); + return content; + }; + var preProcess = function (editor, content) { + return $_xr8b0ikjjgwectl.shouldUseDefaultFilters(editor) ? filterWordContent(editor, content) : content; + }; + var $_dfatuiivjjgwecu8 = { + preProcess: preProcess, + isWordContent: isWordContent + }; - function hasContentType(clipboardContent, mimeType) { - return mimeType in clipboardContent && clipboardContent[mimeType].length > 0; - } - - function isKeyboardPasteEvent(e) { - return (VK.metaKeyPressed(e) && e.keyCode == 86) || (e.shiftKey && e.keyCode == 45); - } - - function registerEventHandlers() { - editor.on('keydown', function(e) { - function removePasteBinOnKeyUp(e) { - // Ctrl+V or Shift+Insert - if (isKeyboardPasteEvent(e) && !e.isDefaultPrevented()) { - removePasteBin(); - } - } - - // Ctrl+V or Shift+Insert - if (isKeyboardPasteEvent(e) && !e.isDefaultPrevented()) { - keyboardPastePlainTextState = e.shiftKey && e.keyCode == 86; - - // Edge case on Safari on Mac where it doesn't handle Cmd+Shift+V correctly - // it fires the keydown but no paste or keyup so we are left with a paste bin - if (keyboardPastePlainTextState && Env.webkit && navigator.userAgent.indexOf('Version/') != -1) { - return; - } - - // Prevent undoManager keydown handler from making an undo level with the pastebin in it - e.stopImmediatePropagation(); - - keyboardPasteTimeStamp = new Date().getTime(); - - // IE doesn't support Ctrl+Shift+V and it doesn't even produce a paste event - // so lets fake a paste event and let IE use the execCommand/dataTransfer methods - if (Env.ie && keyboardPastePlainTextState) { - e.preventDefault(); - editor.fire('paste', {ieFake: true}); - return; - } - - removePasteBin(); - createPasteBin(); - - // Remove pastebin if we get a keyup and no paste event - // For example pasting a file in IE 11 will not produce a paste event - editor.once('keyup', removePasteBinOnKeyUp); - editor.once('paste', function() { - editor.off('keyup', removePasteBinOnKeyUp); - }); - } - }); - - editor.on('paste', function(e) { - // Getting content from the Clipboard can take some time - var clipboardTimer = new Date().getTime(); - var clipboardContent = getClipboardContent(e); - var clipboardDelay = new Date().getTime() - clipboardTimer; - - var isKeyBoardPaste = (new Date().getTime() - keyboardPasteTimeStamp - clipboardDelay) < 1000; - var plainTextMode = self.pasteFormat == "text" || keyboardPastePlainTextState; - - keyboardPastePlainTextState = false; - - if (e.isDefaultPrevented() || isBrokenAndroidClipboardEvent(e)) { - removePasteBin(); - return; - } - - if (pasteImageData(e)) { - removePasteBin(); - return; - } - - // Not a keyboard paste prevent default paste and try to grab the clipboard contents using different APIs - if (!isKeyBoardPaste) { - e.preventDefault(); - } - - // Try IE only method if paste isn't a keyboard paste - if (Env.ie && (!isKeyBoardPaste || e.ieFake)) { - createPasteBin(); - - editor.dom.bind(pasteBinElm, 'paste', function(e) { - e.stopPropagation(); - }); - - editor.getDoc().execCommand('Paste', false, null); - clipboardContent["text/html"] = getPasteBinHtml(); - } - - setTimeout(function() { - var content; - - // Grab HTML from Clipboard API or paste bin as a fallback - if (hasContentType(clipboardContent, 'text/html')) { - content = clipboardContent['text/html']; - } else { - content = getPasteBinHtml(); + var processResult = function (content, cancelled) { + return { + content: content, + cancelled: cancelled + }; + }; + var postProcessFilter = function (editor, html, internal, isWordHtml) { + var tempBody = editor.dom.create('div', { style: 'display:none' }, html); + var postProcessArgs = $_8tki3zijjjgwectj.firePastePostProcess(editor, tempBody, internal, isWordHtml); + return processResult(postProcessArgs.node.innerHTML, postProcessArgs.isDefaultPrevented()); + }; + var filterContent = function (editor, content, internal, isWordHtml) { + var preProcessArgs = $_8tki3zijjjgwectj.firePastePreProcess(editor, content, internal, isWordHtml); + if (editor.hasEventListeners('PastePostProcess') && !preProcessArgs.isDefaultPrevented()) { + return postProcessFilter(editor, preProcessArgs.content, internal, isWordHtml); + } else { + return processResult(preProcessArgs.content, preProcessArgs.isDefaultPrevented()); + } + }; + var process = function (editor, html, internal) { + var isWordHtml = $_dfatuiivjjgwecu8.isWordContent(html); + var content = isWordHtml ? $_dfatuiivjjgwecu8.preProcess(editor, html) : html; + return filterContent(editor, content, internal, isWordHtml); + }; + var $_3scw66iujjgwecu4 = { process: process }; - // If paste bin is empty try using plain text mode - // since that is better than nothing right - if (content == pasteBinDefaultContent) { - plainTextMode = true; - } - } - - content = Utils.trimHtml(content); - - // WebKit has a nice bug where it clones the paste bin if you paste from for example notepad - // so we need to force plain text mode in this case - if (pasteBinElm && pasteBinElm.firstChild && pasteBinElm.firstChild.id === 'mcepastebin') { - plainTextMode = true; - } - - removePasteBin(); - - // If we got nothing from clipboard API and pastebin then we could try the last resort: plain/text - if (!content.length) { - plainTextMode = true; - } - - // Grab plain text from Clipboard API or convert existing HTML to plain text - if (plainTextMode) { - // 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') && content.indexOf('

') == -1) { - content = clipboardContent['text/plain']; - } else { - content = Utils.innerText(content); - } - } - - // If the content is the paste bin default HTML then it was - // impossible to get the cliboard data out. - if (content == pasteBinDefaultContent) { - if (!isKeyBoardPaste) { - editor.windowManager.alert('Please use Ctrl+V/Cmd+V keyboard shortcuts to paste contents.'); - } - - return; - } - - if (plainTextMode) { - pasteText(content); - } else { - pasteHtml(content); - } - }, 0); - }); - - editor.on('dragstart dragend', function(e) { - draggingInternally = e.type == 'dragstart'; - }); - - editor.on('drop', function(e) { - var rng = getCaretRangeFromEvent(e); - - if (e.isDefaultPrevented() || draggingInternally) { - return; - } - - if (pasteImageData(e, rng)) { - return; - } - - if (rng && editor.settings.paste_filter_drop !== false) { - var dropContent = getDataTransferItems(e.dataTransfer); - var content = dropContent['mce-internal'] || dropContent['text/html'] || dropContent['text/plain']; - - if (content) { - e.preventDefault(); - - editor.undoManager.transact(function() { - if (dropContent['mce-internal']) { - editor.execCommand('Delete'); - } - - editor.selection.setRng(rng); - - content = Utils.trimHtml(content); - - if (!dropContent['text/html']) { - pasteText(content); - } else { - pasteHtml(content); - } - }); - } - } - }); - - editor.on('dragover dragend', function(e) { - if (editor.settings.paste_data_images) { - e.preventDefault(); - } - }); - } - - self.pasteHtml = pasteHtml; - self.pasteText = pasteText; + var pasteHtml = function (editor, html) { + editor.insertContent(html, { + merge: $_xr8b0ikjjgwectl.shouldMergeFormats(editor), + paste: true + }); + return true; + }; + var isAbsoluteUrl = function (url) { + return /^https?:\/\/[\w\?\-\/+=.&%@~#]+$/i.test(url); + }; + var isImageUrl = function (url) { + return isAbsoluteUrl(url) && /.(gif|jpe?g|png)$/.test(url); + }; + var createImage = function (editor, url, pasteHtmlFn) { + editor.undoManager.extra(function () { + pasteHtmlFn(editor, url); + }, function () { + editor.insertContent(''); + }); + return true; + }; + var createLink = function (editor, url, pasteHtmlFn) { + editor.undoManager.extra(function () { + pasteHtmlFn(editor, url); + }, function () { + editor.execCommand('mceInsertLink', false, url); + }); + return true; + }; + var linkSelection = function (editor, html, pasteHtmlFn) { + return editor.selection.isCollapsed() === false && isAbsoluteUrl(html) ? createLink(editor, html, pasteHtmlFn) : false; + }; + var insertImage = function (editor, html, pasteHtmlFn) { + return isImageUrl(html) ? createImage(editor, html, pasteHtmlFn) : false; + }; + var smartInsertContent = function (editor, html) { + global$3.each([ + linkSelection, + insertImage, + pasteHtml + ], function (action) { + return action(editor, html, pasteHtml) !== true; + }); + }; + var insertContent = function (editor, html) { + if ($_xr8b0ikjjgwectl.isSmartPasteEnabled(editor) === false) { + pasteHtml(editor, html); + } else { + smartInsertContent(editor, html); + } + }; + var $_d8pzpej1jjgwecum = { + isImageUrl: isImageUrl, + isAbsoluteUrl: isAbsoluteUrl, + insertContent: insertContent + }; - editor.on('preInit', function() { - registerEventHandlers(); - - // Remove all data images from paste for example from Gecko - // except internal images like video elements - editor.parser.addNodeFilter('img', function(nodes) { - if (!editor.settings.paste_data_images) { - var i = nodes.length; - - while (i--) { - var src = nodes[i].attributes.map.src; - - // Some browsers automatically produce data uris on paste - // Safari on Mac produces webkit-fake-url see: https://bugs.webkit.org/show_bug.cgi?id=49141 - if (src && /^(data:image|webkit\-fake\-url)/.test(src)) { - if (!nodes[i].attr('data-mce-object') && src !== Env.transparentSrc) { - nodes[i].remove(); - } - } - } - } - }); - }); - }; -}); - -// Included from: js/tinymce/plugins/paste/classes/WordFilter.js - -/** - * WordFilter.js - * - * Copyright, Moxiecode Systems AB - * Released under LGPL License. - * - * License: http://www.tinymce.com/license - * Contributing: http://www.tinymce.com/contributing - */ - -/** - * This class parses word HTML into proper TinyMCE markup. - * - * @class tinymce.pasteplugin.WordFilter - * @private - */ -define("tinymce/pasteplugin/WordFilter", [ - "tinymce/util/Tools", - "tinymce/html/DomParser", - "tinymce/html/Schema", - "tinymce/html/Serializer", - "tinymce/html/Node", - "tinymce/pasteplugin/Utils" -], function(Tools, DomParser, Schema, Serializer, Node, Utils) { - /** - * Checks if the specified content is from any of the following sources: MS Word/Office 365/Google docs. - */ - function isWordContent(content) { - return ( - (/]+id="?docs-internal-[^>]*>/gi, ''); - content = content.replace(/
/gi, ''); - - retainStyleProperties = settings.paste_retain_style_properties; - if (retainStyleProperties) { - validStyles = Tools.makeMap(retainStyleProperties.split(/[, ]/)); - } - - /** - * Converts fake bullet and numbered lists to real semantic OL/UL. - * - * @param {tinymce.html.Node} node Root node to convert children of. - */ - function convertFakeListsToProperLists(node) { - var currentListNode, prevListNode, lastLevel = 1; - - function getText(node) { - var txt = ''; - - if (node.type === 3) { - return node.value; - } - - if ((node = node.firstChild)) { - do { - txt += getText(node); - } while ((node = node.next)); - } - - return txt; - } - - function trimListStart(node, regExp) { - if (node.type === 3) { - if (regExp.test(node.value)) { - node.value = node.value.replace(regExp, ''); - return false; - } - } - - if ((node = node.firstChild)) { - do { - if (!trimListStart(node, regExp)) { - return false; - } - } while ((node = node.next)); - } - - return true; - } - - function removeIgnoredNodes(node) { - if (node._listIgnore) { - node.remove(); - return; - } - - if ((node = node.firstChild)) { - do { - removeIgnoredNodes(node); - } while ((node = node.next)); - } - } - - function convertParagraphToLi(paragraphNode, listName, start) { - var level = paragraphNode._listLevel || lastLevel; - - // Handle list nesting - if (level != lastLevel) { - if (level < lastLevel) { - // Move to parent list - if (currentListNode) { - currentListNode = currentListNode.parent.parent; - } - } else { - // Create new list - prevListNode = currentListNode; - currentListNode = null; - } - } - - if (!currentListNode || currentListNode.name != listName) { - prevListNode = prevListNode || currentListNode; - currentListNode = new Node(listName, 1); - - if (start > 1) { - currentListNode.attr('start', '' + start); - } - - paragraphNode.wrap(currentListNode); - } else { - currentListNode.append(paragraphNode); - } - - paragraphNode.name = 'li'; - - // Append list to previous list if it exists - if (level > lastLevel && prevListNode) { - prevListNode.lastChild.append(currentListNode); - } - - lastLevel = level; - - // Remove start of list item "1. " or "· " etc - removeIgnoredNodes(paragraphNode); - trimListStart(paragraphNode, /^\u00a0+/); - trimListStart(paragraphNode, /^\s*([\u2022\u00b7\u00a7\u25CF]|\w+\.)/); - trimListStart(paragraphNode, /^\u00a0+/); - } - - // Build a list of all root level elements before we start - // altering them in the loop below. - var elements = [], child = node.firstChild; - while (typeof child !== 'undefined' && child !== null) { - elements.push(child); - - child = child.walk(); - if (child !== null) { - while (typeof child !== 'undefined' && child.parent !== node) { - child = child.walk(); - } - } - } - - for (var i = 0; i < elements.length; i++) { - node = elements[i]; - - if (node.name == 'p' && node.firstChild) { - // Find first text node in paragraph - var nodeText = getText(node); - - // Detect unordered lists look for bullets - if (isBulletList(nodeText)) { - convertParagraphToLi(node, 'ul'); - continue; - } - - // Detect ordered lists 1., a. or ixv. - if (isNumericList(nodeText)) { - // Parse OL start number - var matches = /([0-9]+)\./.exec(nodeText); - var start = 1; - if (matches) { - start = parseInt(matches[1], 10); - } - - convertParagraphToLi(node, 'ol', start); - continue; - } - - // Convert paragraphs marked as lists but doesn't look like anything - if (node._listLevel) { - convertParagraphToLi(node, 'ul', 1); - continue; - } - - currentListNode = null; - } else { - // If the root level element isn't a p tag which can be - // processed by convertParagraphToLi, it interrupts the - // lists, causing a new list to start instead of having - // elements from the next list inserted above this tag. - prevListNode = currentListNode; - currentListNode = null; - } - } - } - - function filterStyles(node, styleValue) { - var outputStyles = {}, matches, styles = editor.dom.parseStyle(styleValue); - - Tools.each(styles, function(value, name) { - // Convert various MS styles to W3C styles - switch (name) { - case 'mso-list': - // Parse out list indent level for lists - matches = /\w+ \w+([0-9]+)/i.exec(styleValue); - if (matches) { - node._listLevel = parseInt(matches[1], 10); - } - - // Remove these nodes o - // Since the span gets removed we mark the text node and the span - if (/Ignore/i.test(value) && node.firstChild) { - node._listIgnore = true; - node.firstChild._listIgnore = true; - } - - break; - - case "horiz-align": - name = "text-align"; - break; - - case "vert-align": - name = "vertical-align"; - break; - - case "font-color": - case "mso-foreground": - name = "color"; - break; - - case "mso-background": - case "mso-highlight": - name = "background"; - break; - - case "font-weight": - case "font-style": - if (value != "normal") { - outputStyles[name] = value; - } - return; - - case "mso-element": - // Remove track changes code - if (/^(comment|comment-list)$/i.test(value)) { - node.remove(); - return; - } - - break; - } - - if (name.indexOf('mso-comment') === 0) { - node.remove(); - return; - } - - // Never allow mso- prefixed names - if (name.indexOf('mso-') === 0) { - return; - } - - // Output only valid styles - if (retainStyleProperties == "all" || (validStyles && validStyles[name])) { - outputStyles[name] = value; - } - }); - - // Convert bold style to "b" element - if (/(bold)/i.test(outputStyles["font-weight"])) { - delete outputStyles["font-weight"]; - node.wrap(new Node("b", 1)); - } - - // Convert italic style to "i" element - if (/(italic)/i.test(outputStyles["font-style"])) { - delete outputStyles["font-style"]; - node.wrap(new Node("i", 1)); - } - - // Serialize the styles and see if there is something left to keep - outputStyles = editor.dom.serializeStyle(outputStyles, node.name); - if (outputStyles) { - return outputStyles; - } - - return null; - } - - if (settings.paste_enable_default_filters === false) { - return; - } - - // Detect is the contents is Word junk HTML - if (isWordContent(e.content)) { - e.wordContent = true; // Mark it for other processors - - // Remove basic Word junk - content = Utils.filter(content, [ - // Word comments like conditional comments etc - //gi, - - // Remove comments, scripts (e.g., msoShowComment), XML tag, VML content, - // MS Office namespaced tags, and a few other tags - /<(!|script[^>]*>.*?<\/script(?=[>\s])|\/?(\?xml(:\w+)?|img|meta|link|style|\w:\w+)(?=[\s\/>]))[^>]*>/gi, - - // Convert into for line-though - [/<(\/?)s>/gi, "<$1strike>"], - - // Replace nsbp entites to char since it's easier to handle - [/ /gi, "\u00a0"], - - // Convert ___ to string of alternating - // breaking/non-breaking spaces of same length - [/([\s\u00a0]*)<\/span>/gi, - function(str, spaces) { - return (spaces.length > 0) ? - spaces.replace(/./, " ").slice(Math.floor(spaces.length / 2)).split("").join("\u00a0") : ""; - } - ] - ]); + var pasteHtml$1 = function (editor, html, internalFlag) { + var internal = internalFlag ? internalFlag : $_4x13hjirjjgwecu1.isMarked(html); + var args = $_3scw66iujjgwecu4.process(editor, $_4x13hjirjjgwecu1.unmark(html), internal); + if (args.cancelled === false) { + $_d8pzpej1jjgwecum.insertContent(editor, args.content); + } + }; + var pasteText = function (editor, text) { + text = editor.dom.encode(text).replace(/\r\n/g, '\n'); + text = $_4h3hnrisjjgwecu2.convert(text, editor.settings.forced_root_block, editor.settings.forced_root_block_attrs); + pasteHtml$1(editor, text, false); + }; + var getDataTransferItems = function (dataTransfer) { + var items = {}; + var mceInternalUrlPrefix = 'data:text/mce-internal,'; + if (dataTransfer) { + if (dataTransfer.getData) { + var legacyText = dataTransfer.getData('Text'); + if (legacyText && legacyText.length > 0) { + if (legacyText.indexOf(mceInternalUrlPrefix) === -1) { + items['text/plain'] = legacyText; + } + } + } + if (dataTransfer.types) { + for (var i = 0; i < dataTransfer.types.length; i++) { + var contentType = dataTransfer.types[i]; + try { + items[contentType] = dataTransfer.getData(contentType); + } catch (ex) { + items[contentType] = ''; + } + } + } + } + return items; + }; + var getClipboardContent = function (editor, clipboardEvent) { + var content = getDataTransferItems(clipboardEvent.clipboardData || editor.getDoc().dataTransfer); + return $_4bi2o9j0jjgwecui.isMsEdge() ? global$3.extend(content, { 'text/html': '' }) : content; + }; + var hasContentType = function (clipboardContent, mimeType) { + return mimeType in clipboardContent && clipboardContent[mimeType].length > 0; + }; + var hasHtmlOrText = function (content) { + return hasContentType(content, 'text/html') || hasContentType(content, 'text/plain'); + }; + var getBase64FromUri = function (uri) { + var idx; + idx = uri.indexOf(','); + if (idx !== -1) { + return uri.substr(idx + 1); + } + return null; + }; + var isValidDataUriImage = function (settings, imgElm) { + return settings.images_dataimg_filter ? settings.images_dataimg_filter(imgElm) : true; + }; + var extractFilename = function (editor, str) { + var m = str.match(/([\s\S]+?)\.(?:jpeg|jpg|png|gif)$/i); + return m ? editor.dom.encode(m[1]) : null; + }; + var uniqueId = $_4bi2o9j0jjgwecui.createIdGenerator('mceclip'); + var pasteImage = function (editor, rng, reader, blob) { + if (rng) { + editor.selection.setRng(rng); + rng = null; + } + var dataUri = reader.result; + var base64 = getBase64FromUri(dataUri); + var id = uniqueId(); + var name$$1 = editor.settings.images_reuse_filename && blob.name ? extractFilename(editor, blob.name) : id; + var img = new Image(); + img.src = dataUri; + if (isValidDataUriImage(editor.settings, img)) { + var blobCache = editor.editorUpload.blobCache; + var blobInfo = void 0, existingBlobInfo = void 0; + existingBlobInfo = blobCache.findFirst(function (cachedBlobInfo) { + return cachedBlobInfo.base64() === base64; + }); + if (!existingBlobInfo) { + blobInfo = blobCache.create(id, blob, base64, name$$1); + blobCache.add(blobInfo); + } else { + blobInfo = existingBlobInfo; + } + pasteHtml$1(editor, '', false); + } else { + pasteHtml$1(editor, '', false); + } + }; + var isClipboardEvent = function (event$$1) { + return event$$1.type === 'paste'; + }; + var pasteImageData = function (editor, e, rng) { + var dataTransfer = isClipboardEvent(e) ? e.clipboardData : e.dataTransfer; + function processItems(items) { + var i, item, reader, hadImage = false; + if (items) { + for (i = 0; i < items.length; i++) { + item = items[i]; + if (/^image\/(jpeg|png|gif|bmp)$/.test(item.type)) { + var blob = item.getAsFile ? item.getAsFile() : item; + reader = new window.FileReader(); + reader.onload = pasteImage.bind(null, editor, rng, reader, blob); + reader.readAsDataURL(blob); + e.preventDefault(); + hadImage = true; + } + } + } + return hadImage; + } + if (editor.settings.paste_data_images && dataTransfer) { + return processItems(dataTransfer.items) || processItems(dataTransfer.files); + } + }; + var isBrokenAndroidClipboardEvent = function (e) { + var clipboardData = e.clipboardData; + return navigator.userAgent.indexOf('Android') !== -1 && clipboardData && clipboardData.items && clipboardData.items.length === 0; + }; + var isKeyboardPasteEvent = function (e) { + return global$4.metaKeyPressed(e) && e.keyCode === 86 || e.shiftKey && e.keyCode === 45; + }; + var registerEventHandlers = function (editor, pasteBin, pasteFormat) { + var keyboardPasteTimeStamp = 0; + var keyboardPastePlainTextState; + editor.on('keydown', function (e) { + function removePasteBinOnKeyUp(e) { + if (isKeyboardPasteEvent(e) && !e.isDefaultPrevented()) { + pasteBin.remove(); + } + } + if (isKeyboardPasteEvent(e) && !e.isDefaultPrevented()) { + keyboardPastePlainTextState = e.shiftKey && e.keyCode === 86; + if (keyboardPastePlainTextState && global$1.webkit && navigator.userAgent.indexOf('Version/') !== -1) { + return; + } + e.stopImmediatePropagation(); + keyboardPasteTimeStamp = new Date().getTime(); + if (global$1.ie && keyboardPastePlainTextState) { + e.preventDefault(); + $_8tki3zijjjgwectj.firePaste(editor, true); + return; + } + pasteBin.remove(); + pasteBin.create(); + editor.once('keyup', removePasteBinOnKeyUp); + editor.once('paste', function () { + editor.off('keyup', removePasteBinOnKeyUp); + }); + } + }); + function insertClipboardContent(clipboardContent, isKeyBoardPaste, plainTextMode, internal) { + var content, isPlainTextHtml; + if (hasContentType(clipboardContent, 'text/html')) { + content = clipboardContent['text/html']; + } else { + content = pasteBin.getHtml(); + internal = internal ? internal : $_4x13hjirjjgwecu1.isMarked(content); + if (pasteBin.isDefaultContent(content)) { + plainTextMode = true; + } + } + content = $_4bi2o9j0jjgwecui.trimHtml(content); + pasteBin.remove(); + isPlainTextHtml = internal === false && $_4h3hnrisjjgwecu2.isPlainText(content); + if (!content.length || isPlainTextHtml) { + plainTextMode = true; + } + if (plainTextMode) { + if (hasContentType(clipboardContent, 'text/plain') && isPlainTextHtml) { + content = clipboardContent['text/plain']; + } else { + content = $_4bi2o9j0jjgwecui.innerText(content); + } + } + if (pasteBin.isDefaultContent(content)) { + if (!isKeyBoardPaste) { + editor.windowManager.alert('Please use Ctrl+V/Cmd+V keyboard shortcuts to paste contents.'); + } + return; + } + if (plainTextMode) { + pasteText(editor, content); + } else { + pasteHtml$1(editor, content, internal); + } + } + var getLastRng = function () { + return pasteBin.getLastRng() || editor.selection.getRng(); + }; + editor.on('paste', function (e) { + var clipboardTimer = new Date().getTime(); + var clipboardContent = getClipboardContent(editor, e); + var clipboardDelay = new Date().getTime() - clipboardTimer; + var isKeyBoardPaste = new Date().getTime() - keyboardPasteTimeStamp - clipboardDelay < 1000; + var plainTextMode = pasteFormat.get() === 'text' || keyboardPastePlainTextState; + var internal = hasContentType(clipboardContent, $_4x13hjirjjgwecu1.internalHtmlMime()); + keyboardPastePlainTextState = false; + if (e.isDefaultPrevented() || isBrokenAndroidClipboardEvent(e)) { + pasteBin.remove(); + return; + } + if (!hasHtmlOrText(clipboardContent) && pasteImageData(editor, e, getLastRng())) { + pasteBin.remove(); + return; + } + if (!isKeyBoardPaste) { + e.preventDefault(); + } + if (global$1.ie && (!isKeyBoardPaste || e.ieFake) && !hasContentType(clipboardContent, 'text/html')) { + pasteBin.create(); + editor.dom.bind(pasteBin.getEl(), 'paste', function (e) { + e.stopPropagation(); + }); + editor.getDoc().execCommand('Paste', false, null); + clipboardContent['text/html'] = pasteBin.getHtml(); + } + if (hasContentType(clipboardContent, 'text/html')) { + e.preventDefault(); + if (!internal) { + internal = $_4x13hjirjjgwecu1.isMarked(clipboardContent['text/html']); + } + insertClipboardContent(clipboardContent, isKeyBoardPaste, plainTextMode, internal); + } else { + global$2.setEditorTimeout(editor, function () { + insertClipboardContent(clipboardContent, isKeyBoardPaste, plainTextMode, internal); + }, 0); + } + }); + }; + var registerEventsAndFilters = function (editor, pasteBin, pasteFormat) { + registerEventHandlers(editor, pasteBin, pasteFormat); + var src; + editor.parser.addNodeFilter('img', function (nodes, name$$1, args) { + var isPasteInsert = function (args) { + return args.data && args.data.paste === true; + }; + var remove = function (node) { + if (!node.attr('data-mce-object') && src !== global$1.transparentSrc) { + node.remove(); + } + }; + var isWebKitFakeUrl = function (src) { + return src.indexOf('webkit-fake-url') === 0; + }; + var isDataUri = function (src) { + return src.indexOf('data:') === 0; + }; + if (!editor.settings.paste_data_images && isPasteInsert(args)) { + var i = nodes.length; + while (i--) { + src = nodes[i].attributes.map.src; + if (!src) { + continue; + } + if (isWebKitFakeUrl(src)) { + remove(nodes[i]); + } else if (!editor.settings.allow_html_data_urls && isDataUri(src)) { + remove(nodes[i]); + } + } + } + }); + }; - var validElements = settings.paste_word_valid_elements; - if (!validElements) { - validElements = ( - '-strong/b,-em/i,-u,-span,-p,-ol,-ul,-li,-h1,-h2,-h3,-h4,-h5,-h6,' + - '-p/div,-a[href|name],sub,sup,strike,br,del,table[width],tr,' + - 'td[colspan|rowspan|width],th[colspan|rowspan|width],thead,tfoot,tbody' - ); - } - - // Setup strict schema - var schema = new Schema({ - valid_elements: validElements, - valid_children: '-li[p]' - }); - - // Add style/class attribute to all element rules since the user might have removed them from - // paste_word_valid_elements config option and we need to check them for properties - Tools.each(schema.elements, function(rule) { - /*eslint dot-notation:0*/ - if (!rule.attributes["class"]) { - rule.attributes["class"] = {}; - rule.attributesOrder.push("class"); - } - - if (!rule.attributes.style) { - rule.attributes.style = {}; - rule.attributesOrder.push("style"); - } - }); - - // Parse HTML into DOM structure - var domParser = new DomParser({}, schema); - - // Filter styles to remove "mso" specific styles and convert some of them - domParser.addAttributeFilter('style', function(nodes) { - var i = nodes.length, node; - - while (i--) { - node = nodes[i]; - node.attr('style', filterStyles(node, node.attr('style'))); - - // Remove pointess spans - if (node.name == 'span' && node.parent && !node.attributes.length) { - node.unwrap(); - } - } - }); - - // Check the class attribute for comments or del items and remove those - domParser.addAttributeFilter('class', function(nodes) { - var i = nodes.length, node, className; - - while (i--) { - node = nodes[i]; - - className = node.attr('class'); - if (/^(MsoCommentReference|MsoCommentText|msoDel)$/i.test(className)) { - node.remove(); - } - - node.attr('class', null); - } - }); - - // Remove all del elements since we don't want the track changes code in the editor - domParser.addNodeFilter('del', function(nodes) { - var i = nodes.length; - - while (i--) { - nodes[i].remove(); - } - }); - - // Keep some of the links and anchors - domParser.addNodeFilter('a', function(nodes) { - var i = nodes.length, node, href, name; - - while (i--) { - node = nodes[i]; - href = node.attr('href'); - name = node.attr('name'); - - if (href && href.indexOf('#_msocom_') != -1) { - node.remove(); - continue; - } - - if (href && href.indexOf('file://') === 0) { - href = href.split('#')[1]; - if (href) { - href = '#' + href; - } - } + var getPasteBinParent = function (editor) { + return global$1.ie && editor.inline ? document.body : editor.getBody(); + }; + var isExternalPasteBin = function (editor) { + return getPasteBinParent(editor) !== editor.getBody(); + }; + var delegatePasteEvents = function (editor, pasteBinElm) { + if (isExternalPasteBin(editor)) { + editor.dom.bind(pasteBinElm, 'paste keyup', function (e) { + setTimeout(function () { + editor.fire('paste'); + }, 0); + }); + } + }; + var create = function (editor, lastRngCell, pasteBinDefaultContent) { + var dom = editor.dom, body = editor.getBody(); + var pasteBinElm; + lastRngCell.set(editor.selection.getRng()); + pasteBinElm = editor.dom.add(getPasteBinParent(editor), 'div', { + 'id': 'mcepastebin', + 'class': 'mce-pastebin', + 'contentEditable': true, + 'data-mce-bogus': 'all', + 'style': 'position: fixed; top: 50%; width: 10px; height: 10px; overflow: hidden; opacity: 0' + }, pasteBinDefaultContent); + if (global$1.ie || global$1.gecko) { + dom.setStyle(pasteBinElm, 'left', dom.getStyle(body, 'direction', true) === 'rtl' ? 65535 : -65535); + } + dom.bind(pasteBinElm, 'beforedeactivate focusin focusout', function (e) { + e.stopPropagation(); + }); + delegatePasteEvents(editor, pasteBinElm); + pasteBinElm.focus(); + editor.selection.select(pasteBinElm, true); + }; + var remove = function (editor, lastRngCell) { + if (getEl(editor)) { + var pasteBinClone = void 0; + var lastRng = lastRngCell.get(); + while (pasteBinClone = editor.dom.get('mcepastebin')) { + editor.dom.remove(pasteBinClone); + editor.dom.unbind(pasteBinClone); + } + if (lastRng) { + editor.selection.setRng(lastRng); + } + } + lastRngCell.set(null); + }; + var getEl = function (editor) { + return editor.dom.get('mcepastebin'); + }; + var getHtml = function (editor) { + var pasteBinElm, pasteBinClones, i, dirtyWrappers, cleanWrapper; + var copyAndRemove = function (toElm, fromElm) { + toElm.appendChild(fromElm); + editor.dom.remove(fromElm, true); + }; + pasteBinClones = global$3.grep(getPasteBinParent(editor).childNodes, function (elm) { + return elm.id === 'mcepastebin'; + }); + pasteBinElm = pasteBinClones.shift(); + global$3.each(pasteBinClones, function (pasteBinClone) { + copyAndRemove(pasteBinElm, pasteBinClone); + }); + dirtyWrappers = editor.dom.select('div[id=mcepastebin]', pasteBinElm); + for (i = dirtyWrappers.length - 1; i >= 0; i--) { + cleanWrapper = editor.dom.create('div'); + pasteBinElm.insertBefore(cleanWrapper, dirtyWrappers[i]); + copyAndRemove(cleanWrapper, dirtyWrappers[i]); + } + return pasteBinElm ? pasteBinElm.innerHTML : ''; + }; + var getLastRng = function (lastRng) { + return lastRng.get(); + }; + var isDefaultContent = function (pasteBinDefaultContent, content) { + return content === pasteBinDefaultContent; + }; + var isPasteBin = function (elm) { + return elm && elm.id === 'mcepastebin'; + }; + var isDefault = function (editor, pasteBinDefaultContent) { + var pasteBinElm = getEl(editor); + return isPasteBin(pasteBinElm) && isDefaultContent(pasteBinDefaultContent, pasteBinElm.innerHTML); + }; + var PasteBin = function (editor) { + var lastRng = Cell(null); + var pasteBinDefaultContent = '%MCEPASTEBIN%'; + return { + create: function () { + return create(editor, lastRng, pasteBinDefaultContent); + }, + remove: function () { + return remove(editor, lastRng); + }, + getEl: function () { + return getEl(editor); + }, + getHtml: function () { + return getHtml(editor); + }, + getLastRng: function () { + return getLastRng(lastRng); + }, + isDefault: function () { + return isDefault(editor, pasteBinDefaultContent); + }, + isDefaultContent: function (content) { + return isDefaultContent(pasteBinDefaultContent, content); + } + }; + }; - if (!href && !name) { - node.unwrap(); - } else { - // Remove all named anchors that aren't specific to TOC, Footnotes or Endnotes - if (name && !/^_?(?:toc|edn|ftn)/i.test(name)) { - node.unwrap(); - continue; - } - - node.attr({ - href: href, - name: name - }); - } - } - }); - - // Parse into DOM structure - var rootNode = domParser.parse(content); - - // Process DOM - if (settings.paste_convert_word_fake_lists !== false) { - convertFakeListsToProperLists(rootNode); - } - - // Serialize DOM back to HTML - e.content = new Serializer({}, schema).serialize(rootNode); - } - }); - } - - WordFilter.isWordContent = isWordContent; - - return WordFilter; -}); - -// Included from: js/tinymce/plugins/paste/classes/Quirks.js - -/** - * Quirks.js - * - * Copyright, Moxiecode Systems AB - * Released under LGPL License. - * - * License: http://www.tinymce.com/license - * Contributing: http://www.tinymce.com/contributing - */ + var Clipboard = function (editor, pasteFormat) { + var pasteBin = PasteBin(editor); + editor.on('preInit', function () { + return registerEventsAndFilters(editor, pasteBin, pasteFormat); + }); + return { + pasteFormat: pasteFormat, + pasteHtml: function (html, internalFlag) { + return pasteHtml$1(editor, html, internalFlag); + }, + pasteText: function (text) { + return pasteText(editor, text); + }, + pasteImageData: function (e, rng) { + return pasteImageData(editor, e, rng); + }, + getDataTransferItems: getDataTransferItems, + hasHtmlOrText: hasHtmlOrText, + hasContentType: hasContentType + }; + }; -/** - * This class contains various fixes for browsers. These issues can not be feature - * detected since we have no direct control over the clipboard. However we might be able - * to remove some of these fixes once the browsers gets updated/fixed. - * - * @class tinymce.pasteplugin.Quirks - * @private - */ -define("tinymce/pasteplugin/Quirks", [ - "tinymce/Env", - "tinymce/util/Tools", - "tinymce/pasteplugin/WordFilter", - "tinymce/pasteplugin/Utils" -], function(Env, Tools, WordFilter, Utils) { - "use strict"; - - return function(editor) { - function addPreProcessFilter(filterFunc) { - editor.on('BeforePastePreProcess', function(e) { - e.content = filterFunc(e.content); - }); - } + var noop = function () { + }; + var hasWorkingClipboardApi = function (clipboardData) { + return global$1.iOS === false && clipboardData !== undefined && typeof clipboardData.setData === 'function' && $_4bi2o9j0jjgwecui.isMsEdge() !== true; + }; + var setHtml5Clipboard = function (clipboardData, html, text) { + if (hasWorkingClipboardApi(clipboardData)) { + try { + clipboardData.clearData(); + clipboardData.setData('text/html', html); + clipboardData.setData('text/plain', text); + clipboardData.setData($_4x13hjirjjgwecu1.internalHtmlMime(), html); + return true; + } catch (e) { + return false; + } + } else { + return false; + } + }; + var setClipboardData = function (evt, data, fallback, done) { + if (setHtml5Clipboard(evt.clipboardData, data.html, data.text)) { + evt.preventDefault(); + done(); + } else { + fallback(data.html, done); + } + }; + var fallback = function (editor) { + return function (html, done) { + var markedHtml = $_4x13hjirjjgwecu1.mark(html); + var outer = editor.dom.create('div', { + 'contenteditable': 'false', + 'data-mce-bogus': 'all' + }); + var inner = editor.dom.create('div', { contenteditable: 'true' }, markedHtml); + editor.dom.setStyles(outer, { + position: 'fixed', + top: '0', + left: '-3000px', + width: '1000px', + overflow: 'hidden' + }); + outer.appendChild(inner); + editor.dom.add(editor.getBody(), outer); + var range = editor.selection.getRng(); + inner.focus(); + var offscreenRange = editor.dom.createRng(); + offscreenRange.selectNodeContents(inner); + editor.selection.setRng(offscreenRange); + setTimeout(function () { + editor.selection.setRng(range); + outer.parentNode.removeChild(outer); + done(); + }, 0); + }; + }; + var getData = function (editor) { + return { + html: editor.selection.getContent({ contextual: true }), + text: editor.selection.getContent({ format: 'text' }) + }; + }; + var cut = function (editor) { + return function (evt) { + if (editor.selection.isCollapsed() === false) { + setClipboardData(evt, getData(editor), fallback(editor), function () { + setTimeout(function () { + editor.execCommand('Delete'); + }, 0); + }); + } + }; + }; + var copy = function (editor) { + return function (evt) { + if (editor.selection.isCollapsed() === false) { + setClipboardData(evt, getData(editor), fallback(editor), noop); + } + }; + }; + var register$1 = function (editor) { + editor.on('cut', cut(editor)); + editor.on('copy', copy(editor)); + }; + var $_32blojj3jjgwecv4 = { register: register$1 }; - /** - * Removes BR elements after block elements. IE9 has a nasty bug where it puts a BR element after each - * block element when pasting from word. This removes those elements. - * - * This: - *

a


b

- * - * Becomes: - *

a

b

- */ - function removeExplorerBrElementsAfterBlocks(html) { - // Only filter word specific content - if (!WordFilter.isWordContent(html)) { - return html; - } - - // Produce block regexp based on the block elements in schema - var blockElements = []; - - Tools.each(editor.schema.getBlockElements(), function(block, blockName) { - blockElements.push(blockName); - }); - - var explorerBlocksRegExp = new RegExp( - '(?:
 [\\s\\r\\n]+|
)*(<\\/?(' + blockElements.join('|') + ')[^>]*>)(?:
 [\\s\\r\\n]+|
)*', - 'g' - ); - - // Remove BR:s from: X
- html = Utils.filter(html, [ - [explorerBlocksRegExp, '$1'] - ]); + var global$10 = tinymce.util.Tools.resolve('tinymce.dom.RangeUtils'); - // IE9 also adds an extra BR element for each soft-linefeed and it also adds a BR for each word wrap break - html = Utils.filter(html, [ - [/

/g, '

'], // Replace multiple BR elements with uppercase BR to keep them intact - [/
/g, ' '], // Replace single br elements with space since they are word wrap BR:s - [/

/g, '
'] // Replace back the double brs but into a single BR - ]); - - return html; - } - - /** - * WebKit has a nasty bug where the all computed styles gets added to style attributes when copy/pasting contents. - * This fix solves that by simply removing the whole style attribute. - * - * The paste_webkit_styles option can be set to specify what to keep: - * paste_webkit_styles: "none" // Keep no styles - * paste_webkit_styles: "all", // Keep all of them - * paste_webkit_styles: "font-weight color" // Keep specific ones - * - * @param {String} content Content that needs to be processed. - * @return {String} Processed contents. - */ - function removeWebKitStyles(content) { - // Passthrough all styles from Word and let the WordFilter handle that junk - if (WordFilter.isWordContent(content)) { - return content; - } - - // Filter away styles that isn't matching the target node - var webKitStyles = editor.settings.paste_webkit_styles; - - if (editor.settings.paste_remove_styles_if_webkit === false || webKitStyles == "all") { - return content; - } - - if (webKitStyles) { - webKitStyles = webKitStyles.split(/[, ]/); - } - - // Keep specific styles that doesn't match the current node computed style - if (webKitStyles) { - var dom = editor.dom, node = editor.selection.getNode(); - - content = content.replace(/(<[^>]+) style="([^"]*)"([^>]*>)/gi, function(all, before, value, after) { - var inputStyles = dom.parseStyle(value, 'span'), outputStyles = {}; + var getCaretRangeFromEvent = function (editor, e) { + return global$10.getCaretRangeFromPoint(e.clientX, e.clientY, editor.getDoc()); + }; + var isPlainTextFileUrl = function (content) { + var plainTextContent = content['text/plain']; + return plainTextContent ? plainTextContent.indexOf('file://') === 0 : false; + }; + var setFocusedRange = function (editor, rng) { + editor.focus(); + editor.selection.setRng(rng); + }; + var setup = function (editor, clipboard, draggingInternallyState) { + if ($_xr8b0ikjjgwectl.shouldBlockDrop(editor)) { + editor.on('dragend dragover draggesture dragdrop drop drag', function (e) { + e.preventDefault(); + e.stopPropagation(); + }); + } + if (!$_xr8b0ikjjgwectl.shouldPasteDataImages(editor)) { + editor.on('drop', function (e) { + var dataTransfer = e.dataTransfer; + if (dataTransfer && dataTransfer.files && dataTransfer.files.length > 0) { + e.preventDefault(); + } + }); + } + editor.on('drop', function (e) { + var dropContent, rng; + rng = getCaretRangeFromEvent(editor, e); + if (e.isDefaultPrevented() || draggingInternallyState.get()) { + return; + } + dropContent = clipboard.getDataTransferItems(e.dataTransfer); + var internal = clipboard.hasContentType(dropContent, $_4x13hjirjjgwecu1.internalHtmlMime()); + if ((!clipboard.hasHtmlOrText(dropContent) || isPlainTextFileUrl(dropContent)) && clipboard.pasteImageData(e, rng)) { + return; + } + if (rng && $_xr8b0ikjjgwectl.shouldFilterDrop(editor)) { + var content_1 = dropContent['mce-internal'] || dropContent['text/html'] || dropContent['text/plain']; + if (content_1) { + e.preventDefault(); + global$2.setEditorTimeout(editor, function () { + editor.undoManager.transact(function () { + if (dropContent['mce-internal']) { + editor.execCommand('Delete'); + } + setFocusedRange(editor, rng); + content_1 = $_4bi2o9j0jjgwecui.trimHtml(content_1); + if (!dropContent['text/html']) { + clipboard.pasteText(content_1); + } else { + clipboard.pasteHtml(content_1, internal); + } + }); + }); + } + } + }); + editor.on('dragstart', function (e) { + draggingInternallyState.set(true); + }); + editor.on('dragover dragend', function (e) { + if ($_xr8b0ikjjgwectl.shouldPasteDataImages(editor) && draggingInternallyState.get() === false) { + e.preventDefault(); + setFocusedRange(editor, getCaretRangeFromEvent(editor, e)); + } + if (e.type === 'dragend') { + draggingInternallyState.set(false); + } + }); + }; + var $_b4etj0j4jjgwecv7 = { setup: setup }; - if (webKitStyles === "none") { - return before + after; - } - - for (var i = 0; i < webKitStyles.length; i++) { - var inputValue = inputStyles[webKitStyles[i]], currentValue = dom.getStyle(node, webKitStyles[i], true); - - if (/color/.test(webKitStyles[i])) { - inputValue = dom.toHex(inputValue); - currentValue = dom.toHex(currentValue); - } - - if (currentValue != inputValue) { - outputStyles[webKitStyles[i]] = inputValue; - } - } - - outputStyles = dom.serializeStyle(outputStyles, 'span'); - if (outputStyles) { - return before + ' style="' + outputStyles + '"' + after; - } - - return before + after; - }); - } else { - // Remove all external styles - content = content.replace(/(<[^>]+) style="([^"]*)"([^>]*>)/gi, '$1$3'); - } - - // Keep internal styles - content = content.replace(/(<[^>]+) data-mce-style="([^"]+)"([^>]*>)/gi, function(all, before, value, after) { - return before + ' style="' + value + '"' + after; - }); - - return content; - } - - // Sniff browsers and apply fixes since we can't feature detect - if (Env.webkit) { - addPreProcessFilter(removeWebKitStyles); - } - - if (Env.ie) { - addPreProcessFilter(removeExplorerBrElementsAfterBlocks); - } - }; -}); - -// Included from: js/tinymce/plugins/paste/classes/Plugin.js + var setup$1 = function (editor) { + var plugin = editor.plugins.paste; + var preProcess = $_xr8b0ikjjgwectl.getPreProcess(editor); + if (preProcess) { + editor.on('PastePreProcess', function (e) { + preProcess.call(plugin, plugin, e); + }); + } + var postProcess = $_xr8b0ikjjgwectl.getPostProcess(editor); + if (postProcess) { + editor.on('PastePostProcess', function (e) { + postProcess.call(plugin, plugin, e); + }); + } + }; + var $_c5bihmj6jjgwecva = { setup: setup$1 }; -/** - * Plugin.js - * - * Copyright, Moxiecode Systems AB - * Released under LGPL License. - * - * License: http://www.tinymce.com/license - * Contributing: http://www.tinymce.com/contributing - */ - -/** - * This class contains the tinymce plugin logic for the paste plugin. - * - * @class tinymce.pasteplugin.Plugin - * @private - */ -define("tinymce/pasteplugin/Plugin", [ - "tinymce/PluginManager", - "tinymce/pasteplugin/Clipboard", - "tinymce/pasteplugin/WordFilter", - "tinymce/pasteplugin/Quirks" -], function(PluginManager, Clipboard, WordFilter, Quirks) { - var userIsInformed; - - PluginManager.add('paste', function(editor) { - var self = this, clipboard, settings = editor.settings; - - function togglePlainTextPaste() { - if (clipboard.pasteFormat == "text") { - this.active(false); - clipboard.pasteFormat = "html"; - } else { - clipboard.pasteFormat = "text"; - this.active(true); - - if (!userIsInformed) { - editor.windowManager.alert( - 'Paste is now in plain text mode. Contents will now ' + - 'be pasted as plain text until you toggle this option off.' - ); - - userIsInformed = true; - } - } - } - - self.clipboard = clipboard = new Clipboard(editor); - self.quirks = new Quirks(editor); - self.wordFilter = new WordFilter(editor); - - if (editor.settings.paste_as_text) { - self.clipboard.pasteFormat = "text"; - } + function addPreProcessFilter(editor, filterFunc) { + editor.on('PastePreProcess', function (e) { + e.content = filterFunc(editor, e.content, e.internal, e.wordContent); + }); + } + function addPostProcessFilter(editor, filterFunc) { + editor.on('PastePostProcess', function (e) { + filterFunc(editor, e.node); + }); + } + function removeExplorerBrElementsAfterBlocks(editor, html) { + if (!$_dfatuiivjjgwecu8.isWordContent(html)) { + return html; + } + var blockElements = []; + global$3.each(editor.schema.getBlockElements(), function (block, blockName) { + blockElements.push(blockName); + }); + var explorerBlocksRegExp = new RegExp('(?:
 [\\s\\r\\n]+|
)*(<\\/?(' + blockElements.join('|') + ')[^>]*>)(?:
 [\\s\\r\\n]+|
)*', 'g'); + html = $_4bi2o9j0jjgwecui.filter(html, [[ + explorerBlocksRegExp, + '$1' + ]]); + html = $_4bi2o9j0jjgwecui.filter(html, [ + [ + /

/g, + '

' + ], + [ + /
/g, + ' ' + ], + [ + /

/g, + '
' + ] + ]); + return html; + } + function removeWebKitStyles(editor, content, internal, isWordHtml) { + if (isWordHtml || internal) { + return content; + } + var webKitStylesSetting = $_xr8b0ikjjgwectl.getWebkitStyles(editor); + var webKitStyles; + if ($_xr8b0ikjjgwectl.shouldRemoveWebKitStyles(editor) === false || webKitStylesSetting === 'all') { + return content; + } + if (webKitStylesSetting) { + webKitStyles = webKitStylesSetting.split(/[, ]/); + } + if (webKitStyles) { + var dom_1 = editor.dom, node_1 = editor.selection.getNode(); + content = content.replace(/(<[^>]+) style="([^"]*)"([^>]*>)/gi, function (all, before, value, after) { + var inputStyles = dom_1.parseStyle(dom_1.decode(value)); + var outputStyles = {}; + if (webKitStyles === 'none') { + return before + after; + } + for (var i = 0; i < webKitStyles.length; i++) { + var inputValue = inputStyles[webKitStyles[i]], currentValue = dom_1.getStyle(node_1, webKitStyles[i], true); + if (/color/.test(webKitStyles[i])) { + inputValue = dom_1.toHex(inputValue); + currentValue = dom_1.toHex(currentValue); + } + if (currentValue !== inputValue) { + outputStyles[webKitStyles[i]] = inputValue; + } + } + outputStyles = dom_1.serializeStyle(outputStyles, 'span'); + if (outputStyles) { + return before + ' style="' + outputStyles + '"' + after; + } + return before + after; + }); + } else { + content = content.replace(/(<[^>]+) style="([^"]*)"([^>]*>)/gi, '$1$3'); + } + content = content.replace(/(<[^>]+) data-mce-style="([^"]+)"([^>]*>)/gi, function (all, before, value, after) { + return before + ' style="' + value + '"' + after; + }); + return content; + } + function removeUnderlineAndFontInAnchor(editor, root) { + editor.$('a', root).find('font,u').each(function (i, node) { + editor.dom.remove(node, true); + }); + } + var setup$2 = function (editor) { + if (global$1.webkit) { + addPreProcessFilter(editor, removeWebKitStyles); + } + if (global$1.ie) { + addPreProcessFilter(editor, removeExplorerBrElementsAfterBlocks); + addPostProcessFilter(editor, removeUnderlineAndFontInAnchor); + } + }; + var $_36tmgyj7jjgwecvc = { setup: setup$2 }; - if (settings.paste_preprocess) { - editor.on('PastePreProcess', function(e) { - settings.paste_preprocess.call(self, self, e); - }); - } - - if (settings.paste_postprocess) { - editor.on('PastePostProcess', function(e) { - settings.paste_postprocess.call(self, self, e); - }); - } - - editor.addCommand('mceInsertClipboardContent', function(ui, value) { - if (value.content) { - self.clipboard.pasteHtml(value.content); - } - - if (value.text) { - self.clipboard.pasteText(value.text); - } - }); - - // Block all drag/drop events - if (editor.paste_block_drop) { - editor.on('dragend dragover draggesture dragdrop drop drag', function(e) { - e.preventDefault(); - e.stopPropagation(); - }); - } + var curry = function (f) { + var x = []; + for (var _i = 1; _i < arguments.length; _i++) { + x[_i - 1] = arguments[_i]; + } + var args = new Array(arguments.length - 1); + for (var i = 1; i < arguments.length; i++) + args[i - 1] = arguments[i]; + return function () { + var x = []; + for (var _i = 0; _i < arguments.length; _i++) { + x[_i] = arguments[_i]; + } + var newArgs = new Array(arguments.length); + for (var j = 0; j < newArgs.length; j++) + newArgs[j] = arguments[j]; + var all = args.concat(newArgs); + return f.apply(null, all); + }; + }; - // Prevent users from dropping data images on Gecko - if (!editor.settings.paste_data_images) { - editor.on('drop', function(e) { - var dataTransfer = e.dataTransfer; - - if (dataTransfer && dataTransfer.files && dataTransfer.files.length > 0) { - e.preventDefault(); - } - }); - } + var stateChange = function (editor, clipboard, e) { + var ctrl = e.control; + ctrl.active(clipboard.pasteFormat.get() === 'text'); + editor.on('PastePlainTextToggle', function (e) { + ctrl.active(e.state); + }); + }; + var register$2 = function (editor, clipboard) { + var postRender = curry(stateChange, editor, clipboard); + editor.addButton('pastetext', { + active: false, + icon: 'pastetext', + tooltip: 'Paste as text', + cmd: 'mceTogglePlainTextPaste', + onPostRender: postRender + }); + editor.addMenuItem('pastetext', { + text: 'Paste as text', + selectable: true, + active: clipboard.pasteFormat, + cmd: 'mceTogglePlainTextPaste', + onPostRender: postRender + }); + }; + var $_g9yhwdj8jjgwecvf = { register: register$2 }; - editor.addButton('pastetext', { - icon: 'pastetext', - tooltip: 'Paste as text', - onclick: togglePlainTextPaste, - active: self.clipboard.pasteFormat == "text" - }); + global.add('paste', function (editor) { + if ($_15bf6siejjgwect1.hasProPlugin(editor) === false) { + var userIsInformedState = Cell(false); + var draggingInternallyState = Cell(false); + var pasteFormat = Cell($_xr8b0ikjjgwectl.isPasteAsTextEnabled(editor) ? 'text' : 'html'); + var clipboard = Clipboard(editor, pasteFormat); + var quirks = $_36tmgyj7jjgwecvc.setup(editor); + $_g9yhwdj8jjgwecvf.register(editor, clipboard); + $_fldd1mihjjgwecth.register(editor, clipboard, userIsInformedState); + $_c5bihmj6jjgwecva.setup(editor); + $_32blojj3jjgwecv4.register(editor); + $_b4etj0j4jjgwecv7.setup(editor, clipboard, draggingInternallyState); + return $_6gtliyigjjgwecte.get(clipboard, quirks); + } + }); + function Plugin () { + } - editor.addMenuItem('pastetext', { - text: 'Paste as text', - selectable: true, - active: clipboard.pasteFormat, - onclick: togglePlainTextPaste - }); - }); -}); + return Plugin; -expose(["tinymce/pasteplugin/Utils"]); -})(this); \ No newline at end of file +}()); +})();