diff --git a/CHANGES.md b/CHANGES.md index e81fdf7bc1f..9d57fbde9c5 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -102,7 +102,11 @@ Fixed issues: Fixed Issues: +* [#13232](http://dev.ckeditor.com/ticket/13232): [Safari] Fixed: Method [`element.appendText()`](http://docs.ckeditor.com/#!/api/CKEDITOR.dom.element-method-appendText) work properly for empty elements. +* [#13233](http://dev.ckeditor.com/ticket/13233): Fixed: HTMLDataProcessor can process `foo:href` attributes. * [#12899](http://dev.ckeditor.com/ticket/12899): Fixed: Corrected wrong tag ending for horizontal box definition in the [Dialog User Interface](http://ckeditor.com/addon/dialogui) plugin. Thanks to [mizafish](https://github.com/mizafish)! +* [#13254](http://dev.ckeditor.com/ticket/13254): Fixed: Cannot outdent block after indent when using [Divarea](http://ckeditor.com/addon/divarea) plugin. Thanks to [Jonathan Cottrill](https://github.com/jcttrll)! +* [#13268](http://dev.ckeditor.com/ticket/13268): Fixed: Documentation for `CKEDITOR.dom.text` is incorrect. Thanks to [Ben Kiefer](https://github.com/benkiefer)! * [#12796](http://dev.ckeditor.com/ticket/12796): Fixed: The [Indent List](http://ckeditor.com/addon/indentlist) plugin unwraps parent `
  • ` elements. * [#12885](http://dev.ckeditor.com/ticket/12885): Added missing [`editor.getData()`](http://docs.ckeditor.com/#!/api/CKEDITOR.editor-method-getData) parameter documentation. * [#11982](http://dev.ckeditor.com/ticket/11982): Bullet added in wrong position after the *Enter* key is pressed in a nested list. @@ -112,11 +116,14 @@ Fixed Issues: * [#13031](http://dev.ckeditor.com/ticket/13031): [Firefox] Fixed: No more line breaks in source view since Firefox 36. * [#13131](http://dev.ckeditor.com/ticket/13131): Fixed: The [Code Snippet](http://ckeditor.com/addon/codesnippet) plugin cannot be used without the [IFrame Editing Area](http://ckeditor.com/addon/wysiwygarea) plugin. * [#9086](http://dev.ckeditor.com/ticket/9086): Fixed: Invalid ARIA property used on paste iframe. +* [#13164](http://dev.ckeditor.com/ticket/13164): Fixed: Error when inserting a hidden field. Other Changes: * [#12844](http://dev.ckeditor.com/ticket/12844) and [#13103](http://dev.ckeditor.com/ticket/13103): Upgraded the [testing environment](http://docs.ckeditor.com/#!/guide/dev_tests) to [Bender.js](https://github.com/benderjs/benderjs) `0.2.3`. * [#12930](http://dev.ckeditor.com/ticket/12930): Because of licenses, removed `truncated-mathjax/` from the `tests/` directory. Now `bender.config.mathJaxLibPath` must be configured manually in order to run MathJax plugin's tests. +* [#13266](http://dev.ckeditor.com/ticket/13266): Added more shades of gray. + ## CKEditor 4.4.7 diff --git a/core/dom/element.js b/core/dom/element.js index cfc620d17e5..c5e057e6981 100644 --- a/core/dom/element.js +++ b/core/dom/element.js @@ -267,10 +267,11 @@ CKEDITOR.dom.element.clearMarkers = function( database, element, removeFromDatab * // Result: '

    This is some text

    ' * * @param {String} text The text to be appended. - * @returns {CKEDITOR.dom.node} The appended node. */ appendText: function( text ) { - if ( this.$.text != null ) + // On IE8 it is impossible to append node to script tag, so we use its text. + // On the contrary, on Safari the text property is unpredictable in links. (#13232) + if ( this.$.text != null && CKEDITOR.env.ie && CKEDITOR.env.version < 9 ) this.$.text += text; else this.append( new CKEDITOR.dom.text( text ) ); diff --git a/core/dom/text.js b/core/dom/text.js index 3648c64c13d..7c403f90647 100644 --- a/core/dom/text.js +++ b/core/dom/text.js @@ -12,9 +12,9 @@ * Represents a DOM text node. * * var nativeNode = document.createTextNode( 'Example' ); - * var text = CKEDITOR.dom.text( nativeNode ); + * var text = new CKEDITOR.dom.text( nativeNode ); * - * var text = CKEDITOR.dom.text( 'Example' ); + * var text = new CKEDITOR.dom.text( 'Example' ); * * @class * @extends CKEDITOR.dom.node diff --git a/core/htmldataprocessor.js b/core/htmldataprocessor.js index 928975e3872..51d1d1f6bcd 100644 --- a/core/htmldataprocessor.js +++ b/core/htmldataprocessor.js @@ -772,7 +772,7 @@ // 'data-x' => '<a href="X"' // // which, can be easily filtered out (#11508). - protectAttributeRegex = /([\w-]+)\s*=\s*(?:(?:"[^"]*")|(?:'[^']*')|(?:[^ "'>]+))/gi, + protectAttributeRegex = /([\w-:]+)\s*=\s*(?:(?:"[^"]*")|(?:'[^']*')|(?:[^ "'>]+))/gi, protectAttributeNameRegex = /^(href|src|name)$/i; // Note: we use lazy star '*?' to prevent eating everything up to the last occurrence of or . diff --git a/plugins/colordialog/dialogs/colordialog.js b/plugins/colordialog/dialogs/colordialog.js index ab66a925035..152423ab7fd 100644 --- a/plugins/colordialog/dialogs/colordialog.js +++ b/plugins/colordialog/dialogs/colordialog.js @@ -236,14 +236,12 @@ CKEDITOR.dialog.add( 'colordialog', function( editor ) { oRow.setAttribute( 'role', 'row' ); // Create the gray scale colors cells. - for ( var n = 0; n < 6; n++ ) { - appendColorCell( oRow.$, '#' + aColors[ n ] + aColors[ n ] + aColors[ n ] ); - } - - // Fill the row with black cells. - for ( var i = 0; i < 12; i++ ) { - appendColorCell( oRow.$, '#000000' ); + appendColorCell( oRow.$, '#000000' ); + for ( var n = 0; n < 16; n++ ) { + var c = n.toString( 16 ); + appendColorCell( oRow.$, '#' + c + c + c + c + c + c ); } + appendColorCell( oRow.$, '#ffffff' ); } var numbering = function( id ) { diff --git a/plugins/forms/dialogs/hiddenfield.js b/plugins/forms/dialogs/hiddenfield.js index 2caa8152ff6..65c259c2f60 100644 --- a/plugins/forms/dialogs/hiddenfield.js +++ b/plugins/forms/dialogs/hiddenfield.js @@ -26,8 +26,9 @@ CKEDITOR.dialog.add( 'hiddenfield', function( editor ) { onOk: function() { var name = this.getValueOf( 'info', '_cke_saved_name' ), editor = this.getParentEditor(), - elementHtml = ( CKEDITOR.document.$.documentMode < 8 ? '' : 'input' ), - element = CKEDITOR.env.ie && editor.document.createElement( elementHtml ); + element = CKEDITOR.env.ie && CKEDITOR.document.$.documentMode < 8 ? + editor.document.createElement( '' ) : + editor.document.createElement( 'input' ); element.setAttribute( 'type', 'hidden' ); this.commitContent( element ); diff --git a/plugins/indentblock/plugin.js b/plugins/indentblock/plugin.js index 0e4f043bc5c..63bb70bf147 100644 --- a/plugins/indentblock/plugin.js +++ b/plugins/indentblock/plugin.js @@ -53,7 +53,9 @@ // Switch context from somewhere inside list item to list item, // if not found just assign self (doing nothing). if ( !firstBlock.is( $listItem ) ) { - firstBlock = firstBlock.getAscendant( $listItem ) || firstBlock; + var ascendant = firstBlock.getAscendant( $listItem ); + + firstBlock = ( ascendant && path.contains( ascendant ) ) || firstBlock; } // Switch context from list item to list diff --git a/tests/_benderjs/ckeditor/static/tools.js b/tests/_benderjs/ckeditor/static/tools.js index c4d6f5852f2..c30507a8fff 100644 --- a/tests/_benderjs/ckeditor/static/tools.js +++ b/tests/_benderjs/ckeditor/static/tools.js @@ -271,7 +271,7 @@ if ( fixStyles ) { html = html.replace( / style="([^"]+)"/g, function( match, style ) { - style = CKEDITOR.tools.writeCssText( CKEDITOR.tools.parseCssText( style, true ) ); + style = CKEDITOR.tools.writeCssText( CKEDITOR.tools.parseCssText( style, true ), true ); // Encode e.g. "" in urls(). style = CKEDITOR.tools.htmlEncodeAttr( style ); diff --git a/tests/core/dom/element/element.js b/tests/core/dom/element/element.js index ad75b6880f9..caf46e05495 100644 --- a/tests/core/dom/element/element.js +++ b/tests/core/dom/element/element.js @@ -133,6 +133,13 @@ bender.test( appendDomObjectTests( assert.areEqual( 'Test appendText', element.$.text ); }, + // #13232 + 'test appendText to link': function() { + var element = newElement( 'a' ); + element.appendText( '@' ); + assert.areEqual( '@', element.getText() ); + }, + test_setHtml: function() { var element = newElement( document.getElementById( 'append' ) ); element.setHtml( 'Test' ); diff --git a/tests/core/dom/range/misc.js b/tests/core/dom/range/misc.js index 1b0dd7516e7..522f7e74b15 100644 --- a/tests/core/dom/range/misc.js +++ b/tests/core/dom/range/misc.js @@ -255,10 +255,27 @@ assert.areEqual( '
    te[xt
    ]x
    ', bender.tools.getHtmlWithRanges( playground, new CKEDITOR.dom.rangeList( [ range ] ) ) ); }, + 'test clone': function() { + var range = new CKEDITOR.dom.range( doc ); + + range.selectNodeContents( doc.getBody() ); + + var range2 = range.clone(); + + assert.areSame( range.root, range2.root, 'root' ); + assert.areSame( range.startContainer, range2.startContainer, 'startContainer' ); + assert.areSame( range.endContainer, range2.endContainer, 'endContainer' ); + assert.areSame( range.startOffset, range2.startOffset, 'startOffset' ); + assert.areSame( range.endOffset, range2.endOffset, 'endOffset' ); + assert.areSame( range.collapsed, range2.collapsed, 'collapsed' ); + }, + 'test _setStartContainer': function() { var range = new CKEDITOR.dom.range( doc ), start = new CKEDITOR.dom.element( 'a', doc ); + doc.getBody().append( start ); + range._setStartContainer( start ); assert.areSame( start, range.startContainer ); }, @@ -267,6 +284,8 @@ var range = new CKEDITOR.dom.range( doc ), end = new CKEDITOR.dom.element( 'a', doc ); + doc.getBody().append( end ); + range._setEndContainer( end ); assert.areSame( end, range.endContainer ); } diff --git a/tests/core/htmldataprocessor.js b/tests/core/htmldataprocessor.js index 290944abd67..9cfb1fcd9b5 100644 --- a/tests/core/htmldataprocessor.js +++ b/tests/core/htmldataprocessor.js @@ -498,6 +498,12 @@ } }, + // #13233 + 'test don\'t protect foo:href attributes': function() { + assert.areSame( 'foo', + bender.tools.fixHtml( this.editor.dataProcessor.toHtml( 'foo' ) ) ); + }, + // #4243 'test custom protected source': function() { var source = '

    someprotectedtext

    '; diff --git a/tests/core/style/applyremove.js b/tests/core/style/applyremove.js index c70d9778f93..189a9475a59 100644 --- a/tests/core/style/applyremove.js +++ b/tests/core/style/applyremove.js @@ -24,10 +24,29 @@ return style; } + function getHtml( element ) { + var html = element.getHtml(); + + // Fill empty inline elements with '#', because otherwise they are gonna be lost during processing :(. + html = html.replace( /<(\w)><\/\1>/g, function( match, elementName ) { + elementName = elementName.toLowerCase(); + + if ( elementName in CKEDITOR.dtd.$inline ) { + return '<' + elementName + '>#'; + } else { + return '<' + elementName + '>'; + } + } ); + + return bender.tools.html.prepareInnerHtmlForComparison( html, { + fixStyles: true + } ); + } + function assertAppliedStyle( container, range, definitionOrStyle, expectedOutput ) { getStyle( definitionOrStyle ).applyToRange( range ); - assert.areSame( expectedOutput, makeShortcuts( getInnerHtml( container ) ) ); + assert.areSame( expectedOutput, makeShortcuts( getHtml( container ) ) ); } function assertAppliedStyle2( container, definitionOrStyle, htmlWithRange, expectedOutput, msg ) { @@ -35,7 +54,7 @@ getStyle( definitionOrStyle ).applyToRange( range ); - assert.areSame( expectedOutput, makeShortcuts( getInnerHtml( container ) ), msg ); + assert.areSame( expectedOutput, makeShortcuts( getHtml( container ) ), msg ); } function assertRemovedStyle2( container, definitionOrStyle, htmlWithRange, expectedOutput, msg ) { @@ -43,7 +62,7 @@ getStyle( definitionOrStyle ).removeFromRange( range ); - assert.areSame( expectedOutput, makeShortcuts( getInnerHtml( container ) ), msg ); + assert.areSame( expectedOutput, makeShortcuts( getHtml( container ) ), msg ); } function createAssertionFunction2( tcs, tcsGroupName, definitionOrStyle, enterMode ) { @@ -136,7 +155,7 @@ }; assertAppliedStyle( playground, range, style, - 'this is some sample text' ); + 'this is some sample text' ); }, test_inline11: function() { @@ -159,7 +178,7 @@ }; assertAppliedStyle( playground, range, style, - 'this is some sample text' ); + 'this is some sample text' ); }, test_inline11b: function() { @@ -183,7 +202,7 @@ assertAppliedStyle( playground, range, { element: 'span', styles: { 'font-size': '1.5em' } }, - 'this is some sample text' ); + 'this is some sample text' ); }, test_inline13: function() { @@ -238,7 +257,7 @@ assertAppliedStyle( playground, range, { element: 'b', styles: { color: 'red', 'font-weight': '700' } }, - 'this is some sample text' ); + 'this is some sample text' ); }, test_inline_nobreak1: function() { @@ -303,7 +322,7 @@ styles: { 'line-height': '18px' } }; - assertAppliedStyle( playground, range, style, 'foo' ); + assertAppliedStyle( playground, range, style, 'foo' ); }, test_ticket_2040: function() { @@ -314,7 +333,7 @@ range.setEnd( playground.getChild( 1 ).getFirst(), 6 ); assertAppliedStyle( playground, range, { element: 'i' }, - 'this is some sample text<\/strong>. you are using ckeditor<\/a>.' ); + 'This is some sample text<\/strong>. You are using ckeditor<\/a>.' ); }, test_ticket_3091: function() { @@ -498,7 +517,7 @@ if ( !CKEDITOR.env.needsBrFiller ) assert.ignore(); - assertAppliedStyle2( playground, { element: 'h1' }, '

    []

    ', '


    ' ); + assertAppliedStyle2( playground, { element: 'h1' }, '

    []

    ', '


    ' ); } }; @@ -558,8 +577,8 @@ t = createAssertionFunction2( tcs, 'test apply inline style - single element', { element: 'b' } ); - t.a( '

    x

    a{}b

    x

    ', '

    x

    ab

    x

    ', 'tc1a' ); - t.a( '

    x

    a[]b

    x

    ', '

    x

    ab

    x

    ', 'tc1b' ); + t.a( '

    x

    a{}b

    x

    ', '

    x

    a#b

    x

    ', 'tc1a' ); + t.a( '

    x

    a[]b

    x

    ', '

    x

    a#b

    x

    ', 'tc1b' ); t.a( '

    x

    {ab}

    x

    ', '

    x

    ab

    x

    ', 'tc2a' ); t.a( '

    x

    [ab]

    x

    ', '

    x

    ab

    x

    ', 'tc2b' ); t.a( '

    {x

    a}b

    x

    ', '

    x

    ab

    x

    ', 'tc3' ); @@ -638,14 +657,14 @@ t.a( '

    {this is some sample} text

    ', '

    this is some sample text

    ', 'tc2.1' ); // This behavior is broken. We keep this TC as a backwards compat test. t.a( '

    {this is some sample} text

    ', - '

    this is some sample text

    ', 'tc2.2' ); + '

    this is some sample text

    ', 'tc2.2' ); t.a( '

    {this is some sample} text

    ', '

    this is some sample text

    ', 'tc3.1' ); t.a( '

    {this is some sample} text

    ', '

    this is some sample text

    ', 'tc3.2' ); t.a( '

    {this is some sample} text

    ', '

    this is some sample text

    ', 'tc3.3' ); // This behavior is broken. We keep this TC as a backwards compat test. t.a( '

    {this is some sample} text

    ', - '

    this is some sample text

    ', 'tc3.4' ); + '

    this is some sample text

    ', 'tc3.4' ); t = createAssertionFunction2( tcs, 'test apply inline style - override style with attrs/styles - collisions', @@ -659,22 +678,22 @@ } ); - t.a( '

    {this is some sample} text

    ', '

    this is some sample text

    ', 'tc1.1' ); - t.a( '

    {this is some sample} text

    ', '

    this is some sample text

    ', 'tc1.2' ); - t.a( '

    {this is some sample} text

    ', '

    this is some sample text

    ', 'tc1.3' ); + t.a( '

    {this is some sample} text

    ', '

    this is some sample text

    ', 'tc1.1' ); + t.a( '

    {this is some sample} text

    ', '

    this is some sample text

    ', 'tc1.2' ); + t.a( '

    {this is some sample} text

    ', '

    this is some sample text

    ', 'tc1.3' ); t.a( '

    {this is some sample} text

    ', - '

    this is some sample text

    ', 'tc1.4' ); + '

    this is some sample text

    ', 'tc1.4' ); - t.a( '

    {this is some sample} text

    ', '

    this is some sample text

    ', 'tc2.1' ); + t.a( '

    {this is some sample} text

    ', '

    this is some sample text

    ', 'tc2.1' ); t.a( '

    {this is some sample} text

    ', - '

    this is some sample text

    ', 'tc2.2' ); + '

    this is some sample text

    ', 'tc2.2' ); - t.a( '

    {this is some sample} text

    ', '

    this is some sample text

    ', 'tc3.1' ); - t.a( '

    {this is some sample} text

    ', '

    this is some sample text

    ', 'tc3.2' ); + t.a( '

    {this is some sample} text

    ', '

    this is some sample text

    ', 'tc3.1' ); + t.a( '

    {this is some sample} text

    ', '

    this is some sample text

    ', 'tc3.2' ); t.a( '

    {this is some sample} text

    ', - '

    this is some sample text

    ', 'tc3.3' ); + '

    this is some sample text

    ', 'tc3.3' ); t.a( '

    {this is some sample} text

    ', - '

    this is some sample text

    ', 'tc3.4' ); + '

    this is some sample text

    ', 'tc3.4' ); t = createAssertionFunction2( tcs, 'test remove inline style - override style with attrs/styles', @@ -698,7 +717,7 @@ t.r( '

    {this is some sample} text

    ', '

    this is some sample text

    ', 'tc2.1' ); // This behavior is broken. We keep this TC as a backwards compat test. t.r( '

    {this is some sample} text

    ', - '

    this is some sample text

    ', 'tc2.2' ); + '

    this is some sample text

    ', 'tc2.2' ); // Compare with tc2.1... t.r( '

    {this is some sample} text

    ', '

    this is some sample text

    ', 'tc3.1' ); @@ -706,7 +725,7 @@ t.r( '

    {this is some sample} text

    ', '

    this is some sample text

    ', 'tc3.3' ); // This behavior is broken. We keep this TC as a backwards compat test. t.r( '

    {this is some sample} text

    ', - '

    this is some sample text

    ', 'tc3.4' ); + '

    this is some sample text

    ', 'tc3.4' ); t = createAssertionFunction2( tcs, 'test remove inline style - strictly matches overrides or the style', @@ -756,7 +775,7 @@ t.a( '

    {this is some sample} text

    ', '

    this is some sample text

    ', 'tc2' ); t.a( '

    {this is some sample} text

    ', '

    this is some sample text

    ', 'tc3' ); t.a( '

    {this is some sample} text

    ', - '

    this is some sample text

    ', 'tc4' ); + '

    this is some sample text

    ', 'tc4' ); t = createAssertionFunction2( tcs, 'test remove inline style - override similar style', @@ -771,13 +790,13 @@ // Compare with the previous section... t.r( '

    this {is some sample} text

    ', '

    this is some sample text

    ', 'tc1.3' ); t.r( '

    this {is some sample} text

    ', - '

    this is some sample text

    ', 'tc1.4' ); + '

    this is some sample text

    ', 'tc1.4' ); t.r( '

    {this is some sample} text

    ', '

    this is some sample text

    ', 'tc2.1' ); t.r( '

    {this is some sample} text

    ', '

    this is some sample text

    ', 'tc2.2' ); t.r( '

    {this is some sample} text

    ', '

    this is some sample text

    ', 'tc2.3' ); t.r( '

    {this is some sample} text

    ', - '

    this is some sample text

    ', 'tc2.4' ); + '

    this is some sample text

    ', 'tc2.4' ); // diff --git a/tests/tickets/13254/1.html b/tests/tickets/13254/1.html new file mode 100644 index 00000000000..5f8ca7a845c --- /dev/null +++ b/tests/tickets/13254/1.html @@ -0,0 +1,7 @@ +
    +
      +
    • + +
    • +
    +
    diff --git a/tests/tickets/13254/1.js b/tests/tickets/13254/1.js new file mode 100644 index 00000000000..bd1b4e28c7b --- /dev/null +++ b/tests/tickets/13254/1.js @@ -0,0 +1,30 @@ +/* bender-tags: indent,indentblock */ +/* bender-ckeditor-plugins: button,indent,indentblock,divarea */ + +'use strict'; + +bender.editor = { + creator: 'replace', + name: 'editor' +}; + +bender.test( { + 'test indenting and outdenting block in divarea plugin container inside li': function() { + var editor = this.editor; + editor.focus(); + bender.tools.selection.setWithHtml( editor, '

    hello{}

    ' ); + + assert.areSame( 2, editor.getCommand( 'indent' ).state, 'initial indent state' ); + assert.areSame( 0, editor.getCommand( 'outdent' ).state, 'initial outdent state' ); + + editor.execCommand( 'indent' ); + + assert.areSame( 2, editor.getCommand( 'indent' ).state, 'indent state after indenting' ); + assert.areSame( 2, editor.getCommand( 'outdent' ).state, 'outdent state after indenting' ); + + editor.execCommand( 'outdent' ); + + assert.areSame( 2, editor.getCommand( 'indent' ).state, 'indent state after outdenting' ); + assert.areSame( 0, editor.getCommand( 'outdent' ).state, 'outdent state after outdenting' ); + } +} ); diff --git a/tests/tickets/13254/2.html b/tests/tickets/13254/2.html new file mode 100644 index 00000000000..b9a34a53f29 --- /dev/null +++ b/tests/tickets/13254/2.html @@ -0,0 +1,13 @@ +
    +
      +
    • + +
    • +
    +
    + + \ No newline at end of file diff --git a/tests/tickets/13254/2.md b/tests/tickets/13254/2.md new file mode 100644 index 00000000000..fabe5edc755 --- /dev/null +++ b/tests/tickets/13254/2.md @@ -0,0 +1,8 @@ +@bender-tags: 4.4.8, tc +@bender-ui: collapsed +@bender-tags: indent,indentblock + +1. Indent block. + * Expected: Outdent button is not disabled. +2. Outent block. + * Expected: It worked. \ No newline at end of file