Search code examples
javascripthtmlckeditor5

How prevent CKEditor from removing <html>, <head> and <body> tags


My problem is basically identical to the one described in this other post except that it concerned CKeditor 4 and I'm actually dealing with the version 5 of the module.

In a nutshell : if I try to edit in ckeditor a html doc like

<html>
<head>
<meta http-equiv="Content-Type" content="text/html" />
</head>
<body>
<p>test</p>
</body>
</html>

The only thing that is visible when displaying it with the source plugin or that is kept after saving it is plainly

<p>test</p>

My ckeditor config is (I commented the useless attempt I made which are described a bit further)

/* multiple plugins import */

class Editor extends DecoupledDocumentEditor {
  constructor(document) {
    super(document);
    // this.data.processor = new XmlDataProcessor( document); // attempt without Html processor
    // this.editing.view.domConverter.preElements =["pre","style","head","html","body","meta"];
    // this.editing.view.domConverter.unsafeElements = ["script"]; // attempts on the view converter
    // this.data.processor.domConverter.preElements =["pre","style","head","html","body","meta"];
    // this.data.processor.domConverter.unsafeElements = ["script"]; // attempts on the data converter
  }
}

// Plugins to be included in the build.
Editor.builtinPlugins = [
        /* List of plugins, for clarity I only left the relevant ones */
    Essentials,
    GeneralHtmlSupport,
    SourceEditing   
];

The instantiation of the editor is done through

DecoupledDocumentEditor
    .create(this.options.textArea.val(), {
        language: Bosecr.config.LOCALE,
        htmlSupport: {
            allow: [
                { // to keep all the html tags and their attributes
                    name: /.*/,
                    attributes: true,
                    classes: true,
                    styles: true
                }
            ]
        },
        updateSourceElementOnDestroy: true
        })  
    .then(editor => {
        console.log("view.preElements : " + editor.editing.view.domConverter.preElements);
        console.log("view.unsafeElements : " + editor.editing.view.domConverter.unsafeElements);
        console.log("data.preElements : " + editor.data.processor.domConverter.preElements);
        console.log("data.unsafeElements : " + editor.data.processor.domConverter.unsafeElements);
        // editor.editing.view.domConverter.preElements=["pre","style","head","html","body"];
        // editor.editing.view.domConverter.unsafeElements=["scripts"]; 
        
        this.options.toolbarArea.append( editor.ui.view.toolbar.element );
        this.options.textArea.append(editor.ui.getEditableElement());
        this.options.widgets.editor = editor;
    })
    .catch(error => {
        alert("error occured during editor creation : " + error);
    });

I've tried

  • to add the plugin General Html support and configure it to allow everything => it did a good job to allows div with homemade style's classes. But it doesn't seems to have any effect outside of the <body> tag.
  • I've also tried to replace the HtmlDataProcessor by a XMLDataProcessor => this bring more issues than solution as the <br> (not self closed) and the &nbsp; are then blocking issues.

I'm not sure to understand why, when or how the content of tag is removed. I can imagine 2 scenarios : either, only the content of <body> is kept (and all the rest is discarded) or only specific tags are removed (is there a configurable list of those somewhere ?)

As a wild guess I tried to act on the DomConverter which seems to be defined in 2 places of the ckeditor 'engine' : both for the editing.view and the data.processor. I tried to add html, body, meta, head tags in the preElements list but without any noticeable effect. Just to be sure, I tried this

  • after the creation of the editor (within the then() function)
  • and before the creation by overriding the constructor in the ckeditor config

I've the feeling that I'm getting close of a solution and that my need is not so strange that it wouldn't be allowed by this new version of CKEditor (as a matter of fact, it was working in the previous version through a plain boolean parameter : fullPage: true)

So I must be missing something. Does any one would have an idea of how or in which direction I could investigate further ?


Solution

  • Well, I'm not sure how I miss it at first place, it looks pretty straightforward now that I found the solution.

    Actually, this is just in the official doc. Aside of the general html support feature, I had to activate the full page html edition feature.

    This is plainly done in the module definition by

    /* multiple plugins import */
    /*GeneralHtmlSupport is for the extra html support like homemade div,
    while FullPage is for the out-of-the-<body> content */
    import {GeneralHtmlSupport, FullPage} from '@ckeditor/ckeditor5-html-support';
    
    class Editor extends DecoupledDocumentEditor {
    /* overriding the constructor is actually useless*/
    }
    
    // Plugins to be included in the build.
    Editor.builtinPlugins = [
            /* List of plugins, for clarity I only left the relevant ones */
        Essentials,
        FullPage,        // declare the new FullPage plugin
        GeneralHtmlSupport,
        SourceEditing   
    ];