aboutsummaryrefslogtreecommitdiff
path: root/sources/plugins/pastefromword
diff options
context:
space:
mode:
Diffstat (limited to 'sources/plugins/pastefromword')
-rw-r--r--sources/plugins/pastefromword/filter/default.js1251
-rw-r--r--sources/plugins/pastefromword/icons/hidpi/pastefromword-rtl.pngbin0 -> 2090 bytes
-rw-r--r--sources/plugins/pastefromword/icons/hidpi/pastefromword.pngbin0 -> 2105 bytes
-rw-r--r--sources/plugins/pastefromword/icons/pastefromword-rtl.pngbin0 -> 720 bytes
-rw-r--r--sources/plugins/pastefromword/icons/pastefromword.pngbin0 -> 723 bytes
-rw-r--r--sources/plugins/pastefromword/lang/af.js10
-rw-r--r--sources/plugins/pastefromword/lang/ar.js10
-rw-r--r--sources/plugins/pastefromword/lang/bg.js10
-rw-r--r--sources/plugins/pastefromword/lang/bn.js10
-rw-r--r--sources/plugins/pastefromword/lang/bs.js10
-rw-r--r--sources/plugins/pastefromword/lang/ca.js10
-rw-r--r--sources/plugins/pastefromword/lang/cs.js10
-rw-r--r--sources/plugins/pastefromword/lang/cy.js10
-rw-r--r--sources/plugins/pastefromword/lang/da.js10
-rw-r--r--sources/plugins/pastefromword/lang/de.js10
-rw-r--r--sources/plugins/pastefromword/lang/el.js10
-rw-r--r--sources/plugins/pastefromword/lang/en-au.js10
-rw-r--r--sources/plugins/pastefromword/lang/en-ca.js10
-rw-r--r--sources/plugins/pastefromword/lang/en-gb.js10
-rw-r--r--sources/plugins/pastefromword/lang/en.js10
-rw-r--r--sources/plugins/pastefromword/lang/eo.js10
-rw-r--r--sources/plugins/pastefromword/lang/es.js10
-rw-r--r--sources/plugins/pastefromword/lang/et.js10
-rw-r--r--sources/plugins/pastefromword/lang/eu.js10
-rw-r--r--sources/plugins/pastefromword/lang/fa.js10
-rw-r--r--sources/plugins/pastefromword/lang/fi.js10
-rw-r--r--sources/plugins/pastefromword/lang/fo.js10
-rw-r--r--sources/plugins/pastefromword/lang/fr-ca.js10
-rw-r--r--sources/plugins/pastefromword/lang/fr.js10
-rw-r--r--sources/plugins/pastefromword/lang/gl.js10
-rw-r--r--sources/plugins/pastefromword/lang/gu.js10
-rw-r--r--sources/plugins/pastefromword/lang/he.js10
-rw-r--r--sources/plugins/pastefromword/lang/hi.js10
-rw-r--r--sources/plugins/pastefromword/lang/hr.js10
-rw-r--r--sources/plugins/pastefromword/lang/hu.js10
-rw-r--r--sources/plugins/pastefromword/lang/id.js10
-rw-r--r--sources/plugins/pastefromword/lang/is.js10
-rw-r--r--sources/plugins/pastefromword/lang/it.js10
-rw-r--r--sources/plugins/pastefromword/lang/ja.js10
-rw-r--r--sources/plugins/pastefromword/lang/ka.js10
-rw-r--r--sources/plugins/pastefromword/lang/km.js10
-rw-r--r--sources/plugins/pastefromword/lang/ko.js10
-rw-r--r--sources/plugins/pastefromword/lang/ku.js10
-rw-r--r--sources/plugins/pastefromword/lang/lt.js10
-rw-r--r--sources/plugins/pastefromword/lang/lv.js10
-rw-r--r--sources/plugins/pastefromword/lang/mk.js10
-rw-r--r--sources/plugins/pastefromword/lang/mn.js10
-rw-r--r--sources/plugins/pastefromword/lang/ms.js10
-rw-r--r--sources/plugins/pastefromword/lang/nb.js10
-rw-r--r--sources/plugins/pastefromword/lang/nl.js10
-rw-r--r--sources/plugins/pastefromword/lang/no.js10
-rw-r--r--sources/plugins/pastefromword/lang/pl.js10
-rw-r--r--sources/plugins/pastefromword/lang/pt-br.js10
-rw-r--r--sources/plugins/pastefromword/lang/pt.js10
-rw-r--r--sources/plugins/pastefromword/lang/ro.js10
-rw-r--r--sources/plugins/pastefromword/lang/ru.js10
-rw-r--r--sources/plugins/pastefromword/lang/si.js10
-rw-r--r--sources/plugins/pastefromword/lang/sk.js10
-rw-r--r--sources/plugins/pastefromword/lang/sl.js10
-rw-r--r--sources/plugins/pastefromword/lang/sq.js10
-rw-r--r--sources/plugins/pastefromword/lang/sr-latn.js10
-rw-r--r--sources/plugins/pastefromword/lang/sr.js10
-rw-r--r--sources/plugins/pastefromword/lang/sv.js10
-rw-r--r--sources/plugins/pastefromword/lang/th.js10
-rw-r--r--sources/plugins/pastefromword/lang/tr.js10
-rw-r--r--sources/plugins/pastefromword/lang/tt.js10
-rw-r--r--sources/plugins/pastefromword/lang/ug.js10
-rw-r--r--sources/plugins/pastefromword/lang/uk.js10
-rw-r--r--sources/plugins/pastefromword/lang/vi.js10
-rw-r--r--sources/plugins/pastefromword/lang/zh-cn.js10
-rw-r--r--sources/plugins/pastefromword/lang/zh.js10
-rw-r--r--sources/plugins/pastefromword/plugin.js149
72 files changed, 2060 insertions, 0 deletions
diff --git a/sources/plugins/pastefromword/filter/default.js b/sources/plugins/pastefromword/filter/default.js
new file mode 100644
index 00000000..0c97ef52
--- /dev/null
+++ b/sources/plugins/pastefromword/filter/default.js
@@ -0,0 +1,1251 @@
1/**
2 * @license Copyright (c) 2003-2015, CKSource - Frederico Knabben. All rights reserved.
3 * For licensing, see LICENSE.md or http://ckeditor.com/license
4 */
5
6( function() {
7 var fragmentPrototype = CKEDITOR.htmlParser.fragment.prototype,
8 elementPrototype = CKEDITOR.htmlParser.element.prototype;
9
10 fragmentPrototype.onlyChild = elementPrototype.onlyChild = function() {
11 var children = this.children,
12 count = children.length,
13 firstChild = ( count == 1 ) && children[ 0 ];
14 return firstChild || null;
15 };
16
17 elementPrototype.removeAnyChildWithName = function( tagName ) {
18 var children = this.children,
19 childs = [],
20 child;
21
22 for ( var i = 0; i < children.length; i++ ) {
23 child = children[ i ];
24 if ( !child.name )
25 continue;
26
27 if ( child.name == tagName ) {
28 childs.push( child );
29 children.splice( i--, 1 );
30 }
31 childs = childs.concat( child.removeAnyChildWithName( tagName ) );
32 }
33 return childs;
34 };
35
36 elementPrototype.getAncestor = function( tagNameRegex ) {
37 var parent = this.parent;
38 while ( parent && !( parent.name && parent.name.match( tagNameRegex ) ) )
39 parent = parent.parent;
40 return parent;
41 };
42
43 fragmentPrototype.firstChild = elementPrototype.firstChild = function( evaluator ) {
44 var child;
45
46 for ( var i = 0; i < this.children.length; i++ ) {
47 child = this.children[ i ];
48 if ( evaluator( child ) )
49 return child;
50 else if ( child.name ) {
51 child = child.firstChild( evaluator );
52 if ( child )
53 return child;
54 }
55 }
56
57 return null;
58 };
59
60 // Adding a (set) of styles to the element's 'style' attributes.
61 elementPrototype.addStyle = function( name, value, isPrepend ) {
62 var styleText,
63 addingStyleText = '';
64 // name/value pair.
65 if ( typeof value == 'string' )
66 addingStyleText += name + ':' + value + ';';
67 else {
68 // style literal.
69 if ( typeof name == 'object' ) {
70 for ( var style in name ) {
71 if ( name.hasOwnProperty( style ) )
72 addingStyleText += style + ':' + name[ style ] + ';';
73 }
74 }
75 // raw style text form.
76 else {
77 addingStyleText += name;
78 }
79
80 isPrepend = value;
81 }
82
83 if ( !this.attributes )
84 this.attributes = {};
85
86 styleText = this.attributes.style || '';
87
88 styleText = ( isPrepend ? [ addingStyleText, styleText ] : [ styleText, addingStyleText ] ).join( ';' );
89
90 this.attributes.style = styleText.replace( /^;+|;(?=;)/g, '' );
91 };
92
93 // Retrieve a style property value of the element.
94 elementPrototype.getStyle = function( name ) {
95 var styles = this.attributes.style;
96 if ( styles ) {
97 styles = CKEDITOR.tools.parseCssText( styles, 1 );
98 return styles[ name ];
99 }
100 };
101
102 /**
103 * Return the DTD-valid parent tag names of the specified one.
104 *
105 * @member CKEDITOR.dtd
106 * @param {String} tagName
107 * @returns {Object}
108 */
109 CKEDITOR.dtd.parentOf = function( tagName ) {
110 var result = {};
111 for ( var tag in this ) {
112 if ( tag.indexOf( '$' ) == -1 && this[ tag ][ tagName ] )
113 result[ tag ] = 1;
114 }
115 return result;
116 };
117
118 // 1. move consistent list item styles up to list root.
119 // 2. clear out unnecessary list item numbering.
120 function postProcessList( list ) {
121 var children = list.children,
122 child, attrs,
123 count = list.children.length,
124 match, mergeStyle,
125 styleTypeRegexp = /list-style-type:(.*?)(?:;|$)/,
126 stylesFilter = CKEDITOR.plugins.pastefromword.filters.stylesFilter;
127
128 attrs = list.attributes;
129 if ( styleTypeRegexp.exec( attrs.style ) )
130 return;
131
132 for ( var i = 0; i < count; i++ ) {
133 child = children[ i ];
134
135 if ( child.attributes.value && Number( child.attributes.value ) == i + 1 )
136 delete child.attributes.value;
137
138 match = styleTypeRegexp.exec( child.attributes.style );
139
140 if ( match ) {
141 if ( match[ 1 ] == mergeStyle || !mergeStyle )
142 mergeStyle = match[ 1 ];
143 else {
144 mergeStyle = null;
145 break;
146 }
147 }
148 }
149
150 if ( mergeStyle ) {
151 for ( i = 0; i < count; i++ ) {
152 attrs = children[ i ].attributes;
153 attrs.style && ( attrs.style = stylesFilter( [ [ 'list-style-type' ] ] )( attrs.style ) || '' );
154 }
155
156 list.addStyle( 'list-style-type', mergeStyle );
157 }
158 }
159
160 var emptyMarginRegex = /^(?:\b0[^\s]*\s*){1,4}$/; // e.g. 0px 0pt 0px
161 var romanLiternalPattern = '^m{0,4}(cm|cd|d?c{0,3})(xc|xl|l?x{0,3})(ix|iv|v?i{0,3})$',
162 lowerRomanLiteralRegex = new RegExp( romanLiternalPattern ),
163 upperRomanLiteralRegex = new RegExp( romanLiternalPattern.toUpperCase() );
164
165 var orderedPatterns = { 'decimal': /\d+/, 'lower-roman': lowerRomanLiteralRegex, 'upper-roman': upperRomanLiteralRegex, 'lower-alpha': /^[a-z]+$/, 'upper-alpha': /^[A-Z]+$/ },
166 unorderedPatterns = { 'disc': /[l\u00B7\u2002]/, 'circle': /[\u006F\u00D8]/, 'square': /[\u006E\u25C6]/ },
167 listMarkerPatterns = { 'ol': orderedPatterns, 'ul': unorderedPatterns },
168 romans = [ [ 1000, 'M' ], [ 900, 'CM' ], [ 500, 'D' ], [ 400, 'CD' ], [ 100, 'C' ], [ 90, 'XC' ], [ 50, 'L' ], [ 40, 'XL' ], [ 10, 'X' ], [ 9, 'IX' ], [ 5, 'V' ], [ 4, 'IV' ], [ 1, 'I' ] ],
169 alpahbets = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ';
170
171 // Convert roman numbering back to decimal.
172 function fromRoman( str ) {
173 str = str.toUpperCase();
174 var l = romans.length,
175 retVal = 0;
176 for ( var i = 0; i < l; ++i ) {
177 for ( var j = romans[ i ], k = j[ 1 ].length; str.substr( 0, k ) == j[ 1 ]; str = str.substr( k ) )
178 retVal += j[ 0 ];
179 }
180 return retVal;
181 }
182
183 // Convert alphabet numbering back to decimal.
184 function fromAlphabet( str ) {
185 str = str.toUpperCase();
186 var l = alpahbets.length,
187 retVal = 1;
188 for ( var x = 1; str.length > 0; x *= l ) {
189 retVal += alpahbets.indexOf( str.charAt( str.length - 1 ) ) * x;
190 str = str.substr( 0, str.length - 1 );
191 }
192 return retVal;
193 }
194
195 var listBaseIndent = 0,
196 previousListItemMargin = null,
197 previousListId;
198
199 var plugin = ( CKEDITOR.plugins.pastefromword = {
200 utils: {
201 // Create a <cke:listbullet> which indicate an list item type.
202 createListBulletMarker: function( bullet, bulletText ) {
203 var marker = new CKEDITOR.htmlParser.element( 'cke:listbullet' );
204 marker.attributes = { 'cke:listsymbol': bullet[ 0 ] };
205 marker.add( new CKEDITOR.htmlParser.text( bulletText ) );
206 return marker;
207 },
208
209 isListBulletIndicator: function( element ) {
210 var styleText = element.attributes && element.attributes.style;
211 if ( /mso-list\s*:\s*Ignore/i.test( styleText ) )
212 return true;
213 },
214
215 isContainingOnlySpaces: function( element ) {
216 var text;
217 return ( ( text = element.onlyChild() ) && ( /^(:?\s|&nbsp;)+$/ ).test( text.value ) );
218 },
219
220 resolveList: function( element ) {
221 // <cke:listbullet> indicate a list item.
222 var attrs = element.attributes,
223 listMarker;
224
225 if ( ( listMarker = element.removeAnyChildWithName( 'cke:listbullet' ) ) && listMarker.length && ( listMarker = listMarker[ 0 ] ) ) {
226 element.name = 'cke:li';
227
228 if ( attrs.style ) {
229 attrs.style = plugin.filters.stylesFilter( [
230 // Text-indent is not representing list item level any more.
231 [ 'text-indent' ],
232 [ 'line-height' ],
233 // First attempt is to resolve indent level from on a constant margin increment.
234 [ ( /^margin(:?-left)?$/ ), null, function( margin ) {
235 // Deal with component/short-hand form.
236 var values = margin.split( ' ' );
237 margin = CKEDITOR.tools.convertToPx( values[ 3 ] || values[ 1 ] || values[ 0 ] );
238
239 // Figure out the indent unit by checking the first time of incrementation.
240 if ( !listBaseIndent && previousListItemMargin !== null && margin > previousListItemMargin )
241 listBaseIndent = margin - previousListItemMargin;
242
243 previousListItemMargin = margin;
244
245 attrs[ 'cke:indent' ] = listBaseIndent && ( Math.ceil( margin / listBaseIndent ) + 1 ) || 1;
246 } ],
247 // The best situation: "mso-list:l0 level1 lfo2" tells the belonged list root, list item indentation, etc.
248 [ ( /^mso-list$/ ), null, function( val ) {
249 val = val.split( ' ' );
250 // Ignore values like "mso-list:Ignore". (FF #11976)
251 if ( val.length < 2 ) {
252 return;
253 }
254
255 var listId = Number( val[ 0 ].match( /\d+/ ) ),
256 indent = Number( val[ 1 ].match( /\d+/ ) );
257
258 if ( indent == 1 ) {
259 listId !== previousListId && ( attrs[ 'cke:reset' ] = 1 );
260 previousListId = listId;
261 }
262 attrs[ 'cke:indent' ] = indent;
263 } ]
264 ] )( attrs.style, element ) || '';
265 }
266
267 // First level list item might be presented without a margin.
268
269
270 // In case all above doesn't apply.
271 if ( !attrs[ 'cke:indent' ] ) {
272 previousListItemMargin = 0;
273 attrs[ 'cke:indent' ] = 1;
274 }
275
276 // Inherit attributes from bullet.
277 CKEDITOR.tools.extend( attrs, listMarker.attributes );
278 return true;
279 }
280 // Current list disconnected.
281 else {
282 previousListId = previousListItemMargin = listBaseIndent = null;
283 }
284
285 return false;
286 },
287
288 // Providing a shorthand style then retrieve one or more style component values.
289 getStyleComponents: ( function() {
290 var calculator = CKEDITOR.dom.element.createFromHtml( '<div style="position:absolute;left:-9999px;top:-9999px;"></div>', CKEDITOR.document );
291 CKEDITOR.document.getBody().append( calculator );
292
293 return function( name, styleValue, fetchList ) {
294 calculator.setStyle( name, styleValue );
295 var styles = {},
296 count = fetchList.length;
297 for ( var i = 0; i < count; i++ )
298 styles[ fetchList[ i ] ] = calculator.getStyle( fetchList[ i ] );
299
300 return styles;
301 };
302 } )(),
303
304 listDtdParents: CKEDITOR.dtd.parentOf( 'ol' )
305 },
306
307 filters: {
308 // Transform a normal list into flat list items only presentation.
309 // E.g. <ul><li>level1<ol><li>level2</li></ol></li> =>
310 // <cke:li cke:listtype="ul" cke:indent="1">level1</cke:li>
311 // <cke:li cke:listtype="ol" cke:indent="2">level2</cke:li>
312 flattenList: function( element, level ) {
313 level = typeof level == 'number' ? level : 1;
314
315 var attrs = element.attributes,
316 listStyleType;
317
318 // All list items are of the same type.
319 switch ( attrs.type ) {
320 case 'a':
321 listStyleType = 'lower-alpha';
322 break;
323 case '1':
324 listStyleType = 'decimal';
325 break;
326 // TODO: Support more list style type from MS-Word.
327 }
328
329 var children = element.children,
330 child;
331
332 for ( var i = 0; i < children.length; i++ ) {
333 child = children[ i ];
334
335 if ( child.name in CKEDITOR.dtd.$listItem ) {
336 var attributes = child.attributes,
337 listItemChildren = child.children,
338 count = listItemChildren.length,
339 first = listItemChildren[ 0 ],
340 last = listItemChildren[ count - 1 ];
341
342 // Converts <li><p style="_MSO_LIST_STYLES_">{...}</p></li> -> <li style="_MSO_LIST_STYLES_">{...}</li>.
343 // The above format is what we got when pasting from Word 2010 to IE11 and possibly some others.
344 // Existence of extra <p> tag that can be later recognized as list item (see #getRules.return.elements.p)
345 // creates incorrect and problematic structures similar to <cke:li><cke:li>{...}</cke:li></cke:li>. (#11376)
346 if ( first.attributes && first.attributes.style && first.attributes.style.indexOf( 'mso-list' ) > -1 ) {
347 child.attributes.style = first.attributes.style;
348 first.replaceWithChildren();
349 }
350
351 // Move out nested list.
352 if ( last.name in CKEDITOR.dtd.$list ) {
353 element.add( last, i + 1 );
354
355 // Remove the parent list item if it's just a holder.
356 if ( !--listItemChildren.length )
357 children.splice( i--, 1 );
358 }
359
360 child.name = 'cke:li';
361
362 // Inherit numbering from list root on the first list item.
363 attrs.start && !i && ( attributes.value = attrs.start );
364
365 plugin.filters.stylesFilter( [
366 [ 'tab-stops', null, function( val ) {
367 // val = [left|center|right|decimal] <value><unit> Source: W3C, WD-tabs-970117.
368 // In some cases the first word is missing - hence the square brackets.
369 var margin = val.match( /0$|\d+\.?\d*\w+/ );
370 margin && ( previousListItemMargin = CKEDITOR.tools.convertToPx( margin[ 0 ] ) );
371 } ],
372 ( level == 1 ? [ 'mso-list', null, function( val ) {
373 val = val.split( ' ' );
374 var listId = Number( val[ 0 ].match( /\d+/ ) );
375 listId !== previousListId && ( attributes[ 'cke:reset' ] = 1 );
376 previousListId = listId;
377 } ] : null )
378 ] )( attributes.style );
379
380 attributes[ 'cke:indent' ] = level;
381 attributes[ 'cke:listtype' ] = element.name;
382 attributes[ 'cke:list-style-type' ] = listStyleType;
383 }
384 // Flatten sub list.
385 else if ( child.name in CKEDITOR.dtd.$list ) {
386 // Absorb sub list children.
387 arguments.callee.apply( this, [ child, level + 1 ] );
388 children = children.slice( 0, i ).concat( child.children ).concat( children.slice( i + 1 ) );
389 element.children = [];
390 for ( var j = 0, num = children.length; j < num; j++ )
391 element.add( children[ j ] );
392
393 children = element.children;
394 }
395 }
396
397 delete element.name;
398
399 // We're loosing tag name here, signalize this element as a list.
400 attrs[ 'cke:list' ] = 1;
401 },
402
403 // Try to collect all list items among the children and establish one
404 // or more HTML list structures for them.
405 // @param element
406 assembleList: function( element ) {
407 var children = element.children,
408 child, listItem, // The current processing cke:li element.
409 listItemAttrs, listItemIndent, // Indent level of current list item.
410 lastIndent, lastListItem, // The previous one just been added to the list.
411 list, // Current staging list and it's parent list if any.
412 openedLists = [],
413 previousListStyleType, previousListType;
414
415 // Properties of the list item are to be resolved from the list bullet.
416 var bullet, listType, listStyleType, itemNumeric;
417
418 for ( var i = 0; i < children.length; i++ ) {
419 child = children[ i ];
420
421 if ( child.name == 'cke:li' ) {
422 child.name = 'li';
423 listItem = child;
424 listItemAttrs = listItem.attributes;
425 bullet = listItemAttrs[ 'cke:listsymbol' ];
426 bullet = bullet && bullet.match( /^(?:[(]?)([^\s]+?)([.)]?)$/ );
427 listType = listStyleType = itemNumeric = null;
428
429 if ( listItemAttrs[ 'cke:ignored' ] ) {
430 children.splice( i--, 1 );
431 continue;
432 }
433
434
435 // This's from a new list root.
436 listItemAttrs[ 'cke:reset' ] && ( list = lastIndent = lastListItem = null );
437
438 // List item indent level might come from a real list indentation or
439 // been resolved from a pseudo list item's margin value, even get
440 // no indentation at all.
441 listItemIndent = Number( listItemAttrs[ 'cke:indent' ] );
442
443 // We're moving out of the current list, cleaning up.
444 if ( listItemIndent != lastIndent )
445 previousListType = previousListStyleType = null;
446
447 // List type and item style are already resolved.
448 if ( !bullet ) {
449 listType = listItemAttrs[ 'cke:listtype' ] || 'ol';
450 listStyleType = listItemAttrs[ 'cke:list-style-type' ];
451 } else {
452 // Probably share the same list style type with previous list item,
453 // give it priority to avoid ambiguous between C(Alpha) and C.(Roman).
454 if ( previousListType && listMarkerPatterns[ previousListType ][ previousListStyleType ].test( bullet[ 1 ] ) ) {
455 listType = previousListType;
456 listStyleType = previousListStyleType;
457 } else {
458 for ( var type in listMarkerPatterns ) {
459 for ( var style in listMarkerPatterns[ type ] ) {
460 if ( listMarkerPatterns[ type ][ style ].test( bullet[ 1 ] ) ) {
461 // Small numbering has higher priority, when dealing with ambiguous
462 // between C(Alpha) and C.(Roman).
463 if ( type == 'ol' && ( /alpha|roman/ ).test( style ) ) {
464 var num = /roman/.test( style ) ? fromRoman( bullet[ 1 ] ) : fromAlphabet( bullet[ 1 ] );
465 if ( !itemNumeric || num < itemNumeric ) {
466 itemNumeric = num;
467 listType = type;
468 listStyleType = style;
469 }
470 } else {
471 listType = type;
472 listStyleType = style;
473 break;
474 }
475 }
476 }
477 }
478 }
479
480 // Simply use decimal/disc for the rest forms of unrepresentable
481 // numerals, e.g. Chinese..., but as long as there a second part
482 // included, it has a bigger chance of being a order list ;)
483 !listType && ( listType = bullet[ 2 ] ? 'ol' : 'ul' );
484 }
485
486 previousListType = listType;
487 previousListStyleType = listStyleType || ( listType == 'ol' ? 'decimal' : 'disc' );
488 if ( listStyleType && listStyleType != ( listType == 'ol' ? 'decimal' : 'disc' ) )
489 listItem.addStyle( 'list-style-type', listStyleType );
490
491 // Figure out start numbering.
492 if ( listType == 'ol' && bullet ) {
493 switch ( listStyleType ) {
494 case 'decimal':
495 itemNumeric = Number( bullet[ 1 ] );
496 break;
497 case 'lower-roman':
498 case 'upper-roman':
499 itemNumeric = fromRoman( bullet[ 1 ] );
500 break;
501 case 'lower-alpha':
502 case 'upper-alpha':
503 itemNumeric = fromAlphabet( bullet[ 1 ] );
504 break;
505 }
506
507 // Always create the numbering, swipe out unnecessary ones later.
508 listItem.attributes.value = itemNumeric;
509 }
510
511 // Start the list construction.
512 if ( !list ) {
513 openedLists.push( list = new CKEDITOR.htmlParser.element( listType ) );
514 list.add( listItem );
515 children[ i ] = list;
516 } else {
517 if ( listItemIndent > lastIndent ) {
518 openedLists.push( list = new CKEDITOR.htmlParser.element( listType ) );
519 list.add( listItem );
520 lastListItem.add( list );
521 } else if ( listItemIndent < lastIndent ) {
522 // There might be a negative gap between two list levels. (#4944)
523 var diff = lastIndent - listItemIndent,
524 parent;
525 while ( diff-- && ( parent = list.parent ) )
526 list = parent.parent;
527
528 list.add( listItem );
529 } else {
530 list.add( listItem );
531 }
532
533 children.splice( i--, 1 );
534 }
535
536 lastListItem = listItem;
537 lastIndent = listItemIndent;
538 } else if ( list ) {
539 list = lastIndent = lastListItem = null;
540 }
541 }
542
543 for ( i = 0; i < openedLists.length; i++ )
544 postProcessList( openedLists[ i ] );
545
546 list = lastIndent = lastListItem = previousListId = previousListItemMargin = listBaseIndent = null;
547 },
548
549 // A simple filter which always rejecting.
550 falsyFilter: function() {
551 return false;
552 },
553
554 // A filter dedicated on the 'style' attribute filtering, e.g. dropping/replacing style properties.
555 // @param styles {Array} in form of [ styleNameRegexp, styleValueRegexp,
556 // newStyleValue/newStyleGenerator, newStyleName ] where only the first
557 // parameter is mandatory.
558 // @param whitelist {Boolean} Whether the {@param styles} will be considered as a white-list.
559 stylesFilter: function( styles, whitelist ) {
560 return function( styleText, element ) {
561 var rules = [];
562 // html-encoded quote might be introduced by 'font-family'
563 // from MS-Word which confused the following regexp. e.g.
564 //'font-family: &quot;Lucida, Console&quot;'
565 ( styleText || '' ).replace( /&quot;/g, '"' ).replace( /\s*([^ :;]+)\s*:\s*([^;]+)\s*(?=;|$)/g, function( match, name, value ) {
566 name = name.toLowerCase();
567 name == 'font-family' && ( value = value.replace( /["']/g, '' ) );
568
569 var namePattern, valuePattern, newValue, newName;
570 for ( var i = 0; i < styles.length; i++ ) {
571 if ( styles[ i ] ) {
572 namePattern = styles[ i ][ 0 ];
573 valuePattern = styles[ i ][ 1 ];
574 newValue = styles[ i ][ 2 ];
575 newName = styles[ i ][ 3 ];
576
577 if ( name.match( namePattern ) && ( !valuePattern || value.match( valuePattern ) ) ) {
578 name = newName || name;
579 whitelist && ( newValue = newValue || value );
580
581 if ( typeof newValue == 'function' )
582 newValue = newValue( value, element, name );
583
584 // Return an couple indicate both name and value
585 // changed.
586 if ( newValue && newValue.push )
587 name = newValue[ 0 ], newValue = newValue[ 1 ];
588
589 if ( typeof newValue == 'string' )
590 rules.push( [ name, newValue ] );
591 return;
592 }
593 }
594 }
595
596 !whitelist && rules.push( [ name, value ] );
597
598 } );
599
600 for ( var i = 0; i < rules.length; i++ )
601 rules[ i ] = rules[ i ].join( ':' );
602 return rules.length ? ( rules.join( ';' ) + ';' ) : false;
603 };
604 },
605
606 // Migrate the element by decorate styles on it.
607 // @param styleDefinition
608 // @param variables
609 elementMigrateFilter: function( styleDefinition, variables ) {
610 return styleDefinition ? function( element ) {
611 var styleDef = variables ? new CKEDITOR.style( styleDefinition, variables )._.definition : styleDefinition;
612 element.name = styleDef.element;
613 CKEDITOR.tools.extend( element.attributes, CKEDITOR.tools.clone( styleDef.attributes ) );
614 element.addStyle( CKEDITOR.style.getStyleText( styleDef ) );
615 // Mark style classes as allowed so they will not be filtered out (#12256).
616 if ( styleDef.attributes && styleDef.attributes[ 'class' ] ) {
617 element.classWhiteList = ' ' + styleDef.attributes[ 'class' ] + ' ';
618 }
619 } : function() {};
620 },
621
622 // Migrate styles by creating a new nested stylish element.
623 // @param styleDefinition
624 styleMigrateFilter: function( styleDefinition, variableName ) {
625
626 var elementMigrateFilter = this.elementMigrateFilter;
627 return styleDefinition ? function( value, element ) {
628 // Build an stylish element first.
629 var styleElement = new CKEDITOR.htmlParser.element( null ),
630 variables = {};
631
632 variables[ variableName ] = value;
633 elementMigrateFilter( styleDefinition, variables )( styleElement );
634 // Place the new element inside the existing span.
635 styleElement.children = element.children;
636 element.children = [ styleElement ];
637
638 // #10285 - later on styleElement will replace element if element won't have any attributes.
639 // However, in some cases styleElement is identical to element and therefore should not be filtered
640 // to avoid inf loop. Unfortunately calling element.filterChildren() does not prevent from that (#10327).
641 // However, we can assume that we don't need to filter styleElement at all, so it is safe to replace
642 // its filter method.
643 styleElement.filter = function() {};
644 styleElement.parent = element;
645 } : function() {};
646 },
647
648 // A filter which remove cke-namespaced-attribute on
649 // all none-cke-namespaced elements.
650 // @param value
651 // @param element
652 bogusAttrFilter: function( value, element ) {
653 if ( element.name.indexOf( 'cke:' ) == -1 )
654 return false;
655 },
656
657 // A filter which will be used to apply inline css style according the stylesheet
658 // definition rules, is generated lazily when filtering.
659 applyStyleFilter: null
660
661 },
662
663 getRules: function( editor, filter ) {
664 var dtd = CKEDITOR.dtd,
665 blockLike = CKEDITOR.tools.extend( {}, dtd.$block, dtd.$listItem, dtd.$tableContent ),
666 config = editor.config,
667 filters = this.filters,
668 falsyFilter = filters.falsyFilter,
669 stylesFilter = filters.stylesFilter,
670 elementMigrateFilter = filters.elementMigrateFilter,
671 styleMigrateFilter = CKEDITOR.tools.bind( this.filters.styleMigrateFilter, this.filters ),
672 createListBulletMarker = this.utils.createListBulletMarker,
673 flattenList = filters.flattenList,
674 assembleList = filters.assembleList,
675 isListBulletIndicator = this.utils.isListBulletIndicator,
676 containsNothingButSpaces = this.utils.isContainingOnlySpaces,
677 resolveListItem = this.utils.resolveList,
678 convertToPx = function( value ) {
679 value = CKEDITOR.tools.convertToPx( value );
680 return isNaN( value ) ? value : value + 'px';
681 },
682 getStyleComponents = this.utils.getStyleComponents,
683 listDtdParents = this.utils.listDtdParents,
684 removeFontStyles = config.pasteFromWordRemoveFontStyles !== false,
685 removeStyles = config.pasteFromWordRemoveStyles !== false;
686
687 return {
688
689 elementNames: [
690 // Remove script, meta and link elements.
691 [ ( /meta|link|script/ ), '' ]
692 ],
693
694 root: function( element ) {
695 element.filterChildren( filter );
696 assembleList( element );
697 },
698
699 elements: {
700 '^': function( element ) {
701 // Transform CSS style declaration to inline style.
702 var applyStyleFilter;
703 if ( CKEDITOR.env.gecko && ( applyStyleFilter = filters.applyStyleFilter ) )
704 applyStyleFilter( element );
705 },
706
707 $: function( element ) {
708 var tagName = element.name || '',
709 attrs = element.attributes;
710
711 // Convert length unit of width/height on blocks to
712 // a more editor-friendly way (px).
713 if ( tagName in blockLike && attrs.style )
714 attrs.style = stylesFilter( [ [ ( /^(:?width|height)$/ ), null, convertToPx ] ] )( attrs.style ) || '';
715
716 // Processing headings.
717 if ( tagName.match( /h\d/ ) ) {
718 element.filterChildren( filter );
719 // Is the heading actually a list item?
720 if ( resolveListItem( element ) )
721 return;
722
723 // Adapt heading styles to editor's convention.
724 elementMigrateFilter( config[ 'format_' + tagName ] )( element );
725 }
726 // Remove inline elements which contain only empty spaces.
727 else if ( tagName in dtd.$inline ) {
728 element.filterChildren( filter );
729 if ( containsNothingButSpaces( element ) )
730 delete element.name;
731 }
732 // Remove element with ms-office namespace,
733 // with it's content preserved, e.g. 'o:p'.
734 else if ( tagName.indexOf( ':' ) != -1 && tagName.indexOf( 'cke' ) == -1 ) {
735 element.filterChildren( filter );
736
737 // Restore image real link from vml.
738 if ( tagName == 'v:imagedata' ) {
739 var href = element.attributes[ 'o:href' ];
740 if ( href )
741 element.attributes.src = href;
742 element.name = 'img';
743 return;
744 }
745 delete element.name;
746 }
747
748 // Assembling list items into a whole list.
749 if ( tagName in listDtdParents ) {
750 element.filterChildren( filter );
751 assembleList( element );
752 }
753 },
754
755 // We'll drop any style sheet, but Firefox conclude
756 // certain styles in a single style element, which are
757 // required to be changed into inline ones.
758 'style': function( element ) {
759 if ( CKEDITOR.env.gecko ) {
760 // Grab only the style definition section.
761 var styleDefSection = element.onlyChild().value.match( /\/\* Style Definitions \*\/([\s\S]*?)\/\*/ ),
762 styleDefText = styleDefSection && styleDefSection[ 1 ],
763 rules = {}; // Storing the parsed result.
764
765 if ( styleDefText ) {
766 styleDefText
767 // Remove line-breaks.
768 .replace( /[\n\r]/g, '' )
769 // Extract selectors and style properties.
770 .replace( /(.+?)\{(.+?)\}/g, function( rule, selectors, styleBlock ) {
771 selectors = selectors.split( ',' );
772 var length = selectors.length;
773 for ( var i = 0; i < length; i++ ) {
774 // Assume MS-Word mostly generate only simple
775 // selector( [Type selector][Class selector]).
776 CKEDITOR.tools.trim( selectors[ i ] ).replace( /^(\w+)(\.[\w-]+)?$/g, function( match, tagName, className ) {
777 tagName = tagName || '*';
778 className = className.substring( 1, className.length );
779
780 // Reject MS-Word Normal styles.
781 if ( className.match( /MsoNormal/ ) )
782 return;
783
784 if ( !rules[ tagName ] )
785 rules[ tagName ] = {};
786 if ( className )
787 rules[ tagName ][ className ] = styleBlock;
788 else
789 rules[ tagName ] = styleBlock;
790 } );
791 }
792 } );
793
794 filters.applyStyleFilter = function( element ) {
795 var name = rules[ '*' ] ? '*' : element.name,
796 className = element.attributes && element.attributes[ 'class' ],
797 style;
798 if ( name in rules ) {
799 style = rules[ name ];
800 if ( typeof style == 'object' )
801 style = style[ className ];
802 // Maintain style rules priorities.
803 style && element.addStyle( style, true );
804 }
805 };
806 }
807 }
808 return false;
809 },
810
811 'p': function( element ) {
812 // A a fall-back approach to resolve list item in browsers
813 // that doesn't include "mso-list:Ignore" on list bullets,
814 // note it's not perfect as not all list style (e.g. "heading list") is shipped
815 // with this pattern. (#6662)
816 if ( ( /MsoListParagraph/i ).exec( element.attributes[ 'class' ] ) ||
817 ( element.getStyle( 'mso-list' ) && !element.getStyle( 'mso-list' ).match( /^(none|skip)$/i ) ) ) {
818 var bulletText = element.firstChild( function( node ) {
819 return node.type == CKEDITOR.NODE_TEXT && !containsNothingButSpaces( node.parent );
820 } );
821
822 var bullet = bulletText && bulletText.parent;
823 if ( bullet )
824 bullet.addStyle( 'mso-list', 'Ignore' );
825
826 }
827
828 element.filterChildren( filter );
829
830 // Is the paragraph actually a list item?
831 if ( resolveListItem( element ) )
832 return;
833
834 // Adapt paragraph formatting to editor's convention
835 // according to enter-mode.
836 if ( config.enterMode == CKEDITOR.ENTER_BR ) {
837 // We suffer from attribute/style lost in this situation.
838 delete element.name;
839 element.add( new CKEDITOR.htmlParser.element( 'br' ) );
840 } else {
841 elementMigrateFilter( config[ 'format_' + ( config.enterMode == CKEDITOR.ENTER_P ? 'p' : 'div' ) ] )( element );
842 }
843 },
844
845 'div': function( element ) {
846 // Aligned table with no text surrounded is represented by a wrapper div, from which
847 // table cells inherit as text-align styles, which is wrong.
848 // Instead we use a clear-float div after the table to properly achieve the same layout.
849 var singleChild = element.onlyChild();
850 if ( singleChild && singleChild.name == 'table' ) {
851 var attrs = element.attributes;
852 singleChild.attributes = CKEDITOR.tools.extend( singleChild.attributes, attrs );
853 attrs.style && singleChild.addStyle( attrs.style );
854
855 var clearFloatDiv = new CKEDITOR.htmlParser.element( 'div' );
856 clearFloatDiv.addStyle( 'clear', 'both' );
857 element.add( clearFloatDiv );
858 delete element.name;
859 }
860 },
861
862 'td': function( element ) {
863 // 'td' in 'thead' is actually <th>.
864 if ( element.getAncestor( 'thead' ) )
865 element.name = 'th';
866 },
867
868 // MS-Word sometimes present list as a mixing of normal list
869 // and pseudo-list, normalize the previous ones into pseudo form.
870 'ol': flattenList,
871 'ul': flattenList,
872 'dl': flattenList,
873
874 'font': function( element ) {
875 // Drop the font tag if it comes from list bullet text.
876 if ( isListBulletIndicator( element.parent ) ) {
877 delete element.name;
878 return;
879 }
880
881 element.filterChildren( filter );
882
883 var attrs = element.attributes,
884 styleText = attrs.style,
885 parent = element.parent;
886
887 if ( parent.name == 'font' ) { // Merge nested <font> tags.
888 CKEDITOR.tools.extend( parent.attributes, element.attributes );
889 styleText && parent.addStyle( styleText );
890 delete element.name;
891 }
892 // Convert the merged into a span with all attributes preserved.
893 else {
894 // Use array to avoid string concatenation and get rid of problems with trailing ";" (#12243).
895 styleText = ( styleText || '' ).split( ';' );
896
897 // IE's having those deprecated attributes, normalize them.
898 if ( attrs.color ) {
899 if ( attrs.color != '#000000' )
900 styleText.push( 'color:' + attrs.color );
901 delete attrs.color;
902 }
903 if ( attrs.face ) {
904 styleText.push( 'font-family:' + attrs.face );
905 delete attrs.face;
906 }
907 // TODO: Mapping size in ranges of xx-small,
908 // x-small, small, medium, large, x-large, xx-large.
909 if ( attrs.size ) {
910 styleText.push( 'font-size:' +
911 ( attrs.size > 3 ? 'large' : ( attrs.size < 3 ? 'small' : 'medium' ) ) );
912 delete attrs.size;
913 }
914
915 element.name = 'span';
916 element.addStyle( styleText.join( ';' ) );
917 }
918 },
919
920 'span': function( element ) {
921 // Remove the span if it comes from list bullet text.
922 if ( isListBulletIndicator( element.parent ) )
923 return false;
924
925 element.filterChildren( filter );
926 if ( containsNothingButSpaces( element ) ) {
927 delete element.name;
928 return null;
929 }
930
931 // List item bullet type is supposed to be indicated by
932 // the text of a span with style 'mso-list : Ignore' or an image.
933 if ( isListBulletIndicator( element ) ) {
934 var listSymbolNode = element.firstChild( function( node ) {
935 return node.value || node.name == 'img';
936 } );
937
938 var listSymbol = listSymbolNode && ( listSymbolNode.value || 'l.' ),
939 listType = listSymbol && listSymbol.match( /^(?:[(]?)([^\s]+?)([.)]?)$/ );
940
941 if ( listType ) {
942 var marker = createListBulletMarker( listType, listSymbol );
943 // Some non-existed list items might be carried by an inconsequential list, indicate by "mso-hide:all/display:none",
944 // those are to be removed later, now mark it with "cke:ignored".
945 var ancestor = element.getAncestor( 'span' );
946 if ( ancestor && ( / mso-hide:\s*all|display:\s*none / ).test( ancestor.attributes.style ) )
947 marker.attributes[ 'cke:ignored' ] = 1;
948 return marker;
949 }
950 }
951
952 // Update the src attribute of image element with href.
953 var attrs = element.attributes,
954 styleText = attrs && attrs.style;
955
956 // Assume MS-Word mostly carry font related styles on <span>,
957 // adapting them to editor's convention.
958 if ( styleText ) {
959 attrs.style = stylesFilter( [
960 // Drop 'inline-height' style which make lines overlapping.
961 [ 'line-height' ],
962 [ ( /^font-family$/ ), null, !removeFontStyles ? styleMigrateFilter( config.font_style, 'family' ) : null ],
963 [ ( /^font-size$/ ), null, !removeFontStyles ? styleMigrateFilter( config.fontSize_style, 'size' ) : null ],
964 [ ( /^color$/ ), null, !removeFontStyles ? styleMigrateFilter( config.colorButton_foreStyle, 'color' ) : null ],
965 [ ( /^background-color$/ ), null, !removeFontStyles ? styleMigrateFilter( config.colorButton_backStyle, 'color' ) : null ]
966 ] )( styleText, element ) || '';
967 }
968
969 if ( !attrs.style )
970 delete attrs.style;
971
972 if ( CKEDITOR.tools.isEmpty( attrs ) )
973 delete element.name;
974
975 return null;
976 },
977
978 // Migrate basic style formats to editor configured ones.
979 b: elementMigrateFilter( config.coreStyles_bold ),
980 i: elementMigrateFilter( config.coreStyles_italic ),
981 u: elementMigrateFilter( config.coreStyles_underline ),
982 s: elementMigrateFilter( config.coreStyles_strike ),
983 sup: elementMigrateFilter( config.coreStyles_superscript ),
984 sub: elementMigrateFilter( config.coreStyles_subscript ),
985
986 // Remove full paths from links to anchors.
987 a: function( element ) {
988 var attrs = element.attributes;
989
990 if ( attrs.name && attrs.name.match( /ole_link\d+/i ) ) {
991 delete element.name;
992 return;
993 }
994
995 if ( attrs.href && attrs.href.match( /^file:\/\/\/[\S]+#/i ) )
996 attrs.href = attrs.href.replace( /^file:\/\/\/[^#]+/i, '' );
997 },
998
999 'cke:listbullet': function( element ) {
1000 if ( element.getAncestor( /h\d/ ) && !config.pasteFromWordNumberedHeadingToList )
1001 delete element.name;
1002 }
1003 },
1004
1005 attributeNames: [
1006 // Remove onmouseover and onmouseout events (from MS Word comments effect)
1007 [ ( /^onmouse(:?out|over)/ ), '' ],
1008 // Onload on image element.
1009 [ ( /^onload$/ ), '' ],
1010 // Remove office and vml attribute from elements.
1011 [ ( /(?:v|o):\w+/ ), '' ],
1012 // Remove lang/language attributes.
1013 [ ( /^lang/ ), '' ]
1014 ],
1015
1016 attributes: {
1017 'style': stylesFilter( removeStyles ?
1018 // Provide a white-list of styles that we preserve, those should
1019 // be the ones that could later be altered with editor tools.
1020 [
1021 // Leave list-style-type
1022 [ ( /^list-style-type$/ ), null ],
1023
1024 // Preserve margin-left/right which used as default indent style in the editor.
1025 [ ( /^margin$|^margin-(?!bottom|top)/ ), null, function( value, element, name ) {
1026 if ( element.name in { p: 1, div: 1 } ) {
1027 var indentStyleName = config.contentsLangDirection == 'ltr' ? 'margin-left' : 'margin-right';
1028
1029 // Extract component value from 'margin' shorthand.
1030 if ( name == 'margin' )
1031 value = getStyleComponents( name, value, [ indentStyleName ] )[ indentStyleName ];
1032 else if ( name != indentStyleName )
1033 return null;
1034
1035 if ( value && !emptyMarginRegex.test( value ) )
1036 return [ indentStyleName, value ];
1037 }
1038
1039 return null;
1040 } ],
1041
1042 // Preserve clear float style.
1043 [ ( /^clear$/ ) ],
1044
1045 [ ( /^border.*|margin.*|vertical-align|float$/ ), null, function( value, element ) {
1046 if ( element.name == 'img' )
1047 return value;
1048 } ],
1049
1050 [ ( /^width|height$/ ), null, function( value, element ) {
1051 if ( element.name in { table: 1, td: 1, th: 1, img: 1 } )
1052 return value;
1053 } ]
1054 ] :
1055 // Otherwise provide a black-list of styles that we remove.
1056 [
1057 [ ( /^mso-/ ) ],
1058 // Fixing color values.
1059 [ ( /-color$/ ), null, function( value ) {
1060 if ( value == 'transparent' )
1061 return false;
1062 if ( CKEDITOR.env.gecko )
1063 return value.replace( /-moz-use-text-color/g, 'transparent' );
1064 } ],
1065 // Remove empty margin values, e.g. 0.00001pt 0em 0pt
1066 [ ( /^margin$/ ), emptyMarginRegex ],
1067 [ 'text-indent', '0cm' ],
1068 [ 'page-break-before' ],
1069 [ 'tab-stops' ],
1070 [ 'display', 'none' ],
1071 removeFontStyles ? [ ( /font-?/ ) ] : null
1072 ], removeStyles ),
1073
1074 // Prefer width styles over 'width' attributes.
1075 'width': function( value, element ) {
1076 if ( element.name in dtd.$tableContent )
1077 return false;
1078 },
1079 // Prefer border styles over table 'border' attributes.
1080 'border': function( value, element ) {
1081 if ( element.name in dtd.$tableContent )
1082 return false;
1083 },
1084
1085 // Only Firefox carry style sheet from MS-Word, which
1086 // will be applied by us manually. For other browsers
1087 // the css className is useless.
1088 // We need to keep classes added as a style (#12256).
1089 'class': function( value, element ) {
1090 if ( element.classWhiteList && element.classWhiteList.indexOf( ' ' + value + ' ' ) != -1 ) {
1091 return value;
1092 }
1093 return false;
1094 },
1095
1096 // MS-Word always generate 'background-color' along with 'bgcolor',
1097 // simply drop the deprecated attributes.
1098 'bgcolor': falsyFilter,
1099
1100 // Deprecate 'valign' attribute in favor of 'vertical-align'.
1101 'valign': removeStyles ? falsyFilter : function( value, element ) {
1102 element.addStyle( 'vertical-align', value );
1103 return false;
1104 }
1105 },
1106
1107 // Fore none-IE, some useful data might be buried under these IE-conditional
1108 // comments where RegExp were the right approach to dig them out where usual approach
1109 // is transform it into a fake element node which hold the desired data.
1110 comment: !CKEDITOR.env.ie ? function( value, node ) {
1111 var imageInfo = value.match( /<img.*?>/ ),
1112 listInfo = value.match( /^\[if !supportLists\]([\s\S]*?)\[endif\]$/ );
1113
1114 // Seek for list bullet indicator.
1115 if ( listInfo ) {
1116 // Bullet symbol could be either text or an image.
1117 var listSymbol = listInfo[ 1 ] || ( imageInfo && 'l.' ),
1118 listType = listSymbol && listSymbol.match( />(?:[(]?)([^\s]+?)([.)]?)</ );
1119 return createListBulletMarker( listType, listSymbol );
1120 }
1121
1122 // Reveal the <img> element in conditional comments for Firefox.
1123 if ( CKEDITOR.env.gecko && imageInfo ) {
1124 var img = CKEDITOR.htmlParser.fragment.fromHtml( imageInfo[ 0 ] ).children[ 0 ],
1125 previousComment = node.previous,
1126 // Try to dig the real image link from vml markup from previous comment text.
1127 imgSrcInfo = previousComment && previousComment.value.match( /<v:imagedata[^>]*o:href=['"](.*?)['"]/ ),
1128 imgSrc = imgSrcInfo && imgSrcInfo[ 1 ];
1129
1130 // Is there a real 'src' url to be used?
1131 imgSrc && ( img.attributes.src = imgSrc );
1132 return img;
1133 }
1134
1135 return false;
1136 } : falsyFilter
1137 };
1138 }
1139 } );
1140
1141 // The paste processor here is just a reduced copy of html data processor.
1142 var pasteProcessor = function() {
1143 this.dataFilter = new CKEDITOR.htmlParser.filter();
1144 };
1145
1146 pasteProcessor.prototype = {
1147 toHtml: function( data ) {
1148 var fragment = CKEDITOR.htmlParser.fragment.fromHtml( data ),
1149 writer = new CKEDITOR.htmlParser.basicWriter();
1150
1151 fragment.writeHtml( writer, this.dataFilter );
1152 return writer.getHtml( true );
1153 }
1154 };
1155
1156 CKEDITOR.cleanWord = function( data, editor ) {
1157 // We get <![if !supportLists]> and <![endif]> when we started using `dataTransfer` instead of pasteBin, so we need to
1158 // change <![if !supportLists]> to <!--[if !supportLists]--> and <![endif]> to <!--[endif]-->.
1159 data = data.replace( /<!\[([^\]]*?)\]>/g, '<!--[$1]-->' );
1160
1161 // Firefox will be confused by those downlevel-revealed IE conditional
1162 // comments, fixing them first( convert it to upperlevel-revealed one ).
1163 // e.g. <![if !vml]>...<![endif]>
1164 if ( CKEDITOR.env.gecko )
1165 data = data.replace( /(<!--\[if[^<]*?\])-->([\S\s]*?)<!--(\[endif\]-->)/gi, '$1$2$3' );
1166
1167 // #9456 - Webkit doesn't wrap list number with span, which is crucial for filter to recognize list.
1168 //
1169 // <p class="MsoListParagraphCxSpLast" style="text-indent:-18.0pt;mso-list:l0 level1 lfo2">
1170 // <!--[if !supportLists]-->
1171 // 3.<span style="font-size: 7pt; line-height: normal; font-family: 'Times New Roman';">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span>
1172 // <!--[endif]-->Test3<o:p></o:p>
1173 // </p>
1174 //
1175 // Transform to:
1176 //
1177 // <p class="MsoListParagraphCxSpLast" style="text-indent:-18.0pt;mso-list:l0 level1 lfo2">
1178 // <!--[if !supportLists]-->
1179 // <span>
1180 // 3.<span style="font-size: 7pt; line-height: normal; font-family: 'Times New Roman';">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span>
1181 // </span>
1182 // <!--[endif]-->Test3<o:p></o:p>
1183 // </p>
1184 if ( CKEDITOR.env.webkit )
1185 data = data.replace( /(class="MsoListParagraph[^>]+><!--\[if !supportLists\]-->)([^<]+<span[^<]+<\/span>)(<!--\[endif\]-->)/gi, '$1<span>$2</span>$3' );
1186
1187 var dataProcessor = new pasteProcessor(),
1188 dataFilter = dataProcessor.dataFilter;
1189
1190 // These rules will have higher priorities than default ones.
1191 dataFilter.addRules( CKEDITOR.plugins.pastefromword.getRules( editor, dataFilter ) );
1192
1193 // Allow extending data filter rules.
1194 editor.fire( 'beforeCleanWord', { filter: dataFilter } );
1195
1196 try {
1197 data = dataProcessor.toHtml( data );
1198 } catch ( e ) {
1199 editor.showNotification( editor.lang.pastefromword.error );
1200 }
1201
1202 // Below post processing those things that are unable to delivered by filter rules.
1203
1204 // Remove 'cke' namespaced attribute used in filter rules as marker.
1205 data = data.replace( /cke:.*?".*?"/g, '' );
1206
1207 // Remove empty style attribute.
1208 data = data.replace( /style=""/g, '' );
1209
1210 // Remove the dummy spans ( having no inline style ).
1211 data = data.replace( /<span>/g, '' );
1212
1213 return data;
1214 };
1215} )();
1216
1217/**
1218 * Whether to ignore all font related formatting styles, including:
1219 *
1220 * * font size;
1221 * * font family;
1222 * * font foreground/background color.
1223 *
1224 * config.pasteFromWordRemoveFontStyles = false;
1225 *
1226 * @since 3.1
1227 * @cfg {Boolean} [pasteFromWordRemoveFontStyles=true]
1228 * @member CKEDITOR.config
1229 */
1230
1231/**
1232 * Whether to transform MS Word outline numbered headings into lists.
1233 *
1234 * config.pasteFromWordNumberedHeadingToList = true;
1235 *
1236 * @since 3.1
1237 * @cfg {Boolean} [pasteFromWordNumberedHeadingToList=false]
1238 * @member CKEDITOR.config
1239 */
1240
1241/**
1242 * Whether to remove element styles that can't be managed with the editor. Note
1243 * that this doesn't handle the font specific styles, which depends on the
1244 * {@link #pasteFromWordRemoveFontStyles} setting instead.
1245 *
1246 * config.pasteFromWordRemoveStyles = false;
1247 *
1248 * @since 3.1
1249 * @cfg {Boolean} [pasteFromWordRemoveStyles=true]
1250 * @member CKEDITOR.config
1251 */
diff --git a/sources/plugins/pastefromword/icons/hidpi/pastefromword-rtl.png b/sources/plugins/pastefromword/icons/hidpi/pastefromword-rtl.png
new file mode 100644
index 00000000..142bd569
--- /dev/null
+++ b/sources/plugins/pastefromword/icons/hidpi/pastefromword-rtl.png
Binary files differ
diff --git a/sources/plugins/pastefromword/icons/hidpi/pastefromword.png b/sources/plugins/pastefromword/icons/hidpi/pastefromword.png
new file mode 100644
index 00000000..ac043cdd
--- /dev/null
+++ b/sources/plugins/pastefromword/icons/hidpi/pastefromword.png
Binary files differ
diff --git a/sources/plugins/pastefromword/icons/pastefromword-rtl.png b/sources/plugins/pastefromword/icons/pastefromword-rtl.png
new file mode 100644
index 00000000..7b69c555
--- /dev/null
+++ b/sources/plugins/pastefromword/icons/pastefromword-rtl.png
Binary files differ
diff --git a/sources/plugins/pastefromword/icons/pastefromword.png b/sources/plugins/pastefromword/icons/pastefromword.png
new file mode 100644
index 00000000..61a0ae43
--- /dev/null
+++ b/sources/plugins/pastefromword/icons/pastefromword.png
Binary files differ
diff --git a/sources/plugins/pastefromword/lang/af.js b/sources/plugins/pastefromword/lang/af.js
new file mode 100644
index 00000000..0e047b32
--- /dev/null
+++ b/sources/plugins/pastefromword/lang/af.js
@@ -0,0 +1,10 @@
1/*
2Copyright (c) 2003-2015, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'pastefromword', 'af', {
6 confirmCleanup: 'Die teks wat u wil plak lyk asof dit uit Word gekopiëer is. Wil u dit eers skoonmaak voordat dit geplak word?',
7 error: 'Die geplakte teks kon nie skoongemaak word nie, weens \'n interne fout',
8 title: 'Plak vanuit Word',
9 toolbar: 'Plak vanuit Word'
10} );
diff --git a/sources/plugins/pastefromword/lang/ar.js b/sources/plugins/pastefromword/lang/ar.js
new file mode 100644
index 00000000..37d6c35d
--- /dev/null
+++ b/sources/plugins/pastefromword/lang/ar.js
@@ -0,0 +1,10 @@
1/*
2Copyright (c) 2003-2015, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'pastefromword', 'ar', {
6 confirmCleanup: 'يبدو أن النص المراد لصقه منسوخ من برنامج وورد. هل تود تنظيفه قبل الشروع في عملية اللصق؟',
7 error: 'لم يتم مسح المعلومات الملصقة لخلل داخلي',
8 title: 'لصق من وورد',
9 toolbar: 'لصق من وورد'
10} );
diff --git a/sources/plugins/pastefromword/lang/bg.js b/sources/plugins/pastefromword/lang/bg.js
new file mode 100644
index 00000000..eb4a6fab
--- /dev/null
+++ b/sources/plugins/pastefromword/lang/bg.js
@@ -0,0 +1,10 @@
1/*
2Copyright (c) 2003-2015, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'pastefromword', 'bg', {
6 confirmCleanup: 'The text you want to paste seems to be copied from Word. Do you want to clean it before pasting?', // MISSING
7 error: 'It was not possible to clean up the pasted data due to an internal error', // MISSING
8 title: 'Вмъкни от MS Word',
9 toolbar: 'Вмъкни от MS Word'
10} );
diff --git a/sources/plugins/pastefromword/lang/bn.js b/sources/plugins/pastefromword/lang/bn.js
new file mode 100644
index 00000000..9fedb959
--- /dev/null
+++ b/sources/plugins/pastefromword/lang/bn.js
@@ -0,0 +1,10 @@
1/*
2Copyright (c) 2003-2015, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'pastefromword', 'bn', {
6 confirmCleanup: 'The text you want to paste seems to be copied from Word. Do you want to clean it before pasting?', // MISSING
7 error: 'It was not possible to clean up the pasted data due to an internal error', // MISSING
8 title: 'পেস্ট (শব্দ)',
9 toolbar: 'পেস্ট (শব্দ)'
10} );
diff --git a/sources/plugins/pastefromword/lang/bs.js b/sources/plugins/pastefromword/lang/bs.js
new file mode 100644
index 00000000..2b0528a7
--- /dev/null
+++ b/sources/plugins/pastefromword/lang/bs.js
@@ -0,0 +1,10 @@
1/*
2Copyright (c) 2003-2015, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'pastefromword', 'bs', {
6 confirmCleanup: 'The text you want to paste seems to be copied from Word. Do you want to clean it before pasting?', // MISSING
7 error: 'It was not possible to clean up the pasted data due to an internal error', // MISSING
8 title: 'Zalijepi iz Word-a',
9 toolbar: 'Zalijepi iz Word-a'
10} );
diff --git a/sources/plugins/pastefromword/lang/ca.js b/sources/plugins/pastefromword/lang/ca.js
new file mode 100644
index 00000000..b2da5cd8
--- /dev/null
+++ b/sources/plugins/pastefromword/lang/ca.js
@@ -0,0 +1,10 @@
1/*
2Copyright (c) 2003-2015, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'pastefromword', 'ca', {
6 confirmCleanup: 'El text que voleu enganxar sembla provenir de Word. Voleu netejar aquest text abans que sigui enganxat?',
7 error: 'No ha estat possible netejar les dades enganxades degut a un error intern',
8 title: 'Enganxa des del Word',
9 toolbar: 'Enganxa des del Word'
10} );
diff --git a/sources/plugins/pastefromword/lang/cs.js b/sources/plugins/pastefromword/lang/cs.js
new file mode 100644
index 00000000..5cb7c174
--- /dev/null
+++ b/sources/plugins/pastefromword/lang/cs.js
@@ -0,0 +1,10 @@
1/*
2Copyright (c) 2003-2015, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'pastefromword', 'cs', {
6 confirmCleanup: 'Jak je vidět, vkládaný text je kopírován z Wordu. Chcete jej před vložením vyčistit?',
7 error: 'Z důvodu vnitřní chyby nebylo možné provést vyčištění vkládaného textu.',
8 title: 'Vložit z Wordu',
9 toolbar: 'Vložit z Wordu'
10} );
diff --git a/sources/plugins/pastefromword/lang/cy.js b/sources/plugins/pastefromword/lang/cy.js
new file mode 100644
index 00000000..75fe3662
--- /dev/null
+++ b/sources/plugins/pastefromword/lang/cy.js
@@ -0,0 +1,10 @@
1/*
2Copyright (c) 2003-2015, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'pastefromword', 'cy', {
6 confirmCleanup: 'Mae\'r testun rydych chi am ludo wedi\'i gopïo o Word. Ydych chi am ei lanhau cyn ei ludo?',
7 error: 'Doedd dim modd glanhau y data a ludwyd oherwydd gwall mewnol',
8 title: 'Gludo o Word',
9 toolbar: 'Gludo o Word'
10} );
diff --git a/sources/plugins/pastefromword/lang/da.js b/sources/plugins/pastefromword/lang/da.js
new file mode 100644
index 00000000..81b26307
--- /dev/null
+++ b/sources/plugins/pastefromword/lang/da.js
@@ -0,0 +1,10 @@
1/*
2Copyright (c) 2003-2015, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'pastefromword', 'da', {
6 confirmCleanup: 'Den tekst du forsøger at indsætte ser ud til at komme fra Word. Vil du rense teksten før den indsættes?',
7 error: 'Det var ikke muligt at fjerne formatteringen på den indsatte tekst grundet en intern fejl',
8 title: 'Indsæt fra Word',
9 toolbar: 'Indsæt fra Word'
10} );
diff --git a/sources/plugins/pastefromword/lang/de.js b/sources/plugins/pastefromword/lang/de.js
new file mode 100644
index 00000000..836b7d74
--- /dev/null
+++ b/sources/plugins/pastefromword/lang/de.js
@@ -0,0 +1,10 @@
1/*
2Copyright (c) 2003-2015, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'pastefromword', 'de', {
6 confirmCleanup: 'Der Text, den Sie einfügen möchten, scheint aus MS-Word kopiert zu sein. Möchten Sie ihn zuvor bereinigen lassen?',
7 error: 'Aufgrund eines internen Fehlers war es nicht möglich die eingefügten Daten zu bereinigen',
8 title: 'Aus Word einfügen',
9 toolbar: 'Aus Word einfügen'
10} );
diff --git a/sources/plugins/pastefromword/lang/el.js b/sources/plugins/pastefromword/lang/el.js
new file mode 100644
index 00000000..96d1e878
--- /dev/null
+++ b/sources/plugins/pastefromword/lang/el.js
@@ -0,0 +1,10 @@
1/*
2Copyright (c) 2003-2015, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'pastefromword', 'el', {
6 confirmCleanup: 'Το κείμενο που επικολλάται φαίνεται να είναι αντιγραμμένο από το Word. Μήπως θα θέλατε να καθαριστεί προτού επικολληθεί;',
7 error: 'Δεν ήταν δυνατό να καθαριστούν τα δεδομένα λόγω ενός εσωτερικού σφάλματος',
8 title: 'Επικόλληση από το Word',
9 toolbar: 'Επικόλληση από το Word'
10} );
diff --git a/sources/plugins/pastefromword/lang/en-au.js b/sources/plugins/pastefromword/lang/en-au.js
new file mode 100644
index 00000000..0f677593
--- /dev/null
+++ b/sources/plugins/pastefromword/lang/en-au.js
@@ -0,0 +1,10 @@
1/*
2Copyright (c) 2003-2015, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'pastefromword', 'en-au', {
6 confirmCleanup: 'The text you want to paste seems to be copied from Word. Do you want to clean it before pasting?', // MISSING
7 error: 'It was not possible to clean up the pasted data due to an internal error', // MISSING
8 title: 'Paste from Word',
9 toolbar: 'Paste from Word'
10} );
diff --git a/sources/plugins/pastefromword/lang/en-ca.js b/sources/plugins/pastefromword/lang/en-ca.js
new file mode 100644
index 00000000..c3386622
--- /dev/null
+++ b/sources/plugins/pastefromword/lang/en-ca.js
@@ -0,0 +1,10 @@
1/*
2Copyright (c) 2003-2015, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'pastefromword', 'en-ca', {
6 confirmCleanup: 'The text you want to paste seems to be copied from Word. Do you want to clean it before pasting?', // MISSING
7 error: 'It was not possible to clean up the pasted data due to an internal error', // MISSING
8 title: 'Paste from Word',
9 toolbar: 'Paste from Word'
10} );
diff --git a/sources/plugins/pastefromword/lang/en-gb.js b/sources/plugins/pastefromword/lang/en-gb.js
new file mode 100644
index 00000000..085e6bce
--- /dev/null
+++ b/sources/plugins/pastefromword/lang/en-gb.js
@@ -0,0 +1,10 @@
1/*
2Copyright (c) 2003-2015, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'pastefromword', 'en-gb', {
6 confirmCleanup: 'The text you want to paste seems to be copied from Word. Do you want to clean it before pasting?',
7 error: 'It was not possible to clean up the pasted data due to an internal error',
8 title: 'Paste from Word',
9 toolbar: 'Paste from Word'
10} );
diff --git a/sources/plugins/pastefromword/lang/en.js b/sources/plugins/pastefromword/lang/en.js
new file mode 100644
index 00000000..396c85b8
--- /dev/null
+++ b/sources/plugins/pastefromword/lang/en.js
@@ -0,0 +1,10 @@
1/*
2Copyright (c) 2003-2015, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'pastefromword', 'en', {
6 confirmCleanup: 'The text you want to paste seems to be copied from Word. Do you want to clean it before pasting?',
7 error: 'It was not possible to clean up the pasted data due to an internal error',
8 title: 'Paste from Word',
9 toolbar: 'Paste from Word'
10} );
diff --git a/sources/plugins/pastefromword/lang/eo.js b/sources/plugins/pastefromword/lang/eo.js
new file mode 100644
index 00000000..b9fc8e57
--- /dev/null
+++ b/sources/plugins/pastefromword/lang/eo.js
@@ -0,0 +1,10 @@
1/*
2Copyright (c) 2003-2015, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'pastefromword', 'eo', {
6 confirmCleanup: 'La teksto, kiun vi volas interglui, ŝajnas esti kopiita el Word. Ĉu vi deziras purigi ĝin antaŭ intergluo?',
7 error: 'Ne eblis purigi la intergluitajn datenojn pro interna eraro',
8 title: 'Interglui el Word',
9 toolbar: 'Interglui el Word'
10} );
diff --git a/sources/plugins/pastefromword/lang/es.js b/sources/plugins/pastefromword/lang/es.js
new file mode 100644
index 00000000..031de57f
--- /dev/null
+++ b/sources/plugins/pastefromword/lang/es.js
@@ -0,0 +1,10 @@
1/*
2Copyright (c) 2003-2015, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'pastefromword', 'es', {
6 confirmCleanup: 'El texto que desea parece provenir de Word.\r\n¿Desea depurarlo antes de pegarlo?',
7 error: 'No ha sido posible limpiar los datos debido a un error interno',
8 title: 'Pegar desde Word',
9 toolbar: 'Pegar desde Word'
10} );
diff --git a/sources/plugins/pastefromword/lang/et.js b/sources/plugins/pastefromword/lang/et.js
new file mode 100644
index 00000000..f41c5ac9
--- /dev/null
+++ b/sources/plugins/pastefromword/lang/et.js
@@ -0,0 +1,10 @@
1/*
2Copyright (c) 2003-2015, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'pastefromword', 'et', {
6 confirmCleanup: 'Tekst, mida tahad asetada näib pärinevat Wordist. Kas tahad selle enne asetamist puhastada?',
7 error: 'Asetatud andmete puhastamine ei olnud sisemise vea tõttu võimalik',
8 title: 'Asetamine Wordist',
9 toolbar: 'Asetamine Wordist'
10} );
diff --git a/sources/plugins/pastefromword/lang/eu.js b/sources/plugins/pastefromword/lang/eu.js
new file mode 100644
index 00000000..3035a14c
--- /dev/null
+++ b/sources/plugins/pastefromword/lang/eu.js
@@ -0,0 +1,10 @@
1/*
2Copyright (c) 2003-2015, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'pastefromword', 'eu', {
6 confirmCleanup: 'Itsatsi nahi duzun testua Word-etik kopiatua dela dirudi. Itsatsi baino lehen garbitu nahi duzu?',
7 error: 'Barne-errore bat dela eta ezin izan da itsatsitako testua garbitu',
8 title: 'Itsatsi Word-etik',
9 toolbar: 'Itsatsi Word-etik'
10} );
diff --git a/sources/plugins/pastefromword/lang/fa.js b/sources/plugins/pastefromword/lang/fa.js
new file mode 100644
index 00000000..029209ba
--- /dev/null
+++ b/sources/plugins/pastefromword/lang/fa.js
@@ -0,0 +1,10 @@
1/*
2Copyright (c) 2003-2015, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'pastefromword', 'fa', {
6 confirmCleanup: 'متنی که میخواهید بچسبانید به نظر میرسد که از Word کپی شده است. آیا میخواهید قبل از چسباندن آن را پاکسازی کنید؟',
7 error: 'به دلیل بروز خطای داخلی امکان پاکسازی اطلاعات بازنشانی شده وجود ندارد.',
8 title: 'چسباندن از Word',
9 toolbar: 'چسباندن از Word'
10} );
diff --git a/sources/plugins/pastefromword/lang/fi.js b/sources/plugins/pastefromword/lang/fi.js
new file mode 100644
index 00000000..7b368fe7
--- /dev/null
+++ b/sources/plugins/pastefromword/lang/fi.js
@@ -0,0 +1,10 @@
1/*
2Copyright (c) 2003-2015, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'pastefromword', 'fi', {
6 confirmCleanup: 'Liittämäsi teksti näyttäisi olevan Word-dokumentista. Haluatko siivota sen ennen liittämistä? (Suositus: Kyllä)',
7 error: 'Liitetyn tiedon siivoaminen ei onnistunut sisäisen virheen takia',
8 title: 'Liitä Word-dokumentista',
9 toolbar: 'Liitä Word-dokumentista'
10} );
diff --git a/sources/plugins/pastefromword/lang/fo.js b/sources/plugins/pastefromword/lang/fo.js
new file mode 100644
index 00000000..dc994220
--- /dev/null
+++ b/sources/plugins/pastefromword/lang/fo.js
@@ -0,0 +1,10 @@
1/*
2Copyright (c) 2003-2015, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'pastefromword', 'fo', {
6 confirmCleanup: 'Teksturin, tú roynir at seta inn, sýnist at stava frá Word. Skal teksturin reinsast fyrst?',
7 error: 'Tað eydnaðist ikki at reinsa tekstin vegna ein internan feil',
8 title: 'Innrita frá Word',
9 toolbar: 'Innrita frá Word'
10} );
diff --git a/sources/plugins/pastefromword/lang/fr-ca.js b/sources/plugins/pastefromword/lang/fr-ca.js
new file mode 100644
index 00000000..4e27e997
--- /dev/null
+++ b/sources/plugins/pastefromword/lang/fr-ca.js
@@ -0,0 +1,10 @@
1/*
2Copyright (c) 2003-2015, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'pastefromword', 'fr-ca', {
6 confirmCleanup: 'Le texte que vous tentez de coller semble provenir de Word. Désirez vous le nettoyer avant de coller?',
7 error: 'Il n\'a pas été possible de nettoyer les données collées du à une erreur interne',
8 title: 'Coller de Word',
9 toolbar: 'Coller de Word'
10} );
diff --git a/sources/plugins/pastefromword/lang/fr.js b/sources/plugins/pastefromword/lang/fr.js
new file mode 100644
index 00000000..13126f7a
--- /dev/null
+++ b/sources/plugins/pastefromword/lang/fr.js
@@ -0,0 +1,10 @@
1/*
2Copyright (c) 2003-2015, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'pastefromword', 'fr', {
6 confirmCleanup: 'Le texte à coller semble provenir de Word. Désirez-vous le nettoyer avant de coller?',
7 error: 'Il n\'a pas été possible de nettoyer les données collées à la suite d\'une erreur interne.',
8 title: 'Coller depuis Word',
9 toolbar: 'Coller depuis Word'
10} );
diff --git a/sources/plugins/pastefromword/lang/gl.js b/sources/plugins/pastefromword/lang/gl.js
new file mode 100644
index 00000000..655cc3d5
--- /dev/null
+++ b/sources/plugins/pastefromword/lang/gl.js
@@ -0,0 +1,10 @@
1/*
2Copyright (c) 2003-2015, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'pastefromword', 'gl', {
6 confirmCleanup: 'O texto que quere pegar semella ser copiado desde o Word. Quere depuralo antes de pegalo?',
7 error: 'Non foi posíbel depurar os datos pegados por mor dun erro interno',
8 title: 'Pegar desde Word',
9 toolbar: 'Pegar desde Word'
10} );
diff --git a/sources/plugins/pastefromword/lang/gu.js b/sources/plugins/pastefromword/lang/gu.js
new file mode 100644
index 00000000..6ea245d6
--- /dev/null
+++ b/sources/plugins/pastefromword/lang/gu.js
@@ -0,0 +1,10 @@
1/*
2Copyright (c) 2003-2015, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'pastefromword', 'gu', {
6 confirmCleanup: 'તમે જે ટેક્ષ્ત્ કોપી કરી રહ્યા છો ટે વર્ડ ની છે. કોપી કરતા પેહલા સાફ કરવી છે?',
7 error: 'પેસ્ટ કરેલો ડેટા ઇન્ટરનલ એરર ના લીથે સાફ કરી શકાયો નથી.',
8 title: 'પેસ્ટ (વડૅ ટેક્સ્ટ)',
9 toolbar: 'પેસ્ટ (વડૅ ટેક્સ્ટ)'
10} );
diff --git a/sources/plugins/pastefromword/lang/he.js b/sources/plugins/pastefromword/lang/he.js
new file mode 100644
index 00000000..80666c70
--- /dev/null
+++ b/sources/plugins/pastefromword/lang/he.js
@@ -0,0 +1,10 @@
1/*
2Copyright (c) 2003-2015, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'pastefromword', 'he', {
6 confirmCleanup: 'נראה הטקסט שבכוונתך להדביק מקורו בקובץ וורד. האם ברצונך לנקות אותו טרם ההדבקה?',
7 error: 'לא ניתן היה לנקות את המידע בשל תקלה פנימית.',
8 title: 'הדבקה מ-Word',
9 toolbar: 'הדבקה מ-Word'
10} );
diff --git a/sources/plugins/pastefromword/lang/hi.js b/sources/plugins/pastefromword/lang/hi.js
new file mode 100644
index 00000000..2e39fee2
--- /dev/null
+++ b/sources/plugins/pastefromword/lang/hi.js
@@ -0,0 +1,10 @@
1/*
2Copyright (c) 2003-2015, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'pastefromword', 'hi', {
6 confirmCleanup: 'The text you want to paste seems to be copied from Word. Do you want to clean it before pasting?', // MISSING
7 error: 'It was not possible to clean up the pasted data due to an internal error', // MISSING
8 title: 'पेस्ट (वर्ड से)',
9 toolbar: 'पेस्ट (वर्ड से)'
10} );
diff --git a/sources/plugins/pastefromword/lang/hr.js b/sources/plugins/pastefromword/lang/hr.js
new file mode 100644
index 00000000..2a765328
--- /dev/null
+++ b/sources/plugins/pastefromword/lang/hr.js
@@ -0,0 +1,10 @@
1/*
2Copyright (c) 2003-2015, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'pastefromword', 'hr', {
6 confirmCleanup: 'Tekst koji želite zalijepiti čini se da je kopiran iz Worda. Želite li prije očistiti tekst?',
7 error: 'Nije moguće očistiti podatke za ljepljenje zbog interne greške',
8 title: 'Zalijepi iz Worda',
9 toolbar: 'Zalijepi iz Worda'
10} );
diff --git a/sources/plugins/pastefromword/lang/hu.js b/sources/plugins/pastefromword/lang/hu.js
new file mode 100644
index 00000000..5f670e1e
--- /dev/null
+++ b/sources/plugins/pastefromword/lang/hu.js
@@ -0,0 +1,10 @@
1/*
2Copyright (c) 2003-2015, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'pastefromword', 'hu', {
6 confirmCleanup: 'Úgy tűnik a beillesztett szöveget Word-ből másolt át. Meg szeretné tisztítani a szöveget? (ajánlott)',
7 error: 'Egy belső hiba miatt nem sikerült megtisztítani a szöveget',
8 title: 'Beillesztés Word-ből',
9 toolbar: 'Beillesztés Word-ből'
10} );
diff --git a/sources/plugins/pastefromword/lang/id.js b/sources/plugins/pastefromword/lang/id.js
new file mode 100644
index 00000000..be60dd24
--- /dev/null
+++ b/sources/plugins/pastefromword/lang/id.js
@@ -0,0 +1,10 @@
1/*
2Copyright (c) 2003-2015, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'pastefromword', 'id', {
6 confirmCleanup: 'Teks yang ingin anda tempel sepertinya di salin dari Word. Apakah anda mau membersihkannya sebelum menempel?',
7 error: 'Tidak mungkin membersihkan data yang ditempel dikerenakan kesalahan internal',
8 title: 'Tempel dari Word',
9 toolbar: 'Tempel dari Word'
10} );
diff --git a/sources/plugins/pastefromword/lang/is.js b/sources/plugins/pastefromword/lang/is.js
new file mode 100644
index 00000000..35dfe084
--- /dev/null
+++ b/sources/plugins/pastefromword/lang/is.js
@@ -0,0 +1,10 @@
1/*
2Copyright (c) 2003-2015, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'pastefromword', 'is', {
6 confirmCleanup: 'The text you want to paste seems to be copied from Word. Do you want to clean it before pasting?', // MISSING
7 error: 'It was not possible to clean up the pasted data due to an internal error', // MISSING
8 title: 'Líma úr Word',
9 toolbar: 'Líma úr Word'
10} );
diff --git a/sources/plugins/pastefromword/lang/it.js b/sources/plugins/pastefromword/lang/it.js
new file mode 100644
index 00000000..68020681
--- /dev/null
+++ b/sources/plugins/pastefromword/lang/it.js
@@ -0,0 +1,10 @@
1/*
2Copyright (c) 2003-2015, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'pastefromword', 'it', {
6 confirmCleanup: 'Il testo da incollare sembra provenire da Word. Desideri pulirlo prima di incollare?',
7 error: 'Non è stato possibile eliminare il testo incollato a causa di un errore interno.',
8 title: 'Incolla da Word',
9 toolbar: 'Incolla da Word'
10} );
diff --git a/sources/plugins/pastefromword/lang/ja.js b/sources/plugins/pastefromword/lang/ja.js
new file mode 100644
index 00000000..a1269c98
--- /dev/null
+++ b/sources/plugins/pastefromword/lang/ja.js
@@ -0,0 +1,10 @@
1/*
2Copyright (c) 2003-2015, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'pastefromword', 'ja', {
6 confirmCleanup: '貼り付けを行うテキストはワード文章からコピーされようとしています。貼り付ける前にクリーニングを行いますか?',
7 error: '内部エラーにより貼り付けたデータをクリアできませんでした',
8 title: 'ワード文章から貼り付け',
9 toolbar: 'ワード文章から貼り付け'
10} );
diff --git a/sources/plugins/pastefromword/lang/ka.js b/sources/plugins/pastefromword/lang/ka.js
new file mode 100644
index 00000000..472ff533
--- /dev/null
+++ b/sources/plugins/pastefromword/lang/ka.js
@@ -0,0 +1,10 @@
1/*
2Copyright (c) 2003-2015, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'pastefromword', 'ka', {
6 confirmCleanup: 'ჩასასმელი ტექსტი ვორდიდან გადმოტანილს გავს - გინდათ მისი წინასწარ გაწმენდა?',
7 error: 'შიდა შეცდომის გამო ვერ მოხერხდა ტექსტის გაწმენდა',
8 title: 'ვორდიდან ჩასმა',
9 toolbar: 'ვორდიდან ჩასმა'
10} );
diff --git a/sources/plugins/pastefromword/lang/km.js b/sources/plugins/pastefromword/lang/km.js
new file mode 100644
index 00000000..cd5268dc
--- /dev/null
+++ b/sources/plugins/pastefromword/lang/km.js
@@ -0,0 +1,10 @@
1/*
2Copyright (c) 2003-2015, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'pastefromword', 'km', {
6 confirmCleanup: 'អត្ថបទ​ដែល​អ្នក​ចង់​បិទ​ភ្ជាប់​នេះ ទំនង​ដូច​ជា​ចម្លង​មក​ពី Word។ តើ​អ្នក​ចង់​សម្អាត​វា​មុន​បិទ​ភ្ជាប់​ទេ?',
7 error: 'ដោយ​សារ​មាន​បញ្ហា​ផ្នែក​ក្នុង​ធ្វើ​ឲ្យ​មិន​អាច​សម្អាត​ទិន្នន័យ​ដែល​បាន​បិទ​ភ្ជាប់',
8 title: 'បិទ​ភ្ជាប់​ពី Word',
9 toolbar: 'បិទ​ភ្ជាប់​ពី Word'
10} );
diff --git a/sources/plugins/pastefromword/lang/ko.js b/sources/plugins/pastefromword/lang/ko.js
new file mode 100644
index 00000000..54870707
--- /dev/null
+++ b/sources/plugins/pastefromword/lang/ko.js
@@ -0,0 +1,10 @@
1/*
2Copyright (c) 2003-2015, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'pastefromword', 'ko', {
6 confirmCleanup: '붙여 넣을 내용은 MS Word에서 복사 한 것입니다. 붙여 넣기 전에 정리 하시겠습니까?',
7 error: '내부 오류로 붙여 넣은 데이터를 정리 할 수 없습니다.',
8 title: 'MS Word 에서 붙여넣기',
9 toolbar: 'MS Word 에서 붙여넣기'
10} );
diff --git a/sources/plugins/pastefromword/lang/ku.js b/sources/plugins/pastefromword/lang/ku.js
new file mode 100644
index 00000000..7fa47dd7
--- /dev/null
+++ b/sources/plugins/pastefromword/lang/ku.js
@@ -0,0 +1,10 @@
1/*
2Copyright (c) 2003-2015, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'pastefromword', 'ku', {
6 confirmCleanup: 'ئەم دەقەی بەتەمای بیلکێنی پێدەچێت له word هێنرابێت. دەتەوێت پاکی بکەیوه پێش ئەوەی بیلکێنی؟',
7 error: 'هیچ ڕێگەیەك نەبوو لەلکاندنی دەقەکه بەهۆی هەڵەیەکی ناوەخۆیی',
8 title: 'لکاندنی لەلایەن Word',
9 toolbar: 'لکاندنی لەڕێی Word'
10} );
diff --git a/sources/plugins/pastefromword/lang/lt.js b/sources/plugins/pastefromword/lang/lt.js
new file mode 100644
index 00000000..b46b34f4
--- /dev/null
+++ b/sources/plugins/pastefromword/lang/lt.js
@@ -0,0 +1,10 @@
1/*
2Copyright (c) 2003-2015, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'pastefromword', 'lt', {
6 confirmCleanup: 'Tekstas, kurį įkeliate yra kopijuojamas iš Word. Ar norite jį išvalyti prieš įkeliant?',
7 error: 'Dėl vidinių sutrikimų, nepavyko išvalyti įkeliamo teksto',
8 title: 'Įdėti iš Word',
9 toolbar: 'Įdėti iš Word'
10} );
diff --git a/sources/plugins/pastefromword/lang/lv.js b/sources/plugins/pastefromword/lang/lv.js
new file mode 100644
index 00000000..c82f2093
--- /dev/null
+++ b/sources/plugins/pastefromword/lang/lv.js
@@ -0,0 +1,10 @@
1/*
2Copyright (c) 2003-2015, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'pastefromword', 'lv', {
6 confirmCleanup: 'Teksts, kuru vēlaties ielīmēt, izskatās ir nokopēts no Word. Vai vēlaties to iztīrīt pirms ielīmēšanas?',
7 error: 'Iekšējas kļūdas dēļ, neizdevās iztīrīt ielīmētos datus.',
8 title: 'Ievietot no Worda',
9 toolbar: 'Ievietot no Worda'
10} );
diff --git a/sources/plugins/pastefromword/lang/mk.js b/sources/plugins/pastefromword/lang/mk.js
new file mode 100644
index 00000000..b856a05e
--- /dev/null
+++ b/sources/plugins/pastefromword/lang/mk.js
@@ -0,0 +1,10 @@
1/*
2Copyright (c) 2003-2015, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'pastefromword', 'mk', {
6 confirmCleanup: 'The text you want to paste seems to be copied from Word. Do you want to clean it before pasting?', // MISSING
7 error: 'It was not possible to clean up the pasted data due to an internal error', // MISSING
8 title: 'Paste from Word', // MISSING
9 toolbar: 'Paste from Word' // MISSING
10} );
diff --git a/sources/plugins/pastefromword/lang/mn.js b/sources/plugins/pastefromword/lang/mn.js
new file mode 100644
index 00000000..2e6fb128
--- /dev/null
+++ b/sources/plugins/pastefromword/lang/mn.js
@@ -0,0 +1,10 @@
1/*
2Copyright (c) 2003-2015, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'pastefromword', 'mn', {
6 confirmCleanup: 'The text you want to paste seems to be copied from Word. Do you want to clean it before pasting?', // MISSING
7 error: 'It was not possible to clean up the pasted data due to an internal error', // MISSING
8 title: 'Word-оос буулгах',
9 toolbar: 'Word-оос буулгах'
10} );
diff --git a/sources/plugins/pastefromword/lang/ms.js b/sources/plugins/pastefromword/lang/ms.js
new file mode 100644
index 00000000..ce6ffe6e
--- /dev/null
+++ b/sources/plugins/pastefromword/lang/ms.js
@@ -0,0 +1,10 @@
1/*
2Copyright (c) 2003-2015, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'pastefromword', 'ms', {
6 confirmCleanup: 'The text you want to paste seems to be copied from Word. Do you want to clean it before pasting?', // MISSING
7 error: 'It was not possible to clean up the pasted data due to an internal error', // MISSING
8 title: 'Tampal dari Word',
9 toolbar: 'Tampal dari Word'
10} );
diff --git a/sources/plugins/pastefromword/lang/nb.js b/sources/plugins/pastefromword/lang/nb.js
new file mode 100644
index 00000000..edd15bdd
--- /dev/null
+++ b/sources/plugins/pastefromword/lang/nb.js
@@ -0,0 +1,10 @@
1/*
2Copyright (c) 2003-2015, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'pastefromword', 'nb', {
6 confirmCleanup: 'Teksten du limer inn ser ut til å være kopiert fra Word. Vil du renske den før du limer den inn?',
7 error: 'Det var ikke mulig å renske den innlimte teksten på grunn av en intern feil',
8 title: 'Lim inn fra Word',
9 toolbar: 'Lim inn fra Word'
10} );
diff --git a/sources/plugins/pastefromword/lang/nl.js b/sources/plugins/pastefromword/lang/nl.js
new file mode 100644
index 00000000..a699f3d0
--- /dev/null
+++ b/sources/plugins/pastefromword/lang/nl.js
@@ -0,0 +1,10 @@
1/*
2Copyright (c) 2003-2015, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'pastefromword', 'nl', {
6 confirmCleanup: 'De tekst die u wilt plakken lijkt gekopieerd te zijn vanuit Word. Wilt u de tekst opschonen voordat deze geplakt wordt?',
7 error: 'Het was niet mogelijk om de geplakte tekst op te schonen door een interne fout',
8 title: 'Plakken vanuit Word',
9 toolbar: 'Plakken vanuit Word'
10} );
diff --git a/sources/plugins/pastefromword/lang/no.js b/sources/plugins/pastefromword/lang/no.js
new file mode 100644
index 00000000..fbb970be
--- /dev/null
+++ b/sources/plugins/pastefromword/lang/no.js
@@ -0,0 +1,10 @@
1/*
2Copyright (c) 2003-2015, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'pastefromword', 'no', {
6 confirmCleanup: 'Teksten du limer inn ser ut til å være kopiert fra Word. Vil du renske den før du limer den inn?',
7 error: 'Det var ikke mulig å renske den innlimte teksten på grunn av en intern feil',
8 title: 'Lim inn fra Word',
9 toolbar: 'Lim inn fra Word'
10} );
diff --git a/sources/plugins/pastefromword/lang/pl.js b/sources/plugins/pastefromword/lang/pl.js
new file mode 100644
index 00000000..245b7d05
--- /dev/null
+++ b/sources/plugins/pastefromword/lang/pl.js
@@ -0,0 +1,10 @@
1/*
2Copyright (c) 2003-2015, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'pastefromword', 'pl', {
6 confirmCleanup: 'Tekst, który chcesz wkleić, prawdopodobnie pochodzi z programu Microsoft Word. Czy chcesz go wyczyścić przed wklejeniem?',
7 error: 'Wyczyszczenie wklejonych danych nie było możliwe z powodu wystąpienia błędu.',
8 title: 'Wklej z programu MS Word',
9 toolbar: 'Wklej z programu MS Word'
10} );
diff --git a/sources/plugins/pastefromword/lang/pt-br.js b/sources/plugins/pastefromword/lang/pt-br.js
new file mode 100644
index 00000000..199b5a6b
--- /dev/null
+++ b/sources/plugins/pastefromword/lang/pt-br.js
@@ -0,0 +1,10 @@
1/*
2Copyright (c) 2003-2015, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'pastefromword', 'pt-br', {
6 confirmCleanup: 'O texto que você deseja colar parece ter sido copiado do Word. Você gostaria de remover a formatação antes de colar?',
7 error: 'Não foi possível limpar os dados colados devido a um erro interno',
8 title: 'Colar do Word',
9 toolbar: 'Colar do Word'
10} );
diff --git a/sources/plugins/pastefromword/lang/pt.js b/sources/plugins/pastefromword/lang/pt.js
new file mode 100644
index 00000000..06cdee8a
--- /dev/null
+++ b/sources/plugins/pastefromword/lang/pt.js
@@ -0,0 +1,10 @@
1/*
2Copyright (c) 2003-2015, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'pastefromword', 'pt', {
6 confirmCleanup: 'O texto que pretende colar parece ter sido copiado do Word. Deseja limpá-lo antes de colar?',
7 error: 'Não foi possivel limpar a informação colada decido a um erro interno.',
8 title: 'Colar do Word',
9 toolbar: 'Colar do Word'
10} );
diff --git a/sources/plugins/pastefromword/lang/ro.js b/sources/plugins/pastefromword/lang/ro.js
new file mode 100644
index 00000000..5871070c
--- /dev/null
+++ b/sources/plugins/pastefromword/lang/ro.js
@@ -0,0 +1,10 @@
1/*
2Copyright (c) 2003-2015, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'pastefromword', 'ro', {
6 confirmCleanup: 'Textul pe care doriți să-l lipiți este din Word. Doriți curățarea textului înante de a-l adăuga?',
7 error: 'Nu a fost posibilă curățarea datelor adăugate datorită unei erori interne',
8 title: 'Adaugă din Word',
9 toolbar: 'Adaugă din Word'
10} );
diff --git a/sources/plugins/pastefromword/lang/ru.js b/sources/plugins/pastefromword/lang/ru.js
new file mode 100644
index 00000000..1a8e159d
--- /dev/null
+++ b/sources/plugins/pastefromword/lang/ru.js
@@ -0,0 +1,10 @@
1/*
2Copyright (c) 2003-2015, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'pastefromword', 'ru', {
6 confirmCleanup: 'Текст, который вы желаете вставить, по всей видимости, был скопирован из Word. Следует ли очистить его перед вставкой?',
7 error: 'Невозможно очистить вставленные данные из-за внутренней ошибки',
8 title: 'Вставить из Word',
9 toolbar: 'Вставить из Word'
10} );
diff --git a/sources/plugins/pastefromword/lang/si.js b/sources/plugins/pastefromword/lang/si.js
new file mode 100644
index 00000000..e66b0cbd
--- /dev/null
+++ b/sources/plugins/pastefromword/lang/si.js
@@ -0,0 +1,10 @@
1/*
2Copyright (c) 2003-2015, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'pastefromword', 'si', {
6 confirmCleanup: 'The text you want to paste seems to be copied from Word. Do you want to clean it before pasting?', // MISSING
7 error: 'It was not possible to clean up the pasted data due to an internal error', // MISSING
8 title: 'වචන වලින් අලවන්න',
9 toolbar: 'වචන වලින් අලවන්න'
10} );
diff --git a/sources/plugins/pastefromword/lang/sk.js b/sources/plugins/pastefromword/lang/sk.js
new file mode 100644
index 00000000..8386c681
--- /dev/null
+++ b/sources/plugins/pastefromword/lang/sk.js
@@ -0,0 +1,10 @@
1/*
2Copyright (c) 2003-2015, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'pastefromword', 'sk', {
6 confirmCleanup: 'Vkladaný text vyzerá byť skopírovaný z Wordu. Chcete ho automaticky vyčistiť pred vkladaním?',
7 error: 'Nebolo možné vyčistiť vložené dáta kvôli internej chybe',
8 title: 'Vložiť z Wordu',
9 toolbar: 'Vložiť z Wordu'
10} );
diff --git a/sources/plugins/pastefromword/lang/sl.js b/sources/plugins/pastefromword/lang/sl.js
new file mode 100644
index 00000000..b558ca8a
--- /dev/null
+++ b/sources/plugins/pastefromword/lang/sl.js
@@ -0,0 +1,10 @@
1/*
2Copyright (c) 2003-2015, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'pastefromword', 'sl', {
6 confirmCleanup: 'Besedilo, ki ga želite prilepiti je kopirano iz Word-a. Ali ga želite očistiti, preden ga prilepite?',
7 error: 'Ni bilo mogoče očistiti prilepljenih podatkov zaradi notranje napake',
8 title: 'Prilepi iz Worda',
9 toolbar: 'Prilepi iz Worda'
10} );
diff --git a/sources/plugins/pastefromword/lang/sq.js b/sources/plugins/pastefromword/lang/sq.js
new file mode 100644
index 00000000..41c7c775
--- /dev/null
+++ b/sources/plugins/pastefromword/lang/sq.js
@@ -0,0 +1,10 @@
1/*
2Copyright (c) 2003-2015, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'pastefromword', 'sq', {
6 confirmCleanup: 'Teksti që dëshironi të e hidhni siç duket është kopjuar nga Word-i. Dëshironi të e pastroni para se të e hidhni?',
7 error: 'Nuk ishte e mundur të fshiheshin të dhënat e hedhura për shkak të një gabimi të brendshëm',
8 title: 'Hidhe nga Word-i',
9 toolbar: 'Hidhe nga Word-i'
10} );
diff --git a/sources/plugins/pastefromword/lang/sr-latn.js b/sources/plugins/pastefromword/lang/sr-latn.js
new file mode 100644
index 00000000..3774a3de
--- /dev/null
+++ b/sources/plugins/pastefromword/lang/sr-latn.js
@@ -0,0 +1,10 @@
1/*
2Copyright (c) 2003-2015, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'pastefromword', 'sr-latn', {
6 confirmCleanup: 'The text you want to paste seems to be copied from Word. Do you want to clean it before pasting?', // MISSING
7 error: 'It was not possible to clean up the pasted data due to an internal error', // MISSING
8 title: 'Zalepi iz Worda',
9 toolbar: 'Zalepi iz Worda'
10} );
diff --git a/sources/plugins/pastefromword/lang/sr.js b/sources/plugins/pastefromword/lang/sr.js
new file mode 100644
index 00000000..259715b3
--- /dev/null
+++ b/sources/plugins/pastefromword/lang/sr.js
@@ -0,0 +1,10 @@
1/*
2Copyright (c) 2003-2015, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'pastefromword', 'sr', {
6 confirmCleanup: 'The text you want to paste seems to be copied from Word. Do you want to clean it before pasting?', // MISSING
7 error: 'It was not possible to clean up the pasted data due to an internal error', // MISSING
8 title: 'Залепи из Worda',
9 toolbar: 'Залепи из Worda'
10} );
diff --git a/sources/plugins/pastefromword/lang/sv.js b/sources/plugins/pastefromword/lang/sv.js
new file mode 100644
index 00000000..d5954b49
--- /dev/null
+++ b/sources/plugins/pastefromword/lang/sv.js
@@ -0,0 +1,10 @@
1/*
2Copyright (c) 2003-2015, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'pastefromword', 'sv', {
6 confirmCleanup: 'Texten du vill klistra in verkar vara kopierad från Word. Vill du rensa den innan du klistrar in den?',
7 error: 'Det var inte möjligt att städa upp den inklistrade data på grund av ett internt fel',
8 title: 'Klistra in från Word',
9 toolbar: 'Klistra in från Word'
10} );
diff --git a/sources/plugins/pastefromword/lang/th.js b/sources/plugins/pastefromword/lang/th.js
new file mode 100644
index 00000000..2ddcca55
--- /dev/null
+++ b/sources/plugins/pastefromword/lang/th.js
@@ -0,0 +1,10 @@
1/*
2Copyright (c) 2003-2015, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'pastefromword', 'th', {
6 confirmCleanup: 'ข้อความที่คุณต้องการวางลงไปเป็นข้อความที่คัดลอกมาจากโปรแกรมไมโครซอฟท์เวิร์ด คุณต้องการล้างค่าข้อความดังกล่าวก่อนวางลงไปหรือไม่?',
7 error: 'ไม่สามารถล้างข้อมูลที่ต้องการวางได้เนื่องจากเกิดข้อผิดพลาดภายในระบบ',
8 title: 'วางสำเนาจากตัวอักษรเวิร์ด',
9 toolbar: 'วางสำเนาจากตัวอักษรเวิร์ด'
10} );
diff --git a/sources/plugins/pastefromword/lang/tr.js b/sources/plugins/pastefromword/lang/tr.js
new file mode 100644
index 00000000..12331e38
--- /dev/null
+++ b/sources/plugins/pastefromword/lang/tr.js
@@ -0,0 +1,10 @@
1/*
2Copyright (c) 2003-2015, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'pastefromword', 'tr', {
6 confirmCleanup: 'Yapıştırmaya çalıştığınız metin Word\'den kopyalanmıştır. Yapıştırmadan önce silmek istermisiniz?',
7 error: 'Yapıştırmadaki veri bilgisi hata düzelene kadar silinmeyecektir',
8 title: 'Word\'den Yapıştır',
9 toolbar: 'Word\'den Yapıştır'
10} );
diff --git a/sources/plugins/pastefromword/lang/tt.js b/sources/plugins/pastefromword/lang/tt.js
new file mode 100644
index 00000000..a5876219
--- /dev/null
+++ b/sources/plugins/pastefromword/lang/tt.js
@@ -0,0 +1,10 @@
1/*
2Copyright (c) 2003-2015, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'pastefromword', 'tt', {
6 confirmCleanup: 'The text you want to paste seems to be copied from Word. Do you want to clean it before pasting?', // MISSING
7 error: 'It was not possible to clean up the pasted data due to an internal error', // MISSING
8 title: 'Word\'тан өстәү',
9 toolbar: 'Word\'тан өстәү'
10} );
diff --git a/sources/plugins/pastefromword/lang/ug.js b/sources/plugins/pastefromword/lang/ug.js
new file mode 100644
index 00000000..8285b371
--- /dev/null
+++ b/sources/plugins/pastefromword/lang/ug.js
@@ -0,0 +1,10 @@
1/*
2Copyright (c) 2003-2015, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'pastefromword', 'ug', {
6 confirmCleanup: 'سىز چاپلىماقچى بولغان مەزمۇن MS Word تىن كەلگەندەك قىلىدۇ، MS Word پىچىمىنى تازىلىۋەتكەندىن كېيىن ئاندىن چاپلامدۇ؟',
7 error: 'ئىچكى خاتالىق سەۋەبىدىن چاپلايدىغان سانلىق مەلۇماتنى تازىلىيالمايدۇ',
8 title: 'MS Word تىن چاپلا',
9 toolbar: 'MS Word تىن چاپلا'
10} );
diff --git a/sources/plugins/pastefromword/lang/uk.js b/sources/plugins/pastefromword/lang/uk.js
new file mode 100644
index 00000000..ff3fe230
--- /dev/null
+++ b/sources/plugins/pastefromword/lang/uk.js
@@ -0,0 +1,10 @@
1/*
2Copyright (c) 2003-2015, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'pastefromword', 'uk', {
6 confirmCleanup: 'Текст, що Ви намагаєтесь вставити, схожий на скопійований з Word. Бажаєте очистити його форматування перед вставлянням?',
7 error: 'Неможливо очистити форматування через внутрішню помилку.',
8 title: 'Вставити з Word',
9 toolbar: 'Вставити з Word'
10} );
diff --git a/sources/plugins/pastefromword/lang/vi.js b/sources/plugins/pastefromword/lang/vi.js
new file mode 100644
index 00000000..e967297f
--- /dev/null
+++ b/sources/plugins/pastefromword/lang/vi.js
@@ -0,0 +1,10 @@
1/*
2Copyright (c) 2003-2015, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'pastefromword', 'vi', {
6 confirmCleanup: 'Văn bản bạn muốn dán có kèm định dạng của Word. Bạn có muốn loại bỏ định dạng Word trước khi dán?',
7 error: 'Không thể để làm sạch các dữ liệu dán do một lỗi nội bộ',
8 title: 'Dán với định dạng Word',
9 toolbar: 'Dán với định dạng Word'
10} );
diff --git a/sources/plugins/pastefromword/lang/zh-cn.js b/sources/plugins/pastefromword/lang/zh-cn.js
new file mode 100644
index 00000000..f9e1a952
--- /dev/null
+++ b/sources/plugins/pastefromword/lang/zh-cn.js
@@ -0,0 +1,10 @@
1/*
2Copyright (c) 2003-2015, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'pastefromword', 'zh-cn', {
6 confirmCleanup: '您要粘贴的内容好像是来自 MS Word,是否要清除 MS Word 格式后再粘贴?',
7 error: '由于内部错误无法清理要粘贴的数据',
8 title: '从 MS Word 粘贴',
9 toolbar: '从 MS Word 粘贴'
10} );
diff --git a/sources/plugins/pastefromword/lang/zh.js b/sources/plugins/pastefromword/lang/zh.js
new file mode 100644
index 00000000..fc460ba6
--- /dev/null
+++ b/sources/plugins/pastefromword/lang/zh.js
@@ -0,0 +1,10 @@
1/*
2Copyright (c) 2003-2015, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'pastefromword', 'zh', {
6 confirmCleanup: '您想貼上的文字似乎是自 Word 複製而來,請問您是否要先清除 Word 的格式後再行貼上?',
7 error: '由於發生內部錯誤,無法清除清除 Word 的格式。',
8 title: '自 Word 貼上',
9 toolbar: '自 Word 貼上'
10} );
diff --git a/sources/plugins/pastefromword/plugin.js b/sources/plugins/pastefromword/plugin.js
new file mode 100644
index 00000000..3bc93798
--- /dev/null
+++ b/sources/plugins/pastefromword/plugin.js
@@ -0,0 +1,149 @@
1/**
2 * @license Copyright (c) 2003-2015, CKSource - Frederico Knabben. All rights reserved.
3 * For licensing, see LICENSE.md or http://ckeditor.com/license
4 */
5
6( function() {
7 CKEDITOR.plugins.add( 'pastefromword', {
8 requires: 'clipboard',
9 // jscs:disable maximumLineLength
10 lang: 'af,ar,bg,bn,bs,ca,cs,cy,da,de,el,en,en-au,en-ca,en-gb,eo,es,et,eu,fa,fi,fo,fr,fr-ca,gl,gu,he,hi,hr,hu,id,is,it,ja,ka,km,ko,ku,lt,lv,mk,mn,ms,nb,nl,no,pl,pt,pt-br,ro,ru,si,sk,sl,sq,sr,sr-latn,sv,th,tr,tt,ug,uk,vi,zh,zh-cn', // %REMOVE_LINE_CORE%
11 // jscs:enable maximumLineLength
12 icons: 'pastefromword,pastefromword-rtl', // %REMOVE_LINE_CORE%
13 hidpi: true, // %REMOVE_LINE_CORE%
14 init: function( editor ) {
15 var commandName = 'pastefromword',
16 // Flag indicate this command is actually been asked instead of a generic pasting.
17 forceFromWord = 0,
18 path = this.path;
19
20 editor.addCommand( commandName, {
21 // Snapshots are done manually by editable.insertXXX methods.
22 canUndo: false,
23 async: true,
24
25 exec: function( editor ) {
26 var cmd = this;
27
28 forceFromWord = 1;
29 // Force html mode for incomming paste events sequence.
30 editor.once( 'beforePaste', forceHtmlMode );
31
32 editor.getClipboardData( { title: editor.lang.pastefromword.title }, function( data ) {
33 // Do not use editor#paste, because it would start from beforePaste event.
34 data && editor.fire( 'paste', {
35 type: 'html',
36 dataValue: data.dataValue,
37 method: 'paste',
38 dataTransfer: CKEDITOR.plugins.clipboard.initPasteDataTransfer()
39 } );
40
41 editor.fire( 'afterCommandExec', {
42 name: commandName,
43 command: cmd,
44 returnValue: !!data
45 } );
46 } );
47 }
48 } );
49
50 // Register the toolbar button.
51 editor.ui.addButton && editor.ui.addButton( 'PasteFromWord', {
52 label: editor.lang.pastefromword.toolbar,
53 command: commandName,
54 toolbar: 'clipboard,50'
55 } );
56
57 editor.on( 'pasteState', function( evt ) {
58 editor.getCommand( commandName ).setState( evt.data );
59 } );
60
61 // Features bring by this command beside the normal process:
62 // 1. No more bothering of user about the clean-up.
63 // 2. Perform the clean-up even if content is not from MS-Word.
64 // (e.g. from a MS-Word similar application.)
65 // 3. Listen with high priority (3), so clean up is done before content
66 // type sniffing (priority = 6).
67 editor.on( 'paste', function( evt ) {
68 var data = evt.data,
69 mswordHtml = data.dataValue;
70
71 // MS-WORD format sniffing.
72 if ( mswordHtml && ( forceFromWord || ( /(class=\"?Mso|style=\"[^\"]*\bmso\-|w:WordDocument)/ ).test( mswordHtml ) ) ) {
73 // Do not apply paste filter to data filtered by the Word filter (#13093).
74 data.dontFilter = true;
75
76 // If filter rules aren't loaded then cancel 'paste' event,
77 // load them and when they'll get loaded fire new paste event
78 // for which data will be filtered in second execution of
79 // this listener.
80 var isLazyLoad = loadFilterRules( editor, path, function() {
81 // Event continuation with the original data.
82 if ( isLazyLoad )
83 editor.fire( 'paste', data );
84 else if ( !editor.config.pasteFromWordPromptCleanup || ( forceFromWord || confirm( editor.lang.pastefromword.confirmCleanup ) ) ) // jshint ignore:line
85 data.dataValue = CKEDITOR.cleanWord( mswordHtml, editor );
86
87 // Reset forceFromWord.
88 forceFromWord = 0;
89 } );
90
91 // The cleanup rules are to be loaded, we should just cancel
92 // this event.
93 isLazyLoad && evt.cancel();
94 }
95 }, null, null, 3 );
96 }
97
98 } );
99
100 function loadFilterRules( editor, path, callback ) {
101 var isLoaded = CKEDITOR.cleanWord;
102
103 if ( isLoaded )
104 callback();
105 else {
106 var filterFilePath = CKEDITOR.getUrl( editor.config.pasteFromWordCleanupFile || ( path + 'filter/default.js' ) );
107
108 // Load with busy indicator.
109 CKEDITOR.scriptLoader.load( filterFilePath, callback, null, true );
110 }
111
112 return !isLoaded;
113 }
114
115 function forceHtmlMode( evt ) {
116 evt.data.type = 'html';
117 }
118} )();
119
120
121/**
122 * Whether to prompt the user about the clean up of content being pasted from MS Word.
123 *
124 * config.pasteFromWordPromptCleanup = true;
125 *
126 * @since 3.1
127 * @cfg {Boolean} [pasteFromWordPromptCleanup=false]
128 * @member CKEDITOR.config
129 */
130
131/**
132 * The file that provides the MS Word cleanup function for pasting operations.
133 *
134 * **Note:** This is a global configuration shared by all editor instances present
135 * in the page.
136 *
137 * // Load from 'pastefromword' plugin 'filter' sub folder (custom.js file) using path relative to CKEditor installation folder.
138 * CKEDITOR.config.pasteFromWordCleanupFile = 'plugins/pastefromword/filter/custom.js';
139 *
140 * // Load from 'pastefromword' plugin 'filter' sub folder (custom.js file) using full path (including CKEditor installation folder).
141 * CKEDITOR.config.pasteFromWordCleanupFile = '/ckeditor/plugins/pastefromword/filter/custom.js';
142 *
143 * // Load custom.js file from 'customFilerts' folder (located in server's root) using full URL.
144 * CKEDITOR.config.pasteFromWordCleanupFile = 'http://my.example.com/customFilerts/custom.js';
145 *
146 * @since 3.1
147 * @cfg {String} [pasteFromWordCleanupFile=<plugin path> + 'filter/default.js']
148 * @member CKEDITOR.config
149 */