X-Git-Url: https://jasonwoof.com/gitweb/?a=blobdiff_plain;f=_source%2Fplugins%2Fpastefromword%2Ffilter%2Fdefault.js;h=2eb948dab82c44128aaf54e19ff49485f7cd361c;hb=f0610347140239143439a511ee2bd48cb784f470;hp=745bda36cd1d3190cf186022f09072c1e4426a58;hpb=941b0a9ba4e673e292510d80a5a86806994b8ea6;p=ckeditor.git diff --git a/_source/plugins/pastefromword/filter/default.js b/_source/plugins/pastefromword/filter/default.js index 745bda3..2eb948d 100644 --- a/_source/plugins/pastefromword/filter/default.js +++ b/_source/plugins/pastefromword/filter/default.js @@ -1,5 +1,5 @@ /* -Copyright (c) 2003-2010, CKSource - Frederico Knabben. All rights reserved. +Copyright (c) 2003-2011, CKSource - Frederico Knabben. All rights reserved. For licensing, see LICENSE.html or http://ckeditor.com/license */ @@ -25,7 +25,7 @@ For licensing, see LICENSE.html or http://ckeditor.com/license for ( var i = 0; i < children.length; i++ ) { child = children[ i ]; - if( !child.name ) + if ( !child.name ) continue; if ( child.name == tagName ) @@ -60,15 +60,13 @@ For licensing, see LICENSE.html or http://ckeditor.com/license child = child.firstChild( evaluator ); if ( child ) return child; - else - continue; } } return null; }; - // Adding a (set) of styles to the element's attributes. + // Adding a (set) of styles to the element's 'style' attributes. elementPrototype.addStyle = function( name, value, isPrepend ) { var styleText, addingStyleText = ''; @@ -80,9 +78,9 @@ For licensing, see LICENSE.html or http://ckeditor.com/license // style literal. if ( typeof name == 'object' ) { - for( var style in name ) + for ( var style in name ) { - if( name.hasOwnProperty( style ) ) + if ( name.hasOwnProperty( style ) ) addingStyleText += style + ':' + name[ style ] + ';'; } } @@ -93,7 +91,7 @@ For licensing, see LICENSE.html or http://ckeditor.com/license isPrepend = value; } - if( !this.attributes ) + if ( !this.attributes ) this.attributes = {}; styleText = this.attributes.style || ''; @@ -120,65 +118,107 @@ For licensing, see LICENSE.html or http://ckeditor.com/license return result; }; - var cssLengthRelativeUnit = /^(\d[.\d]*)+(em|ex|px|gd|rem|vw|vh|vm|ch|mm|cm|in|pt|pc|deg|rad|ms|s|hz|khz){1}?/i; - var emptyMarginRegex = /^(?:\b0[^\s]*\s*){1,4}$/; + // 1. move consistent list item styles up to list root. + // 2. clear out unnecessary list item numbering. + function postProcessList( list ) + { + var children = list.children, + child, + attrs, + count = list.children.length, + match, + mergeStyle, + styleTypeRegexp = /list-style-type:(.*?)(?:;|$)/, + stylesFilter = CKEDITOR.plugins.pastefromword.filters.stylesFilter; + + attrs = list.attributes; + if ( styleTypeRegexp.exec( attrs.style ) ) + return; + + for ( var i = 0; i < count; i++ ) + { + child = children[ i ]; + + if ( child.attributes.value && Number( child.attributes.value ) == i + 1 ) + delete child.attributes.value; + + match = styleTypeRegexp.exec( child.attributes.style ); + + if ( match ) + { + if ( match[ 1 ] == mergeStyle || !mergeStyle ) + mergeStyle = match[ 1 ]; + else + { + mergeStyle = null; + break; + } + } + } + + if ( mergeStyle ) + { + for ( i = 0; i < count; i++ ) + { + attrs = children[ i ].attributes; + attrs.style && ( attrs.style = stylesFilter( [ [ 'list-style-type'] ] )( attrs.style ) || '' ); + } + + list.addStyle( 'list-style-type', mergeStyle ); + } + } + + var cssLengthRelativeUnit = /^([.\d]*)+(em|ex|px|gd|rem|vw|vh|vm|ch|mm|cm|in|pt|pc|deg|rad|ms|s|hz|khz){1}?/i; + var emptyMarginRegex = /^(?:\b0[^\s]*\s*){1,4}$/; // e.g. 0px 0pt 0px + var romanLiternalPattern = '^m{0,4}(cm|cd|d?c{0,3})(xc|xl|l?x{0,3})(ix|iv|v?i{0,3})$', + lowerRomanLiteralRegex = new RegExp( romanLiternalPattern ), + upperRomanLiteralRegex = new RegExp( romanLiternalPattern.toUpperCase() ); + + var orderedPatterns = { 'decimal' : /\d+/, 'lower-roman': lowerRomanLiteralRegex, 'upper-roman': upperRomanLiteralRegex, 'lower-alpha' : /^[a-z]+$/, 'upper-alpha': /^[A-Z]+$/ }, + unorderedPatterns = { 'disc' : /[l\u00B7\u2002]/, 'circle' : /[\u006F\u00D8]/,'square' : /[\u006E\u25C6]/}, + listMarkerPatterns = { 'ol' : orderedPatterns, 'ul' : unorderedPatterns }, + 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'] ], + alpahbets = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"; + + // Convert roman numbering back to decimal. + function fromRoman( str ) + { + str = str.toUpperCase(); + var l = romans.length, retVal = 0; + for ( var i = 0; i < l; ++i ) + { + for ( var j = romans[i], k = j[1].length; str.substr( 0, k ) == j[1]; str = str.substr( k ) ) + retVal += j[ 0 ]; + } + return retVal; + } + + // Convert alphabet numbering back to decimal. + function fromAlphabet( str ) + { + str = str.toUpperCase(); + var l = alpahbets.length, retVal = 1; + for ( var x = 1; str.length > 0; x *= l ) + { + retVal += alpahbets.indexOf( str.charAt( str.length - 1 ) ) * x; + str = str.substr( 0, str.length - 1 ); + } + return retVal; + } var listBaseIndent = 0, - previousListItemMargin; + previousListItemMargin = null, + previousListId; - CKEDITOR.plugins.pastefromword = + var plugin = ( CKEDITOR.plugins.pastefromword = { utils : { // Create a which indicate an list item type. - createListBulletMarker : function ( bulletStyle, bulletText ) + createListBulletMarker : function ( bullet, bulletText ) { - var marker = new CKEDITOR.htmlParser.element( 'cke:listbullet' ), - listType; - - // TODO: Support more list style type from MS-Word. - if ( !bulletStyle ) - { - bulletStyle = 'decimal'; - listType = 'ol'; - } - else if ( bulletStyle[ 2 ] ) - { - if ( !isNaN( bulletStyle[ 1 ] ) ) - bulletStyle = 'decimal'; - // No way to distinguish between Roman numerals and Alphas, - // detect them as a whole. - else if ( /^[a-z]+$/.test( bulletStyle[ 1 ] ) ) - bulletStyle = 'lower-alpha'; - else if ( /^[A-Z]+$/.test( bulletStyle[ 1 ] ) ) - bulletStyle = 'upper-alpha'; - // Simply use decimal for the rest forms of unrepresentable - // numerals, e.g. Chinese... - else - bulletStyle = 'decimal'; - - listType = 'ol'; - } - else - { - if ( /[l\u00B7\u2002]/.test( bulletStyle[ 1 ] ) ) //l·• - bulletStyle = 'disc'; - else if ( /[\u006F\u00D8]/.test( bulletStyle[ 1 ] ) ) //oØ - bulletStyle = 'circle'; - else if ( /[\u006E\u25C6]/.test( bulletStyle[ 1 ] ) ) //n◆ - bulletStyle = 'square'; - else - bulletStyle = 'disc'; - - listType = 'ul'; - } - - // Represent list type as CSS style. - marker.attributes = - { - 'cke:listtype' : listType, - 'style' : 'list-style-type:' + bulletStyle + ';' - }; + var marker = new CKEDITOR.htmlParser.element( 'cke:listbullet' ); + marker.attributes = { 'cke:listsymbol' : bullet[ 0 ] }; marker.add( new CKEDITOR.htmlParser.text( bulletText ) ); return marker; }, @@ -186,7 +226,7 @@ For licensing, see LICENSE.html or http://ckeditor.com/license isListBulletIndicator : function( element ) { var styleText = element.attributes && element.attributes.style; - if( /mso-list\s*:\s*Ignore/i.test( styleText ) ) + if ( /mso-list\s*:\s*Ignore/i.test( styleText ) ) return true; }, @@ -200,73 +240,75 @@ For licensing, see LICENSE.html or http://ckeditor.com/license resolveList : function( element ) { // indicate a list item. - var children = element.children, - attrs = element.attributes, + var attrs = element.attributes, listMarker; if ( ( listMarker = element.removeAnyChildWithName( 'cke:listbullet' ) ) - && listMarker.length - && ( listMarker = listMarker[ 0 ] ) ) + && listMarker.length + && ( listMarker = listMarker[ 0 ] ) ) { element.name = 'cke:li'; if ( attrs.style ) { - attrs.style = CKEDITOR.plugins.pastefromword.filters.stylesFilter( + attrs.style = plugin.filters.stylesFilter( [ // Text-indent is not representing list item level any more. [ 'text-indent' ], [ 'line-height' ], - // Resolve indent level from 'margin-left' value. + // First attempt is to resolve indent level from on a constant margin increment. [ ( /^margin(:?-left)?$/ ), null, function( margin ) { - // Be able to deal with component/short-hand form style. + // Deal with component/short-hand form. var values = margin.split( ' ' ); - margin = values[ 3 ] || values[ 1 ] || values [ 0 ]; - margin = parseInt( margin, 10 ); + margin = CKEDITOR.tools.convertToPx( values[ 3 ] || values[ 1 ] || values [ 0 ] ); - // Figure out the indent unit by looking at the first increament. - if ( !listBaseIndent && previousListItemMargin && margin > previousListItemMargin ) + // Figure out the indent unit by checking the first time of incrementation. + if ( !listBaseIndent && previousListItemMargin !== null && margin > previousListItemMargin ) listBaseIndent = margin - previousListItemMargin; - attrs[ 'cke:margin' ] = previousListItemMargin = margin; + previousListItemMargin = margin; + + attrs[ 'cke:indent' ] = listBaseIndent && ( Math.ceil( margin / listBaseIndent ) + 1 ) || 1; + } ], + // The best situation: "mso-list:l0 level1 lfo2" tells the belonged list root, list item indentation, etc. + [ ( /^mso-list$/ ), null, function( val ) + { + val = val.split( ' ' ); + var listId = Number( val[ 0 ].match( /\d+/ ) ), + indent = Number( val[ 1 ].match( /\d+/ ) ); + + if ( indent == 1 ) + { + listId !== previousListId && ( attrs[ 'cke:reset' ] = 1 ); + previousListId = listId; + } + attrs[ 'cke:indent' ] = indent; } ] - ] )( attrs.style, element ) || '' ; + ] )( attrs.style, element ) || ''; } - // Inherit list-type-style from bullet. - var listBulletAttrs = listMarker.attributes, - listBulletStyle = listBulletAttrs.style; + // First level list item might be presented without a margin. + - element.addStyle( listBulletStyle ); - CKEDITOR.tools.extend( attrs, listBulletAttrs ); + // In case all above doesn't apply. + if ( !attrs[ 'cke:indent' ] ) + { + previousListItemMargin = 0; + attrs[ 'cke:indent' ] = 1; + } + + // Inherit attributes from bullet. + CKEDITOR.tools.extend( attrs, listMarker.attributes ); return true; } + // Current list disconnected. + else + previousListId = previousListItemMargin = listBaseIndent = null; return false; }, - // Convert various length units to 'px' in ignorance of DPI. - convertToPx : ( function () - { - var calculator = CKEDITOR.dom.element.createFromHtml( - '
', CKEDITOR.document ); - CKEDITOR.document.getBody().append( calculator ); - - return function( cssLength ) - { - if( cssLengthRelativeUnit.test( cssLength ) ) - { - calculator.setStyle( 'width', cssLength ); - return calculator.$.clientWidth + 'px'; - } - - return cssLength; - }; - } )(), - // Providing a shorthand style then retrieve one or more style component values. getStyleComponents : ( function() { @@ -296,20 +338,12 @@ For licensing, see LICENSE.html or http://ckeditor.com/license // E.g.