Ticket #7131: 7131_2.patch

File 7131_2.patch, 13.7 KB (added by Garry Yao, 9 years ago)
  • _source/plugins/pastefromword/filter/default.js

     
    118118                return result;
    119119        };
    120120
     121        // Move list item styles up to list root if they're consistent.
     122        function mergeListStyleType( list )
     123        {
     124                var children = list.children,
     125                        attrs,
     126                        count = list.children.length,
     127                        match,
     128                        mergeStyle,
     129                        styleTypeRegexp = /list-style-type:(.*?)(?:;|$)/,
     130                        stylesFilter = CKEDITOR.plugins.pastefromword.filters.stylesFilter;
     131
     132                attrs = list.attributes;
     133                if ( styleTypeRegexp.exec( attrs.style ) )
     134                        return;
     135
     136                for ( var i = 0; i < count; i++ )
     137                {
     138                        match = styleTypeRegexp.exec( children[ i ].attributes.style );
     139
     140                        if ( match )
     141                        {
     142                                if ( match[ 1 ] == mergeStyle || !mergeStyle )
     143                                        mergeStyle = match[ 1 ];
     144                                else
     145                                {
     146                                        mergeStyle = null;
     147                                        break;
     148                                }
     149                        }
     150                }
     151
     152                if ( mergeStyle )
     153                {
     154                        for ( i = 0; i < count; i++ )
     155                        {
     156                                attrs = children[ i ].attributes;
     157                                attrs.style = stylesFilter( [ [ 'list-style-type'] ] )( attrs.style ) || ''
     158                        }
     159
     160                        list.addStyle( 'list-style-type', mergeStyle );
     161                }
     162        }
     163
    121164        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;
    122165        var emptyMarginRegex = /^(?:\b0[^\s]*\s*){1,4}$/;               // e.g. 0px 0pt 0px
    123166        var romanLiternalPattern = '^m{0,4}(cm|cd|d?c{0,3})(xc|xl|l?x{0,3})(ix|iv|v?i{0,3})$',
    124167                lowerRomanLiteralRegex = new RegExp( romanLiternalPattern ),
    125168                upperRomanLiteralRegex = new RegExp( romanLiternalPattern.toUpperCase() );
    126169
    127         var listBaseIndent = 0,
    128                  previousListItemMargin;
     170        var orderedPatterns = { 'decimal' : /\d+/, 'lower-roman': lowerRomanLiteralRegex, 'upper-roman': upperRomanLiteralRegex, 'lower-alpha' : /^[a-z]+$/, 'upper-alpha': /^[A-Z]+$/ },
     171                unorderedPatterns = { 'disc' : /[l\u00B7\u2002]/, 'circle' : /[\u006F\u00D8]/,'square' : /[\u006E\u25C6]/},
     172                listMarkerPatterns = { 'ol' : orderedPatterns, 'ul' : unorderedPatterns },
     173                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'] ],
     174                alpahbets = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
    129175
    130         CKEDITOR.plugins.pastefromword =
    131         {
    132                 utils :
    133                 {
    134                         // Create a <cke:listbullet> which indicate an list item type.
    135                         createListBulletMarker : function ( bulletStyle, bulletText )
    136                         {
    137                                 var marker = new CKEDITOR.htmlParser.element( 'cke:listbullet' ),
    138                                         listType;
     176        // Convert roman numbering back to decimal.
     177        function fromRoman( str )
     178         {
     179                 str = str.toUpperCase();
     180                 var l = romans.length, retVal = 0;
     181                 for ( var i = 0; i < l; ++i )
     182                 {
     183                         for ( var j = romans[i], k = j[1].length; str.substr( 0, k ) == j[1]; str = str.substr( k ) )
     184                                 retVal += j[ 0 ];
     185                 }
     186                 return retVal;
     187         }
    139188
    140                                 // TODO: Support more list style type from MS-Word.
    141                                 if ( !bulletStyle )
    142                                 {
    143                                         bulletStyle = 'decimal';
    144                                         listType = 'ol';
    145                                 }
    146                                 else if ( bulletStyle[ 2 ] )
    147                                 {
    148                                         if ( !isNaN( bulletStyle[ 1 ] ) )
    149                                                 bulletStyle = 'decimal';
    150                                         else if ( lowerRomanLiteralRegex.test( bulletStyle[ 1 ] ) )
    151                                                 bulletStyle = 'lower-roman';
    152                                         else if ( upperRomanLiteralRegex.test( bulletStyle[ 1 ] ) )
    153                                                 bulletStyle = 'upper-roman';
    154                                         else if ( /^[a-z]+$/.test( bulletStyle[ 1 ] ) )
    155                                                 bulletStyle = 'lower-alpha';
    156                                         else if ( /^[A-Z]+$/.test( bulletStyle[ 1 ] ) )
    157                                                 bulletStyle = 'upper-alpha';
    158                                         // Simply use decimal for the rest forms of unrepresentable
    159                                         // numerals, e.g. Chinese...
    160                                         else
    161                                                 bulletStyle = 'decimal';
    162 
    163                                         listType = 'ol';
    164                                 }
    165                                 else
    166                                 {
    167                                         if ( /[l\u00B7\u2002]/.test( bulletStyle[ 1 ] ) )
    168                                                 bulletStyle = 'disc';
    169                                         else if ( /[\u006F\u00D8]/.test( bulletStyle[ 1 ] ) )
    170                                                 bulletStyle = 'circle';
    171                                         else if ( /[\u006E\u25C6]/.test( bulletStyle[ 1 ] ) )
    172                                                 bulletStyle = 'square';
    173                                         else
    174                                                 bulletStyle = 'disc';
    175 
    176                                         listType = 'ul';
    177                                 }
     189        // Convert alphabet numbering back to decimal.
     190        function fromAlphabet( str )
     191        {
     192                str = str.toUpperCase();
     193                var l = alpahbets.length, retVal = 1;
     194                for ( var x = 1; str.length > 0; x *= l )
     195                {
     196                        retVal += alpahbets.indexOf( str.charAt( str.length - 1 ) ) * x;
     197                        str = str.substr( 0, str.length - 1 );
     198                }
     199                return retVal;
     200        }
    178201
    179                                 // Represent list type as CSS style.
    180                                 marker.attributes =
    181                                 {
    182                                         'cke:listtype' : listType,
    183                                         'style' : 'list-style-type:' + bulletStyle + ';'
    184                                 };
     202        var listBaseIndent = 0,
     203                previousListItemMargin;
     204
     205        CKEDITOR.plugins.pastefromword =
     206        {
     207                utils :
     208                {
     209                        // Create a <cke:listbullet> which indicate an list item type.
     210                        createListBulletMarker : function ( bullet, bulletText )
     211                        {
     212                                var marker = new CKEDITOR.htmlParser.element( 'cke:listbullet' );
     213                                marker.attributes = { 'cke:listsymbol' : bullet[ 0 ] };
    185214                                marker.add( new CKEDITOR.htmlParser.text( bulletText ) );
    186215                                return marker;
    187216                        },
     
    236265                                                        ] )( attrs.style, element ) || '' ;
    237266                                        }
    238267
    239                                         // Inherit list-type-style from bullet.
    240                                         var listBulletAttrs = listMarker.attributes,
    241                                                 listBulletStyle = listBulletAttrs.style;
    242 
    243                                         element.addStyle( listBulletStyle );
    244                                         CKEDITOR.tools.extend( attrs, listBulletAttrs );
     268                                        CKEDITOR.tools.extend( attrs, listMarker.attributes );
    245269                                        return true;
    246270                                }
    247271
     
    371395                                        var children = element.children, child,
    372396                                                        listItem,   // The current processing cke:li element.
    373397                                                        listItemAttrs,
    374                                                         listType,   // Determine the root type of the list.
    375398                                                        listItemIndent, // Indent level of current list item.
     399                                                        lastIndent,
    376400                                                        lastListItem, // The previous one just been added to the list.
    377                                                         list, parentList, // Current staging list and it's parent list if any.
    378                                                         indent;
     401                                                        list, // Current staging list and it's parent list if any.
     402                                                        openedLists = [],
     403                                                        previousListStyleType,
     404                                                        previousListType,
     405                                                        previousNumeric;
    379406
     407                                        // Properties of the list item are to be resolved from the list bullet.
     408                                        var bullet,
     409                                                listType,
     410                                                listStyleType,
     411                                                itemNumeric;
     412
    380413                                        for ( var i = 0; i < children.length; i++ )
    381414                                        {
    382415                                                child = children[ i ];
     
    386419                                                        child.name = 'li';
    387420                                                        listItem = child;
    388421                                                        listItemAttrs = listItem.attributes;
    389                                                         listType = listItem.attributes[ 'cke:listtype' ];
     422                                                        bullet = listItemAttrs[ 'cke:listsymbol' ].match( /^([^\s]+?)([.)]?)$/ );
     423                                                        listType = listStyleType = itemNumeric = null;
    390424
    391425                                                        // List item indent level might come from a real list indentation or
    392426                                                        // been resolved from a pseudo list item's margin value, even get
    393427                                                        // no indentation at all.
    394428                                                        listItemIndent = parseInt( listItemAttrs[ 'cke:indent' ], 10 )
    395                                                                                                         || listBaseIndent && ( Math.ceil( listItemAttrs[ 'cke:margin' ] / listBaseIndent ) )
    396                                                                                                         || 1;
     429                                                                        || listBaseIndent && ( Math.ceil( listItemAttrs[ 'cke:margin' ] / listBaseIndent ) )
     430                                                                        || 1;
    397431
    398                                                         // Ignore the 'list-style-type' attribute if it's matched with
    399                                                         // the list root element's default style type.
    400                                                         listItemAttrs.style && ( listItemAttrs.style =
    401                                                                 CKEDITOR.plugins.pastefromword.filters.stylesFilter(
    402                                                                         [
    403                                                                                 [ 'list-style-type', listType == 'ol' ? 'decimal' : 'disc' ]
    404                                                                         ] )( listItemAttrs.style )
    405                                                                         || '' );
     432                                                        // We're moving out of the current list, cleaning up.
     433                                                        if ( listItemIndent != lastIndent )
     434                                                                previousListType = previousListStyleType = previousNumeric = null;
    406435
     436                                                        if ( !bullet )
     437                                                        {
     438                                                                listType = 'ol';
     439                                                                listStyleType = 'decimal';
     440                                                        }
     441                                                        else
     442                                                        {
     443                                                                // Probably share the same list style type with previous list item,
     444                                                                // give it priority to avoid ambiguous between C(Alpha) and C.(Roman).
     445                                                                if ( previousListType && listMarkerPatterns[ previousListType ] [ previousListStyleType ].test( bullet[ 1 ] ) )
     446                                                                {
     447                                                                        listType = previousListType;
     448                                                                        listStyleType = previousListStyleType;
     449                                                                }
     450                                                                else
     451                                                                {
     452                                                                        for ( var type in listMarkerPatterns )
     453                                                                        {
     454                                                                                for ( var style in listMarkerPatterns[ type ] )
     455                                                                                {
     456                                                                                        if ( listMarkerPatterns[ type ][ style ].test( bullet[ 1 ] ) )
     457                                                                                        {
     458                                                                                                // Small numbering has higher priority, when dealing with ambiguous
     459                                                                                                // between C(Alpha) and C.(Roman).
     460                                                                                                if ( type == 'ol' && /alpha|roman/.test( style ) )
     461                                                                                                {
     462                                                                                                        var num = /roman/.test( style ) ? fromRoman( bullet[ 1 ] ) : fromAlphabet( bullet[ 1 ] );
     463                                                                                                        if ( !itemNumeric || num < itemNumeric )
     464                                                                                                        {
     465                                                                                                                itemNumeric = num;
     466                                                                                                                listType = type;
     467                                                                                                                listStyleType = style;
     468                                                                                                        }
     469                                                                                                }
     470                                                                                                else
     471                                                                                                {
     472                                                                                                        listType = type;
     473                                                                                                        listStyleType = style;
     474                                                                                                        break;
     475                                                                                                }
     476                                                                                        }
     477                                                                                }
     478                                                                        }
     479                                                                }
     480
     481                                                                // Simply use decimal/disc for the rest forms of unrepresentable
     482                                                                // numerals, e.g. Chinese..., but as long as there a second part
     483                                                                // included, it has a bigger chance of being a order list ;)
     484                                                                !listType && ( listType = bullet[ 2 ] ? 'ol' : 'ul' );
     485                                                        }
     486
     487                                                        previousListType = listType;
     488                                                        previousListStyleType = listStyleType || ( listType == 'ol' ? 'decimal' : 'disc' );
     489                                                        if ( listStyleType && listStyleType != ( listType == 'ol' ? 'decimal' : 'disc' ) )
     490                                                                listItem.addStyle( 'list-style-type', listStyleType );
     491
     492                                                        // Figure out start numbering.
     493                                                        if ( listType == 'ol' )
     494                                                        {
     495                                                                switch ( listStyleType )
     496                                                                {
     497                                                                        case 'decimal' :
     498                                                                                itemNumeric = bullet[ 1 ];
     499                                                                                break;
     500                                                                        case 'lower-roman':
     501                                                                        case 'upper-roman':
     502                                                                                itemNumeric = fromRoman( bullet[ 1 ] );
     503                                                                                break;
     504                                                                        case 'lower-alpha':
     505                                                                        case 'upper-alpha':
     506                                                                                itemNumeric = fromAlphabet( bullet[ 1 ] );
     507                                                                                break;
     508                                                                }
     509
     510                                                                if ( itemNumeric && itemNumeric != ( previousNumeric ? previousNumeric + 1 : 1 ) )
     511                                                                        listItem.attributes.value = itemNumeric;
     512                                                                previousNumeric = itemNumeric;
     513                                                        }
     514
     515                                                        // Start the list construction.
    407516                                                        if ( !list )
    408517                                                        {
    409                                                                 list = new CKEDITOR.htmlParser.element( listType );
     518                                                                openedLists.push( list = new CKEDITOR.htmlParser.element( listType ) );
    410519                                                                list.add( listItem );
    411520                                                                children[ i ] = list;
    412521                                                        }
    413522                                                        else
    414523                                                        {
    415                                                                 if ( listItemIndent > indent )
     524                                                                if ( listItemIndent > lastIndent )
    416525                                                                {
    417                                                                         list = new CKEDITOR.htmlParser.element( listType );
     526                                                                        openedLists.push( list = new CKEDITOR.htmlParser.element( listType ) );
    418527                                                                        list.add( listItem );
    419528                                                                        lastListItem.add( list );
    420529                                                                }
    421                                                                 else if ( listItemIndent < indent )
     530                                                                else if ( listItemIndent < lastIndent )
    422531                                                                {
    423532                                                                        // There might be a negative gap between two list levels. (#4944)
    424                                                                         var diff = indent - listItemIndent,
    425                                                                                 parent;
     533                                                                        var diff = lastIndent - listItemIndent,
     534                                                                                        parent;
    426535                                                                        while ( diff-- && ( parent = list.parent ) )
    427536                                                                                list = parent.parent;
    428537
     
    435544                                                        }
    436545
    437546                                                        lastListItem = listItem;
    438                                                         indent = listItemIndent;
     547                                                        lastIndent = listItemIndent;
    439548                                                }
    440                                                 else
    441                                                         list = null;
     549                                                else if ( list )
     550                                                        list = lastIndent = lastListItem = null;
    442551                                        }
    443552
     553                                        for ( i = 0; i < openedLists.length; i++ )
     554                                                mergeListStyleType( openedLists[ i ] );
     555
    444556                                        listBaseIndent = 0;
    445557                                },
    446558
     
    807919
    808920                                        'font' : function( element )
    809921                                        {
    810                                                 // IE/Safari: drop the font tag if it comes from list bullet text.
    811                                                 if ( !CKEDITOR.env.gecko && isListBulletIndicator( element.parent ) )
     922                                                // Drop the font tag if it comes from list bullet text.
     923                                                if ( isListBulletIndicator( element.parent ) )
    812924                                                {
    813925                                                        delete element.name;
    814926                                                        return;
     
    859971
    860972                                        'span' : function( element )
    861973                                        {
    862                                                 // IE/Safari: remove the span if it comes from list bullet text.
    863                                                 if ( !CKEDITOR.env.gecko && isListBulletIndicator( element.parent ) )
     974                                                // Remove the span if it comes from list bullet text.
     975                                                if ( isListBulletIndicator( element.parent ) )
    864976                                                        return false;
    865977
    866978                                                element.filterChildren();
     
    870982                                                        return null;
    871983                                                }
    872984
    873                                                 // For IE/Safari: List item bullet type is supposed to be indicated by
     985                                                // List item bullet type is supposed to be indicated by
    874986                                                // the text of a span with style 'mso-list : Ignore' or an image.
    875                                                 if ( !CKEDITOR.env.gecko && isListBulletIndicator( element ) )
     987                                                if ( isListBulletIndicator( element ) )
    876988                                                {
    877989                                                        var listSymbolNode = element.firstChild( function( node )
    878990                                                        {
     
    9491061                                        // Provide a white-list of styles that we preserve, those should
    9501062                                        // be the ones that could later be altered with editor tools.
    9511063                                        [
     1064                                                // Leave list-style-type
     1065                                                [ /^list-style-type$/, null ],
     1066
    9521067                                                // Preserve margin-left/right which used as default indent style in the editor.
    9531068                                                [ ( /^margin$|^margin-(?!bottom|top)/ ), null, function( value, element, name )
    9541069                                                        {
© 2003 – 2019 CKSource – Frederico Knabben. All rights reserved. | Terms of use | Privacy policy