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

T/53a: Split "heading" command into independent commands. #58

Merged
merged 6 commits into from
Mar 13, 2017
Merged

Conversation

oleq
Copy link
Member

@oleq oleq commented Mar 7, 2017

Suggested merge commit message (convention)

Feature: Split "heading" command into independent commands. Closes ckeditor/ckeditor5#2435. Closes ckeditor/ckeditor5#2442. Closes ckeditor/ckeditor5#2437.

BREAKING CHANGE: The "heading" command is no longer available. Replaced by "heading1", "heading2", "heading3" and "paragraph".
BREAKING CHANGE: Heading plugin requires Paragraph to work properly (ParagraphCommand registered as "paragraph" in editor.commands).
BREAKING CHANGE: config.heading.options format has changed. The valid HeadingOption syntax is now { modelElement: 'heading1', viewElement: 'h1', title: 'Heading 1' }.


Additional information

Requires ckeditor/ckeditor5-paragraph#15.

@oleq
Copy link
Member Author

oleq commented Mar 8, 2017

self.R-. There's no need for HeadingEngine exposing #commands collection. It turned out it's pretty useless when dealing with https://github.com/ckeditor/ckeditor5-heading/issues/38.


for ( let option of options ) {
// Add the option to the collection.
dropdownItems.add( new Model( {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does it have to be a model instance? Can't this be a simple object?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Binding requires observable. We could pass an object here and convert it into observable in createlistdropdown. But this is beyond the scope of this issue as it didn't change this part.

Copy link
Member Author

@oleq oleq Mar 9, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

OTOH I'm not sure whether would make more sense. There could be cases when a feature using the dropdown might want to play with models in #items immediately, i.e. bind its attributes to something else.

If we enforce that #items is Collection.<Object>, developers would need to pick those models from the dropdown after createListDropdown was called which is not very convenient.

Besides, what would ListView look like then if #items would be Collection.<Object>? Where to store the "intermediate models" created in createListDropdown()? Because there must be models for Model->ListItemView bindings.

src/heading.js Outdated
// Add the option to the collection.
dropdownItems.add( new Model( {
modelElement: option.modelElement,
label: option.title
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This label = title doesn't look good.

I think that the name of the option property should be as generic as possible because we'll have the same problem all around our code. I wonder what's better – label, title or perhaps name. We have the same problem in ImageStyles and it would be good to find a naming convention fitting all such scenarios.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It may not look good but OTOH it makes sense. "Label" is a label in DOM, in the UI component. "Title" is any kind of title, it could be a label, but also aria attribute or plain text. This is where two of them meet.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

OK, so if you find "title" more generic, then let's use it. Then, we're also fine in the ImageStyles which uses the same property name.

src/heading.js Outdated

// Register UI component.
editor.ui.componentFactory.add( 'headings', ( locale ) => {
const dropdown = createListDropdown( dropdownModel, locale );

// Execute command when an item from the dropdown is selected.
this.listenTo( dropdown, 'execute', ( { source: { id } } ) => {
editor.execute( 'heading', { id } );
this.listenTo( dropdown, 'execute', ( { source: { modelElement } } ) => {
Copy link
Member

@Reinmar Reinmar Mar 8, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The param of the callback is impossible for me to parse. Please use a more human-readable solution.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Learn destructuring then ;-)

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I know destructuring and it doesn't help. Which means that the code is wrong.

src/heading.js Outdated
this.listenTo( dropdown, 'execute', ( { source: { id } } ) => {
editor.execute( 'heading', { id } );
this.listenTo( dropdown, 'execute', ( { source: { modelElement } } ) => {
editor.execute( modelElement );
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If you execute this, then it's a commandName not modelElement.

src/heading.js Outdated
return editor.config.get( 'heading.options' ).map( option => {
let title;

if ( option.modelElement == 'paragraph' ) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why this condition? Can't it go through the usual:

title = localizedTitles[ option.title ];

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I meant – why it doesn't have that property? It doesn't make sense that it has viewElement. It doesn't also make sense that it has modelElement – it could be replaced with defaultBlock: true or something (but we can stick to modelElement – I'm ok with this). But it certainly can have title.

Copy link
Member

@Reinmar Reinmar Mar 8, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actually, without it it's not localizable AFAICS. I mean – it can be localized through translations, but you can't use custom title.

}
}
// When applying new option.
else {
batch.rename( element, id );
batch.rename( element, this.modelElement );
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Like in the paragraph command – you can skip renaming elements which are already named correctly.

}
}

// If range's selection start/end is placed directly in renamed block - we need to restore it's position
// after renaming, because renaming puts new element there.
doc.selection.setRanges( ranges, isSelectionBackward );
selection.setRanges( ranges, isSelectionBackward );
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If everything else works correctly, this should be unnecessary. This command does not change the selection.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

PS. This might've been necessary in the past when renaming wasn't an operation because then the live selection transformations might not have been able to keep the selection position.

.toElement( option.modelElement );

// Register the heading command for this option.
command = new HeadingCommand( editor, option );
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This variable is unnecessary.

@szymonkups szymonkups merged commit 7a8f6f0 into master Mar 13, 2017
@szymonkups szymonkups deleted the t/53a branch March 13, 2017 10:43
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Use Selection#getSelectedBlocks Get rid of "format" from the code Separate commands for each heading
3 participants