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

Commit 72ee3d6

Browse files
authored
Merge pull request #99 from ckeditor/t/ckeditor5-alignment/16
Other: Update naming of UI components & commands. BREAKING CHANGE: Renamed the `'headings'` dropdown UI component to `'heading'`. BREAKING CHANGE: The `'heading1'`, `'heading2'` and `'heading3'` commands are no longer available. They were replaced by the `'heading'` command that accepts heading model element name as a value. BREAKING CHANGE: The `HeadingCommand#value` is no longer a boolean only. Now it stores a name of the heading model element when selection is inside a heading. BREAKING CHANGE: The `HeadingCommand` constructor's second parameter is now an array of supported model elements.
2 parents bbf7d60 + d7bbf1f commit 72ee3d6

File tree

10 files changed

+151
-112
lines changed

10 files changed

+151
-112
lines changed

docs/features/headings.md

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -122,7 +122,7 @@ import Heading from '@ckeditor/ckeditor5-heading/src/heading';
122122
ClassicEditor
123123
.create( document.querySelector( '#editor' ), {
124124
plugins: [ Heading, ... ],
125-
toolbar: [ 'headings', ... ]
125+
toolbar: [ 'heading', ... ]
126126
} )
127127
.then( ... )
128128
.catch( ... );
@@ -132,13 +132,13 @@ ClassicEditor
132132

133133
The {@link module:heading/heading~Heading} plugin registers:
134134

135-
* The `'headings'` dropdown.
136-
* The `'heading1'`, `'heading2'`, ..., `'headingN'` commands based on the {@link module:heading/heading~HeadingConfig#options `heading.options`} configuration option.
135+
* The `'heading'` dropdown.
136+
* The `'heading'` command that accepts value based on the {@link module:heading/heading~HeadingConfig#options `heading.options`} configuration option.
137137

138138
You can turn the currently selected block(s) to headings by executing one of these commands:
139139

140140
```js
141-
editor.execute( 'heading2' );
141+
editor.execute( 'heading', { value: 'heading2' } );
142142
```
143143

144144
## Contribute

src/heading.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -95,10 +95,10 @@ export default class Heading extends Plugin {
9595
* That's assumption is used by features like {@link module:autoformat/autoformat~Autoformat} to know which element
9696
* they should use when applying the first level heading.
9797
*
98-
* The defined headings are also available in {@link module:core/commandcollection~CommandCollection} under their model names.
98+
* The defined headings are also available as values passed to `heading` command under their model names.
9999
* For example, the below code will apply `<heading1>` to the current selection:
100100
*
101-
* editor.execute( 'heading1' );
101+
* editor.execute( 'heading', { value: 'heading1' } );
102102
*
103103
* @member {Array.<module:heading/heading~HeadingOption>} module:heading/heading~HeadingConfig#options
104104
*/

src/headingcommand.js

Lines changed: 23 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -20,27 +20,29 @@ export default class HeadingCommand extends Command {
2020
* Creates an instance of the command.
2121
*
2222
* @param {module:core/editor/editor~Editor} editor Editor instance.
23-
* @param {String} modelElement Name of the element which this command will apply in the model.
23+
* @param {Array.<String>} modelElements Names of the element which this command can apply in the model.
2424
*/
25-
constructor( editor, modelElement ) {
25+
constructor( editor, modelElements ) {
2626
super( editor );
2727

2828
/**
29-
* Whether the selection starts in a heading of {@link #modelElement this level}.
29+
* If the selection starts in a heading (which {@link #modelElements is supported by this command})
30+
* the value is set to the name of that heading model element.
31+
* It is set to `false` otherwise.
3032
*
3133
* @observable
3234
* @readonly
33-
* @member {Boolean} #value
35+
* @member {Boolean|String} #value
3436
*/
3537

3638
/**
37-
* Unique identifier of the command, also element's name in the model.
39+
* Set of defined model's elements names that this command support.
3840
* See {@link module:heading/heading~HeadingOption}.
3941
*
4042
* @readonly
41-
* @member {String}
43+
* @member {Array.<String>}
4244
*/
43-
this.modelElement = modelElement;
45+
this.modelElements = modelElements;
4446
}
4547

4648
/**
@@ -49,29 +51,37 @@ export default class HeadingCommand extends Command {
4951
refresh() {
5052
const block = first( this.editor.model.document.selection.getSelectedBlocks() );
5153

52-
this.value = !!block && block.is( this.modelElement );
53-
this.isEnabled = !!block && checkCanBecomeHeading( block, this.modelElement, this.editor.model.schema );
54+
this.value = !!block && this.modelElements.includes( block.name ) && block.name;
55+
this.isEnabled = !!block && this.modelElements.some( heading => checkCanBecomeHeading( block, heading, this.editor.model.schema ) );
5456
}
5557

5658
/**
5759
* Executes the command. Applies the heading to the selected blocks or, if the first selected
5860
* block is a heading already, turns selected headings (of this level only) to paragraphs.
5961
*
62+
* @param {Object} options
63+
* @param {String} options.value Name of the element which this command will apply in the model.
6064
* @fires execute
6165
*/
62-
execute() {
66+
execute( options = {} ) {
6367
const model = this.editor.model;
6468
const document = model.document;
6569

70+
const modelElement = options.value;
71+
72+
if ( !this.modelElements.includes( modelElement ) ) {
73+
return;
74+
}
75+
6676
model.change( writer => {
6777
const blocks = Array.from( document.selection.getSelectedBlocks() )
6878
.filter( block => {
69-
return checkCanBecomeHeading( block, this.modelElement, model.schema );
79+
return checkCanBecomeHeading( block, modelElement, model.schema );
7080
} );
7181

7282
for ( const block of blocks ) {
73-
if ( !block.is( this.modelElement ) ) {
74-
writer.rename( block, this.modelElement );
83+
if ( !block.is( modelElement ) ) {
84+
writer.rename( block, modelElement );
7585
}
7686
}
7787
} );

src/headingediting.js

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,8 @@ export default class HeadingEditing extends Plugin {
5151
const editor = this.editor;
5252
const options = editor.config.get( 'heading.options' );
5353

54+
const modelElements = [];
55+
5456
for ( const option of options ) {
5557
// Skip paragraph - it is defined in required Paragraph feature.
5658
if ( option.model !== defaultModelElement ) {
@@ -61,10 +63,12 @@ export default class HeadingEditing extends Plugin {
6163

6264
editor.conversion.elementToElement( option );
6365

64-
// Register the heading command for this option.
65-
editor.commands.add( option.model, new HeadingCommand( editor, option.model ) );
66+
modelElements.push( option.model );
6667
}
6768
}
69+
70+
// Register the heading command for this option.
71+
editor.commands.add( 'heading', new HeadingCommand( editor, modelElements ) );
6872
}
6973

7074
/**

src/headingui.js

Lines changed: 23 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -33,24 +33,37 @@ export default class HeadingUI extends Plugin {
3333
const dropdownTooltip = t( 'Heading' );
3434

3535
// Register UI component.
36-
editor.ui.componentFactory.add( 'headings', locale => {
37-
const commands = [];
36+
editor.ui.componentFactory.add( 'heading', locale => {
37+
const titles = {};
3838
const dropdownItems = new Collection();
3939

40+
const headingCommand = editor.commands.get( 'heading' );
41+
const paragraphCommand = editor.commands.get( 'paragraph' );
42+
43+
const commands = [ headingCommand ];
44+
4045
for ( const option of options ) {
41-
const command = editor.commands.get( option.model );
4246
const itemModel = new Model( {
43-
commandName: option.model,
4447
label: option.title,
4548
class: option.class
4649
} );
4750

48-
itemModel.bind( 'isActive' ).to( command, 'value' );
51+
if ( option.model === 'paragraph' ) {
52+
itemModel.bind( 'isActive' ).to( paragraphCommand, 'value' );
53+
itemModel.set( 'commandName', 'paragraph' );
54+
commands.push( paragraphCommand );
55+
} else {
56+
itemModel.bind( 'isActive' ).to( headingCommand, 'value', value => value === option.model );
57+
itemModel.set( {
58+
commandName: 'heading',
59+
commandValue: option.model
60+
} );
61+
}
4962

5063
// Add the option to the collection.
5164
dropdownItems.add( itemModel );
5265

53-
commands.push( command );
66+
titles[ option.model ] = option.title;
5467
}
5568

5669
const dropdownView = createDropdown( locale );
@@ -74,16 +87,15 @@ export default class HeadingUI extends Plugin {
7487
return areEnabled.some( isEnabled => isEnabled );
7588
} );
7689

77-
dropdownView.buttonView.bind( 'label' ).toMany( commands, 'value', ( ...areActive ) => {
78-
const index = areActive.findIndex( value => value );
79-
90+
dropdownView.buttonView.bind( 'label' ).to( headingCommand, 'value', paragraphCommand, 'value', ( value, para ) => {
91+
const whichModel = value || para && 'paragraph';
8092
// If none of the commands is active, display default title.
81-
return options[ index ] ? options[ index ].title : defaultTitle;
93+
return titles[ whichModel ] ? titles[ whichModel ] : defaultTitle;
8294
} );
8395

8496
// Execute command when an item from the dropdown is selected.
8597
this.listenTo( dropdownView, 'execute', evt => {
86-
editor.execute( evt.source.commandName );
98+
editor.execute( evt.source.commandName, evt.source.commandValue ? { value: evt.source.commandValue } : undefined );
8799
editor.editing.view.focus();
88100
} );
89101

0 commit comments

Comments
 (0)