'Is there any way to prevent CKEditor5 from modifying an inline style tag on an programmatically inserted Div?

I have an application that generates DIV content that has to automatically be inserted into a ckeditor instance. At the moment, I'm using editorInstance.model.insertContent( modelFragment ); and have a custom plugin as follows to process the insert of these elements:

      // Allow <div> elements in the model.
        editor.model.schema.register( 'div', {
            allowWhere: '$block',
            allowContentOf: '$root',
            inheritAllFrom: '$block',
            allowAttributes: [ 'style' ]
        } );

        // Allow <div> elements in the model to have all attributes.
        editor.model.schema.addAttributeCheck( context => {
            if ( context.endsWith( 'div' ) ) {
                return true;
            }
        } );

        // The view-to-model converter converting a view <div> with all its attributes to the model.
        editor.conversion.for( 'upcast' ).elementToElement( {
            view: 'div',
            model: ( viewElement, { writer: modelWriter } ) => {
                return modelWriter.createElement( 'div', viewElement.getAttributes() );
            }
        } );

        // The model-to-view converter for the <div> element (attributes are converted separately).
        editor.conversion.for( 'downcast' ).elementToElement( {
            model: 'div',
            view: 'div'
        } );

        // The model-to-view converter for <div> attributes.
        // Note that a lower-level, event-based API is used here.
        editor.conversion.for( 'downcast' ).add( dispatcher => {
            dispatcher.on( 'attribute', ( evt, data, conversionApi ) => {
                // Convert <div> attributes only.
                if ( data.item.name != 'div' ) {
                    return;
                }

                const viewWriter = conversionApi.writer;
                const viewDiv = conversionApi.mapper.toViewElement( data.item );

                // In the model-to-view conversion we convert changes.
                // An attribute can be added or removed or changed.
                // The below code handles all 3 cases.
                if ( data.attributeNewValue ) {
                    viewWriter.setAttribute( data.attributeKey, data.attributeNewValue, viewDiv );
                } else {
                    viewWriter.removeAttribute( data.attributeKey, viewDiv );
                }
            } );
        } );
    }

However, some of the DIV elements that I'm inserting have custom style tags. For 'basic' stuff, such as background-image, background-color, this works OK, but when I try to insert a div with background: linear-gradient(...... it seems to strip the entire style tag empty. These elements are generated on the fly, so I can't style them any other way than inline.

Is it possible to force CKEditor5 not to parse the style tag on the div, or to allow background: linear-gradient(...?



Solution 1:[1]

I had similar requirement, so I was able to achieve something through this code

here I created a list of custom styles I wanted to use, so I used upcast and downcast dispatcher

 const allowedStyles = {
'lineHeight': 'line-height',
}

schema.extend( modelName, {
        allowAttributes: [...Object.keys( allowedStyles )]
      } )

editor.data.upcastDispatcher.on(
  "element",
  (evt, data, conversionApi) => {
    for (const [modelStyle, viewStyle] of Object.entries(allowedStyles)) {
      const styleValue =
        data.viewItem.getNormalizedStyle(viewStyle)

      //if range is null
      if (!data.modelRange) {
        return;
      }

      for (const item of data.modelRange.getItems({ shallow: true })) {
        if (schema.checkAttribute(item, modelStyle)) {
          conversionApi.writer.setAttribute(modelStyle, styleValue, item);
        }
      }
    }
  },
  {
    priority: "low",
  }
);

for (const [modelAttribute, viewStyle] of Object.entries(allowedStyles)) {
  conversion.for("downcast").add((dispatcher) =>
    dispatcher.on(`attribute:${modelAttribute}`, (evt, data, conversionApi) => {
      const {
        item,

        attributeNewValue,
      } = data;

      //if item name is not defined

      if (!item.name) {
        return;
      }

      const {
        mapper,

        writer,
      } = conversionApi;

      // if ( !conversionApi.consumable.consume( data.item, evt.name ) ) {
      //  return;
      // }

      const div = mapper.toViewElement(item);

      if (attributeNewValue) {
        writer.setStyle(viewStyle, attributeNewValue, div);
      } else {
        writer.removeStyle(viewStyle, div);
      }
    })
  );
}


Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 SDP