TinyMCE ContentCSS Config Per Domain

Vote:
 

We host several unique domains on DXP, but use a common set of blocks.  We've been asked to have the TinyMCE editor show unique branding per domain.  Allowing editors to see unique branding for things like: background color, font colors, font faces, etc

In our setup, we start with a Default Configuation:

config.Default()
  .AddEpiserverSupport()
  .ContentCss("../../Static/tinymce/ContentEditor.css")

Then we create a specific TinyMCE editor config for other Brands

var brandXConfiguration = config.Default().Clone()
  .AddEpiserverSupport()
  .ContentCss("../../Static/tinymce/BrandXEditor.css")

The issue we're seeing is when we apply that branding to common blocks.  The following code causes every CommonBlock usage (no matter the domain) to show the 'BrandX' styles, not branding specific to the 'Domain' like we're being asked. 

config.For<Models.Blocks.CommonBlock>(a => a.MainBody, brandXConfiguration);

Is there a way to apply a specific ContentCSS settings based on the domain that the block is being utilized?  We are using CMS 11 / CMS TinyMCE 2.

#275074
Mar 01, 2022 16:57
Vote:
 

I am not sure I fully understand what you are trying to accomplish. The following code applies brand-x-configuration to common blocks. Is that not what you want?

config.For<Models.Blocks.CommonBlock>(a => a.MainBody, brandXConfiguration);

What I think you want is to  use the same set of blocks (CommonBlock) on multiple domains, and have the ContentCss vary from domain to domain. There is one problem with that. The same block can be used in more than one place, so how do you determine what content CSS to use?

If you wanted to customize content css for TinyMCE on pages (not blocks) that would be easier, as pages can not belong to mulitple sites. You could just merge this code for creating and attribute, that unlike the initialization module, will be run every time the editor is sown: https://www.gulla.net/en/blog/episerver-tinymce-settings-attribute/

And use this code to determine the current domain:
https://world.optimizely.com/blogs/ravindra-s--rathore/dates/2019/8/retrieve-relative-url-of-a-page-on-page-or-block/

inspect the settings-variable to find the correct key for the contentcss, and update it based on the current domain.

#275265
Mar 01, 2022 21:19
Vote:
 

You can do this with a custom EditorDescriptor class for XhtmlString. Here is a simple example of how to configure the ContentCSS setting. Although I recommend using a site setting of sorts to configure the brand instead of checking the domain name — it makes the solution more robust and reusable.

[EditorDescriptorRegistration(TargetType = typeof(XhtmlString), EditorDescriptorBehavior = EditorDescriptorBehavior.PlaceLast)]
public class XhtmlStringEditorDescriptor : EditorDescriptor
{
    public override void ModifyMetadata(ExtendedMetadata metadata,
        IEnumerable<Attribute> attributes)
    {
        if (metadata.EditorConfiguration["settings"] is Dictionary<string, object> settings)
        {
            if (SiteDefinition.Current.SiteUrl.AbsoluteUri.Contains("mybranddomain"))
            {
                settings["content_css"] = "../../Static/tinymce/BrandXEditor.css";
            }
        }
    }
}

 Is this sort of what you meant @Tomas? I've had a similar scenario in the past and this answer is based on that. 

#275268
Mar 01, 2022 22:58
Tomas Hensrud Gulla - Mar 02, 2022 6:27
Yes, that was what I had in mind - you put the pieces nicely together! 👍

My concerns about blocks not necessary belonging to one specific domain is still valid. My understanding is that the same block is being used across domains, as a shared block. If the block is used on two domains, and edited outside of the context of a pave - how are you going to select the right kind of css?
Ynze Nunnink - Mar 03, 2022 4:34
Yes I agree. I don't think there is much much you can do about that — however it's not necessarily a problem. Reading Brandon's question, I think he's reusing content types across multiple sites with different themes/branding and not necessarily sharing the block content as well. The theme/branding will be based on the context in which you are previewing the content.
Vote:
 

The solution looks good to me,

I think content CSS is expecting an array, but no idea if it actually makes any difference setting it to a string. If you cast to TinyMceSettings (EPiServer.Cms.TinyMce.Core) you can use the ContentCss method to modify the value like this:

public override void ModifyMetadata(ExtendedMetadata metadata, IEnumerable<Attribute> attributes)
{
    if (!(metadata.EditorConfiguration["settings"] is TinyMceSettings settings))
    {
        return;
    }

    if (SiteDefinition.Current.SiteUrl.AbsoluteUri.Contains("mybranddomain"))
    {
        settings.ContentCss("../../Static/tinymce/BrandXEditor.css");
    }
}
#275905
Mar 08, 2022 13:11
* You are NOT allowed to include any hyperlinks in the post because your account hasn't associated to your company. User profile should be updated.