-
Notifications
You must be signed in to change notification settings - Fork 29
Added defaultValue to ManualDecorators. #258
Changes from 4 commits
3c88b6d
8246201
2068a0f
e631e7e
5ea7fac
b2dc424
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -15,6 +15,8 @@ import AutomaticDecorators from './utils/automaticdecorators'; | |
import ManualDecorator from './utils/manualdecorator'; | ||
import bindTwoStepCaretToAttribute from '@ckeditor/ckeditor5-engine/src/utils/bindtwostepcarettoattribute'; | ||
import findLinkRange from './findlinkrange'; | ||
import Matcher from '@ckeditor/ckeditor5-engine/src/view/matcher'; | ||
|
||
import '../theme/link.css'; | ||
|
||
const HIGHLIGHT_CLASS = 'ck-link_selected'; | ||
|
@@ -187,6 +189,41 @@ export default class LinkEditing extends Plugin { | |
key: decorator.id | ||
} | ||
} ); | ||
|
||
// For a decorator that is enabled by default we must check if it was applied to reflect that in the model. | ||
if ( decorator.defaultValue ) { | ||
editor.conversion.for( 'upcast' ).add( dispatcher => { | ||
const matcher = new Matcher( { | ||
name: 'a', | ||
attributes: { | ||
href: true | ||
} | ||
} ); | ||
|
||
dispatcher.on( 'element', ( evt, data, conversionApi ) => { | ||
const matcherResult = matcher.match( data.viewItem ); | ||
|
||
if ( !matcherResult ) { | ||
return; | ||
} | ||
|
||
// We must check if all decorator values are set on view element. | ||
const decoratorValue = Object.entries( decorator.attributes ).every( ( [ key, value ] ) => { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I wanted to write that this comparison is not precise enough because you can have two decorators using the class attribute but I can see that this is not supported already. It's a pity because the engine treats each class separately (styles and classes are special types of attributes) and this could work. In fact, getData() works, but setData() breaks. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I reported a ticket for that in ckeditor/ckeditor5#6571. |
||
return matcherResult.element.getAttribute( key ) == value; | ||
} ); | ||
|
||
// The decorator is applied, model attribute was already up-casted. | ||
if ( decoratorValue ) { | ||
return; | ||
} | ||
|
||
// Set attribute on each item in range according to Schema. | ||
for ( const node of Array.from( data.modelRange.getItems() ) ) { | ||
conversionApi.writer.setAttribute( decorator.id, false, node ); | ||
} | ||
}, { priority: 'low' } ); | ||
} ); | ||
} | ||
} ); | ||
} | ||
|
||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -284,10 +284,18 @@ describe( 'LinkCommand', () => { | |
target: '_blank' | ||
} | ||
} ) ); | ||
command.manualDecorators.add( new ManualDecorator( { | ||
id: 'linkIsSth', | ||
label: 'Sth', | ||
attributes: { | ||
class: 'sth' | ||
}, | ||
defaultValue: true | ||
} ) ); | ||
|
||
model.schema.extend( '$text', { | ||
allowIn: '$root', | ||
allowAttributes: [ 'linkHref', 'linkIsFoo', 'linkIsBar' ] | ||
allowAttributes: [ 'linkHref', 'linkIsFoo', 'linkIsBar', 'linkIsSth' ] | ||
} ); | ||
|
||
model.schema.register( 'p', { inheritAllFrom: '$block' } ); | ||
|
@@ -302,19 +310,19 @@ describe( 'LinkCommand', () => { | |
it( 'should insert additional attributes to link when it is created', () => { | ||
setData( model, 'foo[]bar' ); | ||
|
||
command.execute( 'url', { linkIsFoo: true, linkIsBar: true } ); | ||
command.execute( 'url', { linkIsFoo: true, linkIsBar: true, linkIsSth: true } ); | ||
|
||
expect( getData( model ) ).to | ||
.equal( 'foo[<$text linkHref="url" linkIsBar="true" linkIsFoo="true">url</$text>]bar' ); | ||
.equal( 'foo[<$text linkHref="url" linkIsBar="true" linkIsFoo="true" linkIsSth="true">url</$text>]bar' ); | ||
} ); | ||
|
||
it( 'should add additional attributes to link when link is modified', () => { | ||
setData( model, 'f<$text linkHref="url">o[]oba</$text>r' ); | ||
|
||
command.execute( 'url', { linkIsFoo: true, linkIsBar: true } ); | ||
command.execute( 'url', { linkIsFoo: true, linkIsBar: true, linkIsSth: true } ); | ||
|
||
expect( getData( model ) ).to | ||
.equal( 'f[<$text linkHref="url" linkIsBar="true" linkIsFoo="true">ooba</$text>]r' ); | ||
.equal( 'f[<$text linkHref="url" linkIsBar="true" linkIsFoo="true" linkIsSth="true">ooba</$text>]r' ); | ||
} ); | ||
|
||
it( 'should remove additional attributes to link if those are falsy', () => { | ||
|
@@ -324,25 +332,33 @@ describe( 'LinkCommand', () => { | |
|
||
expect( getData( model ) ).to.equal( 'foo[<$text linkHref="url">url</$text>]bar' ); | ||
} ); | ||
|
||
it( 'should add additional attributes to link if those are falsy but decorator\'s defaultValue is set to true', () => { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Why storing the There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. As I see this – the only thing that needs to change when There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. As discussed on a call:
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Why storing the There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. |
||
setData( model, 'foo<$text linkHref="url" linkIsBar="true" linkIsFoo="true">u[]rl</$text>bar' ); | ||
|
||
command.execute( 'url', { linkIsFoo: false, linkIsBar: false, linkIsSth: false } ); | ||
|
||
expect( getData( model ) ).to.equal( 'foo[<$text linkHref="url" linkIsSth="false">url</$text>]bar' ); | ||
} ); | ||
} ); | ||
|
||
describe( 'range selection', () => { | ||
it( 'should insert additional attributes to link when it is created', () => { | ||
setData( model, 'f[ooba]r' ); | ||
|
||
command.execute( 'url', { linkIsFoo: true, linkIsBar: true } ); | ||
command.execute( 'url', { linkIsFoo: true, linkIsBar: true, linkIsSth: true } ); | ||
|
||
expect( getData( model ) ).to | ||
.equal( 'f[<$text linkHref="url" linkIsBar="true" linkIsFoo="true">ooba</$text>]r' ); | ||
.equal( 'f[<$text linkHref="url" linkIsBar="true" linkIsFoo="true" linkIsSth="true">ooba</$text>]r' ); | ||
} ); | ||
|
||
it( 'should add additional attributes to link when link is modified', () => { | ||
setData( model, 'f[<$text linkHref="foo">ooba</$text>]r' ); | ||
|
||
command.execute( 'url', { linkIsFoo: true, linkIsBar: true } ); | ||
command.execute( 'url', { linkIsFoo: true, linkIsBar: true, linkIsSth: true } ); | ||
|
||
expect( getData( model ) ).to | ||
.equal( 'f[<$text linkHref="url" linkIsBar="true" linkIsFoo="true">ooba</$text>]r' ); | ||
.equal( 'f[<$text linkHref="url" linkIsBar="true" linkIsFoo="true" linkIsSth="true">ooba</$text>]r' ); | ||
} ); | ||
|
||
it( 'should remove additional attributes to link if those are falsy', () => { | ||
|
@@ -352,29 +368,66 @@ describe( 'LinkCommand', () => { | |
|
||
expect( getData( model ) ).to.equal( 'foo[<$text linkHref="url">url</$text>]bar' ); | ||
} ); | ||
|
||
it( 'should add additional attributes to link if those are falsy but decorator\'s defaultValue is set to true', () => { | ||
setData( model, 'foo[<$text linkHref="url" linkIsBar="true" linkIsFoo="true">url</$text>]bar' ); | ||
|
||
command.execute( 'url', { linkIsFoo: false, linkIsBar: false, linkIsSth: false } ); | ||
|
||
expect( getData( model ) ).to.equal( 'foo[<$text linkHref="url" linkIsSth="false">url</$text>]bar' ); | ||
} ); | ||
} ); | ||
|
||
describe( 'restoreManualDecoratorStates()', () => { | ||
it( 'synchronize values with current model state', () => { | ||
setData( model, 'foo<$text linkHref="url" linkIsBar="true" linkIsFoo="true">u[]rl</$text>bar' ); | ||
setData( model, 'foo<$text linkHref="url" linkIsBar="true" linkIsFoo="true" linkIsSth="true">u[]rl</$text>bar' ); | ||
|
||
expect( decoratorStates( command.manualDecorators ) ).to.deep.equal( { | ||
linkIsFoo: true, | ||
linkIsBar: true | ||
linkIsBar: true, | ||
linkIsSth: true | ||
} ); | ||
|
||
command.manualDecorators.first.value = false; | ||
|
||
expect( decoratorStates( command.manualDecorators ) ).to.deep.equal( { | ||
linkIsFoo: false, | ||
linkIsBar: true | ||
linkIsBar: true, | ||
linkIsSth: true | ||
} ); | ||
|
||
command.restoreManualDecoratorStates(); | ||
|
||
expect( decoratorStates( command.manualDecorators ) ).to.deep.equal( { | ||
linkIsFoo: true, | ||
linkIsBar: true, | ||
linkIsSth: true | ||
} ); | ||
} ); | ||
|
||
it( 'synchronize values with current model state when the decorator that is "on" default is "off"', () => { | ||
setData( model, 'foo<$text linkHref="url" linkIsBar="true" linkIsFoo="true" linkIsSth="false">u[]rl</$text>bar' ); | ||
|
||
expect( decoratorStates( command.manualDecorators ) ).to.deep.equal( { | ||
linkIsFoo: true, | ||
linkIsBar: true, | ||
linkIsSth: false | ||
} ); | ||
|
||
command.manualDecorators.last.value = true; | ||
|
||
expect( decoratorStates( command.manualDecorators ) ).to.deep.equal( { | ||
linkIsFoo: true, | ||
linkIsBar: true, | ||
linkIsSth: true | ||
} ); | ||
|
||
command.restoreManualDecoratorStates(); | ||
|
||
expect( decoratorStates( command.manualDecorators ) ).to.deep.equal( { | ||
linkIsFoo: true, | ||
linkIsBar: true | ||
linkIsBar: true, | ||
linkIsSth: false | ||
} ); | ||
} ); | ||
} ); | ||
|
@@ -383,8 +436,16 @@ describe( 'LinkCommand', () => { | |
it( 'obtain current values from the model', () => { | ||
setData( model, 'foo[<$text linkHref="url" linkIsBar="true">url</$text>]bar' ); | ||
|
||
expect( command._getDecoratorStateFromModel( 'linkIsFoo' ) ).to.be.false; | ||
expect( command._getDecoratorStateFromModel( 'linkIsBar' ) ).to.be.true; | ||
expect( command._getDecoratorStateFromModel( command.manualDecorators.get( 'linkIsFoo' ) ) ).to.be.false; | ||
expect( command._getDecoratorStateFromModel( command.manualDecorators.get( 'linkIsBar' ) ) ).to.be.true; | ||
} ); | ||
|
||
it( 'fallbacks to defaultValue if there is no attribute in model', () => { | ||
setData( model, 'foo[<$text linkHref="url">url</$text>]bar' ); | ||
|
||
expect( command._getDecoratorStateFromModel( command.manualDecorators.get( 'linkIsFoo' ) ) ).to.be.false; | ||
expect( command._getDecoratorStateFromModel( command.manualDecorators.get( 'linkIsBar' ) ) ).to.be.false; | ||
expect( command._getDecoratorStateFromModel( command.manualDecorators.get( 'linkIsSth' ) ) ).to.be.true; | ||
} ); | ||
} ); | ||
} ); | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.