Skip to content
This repository was archived by the owner on Jun 26, 2020. It is now read-only.

Commit d71cad8

Browse files
committed
Fix: ContextualToolbar will accept the object format of config.contextualToolbar. Closes #316.
BREAKING CHANGE: `Toolbar#fillFromConfig()` cannot be now called with an `undefined`. Make sure to use `normalizeToolbarConfig()` to get a reliable object.
1 parent 93feb9c commit d71cad8

File tree

6 files changed

+68
-23
lines changed

6 files changed

+68
-23
lines changed

src/toolbar/contextual/contextualtoolbar.js

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ import ToolbarView from '../toolbarview';
1414
import BalloonPanelView from '../../panel/balloon/balloonpanelview.js';
1515
import debounce from '@ckeditor/ckeditor5-utils/src/lib/lodash/debounce';
1616
import Rect from '@ckeditor/ckeditor5-utils/src/dom/rect';
17+
import normalizeToolbarConfig from '../normalizetoolbarconfig';
1718

1819
/**
1920
* The contextual toolbar.
@@ -89,15 +90,15 @@ export default class ContextualToolbar extends Plugin {
8990

9091
/**
9192
* Creates toolbar components based on given configuration.
92-
* This needs to be done when all plugins will be ready.
93+
* This needs to be done when all plugins are ready.
9394
*
9495
* @inheritDoc
9596
*/
9697
afterInit() {
97-
const config = this.editor.config.get( 'contextualToolbar' );
98+
const config = normalizeToolbarConfig( this.editor.config.get( 'contextualToolbar' ) );
9899
const factory = this.editor.ui.componentFactory;
99100

100-
this.toolbarView.fillFromConfig( config, factory );
101+
this.toolbarView.fillFromConfig( config.items, factory );
101102
}
102103

103104
/**
@@ -296,5 +297,5 @@ function getBalloonPositions( isBackward ) {
296297
*
297298
* Read also about configuring the main editor toolbar in {@link module:core/editor/editorconfig~EditorConfig#toolbar}.
298299
*
299-
* @member {Array.<String>} module:core/editor/editorconfig~EditorConfig#contextualToolbar
300+
* @member {Array.<String>|Object} module:core/editor/editorconfig~EditorConfig#contextualToolbar
300301
*/

src/toolbar/normalizetoolbarconfig.js

Lines changed: 17 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -8,28 +8,40 @@
88
*/
99

1010
/**
11-
* Normalizes the toolbar configuration (`config.toolbar`), which may be defined as an `Array`:
11+
* Normalizes the toolbar configuration (`config.toolbar`), which:
12+
*
13+
* * may be defined as an `Array`:
1214
*
1315
* toolbar: [ 'headings', 'bold', 'italic', 'link', ... ]
1416
*
15-
* or an `Object`:
17+
* * or an `Object`:
1618
*
1719
* toolbar: {
1820
* items: [ 'headings', 'bold', 'italic', 'link', ... ],
1921
* ...
2022
* }
2123
*
24+
* * or may not be defined at all (`undefined`)
25+
*
2226
* and returns it in the object form.
2327
*
24-
* @param {Array|Object} config The value of `config.toolbar`.
28+
* @param {Array|Object|undefined} config The value of `config.toolbar`.
2529
* @returns {Object} A normalized toolbar config object.
2630
*/
2731
export default function normalizeToolbarConfig( config ) {
2832
if ( Array.isArray( config ) ) {
29-
config = {
33+
return {
3034
items: config
3135
};
3236
}
3337

34-
return config;
38+
if ( !config ) {
39+
return {
40+
items: []
41+
};
42+
}
43+
44+
return Object.assign( {
45+
items: []
46+
}, config );
3547
}

src/toolbar/toolbarview.js

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -122,10 +122,6 @@ export default class ToolbarView extends View {
122122
* @param {module:ui/componentfactory~ComponentFactory} factory A factory producing toolbar items.
123123
*/
124124
fillFromConfig( config, factory ) {
125-
if ( !config ) {
126-
return;
127-
}
128-
129125
config.map( name => {
130126
if ( name == '|' ) {
131127
this.items.add( new ToolbarSeparatorView() );

tests/toolbar/contextual/contextualtoolbar.js

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ import ToolbarView from '../../../src/toolbar/toolbarview';
1010
import Plugin from '@ckeditor/ckeditor5-core/src/plugin';
1111
import Bold from '@ckeditor/ckeditor5-basic-styles/src/bold';
1212
import Italic from '@ckeditor/ckeditor5-basic-styles/src/italic';
13+
import Underline from '@ckeditor/ckeditor5-basic-styles/src/underline';
1314
import Paragraph from '@ckeditor/ckeditor5-paragraph/src/paragraph';
1415

1516
import { setData } from '@ckeditor/ckeditor5-engine/src/dev-utils/model.js';
@@ -71,6 +72,28 @@ describe( 'ContextualToolbar', () => {
7172
expect( contextualToolbar.toolbarView.items ).to.length( 2 );
7273
} );
7374

75+
it( 'should accept the extended format of the toolbar config', () => {
76+
const editorElement = document.createElement( 'div' );
77+
document.body.appendChild( editorElement );
78+
79+
return ClassicTestEditor
80+
.create( editorElement, {
81+
plugins: [ Paragraph, Bold, Italic, Underline, ContextualToolbar ],
82+
contextualToolbar: {
83+
items: [ 'bold', 'italic', 'underline' ]
84+
}
85+
} )
86+
.then( editor => {
87+
const contextualToolbar = editor.plugins.get( ContextualToolbar );
88+
89+
expect( contextualToolbar.toolbarView.items ).to.length( 3 );
90+
91+
editorElement.remove();
92+
93+
return editor.destroy();
94+
} );
95+
} );
96+
7497
it( 'should fire internal `_selectionChangeDebounced` event 200 ms after last selection change', done => {
7598
// This test uses setTimeout to test lodash#debounce because sinon fake timers
7699
// doesn't work with lodash. Lodash keeps time related stuff in a closure

tests/toolbar/normalizetoolbarconfig.js

Lines changed: 23 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ describe( 'normalizeToolbarConfig()', () => {
1111
const normalized = normalizeToolbarConfig( cfg );
1212

1313
expect( normalized ).to.be.an( 'object' );
14-
expect( normalized.items ).to.equal( cfg );
14+
expect( normalized.items ).to.deep.equal( cfg );
1515
} );
1616

1717
it( 'passes through an already normalized config', () => {
@@ -21,8 +21,27 @@ describe( 'normalizeToolbarConfig()', () => {
2121
};
2222
const normalized = normalizeToolbarConfig( cfg );
2323

24-
expect( normalized ).to.equal( cfg );
25-
expect( normalized.items ).to.equal( cfg.items );
26-
expect( normalized.foo ).to.equal( cfg.foo );
24+
expect( normalized ).to.deep.equal( cfg );
25+
} );
26+
27+
it( 'adds missing items property', () => {
28+
const cfg = {
29+
foo: 'bar'
30+
};
31+
32+
const normalized = normalizeToolbarConfig( cfg );
33+
34+
expect( normalized ).to.deep.equal( {
35+
items: [],
36+
foo: 'bar'
37+
} );
38+
expect( normalized ).to.not.equal( cfg ); // Make sure we don't modify an existing obj.
39+
} );
40+
41+
it( 'returns an empty config if config is not defined', () => {
42+
const normalized = normalizeToolbarConfig();
43+
44+
expect( normalized ).to.be.an( 'object' );
45+
expect( normalized.items ).to.be.an( 'array' ).of.length( 0 );
2746
} );
2847
} );

tests/toolbar/toolbarview.js

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -234,12 +234,6 @@ describe( 'ToolbarView', () => {
234234
factory.add( 'bar', namedFactory( 'bar' ) );
235235
} );
236236

237-
it( 'does not throw when no config is provided', () => {
238-
expect( () => {
239-
view.fillFromConfig();
240-
} ).to.not.throw();
241-
} );
242-
243237
it( 'expands the config into collection', () => {
244238
view.fillFromConfig( [ 'foo', 'bar', '|', 'foo' ], factory );
245239

0 commit comments

Comments
 (0)