cssangularsap-commerce-cloudspartacus-storefrontsmartedit

SAP Spartacus - Inline styles in Paragraph component (SmartEdit)


I've been trying to use one of the simplest OOTB features of the Paragraph component in SmartEdit (from a SAP Commerce fresh installation with the Spartacus storefront) - adding a color to some text in the Rich Text Editor - but it seems like the component sanitises the HTML therefore removing my styles.

Reproduction steps:

The obvious / simplest solution would be to:

  1. create a SafeHtmlPipe to leverage the DomSanitizer
  2. then extend the OOTB Paragraph component
  3. and use the pipe on the desired element (as described in this other StackOverflow thread: Angular2 innerHtml binding remove style attribute)

BUT is this the expected OOTB behaviour or did I do something wrong while installing the project (or when I configured the settings)?

If it's the expected behaviour it would mean that some of the OOTB features can't actually be used without some coding and that's quite disappointing.

What do we do when we have lots of components using Rich Text Editors or HTML input fields? Are we going to extend them all?


Solution

  • yes it is true that not everything works OOTB.

    As you described, you can fix this issue by yourself, replacing the default CMSParagraphComponent with your custom one:

    export const paragraphCmsConfig: CmsConfig = {
      cmsComponents: {
        CMSParagraphComponent: {
          component: YourParagraphComponent,
        },
      },
    }
    

    Inside of YourParagraphComponent you extend the given ParagraphComponent

    @Component({
      selector: 'your-paragraph',
      templateUrl: './your-paragraph.component.html',
      styleUrls: ['./your-paragraph.component.scss'],
    })
    export class YourParagraphComponent extends ParagraphComponent {}
    

    and implement your own SafeHtmlPipe

    <div class="your-paragraph" *ngIf="component.data$ | async as data" [innerHTML]="data.content | trust: 'html'"></div>
    

    In our case, the Pipe was named trust

    @Pipe({
      name: 'trust',
    })
    export class YourSafeHtmlPipe implements PipeTransform {
      constructor(protected sanitizer: DomSanitizer) {}
    
      public transform(
        value: any,
        type: string
      ): SafeHtml | SafeStyle | SafeScript | SafeUrl | SafeResourceUrl {
        switch (type) {
          case 'html':
            return this.sanitizer.bypassSecurityTrustHtml(value)
          case 'style':
            return this.sanitizer.bypassSecurityTrustStyle(value)
          case 'script':
            return this.sanitizer.bypassSecurityTrustScript(value)
          case 'url':
            return this.sanitizer.bypassSecurityTrustUrl(value)
          case 'resourceUrl':
            return this.sanitizer.bypassSecurityTrustResourceUrl(value)
          default:
            throw new Error(`Invalid safe type specified: ${type}`)
        }
      }
    }
    

    Hook all together in a module and import it into your custom implementation

    @NgModule({
      imports: [CommonModule, CmsParagraphModule],
      declarations: [YourParagraphComponent],
      exports: [YourParagraphComponent],
      providers: [provideConfig(paragraphCmsConfig),YourSafeHtmlPipe],
    })
    export class YourParagraphComponentModule {}