summaryrefslogtreecommitdiff
path: root/public/javascripts/tiny_mce/plugins/paste
diff options
context:
space:
mode:
authorerdgeist <erdgeist@erdgeist.org>2026-06-27 16:58:53 +0200
committererdgeist <erdgeist@erdgeist.org>2026-06-27 16:58:53 +0200
commit420506e58fdfc84f1a5bede0a01dedf0af3bb4f3 (patch)
tree57726b40e8aa9ccf80f874f39d3facefc0331420 /public/javascripts/tiny_mce/plugins/paste
parent241d5e91b2b6716e2861cc77d319c3d3568343a8 (diff)
Stage 7: Rails 7.2 → 8.1 on Ruby 3.2.11
- Bump Rails to 8.1.3 (Ruby unchanged at 3.2.11, new gemset rails8-upgrade) - config.load_defaults 8.1; merge app:update diffs for all environment files - Remove routing-filter 0.7.0; replace with native scope '(:locale)' in routes.rb and default_url_options in ApplicationController - Delete config/initializers/routing_filter_rails71_patch.rb - Replace vendored TinyMCE 3.x (~200 files) with tinymce-rails ~> 8.3; migrate admin_interface.js from jQuery .tinymce()/advanced theme to tinymce.init(); add config/tinymce.yml; note: TinyMCE 7+ is GPL - rails-i18n ~> 8.0 added explicitly (previously indirect dependency) - awesome_nested_set, acts-as-taggable-on pinned to git main/master (gemspec activerecord < 8.1 ceiling; no functional incompatibility; repin to version once upstream releases updated gemspecs) - globalize ~> 7.0, libxml-ruby ~> 5.0, nokogiri ~> 1.18, pg ~> 1.5 - sass-rails, coffee-rails, uglifier moved from :assets group to main (Sprockets 4 convention; :assets group no longer meaningful) - Node: head, draft, lock_owner marked belongs_to optional: true - Page: node, user, editor marked belongs_to optional: true - Static assets in public/images/ and public/javascripts/ referenced via plain HTML tags; Rails 8 load_defaults raises on pipeline helpers for undeclared assets - sessions_controller_test.rb: remove stale require and dead rescue_action - users_controller_test.rb: assert button[type=submit] not input[type=submit] (Rails 8 button_to renders <button> not <input>) - test_helper.rb: node.reload after children.create! (awesome_nested_set 3.9.0 does not refresh parent in memory after callback) - 129 runs, 339 assertions, 3 failures, 0 errors — identical baseline to 7.2
Diffstat (limited to 'public/javascripts/tiny_mce/plugins/paste')
-rw-r--r--public/javascripts/tiny_mce/plugins/paste/editor_plugin.js1
-rw-r--r--public/javascripts/tiny_mce/plugins/paste/editor_plugin_src.js531
-rw-r--r--public/javascripts/tiny_mce/plugins/paste/js/pastetext.js36
-rw-r--r--public/javascripts/tiny_mce/plugins/paste/js/pasteword.js51
-rw-r--r--public/javascripts/tiny_mce/plugins/paste/langs/en_dlg.js5
-rw-r--r--public/javascripts/tiny_mce/plugins/paste/pastetext.htm33
-rw-r--r--public/javascripts/tiny_mce/plugins/paste/pasteword.htm27
7 files changed, 0 insertions, 684 deletions
diff --git a/public/javascripts/tiny_mce/plugins/paste/editor_plugin.js b/public/javascripts/tiny_mce/plugins/paste/editor_plugin.js
deleted file mode 100644
index 7b2bbd9..0000000
--- a/public/javascripts/tiny_mce/plugins/paste/editor_plugin.js
+++ /dev/null
@@ -1 +0,0 @@
1(function(){var a=tinymce.each;tinymce.create("tinymce.plugins.PastePlugin",{init:function(c,d){var e=this,b;e.editor=c;e.url=d;e.onPreProcess=new tinymce.util.Dispatcher(e);e.onPostProcess=new tinymce.util.Dispatcher(e);e.onPreProcess.add(e._preProcess);e.onPostProcess.add(e._postProcess);e.onPreProcess.add(function(h,i){c.execCallback("paste_preprocess",h,i)});e.onPostProcess.add(function(h,i){c.execCallback("paste_postprocess",h,i)});function g(i){var h=c.dom;e.onPreProcess.dispatch(e,i);i.node=h.create("div",0,i.content);e.onPostProcess.dispatch(e,i);i.content=c.serializer.serialize(i.node,{getInner:1});if(/<(p|h[1-6]|ul|ol)/.test(i.content)){e._insertBlockContent(c,h,i.content)}else{e._insert(i.content)}}c.addCommand("mceInsertClipboardContent",function(h,i){g(i)});function f(l){var p,k,i,j=c.selection,o=c.dom,h=c.getBody(),m;if(o.get("_mcePaste")){return}p=o.add(h,"div",{id:"_mcePaste"},"\uFEFF");if(h!=c.getDoc().body){m=o.getPos(c.selection.getStart(),h).y}else{m=h.scrollTop}o.setStyles(p,{position:"absolute",left:-10000,top:m,width:1,height:1,overflow:"hidden"});if(tinymce.isIE){i=o.doc.body.createTextRange();i.moveToElementText(p);i.execCommand("Paste");o.remove(p);if(p.innerHTML==="\uFEFF"){c.execCommand("mcePasteWord");l.preventDefault();return}g({content:p.innerHTML});return tinymce.dom.Event.cancel(l)}else{k=c.selection.getRng();p=p.firstChild;i=c.getDoc().createRange();i.setStart(p,0);i.setEnd(p,1);j.setRng(i);window.setTimeout(function(){var q="",n=o.select("div[id=_mcePaste]");a(n,function(r){q+=(o.select("> span.Apple-style-span div",r)[0]||o.select("> span.Apple-style-span",r)[0]||r).innerHTML});a(n,function(r){o.remove(r)});if(k){j.setRng(k)}g({content:q})},0)}}if(c.getParam("paste_auto_cleanup_on_paste",true)){if(tinymce.isOpera||/Firefox\/2/.test(navigator.userAgent)){c.onKeyDown.add(function(h,i){if(((tinymce.isMac?i.metaKey:i.ctrlKey)&&i.keyCode==86)||(i.shiftKey&&i.keyCode==45)){f(i)}})}else{c.onPaste.addToTop(function(h,i){return f(i)})}}if(c.getParam("paste_block_drop")){c.onInit.add(function(){c.dom.bind(c.getBody(),["dragend","dragover","draggesture","dragdrop","drop","drag"],function(h){h.preventDefault();h.stopPropagation();return false})})}e._legacySupport()},getInfo:function(){return{longname:"Paste text/word",author:"Moxiecode Systems AB",authorurl:"http://tinymce.moxiecode.com",infourl:"http://wiki.moxiecode.com/index.php/TinyMCE:Plugins/paste",version:tinymce.majorVersion+"."+tinymce.minorVersion}},_preProcess:function(d,i){var b=this.editor,c=i.content,g,f;function g(h){a(h,function(j){if(j.constructor==RegExp){c=c.replace(j,"")}else{c=c.replace(j[0],j[1])}})}if(/(class=\"?Mso|style=\"[^\"]*\bmso\-|w:WordDocument)/.test(c)||i.wordContent){i.wordContent=true;g([/^\s*(&nbsp;)+/g,/(&nbsp;|<br[^>]*>)+\s*$/g]);if(b.getParam("paste_convert_middot_lists",true)){g([[/<!--\[if !supportLists\]-->/gi,"$&__MCE_ITEM__"],[/(<span[^>]+:\s*symbol[^>]+>)/gi,"$1__MCE_ITEM__"],[/(<span[^>]+mso-list:[^>]+>)/gi,"$1__MCE_ITEM__"]])}g([/<!--[\s\S]+?-->/gi,/<\/?(img|font|meta|link|style|div|v:\w+)[^>]*>/gi,/<\\?\?xml[^>]*>/gi,/<\/?o:[^>]*>/gi,/ (id|name|language|type|on\w+|v:\w+)=\"([^\"]*)\"/gi,/ (id|name|language|type|on\w+|v:\w+)=(\w+)/gi,[/<(\/?)s>/gi,"<$1strike>"],/<script[^>]+>[\s\S]*?<\/script>/gi,[/&nbsp;/g,"\u00a0"]]);if(!b.getParam("paste_retain_style_properties")){g([/<\/?(span)[^>]*>/gi])}}f=b.getParam("paste_strip_class_attributes");if(f!="none"){function e(l,h){var k,j="";if(f=="all"){return""}h=tinymce.explode(h," ");for(k=h.length-1;k>=0;k--){if(!/^(Mso)/i.test(h[k])){j+=(!j?"":" ")+h[k]}}return' class="'+j+'"'}g([[/ class=\"([^\"]*)\"/gi,e],[/ class=(\w+)/gi,e]])}if(b.getParam("paste_remove_spans")){g([/<\/?(span)[^>]*>/gi])}i.content=c},_postProcess:function(e,g){var d=this,c=d.editor,f=c.dom,b;if(g.wordContent){a(f.select("a",g.node),function(h){if(!h.href||h.href.indexOf("#_Toc")!=-1){f.remove(h,1)}});if(d.editor.getParam("paste_convert_middot_lists",true)){d._convertLists(e,g)}b=c.getParam("paste_retain_style_properties");if(tinymce.is(b,"string")){b=tinymce.explode(b)}a(f.select("*",g.node),function(l){var m={},j=0,k,n,h;if(b){for(k=0;k<b.length;k++){n=b[k];h=f.getStyle(l,n);if(h){m[n]=h;j++}}}f.setAttrib(l,"style","");if(b&&j>0){f.setStyles(l,m)}else{if(l.nodeName=="SPAN"&&!l.className){f.remove(l,true)}}})}if(c.getParam("paste_remove_styles")||(c.getParam("paste_remove_styles_if_webkit")&&tinymce.isWebKit)){a(f.select("*[style]",g.node),function(h){h.removeAttribute("style");h.removeAttribute("mce_style")})}else{if(tinymce.isWebKit){a(f.select("*",g.node),function(h){h.removeAttribute("mce_style")})}}},_convertLists:function(e,c){var g=e.editor.dom,f,j,b=-1,d,k=[],i,h;a(g.select("p",c.node),function(r){var n,s="",q,o,l,m;for(n=r.firstChild;n&&n.nodeType==3;n=n.nextSibling){s+=n.nodeValue}s=r.innerHTML.replace(/<\/?\w+[^>]*>/gi,"").replace(/&nbsp;/g,"\u00a0");if(/^(__MCE_ITEM__)+[\u2022\u00b7\u00a7\u00d8o]\s*\u00a0*/.test(s)){q="ul"}if(/^__MCE_ITEM__\s*\w+\.\s*\u00a0{2,}/.test(s)){q="ol"}if(q){d=parseFloat(r.style.marginLeft||0);if(d>b){k.push(d)}if(!f||q!=i){f=g.create(q);g.insertAfter(f,r)}else{if(d>b){f=j.appendChild(g.create(q))}else{if(d<b){l=tinymce.inArray(k,d);m=g.getParents(f.parentNode,q);f=m[m.length-1-l]||f}}}a(g.select("span",r),function(t){var p=t.innerHTML.replace(/<\/?\w+[^>]*>/gi,"");if(q=="ul"&&/^[\u2022\u00b7\u00a7\u00d8o]/.test(p)){g.remove(t)}else{if(/^[\s\S]*\w+\.(&nbsp;|\u00a0)*\s*/.test(p)){g.remove(t)}}});o=r.innerHTML;if(q=="ul"){o=r.innerHTML.replace(/__MCE_ITEM__/g,"").replace(/^[\u2022\u00b7\u00a7\u00d8o]\s*(&nbsp;|\u00a0)+\s*/,"")}else{o=r.innerHTML.replace(/__MCE_ITEM__/g,"").replace(/^\s*\w+\.(&nbsp;|\u00a0)+\s*/,"")}j=f.appendChild(g.create("li",0,o));g.remove(r);b=d;i=q}else{f=b=0}});h=c.node.innerHTML;if(h.indexOf("__MCE_ITEM__")!=-1){c.node.innerHTML=h.replace(/__MCE_ITEM__/g,"")}},_insertBlockContent:function(h,e,i){var c,g,d=h.selection,m,j,b,k,f;function l(p){var o;if(tinymce.isIE){o=h.getDoc().body.createTextRange();o.moveToElementText(p);o.collapse(false);o.select()}else{d.select(p,1);d.collapse(false)}}this._insert('<span id="_marker">&nbsp;</span>',1);g=e.get("_marker");c=e.getParent(g,"p,h1,h2,h3,h4,h5,h6,ul,ol,th,td");if(c&&!/TD|TH/.test(c.nodeName)){g=e.split(c,g);a(e.create("div",0,i).childNodes,function(o){m=g.parentNode.insertBefore(o.cloneNode(true),g)});l(m)}else{e.setOuterHTML(g,i);d.select(h.getBody(),1);d.collapse(0)}e.remove("_marker");j=d.getStart();b=e.getViewPort(h.getWin());k=h.dom.getPos(j).y;f=j.clientHeight;if(k<b.y||k+f>b.y+b.h){h.getDoc().body.scrollTop=k<b.y?k:k-b.h+25}},_insert:function(d,b){var c=this.editor;if(!c.selection.isCollapsed()){c.getDoc().execCommand("Delete",false,null)}c.execCommand(tinymce.isGecko?"insertHTML":"mceInsertContent",false,d,{skip_undo:b})},_legacySupport:function(){var c=this,b=c.editor;a(["mcePasteText","mcePasteWord"],function(d){b.addCommand(d,function(){b.windowManager.open({file:c.url+(d=="mcePasteText"?"/pastetext.htm":"/pasteword.htm"),width:parseInt(b.getParam("paste_dialog_width","450")),height:parseInt(b.getParam("paste_dialog_height","400")),inline:1})})});b.addButton("pastetext",{title:"paste.paste_text_desc",cmd:"mcePasteText"});b.addButton("pasteword",{title:"paste.paste_word_desc",cmd:"mcePasteWord"});b.addButton("selectall",{title:"paste.selectall_desc",cmd:"selectall"})}});tinymce.PluginManager.add("paste",tinymce.plugins.PastePlugin)})(); \ No newline at end of file
diff --git a/public/javascripts/tiny_mce/plugins/paste/editor_plugin_src.js b/public/javascripts/tiny_mce/plugins/paste/editor_plugin_src.js
deleted file mode 100644
index 8b6cae3..0000000
--- a/public/javascripts/tiny_mce/plugins/paste/editor_plugin_src.js
+++ /dev/null
@@ -1,531 +0,0 @@
1/**
2 * $Id: editor_plugin_src.js 1225 2009-09-07 19:06:19Z spocke $
3 *
4 * @author Moxiecode
5 * @copyright Copyright © 2004-2008, Moxiecode Systems AB, All rights reserved.
6 */
7
8(function() {
9 var each = tinymce.each;
10
11 tinymce.create('tinymce.plugins.PastePlugin', {
12 init : function(ed, url) {
13 var t = this, cb;
14
15 t.editor = ed;
16 t.url = url;
17
18 // Setup plugin events
19 t.onPreProcess = new tinymce.util.Dispatcher(t);
20 t.onPostProcess = new tinymce.util.Dispatcher(t);
21
22 // Register default handlers
23 t.onPreProcess.add(t._preProcess);
24 t.onPostProcess.add(t._postProcess);
25
26 // Register optional preprocess handler
27 t.onPreProcess.add(function(pl, o) {
28 ed.execCallback('paste_preprocess', pl, o);
29 });
30
31 // Register optional postprocess
32 t.onPostProcess.add(function(pl, o) {
33 ed.execCallback('paste_postprocess', pl, o);
34 });
35
36 // This function executes the process handlers and inserts the contents
37 function process(o) {
38 var dom = ed.dom;
39
40 // Execute pre process handlers
41 t.onPreProcess.dispatch(t, o);
42
43 // Create DOM structure
44 o.node = dom.create('div', 0, o.content);
45
46 // Execute post process handlers
47 t.onPostProcess.dispatch(t, o);
48
49 // Serialize content
50 o.content = ed.serializer.serialize(o.node, {getInner : 1});
51
52 // Insert cleaned content. We need to handle insertion of contents containing block elements separately
53 if (/<(p|h[1-6]|ul|ol)/.test(o.content))
54 t._insertBlockContent(ed, dom, o.content);
55 else
56 t._insert(o.content);
57 };
58
59 // Add command for external usage
60 ed.addCommand('mceInsertClipboardContent', function(u, o) {
61 process(o);
62 });
63
64 // This function grabs the contents from the clipboard by adding a
65 // hidden div and placing the caret inside it and after the browser paste
66 // is done it grabs that contents and processes that
67 function grabContent(e) {
68 var n, or, rng, sel = ed.selection, dom = ed.dom, body = ed.getBody(), posY;
69
70 if (dom.get('_mcePaste'))
71 return;
72
73 // Create container to paste into
74 n = dom.add(body, 'div', {id : '_mcePaste'}, '\uFEFF');
75
76 // If contentEditable mode we need to find out the position of the closest element
77 if (body != ed.getDoc().body)
78 posY = dom.getPos(ed.selection.getStart(), body).y;
79 else
80 posY = body.scrollTop;
81
82 // Styles needs to be applied after the element is added to the document since WebKit will otherwise remove all styles
83 dom.setStyles(n, {
84 position : 'absolute',
85 left : -10000,
86 top : posY,
87 width : 1,
88 height : 1,
89 overflow : 'hidden'
90 });
91
92 if (tinymce.isIE) {
93 // Select the container
94 rng = dom.doc.body.createTextRange();
95 rng.moveToElementText(n);
96 rng.execCommand('Paste');
97
98 // Remove container
99 dom.remove(n);
100
101 // Check if the contents was changed, if it wasn't then clipboard extraction failed probably due
102 // to IE security settings so we pass the junk though better than nothing right
103 if (n.innerHTML === '\uFEFF') {
104 ed.execCommand('mcePasteWord');
105 e.preventDefault();
106 return;
107 }
108
109 // Process contents
110 process({content : n.innerHTML});
111
112 // Block the real paste event
113 return tinymce.dom.Event.cancel(e);
114 } else {
115 or = ed.selection.getRng();
116
117 // Move caret into hidden div
118 n = n.firstChild;
119 rng = ed.getDoc().createRange();
120 rng.setStart(n, 0);
121 rng.setEnd(n, 1);
122 sel.setRng(rng);
123
124 // Wait a while and grab the pasted contents
125 window.setTimeout(function() {
126 var h = '', nl = dom.select('div[id=_mcePaste]');
127
128 // WebKit will split the div into multiple ones so this will loop through then all and join them to get the whole HTML string
129 each(nl, function(n) {
130 h += (dom.select('> span.Apple-style-span div', n)[0] || dom.select('> span.Apple-style-span', n)[0] || n).innerHTML;
131 });
132
133 // Remove the nodes
134 each(nl, function(n) {
135 dom.remove(n);
136 });
137
138 // Restore the old selection
139 if (or)
140 sel.setRng(or);
141
142 process({content : h});
143 }, 0);
144 }
145 };
146
147 // Check if we should use the new auto process method
148 if (ed.getParam('paste_auto_cleanup_on_paste', true)) {
149 // Is it's Opera or older FF use key handler
150 if (tinymce.isOpera || /Firefox\/2/.test(navigator.userAgent)) {
151 ed.onKeyDown.add(function(ed, e) {
152 if (((tinymce.isMac ? e.metaKey : e.ctrlKey) && e.keyCode == 86) || (e.shiftKey && e.keyCode == 45))
153 grabContent(e);
154 });
155 } else {
156 // Grab contents on paste event on Gecko and WebKit
157 ed.onPaste.addToTop(function(ed, e) {
158 return grabContent(e);
159 });
160 }
161 }
162
163 // Block all drag/drop events
164 if (ed.getParam('paste_block_drop')) {
165 ed.onInit.add(function() {
166 ed.dom.bind(ed.getBody(), ['dragend', 'dragover', 'draggesture', 'dragdrop', 'drop', 'drag'], function(e) {
167 e.preventDefault();
168 e.stopPropagation();
169
170 return false;
171 });
172 });
173 }
174
175 // Add legacy support
176 t._legacySupport();
177 },
178
179 getInfo : function() {
180 return {
181 longname : 'Paste text/word',
182 author : 'Moxiecode Systems AB',
183 authorurl : 'http://tinymce.moxiecode.com',
184 infourl : 'http://wiki.moxiecode.com/index.php/TinyMCE:Plugins/paste',
185 version : tinymce.majorVersion + "." + tinymce.minorVersion
186 };
187 },
188
189 _preProcess : function(pl, o) {
190 var ed = this.editor, h = o.content, process, stripClass;
191
192 //console.log('Before preprocess:' + o.content);
193
194 function process(items) {
195 each(items, function(v) {
196 // Remove or replace
197 if (v.constructor == RegExp)
198 h = h.replace(v, '');
199 else
200 h = h.replace(v[0], v[1]);
201 });
202 };
203
204 // Detect Word content and process it more aggressive
205 if (/(class=\"?Mso|style=\"[^\"]*\bmso\-|w:WordDocument)/.test(h) || o.wordContent) {
206 o.wordContent = true; // Mark the pasted contents as word specific content
207 //console.log('Word contents detected.');
208
209 // Process away some basic content
210 process([
211 /^\s*(&nbsp;)+/g, // nbsp entities at the start of contents
212 /(&nbsp;|<br[^>]*>)+\s*$/g // nbsp entities at the end of contents
213 ]);
214
215 if (ed.getParam('paste_convert_middot_lists', true)) {
216 process([
217 [/<!--\[if !supportLists\]-->/gi, '$&__MCE_ITEM__'], // Convert supportLists to a list item marker
218 [/(<span[^>]+:\s*symbol[^>]+>)/gi, '$1__MCE_ITEM__'], // Convert symbol spans to list items
219 [/(<span[^>]+mso-list:[^>]+>)/gi, '$1__MCE_ITEM__'] // Convert mso-list to item marker
220 ]);
221 }
222
223 process([
224 /<!--[\s\S]+?-->/gi, // Word comments
225 /<\/?(img|font|meta|link|style|div|v:\w+)[^>]*>/gi, // Remove some tags including VML content
226 /<\\?\?xml[^>]*>/gi, // XML namespace declarations
227 /<\/?o:[^>]*>/gi, // MS namespaced elements <o:tag>
228 / (id|name|language|type|on\w+|v:\w+)=\"([^\"]*)\"/gi, // on.., class, style and language attributes with quotes
229 / (id|name|language|type|on\w+|v:\w+)=(\w+)/gi, // on.., class, style and language attributes without quotes (IE)
230 [/<(\/?)s>/gi, '<$1strike>'], // Convert <s> into <strike> for line-though
231 /<script[^>]+>[\s\S]*?<\/script>/gi, // All scripts elements for msoShowComment for example
232 [/&nbsp;/g, '\u00a0'] // Replace nsbp entites to char since it's easier to handle
233 ]);
234
235 // Remove all spans if no styles is to be retained
236 if (!ed.getParam('paste_retain_style_properties')) {
237 process([
238 /<\/?(span)[^>]*>/gi
239 ]);
240 }
241 }
242
243 // Allow for class names to be retained if desired; either all, or just the ones from Word
244 // Note that the paste_strip_class_attributes: 'none, verify_css_classes: true is also a good variation.
245 stripClass = ed.getParam('paste_strip_class_attributes');
246 if (stripClass != 'none') {
247 // Cleans everything but mceItem... classes
248 function cleanClasses(str, cls) {
249 var i, out = '';
250
251 // Remove all classes
252 if (stripClass == 'all')
253 return '';
254
255 cls = tinymce.explode(cls, ' ');
256
257 for (i = cls.length - 1; i >= 0; i--) {
258 // Remove Mso classes
259 if (!/^(Mso)/i.test(cls[i]))
260 out += (!out ? '' : ' ') + cls[i];
261 }
262
263 return ' class="' + out + '"';
264 };
265
266 process([
267 [/ class=\"([^\"]*)\"/gi, cleanClasses], // class attributes with quotes
268 [/ class=(\w+)/gi, cleanClasses] // class attributes without quotes (IE)
269 ]);
270 }
271
272 // Remove spans option
273 if (ed.getParam('paste_remove_spans')) {
274 process([
275 /<\/?(span)[^>]*>/gi
276 ]);
277 }
278
279 //console.log('After preprocess:' + h);
280
281 o.content = h;
282 },
283
284 /**
285 * Various post process items.
286 */
287 _postProcess : function(pl, o) {
288 var t = this, ed = t.editor, dom = ed.dom, styleProps;
289
290 if (o.wordContent) {
291 // Remove named anchors or TOC links
292 each(dom.select('a', o.node), function(a) {
293 if (!a.href || a.href.indexOf('#_Toc') != -1)
294 dom.remove(a, 1);
295 });
296
297 if (t.editor.getParam('paste_convert_middot_lists', true))
298 t._convertLists(pl, o);
299
300 // Process styles
301 styleProps = ed.getParam('paste_retain_style_properties'); // retained properties
302
303 // If string property then split it
304 if (tinymce.is(styleProps, 'string'))
305 styleProps = tinymce.explode(styleProps);
306
307 // Retains some style properties
308 each(dom.select('*', o.node), function(el) {
309 var newStyle = {}, npc = 0, i, sp, sv;
310
311 // Store a subset of the existing styles
312 if (styleProps) {
313 for (i = 0; i < styleProps.length; i++) {
314 sp = styleProps[i];
315 sv = dom.getStyle(el, sp);
316
317 if (sv) {
318 newStyle[sp] = sv;
319 npc++;
320 }
321 }
322 }
323
324 // Remove all of the existing styles
325 dom.setAttrib(el, 'style', '');
326
327 if (styleProps && npc > 0)
328 dom.setStyles(el, newStyle); // Add back the stored subset of styles
329 else // Remove empty span tags that do not have class attributes
330 if (el.nodeName == 'SPAN' && !el.className)
331 dom.remove(el, true);
332 });
333 }
334
335 // Remove all style information or only specifically on WebKit to avoid the style bug on that browser
336 if (ed.getParam("paste_remove_styles") || (ed.getParam("paste_remove_styles_if_webkit") && tinymce.isWebKit)) {
337 each(dom.select('*[style]', o.node), function(el) {
338 el.removeAttribute('style');
339 el.removeAttribute('mce_style');
340 });
341 } else {
342 if (tinymce.isWebKit) {
343 // We need to compress the styles on WebKit since if you paste <img border="0" /> it will become <img border="0" style="... lots of junk ..." />
344 // Removing the mce_style that contains the real value will force the Serializer engine to compress the styles
345 each(dom.select('*', o.node), function(el) {
346 el.removeAttribute('mce_style');
347 });
348 }
349 }
350 },
351
352 /**
353 * Converts the most common bullet and number formats in Office into a real semantic UL/LI list.
354 */
355 _convertLists : function(pl, o) {
356 var dom = pl.editor.dom, listElm, li, lastMargin = -1, margin, levels = [], lastType, html;
357
358 // Convert middot lists into real semantic lists
359 each(dom.select('p', o.node), function(p) {
360 var sib, val = '', type, html, idx, parents;
361
362 // Get text node value at beginning of paragraph
363 for (sib = p.firstChild; sib && sib.nodeType == 3; sib = sib.nextSibling)
364 val += sib.nodeValue;
365
366 val = p.innerHTML.replace(/<\/?\w+[^>]*>/gi, '').replace(/&nbsp;/g, '\u00a0');
367
368 // Detect unordered lists look for bullets
369 if (/^(__MCE_ITEM__)+[\u2022\u00b7\u00a7\u00d8o]\s*\u00a0*/.test(val))
370 type = 'ul';
371
372 // Detect ordered lists 1., a. or ixv.
373 if (/^__MCE_ITEM__\s*\w+\.\s*\u00a0{2,}/.test(val))
374 type = 'ol';
375
376 // Check if node value matches the list pattern: o&nbsp;&nbsp;
377 if (type) {
378 margin = parseFloat(p.style.marginLeft || 0);
379
380 if (margin > lastMargin)
381 levels.push(margin);
382
383 if (!listElm || type != lastType) {
384 listElm = dom.create(type);
385 dom.insertAfter(listElm, p);
386 } else {
387 // Nested list element
388 if (margin > lastMargin) {
389 listElm = li.appendChild(dom.create(type));
390 } else if (margin < lastMargin) {
391 // Find parent level based on margin value
392 idx = tinymce.inArray(levels, margin);
393 parents = dom.getParents(listElm.parentNode, type);
394 listElm = parents[parents.length - 1 - idx] || listElm;
395 }
396 }
397
398 // Remove middot or number spans if they exists
399 each(dom.select('span', p), function(span) {
400 var html = span.innerHTML.replace(/<\/?\w+[^>]*>/gi, '');
401
402 // Remove span with the middot or the number
403 if (type == 'ul' && /^[\u2022\u00b7\u00a7\u00d8o]/.test(html))
404 dom.remove(span);
405 else if (/^[\s\S]*\w+\.(&nbsp;|\u00a0)*\s*/.test(html))
406 dom.remove(span);
407 });
408
409 html = p.innerHTML;
410
411 // Remove middot/list items
412 if (type == 'ul')
413 html = p.innerHTML.replace(/__MCE_ITEM__/g, '').replace(/^[\u2022\u00b7\u00a7\u00d8o]\s*(&nbsp;|\u00a0)+\s*/, '');
414 else
415 html = p.innerHTML.replace(/__MCE_ITEM__/g, '').replace(/^\s*\w+\.(&nbsp;|\u00a0)+\s*/, '');
416
417 // Create li and add paragraph data into the new li
418 li = listElm.appendChild(dom.create('li', 0, html));
419 dom.remove(p);
420
421 lastMargin = margin;
422 lastType = type;
423 } else
424 listElm = lastMargin = 0; // End list element
425 });
426
427 // Remove any left over makers
428 html = o.node.innerHTML;
429 if (html.indexOf('__MCE_ITEM__') != -1)
430 o.node.innerHTML = html.replace(/__MCE_ITEM__/g, '');
431 },
432
433 /**
434 * This method will split the current block parent and insert the contents inside the split position.
435 * This logic can be improved so text nodes at the start/end remain in the start/end block elements
436 */
437 _insertBlockContent : function(ed, dom, content) {
438 var parentBlock, marker, sel = ed.selection, last, elm, vp, y, elmHeight;
439
440 function select(n) {
441 var r;
442
443 if (tinymce.isIE) {
444 r = ed.getDoc().body.createTextRange();
445 r.moveToElementText(n);
446 r.collapse(false);
447 r.select();
448 } else {
449 sel.select(n, 1);
450 sel.collapse(false);
451 }
452 };
453
454 // Insert a marker for the caret position
455 this._insert('<span id="_marker">&nbsp;</span>', 1);
456 marker = dom.get('_marker');
457 parentBlock = dom.getParent(marker, 'p,h1,h2,h3,h4,h5,h6,ul,ol,th,td');
458
459 // If it's a parent block but not a table cell
460 if (parentBlock && !/TD|TH/.test(parentBlock.nodeName)) {
461 // Split parent block
462 marker = dom.split(parentBlock, marker);
463
464 // Insert nodes before the marker
465 each(dom.create('div', 0, content).childNodes, function(n) {
466 last = marker.parentNode.insertBefore(n.cloneNode(true), marker);
467 });
468
469 // Move caret after marker
470 select(last);
471 } else {
472 dom.setOuterHTML(marker, content);
473 sel.select(ed.getBody(), 1);
474 sel.collapse(0);
475 }
476
477 dom.remove('_marker'); // Remove marker if it's left
478
479 // Get element, position and height
480 elm = sel.getStart();
481 vp = dom.getViewPort(ed.getWin());
482 y = ed.dom.getPos(elm).y;
483 elmHeight = elm.clientHeight;
484
485 // Is element within viewport if not then scroll it into view
486 if (y < vp.y || y + elmHeight > vp.y + vp.h)
487 ed.getDoc().body.scrollTop = y < vp.y ? y : y - vp.h + 25;
488 },
489
490 /**
491 * Inserts the specified contents at the caret position.
492 */
493 _insert : function(h, skip_undo) {
494 var ed = this.editor;
495
496 // First delete the contents seems to work better on WebKit
497 if (!ed.selection.isCollapsed())
498 ed.getDoc().execCommand('Delete', false, null);
499
500 // It's better to use the insertHTML method on Gecko since it will combine paragraphs correctly before inserting the contents
501 ed.execCommand(tinymce.isGecko ? 'insertHTML' : 'mceInsertContent', false, h, {skip_undo : skip_undo});
502 },
503
504 /**
505 * This method will open the old style paste dialogs. Some users might want the old behavior but still use the new cleanup engine.
506 */
507 _legacySupport : function() {
508 var t = this, ed = t.editor;
509
510 // Register commands for backwards compatibility
511 each(['mcePasteText', 'mcePasteWord'], function(cmd) {
512 ed.addCommand(cmd, function() {
513 ed.windowManager.open({
514 file : t.url + (cmd == 'mcePasteText' ? '/pastetext.htm' : '/pasteword.htm'),
515 width : parseInt(ed.getParam("paste_dialog_width", "450")),
516 height : parseInt(ed.getParam("paste_dialog_height", "400")),
517 inline : 1
518 });
519 });
520 });
521
522 // Register buttons for backwards compatibility
523 ed.addButton('pastetext', {title : 'paste.paste_text_desc', cmd : 'mcePasteText'});
524 ed.addButton('pasteword', {title : 'paste.paste_word_desc', cmd : 'mcePasteWord'});
525 ed.addButton('selectall', {title : 'paste.selectall_desc', cmd : 'selectall'});
526 }
527 });
528
529 // Register plugin
530 tinymce.PluginManager.add('paste', tinymce.plugins.PastePlugin);
531})(); \ No newline at end of file
diff --git a/public/javascripts/tiny_mce/plugins/paste/js/pastetext.js b/public/javascripts/tiny_mce/plugins/paste/js/pastetext.js
deleted file mode 100644
index c524f9e..0000000
--- a/public/javascripts/tiny_mce/plugins/paste/js/pastetext.js
+++ /dev/null
@@ -1,36 +0,0 @@
1tinyMCEPopup.requireLangPack();
2
3var PasteTextDialog = {
4 init : function() {
5 this.resize();
6 },
7
8 insert : function() {
9 var h = tinyMCEPopup.dom.encode(document.getElementById('content').value), lines;
10
11 // Convert linebreaks into paragraphs
12 if (document.getElementById('linebreaks').checked) {
13 lines = h.split(/\r?\n/);
14 if (lines.length > 1) {
15 h = '';
16 tinymce.each(lines, function(row) {
17 h += '<p>' + row + '</p>';
18 });
19 }
20 }
21
22 tinyMCEPopup.editor.execCommand('mceInsertClipboardContent', false, {content : h});
23 tinyMCEPopup.close();
24 },
25
26 resize : function() {
27 var vp = tinyMCEPopup.dom.getViewPort(window), el;
28
29 el = document.getElementById('content');
30
31 el.style.width = (vp.w - 20) + 'px';
32 el.style.height = (vp.h - 90) + 'px';
33 }
34};
35
36tinyMCEPopup.onInit.add(PasteTextDialog.init, PasteTextDialog);
diff --git a/public/javascripts/tiny_mce/plugins/paste/js/pasteword.js b/public/javascripts/tiny_mce/plugins/paste/js/pasteword.js
deleted file mode 100644
index a52731c..0000000
--- a/public/javascripts/tiny_mce/plugins/paste/js/pasteword.js
+++ /dev/null
@@ -1,51 +0,0 @@
1tinyMCEPopup.requireLangPack();
2
3var PasteWordDialog = {
4 init : function() {
5 var ed = tinyMCEPopup.editor, el = document.getElementById('iframecontainer'), ifr, doc, css, cssHTML = '';
6
7 // Create iframe
8 el.innerHTML = '<iframe id="iframe" src="javascript:\'\';" frameBorder="0" style="border: 1px solid gray"></iframe>';
9 ifr = document.getElementById('iframe');
10 doc = ifr.contentWindow.document;
11
12 // Force absolute CSS urls
13 css = [ed.baseURI.toAbsolute("themes/" + ed.settings.theme + "/skins/" + ed.settings.skin + "/content.css")];
14 css = css.concat(tinymce.explode(ed.settings.content_css) || []);
15 tinymce.each(css, function(u) {
16 cssHTML += '<link href="' + ed.documentBaseURI.toAbsolute('' + u) + '" rel="stylesheet" type="text/css" />';
17 });
18
19 // Write content into iframe
20 doc.open();
21 doc.write('<html><head>' + cssHTML + '</head><body class="mceContentBody" spellcheck="false"></body></html>');
22 doc.close();
23
24 doc.designMode = 'on';
25 this.resize();
26
27 window.setTimeout(function() {
28 ifr.contentWindow.focus();
29 }, 10);
30 },
31
32 insert : function() {
33 var h = document.getElementById('iframe').contentWindow.document.body.innerHTML;
34
35 tinyMCEPopup.editor.execCommand('mceInsertClipboardContent', false, {content : h, wordContent : true});
36 tinyMCEPopup.close();
37 },
38
39 resize : function() {
40 var vp = tinyMCEPopup.dom.getViewPort(window), el;
41
42 el = document.getElementById('iframe');
43
44 if (el) {
45 el.style.width = (vp.w - 20) + 'px';
46 el.style.height = (vp.h - 90) + 'px';
47 }
48 }
49};
50
51tinyMCEPopup.onInit.add(PasteWordDialog.init, PasteWordDialog);
diff --git a/public/javascripts/tiny_mce/plugins/paste/langs/en_dlg.js b/public/javascripts/tiny_mce/plugins/paste/langs/en_dlg.js
deleted file mode 100644
index eeac778..0000000
--- a/public/javascripts/tiny_mce/plugins/paste/langs/en_dlg.js
+++ /dev/null
@@ -1,5 +0,0 @@
1tinyMCE.addI18n('en.paste_dlg',{
2text_title:"Use CTRL+V on your keyboard to paste the text into the window.",
3text_linebreaks:"Keep linebreaks",
4word_title:"Use CTRL+V on your keyboard to paste the text into the window."
5}); \ No newline at end of file
diff --git a/public/javascripts/tiny_mce/plugins/paste/pastetext.htm b/public/javascripts/tiny_mce/plugins/paste/pastetext.htm
deleted file mode 100644
index 42c3d9c..0000000
--- a/public/javascripts/tiny_mce/plugins/paste/pastetext.htm
+++ /dev/null
@@ -1,33 +0,0 @@
1<html xmlns="http://www.w3.org/1999/xhtml">
2<head>
3 <title>{#paste.paste_text_desc}</title>
4 <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
5 <script type="text/javascript" src="../../tiny_mce_popup.js"></script>
6 <script type="text/javascript" src="js/pastetext.js"></script>
7</head>
8<body onresize="PasteTextDialog.resize();" style="display:none; overflow:hidden;">
9 <form name="source" onsubmit="return PasteTextDialog.insert();" action="#">
10 <div style="float: left" class="title">{#paste.paste_text_desc}</div>
11
12 <div style="float: right">
13 <input type="checkbox" name="linebreaks" id="linebreaks" class="wordWrapCode" checked="checked" /><label for="linebreaks">{#paste_dlg.text_linebreaks}</label>
14 </div>
15
16 <br style="clear: both" />
17
18 <div>{#paste_dlg.text_title}</div>
19
20 <textarea id="content" name="content" rows="15" cols="100" style="width: 100%; height: 100%; font-family: 'Courier New',Courier,mono; font-size: 12px;" dir="ltr" wrap="soft" class="mceFocus"></textarea>
21
22 <div class="mceActionPanel">
23 <div style="float: left">
24 <input type="submit" name="insert" value="{#insert}" id="insert" />
25 </div>
26
27 <div style="float: right">
28 <input type="button" name="cancel" value="{#cancel}" onclick="tinyMCEPopup.close();" id="cancel" />
29 </div>
30 </div>
31 </form>
32</body>
33</html> \ No newline at end of file
diff --git a/public/javascripts/tiny_mce/plugins/paste/pasteword.htm b/public/javascripts/tiny_mce/plugins/paste/pasteword.htm
deleted file mode 100644
index f4a9b3d..0000000
--- a/public/javascripts/tiny_mce/plugins/paste/pasteword.htm
+++ /dev/null
@@ -1,27 +0,0 @@
1<html xmlns="http://www.w3.org/1999/xhtml">
2<head>
3 <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
4 <title>{#paste.paste_word_desc}</title>
5 <script type="text/javascript" src="../../tiny_mce_popup.js"></script>
6 <script type="text/javascript" src="js/pasteword.js"></script>
7</head>
8<body onresize="PasteWordDialog.resize();" style="display:none; overflow:hidden;">
9 <form name="source" onsubmit="return PasteWordDialog.insert();" action="#">
10 <div class="title">{#paste.paste_word_desc}</div>
11
12 <div>{#paste_dlg.word_title}</div>
13
14 <div id="iframecontainer"></div>
15
16 <div class="mceActionPanel">
17 <div style="float: left">
18 <input type="submit" id="insert" name="insert" value="{#insert}" />
19 </div>
20
21 <div style="float: right">
22 <input type="button" id="cancel" name="cancel" value="{#cancel}" onclick="tinyMCEPopup.close();" />
23 </div>
24 </div>
25 </form>
26</body>
27</html>