Content manipulation in beforeUpdate lifecycle preventing from publish

System Information
  • Strapi Version: 4.14.5
  • Operating System: macos
  • Database: postgresql
  • Node Version: 18.18.1
  • NPM Version:
  • Yarn Version:

Hello,
I am using the ‘@_sh/strapi-plugin-ckeditor’ as the rich text editor.
I want to embed iframes from datawrapper (a tool that render any kind of table inside an iframe and allow extra ) inside the content field which is using CKeditor.
I know that ckeditor has html embeds, but those snippets conflict with the site UI, so decided to disable them and paste embed codes directly into the editor.
The only issue is, datawrapper embed code consists of an iframe and a script tag. I want to remove the script tag but keep the iframe in the content.

For that I wanted to use the sanitize-html library sanitize-html - npm

I spent two days configuring it and put it in my content type lifecycles.ts field.

It looks like this:

import sanitizeHtml from "sanitize-html";
export default { 
  beforeCreate(event) {
    sanitizeContent(event.params.data);
  },
  beforeUpdate(event) {
    sanitizeContent(event.params.data);
  }
}
const sanitizeContent = (data: any) => {
  if(data?.content) {
    data.content = sanitizeHtml(data.content, {/* some sanitisation options */});
  }
}

If I just add content and hit save, the content gets inserted, everything works fine. I can publish/unpublish, etc.
But if I edit the entry after creation, it saves the change, does sanitisation correctly, but the Save button is still enabled, just like there was an unsaved change. Publish/unpublish button is disabled, and if I try to navigate away from the entry, I see a pop-up asking if I’m sure I want to abandon unsaved changes.

The question is , what am I doing wrong?

I also tried doing in a global middleware instead like this:

export default ()=> {
  return async (ctx, next) => {
    if (ctx.request.method === 'PUT' || ctx.request.method === 'POST') {
      if (ctx.request.url.includes('/content-manager/collection-types/api::article.article')) {
        sanitizeContent(ctx.request.body);
      }
    }
   await next();
}

Unfortunately, the outcome is the same as in lifecycle functions.

Update:
I think this is because output of sanitize-html has a different formatting than ckeditor (sanitize-html removes indentation, new line characters, etc, whereas ckeditor always reformats the source. This causes the field to be constantly in a changed state.

Does anyone know if I can configure either of them to accept the other’s formatting?

I guess you can close this thread.

I the end I decided to put sanitization in the content controller.