diff --git a/packages/ckeditor5-engine/src/conversion/downcasthelpers.js b/packages/ckeditor5-engine/src/conversion/downcasthelpers.js
index acfd26b880e..32886a6537e 100644
--- a/packages/ckeditor5-engine/src/conversion/downcasthelpers.js
+++ b/packages/ckeditor5-engine/src/conversion/downcasthelpers.js
@@ -405,9 +405,8 @@ export default class DowncastHelpers extends ConversionHelpers {
*
* This conversion creates a representation for model marker boundaries in the view:
*
- * * If the marker boundary is at a position where text nodes are allowed, then a view element with the specified tag name
- * and `name` attribute is added at this position.
- * * In other cases, a specified attribute is set on a view element that is before or after the marker boundary.
+ * * If the marker boundary is before or after a model element, a view attribute is set on a corresponding view element.
+ * * In other cases, a view element with the specified tag name is inserted at corresponding view position.
*
* Typically, marker names use the `group:uniqueId:otherData` convention. For example: `comment:e34zfk9k2n459df53sjl34:zx32c`.
* The default configuration for this conversion is that the first part is the `group` part and the rest of
@@ -945,32 +944,33 @@ function insertMarkerData( viewCreator ) {
// Helper function for `insertMarkerData()` that marks a marker boundary at the beginning or end of given `range`.
function handleMarkerBoundary( range, isStart, conversionApi, data, viewMarkerData ) {
const modelPosition = isStart ? range.start : range.end;
- const canInsertElement = conversionApi.schema.checkChild( modelPosition, '$text' );
+ const elementAfter = modelPosition.nodeAfter && modelPosition.nodeAfter.is( 'element' ) ? modelPosition.nodeAfter : null;
+ const elementBefore = modelPosition.nodeBefore && modelPosition.nodeBefore.is( 'element' ) ? modelPosition.nodeBefore : null;
- if ( canInsertElement ) {
- const viewPosition = conversionApi.mapper.toViewPosition( modelPosition );
-
- insertMarkerAsElement( viewPosition, isStart, conversionApi, data, viewMarkerData );
- } else {
+ if ( elementAfter || elementBefore ) {
let modelElement;
let isBefore;
// If possible, we want to add `data-group-start-before` and `data-group-end-after` attributes.
- // Below `if` is constructed in a way that will favor adding these attributes.
- //
- // Also, I assume that there will be always an element either after or before the position.
- // If not, then it is a case when we are not in a position where text is allowed and also there are no elements around...
- if ( isStart && modelPosition.nodeAfter || !isStart && !modelPosition.nodeBefore ) {
- modelElement = modelPosition.nodeAfter;
+ if ( isStart && elementAfter || !isStart && !elementBefore ) {
+ // [
Foo
' ); } ); + it( 'default conversion, document fragment, text', () => { + const dataController = new DataController( model, new StylesProcessor() ); + downcastHelpers = new DowncastHelpers( [ dataController.downcastDispatcher ] ); + + downcastHelpers.markerToData( { model: 'group' } ); + + let modelDocumentFragment; + + model.change( writer => { + modelDocumentFragment = writer.createDocumentFragment(); + + writer.insertText( 'foobar', [], modelDocumentFragment, 0 ); + + const range = writer.createRange( + writer.createPositionFromPath( modelDocumentFragment, [ 2 ] ), + writer.createPositionFromPath( modelDocumentFragment, [ 5 ] ) + ); + + modelDocumentFragment.markers.set( 'group:foo:bar', range ); + } ); + + const expectedResult = 'fo'; + + expect( dataController.stringify( modelDocumentFragment ) ).to.equal( expectedResult ); + } ); + it( 'conversion callback, mixed, multiple markers, name', () => { const customData = { foo: 'bar',