Skip to content

Commit

Permalink
Merge pull request #9251 from ckeditor/i/8362
Browse files Browse the repository at this point in the history
Feature (widget): Added attributes support in default markers highlight downcast conversion for widgets. Closes #8362.
  • Loading branch information
pomek authored Mar 17, 2021
2 parents 5f80e85 + 3de90dc commit 0bd718a
Show file tree
Hide file tree
Showing 4 changed files with 69 additions and 21 deletions.
11 changes: 6 additions & 5 deletions packages/ckeditor5-engine/src/conversion/downcasthelpers.js
Original file line number Diff line number Diff line change
Expand Up @@ -360,18 +360,19 @@ export default class DowncastHelpers extends ConversionHelpers {
*
* editor.conversion.for( 'downcast' ).markerToHighlight( {
* model: 'comment',
* view: { classes: 'new-comment' },
* view: { classes: 'comment' },
* converterPriority: 'high'
* } );
*
* editor.conversion.for( 'downcast' ).markerToHighlight( {
* model: 'comment',
* view: ( data, converstionApi ) => {
* // Assuming that the marker name is in a form of comment:commentType.
* const commentType = data.markerName.split( ':' )[ 1 ];
* view: ( data, conversionApi ) => {
* // Assuming that the marker name is in a form of comment:commentType:commentId.
* const [ , commentType, commentId ] = data.markerName.split( ':' );
*
* return {
* classes: [ 'comment', 'comment-' + commentType ]
* classes: [ 'comment', 'comment-' + commentType ],
* attributes: { 'data-comment-id': commentId }
* };
* }
* } );
Expand Down
16 changes: 7 additions & 9 deletions packages/ckeditor5-engine/tests/conversion/downcasthelpers.js
Original file line number Diff line number Diff line change
Expand Up @@ -2673,25 +2673,23 @@ describe( 'DowncastHelpers', () => {
it( 'config.view is a function', () => {
downcastHelpers.markerToHighlight( {
model: 'comment',
view: ( data, conversionApi ) => {
const commentType = data.markerName.split( ':' )[ 1 ];

// To ensure conversion API is provided.
expect( conversionApi.writer ).to.instanceof( DowncastWriter );

view: data => {
// Assuming that the marker name is in a form of comment:commentType:commentId.
const [ , commentType, commentId ] = data.markerName.split( ':' );
return {
classes: [ 'comment', 'comment-' + commentType ]
classes: [ 'comment', 'comment-' + commentType ],
attributes: { 'data-comment-id': commentId }
};
}
} );

model.change( writer => {
writer.insertText( 'foo', modelRoot, 0 );
const range = writer.createRange( writer.createPositionAt( modelRoot, 0 ), writer.createPositionAt( modelRoot, 3 ) );
writer.addMarker( 'comment:abc', { range, usingOperation: false } );
writer.addMarker( 'comment:abc:id', { range, usingOperation: false } );
} );

expectResult( '<span class="comment comment-abc">foo</span>' );
expectResult( '<span class="comment comment-abc" data-comment-id="id">foo</span>' );
} );

describe( 'highlight', () => {
Expand Down
43 changes: 37 additions & 6 deletions packages/ckeditor5-widget/src/utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -124,16 +124,47 @@ export function toWidget( element, writer, options = {} ) {
addSelectionHandle( element, writer );
}

setHighlightHandling(
element,
writer,
( element, descriptor, writer ) => writer.addClass( toArray( descriptor.classes ), element ),
( element, descriptor, writer ) => writer.removeClass( toArray( descriptor.classes ), element )
);
setHighlightHandling( element, writer, addHighlight, removeHighlight );

return element;
}

// Default handler for adding a highlight on a widget.
// It adds CSS class and attributes basing on the given highlight descriptor.
//
// @param {module:engine/view/element~Element} element
// @param {module:engine/conversion/downcasthelpers~HighlightDescriptor} descriptor
// @param {module:engine/view/downcastwriter~DowncastWriter} writer
function addHighlight( element, descriptor, writer ) {
if ( descriptor.classes ) {
writer.addClass( toArray( descriptor.classes ), element );
}

if ( descriptor.attributes ) {
for ( const key in descriptor.attributes ) {
writer.setAttribute( key, descriptor.attributes[ key ], element );
}
}
}

// Default handler for removing a highlight from a widget.
// It removes CSS class and attributes basing on the given highlight descriptor.
//
// @param {module:engine/view/element~Element} element
// @param {module:engine/conversion/downcasthelpers~HighlightDescriptor} descriptor
// @param {module:engine/view/downcastwriter~DowncastWriter} writer
function removeHighlight( element, descriptor, writer ) {
if ( descriptor.classes ) {
writer.removeClass( toArray( descriptor.classes ), element );
}

if ( descriptor.attributes ) {
for ( const key in descriptor.attributes ) {
writer.removeAttribute( key, element );
}
}
}

/**
* Sets highlight handling methods. Uses {@link module:widget/highlightstack~HighlightStack} to
* properly determine which highlight descriptor should be used at given time.
Expand Down
20 changes: 19 additions & 1 deletion packages/ckeditor5-widget/tests/utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@ describe( 'widget utils', () => {
expect( getLabel( element ) ).to.equal( 'foo bar baz label' );
} );

it( 'should set default highlight handling methods', () => {
it( 'should set default highlight handling methods - CSS class', () => {
toWidget( element, writer );

const set = element.getCustomProperty( 'addHighlight' );
Expand Down Expand Up @@ -108,6 +108,24 @@ describe( 'widget utils', () => {
expect( element.hasClass( 'foo' ) ).to.be.false;
} );

it( 'should set default highlight handling methods - attributes', () => {
toWidget( element, writer );

const set = element.getCustomProperty( 'addHighlight' );
const remove = element.getCustomProperty( 'removeHighlight' );

expect( typeof set ).to.equal( 'function' );
expect( typeof remove ).to.equal( 'function' );

set( element, { priority: 1, attributes: { foo: 'bar', abc: 'xyz' }, id: 'highlight' }, writer );
expect( element.getAttribute( 'foo' ) ).to.equal( 'bar' );
expect( element.getAttribute( 'abc' ) ).to.equal( 'xyz' );

remove( element, 'highlight', writer );
expect( element.hasAttribute( 'foo' ) ).to.be.false;
expect( element.hasAttribute( 'abc' ) ).to.be.false;
} );

it( 'should add element a selection handle to widget if hasSelectionHandle=true is passed', () => {
toWidget( element, writer, { hasSelectionHandle: true } );

Expand Down

0 comments on commit 0bd718a

Please sign in to comment.