bedrock_sass 0.1.2 → 0.1.3

Sign up to get free protection for your applications and to get access to all the features.
Files changed (198) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +1 -1
  3. data/assets/_vendor/tinymce/plugins/advlist/index.js +7 -0
  4. data/assets/_vendor/tinymce/plugins/advlist/plugin.js +428 -0
  5. data/assets/_vendor/tinymce/plugins/advlist/plugin.min.js +1 -0
  6. data/assets/_vendor/tinymce/plugins/anchor/index.js +7 -0
  7. data/assets/_vendor/tinymce/plugins/anchor/plugin.js +338 -0
  8. data/assets/_vendor/tinymce/plugins/anchor/plugin.min.js +1 -0
  9. data/assets/_vendor/tinymce/plugins/autolink/index.js +7 -0
  10. data/assets/_vendor/tinymce/plugins/autolink/plugin.js +404 -0
  11. data/assets/_vendor/tinymce/plugins/autolink/plugin.min.js +1 -0
  12. data/assets/_vendor/tinymce/plugins/autoresize/index.js +7 -0
  13. data/assets/_vendor/tinymce/plugins/autoresize/plugin.js +451 -0
  14. data/assets/_vendor/tinymce/plugins/autoresize/plugin.min.js +1 -0
  15. data/assets/_vendor/tinymce/plugins/autosave/index.js +7 -0
  16. data/assets/_vendor/tinymce/plugins/autosave/plugin.js +608 -0
  17. data/assets/_vendor/tinymce/plugins/autosave/plugin.min.js +1 -0
  18. data/assets/_vendor/tinymce/plugins/bbcode/index.js +7 -0
  19. data/assets/_vendor/tinymce/plugins/bbcode/plugin.js +264 -0
  20. data/assets/_vendor/tinymce/plugins/bbcode/plugin.min.js +1 -0
  21. data/assets/_vendor/tinymce/plugins/charmap/index.js +7 -0
  22. data/assets/_vendor/tinymce/plugins/charmap/plugin.js +850 -0
  23. data/assets/_vendor/tinymce/plugins/charmap/plugin.min.js +1 -0
  24. data/assets/_vendor/tinymce/plugins/code/index.js +7 -0
  25. data/assets/_vendor/tinymce/plugins/code/plugin.js +338 -0
  26. data/assets/_vendor/tinymce/plugins/code/plugin.min.js +1 -0
  27. data/assets/_vendor/tinymce/plugins/codesample/css/prism.css +138 -0
  28. data/assets/_vendor/tinymce/plugins/codesample/index.js +7 -0
  29. data/assets/_vendor/tinymce/plugins/codesample/plugin.js +1582 -0
  30. data/assets/_vendor/tinymce/plugins/codesample/plugin.min.js +1 -0
  31. data/assets/_vendor/tinymce/plugins/colorpicker/index.js +7 -0
  32. data/assets/_vendor/tinymce/plugins/colorpicker/plugin.js +272 -0
  33. data/assets/_vendor/tinymce/plugins/colorpicker/plugin.min.js +1 -0
  34. data/assets/_vendor/tinymce/plugins/contextmenu/index.js +7 -0
  35. data/assets/_vendor/tinymce/plugins/contextmenu/plugin.js +496 -0
  36. data/assets/_vendor/tinymce/plugins/contextmenu/plugin.min.js +1 -0
  37. data/assets/_vendor/tinymce/plugins/directionality/index.js +7 -0
  38. data/assets/_vendor/tinymce/plugins/directionality/plugin.js +270 -0
  39. data/assets/_vendor/tinymce/plugins/directionality/plugin.min.js +1 -0
  40. data/assets/_vendor/tinymce/plugins/emoticons/img/smiley-cool.gif +0 -0
  41. data/assets/_vendor/tinymce/plugins/emoticons/img/smiley-cry.gif +0 -0
  42. data/assets/_vendor/tinymce/plugins/emoticons/img/smiley-embarassed.gif +0 -0
  43. data/assets/_vendor/tinymce/plugins/emoticons/img/smiley-foot-in-mouth.gif +0 -0
  44. data/assets/_vendor/tinymce/plugins/emoticons/img/smiley-frown.gif +0 -0
  45. data/assets/_vendor/tinymce/plugins/emoticons/img/smiley-innocent.gif +0 -0
  46. data/assets/_vendor/tinymce/plugins/emoticons/img/smiley-kiss.gif +0 -0
  47. data/assets/_vendor/tinymce/plugins/emoticons/img/smiley-laughing.gif +0 -0
  48. data/assets/_vendor/tinymce/plugins/emoticons/img/smiley-money-mouth.gif +0 -0
  49. data/assets/_vendor/tinymce/plugins/emoticons/img/smiley-sealed.gif +0 -0
  50. data/assets/_vendor/tinymce/plugins/emoticons/img/smiley-smile.gif +0 -0
  51. data/assets/_vendor/tinymce/plugins/emoticons/img/smiley-surprised.gif +0 -0
  52. data/assets/_vendor/tinymce/plugins/emoticons/img/smiley-tongue-out.gif +0 -0
  53. data/assets/_vendor/tinymce/plugins/emoticons/img/smiley-undecided.gif +0 -0
  54. data/assets/_vendor/tinymce/plugins/emoticons/img/smiley-wink.gif +0 -0
  55. data/assets/_vendor/tinymce/plugins/emoticons/img/smiley-yell.gif +0 -0
  56. data/assets/_vendor/tinymce/plugins/emoticons/index.js +7 -0
  57. data/assets/_vendor/tinymce/plugins/emoticons/plugin.js +256 -0
  58. data/assets/_vendor/tinymce/plugins/emoticons/plugin.min.js +1 -0
  59. data/assets/_vendor/tinymce/plugins/fullpage/index.js +7 -0
  60. data/assets/_vendor/tinymce/plugins/fullpage/plugin.js +962 -0
  61. data/assets/_vendor/tinymce/plugins/fullpage/plugin.min.js +1 -0
  62. data/assets/_vendor/tinymce/plugins/fullscreen/index.js +7 -0
  63. data/assets/_vendor/tinymce/plugins/fullscreen/plugin.js +455 -0
  64. data/assets/_vendor/tinymce/plugins/fullscreen/plugin.min.js +1 -0
  65. data/assets/_vendor/tinymce/plugins/help/img/logo.png +0 -0
  66. data/assets/_vendor/tinymce/plugins/help/index.js +7 -0
  67. data/assets/_vendor/tinymce/plugins/help/plugin.js +1527 -0
  68. data/assets/_vendor/tinymce/plugins/help/plugin.min.js +1 -0
  69. data/assets/_vendor/tinymce/plugins/hr/index.js +7 -0
  70. data/assets/_vendor/tinymce/plugins/hr/plugin.js +195 -0
  71. data/assets/_vendor/tinymce/plugins/hr/plugin.min.js +1 -0
  72. data/assets/_vendor/tinymce/plugins/image/index.js +7 -0
  73. data/assets/_vendor/tinymce/plugins/image/plugin.js +1572 -0
  74. data/assets/_vendor/tinymce/plugins/image/plugin.min.js +1 -0
  75. data/assets/_vendor/tinymce/plugins/imagetools/index.js +7 -0
  76. data/assets/_vendor/tinymce/plugins/imagetools/plugin.js +4444 -0
  77. data/assets/_vendor/tinymce/plugins/imagetools/plugin.min.js +2 -0
  78. data/assets/_vendor/tinymce/plugins/importcss/index.js +7 -0
  79. data/assets/_vendor/tinymce/plugins/importcss/plugin.js +577 -0
  80. data/assets/_vendor/tinymce/plugins/importcss/plugin.min.js +1 -0
  81. data/assets/_vendor/tinymce/plugins/insertdatetime/index.js +7 -0
  82. data/assets/_vendor/tinymce/plugins/insertdatetime/plugin.js +482 -0
  83. data/assets/_vendor/tinymce/plugins/insertdatetime/plugin.min.js +1 -0
  84. data/assets/_vendor/tinymce/plugins/legacyoutput/index.js +7 -0
  85. data/assets/_vendor/tinymce/plugins/legacyoutput/plugin.js +395 -0
  86. data/assets/_vendor/tinymce/plugins/legacyoutput/plugin.min.js +1 -0
  87. data/assets/_vendor/tinymce/plugins/link/index.js +7 -0
  88. data/assets/_vendor/tinymce/plugins/link/plugin.js +1231 -0
  89. data/assets/_vendor/tinymce/plugins/link/plugin.min.js +1 -0
  90. data/assets/_vendor/tinymce/plugins/lists/index.js +7 -0
  91. data/assets/_vendor/tinymce/plugins/lists/plugin.js +1985 -0
  92. data/assets/_vendor/tinymce/plugins/lists/plugin.min.js +1 -0
  93. data/assets/_vendor/tinymce/plugins/media/index.js +7 -0
  94. data/assets/_vendor/tinymce/plugins/media/plugin.js +2026 -0
  95. data/assets/_vendor/tinymce/plugins/media/plugin.min.js +1 -0
  96. data/assets/_vendor/tinymce/plugins/nonbreaking/index.js +7 -0
  97. data/assets/_vendor/tinymce/plugins/nonbreaking/plugin.js +313 -0
  98. data/assets/_vendor/tinymce/plugins/nonbreaking/plugin.min.js +1 -0
  99. data/assets/_vendor/tinymce/plugins/noneditable/index.js +7 -0
  100. data/assets/_vendor/tinymce/plugins/noneditable/plugin.js +316 -0
  101. data/assets/_vendor/tinymce/plugins/noneditable/plugin.min.js +1 -0
  102. data/assets/_vendor/tinymce/plugins/pagebreak/index.js +7 -0
  103. data/assets/_vendor/tinymce/plugins/pagebreak/plugin.js +354 -0
  104. data/assets/_vendor/tinymce/plugins/pagebreak/plugin.min.js +1 -0
  105. data/assets/_vendor/tinymce/plugins/paste/index.js +7 -0
  106. data/assets/_vendor/tinymce/plugins/paste/plugin.js +2935 -0
  107. data/assets/_vendor/tinymce/plugins/paste/plugin.min.js +1 -0
  108. data/assets/_vendor/tinymce/plugins/preview/index.js +7 -0
  109. data/assets/_vendor/tinymce/plugins/preview/plugin.js +410 -0
  110. data/assets/_vendor/tinymce/plugins/preview/plugin.min.js +1 -0
  111. data/assets/_vendor/tinymce/plugins/print/index.js +7 -0
  112. data/assets/_vendor/tinymce/plugins/print/plugin.js +194 -0
  113. data/assets/_vendor/tinymce/plugins/print/plugin.min.js +1 -0
  114. data/assets/_vendor/tinymce/plugins/save/index.js +7 -0
  115. data/assets/_vendor/tinymce/plugins/save/plugin.js +370 -0
  116. data/assets/_vendor/tinymce/plugins/save/plugin.min.js +1 -0
  117. data/assets/_vendor/tinymce/plugins/searchreplace/index.js +7 -0
  118. data/assets/_vendor/tinymce/plugins/searchreplace/plugin.js +977 -0
  119. data/assets/_vendor/tinymce/plugins/searchreplace/plugin.min.js +1 -0
  120. data/assets/_vendor/tinymce/plugins/spellchecker/index.js +7 -0
  121. data/assets/_vendor/tinymce/plugins/spellchecker/plugin.js +1419 -0
  122. data/assets/_vendor/tinymce/plugins/spellchecker/plugin.min.js +1 -0
  123. data/assets/_vendor/tinymce/plugins/tabfocus/index.js +7 -0
  124. data/assets/_vendor/tinymce/plugins/tabfocus/plugin.js +419 -0
  125. data/assets/_vendor/tinymce/plugins/tabfocus/plugin.min.js +1 -0
  126. data/assets/_vendor/tinymce/plugins/table/index.js +7 -0
  127. data/assets/_vendor/tinymce/plugins/table/plugin.js +15527 -0
  128. data/assets/_vendor/tinymce/plugins/table/plugin.min.js +5 -0
  129. data/assets/_vendor/tinymce/plugins/template/index.js +7 -0
  130. data/assets/_vendor/tinymce/plugins/template/plugin.js +807 -0
  131. data/assets/_vendor/tinymce/plugins/template/plugin.min.js +1 -0
  132. data/assets/_vendor/tinymce/plugins/textcolor/index.js +7 -0
  133. data/assets/_vendor/tinymce/plugins/textcolor/plugin.js +619 -0
  134. data/assets/_vendor/tinymce/plugins/textcolor/plugin.min.js +1 -0
  135. data/assets/_vendor/tinymce/plugins/textpattern/index.js +7 -0
  136. data/assets/_vendor/tinymce/plugins/textpattern/plugin.js +718 -0
  137. data/assets/_vendor/tinymce/plugins/textpattern/plugin.min.js +1 -0
  138. data/assets/_vendor/tinymce/plugins/toc/index.js +7 -0
  139. data/assets/_vendor/tinymce/plugins/toc/plugin.js +559 -0
  140. data/assets/_vendor/tinymce/plugins/toc/plugin.min.js +1 -0
  141. data/assets/_vendor/tinymce/plugins/visualblocks/css/visualblocks.css +154 -0
  142. data/assets/_vendor/tinymce/plugins/visualblocks/index.js +7 -0
  143. data/assets/_vendor/tinymce/plugins/visualblocks/plugin.js +459 -0
  144. data/assets/_vendor/tinymce/plugins/visualblocks/plugin.min.js +1 -0
  145. data/assets/_vendor/tinymce/plugins/visualchars/index.js +7 -0
  146. data/assets/_vendor/tinymce/plugins/visualchars/plugin.js +1325 -0
  147. data/assets/_vendor/tinymce/plugins/visualchars/plugin.min.js +1 -0
  148. data/assets/_vendor/tinymce/plugins/wordcount/index.js +7 -0
  149. data/assets/_vendor/tinymce/plugins/wordcount/plugin.js +735 -0
  150. data/assets/_vendor/tinymce/plugins/wordcount/plugin.min.js +1 -0
  151. data/assets/_vendor/tinymce/skins/lightgray/content.inline.min.css +1 -0
  152. data/assets/_vendor/tinymce/skins/lightgray/content.min.css +1 -0
  153. data/assets/_vendor/tinymce/skins/lightgray/content.mobile.min.css +1 -0
  154. data/assets/_vendor/tinymce/skins/lightgray/fonts/tinymce-mobile.woff +0 -0
  155. data/assets/_vendor/tinymce/skins/lightgray/fonts/tinymce-small.eot +0 -0
  156. data/assets/_vendor/tinymce/skins/lightgray/fonts/tinymce-small.svg +63 -0
  157. data/assets/_vendor/tinymce/skins/lightgray/fonts/tinymce-small.ttf +0 -0
  158. data/assets/_vendor/tinymce/skins/lightgray/fonts/tinymce-small.woff +0 -0
  159. data/assets/_vendor/tinymce/skins/lightgray/fonts/tinymce.eot +0 -0
  160. data/assets/_vendor/tinymce/skins/lightgray/fonts/tinymce.svg +131 -0
  161. data/assets/_vendor/tinymce/skins/lightgray/fonts/tinymce.ttf +0 -0
  162. data/assets/_vendor/tinymce/skins/lightgray/fonts/tinymce.woff +0 -0
  163. data/assets/_vendor/tinymce/skins/lightgray/img/anchor.gif +0 -0
  164. data/assets/_vendor/tinymce/skins/lightgray/img/loader.gif +0 -0
  165. data/assets/_vendor/tinymce/skins/lightgray/img/object.gif +0 -0
  166. data/assets/_vendor/tinymce/skins/lightgray/img/trans.gif +0 -0
  167. data/assets/_vendor/tinymce/skins/lightgray/skin.min.css +1 -0
  168. data/assets/_vendor/tinymce/skins/lightgray/skin.mobile.min.css +2 -0
  169. data/assets/_vendor/tinymce/themes/inlite/index.js +7 -0
  170. data/assets/_vendor/tinymce/themes/inlite/theme.js +18787 -0
  171. data/assets/_vendor/tinymce/themes/inlite/theme.min.js +5 -0
  172. data/assets/_vendor/tinymce/themes/mobile/index.js +7 -0
  173. data/assets/_vendor/tinymce/themes/mobile/theme.js +23384 -0
  174. data/assets/_vendor/tinymce/themes/mobile/theme.min.js +8 -0
  175. data/assets/_vendor/tinymce/themes/modern/index.js +7 -0
  176. data/assets/_vendor/tinymce/themes/modern/theme.js +18311 -0
  177. data/assets/_vendor/tinymce/themes/modern/theme.min.js +5 -0
  178. data/assets/_vendor/tinymce/tinymce.js +44399 -0
  179. data/assets/bedrock/js/bedrock.js +16587 -6193
  180. data/assets/bedrock/scss/_bedrock-components.scss +16 -0
  181. data/assets/bedrock/scss/_bedrock-settings.scss +15 -0
  182. data/assets/bedrock/scss/components/attachments-grid.scss +138 -0
  183. data/assets/bedrock/scss/components/dropzone-upload.scss +158 -0
  184. data/assets/bedrock/scss/components/global.scss +16 -8
  185. data/assets/bedrock/scss/components/helper-classes.scss +59 -0
  186. data/assets/bedrock/scss/components/inline-edit-box.scss +80 -0
  187. data/assets/bedrock/scss/components/login-box.scss +48 -0
  188. data/assets/bedrock/scss/components/no-content.scss +31 -0
  189. data/assets/bedrock/scss/components/off-canvas-menu.scss +1 -1
  190. data/assets/bedrock/scss/components/page-content.scss +51 -0
  191. data/assets/bedrock/scss/components/reveal-panel.scss +89 -0
  192. data/assets/bedrock/scss/components/select-box.scss +332 -0
  193. data/assets/bedrock/scss/components/tiny-mce-editor.scss +14 -7
  194. data/lib/bedrock_sass.rb +6 -0
  195. data/lib/bedrock_sass/engine.rb +8 -0
  196. data/lib/bedrock_sass/version.rb +1 -1
  197. data/lib/tasks/before_assets_precompile.rake +11 -0
  198. metadata +188 -2
@@ -0,0 +1 @@
1
+ !function(){var a={},b=function(b){for(var c=a[b],e=c.deps,f=c.defn,g=e.length,h=new Array(g),i=0;i<g;++i)h[i]=d(e[i]);var j=f.apply(null,h);if(void 0===j)throw"module ["+b+"] returned undefined";c.instance=j},c=function(b,c,d){if("string"!=typeof b)throw"module id must be a string";if(void 0===c)throw"no dependencies for "+b;if(void 0===d)throw"no definition function for "+b;a[b]={deps:c,defn:d,instance:void 0}},d=function(c){var d=a[c];if(void 0===d)throw"module ["+c+"] was undefined";return void 0===d.instance&&b(c),d.instance},e=function(a,b){for(var c=a.length,e=new Array(c),f=0;f<c;++f)e[f]=d(a[f]);b.apply(null,e)},f={};f.bolt={module:{api:{define:c,require:e,demand:d}}};var g=c,h=function(a,b){g(a,[],function(){return b})};h("3",tinymce.util.Tools.resolve),g("1",["3"],function(a){return a("tinymce.PluginManager")}),g("4",["3"],function(a){return a("tinymce.util.Tools")}),g("5",[],function(){var a=function(a){return a.getParam("noneditable_noneditable_class","mceNonEditable")},b=function(a){return a.getParam("noneditable_editable_class","mceEditable")},c=function(a){var b=a.getParam("noneditable_regexp",[]);return b&&b.constructor===RegExp?[b]:b};return{getNonEditableClass:a,getEditableClass:b,getNonEditableRegExps:c}}),g("2",["4","5"],function(a,b){var c=function(a){return function(b){return(" "+b.attr("class")+" ").indexOf(a)!==-1}},d=function(a,b,c){return function(d){var e=arguments,f=e[e.length-2],g=f>0?b.charAt(f-1):"";if('"'===g)return d;if(">"===g){var h=b.lastIndexOf("<",f);if(h!==-1){var i=b.substring(h,f);if(i.indexOf('contenteditable="false"')!==-1)return d}}return'<span class="'+c+'" data-mce-content="'+a.dom.encode(e[0])+'">'+a.dom.encode("string"==typeof e[1]?e[1]:e[0])+"</span>"}},e=function(a,c,e){var f=c.length,g=e.content;if("raw"!==e.format){for(;f--;)g=g.replace(c[f],d(a,g,b.getNonEditableClass(a)));e.content=g}},f=function(d){var f,g,h="contenteditable";f=" "+a.trim(b.getEditableClass(d))+" ",g=" "+a.trim(b.getNonEditableClass(d))+" ";var i=c(f),j=c(g),k=b.getNonEditableRegExps(d);d.on("PreInit",function(){k.length>0&&d.on("BeforeSetContent",function(a){e(d,k,a)}),d.parser.addAttributeFilter("class",function(a){for(var b,c=a.length;c--;)b=a[c],i(b)?b.attr(h,"true"):j(b)&&b.attr(h,"false")}),d.serializer.addAttributeFilter(h,function(a){for(var b,c=a.length;c--;)b=a[c],(i(b)||j(b))&&(k.length>0&&b.attr("data-mce-content")?(b.name="#text",b.type=3,b.raw=!0,b.value=b.attr("data-mce-content")):b.attr(h,null))})})};return{setup:f}}),g("0",["1","2"],function(a,b){return a.add("noneditable",function(a){b.setup(a)}),function(){}}),d("0")()}();
@@ -0,0 +1,7 @@
1
+ // Exports the "pagebreak" plugin for usage with module loaders
2
+ // Usage:
3
+ // CommonJS:
4
+ // require('tinymce/plugins/pagebreak')
5
+ // ES2015:
6
+ // import 'tinymce/plugins/pagebreak'
7
+ require('./plugin.js');
@@ -0,0 +1,354 @@
1
+ (function () {
2
+
3
+ var defs = {}; // id -> {dependencies, definition, instance (possibly undefined)}
4
+
5
+ // Used when there is no 'main' module.
6
+ // The name is probably (hopefully) unique so minification removes for releases.
7
+ var register_3795 = function (id) {
8
+ var module = dem(id);
9
+ var fragments = id.split('.');
10
+ var target = Function('return this;')();
11
+ for (var i = 0; i < fragments.length - 1; ++i) {
12
+ if (target[fragments[i]] === undefined)
13
+ target[fragments[i]] = {};
14
+ target = target[fragments[i]];
15
+ }
16
+ target[fragments[fragments.length - 1]] = module;
17
+ };
18
+
19
+ var instantiate = function (id) {
20
+ var actual = defs[id];
21
+ var dependencies = actual.deps;
22
+ var definition = actual.defn;
23
+ var len = dependencies.length;
24
+ var instances = new Array(len);
25
+ for (var i = 0; i < len; ++i)
26
+ instances[i] = dem(dependencies[i]);
27
+ var defResult = definition.apply(null, instances);
28
+ if (defResult === undefined)
29
+ throw 'module [' + id + '] returned undefined';
30
+ actual.instance = defResult;
31
+ };
32
+
33
+ var def = function (id, dependencies, definition) {
34
+ if (typeof id !== 'string')
35
+ throw 'module id must be a string';
36
+ else if (dependencies === undefined)
37
+ throw 'no dependencies for ' + id;
38
+ else if (definition === undefined)
39
+ throw 'no definition function for ' + id;
40
+ defs[id] = {
41
+ deps: dependencies,
42
+ defn: definition,
43
+ instance: undefined
44
+ };
45
+ };
46
+
47
+ var dem = function (id) {
48
+ var actual = defs[id];
49
+ if (actual === undefined)
50
+ throw 'module [' + id + '] was undefined';
51
+ else if (actual.instance === undefined)
52
+ instantiate(id);
53
+ return actual.instance;
54
+ };
55
+
56
+ var req = function (ids, callback) {
57
+ var len = ids.length;
58
+ var instances = new Array(len);
59
+ for (var i = 0; i < len; ++i)
60
+ instances[i] = dem(ids[i]);
61
+ callback.apply(null, instances);
62
+ };
63
+
64
+ var ephox = {};
65
+
66
+ ephox.bolt = {
67
+ module: {
68
+ api: {
69
+ define: def,
70
+ require: req,
71
+ demand: dem
72
+ }
73
+ }
74
+ };
75
+
76
+ var define = def;
77
+ var require = req;
78
+ var demand = dem;
79
+ // this helps with minification when using a lot of global references
80
+ var defineGlobal = function (id, ref) {
81
+ define(id, [], function () { return ref; });
82
+ };
83
+ /*jsc
84
+ ["tinymce.plugins.pagebreak.Plugin","tinymce.core.Env","tinymce.core.PluginManager","tinymce.plugins.pagebreak.api.Commands","tinymce.plugins.pagebreak.core.FilterContent","tinymce.plugins.pagebreak.core.ResolveName","tinymce.plugins.pagebreak.ui.Buttons","global!tinymce.util.Tools.resolve","tinymce.plugins.pagebreak.api.Settings"]
85
+ jsc*/
86
+ defineGlobal("global!tinymce.util.Tools.resolve", tinymce.util.Tools.resolve);
87
+ /**
88
+ * ResolveGlobal.js
89
+ *
90
+ * Released under LGPL License.
91
+ * Copyright (c) 1999-2017 Ephox Corp. All rights reserved
92
+ *
93
+ * License: http://www.tinymce.com/license
94
+ * Contributing: http://www.tinymce.com/contributing
95
+ */
96
+
97
+ define(
98
+ 'tinymce.core.Env',
99
+ [
100
+ 'global!tinymce.util.Tools.resolve'
101
+ ],
102
+ function (resolve) {
103
+ return resolve('tinymce.Env');
104
+ }
105
+ );
106
+
107
+ /**
108
+ * ResolveGlobal.js
109
+ *
110
+ * Released under LGPL License.
111
+ * Copyright (c) 1999-2017 Ephox Corp. All rights reserved
112
+ *
113
+ * License: http://www.tinymce.com/license
114
+ * Contributing: http://www.tinymce.com/contributing
115
+ */
116
+
117
+ define(
118
+ 'tinymce.core.PluginManager',
119
+ [
120
+ 'global!tinymce.util.Tools.resolve'
121
+ ],
122
+ function (resolve) {
123
+ return resolve('tinymce.PluginManager');
124
+ }
125
+ );
126
+
127
+ /**
128
+ * Settings.js
129
+ *
130
+ * Released under LGPL License.
131
+ * Copyright (c) 1999-2017 Ephox Corp. All rights reserved
132
+ *
133
+ * License: http://www.tinymce.com/license
134
+ * Contributing: http://www.tinymce.com/contributing
135
+ */
136
+
137
+ define(
138
+ 'tinymce.plugins.pagebreak.api.Settings',
139
+ [
140
+ ],
141
+ function () {
142
+ var getSeparatorHtml = function (editor) {
143
+ return editor.getParam('pagebreak_separator', '<!-- pagebreak -->');
144
+ };
145
+
146
+ var shouldSplitBlock = function (editor) {
147
+ return editor.getParam('pagebreak_split_block', false);
148
+ };
149
+
150
+ return {
151
+ getSeparatorHtml: getSeparatorHtml,
152
+ shouldSplitBlock: shouldSplitBlock
153
+ };
154
+ }
155
+ );
156
+
157
+ /**
158
+ * FilterContent.js
159
+ *
160
+ * Released under LGPL License.
161
+ * Copyright (c) 1999-2017 Ephox Corp. All rights reserved
162
+ *
163
+ * License: http://www.tinymce.com/license
164
+ * Contributing: http://www.tinymce.com/contributing
165
+ */
166
+
167
+ define(
168
+ 'tinymce.plugins.pagebreak.core.FilterContent',
169
+ [
170
+ 'tinymce.core.Env',
171
+ 'tinymce.plugins.pagebreak.api.Settings'
172
+ ],
173
+ function (Env, Settings) {
174
+ var getPageBreakClass = function () {
175
+ return 'mce-pagebreak';
176
+ };
177
+
178
+ var getPlaceholderHtml = function () {
179
+ return '<img src="' + Env.transparentSrc + '" class="' + getPageBreakClass() + '" data-mce-resize="false" data-mce-placeholder />';
180
+ };
181
+
182
+ var setup = function (editor) {
183
+ var separatorHtml = Settings.getSeparatorHtml(editor);
184
+
185
+ var pageBreakSeparatorRegExp = new RegExp(separatorHtml.replace(/[\?\.\*\[\]\(\)\{\}\+\^\$\:]/g, function (a) {
186
+ return '\\' + a;
187
+ }), 'gi');
188
+
189
+ editor.on('BeforeSetContent', function (e) {
190
+ e.content = e.content.replace(pageBreakSeparatorRegExp, getPlaceholderHtml());
191
+ });
192
+
193
+ editor.on('PreInit', function () {
194
+ editor.serializer.addNodeFilter('img', function (nodes) {
195
+ var i = nodes.length, node, className;
196
+
197
+ while (i--) {
198
+ node = nodes[i];
199
+ className = node.attr('class');
200
+ if (className && className.indexOf('mce-pagebreak') !== -1) {
201
+ // Replace parent block node if pagebreak_split_block is enabled
202
+ var parentNode = node.parent;
203
+ if (editor.schema.getBlockElements()[parentNode.name] && Settings.shouldSplitBlock(editor)) {
204
+ parentNode.type = 3;
205
+ parentNode.value = separatorHtml;
206
+ parentNode.raw = true;
207
+ node.remove();
208
+ continue;
209
+ }
210
+
211
+ node.type = 3;
212
+ node.value = separatorHtml;
213
+ node.raw = true;
214
+ }
215
+ }
216
+ });
217
+ });
218
+ };
219
+
220
+ return {
221
+ setup: setup,
222
+ getPlaceholderHtml: getPlaceholderHtml,
223
+ getPageBreakClass: getPageBreakClass
224
+ };
225
+ }
226
+ );
227
+ /**
228
+ * Commands.js
229
+ *
230
+ * Released under LGPL License.
231
+ * Copyright (c) 1999-2017 Ephox Corp. All rights reserved
232
+ *
233
+ * License: http://www.tinymce.com/license
234
+ * Contributing: http://www.tinymce.com/contributing
235
+ */
236
+
237
+ define(
238
+ 'tinymce.plugins.pagebreak.api.Commands',
239
+ [
240
+ 'tinymce.plugins.pagebreak.core.FilterContent'
241
+ ],
242
+ function (FilterContent) {
243
+ var register = function (editor) {
244
+ editor.addCommand('mcePageBreak', function () {
245
+ if (editor.settings.pagebreak_split_block) {
246
+ editor.insertContent('<p>' + FilterContent.getPlaceholderHtml() + '</p>');
247
+ } else {
248
+ editor.insertContent(FilterContent.getPlaceholderHtml());
249
+ }
250
+ });
251
+ };
252
+
253
+ return {
254
+ register: register
255
+ };
256
+ }
257
+ );
258
+ /**
259
+ * ResolveName.js
260
+ *
261
+ * Released under LGPL License.
262
+ * Copyright (c) 1999-2017 Ephox Corp. All rights reserved
263
+ *
264
+ * License: http://www.tinymce.com/license
265
+ * Contributing: http://www.tinymce.com/contributing
266
+ */
267
+
268
+ define(
269
+ 'tinymce.plugins.pagebreak.core.ResolveName',
270
+ [
271
+ 'tinymce.plugins.pagebreak.core.FilterContent'
272
+ ],
273
+ function (FilterContent) {
274
+ var setup = function (editor) {
275
+ editor.on('ResolveName', function (e) {
276
+ if (e.target.nodeName === 'IMG' && editor.dom.hasClass(e.target, FilterContent.getPageBreakClass())) {
277
+ e.name = 'pagebreak';
278
+ }
279
+ });
280
+ };
281
+
282
+ return {
283
+ setup: setup
284
+ };
285
+ }
286
+ );
287
+
288
+ /**
289
+ * Buttons.js
290
+ *
291
+ * Released under LGPL License.
292
+ * Copyright (c) 1999-2017 Ephox Corp. All rights reserved
293
+ *
294
+ * License: http://www.tinymce.com/license
295
+ * Contributing: http://www.tinymce.com/contributing
296
+ */
297
+
298
+ define(
299
+ 'tinymce.plugins.pagebreak.ui.Buttons',
300
+ [
301
+ ],
302
+ function () {
303
+ var register = function (editor) {
304
+ editor.addButton('pagebreak', {
305
+ title: 'Page break',
306
+ cmd: 'mcePageBreak'
307
+ });
308
+
309
+ editor.addMenuItem('pagebreak', {
310
+ text: 'Page break',
311
+ icon: 'pagebreak',
312
+ cmd: 'mcePageBreak',
313
+ context: 'insert'
314
+ });
315
+ };
316
+
317
+ return {
318
+ register: register
319
+ };
320
+ }
321
+ );
322
+ /**
323
+ * Plugin.js
324
+ *
325
+ * Released under LGPL License.
326
+ * Copyright (c) 1999-2017 Ephox Corp. All rights reserved
327
+ *
328
+ * License: http://www.tinymce.com/license
329
+ * Contributing: http://www.tinymce.com/contributing
330
+ */
331
+
332
+ define(
333
+ 'tinymce.plugins.pagebreak.Plugin',
334
+ [
335
+ 'tinymce.core.Env',
336
+ 'tinymce.core.PluginManager',
337
+ 'tinymce.plugins.pagebreak.api.Commands',
338
+ 'tinymce.plugins.pagebreak.core.FilterContent',
339
+ 'tinymce.plugins.pagebreak.core.ResolveName',
340
+ 'tinymce.plugins.pagebreak.ui.Buttons'
341
+ ],
342
+ function (Env, PluginManager, Commands, FilterContent, ResolveName, Buttons) {
343
+ PluginManager.add('pagebreak', function (editor) {
344
+ Commands.register(editor);
345
+ Buttons.register(editor);
346
+ FilterContent.setup(editor);
347
+ ResolveName.setup(editor);
348
+ });
349
+
350
+ return function () { };
351
+ }
352
+ );
353
+ dem('tinymce.plugins.pagebreak.Plugin')();
354
+ })();
@@ -0,0 +1 @@
1
+ !function(){var a={},b=function(b){for(var c=a[b],e=c.deps,f=c.defn,g=e.length,h=new Array(g),i=0;i<g;++i)h[i]=d(e[i]);var j=f.apply(null,h);if(void 0===j)throw"module ["+b+"] returned undefined";c.instance=j},c=function(b,c,d){if("string"!=typeof b)throw"module id must be a string";if(void 0===c)throw"no dependencies for "+b;if(void 0===d)throw"no definition function for "+b;a[b]={deps:c,defn:d,instance:void 0}},d=function(c){var d=a[c];if(void 0===d)throw"module ["+c+"] was undefined";return void 0===d.instance&&b(c),d.instance},e=function(a,b){for(var c=a.length,e=new Array(c),f=0;f<c;++f)e[f]=d(a[f]);b.apply(null,e)},f={};f.bolt={module:{api:{define:c,require:e,demand:d}}};var g=c,h=function(a,b){g(a,[],function(){return b})};h("7",tinymce.util.Tools.resolve),g("1",["7"],function(a){return a("tinymce.Env")}),g("2",["7"],function(a){return a("tinymce.PluginManager")}),g("8",[],function(){var a=function(a){return a.getParam("pagebreak_separator","<!-- pagebreak -->")},b=function(a){return a.getParam("pagebreak_split_block",!1)};return{getSeparatorHtml:a,shouldSplitBlock:b}}),g("4",["1","8"],function(a,b){var c=function(){return"mce-pagebreak"},d=function(){return'<img src="'+a.transparentSrc+'" class="'+c()+'" data-mce-resize="false" data-mce-placeholder />'},e=function(a){var c=b.getSeparatorHtml(a),e=new RegExp(c.replace(/[\?\.\*\[\]\(\)\{\}\+\^\$\:]/g,function(a){return"\\"+a}),"gi");a.on("BeforeSetContent",function(a){a.content=a.content.replace(e,d())}),a.on("PreInit",function(){a.serializer.addNodeFilter("img",function(d){for(var e,f,g=d.length;g--;)if(e=d[g],f=e.attr("class"),f&&f.indexOf("mce-pagebreak")!==-1){var h=e.parent;if(a.schema.getBlockElements()[h.name]&&b.shouldSplitBlock(a)){h.type=3,h.value=c,h.raw=!0,e.remove();continue}e.type=3,e.value=c,e.raw=!0}})})};return{setup:e,getPlaceholderHtml:d,getPageBreakClass:c}}),g("3",["4"],function(a){var b=function(b){b.addCommand("mcePageBreak",function(){b.settings.pagebreak_split_block?b.insertContent("<p>"+a.getPlaceholderHtml()+"</p>"):b.insertContent(a.getPlaceholderHtml())})};return{register:b}}),g("5",["4"],function(a){var b=function(b){b.on("ResolveName",function(c){"IMG"===c.target.nodeName&&b.dom.hasClass(c.target,a.getPageBreakClass())&&(c.name="pagebreak")})};return{setup:b}}),g("6",[],function(){var a=function(a){a.addButton("pagebreak",{title:"Page break",cmd:"mcePageBreak"}),a.addMenuItem("pagebreak",{text:"Page break",icon:"pagebreak",cmd:"mcePageBreak",context:"insert"})};return{register:a}}),g("0",["1","2","3","4","5","6"],function(a,b,c,d,e,f){return b.add("pagebreak",function(a){c.register(a),f.register(a),d.setup(a),e.setup(a)}),function(){}}),d("0")()}();
@@ -0,0 +1,7 @@
1
+ // Exports the "paste" plugin for usage with module loaders
2
+ // Usage:
3
+ // CommonJS:
4
+ // require('tinymce/plugins/paste')
5
+ // ES2015:
6
+ // import 'tinymce/plugins/paste'
7
+ require('./plugin.js');
@@ -0,0 +1,2935 @@
1
+ (function () {
2
+
3
+ var defs = {}; // id -> {dependencies, definition, instance (possibly undefined)}
4
+
5
+ // Used when there is no 'main' module.
6
+ // The name is probably (hopefully) unique so minification removes for releases.
7
+ var register_3795 = function (id) {
8
+ var module = dem(id);
9
+ var fragments = id.split('.');
10
+ var target = Function('return this;')();
11
+ for (var i = 0; i < fragments.length - 1; ++i) {
12
+ if (target[fragments[i]] === undefined)
13
+ target[fragments[i]] = {};
14
+ target = target[fragments[i]];
15
+ }
16
+ target[fragments[fragments.length - 1]] = module;
17
+ };
18
+
19
+ var instantiate = function (id) {
20
+ var actual = defs[id];
21
+ var dependencies = actual.deps;
22
+ var definition = actual.defn;
23
+ var len = dependencies.length;
24
+ var instances = new Array(len);
25
+ for (var i = 0; i < len; ++i)
26
+ instances[i] = dem(dependencies[i]);
27
+ var defResult = definition.apply(null, instances);
28
+ if (defResult === undefined)
29
+ throw 'module [' + id + '] returned undefined';
30
+ actual.instance = defResult;
31
+ };
32
+
33
+ var def = function (id, dependencies, definition) {
34
+ if (typeof id !== 'string')
35
+ throw 'module id must be a string';
36
+ else if (dependencies === undefined)
37
+ throw 'no dependencies for ' + id;
38
+ else if (definition === undefined)
39
+ throw 'no definition function for ' + id;
40
+ defs[id] = {
41
+ deps: dependencies,
42
+ defn: definition,
43
+ instance: undefined
44
+ };
45
+ };
46
+
47
+ var dem = function (id) {
48
+ var actual = defs[id];
49
+ if (actual === undefined)
50
+ throw 'module [' + id + '] was undefined';
51
+ else if (actual.instance === undefined)
52
+ instantiate(id);
53
+ return actual.instance;
54
+ };
55
+
56
+ var req = function (ids, callback) {
57
+ var len = ids.length;
58
+ var instances = new Array(len);
59
+ for (var i = 0; i < len; ++i)
60
+ instances[i] = dem(ids[i]);
61
+ callback.apply(null, instances);
62
+ };
63
+
64
+ var ephox = {};
65
+
66
+ ephox.bolt = {
67
+ module: {
68
+ api: {
69
+ define: def,
70
+ require: req,
71
+ demand: dem
72
+ }
73
+ }
74
+ };
75
+
76
+ var define = def;
77
+ var require = req;
78
+ var demand = dem;
79
+ // this helps with minification when using a lot of global references
80
+ var defineGlobal = function (id, ref) {
81
+ define(id, [], function () { return ref; });
82
+ };
83
+ /*jsc
84
+ ["tinymce.plugins.paste.Plugin","ephox.katamari.api.Cell","tinymce.core.PluginManager","tinymce.plugins.paste.alien.DetectProPlugin","tinymce.plugins.paste.api.Api","tinymce.plugins.paste.api.Commands","tinymce.plugins.paste.core.Clipboard","tinymce.plugins.paste.core.CutCopy","tinymce.plugins.paste.core.DragDrop","tinymce.plugins.paste.core.PrePostProcess","tinymce.plugins.paste.core.Quirks","tinymce.plugins.paste.ui.Buttons","global!tinymce.util.Tools.resolve","global!window","tinymce.plugins.paste.core.Actions","global!Image","global!navigator","tinymce.core.Env","tinymce.core.util.Delay","tinymce.core.util.Tools","tinymce.core.util.VK","tinymce.plugins.paste.api.Events","tinymce.plugins.paste.api.Settings","tinymce.plugins.paste.core.InternalHtml","tinymce.plugins.paste.core.Newlines","tinymce.plugins.paste.core.PasteBin","tinymce.plugins.paste.core.ProcessFilters","tinymce.plugins.paste.core.SmartPaste","tinymce.plugins.paste.core.Utils","global!setTimeout","tinymce.core.api.dom.RangeUtils","tinymce.plugins.paste.core.WordFilter","ephox.katamari.api.Fun","tinymce.core.html.Entities","tinymce.core.html.DomParser","tinymce.core.html.Node","tinymce.core.html.Schema","tinymce.core.html.Serializer","global!Array","global!Error"]
85
+ jsc*/
86
+ define(
87
+ 'ephox.katamari.api.Cell',
88
+
89
+ [
90
+ ],
91
+
92
+ function () {
93
+ var Cell = function (initial) {
94
+ var value = initial;
95
+
96
+ var get = function () {
97
+ return value;
98
+ };
99
+
100
+ var set = function (v) {
101
+ value = v;
102
+ };
103
+
104
+ var clone = function () {
105
+ return Cell(get());
106
+ };
107
+
108
+ return {
109
+ get: get,
110
+ set: set,
111
+ clone: clone
112
+ };
113
+ };
114
+
115
+ return Cell;
116
+ }
117
+ );
118
+
119
+ defineGlobal("global!tinymce.util.Tools.resolve", tinymce.util.Tools.resolve);
120
+ /**
121
+ * ResolveGlobal.js
122
+ *
123
+ * Released under LGPL License.
124
+ * Copyright (c) 1999-2017 Ephox Corp. All rights reserved
125
+ *
126
+ * License: http://www.tinymce.com/license
127
+ * Contributing: http://www.tinymce.com/contributing
128
+ */
129
+
130
+ define(
131
+ 'tinymce.core.PluginManager',
132
+ [
133
+ 'global!tinymce.util.Tools.resolve'
134
+ ],
135
+ function (resolve) {
136
+ return resolve('tinymce.PluginManager');
137
+ }
138
+ );
139
+
140
+ defineGlobal("global!window", window);
141
+ /**
142
+ * DetectProPlugin.js
143
+ *
144
+ * Released under LGPL License.
145
+ * Copyright (c) 1999-2017 Ephox Corp. All rights reserved
146
+ *
147
+ * License: http://www.tinymce.com/license
148
+ * Contributing: http://www.tinymce.com/contributing
149
+ */
150
+
151
+ define(
152
+ 'tinymce.plugins.paste.alien.DetectProPlugin',
153
+ [
154
+ 'global!window',
155
+ 'tinymce.core.PluginManager'
156
+ ],
157
+ function (window, PluginManager) {
158
+ var hasProPlugin = function (editor) {
159
+ // draw back if power version is requested and registered
160
+ if (/(^|[ ,])powerpaste([, ]|$)/.test(editor.settings.plugins) && PluginManager.get('powerpaste')) {
161
+ /*eslint no-console:0 */
162
+ if (typeof window.console !== "undefined" && window.console.log) {
163
+ window.console.log("PowerPaste is incompatible with Paste plugin! Remove 'paste' from the 'plugins' option.");
164
+ }
165
+ return true;
166
+ } else {
167
+ return false;
168
+ }
169
+ };
170
+
171
+ return {
172
+ hasProPlugin: hasProPlugin
173
+ };
174
+ }
175
+ );
176
+
177
+ /**
178
+ * Api.js
179
+ *
180
+ * Released under LGPL License.
181
+ * Copyright (c) 1999-2017 Ephox Corp. All rights reserved
182
+ *
183
+ * License: http://www.tinymce.com/license
184
+ * Contributing: http://www.tinymce.com/contributing
185
+ */
186
+
187
+ define(
188
+ 'tinymce.plugins.paste.api.Api',
189
+ [
190
+ ],
191
+ function (Actions) {
192
+ var get = function (clipboard, quirks) {
193
+ return {
194
+ clipboard: clipboard,
195
+ quirks: quirks
196
+ };
197
+ };
198
+
199
+ return {
200
+ get: get
201
+ };
202
+ }
203
+ );
204
+
205
+ /**
206
+ * Events.js
207
+ *
208
+ * Released under LGPL License.
209
+ * Copyright (c) 1999-2017 Ephox Corp. All rights reserved
210
+ *
211
+ * License: http://www.tinymce.com/license
212
+ * Contributing: http://www.tinymce.com/contributing
213
+ */
214
+
215
+ define(
216
+ 'tinymce.plugins.paste.api.Events',
217
+ [
218
+ ],
219
+ function () {
220
+ var firePastePreProcess = function (editor, html, internal, isWordHtml) {
221
+ return editor.fire('PastePreProcess', { content: html, internal: internal, wordContent: isWordHtml });
222
+ };
223
+
224
+ var firePastePostProcess = function (editor, node, internal, isWordHtml) {
225
+ return editor.fire('PastePostProcess', { node: node, internal: internal, wordContent: isWordHtml });
226
+ };
227
+
228
+ var firePastePlainTextToggle = function (editor, state) {
229
+ return editor.fire('PastePlainTextToggle', { state: state });
230
+ };
231
+
232
+ var firePaste = function (editor, ieFake) {
233
+ return editor.fire('paste', { ieFake: ieFake });
234
+ };
235
+
236
+ return {
237
+ firePastePreProcess: firePastePreProcess,
238
+ firePastePostProcess: firePastePostProcess,
239
+ firePastePlainTextToggle: firePastePlainTextToggle,
240
+ firePaste: firePaste
241
+ };
242
+ }
243
+ );
244
+
245
+ /**
246
+ * Settings.js
247
+ *
248
+ * Released under LGPL License.
249
+ * Copyright (c) 1999-2017 Ephox Corp. All rights reserved
250
+ *
251
+ * License: http://www.tinymce.com/license
252
+ * Contributing: http://www.tinymce.com/contributing
253
+ */
254
+
255
+ define(
256
+ 'tinymce.plugins.paste.api.Settings',
257
+ [
258
+ ],
259
+ function () {
260
+ var shouldPlainTextInform = function (editor) {
261
+ return editor.getParam('paste_plaintext_inform', true);
262
+ };
263
+
264
+ var shouldBlockDrop = function (editor) {
265
+ return editor.getParam('paste_block_drop', false);
266
+ };
267
+
268
+ var shouldPasteDataImages = function (editor) {
269
+ return editor.getParam('paste_data_images', false);
270
+ };
271
+
272
+ var shouldFilterDrop = function (editor) {
273
+ return editor.getParam('paste_filter_drop', true);
274
+ };
275
+
276
+ var getPreProcess = function (editor) {
277
+ return editor.getParam('paste_preprocess');
278
+ };
279
+
280
+ var getPostProcess = function (editor) {
281
+ return editor.getParam('paste_postprocess');
282
+ };
283
+
284
+ var getWebkitStyles = function (editor) {
285
+ return editor.getParam('paste_webkit_styles');
286
+ };
287
+
288
+ var shouldRemoveWebKitStyles = function (editor) {
289
+ return editor.getParam('paste_remove_styles_if_webkit', true);
290
+ };
291
+
292
+ var shouldMergeFormats = function (editor) {
293
+ return editor.getParam('paste_merge_formats', true);
294
+ };
295
+
296
+ var isSmartPasteEnabled = function (editor) {
297
+ return editor.getParam('smart_paste', true);
298
+ };
299
+
300
+ var isPasteAsTextEnabled = function (editor) {
301
+ return editor.getParam('paste_as_text', false);
302
+ };
303
+
304
+ var getRetainStyleProps = function (editor) {
305
+ return editor.getParam('paste_retain_style_properties');
306
+ };
307
+
308
+ var getWordValidElements = function (editor) {
309
+ var defaultValidElements = (
310
+ '-strong/b,-em/i,-u,-span,-p,-ol,-ul,-li,-h1,-h2,-h3,-h4,-h5,-h6,' +
311
+ '-p/div,-a[href|name],sub,sup,strike,br,del,table[width],tr,' +
312
+ 'td[colspan|rowspan|width],th[colspan|rowspan|width],thead,tfoot,tbody'
313
+ );
314
+
315
+ return editor.getParam('paste_word_valid_elements', defaultValidElements);
316
+ };
317
+
318
+ var shouldConvertWordFakeLists = function (editor) {
319
+ return editor.getParam('paste_convert_word_fake_lists', true);
320
+ };
321
+
322
+ var shouldUseDefaultFilters = function (editor) {
323
+ return editor.getParam('paste_enable_default_filters', true);
324
+ };
325
+
326
+ return {
327
+ shouldPlainTextInform: shouldPlainTextInform,
328
+ shouldBlockDrop: shouldBlockDrop,
329
+ shouldPasteDataImages: shouldPasteDataImages,
330
+ shouldFilterDrop: shouldFilterDrop,
331
+ getPreProcess: getPreProcess,
332
+ getPostProcess: getPostProcess,
333
+ getWebkitStyles: getWebkitStyles,
334
+ shouldRemoveWebKitStyles: shouldRemoveWebKitStyles,
335
+ shouldMergeFormats: shouldMergeFormats,
336
+ isSmartPasteEnabled: isSmartPasteEnabled,
337
+ isPasteAsTextEnabled: isPasteAsTextEnabled,
338
+ getRetainStyleProps: getRetainStyleProps,
339
+ getWordValidElements: getWordValidElements,
340
+ shouldConvertWordFakeLists: shouldConvertWordFakeLists,
341
+ shouldUseDefaultFilters: shouldUseDefaultFilters
342
+ };
343
+ }
344
+ );
345
+
346
+ /**
347
+ * Actions.js
348
+ *
349
+ * Released under LGPL License.
350
+ * Copyright (c) 1999-2017 Ephox Corp. All rights reserved
351
+ *
352
+ * License: http://www.tinymce.com/license
353
+ * Contributing: http://www.tinymce.com/contributing
354
+ */
355
+
356
+ define(
357
+ 'tinymce.plugins.paste.core.Actions',
358
+ [
359
+ 'tinymce.plugins.paste.api.Events',
360
+ 'tinymce.plugins.paste.api.Settings'
361
+ ],
362
+ function (Events, Settings) {
363
+ var shouldInformUserAboutPlainText = function (editor, userIsInformedState) {
364
+ return userIsInformedState.get() === false && Settings.shouldPlainTextInform(editor);
365
+ };
366
+
367
+ var displayNotification = function (editor, message) {
368
+ editor.notificationManager.open({
369
+ text: editor.translate(message),
370
+ type: 'info'
371
+ });
372
+ };
373
+
374
+ var togglePlainTextPaste = function (editor, clipboard, userIsInformedState) {
375
+ if (clipboard.pasteFormat === "text") {
376
+ clipboard.pasteFormat = "html";
377
+ Events.firePastePlainTextToggle(editor, false);
378
+ } else {
379
+ clipboard.pasteFormat = "text";
380
+ Events.firePastePlainTextToggle(editor, true);
381
+
382
+ if (shouldInformUserAboutPlainText(editor, userIsInformedState)) {
383
+ displayNotification(editor, 'Paste is now in plain text mode. Contents will now be pasted as plain text until you toggle this option off.');
384
+ userIsInformedState.set(true);
385
+ }
386
+ }
387
+
388
+ editor.focus();
389
+ };
390
+
391
+ return {
392
+ togglePlainTextPaste: togglePlainTextPaste
393
+ };
394
+ }
395
+ );
396
+ /**
397
+ * Commands.js
398
+ *
399
+ * Released under LGPL License.
400
+ * Copyright (c) 1999-2017 Ephox Corp. All rights reserved
401
+ *
402
+ * License: http://www.tinymce.com/license
403
+ * Contributing: http://www.tinymce.com/contributing
404
+ */
405
+
406
+ define(
407
+ 'tinymce.plugins.paste.api.Commands',
408
+ [
409
+ 'tinymce.plugins.paste.core.Actions'
410
+ ],
411
+ function (Actions) {
412
+ var register = function (editor, clipboard, userIsInformedState) {
413
+ editor.addCommand('mceTogglePlainTextPaste', function () {
414
+ Actions.togglePlainTextPaste(editor, clipboard, userIsInformedState);
415
+ });
416
+
417
+ editor.addCommand('mceInsertClipboardContent', function (ui, value) {
418
+ if (value.content) {
419
+ clipboard.pasteHtml(value.content, value.internal);
420
+ }
421
+
422
+ if (value.text) {
423
+ clipboard.pasteText(value.text);
424
+ }
425
+ });
426
+ };
427
+
428
+ return {
429
+ register: register
430
+ };
431
+ }
432
+ );
433
+
434
+ defineGlobal("global!Image", Image);
435
+ defineGlobal("global!navigator", navigator);
436
+ /**
437
+ * ResolveGlobal.js
438
+ *
439
+ * Released under LGPL License.
440
+ * Copyright (c) 1999-2017 Ephox Corp. All rights reserved
441
+ *
442
+ * License: http://www.tinymce.com/license
443
+ * Contributing: http://www.tinymce.com/contributing
444
+ */
445
+
446
+ define(
447
+ 'tinymce.core.Env',
448
+ [
449
+ 'global!tinymce.util.Tools.resolve'
450
+ ],
451
+ function (resolve) {
452
+ return resolve('tinymce.Env');
453
+ }
454
+ );
455
+
456
+ /**
457
+ * ResolveGlobal.js
458
+ *
459
+ * Released under LGPL License.
460
+ * Copyright (c) 1999-2017 Ephox Corp. All rights reserved
461
+ *
462
+ * License: http://www.tinymce.com/license
463
+ * Contributing: http://www.tinymce.com/contributing
464
+ */
465
+
466
+ define(
467
+ 'tinymce.core.util.Delay',
468
+ [
469
+ 'global!tinymce.util.Tools.resolve'
470
+ ],
471
+ function (resolve) {
472
+ return resolve('tinymce.util.Delay');
473
+ }
474
+ );
475
+
476
+ /**
477
+ * ResolveGlobal.js
478
+ *
479
+ * Released under LGPL License.
480
+ * Copyright (c) 1999-2017 Ephox Corp. All rights reserved
481
+ *
482
+ * License: http://www.tinymce.com/license
483
+ * Contributing: http://www.tinymce.com/contributing
484
+ */
485
+
486
+ define(
487
+ 'tinymce.core.util.Tools',
488
+ [
489
+ 'global!tinymce.util.Tools.resolve'
490
+ ],
491
+ function (resolve) {
492
+ return resolve('tinymce.util.Tools');
493
+ }
494
+ );
495
+
496
+ /**
497
+ * ResolveGlobal.js
498
+ *
499
+ * Released under LGPL License.
500
+ * Copyright (c) 1999-2017 Ephox Corp. All rights reserved
501
+ *
502
+ * License: http://www.tinymce.com/license
503
+ * Contributing: http://www.tinymce.com/contributing
504
+ */
505
+
506
+ define(
507
+ 'tinymce.core.util.VK',
508
+ [
509
+ 'global!tinymce.util.Tools.resolve'
510
+ ],
511
+ function (resolve) {
512
+ return resolve('tinymce.util.VK');
513
+ }
514
+ );
515
+
516
+ /**
517
+ * InternalHtml.js
518
+ *
519
+ * Released under LGPL License.
520
+ * Copyright (c) 1999-2017 Ephox Corp. All rights reserved
521
+ *
522
+ * License: http://www.tinymce.com/license
523
+ * Contributing: http://www.tinymce.com/contributing
524
+ */
525
+
526
+ define(
527
+ 'tinymce.plugins.paste.core.InternalHtml',
528
+ [
529
+ ],
530
+ function () {
531
+ var internalMimeType = 'x-tinymce/html';
532
+ var internalMark = '<!-- ' + internalMimeType + ' -->';
533
+
534
+ var mark = function (html) {
535
+ return internalMark + html;
536
+ };
537
+
538
+ var unmark = function (html) {
539
+ return html.replace(internalMark, '');
540
+ };
541
+
542
+ var isMarked = function (html) {
543
+ return html.indexOf(internalMark) !== -1;
544
+ };
545
+
546
+ return {
547
+ mark: mark,
548
+ unmark: unmark,
549
+ isMarked: isMarked,
550
+ internalHtmlMime: function () {
551
+ return internalMimeType;
552
+ }
553
+ };
554
+ }
555
+ );
556
+ /**
557
+ * ResolveGlobal.js
558
+ *
559
+ * Released under LGPL License.
560
+ * Copyright (c) 1999-2017 Ephox Corp. All rights reserved
561
+ *
562
+ * License: http://www.tinymce.com/license
563
+ * Contributing: http://www.tinymce.com/contributing
564
+ */
565
+
566
+ define(
567
+ 'tinymce.core.html.Entities',
568
+ [
569
+ 'global!tinymce.util.Tools.resolve'
570
+ ],
571
+ function (resolve) {
572
+ return resolve('tinymce.html.Entities');
573
+ }
574
+ );
575
+
576
+ /**
577
+ * Newlines.js
578
+ *
579
+ * Released under LGPL License.
580
+ * Copyright (c) 1999-2017 Ephox Corp. All rights reserved
581
+ *
582
+ * License: http://www.tinymce.com/license
583
+ * Contributing: http://www.tinymce.com/contributing
584
+ */
585
+
586
+ /**
587
+ * Newlines class contains utilities to convert newlines (\n or \r\n) tp BRs or to a combination of the specified block element and BRs
588
+ *
589
+ * @class tinymce.Newlines
590
+ * @private
591
+ */
592
+ define(
593
+ 'tinymce.plugins.paste.core.Newlines',
594
+ [
595
+ 'tinymce.core.util.Tools',
596
+ 'tinymce.core.html.Entities'
597
+ ],
598
+ function (Tools, Entities) {
599
+
600
+ var isPlainText = function (text) {
601
+ // so basically any tag that is not one of the "p, div, span, br", or is one of them, but is followed
602
+ // by some additional characters qualifies the text as not a plain text (having some HTML tags)
603
+ // <span style="white-space:pre"> and <br /> are added as separate exceptions to the rule
604
+ return !/<(?:\/?(?!(?:div|p|br|span)>)\w+|(?:(?!(?:span style="white-space:\s?pre;?">)|br\s?\/>))\w+\s[^>]+)>/i.test(text);
605
+ };
606
+
607
+
608
+ var toBRs = function (text) {
609
+ return text.replace(/\r?\n/g, '<br>');
610
+ };
611
+
612
+
613
+ var openContainer = function (rootTag, rootAttrs) {
614
+ var key, attrs = [];
615
+ var tag = '<' + rootTag;
616
+
617
+ if (typeof rootAttrs === 'object') {
618
+ for (key in rootAttrs) {
619
+ if (rootAttrs.hasOwnProperty(key)) {
620
+ attrs.push(key + '="' + Entities.encodeAllRaw(rootAttrs[key]) + '"');
621
+ }
622
+ }
623
+
624
+ if (attrs.length) {
625
+ tag += ' ' + attrs.join(' ');
626
+ }
627
+ }
628
+ return tag + '>';
629
+ };
630
+
631
+
632
+ var toBlockElements = function (text, rootTag, rootAttrs) {
633
+ var blocks = text.split(/\n\n/);
634
+ var tagOpen = openContainer(rootTag, rootAttrs);
635
+ var tagClose = '</' + rootTag + '>';
636
+
637
+ var paragraphs = Tools.map(blocks, function (p) {
638
+ return p.split(/\n/).join('<br />');
639
+ });
640
+
641
+ var stitch = function (p) {
642
+ return tagOpen + p + tagClose;
643
+ };
644
+
645
+ return paragraphs.length === 1 ? paragraphs[0] : Tools.map(paragraphs, stitch).join('');
646
+ };
647
+
648
+
649
+ var convert = function (text, rootTag, rootAttrs) {
650
+ return rootTag ? toBlockElements(text, rootTag, rootAttrs) : toBRs(text);
651
+ };
652
+
653
+
654
+ return {
655
+ isPlainText: isPlainText,
656
+ convert: convert,
657
+ toBRs: toBRs,
658
+ toBlockElements: toBlockElements
659
+ };
660
+ }
661
+ );
662
+ /**
663
+ * PasteBin.js
664
+ *
665
+ * Released under LGPL License.
666
+ * Copyright (c) 1999-2017 Ephox Corp. All rights reserved
667
+ *
668
+ * License: http://www.tinymce.com/license
669
+ * Contributing: http://www.tinymce.com/contributing
670
+ */
671
+
672
+ /**
673
+ * @class tinymce.pasteplugin.PasteBin
674
+ * @private
675
+ */
676
+ define(
677
+ 'tinymce.plugins.paste.core.PasteBin',
678
+ [
679
+ 'tinymce.core.util.Tools',
680
+ 'tinymce.core.Env'
681
+ ],
682
+ function (Tools, Env) {
683
+ return function (editor) {
684
+ var lastRng;
685
+ var pasteBinDefaultContent = '%MCEPASTEBIN%';
686
+
687
+ /**
688
+ * Creates a paste bin element as close as possible to the current caret location and places the focus inside that element
689
+ * so that when the real paste event occurs the contents gets inserted into this element
690
+ * instead of the current editor selection element.
691
+ */
692
+ var create = function () {
693
+ var dom = editor.dom, body = editor.getBody();
694
+ var viewport = editor.dom.getViewPort(editor.getWin()), scrollTop = viewport.y, top = 20;
695
+ var pasteBinElm;
696
+ var scrollContainer;
697
+
698
+ lastRng = editor.selection.getRng();
699
+
700
+ if (editor.inline) {
701
+ scrollContainer = editor.selection.getScrollContainer();
702
+
703
+ // Can't always rely on scrollTop returning a useful value.
704
+ // It returns 0 if the browser doesn't support scrollTop for the element or is non-scrollable
705
+ if (scrollContainer && scrollContainer.scrollTop > 0) {
706
+ scrollTop = scrollContainer.scrollTop;
707
+ }
708
+ }
709
+
710
+ /**
711
+ * Returns the rect of the current caret if the caret is in an empty block before a
712
+ * BR we insert a temporary invisible character that we get the rect this way we always get a proper rect.
713
+ *
714
+ * TODO: This might be useful in core.
715
+ */
716
+ function getCaretRect(rng) {
717
+ var rects, textNode, node, container = rng.startContainer;
718
+
719
+ rects = rng.getClientRects();
720
+ if (rects.length) {
721
+ return rects[0];
722
+ }
723
+
724
+ if (!rng.collapsed || container.nodeType !== 1) {
725
+ return;
726
+ }
727
+
728
+ node = container.childNodes[lastRng.startOffset];
729
+
730
+ // Skip empty whitespace nodes
731
+ while (node && node.nodeType === 3 && !node.data.length) {
732
+ node = node.nextSibling;
733
+ }
734
+
735
+ if (!node) {
736
+ return;
737
+ }
738
+
739
+ // Check if the location is |<br>
740
+ // TODO: Might need to expand this to say |<table>
741
+ if (node.tagName === 'BR') {
742
+ textNode = dom.doc.createTextNode('\uFEFF');
743
+ node.parentNode.insertBefore(textNode, node);
744
+
745
+ rng = dom.createRng();
746
+ rng.setStartBefore(textNode);
747
+ rng.setEndAfter(textNode);
748
+
749
+ rects = rng.getClientRects();
750
+ dom.remove(textNode);
751
+ }
752
+
753
+ if (rects.length) {
754
+ return rects[0];
755
+ }
756
+ }
757
+
758
+ // Calculate top cordinate this is needed to avoid scrolling to top of document
759
+ // We want the paste bin to be as close to the caret as possible to avoid scrolling
760
+ if (lastRng.getClientRects) {
761
+ var rect = getCaretRect(lastRng);
762
+
763
+ if (rect) {
764
+ // Client rects gets us closes to the actual
765
+ // caret location in for example a wrapped paragraph block
766
+ top = scrollTop + (rect.top - dom.getPos(body).y);
767
+ } else {
768
+ top = scrollTop;
769
+
770
+ // Check if we can find a closer location by checking the range element
771
+ var container = lastRng.startContainer;
772
+ if (container) {
773
+ if (container.nodeType === 3 && container.parentNode !== body) {
774
+ container = container.parentNode;
775
+ }
776
+
777
+ if (container.nodeType === 1) {
778
+ top = dom.getPos(container, scrollContainer || body).y;
779
+ }
780
+ }
781
+ }
782
+ }
783
+
784
+ // Create a pastebin
785
+ pasteBinElm = editor.dom.add(editor.getBody(), 'div', {
786
+ id: "mcepastebin",
787
+ contentEditable: true,
788
+ "data-mce-bogus": "all",
789
+ style: 'position: absolute; top: ' + top + 'px; width: 10px; height: 10px; overflow: hidden; opacity: 0'
790
+ }, pasteBinDefaultContent);
791
+
792
+ // Move paste bin out of sight since the controlSelection rect gets displayed otherwise on IE and Gecko
793
+ if (Env.ie || Env.gecko) {
794
+ dom.setStyle(pasteBinElm, 'left', dom.getStyle(body, 'direction', true) === 'rtl' ? 0xFFFF : -0xFFFF);
795
+ }
796
+
797
+ // Prevent focus events from bubbeling fixed FocusManager issues
798
+ dom.bind(pasteBinElm, 'beforedeactivate focusin focusout', function (e) {
799
+ e.stopPropagation();
800
+ });
801
+
802
+ pasteBinElm.focus();
803
+ editor.selection.select(pasteBinElm, true);
804
+ };
805
+
806
+ /**
807
+ * Removes the paste bin if it exists.
808
+ */
809
+ var remove = function () {
810
+ if (getEl()) {
811
+ var pasteBinClone;
812
+
813
+ // WebKit/Blink might clone the div so
814
+ // lets make sure we remove all clones
815
+ // TODO: Man o man is this ugly. WebKit is the new IE! Remove this if they ever fix it!
816
+ while ((pasteBinClone = editor.dom.get('mcepastebin'))) {
817
+ editor.dom.remove(pasteBinClone);
818
+ editor.dom.unbind(pasteBinClone);
819
+ }
820
+
821
+ if (lastRng) {
822
+ editor.selection.setRng(lastRng);
823
+ }
824
+ }
825
+
826
+ lastRng = null;
827
+ };
828
+
829
+
830
+ var getEl = function () {
831
+ return editor.dom.get('mcepastebin');
832
+ };
833
+
834
+ /**
835
+ * Returns the contents of the paste bin as a HTML string.
836
+ *
837
+ * @return {String} Get the contents of the paste bin.
838
+ */
839
+ var getHtml = function () {
840
+ var pasteBinElm, pasteBinClones, i, dirtyWrappers, cleanWrapper;
841
+
842
+ // Since WebKit/Chrome might clone the paste bin when pasting
843
+ // for example: <img style="float: right"> we need to check if any of them contains some useful html.
844
+ // TODO: Man o man is this ugly. WebKit is the new IE! Remove this if they ever fix it!
845
+
846
+ var copyAndRemove = function (toElm, fromElm) {
847
+ toElm.appendChild(fromElm);
848
+ editor.dom.remove(fromElm, true); // remove, but keep children
849
+ };
850
+
851
+ // find only top level elements (there might be more nested inside them as well, see TINY-1162)
852
+ pasteBinClones = Tools.grep(editor.getBody().childNodes, function (elm) {
853
+ return elm.id === 'mcepastebin';
854
+ });
855
+ pasteBinElm = pasteBinClones.shift();
856
+
857
+ // if clones were found, move their content into the first bin
858
+ Tools.each(pasteBinClones, function (pasteBinClone) {
859
+ copyAndRemove(pasteBinElm, pasteBinClone);
860
+ });
861
+
862
+ // TINY-1162: when copying plain text (from notepad for example) WebKit clones
863
+ // paste bin (with styles and attributes) and uses it as a default wrapper for
864
+ // the chunks of the content, here we cycle over the whole paste bin and replace
865
+ // those wrappers with a basic div
866
+ dirtyWrappers = editor.dom.select('div[id=mcepastebin]', pasteBinElm);
867
+ for (i = dirtyWrappers.length - 1; i >= 0; i--) {
868
+ cleanWrapper = editor.dom.create('div');
869
+ pasteBinElm.insertBefore(cleanWrapper, dirtyWrappers[i]);
870
+ copyAndRemove(cleanWrapper, dirtyWrappers[i]);
871
+ }
872
+
873
+ return pasteBinElm ? pasteBinElm.innerHTML : '';
874
+ };
875
+
876
+
877
+ var getLastRng = function () {
878
+ return lastRng;
879
+ };
880
+
881
+
882
+ var isDefaultContent = function (content) {
883
+ return content === pasteBinDefaultContent;
884
+ };
885
+
886
+
887
+ var isPasteBin = function (elm) {
888
+ return elm && elm.id === 'mcepastebin';
889
+ };
890
+
891
+
892
+ var isDefault = function () {
893
+ var pasteBinElm = getEl();
894
+ return isPasteBin(pasteBinElm) && isDefaultContent(pasteBinElm.innerHTML);
895
+ };
896
+
897
+ return {
898
+ create: create,
899
+ remove: remove,
900
+ getEl: getEl,
901
+ getHtml: getHtml,
902
+ getLastRng: getLastRng,
903
+ isDefault: isDefault,
904
+ isDefaultContent: isDefaultContent
905
+ };
906
+ };
907
+ }
908
+ );
909
+
910
+ /**
911
+ * ResolveGlobal.js
912
+ *
913
+ * Released under LGPL License.
914
+ * Copyright (c) 1999-2017 Ephox Corp. All rights reserved
915
+ *
916
+ * License: http://www.tinymce.com/license
917
+ * Contributing: http://www.tinymce.com/contributing
918
+ */
919
+
920
+ define(
921
+ 'tinymce.core.html.DomParser',
922
+ [
923
+ 'global!tinymce.util.Tools.resolve'
924
+ ],
925
+ function (resolve) {
926
+ return resolve('tinymce.html.DomParser');
927
+ }
928
+ );
929
+
930
+ /**
931
+ * ResolveGlobal.js
932
+ *
933
+ * Released under LGPL License.
934
+ * Copyright (c) 1999-2017 Ephox Corp. All rights reserved
935
+ *
936
+ * License: http://www.tinymce.com/license
937
+ * Contributing: http://www.tinymce.com/contributing
938
+ */
939
+
940
+ define(
941
+ 'tinymce.core.html.Node',
942
+ [
943
+ 'global!tinymce.util.Tools.resolve'
944
+ ],
945
+ function (resolve) {
946
+ return resolve('tinymce.html.Node');
947
+ }
948
+ );
949
+
950
+ /**
951
+ * ResolveGlobal.js
952
+ *
953
+ * Released under LGPL License.
954
+ * Copyright (c) 1999-2017 Ephox Corp. All rights reserved
955
+ *
956
+ * License: http://www.tinymce.com/license
957
+ * Contributing: http://www.tinymce.com/contributing
958
+ */
959
+
960
+ define(
961
+ 'tinymce.core.html.Schema',
962
+ [
963
+ 'global!tinymce.util.Tools.resolve'
964
+ ],
965
+ function (resolve) {
966
+ return resolve('tinymce.html.Schema');
967
+ }
968
+ );
969
+
970
+ /**
971
+ * ResolveGlobal.js
972
+ *
973
+ * Released under LGPL License.
974
+ * Copyright (c) 1999-2017 Ephox Corp. All rights reserved
975
+ *
976
+ * License: http://www.tinymce.com/license
977
+ * Contributing: http://www.tinymce.com/contributing
978
+ */
979
+
980
+ define(
981
+ 'tinymce.core.html.Serializer',
982
+ [
983
+ 'global!tinymce.util.Tools.resolve'
984
+ ],
985
+ function (resolve) {
986
+ return resolve('tinymce.html.Serializer');
987
+ }
988
+ );
989
+
990
+ /**
991
+ * Utils.js
992
+ *
993
+ * Released under LGPL License.
994
+ * Copyright (c) 1999-2017 Ephox Corp. All rights reserved
995
+ *
996
+ * License: http://www.tinymce.com/license
997
+ * Contributing: http://www.tinymce.com/contributing
998
+ */
999
+
1000
+ /**
1001
+ * This class contails various utility functions for the paste plugin.
1002
+ *
1003
+ * @class tinymce.pasteplugin.Utils
1004
+ */
1005
+ define(
1006
+ 'tinymce.plugins.paste.core.Utils',
1007
+ [
1008
+ 'global!navigator',
1009
+ 'tinymce.core.html.DomParser',
1010
+ 'tinymce.core.html.Schema',
1011
+ 'tinymce.core.util.Tools'
1012
+ ],
1013
+ function (navigator, DomParser, Schema, Tools) {
1014
+ function filter(content, items) {
1015
+ Tools.each(items, function (v) {
1016
+ if (v.constructor === RegExp) {
1017
+ content = content.replace(v, '');
1018
+ } else {
1019
+ content = content.replace(v[0], v[1]);
1020
+ }
1021
+ });
1022
+
1023
+ return content;
1024
+ }
1025
+
1026
+ /**
1027
+ * Gets the innerText of the specified element. It will handle edge cases
1028
+ * and works better than textContent on Gecko.
1029
+ *
1030
+ * @param {String} html HTML string to get text from.
1031
+ * @return {String} String of text with line feeds.
1032
+ */
1033
+ function innerText(html) {
1034
+ var schema = new Schema(), domParser = new DomParser({}, schema), text = '';
1035
+ var shortEndedElements = schema.getShortEndedElements();
1036
+ var ignoreElements = Tools.makeMap('script noscript style textarea video audio iframe object', ' ');
1037
+ var blockElements = schema.getBlockElements();
1038
+
1039
+ function walk(node) {
1040
+ var name = node.name, currentNode = node;
1041
+
1042
+ if (name === 'br') {
1043
+ text += '\n';
1044
+ return;
1045
+ }
1046
+
1047
+ // img/input/hr
1048
+ if (shortEndedElements[name]) {
1049
+ text += ' ';
1050
+ }
1051
+
1052
+ // Ingore script, video contents
1053
+ if (ignoreElements[name]) {
1054
+ text += ' ';
1055
+ return;
1056
+ }
1057
+
1058
+ if (node.type === 3) {
1059
+ text += node.value;
1060
+ }
1061
+
1062
+ // Walk all children
1063
+ if (!node.shortEnded) {
1064
+ if ((node = node.firstChild)) {
1065
+ do {
1066
+ walk(node);
1067
+ } while ((node = node.next));
1068
+ }
1069
+ }
1070
+
1071
+ // Add \n or \n\n for blocks or P
1072
+ if (blockElements[name] && currentNode.next) {
1073
+ text += '\n';
1074
+
1075
+ if (name === 'p') {
1076
+ text += '\n';
1077
+ }
1078
+ }
1079
+ }
1080
+
1081
+ html = filter(html, [
1082
+ /<!\[[^\]]+\]>/g // Conditional comments
1083
+ ]);
1084
+
1085
+ walk(domParser.parse(html));
1086
+
1087
+ return text;
1088
+ }
1089
+
1090
+ /**
1091
+ * Trims the specified HTML by removing all WebKit fragments, all elements wrapping the body trailing BR elements etc.
1092
+ *
1093
+ * @param {String} html Html string to trim contents on.
1094
+ * @return {String} Html contents that got trimmed.
1095
+ */
1096
+ function trimHtml(html) {
1097
+ function trimSpaces(all, s1, s2) {
1098
+ // WebKit &nbsp; meant to preserve multiple spaces but instead inserted around all inline tags,
1099
+ // including the spans with inline styles created on paste
1100
+ if (!s1 && !s2) {
1101
+ return ' ';
1102
+ }
1103
+
1104
+ return '\u00a0';
1105
+ }
1106
+
1107
+ html = filter(html, [
1108
+ /^[\s\S]*<body[^>]*>\s*|\s*<\/body[^>]*>[\s\S]*$/ig, // Remove anything but the contents within the BODY element
1109
+ /<!--StartFragment-->|<!--EndFragment-->/g, // Inner fragments (tables from excel on mac)
1110
+ [/( ?)<span class="Apple-converted-space">\u00a0<\/span>( ?)/g, trimSpaces],
1111
+ /<br class="Apple-interchange-newline">/g,
1112
+ /<br>$/i // Trailing BR elements
1113
+ ]);
1114
+
1115
+ return html;
1116
+ }
1117
+
1118
+ // TODO: Should be in some global class
1119
+ function createIdGenerator(prefix) {
1120
+ var count = 0;
1121
+
1122
+ return function () {
1123
+ return prefix + (count++);
1124
+ };
1125
+ }
1126
+
1127
+ var isMsEdge = function () {
1128
+ return navigator.userAgent.indexOf(' Edge/') !== -1;
1129
+ };
1130
+
1131
+ return {
1132
+ filter: filter,
1133
+ innerText: innerText,
1134
+ trimHtml: trimHtml,
1135
+ createIdGenerator: createIdGenerator,
1136
+ isMsEdge: isMsEdge
1137
+ };
1138
+ }
1139
+ );
1140
+
1141
+ /**
1142
+ * WordFilter.js
1143
+ *
1144
+ * Released under LGPL License.
1145
+ * Copyright (c) 1999-2017 Ephox Corp. All rights reserved
1146
+ *
1147
+ * License: http://www.tinymce.com/license
1148
+ * Contributing: http://www.tinymce.com/contributing
1149
+ */
1150
+
1151
+ /**
1152
+ * This class parses word HTML into proper TinyMCE markup.
1153
+ *
1154
+ * @class tinymce.pasteplugin.WordFilter
1155
+ * @private
1156
+ */
1157
+ define(
1158
+ 'tinymce.plugins.paste.core.WordFilter',
1159
+ [
1160
+ 'tinymce.core.html.DomParser',
1161
+ 'tinymce.core.html.Node',
1162
+ 'tinymce.core.html.Schema',
1163
+ 'tinymce.core.html.Serializer',
1164
+ 'tinymce.core.util.Tools',
1165
+ 'tinymce.plugins.paste.api.Settings',
1166
+ 'tinymce.plugins.paste.core.Utils'
1167
+ ],
1168
+ function (DomParser, Node, Schema, Serializer, Tools, Settings, Utils) {
1169
+ /**
1170
+ * Checks if the specified content is from any of the following sources: MS Word/Office 365/Google docs.
1171
+ */
1172
+ function isWordContent(content) {
1173
+ return (
1174
+ (/<font face="Times New Roman"|class="?Mso|style="[^"]*\bmso-|style='[^'']*\bmso-|w:WordDocument/i).test(content) ||
1175
+ (/class="OutlineElement/).test(content) ||
1176
+ (/id="?docs\-internal\-guid\-/.test(content))
1177
+ );
1178
+ }
1179
+
1180
+ /**
1181
+ * Checks if the specified text starts with "1. " or "a. " etc.
1182
+ */
1183
+ function isNumericList(text) {
1184
+ var found, patterns;
1185
+
1186
+ patterns = [
1187
+ /^[IVXLMCD]{1,2}\.[ \u00a0]/, // Roman upper case
1188
+ /^[ivxlmcd]{1,2}\.[ \u00a0]/, // Roman lower case
1189
+ /^[a-z]{1,2}[\.\)][ \u00a0]/, // Alphabetical a-z
1190
+ /^[A-Z]{1,2}[\.\)][ \u00a0]/, // Alphabetical A-Z
1191
+ /^[0-9]+\.[ \u00a0]/, // Numeric lists
1192
+ /^[\u3007\u4e00\u4e8c\u4e09\u56db\u4e94\u516d\u4e03\u516b\u4e5d]+\.[ \u00a0]/, // Japanese
1193
+ /^[\u58f1\u5f10\u53c2\u56db\u4f0d\u516d\u4e03\u516b\u4e5d\u62fe]+\.[ \u00a0]/ // Chinese
1194
+ ];
1195
+
1196
+ text = text.replace(/^[\u00a0 ]+/, '');
1197
+
1198
+ Tools.each(patterns, function (pattern) {
1199
+ if (pattern.test(text)) {
1200
+ found = true;
1201
+ return false;
1202
+ }
1203
+ });
1204
+
1205
+ return found;
1206
+ }
1207
+
1208
+ function isBulletList(text) {
1209
+ return /^[\s\u00a0]*[\u2022\u00b7\u00a7\u25CF]\s*/.test(text);
1210
+ }
1211
+
1212
+ /**
1213
+ * Converts fake bullet and numbered lists to real semantic OL/UL.
1214
+ *
1215
+ * @param {tinymce.html.Node} node Root node to convert children of.
1216
+ */
1217
+ function convertFakeListsToProperLists(node) {
1218
+ var currentListNode, prevListNode, lastLevel = 1;
1219
+
1220
+ function getText(node) {
1221
+ var txt = '';
1222
+
1223
+ if (node.type === 3) {
1224
+ return node.value;
1225
+ }
1226
+
1227
+ if ((node = node.firstChild)) {
1228
+ do {
1229
+ txt += getText(node);
1230
+ } while ((node = node.next));
1231
+ }
1232
+
1233
+ return txt;
1234
+ }
1235
+
1236
+ function trimListStart(node, regExp) {
1237
+ if (node.type === 3) {
1238
+ if (regExp.test(node.value)) {
1239
+ node.value = node.value.replace(regExp, '');
1240
+ return false;
1241
+ }
1242
+ }
1243
+
1244
+ if ((node = node.firstChild)) {
1245
+ do {
1246
+ if (!trimListStart(node, regExp)) {
1247
+ return false;
1248
+ }
1249
+ } while ((node = node.next));
1250
+ }
1251
+
1252
+ return true;
1253
+ }
1254
+
1255
+ function removeIgnoredNodes(node) {
1256
+ if (node._listIgnore) {
1257
+ node.remove();
1258
+ return;
1259
+ }
1260
+
1261
+ if ((node = node.firstChild)) {
1262
+ do {
1263
+ removeIgnoredNodes(node);
1264
+ } while ((node = node.next));
1265
+ }
1266
+ }
1267
+
1268
+ function convertParagraphToLi(paragraphNode, listName, start) {
1269
+ var level = paragraphNode._listLevel || lastLevel;
1270
+
1271
+ // Handle list nesting
1272
+ if (level !== lastLevel) {
1273
+ if (level < lastLevel) {
1274
+ // Move to parent list
1275
+ if (currentListNode) {
1276
+ currentListNode = currentListNode.parent.parent;
1277
+ }
1278
+ } else {
1279
+ // Create new list
1280
+ prevListNode = currentListNode;
1281
+ currentListNode = null;
1282
+ }
1283
+ }
1284
+
1285
+ if (!currentListNode || currentListNode.name !== listName) {
1286
+ prevListNode = prevListNode || currentListNode;
1287
+ currentListNode = new Node(listName, 1);
1288
+
1289
+ if (start > 1) {
1290
+ currentListNode.attr('start', '' + start);
1291
+ }
1292
+
1293
+ paragraphNode.wrap(currentListNode);
1294
+ } else {
1295
+ currentListNode.append(paragraphNode);
1296
+ }
1297
+
1298
+ paragraphNode.name = 'li';
1299
+
1300
+ // Append list to previous list if it exists
1301
+ if (level > lastLevel && prevListNode) {
1302
+ prevListNode.lastChild.append(currentListNode);
1303
+ }
1304
+
1305
+ lastLevel = level;
1306
+
1307
+ // Remove start of list item "1. " or "&middot; " etc
1308
+ removeIgnoredNodes(paragraphNode);
1309
+ trimListStart(paragraphNode, /^\u00a0+/);
1310
+ trimListStart(paragraphNode, /^\s*([\u2022\u00b7\u00a7\u25CF]|\w+\.)/);
1311
+ trimListStart(paragraphNode, /^\u00a0+/);
1312
+ }
1313
+
1314
+ // Build a list of all root level elements before we start
1315
+ // altering them in the loop below.
1316
+ var elements = [], child = node.firstChild;
1317
+ while (typeof child !== 'undefined' && child !== null) {
1318
+ elements.push(child);
1319
+
1320
+ child = child.walk();
1321
+ if (child !== null) {
1322
+ while (typeof child !== 'undefined' && child.parent !== node) {
1323
+ child = child.walk();
1324
+ }
1325
+ }
1326
+ }
1327
+
1328
+ for (var i = 0; i < elements.length; i++) {
1329
+ node = elements[i];
1330
+
1331
+ if (node.name === 'p' && node.firstChild) {
1332
+ // Find first text node in paragraph
1333
+ var nodeText = getText(node);
1334
+
1335
+ // Detect unordered lists look for bullets
1336
+ if (isBulletList(nodeText)) {
1337
+ convertParagraphToLi(node, 'ul');
1338
+ continue;
1339
+ }
1340
+
1341
+ // Detect ordered lists 1., a. or ixv.
1342
+ if (isNumericList(nodeText)) {
1343
+ // Parse OL start number
1344
+ var matches = /([0-9]+)\./.exec(nodeText);
1345
+ var start = 1;
1346
+ if (matches) {
1347
+ start = parseInt(matches[1], 10);
1348
+ }
1349
+
1350
+ convertParagraphToLi(node, 'ol', start);
1351
+ continue;
1352
+ }
1353
+
1354
+ // Convert paragraphs marked as lists but doesn't look like anything
1355
+ if (node._listLevel) {
1356
+ convertParagraphToLi(node, 'ul', 1);
1357
+ continue;
1358
+ }
1359
+
1360
+ currentListNode = null;
1361
+ } else {
1362
+ // If the root level element isn't a p tag which can be
1363
+ // processed by convertParagraphToLi, it interrupts the
1364
+ // lists, causing a new list to start instead of having
1365
+ // elements from the next list inserted above this tag.
1366
+ prevListNode = currentListNode;
1367
+ currentListNode = null;
1368
+ }
1369
+ }
1370
+ }
1371
+
1372
+ function filterStyles(editor, validStyles, node, styleValue) {
1373
+ var outputStyles = {}, matches, styles = editor.dom.parseStyle(styleValue);
1374
+
1375
+ Tools.each(styles, function (value, name) {
1376
+ // Convert various MS styles to W3C styles
1377
+ switch (name) {
1378
+ case 'mso-list':
1379
+ // Parse out list indent level for lists
1380
+ matches = /\w+ \w+([0-9]+)/i.exec(styleValue);
1381
+ if (matches) {
1382
+ node._listLevel = parseInt(matches[1], 10);
1383
+ }
1384
+
1385
+ // Remove these nodes <span style="mso-list:Ignore">o</span>
1386
+ // Since the span gets removed we mark the text node and the span
1387
+ if (/Ignore/i.test(value) && node.firstChild) {
1388
+ node._listIgnore = true;
1389
+ node.firstChild._listIgnore = true;
1390
+ }
1391
+
1392
+ break;
1393
+
1394
+ case "horiz-align":
1395
+ name = "text-align";
1396
+ break;
1397
+
1398
+ case "vert-align":
1399
+ name = "vertical-align";
1400
+ break;
1401
+
1402
+ case "font-color":
1403
+ case "mso-foreground":
1404
+ name = "color";
1405
+ break;
1406
+
1407
+ case "mso-background":
1408
+ case "mso-highlight":
1409
+ name = "background";
1410
+ break;
1411
+
1412
+ case "font-weight":
1413
+ case "font-style":
1414
+ if (value !== "normal") {
1415
+ outputStyles[name] = value;
1416
+ }
1417
+ return;
1418
+
1419
+ case "mso-element":
1420
+ // Remove track changes code
1421
+ if (/^(comment|comment-list)$/i.test(value)) {
1422
+ node.remove();
1423
+ return;
1424
+ }
1425
+
1426
+ break;
1427
+ }
1428
+
1429
+ if (name.indexOf('mso-comment') === 0) {
1430
+ node.remove();
1431
+ return;
1432
+ }
1433
+
1434
+ // Never allow mso- prefixed names
1435
+ if (name.indexOf('mso-') === 0) {
1436
+ return;
1437
+ }
1438
+
1439
+ // Output only valid styles
1440
+ if (Settings.getRetainStyleProps(editor) === "all" || (validStyles && validStyles[name])) {
1441
+ outputStyles[name] = value;
1442
+ }
1443
+ });
1444
+
1445
+ // Convert bold style to "b" element
1446
+ if (/(bold)/i.test(outputStyles["font-weight"])) {
1447
+ delete outputStyles["font-weight"];
1448
+ node.wrap(new Node("b", 1));
1449
+ }
1450
+
1451
+ // Convert italic style to "i" element
1452
+ if (/(italic)/i.test(outputStyles["font-style"])) {
1453
+ delete outputStyles["font-style"];
1454
+ node.wrap(new Node("i", 1));
1455
+ }
1456
+
1457
+ // Serialize the styles and see if there is something left to keep
1458
+ outputStyles = editor.dom.serializeStyle(outputStyles, node.name);
1459
+ if (outputStyles) {
1460
+ return outputStyles;
1461
+ }
1462
+
1463
+ return null;
1464
+ }
1465
+
1466
+ var filterWordContent = function (editor, content) {
1467
+ var retainStyleProperties, validStyles;
1468
+
1469
+ retainStyleProperties = Settings.getRetainStyleProps(editor);
1470
+ if (retainStyleProperties) {
1471
+ validStyles = Tools.makeMap(retainStyleProperties.split(/[, ]/));
1472
+ }
1473
+
1474
+ // Remove basic Word junk
1475
+ content = Utils.filter(content, [
1476
+ // Remove apple new line markers
1477
+ /<br class="?Apple-interchange-newline"?>/gi,
1478
+
1479
+ // Remove google docs internal guid markers
1480
+ /<b[^>]+id="?docs-internal-[^>]*>/gi,
1481
+
1482
+ // Word comments like conditional comments etc
1483
+ /<!--[\s\S]+?-->/gi,
1484
+
1485
+ // Remove comments, scripts (e.g., msoShowComment), XML tag, VML content,
1486
+ // MS Office namespaced tags, and a few other tags
1487
+ /<(!|script[^>]*>.*?<\/script(?=[>\s])|\/?(\?xml(:\w+)?|img|meta|link|style|\w:\w+)(?=[\s\/>]))[^>]*>/gi,
1488
+
1489
+ // Convert <s> into <strike> for line-though
1490
+ [/<(\/?)s>/gi, "<$1strike>"],
1491
+
1492
+ // Replace nsbp entites to char since it's easier to handle
1493
+ [/&nbsp;/gi, "\u00a0"],
1494
+
1495
+ // Convert <span style="mso-spacerun:yes">___</span> to string of alternating
1496
+ // breaking/non-breaking spaces of same length
1497
+ [/<span\s+style\s*=\s*"\s*mso-spacerun\s*:\s*yes\s*;?\s*"\s*>([\s\u00a0]*)<\/span>/gi,
1498
+ function (str, spaces) {
1499
+ return (spaces.length > 0) ?
1500
+ spaces.replace(/./, " ").slice(Math.floor(spaces.length / 2)).split("").join("\u00a0") : "";
1501
+ }
1502
+ ]
1503
+ ]);
1504
+
1505
+ var validElements = Settings.getWordValidElements(editor);
1506
+
1507
+ // Setup strict schema
1508
+ var schema = new Schema({
1509
+ valid_elements: validElements,
1510
+ valid_children: '-li[p]'
1511
+ });
1512
+
1513
+ // Add style/class attribute to all element rules since the user might have removed them from
1514
+ // paste_word_valid_elements config option and we need to check them for properties
1515
+ Tools.each(schema.elements, function (rule) {
1516
+ /*eslint dot-notation:0*/
1517
+ if (!rule.attributes["class"]) {
1518
+ rule.attributes["class"] = {};
1519
+ rule.attributesOrder.push("class");
1520
+ }
1521
+
1522
+ if (!rule.attributes.style) {
1523
+ rule.attributes.style = {};
1524
+ rule.attributesOrder.push("style");
1525
+ }
1526
+ });
1527
+
1528
+ // Parse HTML into DOM structure
1529
+ var domParser = new DomParser({}, schema);
1530
+
1531
+ // Filter styles to remove "mso" specific styles and convert some of them
1532
+ domParser.addAttributeFilter('style', function (nodes) {
1533
+ var i = nodes.length, node;
1534
+
1535
+ while (i--) {
1536
+ node = nodes[i];
1537
+ node.attr('style', filterStyles(editor, validStyles, node, node.attr('style')));
1538
+
1539
+ // Remove pointess spans
1540
+ if (node.name === 'span' && node.parent && !node.attributes.length) {
1541
+ node.unwrap();
1542
+ }
1543
+ }
1544
+ });
1545
+
1546
+ // Check the class attribute for comments or del items and remove those
1547
+ domParser.addAttributeFilter('class', function (nodes) {
1548
+ var i = nodes.length, node, className;
1549
+
1550
+ while (i--) {
1551
+ node = nodes[i];
1552
+
1553
+ className = node.attr('class');
1554
+ if (/^(MsoCommentReference|MsoCommentText|msoDel)$/i.test(className)) {
1555
+ node.remove();
1556
+ }
1557
+
1558
+ node.attr('class', null);
1559
+ }
1560
+ });
1561
+
1562
+ // Remove all del elements since we don't want the track changes code in the editor
1563
+ domParser.addNodeFilter('del', function (nodes) {
1564
+ var i = nodes.length;
1565
+
1566
+ while (i--) {
1567
+ nodes[i].remove();
1568
+ }
1569
+ });
1570
+
1571
+ // Keep some of the links and anchors
1572
+ domParser.addNodeFilter('a', function (nodes) {
1573
+ var i = nodes.length, node, href, name;
1574
+
1575
+ while (i--) {
1576
+ node = nodes[i];
1577
+ href = node.attr('href');
1578
+ name = node.attr('name');
1579
+
1580
+ if (href && href.indexOf('#_msocom_') !== -1) {
1581
+ node.remove();
1582
+ continue;
1583
+ }
1584
+
1585
+ if (href && href.indexOf('file://') === 0) {
1586
+ href = href.split('#')[1];
1587
+ if (href) {
1588
+ href = '#' + href;
1589
+ }
1590
+ }
1591
+
1592
+ if (!href && !name) {
1593
+ node.unwrap();
1594
+ } else {
1595
+ // Remove all named anchors that aren't specific to TOC, Footnotes or Endnotes
1596
+ if (name && !/^_?(?:toc|edn|ftn)/i.test(name)) {
1597
+ node.unwrap();
1598
+ continue;
1599
+ }
1600
+
1601
+ node.attr({
1602
+ href: href,
1603
+ name: name
1604
+ });
1605
+ }
1606
+ }
1607
+ });
1608
+
1609
+ // Parse into DOM structure
1610
+ var rootNode = domParser.parse(content);
1611
+
1612
+ // Process DOM
1613
+ if (Settings.shouldConvertWordFakeLists(editor)) {
1614
+ convertFakeListsToProperLists(rootNode);
1615
+ }
1616
+
1617
+ // Serialize DOM back to HTML
1618
+ content = new Serializer({
1619
+ validate: editor.settings.validate
1620
+ }, schema).serialize(rootNode);
1621
+
1622
+ return content;
1623
+ };
1624
+
1625
+ var preProcess = function (editor, content) {
1626
+ return Settings.shouldUseDefaultFilters(editor) ? filterWordContent(editor, content) : content;
1627
+ };
1628
+
1629
+ return {
1630
+ preProcess: preProcess,
1631
+ isWordContent: isWordContent
1632
+ };
1633
+ }
1634
+ );
1635
+
1636
+ /**
1637
+ * ProcessFilters.js
1638
+ *
1639
+ * Released under LGPL License.
1640
+ * Copyright (c) 1999-2017 Ephox Corp. All rights reserved
1641
+ *
1642
+ * License: http://www.tinymce.com/license
1643
+ * Contributing: http://www.tinymce.com/contributing
1644
+ */
1645
+
1646
+ define(
1647
+ 'tinymce.plugins.paste.core.ProcessFilters',
1648
+ [
1649
+ 'tinymce.plugins.paste.api.Events',
1650
+ 'tinymce.plugins.paste.core.WordFilter'
1651
+ ],
1652
+ function (Events, WordFilter) {
1653
+ var processResult = function (content, cancelled) {
1654
+ return { content: content, cancelled: cancelled };
1655
+ };
1656
+
1657
+ var postProcessFilter = function (editor, html, internal, isWordHtml) {
1658
+ var tempBody = editor.dom.create('div', { style: 'display:none' }, html);
1659
+ var postProcessArgs = Events.firePastePostProcess(editor, tempBody, internal, isWordHtml);
1660
+ return processResult(postProcessArgs.node.innerHTML, postProcessArgs.isDefaultPrevented());
1661
+ };
1662
+
1663
+ var filterContent = function (editor, content, internal, isWordHtml) {
1664
+ var preProcessArgs = Events.firePastePreProcess(editor, content, internal, isWordHtml);
1665
+
1666
+ if (editor.hasEventListeners('PastePostProcess') && !preProcessArgs.isDefaultPrevented()) {
1667
+ return postProcessFilter(editor, preProcessArgs.content, internal, isWordHtml);
1668
+ } else {
1669
+ return processResult(preProcessArgs.content, preProcessArgs.isDefaultPrevented());
1670
+ }
1671
+ };
1672
+
1673
+ var process = function (editor, html, internal) {
1674
+ var isWordHtml = WordFilter.isWordContent(html);
1675
+ var content = isWordHtml ? WordFilter.preProcess(editor, html) : html;
1676
+
1677
+ return filterContent(editor, content, internal, isWordHtml);
1678
+ };
1679
+
1680
+ return {
1681
+ process: process
1682
+ };
1683
+ }
1684
+ );
1685
+
1686
+ /**
1687
+ * SmartPaste.js
1688
+ *
1689
+ * Released under LGPL License.
1690
+ * Copyright (c) 1999-2017 Ephox Corp. All rights reserved
1691
+ *
1692
+ * License: http://www.tinymce.com/license
1693
+ * Contributing: http://www.tinymce.com/contributing
1694
+ */
1695
+
1696
+ /**
1697
+ * Tries to be smart depending on what the user pastes if it looks like an url
1698
+ * it will make a link out of the current selection. If it's an image url that looks
1699
+ * like an image it will check if it's an image and insert it as an image.
1700
+ *
1701
+ * @class tinymce.pasteplugin.SmartPaste
1702
+ * @private
1703
+ */
1704
+ define(
1705
+ 'tinymce.plugins.paste.core.SmartPaste',
1706
+ [
1707
+ 'tinymce.core.util.Tools',
1708
+ 'tinymce.plugins.paste.api.Settings'
1709
+ ],
1710
+ function (Tools, Settings) {
1711
+ var isAbsoluteUrl = function (url) {
1712
+ return /^https?:\/\/[\w\?\-\/+=.&%@~#]+$/i.test(url);
1713
+ };
1714
+
1715
+ var isImageUrl = function (url) {
1716
+ return isAbsoluteUrl(url) && /.(gif|jpe?g|png)$/.test(url);
1717
+ };
1718
+
1719
+ var createImage = function (editor, url, pasteHtml) {
1720
+ editor.undoManager.extra(function () {
1721
+ pasteHtml(editor, url);
1722
+ }, function () {
1723
+ editor.insertContent('<img src="' + url + '">');
1724
+ });
1725
+
1726
+ return true;
1727
+ };
1728
+
1729
+ var createLink = function (editor, url, pasteHtml) {
1730
+ editor.undoManager.extra(function () {
1731
+ pasteHtml(editor, url);
1732
+ }, function () {
1733
+ editor.execCommand('mceInsertLink', false, url);
1734
+ });
1735
+
1736
+ return true;
1737
+ };
1738
+
1739
+ var linkSelection = function (editor, html, pasteHtml) {
1740
+ return editor.selection.isCollapsed() === false && isAbsoluteUrl(html) ? createLink(editor, html, pasteHtml) : false;
1741
+ };
1742
+
1743
+ var insertImage = function (editor, html, pasteHtml) {
1744
+ return isImageUrl(html) ? createImage(editor, html, pasteHtml) : false;
1745
+ };
1746
+
1747
+ var pasteHtml = function (editor, html) {
1748
+ editor.insertContent(html, {
1749
+ merge: Settings.shouldMergeFormats(editor),
1750
+ paste: true
1751
+ });
1752
+
1753
+ return true;
1754
+ };
1755
+
1756
+ var smartInsertContent = function (editor, html) {
1757
+ Tools.each([
1758
+ linkSelection,
1759
+ insertImage,
1760
+ pasteHtml
1761
+ ], function (action) {
1762
+ return action(editor, html, pasteHtml) !== true;
1763
+ });
1764
+ };
1765
+
1766
+ var insertContent = function (editor, html) {
1767
+ if (Settings.isSmartPasteEnabled(editor) === false) {
1768
+ pasteHtml(editor, html);
1769
+ } else {
1770
+ smartInsertContent(editor, html);
1771
+ }
1772
+ };
1773
+
1774
+ return {
1775
+ isImageUrl: isImageUrl,
1776
+ isAbsoluteUrl: isAbsoluteUrl,
1777
+ insertContent: insertContent
1778
+ };
1779
+ }
1780
+ );
1781
+
1782
+ /**
1783
+ * Clipboard.js
1784
+ *
1785
+ * Released under LGPL License.
1786
+ * Copyright (c) 1999-2017 Ephox Corp. All rights reserved
1787
+ *
1788
+ * License: http://www.tinymce.com/license
1789
+ * Contributing: http://www.tinymce.com/contributing
1790
+ */
1791
+
1792
+ /**
1793
+ * This class contains logic for getting HTML contents out of the clipboard.
1794
+ *
1795
+ * We need to make a lot of ugly hacks to get the contents out of the clipboard since
1796
+ * the W3C Clipboard API is broken in all browsers that have it: Gecko/WebKit/Blink.
1797
+ * We might rewrite this the way those API:s stabilize. Browsers doesn't handle pasting
1798
+ * from applications like Word the same way as it does when pasting into a contentEditable area
1799
+ * so we need to do lots of extra work to try to get to this clipboard data.
1800
+ *
1801
+ * Current implementation steps:
1802
+ * 1. On keydown with paste keys Ctrl+V or Shift+Insert create
1803
+ * a paste bin element and move focus to that element.
1804
+ * 2. Wait for the browser to fire a "paste" event and get the contents out of the paste bin.
1805
+ * 3. Check if the paste was successful if true, process the HTML.
1806
+ * (4). If the paste was unsuccessful use IE execCommand, Clipboard API, document.dataTransfer old WebKit API etc.
1807
+ *
1808
+ * @class tinymce.pasteplugin.Clipboard
1809
+ * @private
1810
+ */
1811
+ define(
1812
+ 'tinymce.plugins.paste.core.Clipboard',
1813
+ [
1814
+ 'global!Image',
1815
+ 'global!navigator',
1816
+ 'global!window',
1817
+ 'tinymce.core.Env',
1818
+ 'tinymce.core.util.Delay',
1819
+ 'tinymce.core.util.Tools',
1820
+ 'tinymce.core.util.VK',
1821
+ 'tinymce.plugins.paste.api.Events',
1822
+ 'tinymce.plugins.paste.api.Settings',
1823
+ 'tinymce.plugins.paste.core.InternalHtml',
1824
+ 'tinymce.plugins.paste.core.Newlines',
1825
+ 'tinymce.plugins.paste.core.PasteBin',
1826
+ 'tinymce.plugins.paste.core.ProcessFilters',
1827
+ 'tinymce.plugins.paste.core.SmartPaste',
1828
+ 'tinymce.plugins.paste.core.Utils'
1829
+ ],
1830
+ function (Image, navigator, window, Env, Delay, Tools, VK, Events, Settings, InternalHtml, Newlines, PasteBin, ProcessFilters, SmartPaste, Utils) {
1831
+ return function (editor) {
1832
+ var self = this, keyboardPasteTimeStamp = 0;
1833
+ var pasteBin = new PasteBin(editor);
1834
+ var keyboardPastePlainTextState;
1835
+ var mceInternalUrlPrefix = 'data:text/mce-internal,';
1836
+ var uniqueId = Utils.createIdGenerator("mceclip");
1837
+
1838
+ self.pasteFormat = Settings.isPasteAsTextEnabled(editor) ? 'text' : 'html';
1839
+
1840
+ /**
1841
+ * Pastes the specified HTML. This means that the HTML is filtered and then
1842
+ * inserted at the current selection in the editor. It will also fire paste events
1843
+ * for custom user filtering.
1844
+ *
1845
+ * @param {String} html HTML code to paste into the current selection.
1846
+ * @param {Boolean?} internalFlag Optional true/false flag if the contents is internal or external.
1847
+ */
1848
+ function pasteHtml(html, internalFlag) {
1849
+ var internal = internalFlag ? internalFlag : InternalHtml.isMarked(html);
1850
+ var args = ProcessFilters.process(editor, InternalHtml.unmark(html), internal);
1851
+
1852
+ if (args.cancelled === false) {
1853
+ SmartPaste.insertContent(editor, args.content);
1854
+ }
1855
+ }
1856
+
1857
+ /**
1858
+ * Pastes the specified text. This means that the plain text is processed
1859
+ * and converted into BR and P elements. It will fire paste events for custom filtering.
1860
+ *
1861
+ * @param {String} text Text to paste as the current selection location.
1862
+ */
1863
+ function pasteText(text) {
1864
+ text = editor.dom.encode(text).replace(/\r\n/g, '\n');
1865
+ text = Newlines.convert(text, editor.settings.forced_root_block, editor.settings.forced_root_block_attrs);
1866
+
1867
+ pasteHtml(text, false);
1868
+ }
1869
+
1870
+
1871
+ /**
1872
+ * Gets various content types out of a datatransfer object.
1873
+ *
1874
+ * @param {DataTransfer} dataTransfer Event fired on paste.
1875
+ * @return {Object} Object with mime types and data for those mime types.
1876
+ */
1877
+ function getDataTransferItems(dataTransfer) {
1878
+ var items = {};
1879
+
1880
+ if (dataTransfer) {
1881
+ // Use old WebKit/IE API
1882
+ if (dataTransfer.getData) {
1883
+ var legacyText = dataTransfer.getData('Text');
1884
+ if (legacyText && legacyText.length > 0) {
1885
+ if (legacyText.indexOf(mceInternalUrlPrefix) === -1) {
1886
+ items['text/plain'] = legacyText;
1887
+ }
1888
+ }
1889
+ }
1890
+
1891
+ if (dataTransfer.types) {
1892
+ for (var i = 0; i < dataTransfer.types.length; i++) {
1893
+ var contentType = dataTransfer.types[i];
1894
+ try { // IE11 throws exception when contentType is Files (type is present but data cannot be retrieved via getData())
1895
+ items[contentType] = dataTransfer.getData(contentType);
1896
+ } catch (ex) {
1897
+ items[contentType] = ""; // useless in general, but for consistency across browsers
1898
+ }
1899
+ }
1900
+ }
1901
+ }
1902
+
1903
+ return items;
1904
+ }
1905
+
1906
+ /**
1907
+ * Gets various content types out of the Clipboard API. It will also get the
1908
+ * plain text using older IE and WebKit API:s.
1909
+ *
1910
+ * @param {ClipboardEvent} clipboardEvent Event fired on paste.
1911
+ * @return {Object} Object with mime types and data for those mime types.
1912
+ */
1913
+ function getClipboardContent(clipboardEvent) {
1914
+ var content = getDataTransferItems(clipboardEvent.clipboardData || editor.getDoc().dataTransfer);
1915
+
1916
+ // Edge 15 has a broken HTML Clipboard API see https://developer.microsoft.com/en-us/microsoft-edge/platform/issues/11877517/
1917
+ return Utils.isMsEdge() ? Tools.extend(content, { 'text/html': '' }) : content;
1918
+ }
1919
+
1920
+ function hasHtmlOrText(content) {
1921
+ return hasContentType(content, 'text/html') || hasContentType(content, 'text/plain');
1922
+ }
1923
+
1924
+ function getBase64FromUri(uri) {
1925
+ var idx;
1926
+
1927
+ idx = uri.indexOf(',');
1928
+ if (idx !== -1) {
1929
+ return uri.substr(idx + 1);
1930
+ }
1931
+
1932
+ return null;
1933
+ }
1934
+
1935
+ function isValidDataUriImage(settings, imgElm) {
1936
+ return settings.images_dataimg_filter ? settings.images_dataimg_filter(imgElm) : true;
1937
+ }
1938
+
1939
+ function extractFilename(str) {
1940
+ var m = str.match(/([\s\S]+?)\.(?:jpeg|jpg|png|gif)$/i);
1941
+ return m ? editor.dom.encode(m[1]) : null;
1942
+ }
1943
+
1944
+ function pasteImage(rng, reader, blob) {
1945
+ if (rng) {
1946
+ editor.selection.setRng(rng);
1947
+ rng = null;
1948
+ }
1949
+
1950
+ var dataUri = reader.result;
1951
+ var base64 = getBase64FromUri(dataUri);
1952
+ var id = uniqueId();
1953
+ var name = editor.settings.images_reuse_filename && blob.name ? extractFilename(blob.name) : id;
1954
+ var img = new Image();
1955
+
1956
+ img.src = dataUri;
1957
+
1958
+ // TODO: Move the bulk of the cache logic to EditorUpload
1959
+ if (isValidDataUriImage(editor.settings, img)) {
1960
+ var blobCache = editor.editorUpload.blobCache;
1961
+ var blobInfo, existingBlobInfo;
1962
+
1963
+ existingBlobInfo = blobCache.findFirst(function (cachedBlobInfo) {
1964
+ return cachedBlobInfo.base64() === base64;
1965
+ });
1966
+
1967
+ if (!existingBlobInfo) {
1968
+ blobInfo = blobCache.create(id, blob, base64, name);
1969
+ blobCache.add(blobInfo);
1970
+ } else {
1971
+ blobInfo = existingBlobInfo;
1972
+ }
1973
+
1974
+ pasteHtml('<img src="' + blobInfo.blobUri() + '">', false);
1975
+ } else {
1976
+ pasteHtml('<img src="' + dataUri + '">', false);
1977
+ }
1978
+ }
1979
+
1980
+ /**
1981
+ * Checks if the clipboard contains image data if it does it will take that data
1982
+ * and convert it into a data url image and paste that image at the caret location.
1983
+ *
1984
+ * @param {ClipboardEvent} e Paste/drop event object.
1985
+ * @param {DOMRange} rng Rng object to move selection to.
1986
+ * @return {Boolean} true/false if the image data was found or not.
1987
+ */
1988
+ function pasteImageData(e, rng) {
1989
+ var dataTransfer = e.clipboardData || e.dataTransfer;
1990
+
1991
+ function processItems(items) {
1992
+ var i, item, reader, hadImage = false;
1993
+
1994
+ if (items) {
1995
+ for (i = 0; i < items.length; i++) {
1996
+ item = items[i];
1997
+
1998
+ if (/^image\/(jpeg|png|gif|bmp)$/.test(item.type)) {
1999
+ var blob = item.getAsFile ? item.getAsFile() : item;
2000
+
2001
+ reader = new window.FileReader();
2002
+ reader.onload = pasteImage.bind(null, rng, reader, blob);
2003
+ reader.readAsDataURL(blob);
2004
+
2005
+ e.preventDefault();
2006
+ hadImage = true;
2007
+ }
2008
+ }
2009
+ }
2010
+
2011
+ return hadImage;
2012
+ }
2013
+
2014
+ if (editor.settings.paste_data_images && dataTransfer) {
2015
+ return processItems(dataTransfer.items) || processItems(dataTransfer.files);
2016
+ }
2017
+ }
2018
+
2019
+ /**
2020
+ * Chrome on Android doesn't support proper clipboard access so we have no choice but to allow the browser default behavior.
2021
+ *
2022
+ * @param {Event} e Paste event object to check if it contains any data.
2023
+ * @return {Boolean} true/false if the clipboard is empty or not.
2024
+ */
2025
+ function isBrokenAndroidClipboardEvent(e) {
2026
+ var clipboardData = e.clipboardData;
2027
+
2028
+ return navigator.userAgent.indexOf('Android') !== -1 && clipboardData && clipboardData.items && clipboardData.items.length === 0;
2029
+ }
2030
+
2031
+ function hasContentType(clipboardContent, mimeType) {
2032
+ return mimeType in clipboardContent && clipboardContent[mimeType].length > 0;
2033
+ }
2034
+
2035
+ function isKeyboardPasteEvent(e) {
2036
+ return (VK.metaKeyPressed(e) && e.keyCode === 86) || (e.shiftKey && e.keyCode === 45);
2037
+ }
2038
+
2039
+ function registerEventHandlers() {
2040
+ editor.on('keydown', function (e) {
2041
+ function removePasteBinOnKeyUp(e) {
2042
+ // Ctrl+V or Shift+Insert
2043
+ if (isKeyboardPasteEvent(e) && !e.isDefaultPrevented()) {
2044
+ pasteBin.remove();
2045
+ }
2046
+ }
2047
+
2048
+ // Ctrl+V or Shift+Insert
2049
+ if (isKeyboardPasteEvent(e) && !e.isDefaultPrevented()) {
2050
+ keyboardPastePlainTextState = e.shiftKey && e.keyCode === 86;
2051
+
2052
+ // Edge case on Safari on Mac where it doesn't handle Cmd+Shift+V correctly
2053
+ // it fires the keydown but no paste or keyup so we are left with a paste bin
2054
+ if (keyboardPastePlainTextState && Env.webkit && navigator.userAgent.indexOf('Version/') !== -1) {
2055
+ return;
2056
+ }
2057
+
2058
+ // Prevent undoManager keydown handler from making an undo level with the pastebin in it
2059
+ e.stopImmediatePropagation();
2060
+
2061
+ keyboardPasteTimeStamp = new Date().getTime();
2062
+
2063
+ // IE doesn't support Ctrl+Shift+V and it doesn't even produce a paste event
2064
+ // so lets fake a paste event and let IE use the execCommand/dataTransfer methods
2065
+ if (Env.ie && keyboardPastePlainTextState) {
2066
+ e.preventDefault();
2067
+ Events.firePaste(editor, true);
2068
+ return;
2069
+ }
2070
+
2071
+ pasteBin.remove();
2072
+ pasteBin.create();
2073
+
2074
+ // Remove pastebin if we get a keyup and no paste event
2075
+ // For example pasting a file in IE 11 will not produce a paste event
2076
+ editor.once('keyup', removePasteBinOnKeyUp);
2077
+ editor.once('paste', function () {
2078
+ editor.off('keyup', removePasteBinOnKeyUp);
2079
+ });
2080
+ }
2081
+ });
2082
+
2083
+ function insertClipboardContent(clipboardContent, isKeyBoardPaste, plainTextMode, internal) {
2084
+ var content, isPlainTextHtml;
2085
+
2086
+ // Grab HTML from Clipboard API or paste bin as a fallback
2087
+ if (hasContentType(clipboardContent, 'text/html')) {
2088
+ content = clipboardContent['text/html'];
2089
+ } else {
2090
+ content = pasteBin.getHtml();
2091
+ internal = internal ? internal : InternalHtml.isMarked(content);
2092
+
2093
+ // If paste bin is empty try using plain text mode
2094
+ // since that is better than nothing right
2095
+ if (pasteBin.isDefaultContent(content)) {
2096
+ plainTextMode = true;
2097
+ }
2098
+ }
2099
+
2100
+ content = Utils.trimHtml(content);
2101
+
2102
+ pasteBin.remove();
2103
+
2104
+ isPlainTextHtml = (internal === false && Newlines.isPlainText(content));
2105
+
2106
+ // If we got nothing from clipboard API and pastebin or the content is a plain text (with only
2107
+ // some BRs, Ps or DIVs as newlines) then we fallback to plain/text
2108
+ if (!content.length || isPlainTextHtml) {
2109
+ plainTextMode = true;
2110
+ }
2111
+
2112
+ // Grab plain text from Clipboard API or convert existing HTML to plain text
2113
+ if (plainTextMode) {
2114
+ // Use plain text contents from Clipboard API unless the HTML contains paragraphs then
2115
+ // we should convert the HTML to plain text since works better when pasting HTML/Word contents as plain text
2116
+ if (hasContentType(clipboardContent, 'text/plain') && isPlainTextHtml) {
2117
+ content = clipboardContent['text/plain'];
2118
+ } else {
2119
+ content = Utils.innerText(content);
2120
+ }
2121
+ }
2122
+
2123
+ // If the content is the paste bin default HTML then it was
2124
+ // impossible to get the cliboard data out.
2125
+ if (pasteBin.isDefaultContent(content)) {
2126
+ if (!isKeyBoardPaste) {
2127
+ editor.windowManager.alert('Please use Ctrl+V/Cmd+V keyboard shortcuts to paste contents.');
2128
+ }
2129
+
2130
+ return;
2131
+ }
2132
+
2133
+ if (plainTextMode) {
2134
+ pasteText(content);
2135
+ } else {
2136
+ pasteHtml(content, internal);
2137
+ }
2138
+ }
2139
+
2140
+ var getLastRng = function () {
2141
+ return pasteBin.getLastRng() || editor.selection.getRng();
2142
+ };
2143
+
2144
+ editor.on('paste', function (e) {
2145
+ // Getting content from the Clipboard can take some time
2146
+ var clipboardTimer = new Date().getTime();
2147
+ var clipboardContent = getClipboardContent(e);
2148
+ var clipboardDelay = new Date().getTime() - clipboardTimer;
2149
+
2150
+ var isKeyBoardPaste = (new Date().getTime() - keyboardPasteTimeStamp - clipboardDelay) < 1000;
2151
+ var plainTextMode = self.pasteFormat === "text" || keyboardPastePlainTextState;
2152
+ var internal = hasContentType(clipboardContent, InternalHtml.internalHtmlMime());
2153
+
2154
+ keyboardPastePlainTextState = false;
2155
+
2156
+ if (e.isDefaultPrevented() || isBrokenAndroidClipboardEvent(e)) {
2157
+ pasteBin.remove();
2158
+ return;
2159
+ }
2160
+
2161
+ if (!hasHtmlOrText(clipboardContent) && pasteImageData(e, getLastRng())) {
2162
+ pasteBin.remove();
2163
+ return;
2164
+ }
2165
+
2166
+ // Not a keyboard paste prevent default paste and try to grab the clipboard contents using different APIs
2167
+ if (!isKeyBoardPaste) {
2168
+ e.preventDefault();
2169
+ }
2170
+
2171
+ // Try IE only method if paste isn't a keyboard paste
2172
+ if (Env.ie && (!isKeyBoardPaste || e.ieFake) && !hasContentType(clipboardContent, 'text/html')) {
2173
+ pasteBin.create();
2174
+
2175
+ editor.dom.bind(pasteBin.getEl(), 'paste', function (e) {
2176
+ e.stopPropagation();
2177
+ });
2178
+
2179
+ editor.getDoc().execCommand('Paste', false, null);
2180
+ clipboardContent["text/html"] = pasteBin.getHtml();
2181
+ }
2182
+
2183
+ // If clipboard API has HTML then use that directly
2184
+ if (hasContentType(clipboardContent, 'text/html')) {
2185
+ e.preventDefault();
2186
+
2187
+ // if clipboard lacks internal mime type, inspect html for internal markings
2188
+ if (!internal) {
2189
+ internal = InternalHtml.isMarked(clipboardContent['text/html']);
2190
+ }
2191
+
2192
+ insertClipboardContent(clipboardContent, isKeyBoardPaste, plainTextMode, internal);
2193
+ } else {
2194
+ Delay.setEditorTimeout(editor, function () {
2195
+ insertClipboardContent(clipboardContent, isKeyBoardPaste, plainTextMode, internal);
2196
+ }, 0);
2197
+ }
2198
+ });
2199
+ }
2200
+
2201
+ self.pasteHtml = pasteHtml;
2202
+ self.pasteText = pasteText;
2203
+ self.pasteImageData = pasteImageData;
2204
+ self.getDataTransferItems = getDataTransferItems;
2205
+ self.hasHtmlOrText = hasHtmlOrText;
2206
+ self.hasContentType = hasContentType;
2207
+
2208
+ editor.on('preInit', function () {
2209
+ registerEventHandlers();
2210
+
2211
+ // Remove all data images from paste for example from Gecko
2212
+ // except internal images like video elements
2213
+ editor.parser.addNodeFilter('img', function (nodes, name, args) {
2214
+ function isPasteInsert(args) {
2215
+ return args.data && args.data.paste === true;
2216
+ }
2217
+
2218
+ function remove(node) {
2219
+ if (!node.attr('data-mce-object') && src !== Env.transparentSrc) {
2220
+ node.remove();
2221
+ }
2222
+ }
2223
+
2224
+ function isWebKitFakeUrl(src) {
2225
+ return src.indexOf("webkit-fake-url") === 0;
2226
+ }
2227
+
2228
+ function isDataUri(src) {
2229
+ return src.indexOf("data:") === 0;
2230
+ }
2231
+
2232
+ if (!editor.settings.paste_data_images && isPasteInsert(args)) {
2233
+ var i = nodes.length;
2234
+
2235
+ while (i--) {
2236
+ var src = nodes[i].attributes.map.src;
2237
+
2238
+ if (!src) {
2239
+ continue;
2240
+ }
2241
+
2242
+ // Safari on Mac produces webkit-fake-url see: https://bugs.webkit.org/show_bug.cgi?id=49141
2243
+ if (isWebKitFakeUrl(src)) {
2244
+ remove(nodes[i]);
2245
+ } else if (!editor.settings.allow_html_data_urls && isDataUri(src)) {
2246
+ remove(nodes[i]);
2247
+ }
2248
+ }
2249
+ }
2250
+ });
2251
+ });
2252
+ };
2253
+ }
2254
+ );
2255
+
2256
+ defineGlobal("global!setTimeout", setTimeout);
2257
+ /**
2258
+ * CutCopy.js
2259
+ *
2260
+ * Released under LGPL License.
2261
+ * Copyright (c) 1999-2017 Ephox Corp. All rights reserved
2262
+ *
2263
+ * License: http://www.tinymce.com/license
2264
+ * Contributing: http://www.tinymce.com/contributing
2265
+ */
2266
+
2267
+ define(
2268
+ 'tinymce.plugins.paste.core.CutCopy',
2269
+ [
2270
+ 'global!setTimeout',
2271
+ 'tinymce.core.Env',
2272
+ 'tinymce.plugins.paste.core.InternalHtml',
2273
+ 'tinymce.plugins.paste.core.Utils'
2274
+ ],
2275
+ function (setTimeout, Env, InternalHtml, Utils) {
2276
+ var noop = function () {
2277
+ };
2278
+
2279
+ var hasWorkingClipboardApi = function (clipboardData) {
2280
+ // iOS supports the clipboardData API but it doesn't do anything for cut operations
2281
+ // Edge 15 has a broken HTML Clipboard API see https://developer.microsoft.com/en-us/microsoft-edge/platform/issues/11780845/
2282
+ return Env.iOS === false && clipboardData !== undefined && typeof clipboardData.setData === 'function' && Utils.isMsEdge() !== true;
2283
+ };
2284
+
2285
+ var setHtml5Clipboard = function (clipboardData, html, text) {
2286
+ if (hasWorkingClipboardApi(clipboardData)) {
2287
+ try {
2288
+ clipboardData.clearData();
2289
+ clipboardData.setData('text/html', html);
2290
+ clipboardData.setData('text/plain', text);
2291
+ clipboardData.setData(InternalHtml.internalHtmlMime(), html);
2292
+ return true;
2293
+ } catch (e) {
2294
+ return false;
2295
+ }
2296
+ } else {
2297
+ return false;
2298
+ }
2299
+ };
2300
+
2301
+ var setClipboardData = function (evt, data, fallback, done) {
2302
+ if (setHtml5Clipboard(evt.clipboardData, data.html, data.text)) {
2303
+ evt.preventDefault();
2304
+ done();
2305
+ } else {
2306
+ fallback(data.html, done);
2307
+ }
2308
+ };
2309
+
2310
+ var fallback = function (editor) {
2311
+ return function (html, done) {
2312
+ var markedHtml = InternalHtml.mark(html);
2313
+ var outer = editor.dom.create('div', {
2314
+ contenteditable: "false",
2315
+ "data-mce-bogus": "all"
2316
+ });
2317
+ var inner = editor.dom.create('div', { contenteditable: "true" }, markedHtml);
2318
+ editor.dom.setStyles(outer, {
2319
+ position: 'fixed',
2320
+ left: '-3000px',
2321
+ width: '1000px',
2322
+ overflow: 'hidden'
2323
+ });
2324
+ outer.appendChild(inner);
2325
+ editor.dom.add(editor.getBody(), outer);
2326
+
2327
+ var range = editor.selection.getRng();
2328
+ inner.focus();
2329
+
2330
+ var offscreenRange = editor.dom.createRng();
2331
+ offscreenRange.selectNodeContents(inner);
2332
+ editor.selection.setRng(offscreenRange);
2333
+
2334
+ setTimeout(function () {
2335
+ outer.parentNode.removeChild(outer);
2336
+ editor.selection.setRng(range);
2337
+ done();
2338
+ }, 0);
2339
+ };
2340
+ };
2341
+
2342
+ var getData = function (editor) {
2343
+ return {
2344
+ html: editor.selection.getContent({ contextual: true }),
2345
+ text: editor.selection.getContent({ format: 'text' })
2346
+ };
2347
+ };
2348
+
2349
+ var cut = function (editor) {
2350
+ return function (evt) {
2351
+ if (editor.selection.isCollapsed() === false) {
2352
+ setClipboardData(evt, getData(editor), fallback(editor), function () {
2353
+ // Chrome fails to execCommand from another execCommand with this message:
2354
+ // "We don't execute document.execCommand() this time, because it is called recursively.""
2355
+ setTimeout(function () { // detach
2356
+ editor.execCommand('Delete');
2357
+ }, 0);
2358
+ });
2359
+ }
2360
+ };
2361
+ };
2362
+
2363
+ var copy = function (editor) {
2364
+ return function (evt) {
2365
+ if (editor.selection.isCollapsed() === false) {
2366
+ setClipboardData(evt, getData(editor), fallback(editor), noop);
2367
+ }
2368
+ };
2369
+ };
2370
+
2371
+ var register = function (editor) {
2372
+ editor.on('cut', cut(editor));
2373
+ editor.on('copy', copy(editor));
2374
+ };
2375
+
2376
+ return {
2377
+ register: register
2378
+ };
2379
+ }
2380
+ );
2381
+ /**
2382
+ * ResolveGlobal.js
2383
+ *
2384
+ * Released under LGPL License.
2385
+ * Copyright (c) 1999-2017 Ephox Corp. All rights reserved
2386
+ *
2387
+ * License: http://www.tinymce.com/license
2388
+ * Contributing: http://www.tinymce.com/contributing
2389
+ */
2390
+
2391
+ define(
2392
+ 'tinymce.core.api.dom.RangeUtils',
2393
+ [
2394
+ 'global!tinymce.util.Tools.resolve'
2395
+ ],
2396
+ function (resolve) {
2397
+ return resolve('tinymce.dom.RangeUtils');
2398
+ }
2399
+ );
2400
+
2401
+ /**
2402
+ * DragDrop.js
2403
+ *
2404
+ * Released under LGPL License.
2405
+ * Copyright (c) 1999-2017 Ephox Corp. All rights reserved
2406
+ *
2407
+ * License: http://www.tinymce.com/license
2408
+ * Contributing: http://www.tinymce.com/contributing
2409
+ */
2410
+
2411
+ define(
2412
+ 'tinymce.plugins.paste.core.DragDrop',
2413
+ [
2414
+ 'tinymce.core.api.dom.RangeUtils',
2415
+ 'tinymce.core.util.Delay',
2416
+ 'tinymce.plugins.paste.api.Settings',
2417
+ 'tinymce.plugins.paste.core.InternalHtml',
2418
+ 'tinymce.plugins.paste.core.Utils'
2419
+ ],
2420
+ function (RangeUtils, Delay, Settings, InternalHtml, Utils) {
2421
+ var getCaretRangeFromEvent = function (editor, e) {
2422
+ return RangeUtils.getCaretRangeFromPoint(e.clientX, e.clientY, editor.getDoc());
2423
+ };
2424
+
2425
+ var isPlainTextFileUrl = function (content) {
2426
+ var plainTextContent = content['text/plain'];
2427
+ return plainTextContent ? plainTextContent.indexOf('file://') === 0 : false;
2428
+ };
2429
+
2430
+ var setFocusedRange = function (editor, rng) {
2431
+ editor.focus();
2432
+ editor.selection.setRng(rng);
2433
+ };
2434
+
2435
+ var setup = function (editor, clipboard, draggingInternallyState) {
2436
+ // Block all drag/drop events
2437
+ if (Settings.shouldBlockDrop(editor)) {
2438
+ editor.on('dragend dragover draggesture dragdrop drop drag', function (e) {
2439
+ e.preventDefault();
2440
+ e.stopPropagation();
2441
+ });
2442
+ }
2443
+
2444
+ // Prevent users from dropping data images on Gecko
2445
+ if (!Settings.shouldPasteDataImages(editor)) {
2446
+ editor.on('drop', function (e) {
2447
+ var dataTransfer = e.dataTransfer;
2448
+
2449
+ if (dataTransfer && dataTransfer.files && dataTransfer.files.length > 0) {
2450
+ e.preventDefault();
2451
+ }
2452
+ });
2453
+ }
2454
+
2455
+ editor.on('drop', function (e) {
2456
+ var dropContent, rng;
2457
+
2458
+ rng = getCaretRangeFromEvent(editor, e);
2459
+
2460
+ if (e.isDefaultPrevented() || draggingInternallyState.get()) {
2461
+ return;
2462
+ }
2463
+
2464
+ dropContent = clipboard.getDataTransferItems(e.dataTransfer);
2465
+ var internal = clipboard.hasContentType(dropContent, InternalHtml.internalHtmlMime());
2466
+
2467
+ if ((!clipboard.hasHtmlOrText(dropContent) || isPlainTextFileUrl(dropContent)) && clipboard.pasteImageData(e, rng)) {
2468
+ return;
2469
+ }
2470
+
2471
+ if (rng && Settings.shouldFilterDrop(editor)) {
2472
+ var content = dropContent['mce-internal'] || dropContent['text/html'] || dropContent['text/plain'];
2473
+
2474
+ if (content) {
2475
+ e.preventDefault();
2476
+
2477
+ // FF 45 doesn't paint a caret when dragging in text in due to focus call by execCommand
2478
+ Delay.setEditorTimeout(editor, function () {
2479
+ editor.undoManager.transact(function () {
2480
+ if (dropContent['mce-internal']) {
2481
+ editor.execCommand('Delete');
2482
+ }
2483
+
2484
+ setFocusedRange(editor, rng);
2485
+
2486
+ content = Utils.trimHtml(content);
2487
+
2488
+ if (!dropContent['text/html']) {
2489
+ clipboard.pasteText(content);
2490
+ } else {
2491
+ clipboard.pasteHtml(content, internal);
2492
+ }
2493
+ });
2494
+ });
2495
+ }
2496
+ }
2497
+ });
2498
+
2499
+ editor.on('dragstart', function (e) {
2500
+ draggingInternallyState.set(true);
2501
+ });
2502
+
2503
+ editor.on('dragover dragend', function (e) {
2504
+ if (Settings.shouldPasteDataImages(editor) && draggingInternallyState.get() === false) {
2505
+ e.preventDefault();
2506
+ setFocusedRange(editor, getCaretRangeFromEvent(editor, e));
2507
+ }
2508
+
2509
+ if (e.type === 'dragend') {
2510
+ draggingInternallyState.set(false);
2511
+ }
2512
+ });
2513
+ };
2514
+
2515
+ return {
2516
+ setup: setup
2517
+ };
2518
+ }
2519
+ );
2520
+ /**
2521
+ * Plugin.js
2522
+ *
2523
+ * Released under LGPL License.
2524
+ * Copyright (c) 1999-2017 Ephox Corp. All rights reserved
2525
+ *
2526
+ * License: http://www.tinymce.com/license
2527
+ * Contributing: http://www.tinymce.com/contributing
2528
+ */
2529
+
2530
+ define(
2531
+ 'tinymce.plugins.paste.core.PrePostProcess',
2532
+ [
2533
+ 'tinymce.plugins.paste.api.Settings'
2534
+ ],
2535
+ function (Settings) {
2536
+ var setup = function (editor) {
2537
+ var plugin = editor.plugins.paste;
2538
+
2539
+ var preProcess = Settings.getPreProcess(editor);
2540
+ if (preProcess) {
2541
+ editor.on('PastePreProcess', function (e) {
2542
+ preProcess.call(plugin, plugin, e);
2543
+ });
2544
+ }
2545
+
2546
+ var postProcess = Settings.getPostProcess(editor);
2547
+ if (postProcess) {
2548
+ editor.on('PastePostProcess', function (e) {
2549
+ postProcess.call(plugin, plugin, e);
2550
+ });
2551
+ }
2552
+ };
2553
+
2554
+ return {
2555
+ setup: setup
2556
+ };
2557
+ }
2558
+ );
2559
+
2560
+ /**
2561
+ * Quirks.js
2562
+ *
2563
+ * Released under LGPL License.
2564
+ * Copyright (c) 1999-2017 Ephox Corp. All rights reserved
2565
+ *
2566
+ * License: http://www.tinymce.com/license
2567
+ * Contributing: http://www.tinymce.com/contributing
2568
+ */
2569
+
2570
+ /**
2571
+ * This class contains various fixes for browsers. These issues can not be feature
2572
+ * detected since we have no direct control over the clipboard. However we might be able
2573
+ * to remove some of these fixes once the browsers gets updated/fixed.
2574
+ *
2575
+ * @class tinymce.pasteplugin.Quirks
2576
+ * @private
2577
+ */
2578
+ define(
2579
+ 'tinymce.plugins.paste.core.Quirks',
2580
+ [
2581
+ 'tinymce.core.Env',
2582
+ 'tinymce.core.util.Tools',
2583
+ 'tinymce.plugins.paste.api.Settings',
2584
+ 'tinymce.plugins.paste.core.Utils',
2585
+ 'tinymce.plugins.paste.core.WordFilter'
2586
+ ],
2587
+ function (Env, Tools, Settings, Utils, WordFilter) {
2588
+ function addPreProcessFilter(editor, filterFunc) {
2589
+ editor.on('PastePreProcess', function (e) {
2590
+ e.content = filterFunc(editor, e.content, e.internal, e.wordContent);
2591
+ });
2592
+ }
2593
+
2594
+ function addPostProcessFilter(editor, filterFunc) {
2595
+ editor.on('PastePostProcess', function (e) {
2596
+ filterFunc(editor, e.node);
2597
+ });
2598
+ }
2599
+
2600
+ /**
2601
+ * Removes BR elements after block elements. IE9 has a nasty bug where it puts a BR element after each
2602
+ * block element when pasting from word. This removes those elements.
2603
+ *
2604
+ * This:
2605
+ * <p>a</p><br><p>b</p>
2606
+ *
2607
+ * Becomes:
2608
+ * <p>a</p><p>b</p>
2609
+ */
2610
+ function removeExplorerBrElementsAfterBlocks(editor, html) {
2611
+ // Only filter word specific content
2612
+ if (!WordFilter.isWordContent(html)) {
2613
+ return html;
2614
+ }
2615
+
2616
+ // Produce block regexp based on the block elements in schema
2617
+ var blockElements = [];
2618
+
2619
+ Tools.each(editor.schema.getBlockElements(), function (block, blockName) {
2620
+ blockElements.push(blockName);
2621
+ });
2622
+
2623
+ var explorerBlocksRegExp = new RegExp(
2624
+ '(?:<br>&nbsp;[\\s\\r\\n]+|<br>)*(<\\/?(' + blockElements.join('|') + ')[^>]*>)(?:<br>&nbsp;[\\s\\r\\n]+|<br>)*',
2625
+ 'g'
2626
+ );
2627
+
2628
+ // Remove BR:s from: <BLOCK>X</BLOCK><BR>
2629
+ html = Utils.filter(html, [
2630
+ [explorerBlocksRegExp, '$1']
2631
+ ]);
2632
+
2633
+ // IE9 also adds an extra BR element for each soft-linefeed and it also adds a BR for each word wrap break
2634
+ html = Utils.filter(html, [
2635
+ [/<br><br>/g, '<BR><BR>'], // Replace multiple BR elements with uppercase BR to keep them intact
2636
+ [/<br>/g, ' '], // Replace single br elements with space since they are word wrap BR:s
2637
+ [/<BR><BR>/g, '<br>'] // Replace back the double brs but into a single BR
2638
+ ]);
2639
+
2640
+ return html;
2641
+ }
2642
+
2643
+ /**
2644
+ * WebKit has a nasty bug where the all computed styles gets added to style attributes when copy/pasting contents.
2645
+ * This fix solves that by simply removing the whole style attribute.
2646
+ *
2647
+ * The paste_webkit_styles option can be set to specify what to keep:
2648
+ * paste_webkit_styles: "none" // Keep no styles
2649
+ * paste_webkit_styles: "all", // Keep all of them
2650
+ * paste_webkit_styles: "font-weight color" // Keep specific ones
2651
+ */
2652
+ function removeWebKitStyles(editor, content, internal, isWordHtml) {
2653
+ // WordFilter has already processed styles at this point and internal doesn't need any processing
2654
+ if (isWordHtml || internal) {
2655
+ return content;
2656
+ }
2657
+
2658
+ // Filter away styles that isn't matching the target node
2659
+ var webKitStyles = Settings.getWebkitStyles(editor);
2660
+
2661
+ if (Settings.shouldRemoveWebKitStyles(editor) === false || webKitStyles === "all") {
2662
+ return content;
2663
+ }
2664
+
2665
+ if (webKitStyles) {
2666
+ webKitStyles = webKitStyles.split(/[, ]/);
2667
+ }
2668
+
2669
+ // Keep specific styles that doesn't match the current node computed style
2670
+ if (webKitStyles) {
2671
+ var dom = editor.dom, node = editor.selection.getNode();
2672
+
2673
+ content = content.replace(/(<[^>]+) style="([^"]*)"([^>]*>)/gi, function (all, before, value, after) {
2674
+ var inputStyles = dom.parseStyle(dom.decode(value), 'span');
2675
+ var outputStyles = {};
2676
+
2677
+ if (webKitStyles === "none") {
2678
+ return before + after;
2679
+ }
2680
+
2681
+ for (var i = 0; i < webKitStyles.length; i++) {
2682
+ var inputValue = inputStyles[webKitStyles[i]], currentValue = dom.getStyle(node, webKitStyles[i], true);
2683
+
2684
+ if (/color/.test(webKitStyles[i])) {
2685
+ inputValue = dom.toHex(inputValue);
2686
+ currentValue = dom.toHex(currentValue);
2687
+ }
2688
+
2689
+ if (currentValue !== inputValue) {
2690
+ outputStyles[webKitStyles[i]] = inputValue;
2691
+ }
2692
+ }
2693
+
2694
+ outputStyles = dom.serializeStyle(outputStyles, 'span');
2695
+ if (outputStyles) {
2696
+ return before + ' style="' + outputStyles + '"' + after;
2697
+ }
2698
+
2699
+ return before + after;
2700
+ });
2701
+ } else {
2702
+ // Remove all external styles
2703
+ content = content.replace(/(<[^>]+) style="([^"]*)"([^>]*>)/gi, '$1$3');
2704
+ }
2705
+
2706
+ // Keep internal styles
2707
+ content = content.replace(/(<[^>]+) data-mce-style="([^"]+)"([^>]*>)/gi, function (all, before, value, after) {
2708
+ return before + ' style="' + value + '"' + after;
2709
+ });
2710
+
2711
+ return content;
2712
+ }
2713
+
2714
+ function removeUnderlineAndFontInAnchor(editor, root) {
2715
+ editor.$('a', root).find('font,u').each(function (i, node) {
2716
+ editor.dom.remove(node, true);
2717
+ });
2718
+ }
2719
+
2720
+ var setup = function (editor) {
2721
+ if (Env.webkit) {
2722
+ addPreProcessFilter(editor, removeWebKitStyles);
2723
+ }
2724
+
2725
+ if (Env.ie) {
2726
+ addPreProcessFilter(editor, removeExplorerBrElementsAfterBlocks);
2727
+ addPostProcessFilter(editor, removeUnderlineAndFontInAnchor);
2728
+ }
2729
+ };
2730
+
2731
+ return {
2732
+ setup: setup
2733
+ };
2734
+ }
2735
+ );
2736
+ defineGlobal("global!Array", Array);
2737
+ defineGlobal("global!Error", Error);
2738
+ define(
2739
+ 'ephox.katamari.api.Fun',
2740
+
2741
+ [
2742
+ 'global!Array',
2743
+ 'global!Error'
2744
+ ],
2745
+
2746
+ function (Array, Error) {
2747
+
2748
+ var noop = function () { };
2749
+
2750
+ var noarg = function (f) {
2751
+ return function () {
2752
+ return f();
2753
+ };
2754
+ };
2755
+
2756
+ var compose = function (fa, fb) {
2757
+ return function () {
2758
+ return fa(fb.apply(null, arguments));
2759
+ };
2760
+ };
2761
+
2762
+ var constant = function (value) {
2763
+ return function () {
2764
+ return value;
2765
+ };
2766
+ };
2767
+
2768
+ var identity = function (x) {
2769
+ return x;
2770
+ };
2771
+
2772
+ var tripleEquals = function(a, b) {
2773
+ return a === b;
2774
+ };
2775
+
2776
+ // Don't use array slice(arguments), makes the whole function unoptimisable on Chrome
2777
+ var curry = function (f) {
2778
+ // equivalent to arguments.slice(1)
2779
+ // starting at 1 because 0 is the f, makes things tricky.
2780
+ // Pay attention to what variable is where, and the -1 magic.
2781
+ // thankfully, we have tests for this.
2782
+ var args = new Array(arguments.length - 1);
2783
+ for (var i = 1; i < arguments.length; i++) args[i-1] = arguments[i];
2784
+
2785
+ return function () {
2786
+ var newArgs = new Array(arguments.length);
2787
+ for (var j = 0; j < newArgs.length; j++) newArgs[j] = arguments[j];
2788
+
2789
+ var all = args.concat(newArgs);
2790
+ return f.apply(null, all);
2791
+ };
2792
+ };
2793
+
2794
+ var not = function (f) {
2795
+ return function () {
2796
+ return !f.apply(null, arguments);
2797
+ };
2798
+ };
2799
+
2800
+ var die = function (msg) {
2801
+ return function () {
2802
+ throw new Error(msg);
2803
+ };
2804
+ };
2805
+
2806
+ var apply = function (f) {
2807
+ return f();
2808
+ };
2809
+
2810
+ var call = function(f) {
2811
+ f();
2812
+ };
2813
+
2814
+ var never = constant(false);
2815
+ var always = constant(true);
2816
+
2817
+
2818
+ return {
2819
+ noop: noop,
2820
+ noarg: noarg,
2821
+ compose: compose,
2822
+ constant: constant,
2823
+ identity: identity,
2824
+ tripleEquals: tripleEquals,
2825
+ curry: curry,
2826
+ not: not,
2827
+ die: die,
2828
+ apply: apply,
2829
+ call: call,
2830
+ never: never,
2831
+ always: always
2832
+ };
2833
+ }
2834
+ );
2835
+
2836
+ /**
2837
+ * Buttons.js
2838
+ *
2839
+ * Released under LGPL License.
2840
+ * Copyright (c) 1999-2017 Ephox Corp. All rights reserved
2841
+ *
2842
+ * License: http://www.tinymce.com/license
2843
+ * Contributing: http://www.tinymce.com/contributing
2844
+ */
2845
+
2846
+ define(
2847
+ 'tinymce.plugins.paste.ui.Buttons',
2848
+ [
2849
+ 'ephox.katamari.api.Fun'
2850
+ ],
2851
+ function (Fun) {
2852
+ var stateChange = function (editor, clipboard, e) {
2853
+ var ctrl = e.control;
2854
+
2855
+ ctrl.active(clipboard.pasteFormat === 'text');
2856
+
2857
+ editor.on('PastePlainTextToggle', function (e) {
2858
+ ctrl.active(e.state);
2859
+ });
2860
+ };
2861
+
2862
+ var register = function (editor, clipboard) {
2863
+ var postRender = Fun.curry(stateChange, editor, clipboard);
2864
+
2865
+ editor.addButton('pastetext', {
2866
+ active: false,
2867
+ icon: 'pastetext',
2868
+ tooltip: 'Paste as text',
2869
+ cmd: 'mceTogglePlainTextPaste',
2870
+ onPostRender: postRender
2871
+ });
2872
+
2873
+ editor.addMenuItem('pastetext', {
2874
+ text: 'Paste as text',
2875
+ selectable: true,
2876
+ active: clipboard.pasteFormat,
2877
+ cmd: 'mceTogglePlainTextPaste',
2878
+ onPostRender: postRender
2879
+ });
2880
+ };
2881
+
2882
+ return {
2883
+ register: register
2884
+ };
2885
+ }
2886
+ );
2887
+ /**
2888
+ * Plugin.js
2889
+ *
2890
+ * Released under LGPL License.
2891
+ * Copyright (c) 1999-2017 Ephox Corp. All rights reserved
2892
+ *
2893
+ * License: http://www.tinymce.com/license
2894
+ * Contributing: http://www.tinymce.com/contributing
2895
+ */
2896
+
2897
+ define(
2898
+ 'tinymce.plugins.paste.Plugin',
2899
+ [
2900
+ 'ephox.katamari.api.Cell',
2901
+ 'tinymce.core.PluginManager',
2902
+ 'tinymce.plugins.paste.alien.DetectProPlugin',
2903
+ 'tinymce.plugins.paste.api.Api',
2904
+ 'tinymce.plugins.paste.api.Commands',
2905
+ 'tinymce.plugins.paste.core.Clipboard',
2906
+ 'tinymce.plugins.paste.core.CutCopy',
2907
+ 'tinymce.plugins.paste.core.DragDrop',
2908
+ 'tinymce.plugins.paste.core.PrePostProcess',
2909
+ 'tinymce.plugins.paste.core.Quirks',
2910
+ 'tinymce.plugins.paste.ui.Buttons'
2911
+ ],
2912
+ function (Cell, PluginManager, DetectProPlugin, Api, Commands, Clipboard, CutCopy, DragDrop, PrePostProcess, Quirks, Buttons) {
2913
+ var userIsInformedState = Cell(false);
2914
+
2915
+ PluginManager.add('paste', function (editor) {
2916
+ if (DetectProPlugin.hasProPlugin(editor) === false) {
2917
+ var clipboard = new Clipboard(editor);
2918
+ var quirks = Quirks.setup(editor);
2919
+ var draggingInternallyState = Cell(false);
2920
+
2921
+ Buttons.register(editor, clipboard);
2922
+ Commands.register(editor, clipboard, userIsInformedState);
2923
+ PrePostProcess.setup(editor);
2924
+ CutCopy.register(editor);
2925
+ DragDrop.setup(editor, clipboard, draggingInternallyState);
2926
+
2927
+ return Api.get(clipboard, quirks);
2928
+ }
2929
+ });
2930
+
2931
+ return function () { };
2932
+ }
2933
+ );
2934
+ dem('tinymce.plugins.paste.Plugin')();
2935
+ })();