wp/wp-includes/js/tinymce/plugins/paste/plugin.js
changeset 7 cf61fcea0001
parent 5 5e2f62d02dcd
child 9 177826044cd9
equal deleted inserted replaced
6:490d5cc509ed 7:cf61fcea0001
     1 /**
     1 (function () {
     2  * Compiled inline version. (Library mode)
     2 var paste = (function () {
     3  */
     3   'use strict';
     4 
     4 
     5 /*jshint smarttabs:true, undef:true, latedef:true, curly:true, bitwise:true, camelcase:true */
     5   var Cell = function (initial) {
     6 /*globals $code */
     6     var value = initial;
     7 
     7     var get = function () {
     8 (function(exports, undefined) {
     8       return value;
     9 	"use strict";
     9     };
    10 
    10     var set = function (v) {
    11 	var modules = {};
    11       value = v;
    12 
    12     };
    13 	function require(ids, callback) {
    13     var clone = function () {
    14 		var module, defs = [];
    14       return Cell(get());
    15 
    15     };
    16 		for (var i = 0; i < ids.length; ++i) {
    16     return {
    17 			module = modules[ids[i]] || resolve(ids[i]);
    17       get: get,
    18 			if (!module) {
    18       set: set,
    19 				throw 'module definition dependecy not found: ' + ids[i];
    19       clone: clone
    20 			}
    20     };
    21 
    21   };
    22 			defs.push(module);
    22 
    23 		}
    23   var global = tinymce.util.Tools.resolve('tinymce.PluginManager');
    24 
    24 
    25 		callback.apply(null, defs);
    25   var hasProPlugin = function (editor) {
    26 	}
    26     if (/(^|[ ,])powerpaste([, ]|$)/.test(editor.settings.plugins) && global.get('powerpaste')) {
    27 
    27       if (typeof window.console !== 'undefined' && window.console.log) {
    28 	function define(id, dependencies, definition) {
    28         window.console.log('PowerPaste is incompatible with Paste plugin! Remove \'paste\' from the \'plugins\' option.');
    29 		if (typeof id !== 'string') {
    29       }
    30 			throw 'invalid module definition, module id must be defined and be a string';
    30       return true;
    31 		}
    31     } else {
    32 
    32       return false;
    33 		if (dependencies === undefined) {
    33     }
    34 			throw 'invalid module definition, dependencies must be specified';
    34   };
    35 		}
    35   var $_15bf6siejjgwect1 = { hasProPlugin: hasProPlugin };
    36 
    36 
    37 		if (definition === undefined) {
    37   var get = function (clipboard, quirks) {
    38 			throw 'invalid module definition, definition function must be specified';
    38     return {
    39 		}
    39       clipboard: clipboard,
    40 
    40       quirks: quirks
    41 		require(dependencies, function() {
    41     };
    42 			modules[id] = definition.apply(null, arguments);
    42   };
    43 		});
    43   var $_6gtliyigjjgwecte = { get: get };
    44 	}
    44 
    45 
    45   var firePastePreProcess = function (editor, html, internal, isWordHtml) {
    46 	function defined(id) {
    46     return editor.fire('PastePreProcess', {
    47 		return !!modules[id];
    47       content: html,
    48 	}
    48       internal: internal,
    49 
    49       wordContent: isWordHtml
    50 	function resolve(id) {
    50     });
    51 		var target = exports;
    51   };
    52 		var fragments = id.split(/[.\/]/);
    52   var firePastePostProcess = function (editor, node, internal, isWordHtml) {
    53 
    53     return editor.fire('PastePostProcess', {
    54 		for (var fi = 0; fi < fragments.length; ++fi) {
    54       node: node,
    55 			if (!target[fragments[fi]]) {
    55       internal: internal,
    56 				return;
    56       wordContent: isWordHtml
    57 			}
    57     });
    58 
    58   };
    59 			target = target[fragments[fi]];
    59   var firePastePlainTextToggle = function (editor, state) {
    60 		}
    60     return editor.fire('PastePlainTextToggle', { state: state });
    61 
    61   };
    62 		return target;
    62   var firePaste = function (editor, ieFake) {
    63 	}
    63     return editor.fire('paste', { ieFake: ieFake });
    64 
    64   };
    65 	function expose(ids) {
    65   var $_8tki3zijjjgwectj = {
    66 		for (var i = 0; i < ids.length; i++) {
    66     firePastePreProcess: firePastePreProcess,
    67 			var target = exports;
    67     firePastePostProcess: firePastePostProcess,
    68 			var id = ids[i];
    68     firePastePlainTextToggle: firePastePlainTextToggle,
    69 			var fragments = id.split(/[.\/]/);
    69     firePaste: firePaste
    70 
    70   };
    71 			for (var fi = 0; fi < fragments.length - 1; ++fi) {
    71 
    72 				if (target[fragments[fi]] === undefined) {
    72   var shouldPlainTextInform = function (editor) {
    73 					target[fragments[fi]] = {};
    73     return editor.getParam('paste_plaintext_inform', true);
    74 				}
    74   };
    75 
    75   var shouldBlockDrop = function (editor) {
    76 				target = target[fragments[fi]];
    76     return editor.getParam('paste_block_drop', false);
    77 			}
    77   };
    78 
    78   var shouldPasteDataImages = function (editor) {
    79 			target[fragments[fragments.length - 1]] = modules[id];
    79     return editor.getParam('paste_data_images', false);
    80 		}
    80   };
    81 	}
    81   var shouldFilterDrop = function (editor) {
    82 
    82     return editor.getParam('paste_filter_drop', true);
    83 // Included from: js/tinymce/plugins/paste/classes/Utils.js
    83   };
    84 
    84   var getPreProcess = function (editor) {
    85 /**
    85     return editor.getParam('paste_preprocess');
    86  * Utils.js
    86   };
    87  *
    87   var getPostProcess = function (editor) {
    88  * Copyright, Moxiecode Systems AB
    88     return editor.getParam('paste_postprocess');
    89  * Released under LGPL License.
    89   };
    90  *
    90   var getWebkitStyles = function (editor) {
    91  * License: http://www.tinymce.com/license
    91     return editor.getParam('paste_webkit_styles');
    92  * Contributing: http://www.tinymce.com/contributing
    92   };
    93  */
    93   var shouldRemoveWebKitStyles = function (editor) {
    94 
    94     return editor.getParam('paste_remove_styles_if_webkit', true);
    95 /**
    95   };
    96  * This class contails various utility functions for the paste plugin.
    96   var shouldMergeFormats = function (editor) {
    97  *
    97     return editor.getParam('paste_merge_formats', true);
    98  * @class tinymce.pasteplugin.Utils
    98   };
    99  */
    99   var isSmartPasteEnabled = function (editor) {
   100 define("tinymce/pasteplugin/Utils", [
   100     return editor.getParam('smart_paste', true);
   101 	"tinymce/util/Tools",
   101   };
   102 	"tinymce/html/DomParser",
   102   var isPasteAsTextEnabled = function (editor) {
   103 	"tinymce/html/Schema"
   103     return editor.getParam('paste_as_text', false);
   104 ], function(Tools, DomParser, Schema) {
   104   };
   105 	function filter(content, items) {
   105   var getRetainStyleProps = function (editor) {
   106 		Tools.each(items, function(v) {
   106     return editor.getParam('paste_retain_style_properties');
   107 			if (v.constructor == RegExp) {
   107   };
   108 				content = content.replace(v, '');
   108   var getWordValidElements = function (editor) {
   109 			} else {
   109     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';
   110 				content = content.replace(v[0], v[1]);
   110     return editor.getParam('paste_word_valid_elements', defaultValidElements);
   111 			}
   111   };
   112 		});
   112   var shouldConvertWordFakeLists = function (editor) {
   113 
   113     return editor.getParam('paste_convert_word_fake_lists', true);
   114 		return content;
   114   };
   115 	}
   115   var shouldUseDefaultFilters = function (editor) {
   116 
   116     return editor.getParam('paste_enable_default_filters', true);
   117 	/**
   117   };
   118 	 * Gets the innerText of the specified element. It will handle edge cases
   118   var $_xr8b0ikjjgwectl = {
   119 	 * and works better than textContent on Gecko.
   119     shouldPlainTextInform: shouldPlainTextInform,
   120 	 *
   120     shouldBlockDrop: shouldBlockDrop,
   121 	 * @param {String} html HTML string to get text from.
   121     shouldPasteDataImages: shouldPasteDataImages,
   122 	 * @return {String} String of text with line feeds.
   122     shouldFilterDrop: shouldFilterDrop,
   123 	 */
   123     getPreProcess: getPreProcess,
   124 	function innerText(html) {
   124     getPostProcess: getPostProcess,
   125 		var schema = new Schema(), domParser = new DomParser({}, schema), text = '';
   125     getWebkitStyles: getWebkitStyles,
   126 		var shortEndedElements = schema.getShortEndedElements();
   126     shouldRemoveWebKitStyles: shouldRemoveWebKitStyles,
   127 		var ignoreElements = Tools.makeMap('script noscript style textarea video audio iframe object', ' ');
   127     shouldMergeFormats: shouldMergeFormats,
   128 		var blockElements = schema.getBlockElements();
   128     isSmartPasteEnabled: isSmartPasteEnabled,
   129 
   129     isPasteAsTextEnabled: isPasteAsTextEnabled,
   130 		function walk(node) {
   130     getRetainStyleProps: getRetainStyleProps,
   131 			var name = node.name, currentNode = node;
   131     getWordValidElements: getWordValidElements,
   132 
   132     shouldConvertWordFakeLists: shouldConvertWordFakeLists,
   133 			if (name === 'br') {
   133     shouldUseDefaultFilters: shouldUseDefaultFilters
   134 				text += '\n';
   134   };
   135 				return;
   135 
   136 			}
   136   var shouldInformUserAboutPlainText = function (editor, userIsInformedState) {
   137 
   137     return userIsInformedState.get() === false && $_xr8b0ikjjgwectl.shouldPlainTextInform(editor);
   138 			// img/input/hr
   138   };
   139 			if (shortEndedElements[name]) {
   139   var displayNotification = function (editor, message) {
   140 				text += ' ';
   140     editor.notificationManager.open({
   141 			}
   141       text: editor.translate(message),
   142 
   142       type: 'info'
   143 			// Ingore script, video contents
   143     });
   144 			if (ignoreElements[name]) {
   144   };
   145 				text += ' ';
   145   var togglePlainTextPaste = function (editor, clipboard, userIsInformedState) {
   146 				return;
   146     if (clipboard.pasteFormat.get() === 'text') {
   147 			}
   147       clipboard.pasteFormat.set('html');
   148 
   148       $_8tki3zijjjgwectj.firePastePlainTextToggle(editor, false);
   149 			if (node.type == 3) {
   149     } else {
   150 				text += node.value;
   150       clipboard.pasteFormat.set('text');
   151 			}
   151       $_8tki3zijjjgwectj.firePastePlainTextToggle(editor, true);
   152 
   152       if (shouldInformUserAboutPlainText(editor, userIsInformedState)) {
   153 			// Walk all children
   153         displayNotification(editor, 'Paste is now in plain text mode. Contents will now be pasted as plain text until you toggle this option off.');
   154 			if (!node.shortEnded) {
   154         userIsInformedState.set(true);
   155 				if ((node = node.firstChild)) {
   155       }
   156 					do {
   156     }
   157 						walk(node);
   157     editor.focus();
   158 					} while ((node = node.next));
   158   };
   159 				}
   159   var $_2j7vw7iijjgwecti = { togglePlainTextPaste: togglePlainTextPaste };
   160 			}
   160 
   161 
   161   var register = function (editor, clipboard, userIsInformedState) {
   162 			// Add \n or \n\n for blocks or P
   162     editor.addCommand('mceTogglePlainTextPaste', function () {
   163 			if (blockElements[name] && currentNode.next) {
   163       $_2j7vw7iijjgwecti.togglePlainTextPaste(editor, clipboard, userIsInformedState);
   164 				text += '\n';
   164     });
   165 
   165     editor.addCommand('mceInsertClipboardContent', function (ui, value) {
   166 				if (name == 'p') {
   166       if (value.content) {
   167 					text += '\n';
   167         clipboard.pasteHtml(value.content, value.internal);
   168 				}
   168       }
   169 			}
   169       if (value.text) {
   170 		}
   170         clipboard.pasteText(value.text);
   171 
   171       }
   172 		html = filter(html, [
   172     });
   173 			/<!\[[^\]]+\]>/g // Conditional comments
   173   };
   174 		]);
   174   var $_fldd1mihjjgwecth = { register: register };
   175 
   175 
   176 		walk(domParser.parse(html));
   176   var global$1 = tinymce.util.Tools.resolve('tinymce.Env');
   177 
   177 
   178 		return text;
   178   var global$2 = tinymce.util.Tools.resolve('tinymce.util.Delay');
   179 	}
   179 
   180 
   180   var global$3 = tinymce.util.Tools.resolve('tinymce.util.Tools');
   181 	/**
   181 
   182 	 * Trims the specified HTML by removing all WebKit fragments, all elements wrapping the body trailing BR elements etc.
   182   var global$4 = tinymce.util.Tools.resolve('tinymce.util.VK');
   183 	 *
   183 
   184 	 * @param {String} html Html string to trim contents on.
   184   var internalMimeType = 'x-tinymce/html';
   185 	 * @return {String} Html contents that got trimmed.
   185   var internalMark = '<!-- ' + internalMimeType + ' -->';
   186 	 */
   186   var mark = function (html) {
   187 	function trimHtml(html) {
   187     return internalMark + html;
   188 		function trimSpaces(all, s1, s2) {
   188   };
   189 			// WebKit &nbsp; meant to preserve multiple spaces but instead inserted around all inline tags,
   189   var unmark = function (html) {
   190 			// including the spans with inline styles created on paste
   190     return html.replace(internalMark, '');
   191 			if (!s1 && !s2) {
   191   };
   192 				return ' ';
   192   var isMarked = function (html) {
   193 			}
   193     return html.indexOf(internalMark) !== -1;
   194 
   194   };
   195 			return '\u00a0';
   195   var $_4x13hjirjjgwecu1 = {
   196 		}
   196     mark: mark,
   197 
   197     unmark: unmark,
   198 		html = filter(html, [
   198     isMarked: isMarked,
   199 			/^[\s\S]*<body[^>]*>\s*|\s*<\/body[^>]*>[\s\S]*$/g, // Remove anything but the contents within the BODY element
   199     internalHtmlMime: function () {
   200 			/<!--StartFragment-->|<!--EndFragment-->/g, // Inner fragments (tables from excel on mac)
   200       return internalMimeType;
   201 			[/( ?)<span class="Apple-converted-space">\u00a0<\/span>( ?)/g, trimSpaces],
   201     }
   202 			/<br>$/i // Trailing BR elements
   202   };
   203 		]);
   203 
   204 
   204   var global$5 = tinymce.util.Tools.resolve('tinymce.html.Entities');
   205 		return html;
   205 
   206 	}
   206   var isPlainText = function (text) {
   207 
   207     return !/<(?:\/?(?!(?:div|p|br|span)>)\w+|(?:(?!(?:span style="white-space:\s?pre;?">)|br\s?\/>))\w+\s[^>]+)>/i.test(text);
   208 	return {
   208   };
   209 		filter: filter,
   209   var toBRs = function (text) {
   210 		innerText: innerText,
   210     return text.replace(/\r?\n/g, '<br>');
   211 		trimHtml: trimHtml
   211   };
   212 	};
   212   var openContainer = function (rootTag, rootAttrs) {
   213 });
   213     var key;
   214 
   214     var attrs = [];
   215 // Included from: js/tinymce/plugins/paste/classes/Clipboard.js
   215     var tag = '<' + rootTag;
   216 
   216     if (typeof rootAttrs === 'object') {
   217 /**
   217       for (key in rootAttrs) {
   218  * Clipboard.js
   218         if (rootAttrs.hasOwnProperty(key)) {
   219  *
   219           attrs.push(key + '="' + global$5.encodeAllRaw(rootAttrs[key]) + '"');
   220  * Copyright, Moxiecode Systems AB
   220         }
   221  * Released under LGPL License.
   221       }
   222  *
   222       if (attrs.length) {
   223  * License: http://www.tinymce.com/license
   223         tag += ' ' + attrs.join(' ');
   224  * Contributing: http://www.tinymce.com/contributing
   224       }
   225  */
   225     }
   226 
   226     return tag + '>';
   227 /**
   227   };
   228  * This class contains logic for getting HTML contents out of the clipboard.
   228   var toBlockElements = function (text, rootTag, rootAttrs) {
   229  *
   229     var blocks = text.split(/\n\n/);
   230  * We need to make a lot of ugly hacks to get the contents out of the clipboard since
   230     var tagOpen = openContainer(rootTag, rootAttrs);
   231  * the W3C Clipboard API is broken in all browsers that have it: Gecko/WebKit/Blink.
   231     var tagClose = '</' + rootTag + '>';
   232  * We might rewrite this the way those API:s stabilize. Browsers doesn't handle pasting
   232     var paragraphs = global$3.map(blocks, function (p) {
   233  * from applications like Word the same way as it does when pasting into a contentEditable area
   233       return p.split(/\n/).join('<br />');
   234  * so we need to do lots of extra work to try to get to this clipboard data.
   234     });
   235  *
   235     var stitch = function (p) {
   236  * Current implementation steps:
   236       return tagOpen + p + tagClose;
   237  *  1. On keydown with paste keys Ctrl+V or Shift+Insert create
   237     };
   238  *     a paste bin element and move focus to that element.
   238     return paragraphs.length === 1 ? paragraphs[0] : global$3.map(paragraphs, stitch).join('');
   239  *  2. Wait for the browser to fire a "paste" event and get the contents out of the paste bin.
   239   };
   240  *  3. Check if the paste was successful if true, process the HTML.
   240   var convert = function (text, rootTag, rootAttrs) {
   241  *  (4). If the paste was unsuccessful use IE execCommand, Clipboard API, document.dataTransfer old WebKit API etc.
   241     return rootTag ? toBlockElements(text, rootTag, rootAttrs) : toBRs(text);
   242  *
   242   };
   243  * @class tinymce.pasteplugin.Clipboard
   243   var $_4h3hnrisjjgwecu2 = {
   244  * @private
   244     isPlainText: isPlainText,
   245  */
   245     convert: convert,
   246 define("tinymce/pasteplugin/Clipboard", [
   246     toBRs: toBRs,
   247 	"tinymce/Env",
   247     toBlockElements: toBlockElements
   248 	"tinymce/dom/RangeUtils",
   248   };
   249 	"tinymce/util/VK",
   249 
   250 	"tinymce/pasteplugin/Utils"
   250   var global$6 = tinymce.util.Tools.resolve('tinymce.html.DomParser');
   251 ], function(Env, RangeUtils, VK, Utils) {
   251 
   252 	return function(editor) {
   252   var global$7 = tinymce.util.Tools.resolve('tinymce.html.Node');
   253 		var self = this, pasteBinElm, lastRng, keyboardPasteTimeStamp = 0, draggingInternally = false;
   253 
   254 		var pasteBinDefaultContent = '%MCEPASTEBIN%', keyboardPastePlainTextState;
   254   var global$8 = tinymce.util.Tools.resolve('tinymce.html.Schema');
   255 		var mceInternalUrlPrefix = 'data:text/mce-internal,';
   255 
   256 
   256   var global$9 = tinymce.util.Tools.resolve('tinymce.html.Serializer');
   257 		/**
   257 
   258 		 * Pastes the specified HTML. This means that the HTML is filtered and then
   258   function filter(content, items) {
   259 		 * inserted at the current selection in the editor. It will also fire paste events
   259     global$3.each(items, function (v) {
   260 		 * for custom user filtering.
   260       if (v.constructor === RegExp) {
   261 		 *
   261         content = content.replace(v, '');
   262 		 * @param {String} html HTML code to paste into the current selection.
   262       } else {
   263 		 */
   263         content = content.replace(v[0], v[1]);
   264 		function pasteHtml(html) {
   264       }
   265 			var args, dom = editor.dom;
   265     });
   266 
   266     return content;
   267 			args = editor.fire('BeforePastePreProcess', {content: html}); // Internal event used by Quirks
   267   }
   268 			args = editor.fire('PastePreProcess', args);
   268   function innerText(html) {
   269 			html = args.content;
   269     var schema = global$8();
   270 
   270     var domParser = global$6({}, schema);
   271 			if (!args.isDefaultPrevented()) {
   271     var text = '';
   272 				// User has bound PastePostProcess events then we need to pass it through a DOM node
   272     var shortEndedElements = schema.getShortEndedElements();
   273 				// This is not ideal but we don't want to let the browser mess up the HTML for example
   273     var ignoreElements = global$3.makeMap('script noscript style textarea video audio iframe object', ' ');
   274 				// some browsers add &nbsp; to P tags etc
   274     var blockElements = schema.getBlockElements();
   275 				if (editor.hasEventListeners('PastePostProcess') && !args.isDefaultPrevented()) {
   275     function walk(node) {
   276 					// We need to attach the element to the DOM so Sizzle selectors work on the contents
   276       var name$$1 = node.name, currentNode = node;
   277 					var tempBody = dom.add(editor.getBody(), 'div', {style: 'display:none'}, html);
   277       if (name$$1 === 'br') {
   278 					args = editor.fire('PastePostProcess', {node: tempBody});
   278         text += '\n';
   279 					dom.remove(tempBody);
   279         return;
   280 					html = args.node.innerHTML;
   280       }
   281 				}
   281       if (shortEndedElements[name$$1]) {
   282 
   282         text += ' ';
   283 				if (!args.isDefaultPrevented()) {
   283       }
   284 					editor.insertContent(html, {merge: editor.settings.paste_merge_formats !== false});
   284       if (ignoreElements[name$$1]) {
   285 				}
   285         text += ' ';
   286 			}
   286         return;
   287 		}
   287       }
   288 
   288       if (node.type === 3) {
   289 		/**
   289         text += node.value;
   290 		 * Pastes the specified text. This means that the plain text is processed
   290       }
   291 		 * and converted into BR and P elements. It will fire paste events for custom filtering.
   291       if (!node.shortEnded) {
   292 		 *
   292         if (node = node.firstChild) {
   293 		 * @param {String} text Text to paste as the current selection location.
   293           do {
   294 		 */
   294             walk(node);
   295 		function pasteText(text) {
   295           } while (node = node.next);
   296 			text = editor.dom.encode(text).replace(/\r\n/g, '\n');
   296         }
   297 
   297       }
   298 			var startBlock = editor.dom.getParent(editor.selection.getStart(), editor.dom.isBlock);
   298       if (blockElements[name$$1] && currentNode.next) {
   299 
   299         text += '\n';
   300 			// Create start block html for example <p attr="value">
   300         if (name$$1 === 'p') {
   301 			var forcedRootBlockName = editor.settings.forced_root_block;
   301           text += '\n';
   302 			var forcedRootBlockStartHtml;
   302         }
   303 			if (forcedRootBlockName) {
   303       }
   304 				forcedRootBlockStartHtml = editor.dom.createHTML(forcedRootBlockName, editor.settings.forced_root_block_attrs);
   304     }
   305 				forcedRootBlockStartHtml = forcedRootBlockStartHtml.substr(0, forcedRootBlockStartHtml.length - 3) + '>';
   305     html = filter(html, [/<!\[[^\]]+\]>/g]);
   306 			}
   306     walk(domParser.parse(html));
   307 
   307     return text;
   308 			if ((startBlock && /^(PRE|DIV)$/.test(startBlock.nodeName)) || !forcedRootBlockName) {
   308   }
   309 				text = Utils.filter(text, [
   309   function trimHtml(html) {
   310 					[/\n/g, "<br>"]
   310     function trimSpaces(all, s1, s2) {
   311 				]);
   311       if (!s1 && !s2) {
   312 			} else {
   312         return ' ';
   313 				text = Utils.filter(text, [
   313       }
   314 					[/\n\n/g, "</p>" + forcedRootBlockStartHtml],
   314       return '\xA0';
   315 					[/^(.*<\/p>)(<p>)$/, forcedRootBlockStartHtml + '$1'],
   315     }
   316 					[/\n/g, "<br />"]
   316     html = filter(html, [
   317 				]);
   317       /^[\s\S]*<body[^>]*>\s*|\s*<\/body[^>]*>[\s\S]*$/ig,
   318 
   318       /<!--StartFragment-->|<!--EndFragment-->/g,
   319 				if (text.indexOf('<p>') != -1) {
   319       [
   320 					text = forcedRootBlockStartHtml + text;
   320         /( ?)<span class="Apple-converted-space">\u00a0<\/span>( ?)/g,
   321 				}
   321         trimSpaces
   322 			}
   322       ],
   323 
   323       /<br class="Apple-interchange-newline">/g,
   324 			pasteHtml(text);
   324       /<br>$/i
   325 		}
   325     ]);
   326 
   326     return html;
   327 		/**
   327   }
   328 		 * Creates a paste bin element as close as possible to the current caret location and places the focus inside that element
   328   function createIdGenerator(prefix) {
   329 		 * so that when the real paste event occurs the contents gets inserted into this element
   329     var count = 0;
   330 		 * instead of the current editor selection element.
   330     return function () {
   331 		 */
   331       return prefix + count++;
   332 		function createPasteBin() {
   332     };
   333 			var dom = editor.dom, body = editor.getBody();
   333   }
   334 			var viewport = editor.dom.getViewPort(editor.getWin()), scrollTop = viewport.y, top = 20;
   334   var isMsEdge = function () {
   335 			var scrollContainer;
   335     return navigator.userAgent.indexOf(' Edge/') !== -1;
   336 
   336   };
   337 			lastRng = editor.selection.getRng();
   337   var $_4bi2o9j0jjgwecui = {
   338 
   338     filter: filter,
   339 			if (editor.inline) {
   339     innerText: innerText,
   340 				scrollContainer = editor.selection.getScrollContainer();
   340     trimHtml: trimHtml,
   341 
   341     createIdGenerator: createIdGenerator,
   342 				// Can't always rely on scrollTop returning a useful value.
   342     isMsEdge: isMsEdge
   343 				// It returns 0 if the browser doesn't support scrollTop for the element or is non-scrollable
   343   };
   344 				if (scrollContainer && scrollContainer.scrollTop > 0) {
   344 
   345 					scrollTop = scrollContainer.scrollTop;
   345   function isWordContent(content) {
   346 				}
   346     return /<font face="Times New Roman"|class="?Mso|style="[^"]*\bmso-|style='[^'']*\bmso-|w:WordDocument/i.test(content) || /class="OutlineElement/.test(content) || /id="?docs\-internal\-guid\-/.test(content);
   347 			}
   347   }
   348 
   348   function isNumericList(text) {
   349 			/**
   349     var found, patterns;
   350 			 * Returns the rect of the current caret if the caret is in an empty block before a
   350     patterns = [
   351 			 * BR we insert a temporary invisible character that we get the rect this way we always get a proper rect.
   351       /^[IVXLMCD]{1,2}\.[ \u00a0]/,
   352 			 *
   352       /^[ivxlmcd]{1,2}\.[ \u00a0]/,
   353 			 * TODO: This might be useful in core.
   353       /^[a-z]{1,2}[\.\)][ \u00a0]/,
   354 			 */
   354       /^[A-Z]{1,2}[\.\)][ \u00a0]/,
   355 			function getCaretRect(rng) {
   355       /^[0-9]+\.[ \u00a0]/,
   356 				var rects, textNode, node, container = rng.startContainer;
   356       /^[\u3007\u4e00\u4e8c\u4e09\u56db\u4e94\u516d\u4e03\u516b\u4e5d]+\.[ \u00a0]/,
   357 
   357       /^[\u58f1\u5f10\u53c2\u56db\u4f0d\u516d\u4e03\u516b\u4e5d\u62fe]+\.[ \u00a0]/
   358 				rects = rng.getClientRects();
   358     ];
   359 				if (rects.length) {
   359     text = text.replace(/^[\u00a0 ]+/, '');
   360 					return rects[0];
   360     global$3.each(patterns, function (pattern) {
   361 				}
   361       if (pattern.test(text)) {
   362 
   362         found = true;
   363 				if (!rng.collapsed || container.nodeType != 1) {
   363         return false;
   364 					return;
   364       }
   365 				}
   365     });
   366 
   366     return found;
   367 				node = container.childNodes[lastRng.startOffset];
   367   }
   368 
   368   function isBulletList(text) {
   369 				// Skip empty whitespace nodes
   369     return /^[\s\u00a0]*[\u2022\u00b7\u00a7\u25CF]\s*/.test(text);
   370 				while (node && node.nodeType == 3 && !node.data.length) {
   370   }
   371 					node = node.nextSibling;
   371   function convertFakeListsToProperLists(node) {
   372 				}
   372     var currentListNode, prevListNode, lastLevel = 1;
   373 
   373     function getText(node) {
   374 				if (!node) {
   374       var txt = '';
   375 					return;
   375       if (node.type === 3) {
   376 				}
   376         return node.value;
   377 
   377       }
   378 				// Check if the location is |<br>
   378       if (node = node.firstChild) {
   379 				// TODO: Might need to expand this to say |<table>
   379         do {
   380 				if (node.tagName == 'BR') {
   380           txt += getText(node);
   381 					textNode = dom.doc.createTextNode('\uFEFF');
   381         } while (node = node.next);
   382 					node.parentNode.insertBefore(textNode, node);
   382       }
   383 
   383       return txt;
   384 					rng = dom.createRng();
   384     }
   385 					rng.setStartBefore(textNode);
   385     function trimListStart(node, regExp) {
   386 					rng.setEndAfter(textNode);
   386       if (node.type === 3) {
   387 
   387         if (regExp.test(node.value)) {
   388 					rects = rng.getClientRects();
   388           node.value = node.value.replace(regExp, '');
   389 					dom.remove(textNode);
   389           return false;
   390 				}
   390         }
   391 
   391       }
   392 				if (rects.length) {
   392       if (node = node.firstChild) {
   393 					return rects[0];
   393         do {
   394 				}
   394           if (!trimListStart(node, regExp)) {
   395 			}
   395             return false;
   396 
   396           }
   397 			// Calculate top cordinate this is needed to avoid scrolling to top of document
   397         } while (node = node.next);
   398 			// We want the paste bin to be as close to the caret as possible to avoid scrolling
   398       }
   399 			if (lastRng.getClientRects) {
   399       return true;
   400 				var rect = getCaretRect(lastRng);
   400     }
   401 
   401     function removeIgnoredNodes(node) {
   402 				if (rect) {
   402       if (node._listIgnore) {
   403 					// Client rects gets us closes to the actual
   403         node.remove();
   404 					// caret location in for example a wrapped paragraph block
   404         return;
   405 					top = scrollTop + (rect.top - dom.getPos(body).y);
   405       }
   406 				} else {
   406       if (node = node.firstChild) {
   407 					top = scrollTop;
   407         do {
   408 
   408           removeIgnoredNodes(node);
   409 					// Check if we can find a closer location by checking the range element
   409         } while (node = node.next);
   410 					var container = lastRng.startContainer;
   410       }
   411 					if (container) {
   411     }
   412 						if (container.nodeType == 3 && container.parentNode != body) {
   412     function convertParagraphToLi(paragraphNode, listName, start) {
   413 							container = container.parentNode;
   413       var level = paragraphNode._listLevel || lastLevel;
   414 						}
   414       if (level !== lastLevel) {
   415 
   415         if (level < lastLevel) {
   416 						if (container.nodeType == 1) {
   416           if (currentListNode) {
   417 							top = dom.getPos(container, scrollContainer || body).y;
   417             currentListNode = currentListNode.parent.parent;
   418 						}
   418           }
   419 					}
   419         } else {
   420 				}
   420           prevListNode = currentListNode;
   421 			}
   421           currentListNode = null;
   422 
   422         }
   423 			// Create a pastebin
   423       }
   424 			pasteBinElm = dom.add(editor.getBody(), 'div', {
   424       if (!currentListNode || currentListNode.name !== listName) {
   425 				id: "mcepastebin",
   425         prevListNode = prevListNode || currentListNode;
   426 				contentEditable: true,
   426         currentListNode = new global$7(listName, 1);
   427 				"data-mce-bogus": "all",
   427         if (start > 1) {
   428 				style: 'position: absolute; top: ' + top + 'px;' +
   428           currentListNode.attr('start', '' + start);
   429 					'width: 10px; height: 10px; overflow: hidden; opacity: 0'
   429         }
   430 			}, pasteBinDefaultContent);
   430         paragraphNode.wrap(currentListNode);
   431 
   431       } else {
   432 			// Move paste bin out of sight since the controlSelection rect gets displayed otherwise on IE and Gecko
   432         currentListNode.append(paragraphNode);
   433 			if (Env.ie || Env.gecko) {
   433       }
   434 				dom.setStyle(pasteBinElm, 'left', dom.getStyle(body, 'direction', true) == 'rtl' ? 0xFFFF : -0xFFFF);
   434       paragraphNode.name = 'li';
   435 			}
   435       if (level > lastLevel && prevListNode) {
   436 
   436         prevListNode.lastChild.append(currentListNode);
   437 			// Prevent focus events from bubbeling fixed FocusManager issues
   437       }
   438 			dom.bind(pasteBinElm, 'beforedeactivate focusin focusout', function(e) {
   438       lastLevel = level;
   439 				e.stopPropagation();
   439       removeIgnoredNodes(paragraphNode);
   440 			});
   440       trimListStart(paragraphNode, /^\u00a0+/);
   441 
   441       trimListStart(paragraphNode, /^\s*([\u2022\u00b7\u00a7\u25CF]|\w+\.)/);
   442 			pasteBinElm.focus();
   442       trimListStart(paragraphNode, /^\u00a0+/);
   443 			editor.selection.select(pasteBinElm, true);
   443     }
   444 		}
   444     var elements = [];
   445 
   445     var child = node.firstChild;
   446 		/**
   446     while (typeof child !== 'undefined' && child !== null) {
   447 		 * Removes the paste bin if it exists.
   447       elements.push(child);
   448 		 */
   448       child = child.walk();
   449 		function removePasteBin() {
   449       if (child !== null) {
   450 			if (pasteBinElm) {
   450         while (typeof child !== 'undefined' && child.parent !== node) {
   451 				var pasteBinClone;
   451           child = child.walk();
   452 
   452         }
   453 				// WebKit/Blink might clone the div so
   453       }
   454 				// lets make sure we remove all clones
   454     }
   455 				// TODO: Man o man is this ugly. WebKit is the new IE! Remove this if they ever fix it!
   455     for (var i = 0; i < elements.length; i++) {
   456 				while ((pasteBinClone = editor.dom.get('mcepastebin'))) {
   456       node = elements[i];
   457 					editor.dom.remove(pasteBinClone);
   457       if (node.name === 'p' && node.firstChild) {
   458 					editor.dom.unbind(pasteBinClone);
   458         var nodeText = getText(node);
   459 				}
   459         if (isBulletList(nodeText)) {
   460 
   460           convertParagraphToLi(node, 'ul');
   461 				if (lastRng) {
   461           continue;
   462 					editor.selection.setRng(lastRng);
   462         }
   463 				}
   463         if (isNumericList(nodeText)) {
   464 			}
   464           var matches = /([0-9]+)\./.exec(nodeText);
   465 
   465           var start = 1;
   466 			pasteBinElm = lastRng = null;
   466           if (matches) {
   467 		}
   467             start = parseInt(matches[1], 10);
   468 
   468           }
   469 		/**
   469           convertParagraphToLi(node, 'ol', start);
   470 		 * Returns the contents of the paste bin as a HTML string.
   470           continue;
   471 		 *
   471         }
   472 		 * @return {String} Get the contents of the paste bin.
   472         if (node._listLevel) {
   473 		 */
   473           convertParagraphToLi(node, 'ul', 1);
   474 		function getPasteBinHtml() {
   474           continue;
   475 			var html = '', pasteBinClones, i, clone, cloneHtml;
   475         }
   476 
   476         currentListNode = null;
   477 			// Since WebKit/Chrome might clone the paste bin when pasting
   477       } else {
   478 			// for example: <img style="float: right"> we need to check if any of them contains some useful html.
   478         prevListNode = currentListNode;
   479 			// TODO: Man o man is this ugly. WebKit is the new IE! Remove this if they ever fix it!
   479         currentListNode = null;
   480 			pasteBinClones = editor.dom.select('div[id=mcepastebin]');
   480       }
   481 			for (i = 0; i < pasteBinClones.length; i++) {
   481     }
   482 				clone = pasteBinClones[i];
   482   }
   483 
   483   function filterStyles(editor, validStyles, node, styleValue) {
   484 				// Pasting plain text produces pastebins in pastebinds makes sence right!?
   484     var outputStyles = {}, matches;
   485 				if (clone.firstChild && clone.firstChild.id == 'mcepastebin') {
   485     var styles = editor.dom.parseStyle(styleValue);
   486 					clone = clone.firstChild;
   486     global$3.each(styles, function (value, name) {
   487 				}
   487       switch (name) {
   488 
   488       case 'mso-list':
   489 				cloneHtml = clone.innerHTML;
   489         matches = /\w+ \w+([0-9]+)/i.exec(styleValue);
   490 				if (html != pasteBinDefaultContent) {
   490         if (matches) {
   491 					html += cloneHtml;
   491           node._listLevel = parseInt(matches[1], 10);
   492 				}
   492         }
   493 			}
   493         if (/Ignore/i.test(value) && node.firstChild) {
   494 
   494           node._listIgnore = true;
   495 			return html;
   495           node.firstChild._listIgnore = true;
   496 		}
   496         }
   497 
   497         break;
   498 		/**
   498       case 'horiz-align':
   499 		 * Gets various content types out of a datatransfer object.
   499         name = 'text-align';
   500 		 *
   500         break;
   501 		 * @param {DataTransfer} dataTransfer Event fired on paste.
   501       case 'vert-align':
   502 		 * @return {Object} Object with mime types and data for those mime types.
   502         name = 'vertical-align';
   503 		 */
   503         break;
   504 		function getDataTransferItems(dataTransfer) {
   504       case 'font-color':
   505 			var data = {};
   505       case 'mso-foreground':
   506 
   506         name = 'color';
   507 			if (dataTransfer) {
   507         break;
   508 				// Use old WebKit/IE API
   508       case 'mso-background':
   509 				if (dataTransfer.getData) {
   509       case 'mso-highlight':
   510 					var legacyText = dataTransfer.getData('Text');
   510         name = 'background';
   511 					if (legacyText && legacyText.length > 0) {
   511         break;
   512 						if (legacyText.indexOf(mceInternalUrlPrefix) == -1) {
   512       case 'font-weight':
   513 							data['text/plain'] = legacyText;
   513       case 'font-style':
   514 						}
   514         if (value !== 'normal') {
   515 					}
   515           outputStyles[name] = value;
   516 				}
   516         }
   517 
   517         return;
   518 				if (dataTransfer.types) {
   518       case 'mso-element':
   519 					for (var i = 0; i < dataTransfer.types.length; i++) {
   519         if (/^(comment|comment-list)$/i.test(value)) {
   520 						var contentType = dataTransfer.types[i];
   520           node.remove();
   521 						data[contentType] = dataTransfer.getData(contentType);
   521           return;
   522 					}
   522         }
   523 				}
   523         break;
   524 			}
   524       }
   525 
   525       if (name.indexOf('mso-comment') === 0) {
   526 			return data;
   526         node.remove();
   527 		}
   527         return;
   528 
   528       }
   529 		/**
   529       if (name.indexOf('mso-') === 0) {
   530 		 * Gets various content types out of the Clipboard API. It will also get the
   530         return;
   531 		 * plain text using older IE and WebKit API:s.
   531       }
   532 		 *
   532       if ($_xr8b0ikjjgwectl.getRetainStyleProps(editor) === 'all' || validStyles && validStyles[name]) {
   533 		 * @param {ClipboardEvent} clipboardEvent Event fired on paste.
   533         outputStyles[name] = value;
   534 		 * @return {Object} Object with mime types and data for those mime types.
   534       }
   535 		 */
   535     });
   536 		function getClipboardContent(clipboardEvent) {
   536     if (/(bold)/i.test(outputStyles['font-weight'])) {
   537 			return getDataTransferItems(clipboardEvent.clipboardData || editor.getDoc().dataTransfer);
   537       delete outputStyles['font-weight'];
   538 		}
   538       node.wrap(new global$7('b', 1));
   539 
   539     }
   540 		/**
   540     if (/(italic)/i.test(outputStyles['font-style'])) {
   541 		 * Checks if the clipboard contains image data if it does it will take that data
   541       delete outputStyles['font-style'];
   542 		 * and convert it into a data url image and paste that image at the caret location.
   542       node.wrap(new global$7('i', 1));
   543 		 *
   543     }
   544 		 * @param  {ClipboardEvent} e Paste/drop event object.
   544     outputStyles = editor.dom.serializeStyle(outputStyles, node.name);
   545 		 * @param  {DOMRange} rng Optional rng object to move selection to.
   545     if (outputStyles) {
   546 		 * @return {Boolean} true/false if the image data was found or not.
   546       return outputStyles;
   547 		 */
   547     }
   548 		function pasteImageData(e, rng) {
   548     return null;
   549 			var dataTransfer = e.clipboardData || e.dataTransfer;
   549   }
   550 
   550   var filterWordContent = function (editor, content) {
   551 			function processItems(items) {
   551     var retainStyleProperties, validStyles;
   552 				var i, item, reader, hadImage = false;
   552     retainStyleProperties = $_xr8b0ikjjgwectl.getRetainStyleProps(editor);
   553 
   553     if (retainStyleProperties) {
   554 				function pasteImage(reader) {
   554       validStyles = global$3.makeMap(retainStyleProperties.split(/[, ]/));
   555 					if (rng) {
   555     }
   556 						editor.selection.setRng(rng);
   556     content = $_4bi2o9j0jjgwecui.filter(content, [
   557 						rng = null;
   557       /<br class="?Apple-interchange-newline"?>/gi,
   558 					}
   558       /<b[^>]+id="?docs-internal-[^>]*>/gi,
   559 
   559       /<!--[\s\S]+?-->/gi,
   560 					pasteHtml('<img src="' + reader.result + '">');
   560       /<(!|script[^>]*>.*?<\/script(?=[>\s])|\/?(\?xml(:\w+)?|img|meta|link|style|\w:\w+)(?=[\s\/>]))[^>]*>/gi,
   561 				}
   561       [
   562 
   562         /<(\/?)s>/gi,
   563 				if (items) {
   563         '<$1strike>'
   564 					for (i = 0; i < items.length; i++) {
   564       ],
   565 						item = items[i];
   565       [
   566 
   566         /&nbsp;/gi,
   567 						if (/^image\/(jpeg|png|gif|bmp)$/.test(item.type)) {
   567         '\xA0'
   568 							reader = new FileReader();
   568       ],
   569 							reader.onload = pasteImage.bind(null, reader);
   569       [
   570 							reader.readAsDataURL(item.getAsFile ? item.getAsFile() : item);
   570         /<span\s+style\s*=\s*"\s*mso-spacerun\s*:\s*yes\s*;?\s*"\s*>([\s\u00a0]*)<\/span>/gi,
   571 
   571         function (str, spaces) {
   572 							e.preventDefault();
   572           return spaces.length > 0 ? spaces.replace(/./, ' ').slice(Math.floor(spaces.length / 2)).split('').join('\xA0') : '';
   573 							hadImage = true;
   573         }
   574 						}
   574       ]
   575 					}
   575     ]);
   576 				}
   576     var validElements = $_xr8b0ikjjgwectl.getWordValidElements(editor);
   577 
   577     var schema = global$8({
   578 				return hadImage;
   578       valid_elements: validElements,
   579 			}
   579       valid_children: '-li[p]'
   580 
   580     });
   581 			if (editor.settings.paste_data_images && dataTransfer) {
   581     global$3.each(schema.elements, function (rule) {
   582 				return processItems(dataTransfer.items) || processItems(dataTransfer.files);
   582       if (!rule.attributes.class) {
   583 			}
   583         rule.attributes.class = {};
   584 		}
   584         rule.attributesOrder.push('class');
   585 
   585       }
   586 		/**
   586       if (!rule.attributes.style) {
   587 		 * Chrome on Android doesn't support proper clipboard access so we have no choice but to allow the browser default behavior.
   587         rule.attributes.style = {};
   588 		 *
   588         rule.attributesOrder.push('style');
   589 		 * @param {Event} e Paste event object to check if it contains any data.
   589       }
   590 		 * @return {Boolean} true/false if the clipboard is empty or not.
   590     });
   591 		 */
   591     var domParser = global$6({}, schema);
   592 		function isBrokenAndroidClipboardEvent(e) {
   592     domParser.addAttributeFilter('style', function (nodes) {
   593 			var clipboardData = e.clipboardData;
   593       var i = nodes.length, node;
   594 
   594       while (i--) {
   595 			return navigator.userAgent.indexOf('Android') != -1 && clipboardData && clipboardData.items && clipboardData.items.length === 0;
   595         node = nodes[i];
   596 		}
   596         node.attr('style', filterStyles(editor, validStyles, node, node.attr('style')));
   597 
   597         if (node.name === 'span' && node.parent && !node.attributes.length) {
   598 		function getCaretRangeFromEvent(e) {
   598           node.unwrap();
   599 			return RangeUtils.getCaretRangeFromPoint(e.clientX, e.clientY, editor.getDoc());
   599         }
   600 		}
   600       }
   601 
   601     });
   602 		function hasContentType(clipboardContent, mimeType) {
   602     domParser.addAttributeFilter('class', function (nodes) {
   603 			return mimeType in clipboardContent && clipboardContent[mimeType].length > 0;
   603       var i = nodes.length, node, className;
   604 		}
   604       while (i--) {
   605 
   605         node = nodes[i];
   606 		function isKeyboardPasteEvent(e) {
   606         className = node.attr('class');
   607 			return (VK.metaKeyPressed(e) && e.keyCode == 86) || (e.shiftKey && e.keyCode == 45);
   607         if (/^(MsoCommentReference|MsoCommentText|msoDel)$/i.test(className)) {
   608 		}
   608           node.remove();
   609 
   609         }
   610 		function registerEventHandlers() {
   610         node.attr('class', null);
   611 			editor.on('keydown', function(e) {
   611       }
   612 				function removePasteBinOnKeyUp(e) {
   612     });
   613 					// Ctrl+V or Shift+Insert
   613     domParser.addNodeFilter('del', function (nodes) {
   614 					if (isKeyboardPasteEvent(e) && !e.isDefaultPrevented()) {
   614       var i = nodes.length;
   615 						removePasteBin();
   615       while (i--) {
   616 					}
   616         nodes[i].remove();
   617 				}
   617       }
   618 
   618     });
   619 				// Ctrl+V or Shift+Insert
   619     domParser.addNodeFilter('a', function (nodes) {
   620 				if (isKeyboardPasteEvent(e) && !e.isDefaultPrevented()) {
   620       var i = nodes.length, node, href, name;
   621 					keyboardPastePlainTextState = e.shiftKey && e.keyCode == 86;
   621       while (i--) {
   622 
   622         node = nodes[i];
   623 					// Edge case on Safari on Mac where it doesn't handle Cmd+Shift+V correctly
   623         href = node.attr('href');
   624 					// it fires the keydown but no paste or keyup so we are left with a paste bin
   624         name = node.attr('name');
   625 					if (keyboardPastePlainTextState && Env.webkit && navigator.userAgent.indexOf('Version/') != -1) {
   625         if (href && href.indexOf('#_msocom_') !== -1) {
   626 						return;
   626           node.remove();
   627 					}
   627           continue;
   628 
   628         }
   629 					// Prevent undoManager keydown handler from making an undo level with the pastebin in it
   629         if (href && href.indexOf('file://') === 0) {
   630 					e.stopImmediatePropagation();
   630           href = href.split('#')[1];
   631 
   631           if (href) {
   632 					keyboardPasteTimeStamp = new Date().getTime();
   632             href = '#' + href;
   633 
   633           }
   634 					// IE doesn't support Ctrl+Shift+V and it doesn't even produce a paste event
   634         }
   635 					// so lets fake a paste event and let IE use the execCommand/dataTransfer methods
   635         if (!href && !name) {
   636 					if (Env.ie && keyboardPastePlainTextState) {
   636           node.unwrap();
   637 						e.preventDefault();
   637         } else {
   638 						editor.fire('paste', {ieFake: true});
   638           if (name && !/^_?(?:toc|edn|ftn)/i.test(name)) {
   639 						return;
   639             node.unwrap();
   640 					}
   640             continue;
   641 
   641           }
   642 					removePasteBin();
   642           node.attr({
   643 					createPasteBin();
   643             href: href,
   644 
   644             name: name
   645 					// Remove pastebin if we get a keyup and no paste event
   645           });
   646 					// For example pasting a file in IE 11 will not produce a paste event
   646         }
   647 					editor.once('keyup', removePasteBinOnKeyUp);
   647       }
   648 					editor.once('paste', function() {
   648     });
   649 						editor.off('keyup', removePasteBinOnKeyUp);
   649     var rootNode = domParser.parse(content);
   650 					});
   650     if ($_xr8b0ikjjgwectl.shouldConvertWordFakeLists(editor)) {
   651 				}
   651       convertFakeListsToProperLists(rootNode);
   652 			});
   652     }
   653 
   653     content = global$9({ validate: editor.settings.validate }, schema).serialize(rootNode);
   654 			editor.on('paste', function(e) {
   654     return content;
   655 				// Getting content from the Clipboard can take some time
   655   };
   656 				var clipboardTimer = new Date().getTime();
   656   var preProcess = function (editor, content) {
   657 				var clipboardContent = getClipboardContent(e);
   657     return $_xr8b0ikjjgwectl.shouldUseDefaultFilters(editor) ? filterWordContent(editor, content) : content;
   658 				var clipboardDelay = new Date().getTime() - clipboardTimer;
   658   };
   659 
   659   var $_dfatuiivjjgwecu8 = {
   660 				var isKeyBoardPaste = (new Date().getTime() - keyboardPasteTimeStamp - clipboardDelay) < 1000;
   660     preProcess: preProcess,
   661 				var plainTextMode = self.pasteFormat == "text" || keyboardPastePlainTextState;
   661     isWordContent: isWordContent
   662 
   662   };
   663 				keyboardPastePlainTextState = false;
   663 
   664 
   664   var processResult = function (content, cancelled) {
   665 				if (e.isDefaultPrevented() || isBrokenAndroidClipboardEvent(e)) {
   665     return {
   666 					removePasteBin();
   666       content: content,
   667 					return;
   667       cancelled: cancelled
   668 				}
   668     };
   669 
   669   };
   670 				if (pasteImageData(e)) {
   670   var postProcessFilter = function (editor, html, internal, isWordHtml) {
   671 					removePasteBin();
   671     var tempBody = editor.dom.create('div', { style: 'display:none' }, html);
   672 					return;
   672     var postProcessArgs = $_8tki3zijjjgwectj.firePastePostProcess(editor, tempBody, internal, isWordHtml);
   673 				}
   673     return processResult(postProcessArgs.node.innerHTML, postProcessArgs.isDefaultPrevented());
   674 
   674   };
   675 				// Not a keyboard paste prevent default paste and try to grab the clipboard contents using different APIs
   675   var filterContent = function (editor, content, internal, isWordHtml) {
   676 				if (!isKeyBoardPaste) {
   676     var preProcessArgs = $_8tki3zijjjgwectj.firePastePreProcess(editor, content, internal, isWordHtml);
   677 					e.preventDefault();
   677     if (editor.hasEventListeners('PastePostProcess') && !preProcessArgs.isDefaultPrevented()) {
   678 				}
   678       return postProcessFilter(editor, preProcessArgs.content, internal, isWordHtml);
   679 
   679     } else {
   680 				// Try IE only method if paste isn't a keyboard paste
   680       return processResult(preProcessArgs.content, preProcessArgs.isDefaultPrevented());
   681 				if (Env.ie && (!isKeyBoardPaste || e.ieFake)) {
   681     }
   682 					createPasteBin();
   682   };
   683 
   683   var process = function (editor, html, internal) {
   684 					editor.dom.bind(pasteBinElm, 'paste', function(e) {
   684     var isWordHtml = $_dfatuiivjjgwecu8.isWordContent(html);
   685 						e.stopPropagation();
   685     var content = isWordHtml ? $_dfatuiivjjgwecu8.preProcess(editor, html) : html;
   686 					});
   686     return filterContent(editor, content, internal, isWordHtml);
   687 
   687   };
   688 					editor.getDoc().execCommand('Paste', false, null);
   688   var $_3scw66iujjgwecu4 = { process: process };
   689 					clipboardContent["text/html"] = getPasteBinHtml();
   689 
   690 				}
   690   var pasteHtml = function (editor, html) {
   691 
   691     editor.insertContent(html, {
   692 				setTimeout(function() {
   692       merge: $_xr8b0ikjjgwectl.shouldMergeFormats(editor),
   693 					var content;
   693       paste: true
   694 
   694     });
   695 					// Grab HTML from Clipboard API or paste bin as a fallback
   695     return true;
   696 					if (hasContentType(clipboardContent, 'text/html')) {
   696   };
   697 						content = clipboardContent['text/html'];
   697   var isAbsoluteUrl = function (url) {
   698 					} else {
   698     return /^https?:\/\/[\w\?\-\/+=.&%@~#]+$/i.test(url);
   699 						content = getPasteBinHtml();
   699   };
   700 
   700   var isImageUrl = function (url) {
   701 						// If paste bin is empty try using plain text mode
   701     return isAbsoluteUrl(url) && /.(gif|jpe?g|png)$/.test(url);
   702 						// since that is better than nothing right
   702   };
   703 						if (content == pasteBinDefaultContent) {
   703   var createImage = function (editor, url, pasteHtmlFn) {
   704 							plainTextMode = true;
   704     editor.undoManager.extra(function () {
   705 						}
   705       pasteHtmlFn(editor, url);
   706 					}
   706     }, function () {
   707 
   707       editor.insertContent('<img src="' + url + '">');
   708 					content = Utils.trimHtml(content);
   708     });
   709 
   709     return true;
   710 					// WebKit has a nice bug where it clones the paste bin if you paste from for example notepad
   710   };
   711 					// so we need to force plain text mode in this case
   711   var createLink = function (editor, url, pasteHtmlFn) {
   712 					if (pasteBinElm && pasteBinElm.firstChild && pasteBinElm.firstChild.id === 'mcepastebin') {
   712     editor.undoManager.extra(function () {
   713 						plainTextMode = true;
   713       pasteHtmlFn(editor, url);
   714 					}
   714     }, function () {
   715 
   715       editor.execCommand('mceInsertLink', false, url);
   716 					removePasteBin();
   716     });
   717 
   717     return true;
   718 					// If we got nothing from clipboard API and pastebin then we could try the last resort: plain/text
   718   };
   719 					if (!content.length) {
   719   var linkSelection = function (editor, html, pasteHtmlFn) {
   720 						plainTextMode = true;
   720     return editor.selection.isCollapsed() === false && isAbsoluteUrl(html) ? createLink(editor, html, pasteHtmlFn) : false;
   721 					}
   721   };
   722 
   722   var insertImage = function (editor, html, pasteHtmlFn) {
   723 					// Grab plain text from Clipboard API or convert existing HTML to plain text
   723     return isImageUrl(html) ? createImage(editor, html, pasteHtmlFn) : false;
   724 					if (plainTextMode) {
   724   };
   725 						// Use plain text contents from Clipboard API unless the HTML contains paragraphs then
   725   var smartInsertContent = function (editor, html) {
   726 						// we should convert the HTML to plain text since works better when pasting HTML/Word contents as plain text
   726     global$3.each([
   727 						if (hasContentType(clipboardContent, 'text/plain') && content.indexOf('</p>') == -1) {
   727       linkSelection,
   728 							content = clipboardContent['text/plain'];
   728       insertImage,
   729 						} else {
   729       pasteHtml
   730 							content = Utils.innerText(content);
   730     ], function (action) {
   731 						}
   731       return action(editor, html, pasteHtml) !== true;
   732 					}
   732     });
   733 
   733   };
   734 					// If the content is the paste bin default HTML then it was
   734   var insertContent = function (editor, html) {
   735 					// impossible to get the cliboard data out.
   735     if ($_xr8b0ikjjgwectl.isSmartPasteEnabled(editor) === false) {
   736 					if (content == pasteBinDefaultContent) {
   736       pasteHtml(editor, html);
   737 						if (!isKeyBoardPaste) {
   737     } else {
   738 							editor.windowManager.alert('Please use Ctrl+V/Cmd+V keyboard shortcuts to paste contents.');
   738       smartInsertContent(editor, html);
   739 						}
   739     }
   740 
   740   };
   741 						return;
   741   var $_d8pzpej1jjgwecum = {
   742 					}
   742     isImageUrl: isImageUrl,
   743 
   743     isAbsoluteUrl: isAbsoluteUrl,
   744 					if (plainTextMode) {
   744     insertContent: insertContent
   745 						pasteText(content);
   745   };
   746 					} else {
   746 
   747 						pasteHtml(content);
   747   var pasteHtml$1 = function (editor, html, internalFlag) {
   748 					}
   748     var internal = internalFlag ? internalFlag : $_4x13hjirjjgwecu1.isMarked(html);
   749 				}, 0);
   749     var args = $_3scw66iujjgwecu4.process(editor, $_4x13hjirjjgwecu1.unmark(html), internal);
   750 			});
   750     if (args.cancelled === false) {
   751 
   751       $_d8pzpej1jjgwecum.insertContent(editor, args.content);
   752 			editor.on('dragstart dragend', function(e) {
   752     }
   753 				draggingInternally = e.type == 'dragstart';
   753   };
   754 			});
   754   var pasteText = function (editor, text) {
   755 
   755     text = editor.dom.encode(text).replace(/\r\n/g, '\n');
   756 			editor.on('drop', function(e) {
   756     text = $_4h3hnrisjjgwecu2.convert(text, editor.settings.forced_root_block, editor.settings.forced_root_block_attrs);
   757 				var rng = getCaretRangeFromEvent(e);
   757     pasteHtml$1(editor, text, false);
   758 
   758   };
   759 				if (e.isDefaultPrevented() || draggingInternally) {
   759   var getDataTransferItems = function (dataTransfer) {
   760 					return;
   760     var items = {};
   761 				}
   761     var mceInternalUrlPrefix = 'data:text/mce-internal,';
   762 
   762     if (dataTransfer) {
   763 				if (pasteImageData(e, rng)) {
   763       if (dataTransfer.getData) {
   764 					return;
   764         var legacyText = dataTransfer.getData('Text');
   765 				}
   765         if (legacyText && legacyText.length > 0) {
   766 
   766           if (legacyText.indexOf(mceInternalUrlPrefix) === -1) {
   767 				if (rng && editor.settings.paste_filter_drop !== false) {
   767             items['text/plain'] = legacyText;
   768 					var dropContent = getDataTransferItems(e.dataTransfer);
   768           }
   769 					var content = dropContent['mce-internal'] || dropContent['text/html'] || dropContent['text/plain'];
   769         }
   770 
   770       }
   771 					if (content) {
   771       if (dataTransfer.types) {
   772 						e.preventDefault();
   772         for (var i = 0; i < dataTransfer.types.length; i++) {
   773 
   773           var contentType = dataTransfer.types[i];
   774 						editor.undoManager.transact(function() {
   774           try {
   775 							if (dropContent['mce-internal']) {
   775             items[contentType] = dataTransfer.getData(contentType);
   776 								editor.execCommand('Delete');
   776           } catch (ex) {
   777 							}
   777             items[contentType] = '';
   778 
   778           }
   779 							editor.selection.setRng(rng);
   779         }
   780 
   780       }
   781 							content = Utils.trimHtml(content);
   781     }
   782 
   782     return items;
   783 							if (!dropContent['text/html']) {
   783   };
   784 								pasteText(content);
   784   var getClipboardContent = function (editor, clipboardEvent) {
   785 							} else {
   785     var content = getDataTransferItems(clipboardEvent.clipboardData || editor.getDoc().dataTransfer);
   786 								pasteHtml(content);
   786     return $_4bi2o9j0jjgwecui.isMsEdge() ? global$3.extend(content, { 'text/html': '' }) : content;
   787 							}
   787   };
   788 						});
   788   var hasContentType = function (clipboardContent, mimeType) {
   789 					}
   789     return mimeType in clipboardContent && clipboardContent[mimeType].length > 0;
   790 				}
   790   };
   791 			});
   791   var hasHtmlOrText = function (content) {
   792 
   792     return hasContentType(content, 'text/html') || hasContentType(content, 'text/plain');
   793 			editor.on('dragover dragend', function(e) {
   793   };
   794 				if (editor.settings.paste_data_images) {
   794   var getBase64FromUri = function (uri) {
   795 					e.preventDefault();
   795     var idx;
   796 				}
   796     idx = uri.indexOf(',');
   797 			});
   797     if (idx !== -1) {
   798 		}
   798       return uri.substr(idx + 1);
   799 
   799     }
   800 		self.pasteHtml = pasteHtml;
   800     return null;
   801 		self.pasteText = pasteText;
   801   };
   802 
   802   var isValidDataUriImage = function (settings, imgElm) {
   803 		editor.on('preInit', function() {
   803     return settings.images_dataimg_filter ? settings.images_dataimg_filter(imgElm) : true;
   804 			registerEventHandlers();
   804   };
   805 
   805   var extractFilename = function (editor, str) {
   806 			// Remove all data images from paste for example from Gecko
   806     var m = str.match(/([\s\S]+?)\.(?:jpeg|jpg|png|gif)$/i);
   807 			// except internal images like video elements
   807     return m ? editor.dom.encode(m[1]) : null;
   808 			editor.parser.addNodeFilter('img', function(nodes) {
   808   };
   809 				if (!editor.settings.paste_data_images) {
   809   var uniqueId = $_4bi2o9j0jjgwecui.createIdGenerator('mceclip');
   810 					var i = nodes.length;
   810   var pasteImage = function (editor, rng, reader, blob) {
   811 
   811     if (rng) {
   812 					while (i--) {
   812       editor.selection.setRng(rng);
   813 						var src = nodes[i].attributes.map.src;
   813       rng = null;
   814 
   814     }
   815 						// Some browsers automatically produce data uris on paste
   815     var dataUri = reader.result;
   816 						// Safari on Mac produces webkit-fake-url see: https://bugs.webkit.org/show_bug.cgi?id=49141
   816     var base64 = getBase64FromUri(dataUri);
   817 						if (src && /^(data:image|webkit\-fake\-url)/.test(src)) {
   817     var id = uniqueId();
   818 							if (!nodes[i].attr('data-mce-object') && src !== Env.transparentSrc) {
   818     var name$$1 = editor.settings.images_reuse_filename && blob.name ? extractFilename(editor, blob.name) : id;
   819 								nodes[i].remove();
   819     var img = new Image();
   820 							}
   820     img.src = dataUri;
   821 						}
   821     if (isValidDataUriImage(editor.settings, img)) {
   822 					}
   822       var blobCache = editor.editorUpload.blobCache;
   823 				}
   823       var blobInfo = void 0, existingBlobInfo = void 0;
   824 			});
   824       existingBlobInfo = blobCache.findFirst(function (cachedBlobInfo) {
   825 		});
   825         return cachedBlobInfo.base64() === base64;
   826 	};
   826       });
   827 });
   827       if (!existingBlobInfo) {
   828 
   828         blobInfo = blobCache.create(id, blob, base64, name$$1);
   829 // Included from: js/tinymce/plugins/paste/classes/WordFilter.js
   829         blobCache.add(blobInfo);
   830 
   830       } else {
   831 /**
   831         blobInfo = existingBlobInfo;
   832  * WordFilter.js
   832       }
   833  *
   833       pasteHtml$1(editor, '<img src="' + blobInfo.blobUri() + '">', false);
   834  * Copyright, Moxiecode Systems AB
   834     } else {
   835  * Released under LGPL License.
   835       pasteHtml$1(editor, '<img src="' + dataUri + '">', false);
   836  *
   836     }
   837  * License: http://www.tinymce.com/license
   837   };
   838  * Contributing: http://www.tinymce.com/contributing
   838   var isClipboardEvent = function (event$$1) {
   839  */
   839     return event$$1.type === 'paste';
   840 
   840   };
   841 /**
   841   var pasteImageData = function (editor, e, rng) {
   842  * This class parses word HTML into proper TinyMCE markup.
   842     var dataTransfer = isClipboardEvent(e) ? e.clipboardData : e.dataTransfer;
   843  *
   843     function processItems(items) {
   844  * @class tinymce.pasteplugin.WordFilter
   844       var i, item, reader, hadImage = false;
   845  * @private
   845       if (items) {
   846  */
   846         for (i = 0; i < items.length; i++) {
   847 define("tinymce/pasteplugin/WordFilter", [
   847           item = items[i];
   848 	"tinymce/util/Tools",
   848           if (/^image\/(jpeg|png|gif|bmp)$/.test(item.type)) {
   849 	"tinymce/html/DomParser",
   849             var blob = item.getAsFile ? item.getAsFile() : item;
   850 	"tinymce/html/Schema",
   850             reader = new window.FileReader();
   851 	"tinymce/html/Serializer",
   851             reader.onload = pasteImage.bind(null, editor, rng, reader, blob);
   852 	"tinymce/html/Node",
   852             reader.readAsDataURL(blob);
   853 	"tinymce/pasteplugin/Utils"
   853             e.preventDefault();
   854 ], function(Tools, DomParser, Schema, Serializer, Node, Utils) {
   854             hadImage = true;
   855 	/**
   855           }
   856 	 * Checks if the specified content is from any of the following sources: MS Word/Office 365/Google docs.
   856         }
   857 	 */
   857       }
   858 	function isWordContent(content) {
   858       return hadImage;
   859 		return (
   859     }
   860 			(/<font face="Times New Roman"|class="?Mso|style="[^"]*\bmso-|style='[^'']*\bmso-|w:WordDocument/i).test(content) ||
   860     if (editor.settings.paste_data_images && dataTransfer) {
   861 			(/class="OutlineElement/).test(content) ||
   861       return processItems(dataTransfer.items) || processItems(dataTransfer.files);
   862 			(/id="?docs\-internal\-guid\-/.test(content))
   862     }
   863 		);
   863   };
   864 	}
   864   var isBrokenAndroidClipboardEvent = function (e) {
   865 
   865     var clipboardData = e.clipboardData;
   866 	/**
   866     return navigator.userAgent.indexOf('Android') !== -1 && clipboardData && clipboardData.items && clipboardData.items.length === 0;
   867 	 * Checks if the specified text starts with "1. " or "a. " etc.
   867   };
   868 	 */
   868   var isKeyboardPasteEvent = function (e) {
   869 	function isNumericList(text) {
   869     return global$4.metaKeyPressed(e) && e.keyCode === 86 || e.shiftKey && e.keyCode === 45;
   870 		var found, patterns;
   870   };
   871 
   871   var registerEventHandlers = function (editor, pasteBin, pasteFormat) {
   872 		patterns = [
   872     var keyboardPasteTimeStamp = 0;
   873 			/^[IVXLMCD]{1,2}\.[ \u00a0]/,  // Roman upper case
   873     var keyboardPastePlainTextState;
   874 			/^[ivxlmcd]{1,2}\.[ \u00a0]/,  // Roman lower case
   874     editor.on('keydown', function (e) {
   875 			/^[a-z]{1,2}[\.\)][ \u00a0]/,  // Alphabetical a-z
   875       function removePasteBinOnKeyUp(e) {
   876 			/^[A-Z]{1,2}[\.\)][ \u00a0]/,  // Alphabetical A-Z
   876         if (isKeyboardPasteEvent(e) && !e.isDefaultPrevented()) {
   877 			/^[0-9]+\.[ \u00a0]/,          // Numeric lists
   877           pasteBin.remove();
   878 			/^[\u3007\u4e00\u4e8c\u4e09\u56db\u4e94\u516d\u4e03\u516b\u4e5d]+\.[ \u00a0]/, // Japanese
   878         }
   879 			/^[\u58f1\u5f10\u53c2\u56db\u4f0d\u516d\u4e03\u516b\u4e5d\u62fe]+\.[ \u00a0]/  // Chinese
   879       }
   880 		];
   880       if (isKeyboardPasteEvent(e) && !e.isDefaultPrevented()) {
   881 
   881         keyboardPastePlainTextState = e.shiftKey && e.keyCode === 86;
   882 		text = text.replace(/^[\u00a0 ]+/, '');
   882         if (keyboardPastePlainTextState && global$1.webkit && navigator.userAgent.indexOf('Version/') !== -1) {
   883 
   883           return;
   884 		Tools.each(patterns, function(pattern) {
   884         }
   885 			if (pattern.test(text)) {
   885         e.stopImmediatePropagation();
   886 				found = true;
   886         keyboardPasteTimeStamp = new Date().getTime();
   887 				return false;
   887         if (global$1.ie && keyboardPastePlainTextState) {
   888 			}
   888           e.preventDefault();
   889 		});
   889           $_8tki3zijjjgwectj.firePaste(editor, true);
   890 
   890           return;
   891 		return found;
   891         }
   892 	}
   892         pasteBin.remove();
   893 
   893         pasteBin.create();
   894 	function isBulletList(text) {
   894         editor.once('keyup', removePasteBinOnKeyUp);
   895 		return /^[\s\u00a0]*[\u2022\u00b7\u00a7\u25CF]\s*/.test(text);
   895         editor.once('paste', function () {
   896 	}
   896           editor.off('keyup', removePasteBinOnKeyUp);
   897 
   897         });
   898 	function WordFilter(editor) {
   898       }
   899 		var settings = editor.settings;
   899     });
   900 
   900     function insertClipboardContent(clipboardContent, isKeyBoardPaste, plainTextMode, internal) {
   901 		editor.on('BeforePastePreProcess', function(e) {
   901       var content, isPlainTextHtml;
   902 			var content = e.content, retainStyleProperties, validStyles;
   902       if (hasContentType(clipboardContent, 'text/html')) {
   903 
   903         content = clipboardContent['text/html'];
   904 			// Remove google docs internal guid markers
   904       } else {
   905 			content = content.replace(/<b[^>]+id="?docs-internal-[^>]*>/gi, '');
   905         content = pasteBin.getHtml();
   906 			content = content.replace(/<br class="?Apple-interchange-newline"?>/gi, '');
   906         internal = internal ? internal : $_4x13hjirjjgwecu1.isMarked(content);
   907 
   907         if (pasteBin.isDefaultContent(content)) {
   908 			retainStyleProperties = settings.paste_retain_style_properties;
   908           plainTextMode = true;
   909 			if (retainStyleProperties) {
   909         }
   910 				validStyles = Tools.makeMap(retainStyleProperties.split(/[, ]/));
   910       }
   911 			}
   911       content = $_4bi2o9j0jjgwecui.trimHtml(content);
   912 
   912       pasteBin.remove();
   913 			/**
   913       isPlainTextHtml = internal === false && $_4h3hnrisjjgwecu2.isPlainText(content);
   914 			 * Converts fake bullet and numbered lists to real semantic OL/UL.
   914       if (!content.length || isPlainTextHtml) {
   915 			 *
   915         plainTextMode = true;
   916 			 * @param {tinymce.html.Node} node Root node to convert children of.
   916       }
   917 			 */
   917       if (plainTextMode) {
   918 			function convertFakeListsToProperLists(node) {
   918         if (hasContentType(clipboardContent, 'text/plain') && isPlainTextHtml) {
   919 				var currentListNode, prevListNode, lastLevel = 1;
   919           content = clipboardContent['text/plain'];
   920 
   920         } else {
   921 				function getText(node) {
   921           content = $_4bi2o9j0jjgwecui.innerText(content);
   922 					var txt = '';
   922         }
   923 
   923       }
   924 					if (node.type === 3) {
   924       if (pasteBin.isDefaultContent(content)) {
   925 						return node.value;
   925         if (!isKeyBoardPaste) {
   926 					}
   926           editor.windowManager.alert('Please use Ctrl+V/Cmd+V keyboard shortcuts to paste contents.');
   927 
   927         }
   928 					if ((node = node.firstChild)) {
   928         return;
   929 						do {
   929       }
   930 							txt += getText(node);
   930       if (plainTextMode) {
   931 						} while ((node = node.next));
   931         pasteText(editor, content);
   932 					}
   932       } else {
   933 
   933         pasteHtml$1(editor, content, internal);
   934 					return txt;
   934       }
   935 				}
   935     }
   936 
   936     var getLastRng = function () {
   937 				function trimListStart(node, regExp) {
   937       return pasteBin.getLastRng() || editor.selection.getRng();
   938 					if (node.type === 3) {
   938     };
   939 						if (regExp.test(node.value)) {
   939     editor.on('paste', function (e) {
   940 							node.value = node.value.replace(regExp, '');
   940       var clipboardTimer = new Date().getTime();
   941 							return false;
   941       var clipboardContent = getClipboardContent(editor, e);
   942 						}
   942       var clipboardDelay = new Date().getTime() - clipboardTimer;
   943 					}
   943       var isKeyBoardPaste = new Date().getTime() - keyboardPasteTimeStamp - clipboardDelay < 1000;
   944 
   944       var plainTextMode = pasteFormat.get() === 'text' || keyboardPastePlainTextState;
   945 					if ((node = node.firstChild)) {
   945       var internal = hasContentType(clipboardContent, $_4x13hjirjjgwecu1.internalHtmlMime());
   946 						do {
   946       keyboardPastePlainTextState = false;
   947 							if (!trimListStart(node, regExp)) {
   947       if (e.isDefaultPrevented() || isBrokenAndroidClipboardEvent(e)) {
   948 								return false;
   948         pasteBin.remove();
   949 							}
   949         return;
   950 						} while ((node = node.next));
   950       }
   951 					}
   951       if (!hasHtmlOrText(clipboardContent) && pasteImageData(editor, e, getLastRng())) {
   952 
   952         pasteBin.remove();
   953 					return true;
   953         return;
   954 				}
   954       }
   955 
   955       if (!isKeyBoardPaste) {
   956 				function removeIgnoredNodes(node) {
   956         e.preventDefault();
   957 					if (node._listIgnore) {
   957       }
   958 						node.remove();
   958       if (global$1.ie && (!isKeyBoardPaste || e.ieFake) && !hasContentType(clipboardContent, 'text/html')) {
   959 						return;
   959         pasteBin.create();
   960 					}
   960         editor.dom.bind(pasteBin.getEl(), 'paste', function (e) {
   961 
   961           e.stopPropagation();
   962 					if ((node = node.firstChild)) {
   962         });
   963 						do {
   963         editor.getDoc().execCommand('Paste', false, null);
   964 							removeIgnoredNodes(node);
   964         clipboardContent['text/html'] = pasteBin.getHtml();
   965 						} while ((node = node.next));
   965       }
   966 					}
   966       if (hasContentType(clipboardContent, 'text/html')) {
   967 				}
   967         e.preventDefault();
   968 
   968         if (!internal) {
   969 				function convertParagraphToLi(paragraphNode, listName, start) {
   969           internal = $_4x13hjirjjgwecu1.isMarked(clipboardContent['text/html']);
   970 					var level = paragraphNode._listLevel || lastLevel;
   970         }
   971 
   971         insertClipboardContent(clipboardContent, isKeyBoardPaste, plainTextMode, internal);
   972 					// Handle list nesting
   972       } else {
   973 					if (level != lastLevel) {
   973         global$2.setEditorTimeout(editor, function () {
   974 						if (level < lastLevel) {
   974           insertClipboardContent(clipboardContent, isKeyBoardPaste, plainTextMode, internal);
   975 							// Move to parent list
   975         }, 0);
   976 							if (currentListNode) {
   976       }
   977 								currentListNode = currentListNode.parent.parent;
   977     });
   978 							}
   978   };
   979 						} else {
   979   var registerEventsAndFilters = function (editor, pasteBin, pasteFormat) {
   980 							// Create new list
   980     registerEventHandlers(editor, pasteBin, pasteFormat);
   981 							prevListNode = currentListNode;
   981     var src;
   982 							currentListNode = null;
   982     editor.parser.addNodeFilter('img', function (nodes, name$$1, args) {
   983 						}
   983       var isPasteInsert = function (args) {
   984 					}
   984         return args.data && args.data.paste === true;
   985 
   985       };
   986 					if (!currentListNode || currentListNode.name != listName) {
   986       var remove = function (node) {
   987 						prevListNode = prevListNode || currentListNode;
   987         if (!node.attr('data-mce-object') && src !== global$1.transparentSrc) {
   988 						currentListNode = new Node(listName, 1);
   988           node.remove();
   989 
   989         }
   990 						if (start > 1) {
   990       };
   991 							currentListNode.attr('start', '' + start);
   991       var isWebKitFakeUrl = function (src) {
   992 						}
   992         return src.indexOf('webkit-fake-url') === 0;
   993 
   993       };
   994 						paragraphNode.wrap(currentListNode);
   994       var isDataUri = function (src) {
   995 					} else {
   995         return src.indexOf('data:') === 0;
   996 						currentListNode.append(paragraphNode);
   996       };
   997 					}
   997       if (!editor.settings.paste_data_images && isPasteInsert(args)) {
   998 
   998         var i = nodes.length;
   999 					paragraphNode.name = 'li';
   999         while (i--) {
  1000 
  1000           src = nodes[i].attributes.map.src;
  1001 					// Append list to previous list if it exists
  1001           if (!src) {
  1002 					if (level > lastLevel && prevListNode) {
  1002             continue;
  1003 						prevListNode.lastChild.append(currentListNode);
  1003           }
  1004 					}
  1004           if (isWebKitFakeUrl(src)) {
  1005 
  1005             remove(nodes[i]);
  1006 					lastLevel = level;
  1006           } else if (!editor.settings.allow_html_data_urls && isDataUri(src)) {
  1007 
  1007             remove(nodes[i]);
  1008 					// Remove start of list item "1. " or "&middot; " etc
  1008           }
  1009 					removeIgnoredNodes(paragraphNode);
  1009         }
  1010 					trimListStart(paragraphNode, /^\u00a0+/);
  1010       }
  1011 					trimListStart(paragraphNode, /^\s*([\u2022\u00b7\u00a7\u25CF]|\w+\.)/);
  1011     });
  1012 					trimListStart(paragraphNode, /^\u00a0+/);
  1012   };
  1013 				}
  1013 
  1014 
  1014   var getPasteBinParent = function (editor) {
  1015 				// Build a list of all root level elements before we start
  1015     return global$1.ie && editor.inline ? document.body : editor.getBody();
  1016 				// altering them in the loop below.
  1016   };
  1017 				var elements = [], child = node.firstChild;
  1017   var isExternalPasteBin = function (editor) {
  1018 				while (typeof child !== 'undefined' && child !== null) {
  1018     return getPasteBinParent(editor) !== editor.getBody();
  1019 					elements.push(child);
  1019   };
  1020 
  1020   var delegatePasteEvents = function (editor, pasteBinElm) {
  1021 					child = child.walk();
  1021     if (isExternalPasteBin(editor)) {
  1022 					if (child !== null) {
  1022       editor.dom.bind(pasteBinElm, 'paste keyup', function (e) {
  1023 						while (typeof child !== 'undefined' && child.parent !== node) {
  1023         setTimeout(function () {
  1024 							child = child.walk();
  1024           editor.fire('paste');
  1025 						}
  1025         }, 0);
  1026 					}
  1026       });
  1027 				}
  1027     }
  1028 
  1028   };
  1029 				for (var i = 0; i < elements.length; i++) {
  1029   var create = function (editor, lastRngCell, pasteBinDefaultContent) {
  1030 					node = elements[i];
  1030     var dom = editor.dom, body = editor.getBody();
  1031 
  1031     var pasteBinElm;
  1032 					if (node.name == 'p' && node.firstChild) {
  1032     lastRngCell.set(editor.selection.getRng());
  1033 						// Find first text node in paragraph
  1033     pasteBinElm = editor.dom.add(getPasteBinParent(editor), 'div', {
  1034 						var nodeText = getText(node);
  1034       'id': 'mcepastebin',
  1035 
  1035       'class': 'mce-pastebin',
  1036 						// Detect unordered lists look for bullets
  1036       'contentEditable': true,
  1037 						if (isBulletList(nodeText)) {
  1037       'data-mce-bogus': 'all',
  1038 							convertParagraphToLi(node, 'ul');
  1038       'style': 'position: fixed; top: 50%; width: 10px; height: 10px; overflow: hidden; opacity: 0'
  1039 							continue;
  1039     }, pasteBinDefaultContent);
  1040 						}
  1040     if (global$1.ie || global$1.gecko) {
  1041 
  1041       dom.setStyle(pasteBinElm, 'left', dom.getStyle(body, 'direction', true) === 'rtl' ? 65535 : -65535);
  1042 						// Detect ordered lists 1., a. or ixv.
  1042     }
  1043 						if (isNumericList(nodeText)) {
  1043     dom.bind(pasteBinElm, 'beforedeactivate focusin focusout', function (e) {
  1044 							// Parse OL start number
  1044       e.stopPropagation();
  1045 							var matches = /([0-9]+)\./.exec(nodeText);
  1045     });
  1046 							var start = 1;
  1046     delegatePasteEvents(editor, pasteBinElm);
  1047 							if (matches) {
  1047     pasteBinElm.focus();
  1048 								start = parseInt(matches[1], 10);
  1048     editor.selection.select(pasteBinElm, true);
  1049 							}
  1049   };
  1050 
  1050   var remove = function (editor, lastRngCell) {
  1051 							convertParagraphToLi(node, 'ol', start);
  1051     if (getEl(editor)) {
  1052 							continue;
  1052       var pasteBinClone = void 0;
  1053 						}
  1053       var lastRng = lastRngCell.get();
  1054 
  1054       while (pasteBinClone = editor.dom.get('mcepastebin')) {
  1055 						// Convert paragraphs marked as lists but doesn't look like anything
  1055         editor.dom.remove(pasteBinClone);
  1056 						if (node._listLevel) {
  1056         editor.dom.unbind(pasteBinClone);
  1057 							convertParagraphToLi(node, 'ul', 1);
  1057       }
  1058 							continue;
  1058       if (lastRng) {
  1059 						}
  1059         editor.selection.setRng(lastRng);
  1060 
  1060       }
  1061 						currentListNode = null;
  1061     }
  1062 					} else {
  1062     lastRngCell.set(null);
  1063 						// If the root level element isn't a p tag which can be
  1063   };
  1064 						// processed by convertParagraphToLi, it interrupts the
  1064   var getEl = function (editor) {
  1065 						// lists, causing a new list to start instead of having
  1065     return editor.dom.get('mcepastebin');
  1066 						// elements from the next list inserted above this tag.
  1066   };
  1067 						prevListNode = currentListNode;
  1067   var getHtml = function (editor) {
  1068 						currentListNode = null;
  1068     var pasteBinElm, pasteBinClones, i, dirtyWrappers, cleanWrapper;
  1069 					}
  1069     var copyAndRemove = function (toElm, fromElm) {
  1070 				}
  1070       toElm.appendChild(fromElm);
  1071 			}
  1071       editor.dom.remove(fromElm, true);
  1072 
  1072     };
  1073 			function filterStyles(node, styleValue) {
  1073     pasteBinClones = global$3.grep(getPasteBinParent(editor).childNodes, function (elm) {
  1074 				var outputStyles = {}, matches, styles = editor.dom.parseStyle(styleValue);
  1074       return elm.id === 'mcepastebin';
  1075 
  1075     });
  1076 				Tools.each(styles, function(value, name) {
  1076     pasteBinElm = pasteBinClones.shift();
  1077 					// Convert various MS styles to W3C styles
  1077     global$3.each(pasteBinClones, function (pasteBinClone) {
  1078 					switch (name) {
  1078       copyAndRemove(pasteBinElm, pasteBinClone);
  1079 						case 'mso-list':
  1079     });
  1080 							// Parse out list indent level for lists
  1080     dirtyWrappers = editor.dom.select('div[id=mcepastebin]', pasteBinElm);
  1081 							matches = /\w+ \w+([0-9]+)/i.exec(styleValue);
  1081     for (i = dirtyWrappers.length - 1; i >= 0; i--) {
  1082 							if (matches) {
  1082       cleanWrapper = editor.dom.create('div');
  1083 								node._listLevel = parseInt(matches[1], 10);
  1083       pasteBinElm.insertBefore(cleanWrapper, dirtyWrappers[i]);
  1084 							}
  1084       copyAndRemove(cleanWrapper, dirtyWrappers[i]);
  1085 
  1085     }
  1086 							// Remove these nodes <span style="mso-list:Ignore">o</span>
  1086     return pasteBinElm ? pasteBinElm.innerHTML : '';
  1087 							// Since the span gets removed we mark the text node and the span
  1087   };
  1088 							if (/Ignore/i.test(value) && node.firstChild) {
  1088   var getLastRng = function (lastRng) {
  1089 								node._listIgnore = true;
  1089     return lastRng.get();
  1090 								node.firstChild._listIgnore = true;
  1090   };
  1091 							}
  1091   var isDefaultContent = function (pasteBinDefaultContent, content) {
  1092 
  1092     return content === pasteBinDefaultContent;
  1093 							break;
  1093   };
  1094 
  1094   var isPasteBin = function (elm) {
  1095 						case "horiz-align":
  1095     return elm && elm.id === 'mcepastebin';
  1096 							name = "text-align";
  1096   };
  1097 							break;
  1097   var isDefault = function (editor, pasteBinDefaultContent) {
  1098 
  1098     var pasteBinElm = getEl(editor);
  1099 						case "vert-align":
  1099     return isPasteBin(pasteBinElm) && isDefaultContent(pasteBinDefaultContent, pasteBinElm.innerHTML);
  1100 							name = "vertical-align";
  1100   };
  1101 							break;
  1101   var PasteBin = function (editor) {
  1102 
  1102     var lastRng = Cell(null);
  1103 						case "font-color":
  1103     var pasteBinDefaultContent = '%MCEPASTEBIN%';
  1104 						case "mso-foreground":
  1104     return {
  1105 							name = "color";
  1105       create: function () {
  1106 							break;
  1106         return create(editor, lastRng, pasteBinDefaultContent);
  1107 
  1107       },
  1108 						case "mso-background":
  1108       remove: function () {
  1109 						case "mso-highlight":
  1109         return remove(editor, lastRng);
  1110 							name = "background";
  1110       },
  1111 							break;
  1111       getEl: function () {
  1112 
  1112         return getEl(editor);
  1113 						case "font-weight":
  1113       },
  1114 						case "font-style":
  1114       getHtml: function () {
  1115 							if (value != "normal") {
  1115         return getHtml(editor);
  1116 								outputStyles[name] = value;
  1116       },
  1117 							}
  1117       getLastRng: function () {
  1118 							return;
  1118         return getLastRng(lastRng);
  1119 
  1119       },
  1120 						case "mso-element":
  1120       isDefault: function () {
  1121 							// Remove track changes code
  1121         return isDefault(editor, pasteBinDefaultContent);
  1122 							if (/^(comment|comment-list)$/i.test(value)) {
  1122       },
  1123 								node.remove();
  1123       isDefaultContent: function (content) {
  1124 								return;
  1124         return isDefaultContent(pasteBinDefaultContent, content);
  1125 							}
  1125       }
  1126 
  1126     };
  1127 							break;
  1127   };
  1128 					}
  1128 
  1129 
  1129   var Clipboard = function (editor, pasteFormat) {
  1130 					if (name.indexOf('mso-comment') === 0) {
  1130     var pasteBin = PasteBin(editor);
  1131 						node.remove();
  1131     editor.on('preInit', function () {
  1132 						return;
  1132       return registerEventsAndFilters(editor, pasteBin, pasteFormat);
  1133 					}
  1133     });
  1134 
  1134     return {
  1135 					// Never allow mso- prefixed names
  1135       pasteFormat: pasteFormat,
  1136 					if (name.indexOf('mso-') === 0) {
  1136       pasteHtml: function (html, internalFlag) {
  1137 						return;
  1137         return pasteHtml$1(editor, html, internalFlag);
  1138 					}
  1138       },
  1139 
  1139       pasteText: function (text) {
  1140 					// Output only valid styles
  1140         return pasteText(editor, text);
  1141 					if (retainStyleProperties == "all" || (validStyles && validStyles[name])) {
  1141       },
  1142 						outputStyles[name] = value;
  1142       pasteImageData: function (e, rng) {
  1143 					}
  1143         return pasteImageData(editor, e, rng);
  1144 				});
  1144       },
  1145 
  1145       getDataTransferItems: getDataTransferItems,
  1146 				// Convert bold style to "b" element
  1146       hasHtmlOrText: hasHtmlOrText,
  1147 				if (/(bold)/i.test(outputStyles["font-weight"])) {
  1147       hasContentType: hasContentType
  1148 					delete outputStyles["font-weight"];
  1148     };
  1149 					node.wrap(new Node("b", 1));
  1149   };
  1150 				}
  1150 
  1151 
  1151   var noop = function () {
  1152 				// Convert italic style to "i" element
  1152   };
  1153 				if (/(italic)/i.test(outputStyles["font-style"])) {
  1153   var hasWorkingClipboardApi = function (clipboardData) {
  1154 					delete outputStyles["font-style"];
  1154     return global$1.iOS === false && clipboardData !== undefined && typeof clipboardData.setData === 'function' && $_4bi2o9j0jjgwecui.isMsEdge() !== true;
  1155 					node.wrap(new Node("i", 1));
  1155   };
  1156 				}
  1156   var setHtml5Clipboard = function (clipboardData, html, text) {
  1157 
  1157     if (hasWorkingClipboardApi(clipboardData)) {
  1158 				// Serialize the styles and see if there is something left to keep
  1158       try {
  1159 				outputStyles = editor.dom.serializeStyle(outputStyles, node.name);
  1159         clipboardData.clearData();
  1160 				if (outputStyles) {
  1160         clipboardData.setData('text/html', html);
  1161 					return outputStyles;
  1161         clipboardData.setData('text/plain', text);
  1162 				}
  1162         clipboardData.setData($_4x13hjirjjgwecu1.internalHtmlMime(), html);
  1163 
  1163         return true;
  1164 				return null;
  1164       } catch (e) {
  1165 			}
  1165         return false;
  1166 
  1166       }
  1167 			if (settings.paste_enable_default_filters === false) {
  1167     } else {
  1168 				return;
  1168       return false;
  1169 			}
  1169     }
  1170 
  1170   };
  1171 			// Detect is the contents is Word junk HTML
  1171   var setClipboardData = function (evt, data, fallback, done) {
  1172 			if (isWordContent(e.content)) {
  1172     if (setHtml5Clipboard(evt.clipboardData, data.html, data.text)) {
  1173 				e.wordContent = true; // Mark it for other processors
  1173       evt.preventDefault();
  1174 
  1174       done();
  1175 				// Remove basic Word junk
  1175     } else {
  1176 				content = Utils.filter(content, [
  1176       fallback(data.html, done);
  1177 					// Word comments like conditional comments etc
  1177     }
  1178 					/<!--[\s\S]+?-->/gi,
  1178   };
  1179 
  1179   var fallback = function (editor) {
  1180 					// Remove comments, scripts (e.g., msoShowComment), XML tag, VML content,
  1180     return function (html, done) {
  1181 					// MS Office namespaced tags, and a few other tags
  1181       var markedHtml = $_4x13hjirjjgwecu1.mark(html);
  1182 					/<(!|script[^>]*>.*?<\/script(?=[>\s])|\/?(\?xml(:\w+)?|img|meta|link|style|\w:\w+)(?=[\s\/>]))[^>]*>/gi,
  1182       var outer = editor.dom.create('div', {
  1183 
  1183         'contenteditable': 'false',
  1184 					// Convert <s> into <strike> for line-though
  1184         'data-mce-bogus': 'all'
  1185 					[/<(\/?)s>/gi, "<$1strike>"],
  1185       });
  1186 
  1186       var inner = editor.dom.create('div', { contenteditable: 'true' }, markedHtml);
  1187 					// Replace nsbp entites to char since it's easier to handle
  1187       editor.dom.setStyles(outer, {
  1188 					[/&nbsp;/gi, "\u00a0"],
  1188         position: 'fixed',
  1189 
  1189         top: '0',
  1190 					// Convert <span style="mso-spacerun:yes">___</span> to string of alternating
  1190         left: '-3000px',
  1191 					// breaking/non-breaking spaces of same length
  1191         width: '1000px',
  1192 					[/<span\s+style\s*=\s*"\s*mso-spacerun\s*:\s*yes\s*;?\s*"\s*>([\s\u00a0]*)<\/span>/gi,
  1192         overflow: 'hidden'
  1193 						function(str, spaces) {
  1193       });
  1194 							return (spaces.length > 0) ?
  1194       outer.appendChild(inner);
  1195 								spaces.replace(/./, " ").slice(Math.floor(spaces.length / 2)).split("").join("\u00a0") : "";
  1195       editor.dom.add(editor.getBody(), outer);
  1196 						}
  1196       var range = editor.selection.getRng();
  1197 					]
  1197       inner.focus();
  1198 				]);
  1198       var offscreenRange = editor.dom.createRng();
  1199 
  1199       offscreenRange.selectNodeContents(inner);
  1200 				var validElements = settings.paste_word_valid_elements;
  1200       editor.selection.setRng(offscreenRange);
  1201 				if (!validElements) {
  1201       setTimeout(function () {
  1202 					validElements = (
  1202         editor.selection.setRng(range);
  1203 						'-strong/b,-em/i,-u,-span,-p,-ol,-ul,-li,-h1,-h2,-h3,-h4,-h5,-h6,' +
  1203         outer.parentNode.removeChild(outer);
  1204 						'-p/div,-a[href|name],sub,sup,strike,br,del,table[width],tr,' +
  1204         done();
  1205 						'td[colspan|rowspan|width],th[colspan|rowspan|width],thead,tfoot,tbody'
  1205       }, 0);
  1206 					);
  1206     };
  1207 				}
  1207   };
  1208 
  1208   var getData = function (editor) {
  1209 				// Setup strict schema
  1209     return {
  1210 				var schema = new Schema({
  1210       html: editor.selection.getContent({ contextual: true }),
  1211 					valid_elements: validElements,
  1211       text: editor.selection.getContent({ format: 'text' })
  1212 					valid_children: '-li[p]'
  1212     };
  1213 				});
  1213   };
  1214 
  1214   var cut = function (editor) {
  1215 				// Add style/class attribute to all element rules since the user might have removed them from
  1215     return function (evt) {
  1216 				// paste_word_valid_elements config option and we need to check them for properties
  1216       if (editor.selection.isCollapsed() === false) {
  1217 				Tools.each(schema.elements, function(rule) {
  1217         setClipboardData(evt, getData(editor), fallback(editor), function () {
  1218 					/*eslint dot-notation:0*/
  1218           setTimeout(function () {
  1219 					if (!rule.attributes["class"]) {
  1219             editor.execCommand('Delete');
  1220 						rule.attributes["class"] = {};
  1220           }, 0);
  1221 						rule.attributesOrder.push("class");
  1221         });
  1222 					}
  1222       }
  1223 
  1223     };
  1224 					if (!rule.attributes.style) {
  1224   };
  1225 						rule.attributes.style = {};
  1225   var copy = function (editor) {
  1226 						rule.attributesOrder.push("style");
  1226     return function (evt) {
  1227 					}
  1227       if (editor.selection.isCollapsed() === false) {
  1228 				});
  1228         setClipboardData(evt, getData(editor), fallback(editor), noop);
  1229 
  1229       }
  1230 				// Parse HTML into DOM structure
  1230     };
  1231 				var domParser = new DomParser({}, schema);
  1231   };
  1232 
  1232   var register$1 = function (editor) {
  1233 				// Filter styles to remove "mso" specific styles and convert some of them
  1233     editor.on('cut', cut(editor));
  1234 				domParser.addAttributeFilter('style', function(nodes) {
  1234     editor.on('copy', copy(editor));
  1235 					var i = nodes.length, node;
  1235   };
  1236 
  1236   var $_32blojj3jjgwecv4 = { register: register$1 };
  1237 					while (i--) {
  1237 
  1238 						node = nodes[i];
  1238   var global$10 = tinymce.util.Tools.resolve('tinymce.dom.RangeUtils');
  1239 						node.attr('style', filterStyles(node, node.attr('style')));
  1239 
  1240 
  1240   var getCaretRangeFromEvent = function (editor, e) {
  1241 						// Remove pointess spans
  1241     return global$10.getCaretRangeFromPoint(e.clientX, e.clientY, editor.getDoc());
  1242 						if (node.name == 'span' && node.parent && !node.attributes.length) {
  1242   };
  1243 							node.unwrap();
  1243   var isPlainTextFileUrl = function (content) {
  1244 						}
  1244     var plainTextContent = content['text/plain'];
  1245 					}
  1245     return plainTextContent ? plainTextContent.indexOf('file://') === 0 : false;
  1246 				});
  1246   };
  1247 
  1247   var setFocusedRange = function (editor, rng) {
  1248 				// Check the class attribute for comments or del items and remove those
  1248     editor.focus();
  1249 				domParser.addAttributeFilter('class', function(nodes) {
  1249     editor.selection.setRng(rng);
  1250 					var i = nodes.length, node, className;
  1250   };
  1251 
  1251   var setup = function (editor, clipboard, draggingInternallyState) {
  1252 					while (i--) {
  1252     if ($_xr8b0ikjjgwectl.shouldBlockDrop(editor)) {
  1253 						node = nodes[i];
  1253       editor.on('dragend dragover draggesture dragdrop drop drag', function (e) {
  1254 
  1254         e.preventDefault();
  1255 						className = node.attr('class');
  1255         e.stopPropagation();
  1256 						if (/^(MsoCommentReference|MsoCommentText|msoDel)$/i.test(className)) {
  1256       });
  1257 							node.remove();
  1257     }
  1258 						}
  1258     if (!$_xr8b0ikjjgwectl.shouldPasteDataImages(editor)) {
  1259 
  1259       editor.on('drop', function (e) {
  1260 						node.attr('class', null);
  1260         var dataTransfer = e.dataTransfer;
  1261 					}
  1261         if (dataTransfer && dataTransfer.files && dataTransfer.files.length > 0) {
  1262 				});
  1262           e.preventDefault();
  1263 
  1263         }
  1264 				// Remove all del elements since we don't want the track changes code in the editor
  1264       });
  1265 				domParser.addNodeFilter('del', function(nodes) {
  1265     }
  1266 					var i = nodes.length;
  1266     editor.on('drop', function (e) {
  1267 
  1267       var dropContent, rng;
  1268 					while (i--) {
  1268       rng = getCaretRangeFromEvent(editor, e);
  1269 						nodes[i].remove();
  1269       if (e.isDefaultPrevented() || draggingInternallyState.get()) {
  1270 					}
  1270         return;
  1271 				});
  1271       }
  1272 
  1272       dropContent = clipboard.getDataTransferItems(e.dataTransfer);
  1273 				// Keep some of the links and anchors
  1273       var internal = clipboard.hasContentType(dropContent, $_4x13hjirjjgwecu1.internalHtmlMime());
  1274 				domParser.addNodeFilter('a', function(nodes) {
  1274       if ((!clipboard.hasHtmlOrText(dropContent) || isPlainTextFileUrl(dropContent)) && clipboard.pasteImageData(e, rng)) {
  1275 					var i = nodes.length, node, href, name;
  1275         return;
  1276 
  1276       }
  1277 					while (i--) {
  1277       if (rng && $_xr8b0ikjjgwectl.shouldFilterDrop(editor)) {
  1278 						node = nodes[i];
  1278         var content_1 = dropContent['mce-internal'] || dropContent['text/html'] || dropContent['text/plain'];
  1279 						href = node.attr('href');
  1279         if (content_1) {
  1280 						name = node.attr('name');
  1280           e.preventDefault();
  1281 
  1281           global$2.setEditorTimeout(editor, function () {
  1282 						if (href && href.indexOf('#_msocom_') != -1) {
  1282             editor.undoManager.transact(function () {
  1283 							node.remove();
  1283               if (dropContent['mce-internal']) {
  1284 							continue;
  1284                 editor.execCommand('Delete');
  1285 						}
  1285               }
  1286 
  1286               setFocusedRange(editor, rng);
  1287 						if (href && href.indexOf('file://') === 0) {
  1287               content_1 = $_4bi2o9j0jjgwecui.trimHtml(content_1);
  1288 							href = href.split('#')[1];
  1288               if (!dropContent['text/html']) {
  1289 							if (href) {
  1289                 clipboard.pasteText(content_1);
  1290 								href = '#' + href;
  1290               } else {
  1291 							}
  1291                 clipboard.pasteHtml(content_1, internal);
  1292 						}
  1292               }
  1293 
  1293             });
  1294 						if (!href && !name) {
  1294           });
  1295 							node.unwrap();
  1295         }
  1296 						} else {
  1296       }
  1297 							// Remove all named anchors that aren't specific to TOC, Footnotes or Endnotes
  1297     });
  1298 							if (name && !/^_?(?:toc|edn|ftn)/i.test(name)) {
  1298     editor.on('dragstart', function (e) {
  1299 								node.unwrap();
  1299       draggingInternallyState.set(true);
  1300 								continue;
  1300     });
  1301 							}
  1301     editor.on('dragover dragend', function (e) {
  1302 
  1302       if ($_xr8b0ikjjgwectl.shouldPasteDataImages(editor) && draggingInternallyState.get() === false) {
  1303 							node.attr({
  1303         e.preventDefault();
  1304 								href: href,
  1304         setFocusedRange(editor, getCaretRangeFromEvent(editor, e));
  1305 								name: name
  1305       }
  1306 							});
  1306       if (e.type === 'dragend') {
  1307 						}
  1307         draggingInternallyState.set(false);
  1308 					}
  1308       }
  1309 				});
  1309     });
  1310 
  1310   };
  1311 				// Parse into DOM structure
  1311   var $_b4etj0j4jjgwecv7 = { setup: setup };
  1312 				var rootNode = domParser.parse(content);
  1312 
  1313 
  1313   var setup$1 = function (editor) {
  1314 				// Process DOM
  1314     var plugin = editor.plugins.paste;
  1315 				if (settings.paste_convert_word_fake_lists !== false) {
  1315     var preProcess = $_xr8b0ikjjgwectl.getPreProcess(editor);
  1316 					convertFakeListsToProperLists(rootNode);
  1316     if (preProcess) {
  1317 				}
  1317       editor.on('PastePreProcess', function (e) {
  1318 
  1318         preProcess.call(plugin, plugin, e);
  1319 				// Serialize DOM back to HTML
  1319       });
  1320 				e.content = new Serializer({}, schema).serialize(rootNode);
  1320     }
  1321 			}
  1321     var postProcess = $_xr8b0ikjjgwectl.getPostProcess(editor);
  1322 		});
  1322     if (postProcess) {
  1323 	}
  1323       editor.on('PastePostProcess', function (e) {
  1324 
  1324         postProcess.call(plugin, plugin, e);
  1325 	WordFilter.isWordContent = isWordContent;
  1325       });
  1326 
  1326     }
  1327 	return WordFilter;
  1327   };
  1328 });
  1328   var $_c5bihmj6jjgwecva = { setup: setup$1 };
  1329 
  1329 
  1330 // Included from: js/tinymce/plugins/paste/classes/Quirks.js
  1330   function addPreProcessFilter(editor, filterFunc) {
  1331 
  1331     editor.on('PastePreProcess', function (e) {
  1332 /**
  1332       e.content = filterFunc(editor, e.content, e.internal, e.wordContent);
  1333  * Quirks.js
  1333     });
  1334  *
  1334   }
  1335  * Copyright, Moxiecode Systems AB
  1335   function addPostProcessFilter(editor, filterFunc) {
  1336  * Released under LGPL License.
  1336     editor.on('PastePostProcess', function (e) {
  1337  *
  1337       filterFunc(editor, e.node);
  1338  * License: http://www.tinymce.com/license
  1338     });
  1339  * Contributing: http://www.tinymce.com/contributing
  1339   }
  1340  */
  1340   function removeExplorerBrElementsAfterBlocks(editor, html) {
  1341 
  1341     if (!$_dfatuiivjjgwecu8.isWordContent(html)) {
  1342 /**
  1342       return html;
  1343  * This class contains various fixes for browsers. These issues can not be feature
  1343     }
  1344  * detected since we have no direct control over the clipboard. However we might be able
  1344     var blockElements = [];
  1345  * to remove some of these fixes once the browsers gets updated/fixed.
  1345     global$3.each(editor.schema.getBlockElements(), function (block, blockName) {
  1346  *
  1346       blockElements.push(blockName);
  1347  * @class tinymce.pasteplugin.Quirks
  1347     });
  1348  * @private
  1348     var explorerBlocksRegExp = new RegExp('(?:<br>&nbsp;[\\s\\r\\n]+|<br>)*(<\\/?(' + blockElements.join('|') + ')[^>]*>)(?:<br>&nbsp;[\\s\\r\\n]+|<br>)*', 'g');
  1349  */
  1349     html = $_4bi2o9j0jjgwecui.filter(html, [[
  1350 define("tinymce/pasteplugin/Quirks", [
  1350         explorerBlocksRegExp,
  1351 	"tinymce/Env",
  1351         '$1'
  1352 	"tinymce/util/Tools",
  1352       ]]);
  1353 	"tinymce/pasteplugin/WordFilter",
  1353     html = $_4bi2o9j0jjgwecui.filter(html, [
  1354 	"tinymce/pasteplugin/Utils"
  1354       [
  1355 ], function(Env, Tools, WordFilter, Utils) {
  1355         /<br><br>/g,
  1356 	"use strict";
  1356         '<BR><BR>'
  1357 
  1357       ],
  1358 	return function(editor) {
  1358       [
  1359 		function addPreProcessFilter(filterFunc) {
  1359         /<br>/g,
  1360 			editor.on('BeforePastePreProcess', function(e) {
  1360         ' '
  1361 				e.content = filterFunc(e.content);
  1361       ],
  1362 			});
  1362       [
  1363 		}
  1363         /<BR><BR>/g,
  1364 
  1364         '<br>'
  1365 		/**
  1365       ]
  1366 		 * Removes BR elements after block elements. IE9 has a nasty bug where it puts a BR element after each
  1366     ]);
  1367 		 * block element when pasting from word. This removes those elements.
  1367     return html;
  1368 		 *
  1368   }
  1369 		 * This:
  1369   function removeWebKitStyles(editor, content, internal, isWordHtml) {
  1370 		 *  <p>a</p><br><p>b</p>
  1370     if (isWordHtml || internal) {
  1371 		 *
  1371       return content;
  1372 		 * Becomes:
  1372     }
  1373 		 *  <p>a</p><p>b</p>
  1373     var webKitStylesSetting = $_xr8b0ikjjgwectl.getWebkitStyles(editor);
  1374 		 */
  1374     var webKitStyles;
  1375 		function removeExplorerBrElementsAfterBlocks(html) {
  1375     if ($_xr8b0ikjjgwectl.shouldRemoveWebKitStyles(editor) === false || webKitStylesSetting === 'all') {
  1376 			// Only filter word specific content
  1376       return content;
  1377 			if (!WordFilter.isWordContent(html)) {
  1377     }
  1378 				return html;
  1378     if (webKitStylesSetting) {
  1379 			}
  1379       webKitStyles = webKitStylesSetting.split(/[, ]/);
  1380 
  1380     }
  1381 			// Produce block regexp based on the block elements in schema
  1381     if (webKitStyles) {
  1382 			var blockElements = [];
  1382       var dom_1 = editor.dom, node_1 = editor.selection.getNode();
  1383 
  1383       content = content.replace(/(<[^>]+) style="([^"]*)"([^>]*>)/gi, function (all, before, value, after) {
  1384 			Tools.each(editor.schema.getBlockElements(), function(block, blockName) {
  1384         var inputStyles = dom_1.parseStyle(dom_1.decode(value));
  1385 				blockElements.push(blockName);
  1385         var outputStyles = {};
  1386 			});
  1386         if (webKitStyles === 'none') {
  1387 
  1387           return before + after;
  1388 			var explorerBlocksRegExp = new RegExp(
  1388         }
  1389 				'(?:<br>&nbsp;[\\s\\r\\n]+|<br>)*(<\\/?(' + blockElements.join('|') + ')[^>]*>)(?:<br>&nbsp;[\\s\\r\\n]+|<br>)*',
  1389         for (var i = 0; i < webKitStyles.length; i++) {
  1390 				'g'
  1390           var inputValue = inputStyles[webKitStyles[i]], currentValue = dom_1.getStyle(node_1, webKitStyles[i], true);
  1391 			);
  1391           if (/color/.test(webKitStyles[i])) {
  1392 
  1392             inputValue = dom_1.toHex(inputValue);
  1393 			// Remove BR:s from: <BLOCK>X</BLOCK><BR>
  1393             currentValue = dom_1.toHex(currentValue);
  1394 			html = Utils.filter(html, [
  1394           }
  1395 				[explorerBlocksRegExp, '$1']
  1395           if (currentValue !== inputValue) {
  1396 			]);
  1396             outputStyles[webKitStyles[i]] = inputValue;
  1397 
  1397           }
  1398 			// IE9 also adds an extra BR element for each soft-linefeed and it also adds a BR for each word wrap break
  1398         }
  1399 			html = Utils.filter(html, [
  1399         outputStyles = dom_1.serializeStyle(outputStyles, 'span');
  1400 				[/<br><br>/g, '<BR><BR>'], // Replace multiple BR elements with uppercase BR to keep them intact
  1400         if (outputStyles) {
  1401 				[/<br>/g, ' '],            // Replace single br elements with space since they are word wrap BR:s
  1401           return before + ' style="' + outputStyles + '"' + after;
  1402 				[/<BR><BR>/g, '<br>']      // Replace back the double brs but into a single BR
  1402         }
  1403 			]);
  1403         return before + after;
  1404 
  1404       });
  1405 			return html;
  1405     } else {
  1406 		}
  1406       content = content.replace(/(<[^>]+) style="([^"]*)"([^>]*>)/gi, '$1$3');
  1407 
  1407     }
  1408 		/**
  1408     content = content.replace(/(<[^>]+) data-mce-style="([^"]+)"([^>]*>)/gi, function (all, before, value, after) {
  1409 		 * WebKit has a nasty bug where the all computed styles gets added to style attributes when copy/pasting contents.
  1409       return before + ' style="' + value + '"' + after;
  1410 		 * This fix solves that by simply removing the whole style attribute.
  1410     });
  1411 		 *
  1411     return content;
  1412 		 * The paste_webkit_styles option can be set to specify what to keep:
  1412   }
  1413 		 *  paste_webkit_styles: "none" // Keep no styles
  1413   function removeUnderlineAndFontInAnchor(editor, root) {
  1414 		 *  paste_webkit_styles: "all", // Keep all of them
  1414     editor.$('a', root).find('font,u').each(function (i, node) {
  1415 		 *  paste_webkit_styles: "font-weight color" // Keep specific ones
  1415       editor.dom.remove(node, true);
  1416 		 *
  1416     });
  1417 		 * @param {String} content Content that needs to be processed.
  1417   }
  1418 		 * @return {String} Processed contents.
  1418   var setup$2 = function (editor) {
  1419 		 */
  1419     if (global$1.webkit) {
  1420 		function removeWebKitStyles(content) {
  1420       addPreProcessFilter(editor, removeWebKitStyles);
  1421 			// Passthrough all styles from Word and let the WordFilter handle that junk
  1421     }
  1422 			if (WordFilter.isWordContent(content)) {
  1422     if (global$1.ie) {
  1423 				return content;
  1423       addPreProcessFilter(editor, removeExplorerBrElementsAfterBlocks);
  1424 			}
  1424       addPostProcessFilter(editor, removeUnderlineAndFontInAnchor);
  1425 
  1425     }
  1426 			// Filter away styles that isn't matching the target node
  1426   };
  1427 			var webKitStyles = editor.settings.paste_webkit_styles;
  1427   var $_36tmgyj7jjgwecvc = { setup: setup$2 };
  1428 
  1428 
  1429 			if (editor.settings.paste_remove_styles_if_webkit === false || webKitStyles == "all") {
  1429   var curry = function (f) {
  1430 				return content;
  1430     var x = [];
  1431 			}
  1431     for (var _i = 1; _i < arguments.length; _i++) {
  1432 
  1432       x[_i - 1] = arguments[_i];
  1433 			if (webKitStyles) {
  1433     }
  1434 				webKitStyles = webKitStyles.split(/[, ]/);
  1434     var args = new Array(arguments.length - 1);
  1435 			}
  1435     for (var i = 1; i < arguments.length; i++)
  1436 
  1436       args[i - 1] = arguments[i];
  1437 			// Keep specific styles that doesn't match the current node computed style
  1437     return function () {
  1438 			if (webKitStyles) {
  1438       var x = [];
  1439 				var dom = editor.dom, node = editor.selection.getNode();
  1439       for (var _i = 0; _i < arguments.length; _i++) {
  1440 
  1440         x[_i] = arguments[_i];
  1441 				content = content.replace(/(<[^>]+) style="([^"]*)"([^>]*>)/gi, function(all, before, value, after) {
  1441       }
  1442 					var inputStyles = dom.parseStyle(value, 'span'), outputStyles = {};
  1442       var newArgs = new Array(arguments.length);
  1443 
  1443       for (var j = 0; j < newArgs.length; j++)
  1444 					if (webKitStyles === "none") {
  1444         newArgs[j] = arguments[j];
  1445 						return before + after;
  1445       var all = args.concat(newArgs);
  1446 					}
  1446       return f.apply(null, all);
  1447 
  1447     };
  1448 					for (var i = 0; i < webKitStyles.length; i++) {
  1448   };
  1449 						var inputValue = inputStyles[webKitStyles[i]], currentValue = dom.getStyle(node, webKitStyles[i], true);
  1449 
  1450 
  1450   var stateChange = function (editor, clipboard, e) {
  1451 						if (/color/.test(webKitStyles[i])) {
  1451     var ctrl = e.control;
  1452 							inputValue = dom.toHex(inputValue);
  1452     ctrl.active(clipboard.pasteFormat.get() === 'text');
  1453 							currentValue = dom.toHex(currentValue);
  1453     editor.on('PastePlainTextToggle', function (e) {
  1454 						}
  1454       ctrl.active(e.state);
  1455 
  1455     });
  1456 						if (currentValue != inputValue) {
  1456   };
  1457 							outputStyles[webKitStyles[i]] = inputValue;
  1457   var register$2 = function (editor, clipboard) {
  1458 						}
  1458     var postRender = curry(stateChange, editor, clipboard);
  1459 					}
  1459     editor.addButton('pastetext', {
  1460 
  1460       active: false,
  1461 					outputStyles = dom.serializeStyle(outputStyles, 'span');
  1461       icon: 'pastetext',
  1462 					if (outputStyles) {
  1462       tooltip: 'Paste as text',
  1463 						return before + ' style="' + outputStyles + '"' + after;
  1463       cmd: 'mceTogglePlainTextPaste',
  1464 					}
  1464       onPostRender: postRender
  1465 
  1465     });
  1466 					return before + after;
  1466     editor.addMenuItem('pastetext', {
  1467 				});
  1467       text: 'Paste as text',
  1468 			} else {
  1468       selectable: true,
  1469 				// Remove all external styles
  1469       active: clipboard.pasteFormat,
  1470 				content = content.replace(/(<[^>]+) style="([^"]*)"([^>]*>)/gi, '$1$3');
  1470       cmd: 'mceTogglePlainTextPaste',
  1471 			}
  1471       onPostRender: postRender
  1472 
  1472     });
  1473 			// Keep internal styles
  1473   };
  1474 			content = content.replace(/(<[^>]+) data-mce-style="([^"]+)"([^>]*>)/gi, function(all, before, value, after) {
  1474   var $_g9yhwdj8jjgwecvf = { register: register$2 };
  1475 				return before + ' style="' + value + '"' + after;
  1475 
  1476 			});
  1476   global.add('paste', function (editor) {
  1477 
  1477     if ($_15bf6siejjgwect1.hasProPlugin(editor) === false) {
  1478 			return content;
  1478       var userIsInformedState = Cell(false);
  1479 		}
  1479       var draggingInternallyState = Cell(false);
  1480 
  1480       var pasteFormat = Cell($_xr8b0ikjjgwectl.isPasteAsTextEnabled(editor) ? 'text' : 'html');
  1481 		// Sniff browsers and apply fixes since we can't feature detect
  1481       var clipboard = Clipboard(editor, pasteFormat);
  1482 		if (Env.webkit) {
  1482       var quirks = $_36tmgyj7jjgwecvc.setup(editor);
  1483 			addPreProcessFilter(removeWebKitStyles);
  1483       $_g9yhwdj8jjgwecvf.register(editor, clipboard);
  1484 		}
  1484       $_fldd1mihjjgwecth.register(editor, clipboard, userIsInformedState);
  1485 
  1485       $_c5bihmj6jjgwecva.setup(editor);
  1486 		if (Env.ie) {
  1486       $_32blojj3jjgwecv4.register(editor);
  1487 			addPreProcessFilter(removeExplorerBrElementsAfterBlocks);
  1487       $_b4etj0j4jjgwecv7.setup(editor, clipboard, draggingInternallyState);
  1488 		}
  1488       return $_6gtliyigjjgwecte.get(clipboard, quirks);
  1489 	};
  1489     }
  1490 });
  1490   });
  1491 
  1491   function Plugin () {
  1492 // Included from: js/tinymce/plugins/paste/classes/Plugin.js
  1492   }
  1493 
  1493 
  1494 /**
  1494   return Plugin;
  1495  * Plugin.js
  1495 
  1496  *
  1496 }());
  1497  * Copyright, Moxiecode Systems AB
  1497 })();
  1498  * Released under LGPL License.
       
  1499  *
       
  1500  * License: http://www.tinymce.com/license
       
  1501  * Contributing: http://www.tinymce.com/contributing
       
  1502  */
       
  1503 
       
  1504 /**
       
  1505  * This class contains the tinymce plugin logic for the paste plugin.
       
  1506  *
       
  1507  * @class tinymce.pasteplugin.Plugin
       
  1508  * @private
       
  1509  */
       
  1510 define("tinymce/pasteplugin/Plugin", [
       
  1511 	"tinymce/PluginManager",
       
  1512 	"tinymce/pasteplugin/Clipboard",
       
  1513 	"tinymce/pasteplugin/WordFilter",
       
  1514 	"tinymce/pasteplugin/Quirks"
       
  1515 ], function(PluginManager, Clipboard, WordFilter, Quirks) {
       
  1516 	var userIsInformed;
       
  1517 
       
  1518 	PluginManager.add('paste', function(editor) {
       
  1519 		var self = this, clipboard, settings = editor.settings;
       
  1520 
       
  1521 		function togglePlainTextPaste() {
       
  1522 			if (clipboard.pasteFormat == "text") {
       
  1523 				this.active(false);
       
  1524 				clipboard.pasteFormat = "html";
       
  1525 			} else {
       
  1526 				clipboard.pasteFormat = "text";
       
  1527 				this.active(true);
       
  1528 
       
  1529 				if (!userIsInformed) {
       
  1530 					editor.windowManager.alert(
       
  1531 						'Paste is now in plain text mode. Contents will now ' +
       
  1532 						'be pasted as plain text until you toggle this option off.'
       
  1533 					);
       
  1534 
       
  1535 					userIsInformed = true;
       
  1536 				}
       
  1537 			}
       
  1538 		}
       
  1539 
       
  1540 		self.clipboard = clipboard = new Clipboard(editor);
       
  1541 		self.quirks = new Quirks(editor);
       
  1542 		self.wordFilter = new WordFilter(editor);
       
  1543 
       
  1544 		if (editor.settings.paste_as_text) {
       
  1545 			self.clipboard.pasteFormat = "text";
       
  1546 		}
       
  1547 
       
  1548 		if (settings.paste_preprocess) {
       
  1549 			editor.on('PastePreProcess', function(e) {
       
  1550 				settings.paste_preprocess.call(self, self, e);
       
  1551 			});
       
  1552 		}
       
  1553 
       
  1554 		if (settings.paste_postprocess) {
       
  1555 			editor.on('PastePostProcess', function(e) {
       
  1556 				settings.paste_postprocess.call(self, self, e);
       
  1557 			});
       
  1558 		}
       
  1559 
       
  1560 		editor.addCommand('mceInsertClipboardContent', function(ui, value) {
       
  1561 			if (value.content) {
       
  1562 				self.clipboard.pasteHtml(value.content);
       
  1563 			}
       
  1564 
       
  1565 			if (value.text) {
       
  1566 				self.clipboard.pasteText(value.text);
       
  1567 			}
       
  1568 		});
       
  1569 
       
  1570 		// Block all drag/drop events
       
  1571 		if (editor.paste_block_drop) {
       
  1572 			editor.on('dragend dragover draggesture dragdrop drop drag', function(e) {
       
  1573 				e.preventDefault();
       
  1574 				e.stopPropagation();
       
  1575 			});
       
  1576 		}
       
  1577 
       
  1578 		// Prevent users from dropping data images on Gecko
       
  1579 		if (!editor.settings.paste_data_images) {
       
  1580 			editor.on('drop', function(e) {
       
  1581 				var dataTransfer = e.dataTransfer;
       
  1582 
       
  1583 				if (dataTransfer && dataTransfer.files && dataTransfer.files.length > 0) {
       
  1584 					e.preventDefault();
       
  1585 				}
       
  1586 			});
       
  1587 		}
       
  1588 
       
  1589 		editor.addButton('pastetext', {
       
  1590 			icon: 'pastetext',
       
  1591 			tooltip: 'Paste as text',
       
  1592 			onclick: togglePlainTextPaste,
       
  1593 			active: self.clipboard.pasteFormat == "text"
       
  1594 		});
       
  1595 
       
  1596 		editor.addMenuItem('pastetext', {
       
  1597 			text: 'Paste as text',
       
  1598 			selectable: true,
       
  1599 			active: clipboard.pasteFormat,
       
  1600 			onclick: togglePlainTextPaste
       
  1601 		});
       
  1602 	});
       
  1603 });
       
  1604 
       
  1605 expose(["tinymce/pasteplugin/Utils"]);
       
  1606 })(this);