From 31d09c5e04e24502d8d1e6d3ed7ceec3031f35c9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Niels=20Lyngs=C3=B8?= Date: Thu, 12 Sep 2019 13:47:29 +0200 Subject: [PATCH 01/10] paste tidying --- .../common/mocks/editors/prevalues.mocks.js | 2 +- .../src/common/services/tinymce.service.js | 44 ++++++++++++++++++- 2 files changed, 44 insertions(+), 2 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/common/mocks/editors/prevalues.mocks.js b/src/Umbraco.Web.UI.Client/src/common/mocks/editors/prevalues.mocks.js index a77cea15fa..96ce626c44 100644 --- a/src/Umbraco.Web.UI.Client/src/common/mocks/editors/prevalues.mocks.js +++ b/src/Umbraco.Web.UI.Client/src/common/mocks/editors/prevalues.mocks.js @@ -7,7 +7,7 @@ angular.module('umbraco.mocks'). return [401, null, null]; } else { - return [200, { "plugins": [{ "name": "code", "useOnFrontend": true }, { "name": "paste", "useOnFrontend": true }, { "name": "umbracolink", "useOnFrontend": true }], "commands": [{ "icon": "images/editor/code.gif", "command": "code", "alias": "code", "frontEndCommand": "code", "value": "", "priority": 1, "isStylePicker": false }, { "icon": "images/editor/removeformat.gif", "command": "removeformat", "alias": "removeformat", "frontEndCommand": "removeformat", "value": "", "priority": 2, "isStylePicker": false }, { "icon": "images/editor/undo.gif", "command": "undo", "alias": "undo", "frontEndCommand": "undo", "value": "", "priority": 11, "isStylePicker": false }, { "icon": "images/editor/redo.gif", "command": "redo", "alias": "redo", "frontEndCommand": "redo", "value": "", "priority": 12, "isStylePicker": false }, { "icon": "images/editor/cut.gif", "command": "cut", "alias": "cut", "frontEndCommand": "cut", "value": "", "priority": 13, "isStylePicker": false }, { "icon": "images/editor/copy.gif", "command": "copy", "alias": "copy", "frontEndCommand": "copy", "value": "", "priority": 14, "isStylePicker": false }, { "icon": "images/editor/showStyles.png", "command": "styleselect", "alias": "styleselect", "frontEndCommand": "styleselect", "value": "", "priority": 20, "isStylePicker": false }, { "icon": "images/editor/bold.gif", "command": "bold", "alias": "bold", "frontEndCommand": "bold", "value": "", "priority": 21, "isStylePicker": false }, { "icon": "images/editor/italic.gif", "command": "italic", "alias": "italic", "frontEndCommand": "italic", "value": "", "priority": 22, "isStylePicker": false }, { "icon": "images/editor/underline.gif", "command": "underline", "alias": "underline", "frontEndCommand": "underline", "value": "", "priority": 23, "isStylePicker": false }, { "icon": "images/editor/strikethrough.gif", "command": "strikethrough", "alias": "strikethrough", "frontEndCommand": "strikethrough", "value": "", "priority": 24, "isStylePicker": false }, { "icon": "images/editor/justifyleft.gif", "command": "justifyleft", "alias": "justifyleft", "frontEndCommand": "alignleft", "value": "", "priority": 31, "isStylePicker": false }, { "icon": "images/editor/justifycenter.gif", "command": "justifycenter", "alias": "justifycenter", "frontEndCommand": "aligncenter", "value": "", "priority": 32, "isStylePicker": false }, { "icon": "images/editor/justifyright.gif", "command": "justifyright", "alias": "justifyright", "frontEndCommand": "alignright", "value": "", "priority": 33, "isStylePicker": false }, { "icon": "images/editor/justifyfull.gif", "command": "justifyfull", "alias": "justifyfull", "frontEndCommand": "alignfull", "value": "", "priority": 34, "isStylePicker": false }, { "icon": "images/editor/bullist.gif", "command": "bullist", "alias": "bullist", "frontEndCommand": "bullist", "value": "", "priority": 41, "isStylePicker": false }, { "icon": "images/editor/numlist.gif", "command": "numlist", "alias": "numlist", "frontEndCommand": "numlist", "value": "", "priority": 42, "isStylePicker": false }, { "icon": "images/editor/outdent.gif", "command": "outdent", "alias": "outdent", "frontEndCommand": "outdent", "value": "", "priority": 43, "isStylePicker": false }, { "icon": "images/editor/indent.gif", "command": "indent", "alias": "indent", "frontEndCommand": "indent", "value": "", "priority": 44, "isStylePicker": false }, { "icon": "images/editor/link.gif", "command": "link", "alias": "mcelink", "frontEndCommand": "link", "value": "", "priority": 51, "isStylePicker": false }, { "icon": "images/editor/unLink.gif", "command": "unlink", "alias": "unlink", "frontEndCommand": "unlink", "value": "", "priority": 52, "isStylePicker": false }, { "icon": "images/editor/anchor.gif", "command": "anchor", "alias": "mceinsertanchor", "frontEndCommand": "anchor", "value": "", "priority": 53, "isStylePicker": false }, { "icon": "images/editor/image.gif", "command": "image", "alias": "mceimage", "frontEndCommand": "umbmediapicker", "value": "", "priority": 61, "isStylePicker": false }, { "icon": "images/editor/insMacro.gif", "command": "umbracomacro", "alias": "umbracomacro", "frontEndCommand": "umbmacro", "value": "", "priority": 62, "isStylePicker": false }, { "icon": "images/editor/table.gif", "command": "table", "alias": "mceinserttable", "frontEndCommand": "table", "value": "", "priority": 63, "isStylePicker": false }, { "icon": "images/editor/media.gif", "command": "umbracoembed", "alias": "umbracoembed", "frontEndCommand": "umbembeddialog", "value": "", "priority": 66, "isStylePicker": false }, { "icon": "images/editor/hr.gif", "command": "hr", "alias": "inserthorizontalrule", "frontEndCommand": "hr", "value": "", "priority": 71, "isStylePicker": false }, { "icon": "images/editor/sub.gif", "command": "sub", "alias": "subscript", "frontEndCommand": "sub", "value": "", "priority": 72, "isStylePicker": false }, { "icon": "images/editor/sup.gif", "command": "sup", "alias": "superscript", "frontEndCommand": "sup", "value": "", "priority": 73, "isStylePicker": false }, { "icon": "images/editor/charmap.gif", "command": "charmap", "alias": "mcecharmap", "frontEndCommand": "charmap", "value": "", "priority": 74, "isStylePicker": false }], "validElements": "+a[id|style|rel|rev|charset|hreflang|dir|lang|tabindex|accesskey|type|name|href|target|title|class|onfocus|onblur|onclick|ondblclick|onmousedown|onmouseup|onmouseover|onmousemove|onmouseout|onkeypress|onkeydown|onkeyup],-strong/-b[class|style],-em/-i[class|style],-strike[class|style],-u[class|style],#p[id|style|dir|class|align],-ol[class|reversed|start|style|type],-ul[class|style],-li[class|style],br[class],img[id|dir|lang|longdesc|usemap|style|class|src|onmouseover|onmouseout|border|alt=|title|hspace|vspace|width|height|align|umbracoorgwidth|umbracoorgheight|onresize|onresizestart|onresizeend|rel],-sub[style|class],-sup[style|class],-blockquote[dir|style|class],-table[border=0|cellspacing|cellpadding|width|height|class|align|summary|style|dir|id|lang|bgcolor|background|bordercolor],-tr[id|lang|dir|class|rowspan|width|height|align|valign|style|bgcolor|background|bordercolor],tbody[id|class],thead[id|class],tfoot[id|class],#td[id|lang|dir|class|colspan|rowspan|width|height|align|valign|style|bgcolor|background|bordercolor|scope],-th[id|lang|dir|class|colspan|rowspan|width|height|align|valign|style|scope],caption[id|lang|dir|class|style],-div[id|dir|class|align|style],-span[class|align|style],-pre[class|align|style],address[class|align|style],-h1[id|dir|class|align],-h2[id|dir|class|align],-h3[id|dir|class|align],-h4[id|dir|class|align],-h5[id|dir|class|align],-h6[id|style|dir|class|align],hr[class|style],dd[id|class|title|style|dir|lang],dl[id|class|title|style|dir|lang],dt[id|class|title|style|dir|lang],object[class|id|width|height|codebase|*],param[name|value|_value|class],embed[type|width|height|src|class|*],map[name|class],area[shape|coords|href|alt|target|class],bdo[class],button[class],iframe[*]", "inValidElements": "font", "customConfig": { "entity_encoding": "raw" } }, null]; + return [200, { "plugins": [{ "name": "code", "useOnFrontend": true }, { "name": "paste", "useOnFrontend": true }, { "name": "umbracolink", "useOnFrontend": true }], "commands": [{ "icon": "images/editor/code.gif", "command": "code", "alias": "code", "frontEndCommand": "code", "value": "", "priority": 1, "isStylePicker": false }, { "icon": "images/editor/removeformat.gif", "command": "removeformat", "alias": "removeformat", "frontEndCommand": "removeformat", "value": "", "priority": 2, "isStylePicker": false }, { "icon": "images/editor/undo.gif", "command": "undo", "alias": "undo", "frontEndCommand": "undo", "value": "", "priority": 11, "isStylePicker": false }, { "icon": "images/editor/redo.gif", "command": "redo", "alias": "redo", "frontEndCommand": "redo", "value": "", "priority": 12, "isStylePicker": false }, { "icon": "images/editor/cut.gif", "command": "cut", "alias": "cut", "frontEndCommand": "cut", "value": "", "priority": 13, "isStylePicker": false }, { "icon": "images/editor/copy.gif", "command": "copy", "alias": "copy", "frontEndCommand": "copy", "value": "", "priority": 14, "isStylePicker": false }, { "icon": "images/editor/showStyles.png", "command": "styleselect", "alias": "styleselect", "frontEndCommand": "styleselect", "value": "", "priority": 20, "isStylePicker": false }, { "icon": "images/editor/bold.gif", "command": "bold", "alias": "bold", "frontEndCommand": "bold", "value": "", "priority": 21, "isStylePicker": false }, { "icon": "images/editor/italic.gif", "command": "italic", "alias": "italic", "frontEndCommand": "italic", "value": "", "priority": 22, "isStylePicker": false }, { "icon": "images/editor/underline.gif", "command": "underline", "alias": "underline", "frontEndCommand": "underline", "value": "", "priority": 23, "isStylePicker": false }, { "icon": "images/editor/strikethrough.gif", "command": "strikethrough", "alias": "strikethrough", "frontEndCommand": "strikethrough", "value": "", "priority": 24, "isStylePicker": false }, { "icon": "images/editor/justifyleft.gif", "command": "justifyleft", "alias": "justifyleft", "frontEndCommand": "alignleft", "value": "", "priority": 31, "isStylePicker": false }, { "icon": "images/editor/justifycenter.gif", "command": "justifycenter", "alias": "justifycenter", "frontEndCommand": "aligncenter", "value": "", "priority": 32, "isStylePicker": false }, { "icon": "images/editor/justifyright.gif", "command": "justifyright", "alias": "justifyright", "frontEndCommand": "alignright", "value": "", "priority": 33, "isStylePicker": false }, { "icon": "images/editor/justifyfull.gif", "command": "justifyfull", "alias": "justifyfull", "frontEndCommand": "alignfull", "value": "", "priority": 34, "isStylePicker": false }, { "icon": "images/editor/bullist.gif", "command": "bullist", "alias": "bullist", "frontEndCommand": "bullist", "value": "", "priority": 41, "isStylePicker": false }, { "icon": "images/editor/numlist.gif", "command": "numlist", "alias": "numlist", "frontEndCommand": "numlist", "value": "", "priority": 42, "isStylePicker": false }, { "icon": "images/editor/outdent.gif", "command": "outdent", "alias": "outdent", "frontEndCommand": "outdent", "value": "", "priority": 43, "isStylePicker": false }, { "icon": "images/editor/indent.gif", "command": "indent", "alias": "indent", "frontEndCommand": "indent", "value": "", "priority": 44, "isStylePicker": false }, { "icon": "images/editor/link.gif", "command": "link", "alias": "mcelink", "frontEndCommand": "link", "value": "", "priority": 51, "isStylePicker": false }, { "icon": "images/editor/unLink.gif", "command": "unlink", "alias": "unlink", "frontEndCommand": "unlink", "value": "", "priority": 52, "isStylePicker": false }, { "icon": "images/editor/anchor.gif", "command": "anchor", "alias": "mceinsertanchor", "frontEndCommand": "anchor", "value": "", "priority": 53, "isStylePicker": false }, { "icon": "images/editor/image.gif", "command": "image", "alias": "mceimage", "frontEndCommand": "umbmediapicker", "value": "", "priority": 61, "isStylePicker": false }, { "icon": "images/editor/insMacro.gif", "command": "umbracomacro", "alias": "umbracomacro", "frontEndCommand": "umbmacro", "value": "", "priority": 62, "isStylePicker": false }, { "icon": "images/editor/table.gif", "command": "table", "alias": "mceinserttable", "frontEndCommand": "table", "value": "", "priority": 63, "isStylePicker": false }, { "icon": "images/editor/media.gif", "command": "umbracoembed", "alias": "umbracoembed", "frontEndCommand": "umbembeddialog", "value": "", "priority": 66, "isStylePicker": false }, { "icon": "images/editor/hr.gif", "command": "hr", "alias": "inserthorizontalrule", "frontEndCommand": "hr", "value": "", "priority": 71, "isStylePicker": false }, { "icon": "images/editor/sub.gif", "command": "sub", "alias": "subscript", "frontEndCommand": "sub", "value": "", "priority": 72, "isStylePicker": false }, { "icon": "images/editor/sup.gif", "command": "sup", "alias": "superscript", "frontEndCommand": "sup", "value": "", "priority": 73, "isStylePicker": false }, { "icon": "images/editor/charmap.gif", "command": "charmap", "alias": "mcecharmap", "frontEndCommand": "charmap", "value": "", "priority": 74, "isStylePicker": false }], "validElements": "+a[id|style|rel|rev|charset|hreflang|dir|lang|tabindex|accesskey|type|name|href|target|title|class|onfocus|onblur|onclick|ondblclick|onmousedown|onmouseup|onmouseover|onmousemove|onmouseout|onkeypress|onkeydown|onkeyup],-strong/-b[class|style],-em/-i[class|style],-strike[class|style],-u[class|style],#p[id|style|dir|class|align],-ol[class|reversed|start|style|type],-ul[class|style],-li[class|style],br[class],img[id|dir|lang|longdesc|usemap|style|class|src|onmouseover|onmouseout|border|alt=|title|hspace|vspace|width|height|align|umbracoorgwidth|umbracoorgheight|onresize|onresizestart|onresizeend|rel],-sub[style|class],-sup[style|class],-blockquote[dir|style|class],-table[border=0|cellspacing|cellpadding|width|height|class|align|summary|style|dir|id|lang|bgcolor|background|bordercolor],-tr[id|lang|dir|class|rowspan|width|height|align|valign|style|bgcolor|background|bordercolor],tbody[id|class],thead[id|class],tfoot[id|class],#td[id|lang|dir|class|colspan|rowspan|width|height|align|valign|style|bgcolor|background|bordercolor|scope],-th[id|lang|dir|class|colspan|rowspan|width|height|align|valign|style|scope],caption[id|lang|dir|class|style],-div[id|dir|class|align|style],-span[class|align|style],-pre[class|align|style],address[class|align|style],-h1[id|dir|class|align],-h2[id|dir|class|align],-h3[id|dir|class|align],-h4[id|dir|class|align],-h5[id|dir|class|align],-h6[id|style|dir|class|align],hr[class|style],dd[id|class|title|style|dir|lang],dl[id|class|title|style|dir|lang],dt[id|class|title|style|dir|lang],object[class|id|width|height|codebase|*],param[name|value|_value|class],embed[type|width|height|src|class|*],map[name|class],area[shape|coords|href|alt|target|class],bdo[class],button[class],iframe[*]", "inValidElements": "font", "customConfig": { "entity_encoding": "raw" }, "pasteTidying": true }, null]; } } diff --git a/src/Umbraco.Web.UI.Client/src/common/services/tinymce.service.js b/src/Umbraco.Web.UI.Client/src/common/services/tinymce.service.js index 92a2389054..8d96863610 100644 --- a/src/Umbraco.Web.UI.Client/src/common/services/tinymce.service.js +++ b/src/Umbraco.Web.UI.Client/src/common/services/tinymce.service.js @@ -232,6 +232,17 @@ function tinyMceService($rootScope, $q, imageHelper, $locale, $http, $timeout, s } }); } + + function cleanupPastedData(plugin, args) { + + // Remove spans + var spanRemoveRegex = new RegExp("<\/?span[^>]*>([^<\/span]*)<\/span([^>]*)", "g"); + args.content = args.content.replace(spanRemoveRegex,""); + + // Convert b to strong. + args.content = args.content.replace(/]*)>([^<\/b]*)<\/b([^>]*)>/g, "$2"); + + } return { @@ -332,7 +343,38 @@ function tinyMceService($rootScope, $q, imageHelper, $locale, $http, $timeout, s images_replace_blob_uris: false, init_instance_callback: initEvents }; - + + if (tinyMceConfig.pasteTidying) { + plugins.push("paste"); + + // We keep spans here, cause removing spans here also removes b-tags inside of them, instead we strip them out later. + var validElements = "-b,-strong,-i,-em,span,p,a,table,th,thead,tbody,tr,td,ul,ol,li,dl,dt,dd,iframe,svg,img,hr,abbr,sub,sup,figure,picture"; + + // add valid elements from styleFormats. + var style, i = 0; + for(; i < styles.styleFormats.length; i++) { + style = styles.styleFormats[i]; + if(style.block) { + validElements += "," + style.block; + } + } + + var pasteConfig = { + + paste_remove_styles: true, + paste_text_linebreaktype: true, + paste_strip_class_attributes: "all", + paste_retain_style_properties: "all", + + paste_word_valid_elements: validElements, + + paste_preprocess: prepaste + + }; + + angular.extend(config, cleanupPastedData); + } + if (tinyMceConfig.customConfig) { //if there is some custom config, we need to see if the string value of each item might actually be json and if so, we need to From f59cf544a58c69a26bd59c4bd21fc16e95ab3835 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Niels=20Lyngs=C3=B8?= Date: Fri, 13 Sep 2019 13:43:48 +0200 Subject: [PATCH 02/10] make gulp able to watch libs --- src/Umbraco.Web.UI.Client/gulp/tasks/watch.js | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/Umbraco.Web.UI.Client/gulp/tasks/watch.js b/src/Umbraco.Web.UI.Client/gulp/tasks/watch.js index a5c476f7d2..5c2fa2e5c8 100644 --- a/src/Umbraco.Web.UI.Client/gulp/tasks/watch.js +++ b/src/Umbraco.Web.UI.Client/gulp/tasks/watch.js @@ -53,6 +53,13 @@ gulp.task('watch', function () { watch(config.sources.globs.js, { interval: watchInterval }) .pipe(gulp.dest(config.root + config.targets.js)) ); + + + //watch all lib files that will not be merged - copy single file changes + stream.add( + watch(config.sources.globs.lib, { interval: watchInterval }) + .pipe(gulp.dest(config.root + config.targets.lib)) + ); return stream; }); From fa3f5287c1b648e4f9381344081a236a2a0a83e3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Niels=20Lyngs=C3=B8?= Date: Fri, 13 Sep 2019 13:44:54 +0200 Subject: [PATCH 03/10] making our own paste plugin to be able to handle images in pasted content from MS Word --- .../lib/tinymce/plugins/umbpaste/index.js | 7 + .../tinymce/plugins/umbpaste/plugin.min.js | 1867 +++++++++++++++++ .../src/common/services/tinymce.service.js | 36 +- 3 files changed, 1900 insertions(+), 10 deletions(-) create mode 100644 src/Umbraco.Web.UI.Client/lib/tinymce/plugins/umbpaste/index.js create mode 100644 src/Umbraco.Web.UI.Client/lib/tinymce/plugins/umbpaste/plugin.min.js diff --git a/src/Umbraco.Web.UI.Client/lib/tinymce/plugins/umbpaste/index.js b/src/Umbraco.Web.UI.Client/lib/tinymce/plugins/umbpaste/index.js new file mode 100644 index 0000000000..b54d9d1384 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/lib/tinymce/plugins/umbpaste/index.js @@ -0,0 +1,7 @@ +// Exports the "paste" plugin for usage with module loaders +// Usage: +// CommonJS: +// require('tinymce/plugins/paste') +// ES2015: +// import 'tinymce/plugins/paste' +require('./plugin.js'); \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/lib/tinymce/plugins/umbpaste/plugin.min.js b/src/Umbraco.Web.UI.Client/lib/tinymce/plugins/umbpaste/plugin.min.js new file mode 100644 index 0000000000..e197012bfa --- /dev/null +++ b/src/Umbraco.Web.UI.Client/lib/tinymce/plugins/umbpaste/plugin.min.js @@ -0,0 +1,1867 @@ +(function () { +var paste = (function () { + 'use strict'; + + var Cell = function (initial) { + var value = initial; + var get = function () { + return value; + }; + var set = function (v) { + value = v; + }; + var clone = function () { + return Cell(get()); + }; + return { + get: get, + set: set, + clone: clone + }; + }; + + var global = tinymce.util.Tools.resolve('tinymce.PluginManager'); + + var hasProPlugin = function (editor) { + if (/(^|[ ,])powerpaste([, ]|$)/.test(editor.settings.plugins) && global.get('powerpaste')) { + if (typeof window.console !== 'undefined' && window.console.log) { + window.console.log('PowerPaste is incompatible with Paste plugin! Remove \'umbpaste\' from the \'plugins\' option.'); + } + return true; + } else { + return false; + } + }; + var DetectProPlugin = { hasProPlugin: hasProPlugin }; + + var get = function (clipboard, quirks) { + return { + clipboard: clipboard, + quirks: quirks + }; + }; + var Api = { get: get }; + + var firePastePreProcess = function (editor, html, internal, isWordHtml) { + return editor.fire('PastePreProcess', { + content: html, + internal: internal, + wordContent: isWordHtml + }); + }; + var firePastePostProcess = function (editor, node, internal, isWordHtml) { + return editor.fire('PastePostProcess', { + node: node, + internal: internal, + wordContent: isWordHtml + }); + }; + var firePastePlainTextToggle = function (editor, state) { + return editor.fire('PastePlainTextToggle', { state: state }); + }; + var firePaste = function (editor, ieFake) { + return editor.fire('paste', { ieFake: ieFake }); + }; + var Events = { + firePastePreProcess: firePastePreProcess, + firePastePostProcess: firePastePostProcess, + firePastePlainTextToggle: firePastePlainTextToggle, + firePaste: firePaste + }; + + var shouldPlainTextInform = function (editor) { + return editor.getParam('paste_plaintext_inform', true); + }; + var shouldBlockDrop = function (editor) { + return editor.getParam('paste_block_drop', false); + }; + var shouldPasteDataImages = function (editor) { + return editor.getParam('paste_data_images', false); + }; + var shouldFilterDrop = function (editor) { + return editor.getParam('paste_filter_drop', true); + }; + var getPreProcess = function (editor) { + return editor.getParam('paste_preprocess'); + }; + var getPostProcess = function (editor) { + return editor.getParam('paste_postprocess'); + }; + var getWebkitStyles = function (editor) { + return editor.getParam('paste_webkit_styles'); + }; + var shouldRemoveWebKitStyles = function (editor) { + return editor.getParam('paste_remove_styles_if_webkit', true); + }; + var shouldMergeFormats = function (editor) { + return editor.getParam('paste_merge_formats', true); + }; + var isSmartPasteEnabled = function (editor) { + return editor.getParam('smart_paste', true); + }; + var isPasteAsTextEnabled = function (editor) { + return editor.getParam('paste_as_text', false); + }; + var getRetainStyleProps = function (editor) { + return editor.getParam('paste_retain_style_properties'); + }; + var getWordValidElements = function (editor) { + var defaultValidElements = '-strong/b,-em/i,-u,-span,-p,-ol,-ul,-li,-h1,-h2,-h3,-h4,-h5,-h6,' + '-p/div,-a[href|name],sub,sup,strike,br,del,table[width],tr,' + 'td[colspan|rowspan|width],th[colspan|rowspan|width],thead,tfoot,tbody'; + return editor.getParam('paste_word_valid_elements', defaultValidElements); + }; + var shouldConvertWordFakeLists = function (editor) { + return editor.getParam('paste_convert_word_fake_lists', true); + }; + var shouldUseDefaultFilters = function (editor) { + return editor.getParam('paste_enable_default_filters', true); + }; + var Settings = { + shouldPlainTextInform: shouldPlainTextInform, + shouldBlockDrop: shouldBlockDrop, + shouldPasteDataImages: shouldPasteDataImages, + shouldFilterDrop: shouldFilterDrop, + getPreProcess: getPreProcess, + getPostProcess: getPostProcess, + getWebkitStyles: getWebkitStyles, + shouldRemoveWebKitStyles: shouldRemoveWebKitStyles, + shouldMergeFormats: shouldMergeFormats, + isSmartPasteEnabled: isSmartPasteEnabled, + isPasteAsTextEnabled: isPasteAsTextEnabled, + getRetainStyleProps: getRetainStyleProps, + getWordValidElements: getWordValidElements, + shouldConvertWordFakeLists: shouldConvertWordFakeLists, + shouldUseDefaultFilters: shouldUseDefaultFilters + }; + + var shouldInformUserAboutPlainText = function (editor, userIsInformedState) { + return userIsInformedState.get() === false && Settings.shouldPlainTextInform(editor); + }; + var displayNotification = function (editor, message) { + editor.notificationManager.open({ + text: editor.translate(message), + type: 'info' + }); + }; + var togglePlainTextPaste = function (editor, clipboard, userIsInformedState) { + if (clipboard.pasteFormat.get() === 'text') { + clipboard.pasteFormat.set('html'); + Events.firePastePlainTextToggle(editor, false); + } else { + clipboard.pasteFormat.set('text'); + Events.firePastePlainTextToggle(editor, true); + if (shouldInformUserAboutPlainText(editor, userIsInformedState)) { + displayNotification(editor, 'Paste is now in plain text mode. Contents will now be pasted as plain text until you toggle this option off.'); + userIsInformedState.set(true); + } + } + editor.focus(); + }; + var Actions = { togglePlainTextPaste: togglePlainTextPaste }; + + var register = function (editor, clipboard, userIsInformedState) { + editor.addCommand('mceTogglePlainTextPaste', function () { + Actions.togglePlainTextPaste(editor, clipboard, userIsInformedState); + }); + editor.addCommand('mceInsertClipboardContent', function (ui, value) { + if (value.content) { + clipboard.pasteHtml(value.content, value.internal); + } + if (value.text) { + clipboard.pasteText(value.text); + } + }); + }; + var Commands = { register: register }; + + var global$1 = tinymce.util.Tools.resolve('tinymce.Env'); + + var global$2 = tinymce.util.Tools.resolve('tinymce.util.Delay'); + + var global$3 = tinymce.util.Tools.resolve('tinymce.util.Tools'); + + var global$4 = tinymce.util.Tools.resolve('tinymce.util.VK'); + + var internalMimeType = 'x-tinymce/html'; + var internalMark = ''; + var mark = function (html) { + return internalMark + html; + }; + var unmark = function (html) { + return html.replace(internalMark, ''); + }; + var isMarked = function (html) { + return html.indexOf(internalMark) !== -1; + }; + var InternalHtml = { + mark: mark, + unmark: unmark, + isMarked: isMarked, + internalHtmlMime: function () { + return internalMimeType; + } + }; + + var global$5 = tinymce.util.Tools.resolve('tinymce.html.Entities'); + + var isPlainText = function (text) { + return !/<(?:\/?(?!(?:div|p|br|span)>)\w+|(?:(?!(?:span style="white-space:\s?pre;?">)|br\s?\/>))\w+\s[^>]+)>/i.test(text); + }; + var toBRs = function (text) { + return text.replace(/\r?\n/g, '
'); + }; + var openContainer = function (rootTag, rootAttrs) { + var key; + var attrs = []; + var tag = '<' + rootTag; + if (typeof rootAttrs === 'object') { + for (key in rootAttrs) { + if (rootAttrs.hasOwnProperty(key)) { + attrs.push(key + '="' + global$5.encodeAllRaw(rootAttrs[key]) + '"'); + } + } + if (attrs.length) { + tag += ' ' + attrs.join(' '); + } + } + return tag + '>'; + }; + var toBlockElements = function (text, rootTag, rootAttrs) { + var blocks = text.split(/\n\n/); + var tagOpen = openContainer(rootTag, rootAttrs); + var tagClose = ''; + var paragraphs = global$3.map(blocks, function (p) { + return p.split(/\n/).join('
'); + }); + var stitch = function (p) { + return tagOpen + p + tagClose; + }; + return paragraphs.length === 1 ? paragraphs[0] : global$3.map(paragraphs, stitch).join(''); + }; + var convert = function (text, rootTag, rootAttrs) { + return rootTag ? toBlockElements(text, rootTag, rootAttrs) : toBRs(text); + }; + var Newlines = { + isPlainText: isPlainText, + convert: convert, + toBRs: toBRs, + toBlockElements: toBlockElements + }; + + var global$6 = tinymce.util.Tools.resolve('tinymce.html.DomParser'); + + var global$7 = tinymce.util.Tools.resolve('tinymce.html.Node'); + + var global$8 = tinymce.util.Tools.resolve('tinymce.html.Schema'); + + var global$9 = tinymce.util.Tools.resolve('tinymce.html.Serializer'); + + function filter(content, items) { + global$3.each(items, function (v) { + if (v.constructor === RegExp) { + content = content.replace(v, ''); + } else { + content = content.replace(v[0], v[1]); + } + }); + return content; + } + function innerText(html) { + var schema = global$8(); + var domParser = global$6({}, schema); + var text = ''; + var shortEndedElements = schema.getShortEndedElements(); + var ignoreElements = global$3.makeMap('script noscript style textarea video audio iframe object', ' '); + var blockElements = schema.getBlockElements(); + function walk(node) { + var name$$1 = node.name, currentNode = node; + if (name$$1 === 'br') { + text += '\n'; + return; + } + if (name$$1 === 'wbr') { + return; + } + if (shortEndedElements[name$$1]) { + text += ' '; + } + if (ignoreElements[name$$1]) { + text += ' '; + return; + } + if (node.type === 3) { + text += node.value; + } + if (!node.shortEnded) { + if (node = node.firstChild) { + do { + walk(node); + } while (node = node.next); + } + } + if (blockElements[name$$1] && currentNode.next) { + text += '\n'; + if (name$$1 === 'p') { + text += '\n'; + } + } + } + html = filter(html, [//g]); + walk(domParser.parse(html)); + return text; + } + function trimHtml(html) { + function trimSpaces(all, s1, s2) { + if (!s1 && !s2) { + return ' '; + } + return '\xA0'; + } + html = filter(html, [ + /^[\s\S]*]*>\s*|\s*<\/body[^>]*>[\s\S]*$/ig, + /|/g, + [ + /( ?)\u00a0<\/span>( ?)/g, + trimSpaces + ], + /
/g, + /
$/i + ]); + return html; + } + function createIdGenerator(prefix) { + var count = 0; + return function () { + return prefix + count++; + }; + } + var isMsEdge = function () { + return navigator.userAgent.indexOf(' Edge/') !== -1; + }; + var Utils = { + filter: filter, + innerText: innerText, + trimHtml: trimHtml, + createIdGenerator: createIdGenerator, + isMsEdge: isMsEdge + }; + + function isWordContent(content) { + return / 1) { + currentListNode.attr('start', '' + start); + } + paragraphNode.wrap(currentListNode); + } else { + currentListNode.append(paragraphNode); + } + paragraphNode.name = 'li'; + if (level > lastLevel && prevListNode) { + prevListNode.lastChild.append(currentListNode); + } + lastLevel = level; + removeIgnoredNodes(paragraphNode); + trimListStart(paragraphNode, /^\u00a0+/); + trimListStart(paragraphNode, /^\s*([\u2022\u00b7\u00a7\u25CF]|\w+\.)/); + trimListStart(paragraphNode, /^\u00a0+/); + } + var elements = []; + var child = node.firstChild; + while (typeof child !== 'undefined' && child !== null) { + elements.push(child); + child = child.walk(); + if (child !== null) { + while (typeof child !== 'undefined' && child.parent !== node) { + child = child.walk(); + } + } + } + for (var i = 0; i < elements.length; i++) { + node = elements[i]; + if (node.name === 'p' && node.firstChild) { + var nodeText = getText(node); + if (isBulletList(nodeText)) { + convertParagraphToLi(node, 'ul'); + continue; + } + if (isNumericList(nodeText)) { + var matches = /([0-9]+)\./.exec(nodeText); + var start = 1; + if (matches) { + start = parseInt(matches[1], 10); + } + convertParagraphToLi(node, 'ol', start); + continue; + } + if (node._listLevel) { + convertParagraphToLi(node, 'ul', 1); + continue; + } + currentListNode = null; + } else { + prevListNode = currentListNode; + currentListNode = null; + } + } + } + function filterStyles(editor, validStyles, node, styleValue) { + var outputStyles = {}, matches; + var styles = editor.dom.parseStyle(styleValue); + global$3.each(styles, function (value, name) { + switch (name) { + case 'mso-list': + matches = /\w+ \w+([0-9]+)/i.exec(styleValue); + if (matches) { + node._listLevel = parseInt(matches[1], 10); + } + if (/Ignore/i.test(value) && node.firstChild) { + node._listIgnore = true; + node.firstChild._listIgnore = true; + } + break; + case 'horiz-align': + name = 'text-align'; + break; + case 'vert-align': + name = 'vertical-align'; + break; + case 'font-color': + case 'mso-foreground': + name = 'color'; + break; + case 'mso-background': + case 'mso-highlight': + name = 'background'; + break; + case 'font-weight': + case 'font-style': + if (value !== 'normal') { + outputStyles[name] = value; + } + return; + case 'mso-element': + if (/^(comment|comment-list)$/i.test(value)) { + node.remove(); + return; + } + break; + } + if (name.indexOf('mso-comment') === 0) { + node.remove(); + return; + } + if (name.indexOf('mso-') === 0) { + return; + } + if (Settings.getRetainStyleProps(editor) === 'all' || validStyles && validStyles[name]) { + outputStyles[name] = value; + } + }); + if (/(bold)/i.test(outputStyles['font-weight'])) { + delete outputStyles['font-weight']; + node.wrap(new global$7('b', 1)); + } + if (/(italic)/i.test(outputStyles['font-style'])) { + delete outputStyles['font-style']; + node.wrap(new global$7('i', 1)); + } + outputStyles = editor.dom.serializeStyle(outputStyles, node.name); + if (outputStyles) { + return outputStyles; + } + return null; + } + var filterWordContent = function (editor, content) { + + console.log("filterWordContent 3"); + console.log(content); + + content = content.replace(/\/g, '');// removes & + + + var retainStyleProperties, validStyles; + retainStyleProperties = Settings.getRetainStyleProps(editor); + if (retainStyleProperties) { + validStyles = global$3.makeMap(retainStyleProperties.split(/[, ]/)); + } + + content = Utils.filter(content, [ + /
/gi, + /]+id="?docs-internal-[^>]*>/gi, + //gi, + /<(!|script[^>]*>.*?<\/script(?=[>\s])|\/?(\?xml(:\w+)?|img|meta|link|style|\w:\w+)(?=[\s\/>]))[^>]*>/gi, + [ + /<(\/?)s>/gi, + '<$1strike>' + ], + [ + / /gi, + '\xA0' + ], + [ + /([\s\u00a0]*)<\/span>/gi, + function (str, spaces) { + return spaces.length > 0 ? spaces.replace(/./, ' ').slice(Math.floor(spaces.length / 2)).split('').join('\xA0') : ''; + } + ] + ]); + + var validElements = Settings.getWordValidElements(editor); + var schema = global$8({ + valid_elements: validElements, + valid_children: '-li[p]' + }); + global$3.each(schema.elements, function (rule) { + if (!rule.attributes.class) { + rule.attributes.class = {}; + rule.attributesOrder.push('class'); + } + if (!rule.attributes.style) { + rule.attributes.style = {}; + rule.attributesOrder.push('style'); + } + }); + var domParser = global$6({}, schema); + domParser.addAttributeFilter('style', function (nodes) { + var i = nodes.length, node; + while (i--) { + node = nodes[i]; + node.attr('style', filterStyles(editor, validStyles, node, node.attr('style'))); + if (node.name === 'span' && node.parent && !node.attributes.length) { + node.unwrap(); + } + } + }); + domParser.addAttributeFilter('class', function (nodes) { + var i = nodes.length, node, className; + while (i--) { + node = nodes[i]; + className = node.attr('class'); + if (/^(MsoCommentReference|MsoCommentText|msoDel)$/i.test(className)) { + node.remove(); + } + node.attr('class', null); + } + }); + domParser.addNodeFilter('del', function (nodes) { + var i = nodes.length; + while (i--) { + nodes[i].remove(); + } + }); + domParser.addNodeFilter('a', function (nodes) { + var i = nodes.length, node, href, name; + while (i--) { + node = nodes[i]; + href = node.attr('href'); + name = node.attr('name'); + if (href && href.indexOf('#_msocom_') !== -1) { + node.remove(); + continue; + } + if (href && href.indexOf('file://') === 0) { + href = href.split('#')[1]; + if (href) { + href = '#' + href; + } + } + if (!href && !name) { + node.unwrap(); + } else { + if (name && !/^_?(?:toc|edn|ftn)/i.test(name)) { + node.unwrap(); + continue; + } + node.attr({ + href: href, + name: name + }); + } + } + }); + var rootNode = domParser.parse(content); + if (Settings.shouldConvertWordFakeLists(editor)) { + convertFakeListsToProperLists(rootNode); + } + content = global$9({ validate: editor.settings.validate }, schema).serialize(rootNode); + return content; + }; + var preProcess = function (editor, content) { + return Settings.shouldUseDefaultFilters(editor) ? filterWordContent(editor, content) : content; + }; + var WordFilter = { + preProcess: preProcess, + isWordContent: isWordContent + }; + + var processResult = function (content, cancelled) { + return { + content: content, + cancelled: cancelled + }; + }; + var postProcessFilter = function (editor, html, internal, isWordHtml) { + var tempBody = editor.dom.create('div', { style: 'display:none' }, html); + var postProcessArgs = Events.firePastePostProcess(editor, tempBody, internal, isWordHtml); + return processResult(postProcessArgs.node.innerHTML, postProcessArgs.isDefaultPrevented()); + }; + var filterContent = function (editor, content, internal, isWordHtml) { + var preProcessArgs = Events.firePastePreProcess(editor, content, internal, isWordHtml); + if (editor.hasEventListeners('PastePostProcess') && !preProcessArgs.isDefaultPrevented()) { + return postProcessFilter(editor, preProcessArgs.content, internal, isWordHtml); + } else { + return processResult(preProcessArgs.content, preProcessArgs.isDefaultPrevented()); + } + }; + var process = function (editor, html, internal) { + var isWordHtml = WordFilter.isWordContent(html); + var content = isWordHtml ? WordFilter.preProcess(editor, html) : html; + return filterContent(editor, content, internal, isWordHtml); + }; + var ProcessFilters = { process: process }; + + var removeMeta = function (editor, html) { + var body = editor.dom.create('body', {}, html); + global$3.each(body.querySelectorAll('meta'), function (elm) { + return elm.parentNode.removeChild(elm); + }); + return body.innerHTML; + }; + var pasteHtml = function (editor, html) { + editor.insertContent(removeMeta(editor, html), { + merge: Settings.shouldMergeFormats(editor), + paste: true + }); + return true; + }; + var isAbsoluteUrl = function (url) { + return /^https?:\/\/[\w\?\-\/+=.&%@~#]+$/i.test(url); + }; + var isImageUrl = function (url) { + return isAbsoluteUrl(url) && /.(gif|jpe?g|png)$/.test(url); + }; + var createImage = function (editor, url, pasteHtmlFn) { + editor.undoManager.extra(function () { + pasteHtmlFn(editor, url); + }, function () { + editor.insertContent(''); + }); + return true; + }; + var createLink = function (editor, url, pasteHtmlFn) { + editor.undoManager.extra(function () { + pasteHtmlFn(editor, url); + }, function () { + editor.execCommand('mceInsertLink', false, url); + }); + return true; + }; + var linkSelection = function (editor, html, pasteHtmlFn) { + return editor.selection.isCollapsed() === false && isAbsoluteUrl(html) ? createLink(editor, html, pasteHtmlFn) : false; + }; + var insertImage = function (editor, html, pasteHtmlFn) { + return isImageUrl(html) ? createImage(editor, html, pasteHtmlFn) : false; + }; + var smartInsertContent = function (editor, html) { + global$3.each([ + linkSelection, + insertImage, + pasteHtml + ], function (action) { + return action(editor, html, pasteHtml) !== true; + }); + }; + var insertContent = function (editor, html) { + if (Settings.isSmartPasteEnabled(editor) === false) { + pasteHtml(editor, html); + } else { + smartInsertContent(editor, html); + } + }; + var SmartPaste = { + isImageUrl: isImageUrl, + isAbsoluteUrl: isAbsoluteUrl, + insertContent: insertContent + }; + + var constant = function (value) { + return function () { + return value; + }; + }; + function curry(fn) { + var initialArgs = []; + for (var _i = 1; _i < arguments.length; _i++) { + initialArgs[_i - 1] = arguments[_i]; + } + return function () { + var restArgs = []; + for (var _i = 0; _i < arguments.length; _i++) { + restArgs[_i] = arguments[_i]; + } + var all = initialArgs.concat(restArgs); + return fn.apply(null, all); + }; + } + var never = constant(false); + var always = constant(true); + + var never$1 = never; + var always$1 = always; + var none = function () { + return NONE; + }; + var NONE = function () { + var eq = function (o) { + return o.isNone(); + }; + var call$$1 = function (thunk) { + return thunk(); + }; + var id = function (n) { + return n; + }; + var noop$$1 = function () { + }; + var nul = function () { + return null; + }; + var undef = function () { + return undefined; + }; + var me = { + fold: function (n, s) { + return n(); + }, + is: never$1, + isSome: never$1, + isNone: always$1, + getOr: id, + getOrThunk: call$$1, + getOrDie: function (msg) { + throw new Error(msg || 'error: getOrDie called on none.'); + }, + getOrNull: nul, + getOrUndefined: undef, + or: id, + orThunk: call$$1, + map: none, + ap: none, + each: noop$$1, + bind: none, + flatten: none, + exists: never$1, + forall: always$1, + filter: none, + equals: eq, + equals_: eq, + toArray: function () { + return []; + }, + toString: constant('none()') + }; + if (Object.freeze) + Object.freeze(me); + return me; + }(); + var some = function (a) { + var constant_a = function () { + return a; + }; + var self = function () { + return me; + }; + var map = function (f) { + return some(f(a)); + }; + var bind = function (f) { + return f(a); + }; + var me = { + fold: function (n, s) { + return s(a); + }, + is: function (v) { + return a === v; + }, + isSome: always$1, + isNone: never$1, + getOr: constant_a, + getOrThunk: constant_a, + getOrDie: constant_a, + getOrNull: constant_a, + getOrUndefined: constant_a, + or: self, + orThunk: self, + map: map, + ap: function (optfab) { + return optfab.fold(none, function (fab) { + return some(fab(a)); + }); + }, + each: function (f) { + f(a); + }, + bind: bind, + flatten: constant_a, + exists: bind, + forall: bind, + filter: function (f) { + return f(a) ? me : NONE; + }, + equals: function (o) { + return o.is(a); + }, + equals_: function (o, elementEq) { + return o.fold(never$1, function (b) { + return elementEq(a, b); + }); + }, + toArray: function () { + return [a]; + }, + toString: function () { + return 'some(' + a + ')'; + } + }; + return me; + }; + var from = function (value) { + return value === null || value === undefined ? NONE : some(value); + }; + var Option = { + some: some, + none: none, + from: from + }; + + var typeOf = function (x) { + if (x === null) + return 'null'; + var t = typeof x; + if (t === 'object' && Array.prototype.isPrototypeOf(x)) + return 'array'; + if (t === 'object' && String.prototype.isPrototypeOf(x)) + return 'string'; + return t; + }; + var isType = function (type) { + return function (value) { + return typeOf(value) === type; + }; + }; + var isFunction = isType('function'); + + var map = function (xs, f) { + var len = xs.length; + var r = new Array(len); + for (var i = 0; i < len; i++) { + var x = xs[i]; + r[i] = f(x, i, xs); + } + return r; + }; + var each = function (xs, f) { + for (var i = 0, len = xs.length; i < len; i++) { + var x = xs[i]; + f(x, i, xs); + } + }; + var filter$1 = function (xs, pred) { + var r = []; + for (var i = 0, len = xs.length; i < len; i++) { + var x = xs[i]; + if (pred(x, i, xs)) { + r.push(x); + } + } + return r; + }; + var slice = Array.prototype.slice; + var from$1 = isFunction(Array.from) ? Array.from : function (x) { + return slice.call(x); + }; + + var nu = function (baseFn) { + var data = Option.none(); + var callbacks = []; + var map$$1 = function (f) { + return nu(function (nCallback) { + get(function (data) { + nCallback(f(data)); + }); + }); + }; + var get = function (nCallback) { + if (isReady()) + call(nCallback); + else + callbacks.push(nCallback); + }; + var set = function (x) { + data = Option.some(x); + run(callbacks); + callbacks = []; + }; + var isReady = function () { + return data.isSome(); + }; + var run = function (cbs) { + each(cbs, call); + }; + var call = function (cb) { + data.each(function (x) { + setTimeout(function () { + cb(x); + }, 0); + }); + }; + baseFn(set); + return { + get: get, + map: map$$1, + isReady: isReady + }; + }; + var pure$1 = function (a) { + return nu(function (callback) { + callback(a); + }); + }; + var LazyValue = { + nu: nu, + pure: pure$1 + }; + + var bounce = function (f) { + return function () { + var args = []; + for (var _i = 0; _i < arguments.length; _i++) { + args[_i] = arguments[_i]; + } + var me = this; + setTimeout(function () { + f.apply(me, args); + }, 0); + }; + }; + + var nu$1 = function (baseFn) { + var get = function (callback) { + baseFn(bounce(callback)); + }; + var map = function (fab) { + return nu$1(function (callback) { + get(function (a) { + var value = fab(a); + callback(value); + }); + }); + }; + var bind = function (aFutureB) { + return nu$1(function (callback) { + get(function (a) { + aFutureB(a).get(callback); + }); + }); + }; + var anonBind = function (futureB) { + return nu$1(function (callback) { + get(function (a) { + futureB.get(callback); + }); + }); + }; + var toLazy = function () { + return LazyValue.nu(get); + }; + var toCached = function () { + var cache = null; + return nu$1(function (callback) { + if (cache === null) { + cache = toLazy(); + } + cache.get(callback); + }); + }; + return { + map: map, + bind: bind, + anonBind: anonBind, + toLazy: toLazy, + toCached: toCached, + get: get + }; + }; + var pure$2 = function (a) { + return nu$1(function (callback) { + callback(a); + }); + }; + var Future = { + nu: nu$1, + pure: pure$2 + }; + + var par = function (asyncValues, nu) { + return nu(function (callback) { + var r = []; + var count = 0; + var cb = function (i) { + return function (value) { + r[i] = value; + count++; + if (count >= asyncValues.length) { + callback(r); + } + }; + }; + if (asyncValues.length === 0) { + callback([]); + } else { + each(asyncValues, function (asyncValue, i) { + asyncValue.get(cb(i)); + }); + } + }); + }; + + var par$1 = function (futures) { + return par(futures, Future.nu); + }; + var mapM = function (array, fn) { + var futures = map(array, fn); + return par$1(futures); + }; + + var pasteHtml$1 = function (editor, html, internalFlag) { + var internal = internalFlag ? internalFlag : InternalHtml.isMarked(html); + var args = ProcessFilters.process(editor, InternalHtml.unmark(html), internal); + if (args.cancelled === false) { + SmartPaste.insertContent(editor, args.content); + } + }; + var pasteText = function (editor, text) { + text = editor.dom.encode(text).replace(/\r\n/g, '\n'); + text = Newlines.convert(text, editor.settings.forced_root_block, editor.settings.forced_root_block_attrs); + pasteHtml$1(editor, text, false); + }; + var getDataTransferItems = function (dataTransfer) { + var items = {}; + var mceInternalUrlPrefix = 'data:text/mce-internal,'; + if (dataTransfer) { + if (dataTransfer.getData) { + var legacyText = dataTransfer.getData('Text'); + if (legacyText && legacyText.length > 0) { + if (legacyText.indexOf(mceInternalUrlPrefix) === -1) { + items['text/plain'] = legacyText; + } + } + } + if (dataTransfer.types) { + for (var i = 0; i < dataTransfer.types.length; i++) { + var contentType = dataTransfer.types[i]; + try { + items[contentType] = dataTransfer.getData(contentType); + } catch (ex) { + items[contentType] = ''; + } + } + } + } + return items; + }; + var getClipboardContent = function (editor, clipboardEvent) { + var content = getDataTransferItems(clipboardEvent.clipboardData || editor.getDoc().dataTransfer); + return Utils.isMsEdge() ? global$3.extend(content, { 'text/html': '' }) : content; + }; + var hasContentType = function (clipboardContent, mimeType) { + return mimeType in clipboardContent && clipboardContent[mimeType].length > 0; + }; + var hasHtmlOrText = function (content) { + return hasContentType(content, 'text/html') || hasContentType(content, 'text/plain'); + }; + var getBase64FromUri = function (uri) { + var idx; + idx = uri.indexOf(','); + if (idx !== -1) { + return uri.substr(idx + 1); + } + return null; + }; + var isValidDataUriImage = function (settings, imgElm) { + return settings.images_dataimg_filter ? settings.images_dataimg_filter(imgElm) : true; + }; + var extractFilename = function (editor, str) { + var m = str.match(/([\s\S]+?)\.(?:jpeg|jpg|png|gif)$/i); + return m ? editor.dom.encode(m[1]) : null; + }; + var uniqueId = Utils.createIdGenerator('mceclip'); + var pasteImage = function (editor, imageItem) { + var base64 = getBase64FromUri(imageItem.uri); + var id = uniqueId(); + var name$$1 = editor.settings.images_reuse_filename && imageItem.blob.name ? extractFilename(editor, imageItem.blob.name) : id; + var img = new Image(); + img.src = imageItem.uri; + if (isValidDataUriImage(editor.settings, img)) { + var blobCache = editor.editorUpload.blobCache; + var blobInfo = void 0, existingBlobInfo = void 0; + existingBlobInfo = blobCache.findFirst(function (cachedBlobInfo) { + return cachedBlobInfo.base64() === base64; + }); + if (!existingBlobInfo) { + blobInfo = blobCache.create(id, imageItem.blob, base64, name$$1); + blobCache.add(blobInfo); + } else { + blobInfo = existingBlobInfo; + } + pasteHtml$1(editor, '', false); + } else { + pasteHtml$1(editor, '', false); + } + }; + var isClipboardEvent = function (event$$1) { + return event$$1.type === 'paste'; + }; + var readBlobsAsDataUris = function (items) { + return mapM(items, function (item) { + return Future.nu(function (resolve) { + var blob = item.getAsFile ? item.getAsFile() : item; + var reader = new window.FileReader(); + reader.onload = function () { + resolve({ + blob: blob, + uri: reader.result + }); + }; + reader.readAsDataURL(blob); + }); + }); + }; + var getImagesFromDataTransfer = function (dataTransfer) { + var items = dataTransfer.items ? map(from$1(dataTransfer.items), function (item) { + return item.getAsFile(); + }) : []; + var files = dataTransfer.files ? from$1(dataTransfer.files) : []; + var images = filter$1(items.length > 0 ? items : files, function (file) { + return /^image\/(jpeg|png|gif|bmp)$/.test(file.type); + }); + return images; + }; + var pasteImageData = function (editor, e, rng) { + var dataTransfer = isClipboardEvent(e) ? e.clipboardData : e.dataTransfer; + if (editor.settings.paste_data_images && dataTransfer) { + var images = getImagesFromDataTransfer(dataTransfer); + if (images.length > 0) { + e.preventDefault(); + readBlobsAsDataUris(images).get(function (blobResults) { + if (rng) { + editor.selection.setRng(rng); + } + each(blobResults, function (result) { + pasteImage(editor, result); + }); + }); + return true; + } + } + return false; + }; + var isBrokenAndroidClipboardEvent = function (e) { + var clipboardData = e.clipboardData; + return navigator.userAgent.indexOf('Android') !== -1 && clipboardData && clipboardData.items && clipboardData.items.length === 0; + }; + var isKeyboardPasteEvent = function (e) { + return global$4.metaKeyPressed(e) && e.keyCode === 86 || e.shiftKey && e.keyCode === 45; + }; + var registerEventHandlers = function (editor, pasteBin, pasteFormat) { + var keyboardPasteTimeStamp = 0; + var keyboardPastePlainTextState; + editor.on('keydown', function (e) { + function removePasteBinOnKeyUp(e) { + if (isKeyboardPasteEvent(e) && !e.isDefaultPrevented()) { + pasteBin.remove(); + } + } + if (isKeyboardPasteEvent(e) && !e.isDefaultPrevented()) { + keyboardPastePlainTextState = e.shiftKey && e.keyCode === 86; + if (keyboardPastePlainTextState && global$1.webkit && navigator.userAgent.indexOf('Version/') !== -1) { + return; + } + e.stopImmediatePropagation(); + keyboardPasteTimeStamp = new Date().getTime(); + if (global$1.ie && keyboardPastePlainTextState) { + e.preventDefault(); + Events.firePaste(editor, true); + return; + } + pasteBin.remove(); + pasteBin.create(); + editor.once('keyup', removePasteBinOnKeyUp); + editor.once('paste', function () { + editor.off('keyup', removePasteBinOnKeyUp); + }); + } + }); + function insertClipboardContent(clipboardContent, isKeyBoardPaste, plainTextMode, internal) { + var content, isPlainTextHtml; + if (hasContentType(clipboardContent, 'text/html')) { + content = clipboardContent['text/html']; + } else { + content = pasteBin.getHtml(); + internal = internal ? internal : InternalHtml.isMarked(content); + if (pasteBin.isDefaultContent(content)) { + plainTextMode = true; + } + } + content = Utils.trimHtml(content); + pasteBin.remove(); + isPlainTextHtml = internal === false && Newlines.isPlainText(content); + if (!content.length || isPlainTextHtml) { + plainTextMode = true; + } + if (plainTextMode) { + if (hasContentType(clipboardContent, 'text/plain') && isPlainTextHtml) { + content = clipboardContent['text/plain']; + } else { + content = Utils.innerText(content); + } + } + if (pasteBin.isDefaultContent(content)) { + if (!isKeyBoardPaste) { + editor.windowManager.alert('Please use Ctrl+V/Cmd+V keyboard shortcuts to paste contents.'); + } + return; + } + if (plainTextMode) { + pasteText(editor, content); + } else { + pasteHtml$1(editor, content, internal); + } + } + var getLastRng = function () { + return pasteBin.getLastRng() || editor.selection.getRng(); + }; + editor.on('paste', function (e) { + var clipboardTimer = new Date().getTime(); + var clipboardContent = getClipboardContent(editor, e); + var clipboardDelay = new Date().getTime() - clipboardTimer; + var isKeyBoardPaste = new Date().getTime() - keyboardPasteTimeStamp - clipboardDelay < 1000; + var plainTextMode = pasteFormat.get() === 'text' || keyboardPastePlainTextState; + var internal = hasContentType(clipboardContent, InternalHtml.internalHtmlMime()); + keyboardPastePlainTextState = false; + if (e.isDefaultPrevented() || isBrokenAndroidClipboardEvent(e)) { + pasteBin.remove(); + return; + } + if (!hasHtmlOrText(clipboardContent) && pasteImageData(editor, e, getLastRng())) { + pasteBin.remove(); + return; + } + if (!isKeyBoardPaste) { + e.preventDefault(); + } + if (global$1.ie && (!isKeyBoardPaste || e.ieFake) && !hasContentType(clipboardContent, 'text/html')) { + pasteBin.create(); + editor.dom.bind(pasteBin.getEl(), 'paste', function (e) { + e.stopPropagation(); + }); + editor.getDoc().execCommand('Paste', false, null); + clipboardContent['text/html'] = pasteBin.getHtml(); + } + if (hasContentType(clipboardContent, 'text/html')) { + e.preventDefault(); + if (!internal) { + internal = InternalHtml.isMarked(clipboardContent['text/html']); + } + insertClipboardContent(clipboardContent, isKeyBoardPaste, plainTextMode, internal); + } else { + global$2.setEditorTimeout(editor, function () { + insertClipboardContent(clipboardContent, isKeyBoardPaste, plainTextMode, internal); + }, 0); + } + }); + }; + var registerEventsAndFilters = function (editor, pasteBin, pasteFormat) { + registerEventHandlers(editor, pasteBin, pasteFormat); + var src; + editor.parser.addNodeFilter('img', function (nodes, name$$1, args) { + var isPasteInsert = function (args) { + return args.data && args.data.paste === true; + }; + var remove = function (node) { + if (!node.attr('data-mce-object') && src !== global$1.transparentSrc) { + node.remove(); + } + }; + var isWebKitFakeUrl = function (src) { + return src.indexOf('webkit-fake-url') === 0; + }; + var isDataUri = function (src) { + return src.indexOf('data:') === 0; + }; + if (!editor.settings.paste_data_images && isPasteInsert(args)) { + var i = nodes.length; + while (i--) { + src = nodes[i].attributes.map.src; + if (!src) { + continue; + } + if (isWebKitFakeUrl(src)) { + remove(nodes[i]); + } else if (!editor.settings.allow_html_data_urls && isDataUri(src)) { + remove(nodes[i]); + } + } + } + }); + }; + + var getPasteBinParent = function (editor) { + return global$1.ie && editor.inline ? document.body : editor.getBody(); + }; + var isExternalPasteBin = function (editor) { + return getPasteBinParent(editor) !== editor.getBody(); + }; + var delegatePasteEvents = function (editor, pasteBinElm, pasteBinDefaultContent) { + if (isExternalPasteBin(editor)) { + editor.dom.bind(pasteBinElm, 'paste keyup', function (e) { + if (!isDefault(editor, pasteBinDefaultContent)) { + editor.fire('paste'); + } + }); + } + }; + var create = function (editor, lastRngCell, pasteBinDefaultContent) { + var dom = editor.dom, body = editor.getBody(); + var pasteBinElm; + lastRngCell.set(editor.selection.getRng()); + pasteBinElm = editor.dom.add(getPasteBinParent(editor), 'div', { + 'id': 'mcepastebin', + 'class': 'mce-pastebin', + 'contentEditable': true, + 'data-mce-bogus': 'all', + 'style': 'position: fixed; top: 50%; width: 10px; height: 10px; overflow: hidden; opacity: 0' + }, pasteBinDefaultContent); + if (global$1.ie || global$1.gecko) { + dom.setStyle(pasteBinElm, 'left', dom.getStyle(body, 'direction', true) === 'rtl' ? 65535 : -65535); + } + dom.bind(pasteBinElm, 'beforedeactivate focusin focusout', function (e) { + e.stopPropagation(); + }); + delegatePasteEvents(editor, pasteBinElm, pasteBinDefaultContent); + pasteBinElm.focus(); + editor.selection.select(pasteBinElm, true); + }; + var remove = function (editor, lastRngCell) { + if (getEl(editor)) { + var pasteBinClone = void 0; + var lastRng = lastRngCell.get(); + while (pasteBinClone = editor.dom.get('mcepastebin')) { + editor.dom.remove(pasteBinClone); + editor.dom.unbind(pasteBinClone); + } + if (lastRng) { + editor.selection.setRng(lastRng); + } + } + lastRngCell.set(null); + }; + var getEl = function (editor) { + return editor.dom.get('mcepastebin'); + }; + var getHtml = function (editor) { + var pasteBinElm, pasteBinClones, i, dirtyWrappers, cleanWrapper; + var copyAndRemove = function (toElm, fromElm) { + toElm.appendChild(fromElm); + editor.dom.remove(fromElm, true); + }; + pasteBinClones = global$3.grep(getPasteBinParent(editor).childNodes, function (elm) { + return elm.id === 'mcepastebin'; + }); + pasteBinElm = pasteBinClones.shift(); + global$3.each(pasteBinClones, function (pasteBinClone) { + copyAndRemove(pasteBinElm, pasteBinClone); + }); + dirtyWrappers = editor.dom.select('div[id=mcepastebin]', pasteBinElm); + for (i = dirtyWrappers.length - 1; i >= 0; i--) { + cleanWrapper = editor.dom.create('div'); + pasteBinElm.insertBefore(cleanWrapper, dirtyWrappers[i]); + copyAndRemove(cleanWrapper, dirtyWrappers[i]); + } + return pasteBinElm ? pasteBinElm.innerHTML : ''; + }; + var getLastRng = function (lastRng) { + return lastRng.get(); + }; + var isDefaultContent = function (pasteBinDefaultContent, content) { + return content === pasteBinDefaultContent; + }; + var isPasteBin = function (elm) { + return elm && elm.id === 'mcepastebin'; + }; + var isDefault = function (editor, pasteBinDefaultContent) { + var pasteBinElm = getEl(editor); + return isPasteBin(pasteBinElm) && isDefaultContent(pasteBinDefaultContent, pasteBinElm.innerHTML); + }; + var PasteBin = function (editor) { + var lastRng = Cell(null); + var pasteBinDefaultContent = '%MCEPASTEBIN%'; + return { + create: function () { + return create(editor, lastRng, pasteBinDefaultContent); + }, + remove: function () { + return remove(editor, lastRng); + }, + getEl: function () { + return getEl(editor); + }, + getHtml: function () { + return getHtml(editor); + }, + getLastRng: function () { + return getLastRng(lastRng); + }, + isDefault: function () { + return isDefault(editor, pasteBinDefaultContent); + }, + isDefaultContent: function (content) { + return isDefaultContent(pasteBinDefaultContent, content); + } + }; + }; + + var Clipboard = function (editor, pasteFormat) { + var pasteBin = PasteBin(editor); + editor.on('preInit', function () { + return registerEventsAndFilters(editor, pasteBin, pasteFormat); + }); + return { + pasteFormat: pasteFormat, + pasteHtml: function (html, internalFlag) { + return pasteHtml$1(editor, html, internalFlag); + }, + pasteText: function (text) { + return pasteText(editor, text); + }, + pasteImageData: function (e, rng) { + return pasteImageData(editor, e, rng); + }, + getDataTransferItems: getDataTransferItems, + hasHtmlOrText: hasHtmlOrText, + hasContentType: hasContentType + }; + }; + + var noop$1 = function () { + }; + var hasWorkingClipboardApi = function (clipboardData) { + return global$1.iOS === false && clipboardData !== undefined && typeof clipboardData.setData === 'function' && Utils.isMsEdge() !== true; + }; + var setHtml5Clipboard = function (clipboardData, html, text) { + if (hasWorkingClipboardApi(clipboardData)) { + try { + clipboardData.clearData(); + clipboardData.setData('text/html', html); + clipboardData.setData('text/plain', text); + clipboardData.setData(InternalHtml.internalHtmlMime(), html); + return true; + } catch (e) { + return false; + } + } else { + return false; + } + }; + var setClipboardData = function (evt, data, fallback, done) { + if (setHtml5Clipboard(evt.clipboardData, data.html, data.text)) { + evt.preventDefault(); + done(); + } else { + fallback(data.html, done); + } + }; + var fallback = function (editor) { + return function (html, done) { + var markedHtml = InternalHtml.mark(html); + var outer = editor.dom.create('div', { + 'contenteditable': 'false', + 'data-mce-bogus': 'all' + }); + var inner = editor.dom.create('div', { contenteditable: 'true' }, markedHtml); + editor.dom.setStyles(outer, { + position: 'fixed', + top: '0', + left: '-3000px', + width: '1000px', + overflow: 'hidden' + }); + outer.appendChild(inner); + editor.dom.add(editor.getBody(), outer); + var range = editor.selection.getRng(); + inner.focus(); + var offscreenRange = editor.dom.createRng(); + offscreenRange.selectNodeContents(inner); + editor.selection.setRng(offscreenRange); + setTimeout(function () { + editor.selection.setRng(range); + outer.parentNode.removeChild(outer); + done(); + }, 0); + }; + }; + var getData = function (editor) { + return { + html: editor.selection.getContent({ contextual: true }), + text: editor.selection.getContent({ format: 'text' }) + }; + }; + var isTableSelection = function (editor) { + return !!editor.dom.getParent(editor.selection.getStart(), 'td[data-mce-selected],th[data-mce-selected]', editor.getBody()); + }; + var hasSelectedContent = function (editor) { + return !editor.selection.isCollapsed() || isTableSelection(editor); + }; + var cut = function (editor) { + return function (evt) { + if (hasSelectedContent(editor)) { + setClipboardData(evt, getData(editor), fallback(editor), function () { + setTimeout(function () { + editor.execCommand('Delete'); + }, 0); + }); + } + }; + }; + var copy = function (editor) { + return function (evt) { + if (hasSelectedContent(editor)) { + setClipboardData(evt, getData(editor), fallback(editor), noop$1); + } + }; + }; + var register$1 = function (editor) { + editor.on('cut', cut(editor)); + editor.on('copy', copy(editor)); + }; + var CutCopy = { register: register$1 }; + + var global$a = tinymce.util.Tools.resolve('tinymce.dom.RangeUtils'); + + var getCaretRangeFromEvent = function (editor, e) { + return global$a.getCaretRangeFromPoint(e.clientX, e.clientY, editor.getDoc()); + }; + var isPlainTextFileUrl = function (content) { + var plainTextContent = content['text/plain']; + return plainTextContent ? plainTextContent.indexOf('file://') === 0 : false; + }; + var setFocusedRange = function (editor, rng) { + editor.focus(); + editor.selection.setRng(rng); + }; + var setup = function (editor, clipboard, draggingInternallyState) { + if (Settings.shouldBlockDrop(editor)) { + editor.on('dragend dragover draggesture dragdrop drop drag', function (e) { + e.preventDefault(); + e.stopPropagation(); + }); + } + if (!Settings.shouldPasteDataImages(editor)) { + editor.on('drop', function (e) { + var dataTransfer = e.dataTransfer; + if (dataTransfer && dataTransfer.files && dataTransfer.files.length > 0) { + e.preventDefault(); + } + }); + } + editor.on('drop', function (e) { + var dropContent, rng; + rng = getCaretRangeFromEvent(editor, e); + if (e.isDefaultPrevented() || draggingInternallyState.get()) { + return; + } + dropContent = clipboard.getDataTransferItems(e.dataTransfer); + var internal = clipboard.hasContentType(dropContent, InternalHtml.internalHtmlMime()); + if ((!clipboard.hasHtmlOrText(dropContent) || isPlainTextFileUrl(dropContent)) && clipboard.pasteImageData(e, rng)) { + return; + } + if (rng && Settings.shouldFilterDrop(editor)) { + var content_1 = dropContent['mce-internal'] || dropContent['text/html'] || dropContent['text/plain']; + if (content_1) { + e.preventDefault(); + global$2.setEditorTimeout(editor, function () { + editor.undoManager.transact(function () { + if (dropContent['mce-internal']) { + editor.execCommand('Delete'); + } + setFocusedRange(editor, rng); + content_1 = Utils.trimHtml(content_1); + if (!dropContent['text/html']) { + clipboard.pasteText(content_1); + } else { + clipboard.pasteHtml(content_1, internal); + } + }); + }); + } + } + }); + editor.on('dragstart', function (e) { + draggingInternallyState.set(true); + }); + editor.on('dragover dragend', function (e) { + if (Settings.shouldPasteDataImages(editor) && draggingInternallyState.get() === false) { + e.preventDefault(); + setFocusedRange(editor, getCaretRangeFromEvent(editor, e)); + } + if (e.type === 'dragend') { + draggingInternallyState.set(false); + } + }); + }; + var DragDrop = { setup: setup }; + + var setup$1 = function (editor) { + var plugin = editor.plugins.umbpaste; + var preProcess = Settings.getPreProcess(editor); + if (preProcess) { + editor.on('PastePreProcess', function (e) { + preProcess.call(plugin, plugin, e); + }); + } + var postProcess = Settings.getPostProcess(editor); + if (postProcess) { + editor.on('PastePostProcess', function (e) { + postProcess.call(plugin, plugin, e); + }); + } + }; + var PrePostProcess = { setup: setup$1 }; + + function addPreProcessFilter(editor, filterFunc) { + editor.on('PastePreProcess', function (e) { + e.content = filterFunc(editor, e.content, e.internal, e.wordContent); + }); + } + function addPostProcessFilter(editor, filterFunc) { + editor.on('PastePostProcess', function (e) { + filterFunc(editor, e.node); + }); + } + function removeExplorerBrElementsAfterBlocks(editor, html) { + if (!WordFilter.isWordContent(html)) { + return html; + } + var blockElements = []; + global$3.each(editor.schema.getBlockElements(), function (block, blockName) { + blockElements.push(blockName); + }); + var explorerBlocksRegExp = new RegExp('(?:
 [\\s\\r\\n]+|
)*(<\\/?(' + blockElements.join('|') + ')[^>]*>)(?:
 [\\s\\r\\n]+|
)*', 'g'); + html = Utils.filter(html, [[ + explorerBlocksRegExp, + '$1' + ]]); + html = Utils.filter(html, [ + [ + /

/g, + '

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

/g, + '
' + ] + ]); + return html; + } + function removeWebKitStyles(editor, content, internal, isWordHtml) { + if (isWordHtml || internal) { + return content; + } + var webKitStylesSetting = Settings.getWebkitStyles(editor); + var webKitStyles; + if (Settings.shouldRemoveWebKitStyles(editor) === false || webKitStylesSetting === 'all') { + return content; + } + if (webKitStylesSetting) { + webKitStyles = webKitStylesSetting.split(/[, ]/); + } + if (webKitStyles) { + var dom_1 = editor.dom, node_1 = editor.selection.getNode(); + content = content.replace(/(<[^>]+) style="([^"]*)"([^>]*>)/gi, function (all, before, value, after) { + var inputStyles = dom_1.parseStyle(dom_1.decode(value)); + var outputStyles = {}; + if (webKitStyles === 'none') { + return before + after; + } + for (var i = 0; i < webKitStyles.length; i++) { + var inputValue = inputStyles[webKitStyles[i]], currentValue = dom_1.getStyle(node_1, webKitStyles[i], true); + if (/color/.test(webKitStyles[i])) { + inputValue = dom_1.toHex(inputValue); + currentValue = dom_1.toHex(currentValue); + } + if (currentValue !== inputValue) { + outputStyles[webKitStyles[i]] = inputValue; + } + } + outputStyles = dom_1.serializeStyle(outputStyles, 'span'); + if (outputStyles) { + return before + ' style="' + outputStyles + '"' + after; + } + return before + after; + }); + } else { + content = content.replace(/(<[^>]+) style="([^"]*)"([^>]*>)/gi, '$1$3'); + } + content = content.replace(/(<[^>]+) data-mce-style="([^"]+)"([^>]*>)/gi, function (all, before, value, after) { + return before + ' style="' + value + '"' + after; + }); + return content; + } + function removeUnderlineAndFontInAnchor(editor, root) { + editor.$('a', root).find('font,u').each(function (i, node) { + editor.dom.remove(node, true); + }); + } + var setup$2 = function (editor) { + if (global$1.webkit) { + addPreProcessFilter(editor, removeWebKitStyles); + } + if (global$1.ie) { + addPreProcessFilter(editor, removeExplorerBrElementsAfterBlocks); + addPostProcessFilter(editor, removeUnderlineAndFontInAnchor); + } + }; + var Quirks = { setup: setup$2 }; + + var stateChange = function (editor, clipboard, e) { + var ctrl = e.control; + ctrl.active(clipboard.pasteFormat.get() === 'text'); + editor.on('PastePlainTextToggle', function (e) { + ctrl.active(e.state); + }); + }; + var register$2 = function (editor, clipboard) { + var postRender = curry(stateChange, editor, clipboard); + editor.addButton('pastetext', { + active: false, + icon: 'pastetext', + tooltip: 'Paste as text', + cmd: 'mceTogglePlainTextPaste', + onPostRender: postRender + }); + editor.addMenuItem('pastetext', { + text: 'Paste as text', + selectable: true, + active: clipboard.pasteFormat, + cmd: 'mceTogglePlainTextPaste', + onPostRender: postRender + }); + }; + var Buttons = { register: register$2 }; + + global.add('umbpaste', function (editor) { + if (DetectProPlugin.hasProPlugin(editor) === false) { + var userIsInformedState = Cell(false); + var draggingInternallyState = Cell(false); + var pasteFormat = Cell(Settings.isPasteAsTextEnabled(editor) ? 'text' : 'html'); + var clipboard = Clipboard(editor, pasteFormat); + var quirks = Quirks.setup(editor); + Buttons.register(editor, clipboard); + Commands.register(editor, clipboard, userIsInformedState); + PrePostProcess.setup(editor); + CutCopy.register(editor); + DragDrop.setup(editor, clipboard, draggingInternallyState); + return Api.get(clipboard, quirks); + } + }); + function Plugin () { + } + + return Plugin; + +}()); +})(); diff --git a/src/Umbraco.Web.UI.Client/src/common/services/tinymce.service.js b/src/Umbraco.Web.UI.Client/src/common/services/tinymce.service.js index 8d96863610..0832dc0e15 100644 --- a/src/Umbraco.Web.UI.Client/src/common/services/tinymce.service.js +++ b/src/Umbraco.Web.UI.Client/src/common/services/tinymce.service.js @@ -204,6 +204,9 @@ function tinyMceService($rootScope, $q, imageHelper, $locale, $http, $timeout, s function initEvents(editor){ editor.on('SetContent', function (e) { + + console.log("setcontent", e) + var content = e.content; // Upload BLOB images (dragged/pasted ones) @@ -233,14 +236,22 @@ function tinyMceService($rootScope, $q, imageHelper, $locale, $http, $timeout, s }); } - function cleanupPastedData(plugin, args) { + function cleanupPasteData(plugin, args) { + + console.log("cleanupPasteData", args.content); // Remove spans - var spanRemoveRegex = new RegExp("<\/?span[^>]*>([^<\/span]*)<\/span([^>]*)", "g"); - args.content = args.content.replace(spanRemoveRegex,""); + //var spanRemoveRegex = new RegExp("]*>([^]*)", "g"); + //args.content = args.content.replace(spanRemoveRegex, "$1"); + args.content = args.content.replace(/<\s*span[^>]*>(.*?)<\s*\/\s*span>/g, "$1"); // Convert b to strong. - args.content = args.content.replace(/]*)>([^<\/b]*)<\/b([^>]*)>/g, "$2"); + args.content = args.content.replace(/<\s*b([^>]*)>(.*?)<\s*\/\s*b([^>]*)>/g, "$2"); + + // convert i to em + args.content = args.content.replace(/<\s*i([^>]*)>(.*?)<\s*\/\s*i([^>]*)>/g, "$2"); + + console.log(args.content); } @@ -272,6 +283,7 @@ function tinyMceService($rootScope, $q, imageHelper, $locale, $http, $timeout, s //plugins that must always be active plugins.push("autoresize"); plugins.push("noneditable"); + plugins.push("image"); var modeTheme = ''; var modeInline = false; @@ -344,11 +356,11 @@ function tinyMceService($rootScope, $q, imageHelper, $locale, $http, $timeout, s init_instance_callback: initEvents }; - if (tinyMceConfig.pasteTidying) { - plugins.push("paste"); + //if (tinyMceConfig.pasteTidying) { + plugins.push("umbpaste"); // We keep spans here, cause removing spans here also removes b-tags inside of them, instead we strip them out later. - var validElements = "-b,-strong,-i,-em,span,p,a,table,th,thead,tbody,tr,td,ul,ol,li,dl,dt,dd,iframe,svg,img,hr,abbr,sub,sup,figure,picture"; + var validElements = "-strong/b,-em/i,-u,-span,-p,-ol,-ul,-li,-p/div,-a[href|name],sub,sup,strike,br,del,table[width],tr,td[colspan|rowspan|width],th[colspan|rowspan|width],thead,tfoot,tbody,img,ul,ol,li" // add valid elements from styleFormats. var style, i = 0; @@ -361,6 +373,10 @@ function tinyMceService($rootScope, $q, imageHelper, $locale, $http, $timeout, s var pasteConfig = { + //paste_block_drop: false, + //paste_filter_drop: true, + //paste_enable_default_filters: false, // to avoid stripping img tags from word. + paste_remove_styles: true, paste_text_linebreaktype: true, paste_strip_class_attributes: "all", @@ -368,12 +384,12 @@ function tinyMceService($rootScope, $q, imageHelper, $locale, $http, $timeout, s paste_word_valid_elements: validElements, - paste_preprocess: prepaste + paste_preprocess: cleanupPasteData }; - angular.extend(config, cleanupPastedData); - } + angular.extend(config, pasteConfig); + //} if (tinyMceConfig.customConfig) { From ec2e27dd07fb9439f358fc0033f3610551c501dd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Niels=20Lyngs=C3=B8?= Date: Thu, 19 Sep 2019 08:21:06 +0200 Subject: [PATCH 04/10] img configs for tiny --- .../src/common/services/tinymce.service.js | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/common/services/tinymce.service.js b/src/Umbraco.Web.UI.Client/src/common/services/tinymce.service.js index 0832dc0e15..f0084e1f64 100644 --- a/src/Umbraco.Web.UI.Client/src/common/services/tinymce.service.js +++ b/src/Umbraco.Web.UI.Client/src/common/services/tinymce.service.js @@ -205,7 +205,7 @@ function tinyMceService($rootScope, $q, imageHelper, $locale, $http, $timeout, s editor.on('SetContent', function (e) { - console.log("setcontent", e) + console.log("> setcontent", e) var content = e.content; @@ -357,10 +357,13 @@ function tinyMceService($rootScope, $q, imageHelper, $locale, $http, $timeout, s }; //if (tinyMceConfig.pasteTidying) { + plugins.splice(plugins.indexOf("paste"), 1); plugins.push("umbpaste"); + console.log("plugins:", plugins) + // We keep spans here, cause removing spans here also removes b-tags inside of them, instead we strip them out later. - var validElements = "-strong/b,-em/i,-u,-span,-p,-ol,-ul,-li,-p/div,-a[href|name],sub,sup,strike,br,del,table[width],tr,td[colspan|rowspan|width],th[colspan|rowspan|width],thead,tfoot,tbody,img,ul,ol,li" + var validElements = "-strong/b,-em/i,-u,-span,-p,-ol,-ul,-li,-p/div,-a[href|name],sub,sup,strike,br,del,table[width],tr,td[colspan|rowspan|width],th[colspan|rowspan|width],thead,tfoot,tbody,img[src|alt|width|height],ul,ol,li" // add valid elements from styleFormats. var style, i = 0; From f8b248928844b810ec3bac5b7b415cb80ba9384c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Niels=20Lyngs=C3=B8?= Date: Thu, 19 Sep 2019 09:18:11 +0200 Subject: [PATCH 05/10] clean out image tests --- src/Umbraco.Web.UI.Client/gulp/tasks/watch.js | 7 -- .../src/common/services/tinymce.service.js | 66 +++++++------------ 2 files changed, 24 insertions(+), 49 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/gulp/tasks/watch.js b/src/Umbraco.Web.UI.Client/gulp/tasks/watch.js index 5c2fa2e5c8..9077cc693e 100644 --- a/src/Umbraco.Web.UI.Client/gulp/tasks/watch.js +++ b/src/Umbraco.Web.UI.Client/gulp/tasks/watch.js @@ -54,12 +54,5 @@ gulp.task('watch', function () { .pipe(gulp.dest(config.root + config.targets.js)) ); - - //watch all lib files that will not be merged - copy single file changes - stream.add( - watch(config.sources.globs.lib, { interval: watchInterval }) - .pipe(gulp.dest(config.root + config.targets.lib)) - ); - return stream; }); diff --git a/src/Umbraco.Web.UI.Client/src/common/services/tinymce.service.js b/src/Umbraco.Web.UI.Client/src/common/services/tinymce.service.js index f0084e1f64..211e69abb0 100644 --- a/src/Umbraco.Web.UI.Client/src/common/services/tinymce.service.js +++ b/src/Umbraco.Web.UI.Client/src/common/services/tinymce.service.js @@ -205,8 +205,6 @@ function tinyMceService($rootScope, $q, imageHelper, $locale, $http, $timeout, s editor.on('SetContent', function (e) { - console.log("> setcontent", e) - var content = e.content; // Upload BLOB images (dragged/pasted ones) @@ -238,11 +236,7 @@ function tinyMceService($rootScope, $q, imageHelper, $locale, $http, $timeout, s function cleanupPasteData(plugin, args) { - console.log("cleanupPasteData", args.content); - // Remove spans - //var spanRemoveRegex = new RegExp("]*>([^]*)", "g"); - //args.content = args.content.replace(spanRemoveRegex, "$1"); args.content = args.content.replace(/<\s*span[^>]*>(.*?)<\s*\/\s*span>/g, "$1"); // Convert b to strong. @@ -251,7 +245,6 @@ function tinyMceService($rootScope, $q, imageHelper, $locale, $http, $timeout, s // convert i to em args.content = args.content.replace(/<\s*i([^>]*)>(.*?)<\s*\/\s*i([^>]*)>/g, "$2"); - console.log(args.content); } @@ -283,7 +276,6 @@ function tinyMceService($rootScope, $q, imageHelper, $locale, $http, $timeout, s //plugins that must always be active plugins.push("autoresize"); plugins.push("noneditable"); - plugins.push("image"); var modeTheme = ''; var modeInline = false; @@ -356,43 +348,33 @@ function tinyMceService($rootScope, $q, imageHelper, $locale, $http, $timeout, s init_instance_callback: initEvents }; - //if (tinyMceConfig.pasteTidying) { - plugins.splice(plugins.indexOf("paste"), 1); - plugins.push("umbpaste"); - - console.log("plugins:", plugins) - - // We keep spans here, cause removing spans here also removes b-tags inside of them, instead we strip them out later. - var validElements = "-strong/b,-em/i,-u,-span,-p,-ol,-ul,-li,-p/div,-a[href|name],sub,sup,strike,br,del,table[width],tr,td[colspan|rowspan|width],th[colspan|rowspan|width],thead,tfoot,tbody,img[src|alt|width|height],ul,ol,li" - - // add valid elements from styleFormats. - var style, i = 0; - for(; i < styles.styleFormats.length; i++) { - style = styles.styleFormats[i]; - if(style.block) { - validElements += "," + style.block; - } + // We keep spans here, cause removing spans here also removes b-tags inside of them, instead we strip them out later. + var validElements = "-strong/b,-em/i,-u,-span,-p,-ol,-ul,-li,-p/div,-a[href|name],sub,sup,strike,br,del,table[width],tr,td[colspan|rowspan|width],th[colspan|rowspan|width],thead,tfoot,tbody,img[src|alt|width|height],ul,ol,li" + + // add valid elements from styleFormats. + var style, i = 0; + for(; i < styles.styleFormats.length; i++) { + style = styles.styleFormats[i]; + if(style.block) { + validElements += "," + style.block; } + } + + var pasteConfig = { - var pasteConfig = { - - //paste_block_drop: false, - //paste_filter_drop: true, - //paste_enable_default_filters: false, // to avoid stripping img tags from word. - - paste_remove_styles: true, - paste_text_linebreaktype: true, - paste_strip_class_attributes: "all", - paste_retain_style_properties: "all", - - paste_word_valid_elements: validElements, - - paste_preprocess: cleanupPasteData - - }; + paste_remove_styles: true, + paste_text_linebreaktype: true, + paste_strip_class_attributes: "all", + paste_retain_style_properties: "all", - angular.extend(config, pasteConfig); - //} + paste_word_valid_elements: validElements, + + paste_preprocess: cleanupPasteData + + }; + + angular.extend(config, pasteConfig); + if (tinyMceConfig.customConfig) { From 380d876f7ec22b53b479fdc0d49cdb1a7df1a4dd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Niels=20Lyngs=C3=B8?= Date: Thu, 19 Sep 2019 09:19:20 +0200 Subject: [PATCH 06/10] remove test of umb-paste-plugin --- .../lib/tinymce/plugins/umbpaste/index.js | 7 - .../tinymce/plugins/umbpaste/plugin.min.js | 1867 ----------------- 2 files changed, 1874 deletions(-) delete mode 100644 src/Umbraco.Web.UI.Client/lib/tinymce/plugins/umbpaste/index.js delete mode 100644 src/Umbraco.Web.UI.Client/lib/tinymce/plugins/umbpaste/plugin.min.js diff --git a/src/Umbraco.Web.UI.Client/lib/tinymce/plugins/umbpaste/index.js b/src/Umbraco.Web.UI.Client/lib/tinymce/plugins/umbpaste/index.js deleted file mode 100644 index b54d9d1384..0000000000 --- a/src/Umbraco.Web.UI.Client/lib/tinymce/plugins/umbpaste/index.js +++ /dev/null @@ -1,7 +0,0 @@ -// Exports the "paste" plugin for usage with module loaders -// Usage: -// CommonJS: -// require('tinymce/plugins/paste') -// ES2015: -// import 'tinymce/plugins/paste' -require('./plugin.js'); \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/lib/tinymce/plugins/umbpaste/plugin.min.js b/src/Umbraco.Web.UI.Client/lib/tinymce/plugins/umbpaste/plugin.min.js deleted file mode 100644 index e197012bfa..0000000000 --- a/src/Umbraco.Web.UI.Client/lib/tinymce/plugins/umbpaste/plugin.min.js +++ /dev/null @@ -1,1867 +0,0 @@ -(function () { -var paste = (function () { - 'use strict'; - - var Cell = function (initial) { - var value = initial; - var get = function () { - return value; - }; - var set = function (v) { - value = v; - }; - var clone = function () { - return Cell(get()); - }; - return { - get: get, - set: set, - clone: clone - }; - }; - - var global = tinymce.util.Tools.resolve('tinymce.PluginManager'); - - var hasProPlugin = function (editor) { - if (/(^|[ ,])powerpaste([, ]|$)/.test(editor.settings.plugins) && global.get('powerpaste')) { - if (typeof window.console !== 'undefined' && window.console.log) { - window.console.log('PowerPaste is incompatible with Paste plugin! Remove \'umbpaste\' from the \'plugins\' option.'); - } - return true; - } else { - return false; - } - }; - var DetectProPlugin = { hasProPlugin: hasProPlugin }; - - var get = function (clipboard, quirks) { - return { - clipboard: clipboard, - quirks: quirks - }; - }; - var Api = { get: get }; - - var firePastePreProcess = function (editor, html, internal, isWordHtml) { - return editor.fire('PastePreProcess', { - content: html, - internal: internal, - wordContent: isWordHtml - }); - }; - var firePastePostProcess = function (editor, node, internal, isWordHtml) { - return editor.fire('PastePostProcess', { - node: node, - internal: internal, - wordContent: isWordHtml - }); - }; - var firePastePlainTextToggle = function (editor, state) { - return editor.fire('PastePlainTextToggle', { state: state }); - }; - var firePaste = function (editor, ieFake) { - return editor.fire('paste', { ieFake: ieFake }); - }; - var Events = { - firePastePreProcess: firePastePreProcess, - firePastePostProcess: firePastePostProcess, - firePastePlainTextToggle: firePastePlainTextToggle, - firePaste: firePaste - }; - - var shouldPlainTextInform = function (editor) { - return editor.getParam('paste_plaintext_inform', true); - }; - var shouldBlockDrop = function (editor) { - return editor.getParam('paste_block_drop', false); - }; - var shouldPasteDataImages = function (editor) { - return editor.getParam('paste_data_images', false); - }; - var shouldFilterDrop = function (editor) { - return editor.getParam('paste_filter_drop', true); - }; - var getPreProcess = function (editor) { - return editor.getParam('paste_preprocess'); - }; - var getPostProcess = function (editor) { - return editor.getParam('paste_postprocess'); - }; - var getWebkitStyles = function (editor) { - return editor.getParam('paste_webkit_styles'); - }; - var shouldRemoveWebKitStyles = function (editor) { - return editor.getParam('paste_remove_styles_if_webkit', true); - }; - var shouldMergeFormats = function (editor) { - return editor.getParam('paste_merge_formats', true); - }; - var isSmartPasteEnabled = function (editor) { - return editor.getParam('smart_paste', true); - }; - var isPasteAsTextEnabled = function (editor) { - return editor.getParam('paste_as_text', false); - }; - var getRetainStyleProps = function (editor) { - return editor.getParam('paste_retain_style_properties'); - }; - var getWordValidElements = function (editor) { - var defaultValidElements = '-strong/b,-em/i,-u,-span,-p,-ol,-ul,-li,-h1,-h2,-h3,-h4,-h5,-h6,' + '-p/div,-a[href|name],sub,sup,strike,br,del,table[width],tr,' + 'td[colspan|rowspan|width],th[colspan|rowspan|width],thead,tfoot,tbody'; - return editor.getParam('paste_word_valid_elements', defaultValidElements); - }; - var shouldConvertWordFakeLists = function (editor) { - return editor.getParam('paste_convert_word_fake_lists', true); - }; - var shouldUseDefaultFilters = function (editor) { - return editor.getParam('paste_enable_default_filters', true); - }; - var Settings = { - shouldPlainTextInform: shouldPlainTextInform, - shouldBlockDrop: shouldBlockDrop, - shouldPasteDataImages: shouldPasteDataImages, - shouldFilterDrop: shouldFilterDrop, - getPreProcess: getPreProcess, - getPostProcess: getPostProcess, - getWebkitStyles: getWebkitStyles, - shouldRemoveWebKitStyles: shouldRemoveWebKitStyles, - shouldMergeFormats: shouldMergeFormats, - isSmartPasteEnabled: isSmartPasteEnabled, - isPasteAsTextEnabled: isPasteAsTextEnabled, - getRetainStyleProps: getRetainStyleProps, - getWordValidElements: getWordValidElements, - shouldConvertWordFakeLists: shouldConvertWordFakeLists, - shouldUseDefaultFilters: shouldUseDefaultFilters - }; - - var shouldInformUserAboutPlainText = function (editor, userIsInformedState) { - return userIsInformedState.get() === false && Settings.shouldPlainTextInform(editor); - }; - var displayNotification = function (editor, message) { - editor.notificationManager.open({ - text: editor.translate(message), - type: 'info' - }); - }; - var togglePlainTextPaste = function (editor, clipboard, userIsInformedState) { - if (clipboard.pasteFormat.get() === 'text') { - clipboard.pasteFormat.set('html'); - Events.firePastePlainTextToggle(editor, false); - } else { - clipboard.pasteFormat.set('text'); - Events.firePastePlainTextToggle(editor, true); - if (shouldInformUserAboutPlainText(editor, userIsInformedState)) { - displayNotification(editor, 'Paste is now in plain text mode. Contents will now be pasted as plain text until you toggle this option off.'); - userIsInformedState.set(true); - } - } - editor.focus(); - }; - var Actions = { togglePlainTextPaste: togglePlainTextPaste }; - - var register = function (editor, clipboard, userIsInformedState) { - editor.addCommand('mceTogglePlainTextPaste', function () { - Actions.togglePlainTextPaste(editor, clipboard, userIsInformedState); - }); - editor.addCommand('mceInsertClipboardContent', function (ui, value) { - if (value.content) { - clipboard.pasteHtml(value.content, value.internal); - } - if (value.text) { - clipboard.pasteText(value.text); - } - }); - }; - var Commands = { register: register }; - - var global$1 = tinymce.util.Tools.resolve('tinymce.Env'); - - var global$2 = tinymce.util.Tools.resolve('tinymce.util.Delay'); - - var global$3 = tinymce.util.Tools.resolve('tinymce.util.Tools'); - - var global$4 = tinymce.util.Tools.resolve('tinymce.util.VK'); - - var internalMimeType = 'x-tinymce/html'; - var internalMark = ''; - var mark = function (html) { - return internalMark + html; - }; - var unmark = function (html) { - return html.replace(internalMark, ''); - }; - var isMarked = function (html) { - return html.indexOf(internalMark) !== -1; - }; - var InternalHtml = { - mark: mark, - unmark: unmark, - isMarked: isMarked, - internalHtmlMime: function () { - return internalMimeType; - } - }; - - var global$5 = tinymce.util.Tools.resolve('tinymce.html.Entities'); - - var isPlainText = function (text) { - return !/<(?:\/?(?!(?:div|p|br|span)>)\w+|(?:(?!(?:span style="white-space:\s?pre;?">)|br\s?\/>))\w+\s[^>]+)>/i.test(text); - }; - var toBRs = function (text) { - return text.replace(/\r?\n/g, '
'); - }; - var openContainer = function (rootTag, rootAttrs) { - var key; - var attrs = []; - var tag = '<' + rootTag; - if (typeof rootAttrs === 'object') { - for (key in rootAttrs) { - if (rootAttrs.hasOwnProperty(key)) { - attrs.push(key + '="' + global$5.encodeAllRaw(rootAttrs[key]) + '"'); - } - } - if (attrs.length) { - tag += ' ' + attrs.join(' '); - } - } - return tag + '>'; - }; - var toBlockElements = function (text, rootTag, rootAttrs) { - var blocks = text.split(/\n\n/); - var tagOpen = openContainer(rootTag, rootAttrs); - var tagClose = ''; - var paragraphs = global$3.map(blocks, function (p) { - return p.split(/\n/).join('
'); - }); - var stitch = function (p) { - return tagOpen + p + tagClose; - }; - return paragraphs.length === 1 ? paragraphs[0] : global$3.map(paragraphs, stitch).join(''); - }; - var convert = function (text, rootTag, rootAttrs) { - return rootTag ? toBlockElements(text, rootTag, rootAttrs) : toBRs(text); - }; - var Newlines = { - isPlainText: isPlainText, - convert: convert, - toBRs: toBRs, - toBlockElements: toBlockElements - }; - - var global$6 = tinymce.util.Tools.resolve('tinymce.html.DomParser'); - - var global$7 = tinymce.util.Tools.resolve('tinymce.html.Node'); - - var global$8 = tinymce.util.Tools.resolve('tinymce.html.Schema'); - - var global$9 = tinymce.util.Tools.resolve('tinymce.html.Serializer'); - - function filter(content, items) { - global$3.each(items, function (v) { - if (v.constructor === RegExp) { - content = content.replace(v, ''); - } else { - content = content.replace(v[0], v[1]); - } - }); - return content; - } - function innerText(html) { - var schema = global$8(); - var domParser = global$6({}, schema); - var text = ''; - var shortEndedElements = schema.getShortEndedElements(); - var ignoreElements = global$3.makeMap('script noscript style textarea video audio iframe object', ' '); - var blockElements = schema.getBlockElements(); - function walk(node) { - var name$$1 = node.name, currentNode = node; - if (name$$1 === 'br') { - text += '\n'; - return; - } - if (name$$1 === 'wbr') { - return; - } - if (shortEndedElements[name$$1]) { - text += ' '; - } - if (ignoreElements[name$$1]) { - text += ' '; - return; - } - if (node.type === 3) { - text += node.value; - } - if (!node.shortEnded) { - if (node = node.firstChild) { - do { - walk(node); - } while (node = node.next); - } - } - if (blockElements[name$$1] && currentNode.next) { - text += '\n'; - if (name$$1 === 'p') { - text += '\n'; - } - } - } - html = filter(html, [//g]); - walk(domParser.parse(html)); - return text; - } - function trimHtml(html) { - function trimSpaces(all, s1, s2) { - if (!s1 && !s2) { - return ' '; - } - return '\xA0'; - } - html = filter(html, [ - /^[\s\S]*]*>\s*|\s*<\/body[^>]*>[\s\S]*$/ig, - /|/g, - [ - /( ?)\u00a0<\/span>( ?)/g, - trimSpaces - ], - /
/g, - /
$/i - ]); - return html; - } - function createIdGenerator(prefix) { - var count = 0; - return function () { - return prefix + count++; - }; - } - var isMsEdge = function () { - return navigator.userAgent.indexOf(' Edge/') !== -1; - }; - var Utils = { - filter: filter, - innerText: innerText, - trimHtml: trimHtml, - createIdGenerator: createIdGenerator, - isMsEdge: isMsEdge - }; - - function isWordContent(content) { - return / 1) { - currentListNode.attr('start', '' + start); - } - paragraphNode.wrap(currentListNode); - } else { - currentListNode.append(paragraphNode); - } - paragraphNode.name = 'li'; - if (level > lastLevel && prevListNode) { - prevListNode.lastChild.append(currentListNode); - } - lastLevel = level; - removeIgnoredNodes(paragraphNode); - trimListStart(paragraphNode, /^\u00a0+/); - trimListStart(paragraphNode, /^\s*([\u2022\u00b7\u00a7\u25CF]|\w+\.)/); - trimListStart(paragraphNode, /^\u00a0+/); - } - var elements = []; - var child = node.firstChild; - while (typeof child !== 'undefined' && child !== null) { - elements.push(child); - child = child.walk(); - if (child !== null) { - while (typeof child !== 'undefined' && child.parent !== node) { - child = child.walk(); - } - } - } - for (var i = 0; i < elements.length; i++) { - node = elements[i]; - if (node.name === 'p' && node.firstChild) { - var nodeText = getText(node); - if (isBulletList(nodeText)) { - convertParagraphToLi(node, 'ul'); - continue; - } - if (isNumericList(nodeText)) { - var matches = /([0-9]+)\./.exec(nodeText); - var start = 1; - if (matches) { - start = parseInt(matches[1], 10); - } - convertParagraphToLi(node, 'ol', start); - continue; - } - if (node._listLevel) { - convertParagraphToLi(node, 'ul', 1); - continue; - } - currentListNode = null; - } else { - prevListNode = currentListNode; - currentListNode = null; - } - } - } - function filterStyles(editor, validStyles, node, styleValue) { - var outputStyles = {}, matches; - var styles = editor.dom.parseStyle(styleValue); - global$3.each(styles, function (value, name) { - switch (name) { - case 'mso-list': - matches = /\w+ \w+([0-9]+)/i.exec(styleValue); - if (matches) { - node._listLevel = parseInt(matches[1], 10); - } - if (/Ignore/i.test(value) && node.firstChild) { - node._listIgnore = true; - node.firstChild._listIgnore = true; - } - break; - case 'horiz-align': - name = 'text-align'; - break; - case 'vert-align': - name = 'vertical-align'; - break; - case 'font-color': - case 'mso-foreground': - name = 'color'; - break; - case 'mso-background': - case 'mso-highlight': - name = 'background'; - break; - case 'font-weight': - case 'font-style': - if (value !== 'normal') { - outputStyles[name] = value; - } - return; - case 'mso-element': - if (/^(comment|comment-list)$/i.test(value)) { - node.remove(); - return; - } - break; - } - if (name.indexOf('mso-comment') === 0) { - node.remove(); - return; - } - if (name.indexOf('mso-') === 0) { - return; - } - if (Settings.getRetainStyleProps(editor) === 'all' || validStyles && validStyles[name]) { - outputStyles[name] = value; - } - }); - if (/(bold)/i.test(outputStyles['font-weight'])) { - delete outputStyles['font-weight']; - node.wrap(new global$7('b', 1)); - } - if (/(italic)/i.test(outputStyles['font-style'])) { - delete outputStyles['font-style']; - node.wrap(new global$7('i', 1)); - } - outputStyles = editor.dom.serializeStyle(outputStyles, node.name); - if (outputStyles) { - return outputStyles; - } - return null; - } - var filterWordContent = function (editor, content) { - - console.log("filterWordContent 3"); - console.log(content); - - content = content.replace(/\/g, '');// removes & - - - var retainStyleProperties, validStyles; - retainStyleProperties = Settings.getRetainStyleProps(editor); - if (retainStyleProperties) { - validStyles = global$3.makeMap(retainStyleProperties.split(/[, ]/)); - } - - content = Utils.filter(content, [ - /
/gi, - /]+id="?docs-internal-[^>]*>/gi, - //gi, - /<(!|script[^>]*>.*?<\/script(?=[>\s])|\/?(\?xml(:\w+)?|img|meta|link|style|\w:\w+)(?=[\s\/>]))[^>]*>/gi, - [ - /<(\/?)s>/gi, - '<$1strike>' - ], - [ - / /gi, - '\xA0' - ], - [ - /([\s\u00a0]*)<\/span>/gi, - function (str, spaces) { - return spaces.length > 0 ? spaces.replace(/./, ' ').slice(Math.floor(spaces.length / 2)).split('').join('\xA0') : ''; - } - ] - ]); - - var validElements = Settings.getWordValidElements(editor); - var schema = global$8({ - valid_elements: validElements, - valid_children: '-li[p]' - }); - global$3.each(schema.elements, function (rule) { - if (!rule.attributes.class) { - rule.attributes.class = {}; - rule.attributesOrder.push('class'); - } - if (!rule.attributes.style) { - rule.attributes.style = {}; - rule.attributesOrder.push('style'); - } - }); - var domParser = global$6({}, schema); - domParser.addAttributeFilter('style', function (nodes) { - var i = nodes.length, node; - while (i--) { - node = nodes[i]; - node.attr('style', filterStyles(editor, validStyles, node, node.attr('style'))); - if (node.name === 'span' && node.parent && !node.attributes.length) { - node.unwrap(); - } - } - }); - domParser.addAttributeFilter('class', function (nodes) { - var i = nodes.length, node, className; - while (i--) { - node = nodes[i]; - className = node.attr('class'); - if (/^(MsoCommentReference|MsoCommentText|msoDel)$/i.test(className)) { - node.remove(); - } - node.attr('class', null); - } - }); - domParser.addNodeFilter('del', function (nodes) { - var i = nodes.length; - while (i--) { - nodes[i].remove(); - } - }); - domParser.addNodeFilter('a', function (nodes) { - var i = nodes.length, node, href, name; - while (i--) { - node = nodes[i]; - href = node.attr('href'); - name = node.attr('name'); - if (href && href.indexOf('#_msocom_') !== -1) { - node.remove(); - continue; - } - if (href && href.indexOf('file://') === 0) { - href = href.split('#')[1]; - if (href) { - href = '#' + href; - } - } - if (!href && !name) { - node.unwrap(); - } else { - if (name && !/^_?(?:toc|edn|ftn)/i.test(name)) { - node.unwrap(); - continue; - } - node.attr({ - href: href, - name: name - }); - } - } - }); - var rootNode = domParser.parse(content); - if (Settings.shouldConvertWordFakeLists(editor)) { - convertFakeListsToProperLists(rootNode); - } - content = global$9({ validate: editor.settings.validate }, schema).serialize(rootNode); - return content; - }; - var preProcess = function (editor, content) { - return Settings.shouldUseDefaultFilters(editor) ? filterWordContent(editor, content) : content; - }; - var WordFilter = { - preProcess: preProcess, - isWordContent: isWordContent - }; - - var processResult = function (content, cancelled) { - return { - content: content, - cancelled: cancelled - }; - }; - var postProcessFilter = function (editor, html, internal, isWordHtml) { - var tempBody = editor.dom.create('div', { style: 'display:none' }, html); - var postProcessArgs = Events.firePastePostProcess(editor, tempBody, internal, isWordHtml); - return processResult(postProcessArgs.node.innerHTML, postProcessArgs.isDefaultPrevented()); - }; - var filterContent = function (editor, content, internal, isWordHtml) { - var preProcessArgs = Events.firePastePreProcess(editor, content, internal, isWordHtml); - if (editor.hasEventListeners('PastePostProcess') && !preProcessArgs.isDefaultPrevented()) { - return postProcessFilter(editor, preProcessArgs.content, internal, isWordHtml); - } else { - return processResult(preProcessArgs.content, preProcessArgs.isDefaultPrevented()); - } - }; - var process = function (editor, html, internal) { - var isWordHtml = WordFilter.isWordContent(html); - var content = isWordHtml ? WordFilter.preProcess(editor, html) : html; - return filterContent(editor, content, internal, isWordHtml); - }; - var ProcessFilters = { process: process }; - - var removeMeta = function (editor, html) { - var body = editor.dom.create('body', {}, html); - global$3.each(body.querySelectorAll('meta'), function (elm) { - return elm.parentNode.removeChild(elm); - }); - return body.innerHTML; - }; - var pasteHtml = function (editor, html) { - editor.insertContent(removeMeta(editor, html), { - merge: Settings.shouldMergeFormats(editor), - paste: true - }); - return true; - }; - var isAbsoluteUrl = function (url) { - return /^https?:\/\/[\w\?\-\/+=.&%@~#]+$/i.test(url); - }; - var isImageUrl = function (url) { - return isAbsoluteUrl(url) && /.(gif|jpe?g|png)$/.test(url); - }; - var createImage = function (editor, url, pasteHtmlFn) { - editor.undoManager.extra(function () { - pasteHtmlFn(editor, url); - }, function () { - editor.insertContent(''); - }); - return true; - }; - var createLink = function (editor, url, pasteHtmlFn) { - editor.undoManager.extra(function () { - pasteHtmlFn(editor, url); - }, function () { - editor.execCommand('mceInsertLink', false, url); - }); - return true; - }; - var linkSelection = function (editor, html, pasteHtmlFn) { - return editor.selection.isCollapsed() === false && isAbsoluteUrl(html) ? createLink(editor, html, pasteHtmlFn) : false; - }; - var insertImage = function (editor, html, pasteHtmlFn) { - return isImageUrl(html) ? createImage(editor, html, pasteHtmlFn) : false; - }; - var smartInsertContent = function (editor, html) { - global$3.each([ - linkSelection, - insertImage, - pasteHtml - ], function (action) { - return action(editor, html, pasteHtml) !== true; - }); - }; - var insertContent = function (editor, html) { - if (Settings.isSmartPasteEnabled(editor) === false) { - pasteHtml(editor, html); - } else { - smartInsertContent(editor, html); - } - }; - var SmartPaste = { - isImageUrl: isImageUrl, - isAbsoluteUrl: isAbsoluteUrl, - insertContent: insertContent - }; - - var constant = function (value) { - return function () { - return value; - }; - }; - function curry(fn) { - var initialArgs = []; - for (var _i = 1; _i < arguments.length; _i++) { - initialArgs[_i - 1] = arguments[_i]; - } - return function () { - var restArgs = []; - for (var _i = 0; _i < arguments.length; _i++) { - restArgs[_i] = arguments[_i]; - } - var all = initialArgs.concat(restArgs); - return fn.apply(null, all); - }; - } - var never = constant(false); - var always = constant(true); - - var never$1 = never; - var always$1 = always; - var none = function () { - return NONE; - }; - var NONE = function () { - var eq = function (o) { - return o.isNone(); - }; - var call$$1 = function (thunk) { - return thunk(); - }; - var id = function (n) { - return n; - }; - var noop$$1 = function () { - }; - var nul = function () { - return null; - }; - var undef = function () { - return undefined; - }; - var me = { - fold: function (n, s) { - return n(); - }, - is: never$1, - isSome: never$1, - isNone: always$1, - getOr: id, - getOrThunk: call$$1, - getOrDie: function (msg) { - throw new Error(msg || 'error: getOrDie called on none.'); - }, - getOrNull: nul, - getOrUndefined: undef, - or: id, - orThunk: call$$1, - map: none, - ap: none, - each: noop$$1, - bind: none, - flatten: none, - exists: never$1, - forall: always$1, - filter: none, - equals: eq, - equals_: eq, - toArray: function () { - return []; - }, - toString: constant('none()') - }; - if (Object.freeze) - Object.freeze(me); - return me; - }(); - var some = function (a) { - var constant_a = function () { - return a; - }; - var self = function () { - return me; - }; - var map = function (f) { - return some(f(a)); - }; - var bind = function (f) { - return f(a); - }; - var me = { - fold: function (n, s) { - return s(a); - }, - is: function (v) { - return a === v; - }, - isSome: always$1, - isNone: never$1, - getOr: constant_a, - getOrThunk: constant_a, - getOrDie: constant_a, - getOrNull: constant_a, - getOrUndefined: constant_a, - or: self, - orThunk: self, - map: map, - ap: function (optfab) { - return optfab.fold(none, function (fab) { - return some(fab(a)); - }); - }, - each: function (f) { - f(a); - }, - bind: bind, - flatten: constant_a, - exists: bind, - forall: bind, - filter: function (f) { - return f(a) ? me : NONE; - }, - equals: function (o) { - return o.is(a); - }, - equals_: function (o, elementEq) { - return o.fold(never$1, function (b) { - return elementEq(a, b); - }); - }, - toArray: function () { - return [a]; - }, - toString: function () { - return 'some(' + a + ')'; - } - }; - return me; - }; - var from = function (value) { - return value === null || value === undefined ? NONE : some(value); - }; - var Option = { - some: some, - none: none, - from: from - }; - - var typeOf = function (x) { - if (x === null) - return 'null'; - var t = typeof x; - if (t === 'object' && Array.prototype.isPrototypeOf(x)) - return 'array'; - if (t === 'object' && String.prototype.isPrototypeOf(x)) - return 'string'; - return t; - }; - var isType = function (type) { - return function (value) { - return typeOf(value) === type; - }; - }; - var isFunction = isType('function'); - - var map = function (xs, f) { - var len = xs.length; - var r = new Array(len); - for (var i = 0; i < len; i++) { - var x = xs[i]; - r[i] = f(x, i, xs); - } - return r; - }; - var each = function (xs, f) { - for (var i = 0, len = xs.length; i < len; i++) { - var x = xs[i]; - f(x, i, xs); - } - }; - var filter$1 = function (xs, pred) { - var r = []; - for (var i = 0, len = xs.length; i < len; i++) { - var x = xs[i]; - if (pred(x, i, xs)) { - r.push(x); - } - } - return r; - }; - var slice = Array.prototype.slice; - var from$1 = isFunction(Array.from) ? Array.from : function (x) { - return slice.call(x); - }; - - var nu = function (baseFn) { - var data = Option.none(); - var callbacks = []; - var map$$1 = function (f) { - return nu(function (nCallback) { - get(function (data) { - nCallback(f(data)); - }); - }); - }; - var get = function (nCallback) { - if (isReady()) - call(nCallback); - else - callbacks.push(nCallback); - }; - var set = function (x) { - data = Option.some(x); - run(callbacks); - callbacks = []; - }; - var isReady = function () { - return data.isSome(); - }; - var run = function (cbs) { - each(cbs, call); - }; - var call = function (cb) { - data.each(function (x) { - setTimeout(function () { - cb(x); - }, 0); - }); - }; - baseFn(set); - return { - get: get, - map: map$$1, - isReady: isReady - }; - }; - var pure$1 = function (a) { - return nu(function (callback) { - callback(a); - }); - }; - var LazyValue = { - nu: nu, - pure: pure$1 - }; - - var bounce = function (f) { - return function () { - var args = []; - for (var _i = 0; _i < arguments.length; _i++) { - args[_i] = arguments[_i]; - } - var me = this; - setTimeout(function () { - f.apply(me, args); - }, 0); - }; - }; - - var nu$1 = function (baseFn) { - var get = function (callback) { - baseFn(bounce(callback)); - }; - var map = function (fab) { - return nu$1(function (callback) { - get(function (a) { - var value = fab(a); - callback(value); - }); - }); - }; - var bind = function (aFutureB) { - return nu$1(function (callback) { - get(function (a) { - aFutureB(a).get(callback); - }); - }); - }; - var anonBind = function (futureB) { - return nu$1(function (callback) { - get(function (a) { - futureB.get(callback); - }); - }); - }; - var toLazy = function () { - return LazyValue.nu(get); - }; - var toCached = function () { - var cache = null; - return nu$1(function (callback) { - if (cache === null) { - cache = toLazy(); - } - cache.get(callback); - }); - }; - return { - map: map, - bind: bind, - anonBind: anonBind, - toLazy: toLazy, - toCached: toCached, - get: get - }; - }; - var pure$2 = function (a) { - return nu$1(function (callback) { - callback(a); - }); - }; - var Future = { - nu: nu$1, - pure: pure$2 - }; - - var par = function (asyncValues, nu) { - return nu(function (callback) { - var r = []; - var count = 0; - var cb = function (i) { - return function (value) { - r[i] = value; - count++; - if (count >= asyncValues.length) { - callback(r); - } - }; - }; - if (asyncValues.length === 0) { - callback([]); - } else { - each(asyncValues, function (asyncValue, i) { - asyncValue.get(cb(i)); - }); - } - }); - }; - - var par$1 = function (futures) { - return par(futures, Future.nu); - }; - var mapM = function (array, fn) { - var futures = map(array, fn); - return par$1(futures); - }; - - var pasteHtml$1 = function (editor, html, internalFlag) { - var internal = internalFlag ? internalFlag : InternalHtml.isMarked(html); - var args = ProcessFilters.process(editor, InternalHtml.unmark(html), internal); - if (args.cancelled === false) { - SmartPaste.insertContent(editor, args.content); - } - }; - var pasteText = function (editor, text) { - text = editor.dom.encode(text).replace(/\r\n/g, '\n'); - text = Newlines.convert(text, editor.settings.forced_root_block, editor.settings.forced_root_block_attrs); - pasteHtml$1(editor, text, false); - }; - var getDataTransferItems = function (dataTransfer) { - var items = {}; - var mceInternalUrlPrefix = 'data:text/mce-internal,'; - if (dataTransfer) { - if (dataTransfer.getData) { - var legacyText = dataTransfer.getData('Text'); - if (legacyText && legacyText.length > 0) { - if (legacyText.indexOf(mceInternalUrlPrefix) === -1) { - items['text/plain'] = legacyText; - } - } - } - if (dataTransfer.types) { - for (var i = 0; i < dataTransfer.types.length; i++) { - var contentType = dataTransfer.types[i]; - try { - items[contentType] = dataTransfer.getData(contentType); - } catch (ex) { - items[contentType] = ''; - } - } - } - } - return items; - }; - var getClipboardContent = function (editor, clipboardEvent) { - var content = getDataTransferItems(clipboardEvent.clipboardData || editor.getDoc().dataTransfer); - return Utils.isMsEdge() ? global$3.extend(content, { 'text/html': '' }) : content; - }; - var hasContentType = function (clipboardContent, mimeType) { - return mimeType in clipboardContent && clipboardContent[mimeType].length > 0; - }; - var hasHtmlOrText = function (content) { - return hasContentType(content, 'text/html') || hasContentType(content, 'text/plain'); - }; - var getBase64FromUri = function (uri) { - var idx; - idx = uri.indexOf(','); - if (idx !== -1) { - return uri.substr(idx + 1); - } - return null; - }; - var isValidDataUriImage = function (settings, imgElm) { - return settings.images_dataimg_filter ? settings.images_dataimg_filter(imgElm) : true; - }; - var extractFilename = function (editor, str) { - var m = str.match(/([\s\S]+?)\.(?:jpeg|jpg|png|gif)$/i); - return m ? editor.dom.encode(m[1]) : null; - }; - var uniqueId = Utils.createIdGenerator('mceclip'); - var pasteImage = function (editor, imageItem) { - var base64 = getBase64FromUri(imageItem.uri); - var id = uniqueId(); - var name$$1 = editor.settings.images_reuse_filename && imageItem.blob.name ? extractFilename(editor, imageItem.blob.name) : id; - var img = new Image(); - img.src = imageItem.uri; - if (isValidDataUriImage(editor.settings, img)) { - var blobCache = editor.editorUpload.blobCache; - var blobInfo = void 0, existingBlobInfo = void 0; - existingBlobInfo = blobCache.findFirst(function (cachedBlobInfo) { - return cachedBlobInfo.base64() === base64; - }); - if (!existingBlobInfo) { - blobInfo = blobCache.create(id, imageItem.blob, base64, name$$1); - blobCache.add(blobInfo); - } else { - blobInfo = existingBlobInfo; - } - pasteHtml$1(editor, '', false); - } else { - pasteHtml$1(editor, '', false); - } - }; - var isClipboardEvent = function (event$$1) { - return event$$1.type === 'paste'; - }; - var readBlobsAsDataUris = function (items) { - return mapM(items, function (item) { - return Future.nu(function (resolve) { - var blob = item.getAsFile ? item.getAsFile() : item; - var reader = new window.FileReader(); - reader.onload = function () { - resolve({ - blob: blob, - uri: reader.result - }); - }; - reader.readAsDataURL(blob); - }); - }); - }; - var getImagesFromDataTransfer = function (dataTransfer) { - var items = dataTransfer.items ? map(from$1(dataTransfer.items), function (item) { - return item.getAsFile(); - }) : []; - var files = dataTransfer.files ? from$1(dataTransfer.files) : []; - var images = filter$1(items.length > 0 ? items : files, function (file) { - return /^image\/(jpeg|png|gif|bmp)$/.test(file.type); - }); - return images; - }; - var pasteImageData = function (editor, e, rng) { - var dataTransfer = isClipboardEvent(e) ? e.clipboardData : e.dataTransfer; - if (editor.settings.paste_data_images && dataTransfer) { - var images = getImagesFromDataTransfer(dataTransfer); - if (images.length > 0) { - e.preventDefault(); - readBlobsAsDataUris(images).get(function (blobResults) { - if (rng) { - editor.selection.setRng(rng); - } - each(blobResults, function (result) { - pasteImage(editor, result); - }); - }); - return true; - } - } - return false; - }; - var isBrokenAndroidClipboardEvent = function (e) { - var clipboardData = e.clipboardData; - return navigator.userAgent.indexOf('Android') !== -1 && clipboardData && clipboardData.items && clipboardData.items.length === 0; - }; - var isKeyboardPasteEvent = function (e) { - return global$4.metaKeyPressed(e) && e.keyCode === 86 || e.shiftKey && e.keyCode === 45; - }; - var registerEventHandlers = function (editor, pasteBin, pasteFormat) { - var keyboardPasteTimeStamp = 0; - var keyboardPastePlainTextState; - editor.on('keydown', function (e) { - function removePasteBinOnKeyUp(e) { - if (isKeyboardPasteEvent(e) && !e.isDefaultPrevented()) { - pasteBin.remove(); - } - } - if (isKeyboardPasteEvent(e) && !e.isDefaultPrevented()) { - keyboardPastePlainTextState = e.shiftKey && e.keyCode === 86; - if (keyboardPastePlainTextState && global$1.webkit && navigator.userAgent.indexOf('Version/') !== -1) { - return; - } - e.stopImmediatePropagation(); - keyboardPasteTimeStamp = new Date().getTime(); - if (global$1.ie && keyboardPastePlainTextState) { - e.preventDefault(); - Events.firePaste(editor, true); - return; - } - pasteBin.remove(); - pasteBin.create(); - editor.once('keyup', removePasteBinOnKeyUp); - editor.once('paste', function () { - editor.off('keyup', removePasteBinOnKeyUp); - }); - } - }); - function insertClipboardContent(clipboardContent, isKeyBoardPaste, plainTextMode, internal) { - var content, isPlainTextHtml; - if (hasContentType(clipboardContent, 'text/html')) { - content = clipboardContent['text/html']; - } else { - content = pasteBin.getHtml(); - internal = internal ? internal : InternalHtml.isMarked(content); - if (pasteBin.isDefaultContent(content)) { - plainTextMode = true; - } - } - content = Utils.trimHtml(content); - pasteBin.remove(); - isPlainTextHtml = internal === false && Newlines.isPlainText(content); - if (!content.length || isPlainTextHtml) { - plainTextMode = true; - } - if (plainTextMode) { - if (hasContentType(clipboardContent, 'text/plain') && isPlainTextHtml) { - content = clipboardContent['text/plain']; - } else { - content = Utils.innerText(content); - } - } - if (pasteBin.isDefaultContent(content)) { - if (!isKeyBoardPaste) { - editor.windowManager.alert('Please use Ctrl+V/Cmd+V keyboard shortcuts to paste contents.'); - } - return; - } - if (plainTextMode) { - pasteText(editor, content); - } else { - pasteHtml$1(editor, content, internal); - } - } - var getLastRng = function () { - return pasteBin.getLastRng() || editor.selection.getRng(); - }; - editor.on('paste', function (e) { - var clipboardTimer = new Date().getTime(); - var clipboardContent = getClipboardContent(editor, e); - var clipboardDelay = new Date().getTime() - clipboardTimer; - var isKeyBoardPaste = new Date().getTime() - keyboardPasteTimeStamp - clipboardDelay < 1000; - var plainTextMode = pasteFormat.get() === 'text' || keyboardPastePlainTextState; - var internal = hasContentType(clipboardContent, InternalHtml.internalHtmlMime()); - keyboardPastePlainTextState = false; - if (e.isDefaultPrevented() || isBrokenAndroidClipboardEvent(e)) { - pasteBin.remove(); - return; - } - if (!hasHtmlOrText(clipboardContent) && pasteImageData(editor, e, getLastRng())) { - pasteBin.remove(); - return; - } - if (!isKeyBoardPaste) { - e.preventDefault(); - } - if (global$1.ie && (!isKeyBoardPaste || e.ieFake) && !hasContentType(clipboardContent, 'text/html')) { - pasteBin.create(); - editor.dom.bind(pasteBin.getEl(), 'paste', function (e) { - e.stopPropagation(); - }); - editor.getDoc().execCommand('Paste', false, null); - clipboardContent['text/html'] = pasteBin.getHtml(); - } - if (hasContentType(clipboardContent, 'text/html')) { - e.preventDefault(); - if (!internal) { - internal = InternalHtml.isMarked(clipboardContent['text/html']); - } - insertClipboardContent(clipboardContent, isKeyBoardPaste, plainTextMode, internal); - } else { - global$2.setEditorTimeout(editor, function () { - insertClipboardContent(clipboardContent, isKeyBoardPaste, plainTextMode, internal); - }, 0); - } - }); - }; - var registerEventsAndFilters = function (editor, pasteBin, pasteFormat) { - registerEventHandlers(editor, pasteBin, pasteFormat); - var src; - editor.parser.addNodeFilter('img', function (nodes, name$$1, args) { - var isPasteInsert = function (args) { - return args.data && args.data.paste === true; - }; - var remove = function (node) { - if (!node.attr('data-mce-object') && src !== global$1.transparentSrc) { - node.remove(); - } - }; - var isWebKitFakeUrl = function (src) { - return src.indexOf('webkit-fake-url') === 0; - }; - var isDataUri = function (src) { - return src.indexOf('data:') === 0; - }; - if (!editor.settings.paste_data_images && isPasteInsert(args)) { - var i = nodes.length; - while (i--) { - src = nodes[i].attributes.map.src; - if (!src) { - continue; - } - if (isWebKitFakeUrl(src)) { - remove(nodes[i]); - } else if (!editor.settings.allow_html_data_urls && isDataUri(src)) { - remove(nodes[i]); - } - } - } - }); - }; - - var getPasteBinParent = function (editor) { - return global$1.ie && editor.inline ? document.body : editor.getBody(); - }; - var isExternalPasteBin = function (editor) { - return getPasteBinParent(editor) !== editor.getBody(); - }; - var delegatePasteEvents = function (editor, pasteBinElm, pasteBinDefaultContent) { - if (isExternalPasteBin(editor)) { - editor.dom.bind(pasteBinElm, 'paste keyup', function (e) { - if (!isDefault(editor, pasteBinDefaultContent)) { - editor.fire('paste'); - } - }); - } - }; - var create = function (editor, lastRngCell, pasteBinDefaultContent) { - var dom = editor.dom, body = editor.getBody(); - var pasteBinElm; - lastRngCell.set(editor.selection.getRng()); - pasteBinElm = editor.dom.add(getPasteBinParent(editor), 'div', { - 'id': 'mcepastebin', - 'class': 'mce-pastebin', - 'contentEditable': true, - 'data-mce-bogus': 'all', - 'style': 'position: fixed; top: 50%; width: 10px; height: 10px; overflow: hidden; opacity: 0' - }, pasteBinDefaultContent); - if (global$1.ie || global$1.gecko) { - dom.setStyle(pasteBinElm, 'left', dom.getStyle(body, 'direction', true) === 'rtl' ? 65535 : -65535); - } - dom.bind(pasteBinElm, 'beforedeactivate focusin focusout', function (e) { - e.stopPropagation(); - }); - delegatePasteEvents(editor, pasteBinElm, pasteBinDefaultContent); - pasteBinElm.focus(); - editor.selection.select(pasteBinElm, true); - }; - var remove = function (editor, lastRngCell) { - if (getEl(editor)) { - var pasteBinClone = void 0; - var lastRng = lastRngCell.get(); - while (pasteBinClone = editor.dom.get('mcepastebin')) { - editor.dom.remove(pasteBinClone); - editor.dom.unbind(pasteBinClone); - } - if (lastRng) { - editor.selection.setRng(lastRng); - } - } - lastRngCell.set(null); - }; - var getEl = function (editor) { - return editor.dom.get('mcepastebin'); - }; - var getHtml = function (editor) { - var pasteBinElm, pasteBinClones, i, dirtyWrappers, cleanWrapper; - var copyAndRemove = function (toElm, fromElm) { - toElm.appendChild(fromElm); - editor.dom.remove(fromElm, true); - }; - pasteBinClones = global$3.grep(getPasteBinParent(editor).childNodes, function (elm) { - return elm.id === 'mcepastebin'; - }); - pasteBinElm = pasteBinClones.shift(); - global$3.each(pasteBinClones, function (pasteBinClone) { - copyAndRemove(pasteBinElm, pasteBinClone); - }); - dirtyWrappers = editor.dom.select('div[id=mcepastebin]', pasteBinElm); - for (i = dirtyWrappers.length - 1; i >= 0; i--) { - cleanWrapper = editor.dom.create('div'); - pasteBinElm.insertBefore(cleanWrapper, dirtyWrappers[i]); - copyAndRemove(cleanWrapper, dirtyWrappers[i]); - } - return pasteBinElm ? pasteBinElm.innerHTML : ''; - }; - var getLastRng = function (lastRng) { - return lastRng.get(); - }; - var isDefaultContent = function (pasteBinDefaultContent, content) { - return content === pasteBinDefaultContent; - }; - var isPasteBin = function (elm) { - return elm && elm.id === 'mcepastebin'; - }; - var isDefault = function (editor, pasteBinDefaultContent) { - var pasteBinElm = getEl(editor); - return isPasteBin(pasteBinElm) && isDefaultContent(pasteBinDefaultContent, pasteBinElm.innerHTML); - }; - var PasteBin = function (editor) { - var lastRng = Cell(null); - var pasteBinDefaultContent = '%MCEPASTEBIN%'; - return { - create: function () { - return create(editor, lastRng, pasteBinDefaultContent); - }, - remove: function () { - return remove(editor, lastRng); - }, - getEl: function () { - return getEl(editor); - }, - getHtml: function () { - return getHtml(editor); - }, - getLastRng: function () { - return getLastRng(lastRng); - }, - isDefault: function () { - return isDefault(editor, pasteBinDefaultContent); - }, - isDefaultContent: function (content) { - return isDefaultContent(pasteBinDefaultContent, content); - } - }; - }; - - var Clipboard = function (editor, pasteFormat) { - var pasteBin = PasteBin(editor); - editor.on('preInit', function () { - return registerEventsAndFilters(editor, pasteBin, pasteFormat); - }); - return { - pasteFormat: pasteFormat, - pasteHtml: function (html, internalFlag) { - return pasteHtml$1(editor, html, internalFlag); - }, - pasteText: function (text) { - return pasteText(editor, text); - }, - pasteImageData: function (e, rng) { - return pasteImageData(editor, e, rng); - }, - getDataTransferItems: getDataTransferItems, - hasHtmlOrText: hasHtmlOrText, - hasContentType: hasContentType - }; - }; - - var noop$1 = function () { - }; - var hasWorkingClipboardApi = function (clipboardData) { - return global$1.iOS === false && clipboardData !== undefined && typeof clipboardData.setData === 'function' && Utils.isMsEdge() !== true; - }; - var setHtml5Clipboard = function (clipboardData, html, text) { - if (hasWorkingClipboardApi(clipboardData)) { - try { - clipboardData.clearData(); - clipboardData.setData('text/html', html); - clipboardData.setData('text/plain', text); - clipboardData.setData(InternalHtml.internalHtmlMime(), html); - return true; - } catch (e) { - return false; - } - } else { - return false; - } - }; - var setClipboardData = function (evt, data, fallback, done) { - if (setHtml5Clipboard(evt.clipboardData, data.html, data.text)) { - evt.preventDefault(); - done(); - } else { - fallback(data.html, done); - } - }; - var fallback = function (editor) { - return function (html, done) { - var markedHtml = InternalHtml.mark(html); - var outer = editor.dom.create('div', { - 'contenteditable': 'false', - 'data-mce-bogus': 'all' - }); - var inner = editor.dom.create('div', { contenteditable: 'true' }, markedHtml); - editor.dom.setStyles(outer, { - position: 'fixed', - top: '0', - left: '-3000px', - width: '1000px', - overflow: 'hidden' - }); - outer.appendChild(inner); - editor.dom.add(editor.getBody(), outer); - var range = editor.selection.getRng(); - inner.focus(); - var offscreenRange = editor.dom.createRng(); - offscreenRange.selectNodeContents(inner); - editor.selection.setRng(offscreenRange); - setTimeout(function () { - editor.selection.setRng(range); - outer.parentNode.removeChild(outer); - done(); - }, 0); - }; - }; - var getData = function (editor) { - return { - html: editor.selection.getContent({ contextual: true }), - text: editor.selection.getContent({ format: 'text' }) - }; - }; - var isTableSelection = function (editor) { - return !!editor.dom.getParent(editor.selection.getStart(), 'td[data-mce-selected],th[data-mce-selected]', editor.getBody()); - }; - var hasSelectedContent = function (editor) { - return !editor.selection.isCollapsed() || isTableSelection(editor); - }; - var cut = function (editor) { - return function (evt) { - if (hasSelectedContent(editor)) { - setClipboardData(evt, getData(editor), fallback(editor), function () { - setTimeout(function () { - editor.execCommand('Delete'); - }, 0); - }); - } - }; - }; - var copy = function (editor) { - return function (evt) { - if (hasSelectedContent(editor)) { - setClipboardData(evt, getData(editor), fallback(editor), noop$1); - } - }; - }; - var register$1 = function (editor) { - editor.on('cut', cut(editor)); - editor.on('copy', copy(editor)); - }; - var CutCopy = { register: register$1 }; - - var global$a = tinymce.util.Tools.resolve('tinymce.dom.RangeUtils'); - - var getCaretRangeFromEvent = function (editor, e) { - return global$a.getCaretRangeFromPoint(e.clientX, e.clientY, editor.getDoc()); - }; - var isPlainTextFileUrl = function (content) { - var plainTextContent = content['text/plain']; - return plainTextContent ? plainTextContent.indexOf('file://') === 0 : false; - }; - var setFocusedRange = function (editor, rng) { - editor.focus(); - editor.selection.setRng(rng); - }; - var setup = function (editor, clipboard, draggingInternallyState) { - if (Settings.shouldBlockDrop(editor)) { - editor.on('dragend dragover draggesture dragdrop drop drag', function (e) { - e.preventDefault(); - e.stopPropagation(); - }); - } - if (!Settings.shouldPasteDataImages(editor)) { - editor.on('drop', function (e) { - var dataTransfer = e.dataTransfer; - if (dataTransfer && dataTransfer.files && dataTransfer.files.length > 0) { - e.preventDefault(); - } - }); - } - editor.on('drop', function (e) { - var dropContent, rng; - rng = getCaretRangeFromEvent(editor, e); - if (e.isDefaultPrevented() || draggingInternallyState.get()) { - return; - } - dropContent = clipboard.getDataTransferItems(e.dataTransfer); - var internal = clipboard.hasContentType(dropContent, InternalHtml.internalHtmlMime()); - if ((!clipboard.hasHtmlOrText(dropContent) || isPlainTextFileUrl(dropContent)) && clipboard.pasteImageData(e, rng)) { - return; - } - if (rng && Settings.shouldFilterDrop(editor)) { - var content_1 = dropContent['mce-internal'] || dropContent['text/html'] || dropContent['text/plain']; - if (content_1) { - e.preventDefault(); - global$2.setEditorTimeout(editor, function () { - editor.undoManager.transact(function () { - if (dropContent['mce-internal']) { - editor.execCommand('Delete'); - } - setFocusedRange(editor, rng); - content_1 = Utils.trimHtml(content_1); - if (!dropContent['text/html']) { - clipboard.pasteText(content_1); - } else { - clipboard.pasteHtml(content_1, internal); - } - }); - }); - } - } - }); - editor.on('dragstart', function (e) { - draggingInternallyState.set(true); - }); - editor.on('dragover dragend', function (e) { - if (Settings.shouldPasteDataImages(editor) && draggingInternallyState.get() === false) { - e.preventDefault(); - setFocusedRange(editor, getCaretRangeFromEvent(editor, e)); - } - if (e.type === 'dragend') { - draggingInternallyState.set(false); - } - }); - }; - var DragDrop = { setup: setup }; - - var setup$1 = function (editor) { - var plugin = editor.plugins.umbpaste; - var preProcess = Settings.getPreProcess(editor); - if (preProcess) { - editor.on('PastePreProcess', function (e) { - preProcess.call(plugin, plugin, e); - }); - } - var postProcess = Settings.getPostProcess(editor); - if (postProcess) { - editor.on('PastePostProcess', function (e) { - postProcess.call(plugin, plugin, e); - }); - } - }; - var PrePostProcess = { setup: setup$1 }; - - function addPreProcessFilter(editor, filterFunc) { - editor.on('PastePreProcess', function (e) { - e.content = filterFunc(editor, e.content, e.internal, e.wordContent); - }); - } - function addPostProcessFilter(editor, filterFunc) { - editor.on('PastePostProcess', function (e) { - filterFunc(editor, e.node); - }); - } - function removeExplorerBrElementsAfterBlocks(editor, html) { - if (!WordFilter.isWordContent(html)) { - return html; - } - var blockElements = []; - global$3.each(editor.schema.getBlockElements(), function (block, blockName) { - blockElements.push(blockName); - }); - var explorerBlocksRegExp = new RegExp('(?:
 [\\s\\r\\n]+|
)*(<\\/?(' + blockElements.join('|') + ')[^>]*>)(?:
 [\\s\\r\\n]+|
)*', 'g'); - html = Utils.filter(html, [[ - explorerBlocksRegExp, - '$1' - ]]); - html = Utils.filter(html, [ - [ - /

/g, - '

' - ], - [ - /
/g, - ' ' - ], - [ - /

/g, - '
' - ] - ]); - return html; - } - function removeWebKitStyles(editor, content, internal, isWordHtml) { - if (isWordHtml || internal) { - return content; - } - var webKitStylesSetting = Settings.getWebkitStyles(editor); - var webKitStyles; - if (Settings.shouldRemoveWebKitStyles(editor) === false || webKitStylesSetting === 'all') { - return content; - } - if (webKitStylesSetting) { - webKitStyles = webKitStylesSetting.split(/[, ]/); - } - if (webKitStyles) { - var dom_1 = editor.dom, node_1 = editor.selection.getNode(); - content = content.replace(/(<[^>]+) style="([^"]*)"([^>]*>)/gi, function (all, before, value, after) { - var inputStyles = dom_1.parseStyle(dom_1.decode(value)); - var outputStyles = {}; - if (webKitStyles === 'none') { - return before + after; - } - for (var i = 0; i < webKitStyles.length; i++) { - var inputValue = inputStyles[webKitStyles[i]], currentValue = dom_1.getStyle(node_1, webKitStyles[i], true); - if (/color/.test(webKitStyles[i])) { - inputValue = dom_1.toHex(inputValue); - currentValue = dom_1.toHex(currentValue); - } - if (currentValue !== inputValue) { - outputStyles[webKitStyles[i]] = inputValue; - } - } - outputStyles = dom_1.serializeStyle(outputStyles, 'span'); - if (outputStyles) { - return before + ' style="' + outputStyles + '"' + after; - } - return before + after; - }); - } else { - content = content.replace(/(<[^>]+) style="([^"]*)"([^>]*>)/gi, '$1$3'); - } - content = content.replace(/(<[^>]+) data-mce-style="([^"]+)"([^>]*>)/gi, function (all, before, value, after) { - return before + ' style="' + value + '"' + after; - }); - return content; - } - function removeUnderlineAndFontInAnchor(editor, root) { - editor.$('a', root).find('font,u').each(function (i, node) { - editor.dom.remove(node, true); - }); - } - var setup$2 = function (editor) { - if (global$1.webkit) { - addPreProcessFilter(editor, removeWebKitStyles); - } - if (global$1.ie) { - addPreProcessFilter(editor, removeExplorerBrElementsAfterBlocks); - addPostProcessFilter(editor, removeUnderlineAndFontInAnchor); - } - }; - var Quirks = { setup: setup$2 }; - - var stateChange = function (editor, clipboard, e) { - var ctrl = e.control; - ctrl.active(clipboard.pasteFormat.get() === 'text'); - editor.on('PastePlainTextToggle', function (e) { - ctrl.active(e.state); - }); - }; - var register$2 = function (editor, clipboard) { - var postRender = curry(stateChange, editor, clipboard); - editor.addButton('pastetext', { - active: false, - icon: 'pastetext', - tooltip: 'Paste as text', - cmd: 'mceTogglePlainTextPaste', - onPostRender: postRender - }); - editor.addMenuItem('pastetext', { - text: 'Paste as text', - selectable: true, - active: clipboard.pasteFormat, - cmd: 'mceTogglePlainTextPaste', - onPostRender: postRender - }); - }; - var Buttons = { register: register$2 }; - - global.add('umbpaste', function (editor) { - if (DetectProPlugin.hasProPlugin(editor) === false) { - var userIsInformedState = Cell(false); - var draggingInternallyState = Cell(false); - var pasteFormat = Cell(Settings.isPasteAsTextEnabled(editor) ? 'text' : 'html'); - var clipboard = Clipboard(editor, pasteFormat); - var quirks = Quirks.setup(editor); - Buttons.register(editor, clipboard); - Commands.register(editor, clipboard, userIsInformedState); - PrePostProcess.setup(editor); - CutCopy.register(editor); - DragDrop.setup(editor, clipboard, draggingInternallyState); - return Api.get(clipboard, quirks); - } - }); - function Plugin () { - } - - return Plugin; - -}()); -})(); From bb99891c2f861dd286ef41b06d3a8627d3d8e903 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Niels=20Lyngs=C3=B8?= Date: Thu, 19 Sep 2019 09:29:53 +0200 Subject: [PATCH 07/10] a few extra element types to allow --- .../src/common/services/tinymce.service.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/common/services/tinymce.service.js b/src/Umbraco.Web.UI.Client/src/common/services/tinymce.service.js index 211e69abb0..36e4409bc1 100644 --- a/src/Umbraco.Web.UI.Client/src/common/services/tinymce.service.js +++ b/src/Umbraco.Web.UI.Client/src/common/services/tinymce.service.js @@ -349,8 +349,8 @@ function tinyMceService($rootScope, $q, imageHelper, $locale, $http, $timeout, s }; // We keep spans here, cause removing spans here also removes b-tags inside of them, instead we strip them out later. - var validElements = "-strong/b,-em/i,-u,-span,-p,-ol,-ul,-li,-p/div,-a[href|name],sub,sup,strike,br,del,table[width],tr,td[colspan|rowspan|width],th[colspan|rowspan|width],thead,tfoot,tbody,img[src|alt|width|height],ul,ol,li" - + var validElements = "-strong/b,-em/i,-u,-span,-p,-ol,-ul,-li,-p/div,-a[href|name],sub,sup,strike,br,del,table[width],tr,td[colspan|rowspan|width],th[colspan|rowspan|width],thead,tfoot,tbody,img[src|alt|width|height],ul,ol,li,hr,pre,dl,dt,figure,figcaption,wbr" + // add valid elements from styleFormats. var style, i = 0; for(; i < styles.styleFormats.length; i++) { From f28d52898d3317f9451fd0f3b12af12b6c9ec791 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Niels=20Lyngs=C3=B8?= Date: Thu, 19 Sep 2019 11:15:32 +0200 Subject: [PATCH 08/10] no need for this one --- src/Umbraco.Web.UI.Client/src/common/services/tinymce.service.js | 1 - 1 file changed, 1 deletion(-) diff --git a/src/Umbraco.Web.UI.Client/src/common/services/tinymce.service.js b/src/Umbraco.Web.UI.Client/src/common/services/tinymce.service.js index 36e4409bc1..28df45f10f 100644 --- a/src/Umbraco.Web.UI.Client/src/common/services/tinymce.service.js +++ b/src/Umbraco.Web.UI.Client/src/common/services/tinymce.service.js @@ -365,7 +365,6 @@ function tinyMceService($rootScope, $q, imageHelper, $locale, $http, $timeout, s paste_remove_styles: true, paste_text_linebreaktype: true, paste_strip_class_attributes: "all", - paste_retain_style_properties: "all", paste_word_valid_elements: validElements, From a3de75f4c076256fb353b42214d7b58e9d18a54f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Niels=20Lyngs=C3=B8?= Date: Thu, 19 Sep 2019 11:34:45 +0200 Subject: [PATCH 09/10] added comments + better naming --- .../src/common/services/tinymce.service.js | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/common/services/tinymce.service.js b/src/Umbraco.Web.UI.Client/src/common/services/tinymce.service.js index 28df45f10f..865dccc7fa 100644 --- a/src/Umbraco.Web.UI.Client/src/common/services/tinymce.service.js +++ b/src/Umbraco.Web.UI.Client/src/common/services/tinymce.service.js @@ -349,24 +349,24 @@ function tinyMceService($rootScope, $q, imageHelper, $locale, $http, $timeout, s }; // We keep spans here, cause removing spans here also removes b-tags inside of them, instead we strip them out later. - var validElements = "-strong/b,-em/i,-u,-span,-p,-ol,-ul,-li,-p/div,-a[href|name],sub,sup,strike,br,del,table[width],tr,td[colspan|rowspan|width],th[colspan|rowspan|width],thead,tfoot,tbody,img[src|alt|width|height],ul,ol,li,hr,pre,dl,dt,figure,figcaption,wbr" + var validPasteElements = "-strong/b,-em/i,-u,-span,-p,-ol,-ul,-li,-p/div,-a[href|name],sub,sup,strike,br,del,table[width],tr,td[colspan|rowspan|width],th[colspan|rowspan|width],thead,tfoot,tbody,img[src|alt|width|height],ul,ol,li,hr,pre,dl,dt,figure,figcaption,wbr" - // add valid elements from styleFormats. + // add elements from user configurated styleFormats to our list of validPasteElements. var style, i = 0; for(; i < styles.styleFormats.length; i++) { style = styles.styleFormats[i]; if(style.block) { - validElements += "," + style.block; + validPasteElements += "," + style.block; } } var pasteConfig = { paste_remove_styles: true, - paste_text_linebreaktype: true, + paste_text_linebreaktype: true, //Converts plaintext linebreaks to br or p elements. paste_strip_class_attributes: "all", - paste_word_valid_elements: validElements, + paste_word_valid_elements: validPasteElements, paste_preprocess: cleanupPasteData From 59c5f4cd7cb154b18a5f93d96b95979a56a25502 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Niels=20Lyngs=C3=B8?= Date: Thu, 19 Sep 2019 11:36:41 +0200 Subject: [PATCH 10/10] further comment --- .../src/common/services/tinymce.service.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/Umbraco.Web.UI.Client/src/common/services/tinymce.service.js b/src/Umbraco.Web.UI.Client/src/common/services/tinymce.service.js index 865dccc7fa..91427b81c6 100644 --- a/src/Umbraco.Web.UI.Client/src/common/services/tinymce.service.js +++ b/src/Umbraco.Web.UI.Client/src/common/services/tinymce.service.js @@ -350,8 +350,9 @@ function tinyMceService($rootScope, $q, imageHelper, $locale, $http, $timeout, s // We keep spans here, cause removing spans here also removes b-tags inside of them, instead we strip them out later. var validPasteElements = "-strong/b,-em/i,-u,-span,-p,-ol,-ul,-li,-p/div,-a[href|name],sub,sup,strike,br,del,table[width],tr,td[colspan|rowspan|width],th[colspan|rowspan|width],thead,tfoot,tbody,img[src|alt|width|height],ul,ol,li,hr,pre,dl,dt,figure,figcaption,wbr" - + // add elements from user configurated styleFormats to our list of validPasteElements. + // (This means that we only allow H3-element if its configured as a styleFormat on this specific propertyEditor.) var style, i = 0; for(; i < styles.styleFormats.length; i++) { style = styles.styleFormats[i];